Fix for #2875: MacOS cursor should now hide when not on the active screen. This time committed to the correct branch.

Thanks (again!) to Doug Marcey (dougmarcey@gmail.com) for the patch.
This commit is contained in:
azanar@carrel.org 2011-01-10 07:55:41 +00:00
parent cd7249d41d
commit ed1a77252b
2 changed files with 109 additions and 41 deletions

View File

@ -541,6 +541,28 @@ COSXScreen::fakeMouseWheel(SInt32 xDelta, SInt32 yDelta) const
} }
} }
void
COSXScreen::showCursor()
{
CGDisplayShowCursor(m_displayID);
CFStringRef propertyString = CFStringCreateWithCString(NULL, "SetsCursorInBackground", kCFStringEncodingMacRoman);
CGSSetConnectionProperty(_CGSDefaultConnection(), _CGSDefaultConnection(), propertyString, kCFBooleanFalse);
CFRelease(propertyString);
LOG((CLOG_DEBUG "Trying to show cursor."));
}
void
COSXScreen::hideCursor()
{
CFStringRef propertyString = CFStringCreateWithCString(NULL, "SetsCursorInBackground", kCFStringEncodingMacRoman);
CGSSetConnectionProperty(_CGSDefaultConnection(), _CGSDefaultConnection(), propertyString, kCFBooleanTrue);
CFRelease(propertyString);
CGDisplayHideCursor(m_displayID);
LOG((CLOG_DEBUG "Trying to hide cursor."));
}
void void
COSXScreen::enable() COSXScreen::enable()
{ {
@ -558,55 +580,57 @@ COSXScreen::enable()
kCGEventMaskForAllEvents, kCGEventMaskForAllEvents,
handleCGInputEvent, handleCGInputEvent,
this); this);
if(!m_eventTapPort) {
LOG((CLOG_ERR "Failed to create quartz event tap."));
}
m_eventTapRLSR=CFMachPortCreateRunLoopSource(kCFAllocatorDefault, m_eventTapPort, 0);
if(!m_eventTapRLSR) {
LOG((CLOG_ERR "Failed to create a CFRunLoopSourceRef for the quartz event tap."));
}
CFRunLoopAddSource(CFRunLoopGetCurrent(), m_eventTapRLSR, kCFRunLoopDefaultMode);
} }
else { else {
// FIXME -- prevent system from entering power save mode // FIXME -- prevent system from entering power save mode
// hide cursor // hide cursor
if (!m_cursorHidden) { if (!m_cursorHidden) {
// CGDisplayHideCursor(m_displayID); hideCursor();
m_cursorHidden = true; m_cursorHidden = true;
} }
// warp the mouse to the cursor center // warp the mouse to the cursor center
fakeMouseMove(m_xCenter, m_yCenter); fakeMouseMove(m_xCenter, m_yCenter);
// FIXME -- prepare to show cursor if it moves // there may be a better way to do this, but we register an event handler even if we're
// not on the primary display (acting as a client). This way, if a local event comes in
// (either keyboard or mouse), we can make sure to show the cursor if we've hidden it.
m_eventTapPort=CGEventTapCreate(kCGHIDEventTap, kCGHIDEventTap, 0,
kCGEventMaskForAllEvents,
handleCGInputEventSecondary,
this);
} }
if(!m_eventTapPort) {
LOG((CLOG_ERR "Failed to create quartz event tap."));
}
m_eventTapRLSR=CFMachPortCreateRunLoopSource(kCFAllocatorDefault, m_eventTapPort, 0);
if(!m_eventTapRLSR) {
LOG((CLOG_ERR "Failed to create a CFRunLoopSourceRef for the quartz event tap."));
}
CFRunLoopAddSource(CFRunLoopGetCurrent(), m_eventTapRLSR, kCFRunLoopDefaultMode);
} }
void void
COSXScreen::disable() COSXScreen::disable()
{ {
if (m_isPrimary) { // show cursor if hidden
// FIXME -- stop watching jump zones, stop capturing input if (m_cursorHidden) {
showCursor();
if(m_eventTapRLSR) { m_cursorHidden = false;
CFRelease(m_eventTapRLSR);
m_eventTapRLSR=NULL;
}
if(m_eventTapPort) {
CFRelease(m_eventTapPort);
m_eventTapPort=NULL;
}
} }
else {
// show cursor
if (m_cursorHidden) {
// CGDisplayShowCursor(m_displayID);
m_cursorHidden = false;
}
// FIXME -- allow system to enter power saving mode // FIXME -- stop watching jump zones, stop capturing input
if(m_eventTapRLSR) {
CFRelease(m_eventTapRLSR);
m_eventTapRLSR=NULL;
} }
if(m_eventTapPort) {
CFRelease(m_eventTapPort);
m_eventTapPort=NULL;
}
// FIXME -- allow system to enter power saving mode
// disable drag handling // disable drag handling
m_dragNumButtonsDown = 0; m_dragNumButtonsDown = 0;
@ -625,6 +649,11 @@ COSXScreen::disable()
void void
COSXScreen::enter() COSXScreen::enter()
{ {
// show cursor
if (m_cursorHidden) {
showCursor();
m_cursorHidden = false;
}
if (m_isPrimary) { if (m_isPrimary) {
CGSetLocalEventsSuppressionInterval(0.0); CGSetLocalEventsSuppressionInterval(0.0);
@ -632,12 +661,6 @@ COSXScreen::enter()
//setGlobalHotKeysEnabled(true); //setGlobalHotKeysEnabled(true);
} }
else { else {
// show cursor
if (m_cursorHidden) {
// CGDisplayShowCursor(m_displayID);
m_cursorHidden = false;
}
// reset buttons // reset buttons
m_buttonState.reset(); m_buttonState.reset();
@ -659,6 +682,12 @@ COSXScreen::enter()
bool bool
COSXScreen::leave() COSXScreen::leave()
{ {
// hide cursor
if (!m_cursorHidden) {
hideCursor();
m_cursorHidden = true;
}
if (m_isPrimary) { if (m_isPrimary) {
// warp to center // warp to center
warpCursor(m_xCenter, m_yCenter); warpCursor(m_xCenter, m_yCenter);
@ -672,12 +701,6 @@ COSXScreen::leave()
//setGlobalHotKeysEnabled(false); //setGlobalHotKeysEnabled(false);
} }
else { else {
// hide cursor
if (!m_cursorHidden) {
// CGDisplayHideCursor(m_displayID);
m_cursorHidden = true;
}
// warp the mouse to the cursor center // warp the mouse to the cursor center
fakeMouseMove(m_xCenter, m_yCenter); fakeMouseMove(m_xCenter, m_yCenter);
@ -1594,6 +1617,34 @@ COSXScreen::CHotKeyItem::operator<(const CHotKeyItem& x) const
(m_keycode == x.m_keycode && m_mask < x.m_mask)); (m_keycode == x.m_keycode && m_mask < x.m_mask));
} }
// Quartz event tap support for the secondary display. This make sure that we
// will show the cursor if a local event comes in while synergy has the cursor off the screen.
CGEventRef
COSXScreen::handleCGInputEventSecondary(CGEventTapProxy proxy,
CGEventType type,
CGEventRef event,
void* refcon)
{
COSXScreen* screen = (COSXScreen*)refcon;
if (screen->m_cursorHidden) {
CGPoint pos;
bool showCursor = true;
if (type == kCGEventMouseMoved) {
pos = CGEventGetLocation(event);
if (pos.x == screen->m_xCenter && pos.y == screen->m_yCenter) {
showCursor = false;
}
}
if (showCursor) {
LOG((CLOG_DEBUG "Trying to show cursor from local event. (type = %d)", type));
screen->showCursor();
screen->m_cursorHidden = false;
}
}
LOG((CLOG_DEBUG2 "Local event? (type = %d)", type));
return event;
}
// Quartz event tap support // Quartz event tap support
CGEventRef CGEventRef
COSXScreen::handleCGInputEvent(CGEventTapProxy proxy, COSXScreen::handleCGInputEvent(CGEventTapProxy proxy,
@ -1653,6 +1704,8 @@ COSXScreen::handleCGInputEvent(CGEventTapProxy proxy,
// Unknown, forward it // Unknown, forward it
return event; return event;
break; break;
case NX_NUMPROCS:
break;
default: default:
LOG((CLOG_NOTE "Unknown Quartz Event type: 0x%02x", type)); LOG((CLOG_NOTE "Unknown Quartz Event type: 0x%02x", type));
} }

View File

@ -34,6 +34,13 @@
#include <IOKit/pwr_mgt/IOPMLib.h> #include <IOKit/pwr_mgt/IOPMLib.h>
#include <IOKit/IOMessage.h> #include <IOKit/IOMessage.h>
extern "C" {
typedef int CGSConnectionID;
CGError CGSSetConnectionProperty(CGSConnectionID cid, CGSConnectionID targetCID, CFStringRef key, CFTypeRef value);
int _CGSDefaultConnection();
}
template <class T> template <class T>
class CCondVar; class CCondVar;
class CEventQueueTimer; class CEventQueueTimer;
@ -114,6 +121,10 @@ private:
bool onKey(CGEventRef event); bool onKey(CGEventRef event);
bool onHotKey(EventRef event) const; bool onHotKey(EventRef event) const;
// Added here to allow the carbon cursor hack to be called.
void showCursor();
void hideCursor();
// map mac mouse button to synergy buttons // map mac mouse button to synergy buttons
ButtonID mapMacButtonToSynergy(UInt16) const; ButtonID mapMacButtonToSynergy(UInt16) const;
@ -168,6 +179,10 @@ private:
CGEventType type, CGEventType type,
CGEventRef event, CGEventRef event,
void* refcon); void* refcon);
static CGEventRef handleCGInputEventSecondary(CGEventTapProxy proxy,
CGEventType type,
CGEventRef event,
void* refcon);
private: private:
struct CHotKeyItem { struct CHotKeyItem {
public: public: