00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019 #include "CMSWindowsScreen.h"
00020 #include "CMSWindowsClipboard.h"
00021 #include "CMSWindowsDesks.h"
00022 #include "CMSWindowsEventQueueBuffer.h"
00023 #include "CMSWindowsKeyState.h"
00024 #include "CMSWindowsScreenSaver.h"
00025 #include "CClipboard.h"
00026 #include "CKeyMap.h"
00027 #include "XScreen.h"
00028 #include "CLock.h"
00029 #include "CThread.h"
00030 #include "CFunctionJob.h"
00031 #include "CLog.h"
00032 #include "CString.h"
00033 #include "CStringUtil.h"
00034 #include "IEventQueue.h"
00035 #include "TMethodEventJob.h"
00036 #include "TMethodJob.h"
00037 #include "CArch.h"
00038 #include "CArchMiscWindows.h"
00039 #include <string.h>
00040 #include <pbt.h>
00041
00042
00043
00044
00045
00046 #if defined(_MSC_VER)
00047 #pragma warning(push)
00048 #pragma warning(disable: 4706) // assignment within conditional
00049 #define COMPILE_MULTIMON_STUBS
00050 #include <multimon.h>
00051 #pragma warning(pop)
00052 #endif
00053
00054
00055 #if !defined(WM_XBUTTONDOWN)
00056 #define WM_XBUTTONDOWN 0x020B
00057 #define WM_XBUTTONUP 0x020C
00058 #define WM_XBUTTONDBLCLK 0x020D
00059 #define WM_NCXBUTTONDOWN 0x00AB
00060 #define WM_NCXBUTTONUP 0x00AC
00061 #define WM_NCXBUTTONDBLCLK 0x00AD
00062 #define MOUSEEVENTF_XDOWN 0x0080
00063 #define MOUSEEVENTF_XUP 0x0100
00064 #define XBUTTON1 0x0001
00065 #define XBUTTON2 0x0002
00066 #endif
00067 #if !defined(VK_XBUTTON1)
00068 #define VK_XBUTTON1 0x05
00069 #define VK_XBUTTON2 0x06
00070 #endif
00071
00072
00073 #if !defined(PBT_APMRESUMEAUTOMATIC)
00074 #define PBT_APMRESUMEAUTOMATIC 0x0012
00075 #endif
00076
00077
00078
00079
00080
00081 HINSTANCE CMSWindowsScreen::s_windowInstance = NULL;
00082 CMSWindowsScreen* CMSWindowsScreen::s_screen = NULL;
00083
00084 CMSWindowsScreen::CMSWindowsScreen(
00085 bool isPrimary,
00086 bool noHooks,
00087 const CGameDeviceInfo& gameDeviceInfo,
00088 bool stopOnDeskSwitch) :
00089 m_isPrimary(isPrimary),
00090 m_noHooks(noHooks),
00091 m_is95Family(CArchMiscWindows::isWindows95Family()),
00092 m_isOnScreen(m_isPrimary),
00093 m_class(0),
00094 m_x(0), m_y(0),
00095 m_w(0), m_h(0),
00096 m_xCenter(0), m_yCenter(0),
00097 m_multimon(false),
00098 m_xCursor(0), m_yCursor(0),
00099 m_sequenceNumber(0),
00100 m_mark(0),
00101 m_markReceived(0),
00102 m_fixTimer(NULL),
00103 m_keyLayout(NULL),
00104 m_screensaver(NULL),
00105 m_screensaverNotify(false),
00106 m_screensaverActive(false),
00107 m_window(NULL),
00108 m_nextClipboardWindow(NULL),
00109 m_ownClipboard(false),
00110 m_desks(NULL),
00111 m_hookLibrary(NULL),
00112 m_keyState(NULL),
00113 m_hasMouse(GetSystemMetrics(SM_MOUSEPRESENT) != 0),
00114 m_showingMouse(false),
00115 m_gameDeviceInfo(gameDeviceInfo),
00116 m_gameDevice(NULL)
00117 {
00118 assert(s_windowInstance != NULL);
00119 assert(s_screen == NULL);
00120
00121 s_screen = this;
00122 try {
00123 if (m_isPrimary && !m_noHooks) {
00124 m_hookLibrary = openHookLibrary("synrgyhk");
00125 }
00126 m_screensaver = new CMSWindowsScreenSaver();
00127 m_desks = new CMSWindowsDesks(
00128 m_isPrimary, m_noHooks,
00129 m_hookLibrary, m_screensaver,
00130 *EVENTQUEUE,
00131 new TMethodJob<CMSWindowsScreen>(this,
00132 &CMSWindowsScreen::updateKeysCB),
00133 stopOnDeskSwitch);
00134 m_keyState = new CMSWindowsKeyState(m_desks, getEventTarget());
00135 updateScreenShape();
00136 m_class = createWindowClass();
00137 m_window = createWindow(m_class, "Synergy");
00138 forceShowCursor();
00139 LOG((CLOG_DEBUG "screen shape: %d,%d %dx%d %s", m_x, m_y, m_w, m_h, m_multimon ? "(multi-monitor)" : ""));
00140 LOG((CLOG_DEBUG "window is 0x%08x", m_window));
00141 }
00142 catch (...) {
00143 delete m_keyState;
00144 delete m_desks;
00145 delete m_screensaver;
00146 destroyWindow(m_window);
00147 destroyClass(m_class);
00148
00149 if (m_hookLibrary != NULL)
00150 closeHookLibrary(m_hookLibrary);
00151
00152 s_screen = NULL;
00153 throw;
00154 }
00155
00156
00157 EVENTQUEUE->adoptHandler(CEvent::kSystem, IEventQueue::getSystemTarget(),
00158 new TMethodEventJob<CMSWindowsScreen>(this,
00159 &CMSWindowsScreen::handleSystemEvent));
00160
00161
00162 EVENTQUEUE->adoptBuffer(new CMSWindowsEventQueueBuffer);
00163
00164 if ((gameDeviceInfo.m_mode == CGameDeviceInfo::kGameModeXInput) &&
00165 (gameDeviceInfo.m_poll != CGameDeviceInfo::kGamePollDynamic))
00166 LOG((CLOG_WARN "only dynamic polling is supported with xnput."));
00167
00168 if ((gameDeviceInfo.m_mode == CGameDeviceInfo::kGameModeJoyInfoEx) &&
00169 (gameDeviceInfo.m_poll != CGameDeviceInfo::kGamePollStatic))
00170 LOG((CLOG_WARN "only static polling is supported with joyinfoex."));
00171
00172 if (m_gameDeviceInfo.m_mode == CGameDeviceInfo::kGameModeXInput) {
00173 #if GAME_DEVICE_SUPPORT
00174 m_gameDevice = new CMSWindowsXInput(this, gameDeviceInfo);
00175 #else if _AMD64_
00176 LOG((CLOG_WARN "xinput game device mode not supported for 64-bit."));
00177 #endif
00178 }
00179 else {
00180 m_gameDevice = new CEventGameDevice(getEventTarget());
00181 }
00182 }
00183
00184 CMSWindowsScreen::~CMSWindowsScreen()
00185 {
00186 assert(s_screen != NULL);
00187
00188 disable();
00189 EVENTQUEUE->adoptBuffer(NULL);
00190 EVENTQUEUE->removeHandler(CEvent::kSystem, IEventQueue::getSystemTarget());
00191 delete m_keyState;
00192 delete m_desks;
00193 delete m_screensaver;
00194 destroyWindow(m_window);
00195 destroyClass(m_class);
00196
00197 if (m_gameDevice != NULL)
00198 delete m_gameDevice;
00199
00200 if (m_hookLibrary != NULL)
00201 closeHookLibrary(m_hookLibrary);
00202
00203 s_screen = NULL;
00204 }
00205
00206 void
00207 CMSWindowsScreen::init(HINSTANCE windowInstance)
00208 {
00209 assert(s_windowInstance == NULL);
00210 assert(windowInstance != NULL);
00211
00212 s_windowInstance = windowInstance;
00213 }
00214
00215 HINSTANCE
00216 CMSWindowsScreen::getWindowInstance()
00217 {
00218 return s_windowInstance;
00219 }
00220
00221 void
00222 CMSWindowsScreen::enable()
00223 {
00224 assert(m_isOnScreen == m_isPrimary);
00225
00226
00227 m_fixTimer = EVENTQUEUE->newTimer(1.0, NULL);
00228 EVENTQUEUE->adoptHandler(CEvent::kTimer, m_fixTimer,
00229 new TMethodEventJob<CMSWindowsScreen>(this,
00230 &CMSWindowsScreen::handleFixes));
00231
00232
00233 m_nextClipboardWindow = SetClipboardViewer(m_window);
00234
00235
00236 m_desks->enable();
00237
00238 if (m_isPrimary) {
00239 if (m_hookLibrary != NULL) {
00240
00241 m_hookLibraryLoader.m_setZone(m_x, m_y, m_w, m_h, getJumpZoneSize());
00242
00243
00244 m_hookLibraryLoader.m_setMode(kHOOK_WATCH_JUMP_ZONE);
00245 }
00246 }
00247 else {
00248
00249
00250
00251 CArchMiscWindows::addBusyState(CArchMiscWindows::kSYSTEM);
00252 }
00253 }
00254
00255 void
00256 CMSWindowsScreen::disable()
00257 {
00258
00259 m_desks->disable();
00260
00261 if (m_isPrimary) {
00262 if (m_hookLibrary != NULL) {
00263
00264 m_hookLibraryLoader.m_setMode(kHOOK_DISABLE);
00265 }
00266
00267
00268 enableSpecialKeys(true);
00269 }
00270 else {
00271
00272 CArchMiscWindows::removeBusyState(CArchMiscWindows::kSYSTEM |
00273 CArchMiscWindows::kDISPLAY);
00274 }
00275
00276
00277 m_keyState->disable();
00278
00279
00280 ChangeClipboardChain(m_window, m_nextClipboardWindow);
00281 m_nextClipboardWindow = NULL;
00282
00283
00284 if (m_fixTimer != NULL) {
00285 EVENTQUEUE->removeHandler(CEvent::kTimer, m_fixTimer);
00286 EVENTQUEUE->deleteTimer(m_fixTimer);
00287 m_fixTimer = NULL;
00288 }
00289
00290 m_isOnScreen = m_isPrimary;
00291 forceShowCursor();
00292 }
00293
00294 void
00295 CMSWindowsScreen::enter()
00296 {
00297 m_desks->enter();
00298 if (m_isPrimary) {
00299
00300 enableSpecialKeys(true);
00301
00302 if (m_hookLibrary != NULL) {
00303
00304 m_hookLibraryLoader.m_setMode(kHOOK_WATCH_JUMP_ZONE);
00305 }
00306
00307
00308 nextMark();
00309 } else {
00310
00311
00312 CArchMiscWindows::wakeupDisplay();
00313
00314 if(m_screensaver != NULL && m_screensaverActive)
00315 {
00316 m_screensaver->deactivate();
00317 m_screensaverActive = 0;
00318 }
00319 }
00320
00321
00322 m_isOnScreen = true;
00323 forceShowCursor();
00324 }
00325
00326 bool
00327 CMSWindowsScreen::leave()
00328 {
00329
00330
00331 HWND window = GetForegroundWindow();
00332 DWORD thread = GetWindowThreadProcessId(window, NULL);
00333 m_keyLayout = GetKeyboardLayout(thread);
00334
00335
00336 m_keyState->setKeyLayout(m_keyLayout);
00337
00338
00339 m_desks->leave(m_keyLayout);
00340
00341 if (m_isPrimary) {
00342
00343
00344 LOG((CLOG_DEBUG1 "warping cursor to center: %+d, %+d", m_xCenter, m_yCenter));
00345 warpCursor(m_xCenter, m_yCenter);
00346
00347
00348 enableSpecialKeys(false);
00349
00350
00351 nextMark();
00352
00353
00354
00355 m_keyState->saveModifiers();
00356
00357 if (m_hookLibrary != NULL) {
00358
00359 m_hookLibraryLoader.m_setMode(kHOOK_RELAY_EVENTS);
00360 }
00361 }
00362
00363
00364 m_isOnScreen = false;
00365 forceShowCursor();
00366
00367 return true;
00368 }
00369
00370 bool
00371 CMSWindowsScreen::setClipboard(ClipboardID, const IClipboard* src)
00372 {
00373 CMSWindowsClipboard dst(m_window);
00374 if (src != NULL) {
00375
00376 return CClipboard::copy(&dst, src);
00377 }
00378 else {
00379
00380 if (!dst.open(0)) {
00381 return false;
00382 }
00383 dst.empty();
00384 dst.close();
00385 return true;
00386 }
00387 }
00388
00389 void
00390 CMSWindowsScreen::checkClipboards()
00391 {
00392
00393
00394
00395
00396
00397
00398
00399
00400
00401
00402
00403 if (m_ownClipboard && !CMSWindowsClipboard::isOwnedBySynergy()) {
00404 LOG((CLOG_DEBUG "clipboard changed: lost ownership and no notification received"));
00405 m_ownClipboard = false;
00406 sendClipboardEvent(getClipboardGrabbedEvent(), kClipboardClipboard);
00407 sendClipboardEvent(getClipboardGrabbedEvent(), kClipboardSelection);
00408 }
00409 }
00410
00411 void
00412 CMSWindowsScreen::openScreensaver(bool notify)
00413 {
00414 assert(m_screensaver != NULL);
00415
00416 m_screensaverNotify = notify;
00417 if (m_screensaverNotify) {
00418 m_desks->installScreensaverHooks(true);
00419 }
00420 else if (m_screensaver) {
00421 m_screensaver->disable();
00422 }
00423 }
00424
00425 void
00426 CMSWindowsScreen::closeScreensaver()
00427 {
00428 if (m_screensaver != NULL) {
00429 if (m_screensaverNotify) {
00430 m_desks->installScreensaverHooks(false);
00431 }
00432 else {
00433 m_screensaver->enable();
00434 }
00435 }
00436 m_screensaverNotify = false;
00437 }
00438
00439 void
00440 CMSWindowsScreen::screensaver(bool activate)
00441 {
00442 assert(m_screensaver != NULL);
00443 if (m_screensaver==NULL) return;
00444
00445 if (activate) {
00446 m_screensaver->activate();
00447 }
00448 else {
00449 m_screensaver->deactivate();
00450 }
00451 }
00452
00453 void
00454 CMSWindowsScreen::resetOptions()
00455 {
00456 m_desks->resetOptions();
00457 }
00458
00459 void
00460 CMSWindowsScreen::setOptions(const COptionsList& options)
00461 {
00462 m_desks->setOptions(options);
00463 }
00464
00465 void
00466 CMSWindowsScreen::setSequenceNumber(UInt32 seqNum)
00467 {
00468 m_sequenceNumber = seqNum;
00469 }
00470
00471 bool
00472 CMSWindowsScreen::isPrimary() const
00473 {
00474 return m_isPrimary;
00475 }
00476
00477 void*
00478 CMSWindowsScreen::getEventTarget() const
00479 {
00480 return const_cast<CMSWindowsScreen*>(this);
00481 }
00482
00483 bool
00484 CMSWindowsScreen::getClipboard(ClipboardID, IClipboard* dst) const
00485 {
00486 CMSWindowsClipboard src(m_window);
00487 CClipboard::copy(dst, &src);
00488 return true;
00489 }
00490
00491 void
00492 CMSWindowsScreen::getShape(SInt32& x, SInt32& y, SInt32& w, SInt32& h) const
00493 {
00494 assert(m_class != 0);
00495
00496 x = m_x;
00497 y = m_y;
00498 w = m_w;
00499 h = m_h;
00500 }
00501
00502 void
00503 CMSWindowsScreen::getCursorPos(SInt32& x, SInt32& y) const
00504 {
00505 m_desks->getCursorPos(x, y);
00506 }
00507
00508 void
00509 CMSWindowsScreen::reconfigure(UInt32 activeSides)
00510 {
00511 assert(m_isPrimary);
00512
00513 LOG((CLOG_DEBUG "active sides: %x", activeSides));
00514
00515 if (m_hookLibrary != NULL)
00516 m_hookLibraryLoader.m_setSides(activeSides);
00517 }
00518
00519 void
00520 CMSWindowsScreen::warpCursor(SInt32 x, SInt32 y)
00521 {
00522
00523 warpCursorNoFlush(x, y);
00524
00525
00526 MSG msg;
00527 while (PeekMessage(&msg, NULL, SYNERGY_MSG_INPUT_FIRST,
00528 SYNERGY_MSG_INPUT_LAST, PM_REMOVE)) {
00529
00530 }
00531
00532
00533 saveMousePosition(x, y);
00534 }
00535
00536 void CMSWindowsScreen::saveMousePosition(SInt32 x, SInt32 y) {
00537
00538 m_xCursor = x;
00539 m_yCursor = y;
00540
00541 LOG((CLOG_DEBUG5 "saved mouse position for next delta: %+d,%+d", x,y));
00542 }
00543
00544 UInt32
00545 CMSWindowsScreen::registerHotKey(KeyID key, KeyModifierMask mask)
00546 {
00547
00548 if ((mask & ~(KeyModifierShift | KeyModifierControl |
00549 KeyModifierAlt | KeyModifierSuper)) != 0) {
00550
00551
00552 LOG((CLOG_DEBUG "could not map hotkey id=%04x mask=%04x", key, mask));
00553 return 0;
00554 }
00555
00556
00557 if (key == kKeyNone && mask == 0) {
00558 return 0;
00559 }
00560
00561
00562 UINT modifiers = 0;
00563 if ((mask & KeyModifierShift) != 0) {
00564 modifiers |= MOD_SHIFT;
00565 }
00566 if ((mask & KeyModifierControl) != 0) {
00567 modifiers |= MOD_CONTROL;
00568 }
00569 if ((mask & KeyModifierAlt) != 0) {
00570 modifiers |= MOD_ALT;
00571 }
00572 if ((mask & KeyModifierSuper) != 0) {
00573 modifiers |= MOD_WIN;
00574 }
00575 UINT vk = m_keyState->mapKeyToVirtualKey(key);
00576 if (key != kKeyNone && vk == 0) {
00577
00578
00579
00580 LOG((CLOG_DEBUG "could not map hotkey id=%04x mask=%04x", key, mask));
00581 return 0;
00582 }
00583
00584
00585 UInt32 id;
00586 if (!m_oldHotKeyIDs.empty()) {
00587 id = m_oldHotKeyIDs.back();
00588 m_oldHotKeyIDs.pop_back();
00589 }
00590 else {
00591
00592 id = (UInt32)m_hotKeys.size() + 1;
00593 }
00594
00595
00596 bool err;
00597 if (key == kKeyNone) {
00598
00599 err = (m_hotKeyToIDMap.count(CHotKeyItem(vk, modifiers)) > 0);
00600 }
00601 else {
00602
00603 err = (RegisterHotKey(NULL, id, modifiers, vk) == 0);
00604 }
00605
00606 if (!err) {
00607 m_hotKeys.insert(std::make_pair(id, CHotKeyItem(vk, modifiers)));
00608 m_hotKeyToIDMap[CHotKeyItem(vk, modifiers)] = id;
00609 }
00610 else {
00611 m_oldHotKeyIDs.push_back(id);
00612 m_hotKeys.erase(id);
00613 LOG((CLOG_WARN "failed to register hotkey %s (id=%04x mask=%04x)", CKeyMap::formatKey(key, mask).c_str(), key, mask));
00614 return 0;
00615 }
00616
00617 LOG((CLOG_DEBUG "registered hotkey %s (id=%04x mask=%04x) as id=%d", CKeyMap::formatKey(key, mask).c_str(), key, mask, id));
00618 return id;
00619 }
00620
00621 void
00622 CMSWindowsScreen::unregisterHotKey(UInt32 id)
00623 {
00624
00625 HotKeyMap::iterator i = m_hotKeys.find(id);
00626 if (i == m_hotKeys.end()) {
00627 return;
00628 }
00629
00630
00631 bool err;
00632 if (i->second.getVirtualKey() != 0) {
00633 err = !UnregisterHotKey(NULL, id);
00634 }
00635 else {
00636 err = false;
00637 }
00638 if (err) {
00639 LOG((CLOG_WARN "failed to unregister hotkey id=%d", id));
00640 }
00641 else {
00642 LOG((CLOG_DEBUG "unregistered hotkey id=%d", id));
00643 }
00644
00645
00646 m_hotKeyToIDMap.erase(i->second);
00647 m_hotKeys.erase(i);
00648 m_oldHotKeyIDs.push_back(id);
00649 }
00650
00651 void
00652 CMSWindowsScreen::fakeInputBegin()
00653 {
00654 assert(m_isPrimary);
00655
00656 if (!m_isOnScreen) {
00657 m_keyState->useSavedModifiers(true);
00658 }
00659 m_desks->fakeInputBegin();
00660 }
00661
00662 void
00663 CMSWindowsScreen::fakeInputEnd()
00664 {
00665 assert(m_isPrimary);
00666
00667 m_desks->fakeInputEnd();
00668 if (!m_isOnScreen) {
00669 m_keyState->useSavedModifiers(false);
00670 }
00671 }
00672
00673 SInt32
00674 CMSWindowsScreen::getJumpZoneSize() const
00675 {
00676 return 1;
00677 }
00678
00679 bool
00680 CMSWindowsScreen::isAnyMouseButtonDown() const
00681 {
00682 static const char* buttonToName[] = {
00683 "<invalid>",
00684 "Left Button",
00685 "Middle Button",
00686 "Right Button",
00687 "X Button 1",
00688 "X Button 2"
00689 };
00690
00691 for (UInt32 i = 1; i < sizeof(m_buttons) / sizeof(m_buttons[0]); ++i) {
00692 if (m_buttons[i]) {
00693 LOG((CLOG_DEBUG "locked by \"%s\"", buttonToName[i]));
00694 return true;
00695 }
00696 }
00697
00698 return false;
00699 }
00700
00701 void
00702 CMSWindowsScreen::getCursorCenter(SInt32& x, SInt32& y) const
00703 {
00704 x = m_xCenter;
00705 y = m_yCenter;
00706 }
00707
00708 void
00709 CMSWindowsScreen::gameDeviceTimingResp(UInt16 freq)
00710 {
00711 m_gameDevice->gameDeviceTimingResp(freq);
00712 }
00713
00714 void
00715 CMSWindowsScreen::gameDeviceFeedback(GameDeviceID id, UInt16 m1, UInt16 m2)
00716 {
00717 m_gameDevice->gameDeviceFeedback(id, m1, m2);
00718 }
00719
00720 void
00721 CMSWindowsScreen::fakeMouseButton(ButtonID id, bool press)
00722 {
00723 m_desks->fakeMouseButton(id, press);
00724 }
00725
00726 void
00727 CMSWindowsScreen::fakeMouseMove(SInt32 x, SInt32 y) const
00728 {
00729 m_desks->fakeMouseMove(x, y);
00730 }
00731
00732 void
00733 CMSWindowsScreen::fakeMouseRelativeMove(SInt32 dx, SInt32 dy) const
00734 {
00735 m_desks->fakeMouseRelativeMove(dx, dy);
00736 }
00737
00738 void
00739 CMSWindowsScreen::fakeMouseWheel(SInt32 xDelta, SInt32 yDelta) const
00740 {
00741 m_desks->fakeMouseWheel(xDelta, yDelta);
00742 }
00743
00744 void
00745 CMSWindowsScreen::fakeGameDeviceButtons(GameDeviceID id, GameDeviceButton buttons) const
00746 {
00747 LOG((CLOG_DEBUG "fake game device buttons id=%d buttons=%d", id, buttons));
00748 m_gameDevice->fakeGameDeviceButtons(id, buttons);
00749 }
00750
00751 void
00752 CMSWindowsScreen::fakeGameDeviceSticks(GameDeviceID id, SInt16 x1, SInt16 y1, SInt16 x2, SInt16 y2) const
00753 {
00754 LOG((CLOG_DEBUG "fake game device sticks id=%d s1=%+d,%+d s2=%+d,%+d", id, x1, y1, x2, y2));
00755 m_gameDevice->fakeGameDeviceSticks(id, x1, y1, x2, y2);
00756 }
00757
00758 void
00759 CMSWindowsScreen::fakeGameDeviceTriggers(GameDeviceID id, UInt8 t1, UInt8 t2) const
00760 {
00761 LOG((CLOG_DEBUG "fake game device triggers id=%d t1=%d t2=%d", id, t1, t2));
00762 m_gameDevice->fakeGameDeviceTriggers(id, t1, t2);
00763 }
00764
00765 void
00766 CMSWindowsScreen::queueGameDeviceTimingReq() const
00767 {
00768 LOG((CLOG_DEBUG "queue game device timing request"));
00769 m_gameDevice->queueGameDeviceTimingReq();
00770 }
00771
00772 void
00773 CMSWindowsScreen::updateKeys()
00774 {
00775 m_desks->updateKeys();
00776 }
00777
00778 void
00779 CMSWindowsScreen::fakeKeyDown(KeyID id, KeyModifierMask mask,
00780 KeyButton button)
00781 {
00782 CPlatformScreen::fakeKeyDown(id, mask, button);
00783 updateForceShowCursor();
00784 }
00785
00786 bool
00787 CMSWindowsScreen::fakeKeyRepeat(KeyID id, KeyModifierMask mask,
00788 SInt32 count, KeyButton button)
00789 {
00790 bool result = CPlatformScreen::fakeKeyRepeat(id, mask, count, button);
00791 updateForceShowCursor();
00792 return result;
00793 }
00794
00795 bool
00796 CMSWindowsScreen::fakeKeyUp(KeyButton button)
00797 {
00798 bool result = CPlatformScreen::fakeKeyUp(button);
00799 updateForceShowCursor();
00800 return result;
00801 }
00802
00803 void
00804 CMSWindowsScreen::fakeAllKeysUp()
00805 {
00806 CPlatformScreen::fakeAllKeysUp();
00807 updateForceShowCursor();
00808 }
00809
00810 HINSTANCE
00811 CMSWindowsScreen::openHookLibrary(const char* name)
00812 {
00813 return m_hookLibraryLoader.openHookLibrary(name);
00814 }
00815
00816 void
00817 CMSWindowsScreen::closeHookLibrary(HINSTANCE hookLibrary) const
00818 {
00819 if (hookLibrary != NULL) {
00820 m_hookLibraryLoader.m_cleanup();
00821 FreeLibrary(hookLibrary);
00822 }
00823 }
00824
00825 HCURSOR
00826 CMSWindowsScreen::createBlankCursor() const
00827 {
00828
00829 int cw = GetSystemMetrics(SM_CXCURSOR);
00830 int ch = GetSystemMetrics(SM_CYCURSOR);
00831
00832 UInt8* cursorAND = new UInt8[ch * ((cw + 31) >> 2)];
00833 UInt8* cursorXOR = new UInt8[ch * ((cw + 31) >> 2)];
00834 memset(cursorAND, 0xff, ch * ((cw + 31) >> 2));
00835 memset(cursorXOR, 0x00, ch * ((cw + 31) >> 2));
00836 HCURSOR c = CreateCursor(s_windowInstance, 0, 0, cw, ch, cursorAND, cursorXOR);
00837 delete[] cursorXOR;
00838 delete[] cursorAND;
00839 return c;
00840 }
00841
00842 void
00843 CMSWindowsScreen::destroyCursor(HCURSOR cursor) const
00844 {
00845 if (cursor != NULL) {
00846 DestroyCursor(cursor);
00847 }
00848 }
00849
00850 ATOM
00851 CMSWindowsScreen::createWindowClass() const
00852 {
00853 WNDCLASSEX classInfo;
00854 classInfo.cbSize = sizeof(classInfo);
00855 classInfo.style = CS_DBLCLKS | CS_NOCLOSE;
00856 classInfo.lpfnWndProc = &CMSWindowsScreen::wndProc;
00857 classInfo.cbClsExtra = 0;
00858 classInfo.cbWndExtra = 0;
00859 classInfo.hInstance = s_windowInstance;
00860 classInfo.hIcon = NULL;
00861 classInfo.hCursor = NULL;
00862 classInfo.hbrBackground = NULL;
00863 classInfo.lpszMenuName = NULL;
00864 classInfo.lpszClassName = "Synergy";
00865 classInfo.hIconSm = NULL;
00866 return RegisterClassEx(&classInfo);
00867 }
00868
00869 void
00870 CMSWindowsScreen::destroyClass(ATOM windowClass) const
00871 {
00872 if (windowClass != 0) {
00873 UnregisterClass(reinterpret_cast<LPCTSTR>(windowClass), s_windowInstance);
00874 }
00875 }
00876
00877 HWND
00878 CMSWindowsScreen::createWindow(ATOM windowClass, const char* name) const
00879 {
00880 HWND window = CreateWindowEx(WS_EX_TOPMOST |
00881 WS_EX_TRANSPARENT |
00882 WS_EX_TOOLWINDOW,
00883 reinterpret_cast<LPCTSTR>(windowClass),
00884 name,
00885 WS_POPUP,
00886 0, 0, 1, 1,
00887 NULL, NULL,
00888 s_windowInstance,
00889 NULL);
00890 if (window == NULL) {
00891 LOG((CLOG_ERR "failed to create window: %d", GetLastError()));
00892 throw XScreenOpenFailure();
00893 }
00894 return window;
00895 }
00896
00897 void
00898 CMSWindowsScreen::destroyWindow(HWND hwnd) const
00899 {
00900 if (hwnd != NULL) {
00901 DestroyWindow(hwnd);
00902 }
00903 }
00904
00905 void
00906 CMSWindowsScreen::sendEvent(CEvent::Type type, void* data)
00907 {
00908 EVENTQUEUE->addEvent(CEvent(type, getEventTarget(), data));
00909 }
00910
00911 void
00912 CMSWindowsScreen::sendClipboardEvent(CEvent::Type type, ClipboardID id)
00913 {
00914 CClipboardInfo* info = (CClipboardInfo*)malloc(sizeof(CClipboardInfo));
00915 if(info == NULL) {
00916 LOG((CLOG_ERR "malloc failed on %s:%s", __FILE__, __LINE__ ));
00917 return;
00918 }
00919 info->m_id = id;
00920 info->m_sequenceNumber = m_sequenceNumber;
00921 sendEvent(type, info);
00922 }
00923
00924 void
00925 CMSWindowsScreen::handleSystemEvent(const CEvent& event, void*)
00926 {
00927 MSG* msg = reinterpret_cast<MSG*>(event.getData());
00928 assert(msg != NULL);
00929
00930 if (CArchMiscWindows::processDialog(msg)) {
00931 return;
00932 }
00933 if (onPreDispatch(msg->hwnd, msg->message, msg->wParam, msg->lParam)) {
00934 return;
00935 }
00936 TranslateMessage(msg);
00937 DispatchMessage(msg);
00938 }
00939
00940 void
00941 CMSWindowsScreen::updateButtons()
00942 {
00943 int numButtons = GetSystemMetrics(SM_CMOUSEBUTTONS);
00944 m_buttons[kButtonNone] = false;
00945 m_buttons[kButtonLeft] = (GetKeyState(VK_LBUTTON) < 0);
00946 m_buttons[kButtonRight] = (GetKeyState(VK_RBUTTON) < 0);
00947 m_buttons[kButtonMiddle] = (GetKeyState(VK_MBUTTON) < 0);
00948 m_buttons[kButtonExtra0 + 0] = (numButtons >= 4) &&
00949 (GetKeyState(VK_XBUTTON1) < 0);
00950 m_buttons[kButtonExtra0 + 1] = (numButtons >= 5) &&
00951 (GetKeyState(VK_XBUTTON2) < 0);
00952 }
00953
00954 IKeyState*
00955 CMSWindowsScreen::getKeyState() const
00956 {
00957 return m_keyState;
00958 }
00959
00960 bool
00961 CMSWindowsScreen::onPreDispatch(HWND hwnd,
00962 UINT message, WPARAM wParam, LPARAM lParam)
00963 {
00964
00965 switch (message) {
00966 case SYNERGY_MSG_SCREEN_SAVER:
00967 return onScreensaver(wParam != 0);
00968
00969 case SYNERGY_MSG_DEBUG:
00970 LOG((CLOG_DEBUG1 "hook: 0x%08x 0x%08x", wParam, lParam));
00971 return true;
00972 }
00973
00974 if (m_isPrimary) {
00975 return onPreDispatchPrimary(hwnd, message, wParam, lParam);
00976 }
00977
00978 return false;
00979 }
00980
00981 bool
00982 CMSWindowsScreen::onPreDispatchPrimary(HWND,
00983 UINT message, WPARAM wParam, LPARAM lParam)
00984 {
00985 LOG((CLOG_DEBUG5 "handling pre-dispatch primary"));
00986
00987
00988 switch (message) {
00989 case SYNERGY_MSG_MARK:
00990 return onMark(static_cast<UInt32>(wParam));
00991
00992 case SYNERGY_MSG_KEY:
00993 return onKey(wParam, lParam);
00994
00995 case SYNERGY_MSG_MOUSE_BUTTON:
00996 return onMouseButton(wParam, lParam);
00997
00998 case SYNERGY_MSG_MOUSE_MOVE:
00999 return onMouseMove(static_cast<SInt32>(wParam),
01000 static_cast<SInt32>(lParam));
01001
01002 case SYNERGY_MSG_MOUSE_WHEEL:
01003
01004 return onMouseWheel(0, static_cast<SInt32>(wParam));
01005
01006 case SYNERGY_MSG_PRE_WARP:
01007 {
01008
01009 saveMousePosition(static_cast<SInt32>(wParam), static_cast<SInt32>(lParam));
01010
01011
01012
01013
01014
01015
01016 MSG msg;
01017 do {
01018 GetMessage(&msg, NULL, SYNERGY_MSG_MOUSE_MOVE,
01019 SYNERGY_MSG_POST_WARP);
01020 } while (msg.message != SYNERGY_MSG_POST_WARP);
01021 }
01022 return true;
01023
01024 case SYNERGY_MSG_POST_WARP:
01025 LOG((CLOG_WARN "unmatched post warp"));
01026 return true;
01027
01028 case WM_HOTKEY:
01029
01030
01031
01032
01033 break;
01034 }
01035
01036 return false;
01037 }
01038
01039 bool
01040 CMSWindowsScreen::onEvent(HWND, UINT msg,
01041 WPARAM wParam, LPARAM lParam, LRESULT* result)
01042 {
01043 switch (msg) {
01044 case WM_QUERYENDSESSION:
01045 if (m_is95Family) {
01046 *result = TRUE;
01047 return true;
01048 }
01049 break;
01050
01051 case WM_ENDSESSION:
01052 if (m_is95Family) {
01053 if (wParam == TRUE && lParam == 0) {
01054 EVENTQUEUE->addEvent(CEvent(CEvent::kQuit));
01055 }
01056 return true;
01057 }
01058 break;
01059
01060 case WM_DRAWCLIPBOARD:
01061
01062 if (m_nextClipboardWindow != NULL) {
01063 SendMessage(m_nextClipboardWindow, msg, wParam, lParam);
01064 }
01065
01066
01067 return onClipboardChange();
01068
01069 case WM_CHANGECBCHAIN:
01070 if (m_nextClipboardWindow == (HWND)wParam) {
01071 m_nextClipboardWindow = (HWND)lParam;
01072 LOG((CLOG_DEBUG "clipboard chain: new next: 0x%08x", m_nextClipboardWindow));
01073 }
01074 else if (m_nextClipboardWindow != NULL) {
01075 SendMessage(m_nextClipboardWindow, msg, wParam, lParam);
01076 }
01077 return true;
01078
01079 case WM_DISPLAYCHANGE:
01080 return onDisplayChange();
01081
01082 case WM_POWERBROADCAST:
01083 switch (wParam) {
01084 case PBT_APMRESUMEAUTOMATIC:
01085 case PBT_APMRESUMECRITICAL:
01086 case PBT_APMRESUMESUSPEND:
01087 EVENTQUEUE->addEvent(CEvent(IScreen::getResumeEvent(),
01088 getEventTarget(), NULL,
01089 CEvent::kDeliverImmediately));
01090 break;
01091
01092 case PBT_APMSUSPEND:
01093 EVENTQUEUE->addEvent(CEvent(IScreen::getSuspendEvent(),
01094 getEventTarget(), NULL,
01095 CEvent::kDeliverImmediately));
01096 break;
01097 }
01098 *result = TRUE;
01099 return true;
01100
01101 case WM_DEVICECHANGE:
01102 forceShowCursor();
01103 break;
01104
01105 case WM_SETTINGCHANGE:
01106 if (wParam == SPI_SETMOUSEKEYS) {
01107 forceShowCursor();
01108 }
01109 break;
01110 }
01111
01112 return false;
01113 }
01114
01115 bool
01116 CMSWindowsScreen::onMark(UInt32 mark)
01117 {
01118 m_markReceived = mark;
01119 return true;
01120 }
01121
01122 bool
01123 CMSWindowsScreen::onKey(WPARAM wParam, LPARAM lParam)
01124 {
01125 static const KeyModifierMask s_ctrlAlt =
01126 KeyModifierControl | KeyModifierAlt;
01127
01128 LOG((CLOG_DEBUG1 "event: Key char=%d, vk=0x%02x, nagr=%d, lParam=0x%08x", (wParam & 0xff00u) >> 8, wParam & 0xffu, (wParam & 0x10000u) ? 1 : 0, lParam));
01129
01130
01131 KeyButton button = (KeyButton)((lParam & 0x01ff0000) >> 16);
01132 bool down = ((lParam & 0x80000000u) == 0x00000000u);
01133 bool wasDown = isKeyDown(button);
01134 KeyModifierMask oldState = pollActiveModifiers();
01135
01136
01137 if (m_keyState->testAutoRepeat(down, (lParam & 0x40000000u) == 1, button)) {
01138 lParam |= 0x40000000u;
01139 }
01140
01141
01142
01143
01144
01145 if (button == 0) {
01146 button = m_keyState->virtualKeyToButton(wParam & 0xffu);
01147 if (button == 0) {
01148 return true;
01149 }
01150 wasDown = isKeyDown(button);
01151 }
01152
01153
01154 m_keyState->onKey(button, down, oldState);
01155
01156
01157
01158
01159
01160
01161
01162
01163
01164
01165
01166
01167
01168
01169
01170
01171
01172
01173
01174 KeyModifierMask state = pollActiveModifiers();
01175 m_keyState->onKey(button, down, state);
01176
01177
01178 if (oldState != state) {
01179
01180 if (onHotKey(0, lParam)) {
01181 return true;
01182 }
01183 }
01184 else {
01185
01186 if (onHotKey(wParam, lParam)) {
01187 return true;
01188 }
01189 }
01190
01191
01192 if (!ignore()) {
01193
01194
01195 UINT virtKey = (wParam & 0xffu);
01196 if (virtKey == VK_DELETE && (state & s_ctrlAlt) == s_ctrlAlt) {
01197 LOG((CLOG_DEBUG "discard ctrl+alt+del"));
01198 return true;
01199 }
01200
01201
01202 if ((virtKey == VK_PAUSE || virtKey == VK_CANCEL) &&
01203 (state & s_ctrlAlt) == s_ctrlAlt) {
01204 LOG((CLOG_DEBUG "emulate ctrl+alt+del"));
01205
01206
01207
01208
01209 wParam = VK_DELETE | 0x00010000u;
01210 lParam &= 0xfe000000;
01211 lParam |= m_keyState->virtualKeyToButton(wParam & 0xffu) << 16;
01212 lParam |= 0x01000001;
01213 }
01214
01215
01216 KeyModifierMask mask;
01217 KeyID key = m_keyState->mapKeyFromEvent(wParam, lParam, &mask);
01218 button = static_cast<KeyButton>((lParam & 0x01ff0000u) >> 16);
01219 if (key != kKeyNone) {
01220
01221
01222
01223
01224
01225
01226 if (m_is95Family && !wasDown && !down) {
01227 switch (virtKey) {
01228 case VK_SHIFT:
01229 case VK_LSHIFT:
01230 case VK_RSHIFT:
01231 case VK_CONTROL:
01232 case VK_LCONTROL:
01233 case VK_RCONTROL:
01234 case VK_MENU:
01235 case VK_LMENU:
01236 case VK_RMENU:
01237 case VK_LWIN:
01238 case VK_RWIN:
01239 case VK_CAPITAL:
01240 case VK_NUMLOCK:
01241 case VK_SCROLL:
01242 break;
01243
01244 default:
01245 m_keyState->sendKeyEvent(getEventTarget(),
01246 true, false, key, mask, 1, button);
01247 break;
01248 }
01249 }
01250
01251
01252 m_keyState->sendKeyEvent(getEventTarget(),
01253 ((lParam & 0x80000000u) == 0),
01254 ((lParam & 0x40000000u) != 0),
01255 key, mask, (SInt32)(lParam & 0xffff), button);
01256 }
01257 else {
01258 LOG((CLOG_DEBUG1 "cannot map key"));
01259 }
01260 }
01261
01262 return true;
01263 }
01264
01265 bool
01266 CMSWindowsScreen::onHotKey(WPARAM wParam, LPARAM lParam)
01267 {
01268
01269 KeyModifierMask state = getActiveModifiers();
01270 UINT virtKey = (wParam & 0xffu);
01271 UINT modifiers = 0;
01272 if ((state & KeyModifierShift) != 0) {
01273 modifiers |= MOD_SHIFT;
01274 }
01275 if ((state & KeyModifierControl) != 0) {
01276 modifiers |= MOD_CONTROL;
01277 }
01278 if ((state & KeyModifierAlt) != 0) {
01279 modifiers |= MOD_ALT;
01280 }
01281 if ((state & KeyModifierSuper) != 0) {
01282 modifiers |= MOD_WIN;
01283 }
01284
01285
01286 HotKeyToIDMap::const_iterator i =
01287 m_hotKeyToIDMap.find(CHotKeyItem(virtKey, modifiers));
01288 if (i == m_hotKeyToIDMap.end()) {
01289 return false;
01290 }
01291
01292
01293 CEvent::Type type;
01294 if ((lParam & 0x80000000u) == 0u) {
01295 if ((lParam & 0x40000000u) != 0u) {
01296
01297 return true;
01298 }
01299 type = getHotKeyDownEvent();
01300 }
01301 else {
01302 type = getHotKeyUpEvent();
01303 }
01304
01305
01306 EVENTQUEUE->addEvent(CEvent(type, getEventTarget(),
01307 CHotKeyInfo::alloc(i->second)));
01308
01309 return true;
01310 }
01311
01312 bool
01313 CMSWindowsScreen::onMouseButton(WPARAM wParam, LPARAM lParam)
01314 {
01315
01316 bool pressed = mapPressFromEvent(wParam, lParam);
01317 ButtonID button = mapButtonFromEvent(wParam, lParam);
01318
01319
01320 if (button >= kButtonLeft && button <= kButtonExtra0 + 1) {
01321 if (pressed) {
01322 m_buttons[button] = true;
01323 }
01324 else {
01325 m_buttons[button] = false;
01326 }
01327 }
01328
01329
01330 if (!ignore()) {
01331 KeyModifierMask mask = m_keyState->getActiveModifiers();
01332 if (pressed) {
01333 LOG((CLOG_DEBUG1 "event: button press button=%d", button));
01334 if (button != kButtonNone) {
01335 sendEvent(getButtonDownEvent(),
01336 CButtonInfo::alloc(button, mask));
01337 }
01338 }
01339 else {
01340 LOG((CLOG_DEBUG1 "event: button release button=%d", button));
01341 if (button != kButtonNone) {
01342 sendEvent(getButtonUpEvent(),
01343 CButtonInfo::alloc(button, mask));
01344 }
01345 }
01346 }
01347
01348 return true;
01349 }
01350
01351
01352
01353
01354
01355
01356
01357
01358
01359 bool
01360 CMSWindowsScreen::onMouseMove(SInt32 mx, SInt32 my)
01361 {
01362
01363
01364 SInt32 x = mx - m_xCursor;
01365 SInt32 y = my - m_yCursor;
01366
01367 LOG((CLOG_DEBUG3
01368 "mouse move - motion delta: %+d=(%+d - %+d),%+d=(%+d - %+d)",
01369 x, mx, m_xCursor, y, my, m_yCursor));
01370
01371
01372
01373 if (ignore() || (x == 0 && y == 0)) {
01374 return true;
01375 }
01376
01377
01378 saveMousePosition(mx, my);
01379
01380 if (m_isOnScreen) {
01381
01382
01383 sendEvent(
01384 getMotionOnPrimaryEvent(),
01385 CMotionInfo::alloc(m_xCursor, m_yCursor));
01386 }
01387 else
01388 {
01389
01390
01391
01392
01393 LOG((CLOG_DEBUG5 "warping server cursor to center: %+d,%+d", m_xCenter, m_yCenter));
01394 warpCursorNoFlush(m_xCenter, m_yCenter);
01395
01396
01397
01398
01399
01400
01401 static SInt32 bogusZoneSize = 10;
01402 if (-x + bogusZoneSize > m_xCenter - m_x ||
01403 x + bogusZoneSize > m_x + m_w - m_xCenter ||
01404 -y + bogusZoneSize > m_yCenter - m_y ||
01405 y + bogusZoneSize > m_y + m_h - m_yCenter) {
01406
01407 LOG((CLOG_DEBUG "dropped bogus delta motion: %+d,%+d", x, y));
01408 }
01409 else {
01410
01411 sendEvent(getMotionOnSecondaryEvent(), CMotionInfo::alloc(x, y));
01412 }
01413 }
01414
01415 return true;
01416 }
01417
01418 bool
01419 CMSWindowsScreen::onMouseWheel(SInt32 xDelta, SInt32 yDelta)
01420 {
01421
01422 if (!ignore()) {
01423 LOG((CLOG_DEBUG1 "event: button wheel delta=%+d,%+d", xDelta, yDelta));
01424 sendEvent(getWheelEvent(), CWheelInfo::alloc(xDelta, yDelta));
01425 }
01426 return true;
01427 }
01428
01429 bool
01430 CMSWindowsScreen::onScreensaver(bool activated)
01431 {
01432
01433
01434
01435
01436
01437
01438
01439
01440 MSG msg;
01441 if (PeekMessage(&msg, NULL, SYNERGY_MSG_SCREEN_SAVER,
01442 SYNERGY_MSG_SCREEN_SAVER, PM_NOREMOVE)) {
01443 return true;
01444 }
01445
01446 if (activated) {
01447 if (!m_screensaverActive &&
01448 m_screensaver->checkStarted(SYNERGY_MSG_SCREEN_SAVER, FALSE, 0)) {
01449 m_screensaverActive = true;
01450 sendEvent(getScreensaverActivatedEvent());
01451
01452
01453 CArchMiscWindows::removeBusyState(CArchMiscWindows::kDISPLAY);
01454 }
01455 }
01456 else {
01457 if (m_screensaverActive) {
01458 m_screensaverActive = false;
01459 sendEvent(getScreensaverDeactivatedEvent());
01460
01461
01462 CArchMiscWindows::addBusyState(CArchMiscWindows::kDISPLAY);
01463 }
01464 }
01465
01466 return true;
01467 }
01468
01469 bool
01470 CMSWindowsScreen::onDisplayChange()
01471 {
01472
01473 SInt32 xOld = m_x, yOld = m_y, wOld = m_w, hOld = m_h;
01474
01475
01476 updateScreenShape();
01477
01478
01479 if (xOld != m_x || yOld != m_y || wOld != m_w || hOld != m_h) {
01480 if (m_isPrimary) {
01481
01482 if (!m_isOnScreen) {
01483
01484 LOG((CLOG_DEBUG1 "warping cursor to center: %+d, %+d", m_xCenter, m_yCenter));
01485 warpCursor(m_xCenter, m_yCenter);
01486 }
01487
01488
01489 else {
01490 m_hookLibraryLoader.m_setZone(m_x, m_y, m_w, m_h, getJumpZoneSize());
01491 }
01492 }
01493
01494
01495 sendEvent(getShapeChangedEvent());
01496
01497 LOG((CLOG_DEBUG "screen shape: %d,%d %dx%d %s", m_x, m_y, m_w, m_h, m_multimon ? "(multi-monitor)" : ""));
01498 }
01499
01500 return true;
01501 }
01502
01503 bool
01504 CMSWindowsScreen::onClipboardChange()
01505 {
01506
01507
01508 if (!CMSWindowsClipboard::isOwnedBySynergy()) {
01509 if (m_ownClipboard) {
01510 LOG((CLOG_DEBUG "clipboard changed: lost ownership"));
01511 m_ownClipboard = false;
01512 sendClipboardEvent(getClipboardGrabbedEvent(), kClipboardClipboard);
01513 sendClipboardEvent(getClipboardGrabbedEvent(), kClipboardSelection);
01514 }
01515 }
01516 else if (!m_ownClipboard) {
01517 LOG((CLOG_DEBUG "clipboard changed: synergy owned"));
01518 m_ownClipboard = true;
01519 }
01520
01521 return true;
01522 }
01523
01524 void
01525 CMSWindowsScreen::warpCursorNoFlush(SInt32 x, SInt32 y)
01526 {
01527
01528 PostThreadMessage(GetCurrentThreadId(), SYNERGY_MSG_PRE_WARP, x, y);
01529
01530
01531
01532 SetCursorPos(x, y);
01533
01534
01535 POINT cursorPos;
01536 GetCursorPos(&cursorPos);
01537
01538 if ((cursorPos.x != x) && (cursorPos.y != y)) {
01539 LOG((CLOG_DEBUG "SetCursorPos did not work; using fakeMouseMove instead"));
01540
01541
01542
01543
01544
01545
01546
01547
01548
01549 fakeMouseMove(x, y);
01550 }
01551
01552
01553
01554
01555
01556
01557
01558
01559
01560
01561
01562
01563
01564
01565
01566
01567
01568 ARCH->sleep(0.0);
01569
01570
01571 PostThreadMessage(GetCurrentThreadId(), SYNERGY_MSG_POST_WARP, 0, 0);
01572 }
01573
01574 void
01575 CMSWindowsScreen::nextMark()
01576 {
01577
01578 ++m_mark;
01579
01580
01581 PostThreadMessage(GetCurrentThreadId(), SYNERGY_MSG_MARK, m_mark, 0);
01582 }
01583
01584 bool
01585 CMSWindowsScreen::ignore() const
01586 {
01587 return (m_mark != m_markReceived);
01588 }
01589
01590 void
01591 CMSWindowsScreen::updateScreenShape()
01592 {
01593
01594 m_x = GetSystemMetrics(SM_XVIRTUALSCREEN);
01595 m_y = GetSystemMetrics(SM_YVIRTUALSCREEN);
01596 m_w = GetSystemMetrics(SM_CXVIRTUALSCREEN);
01597 m_h = GetSystemMetrics(SM_CYVIRTUALSCREEN);
01598
01599
01600 m_xCenter = GetSystemMetrics(SM_CXSCREEN) >> 1;
01601 m_yCenter = GetSystemMetrics(SM_CYSCREEN) >> 1;
01602
01603
01604 m_multimon = (m_w != GetSystemMetrics(SM_CXSCREEN) ||
01605 m_h != GetSystemMetrics(SM_CYSCREEN));
01606
01607
01608 m_desks->setShape(m_x, m_y, m_w, m_h, m_xCenter, m_yCenter, m_multimon);
01609 }
01610
01611 void
01612 CMSWindowsScreen::handleFixes(const CEvent&, void*)
01613 {
01614
01615 fixClipboardViewer();
01616
01617
01618 if (m_keyState->didGroupsChange()) {
01619 updateKeys();
01620 }
01621 }
01622
01623 void
01624 CMSWindowsScreen::fixClipboardViewer()
01625 {
01626
01627
01628
01629
01630
01631
01632
01633
01634
01635
01636
01637
01638 }
01639
01640 void
01641 CMSWindowsScreen::enableSpecialKeys(bool enable) const
01642 {
01643
01644
01645
01646
01647 if (m_is95Family) {
01648 DWORD dummy = 0;
01649 SystemParametersInfo(SPI_SETSCREENSAVERRUNNING,
01650 enable ? FALSE : TRUE, &dummy, 0);
01651 }
01652 }
01653
01654 ButtonID
01655 CMSWindowsScreen::mapButtonFromEvent(WPARAM msg, LPARAM button) const
01656 {
01657 switch (msg) {
01658 case WM_LBUTTONDOWN:
01659 case WM_LBUTTONDBLCLK:
01660 case WM_LBUTTONUP:
01661 case WM_NCLBUTTONDOWN:
01662 case WM_NCLBUTTONDBLCLK:
01663 case WM_NCLBUTTONUP:
01664 return kButtonLeft;
01665
01666 case WM_MBUTTONDOWN:
01667 case WM_MBUTTONDBLCLK:
01668 case WM_MBUTTONUP:
01669 case WM_NCMBUTTONDOWN:
01670 case WM_NCMBUTTONDBLCLK:
01671 case WM_NCMBUTTONUP:
01672 return kButtonMiddle;
01673
01674 case WM_RBUTTONDOWN:
01675 case WM_RBUTTONDBLCLK:
01676 case WM_RBUTTONUP:
01677 case WM_NCRBUTTONDOWN:
01678 case WM_NCRBUTTONDBLCLK:
01679 case WM_NCRBUTTONUP:
01680 return kButtonRight;
01681
01682 case WM_XBUTTONDOWN:
01683 case WM_XBUTTONDBLCLK:
01684 case WM_XBUTTONUP:
01685 case WM_NCXBUTTONDOWN:
01686 case WM_NCXBUTTONDBLCLK:
01687 case WM_NCXBUTTONUP:
01688 switch (button) {
01689 case XBUTTON1:
01690 if (GetSystemMetrics(SM_CMOUSEBUTTONS) >= 4) {
01691 return kButtonExtra0 + 0;
01692 }
01693 break;
01694
01695 case XBUTTON2:
01696 if (GetSystemMetrics(SM_CMOUSEBUTTONS) >= 5) {
01697 return kButtonExtra0 + 1;
01698 }
01699 break;
01700 }
01701 return kButtonNone;
01702
01703 default:
01704 return kButtonNone;
01705 }
01706 }
01707
01708 bool
01709 CMSWindowsScreen::mapPressFromEvent(WPARAM msg, LPARAM) const
01710 {
01711 switch (msg) {
01712 case WM_LBUTTONDOWN:
01713 case WM_MBUTTONDOWN:
01714 case WM_RBUTTONDOWN:
01715 case WM_XBUTTONDOWN:
01716 case WM_LBUTTONDBLCLK:
01717 case WM_MBUTTONDBLCLK:
01718 case WM_RBUTTONDBLCLK:
01719 case WM_XBUTTONDBLCLK:
01720 case WM_NCLBUTTONDOWN:
01721 case WM_NCMBUTTONDOWN:
01722 case WM_NCRBUTTONDOWN:
01723 case WM_NCXBUTTONDOWN:
01724 case WM_NCLBUTTONDBLCLK:
01725 case WM_NCMBUTTONDBLCLK:
01726 case WM_NCRBUTTONDBLCLK:
01727 case WM_NCXBUTTONDBLCLK:
01728 return true;
01729
01730 case WM_LBUTTONUP:
01731 case WM_MBUTTONUP:
01732 case WM_RBUTTONUP:
01733 case WM_XBUTTONUP:
01734 case WM_NCLBUTTONUP:
01735 case WM_NCMBUTTONUP:
01736 case WM_NCRBUTTONUP:
01737 case WM_NCXBUTTONUP:
01738 return false;
01739
01740 default:
01741 return false;
01742 }
01743 }
01744
01745 void
01746 CMSWindowsScreen::updateKeysCB(void*)
01747 {
01748
01749 bool down[IKeyState::kNumButtons];
01750 bool sendFixes = (isPrimary() && !m_isOnScreen);
01751 if (sendFixes) {
01752 for (KeyButton i = 0; i < IKeyState::kNumButtons; ++i) {
01753 down[i] = m_keyState->isKeyDown(i);
01754 }
01755 }
01756
01757
01758 if (m_keyState->didGroupsChange()) {
01759 CPlatformScreen::updateKeyMap();
01760 }
01761
01762
01763 CPlatformScreen::updateKeyState();
01764
01765
01766
01767 if (sendFixes) {
01768 KeyModifierMask mask = pollActiveModifiers();
01769 for (KeyButton i = 0; i < IKeyState::kNumButtons; ++i) {
01770 if (down[i] && !m_keyState->isKeyDown(i)) {
01771 m_keyState->sendKeyEvent(getEventTarget(),
01772 false, false, kKeyNone, mask, 1, i);
01773 }
01774 }
01775 }
01776 }
01777
01778 void
01779 CMSWindowsScreen::forceShowCursor()
01780 {
01781
01782 m_hasMouse = (GetSystemMetrics(SM_MOUSEPRESENT) != 0);
01783
01784
01785 bool showMouse = (!m_hasMouse && !m_isPrimary && m_isOnScreen);
01786
01787
01788 if (showMouse != m_showingMouse) {
01789 if (showMouse) {
01790 m_oldMouseKeys.cbSize = sizeof(m_oldMouseKeys);
01791 m_gotOldMouseKeys =
01792 (SystemParametersInfo(SPI_GETMOUSEKEYS,
01793 m_oldMouseKeys.cbSize, &m_oldMouseKeys, 0) != 0);
01794 if (m_gotOldMouseKeys) {
01795 m_mouseKeys = m_oldMouseKeys;
01796 m_showingMouse = true;
01797 updateForceShowCursor();
01798 }
01799 }
01800 else {
01801 if (m_gotOldMouseKeys) {
01802 SystemParametersInfo(SPI_SETMOUSEKEYS,
01803 m_oldMouseKeys.cbSize,
01804 &m_oldMouseKeys, SPIF_SENDCHANGE);
01805 m_showingMouse = false;
01806 }
01807 }
01808 }
01809 }
01810
01811 void
01812 CMSWindowsScreen::updateForceShowCursor()
01813 {
01814 DWORD oldFlags = m_mouseKeys.dwFlags;
01815
01816
01817 m_mouseKeys.dwFlags = MKF_AVAILABLE | MKF_MOUSEKEYSON;
01818
01819
01820
01821 if ((m_keyState->getActiveModifiers() & KeyModifierNumLock) != 0) {
01822 m_mouseKeys.dwFlags |= MKF_REPLACENUMBERS;
01823 }
01824
01825
01826 if (oldFlags != m_mouseKeys.dwFlags) {
01827 SystemParametersInfo(SPI_SETMOUSEKEYS,
01828 m_mouseKeys.cbSize, &m_mouseKeys, SPIF_SENDCHANGE);
01829 }
01830 }
01831
01832 LRESULT CALLBACK
01833 CMSWindowsScreen::wndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
01834 {
01835 assert(s_screen != NULL);
01836
01837 LRESULT result = 0;
01838 if (!s_screen->onEvent(hwnd, msg, wParam, lParam, &result)) {
01839 result = DefWindowProc(hwnd, msg, wParam, lParam);
01840 }
01841
01842 return result;
01843 }
01844
01845
01846
01847
01848
01849 CMSWindowsScreen::CHotKeyItem::CHotKeyItem(UINT keycode, UINT mask) :
01850 m_keycode(keycode),
01851 m_mask(mask)
01852 {
01853
01854 }
01855
01856 UINT
01857 CMSWindowsScreen::CHotKeyItem::getVirtualKey() const
01858 {
01859 return m_keycode;
01860 }
01861
01862 bool
01863 CMSWindowsScreen::CHotKeyItem::operator<(const CHotKeyItem& x) const
01864 {
01865 return (m_keycode < x.m_keycode ||
01866 (m_keycode == x.m_keycode && m_mask < x.m_mask));
01867 }