Changed server side of win32 to send ctrl+alt+<key> 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+<key>
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.
This commit is contained in:
crs 2003-09-08 19:42:00 +00:00
parent f4d7ea3d7b
commit 175843b4fb
2 changed files with 83 additions and 53 deletions

View File

@ -1101,52 +1101,21 @@ CMSWindowsKeyMapper::mapKeyFromEvent(WPARAM vkCode, LPARAM info,
keys[VK_MENU] = 0x80; keys[VK_MENU] = 0x80;
} }
// get contents of keyboard layout buffer and clear out that // map to a character
// 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;
bool isMenu = ((menu & 0x80) != 0); bool isMenu = ((menu & 0x80) != 0);
int result = ToAsciiEx(vkCode, scanCode, keys, &ascii, c = mapToCharacter(vkCode, scanCode, keys, press, isMenu, hkl);
isMenu ? 1 : 0, hkl);
// if result is less than zero then it was a dead key // if mapping failed and ctrl and alt are pressed then try again
if (result < 0) { // with both not pressed. this handles the case where ctrl and
// save dead key if a key press. we catch the dead key // alt are being used as individual modifiers rather than AltGr.
// release in the result == 2 case below. if (c == 0 && (control & 0x80) != 0 && (menu & 0x80) != 0) {
if (press) { keys[VK_LCONTROL] = 0;
m_deadKey = static_cast<TCHAR>(ascii & 0xffu); keys[VK_RCONTROL] = 0;
} keys[VK_CONTROL] = 0;
} keys[VK_LMENU] = 0;
keys[VK_RMENU] = 0;
// if result is 1 then the key was succesfully converted keys[VK_MENU] = 0;
else if (result == 1) { c = mapToCharacter(vkCode, scanCode, keys, press, isMenu, hkl);
c = static_cast<char>(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<TCHAR>(ascii & 0xffu);
}
else {
putBackDeadChar(oldDeadKey, hkl, false);
result = toAscii(' ', hkl, false, &ascii);
c = static_cast<char>((ascii >> 8) & 0xffu);
}
}
} }
// map character to key id // map character to key id
@ -1170,15 +1139,6 @@ CMSWindowsKeyMapper::mapKeyFromEvent(WPARAM vkCode, LPARAM info,
id = static_cast<KeyID>(c) & 0xffu; id = static_cast<KeyID>(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 // set mask
@ -1594,3 +1554,67 @@ CMSWindowsKeyMapper::getSavedDeadChar(HKL hkl) const
} }
return 0; 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<TCHAR>(ascii & 0xffu);
}
}
// if result is 1 then the key was succesfully converted
else if (result == 1) {
c = static_cast<char>(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<TCHAR>(ascii & 0xffu);
}
else {
putBackDeadChar(oldDeadKey, hkl, false);
result = toAscii(' ', hkl, false, &ascii);
c = static_cast<char>((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;
}

View File

@ -134,6 +134,12 @@ private:
// get the dead key saved in the given keyboard layout, or 0 if none // get the dead key saved in the given keyboard layout, or 0 if none
TCHAR getSavedDeadChar(HKL hkl) const; 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: private:
class CModifierKeys { class CModifierKeys {
public: public: