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:
parent
cd7249d41d
commit
ed1a77252b
|
@ -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
|
||||
COSXScreen::enable()
|
||||
{
|
||||
|
@ -558,55 +580,57 @@ COSXScreen::enable()
|
|||
kCGEventMaskForAllEvents,
|
||||
handleCGInputEvent,
|
||||
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 {
|
||||
// FIXME -- prevent system from entering power save mode
|
||||
|
||||
// hide cursor
|
||||
if (!m_cursorHidden) {
|
||||
// CGDisplayHideCursor(m_displayID);
|
||||
hideCursor();
|
||||
m_cursorHidden = true;
|
||||
}
|
||||
|
||||
// warp the mouse to the cursor center
|
||||
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
|
||||
COSXScreen::disable()
|
||||
{
|
||||
if (m_isPrimary) {
|
||||
// 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;
|
||||
}
|
||||
// show cursor if hidden
|
||||
if (m_cursorHidden) {
|
||||
showCursor();
|
||||
m_cursorHidden = false;
|
||||
}
|
||||
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
|
||||
m_dragNumButtonsDown = 0;
|
||||
|
@ -625,6 +649,11 @@ COSXScreen::disable()
|
|||
void
|
||||
COSXScreen::enter()
|
||||
{
|
||||
// show cursor
|
||||
if (m_cursorHidden) {
|
||||
showCursor();
|
||||
m_cursorHidden = false;
|
||||
}
|
||||
if (m_isPrimary) {
|
||||
CGSetLocalEventsSuppressionInterval(0.0);
|
||||
|
||||
|
@ -632,12 +661,6 @@ COSXScreen::enter()
|
|||
//setGlobalHotKeysEnabled(true);
|
||||
}
|
||||
else {
|
||||
// show cursor
|
||||
if (m_cursorHidden) {
|
||||
// CGDisplayShowCursor(m_displayID);
|
||||
m_cursorHidden = false;
|
||||
}
|
||||
|
||||
// reset buttons
|
||||
m_buttonState.reset();
|
||||
|
||||
|
@ -659,6 +682,12 @@ COSXScreen::enter()
|
|||
bool
|
||||
COSXScreen::leave()
|
||||
{
|
||||
// hide cursor
|
||||
if (!m_cursorHidden) {
|
||||
hideCursor();
|
||||
m_cursorHidden = true;
|
||||
}
|
||||
|
||||
if (m_isPrimary) {
|
||||
// warp to center
|
||||
warpCursor(m_xCenter, m_yCenter);
|
||||
|
@ -672,12 +701,6 @@ COSXScreen::leave()
|
|||
//setGlobalHotKeysEnabled(false);
|
||||
}
|
||||
else {
|
||||
// hide cursor
|
||||
if (!m_cursorHidden) {
|
||||
// CGDisplayHideCursor(m_displayID);
|
||||
m_cursorHidden = true;
|
||||
}
|
||||
|
||||
// warp the mouse to the cursor center
|
||||
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));
|
||||
}
|
||||
|
||||
// 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
|
||||
CGEventRef
|
||||
COSXScreen::handleCGInputEvent(CGEventTapProxy proxy,
|
||||
|
@ -1653,6 +1704,8 @@ COSXScreen::handleCGInputEvent(CGEventTapProxy proxy,
|
|||
// Unknown, forward it
|
||||
return event;
|
||||
break;
|
||||
case NX_NUMPROCS:
|
||||
break;
|
||||
default:
|
||||
LOG((CLOG_NOTE "Unknown Quartz Event type: 0x%02x", type));
|
||||
}
|
||||
|
|
|
@ -34,6 +34,13 @@
|
|||
#include <IOKit/pwr_mgt/IOPMLib.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>
|
||||
class CCondVar;
|
||||
class CEventQueueTimer;
|
||||
|
@ -113,6 +120,10 @@ private:
|
|||
|
||||
bool onKey(CGEventRef event);
|
||||
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
|
||||
ButtonID mapMacButtonToSynergy(UInt16) const;
|
||||
|
@ -168,6 +179,10 @@ private:
|
|||
CGEventType type,
|
||||
CGEventRef event,
|
||||
void* refcon);
|
||||
static CGEventRef handleCGInputEventSecondary(CGEventTapProxy proxy,
|
||||
CGEventType type,
|
||||
CGEventRef event,
|
||||
void* refcon);
|
||||
private:
|
||||
struct CHotKeyItem {
|
||||
public:
|
||||
|
|
Loading…
Reference in New Issue