Changeset 59345 in vbox
- Timestamp:
- Jan 14, 2016 1:01:39 PM (9 years ago)
- Location:
- trunk/src/VBox/Frontends/VirtualBox/src/runtime
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Frontends/VirtualBox/src/runtime/UIKeyboardHandler.cpp
r59032 r59345 436 436 #endif /* VBOX_WITH_DEBUGGER_GUI */ 437 437 438 #if defined(Q_WS_WIN)438 #ifdef Q_WS_WIN 439 439 /** Tell keyboard event handler to skip host keyboard events. Used for HID LEDs sync 440 440 * when on Windows host a keyboard event is generated in order to change corresponding LED. */ … … 443 443 m_fSkipKeyboardEvents = fSkip; 444 444 } 445 #endif /* Q_WS_WIN */ 446 447 #if QT_VERSION < 0x050000 448 # if defined(Q_WS_WIN) 445 449 446 450 bool UIKeyboardHandler::winEventFilter(MSG *pMsg, ulong uScreenId) … … 595 599 } 596 600 597 #elif defined(Q_WS_X11) 598 # if QT_VERSION >= 0x050000 599 600 bool UIKeyboardHandler::nativeEventFilter(void *pMessage, ulong uScreenId) 601 { 602 /* Cast to XCB event: */ 603 xcb_generic_event_t *pEvent = static_cast<xcb_generic_event_t*>(pMessage); 604 605 /* Check if some system event should be filtered out. 606 * Returning @c true means filtering-out, 607 * Returning @c false means passing event to Qt. */ 608 bool fResult = false; /* Pass to Qt by default. */ 609 switch (pEvent->response_type & ~0x80) 610 { 611 /* Watch for keyboard behavior: */ 612 case XCB_KEY_PRESS: 613 case XCB_KEY_RELEASE: 614 { 615 /* Cast to XCB key-event: */ 616 xcb_key_press_event_t *pKeyEvent = static_cast<xcb_key_press_event_t*>(pMessage); 617 618 /* Translate the keycode to a PC scancode: */ 619 unsigned scan = handleXKeyEvent(QX11Info::display(), pKeyEvent->detail); 620 621 /* Scancodes 0x00 (no valid translation) and 0x80 (extended flag) are ignored: */ 622 if (!(scan & 0x7F)) 623 { 624 fResult = true; 625 break; 626 } 627 628 // /* Fix for http://www.virtualbox.org/ticket/1296: 629 // * when X11 sends events for repeated keys, it always inserts an XKeyRelease before the XKeyPress. */ 630 // XEvent returnEvent; 631 // if ((pEvent->type == XKeyRelease) && (XCheckIfEvent(pEvent->xkey.display, &returnEvent, 632 // UIKeyboardHandlerCompEvent, (XPointer)pEvent) == True)) 633 // { 634 // XPutBackEvent(pEvent->xkey.display, &returnEvent); 635 // fResult = true; 636 // break; 637 // } 638 639 /* Detect common scancode flags: */ 640 int flags = 0; 641 if (scan >> 8) 642 flags |= KeyExtended; 643 if ((pEvent->response_type & ~0x80) == XCB_KEY_PRESS) 644 flags |= KeyPressed; 645 646 /* Remove the extended flag: */ 647 scan &= 0x7F; 648 649 /* Special Korean keys must send scancode 0xF1/0xF2 650 * when pressed and nothing when released. */ 651 if (scan == 0x71 || scan == 0x72) 652 { 653 if ((pEvent->response_type & ~0x80) == XCB_KEY_RELEASE) 654 { 655 fResult = true; 656 break; 657 } 658 /* Re-create the bizarre scancode: */ 659 scan |= 0x80; 660 } 661 662 /* Translate the keycode to a keysym: */ 663 KeySym ks = ::wrapXkbKeycodeToKeysym(QX11Info::display(), pKeyEvent->detail, 0, 0); 664 665 /* Detect particular scancode flags: */ 666 switch (ks) 667 { 668 case XK_Print: 669 flags |= KeyPrint; 670 break; 671 case XK_Pause: 672 if (pKeyEvent->state & ControlMask) 673 { 674 ks = XK_Break; 675 flags |= KeyExtended; 676 scan = 0x46; 677 } 678 else 679 flags |= KeyPause; 680 break; 681 } 682 683 /* Handle key-event: */ 684 fResult = keyEvent(ks, scan, flags, uScreenId); 685 break; 686 } 687 default: 688 break; 689 } 690 /* Return result: */ 691 return fResult; 692 } 693 694 # else /* QT_VERSION < 0x050000 */ 601 # elif defined(Q_WS_X11) 695 602 696 603 static Bool UIKeyboardHandlerCompEvent(Display*, XEvent *pEvent, XPointer pvArg) … … 816 723 } 817 724 818 # endif /* QT_VERSION < 0x050000 */ 819 #endif /* Q_WS_X11 */ 725 # endif /* Q_WS_X11 */ 726 #else /* QT_VERSION >= 0x050000 */ 727 728 bool UIKeyboardHandler::nativeEventFilter(void *pMessage, ulong uScreenId) 729 { 730 /* Cast to XCB event: */ 731 xcb_generic_event_t *pEvent = static_cast<xcb_generic_event_t*>(pMessage); 732 733 /* Check if some system event should be filtered out. 734 * Returning @c true means filtering-out, 735 * Returning @c false means passing event to Qt. */ 736 bool fResult = false; /* Pass to Qt by default. */ 737 switch (pEvent->response_type & ~0x80) 738 { 739 /* Watch for keyboard behavior: */ 740 case XCB_KEY_PRESS: 741 case XCB_KEY_RELEASE: 742 { 743 /* Cast to XCB key-event: */ 744 xcb_key_press_event_t *pKeyEvent = static_cast<xcb_key_press_event_t*>(pMessage); 745 746 /* Translate the keycode to a PC scancode: */ 747 unsigned scan = handleXKeyEvent(QX11Info::display(), pKeyEvent->detail); 748 749 /* Scancodes 0x00 (no valid translation) and 0x80 (extended flag) are ignored: */ 750 if (!(scan & 0x7F)) 751 { 752 fResult = true; 753 break; 754 } 755 756 // /* Fix for http://www.virtualbox.org/ticket/1296: 757 // * when X11 sends events for repeated keys, it always inserts an XKeyRelease before the XKeyPress. */ 758 // XEvent returnEvent; 759 // if ((pEvent->type == XKeyRelease) && (XCheckIfEvent(pEvent->xkey.display, &returnEvent, 760 // UIKeyboardHandlerCompEvent, (XPointer)pEvent) == True)) 761 // { 762 // XPutBackEvent(pEvent->xkey.display, &returnEvent); 763 // fResult = true; 764 // break; 765 // } 766 767 /* Detect common scancode flags: */ 768 int flags = 0; 769 if (scan >> 8) 770 flags |= KeyExtended; 771 if ((pEvent->response_type & ~0x80) == XCB_KEY_PRESS) 772 flags |= KeyPressed; 773 774 /* Remove the extended flag: */ 775 scan &= 0x7F; 776 777 /* Special Korean keys must send scancode 0xF1/0xF2 778 * when pressed and nothing when released. */ 779 if (scan == 0x71 || scan == 0x72) 780 { 781 if ((pEvent->response_type & ~0x80) == XCB_KEY_RELEASE) 782 { 783 fResult = true; 784 break; 785 } 786 /* Re-create the bizarre scancode: */ 787 scan |= 0x80; 788 } 789 790 /* Translate the keycode to a keysym: */ 791 KeySym ks = ::wrapXkbKeycodeToKeysym(QX11Info::display(), pKeyEvent->detail, 0, 0); 792 793 /* Detect particular scancode flags: */ 794 switch (ks) 795 { 796 case XK_Print: 797 flags |= KeyPrint; 798 break; 799 case XK_Pause: 800 if (pKeyEvent->state & ControlMask) 801 { 802 ks = XK_Break; 803 flags |= KeyExtended; 804 scan = 0x46; 805 } 806 else 807 flags |= KeyPause; 808 break; 809 } 810 811 /* Handle key-event: */ 812 fResult = keyEvent(ks, scan, flags, uScreenId); 813 break; 814 } 815 default: 816 break; 817 } 818 /* Return result: */ 819 return fResult; 820 } 821 822 #endif /* QT_VERSION >= 0x050000 */ 820 823 821 824 /* Machine state-change handler: */ … … 885 888 , m_fPassCADtoGuest(false) 886 889 , m_fDebuggerActive(false) 887 #if defined(Q_WS_WIN) 890 #if defined(Q_WS_MAC) 891 , m_darwinKeyModifiers(0) 892 , m_fKeyboardGrabbed(false) 893 , m_iKeyboardGrabViewIndex(-1) 894 #elif defined(Q_WS_WIN) 888 895 , m_bIsHostkeyInCapture(false) 889 896 , m_iKeyboardHookViewIndex(-1) 890 897 , m_fSkipKeyboardEvents(false) 891 898 , m_pAltGrMonitor(0) 892 #elif defined(Q_WS_MAC) 893 , m_darwinKeyModifiers(0) 894 , m_fKeyboardGrabbed(false) 895 , m_iKeyboardGrabViewIndex(-1) 896 #endif /* Q_WS_MAC */ 899 #endif /* Q_WS_WIN */ 897 900 , m_cMonitors(1) 898 901 { … … 1158 1161 } 1159 1162 1160 #if defined(Q_WS_WIN) 1161 1162 LRESULT CALLBACK UIKeyboardHandler::lowLevelKeyboardProc(int nCode, WPARAM wParam, LPARAM lParam) 1163 { 1164 if (nCode == HC_ACTION && m_spKeyboardHandler && m_spKeyboardHandler->winLowKeyboardEvent(wParam, *(KBDLLHOOKSTRUCT*)lParam)) 1165 return 1; 1166 1167 return CallNextHookEx(NULL, nCode, wParam, lParam); 1168 } 1169 1170 bool UIKeyboardHandler::winLowKeyboardEvent(UINT msg, const KBDLLHOOKSTRUCT &event) 1171 { 1172 /* Check what related machine-view was NOT unregistered yet: */ 1173 if (!m_views.contains(m_iKeyboardHookViewIndex)) 1174 return false; 1175 1176 /* It's possible that a key has been pressed while the keyboard was not 1177 * captured, but is being released under the capture. Detect this situation 1178 * and do not pass on the key press to the virtual machine. */ 1179 uint8_t what_pressed = (event.flags & 0x01) 1180 && (event.vkCode != VK_RSHIFT) 1181 ? IsExtKeyPressed : IsKeyPressed; 1182 if ( (event.flags & 0x80) /* released */ 1183 && ( ( UIHostCombo::toKeyCodeList(m_globalSettings.hostCombo()).contains(event.vkCode) 1184 && !m_bIsHostkeyInCapture) 1185 || ( m_pressedKeys[event.scanCode & 0x7F] 1186 & (IsKbdCaptured | what_pressed)) 1187 == what_pressed)) 1188 return false; 1189 1190 if (!m_fIsKeyboardCaptured) 1191 return false; 1192 1193 /* For normal user applications, Windows defines AltGr to be the same as 1194 * LControl + RAlt. Without a low-level hook it is hard to recognise the 1195 * additional LControl event inserted, but in a hook we recognise it by 1196 * its special 0x21D scan code. */ 1197 if ( m_views[m_iKeyboardHookViewIndex]->hasFocus() 1198 && ((event.scanCode & ~0x80) == 0x21D)) 1199 return true; 1200 1201 MSG message; 1202 message.hwnd = (HWND)m_views[m_iKeyboardHookViewIndex]->winId(); 1203 message.message = msg; 1204 message.wParam = event.vkCode; 1205 message.lParam = 1 | (event.scanCode & 0xFF) << 16 | (event.flags & 0xFF) << 24; 1206 1207 /* Windows sets here the extended bit when the Right Shift key is pressed, 1208 * which is totally wrong. Undo it. */ 1209 if (event.vkCode == VK_RSHIFT) 1210 message.lParam &= ~0x1000000; 1211 1212 /* We suppose here that this hook is always called on the main GUI thread */ 1213 long dummyResult; 1214 return m_views[m_iKeyboardHookViewIndex]->winEvent(&message, &dummyResult); 1215 } 1216 1217 #elif defined(Q_WS_MAC) 1163 #if defined(Q_WS_MAC) 1218 1164 1219 1165 void UIKeyboardHandler::darwinGrabKeyboardEvents(bool fGrab) … … 1363 1309 } 1364 1310 1365 #endif 1311 #elif defined(Q_WS_WIN) 1312 1313 LRESULT CALLBACK UIKeyboardHandler::lowLevelKeyboardProc(int nCode, WPARAM wParam, LPARAM lParam) 1314 { 1315 if (nCode == HC_ACTION && m_spKeyboardHandler && m_spKeyboardHandler->winLowKeyboardEvent(wParam, *(KBDLLHOOKSTRUCT*)lParam)) 1316 return 1; 1317 1318 return CallNextHookEx(NULL, nCode, wParam, lParam); 1319 } 1320 1321 bool UIKeyboardHandler::winLowKeyboardEvent(UINT msg, const KBDLLHOOKSTRUCT &event) 1322 { 1323 /* Check what related machine-view was NOT unregistered yet: */ 1324 if (!m_views.contains(m_iKeyboardHookViewIndex)) 1325 return false; 1326 1327 /* It's possible that a key has been pressed while the keyboard was not 1328 * captured, but is being released under the capture. Detect this situation 1329 * and do not pass on the key press to the virtual machine. */ 1330 uint8_t what_pressed = (event.flags & 0x01) 1331 && (event.vkCode != VK_RSHIFT) 1332 ? IsExtKeyPressed : IsKeyPressed; 1333 if ( (event.flags & 0x80) /* released */ 1334 && ( ( UIHostCombo::toKeyCodeList(m_globalSettings.hostCombo()).contains(event.vkCode) 1335 && !m_bIsHostkeyInCapture) 1336 || ( m_pressedKeys[event.scanCode & 0x7F] 1337 & (IsKbdCaptured | what_pressed)) 1338 == what_pressed)) 1339 return false; 1340 1341 if (!m_fIsKeyboardCaptured) 1342 return false; 1343 1344 /* For normal user applications, Windows defines AltGr to be the same as 1345 * LControl + RAlt. Without a low-level hook it is hard to recognise the 1346 * additional LControl event inserted, but in a hook we recognise it by 1347 * its special 0x21D scan code. */ 1348 if ( m_views[m_iKeyboardHookViewIndex]->hasFocus() 1349 && ((event.scanCode & ~0x80) == 0x21D)) 1350 return true; 1351 1352 MSG message; 1353 message.hwnd = (HWND)m_views[m_iKeyboardHookViewIndex]->winId(); 1354 message.message = msg; 1355 message.wParam = event.vkCode; 1356 message.lParam = 1 | (event.scanCode & 0xFF) << 16 | (event.flags & 0xFF) << 24; 1357 1358 /* Windows sets here the extended bit when the Right Shift key is pressed, 1359 * which is totally wrong. Undo it. */ 1360 if (event.vkCode == VK_RSHIFT) 1361 message.lParam &= ~0x1000000; 1362 1363 /* We suppose here that this hook is always called on the main GUI thread */ 1364 long dummyResult; 1365 return m_views[m_iKeyboardHookViewIndex]->winEvent(&message, &dummyResult); 1366 } 1367 1368 #endif /* Q_WS_WIN */ 1366 1369 1367 1370 /** -
trunk/src/VBox/Frontends/VirtualBox/src/runtime/UIKeyboardHandler.h
r58943 r59345 44 44 class UIMachineView; 45 45 class CKeyboard; 46 #if defined(Q_WS_WIN)46 #ifdef Q_WS_WIN 47 47 class WinAltGrMonitor; 48 #elif defined(Q_WS_X11) 48 #endif /* Q_WS_WIN */ 49 #ifdef Q_WS_X11 49 50 # if QT_VERSION < 0x050000 50 51 typedef union _XEvent XEvent; … … 98 99 #endif 99 100 100 /* External event-filters: */ 101 #if defined(Q_WS_WIN) 101 #ifdef Q_WS_WIN 102 void winSkipKeyboardEvents(bool fSkip); 103 #endif /* Q_WS_WIN */ 104 105 #if QT_VERSION < 0x050000 106 # if defined(Q_WS_WIN) 102 107 bool winEventFilter(MSG *pMsg, ulong uScreenId); 103 void winSkipKeyboardEvents(bool fSkip); 104 /** Holds the object monitoring key event stream for problematic AltGr events. */ 105 WinAltGrMonitor *m_pAltGrMonitor; 106 #elif defined(Q_WS_X11) 107 # if QT_VERSION >= 0x050000 108 # elif defined(Q_WS_X11) 109 bool x11EventFilter(XEvent *pEvent, ulong uScreenId); 110 # endif /* Q_WS_X11 */ 111 #else /* QT_VERSION >= 0x050000 */ 108 112 bool nativeEventFilter(void *pMessage, ulong uScreenId); 109 # else /* QT_VERSION < 0x050000 */ 110 bool x11EventFilter(XEvent *pEvent, ulong uScreenId); 111 # endif /* QT_VERSION < 0x050000 */ 112 #endif /* Q_WS_X11 */ 113 #endif /* QT_VERSION >= 0x050000 */ 113 114 114 115 protected slots: … … 141 142 /* Event handler for registered machine-view(s): */ 142 143 bool eventFilter(QObject *pWatchedObject, QEvent *pEvent); 143 #if defined(Q_WS_WIN) 144 145 #if defined(Q_WS_MAC) 146 void darwinGrabKeyboardEvents(bool fGrab); 147 static bool darwinEventHandlerProc(const void *pvCocoaEvent, const void *pvCarbonEvent, void *pvUser); 148 bool darwinKeyboardEvent(const void *pvCocoaEvent, EventRef inEvent); 149 #elif defined(Q_WS_WIN) 144 150 static LRESULT CALLBACK lowLevelKeyboardProc(int nCode, WPARAM wParam, LPARAM lParam); 145 151 bool winLowKeyboardEvent(UINT msg, const KBDLLHOOKSTRUCT &event); 146 #elif defined(Q_WS_MAC) 147 void darwinGrabKeyboardEvents(bool fGrab); 148 bool darwinKeyboardEvent(const void *pvCocoaEvent, EventRef inEvent); 149 static bool darwinEventHandlerProc(const void *pvCocoaEvent, const void *pvCarbonEvent, void *pvUser); 150 #endif 152 #endif /* Q_WS_WIN */ 151 153 152 154 bool keyEventCADHandled(uint8_t uScan); … … 198 200 bool m_fDebuggerActive : 1; 199 201 200 #if defined(Q_WS_WIN) 202 #if defined(Q_WS_MAC) 203 /* The current modifier key mask. Used to figure out which modifier 204 * key was pressed when we get a kEventRawKeyModifiersChanged event. */ 205 UInt32 m_darwinKeyModifiers; 206 bool m_fKeyboardGrabbed; 207 int m_iKeyboardGrabViewIndex; 208 #elif defined(Q_WS_WIN) 201 209 /* Currently this is used in winLowKeyboardEvent() only: */ 202 210 bool m_bIsHostkeyInCapture; … … 207 215 /* A flag that used to tell kbd event filter to ignore keyboard events */ 208 216 bool m_fSkipKeyboardEvents; 209 #elif defined(Q_WS_MAC) 210 /* The current modifier key mask. Used to figure out which modifier 211 * key was pressed when we get a kEventRawKeyModifiersChanged event. */ 212 UInt32 m_darwinKeyModifiers; 213 bool m_fKeyboardGrabbed; 214 int m_iKeyboardGrabViewIndex; 215 #endif /* Q_WS_MAC */ 217 /** Holds the object monitoring key event stream for problematic AltGr events. */ 218 WinAltGrMonitor *m_pAltGrMonitor; 219 #endif /* Q_WS_WIN */ 216 220 217 221 ULONG m_cMonitors;
Note:
See TracChangeset
for help on using the changeset viewer.