platform: Fixed processing of non-ASCII symbols
The non-ASCII symbols missing in CP_THREAD_ACP but present in current KB layout were processed incorrectly. Do not rely on ANSI => UTF16 conversion, obtain UTF16 directly from KB layout driver. BTW, ToAscii is implemented via ToUnicode + RtlUnicodeToMultiByteN, so this is really optimization.
This commit is contained in:
parent
64a9c41edc
commit
09e1dbdf84
|
@ -143,9 +143,9 @@ keyboardGetState(BYTE keys[256], DWORD vkCode, bool kf_up)
|
||||||
|
|
||||||
static
|
static
|
||||||
WPARAM
|
WPARAM
|
||||||
makeKeyMsg(UINT virtKey, char c, bool noAltGr)
|
makeKeyMsg(UINT virtKey, WCHAR wc, bool noAltGr)
|
||||||
{
|
{
|
||||||
return MAKEWPARAM(MAKEWORD(virtKey & 0xff, (BYTE)c), noAltGr ? 1 : 0);
|
return MAKEWPARAM((WORD)wc, MAKEWORD(virtKey & 0xff, noAltGr ? 1 : 0));
|
||||||
}
|
}
|
||||||
|
|
||||||
static
|
static
|
||||||
|
@ -192,7 +192,7 @@ keyboardHookHandler(WPARAM wParam, LPARAM lParam)
|
||||||
(lParam & 0x80000000u) != 0) {
|
(lParam & 0x80000000u) != 0) {
|
||||||
g_deadRelease = 0;
|
g_deadRelease = 0;
|
||||||
PostThreadMessage(g_threadID, BARRIER_MSG_DEBUG,
|
PostThreadMessage(g_threadID, BARRIER_MSG_DEBUG,
|
||||||
wParam | 0x04000000, lParam);
|
wParam | 0x40000000, lParam);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -244,19 +244,19 @@ keyboardHookHandler(WPARAM wParam, LPARAM lParam)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
WORD c = 0;
|
WCHAR wc[2] = { 0, 0 };
|
||||||
|
|
||||||
// map the key event to a character. we have to put the dead
|
// map the key event to a character. we have to put the dead
|
||||||
// key back first and this has the side effect of removing it.
|
// key back first and this has the side effect of removing it.
|
||||||
if (g_deadVirtKey != 0) {
|
if (g_deadVirtKey != 0) {
|
||||||
if (ToAscii((UINT)g_deadVirtKey, (g_deadLParam & 0x10ff0000u) >> 16,
|
if (ToUnicode((UINT)g_deadVirtKey, (g_deadLParam & 0x10ff0000u) >> 16,
|
||||||
g_deadKeyState, &c, flags) == 2) {
|
g_deadKeyState, wc, 2, flags) == 2) {
|
||||||
// If ToAscii returned 2, it means that we accidentally removed
|
// If ToUnicode returned 2, it means that we accidentally removed
|
||||||
// a double dead key instead of restoring it. Thus, we call
|
// a double dead key instead of restoring it. Thus, we call
|
||||||
// ToAscii again with the same parameters to restore the
|
// ToUnicode again with the same parameters to restore the
|
||||||
// internal dead key state.
|
// internal dead key state.
|
||||||
ToAscii((UINT)g_deadVirtKey, (g_deadLParam & 0x10ff0000u) >> 16,
|
ToUnicode((UINT)g_deadVirtKey, (g_deadLParam & 0x10ff0000u) >> 16,
|
||||||
g_deadKeyState, &c, flags);
|
g_deadKeyState, wc, 2, flags);
|
||||||
|
|
||||||
// We need to keep track of this because g_deadVirtKey will be
|
// We need to keep track of this because g_deadVirtKey will be
|
||||||
// cleared later on; this would cause the dead key release to
|
// cleared later on; this would cause the dead key release to
|
||||||
|
@ -266,7 +266,7 @@ keyboardHookHandler(WPARAM wParam, LPARAM lParam)
|
||||||
}
|
}
|
||||||
|
|
||||||
UINT scanCode = ((lParam & 0x10ff0000u) >> 16);
|
UINT scanCode = ((lParam & 0x10ff0000u) >> 16);
|
||||||
int n = ToAscii((UINT)wParam, scanCode, keys, &c, flags);
|
int n = ToUnicode((UINT)wParam, scanCode, keys, wc, 2, flags);
|
||||||
|
|
||||||
// if mapping failed and ctrl and alt are pressed then try again
|
// if mapping failed and ctrl and alt are pressed then try again
|
||||||
// with both not pressed. this handles the case where ctrl and
|
// with both not pressed. this handles the case where ctrl and
|
||||||
|
@ -278,12 +278,12 @@ keyboardHookHandler(WPARAM wParam, LPARAM lParam)
|
||||||
if (n == 0 && (control & 0x80) != 0 && (menu & 0x80) != 0) {
|
if (n == 0 && (control & 0x80) != 0 && (menu & 0x80) != 0) {
|
||||||
noAltGr = true;
|
noAltGr = true;
|
||||||
PostThreadMessage(g_threadID, BARRIER_MSG_DEBUG,
|
PostThreadMessage(g_threadID, BARRIER_MSG_DEBUG,
|
||||||
wParam | 0x05000000, lParam);
|
wParam | 0x50000000, lParam);
|
||||||
if (g_deadVirtKey != 0) {
|
if (g_deadVirtKey != 0) {
|
||||||
if (ToAscii((UINT)g_deadVirtKey, (g_deadLParam & 0x10ff0000u) >> 16,
|
if (ToUnicode((UINT)g_deadVirtKey, (g_deadLParam & 0x10ff0000u) >> 16,
|
||||||
g_deadKeyState, &c, flags) == 2) {
|
g_deadKeyState, wc, 2, flags) == 2) {
|
||||||
ToAscii((UINT)g_deadVirtKey, (g_deadLParam & 0x10ff0000u) >> 16,
|
ToUnicode((UINT)g_deadVirtKey, (g_deadLParam & 0x10ff0000u) >> 16,
|
||||||
g_deadKeyState, &c, flags);
|
g_deadKeyState, wc, 2, flags);
|
||||||
g_deadRelease = g_deadVirtKey;
|
g_deadRelease = g_deadVirtKey;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -297,12 +297,12 @@ keyboardHookHandler(WPARAM wParam, LPARAM lParam)
|
||||||
keys2[VK_LMENU] = 0;
|
keys2[VK_LMENU] = 0;
|
||||||
keys2[VK_RMENU] = 0;
|
keys2[VK_RMENU] = 0;
|
||||||
keys2[VK_MENU] = 0;
|
keys2[VK_MENU] = 0;
|
||||||
n = ToAscii((UINT)wParam, scanCode, keys2, &c, flags);
|
n = ToUnicode((UINT)wParam, scanCode, keys2, wc, 2, flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
PostThreadMessage(g_threadID, BARRIER_MSG_DEBUG,
|
PostThreadMessage(g_threadID, BARRIER_MSG_DEBUG,
|
||||||
wParam | ((c & 0xff) << 8) |
|
(wc[0] & 0xffff) | ((wParam & 0xff) << 16) |
|
||||||
((n & 0xff) << 16) | 0x06000000,
|
((n & 0xf) << 24) | 0x60000000,
|
||||||
lParam);
|
lParam);
|
||||||
WPARAM charAndVirtKey = 0;
|
WPARAM charAndVirtKey = 0;
|
||||||
bool clearDeadKey = false;
|
bool clearDeadKey = false;
|
||||||
|
@ -328,12 +328,12 @@ keyboardHookHandler(WPARAM wParam, LPARAM lParam)
|
||||||
case 0:
|
case 0:
|
||||||
// key doesn't map to a character. this can happen if
|
// key doesn't map to a character. this can happen if
|
||||||
// non-character keys are pressed after a dead key.
|
// non-character keys are pressed after a dead key.
|
||||||
charAndVirtKey = makeKeyMsg((UINT)wParam, (char)0, noAltGr);
|
charAndVirtKey = makeKeyMsg((UINT)wParam, (WCHAR)0, noAltGr);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 1:
|
case 1:
|
||||||
// key maps to a character composed with dead key
|
// key maps to a character composed with dead key
|
||||||
charAndVirtKey = makeKeyMsg((UINT)wParam, (char)LOBYTE(c), noAltGr);
|
charAndVirtKey = makeKeyMsg((UINT)wParam, wc[0], noAltGr);
|
||||||
clearDeadKey = true;
|
clearDeadKey = true;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -341,14 +341,14 @@ keyboardHookHandler(WPARAM wParam, LPARAM lParam)
|
||||||
// previous dead key not composed. send a fake key press
|
// previous dead key not composed. send a fake key press
|
||||||
// and release for the dead key to our window.
|
// and release for the dead key to our window.
|
||||||
WPARAM deadCharAndVirtKey =
|
WPARAM deadCharAndVirtKey =
|
||||||
makeKeyMsg((UINT)g_deadVirtKey, (char)LOBYTE(c), noAltGr);
|
makeKeyMsg((UINT)g_deadVirtKey, wc[0], noAltGr);
|
||||||
PostThreadMessage(g_threadID, BARRIER_MSG_KEY,
|
PostThreadMessage(g_threadID, BARRIER_MSG_KEY,
|
||||||
deadCharAndVirtKey, g_deadLParam & 0x7fffffffu);
|
deadCharAndVirtKey, g_deadLParam & 0x7fffffffu);
|
||||||
PostThreadMessage(g_threadID, BARRIER_MSG_KEY,
|
PostThreadMessage(g_threadID, BARRIER_MSG_KEY,
|
||||||
deadCharAndVirtKey, g_deadLParam | 0x80000000u);
|
deadCharAndVirtKey, g_deadLParam | 0x80000000u);
|
||||||
|
|
||||||
// use uncomposed character
|
// use uncomposed character
|
||||||
charAndVirtKey = makeKeyMsg((UINT)wParam, (char)HIBYTE(c), noAltGr);
|
charAndVirtKey = makeKeyMsg((UINT)wParam, wc[1], noAltGr);
|
||||||
clearDeadKey = true;
|
clearDeadKey = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -356,8 +356,8 @@ keyboardHookHandler(WPARAM wParam, LPARAM lParam)
|
||||||
|
|
||||||
// put back the dead key, if any, for the application to use
|
// put back the dead key, if any, for the application to use
|
||||||
if (g_deadVirtKey != 0) {
|
if (g_deadVirtKey != 0) {
|
||||||
ToAscii((UINT)g_deadVirtKey, (g_deadLParam & 0x10ff0000u) >> 16,
|
ToUnicode((UINT)g_deadVirtKey, (g_deadLParam & 0x10ff0000u) >> 16,
|
||||||
g_deadKeyState, &c, flags);
|
g_deadKeyState, wc, 2, flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
// clear out old dead key state
|
// clear out old dead key state
|
||||||
|
@ -374,7 +374,7 @@ keyboardHookHandler(WPARAM wParam, LPARAM lParam)
|
||||||
// forwarding.
|
// forwarding.
|
||||||
if (charAndVirtKey != 0) {
|
if (charAndVirtKey != 0) {
|
||||||
PostThreadMessage(g_threadID, BARRIER_MSG_DEBUG,
|
PostThreadMessage(g_threadID, BARRIER_MSG_DEBUG,
|
||||||
charAndVirtKey | 0x07000000, lParam);
|
charAndVirtKey | 0x70000000, lParam);
|
||||||
PostThreadMessage(g_threadID, BARRIER_MSG_KEY, charAndVirtKey, lParam);
|
PostThreadMessage(g_threadID, BARRIER_MSG_KEY, charAndVirtKey, lParam);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -688,34 +688,17 @@ MSWindowsKeyState::mapKeyFromEvent(WPARAM charAndVirtKey,
|
||||||
KeyModifierControl | KeyModifierAlt;
|
KeyModifierControl | KeyModifierAlt;
|
||||||
|
|
||||||
// extract character, virtual key, and if we didn't use AltGr
|
// extract character, virtual key, and if we didn't use AltGr
|
||||||
char c = (char)((charAndVirtKey & 0xff00u) >> 8);
|
WCHAR wc = (WCHAR)(charAndVirtKey & 0xffffu);
|
||||||
UINT vkCode = (charAndVirtKey & 0xffu);
|
UINT vkCode = ((charAndVirtKey >> 16) & 0xffu);
|
||||||
bool noAltGr = ((charAndVirtKey & 0xff0000u) != 0);
|
bool noAltGr = ((charAndVirtKey & 0xff000000u) != 0);
|
||||||
|
|
||||||
// handle some keys via table lookup
|
// handle some keys via table lookup
|
||||||
KeyID id = getKeyID(vkCode, (KeyButton)((info >> 16) & 0x1ffu));
|
KeyID id = getKeyID(vkCode, (KeyButton)((info >> 16) & 0x1ffu));
|
||||||
|
|
||||||
// check if not in table; map character to key id
|
// check if not in table; map character to key id
|
||||||
if (id == kKeyNone && c != 0) {
|
if (id == kKeyNone && wc != 0) {
|
||||||
if ((c & 0x80u) == 0) {
|
// UTF16
|
||||||
// ASCII
|
id = static_cast<KeyID>(wc) & 0xffffu;
|
||||||
id = static_cast<KeyID>(c) & 0xffu;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
// character is not really ASCII. instead it's some
|
|
||||||
// character in the current ANSI code page. try to
|
|
||||||
// convert that to a Unicode character. if we fail
|
|
||||||
// then use the single byte character as is.
|
|
||||||
char src = c;
|
|
||||||
wchar_t unicode;
|
|
||||||
if (MultiByteToWideChar(CP_THREAD_ACP, MB_PRECOMPOSED,
|
|
||||||
&src, 1, &unicode, 1) > 0) {
|
|
||||||
id = static_cast<KeyID>(unicode);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
id = static_cast<KeyID>(c) & 0xffu;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// set modifier mask
|
// set modifier mask
|
||||||
|
|
|
@ -1104,7 +1104,7 @@ MSWindowsScreen::onKey(WPARAM wParam, LPARAM lParam)
|
||||||
static const KeyModifierMask s_ctrlAlt =
|
static const KeyModifierMask s_ctrlAlt =
|
||||||
KeyModifierControl | KeyModifierAlt;
|
KeyModifierControl | KeyModifierAlt;
|
||||||
|
|
||||||
LOG((CLOG_DEBUG1 "event: Key char=%d, vk=0x%02x, nagr=%d, lParam=0x%08x", (wParam & 0xff00u) >> 8, wParam & 0xffu, (wParam & 0x10000u) ? 1 : 0, lParam));
|
LOG((CLOG_DEBUG1 "event: Key char=%d, vk=0x%02x, nagr=%d, lParam=0x%08x", wParam & 0xffffu, (wParam >> 16) & 0xffu, (wParam & 0x1000000u) ? 1 : 0, lParam));
|
||||||
|
|
||||||
// get event info
|
// get event info
|
||||||
KeyButton button = (KeyButton)((lParam & 0x01ff0000) >> 16);
|
KeyButton button = (KeyButton)((lParam & 0x01ff0000) >> 16);
|
||||||
|
@ -1122,7 +1122,7 @@ MSWindowsScreen::onKey(WPARAM wParam, LPARAM lParam)
|
||||||
// that maps mouse buttons to keys is known to do this.
|
// that maps mouse buttons to keys is known to do this.
|
||||||
// alternatively, we could just throw these events out.
|
// alternatively, we could just throw these events out.
|
||||||
if (button == 0) {
|
if (button == 0) {
|
||||||
button = m_keyState->virtualKeyToButton(wParam & 0xffu);
|
button = m_keyState->virtualKeyToButton((wParam >> 16) & 0xffu);
|
||||||
if (button == 0) {
|
if (button == 0) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -1188,7 +1188,7 @@ MSWindowsScreen::onKey(WPARAM wParam, LPARAM lParam)
|
||||||
if (!ignore()) {
|
if (!ignore()) {
|
||||||
// check for ctrl+alt+del. we do not want to pass that to the
|
// check for ctrl+alt+del. we do not want to pass that to the
|
||||||
// client. the user can use ctrl+alt+pause to emulate it.
|
// client. the user can use ctrl+alt+pause to emulate it.
|
||||||
UINT virtKey = (wParam & 0xffu);
|
UINT virtKey = (wParam >> 16) & 0xffu;
|
||||||
if (virtKey == VK_DELETE && (state & s_ctrlAlt) == s_ctrlAlt) {
|
if (virtKey == VK_DELETE && (state & s_ctrlAlt) == s_ctrlAlt) {
|
||||||
LOG((CLOG_DEBUG "discard ctrl+alt+del"));
|
LOG((CLOG_DEBUG "discard ctrl+alt+del"));
|
||||||
return true;
|
return true;
|
||||||
|
@ -1202,9 +1202,9 @@ MSWindowsScreen::onKey(WPARAM wParam, LPARAM lParam)
|
||||||
// pressed or released. when mapping the key we require that
|
// pressed or released. when mapping the key we require that
|
||||||
// we not use AltGr (the 0x10000 flag in wParam) and we not
|
// we not use AltGr (the 0x10000 flag in wParam) and we not
|
||||||
// use the keypad delete key (the 0x01000000 flag in lParam).
|
// use the keypad delete key (the 0x01000000 flag in lParam).
|
||||||
wParam = VK_DELETE | 0x00010000u;
|
wParam = (VK_DELETE << 16) | 0x01000000u;
|
||||||
lParam &= 0xfe000000;
|
lParam &= 0xfe000000;
|
||||||
lParam |= m_keyState->virtualKeyToButton(wParam & 0xffu) << 16;
|
lParam |= m_keyState->virtualKeyToButton(VK_DELETE) << 16;
|
||||||
lParam |= 0x01000001;
|
lParam |= 0x01000001;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1232,7 +1232,7 @@ MSWindowsScreen::onHotKey(WPARAM wParam, LPARAM lParam)
|
||||||
{
|
{
|
||||||
// get the key info
|
// get the key info
|
||||||
KeyModifierMask state = getActiveModifiers();
|
KeyModifierMask state = getActiveModifiers();
|
||||||
UINT virtKey = (wParam & 0xffu);
|
UINT virtKey = (wParam >> 16) & 0xffu;
|
||||||
UINT modifiers = 0;
|
UINT modifiers = 0;
|
||||||
if ((state & KeyModifierShift) != 0) {
|
if ((state & KeyModifierShift) != 0) {
|
||||||
modifiers |= MOD_SHIFT;
|
modifiers |= MOD_SHIFT;
|
||||||
|
@ -1939,7 +1939,7 @@ MSWindowsScreen::isModifierRepeat(KeyModifierMask oldState, KeyModifierMask stat
|
||||||
bool result = false;
|
bool result = false;
|
||||||
|
|
||||||
if (oldState == state && state != 0) {
|
if (oldState == state && state != 0) {
|
||||||
UINT virtKey = (wParam & 0xffu);
|
UINT virtKey = (wParam >> 16) & 0xffu;
|
||||||
if ((state & KeyModifierShift) != 0
|
if ((state & KeyModifierShift) != 0
|
||||||
&& (virtKey == VK_LSHIFT || virtKey == VK_RSHIFT)) {
|
&& (virtKey == VK_LSHIFT || virtKey == VK_RSHIFT)) {
|
||||||
result = true;
|
result = true;
|
||||||
|
|
Loading…
Reference in New Issue