- Timestamp:
- Aug 20, 2006, 8:17:41 AM (19 years ago)
- Location:
- trunk/synergy/lib/platform
- Files:
-
- 2 edited
-
CPMScreen.cpp (modified) (64 diffs)
-
CPMScreen.h (modified) (2 diffs)
Legend:
- Unmodified
- Added
- Removed
-
trunk/synergy/lib/platform/CPMScreen.cpp
r2765 r2771 40 40 // 41 41 42 CPMScreen* CPMScreen::s_screen = NULL;42 CPMScreen* CPMScreen::s_screen = NULL; 43 43 44 44 CPMScreen::CPMScreen(bool isPrimary) : 45 m_isPrimary(isPrimary),46 m_isOnScreen(m_isPrimary),47 m_x(0), m_y(0),48 m_cx(0), m_cy(0),49 m_xCenter(0), m_yCenter(0),50 m_multimon(false),51 m_xCursor(0), m_yCursor(0),52 m_sequenceNumber(0),53 m_mark(0),54 m_markReceived(0),55 m_screensaver(NULL),56 m_screensaverNotify(false),57 m_screensaverActive(false),58 m_window(NULLHANDLE),59 m_nextClipboardWindow(NULLHANDLE),60 m_ownClipboard(false),61 m_hmodHook(NULLHANDLE),62 m_init(NULL),63 m_cleanup(NULL),64 m_setSides(NULL),65 m_setZone(NULL),66 m_setMode(NULL),67 m_keyState(NULL),68 m_hasMouse(WinQuerySysValue(HWND_DESKTOP, SV_MOUSEPRESENT) != FALSE),69 m_showingMouse(false)70 { 71 assert(s_screen == NULL);72 s_screen = this;45 m_isPrimary(isPrimary), 46 m_isOnScreen(m_isPrimary), 47 m_x(0), m_y(0), 48 m_cx(0), m_cy(0), 49 m_xCenter(0), m_yCenter(0), 50 m_multimon(false), 51 m_xCursor(0), m_yCursor(0), 52 m_sequenceNumber(0), 53 m_mark(0), 54 m_markReceived(0), 55 m_screensaver(NULL), 56 m_screensaverNotify(false), 57 m_screensaverActive(false), 58 m_window(NULLHANDLE), 59 m_nextClipboardWindow(NULLHANDLE), 60 m_ownClipboard(false), 61 m_hmodHook(NULLHANDLE), 62 m_init(NULL), 63 m_cleanup(NULL), 64 m_setSides(NULL), 65 m_setZone(NULL), 66 m_setMode(NULL), 67 m_keyState(NULL), 68 m_hasMouse(WinQuerySysValue(HWND_DESKTOP, SV_MOUSEPRESENT) != FALSE), 69 m_showingMouse(false) 70 { 71 assert(s_screen == NULL); 72 s_screen = this; 73 73 LOG((CLOG_DEBUG1 "CPMScreen: isPrimary=%d", isPrimary)); 74 74 75 75 // create the event queue buffer first so we know there is a message queue. 76 76 CPMEventQueueBuffer *eventQueue = new CPMEventQueueBuffer(); 77 77 78 // query curren thread bits.79 m_threadID = _gettid();80 m_hab = WinQueryAnchorBlock(HWND_DESKTOP);78 // query curren thread bits. 79 m_threadID = _gettid(); 80 m_hab = WinQueryAnchorBlock(HWND_DESKTOP); 81 81 //if (m_hab == NULLHANDLE) { 82 // m_hab = WinInitialize(0);82 // m_hab = WinInitialize(0); 83 83 //} 84 m_hmq = WinQueueFromID(m_hab, getpid(), _gettid());84 m_hmq = WinQueueFromID(m_hab, getpid(), _gettid()); 85 85 //if (m_hab != NULLHANDLE && m_hmq == NULLHANDLE) { 86 86 // m_hmq = WinCreateMsgQueue(m_hab, 0); 87 87 //} 88 if (m_hab == NULLHANDLE || m_hmq == NULLHANDLE) {89 LOG((CLOG_CRIT "couldn't get the hab(%ld)/hmq(%ld) of the current thread! %d", m_hab, m_hmq));88 if (m_hab == NULLHANDLE || m_hmq == NULLHANDLE) { 89 LOG((CLOG_CRIT "couldn't get the hab(%ld)/hmq(%ld) of the current thread! %d", m_hab, m_hmq)); 90 90 delete eventQueue; 91 s_screen = NULL;92 throw XScreenOpenFailure();93 }94 95 try {96 m_hmodHook = openHookLibrary("synrgyhk");97 m_screensaver = new CPMScreenSaver();98 m_keyState = new CPMKeyState(getEventTarget(), m_fakeMsg);99 updateScreenShape();100 m_window = createWindow("Synergy");101 forceShowCursor();102 LOG((CLOG_DEBUG "screen shape: %d,%d %dx%d %s", m_x, m_y, m_cx, m_cy, m_multimon ? "(multi-monitor)" : ""));103 LOG((CLOG_DEBUG "window is 0x%08x", m_window));104 } catch (...) {105 delete m_keyState;106 delete m_screensaver;107 destroyWindow(m_window);108 closeHookLibrary(m_hmodHook);91 s_screen = NULL; 92 throw XScreenOpenFailure(); 93 } 94 95 try { 96 m_hmodHook = openHookLibrary("synrgyhk"); 97 m_screensaver = new CPMScreenSaver(); 98 m_keyState = new CPMKeyState(getEventTarget(), m_fakeMsg); 99 updateScreenShape(); 100 m_window = createWindow("Synergy"); 101 forceShowCursor(); 102 LOG((CLOG_DEBUG "screen shape: %d,%d %dx%d %s", m_x, m_y, m_cx, m_cy, m_multimon ? "(multi-monitor)" : "")); 103 LOG((CLOG_DEBUG "window is 0x%08x", m_window)); 104 } catch (...) { 105 delete m_keyState; 106 delete m_screensaver; 107 destroyWindow(m_window); 108 closeHookLibrary(m_hmodHook); 109 109 delete eventQueue; 110 s_screen = NULL;111 throw;112 }113 114 // install event handlers115 EVENTQUEUE->adoptHandler(CEvent::kSystem, IEventQueue::getSystemTarget(),116 new TMethodEventJob<CPMScreen>(this, &CPMScreen::handleSystemEvent));117 118 // install the platform event queue119 EVENTQUEUE->adoptBuffer(new CPMEventQueueBuffer);110 s_screen = NULL; 111 throw; 112 } 113 114 // install event handlers 115 EVENTQUEUE->adoptHandler(CEvent::kSystem, IEventQueue::getSystemTarget(), 116 new TMethodEventJob<CPMScreen>(this, &CPMScreen::handleSystemEvent)); 117 118 // install the platform event queue 119 EVENTQUEUE->adoptBuffer(new CPMEventQueueBuffer); 120 120 } 121 121 122 122 CPMScreen::~CPMScreen() 123 123 { 124 assert(s_screen != NULL);125 126 disable();127 EVENTQUEUE->adoptBuffer(NULL);128 EVENTQUEUE->removeHandler(CEvent::kSystem, IEventQueue::getSystemTarget());129 delete m_keyState;130 delete m_screensaver;131 destroyWindow(m_window);132 closeHookLibrary(m_hmodHook);133 s_screen = NULL;124 assert(s_screen != NULL); 125 126 disable(); 127 EVENTQUEUE->adoptBuffer(NULL); 128 EVENTQUEUE->removeHandler(CEvent::kSystem, IEventQueue::getSystemTarget()); 129 delete m_keyState; 130 delete m_screensaver; 131 destroyWindow(m_window); 132 closeHookLibrary(m_hmodHook); 133 s_screen = NULL; 134 134 } 135 135 … … 137 137 CPMScreen::enable() 138 138 { 139 assert(m_isOnScreen == m_isPrimary);140 141 // install our clipboard snooper139 assert(m_isOnScreen == m_isPrimary); 140 141 // install our clipboard snooper 142 142 HAB hab = CPMUtil::getHAB(); 143 m_nextClipboardWindow = WinQueryClipbrdViewer(hab);143 m_nextClipboardWindow = WinQueryClipbrdViewer(hab); 144 144 WinSetClipbrdViewer(hab, m_window); 145 145 146 if (m_isPrimary) {147 // set jump zones148 m_setZone(m_x, m_y, m_cx, m_cy, getJumpZoneSize());149 150 // watch jump zones151 m_setMode(kHOOK_WATCH_JUMP_ZONE);152 }146 if (m_isPrimary) { 147 // set jump zones 148 m_setZone(m_x, m_y, m_cx, m_cy, getJumpZoneSize()); 149 150 // watch jump zones 151 m_setMode(kHOOK_WATCH_JUMP_ZONE); 152 } 153 153 } 154 154 … … 156 156 CPMScreen::disable() 157 157 { 158 if (m_isPrimary) {159 // disable hooks160 m_setMode(kHOOK_DISABLE);161 }162 163 // tell key state164 m_keyState->disable();165 166 // stop snooping the clipboard167 WinSetClipbrdViewer(m_window, m_nextClipboardWindow);168 m_nextClipboardWindow = NULL;169 170 m_isOnScreen = m_isPrimary;171 forceShowCursor();158 if (m_isPrimary) { 159 // disable hooks 160 m_setMode(kHOOK_DISABLE); 161 } 162 163 // tell key state 164 m_keyState->disable(); 165 166 // stop snooping the clipboard 167 WinSetClipbrdViewer(m_window, m_nextClipboardWindow); 168 m_nextClipboardWindow = NULL; 169 170 m_isOnScreen = m_isPrimary; 171 forceShowCursor(); 172 172 } 173 173 … … 175 175 CPMScreen::enter() 176 176 { 177 // show the pointer (?), hide the synergy window and restore focus.178 WinShowPointer(HWND_DESKTOP, TRUE);179 WinSetWindowPos(m_window, HWND_BOTTOM, 0, 0, 0, 0, SWP_HIDE);180 //?? WinSetFocus(181 //?? WinEnableWindow182 183 if (m_isPrimary) {184 // watch jump zones185 m_setMode(kHOOK_WATCH_JUMP_ZONE);186 187 // all messages prior to now are invalid188 nextMark();189 }190 191 // now on screen192 m_isOnScreen = true;193 forceShowCursor();177 // show the pointer (?), hide the synergy window and restore focus. 178 WinShowPointer(HWND_DESKTOP, TRUE); 179 WinSetWindowPos(m_window, HWND_BOTTOM, 0, 0, 0, 0, SWP_HIDE); 180 //?? WinSetFocus( 181 //?? WinEnableWindow 182 183 if (m_isPrimary) { 184 // watch jump zones 185 m_setMode(kHOOK_WATCH_JUMP_ZONE); 186 187 // all messages prior to now are invalid 188 nextMark(); 189 } 190 191 // now on screen 192 m_isOnScreen = true; 193 forceShowCursor(); 194 194 } 195 195 … … 197 197 CPMScreen::leave() 198 198 { 199 /// @todo save focus window.200 201 if (m_isPrimary) {202 // warp to center203 warpCursor(m_xCenter, m_yCenter);204 205 // all messages prior to now are invalid206 nextMark();207 208 // remember the modifier state. this is the modifier state209 // reflected in the internal keyboard state.210 m_keyState->saveModifiers();211 212 // capture events213 m_setMode(kHOOK_RELAY_EVENTS);214 }215 216 // now off screen217 m_isOnScreen = false;218 forceShowCursor();219 220 return true;199 /// @todo save focus window. 200 201 if (m_isPrimary) { 202 // warp to center 203 warpCursor(m_xCenter, m_yCenter); 204 205 // all messages prior to now are invalid 206 nextMark(); 207 208 // remember the modifier state. this is the modifier state 209 // reflected in the internal keyboard state. 210 m_keyState->saveModifiers(); 211 212 // capture events 213 m_setMode(kHOOK_RELAY_EVENTS); 214 } 215 216 // now off screen 217 m_isOnScreen = false; 218 forceShowCursor(); 219 220 return true; 221 221 } 222 222 … … 224 224 CPMScreen::setClipboard(ClipboardID, const IClipboard* src) 225 225 { 226 CPMClipboard dst(m_window);227 if (src != NULL) {228 // save clipboard data229 return CClipboard::copy(&dst, src);230 }226 CPMClipboard dst(m_window); 227 if (src != NULL) { 228 // save clipboard data 229 return CClipboard::copy(&dst, src); 230 } 231 231 // assert clipboard ownership 232 232 if (!dst.open(0)) { … … 242 242 { 243 243 // be careful, even if we don't have the NT bugs. 244 if (m_ownClipboard && !CPMClipboard::isOwnedBySynergy()) {245 LOG((CLOG_DEBUG "clipboard changed: lost ownership and no notification received"));246 m_ownClipboard = false;247 sendClipboardEvent(getClipboardGrabbedEvent(), kClipboardClipboard);248 sendClipboardEvent(getClipboardGrabbedEvent(), kClipboardSelection);249 }244 if (m_ownClipboard && !CPMClipboard::isOwnedBySynergy()) { 245 LOG((CLOG_DEBUG "clipboard changed: lost ownership and no notification received")); 246 m_ownClipboard = false; 247 sendClipboardEvent(getClipboardGrabbedEvent(), kClipboardClipboard); 248 sendClipboardEvent(getClipboardGrabbedEvent(), kClipboardSelection); 249 } 250 250 } 251 251 … … 253 253 CPMScreen::openScreensaver(bool notify) 254 254 { 255 m_screensaverNotify = notify;256 if (!m_screensaverNotify)257 m_screensaver->disable();255 m_screensaverNotify = notify; 256 if (!m_screensaverNotify) 257 m_screensaver->disable(); 258 258 } 259 259 … … 261 261 CPMScreen::closeScreensaver() 262 262 { 263 if (!m_screensaverNotify)264 m_screensaver->enable();263 if (!m_screensaverNotify) 264 m_screensaver->enable(); 265 265 } 266 266 … … 294 294 CPMScreen::setSequenceNumber(UInt32 seqNum) 295 295 { 296 m_sequenceNumber = seqNum;296 m_sequenceNumber = seqNum; 297 297 } 298 298 … … 300 300 CPMScreen::isPrimary() const 301 301 { 302 return m_isPrimary;302 return m_isPrimary; 303 303 } 304 304 … … 306 306 CPMScreen::getEventTarget() const 307 307 { 308 return const_cast<CPMScreen*>(this);308 return const_cast<CPMScreen*>(this); 309 309 } 310 310 … … 312 312 CPMScreen::getClipboard(ClipboardID, IClipboard* dst) const 313 313 { 314 CPMClipboard src(m_window);315 return CClipboard::copy(dst, &src);314 CPMClipboard src(m_window); 315 return CClipboard::copy(dst, &src); 316 316 } 317 317 … … 319 319 CPMScreen::getShape(SInt32& x, SInt32& y, SInt32& cx, SInt32& cy) const 320 320 { 321 x = m_x;322 y = m_y;323 cx= m_cx;324 cy = m_cy;321 x = m_x; 322 y = m_y; 323 cx= m_cx; 324 cy = m_cy; 325 325 } 326 326 … … 347 347 CPMScreen::warpCursor(SInt32 x, SInt32 y) 348 348 { 349 // warp mouse350 warpCursorNoFlush(x, y);351 352 // remove all input events before and including warp353 QMSG qmsg;354 while (WinPeekMsg(m_hab, &qmsg, NULLHANDLE, SYNERGY_PM_MSG_INPUT_FIRST, SYNERGY_PM_MSG_INPUT_LAST, PM_REMOVE)) {355 // do nothing356 }357 358 // save position as last position359 m_xCursor = x;360 m_yCursor = y;349 // warp mouse 350 warpCursorNoFlush(x, y); 351 352 // remove all input events before and including warp 353 QMSG qmsg; 354 while (WinPeekMsg(m_hab, &qmsg, NULLHANDLE, SYNERGY_PM_MSG_INPUT_FIRST, SYNERGY_PM_MSG_INPUT_LAST, PM_REMOVE)) { 355 // do nothing 356 } 357 358 // save position as last position 359 m_xCursor = x; 360 m_yCursor = y; 361 361 } 362 362 … … 364 364 CPMScreen::registerHotKey(KeyID key, KeyModifierMask mask) 365 365 { 366 // only allow certain modifiers367 if ((mask & ~(KeyModifierShift | KeyModifierControl |368 KeyModifierAlt | KeyModifierSuper)) != 0) {369 LOG((CLOG_WARN "could not map hotkey id=%04x mask=%04x", key, mask));370 return 0;371 }372 373 // fail if no keys374 if (key == kKeyNone && mask == 0) {375 return 0;376 }366 // only allow certain modifiers 367 if ((mask & ~(KeyModifierShift | KeyModifierControl | 368 KeyModifierAlt | KeyModifierSuper)) != 0) { 369 LOG((CLOG_WARN "could not map hotkey id=%04x mask=%04x", key, mask)); 370 return 0; 371 } 372 373 // fail if no keys 374 if (key == kKeyNone && mask == 0) { 375 return 0; 376 } 377 377 378 378 #if 1 … … 380 380 return 0; 381 381 #else 382 // convert to win32383 UINT modifiers = 0;384 if ((mask & KeyModifierShift) != 0) {385 modifiers |= MOD_SHIFT;386 }387 if ((mask & KeyModifierControl) != 0) {388 modifiers |= MOD_CONTROL;389 }390 if ((mask & KeyModifierAlt) != 0) {391 modifiers |= MOD_ALT;392 }393 if ((mask & KeyModifierSuper) != 0) {394 modifiers |= MOD_WIN;395 }396 UINT vk = m_keyState->mapKeyToVirtualKey(key);397 if (key != kKeyNone && vk == 0) {398 // can't map key399 LOG((CLOG_WARN "could not map hotkey id=%04x mask=%04x", key, mask));400 return 0;401 }402 403 // choose hotkey id404 UInt32 id;405 if (!m_oldHotKeyIDs.empty()) {406 id = m_oldHotKeyIDs.back();407 m_oldHotKeyIDs.pop_back();408 }409 else {410 id = m_hotKeys.size() + 1;411 }412 413 // if this hot key has modifiers only then we'll handle it specially414 bool err;415 if (key == kKeyNone) {416 // check if already registered417 err = (m_hotKeyToIDMap.count(CHotKeyItem(vk, modifiers)) > 0);418 }419 else {420 // register with OS421 err = (RegisterHotKey(NULL, id, modifiers, vk) == 0);422 }423 424 if (!err) {425 m_hotKeys.insert(std::make_pair(id, CHotKeyItem(vk, modifiers)));426 m_hotKeyToIDMap[CHotKeyItem(vk, modifiers)] = id;427 }428 else {429 m_oldHotKeyIDs.push_back(id);430 m_hotKeys.erase(id);431 LOG((CLOG_WARN "failed to register hotkey %s (id=%04x mask=%04x)", CKeyMap::formatKey(key, mask).c_str(), key, mask));432 return 0;433 }434 435 LOG((CLOG_DEBUG "registered hotkey %s (id=%04x mask=%04x) as id=%d", CKeyMap::formatKey(key, mask).c_str(), key, mask, id));436 return id;382 // convert to win32 383 UINT modifiers = 0; 384 if ((mask & KeyModifierShift) != 0) { 385 modifiers |= MOD_SHIFT; 386 } 387 if ((mask & KeyModifierControl) != 0) { 388 modifiers |= MOD_CONTROL; 389 } 390 if ((mask & KeyModifierAlt) != 0) { 391 modifiers |= MOD_ALT; 392 } 393 if ((mask & KeyModifierSuper) != 0) { 394 modifiers |= MOD_WIN; 395 } 396 UINT vk = m_keyState->mapKeyToVirtualKey(key); 397 if (key != kKeyNone && vk == 0) { 398 // can't map key 399 LOG((CLOG_WARN "could not map hotkey id=%04x mask=%04x", key, mask)); 400 return 0; 401 } 402 403 // choose hotkey id 404 UInt32 id; 405 if (!m_oldHotKeyIDs.empty()) { 406 id = m_oldHotKeyIDs.back(); 407 m_oldHotKeyIDs.pop_back(); 408 } 409 else { 410 id = m_hotKeys.size() + 1; 411 } 412 413 // if this hot key has modifiers only then we'll handle it specially 414 bool err; 415 if (key == kKeyNone) { 416 // check if already registered 417 err = (m_hotKeyToIDMap.count(CHotKeyItem(vk, modifiers)) > 0); 418 } 419 else { 420 // register with OS 421 err = (RegisterHotKey(NULL, id, modifiers, vk) == 0); 422 } 423 424 if (!err) { 425 m_hotKeys.insert(std::make_pair(id, CHotKeyItem(vk, modifiers))); 426 m_hotKeyToIDMap[CHotKeyItem(vk, modifiers)] = id; 427 } 428 else { 429 m_oldHotKeyIDs.push_back(id); 430 m_hotKeys.erase(id); 431 LOG((CLOG_WARN "failed to register hotkey %s (id=%04x mask=%04x)", CKeyMap::formatKey(key, mask).c_str(), key, mask)); 432 return 0; 433 } 434 435 LOG((CLOG_DEBUG "registered hotkey %s (id=%04x mask=%04x) as id=%d", CKeyMap::formatKey(key, mask).c_str(), key, mask, id)); 436 return id; 437 437 #endif 438 438 } … … 441 441 CPMScreen::unregisterHotKey(UInt32 id) 442 442 { 443 // look up hotkey444 HotKeyMap::iterator i = m_hotKeys.find(id);445 if (i == m_hotKeys.end()) {446 return;447 }448 449 // unregister with OS450 bool err;443 // look up hotkey 444 HotKeyMap::iterator i = m_hotKeys.find(id); 445 if (i == m_hotKeys.end()) { 446 return; 447 } 448 449 // unregister with OS 450 bool err; 451 451 #if 1 452 452 err = true; 453 453 #else 454 if (i->second.getVirtualKey() != 0) {455 err = !UnregisterHotKey(NULL, id);456 } else {457 err = false;458 }454 if (i->second.getVirtualKey() != 0) { 455 err = !UnregisterHotKey(NULL, id); 456 } else { 457 err = false; 458 } 459 459 #endif 460 if (err) {461 LOG((CLOG_WARN "failed to unregister hotkey id=%d", id));462 }463 else {464 LOG((CLOG_DEBUG "unregistered hotkey id=%d", id));465 }466 467 // discard hot key from map and record old id for reuse468 m_hotKeyToIDMap.erase(i->second);469 m_hotKeys.erase(i);470 m_oldHotKeyIDs.push_back(id);460 if (err) { 461 LOG((CLOG_WARN "failed to unregister hotkey id=%d", id)); 462 } 463 else { 464 LOG((CLOG_DEBUG "unregistered hotkey id=%d", id)); 465 } 466 467 // discard hot key from map and record old id for reuse 468 m_hotKeyToIDMap.erase(i->second); 469 m_hotKeys.erase(i); 470 m_oldHotKeyIDs.push_back(id); 471 471 } 472 472 … … 474 474 CPMScreen::fakeInputBegin() 475 475 { 476 assert(m_isPrimary);477 478 if (!m_isOnScreen) {479 m_keyState->useSavedModifiers(true);480 }481 //m_desks->fakeInputBegin();476 assert(m_isPrimary); 477 478 if (!m_isOnScreen) { 479 m_keyState->useSavedModifiers(true); 480 } 481 //m_desks->fakeInputBegin(); 482 482 } 483 483 … … 485 485 CPMScreen::fakeInputEnd() 486 486 { 487 assert(m_isPrimary);488 489 //m_desks->fakeInputEnd();490 if (!m_isOnScreen) {491 m_keyState->useSavedModifiers(false);492 }487 assert(m_isPrimary); 488 489 //m_desks->fakeInputEnd(); 490 if (!m_isOnScreen) { 491 m_keyState->useSavedModifiers(false); 492 } 493 493 } 494 494 … … 496 496 CPMScreen::getJumpZoneSize() const 497 497 { 498 return 1;498 return 1; 499 499 } 500 500 … … 502 502 CPMScreen::isAnyMouseButtonDown() const 503 503 { 504 static const char* buttonToName[] = {505 "<invalid>",506 "Left Button",507 "Middle Button",508 "Right Button",509 "X Button 1",510 "X Button 2"511 };512 513 for (UInt32 i = 1; i < sizeof(m_buttons) / sizeof(m_buttons[0]); ++i) {514 if (m_buttons[i]) {515 LOG((CLOG_DEBUG "locked by \"%s\"", buttonToName[i]));516 return true;517 }518 }519 520 return false;504 static const char* buttonToName[] = { 505 "<invalid>", 506 "Left Button", 507 "Middle Button", 508 "Right Button", 509 "X Button 1", 510 "X Button 2" 511 }; 512 513 for (UInt32 i = 1; i < sizeof(m_buttons) / sizeof(m_buttons[0]); ++i) { 514 if (m_buttons[i]) { 515 LOG((CLOG_DEBUG "locked by \"%s\"", buttonToName[i])); 516 return true; 517 } 518 } 519 520 return false; 521 521 } 522 522 … … 524 524 CPMScreen::getCursorCenter(SInt32& x, SInt32& y) const 525 525 { 526 x = m_xCenter;527 y = m_yCenter;526 x = m_xCenter; 527 y = m_yCenter; 528 528 } 529 529 … … 535 535 * @param mp1 Message param 2. 536 536 */ 537 void 537 void 538 538 CPMScreen::fakeMessage(ULONG msg, MPARAM mp1, MPARAM mp2) const 539 539 { … … 633 633 void 634 634 CPMScreen::fakeMouseWheel(SInt32 xDelta, SInt32 yDelta) const 635 { 635 { 636 636 #if 0 /** @todo send scroll messages the the window beneath the cursor. */ 637 637 POINTL ptl; … … 652 652 } 653 653 } 654 #endif 654 #endif 655 655 } 656 656 … … 658 658 CPMScreen::updateKeys() 659 659 { 660 //m_desks->updateKeys();660 //m_desks->updateKeys(); 661 661 } 662 662 663 663 void 664 664 CPMScreen::fakeKeyDown(KeyID id, KeyModifierMask mask, 665 KeyButton button)666 { 667 CPlatformScreen::fakeKeyDown(id, mask, button);668 updateForceShowCursor();665 KeyButton button) 666 { 667 CPlatformScreen::fakeKeyDown(id, mask, button); 668 updateForceShowCursor(); 669 669 } 670 670 671 671 void 672 672 CPMScreen::fakeKeyRepeat(KeyID id, KeyModifierMask mask, 673 SInt32 count, KeyButton button)674 { 675 CPlatformScreen::fakeKeyRepeat(id, mask, count, button);676 updateForceShowCursor();673 SInt32 count, KeyButton button) 674 { 675 CPlatformScreen::fakeKeyRepeat(id, mask, count, button); 676 updateForceShowCursor(); 677 677 } 678 678 … … 680 680 CPMScreen::fakeKeyUp(KeyButton button) 681 681 { 682 CPlatformScreen::fakeKeyUp(button);683 updateForceShowCursor();682 CPlatformScreen::fakeKeyUp(button); 683 updateForceShowCursor(); 684 684 } 685 685 … … 687 687 CPMScreen::fakeAllKeysUp() 688 688 { 689 CPlatformScreen::fakeAllKeysUp();690 updateForceShowCursor();689 CPlatformScreen::fakeAllKeysUp(); 690 updateForceShowCursor(); 691 691 } 692 692 … … 694 694 * Gets the path to the directory with the executable. 695 695 * Has trailing slash. 696 * 696 * 697 697 * @returns pszBuf. 698 698 * @returns NULL on buffer overflow. … … 721 721 { 722 722 // 723 // Load the hook dll as a global DLL. 723 // Load the hook dll as a global DLL. 724 724 // 725 725 // The kernel/PM will fuck up if it's loaded with a path (i.e. non global). 726 // What happend was that the DLL wasn't actually loaded into the other 727 // processes for some stupid reason, leading to nasty crashes and even 726 // What happend was that the DLL wasn't actually loaded into the other 727 // processes for some stupid reason, leading to nasty crashes and even 728 728 // weirder behaviour. 729 729 // … … 733 733 || getExecDir(szPath, sizeof(szPath)) == NULL 734 734 || chdir(szPath) != 0) { 735 LOG((CLOG_ERR "can't get cwd or exec dir or failed to change path to the exec dir!"));736 throw XScreenOpenFailure();737 } 738 HMODULE hmod;735 LOG((CLOG_ERR "can't get cwd or exec dir or failed to change path to the exec dir!")); 736 throw XScreenOpenFailure(); 737 } 738 HMODULE hmod; 739 739 APIRET rc = DosLoadModule(NULL, 0, (PCSZ)name, &hmod); 740 740 chdir(szCwd); 741 if (rc != NO_ERROR) {742 LOG((CLOG_ERR "Failed to load hook library (%s), rc=%d ", name, rc));743 throw XScreenOpenFailure();744 }745 746 // resolve the functions747 if ( (rc = DosQueryProcAddr(hmod, 0, (PCSZ)"_fakeMsg",(PPFN)&m_fakeMsg )) != NO_ERROR748 || (rc = DosQueryProcAddr(hmod, 0, (PCSZ)"_setSides",(PPFN)&m_setSides)) != NO_ERROR749 || (rc = DosQueryProcAddr(hmod, 0, (PCSZ)"_setZone",(PPFN)&m_setZone )) != NO_ERROR750 || (rc = DosQueryProcAddr(hmod, 0, (PCSZ)"_setMode",(PPFN)&m_setMode )) != NO_ERROR751 || (rc = DosQueryProcAddr(hmod, 0, (PCSZ)"_init",(PPFN)&m_init )) != NO_ERROR752 || (rc = DosQueryProcAddr(hmod, 0, (PCSZ)"_cleanup",(PPFN)&m_cleanup )) != NO_ERROR) {753 LOG((CLOG_ERR "Invalid hook library; use a newer %s.dll (rc=%d)", name, rc));754 DosFreeModule(hmod);755 throw XScreenOpenFailure();756 }757 758 // initialize hook library759 if (m_init(m_hmq, _gettid(), getpid()) == 0) {760 LOG((CLOG_ERR "Cannot initialize hook library; is synergy already running?"));761 DosFreeModule(hmod);762 throw XScreenOpenFailure();763 }741 if (rc != NO_ERROR) { 742 LOG((CLOG_ERR "Failed to load hook library (%s), rc=%d ", name, rc)); 743 throw XScreenOpenFailure(); 744 } 745 746 // resolve the functions 747 if ( (rc = DosQueryProcAddr(hmod, 0, (PCSZ)"_fakeMsg", (PPFN)&m_fakeMsg )) != NO_ERROR 748 || (rc = DosQueryProcAddr(hmod, 0, (PCSZ)"_setSides", (PPFN)&m_setSides)) != NO_ERROR 749 || (rc = DosQueryProcAddr(hmod, 0, (PCSZ)"_setZone", (PPFN)&m_setZone )) != NO_ERROR 750 || (rc = DosQueryProcAddr(hmod, 0, (PCSZ)"_setMode", (PPFN)&m_setMode )) != NO_ERROR 751 || (rc = DosQueryProcAddr(hmod, 0, (PCSZ)"_init", (PPFN)&m_init )) != NO_ERROR 752 || (rc = DosQueryProcAddr(hmod, 0, (PCSZ)"_cleanup", (PPFN)&m_cleanup )) != NO_ERROR) { 753 LOG((CLOG_ERR "Invalid hook library; use a newer %s.dll (rc=%d)", name, rc)); 754 DosFreeModule(hmod); 755 throw XScreenOpenFailure(); 756 } 757 758 // initialize hook library 759 if (m_init(m_hmq, _gettid(), getpid()) == 0) { 760 LOG((CLOG_ERR "Cannot initialize hook library; is synergy already running?")); 761 DosFreeModule(hmod); 762 throw XScreenOpenFailure(); 763 } 764 764 LOG((CLOG_DEBUG1 "openHookLibrary: hmod=%#lx '%s'", hmod, name)); 765 return hmod;765 return hmod; 766 766 } 767 767 … … 770 770 { 771 771 LOG((CLOG_DEBUG1 "closeHookLibrary: hmod=%#lx\n", hmod)); 772 if (hmod != NULL) {773 m_cleanup(m_hab);774 DosFreeModule(hmod);775 }772 if (hmod != NULL) { 773 m_cleanup(m_hab); 774 DosFreeModule(hmod); 775 } 776 776 } 777 777 … … 779 779 CPMScreen::createWindow(const char* name) 780 780 { 781 WinRegisterClass(m_hab, (PCSZ)"Synergy", CPMScreen::wndProc, CS_MOVENOTIFY, sizeof(uintptr_t));782 HWND hwnd = WinCreateWindow(HWND_DESKTOP,783 (PCSZ)"Synergy",784 NULL,785 0, //WS_?,786 0, 0, 1, 1,787 NULLHANDLE,788 HWND_TOP,789 0,790 this,791 NULL);792 if (hwnd == NULLHANDLE) {793 LOG((CLOG_ERR "failed to create window: %lx", WinGetLastError(m_hab)));794 throw XScreenOpenFailure();795 }796 return hwnd;781 WinRegisterClass(m_hab, (PCSZ)"Synergy", CPMScreen::wndProc, CS_MOVENOTIFY, sizeof(uintptr_t)); 782 HWND hwnd = WinCreateWindow(HWND_DESKTOP, 783 (PCSZ)"Synergy", 784 NULL, 785 0, //WS_?, 786 0, 0, 1, 1, 787 NULLHANDLE, 788 HWND_TOP, 789 0, 790 this, 791 NULL); 792 if (hwnd == NULLHANDLE) { 793 LOG((CLOG_ERR "failed to create window: %lx", WinGetLastError(m_hab))); 794 throw XScreenOpenFailure(); 795 } 796 return hwnd; 797 797 } 798 798 … … 800 800 CPMScreen::destroyWindow(HWND hwnd) const 801 801 { 802 if (hwnd != NULL) {803 WinDestroyWindow(hwnd);804 }802 if (hwnd != NULL) { 803 WinDestroyWindow(hwnd); 804 } 805 805 } 806 806 … … 808 808 CPMScreen::sendEvent(CEvent::Type type, void* data) 809 809 { 810 EVENTQUEUE->addEvent(CEvent(type, getEventTarget(), data));810 EVENTQUEUE->addEvent(CEvent(type, getEventTarget(), data)); 811 811 } 812 812 … … 814 814 CPMScreen::sendClipboardEvent(CEvent::Type type, ClipboardID id) 815 815 { 816 CClipboardInfo* info = (CClipboardInfo*)malloc(sizeof(CClipboardInfo));817 info->m_id = id;818 info->m_sequenceNumber = m_sequenceNumber;819 sendEvent(type, info);816 CClipboardInfo* info = (CClipboardInfo*)malloc(sizeof(CClipboardInfo)); 817 info->m_id = id; 818 info->m_sequenceNumber = m_sequenceNumber; 819 sendEvent(type, info); 820 820 } 821 821 … … 823 823 CPMScreen::handleSystemEvent(const CEvent& event, void*) 824 824 { 825 PQMSG pqmsg = (PQMSG)event.getData();826 assert(pqmsg != NULL);827 if (onPreDispatch(pqmsg->hwnd, pqmsg->msg, pqmsg->mp1, pqmsg->mp2))828 return;829 WinDispatchMsg(CPMUtil::getHAB(), pqmsg);825 PQMSG pqmsg = (PQMSG)event.getData(); 826 assert(pqmsg != NULL); 827 if (onPreDispatch(pqmsg->hwnd, pqmsg->msg, pqmsg->mp1, pqmsg->mp2)) 828 return; 829 WinDispatchMsg(CPMUtil::getHAB(), pqmsg); 830 830 } 831 831 … … 833 833 CPMScreen::updateButtons() 834 834 { 835 m_buttons[kButtonNone] = false;836 m_buttons[kButtonLeft] = (WinGetKeyState(HWND_DESKTOP, VK_BUTTON1) & 0x8000) != 0;837 m_buttons[kButtonRight] = (WinGetKeyState(HWND_DESKTOP, VK_BUTTON2) & 0x8000) != 0;838 m_buttons[kButtonMiddle] = (WinGetKeyState(HWND_DESKTOP, VK_BUTTON3) & 0x8000) != 0;839 m_buttons[kButtonExtra0 + 0] = false;840 m_buttons[kButtonExtra0 + 1] = false;835 m_buttons[kButtonNone] = false; 836 m_buttons[kButtonLeft] = (WinGetKeyState(HWND_DESKTOP, VK_BUTTON1) & 0x8000) != 0; 837 m_buttons[kButtonRight] = (WinGetKeyState(HWND_DESKTOP, VK_BUTTON2) & 0x8000) != 0; 838 m_buttons[kButtonMiddle] = (WinGetKeyState(HWND_DESKTOP, VK_BUTTON3) & 0x8000) != 0; 839 m_buttons[kButtonExtra0 + 0] = false; 840 m_buttons[kButtonExtra0 + 1] = false; 841 841 } 842 842 … … 844 844 CPMScreen::getKeyState() const 845 845 { 846 return m_keyState;846 return m_keyState; 847 847 } 848 848 … … 850 850 CPMScreen::onPreDispatch(HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2) 851 851 { 852 // handle event853 switch (msg) {854 case SYNERGY_PM_MSG_DEBUG:855 LOG((CLOG_DEBUG1 "hook: 0x%08x 0x%08x", mp1, mp2));856 return true;857 }858 859 if (m_isPrimary) {860 return onPreDispatchPrimary(hwnd, msg, mp1, mp2);861 }862 863 return false;852 // handle event 853 switch (msg) { 854 case SYNERGY_PM_MSG_DEBUG: 855 LOG((CLOG_DEBUG1 "hook: 0x%08x 0x%08x", mp1, mp2)); 856 return true; 857 } 858 859 if (m_isPrimary) { 860 return onPreDispatchPrimary(hwnd, msg, mp1, mp2); 861 } 862 863 return false; 864 864 } 865 865 … … 867 867 CPMScreen::onPreDispatchPrimary(HWND, ULONG msg, MPARAM mp1, MPARAM mp2) 868 868 { 869 // handle event870 switch (msg) {871 case SYNERGY_PM_MSG_MARK:872 return onMark((uintptr_t)mp1);873 874 case SYNERGY_PM_MSG_KEY:875 return onKey(SHORT1FROMMP(mp1), CHAR3FROMMP(mp1), CHAR4FROMMP(mp1), SHORT1FROMMP(mp2), SHORT2FROMMP(mp2));876 877 case SYNERGY_PM_MSG_MOUSE_BUTTON:878 return onMouseButton(SHORT1FROMMP(mp1), (SHORT)SHORT1FROMMP(mp2), m_cy - (SHORT)SHORT2FROMMP(mp2));879 880 case SYNERGY_PM_MSG_MOUSE_MOVE:881 return onMouseMove(SHORT1FROMMP(mp1), (SHORT)SHORT1FROMMP(mp2), m_cy - (SHORT)SHORT2FROMMP(mp2));882 883 case SYNERGY_PM_MSG_PRE_WARP:884 {885 // Save position to compute delta of next motion886 m_xCursor = (SInt32)mp1;887 m_yCursor = (SInt32)mp2;888 889 // We warped the mouse. Discard events until we find the890 // matching post warp event. See warpCursorNoFlush() for891 // where the events are sent. We discard the matching892 // post warp event and can be sure we've skipped the warp893 // event.894 QMSG qmsg;895 while ( WinGetMsg(m_hab, &qmsg, NULLHANDLE, SYNERGY_PM_MSG_MOUSE_MOVE, SYNERGY_PM_MSG_POST_WARP)896 && qmsg.msg != SYNERGY_PM_MSG_POST_WARP)897 /* nothing */;898 }899 return true;900 901 case SYNERGY_PM_MSG_POST_WARP:902 LOG((CLOG_WARN "unmatched post warp"));903 return true;904 }905 906 return false;869 // handle event 870 switch (msg) { 871 case SYNERGY_PM_MSG_MARK: 872 return onMark((uintptr_t)mp1); 873 874 case SYNERGY_PM_MSG_KEY: 875 return onKey(SHORT1FROMMP(mp1), CHAR3FROMMP(mp1), CHAR4FROMMP(mp1), SHORT1FROMMP(mp2), SHORT2FROMMP(mp2)); 876 877 case SYNERGY_PM_MSG_MOUSE_BUTTON: 878 return onMouseButton(SHORT1FROMMP(mp1), (SHORT)SHORT1FROMMP(mp2), m_cy - (SHORT)SHORT2FROMMP(mp2)); 879 880 case SYNERGY_PM_MSG_MOUSE_MOVE: 881 return onMouseMove(SHORT1FROMMP(mp1), (SHORT)SHORT1FROMMP(mp2), m_cy - (SHORT)SHORT2FROMMP(mp2)); 882 883 case SYNERGY_PM_MSG_PRE_WARP: 884 { 885 // Save position to compute delta of next motion 886 m_xCursor = (SInt32)mp1; 887 m_yCursor = (SInt32)mp2; 888 889 // We warped the mouse. Discard events until we find the 890 // matching post warp event. See warpCursorNoFlush() for 891 // where the events are sent. We discard the matching 892 // post warp event and can be sure we've skipped the warp 893 // event. 894 QMSG qmsg; 895 while ( WinGetMsg(m_hab, &qmsg, NULLHANDLE, SYNERGY_PM_MSG_MOUSE_MOVE, SYNERGY_PM_MSG_POST_WARP) 896 && qmsg.msg != SYNERGY_PM_MSG_POST_WARP) 897 /* nothing */; 898 } 899 return true; 900 901 case SYNERGY_PM_MSG_POST_WARP: 902 LOG((CLOG_WARN "unmatched post warp")); 903 return true; 904 } 905 906 return false; 907 907 } 908 908 … … 910 910 CPMScreen::onEvent(HWND, ULONG msg, MPARAM mp1, MPARAM mp2, MRESULT *result) 911 911 { 912 switch (msg) {913 case WM_DRAWCLIPBOARD:914 //// first pass on the message915 //if (m_nextClipboardWindow != NULL) {916 //WinSendMessage(m_nextClipboardWindow, msg, mp1, mp2);917 //}918 919 // now handle the message920 return onClipboardChange();921 }922 923 return false;912 switch (msg) { 913 case WM_DRAWCLIPBOARD: 914 //// first pass on the message 915 //if (m_nextClipboardWindow != NULL) { 916 // WinSendMessage(m_nextClipboardWindow, msg, mp1, mp2); 917 //} 918 919 // now handle the message 920 return onClipboardChange(); 921 } 922 923 return false; 924 924 } 925 925 … … 927 927 CPMScreen::onMark(UInt32 mark) 928 928 { 929 m_markReceived = mark;930 return true;929 m_markReceived = mark; 930 return true; 931 931 } 932 932 … … 935 935 { 936 936 #if 0 937 static const KeyModifierMask s_ctrlAlt = KeyModifierControl | KeyModifierAlt;938 939 LOG((CLOG_DEBUG1 "event: Key char=%d, vk=0x%02x, nagr=%d, mp2=0x%08x", (mp1 & 0xff00u) >> 8, mp1 & 0xffu, (mp1 & 0x10000u) ? 1 : 0, mp2));940 941 // get event info942 KeyButton button = (KeyButton)((mp2 & 0x01ff0000) >> 16);943 bool down = ((mp2 & 0x80000000u) == 0x00000000u);944 bool wasDown = isKeyDown(button);945 KeyModifierMask oldState = pollActiveModifiers();946 947 // check for autorepeat948 if (m_keyState->testAutoRepeat(down, (mp2 & 0x40000000u) == 1, button)) {949 mp2 |= 0x40000000u;950 }951 952 // if the button is zero then guess what the button should be.953 // these are badly synthesized key events and logitech software954 // that maps mouse buttons to keys is known to do this.955 // alternatively, we could just throw these events out.956 if (button == 0) {957 button = m_keyState->virtualKeyToButton(mp1 & 0xffu);958 if (button == 0) {959 return true;960 }961 wasDown = isKeyDown(button);962 }963 964 // record keyboard state965 m_keyState->onKey(button, down, oldState);966 967 // windows doesn't tell us the modifier key state on mouse or key968 // events so we have to figure it out. most apps would use969 // GetKeyState() or even GetAsyncKeyState() for that but we can't970 // because our hook doesn't pass on key events for several modifiers.971 // it can't otherwise the system would interpret them normally on972 // the primary screen even when on a secondary screen. so tapping973 // alt would activate menus and tapping the windows key would open974 // the start menu. if you don't pass those events on in the hook975 // then GetKeyState() understandably doesn't reflect the effect of976 // the event. curiously, neither does GetAsyncKeyState(), which is977 // surprising.978 //979 // so anyway, we have to track the modifier state ourselves for980 // at least those modifiers we don't pass on. pollActiveModifiers()981 // does that but we have to update the keyboard state before calling982 // pollActiveModifiers() to get the right answer. but the only way983 // to set the modifier state or to set the up/down state of a key984 // is via onKey(). so we have to call onKey() twice.985 KeyModifierMask state = pollActiveModifiers();986 m_keyState->onKey(button, down, state);987 988 // check for hot keys989 if (oldState != state) {990 // modifier key was pressed/released991 if (onHotKey(0, mp2)) {992 return true;993 }994 }995 else {996 // non-modifier was pressed/released997 if (onHotKey(mp1, mp2)) {998 return true;999 }1000 }1001 1002 // ignore message if posted prior to last mark change1003 if (!ignore()) {1004 // check for ctrl+alt+del. we do not want to pass that to the1005 // client. the user can use ctrl+alt+pause to emulate it.1006 UINT virtKey = (mp1 & 0xffu);1007 if (virtKey == VK_DELETE && (state & s_ctrlAlt) == s_ctrlAlt) {1008 LOG((CLOG_DEBUG "discard ctrl+alt+del"));1009 return true;1010 }1011 1012 // check for ctrl+alt+del emulation1013 if ((virtKey == VK_PAUSE || virtKey == VK_CANCEL) &&1014 (state & s_ctrlAlt) == s_ctrlAlt) {1015 LOG((CLOG_DEBUG "emulate ctrl+alt+del"));1016 // switch mp1 and mp2 to be as if VK_DELETE was1017 // pressed or released. when mapping the key we require that1018 // we not use AltGr (the 0x10000 flag in mp1) and we not1019 // use the keypad delete key (the 0x01000000 flag in mp2).1020 mp1 = VK_DELETE | 0x00010000u;1021 mp2 &= 0xfe000000;1022 mp2 |= m_keyState->virtualKeyToButton(mp1 & 0xffu) << 16;1023 mp2 |= 0x01000001;1024 }1025 1026 // process key1027 KeyModifierMask mask;1028 KeyID key = m_keyState->mapKeyFromEvent((ULONG)mp1, (ULONG)mp2, &mask);1029 button = static_cast<KeyButton>((mp2 & 0x01ff0000u) >> 16);1030 if (key != kKeyNone) {1031 // fix key up. if the key isn't down according to1032 // our table then we never got the key press event1033 // for it. if it's not a modifier key then we'll1034 // synthesize the press first. only do this on1035 // the windows 95 family, which eats certain special1036 // keys like alt+tab, ctrl+esc, etc.1037 if (m_is95Family && !wasDown && !down) {1038 switch (virtKey) {1039 case VK_SHIFT:1040 case VK_LSHIFT:1041 case VK_RSHIFT:1042 case VK_CONTROL:1043 case VK_LCONTROL:1044 case VK_RCONTROL:1045 case VK_MENU:1046 case VK_LMENU:1047 case VK_RMENU:1048 case VK_LWIN:1049 case VK_RWIN:1050 case VK_CAPITAL:1051 case VK_NUMLOCK:1052 case VK_SCROLL:1053 break;1054 1055 default:1056 m_keyState->sendKeyEvent(getEventTarget(),1057 true, false, key, mask, 1, button);1058 break;1059 }1060 }1061 1062 // do it1063 m_keyState->sendKeyEvent(getEventTarget(),1064 ((mp2 & 0x80000000u) == 0),1065 ((mp2 & 0x40000000u) != 0),1066 key, mask, (SInt32)(mp2 & 0xffff), button);1067 }1068 else {1069 LOG((CLOG_DEBUG1 "cannot map key"));1070 }1071 }937 static const KeyModifierMask s_ctrlAlt = KeyModifierControl | KeyModifierAlt; 938 939 LOG((CLOG_DEBUG1 "event: Key char=%d, vk=0x%02x, nagr=%d, mp2=0x%08x", (mp1 & 0xff00u) >> 8, mp1 & 0xffu, (mp1 & 0x10000u) ? 1 : 0, mp2)); 940 941 // get event info 942 KeyButton button = (KeyButton)((mp2 & 0x01ff0000) >> 16); 943 bool down = ((mp2 & 0x80000000u) == 0x00000000u); 944 bool wasDown = isKeyDown(button); 945 KeyModifierMask oldState = pollActiveModifiers(); 946 947 // check for autorepeat 948 if (m_keyState->testAutoRepeat(down, (mp2 & 0x40000000u) == 1, button)) { 949 mp2 |= 0x40000000u; 950 } 951 952 // if the button is zero then guess what the button should be. 953 // these are badly synthesized key events and logitech software 954 // that maps mouse buttons to keys is known to do this. 955 // alternatively, we could just throw these events out. 956 if (button == 0) { 957 button = m_keyState->virtualKeyToButton(mp1 & 0xffu); 958 if (button == 0) { 959 return true; 960 } 961 wasDown = isKeyDown(button); 962 } 963 964 // record keyboard state 965 m_keyState->onKey(button, down, oldState); 966 967 // windows doesn't tell us the modifier key state on mouse or key 968 // events so we have to figure it out. most apps would use 969 // GetKeyState() or even GetAsyncKeyState() for that but we can't 970 // because our hook doesn't pass on key events for several modifiers. 971 // it can't otherwise the system would interpret them normally on 972 // the primary screen even when on a secondary screen. so tapping 973 // alt would activate menus and tapping the windows key would open 974 // the start menu. if you don't pass those events on in the hook 975 // then GetKeyState() understandably doesn't reflect the effect of 976 // the event. curiously, neither does GetAsyncKeyState(), which is 977 // surprising. 978 // 979 // so anyway, we have to track the modifier state ourselves for 980 // at least those modifiers we don't pass on. pollActiveModifiers() 981 // does that but we have to update the keyboard state before calling 982 // pollActiveModifiers() to get the right answer. but the only way 983 // to set the modifier state or to set the up/down state of a key 984 // is via onKey(). so we have to call onKey() twice. 985 KeyModifierMask state = pollActiveModifiers(); 986 m_keyState->onKey(button, down, state); 987 988 // check for hot keys 989 if (oldState != state) { 990 // modifier key was pressed/released 991 if (onHotKey(0, mp2)) { 992 return true; 993 } 994 } 995 else { 996 // non-modifier was pressed/released 997 if (onHotKey(mp1, mp2)) { 998 return true; 999 } 1000 } 1001 1002 // ignore message if posted prior to last mark change 1003 if (!ignore()) { 1004 // check for ctrl+alt+del. we do not want to pass that to the 1005 // client. the user can use ctrl+alt+pause to emulate it. 1006 UINT virtKey = (mp1 & 0xffu); 1007 if (virtKey == VK_DELETE && (state & s_ctrlAlt) == s_ctrlAlt) { 1008 LOG((CLOG_DEBUG "discard ctrl+alt+del")); 1009 return true; 1010 } 1011 1012 // check for ctrl+alt+del emulation 1013 if ((virtKey == VK_PAUSE || virtKey == VK_CANCEL) && 1014 (state & s_ctrlAlt) == s_ctrlAlt) { 1015 LOG((CLOG_DEBUG "emulate ctrl+alt+del")); 1016 // switch mp1 and mp2 to be as if VK_DELETE was 1017 // pressed or released. when mapping the key we require that 1018 // we not use AltGr (the 0x10000 flag in mp1) and we not 1019 // use the keypad delete key (the 0x01000000 flag in mp2). 1020 mp1 = VK_DELETE | 0x00010000u; 1021 mp2 &= 0xfe000000; 1022 mp2 |= m_keyState->virtualKeyToButton(mp1 & 0xffu) << 16; 1023 mp2 |= 0x01000001; 1024 } 1025 1026 // process key 1027 KeyModifierMask mask; 1028 KeyID key = m_keyState->mapKeyFromEvent((ULONG)mp1, (ULONG)mp2, &mask); 1029 button = static_cast<KeyButton>((mp2 & 0x01ff0000u) >> 16); 1030 if (key != kKeyNone) { 1031 // fix key up. if the key isn't down according to 1032 // our table then we never got the key press event 1033 // for it. if it's not a modifier key then we'll 1034 // synthesize the press first. only do this on 1035 // the windows 95 family, which eats certain special 1036 // keys like alt+tab, ctrl+esc, etc. 1037 if (m_is95Family && !wasDown && !down) { 1038 switch (virtKey) { 1039 case VK_SHIFT: 1040 case VK_LSHIFT: 1041 case VK_RSHIFT: 1042 case VK_CONTROL: 1043 case VK_LCONTROL: 1044 case VK_RCONTROL: 1045 case VK_MENU: 1046 case VK_LMENU: 1047 case VK_RMENU: 1048 case VK_LWIN: 1049 case VK_RWIN: 1050 case VK_CAPITAL: 1051 case VK_NUMLOCK: 1052 case VK_SCROLL: 1053 break; 1054 1055 default: 1056 m_keyState->sendKeyEvent(getEventTarget(), 1057 true, false, key, mask, 1, button); 1058 break; 1059 } 1060 } 1061 1062 // do it 1063 m_keyState->sendKeyEvent(getEventTarget(), 1064 ((mp2 & 0x80000000u) == 0), 1065 ((mp2 & 0x40000000u) != 0), 1066 key, mask, (SInt32)(mp2 & 0xffff), button); 1067 } 1068 else { 1069 LOG((CLOG_DEBUG1 "cannot map key")); 1070 } 1071 } 1072 1072 #endif 1073 return true;1073 return true; 1074 1074 } 1075 1075 … … 1078 1078 { 1079 1079 #if 0 1080 // get the key info1081 KeyModifierMask state = getActiveModifiers();1082 UINT virtKey = (mp1 & 0xffu);1083 UINT modifiers = 0;1084 if ((state & KeyModifierShift) != 0) {1085 modifiers |= MOD_SHIFT;1086 }1087 if ((state & KeyModifierControl) != 0) {1088 modifiers |= MOD_CONTROL;1089 }1090 if ((state & KeyModifierAlt) != 0) {1091 modifiers |= MOD_ALT;1092 }1093 if ((state & KeyModifierSuper) != 0) {1094 modifiers |= MOD_WIN;1095 }1096 1097 // find the hot key id1098 HotKeyToIDMap::const_iterator i =1099 m_hotKeyToIDMap.find(CHotKeyItem(virtKey, modifiers));1100 if (i == m_hotKeyToIDMap.end()) {1101 return false;1102 }1103 1104 // find what kind of event1105 CEvent::Type type;1106 if ((mp2 & 0x80000000u) == 0u) {1107 if ((mp2 & 0x40000000u) != 0u) {1108 // ignore key repeats but it counts as a hot key1109 return true;1110 }1111 type = getHotKeyDownEvent();1112 }1113 else {1114 type = getHotKeyUpEvent();1115 }1116 1117 // generate event1118 EVENTQUEUE->addEvent(CEvent(type, getEventTarget(),1119 CHotKeyInfo::alloc(i->second)));1080 // get the key info 1081 KeyModifierMask state = getActiveModifiers(); 1082 UINT virtKey = (mp1 & 0xffu); 1083 UINT modifiers = 0; 1084 if ((state & KeyModifierShift) != 0) { 1085 modifiers |= MOD_SHIFT; 1086 } 1087 if ((state & KeyModifierControl) != 0) { 1088 modifiers |= MOD_CONTROL; 1089 } 1090 if ((state & KeyModifierAlt) != 0) { 1091 modifiers |= MOD_ALT; 1092 } 1093 if ((state & KeyModifierSuper) != 0) { 1094 modifiers |= MOD_WIN; 1095 } 1096 1097 // find the hot key id 1098 HotKeyToIDMap::const_iterator i = 1099 m_hotKeyToIDMap.find(CHotKeyItem(virtKey, modifiers)); 1100 if (i == m_hotKeyToIDMap.end()) { 1101 return false; 1102 } 1103 1104 // find what kind of event 1105 CEvent::Type type; 1106 if ((mp2 & 0x80000000u) == 0u) { 1107 if ((mp2 & 0x40000000u) != 0u) { 1108 // ignore key repeats but it counts as a hot key 1109 return true; 1110 } 1111 type = getHotKeyDownEvent(); 1112 } 1113 else { 1114 type = getHotKeyUpEvent(); 1115 } 1116 1117 // generate event 1118 EVENTQUEUE->addEvent(CEvent(type, getEventTarget(), 1119 CHotKeyInfo::alloc(i->second))); 1120 1120 1121 1121 #endif 1122 return true;1122 return true; 1123 1123 } 1124 1124 … … 1126 1126 CPMScreen::onMouseButton(ULONG msg, SInt32 ax, SInt32 ay) 1127 1127 { 1128 // get which button1129 bool pressed = mapPressFromEvent(msg);1130 ButtonID button = mapButtonFromEvent(msg);1131 1132 // keep our shadow key state up to date1133 if (button >= kButtonLeft && button <= kButtonExtra0 + 1) {1134 if (pressed) {1135 m_buttons[button] = true;1136 }1137 else {1138 m_buttons[button] = false;1139 }1140 }1141 1142 // ignore message if posted prior to last mark change1143 if (!ignore()) {1144 KeyModifierMask mask = m_keyState->getActiveModifiers();1145 if (pressed) {1146 LOG((CLOG_DEBUG1 "event: button press button=%d", button));1147 if (button != kButtonNone) {1148 sendEvent(getButtonDownEvent(),1149 CButtonInfo::alloc(button, mask));1150 }1151 }1152 else {1153 LOG((CLOG_DEBUG1 "event: button release button=%d", button));1154 if (button != kButtonNone) {1155 sendEvent(getButtonUpEvent(),1156 CButtonInfo::alloc(button, mask));1157 }1158 }1159 }1160 1161 return true;1128 // get which button 1129 bool pressed = mapPressFromEvent(msg); 1130 ButtonID button = mapButtonFromEvent(msg); 1131 1132 // keep our shadow key state up to date 1133 if (button >= kButtonLeft && button <= kButtonExtra0 + 1) { 1134 if (pressed) { 1135 m_buttons[button] = true; 1136 } 1137 else { 1138 m_buttons[button] = false; 1139 } 1140 } 1141 1142 // ignore message if posted prior to last mark change 1143 if (!ignore()) { 1144 KeyModifierMask mask = m_keyState->getActiveModifiers(); 1145 if (pressed) { 1146 LOG((CLOG_DEBUG1 "event: button press button=%d", button)); 1147 if (button != kButtonNone) { 1148 sendEvent(getButtonDownEvent(), 1149 CButtonInfo::alloc(button, mask)); 1150 } 1151 } 1152 else { 1153 LOG((CLOG_DEBUG1 "event: button release button=%d", button)); 1154 if (button != kButtonNone) { 1155 sendEvent(getButtonUpEvent(), 1156 CButtonInfo::alloc(button, mask)); 1157 } 1158 } 1159 } 1160 1161 return true; 1162 1162 } 1163 1163 … … 1165 1165 CPMScreen::onMouseMove(ULONG msg, SInt32 ax, SInt32 ay) 1166 1166 { 1167 // compute motion delta (relative to the last known1168 // mouse position)1169 SInt32 x = ax - m_xCursor;1170 SInt32 y = ay - m_yCursor;1171 1172 // ignore if the mouse didn't move or if message posted prior1173 // to last mark change.1174 if (ignore() || (x == 0 && y == 0)) {1175 return true;1176 }1177 1178 // save position to compute delta of next motion1179 m_xCursor = ax;1180 m_yCursor = ay;1181 1182 if (m_isOnScreen) {1183 // motion on primary screen1184 sendEvent(getMotionOnPrimaryEvent(), CMotionInfo::alloc(m_xCursor, m_yCursor));1185 }1186 else {1187 // motion on secondary screen. warp mouse back to1188 // center.1189 warpCursorNoFlush(m_xCenter, m_yCenter);1190 1191 // examine the motion. if it's about the distance1192 // from the center of the screen to an edge then1193 // it's probably a bogus motion that we want to1194 // ignore (see warpCursorNoFlush() for a further1195 // description).1196 static SInt32 bogusZoneSize = 10;1197 if (-x + bogusZoneSize > m_xCenter - m_x ||1198 x + bogusZoneSize > m_x + m_cx - m_xCenter ||1199 -y + bogusZoneSize > m_yCenter - m_y ||1200 y + bogusZoneSize > m_y + m_cy - m_yCenter) {1201 LOG((CLOG_DEBUG "dropped bogus motion %+d,%+d", x, y));1202 }1203 else {1204 // send motion1205 sendEvent(getMotionOnSecondaryEvent(), CMotionInfo::alloc(x, y));1206 }1207 }1208 1209 return true;1167 // compute motion delta (relative to the last known 1168 // mouse position) 1169 SInt32 x = ax - m_xCursor; 1170 SInt32 y = ay - m_yCursor; 1171 1172 // ignore if the mouse didn't move or if message posted prior 1173 // to last mark change. 1174 if (ignore() || (x == 0 && y == 0)) { 1175 return true; 1176 } 1177 1178 // save position to compute delta of next motion 1179 m_xCursor = ax; 1180 m_yCursor = ay; 1181 1182 if (m_isOnScreen) { 1183 // motion on primary screen 1184 sendEvent(getMotionOnPrimaryEvent(), CMotionInfo::alloc(m_xCursor, m_yCursor)); 1185 } 1186 else { 1187 // motion on secondary screen. warp mouse back to 1188 // center. 1189 warpCursorNoFlush(m_xCenter, m_yCenter); 1190 1191 // examine the motion. if it's about the distance 1192 // from the center of the screen to an edge then 1193 // it's probably a bogus motion that we want to 1194 // ignore (see warpCursorNoFlush() for a further 1195 // description). 1196 static SInt32 bogusZoneSize = 10; 1197 if (-x + bogusZoneSize > m_xCenter - m_x || 1198 x + bogusZoneSize > m_x + m_cx - m_xCenter || 1199 -y + bogusZoneSize > m_yCenter - m_y || 1200 y + bogusZoneSize > m_y + m_cy - m_yCenter) { 1201 LOG((CLOG_DEBUG "dropped bogus motion %+d,%+d", x, y)); 1202 } 1203 else { 1204 // send motion 1205 sendEvent(getMotionOnSecondaryEvent(), CMotionInfo::alloc(x, y)); 1206 } 1207 } 1208 1209 return true; 1210 1210 } 1211 1211 … … 1213 1213 CPMScreen::onClipboardChange() 1214 1214 { 1215 // now notify client that somebody changed the clipboard (unless1216 // we're the owner).1217 if (!CPMClipboard::isOwnedBySynergy()) {1218 if (m_ownClipboard) {1219 LOG((CLOG_DEBUG "clipboard changed: lost ownership"));1220 m_ownClipboard = false;1221 sendClipboardEvent(getClipboardGrabbedEvent(), kClipboardClipboard);1222 sendClipboardEvent(getClipboardGrabbedEvent(), kClipboardSelection);1223 }1224 }1225 else if (!m_ownClipboard) {1226 LOG((CLOG_DEBUG "clipboard changed: synergy owned"));1227 m_ownClipboard = true;1228 }1229 1230 return true;1215 // now notify client that somebody changed the clipboard (unless 1216 // we're the owner). 1217 if (!CPMClipboard::isOwnedBySynergy()) { 1218 if (m_ownClipboard) { 1219 LOG((CLOG_DEBUG "clipboard changed: lost ownership")); 1220 m_ownClipboard = false; 1221 sendClipboardEvent(getClipboardGrabbedEvent(), kClipboardClipboard); 1222 sendClipboardEvent(getClipboardGrabbedEvent(), kClipboardSelection); 1223 } 1224 } 1225 else if (!m_ownClipboard) { 1226 LOG((CLOG_DEBUG "clipboard changed: synergy owned")); 1227 m_ownClipboard = true; 1228 } 1229 1230 return true; 1231 1231 } 1232 1232 … … 1234 1234 CPMScreen::warpCursorNoFlush(SInt32 x, SInt32 y) 1235 1235 { 1236 // send an event that we can recognize before the mouse warp1236 // send an event that we can recognize before the mouse warp 1237 1237 WinPostQueueMsg(m_hmq, SYNERGY_PM_MSG_PRE_WARP, (MPARAM)x, (MPARAM)y); 1238 1238 1239 // warp mouse. hopefully this inserts a mouse motion event1240 // between the previous message and the following message.1239 // warp mouse. hopefully this inserts a mouse motion event 1240 // between the previous message and the following message. 1241 1241 WinSetPointerPos(HWND_DESKTOP, x, y); 1242 1242 1243 // yield the CPU. there's a race condition when warping:1244 // a hardware mouse event occurs1245 // the mouse hook is not called because that process doesn't have the CPU1246 // we send PRE_WARP, SetCursorPos(), send POST_WARP1247 // we process all of those events and update m_x, m_y1248 // we finish our time slice1249 // the hook is called1250 // the hook sends us a mouse event from the pre-warp position1251 // we get the CPU1252 // we compute a bogus warp1253 // we need the hook to process all mouse events that occur1254 // before we warp before we do the warp but i'm not sure how1255 // to guarantee that. yielding the CPU here may reduce the1256 // chance of undesired behavior. we'll also check for very1257 // large motions that look suspiciously like about half width1258 // or height of the screen.1259 ARCH->sleep(0.0);1260 1261 // send an event that we can recognize after the mouse warp1243 // yield the CPU. there's a race condition when warping: 1244 // a hardware mouse event occurs 1245 // the mouse hook is not called because that process doesn't have the CPU 1246 // we send PRE_WARP, SetCursorPos(), send POST_WARP 1247 // we process all of those events and update m_x, m_y 1248 // we finish our time slice 1249 // the hook is called 1250 // the hook sends us a mouse event from the pre-warp position 1251 // we get the CPU 1252 // we compute a bogus warp 1253 // we need the hook to process all mouse events that occur 1254 // before we warp before we do the warp but i'm not sure how 1255 // to guarantee that. yielding the CPU here may reduce the 1256 // chance of undesired behavior. we'll also check for very 1257 // large motions that look suspiciously like about half width 1258 // or height of the screen. 1259 ARCH->sleep(0.0); 1260 1261 // send an event that we can recognize after the mouse warp 1262 1262 WinPostQueueMsg(m_hmq, SYNERGY_PM_MSG_POST_WARP, 0, 0); 1263 1263 } … … 1266 1266 CPMScreen::nextMark() 1267 1267 { 1268 // next mark1269 ++m_mark;1270 1271 // mark point in message queue where the mark was changed1268 // next mark 1269 ++m_mark; 1270 1271 // mark point in message queue where the mark was changed 1272 1272 WinPostQueueMsg(m_hmq, SYNERGY_PM_MSG_MARK, (MPARAM)m_mark, 0); 1273 1273 } … … 1276 1276 CPMScreen::ignore() const 1277 1277 { 1278 return (m_mark != m_markReceived);1278 return (m_mark != m_markReceived); 1279 1279 } 1280 1280 … … 1282 1282 CPMScreen::updateScreenShape() 1283 1283 { 1284 // get shape1285 m_x = 0;1286 m_y = 0;1287 m_cx = WinQuerySysValue(HWND_DESKTOP, SV_CXSCREEN);1288 m_cy = WinQuerySysValue(HWND_DESKTOP, SV_CYSCREEN);1289 1290 // get center for cursor1291 m_xCenter = m_cx / 2;1292 m_yCenter = m_cy / 2;1293 1294 // check for multiple monitors1295 m_multimon = false;1284 // get shape 1285 m_x = 0; 1286 m_y = 0; 1287 m_cx = WinQuerySysValue(HWND_DESKTOP, SV_CXSCREEN); 1288 m_cy = WinQuerySysValue(HWND_DESKTOP, SV_CYSCREEN); 1289 1290 // get center for cursor 1291 m_xCenter = m_cx / 2; 1292 m_yCenter = m_cy / 2; 1293 1294 // check for multiple monitors 1295 m_multimon = false; 1296 1296 } 1297 1297 … … 1301 1301 /** @todo query which is left and which is right. */ 1302 1302 1303 switch (msg) {1303 switch (msg) { 1304 1304 case WM_BUTTON1DOWN: 1305 1305 case WM_BUTTON1UP: 1306 1306 case WM_BUTTON1DBLCLK: 1307 1307 case WM_BUTTON1CLICK: //?? 1308 return kButtonLeft;1308 return kButtonLeft; 1309 1309 1310 1310 case WM_BUTTON2DOWN: … … 1319 1319 case WM_BUTTON3CLICK: //?? 1320 1320 return kButtonMiddle; 1321 default:1322 return kButtonNone;1323 }1321 default: 1322 return kButtonNone; 1323 } 1324 1324 } 1325 1325 … … 1327 1327 CPMScreen::mapPressFromEvent(ULONG msg) const 1328 1328 { 1329 switch (msg) {1329 switch (msg) { 1330 1330 case WM_BUTTON1DOWN: 1331 1331 case WM_BUTTON1CLICK: //?? … … 1344 1344 default: 1345 1345 return false; 1346 }1346 } 1347 1347 } 1348 1348 … … 1350 1350 CPMScreen::updateKeysCB(void*) 1351 1351 { 1352 // record which keys we think are down1353 bool down[IKeyState::kNumButtons];1354 bool sendFixes = (isPrimary() && !m_isOnScreen);1355 if (sendFixes) {1356 for (KeyButton i = 0; i < IKeyState::kNumButtons; ++i) {1357 down[i] = m_keyState->isKeyDown(i);1358 }1359 }1360 1361 // now update the keyboard state1362 CPlatformScreen::updateKeyState();1363 1364 // now see which keys we thought were down but now think are up.1365 // send key releases for these keys to the active client.1366 if (sendFixes) {1367 KeyModifierMask mask = pollActiveModifiers();1368 for (KeyButton i = 0; i < IKeyState::kNumButtons; ++i) {1369 if (down[i] && !m_keyState->isKeyDown(i)) {1370 m_keyState->sendKeyEvent(getEventTarget(),1371 false, false, kKeyNone, mask, 1, i);1372 }1373 }1374 }1352 // record which keys we think are down 1353 bool down[IKeyState::kNumButtons]; 1354 bool sendFixes = (isPrimary() && !m_isOnScreen); 1355 if (sendFixes) { 1356 for (KeyButton i = 0; i < IKeyState::kNumButtons; ++i) { 1357 down[i] = m_keyState->isKeyDown(i); 1358 } 1359 } 1360 1361 // now update the keyboard state 1362 CPlatformScreen::updateKeyState(); 1363 1364 // now see which keys we thought were down but now think are up. 1365 // send key releases for these keys to the active client. 1366 if (sendFixes) { 1367 KeyModifierMask mask = pollActiveModifiers(); 1368 for (KeyButton i = 0; i < IKeyState::kNumButtons; ++i) { 1369 if (down[i] && !m_keyState->isKeyDown(i)) { 1370 m_keyState->sendKeyEvent(getEventTarget(), 1371 false, false, kKeyNone, mask, 1, i); 1372 } 1373 } 1374 } 1375 1375 } 1376 1376 … … 1378 1378 CPMScreen::forceShowCursor() 1379 1379 { 1380 // check for mouse - probably not required.1381 m_hasMouse = WinQuerySysValue(HWND_DESKTOP, SV_MOUSEPRESENT) != FALSE;1382 1383 // decide if we should show the mouse1384 bool showMouse = (!m_hasMouse && !m_isPrimary && m_isOnScreen);1385 1386 // show/hide the mouse1387 if (showMouse != m_showingMouse) {1380 // check for mouse - probably not required. 1381 m_hasMouse = WinQuerySysValue(HWND_DESKTOP, SV_MOUSEPRESENT) != FALSE; 1382 1383 // decide if we should show the mouse 1384 bool showMouse = (!m_hasMouse && !m_isPrimary && m_isOnScreen); 1385 1386 // show/hide the mouse 1387 if (showMouse != m_showingMouse) { 1388 1388 WinShowPointer(HWND_DESKTOP, showMouse); 1389 1389 m_showingMouse = WinQuerySysValue(HWND_DESKTOP, SV_POINTERLEVEL) != 0; 1390 }1390 } 1391 1391 } 1392 1392 … … 1400 1400 CPMScreen::wndProc(HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2) 1401 1401 { 1402 assert(s_screen != NULL);1403 1404 MRESULT mr = 0;1405 if (!s_screen->onEvent(hwnd, msg, mp1, mp2, &mr)) {1406 mr = WinDefWindowProc(hwnd, msg, mp1, mp2);1407 }1408 1409 return mr;1402 assert(s_screen != NULL); 1403 1404 MRESULT mr = 0; 1405 if (!s_screen->onEvent(hwnd, msg, mp1, mp2, &mr)) { 1406 mr = WinDefWindowProc(hwnd, msg, mp1, mp2); 1407 } 1408 1409 return mr; 1410 1410 } 1411 1411 … … 1416 1416 1417 1417 CPMScreen::CHotKeyItem::CHotKeyItem(ULONG keycode, ULONG mask) : 1418 m_keycode(keycode),1419 m_mask(mask)1420 { 1421 // do nothing1418 m_keycode(keycode), 1419 m_mask(mask) 1420 { 1421 // do nothing 1422 1422 } 1423 1423 … … 1425 1425 CPMScreen::CHotKeyItem::getVirtualKey() const 1426 1426 { 1427 return m_keycode;1427 return m_keycode; 1428 1428 } 1429 1429 … … 1431 1431 CPMScreen::CHotKeyItem::operator<(const CHotKeyItem& x) const 1432 1432 { 1433 return (m_keycode < x.m_keycode ||1434 (m_keycode == x.m_keycode && m_mask < x.m_mask));1433 return (m_keycode < x.m_keycode || 1434 (m_keycode == x.m_keycode && m_mask < x.m_mask)); 1435 1435 } 1436 1436 … … 1442 1442 * c-basic-offset: 4 1443 1443 * tab-width: 4 1444 * indent-tabs-mode: t1444 * indent-tabs-mode: s 1445 1445 * End: 1446 1446 */ -
trunk/synergy/lib/platform/CPMScreen.h
r2763 r2771 37 37 class CPMScreen : public CPlatformScreen { 38 38 public: 39 CPMScreen(bool isPrimary);40 virtual ~CPMScreen();41 42 // IScreen overrides43 virtual void*getEventTarget() const;44 virtual boolgetClipboard(ClipboardID id, IClipboard*) const;45 virtual voidgetShape(SInt32& x, SInt32& y, SInt32& cx, SInt32& cy) const;46 virtual voidgetCursorPos(SInt32& x, SInt32& y) const;47 48 // IPrimaryScreen overrides49 virtual voidreconfigure(UInt32 activeSides);50 virtual voidwarpCursor(SInt32 x, SInt32 y);51 virtual UInt32registerHotKey(KeyID key,52 KeyModifierMask mask);53 virtual voidunregisterHotKey(UInt32 id);54 virtual voidfakeInputBegin();55 virtual voidfakeInputEnd();56 virtual SInt32getJumpZoneSize() const;57 virtual boolisAnyMouseButtonDown() const;58 virtual voidgetCursorCenter(SInt32& x, SInt32& y) const;59 60 // ISecondaryScreen overrides61 virtual voidfakeMouseButton(ButtonID id, bool press) const;62 virtual voidfakeMouseMove(SInt32 x, SInt32 y) const;63 virtual voidfakeMouseRelativeMove(SInt32 dx, SInt32 dy) const;64 virtual voidfakeMouseWheel(SInt32 xDelta, SInt32 yDelta) const;65 66 // IKeyState overrides67 virtual voidupdateKeys();68 virtual voidfakeKeyDown(KeyID id, KeyModifierMask mask,69 KeyButton button);70 virtual voidfakeKeyRepeat(KeyID id, KeyModifierMask mask,71 SInt32 count, KeyButton button);72 virtual voidfakeKeyUp(KeyButton button);73 virtual voidfakeAllKeysUp();74 75 // IPlatformScreen overrides76 virtual voidenable();77 virtual voiddisable();78 virtual voidenter();79 virtual boolleave();80 virtual boolsetClipboard(ClipboardID, const IClipboard*);81 virtual voidcheckClipboards();82 virtual voidopenScreensaver(bool notify);83 virtual voidcloseScreensaver();84 virtual voidscreensaver(bool activate);85 virtual voidresetOptions();86 virtual voidsetOptions(const COptionsList& options);87 virtual voidsetSequenceNumber(UInt32);88 virtual boolisPrimary() const;39 CPMScreen(bool isPrimary); 40 virtual ~CPMScreen(); 41 42 // IScreen overrides 43 virtual void* getEventTarget() const; 44 virtual bool getClipboard(ClipboardID id, IClipboard*) const; 45 virtual void getShape(SInt32& x, SInt32& y, SInt32& cx, SInt32& cy) const; 46 virtual void getCursorPos(SInt32& x, SInt32& y) const; 47 48 // IPrimaryScreen overrides 49 virtual void reconfigure(UInt32 activeSides); 50 virtual void warpCursor(SInt32 x, SInt32 y); 51 virtual UInt32 registerHotKey(KeyID key, 52 KeyModifierMask mask); 53 virtual void unregisterHotKey(UInt32 id); 54 virtual void fakeInputBegin(); 55 virtual void fakeInputEnd(); 56 virtual SInt32 getJumpZoneSize() const; 57 virtual bool isAnyMouseButtonDown() const; 58 virtual void getCursorCenter(SInt32& x, SInt32& y) const; 59 60 // ISecondaryScreen overrides 61 virtual void fakeMouseButton(ButtonID id, bool press) const; 62 virtual void fakeMouseMove(SInt32 x, SInt32 y) const; 63 virtual void fakeMouseRelativeMove(SInt32 dx, SInt32 dy) const; 64 virtual void fakeMouseWheel(SInt32 xDelta, SInt32 yDelta) const; 65 66 // IKeyState overrides 67 virtual void updateKeys(); 68 virtual void fakeKeyDown(KeyID id, KeyModifierMask mask, 69 KeyButton button); 70 virtual void fakeKeyRepeat(KeyID id, KeyModifierMask mask, 71 SInt32 count, KeyButton button); 72 virtual void fakeKeyUp(KeyButton button); 73 virtual void fakeAllKeysUp(); 74 75 // IPlatformScreen overrides 76 virtual void enable(); 77 virtual void disable(); 78 virtual void enter(); 79 virtual bool leave(); 80 virtual bool setClipboard(ClipboardID, const IClipboard*); 81 virtual void checkClipboards(); 82 virtual void openScreensaver(bool notify); 83 virtual void closeScreensaver(); 84 virtual void screensaver(bool activate); 85 virtual void resetOptions(); 86 virtual void setOptions(const COptionsList& options); 87 virtual void setSequenceNumber(UInt32); 88 virtual bool isPrimary() const; 89 89 90 90 protected: 91 // IPlatformScreen overrides92 virtual voidhandleSystemEvent(const CEvent&, void*);93 virtual voidupdateButtons();94 virtual IKeyState*getKeyState() const;91 // IPlatformScreen overrides 92 virtual void handleSystemEvent(const CEvent&, void*); 93 virtual void updateButtons(); 94 virtual IKeyState* getKeyState() const; 95 95 96 96 private: 97 // initialization and shutdown operations98 HMODULEopenHookLibrary(const char* name);99 voidcloseHookLibrary(HMODULE hookLibrary) const;100 HWNDcreateWindow(const char* name);101 voiddestroyWindow(HWND) const;102 97 // initialization and shutdown operations 98 HMODULE openHookLibrary(const char* name); 99 void closeHookLibrary(HMODULE hookLibrary) const; 100 HWND createWindow(const char* name); 101 void destroyWindow(HWND) const; 102 103 103 // fake message injection 104 104 void fakeMessage(ULONG msg, MPARAM mp1, MPARAM mp2) const; 105 105 void fakeMouseMessage(ULONG msg, MPARAM mp1) const; 106 106 107 // convenience function to send events108 voidsendEvent(CEvent::Type type, void* = NULL);109 voidsendClipboardEvent(CEvent::Type type, ClipboardID id);110 111 // handle message before it gets dispatched. returns true iff112 // the message should not be dispatched.113 boolonPreDispatch(HWND, ULONG, MPARAM, MPARAM);114 115 // handle message before it gets dispatched. returns true iff116 // the message should not be dispatched.117 boolonPreDispatchPrimary(HWND, ULONG, MPARAM, MPARAM);118 119 // handle message. returns true iff handled and optionally sets120 // \c *result (which defaults to 0).121 boolonEvent(HWND, ULONG, MPARAM, MPARAM, MRESULT*);122 123 // message handlers124 boolonMark(UInt32 mark);125 boolonKey(USHORT fsFlags, UCHAR ucRepeat, UCHAR ucScanCode, USHORT usch, USHORT usvk);126 boolonHotKey(MPARAM, MPARAM);127 boolonMouseButton(ULONG msg, SInt32 ax, SInt32 ay);128 boolonMouseMove(ULONG msg, SInt32 ax, SInt32 ay);129 boolonClipboardChange();130 131 // warp cursor without discarding queued events132 voidwarpCursorNoFlush(SInt32 x, SInt32 y);133 134 // discard posted messages135 voidnextMark();136 137 // test if event should be ignored138 boolignore() const;139 140 // update screen size cache141 voidupdateScreenShape();142 143 // fix timer callback144 voidhandleFixes(const CEvent&, void*);145 146 // enable/disable special key combinations so we can catch/pass them147 voidenableSpecialKeys(bool) const;148 149 // map a button event to a button ID150 ButtonIDmapButtonFromEvent(ULONG msg) const;151 152 // map a button event to a press (true) or release (false)153 boolmapPressFromEvent(ULONG msg) const;154 155 // job to update the key state156 voidupdateKeysCB(void*);157 158 // determine whether the mouse is hidden by the system and force159 // it to be displayed if user has entered this secondary screen.160 voidforceShowCursor();161 162 // forceShowCursor uses MouseKeys to show the cursor. since we163 // don't actually want MouseKeys behavior we have to make sure164 // it applies when NumLock is in whatever state it's not in now.165 // this method does that.166 voidupdateForceShowCursor();167 168 // our window proc169 static MRESULT EXPENTRY wndProc(HWND, ULONG, MPARAM, MPARAM);107 // convenience function to send events 108 void sendEvent(CEvent::Type type, void* = NULL); 109 void sendClipboardEvent(CEvent::Type type, ClipboardID id); 110 111 // handle message before it gets dispatched. returns true iff 112 // the message should not be dispatched. 113 bool onPreDispatch(HWND, ULONG, MPARAM, MPARAM); 114 115 // handle message before it gets dispatched. returns true iff 116 // the message should not be dispatched. 117 bool onPreDispatchPrimary(HWND, ULONG, MPARAM, MPARAM); 118 119 // handle message. returns true iff handled and optionally sets 120 // \c *result (which defaults to 0). 121 bool onEvent(HWND, ULONG, MPARAM, MPARAM, MRESULT*); 122 123 // message handlers 124 bool onMark(UInt32 mark); 125 bool onKey(USHORT fsFlags, UCHAR ucRepeat, UCHAR ucScanCode, USHORT usch, USHORT usvk); 126 bool onHotKey(MPARAM, MPARAM); 127 bool onMouseButton(ULONG msg, SInt32 ax, SInt32 ay); 128 bool onMouseMove(ULONG msg, SInt32 ax, SInt32 ay); 129 bool onClipboardChange(); 130 131 // warp cursor without discarding queued events 132 void warpCursorNoFlush(SInt32 x, SInt32 y); 133 134 // discard posted messages 135 void nextMark(); 136 137 // test if event should be ignored 138 bool ignore() const; 139 140 // update screen size cache 141 void updateScreenShape(); 142 143 // fix timer callback 144 void handleFixes(const CEvent&, void*); 145 146 // enable/disable special key combinations so we can catch/pass them 147 void enableSpecialKeys(bool) const; 148 149 // map a button event to a button ID 150 ButtonID mapButtonFromEvent(ULONG msg) const; 151 152 // map a button event to a press (true) or release (false) 153 bool mapPressFromEvent(ULONG msg) const; 154 155 // job to update the key state 156 void updateKeysCB(void*); 157 158 // determine whether the mouse is hidden by the system and force 159 // it to be displayed if user has entered this secondary screen. 160 void forceShowCursor(); 161 162 // forceShowCursor uses MouseKeys to show the cursor. since we 163 // don't actually want MouseKeys behavior we have to make sure 164 // it applies when NumLock is in whatever state it's not in now. 165 // this method does that. 166 void updateForceShowCursor(); 167 168 // our window proc 169 static MRESULT EXPENTRY wndProc(HWND, ULONG, MPARAM, MPARAM); 170 170 171 171 private: 172 struct CHotKeyItem {173 public:174 CHotKeyItem(ULONG vk, ULONG modifiers);175 176 ULONGgetVirtualKey() const;177 178 booloperator<(const CHotKeyItem&) const;179 180 private:181 ULONGm_keycode;182 ULONGm_mask;183 };184 typedef std::map<UInt32, CHotKeyItem> HotKeyMap;185 typedef std::vector<UInt32> HotKeyIDList;186 typedef std::map<CHotKeyItem, UInt32> HotKeyToIDMap;187 188 // true if screen is being used as a primary screen, false otherwise189 boolm_isPrimary;190 boolm_isOnScreen;191 192 // screen shape stuff193 SInt32m_x, m_y;194 SInt32m_cx, m_cy;195 SInt32m_xCenter, m_yCenter;196 197 // true if system appears to have multiple monitors198 boolm_multimon;199 200 // last mouse position201 SInt32m_xCursor, m_yCursor;202 203 // last clipboard204 UInt32m_sequenceNumber;205 206 // used to discard queued messages that are no longer needed207 UInt32m_mark;208 UInt32m_markReceived;209 210 // the main loop's thread id, anchor block and message queue.211 intm_threadID;212 HABm_hab;213 HMQ m_hmq;214 215 // screen saver stuff216 CPMScreenSaver*m_screensaver;217 boolm_screensaverNotify;218 boolm_screensaverActive;219 220 // clipboard stuff. our window is used mainly as a clipboard221 // owner and as a link in the clipboard viewer chain.222 HWNDm_window;223 HWNDm_nextClipboardWindow;224 boolm_ownClipboard;225 226 // hook library stuff227 HMODULEm_hmodHook;228 InitFuncm_init;229 CleanupFuncm_cleanup;230 SetSidesFuncm_setSides;231 SetZoneFuncm_setZone;232 SetModeFuncm_setMode;233 FakeMsgFuncm_fakeMsg;234 235 // keyboard stuff236 CPMKeyState*m_keyState;237 238 // hot key stuff239 HotKeyMapm_hotKeys;240 HotKeyIDListm_oldHotKeyIDs;241 HotKeyToIDMapm_hotKeyToIDMap;242 243 // map of button state244 boolm_buttons[1 + kButtonExtra0 + 1];245 246 boolm_hasMouse;247 boolm_showingMouse;248 249 static CPMScreen*s_screen;172 struct CHotKeyItem { 173 public: 174 CHotKeyItem(ULONG vk, ULONG modifiers); 175 176 ULONG getVirtualKey() const; 177 178 bool operator<(const CHotKeyItem&) const; 179 180 private: 181 ULONG m_keycode; 182 ULONG m_mask; 183 }; 184 typedef std::map<UInt32, CHotKeyItem> HotKeyMap; 185 typedef std::vector<UInt32> HotKeyIDList; 186 typedef std::map<CHotKeyItem, UInt32> HotKeyToIDMap; 187 188 // true if screen is being used as a primary screen, false otherwise 189 bool m_isPrimary; 190 bool m_isOnScreen; 191 192 // screen shape stuff 193 SInt32 m_x, m_y; 194 SInt32 m_cx, m_cy; 195 SInt32 m_xCenter, m_yCenter; 196 197 // true if system appears to have multiple monitors 198 bool m_multimon; 199 200 // last mouse position 201 SInt32 m_xCursor, m_yCursor; 202 203 // last clipboard 204 UInt32 m_sequenceNumber; 205 206 // used to discard queued messages that are no longer needed 207 UInt32 m_mark; 208 UInt32 m_markReceived; 209 210 // the main loop's thread id, anchor block and message queue. 211 int m_threadID; 212 HAB m_hab; 213 HMQ m_hmq; 214 215 // screen saver stuff 216 CPMScreenSaver* m_screensaver; 217 bool m_screensaverNotify; 218 bool m_screensaverActive; 219 220 // clipboard stuff. our window is used mainly as a clipboard 221 // owner and as a link in the clipboard viewer chain. 222 HWND m_window; 223 HWND m_nextClipboardWindow; 224 bool m_ownClipboard; 225 226 // hook library stuff 227 HMODULE m_hmodHook; 228 InitFunc m_init; 229 CleanupFunc m_cleanup; 230 SetSidesFunc m_setSides; 231 SetZoneFunc m_setZone; 232 SetModeFunc m_setMode; 233 FakeMsgFunc m_fakeMsg; 234 235 // keyboard stuff 236 CPMKeyState* m_keyState; 237 238 // hot key stuff 239 HotKeyMap m_hotKeys; 240 HotKeyIDList m_oldHotKeyIDs; 241 HotKeyToIDMap m_hotKeyToIDMap; 242 243 // map of button state 244 bool m_buttons[1 + kButtonExtra0 + 1]; 245 246 bool m_hasMouse; 247 bool m_showingMouse; 248 249 static CPMScreen* s_screen; 250 250 }; 251 251 … … 256 256 * c-basic-offset: 4 257 257 * tab-width: 4 258 * indent-tabs-mode: t258 * indent-tabs-mode: s 259 259 * End: 260 260 */
Note:
See TracChangeset
for help on using the changeset viewer.
