VirtualBox

Changeset 53221 in vbox for trunk/src/VBox/Frontends


Ignore:
Timestamp:
Nov 5, 2014 9:09:40 AM (10 years ago)
Author:
vboxsync
Message:

FE/Qt: win: improved AltGr handling.

Location:
trunk/src/VBox/Frontends/VirtualBox/src
Files:
6 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Frontends/VirtualBox/src/platform/win/WinKeyboard.cpp

    r52730 r53221  
    171171        LogRel2(("HID LEDs sync: broadcast failed\n"));
    172172}
     173
     174/** @brief doesCurrentLayoutHaveAltGr
     175  *
     176  * @return true if this keyboard layout has an AltGr key, false otherwise
     177  * Check to see whether the current keyboard layout actually has an AltGr key
     178  * by checking whether any of the keys which might do produce a symbol when
     179  * AltGr (Control + Alt) is depressed. Generally this loop will exit pretty
     180  * early (it exits on the first iteration for my German layout). If there is
     181  * no AltGr key in the layout then it will run right through, but that should
     182  * hopefully not happen very often.
     183  *
     184  * In theory we could do this once and cache the result, but that involves
     185  * tracking layout switches to invalidate the cache, and I don't think that the
     186  * added complexity is worth the price. */
     187static bool doesCurrentLayoutHaveAltGr()
     188{
     189    /** Keyboard state array with VK_CONTROL and VK_MENU depressed. */
     190    const BYTE auKeyStates[256] =
     191        { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x80, 0x80 };
     192    WORD ach;
     193    unsigned i;
     194
     195    for (i = '0'; i <= VK_OEM_102; ++i)
     196    {
     197        if (ToAscii(i, 0, auKeyStates, &ach, 0))
     198            break;
     199        /* Skip ranges of virtual keys which are undefined or not relevant. */
     200        if (i == '9')
     201            i = 'A' - 1;
     202        if (i == 'Z')
     203            i = VK_OEM_1 - 1;
     204        if (i == VK_OEM_3)
     205            i = VK_OEM_4 - 1;
     206        if (i == VK_OEM_8)
     207            i = VK_OEM_102 - 1;
     208    }
     209    if (i > VK_OEM_102)
     210        return false;
     211    return true;
     212}
     213
     214void WinAltGrMonitor::updateStateFromKeyEvent(unsigned iDownScanCode,
     215                                              bool fKeyDown, bool fExtendedKey)
     216{
     217    LONG messageTime = GetMessageTime();
     218    /* We do not want the make/break: */
     219    AssertRelease(~iDownScanCode & 0x80);
     220    /* Depending on m_enmFakeControlDetectionState: */
     221    switch (m_enmFakeControlDetectionState)
     222    {
     223        case NONE:
     224        case FAKE_CONTROL_DOWN:
     225            if (   iDownScanCode == 0x1D /* left control */
     226                && fKeyDown
     227                && !fExtendedKey)
     228                m_enmFakeControlDetectionState = LAST_EVENT_WAS_LEFT_CONTROL_DOWN;
     229            else
     230                m_enmFakeControlDetectionState = NONE;
     231            break;
     232        case LAST_EVENT_WAS_LEFT_CONTROL_DOWN:
     233            if (   iDownScanCode == 0x38 /* Alt */
     234                && fKeyDown
     235                && fExtendedKey
     236                && m_timeOfLastKeyEvent == messageTime
     237                && doesCurrentLayoutHaveAltGr())
     238            {
     239                m_enmFakeControlDetectionState = FAKE_CONTROL_DOWN;
     240                break;
     241            }
     242            else
     243                m_enmFakeControlDetectionState = LEFT_CONTROL_DOWN;
     244            /* Fall through. */
     245        case LEFT_CONTROL_DOWN:
     246            if (   iDownScanCode == 0x1D /* left control */
     247                && !fKeyDown
     248                && !fExtendedKey)
     249                m_enmFakeControlDetectionState = NONE;
     250            break;
     251        default:
     252            AssertReleaseMsgFailed(("Unknown AltGr detection state.\n"));
     253    }
     254    m_timeOfLastKeyEvent = messageTime;
     255}
     256
     257bool WinAltGrMonitor::isLeftControlReleaseNeeded() const
     258{
     259    return m_enmFakeControlDetectionState == FAKE_CONTROL_DOWN;
     260}
     261
     262bool WinAltGrMonitor::isCurrentEventDefinitelyFake(unsigned iDownScanCode,
     263                                                   bool fKeyDown,
     264                                                   bool fExtendedKey) const
     265{
     266    MSG peekMsg;
     267    LONG messageTime = GetMessageTime();
     268
     269    if (   iDownScanCode != 0x1d /* scan code: Control */ || fExtendedKey)
     270        return false;
     271    if (!PeekMessage(&peekMsg, NULL, WM_KEYFIRST, WM_KEYLAST, PM_NOREMOVE))
     272        return false;
     273
     274                if (   fKeyDown
     275        && (peekMsg.message != WM_KEYDOWN && peekMsg.message != WM_SYSKEYDOWN))
     276        return false;
     277    if (   !fKeyDown
     278        && (peekMsg.message != WM_KEYUP && peekMsg.message != WM_SYSKEYUP))
     279        return false;
     280    if (   ((RT_HIWORD(peekMsg.lParam) & 0xFF) != 0x38 /* scan code: Alt */)
     281        || !(RT_HIWORD(peekMsg.lParam) & KF_EXTENDED))
     282        return false;
     283    if (!doesCurrentLayoutHaveAltGr())
     284        return false;
     285    return true;
     286}
  • trunk/src/VBox/Frontends/VirtualBox/src/platform/win/WinKeyboard.h

    r52727 r53221  
    2828bool winHidLedsInSync(bool fNumLockOn, bool fCapsLockOn, bool fScrollLockOn);
    2929
     30/** Helper class to deal with Windows AltGr handling.
     31  *
     32  * Background: Windows sends AltGr key down and up events as two events: a
     33  * left control event and a right alt one.  Since the left control event does
     34  * not correspond to actually pressing or releasing the left control key we
     35  * would like to detect it and handle it.  This class monitors all key down and
     36  * up events and if it detects that a left control down event has been sendt
     37  * although left control should be up it tells us to insert a left control up
     38  * event into the event stream.  While this does not let us filter out the
     39  * unwanted event at source, it should still make guest system keyboard handling
     40  * work correctly. */
     41class WinAltGrMonitor
     42{
     43public:
     44
     45    /** Constructor. */
     46    WinAltGrMonitor() : m_enmFakeControlDetectionState(NONE), m_timeOfLastKeyEvent(0) {}
     47
     48    /** All key events should be fed to this method.
     49      * @param iDownScanCode the scan code stripped of the make/break bit
     50      * @param fKeyDown      is this a key down event?
     51      * @param fExtended     is this an extended scan code? */
     52    void updateStateFromKeyEvent(unsigned iDownScanCode, bool fKeyDown, bool fExtended);
     53
     54    /** Do we need to insert a left control up into the stream? */
     55    bool isLeftControlReleaseNeeded() const;
     56
     57    /** Can we tell for sure at this point that the current message is a fake
     58     * control event?  This method might fail to recognise a fake event, but
     59     * should never incorrectly flag a non-fake one.
     60     * @note We deliberately do not call this from the host combination editor
     61     *       in an attempt to ensure that the other code path also gets enough
     62     *       test coverage.
     63     */
     64    bool isCurrentEventDefinitelyFake(unsigned iDownScanCode,
     65                                      bool fKeyDown,
     66                                      bool fExtendedKey) const;
     67
     68private:
     69
     70    /** State detection for fake control events which we may have missed. */
     71    enum
     72    {
     73        /** No interesting state. */
     74        NONE,
     75        /** The last keypress might be a fake control. */
     76        LAST_EVENT_WAS_LEFT_CONTROL_DOWN,
     77        /** Left control is down, so we ignore fake control events. */
     78        LEFT_CONTROL_DOWN,
     79        /** A fake control down event and no up was passed to the guest. */
     80        FAKE_CONTROL_DOWN
     81    } m_enmFakeControlDetectionState;
     82    DWORD m_timeOfLastKeyEvent;
     83};
    3084#endif /* __WinKeyboard_h__ */
    3185
  • trunk/src/VBox/Frontends/VirtualBox/src/runtime/UIKeyboardHandler.cpp

    r53138 r53221  
    7272#endif /* Q_WS_MAC */
    7373
    74 
     74#ifdef Q_WS_WIN
     75# include "WinKeyboard.h"
     76#endif /* Q_WS_WIN */
     77 
    7578/* Enums representing different keyboard-states: */
    7679enum { KeyExtended = 0x01, KeyPressed = 0x02, KeyPause = 0x04, KeyPrint = 0x08 };
     
    413416}
    414417
    415 /**
    416  * @brief isSyntheticLCtrl
    417  * @param   pMsg  Windows WM_[SYS]KEY* event message structure
    418  * @return  true if this is a synthetic LCtrl event, false otherwise
    419  * This function is a heuristic to tell whether a key event is the first in
    420  * a synthetic LCtrl+RAlt sequence which Windows uses to signal AltGr.  Our
    421  * heuristic is in two parts.  First of all, we check whether there is a pending
    422  * RAlt key event matching this LCtrl event (i.e. both key up or both key down)
    423  * and if there is, we check whether the current layout has an AltGr key.  We
    424  * check this by looking to see if any of the layout-dependent keys has a symbol
    425  * associated when AltGr is pressed.
    426  */
    427 static bool isSyntheticLCtrl(MSG *pMsg)
    428 {
    429     MSG peekMsg;
    430     /** Keyboard state array with VK_CONTROL and VK_MENU depressed. */
    431     const BYTE auKeyStates[256] =
    432     { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x80, 0x80 };
    433     WORD ach;
    434     unsigned i;
    435 
    436     Assert(   pMsg->message == WM_KEYDOWN || pMsg->message == WM_SYSKEYDOWN
    437            || pMsg->message == WM_KEYUP || pMsg->message == WM_SYSKEYUP);
    438     if (   ((RT_HIWORD(pMsg->lParam) & 0xFF) != 0x1d /* scan code: Control */)
    439         || RT_HIWORD(pMsg->lParam) & KF_EXTENDED)
    440         return false;
    441     if (!PeekMessage(&peekMsg, NULL, WM_KEYFIRST, WM_KEYLAST, PM_NOREMOVE))
    442         return false;
    443     if (   (pMsg->message == WM_KEYDOWN || pMsg->message == WM_SYSKEYDOWN)
    444         && (peekMsg.message != WM_KEYDOWN && peekMsg.message != WM_SYSKEYDOWN))
    445         return false;
    446     if (   (pMsg->message == WM_KEYUP || pMsg->message == WM_SYSKEYUP)
    447         && (peekMsg.message != WM_KEYUP && peekMsg.message != WM_SYSKEYUP))
    448         return false;
    449     if (   ((RT_HIWORD(peekMsg.lParam) & 0xFF) != 0x38 /* scan code: Alt */)
    450         || !(RT_HIWORD(peekMsg.lParam) & KF_EXTENDED))
    451         return false;
    452     /* If we got this far then we have a key event which could potentially
    453      * be a synthetic left control.  Now we check to see whether the current
    454      * keyboard layout actually has an AltGr key by checking whether any of
    455      * the keys which might do produce a symbol when AltGr (Control + Alt) is
    456      * depressed.  Generally this loop will exit pretty early (it exits on the
    457      * first iteration for my German layout).  If there is no AltGr key in the
    458      * layout then it will run right through, but that should not happen very
    459      * often as we should hardly ever reach the loop in that case.
    460      *
    461      * In theory we could do this once and cache the result, but that involves
    462      * tracking layout switches to invalidate the cache, and I don't think
    463      * that the added complexity is worth the price.
    464      */
    465     for (i = '0'; i <= VK_OEM_102; ++i)
    466     {
    467         if (ToAscii(i, 0, auKeyStates, &ach, 0))
    468             break;
    469         /* Skip ranges of virtual keys which are undefined or not relevant. */
    470         if (i == '9')
    471             i = 'A' - 1;
    472         if (i == 'Z')
    473             i = VK_OEM_1 - 1;
    474         if (i == VK_OEM_3)
    475             i = VK_OEM_4 - 1;
    476         if (i == VK_OEM_8)
    477             i = VK_OEM_102 - 1;
    478     }
    479     if (i > VK_OEM_102)
    480         return false;
    481     return true;
    482 }
    483 
    484418bool UIKeyboardHandler::winEventFilter(MSG *pMsg, ulong uScreenId)
    485419{
     
    505439                pMsg->lParam &= ~(0x1 << 25);
    506440                fResult = false;
    507                 break;
    508             }
    509 
    510             if (isSyntheticLCtrl(pMsg))
    511             {
    512                 fResult = true;
    513441                break;
    514442            }
     
    529457            if (!(pMsg->lParam & 0x80000000))
    530458                flags |= KeyPressed;
     459
     460            /* If present - why not just assert this? */
     461            if (m_pAltGrMonitor)
     462            {
     463                /* Bail out if we are sure that this is a fake left control. */
     464                if (m_pAltGrMonitor->isCurrentEventDefinitelyFake(scan, flags & KeyPressed, flags & KeyExtended))
     465                {
     466                    fResult = true;
     467                    break;
     468                }
     469                /* Update AltGR monitor state from key-event: */
     470                m_pAltGrMonitor->updateStateFromKeyEvent(scan, flags & KeyPressed, flags & KeyExtended);
     471                /* And release left Ctrl key early (if required): */
     472                if (m_pAltGrMonitor->isLeftControlReleaseNeeded())
     473                    keyboard().PutScancode(0x1D | 0x80);
     474            }
    531475
    532476            /* Check for special Korean keys. Based on the keyboard layout selected
     
    819763    , m_iKeyboardHookViewIndex(-1)
    820764    , m_fSkipKeyboardEvents(false)
     765    , m_pAltGrMonitor(0)
    821766#elif defined(Q_WS_MAC)
    822767    , m_darwinKeyModifiers(0)
    823768    , m_fKeyboardGrabbed(false)
    824769    , m_iKeyboardGrabViewIndex(-1)
    825 #endif
     770#endif /* Q_WS_MAC */
    826771    , m_cMonitors(1)
    827772{
     
    845790void UIKeyboardHandler::prepareCommon()
    846791{
     792#ifdef Q_WS_WIN
     793    /* Prepare AltGR monitor: */
     794    m_pAltGrMonitor = new WinAltGrMonitor;
     795#endif /* Q_WS_WIN */
     796
    847797    /* Machine state-change updater: */
    848798    connect(uisession(), SIGNAL(sigMachineStateChange()), this, SLOT(sltMachineStateChanged()));
     
    872822{
    873823#if defined(Q_WS_WIN)
     824    /* Cleanup AltGR monitor: */
     825    delete m_pAltGrMonitor;
     826    m_pAltGrMonitor = 0;
     827
    874828    /* Cleaning keyboard-hook: */
    875829    if (m_keyboardHook)
     
    883837    if (m_fKeyboardGrabbed)
    884838        darwinGrabKeyboardEvents(false);
    885 #endif
     839#endif /* Q_WS_MAC */
    886840}
    887841
  • trunk/src/VBox/Frontends/VirtualBox/src/runtime/UIKeyboardHandler.h

    r53138 r53221  
    4141class UIMachineView;
    4242class VBoxGlobalSettings;
    43 #ifdef Q_WS_X11
     43#if defined(Q_WS_WIN)
     44class WinAltGrMonitor;
     45#elif defined(Q_WS_X11)
    4446typedef union  _XEvent XEvent;
    4547#endif /* Q_WS_X11 */
     
    9395    bool winEventFilter(MSG *pMsg, ulong uScreenId);
    9496    void winSkipKeyboardEvents(bool fSkip);
     97    /** Holds the object monitoring key event stream for problematic AltGr events. */
     98    WinAltGrMonitor *m_pAltGrMonitor;
    9599#elif defined(Q_WS_X11)
    96100    bool x11EventFilter(XEvent *pEvent, ulong uScreenId);
     
    198202    bool m_fKeyboardGrabbed;
    199203    int m_iKeyboardGrabViewIndex;
    200 #endif
     204#endif /* Q_WS_MAC */
    201205
    202206    ULONG m_cMonitors;
  • trunk/src/VBox/Frontends/VirtualBox/src/widgets/UIHostComboEditor.cpp

    r52730 r53221  
    4242# undef HIBYTE
    4343# include <windows.h>
     44# include "WinKeyboard.h"
    4445#endif /* Q_WS_WIN */
    4546
     
    391392    : m_pReleaseTimer(0)
    392393    , m_fStartNewSequence(true)
     394#ifdef Q_WS_WIN
     395    , m_pAltGrMonitor(0)
     396#endif /* Q_WS_WIN */
    393397{
    394398    /* Configure widget: */
     
    403407    connect(m_pReleaseTimer, SIGNAL(timeout()), this, SLOT(sltReleasePendingKeys()));
    404408
    405 #ifdef Q_WS_X11
    406     /* Initialize the X keyboard subsystem: */
    407     initMappedX11Keyboard(QX11Info::display(), vboxGlobal().settings().publicProperty("GUI/RemapScancodes"));
    408 #endif /* Q_WS_X11 */
    409 
    410 #ifdef Q_WS_MAC
    411     m_uDarwinKeyModifiers = 0;
    412     UICocoaApplication::instance()->registerForNativeEvents(RT_BIT_32(10) | RT_BIT_32(11) | RT_BIT_32(12) /* NSKeyDown  | NSKeyUp | | NSFlagsChanged */, UIHostComboEditorPrivate::darwinEventHandlerProc, this);
    413     ::DarwinGrabKeyboard(false /* just modifiers */);
    414 #endif /* Q_WS_MAC */
     409#if defined(Q_WS_X11)
     410     /* Initialize the X keyboard subsystem: */
     411     initMappedX11Keyboard(QX11Info::display(), vboxGlobal().settings().publicProperty("GUI/RemapScancodes"));
     412#elif defined(Q_WS_MAC)
     413     m_uDarwinKeyModifiers = 0;
     414     UICocoaApplication::instance()->registerForNativeEvents(RT_BIT_32(10) | RT_BIT_32(11) | RT_BIT_32(12) /* NSKeyDown  | NSKeyUp | | NSFlagsChanged */, UIHostComboEditorPrivate::darwinEventHandlerProc, this);
     415     ::DarwinGrabKeyboard(false /* just modifiers */);
     416#elif defined(Q_WS_WIN)
     417    /* Prepare AltGR monitor: */
     418    m_pAltGrMonitor = new WinAltGrMonitor;
     419#endif /* Q_WS_WIN */
    415420}
    416421
    417422UIHostComboEditorPrivate::~UIHostComboEditorPrivate()
    418423{
    419 #ifdef Q_WS_MAC
     424#if defined(Q_WS_WIN)
     425    /* Cleanup AltGR monitor: */
     426    delete m_pAltGrMonitor;
     427    m_pAltGrMonitor = 0;
     428#elif defined(Q_WS_MAC)
    420429    ::DarwinReleaseKeyboard();
    421430    UICocoaApplication::instance()->unregisterForNativeEvents(RT_BIT_32(10) | RT_BIT_32(11) | RT_BIT_32(12) /* NSKeyDown  | NSKeyUp | | NSFlagsChanged */, UIHostComboEditorPrivate::darwinEventHandlerProc, this);
     
    465474
    466475#ifdef Q_WS_WIN
    467 /**
    468  * @brief isSyntheticLCtrl
    469  * @param   pMsg  Windows WM_[SYS]KEY* event message structure
    470  * @return  true if this is a synthetic LCtrl event, false otherwise
    471  * This function is a heuristic to tell whether a key event is the first in
    472  * a synthetic LCtrl+RAlt sequence which Windows uses to signal AltGr.  Our
    473  * heuristic is in two parts.  First of all, we check whether there is a pending
    474  * RAlt key event matching this LCtrl event (i.e. both key up or both key down)
    475  * and if there is, we check whether the current layout has an AltGr key.  We
    476  * check this by looking to see if any of the layout-dependent keys has a symbol
    477  * associated when AltGr is pressed.
    478  */
    479 static bool isSyntheticLCtrl(MSG *pMsg)
    480 {
    481     MSG peekMsg;
    482     /** Keyboard state array with VK_CONTROL and VK_MENU depressed. */
    483     const BYTE auKeyStates[256] =
    484     { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x80, 0x80 };
    485     WORD ach;
    486     unsigned i;
    487 
    488     Assert(   pMsg->message == WM_KEYDOWN || pMsg->message == WM_SYSKEYDOWN
    489            || pMsg->message == WM_KEYUP || pMsg->message == WM_SYSKEYUP);
    490     if (   ((RT_HIWORD(pMsg->lParam) & 0xFF) != 0x1d /* scan code: Control */)
    491         || RT_HIWORD(pMsg->lParam) & KF_EXTENDED)
    492         return false;
    493     if (!PeekMessage(&peekMsg, NULL, WM_KEYFIRST, WM_KEYLAST, PM_NOREMOVE))
    494         return false;
    495     if (   (pMsg->message == WM_KEYDOWN || pMsg->message == WM_SYSKEYDOWN)
    496         && (peekMsg.message != WM_KEYDOWN && peekMsg.message != WM_SYSKEYDOWN))
    497         return false;
    498     if (   (pMsg->message == WM_KEYUP || pMsg->message == WM_SYSKEYUP)
    499         && (peekMsg.message != WM_KEYUP && peekMsg.message != WM_SYSKEYUP))
    500         return false;
    501     if (   ((RT_HIWORD(peekMsg.lParam) & 0xFF) != 0x38 /* scan code: Alt */)
    502         || !(RT_HIWORD(peekMsg.lParam) & KF_EXTENDED))
    503         return false;
    504     /* If we got this far then we have a key event which could potentially
    505      * be a synthetic left control.  Now we check to see whether the current
    506      * keyboard layout actually has an AltGr key by checking whether any of
    507      * the keys which might do produce a symbol when AltGr (Control + Alt) is
    508      * depressed.  Generally this loop will exit pretty early (it exits on the
    509      * first iteration for my German layout).  If there is no AltGr key in the
    510      * layout then it will run right through, but that should not happen very
    511      * often as we should hardly ever reach the loop in that case.
    512      *
    513      * In theory we could do this once and cache the result, but that involves
    514      * tracking layout switches to invalidate the cache, and I don't think
    515      * that the added complexity is worth the price.
    516      */
    517     for (i = '0'; i <= VK_OEM_102; ++i)
    518     {
    519         if (ToAscii(i, 0, auKeyStates, &ach, 0))
    520             break;
    521         /* Skip ranges of virtual keys which are undefined or not relevant. */
    522         if (i == '9')
    523             i = 'A' - 1;
    524         if (i == 'Z')
    525             i = VK_OEM_1 - 1;
    526         if (i == VK_OEM_3)
    527             i = VK_OEM_4 - 1;
    528         if (i == VK_OEM_8)
    529             i = VK_OEM_102 - 1;
    530     }
    531     if (i > VK_OEM_102)
    532         return false;
    533     return true;
    534 }
    535 
    536476bool UIHostComboEditorPrivate::winEvent(MSG *pMsg, long* /* pResult */)
    537477{
     
    545485            /* Get key-code: */
    546486            int iKeyCode = UINativeHotKey::distinguishModifierVKey((int)pMsg->wParam, (int)pMsg->lParam);
    547 
    548             /* If this is the first event in a synthetic AltGr = LCtrl+RAlt
    549              * sequence then swallow it. */
    550             if (isSyntheticLCtrl(pMsg))
    551                 return true;
     487            unsigned iDownScanCode = (pMsg->lParam >> 16) & 0x7F;
     488            bool fPressed = !(pMsg->lParam & 0x80000000);
     489            bool fExtended = pMsg->lParam & 0x1000000;
     490
     491            /* If present - why not just assert this? */
     492            if (m_pAltGrMonitor)
     493            {
     494                /* Update AltGR monitor state from key-event: */
     495                m_pAltGrMonitor->updateStateFromKeyEvent(iDownScanCode, fPressed, fExtended);
     496                /* And release left Ctrl key early (if required): */
     497                if (m_pAltGrMonitor->isLeftControlReleaseNeeded())
     498                {
     499                    m_pressedKeys.remove(VK_LCONTROL);
     500                    m_shownKeys.remove(VK_LCONTROL);
     501                }
     502                /* Fake LCtrl release events can also end up in the released
     503                 * key set.  Detect them on the immediately following RAlt up. */
     504                if (!m_pressedKeys.contains(VK_LCONTROL))
     505                    m_releasedKeys.remove(VK_LCONTROL);
     506            }
    552507
    553508            /* Process the key event: */
  • trunk/src/VBox/Frontends/VirtualBox/src/widgets/UIHostComboEditor.h

    r52727 r53221  
    3030class UIHostComboEditorPrivate;
    3131class QIToolButton;
     32#ifdef Q_WS_WIN
     33class WinAltGrMonitor;
     34#endif /* Q_WS_WIN */
    3235
    3336/* Native hot-key namespace to unify
     
    171174    bool m_fStartNewSequence;
    172175
    173 #ifdef Q_WS_MAC
    174     /* The current modifier key mask. Used to figure out which modifier
    175      * key was pressed when we get a kEventRawKeyModifiersChanged event. */
    176     uint32_t m_uDarwinKeyModifiers;
    177 #endif /* Q_WS_MAC */
     176#if defined(Q_WS_MAC)
     177     /* The current modifier key mask. Used to figure out which modifier
     178      * key was pressed when we get a kEventRawKeyModifiersChanged event. */
     179     uint32_t m_uDarwinKeyModifiers;
     180#elif defined(Q_WS_WIN)
     181    /** Holds the object monitoring key event stream for problematic AltGr events. */
     182    WinAltGrMonitor *m_pAltGrMonitor;
     183#endif /* Q_WS_WIN */
    178184};
    179185
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