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:
parent
f4d7ea3d7b
commit
175843b4fb
|
@ -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;
|
||||||
|
}
|
||||||
|
|
|
@ -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:
|
||||||
|
|
Loading…
Reference in New Issue