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.
This commit is contained in:
crs 2003-07-17 21:16:58 +00:00
parent 99792b13a5
commit e1985f52c9
2 changed files with 58 additions and 9 deletions

View File

@ -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<UINT>(-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()) {

View File

@ -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,