VirtualBox

Changeset 59345 in vbox


Ignore:
Timestamp:
Jan 14, 2016 1:01:39 PM (9 years ago)
Author:
vboxsync
Message:

FE/Qt: Qt5 migration (part 52): Reworking keyboard-handler: Proper order first of all.

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  
    436436#endif /* VBOX_WITH_DEBUGGER_GUI */
    437437
    438 #if defined(Q_WS_WIN)
     438#ifdef Q_WS_WIN
    439439/** Tell keyboard event handler to skip host keyboard events. Used for HID LEDs sync
    440440 * when on Windows host a keyboard event is generated in order to change corresponding LED. */
     
    443443    m_fSkipKeyboardEvents = fSkip;
    444444}
     445#endif /* Q_WS_WIN */
     446
     447#if QT_VERSION < 0x050000
     448# if defined(Q_WS_WIN)
    445449
    446450bool UIKeyboardHandler::winEventFilter(MSG *pMsg, ulong uScreenId)
     
    595599}
    596600
    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)
    695602
    696603static Bool UIKeyboardHandlerCompEvent(Display*, XEvent *pEvent, XPointer pvArg)
     
    816723}
    817724
    818 # endif /* QT_VERSION < 0x050000 */
    819 #endif /* Q_WS_X11 */
     725# endif /* Q_WS_X11 */
     726#else /* QT_VERSION >= 0x050000 */
     727
     728bool 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 */
    820823
    821824/* Machine state-change handler: */
     
    885888    , m_fPassCADtoGuest(false)
    886889    , 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)
    888895    , m_bIsHostkeyInCapture(false)
    889896    , m_iKeyboardHookViewIndex(-1)
    890897    , m_fSkipKeyboardEvents(false)
    891898    , 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 */
    897900    , m_cMonitors(1)
    898901{
     
    11581161}
    11591162
    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)
    12181164
    12191165void UIKeyboardHandler::darwinGrabKeyboardEvents(bool fGrab)
     
    13631309}
    13641310
    1365 #endif
     1311#elif defined(Q_WS_WIN)
     1312
     1313LRESULT 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
     1321bool 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 */
    13661369
    13671370/**
  • trunk/src/VBox/Frontends/VirtualBox/src/runtime/UIKeyboardHandler.h

    r58943 r59345  
    4444class UIMachineView;
    4545class CKeyboard;
    46 #if defined(Q_WS_WIN)
     46#ifdef Q_WS_WIN
    4747class WinAltGrMonitor;
    48 #elif defined(Q_WS_X11)
     48#endif /* Q_WS_WIN */
     49#ifdef Q_WS_X11
    4950# if QT_VERSION < 0x050000
    5051typedef union _XEvent XEvent;
     
    9899#endif
    99100
    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)
    102107    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 */
    108112    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 */
    113114
    114115protected slots:
     
    141142    /* Event handler for registered machine-view(s): */
    142143    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)
    144150    static LRESULT CALLBACK lowLevelKeyboardProc(int nCode, WPARAM wParam, LPARAM lParam);
    145151    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 */
    151153
    152154    bool keyEventCADHandled(uint8_t uScan);
     
    198200    bool m_fDebuggerActive : 1;
    199201
    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)
    201209    /* Currently this is used in winLowKeyboardEvent() only: */
    202210    bool m_bIsHostkeyInCapture;
     
    207215    /* A flag that used to tell kbd event filter to ignore keyboard events */
    208216    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 */
    216220
    217221    ULONG m_cMonitors;
Note: See TracChangeset for help on using the changeset viewer.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette