From 7bbd33d7870651575a5a46a8f669648c4dd4914a Mon Sep 17 00:00:00 2001 From: crs Date: Sat, 22 Feb 2003 21:53:25 +0000 Subject: [PATCH] Added support on X11 for a global option to delay switching screens when the mouse reaches a jump zone. --- lib/platform/CXWindowsPrimaryScreen.cpp | 12 ++ lib/platform/CXWindowsPrimaryScreen.h | 2 + lib/platform/CXWindowsScreen.cpp | 87 ++++++--- lib/platform/CXWindowsScreen.h | 12 +- lib/platform/CXWindowsSecondaryScreen.cpp | 6 + lib/platform/CXWindowsSecondaryScreen.h | 1 + lib/server/CConfig.cpp | 9 +- lib/server/CPrimaryClient.cpp | 6 + lib/server/CPrimaryClient.h | 7 + lib/server/CServer.cpp | 213 ++++++++++++++++------ lib/server/CServer.h | 10 + lib/synergy/CPrimaryScreen.h | 7 + lib/synergy/IPrimaryScreenReceiver.h | 6 + lib/synergy/IScreenEventHandler.h | 6 + lib/synergy/OptionTypes.h | 1 + 15 files changed, 306 insertions(+), 79 deletions(-) diff --git a/lib/platform/CXWindowsPrimaryScreen.cpp b/lib/platform/CXWindowsPrimaryScreen.cpp index 763cf4ae..67611c39 100644 --- a/lib/platform/CXWindowsPrimaryScreen.cpp +++ b/lib/platform/CXWindowsPrimaryScreen.cpp @@ -102,6 +102,12 @@ CXWindowsPrimaryScreen::setOptions(const COptionsList& options) } } +UInt32 +CXWindowsPrimaryScreen::addOneShotTimer(double timeout) +{ + return m_screen->addOneShotTimer(timeout); +} + KeyModifierMask CXWindowsPrimaryScreen::getToggleMask() const { @@ -387,6 +393,12 @@ CXWindowsPrimaryScreen::onEvent(CEvent* event) return false; } +void +CXWindowsPrimaryScreen::onOneShotTimerExpired(UInt32 id) +{ + m_receiver->onOneShotTimerExpired(id); +} + SInt32 CXWindowsPrimaryScreen::getJumpZoneSize() const { diff --git a/lib/platform/CXWindowsPrimaryScreen.h b/lib/platform/CXWindowsPrimaryScreen.h index c24464b8..5ac54356 100644 --- a/lib/platform/CXWindowsPrimaryScreen.h +++ b/lib/platform/CXWindowsPrimaryScreen.h @@ -40,6 +40,7 @@ public: virtual void warpCursor(SInt32 x, SInt32 y); virtual void resetOptions(); virtual void setOptions(const COptionsList& options); + virtual UInt32 addOneShotTimer(double timeout); virtual KeyModifierMask getToggleMask() const; virtual bool isLockedToScreen() const; virtual IScreen* getScreen() const; @@ -48,6 +49,7 @@ public: virtual void onScreensaver(bool activated); virtual bool onPreDispatch(const CEvent* event); virtual bool onEvent(CEvent* event); + virtual void onOneShotTimerExpired(UInt32 id); virtual SInt32 getJumpZoneSize() const; protected: diff --git a/lib/platform/CXWindowsScreen.cpp b/lib/platform/CXWindowsScreen.cpp index 40e8591d..cae5ff23 100644 --- a/lib/platform/CXWindowsScreen.cpp +++ b/lib/platform/CXWindowsScreen.cpp @@ -54,14 +54,13 @@ // CXWindowsScreen::CTimer // -CXWindowsScreen::CTimer::CTimer(IJob* job, double timeout) : +CXWindowsScreen::CTimer::CTimer(IJob* job, double startTime, double resetTime) : m_job(job), - m_timeout(timeout) + m_timeout(resetTime), + m_time(resetTime), + m_startTime(startTime) { - assert(m_job != NULL); assert(m_timeout > 0.0); - - reset(); } CXWindowsScreen::CTimer::~CTimer() @@ -72,19 +71,23 @@ CXWindowsScreen::CTimer::~CTimer() void CXWindowsScreen::CTimer::run() { - m_job->run(); + if (m_job != NULL) { + m_job->run(); + } } void CXWindowsScreen::CTimer::reset() { - m_time = m_timeout; + m_time = m_timeout; + m_startTime = 0.0; } CXWindowsScreen::CTimer::CTimer& CXWindowsScreen::CTimer::operator-=(double dt) { - m_time -= dt; + m_time -= dt - m_startTime; + m_startTime = 0.0; return *this; } @@ -118,7 +121,8 @@ CXWindowsScreen::CXWindowsScreen(IScreenReceiver* receiver, m_w(0), m_h(0), m_screensaver(NULL), m_screensaverNotify(false), - m_atomScreensaver(None) + m_atomScreensaver(None), + m_oneShotTimer(NULL) { assert(s_screen == NULL); assert(m_receiver != NULL); @@ -137,6 +141,7 @@ CXWindowsScreen::~CXWindowsScreen() assert(s_screen != NULL); assert(m_display == NULL); + delete m_oneShotTimer; s_screen = NULL; } @@ -145,7 +150,7 @@ CXWindowsScreen::addTimer(IJob* job, double timeout) { CLock lock(&m_timersMutex); removeTimerNoLock(job); - m_timers.push(CTimer(job, timeout)); + m_timers.push(CTimer(job, m_time.getTime(), timeout)); } void @@ -172,6 +177,15 @@ CXWindowsScreen::removeTimerNoLock(IJob* job) m_timers.swap(tmp); } +UInt32 +CXWindowsScreen::addOneShotTimer(double timeout) +{ + CLock lock(&m_timersMutex); + // FIXME -- support multiple one-shot timers + m_oneShotTimer = new CTimer(NULL, m_time.getTime(), timeout); + return 0; +} + void CXWindowsScreen::setWindow(Window window) { @@ -262,19 +276,27 @@ CXWindowsScreen::mainLoop() #endif while (!m_stop) { // compute timeout to next timer + double dtimeout; + { + CLock timersLock(&m_timersMutex); + dtimeout = (m_timers.empty() ? -1.0 : m_timers.top()); + if (m_oneShotTimer != NULL && + (dtimeout == -1.0 || *m_oneShotTimer < dtimeout)) { + dtimeout = *m_oneShotTimer; + } + } #if HAVE_POLL - int timeout = (m_timers.empty() ? -1 : - static_cast(1000.0 * m_timers.top())); + int timeout = static_cast(1000.0 * dtimeout); #else struct timeval timeout; struct timeval* timeoutPtr; - if (m_timers.empty()) { + if (dtimeout < 0.0) { timeoutPtr = NULL; } else { - timeout.tv_sec = static_cast(m_timers.top()); + timeout.tv_sec = static_cast(dtimeout); timeout.tv_usec = static_cast(1.0e+6 * - (m_timers.top() - timeout.tv_sec)); + (dtimeout - timeout.tv_sec)); timeoutPtr = &timeout; } @@ -697,6 +719,7 @@ CXWindowsScreen::createBlankCursor() bool CXWindowsScreen::processTimers() { + bool oneShot = false; std::vector jobs; { CLock lock(&m_timersMutex); @@ -705,10 +728,21 @@ CXWindowsScreen::processTimers() const double time = m_time.getTime(); // done if no timers have expired - if (m_timers.empty() || m_timers.top() > time) { + if ((m_oneShotTimer == NULL || *m_oneShotTimer > time) && + (m_timers.empty() || m_timers.top() > time)) { return false; } + // handle one shot timers + if (m_oneShotTimer != NULL) { + *m_oneShotTimer -= time; + if (*m_oneShotTimer <= 0.0) { + delete m_oneShotTimer; + m_oneShotTimer = NULL; + oneShot = true; + } + } + // subtract current time from all timers. note that this won't // change the order of elements in the priority queue (except // for floating point round off which we'll ignore). @@ -718,18 +752,27 @@ CXWindowsScreen::processTimers() } // process all timers at or below zero, saving the jobs - while (m_timers.top() <= 0.0) { - CTimer timer = m_timers.top(); - jobs.push_back(timer.getJob()); - timer.reset(); - m_timers.pop(); - m_timers.push(timer); + if (!m_timers.empty()) { + while (m_timers.top() <= 0.0) { + CTimer timer = m_timers.top(); + jobs.push_back(timer.getJob()); + timer.reset(); + m_timers.pop(); + m_timers.push(timer); + } } // reset the clock m_time.reset(); } + // now notify of the one shot timers + if (oneShot) { + m_mutex.unlock(); + m_eventHandler->onOneShotTimerExpired(0); + m_mutex.lock(); + } + // now run the jobs. note that if one of these jobs removes // a timer later in the jobs list and deletes that job pointer // then this will crash when it tries to run that job. diff --git a/lib/platform/CXWindowsScreen.h b/lib/platform/CXWindowsScreen.h index a6451763..83f10cfa 100644 --- a/lib/platform/CXWindowsScreen.h +++ b/lib/platform/CXWindowsScreen.h @@ -69,6 +69,14 @@ public: */ void removeTimer(IJob*); + //! Install a one-shot timer + /*! + Installs a one-shot timer for \c timeout seconds and returns the + id of the timer (which will be passed to the receiver's + \c onTimerExpired()). + */ + UInt32 addOneShotTimer(double timeout); + //! Set window /*! Set the window (created by the subclass). This performs some @@ -216,7 +224,7 @@ private: // a timer priority queue element class CTimer { public: - CTimer(IJob* job, double timeout); + CTimer(IJob* job, double startTime, double resetTime); ~CTimer(); // manipulators @@ -242,6 +250,7 @@ private: IJob* m_job; double m_timeout; double m_time; + double m_startTime; }; private: @@ -278,6 +287,7 @@ private: CTimerPriorityQueue m_timers; CStopwatch m_time; CMutex m_timersMutex; + CTimer* m_oneShotTimer; // pointer to (singleton) screen. this is only needed by // ioErrorHandler(). diff --git a/lib/platform/CXWindowsSecondaryScreen.cpp b/lib/platform/CXWindowsSecondaryScreen.cpp index 1e848887..31f1affc 100644 --- a/lib/platform/CXWindowsSecondaryScreen.cpp +++ b/lib/platform/CXWindowsSecondaryScreen.cpp @@ -263,6 +263,12 @@ CXWindowsSecondaryScreen::onEvent(CEvent* event) } } +void +CXWindowsSecondaryScreen::onOneShotTimerExpired(UInt32) +{ + // ignore +} + SInt32 CXWindowsSecondaryScreen::getJumpZoneSize() const { diff --git a/lib/platform/CXWindowsSecondaryScreen.h b/lib/platform/CXWindowsSecondaryScreen.h index ad2403c2..6711ee0f 100644 --- a/lib/platform/CXWindowsSecondaryScreen.h +++ b/lib/platform/CXWindowsSecondaryScreen.h @@ -51,6 +51,7 @@ public: virtual void onScreensaver(bool activated); virtual bool onPreDispatch(const CEvent* event); virtual bool onEvent(CEvent* event); + virtual void onOneShotTimerExpired(UInt32 id); virtual SInt32 getJumpZoneSize() const; protected: diff --git a/lib/server/CConfig.cpp b/lib/server/CConfig.cpp index b125206f..09633313 100644 --- a/lib/server/CConfig.cpp +++ b/lib/server/CConfig.cpp @@ -624,6 +624,9 @@ CConfig::getOptionName(OptionID id) if (id == kOptionHeartbeat) { return "heartbeat"; } + if (id == kOptionScreenSwitchDelay) { + return "switchDelay"; + } return NULL; } @@ -659,7 +662,8 @@ CConfig::getOptionValue(OptionID id, OptionValue value) return "none"; } } - if (id == kOptionHeartbeat) { + if (id == kOptionHeartbeat || + id == kOptionScreenSwitchDelay) { return CStringUtil::print("%d", value); } @@ -767,6 +771,9 @@ CConfig::readSectionOptions(std::istream& s) else if (name == "heartbeat") { addOption("", kOptionHeartbeat, parseInt(value)); } + else if (name == "switchDelay") { + addOption("", kOptionScreenSwitchDelay, parseInt(value)); + } else { throw XConfigRead("unknown argument"); } diff --git a/lib/server/CPrimaryClient.cpp b/lib/server/CPrimaryClient.cpp index ca7d37d8..5cd66876 100644 --- a/lib/server/CPrimaryClient.cpp +++ b/lib/server/CPrimaryClient.cpp @@ -63,6 +63,12 @@ CPrimaryClient::reconfigure(UInt32 activeSides) m_screen->reconfigure(activeSides); } +UInt32 +CPrimaryClient::addOneShotTimer(double timeout) +{ + return m_screen->addOneShotTimer(timeout); +} + void CPrimaryClient::getClipboard(ClipboardID id, CString& data) const { diff --git a/lib/server/CPrimaryClient.h b/lib/server/CPrimaryClient.h index 5cd0c259..d6c3f7c6 100644 --- a/lib/server/CPrimaryClient.h +++ b/lib/server/CPrimaryClient.h @@ -59,6 +59,13 @@ public: */ void reconfigure(UInt32 activeSides); + //! Install a one-shot timer + /*! + Installs a one-shot timer for \c timeout seconds and returns the + id of the timer (which will be passed to \c onTimerExpired()). + */ + UInt32 addOneShotTimer(double timeout); + //@} //! @name accessors //@{ diff --git a/lib/server/CServer.cpp b/lib/server/CServer.cpp index cb636300..ce554f9b 100644 --- a/lib/server/CServer.cpp +++ b/lib/server/CServer.cpp @@ -59,7 +59,9 @@ CServer::CServer(const CString& serverName) : m_seqNum(0), m_activeSaver(NULL), m_httpServer(NULL), - m_httpAvailable(&m_mutex, s_httpMaxSimultaneousRequests) + m_httpAvailable(&m_mutex, s_httpMaxSimultaneousRequests), + m_switchWaitDelay(0.0), + m_switchWaitScreen(NULL) { // do nothing } @@ -220,13 +222,18 @@ CServer::setConfig(const CConfig& config) // process global options const CConfig::CScreenOptions* options = m_config.getOptions(""); if (options != NULL && options->size() > 0) { -/* for (CConfig::CScreenOptions::const_iterator index = options->begin(); index != options->end(); ++index) { const OptionID id = index->first; const OptionValue value = index->second; + if (id == kOptionScreenSwitchDelay) { + m_switchWaitDelay = 1.0e-3 * static_cast(value); + if (m_switchWaitDelay < 0.0) { + m_switchWaitDelay = 0.0; + } + clearSwitchWait(); + } } -*/ } // tell primary screen about reconfiguration @@ -496,6 +503,36 @@ CServer::onScreensaver(bool activated) } } +void +CServer::onOneShotTimerExpired(UInt32 id) +{ + CLock lock(&m_mutex); + + // ignore old timer or if there's no jump screen anymore + if (m_switchWaitScreen == NULL || id != m_switchWaitTimer) { + clearSwitchWait(); + return; + } + + // ignore if mouse is locked to screen + if (isLockedToScreenNoLock()) { + clearSwitchWait(); + return; + } + + // switch screen + switchScreen(m_switchWaitScreen, m_switchWaitX, m_switchWaitY, false); +} + +void +CServer::clearSwitchWait() +{ + if (m_switchWaitScreen != NULL) { + LOG((CLOG_DEBUG1 "cancel switch wait")); + m_switchWaitScreen = NULL; + } +} + void CServer::onKeyDown(KeyID id, KeyModifierMask mask) { @@ -582,11 +619,6 @@ CServer::onMouseMovePrimaryNoLock(SInt32 x, SInt32 y) assert(m_primaryClient != NULL); assert(m_active == m_primaryClient); - // ignore if mouse is locked to screen - if (isLockedToScreenNoLock()) { - return false; - } - // get screen shape SInt32 ax, ay, aw, ah; m_active->getShape(ax, ay, aw, ah); @@ -616,6 +648,7 @@ CServer::onMouseMovePrimaryNoLock(SInt32 x, SInt32 y) } else { // still on local screen + clearSwitchWait(); return false; } @@ -623,6 +656,27 @@ CServer::onMouseMovePrimaryNoLock(SInt32 x, SInt32 y) // then ignore the move. IClient* newScreen = getNeighbor(m_active, dir, x, y); if (newScreen == NULL) { + clearSwitchWait(); + return false; + } + + // if waiting before a switch then prepare to switch later + if (m_switchWaitDelay > 0.0) { + if (m_switchWaitScreen == NULL || dir != m_switchWaitDir) { + m_switchWaitDir = dir; + m_switchWaitScreen = newScreen; + m_switchWaitX = x; + m_switchWaitY = y; + m_switchWaitTimer = m_primaryClient->addOneShotTimer( + m_switchWaitDelay); + LOG((CLOG_DEBUG1 "waiting to switch")); + } + return false; + } + + // ignore if mouse is locked to screen + if (isLockedToScreenNoLock()) { + LOG((CLOG_DEBUG1 "locked to screen")); return false; } @@ -667,72 +721,110 @@ CServer::onMouseMoveSecondaryNoLock(SInt32 dx, SInt32 dy) SInt32 ax, ay, aw, ah; m_active->getShape(ax, ay, aw, ah); + // find direction of neighbor + EDirection dir; + IClient* newScreen = NULL; + if (m_x < ax) { + dir = kLeft; + } + else if (m_x > ax + aw - 1) { + dir = kRight; + } + else if (m_y < ay) { + dir = kTop; + } + else if (m_y > ay + ah - 1) { + dir = kBottom; + } + else { + newScreen = m_active; + + // keep compiler quiet about unset variable + dir = kLeft; + } + // switch screens if the mouse is outside the screen and not // locked to the screen - IClient* newScreen = NULL; - if (!isLockedToScreenNoLock()) { - // find direction of neighbor - EDirection dir; - if (m_x < ax) { - dir = kLeft; - } - else if (m_x > ax + aw - 1) { - dir = kRight; - } - else if (m_y < ay) { - dir = kTop; - } - else if (m_y > ay + ah - 1) { - dir = kBottom; - } - else { - newScreen = m_active; - - // keep compiler quiet about unset variable - dir = kLeft; - } - - // get neighbor if we should switch + bool clamp = false; + if (newScreen == NULL) { + // get neighbor we should switch to + newScreen = getNeighbor(m_active, dir, m_x, m_y); + LOG((CLOG_DEBUG1 "leave \"%s\" on %s", m_active->getName().c_str(), CConfig::dirName(dir))); if (newScreen == NULL) { - LOG((CLOG_DEBUG1 "leave \"%s\" on %s", m_active->getName().c_str(), CConfig::dirName(dir))); - - // get new position or clamp to current screen - newScreen = getNeighbor(m_active, dir, m_x, m_y); - if (newScreen == NULL) { - LOG((CLOG_DEBUG1 "no neighbor; clamping")); - if (m_x < ax) { - m_x = ax; - } - else if (m_x > ax + aw - 1) { - m_x = ax + aw - 1; - } - if (m_y < ay) { - m_y = ay; - } - else if (m_y > ay + ah - 1) { - m_y = ay + ah - 1; - } + LOG((CLOG_DEBUG1 "no neighbor %s", CConfig::dirName(dir))); + clamp = true; + } + else if (m_switchWaitDelay > 0.0) { + // wait to switch; prepare to switch later + if (m_switchWaitScreen == NULL || dir != m_switchWaitDir) { + m_switchWaitDir = dir; + m_switchWaitScreen = newScreen; + m_switchWaitX = m_x; + m_switchWaitY = m_y; + m_switchWaitTimer = m_primaryClient->addOneShotTimer( + m_switchWaitDelay); + LOG((CLOG_DEBUG1 "waiting to switch")); } + + // don't try to switch screen now + m_x = xOld + dx; + m_y = yOld + dy; + clamp = true; + } + else if (isLockedToScreenNoLock()) { + // clamp to edge when locked to screen + LOG((CLOG_DEBUG1 "locked to screen")); + clamp = true; } } else { - // clamp to edge when locked + // on same screen. if waiting and mouse is not on the border + // we're waiting on then stop waiting. + if (m_switchWaitScreen != NULL) { + bool clearWait; + SInt32 zoneSize = m_primaryClient->getJumpZoneSize(); + switch (m_switchWaitDir) { + case kLeft: + clearWait = (m_x >= ax + zoneSize); + break; + + case kRight: + clearWait = (m_x <= ax + aw - 1 - zoneSize); + break; + + case kTop: + clearWait = (m_y >= ay + zoneSize); + break; + + case kBottom: + clearWait = (m_y <= ay + ah - 1 + zoneSize); + break; + } + if (clearWait) { + clearSwitchWait(); + } + } + } + + // clamp mouse to edge + if (clamp) { if (m_x < ax) { m_x = ax; - LOG((CLOG_DEBUG1 "clamp to left of \"%s\"", m_active->getName().c_str())); + LOG((CLOG_DEBUG2 "clamp to left of \"%s\"", m_active->getName().c_str())); } else if (m_x > ax + aw - 1) { m_x = ax + aw - 1; - LOG((CLOG_DEBUG1 "clamp to right of \"%s\"", m_active->getName().c_str())); + LOG((CLOG_DEBUG2 "clamp to right of \"%s\"", m_active->getName().c_str())); } if (m_y < ay) { m_y = ay; - LOG((CLOG_DEBUG1 "clamp to top of \"%s\"", m_active->getName().c_str())); + LOG((CLOG_DEBUG2 "clamp to top of \"%s\"", m_active->getName().c_str())); } else if (m_y > ay + ah - 1) { m_y = ay + ah - 1; - LOG((CLOG_DEBUG1 "clamp to bottom of \"%s\"", m_active->getName().c_str())); + LOG((CLOG_DEBUG2 "clamp to bottom of \"%s\"", m_active->getName().c_str())); } + newScreen = NULL; } // warp cursor if on same screen @@ -801,6 +893,9 @@ CServer::switchScreen(IClient* dst, SInt32 x, SInt32 y, bool forScreensaver) LOG((CLOG_INFO "switch from \"%s\" to \"%s\" at %d,%d", m_active->getName().c_str(), dst->getName().c_str(), x, y)); + // stop waiting to switch + clearSwitchWait(); + // record new position m_x = x; m_y = y; @@ -1099,6 +1194,11 @@ CServer::closeClients(const CConfig& config) // close that client assert(index2->second != m_primaryClient); index2->second->close(); + + // don't switch to it if we planned to + if (index2->second == m_switchWaitScreen) { + clearSwitchWait(); + } } else { ++index; @@ -1789,6 +1889,9 @@ CServer::removeConnection(const CString& name) // record new position (center of primary screen) m_primaryClient->getCursorCenter(m_x, m_y); + // stop waiting to switch if we were + clearSwitchWait(); + // don't notify active screen since it probably already disconnected LOG((CLOG_INFO "jump from \"%s\" to \"%s\" at %d,%d", active->getName().c_str(), m_primaryClient->getName().c_str(), m_x, m_y)); diff --git a/lib/server/CServer.h b/lib/server/CServer.h index 885d0e08..d4e93778 100644 --- a/lib/server/CServer.h +++ b/lib/server/CServer.h @@ -141,6 +141,7 @@ public: // IPrimaryScreenReceiver overrides virtual void onScreensaver(bool activated); + virtual void onOneShotTimerExpired(UInt32 id); virtual void onKeyDown(KeyID, KeyModifierMask); virtual void onKeyUp(KeyID, KeyModifierMask); virtual void onKeyRepeat(KeyID, KeyModifierMask, SInt32 count); @@ -197,6 +198,9 @@ private: IClient* getNeighbor(IClient*, EDirection, SInt32& x, SInt32& y) const; + // reset switch wait state + void clearSwitchWait(); + // send screen options to \c client void sendOptions(IClient* client) const; @@ -320,6 +324,12 @@ private: CHTTPServer* m_httpServer; CCondVar m_httpAvailable; static const SInt32 s_httpMaxSimultaneousRequests; + + double m_switchWaitDelay; + EDirection m_switchWaitDir; + UInt32 m_switchWaitTimer; + IClient* m_switchWaitScreen; + SInt32 m_switchWaitX, m_switchWaitY; }; #endif diff --git a/lib/synergy/CPrimaryScreen.h b/lib/synergy/CPrimaryScreen.h index 2e953c25..0ae68e9d 100644 --- a/lib/synergy/CPrimaryScreen.h +++ b/lib/synergy/CPrimaryScreen.h @@ -129,6 +129,13 @@ public: */ virtual void setOptions(const COptionsList& options) = 0; + //! Install a one-shot timer + /*! + Installs a one-shot timer for \c timeout seconds and returns the + id of the timer. + */ + virtual UInt32 addOneShotTimer(double timeout) = 0; + //@} //! @name accessors //@{ diff --git a/lib/synergy/IPrimaryScreenReceiver.h b/lib/synergy/IPrimaryScreenReceiver.h index 430b169a..ec36f263 100644 --- a/lib/synergy/IPrimaryScreenReceiver.h +++ b/lib/synergy/IPrimaryScreenReceiver.h @@ -34,6 +34,12 @@ public: */ virtual void onScreensaver(bool activated) = 0; + //! Notify of one-shot timer expiration + /*! + Called when a one-shot timer expires. + */ + virtual void onOneShotTimerExpired(UInt32 id) = 0; + // call to notify of events. onMouseMovePrimary() returns // true iff the mouse enters a jump zone and jumps. //! Notify of key press diff --git a/lib/synergy/IScreenEventHandler.h b/lib/synergy/IScreenEventHandler.h index 46c05d14..a68858ea 100644 --- a/lib/synergy/IScreenEventHandler.h +++ b/lib/synergy/IScreenEventHandler.h @@ -57,6 +57,12 @@ public: */ virtual bool onEvent(CEvent* event) = 0; + //! Notify of one-shot timer expiration + /*! + Called when a one-shot timer expires. + */ + virtual void onOneShotTimerExpired(UInt32 id) = 0; + //@} //! @name accessors //@{ diff --git a/lib/synergy/OptionTypes.h b/lib/synergy/OptionTypes.h index 5a9ebf10..ea7e594f 100644 --- a/lib/synergy/OptionTypes.h +++ b/lib/synergy/OptionTypes.h @@ -51,6 +51,7 @@ static const OptionID kOptionModifierMapForAlt = OPTION_CODE("MMFA"); static const OptionID kOptionModifierMapForMeta = OPTION_CODE("MMFM"); static const OptionID kOptionModifierMapForSuper = OPTION_CODE("MMFR"); static const OptionID kOptionHeartbeat = OPTION_CODE("HART"); +static const OptionID kOptionScreenSwitchDelay = OPTION_CODE("SSWT"); //@} #undef OPTION_CODE