diff --git a/client/CMSWindowsSecondaryScreen.cpp b/client/CMSWindowsSecondaryScreen.cpp index 0602a05f..c040479b 100644 --- a/client/CMSWindowsSecondaryScreen.cpp +++ b/client/CMSWindowsSecondaryScreen.cpp @@ -2,6 +2,7 @@ #include "CClient.h" #include "CClipboard.h" #include "CMSWindowsClipboard.h" +#include "CMSWindowsScreenSaver.h" #include "CPlatform.h" #include "XScreen.h" #include "CLock.h" @@ -97,6 +98,9 @@ CMSWindowsSecondaryScreen::open(CClient* client) grabClipboard(id); } + // disable the screen saver + getScreenSaver()->disable(); + // hide the cursor m_active = true; leave(); @@ -107,6 +111,9 @@ CMSWindowsSecondaryScreen::close() { assert(m_client != NULL); + // restore the screen saver settings + getScreenSaver()->enable(); + // close the display closeDisplay(); @@ -382,6 +389,17 @@ CMSWindowsSecondaryScreen::grabClipboard(ClipboardID /*id*/) } } +void +CMSWindowsSecondaryScreen::screenSaver(bool activate) +{ + if (activate) { + getScreenSaver()->activate(); + } + else { + getScreenSaver()->deactivate(); + } +} + void CMSWindowsSecondaryScreen::getMousePos(SInt32& x, SInt32& y) const { diff --git a/client/CMSWindowsSecondaryScreen.h b/client/CMSWindowsSecondaryScreen.h index 34d456f0..e5a6452d 100644 --- a/client/CMSWindowsSecondaryScreen.h +++ b/client/CMSWindowsSecondaryScreen.h @@ -36,6 +36,7 @@ public: virtual void mouseWheel(SInt32 delta); virtual void setClipboard(ClipboardID, const IClipboard*); virtual void grabClipboard(ClipboardID); + virtual void screenSaver(bool activate); virtual void getMousePos(SInt32& x, SInt32& y) const; virtual void getShape(SInt32&, SInt32&, SInt32&, SInt32&) const; virtual SInt32 getJumpZoneSize() const; diff --git a/platform/CMSWindowsScreen.cpp b/platform/CMSWindowsScreen.cpp index c3c08105..a9b78907 100644 --- a/platform/CMSWindowsScreen.cpp +++ b/platform/CMSWindowsScreen.cpp @@ -1,4 +1,5 @@ #include "CMSWindowsScreen.h" +#include "CMSWindowsScreenSaver.h" #include "CThread.h" #include "CLock.h" #include "TMethodJob.h" @@ -27,7 +28,8 @@ CMSWindowsScreen::CMSWindowsScreen() : m_cursor(NULL), m_x(0), m_y(0), m_w(0), m_h(0), - m_thread(0) + m_thread(0), + m_screenSaver(NULL) { assert(s_screen == NULL); s_screen = this; @@ -114,13 +116,20 @@ CMSWindowsScreen::openDisplay() // let subclass prep display onOpenDisplay(); + + // initialize the screen saver + m_screenSaver = new CMSWindowsScreenSaver(); } void CMSWindowsScreen::closeDisplay() { - assert(s_instance != NULL); - assert(m_class != 0); + assert(s_instance != NULL); + assert(m_class != 0); + + // done with screen saver + delete m_screenSaver; + m_screenSaver = NULL; // let subclass close down display onCloseDisplay(); @@ -203,6 +212,12 @@ CMSWindowsScreen::isCurrentDesktop(HDESK desk) const getCurrentDesktopName()); } +CMSWindowsScreenSaver* +CMSWindowsScreen::getScreenSaver() const +{ + return m_screenSaver; +} + void CMSWindowsScreen::getEvent(MSG* msg) const { diff --git a/platform/CMSWindowsScreen.h b/platform/CMSWindowsScreen.h index 85dc91bb..110bc499 100644 --- a/platform/CMSWindowsScreen.h +++ b/platform/CMSWindowsScreen.h @@ -7,6 +7,7 @@ #define WIN32_LEAN_AND_MEAN #include +class CMSWindowsScreenSaver; class CThread; class CMSWindowsScreen { @@ -61,6 +62,10 @@ protected: // windows 95/98/me. bool isCurrentDesktop(HDESK desk) const; + // get the screen saver object + CMSWindowsScreenSaver* + getScreenSaver() const; + // wait for and get the next message. cancellable. void getEvent(MSG*) const; @@ -91,6 +96,7 @@ private: SInt32 m_x, m_y; SInt32 m_w, m_h; DWORD m_thread; + CMSWindowsScreenSaver* m_screenSaver; static CMSWindowsScreen* s_screen; }; diff --git a/platform/platform.dsp b/platform/platform.dsp index 1a7efbca..7ebcc139 100644 --- a/platform/platform.dsp +++ b/platform/platform.dsp @@ -95,6 +95,10 @@ SOURCE=.\CMSWindowsScreen.cpp # End Source File # Begin Source File +SOURCE=.\CMSWindowsScreenSaver.cpp +# End Source File +# Begin Source File + SOURCE=.\CPlatform.cpp # End Source File # End Group @@ -111,6 +115,10 @@ SOURCE=.\CMSWindowsScreen.h # End Source File # Begin Source File +SOURCE=.\CMSWindowsScreenSaver.h +# End Source File +# Begin Source File + SOURCE=.\CPlatform.h # End Source File # Begin Source File diff --git a/server/CMSWindowsPrimaryScreen.cpp b/server/CMSWindowsPrimaryScreen.cpp index 417b5683..bf83c4cf 100644 --- a/server/CMSWindowsPrimaryScreen.cpp +++ b/server/CMSWindowsPrimaryScreen.cpp @@ -1,6 +1,7 @@ #include "CMSWindowsPrimaryScreen.h" #include "CServer.h" #include "CMSWindowsClipboard.h" +#include "CMSWindowsScreenSaver.h" #include "CPlatform.h" #include "XScreen.h" #include "XSynergy.h" @@ -34,15 +35,29 @@ CMSWindowsPrimaryScreen::CMSWindowsPrimaryScreen() : m_setRelay = (SetRelayFunc)GetProcAddress(m_hookLibrary, "setRelay"); m_install = (InstallFunc)GetProcAddress(m_hookLibrary, "install"); m_uninstall = (UninstallFunc)GetProcAddress(m_hookLibrary, "uninstall"); + m_init = (InitFunc)GetProcAddress(m_hookLibrary, "init"); + m_cleanup = (CleanupFunc)GetProcAddress(m_hookLibrary, "cleanup"); if (m_setZone == NULL || m_setRelay == NULL || m_install == NULL || - m_uninstall == NULL) { + m_uninstall == NULL || + m_init == NULL || + m_cleanup == NULL) { log((CLOG_ERR "invalid hook library")); FreeLibrary(m_hookLibrary); throw XScreenOpenFailure(); } + // get the screen saver functions + m_installScreenSaver = (InstallScreenSaverFunc)GetProcAddress( + m_hookLibrary, "installScreenSaver"); + m_uninstallScreenSaver = (UninstallScreenSaverFunc)GetProcAddress( + m_hookLibrary, "uninstallScreenSaver"); + if (m_installScreenSaver == NULL || m_uninstallScreenSaver == NULL) { + // disable uninstall if install is unavailable + m_uninstallScreenSaver = NULL; + } + // detect operating system m_is95Family = CPlatform::isWindows95Family(); @@ -56,6 +71,11 @@ CMSWindowsPrimaryScreen::~CMSWindowsPrimaryScreen() assert(m_hookLibrary != NULL); assert(m_window == NULL); + // uninstall screen saver hook + if (m_uninstallScreenSaver != NULL) { + m_uninstallScreenSaver(); + } + // done with hook library FreeLibrary(m_hookLibrary); } @@ -346,6 +366,12 @@ CMSWindowsPrimaryScreen::isLockedToScreen() const return false; } +bool +CMSWindowsPrimaryScreen::isScreenSaverActive() const +{ + return getScreenSaver()->isActive(); +} + void CMSWindowsPrimaryScreen::onOpenDisplay() { @@ -355,6 +381,14 @@ CMSWindowsPrimaryScreen::onOpenDisplay() // save thread id. we'll need to pass this to the hook library. m_threadID = GetCurrentThreadId(); + // initialize hook library + m_init(m_threadID); + + // install the screen saver hook + if (m_installScreenSaver != NULL) { + m_installScreenSaver(); + } + // get the input desktop and switch to it if (m_is95Family) { if (!openDesktop()) { @@ -379,6 +413,14 @@ CMSWindowsPrimaryScreen::onCloseDisplay() switchDesktop(NULL); } + // uninstall the screen saver hook + if (m_uninstallScreenSaver != NULL) { + m_uninstallScreenSaver(); + } + + // cleanup hook library + m_cleanup(); + // clear thread id m_threadID = 0; @@ -507,6 +549,17 @@ CMSWindowsPrimaryScreen::onPreTranslate(MSG* msg) m_y = static_cast(msg->lParam); return true; + case SYNERGY_MSG_SCREEN_SAVER: + if (msg->wParam != 0) { + if (getScreenSaver()->checkStarted(msg->message, FALSE, 0)) { + m_server->onScreenSaver(true); + } + } + else { + m_server->onScreenSaver(false); + } + return true; + case WM_TIMER: // if current desktop is not the input desktop then switch to it if (!m_is95Family) { @@ -709,7 +762,7 @@ bool CMSWindowsPrimaryScreen::openDesktop() { // install hooks - m_install(m_threadID); + m_install(); // note -- we use a fullscreen window to grab input. it should // be possible to use a 1x1 window but i've run into problems @@ -819,7 +872,7 @@ CMSWindowsPrimaryScreen::switchDesktop(HDESK desk) } // install hooks - m_install(m_threadID); + m_install(); // note -- we use a fullscreen window to grab input. it should // be possible to use a 1x1 window but i've run into problems diff --git a/server/CMSWindowsPrimaryScreen.h b/server/CMSWindowsPrimaryScreen.h index 37db16ac..5e4a493f 100644 --- a/server/CMSWindowsPrimaryScreen.h +++ b/server/CMSWindowsPrimaryScreen.h @@ -30,6 +30,7 @@ public: virtual void getClipboard(ClipboardID, IClipboard*) const; virtual KeyModifierMask getToggleMask() const; virtual bool isLockedToScreen() const; + virtual bool isScreenSaverActive() const; protected: // CMSWindowsScreen overrides @@ -106,10 +107,14 @@ private: // hook library stuff HINSTANCE m_hookLibrary; + InitFunc m_init; + CleanupFunc m_cleanup; InstallFunc m_install; UninstallFunc m_uninstall; SetZoneFunc m_setZone; SetRelayFunc m_setRelay; + InstallScreenSaverFunc m_installScreenSaver; + UninstallScreenSaverFunc m_uninstallScreenSaver; // stuff for restoring active window HWND m_lastForegroundWindow; diff --git a/server/CSynergyHook.cpp b/server/CSynergyHook.cpp index e3f70c5b..8440013b 100644 --- a/server/CSynergyHook.cpp +++ b/server/CSynergyHook.cpp @@ -45,6 +45,7 @@ static HANDLE g_keyHookThread = NULL; static DWORD g_keyHookThreadID = 0; static HANDLE g_keyHookEvent = NULL; static HHOOK g_keyboardLL = NULL; +static bool g_screenSaver = false; static bool g_relay = false; static SInt32 g_zoneSize = 0; static UInt32 g_zoneSides = 0; @@ -247,6 +248,14 @@ LRESULT CALLBACK getMessageHook(int code, WPARAM wParam, LPARAM lParam) { if (code >= 0) { + if (g_screenSaver) { + MSG* msg = reinterpret_cast(lParam); + if (msg->message == WM_SYSCOMMAND && msg->wParam == SC_SCREENSAVE) { + // broadcast screen saver started message + PostThreadMessage(g_threadID, + SYNERGY_MSG_SCREEN_SAVER, TRUE, 0); + } + } if (g_relay) { MSG* msg = reinterpret_cast(lParam); if (msg->message == g_wmMouseWheel) { @@ -455,19 +464,46 @@ DllMain(HINSTANCE instance, DWORD reason, LPVOID) extern "C" { int -install(DWORD threadID) +init(DWORD threadID) { - assert(g_threadID == 0); - assert(g_hinstance != NULL); - assert(g_keyboard == NULL); - assert(g_mouse == NULL); - assert(g_cbt == NULL); - assert(g_wheelSupport != kWheelOld || g_getMessage == NULL); + assert(g_hinstance != NULL); + + // see if already initialized + if (g_threadID != 0) { + return 0; + } // save thread id. we'll post messages to this thread's // message queue. g_threadID = threadID; + return 1; +} + +int +cleanup(void) +{ + assert(g_hinstance != NULL); + + g_threadID = 0; + + return 1; +} + +int +install() +{ + assert(g_hinstance != NULL); + assert(g_keyboard == NULL); + assert(g_mouse == NULL); + assert(g_cbt == NULL); + assert(g_getMessage == NULL || g_screenSaver); + + // must be initialized + if (g_threadID == 0) { + return 0; + } + // set defaults g_relay = false; g_zoneSize = 0; @@ -520,8 +556,8 @@ install(DWORD threadID) return 0; } - // install GetMessage hook - if (g_wheelSupport == kWheelOld) { + // install GetMessage hook (unless already installed) + if (g_wheelSupport == kWheelOld && g_getMessage == NULL) { g_getMessage = SetWindowsHookEx(WH_GETMESSAGE, &getMessageHook, g_hinstance, @@ -563,9 +599,7 @@ install(DWORD threadID) int uninstall(void) { - assert(g_keyboard != NULL); - assert(g_mouse != NULL); - assert(g_cbt != NULL); + assert(g_hinstance != NULL); // uninstall hooks if (g_keyHookThread != NULL) { @@ -577,17 +611,22 @@ uninstall(void) g_keyHookThread = NULL; g_keyHookThreadID = 0; } - UnhookWindowsHookEx(g_keyboard); - UnhookWindowsHookEx(g_mouse); - UnhookWindowsHookEx(g_cbt); - if (g_getMessage != NULL) { + if (g_keyboard != NULL) { + UnhookWindowsHookEx(g_keyboard); + } + if (g_mouse != NULL) { + UnhookWindowsHookEx(g_mouse); + } + if (g_cbt != NULL) { + UnhookWindowsHookEx(g_cbt); + } + if (g_getMessage != NULL && !g_screenSaver) { UnhookWindowsHookEx(g_getMessage); + g_getMessage = NULL; } g_keyboard = NULL; g_mouse = NULL; g_cbt = NULL; - g_getMessage = NULL; - g_threadID = 0; // show the cursor restoreCursor(); @@ -595,6 +634,47 @@ uninstall(void) return 1; } +int +installScreenSaver(void) +{ + assert(g_hinstance != NULL); + + // must be initialized + if (g_threadID == 0) { + return 0; + } + + // generate screen saver messages + g_screenSaver = true; + + // install hook unless it's already installed + if (g_getMessage == NULL) { + g_getMessage = SetWindowsHookEx(WH_GETMESSAGE, + &getMessageHook, + g_hinstance, + 0); + } + + return (g_getMessage != NULL) ? 1 : 0; +} + +int +uninstallScreenSaver(void) +{ + assert(g_hinstance != NULL); + + // uninstall hook unless the mouse wheel hook is installed + if (g_getMessage != NULL && g_threadID == 0) { + UnhookWindowsHookEx(g_getMessage); + g_getMessage = NULL; + } + + // screen saver hook is no longer installed + g_screenSaver = false; + + return 1; +} + void setZone(UInt32 sides, SInt32 x, SInt32 y, SInt32 w, SInt32 h, diff --git a/server/CSynergyHook.h b/server/CSynergyHook.h index 03f5eb00..026a1c3c 100644 --- a/server/CSynergyHook.h +++ b/server/CSynergyHook.h @@ -22,17 +22,26 @@ #define SYNERGY_MSG_MOUSE_MOVE WM_APP + 0x0014 // x; y #define SYNERGY_MSG_POST_WARP WM_APP + 0x0015 // x; y #define SYNERGY_MSG_MOUSE_WHEEL WM_APP + 0x0016 // delta; +#define SYNERGY_MSG_SCREEN_SAVER WM_APP + 0x0017 // activated; extern "C" { -typedef int (*InstallFunc)(DWORD targetQueueThreadID); +typedef int (*InitFunc)(DWORD targetQueueThreadID); +typedef int (*CleanupFunc)(void); +typedef int (*InstallFunc)(void); typedef int (*UninstallFunc)(void); +typedef int (*InstallScreenSaverFunc)(void); +typedef int (*UninstallScreenSaverFunc)(void); typedef void (*SetZoneFunc)(UInt32, SInt32, SInt32, SInt32, SInt32, SInt32); typedef void (*SetRelayFunc)(void); -CSYNERGYHOOK_API int install(DWORD); +CSYNERGYHOOK_API int init(DWORD); +CSYNERGYHOOK_API int cleanup(void); +CSYNERGYHOOK_API int install(void); CSYNERGYHOOK_API int uninstall(void); +CSYNERGYHOOK_API int installScreenSaver(void); +CSYNERGYHOOK_API int uninstallScreenSaver(void); CSYNERGYHOOK_API void setZone(UInt32 sides, SInt32 x, SInt32 y, SInt32 w, SInt32 h, SInt32 jumpZoneSize);