From 175843b4fb897626d35a606634dd5c64d3670344 Mon Sep 17 00:00:00 2001 From: crs Date: Mon, 8 Sep 2003 19:42:00 +0000 Subject: [PATCH] Changed server side of win32 to send ctrl+alt+ if the key doesn't map to anything via AltGr. This is an improvement over the previous code which would simply discard the key but it still behaves slightly differently than pressing ctrl+alt+ on the server: if that combination is a hotkey on the server then the hotkey is performed, even if the combination is also a valid AltGr combination; on the client, we'll get the AltGr combination in preference to the hotkey. --- lib/platform/CMSWindowsKeyMapper.cpp | 130 ++++++++++++++++----------- lib/platform/CMSWindowsKeyMapper.h | 6 ++ 2 files changed, 83 insertions(+), 53 deletions(-) diff --git a/lib/platform/CMSWindowsKeyMapper.cpp b/lib/platform/CMSWindowsKeyMapper.cpp index 6e47aa95..ac77cc95 100644 --- a/lib/platform/CMSWindowsKeyMapper.cpp +++ b/lib/platform/CMSWindowsKeyMapper.cpp @@ -1101,52 +1101,21 @@ CMSWindowsKeyMapper::mapKeyFromEvent(WPARAM vkCode, LPARAM info, keys[VK_MENU] = 0x80; } - // get contents of keyboard layout buffer and clear out that - // buffer. we don't want anything placed there by some other - // app interfering and we need to put anything there back in - // place when we're done. - TCHAR oldDeadKey = getSavedDeadChar(hkl); - - // put our previous dead key, if any, in the layout buffer - putBackDeadChar(m_deadKey, hkl, false); - m_deadKey = 0; - - // process key - WORD ascii; + // map to a character bool isMenu = ((menu & 0x80) != 0); - int result = ToAsciiEx(vkCode, scanCode, keys, &ascii, - isMenu ? 1 : 0, hkl); + c = mapToCharacter(vkCode, scanCode, keys, press, isMenu, hkl); - // if result is less than zero then it was a dead key - if (result < 0) { - // save dead key if a key press. we catch the dead key - // release in the result == 2 case below. - if (press) { - m_deadKey = static_cast(ascii & 0xffu); - } - } - - // if result is 1 then the key was succesfully converted - else if (result == 1) { - c = static_cast(ascii & 0xff); - } - - // if result is 2 and the two characters are the same and this - // is a key release then a dead key was released. save the - // dead key. if the two characters are the same and this is - // not a release then a dead key was pressed twice. send the - // dead key. - else if (result == 2) { - if (((ascii & 0xff00u) >> 8) == (ascii & 0x00ffu)) { - if (!press) { - m_deadKey = static_cast(ascii & 0xffu); - } - else { - putBackDeadChar(oldDeadKey, hkl, false); - result = toAscii(' ', hkl, false, &ascii); - c = static_cast((ascii >> 8) & 0xffu); - } - } + // if mapping failed and ctrl and alt are pressed then try again + // with both not pressed. this handles the case where ctrl and + // alt are being used as individual modifiers rather than AltGr. + if (c == 0 && (control & 0x80) != 0 && (menu & 0x80) != 0) { + keys[VK_LCONTROL] = 0; + keys[VK_RCONTROL] = 0; + keys[VK_CONTROL] = 0; + keys[VK_LMENU] = 0; + keys[VK_RMENU] = 0; + keys[VK_MENU] = 0; + c = mapToCharacter(vkCode, scanCode, keys, press, isMenu, hkl); } // map character to key id @@ -1170,15 +1139,6 @@ CMSWindowsKeyMapper::mapKeyFromEvent(WPARAM vkCode, LPARAM info, id = static_cast(c) & 0xffu; } } - - // clear keyboard layout buffer. this removes any dead key we - // may have just put there. - toAscii(' ', hkl, false, NULL); - - // restore keyboard layout buffer so a dead key inserted by - // another app doesn't disappear mysteriously (from its point - // of view). - putBackDeadChar(oldDeadKey, hkl, false); } // set mask @@ -1594,3 +1554,67 @@ CMSWindowsKeyMapper::getSavedDeadChar(HKL hkl) const } return 0; } + +char +CMSWindowsKeyMapper::mapToCharacter(UINT vkCode, UINT scanCode, + BYTE* keys, bool press, bool isMenu, HKL hkl) const +{ + // get contents of keyboard layout buffer and clear out that + // buffer. we don't want anything placed there by some other + // app interfering and we need to put anything there back in + // place when we're done. + TCHAR oldDeadKey = getSavedDeadChar(hkl); + + // put our previous dead key, if any, in the layout buffer + putBackDeadChar(m_deadKey, hkl, false); + m_deadKey = 0; + + // process key + WORD ascii; + int result = ToAsciiEx(vkCode, scanCode, keys, &ascii, + isMenu ? 1 : 0, hkl); + + // if result is less than zero then it was a dead key + char c = 0; + if (result < 0) { + // save dead key if a key press. we catch the dead key + // release in the result == 2 case below. + if (press) { + m_deadKey = static_cast(ascii & 0xffu); + } + } + + // if result is 1 then the key was succesfully converted + else if (result == 1) { + c = static_cast(ascii & 0xff); + } + + // if result is 2 and the two characters are the same and this + // is a key release then a dead key was released. save the + // dead key. if the two characters are the same and this is + // not a release then a dead key was pressed twice. send the + // dead key. + else if (result == 2) { + if (((ascii & 0xff00u) >> 8) == (ascii & 0x00ffu)) { + if (!press) { + m_deadKey = static_cast(ascii & 0xffu); + } + else { + putBackDeadChar(oldDeadKey, hkl, false); + result = toAscii(' ', hkl, false, &ascii); + c = static_cast((ascii >> 8) & 0xffu); + } + } + } + + // clear keyboard layout buffer. this removes any dead key we + // may have just put there. + toAscii(' ', hkl, false, NULL); + + // restore keyboard layout buffer so a dead key inserted by + // another app doesn't disappear mysteriously (from its point + // of view). + putBackDeadChar(oldDeadKey, hkl, false); + + return c; +} diff --git a/lib/platform/CMSWindowsKeyMapper.h b/lib/platform/CMSWindowsKeyMapper.h index 679e6fc7..5bcfcedf 100644 --- a/lib/platform/CMSWindowsKeyMapper.h +++ b/lib/platform/CMSWindowsKeyMapper.h @@ -134,6 +134,12 @@ private: // get the dead key saved in the given keyboard layout, or 0 if none TCHAR getSavedDeadChar(HKL hkl) const; + // map the given virtual key, scan code, and keyboard state to a + // character, if possible. this has the side effect of updating + // m_deadKey. + char mapToCharacter(UINT vkCode, UINT scanCode, + BYTE* keys, bool press, bool isMenu, HKL hkl) const; + private: class CModifierKeys { public: