VirtualBox

Changeset 51439 in vbox for trunk/src/VBox


Ignore:
Timestamp:
May 28, 2014 9:27:03 AM (11 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
93994
Message:

FE/Qt: move Windows AltGr handling out of the keyboard hook and into the normal keyboard handling.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Frontends/VirtualBox/src/runtime/UIKeyboardHandler.cpp

    r50693 r51439  
    363363}
    364364
     365/**
     366 * @brief isSyntheticLCtrl
     367 * @param   pMsg  Windows WM_[SYS]KEY* event message structure
     368 * @return  true if this is a synthetic LCtrl event, false otherwise
     369 * This function is a heuristic to tell whether a key event is the first in
     370 * a synthetic LCtrl+RAlt sequence which Windows uses to signal AltGr.  Our
     371 * heuristic is in two parts.  First of all, we check whether there is a pending
     372 * RAlt key event matching this LCtrl event (i.e. both key up or both key down)
     373 * and if there is, we check whether the current layout has an AltGr key.  We
     374 * check this by looking to see if any of the layout-dependent keys has a symbol
     375 * associated when AltGr is pressed.
     376 */
     377static bool isSyntheticLCtrl(MSG *pMsg)
     378{
     379    MSG peekMsg;
     380    /** Keyboard state array with VK_CONTROL and VK_MENU depressed. */
     381    const BYTE auKeyStates[256] =
     382    { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x80, 0x80 };
     383    WORD ach;
     384    unsigned i;
     385
     386    Assert(   pMsg->message == WM_KEYDOWN || pMsg->message == WM_SYSKEYDOWN
     387           || pMsg->message == WM_KEYUP || pMsg->message == WM_SYSKEYUP);
     388    if (   ((RT_HIWORD(pMsg->lParam) & 0xFF) != 0x1d /* scan code: Control */)
     389        || RT_HIWORD(pMsg->lParam) & KF_EXTENDED)
     390        return false;
     391    if (!PeekMessage(&peekMsg, NULL, WM_KEYFIRST, WM_KEYLAST, PM_NOREMOVE))
     392        return false;
     393    if (   (pMsg->message == WM_KEYDOWN || pMsg->message == WM_SYSKEYDOWN)
     394        && (peekMsg.message != WM_KEYDOWN && peekMsg.message != WM_SYSKEYDOWN))
     395        return false;
     396    if (   (pMsg->message == WM_KEYUP || pMsg->message == WM_SYSKEYUP)
     397        && (peekMsg.message != WM_KEYUP && peekMsg.message != WM_SYSKEYUP))
     398        return false;
     399    if (   ((RT_HIWORD(peekMsg.lParam) & 0xFF) != 0x38 /* scan code: Alt */)
     400        || !(RT_HIWORD(peekMsg.lParam) & KF_EXTENDED))
     401        return false;
     402    /* If we got this far then we have a key event which could potentially
     403     * be a synthetic left control.  Now we check to see whether the current
     404     * keyboard layout actually has an AltGr key by checking whether any of
     405     * the keys which might do produce a symbol when AltGr (Control + Alt) is
     406     * depressed.  Generally this loop will exit pretty early (it exits on the
     407     * first iteration for my German layout).  If there is no AltGr key in the
     408     * layout then it will run right through, but that should not happen very
     409     * often as we should hardly ever reach the loop in that case.
     410     *
     411     * In theory we could do this once and cache the result, but that involves
     412     * tracking layout switches to invalidate the cache, and I don't think
     413     * that the added complexity is worth the price.
     414     */
     415    for (i = '0'; i <= VK_OEM_102; ++i)
     416    {
     417        if (ToAscii(i, 0, auKeyStates, &ach, 0))
     418            break;
     419        /* Skip ranges of virtual keys which are undefined or not relevant. */
     420        if (i == '9')
     421            i = 'A' - 1;
     422        if (i == 'Z')
     423            i = VK_OEM_1 - 1;
     424        if (i == VK_OEM_3)
     425            i = VK_OEM_4 - 1;
     426        if (i == VK_OEM_8)
     427            i = VK_OEM_102 - 1;
     428    }
     429    if (i > VK_OEM_102)
     430        return false;
     431    return true;
     432}
     433
    365434bool UIKeyboardHandler::winEventFilter(MSG *pMsg, ulong uScreenId)
    366435{
     
    386455                pMsg->lParam &= ~(0x1 << 25);
    387456                fResult = false;
     457                break;
     458            }
     459
     460            if (isSyntheticLCtrl(pMsg))
     461            {
     462                fResult = true;
    388463                break;
    389464            }
     
    9771052        return false;
    9781053
    979     /* Sometimes it happens that Win inserts additional events on some key
    980      * press/release. For example, it prepends ALT_GR in German layout with
    981      * the VK_LCONTROL vkey with curious 0x21D scan code (seems to be necessary
    982      * to specially treat ALT_GR to enter additional chars to regular apps).
    983      * These events are definitely unwanted in VM, so filter them out. */
    984     /* Note (michael): it also sometimes sends the VK_CAPITAL vkey with scan
    985      * code 0x23a. If this is not passed through then it is impossible to
    986      * cancel CapsLock on a French keyboard.  I didn't find any other examples
    987      * of these strange events.  Let's hope we are not missing anything else
    988      * of importance! */
    989     if (m_views[m_iKeyboardHookViewIndex]->hasFocus() && (event.scanCode & ~0xFF))
    990     {
    991         if (event.vkCode == VK_CAPITAL)
    992             return false;
    993         else
    994             return true;
    995     }
    996 
    997     /** @todo this needs to be after the preceding check so that
    998      *        we ignore those spurious key events even when the
    999      *        keyboard is not captured.  However, that is probably a
    1000      *        hint that that filtering should be done somewhere else,
    1001      *        and not in the keyboard capture handler. */
    10021054    if (!m_fIsKeyboardCaptured)
    10031055        return false;
Note: See TracChangeset for help on using the changeset viewer.

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