mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-29 07:42:04 +00:00
Bug 773651 Guess VK_RCONTROL and VK_RMENU from extended key flag on XP and don't trust the scan code of key messages r=jimm
This commit is contained in:
parent
7e4f389cbe
commit
084ca1d1c9
File diff suppressed because it is too large
Load Diff
@ -386,37 +386,141 @@ NativeKey::NativeKey(const KeyboardLayout& aKeyboardLayout,
|
||||
{
|
||||
mScanCode = WinUtils::GetScanCode(aKeyOrCharMessage.lParam);
|
||||
mIsExtended = WinUtils::IsExtendedScanCode(aKeyOrCharMessage.lParam);
|
||||
// On WinXP and WinServer2003, we cannot compute the virtual keycode for
|
||||
// extended keys due to the API limitation.
|
||||
bool canComputeVirtualKeyCodeFromScanCode =
|
||||
(!mIsExtended || WinUtils::GetWindowsVersion() >= WinUtils::VISTA_VERSION);
|
||||
switch (aKeyOrCharMessage.message) {
|
||||
case WM_KEYDOWN:
|
||||
case WM_KEYUP:
|
||||
case WM_SYSKEYDOWN:
|
||||
case WM_SYSKEYUP:
|
||||
mOriginalVirtualKeyCode = static_cast<PRUint8>(aKeyOrCharMessage.wParam);
|
||||
switch (aKeyOrCharMessage.wParam) {
|
||||
case WM_SYSKEYUP: {
|
||||
// First, resolve the IME converted virtual keycode to its original
|
||||
// keycode.
|
||||
if (aKeyOrCharMessage.wParam == VK_PROCESSKEY) {
|
||||
mOriginalVirtualKeyCode = static_cast<PRUint8>(
|
||||
::ImmGetVirtualKey(aWindow->GetWindowHandle()));
|
||||
} else {
|
||||
mOriginalVirtualKeyCode =
|
||||
static_cast<PRUint8>(aKeyOrCharMessage.wParam);
|
||||
}
|
||||
|
||||
// Most keys are not distinguished as left or right keys.
|
||||
bool isLeftRightDistinguishedKey = false;
|
||||
|
||||
// mOriginalVirtualKeyCode must not distinguish left or right of
|
||||
// Shift, Control or Alt.
|
||||
switch (mOriginalVirtualKeyCode) {
|
||||
case VK_SHIFT:
|
||||
case VK_CONTROL:
|
||||
case VK_MENU:
|
||||
case VK_SHIFT:
|
||||
mVirtualKeyCode = static_cast<PRUint8>(
|
||||
::MapVirtualKeyEx(GetScanCodeWithExtendedFlag(),
|
||||
MAPVK_VSC_TO_VK_EX, aKeyboardLayout.GetLayout()));
|
||||
isLeftRightDistinguishedKey = true;
|
||||
break;
|
||||
case VK_PROCESSKEY:
|
||||
mVirtualKeyCode = mOriginalVirtualKeyCode =
|
||||
static_cast<PRUint8>(
|
||||
::ImmGetVirtualKey(aWindow->GetWindowHandle()));
|
||||
case VK_LSHIFT:
|
||||
case VK_RSHIFT:
|
||||
mVirtualKeyCode = mOriginalVirtualKeyCode;
|
||||
mOriginalVirtualKeyCode = VK_SHIFT;
|
||||
isLeftRightDistinguishedKey = true;
|
||||
break;
|
||||
case VK_LCONTROL:
|
||||
case VK_RCONTROL:
|
||||
mVirtualKeyCode = mOriginalVirtualKeyCode;
|
||||
mOriginalVirtualKeyCode = VK_CONTROL;
|
||||
isLeftRightDistinguishedKey = true;
|
||||
break;
|
||||
case VK_LMENU:
|
||||
case VK_RMENU:
|
||||
mVirtualKeyCode = mOriginalVirtualKeyCode;
|
||||
mOriginalVirtualKeyCode = VK_MENU;
|
||||
isLeftRightDistinguishedKey = true;
|
||||
break;
|
||||
}
|
||||
|
||||
// If virtual keycode (left-right distinguished keycode) is already
|
||||
// computed, we don't need to do anymore.
|
||||
if (mVirtualKeyCode) {
|
||||
break;
|
||||
}
|
||||
|
||||
// If the keycode doesn't have LR distinguished keycode, we just set
|
||||
// mOriginalVirtualKeyCode to mVirtualKeyCode. Note that don't compute
|
||||
// it from MapVirtualKeyEx() because the scan code might be wrong if
|
||||
// the message is sent/posted by other application. Then, we will compute
|
||||
// unexpected keycode from the scan code.
|
||||
if (!isLeftRightDistinguishedKey) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (!canComputeVirtualKeyCodeFromScanCode) {
|
||||
// The right control key and the right alt key are extended keys.
|
||||
// Therefore, we never get VK_RCONTRL and VK_RMENU for the result of
|
||||
// MapVirtualKeyEx() on WinXP or WinServer2003.
|
||||
//
|
||||
// If VK_CONTROL or VK_MENU key message is caused by an extended key,
|
||||
// we should assume that the right key of them is pressed.
|
||||
switch (mOriginalVirtualKeyCode) {
|
||||
case VK_CONTROL:
|
||||
mVirtualKeyCode = VK_RCONTROL;
|
||||
break;
|
||||
case VK_MENU:
|
||||
mVirtualKeyCode = VK_RMENU;
|
||||
break;
|
||||
case VK_SHIFT:
|
||||
// Neither left shift nor right shift is not an extended key,
|
||||
// let's use VK_LSHIFT for invalid scan code.
|
||||
mVirtualKeyCode = VK_LSHIFT;
|
||||
break;
|
||||
default:
|
||||
MOZ_NOT_REACHED("Unsupported mOriginalVirtualKeyCode");
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
NS_ASSERTION(!mVirtualKeyCode,
|
||||
"mVirtualKeyCode has been computed already");
|
||||
|
||||
// Otherwise, compute the virtual keycode with MapVirtualKeyEx().
|
||||
mVirtualKeyCode = static_cast<PRUint8>(
|
||||
::MapVirtualKeyEx(GetScanCodeWithExtendedFlag(),
|
||||
MAPVK_VSC_TO_VK_EX, aKeyboardLayout.GetLayout()));
|
||||
|
||||
// The result might be unexpected value due to the scan code is
|
||||
// wrong. For example, any key messages can be generated by
|
||||
// SendMessage() or PostMessage() from applications. So, it's possible
|
||||
// failure. Then, let's respect the extended flag even if it might be
|
||||
// set intentionally.
|
||||
switch (mOriginalVirtualKeyCode) {
|
||||
case VK_CONTROL:
|
||||
if (mVirtualKeyCode != VK_LCONTROL &&
|
||||
mVirtualKeyCode != VK_RCONTROL) {
|
||||
mVirtualKeyCode = mIsExtended ? VK_RCONTROL : VK_LCONTROL;
|
||||
}
|
||||
break;
|
||||
case VK_MENU:
|
||||
if (mVirtualKeyCode != VK_LMENU && mVirtualKeyCode != VK_RMENU) {
|
||||
mVirtualKeyCode = mIsExtended ? VK_RMENU : VK_LMENU;
|
||||
}
|
||||
break;
|
||||
case VK_SHIFT:
|
||||
if (mVirtualKeyCode != VK_LSHIFT && mVirtualKeyCode != VK_RSHIFT) {
|
||||
// Neither left shift nor right shift is not an extended key,
|
||||
// let's use VK_LSHIFT for invalid scan code.
|
||||
mVirtualKeyCode = VK_LSHIFT;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
mVirtualKeyCode = mOriginalVirtualKeyCode;
|
||||
MOZ_NOT_REACHED("Unsupported mOriginalVirtualKeyCode");
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case WM_CHAR:
|
||||
case WM_UNICHAR:
|
||||
case WM_SYSCHAR:
|
||||
// We cannot compute the virtual key code from WM_CHAR message on WinXP
|
||||
// and
|
||||
if (mIsExtended &&
|
||||
WinUtils::GetWindowsVersion() < WinUtils::VISTA_VERSION) {
|
||||
// if it's caused by an extended key.
|
||||
if (!canComputeVirtualKeyCodeFromScanCode) {
|
||||
break;
|
||||
}
|
||||
mVirtualKeyCode = mOriginalVirtualKeyCode = static_cast<PRUint8>(
|
||||
@ -446,6 +550,7 @@ NativeKey::GetScanCodeWithExtendedFlag() const
|
||||
// no way to get virtual keycodes from scancode of extended keys.
|
||||
if (!mIsExtended ||
|
||||
WinUtils::GetWindowsVersion() < WinUtils::VISTA_VERSION) {
|
||||
NS_WARNING("GetScanCodeWithExtendedFlat() returns without extended flag");
|
||||
return mScanCode;
|
||||
}
|
||||
return (0xE000 | mScanCode);
|
||||
@ -468,6 +573,7 @@ NativeKey::GetKeyLocation() const
|
||||
return nsIDOMKeyEvent::DOM_KEY_LOCATION_RIGHT;
|
||||
|
||||
case VK_RETURN:
|
||||
// XXX This code assumes that all keyboard drivers use same mapping.
|
||||
return !mIsExtended ? nsIDOMKeyEvent::DOM_KEY_LOCATION_STANDARD :
|
||||
nsIDOMKeyEvent::DOM_KEY_LOCATION_NUMPAD;
|
||||
|
||||
@ -482,6 +588,7 @@ NativeKey::GetKeyLocation() const
|
||||
case VK_HOME:
|
||||
case VK_UP:
|
||||
case VK_PRIOR:
|
||||
// XXX This code assumes that all keyboard drivers use same mapping.
|
||||
return mIsExtended ? nsIDOMKeyEvent::DOM_KEY_LOCATION_STANDARD :
|
||||
nsIDOMKeyEvent::DOM_KEY_LOCATION_NUMPAD;
|
||||
|
||||
@ -503,6 +610,11 @@ NativeKey::GetKeyLocation() const
|
||||
case VK_ADD:
|
||||
return nsIDOMKeyEvent::DOM_KEY_LOCATION_NUMPAD;
|
||||
|
||||
case VK_SHIFT:
|
||||
case VK_CONTROL:
|
||||
case VK_MENU:
|
||||
NS_WARNING("Failed to decide the key location?");
|
||||
|
||||
default:
|
||||
return nsIDOMKeyEvent::DOM_KEY_LOCATION_STANDARD;
|
||||
}
|
||||
|
@ -5700,11 +5700,65 @@ nsWindow::SynthesizeNativeKeyEvent(PRInt32 aNativeKeyboardLayout,
|
||||
HKL oldLayout = gKbdLayout.GetLayout();
|
||||
gKbdLayout.LoadLayout(loadedLayout);
|
||||
|
||||
PRUint8 argumentKeySpecific = 0;
|
||||
switch (aNativeKeyCode) {
|
||||
case VK_SHIFT:
|
||||
aModifierFlags &= ~(nsIWidget::SHIFT_L | nsIWidget::SHIFT_R);
|
||||
argumentKeySpecific = VK_LSHIFT;
|
||||
break;
|
||||
case VK_LSHIFT:
|
||||
aModifierFlags &= ~nsIWidget::SHIFT_L;
|
||||
argumentKeySpecific = aNativeKeyCode;
|
||||
aNativeKeyCode = VK_SHIFT;
|
||||
break;
|
||||
case VK_RSHIFT:
|
||||
aModifierFlags &= ~nsIWidget::SHIFT_R;
|
||||
argumentKeySpecific = aNativeKeyCode;
|
||||
aNativeKeyCode = VK_SHIFT;
|
||||
break;
|
||||
case VK_CONTROL:
|
||||
aModifierFlags &= ~(nsIWidget::CTRL_L | nsIWidget::CTRL_R);
|
||||
argumentKeySpecific = VK_LCONTROL;
|
||||
break;
|
||||
case VK_LCONTROL:
|
||||
aModifierFlags &= ~nsIWidget::CTRL_L;
|
||||
argumentKeySpecific = aNativeKeyCode;
|
||||
aNativeKeyCode = VK_CONTROL;
|
||||
break;
|
||||
case VK_RCONTROL:
|
||||
aModifierFlags &= ~nsIWidget::CTRL_R;
|
||||
argumentKeySpecific = aNativeKeyCode;
|
||||
aNativeKeyCode = VK_CONTROL;
|
||||
break;
|
||||
case VK_MENU:
|
||||
aModifierFlags &= ~(nsIWidget::ALT_L | nsIWidget::ALT_R);
|
||||
argumentKeySpecific = VK_LMENU;
|
||||
break;
|
||||
case VK_LMENU:
|
||||
aModifierFlags &= ~nsIWidget::ALT_L;
|
||||
argumentKeySpecific = aNativeKeyCode;
|
||||
aNativeKeyCode = VK_MENU;
|
||||
break;
|
||||
case VK_RMENU:
|
||||
aModifierFlags &= ~nsIWidget::ALT_R;
|
||||
argumentKeySpecific = aNativeKeyCode;
|
||||
aNativeKeyCode = VK_MENU;
|
||||
break;
|
||||
case VK_CAPITAL:
|
||||
aModifierFlags &= ~nsIWidget::CAPS_LOCK;
|
||||
argumentKeySpecific = VK_CAPITAL;
|
||||
break;
|
||||
case VK_NUMLOCK:
|
||||
aModifierFlags &= ~nsIWidget::NUM_LOCK;
|
||||
argumentKeySpecific = VK_NUMLOCK;
|
||||
break;
|
||||
}
|
||||
|
||||
nsAutoTArray<KeyPair,10> keySequence;
|
||||
SetupKeyModifiersSequence(&keySequence, aModifierFlags);
|
||||
NS_ASSERTION(aNativeKeyCode >= 0 && aNativeKeyCode < 256,
|
||||
"Native VK key code out of range");
|
||||
keySequence.AppendElement(KeyPair(aNativeKeyCode, 0));
|
||||
keySequence.AppendElement(KeyPair(aNativeKeyCode, argumentKeySpecific));
|
||||
|
||||
// Simulate the pressing of each modifier key and then the real key
|
||||
for (PRUint32 i = 0; i < keySequence.Length(); ++i) {
|
||||
@ -5716,8 +5770,9 @@ nsWindow::SynthesizeNativeKeyEvent(PRInt32 aNativeKeyboardLayout,
|
||||
}
|
||||
::SetKeyboardState(kbdState);
|
||||
ModifierKeyState modKeyState;
|
||||
UINT scanCode = ::MapVirtualKeyEx(aNativeKeyCode, MAPVK_VK_TO_VSC,
|
||||
gKbdLayout.GetLayout());
|
||||
UINT scanCode = ::MapVirtualKeyEx(argumentKeySpecific ?
|
||||
argumentKeySpecific : aNativeKeyCode,
|
||||
MAPVK_VK_TO_VSC, gKbdLayout.GetLayout());
|
||||
LPARAM lParam = static_cast<LPARAM>(scanCode << 16);
|
||||
// Add extended key flag to the lParam for right control key and right alt
|
||||
// key.
|
||||
@ -5762,8 +5817,9 @@ nsWindow::SynthesizeNativeKeyEvent(PRInt32 aNativeKeyboardLayout,
|
||||
}
|
||||
::SetKeyboardState(kbdState);
|
||||
ModifierKeyState modKeyState;
|
||||
UINT scanCode = ::MapVirtualKeyEx(aNativeKeyCode, MAPVK_VK_TO_VSC,
|
||||
gKbdLayout.GetLayout());
|
||||
UINT scanCode = ::MapVirtualKeyEx(argumentKeySpecific ?
|
||||
argumentKeySpecific : aNativeKeyCode,
|
||||
MAPVK_VK_TO_VSC, gKbdLayout.GetLayout());
|
||||
LPARAM lParam = static_cast<LPARAM>(scanCode << 16);
|
||||
// Add extended key flag to the lParam for right control key and right alt
|
||||
// key.
|
||||
|
Loading…
Reference in New Issue
Block a user