From e1985f52c90b307dc1e32fc4289d5ff2128b25e0 Mon Sep 17 00:00:00 2001 From: crs Date: Thu, 17 Jul 2003 21:16:58 +0000 Subject: [PATCH] Fixed handling of a dead key followed by space on win32 and X11. A dead key followed by space should convert the dead key to a regular character. --- lib/platform/CMSWindowsSecondaryScreen.cpp | 54 ++++++++++++++++++---- lib/platform/CXWindowsSecondaryScreen.cpp | 13 ++++++ 2 files changed, 58 insertions(+), 9 deletions(-) diff --git a/lib/platform/CMSWindowsSecondaryScreen.cpp b/lib/platform/CMSWindowsSecondaryScreen.cpp index 7895c382..cc617337 100644 --- a/lib/platform/CMSWindowsSecondaryScreen.cpp +++ b/lib/platform/CMSWindowsSecondaryScreen.cpp @@ -127,8 +127,8 @@ CMSWindowsSecondaryScreen::keyDown(KeyID key, // generate key events doKeystrokes(keys, 1); - // do not record button down if button is 0 (invalid) - if (button != 0) { + // do not record button down if button or virtual key is 0 (invalid) + if (button != 0 && virtualKey != 0) { // note that key is now down m_serverKeyMap[button] = virtualKey; m_keys[virtualKey] |= 0x80; @@ -956,21 +956,48 @@ CMSWindowsSecondaryScreen::mapKey(Keystrokes& keys, UINT& virtualKey, virtualKey = mapCharacter(keys, multiByte[0], hkl, m_mask, mask, action); if (virtualKey != static_cast(-1)) { LOG((CLOG_DEBUG2 "KeyID 0x%08x maps to character %u", id, (unsigned char)multiByte[0])); + if ((MapVirtualKey(virtualKey, 2) & 0x80000000u) != 0) { + // it looks like this character is a dead key but + // MapVirtualKey() will claim it's a dead key even if it's + // not (though i don't think it ever claims it's not when + // it is). we need a backup test to ensure that this is + // really a dead key. we could use ToAscii() for this but + // that keeps state and it's a hassle to restore that state. + // OemKeyScan() appears to do the trick. if the character + // cannot be generated with a single keystroke then it + // returns 0xffffffff. + if (OemKeyScan(multiByte[0]) != 0xffffffffu) { + // character mapped to a dead key but we want the + // character for real so send a space key afterwards. + LOG((CLOG_DEBUG2 "character mapped to dead key")); + Keystroke keystroke; + keystroke.m_virtualKey = VK_SPACE; + keystroke.m_press = true; + keystroke.m_repeat = false; + keys.push_back(keystroke); + keystroke.m_press = false; + keys.push_back(keystroke); + + // ignore the release of this key since we already + // handled it in mapCharacter(). + virtualKey = 0; + } + } return m_mask; } nChars = MultiByteToWideChar(codePage, - MB_COMPOSITE | MB_ERR_INVALID_CHARS, - multiByte, nChars, - unicode, 2); + MB_COMPOSITE | MB_ERR_INVALID_CHARS, + multiByte, nChars, + unicode, 2); if (nChars == 0) { LOG((CLOG_DEBUG2 "KeyID 0x%08x mb->wc mapping failed", id)); return m_mask; } nChars = WideCharToMultiByte(codePage, - 0, - unicode, nChars, - multiByte, sizeof(multiByte), - NULL, &error); + 0, + unicode, nChars, + multiByte, sizeof(multiByte), + NULL, &error); if (nChars == 0 || error) { LOG((CLOG_DEBUG2 "KeyID 0x%08x wc->mb mapping failed", id)); return m_mask; @@ -1240,6 +1267,15 @@ CMSWindowsSecondaryScreen::mapToKeystrokes(Keystrokes& keys, break; } + // if this is a dead key press then send a release immediately. + // the dead key may not be processed correctly if its release + // event comes after we release the modifiers. + if (action == kPress && + (MapVirtualKey(virtualKey, 2) & 0x80000000lu) != 0) { + keystroke.m_press = false; + keys.push_back(keystroke); + } + // add key events to restore the modifier state. apply events in // the reverse order that they're stored in undo. while (!undo.empty()) { diff --git a/lib/platform/CXWindowsSecondaryScreen.cpp b/lib/platform/CXWindowsSecondaryScreen.cpp index 33fa1359..b69369e9 100644 --- a/lib/platform/CXWindowsSecondaryScreen.cpp +++ b/lib/platform/CXWindowsSecondaryScreen.cpp @@ -1829,6 +1829,19 @@ const CXWindowsSecondaryScreen::KeySymsMap& CXWindowsSecondaryScreen::getDecomposedKeySymTable() { static const KeySym s_rawTable[] = { + // non-dead version of dead keys + XK_grave, XK_dead_grave, XK_space, 0, + XK_acute, XK_dead_acute, XK_space, 0, + XK_asciicircum, XK_dead_circumflex, XK_space, 0, + XK_asciitilde, XK_dead_tilde, XK_space, 0, + XK_cedilla, XK_dead_cedilla, XK_space, 0, + XK_ogonek, XK_dead_ogonek, XK_space, 0, + XK_caron, XK_dead_caron, XK_space, 0, + XK_abovedot, XK_dead_abovedot, XK_space, 0, + XK_doubleacute, XK_dead_doubleacute, XK_space, 0, + XK_breve, XK_dead_breve, XK_space, 0, + XK_macron, XK_dead_macron, XK_space, 0, + // Latin-1 (ISO 8859-1) XK_Agrave, XK_dead_grave, XK_A, 0, XK_Aacute, XK_dead_acute, XK_A, 0,