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
|
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));
|
||||||
}
|
}
|
||||||
|
|
|
@ -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:
|
||||||
|
|
Loading…
Reference in New Issue