diff --git a/server/CMSWindowsPrimaryScreen.cpp b/server/CMSWindowsPrimaryScreen.cpp index bf83c4cf..e35d2811 100644 --- a/server/CMSWindowsPrimaryScreen.cpp +++ b/server/CMSWindowsPrimaryScreen.cpp @@ -165,7 +165,7 @@ CMSWindowsPrimaryScreen::close() } void -CMSWindowsPrimaryScreen::enter(SInt32 x, SInt32 y) +CMSWindowsPrimaryScreen::enter(SInt32 x, SInt32 y, bool forScreenSaver) { log((CLOG_INFO "entering primary at %d,%d", x, y)); assert(m_active == true); @@ -174,7 +174,9 @@ CMSWindowsPrimaryScreen::enter(SInt32 x, SInt32 y) enterNoWarp(); // warp to requested location - warpCursor(x, y); + if (!forScreenSaver) { + warpCursor(x, y); + } } bool diff --git a/server/CMSWindowsPrimaryScreen.h b/server/CMSWindowsPrimaryScreen.h index 5e4a493f..3a3bfdfd 100644 --- a/server/CMSWindowsPrimaryScreen.h +++ b/server/CMSWindowsPrimaryScreen.h @@ -19,7 +19,7 @@ public: virtual void stop(); virtual void open(CServer*); virtual void close(); - virtual void enter(SInt32 xAbsolute, SInt32 yAbsolute); + virtual void enter(SInt32 xAbsolute, SInt32 yAbsolute, bool); virtual bool leave(); virtual void onConfigure(); virtual void warpCursor(SInt32 xAbsolute, SInt32 yAbsolute); diff --git a/server/CServer.cpp b/server/CServer.cpp index d869d8e9..6ae97436 100644 --- a/server/CServer.cpp +++ b/server/CServer.cpp @@ -588,7 +588,7 @@ CServer::onMouseMovePrimaryNoLock(SInt32 x, SInt32 y) } // switch screen - switchScreen(newScreen, x, y); + switchScreen(newScreen, x, y, false); return true; } @@ -692,7 +692,7 @@ CServer::onMouseMoveSecondaryNoLock(SInt32 dx, SInt32 dy) // otherwise screen screens else { - switchScreen(newScreen, m_x, m_y); + switchScreen(newScreen, m_x, m_y, false); } } @@ -723,11 +723,7 @@ CServer::onScreenSaver(bool activated) // jump to primary screen if (m_active != m_primaryInfo) { -// FIXME -- should have separate "center" pixel reported by screen - m_x = m_primaryInfo->m_x + (m_primaryInfo->m_w >> 1); - m_y = m_primaryInfo->m_y + (m_primaryInfo->m_h >> 1); - m_active = m_primaryInfo; - m_primary->enter(m_x, m_y); + switchScreen(m_primaryInfo, 0, 0, true); } } else { @@ -752,8 +748,8 @@ CServer::onScreenSaver(bool activated) m_ySaver = screen->m_y + screen->m_h - screen->m_zoneSize - 1; } - // now jump - switchScreen(screen, m_xSaver, m_ySaver); + // jump + switchScreen(screen, m_xSaver, m_ySaver, false); } // reset state @@ -794,7 +790,7 @@ CServer::isLockedToScreenNoLock() const } void -CServer::switchScreen(CScreenInfo* dst, SInt32 x, SInt32 y) +CServer::switchScreen(CScreenInfo* dst, SInt32 x, SInt32 y, bool screenSaver) { assert(dst != NULL); assert(x >= dst->m_x && y >= dst->m_y); @@ -840,7 +836,7 @@ CServer::switchScreen(CScreenInfo* dst, SInt32 x, SInt32 y) // enter new screen if (m_active->m_protocol == NULL) { - m_primary->enter(x, y); + m_primary->enter(x, y, screenSaver); } else { m_active->m_protocol->sendEnter(x, y, m_seqNum, @@ -1621,20 +1617,24 @@ CServer::removeConnection(const CString& name) assert(index != m_screens.end()); // if this is active screen then we have to jump off of it - if (m_active == index->second && m_active != m_primaryInfo) { + CScreenInfo* active = (m_activeSaver != NULL) ? m_activeSaver : m_active; + if (active == index->second && active != m_primaryInfo) { // record new position (center of primary screen) // FIXME -- should have separate "center" pixel reported by screen m_x = m_primaryInfo->m_x + (m_primaryInfo->m_w >> 1); m_y = m_primaryInfo->m_y + (m_primaryInfo->m_h >> 1); // don't notify active screen since it probably already disconnected - log((CLOG_INFO "jump from \"%s\" to \"%s\" at %d,%d", m_active->m_name.c_str(), m_primaryInfo->m_name.c_str(), m_x, m_y)); + log((CLOG_INFO "jump from \"%s\" to \"%s\" at %d,%d", active->m_name.c_str(), m_primaryInfo->m_name.c_str(), m_x, m_y)); // cut over m_active = m_primaryInfo; - // enter new screen - m_primary->enter(m_x, m_y); + // enter new screen (unless we already have because of the + // screen saver) + if (m_activeSaver == NULL) { + m_primary->enter(m_x, m_y, false); + } } // if this screen had the cursor when the screen saver activated diff --git a/server/CServer.h b/server/CServer.h index 188ccc86..ed344095 100644 --- a/server/CServer.h +++ b/server/CServer.h @@ -137,7 +137,8 @@ private: bool isLockedToScreenNoLock() const; // change the active screen - void switchScreen(CScreenInfo*, SInt32 x, SInt32 y); + void switchScreen(CScreenInfo*, + SInt32 x, SInt32 y, bool forScreenSaver); // lookup neighboring screen CScreenInfo* getNeighbor(CScreenInfo*, CConfig::EDirection) const; diff --git a/server/CXWindowsPrimaryScreen.cpp b/server/CXWindowsPrimaryScreen.cpp index 24d97652..fe16effa 100644 --- a/server/CXWindowsPrimaryScreen.cpp +++ b/server/CXWindowsPrimaryScreen.cpp @@ -323,20 +323,27 @@ CXWindowsPrimaryScreen::close() } void -CXWindowsPrimaryScreen::enter(SInt32 x, SInt32 y) +CXWindowsPrimaryScreen::enter(SInt32 x, SInt32 y, bool forScreenSaver) { - log((CLOG_INFO "entering primary at %d,%d", x, y)); + log((CLOG_INFO "entering primary at %d,%d%s", x, y, forScreenSaver ? " for screen saver" : "")); assert(m_active == true); assert(m_window != None); CDisplayLock display(this); // warp to requested location - XWarpPointer(display, None, m_window, 0, 0, 0, 0, x, y); + if (!forScreenSaver) { + XWarpPointer(display, None, m_window, 0, 0, 0, 0, x, y); + } // unmap the grab window. this also ungrabs the mouse and keyboard. XUnmapWindow(display, m_window); + // redirect input to root window + if (forScreenSaver) { + XSetInputFocus(display, PointerRoot, PointerRoot, CurrentTime); + } + // remove all input events for grab window XEvent event; while (XCheckWindowEvent(display, m_window, diff --git a/server/CXWindowsPrimaryScreen.h b/server/CXWindowsPrimaryScreen.h index 408c0a2d..c8996650 100644 --- a/server/CXWindowsPrimaryScreen.h +++ b/server/CXWindowsPrimaryScreen.h @@ -15,7 +15,7 @@ public: virtual void stop(); virtual void open(CServer*); virtual void close(); - virtual void enter(SInt32 xAbsolute, SInt32 yAbsolute); + virtual void enter(SInt32 xAbsolute, SInt32 yAbsolute, bool); virtual bool leave(); virtual void onConfigure(); virtual void warpCursor(SInt32 xAbsolute, SInt32 yAbsolute); diff --git a/synergy/IPrimaryScreen.h b/synergy/IPrimaryScreen.h index 94db6bfa..c68d0bad 100644 --- a/synergy/IPrimaryScreen.h +++ b/synergy/IPrimaryScreen.h @@ -41,9 +41,11 @@ public: // called when the user navigates back to the primary screen. // warp the cursor to the given coordinates, unhide it, and // ungrab the input devices. every call to enter has a matching - // call to leave() which preceeds it, however the screen can + // call to leave() which preceeds it, however the screen should // assume an implicit call to enter() in the call to open(). - virtual void enter(SInt32 xAbsolute, SInt32 yAbsolute) = 0; + // if warpCursor is false then do not warp the mouse. + virtual void enter(SInt32 xAbsolute, SInt32 yAbsolute, + bool forScreenSaver) = 0; // called when the user navigates off the primary screen. hide // the cursor and grab exclusive access to the input devices.