diff --git a/synergy/CXWindowsPrimaryScreen.cpp b/synergy/CXWindowsPrimaryScreen.cpp index d464b0f7..0ae0b168 100644 --- a/synergy/CXWindowsPrimaryScreen.cpp +++ b/synergy/CXWindowsPrimaryScreen.cpp @@ -1,6 +1,7 @@ #include "CXWindowsPrimaryScreen.h" #include "CServer.h" #include "CThread.h" +#include "CLock.h" #include "TMethodJob.h" #include "CLog.h" #include @@ -107,6 +108,8 @@ void CXWindowsPrimaryScreen::enter(SInt32 x, SInt32 y) assert(m_window != None); assert(m_active == true); + CLock lock(&m_mutex); + // warp to requested location ::XWarpPointer(m_display, None, m_window, 0, 0, 0, 0, x, y); @@ -135,6 +138,8 @@ void CXWindowsPrimaryScreen::leave() assert(m_window != None); assert(m_active == false); + CLock lock(&m_mutex); + // raise and show the input window ::XMapRaised(m_display, m_window); @@ -169,7 +174,7 @@ void CXWindowsPrimaryScreen::leave() log((CLOG_DEBUG "grabbed keyboard")); // move the mouse to the center of grab window - warpCursor(m_w >> 1, m_h >> 1); + warpCursorNoLock(m_w >> 1, m_h >> 1); // local client now active m_active = true; @@ -177,7 +182,13 @@ void CXWindowsPrimaryScreen::leave() void CXWindowsPrimaryScreen::warpCursor(SInt32 x, SInt32 y) { + CLock lock(&m_mutex); + warpCursorNoLock(x, y); +} +void CXWindowsPrimaryScreen::warpCursorNoLock( + SInt32 x, SInt32 y) +{ // warp the mouse ::XWarpPointer(m_display, None, m_root, 0, 0, 0, 0, x, y); ::XSync(m_display, False); @@ -271,18 +282,24 @@ void CXWindowsPrimaryScreen::eventThread(void*) { for (;;) { // wait for and then get the next event + m_mutex.lock(); while (XPending(m_display) == 0) { + m_mutex.unlock(); CThread::sleep(0.05); + m_mutex.lock(); } XEvent xevent; XNextEvent(m_display, &xevent); + m_mutex.unlock(); // handle event switch (xevent.type) { - case CreateNotify: + case CreateNotify: { // select events on new window + CLock lock(&m_mutex); selectEvents(xevent.xcreatewindow.window); break; + } case KeyPress: { log((CLOG_DEBUG "event: KeyPress code=%d, state=0x%04x", xevent.xkey.keycode, xevent.xkey.state)); @@ -337,17 +354,21 @@ void CXWindowsPrimaryScreen::eventThread(void*) // probably not since key strokes may go to wrong place. // get mouse deltas - Window root, window; - int xRoot, yRoot, xWindow, yWindow; - unsigned int mask; - if (!::XQueryPointer(m_display, m_window, &root, &window, + { + CLock lock(&m_mutex); + Window root, window; + int xRoot, yRoot, xWindow, yWindow; + unsigned int mask; + if (!::XQueryPointer(m_display, m_window, &root, &window, &xRoot, &yRoot, &xWindow, &yWindow, &mask)) - break; - x = xRoot - (m_w >> 1); - y = yRoot - (m_h >> 1); + break; - // warp mouse back to center - warpCursor(m_w >> 1, m_h >> 1); + x = xRoot - (m_w >> 1); + y = yRoot - (m_h >> 1); + + // warp mouse back to center + warpCursorNoLock(m_w >> 1, m_h >> 1); + } m_server->onMouseMoveSecondary(x, y); } diff --git a/synergy/CXWindowsPrimaryScreen.h b/synergy/CXWindowsPrimaryScreen.h index 8ab278bf..0daa3342 100644 --- a/synergy/CXWindowsPrimaryScreen.h +++ b/synergy/CXWindowsPrimaryScreen.h @@ -1,6 +1,7 @@ #ifndef CXWINDOWSPRIMARYSCREEN_H #define CXWINDOWSPRIMARYSCREEN_H +#include "CMutex.h" #include "KeyTypes.h" #include "MouseTypes.h" #include "IPrimaryScreen.h" @@ -25,6 +26,7 @@ class CXWindowsPrimaryScreen : public IPrimaryScreen { private: void selectEvents(Window) const; Cursor createBlankCursor(); + void warpCursorNoLock(SInt32 xAbsolute, SInt32 yAbsolute); void eventThread(void*); KeyModifierMask mapModifier(unsigned int state) const; @@ -40,6 +42,9 @@ class CXWindowsPrimaryScreen : public IPrimaryScreen { SInt32 m_w, m_h; Window m_window; bool m_active; + + // X is not thread safe + CMutex m_mutex; }; #endif diff --git a/synergy/CXWindowsSecondaryScreen.cpp b/synergy/CXWindowsSecondaryScreen.cpp index b2091400..a1a0d0aa 100644 --- a/synergy/CXWindowsSecondaryScreen.cpp +++ b/synergy/CXWindowsSecondaryScreen.cpp @@ -1,6 +1,7 @@ #include "CXWindowsSecondaryScreen.h" #include "CClient.h" #include "CThread.h" +#include "CLock.h" #include "TMethodJob.h" #include "CLog.h" #include @@ -111,8 +112,10 @@ void CXWindowsSecondaryScreen::enter(SInt32 x, SInt32 y) assert(m_display != NULL); assert(m_window != None); + CLock lock(&m_mutex); + // warp to requested location - warpCursor(x, y); + warpCursorNoLock(x, y); // show cursor ::XUnmapWindow(m_display, m_window); @@ -123,6 +126,8 @@ void CXWindowsSecondaryScreen::leave() assert(m_display != NULL); assert(m_window != None); + CLock lock(&m_mutex); + // raise and show the hider window ::XMapRaised(m_display, m_window); @@ -131,6 +136,13 @@ void CXWindowsSecondaryScreen::leave() } void CXWindowsSecondaryScreen::warpCursor(SInt32 x, SInt32 y) +{ + CLock lock(&m_mutex); + warpCursorNoLock(x, y); +} + +void CXWindowsSecondaryScreen::warpCursorNoLock( + SInt32 x, SInt32 y) { assert(m_display != NULL); @@ -143,6 +155,8 @@ void CXWindowsSecondaryScreen::onKeyDown( { assert(m_display != NULL); + CLock lock(&m_mutex); + ::XTestFakeKeyEvent(m_display, mapKey(key, mask), True, CurrentTime); ::XSync(m_display, False); } @@ -152,6 +166,8 @@ void CXWindowsSecondaryScreen::onKeyRepeat( { assert(m_display != NULL); + CLock lock(&m_mutex); + // FIXME } @@ -160,6 +176,8 @@ void CXWindowsSecondaryScreen::onKeyUp( { assert(m_display != NULL); + CLock lock(&m_mutex); + ::XTestFakeKeyEvent(m_display, mapKey(key, mask), False, CurrentTime); ::XSync(m_display, False); } @@ -168,6 +186,8 @@ void CXWindowsSecondaryScreen::onMouseDown(ButtonID button) { assert(m_display != NULL); + CLock lock(&m_mutex); + ::XTestFakeButtonEvent(m_display, mapButton(button), True, CurrentTime); ::XSync(m_display, False); } @@ -176,6 +196,8 @@ void CXWindowsSecondaryScreen::onMouseUp(ButtonID button) { assert(m_display != NULL); + CLock lock(&m_mutex); + ::XTestFakeButtonEvent(m_display, mapButton(button), False, CurrentTime); ::XSync(m_display, False); } @@ -185,6 +207,8 @@ void CXWindowsSecondaryScreen::onMouseMove( { assert(m_display != NULL); + CLock lock(&m_mutex); + ::XTestFakeMotionEvent(m_display, m_screen, x, y, CurrentTime); ::XSync(m_display, False); } @@ -193,6 +217,8 @@ void CXWindowsSecondaryScreen::onMouseWheel(SInt32) { assert(m_display != NULL); + CLock lock(&m_mutex); + // FIXME } @@ -255,18 +281,24 @@ void CXWindowsSecondaryScreen::eventThread(void*) for (;;) { // wait for and then get the next event + m_mutex.lock(); while (XPending(m_display) == 0) { + m_mutex.unlock(); CThread::sleep(0.05); + m_mutex.lock(); } XEvent xevent; XNextEvent(m_display, &xevent); + m_mutex.unlock(); // handle event switch (xevent.type) { - case LeaveNotify: + case LeaveNotify: { // mouse moved out of hider window somehow. hide the window. + CLock lock(&m_mutex); ::XUnmapWindow(m_display, m_window); break; + } /* // FIXME -- handle screen resolution changes diff --git a/synergy/CXWindowsSecondaryScreen.h b/synergy/CXWindowsSecondaryScreen.h index e9688016..18e79416 100644 --- a/synergy/CXWindowsSecondaryScreen.h +++ b/synergy/CXWindowsSecondaryScreen.h @@ -1,6 +1,7 @@ #ifndef CXWINDOWSSECONDARYSCREEN_H #define CXWINDOWSSECONDARYSCREEN_H +#include "CMutex.h" #include "ISecondaryScreen.h" #include @@ -29,6 +30,7 @@ class CXWindowsSecondaryScreen : public ISecondaryScreen { private: Cursor createBlankCursor(); + void warpCursorNoLock(SInt32 xAbsolute, SInt32 yAbsolute); void eventThread(void*); KeyCode mapKey(KeyID, KeyModifierMask) const; unsigned int mapButton(ButtonID button) const; @@ -41,6 +43,9 @@ class CXWindowsSecondaryScreen : public ISecondaryScreen { Window m_root; Window m_window; SInt32 m_w, m_h; + + // X is not thread safe + CMutex m_mutex; }; #endif