VirtualBox

Ignore:
Timestamp:
Dec 7, 2015 7:08:56 PM (9 years ago)
Author:
vboxsync
Message:

FE/Qt: Qt5 migration (part 34): Windows nativeEvent handler implementation for UIHostComboEditor.

Location:
trunk/src/VBox/Frontends/VirtualBox/src/widgets
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Frontends/VirtualBox/src/widgets/UIHostComboEditor.cpp

    r59042 r59043  
    4242
    4343#endif /* !VBOX_WITH_PRECOMPILED_HEADERS */
     44
     45/* Qt includes: */
     46#ifdef Q_WS_WIN
     47# if QT_VERSION >= 0x050000
     48#  include <QAbstractNativeEventFilter>
     49# endif /* QT_VERSION >= 0x050000 */
     50#endif /* Q_WS_WIN */
    4451
    4552/* GUI includes: */
     
    7582
    7683
     84#ifdef Q_WS_WIN
     85# if QT_VERSION >= 0x050000
     86/** QAbstractNativeEventFilter extension
     87  * allowing to handle native Windows (MSG) events.
     88  * Why do we need it? It's because Qt5 have unhandled
     89  * well .. let's call it 'a bug' about native keyboard events
     90  * which come to top-level widget (window) instead of focused sub-widget
     91  * which actually supposed to get them. The funny thing is that target of
     92  * those events (MSG::hwnd) is indeed top-level widget, not the sub-widget
     93  * we expect, so that's probably the reason Qt devs haven't fixed that bug. */
     94class WinEventFilter : public QAbstractNativeEventFilter
     95{
     96public:
     97
     98    /** Constructor which takes the passed @a pParent to redirect events to. */
     99    WinEventFilter(UIHostComboEditorPrivate *pParent)
     100        : m_pParent(pParent)
     101    {}
     102
     103    /** Handles all native events. */
     104    bool nativeEventFilter(const QByteArray &eventType, void *pMessage, long *pResult)
     105    {
     106        /* Redirect event to parent: */
     107        return m_pParent->nativeEvent(eventType, pMessage, pResult);
     108    }
     109
     110private:
     111
     112    /** Holds the passed parent reference. */
     113    UIHostComboEditorPrivate *m_pParent;
     114};
     115# endif /* QT_VERSION >= 0x050000 */
     116#endif /* Q_WS_WIN */
     117
     118
    77119/*********************************************************************************************************************************
    78120*   Namespace UINativeHotKey implementation.                                                                                     *
     
    428470    , m_fStartNewSequence(true)
    429471#ifdef Q_WS_WIN
     472# if QT_VERSION >= 0x050000
     473    , m_pWinEventFilter(0)
     474# endif /* QT_VERSION >= 0x050000 */
    430475    , m_pAltGrMonitor(0)
    431476#endif /* Q_WS_WIN */
     
    443488
    444489#if defined(Q_WS_MAC)
    445      m_uDarwinKeyModifiers = 0;
    446      UICocoaApplication::instance()->registerForNativeEvents(RT_BIT_32(10) | RT_BIT_32(11) | RT_BIT_32(12) /* NSKeyDown  | NSKeyUp | | NSFlagsChanged */, UIHostComboEditorPrivate::darwinEventHandlerProc, this);
    447      ::DarwinGrabKeyboard(false /* just modifiers */);
     490    m_uDarwinKeyModifiers = 0;
     491    UICocoaApplication::instance()->registerForNativeEvents(RT_BIT_32(10) | RT_BIT_32(11) | RT_BIT_32(12) /* NSKeyDown  | NSKeyUp | | NSFlagsChanged */, UIHostComboEditorPrivate::darwinEventHandlerProc, this);
     492    ::DarwinGrabKeyboard(false /* just modifiers */);
    448493#elif defined(Q_WS_WIN)
     494# if QT_VERSION >= 0x050000
     495    /* Prepare Windows event filter: */
     496    m_pWinEventFilter = new WinEventFilter(this);
     497    qApp->installNativeEventFilter(m_pWinEventFilter);
     498# endif /* QT_VERSION >= 0x050000 */
    449499    /* Prepare AltGR monitor: */
    450500    m_pAltGrMonitor = new WinAltGrMonitor;
    451501#elif defined(Q_WS_X11)
    452      /* Initialize the X keyboard subsystem: */
    453      initMappedX11Keyboard(QX11Info::display(), vboxGlobal().settings().publicProperty("GUI/RemapScancodes"));
     502    /* Initialize the X keyboard subsystem: */
     503    initMappedX11Keyboard(QX11Info::display(), vboxGlobal().settings().publicProperty("GUI/RemapScancodes"));
    454504#endif /* Q_WS_X11 */
    455505}
     
    464514    delete m_pAltGrMonitor;
    465515    m_pAltGrMonitor = 0;
     516# if QT_VERSION >= 0x050000
     517    /* Cleanup Windows event filter: */
     518    qApp->removeNativeEventFilter(m_pWinEventFilter);
     519    delete m_pWinEventFilter;
     520    m_pWinEventFilter = 0;
     521# endif /* QT_VERSION >= 0x050000 */
    466522#endif /* Q_WS_WIN */
    467523}
     
    512568bool UIHostComboEditorPrivate::nativeEvent(const QByteArray &eventType, void *pMessage, long *pResult)
    513569{
    514 # if defined(Q_WS_X11)
    515 #  pragma GCC diagnostic push
    516 #  pragma GCC diagnostic ignored "-Wdeprecated-declarations"
    517 
    518     /* Make sure it's generic XCB event: */
    519     if (eventType != "xcb_generic_event_t")
     570# if defined(Q_WS_WIN)
     571
     572    /* Make sure it's generic MSG event: */
     573    if (eventType != "windows_generic_MSG")
    520574        return QLineEdit::nativeEvent(eventType, pMessage, pResult);
    521     xcb_generic_event_t *pEvent = static_cast<xcb_generic_event_t*>(pMessage);
    522 
    523     /* Check if some XCB event should be filtered out.
     575    MSG *pEvent = static_cast<MSG*>(pMessage);
     576
     577    /* Check if some MSG event should be filtered out.
    524578     * Returning @c true means filtering-out,
    525579     * Returning @c false means passing event to Qt. */
    526     switch (pEvent->response_type & ~0x80)
     580    switch (pEvent->message)
    527581    {
    528582        /* Watch for key-events: */
    529         case XCB_KEY_PRESS:
    530         case XCB_KEY_RELEASE:
    531         {
    532             /* Parse key-event: */
    533             xcb_key_press_event_t *pKeyEvent = static_cast<xcb_key_press_event_t*>(pMessage);
    534             const KeySym ks = ::XKeycodeToKeysym(QX11Info::display(), pKeyEvent->detail, 0);
    535             const int iKeySym = static_cast<const int>(ks);
    536 
    537             /* Handle key-event: */
    538             return processKeyEvent(iKeySym, (pEvent->response_type & ~0x80) == XCB_KEY_PRESS);
    539         }
    540         default:
    541             break;
    542     }
    543 
    544 #  pragma GCC diagnostic pop
    545 # endif /* Q_WS_X11 */
    546 
    547     /* Call to base-class: */
    548     return QLineEdit::nativeEvent(eventType, pMessage, pResult);
    549 }
    550 
    551 #else /* QT_VERSION < 0x050000 */
    552 
    553 # if defined(Q_WS_MAC)
    554 
    555 /* static */
    556 bool UIHostComboEditorPrivate::darwinEventHandlerProc(const void *pvCocoaEvent, const void *pvCarbonEvent, void *pvUser)
    557 {
    558     UIHostComboEditorPrivate *pEditor = static_cast<UIHostComboEditorPrivate*>(pvUser);
    559     EventRef inEvent = (EventRef)pvCarbonEvent;
    560     UInt32 EventClass = ::GetEventClass(inEvent);
    561     if (EventClass == kEventClassKeyboard)
    562         return pEditor->darwinKeyboardEvent(pvCocoaEvent, inEvent);
    563     return false;
    564 }
    565 
    566 bool UIHostComboEditorPrivate::darwinKeyboardEvent(const void *pvCocoaEvent, EventRef inEvent)
    567 {
    568     /* Ignore key changes unless we're the focus widget: */
    569     if (!hasFocus())
    570         return false;
    571 
    572     UInt32 eventKind = ::GetEventKind(inEvent);
    573     switch (eventKind)
    574     {
    575         //case kEventRawKeyDown:
    576         //case kEventRawKeyUp:
    577         //case kEventRawKeyRepeat:
    578         case kEventRawKeyModifiersChanged:
    579         {
    580             /* Get modifier mask: */
    581             UInt32 modifierMask = 0;
    582             ::GetEventParameter(inEvent, kEventParamKeyModifiers, typeUInt32, NULL,
    583                                 sizeof(modifierMask), NULL, &modifierMask);
    584             modifierMask = ::DarwinAdjustModifierMask(modifierMask, pvCocoaEvent);
    585             UInt32 changed = m_uDarwinKeyModifiers ^ modifierMask;
    586 
    587             if (!changed)
    588                 break;
    589 
    590             /* Convert to keycode: */
    591             unsigned uKeyCode = ::DarwinModifierMaskToDarwinKeycode(changed);
    592 
    593             if (!uKeyCode || uKeyCode == ~0U)
    594                 return false;
    595 
    596             /* Process the key event: */
    597             if (processKeyEvent(uKeyCode, changed & modifierMask))
    598             {
    599                 /* Save the new modifier mask state. */
    600                 m_uDarwinKeyModifiers = modifierMask;
    601                 return true;
    602             }
    603             break;
    604         }
    605         default:
    606             break;
    607     }
    608     return false;
    609 }
    610 
    611 # elif defined(Q_WS_WIN)
    612 
    613 bool UIHostComboEditorPrivate::winEvent(MSG *pMsg, long* /* pResult */)
    614 {
    615     switch (pMsg->message)
    616     {
    617583        case WM_KEYDOWN:
    618584        case WM_SYSKEYDOWN:
     
    620586        case WM_SYSKEYUP:
    621587        {
    622             /* Get key-code: */
    623             int iKeyCode = UINativeHotKey::distinguishModifierVKey((int)pMsg->wParam, (int)pMsg->lParam);
    624             unsigned iDownScanCode = (pMsg->lParam >> 16) & 0x7F;
    625             bool fPressed = !(pMsg->lParam & 0x80000000);
    626             bool fExtended = pMsg->lParam & 0x1000000;
     588            /* Parse key-event: */
     589            int iKeyCode = UINativeHotKey::distinguishModifierVKey((int)pEvent->wParam, (int)pEvent->lParam);
     590            unsigned iDownScanCode = (pEvent->lParam >> 16) & 0x7F;
     591            const bool fPressed = !(pEvent->lParam & 0x80000000);
     592            const bool fExtended = pEvent->lParam & 0x1000000;
    627593
    628594            /* If present - why not just assert this? */
     
    643609            }
    644610
     611            /* Handle key-event: */
     612            return processKeyEvent(iKeyCode, (pEvent->message == WM_KEYDOWN || pEvent->message == WM_SYSKEYDOWN));
     613        }
     614        default:
     615            break;
     616    }
     617
     618# elif defined(Q_WS_X11)
     619#  pragma GCC diagnostic push
     620#  pragma GCC diagnostic ignored "-Wdeprecated-declarations"
     621
     622    /* Make sure it's generic XCB event: */
     623    if (eventType != "xcb_generic_event_t")
     624        return QLineEdit::nativeEvent(eventType, pMessage, pResult);
     625    xcb_generic_event_t *pEvent = static_cast<xcb_generic_event_t*>(pMessage);
     626
     627    /* Check if some XCB event should be filtered out.
     628     * Returning @c true means filtering-out,
     629     * Returning @c false means passing event to Qt. */
     630    switch (pEvent->response_type & ~0x80)
     631    {
     632        /* Watch for key-events: */
     633        case XCB_KEY_PRESS:
     634        case XCB_KEY_RELEASE:
     635        {
     636            /* Parse key-event: */
     637            xcb_key_press_event_t *pKeyEvent = static_cast<xcb_key_press_event_t*>(pMessage);
     638            const KeySym ks = ::XKeycodeToKeysym(QX11Info::display(), pKeyEvent->detail, 0);
     639            const int iKeySym = static_cast<const int>(ks);
     640
     641            /* Handle key-event: */
     642            return processKeyEvent(iKeySym, (pEvent->response_type & ~0x80) == XCB_KEY_PRESS);
     643        }
     644        default:
     645            break;
     646    }
     647
     648#  pragma GCC diagnostic pop
     649# else
     650
     651#  warning "port me!"
     652
     653# endif
     654
     655    /* Call to base-class: */
     656    return QLineEdit::nativeEvent(eventType, pMessage, pResult);
     657}
     658
     659#else /* QT_VERSION < 0x050000 */
     660
     661# if defined(Q_WS_MAC)
     662
     663/* static */
     664bool UIHostComboEditorPrivate::darwinEventHandlerProc(const void *pvCocoaEvent, const void *pvCarbonEvent, void *pvUser)
     665{
     666    UIHostComboEditorPrivate *pEditor = static_cast<UIHostComboEditorPrivate*>(pvUser);
     667    EventRef inEvent = (EventRef)pvCarbonEvent;
     668    UInt32 EventClass = ::GetEventClass(inEvent);
     669    if (EventClass == kEventClassKeyboard)
     670        return pEditor->darwinKeyboardEvent(pvCocoaEvent, inEvent);
     671    return false;
     672}
     673
     674bool UIHostComboEditorPrivate::darwinKeyboardEvent(const void *pvCocoaEvent, EventRef inEvent)
     675{
     676    /* Ignore key changes unless we're the focus widget: */
     677    if (!hasFocus())
     678        return false;
     679
     680    UInt32 eventKind = ::GetEventKind(inEvent);
     681    switch (eventKind)
     682    {
     683        //case kEventRawKeyDown:
     684        //case kEventRawKeyUp:
     685        //case kEventRawKeyRepeat:
     686        case kEventRawKeyModifiersChanged:
     687        {
     688            /* Get modifier mask: */
     689            UInt32 modifierMask = 0;
     690            ::GetEventParameter(inEvent, kEventParamKeyModifiers, typeUInt32, NULL,
     691                                sizeof(modifierMask), NULL, &modifierMask);
     692            modifierMask = ::DarwinAdjustModifierMask(modifierMask, pvCocoaEvent);
     693            UInt32 changed = m_uDarwinKeyModifiers ^ modifierMask;
     694
     695            if (!changed)
     696                break;
     697
     698            /* Convert to keycode: */
     699            unsigned uKeyCode = ::DarwinModifierMaskToDarwinKeycode(changed);
     700
     701            if (!uKeyCode || uKeyCode == ~0U)
     702                return false;
     703
     704            /* Process the key event: */
     705            if (processKeyEvent(uKeyCode, changed & modifierMask))
     706            {
     707                /* Save the new modifier mask state. */
     708                m_uDarwinKeyModifiers = modifierMask;
     709                return true;
     710            }
     711            break;
     712        }
     713        default:
     714            break;
     715    }
     716    return false;
     717}
     718
     719# elif defined(Q_WS_WIN)
     720
     721bool UIHostComboEditorPrivate::winEvent(MSG *pMsg, long* /* pResult */)
     722{
     723    switch (pMsg->message)
     724    {
     725        case WM_KEYDOWN:
     726        case WM_SYSKEYDOWN:
     727        case WM_KEYUP:
     728        case WM_SYSKEYUP:
     729        {
     730            /* Get key-code: */
     731            int iKeyCode = UINativeHotKey::distinguishModifierVKey((int)pMsg->wParam, (int)pMsg->lParam);
     732            unsigned iDownScanCode = (pMsg->lParam >> 16) & 0x7F;
     733            bool fPressed = !(pMsg->lParam & 0x80000000);
     734            bool fExtended = pMsg->lParam & 0x1000000;
     735
     736            /* If present - why not just assert this? */
     737            if (m_pAltGrMonitor)
     738            {
     739                /* Update AltGR monitor state from key-event: */
     740                m_pAltGrMonitor->updateStateFromKeyEvent(iDownScanCode, fPressed, fExtended);
     741                /* And release left Ctrl key early (if required): */
     742                if (m_pAltGrMonitor->isLeftControlReleaseNeeded())
     743                {
     744                    m_pressedKeys.remove(VK_LCONTROL);
     745                    m_shownKeys.remove(VK_LCONTROL);
     746                }
     747                /* Fake LCtrl release events can also end up in the released
     748                 * key set.  Detect them on the immediately following RAlt up. */
     749                if (!m_pressedKeys.contains(VK_LCONTROL))
     750                    m_releasedKeys.remove(VK_LCONTROL);
     751            }
     752
    645753            /* Process the key event: */
    646754            return processKeyEvent(iKeyCode, pMsg->message == WM_KEYDOWN || pMsg->message == WM_SYSKEYDOWN);
  • trunk/src/VBox/Frontends/VirtualBox/src/widgets/UIHostComboEditor.h

    r59042 r59043  
    3232class UIHostComboEditorPrivate;
    3333#ifdef Q_WS_WIN
     34# if QT_VERSION >= 0x050000
     35class WinEventFilter;
     36# endif /* QT_VERSION >= 0x050000 */
    3437class WinAltGrMonitor;
    3538#endif /* Q_WS_WIN */
     
    187190     uint32_t m_uDarwinKeyModifiers;
    188191#elif defined(Q_WS_WIN)
     192# if QT_VERSION >= 0x050000
     193    /** Win: Holds the native event filter instance. */
     194    WinEventFilter *m_pWinEventFilter;
     195    /** Win: Allows the native event filter to
     196      * redirect events directly to nativeEvent handler. */
     197    friend class WinEventFilter;
     198# endif /* QT_VERSION >= 0x050000 */
    189199    /** Win: Holds the object monitoring key event
    190200      * stream for problematic AltGr events. */
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