SL-14271 Alt Gr should not trigger menu when inputing characters

master
Andrey Kleshchev 2020-11-13 21:50:26 +02:00
parent 273fbb3238
commit 47434d85b7
1 changed files with 55 additions and 13 deletions

View File

@ -2747,22 +2747,64 @@ BOOL LLViewerWindow::handleKey(KEY key, MASK mask)
}
LLFocusableElement* keyboard_focus = gFocusMgr.getKeyboardFocus();
if (keyboard_focus
&& !(mask & (MASK_CONTROL | MASK_ALT))
&& !gFocusMgr.getKeystrokesOnly())
{
// We have keyboard focus, and it's not an accelerator
if (keyboard_focus && keyboard_focus->wantsKeyUpKeyDown())
&& !gFocusMgr.getKeystrokesOnly())
{
#ifdef LL_WINDOWS
// On windows Alt Gr key generates additional Ctrl event, as result handling situations
// like 'AltGr + D' will result in 'Alt+Ctrl+D'. If it results in WM_CHAR, don't let it
// pass into menu or it will trigger 'develop' menu assigned to this combination on top
// of character handling.
// Alt Gr can be additionally modified by Shift
const MASK alt_gr = MASK_CONTROL | MASK_ALT;
if ((mask & alt_gr) != 0
&& key >= 0x30
&& key <= 0x5A
&& (GetKeyState(VK_RMENU) & 0x8000) != 0
&& (GetKeyState(VK_RCONTROL) & 0x8000) == 0) // ensure right control is not pressed, only left one
{
return keyboard_focus->handleKey(key, mask, FALSE );
// Alt Gr key is represented as right alt and left control.
// Any alt+ctrl combination is treated as Alt Gr by TranslateMessage() and
// will generate a WM_CHAR message, but here we only treat virtual Alt Graph
// key by checking if this specific combination has unicode char.
//
// I decided to handle only virtual RAlt+LCtrl==AltGr combination to minimize
// impact on menu, but the right way might be to handle all Alt+Ctrl calls.
BYTE keyboard_state[256];
if (GetKeyboardState(keyboard_state))
{
const int char_count = 6;
wchar_t chars[char_count];
HKL layout = GetKeyboardLayout(0);
// ToUnicodeEx changes buffer state on OS below Win10, which is undesirable,
// but since we already did a TranslateMessage() in gatherInput(), this
// should have no negative effect
int res = ToUnicodeEx(key, 0, keyboard_state, chars, char_count, 1 << 2 /*do not modify buffer flag*/, layout);
if (res == 1 && chars[0] >= 0x20)
{
// Let it fall through to character handler and get a WM_CHAR.
return TRUE;
}
}
}
else if (key < 0x80)
{
// Not a special key, so likely (we hope) to generate a character. Let it fall through to character handler first.
return (keyboard_focus != NULL);
}
}
#endif
if (!(mask & (MASK_CONTROL | MASK_ALT)))
{
// We have keyboard focus, and it's not an accelerator
if (keyboard_focus && keyboard_focus->wantsKeyUpKeyDown())
{
return keyboard_focus->handleKey(key, mask, FALSE);
}
else if (key < 0x80)
{
// Not a special key, so likely (we hope) to generate a character. Let it fall through to character handler first.
return TRUE;
}
}
}
// let menus handle navigation keys for navigation
if ((gMenuBarView && gMenuBarView->handleKey(key, mask, TRUE))