Fixed dead key and AltGr+shift handling on X windows. Also fixed
bug with decomposing characters that have no direct key mapping but do have a direct key mapping for the character with the opposite case.
This commit is contained in:
parent
9f6c8f937a
commit
f65d53d06a
|
@ -95,7 +95,7 @@
|
|||
#if defined(HAVE_X11_XF86KEYSYM_H)
|
||||
static const KeySym g_mapE000[] =
|
||||
{
|
||||
/* 0x00 */ 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
/* 0x00 */ 0, XF86XK_Eject, 0, 0, 0, 0, 0, 0,
|
||||
/* 0x08 */ 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
/* 0x10 */ 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
/* 0x18 */ 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
|
@ -278,6 +278,45 @@ CXWindowsKeyState::mapKey(Keystrokes& keys, KeyID id,
|
|||
|
||||
// get the mapping for this keysym
|
||||
KeySymIndex keyIndex = m_keysymMap.find(keysym);
|
||||
if (keyIndex != m_keysymMap.end()) {
|
||||
// the keysym is mapped to some keycode. create the keystrokes
|
||||
// for this keysym.
|
||||
return mapToKeystrokes(keys, keyIndex, isAutoRepeat);
|
||||
}
|
||||
|
||||
// we can't find the keysym mapped to any keycode. this doesn't
|
||||
// necessarily mean we can't generate the keysym, though. if the
|
||||
// keysym can be created by combining keysyms then we may still
|
||||
// be okay.
|
||||
CXWindowsUtil::KeySyms decomposition;
|
||||
if (CXWindowsUtil::decomposeKeySym(keysym, decomposition)) {
|
||||
LOG((CLOG_DEBUG2 "decomposed keysym 0x%08x into %d keysyms", keysym, decomposition.size()));
|
||||
|
||||
// map each decomposed keysym to keystrokes. we want the mask
|
||||
// and the keycode from the last keysym (which should be the
|
||||
// only non-dead key). the dead keys are not sensitive to
|
||||
// anything but shift and mode switch.
|
||||
KeyButton keycode = 0;
|
||||
for (CXWindowsUtil::KeySyms::const_iterator i = decomposition.begin();
|
||||
i != decomposition.end(); ++i) {
|
||||
// lookup the key
|
||||
keysym = *i;
|
||||
keyIndex = m_keysymMap.find(keysym);
|
||||
if (keyIndex == m_keysymMap.end()) {
|
||||
// missing a required keysym
|
||||
LOG((CLOG_DEBUG2 "can't map keysym %d: 0x%04x", i - decomposition.begin(), keysym));
|
||||
return 0;
|
||||
}
|
||||
|
||||
// the keysym is mapped to some keycode
|
||||
keycode = mapToKeystrokes(keys, keyIndex, isAutoRepeat);
|
||||
if (keycode == 0) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
return keycode;
|
||||
}
|
||||
|
||||
// if the mapping isn't found and keysym is caps lock sensitive
|
||||
// then convert the case of the keysym and try again.
|
||||
|
@ -292,47 +331,14 @@ CXWindowsKeyState::mapKey(Keystrokes& keys, KeyID id,
|
|||
keyIndex = m_keysymMap.find(lKey);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (keyIndex != m_keysymMap.end()) {
|
||||
// the keysym is mapped to some keycode. create the keystrokes
|
||||
// for this keysym.
|
||||
return mapToKeystrokes(keys, keyIndex, isAutoRepeat);
|
||||
}
|
||||
|
||||
// we can't find the keysym mapped to any keycode. this doesn't
|
||||
// necessarily mean we can't generate the keysym, though. if the
|
||||
// keysym can be created by combining keysyms then we may still
|
||||
// be okay.
|
||||
CXWindowsUtil::KeySyms decomposition;
|
||||
if (!CXWindowsUtil::decomposeKeySym(keysym, decomposition)) {
|
||||
return 0;
|
||||
}
|
||||
LOG((CLOG_DEBUG2 "decomposed keysym 0x%08x into %d keysyms", keysym, decomposition.size()));
|
||||
|
||||
// map each decomposed keysym to keystrokes. we want the mask
|
||||
// and the keycode from the last keysym (which should be the
|
||||
// only non-dead key). the dead keys are not sensitive to
|
||||
// anything but shift and mode switch.
|
||||
KeyButton keycode = 0;
|
||||
for (CXWindowsUtil::KeySyms::const_iterator i = decomposition.begin();
|
||||
i != decomposition.end(); ++i) {
|
||||
// lookup the key
|
||||
keysym = *i;
|
||||
keyIndex = m_keysymMap.find(keysym);
|
||||
if (keyIndex == m_keysymMap.end()) {
|
||||
// missing a required keysym
|
||||
return 0;
|
||||
}
|
||||
|
||||
// the keysym is mapped to some keycode
|
||||
keycode = mapToKeystrokes(keys, keyIndex, isAutoRepeat);
|
||||
if (keycode == 0) {
|
||||
return 0;
|
||||
if (keyIndex != m_keysymMap.end()) {
|
||||
// the keysym is mapped to some keycode. create the keystrokes
|
||||
// for this keysym.
|
||||
return mapToKeystrokes(keys, keyIndex, isAutoRepeat);
|
||||
}
|
||||
}
|
||||
|
||||
return keycode;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -794,6 +800,7 @@ CXWindowsKeyState::mapToKeystrokes(Keystrokes& keys,
|
|||
if (isAutoRepeat &&
|
||||
(m_keyControl.auto_repeats[keycode >> 3] &
|
||||
static_cast<char>(1 << (keycode & 7))) == 0) {
|
||||
LOG((CLOG_DEBUG2 "non-autorepeating"));
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -923,24 +930,34 @@ CXWindowsKeyState::adjustModifiers(Keystrokes& keys,
|
|||
// get mode switch set correctly. do this before shift because
|
||||
// mode switch may be sensitive to the shift modifier and will
|
||||
// set/reset it as necessary.
|
||||
const bool wantModeSwitch = ((desiredMask & KeyModifierModeSwitch) != 0);
|
||||
const bool haveModeSwitch = ((currentMask & KeyModifierModeSwitch) != 0);
|
||||
bool forceShift = false;
|
||||
bool wantShift = ((desiredMask & KeyModifierShift) != 0);
|
||||
bool wantModeSwitch = ((desiredMask & KeyModifierModeSwitch) != 0);
|
||||
bool haveModeSwitch = ((currentMask & KeyModifierModeSwitch) != 0);
|
||||
if (wantModeSwitch != haveModeSwitch) {
|
||||
LOG((CLOG_DEBUG2 "fix mode switch"));
|
||||
|
||||
// adjust shift if necessary
|
||||
// adjust shift if necessary (i.e. turn it off it's on and mode
|
||||
// shift is sensitive to the shift key)
|
||||
KeySymIndex modeSwitchIndex = m_keysymMap.find(m_modeSwitchKeysym);
|
||||
assert(modeSwitchIndex != m_keysymMap.end());
|
||||
if (modeSwitchIndex->second.m_shiftSensitive[0]) {
|
||||
const bool wantShift = false;
|
||||
const bool haveShift = ((currentMask & KeyModifierShift) != 0);
|
||||
if (wantShift != haveShift) {
|
||||
bool haveShift = ((currentMask & KeyModifierShift) != 0);
|
||||
if (haveShift) {
|
||||
// add shift keystrokes
|
||||
LOG((CLOG_DEBUG2 "fix shift for mode switch"));
|
||||
if (!mapModifier(keys, undo, KeyModifierShift, wantShift)) {
|
||||
if (!mapModifier(keys, undo, KeyModifierShift, false, true)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// our local concept of shift has flipped
|
||||
currentMask ^= KeyModifierShift;
|
||||
|
||||
// force shift to get turned on below if we had to turn
|
||||
// off here and shift is desired. if we didn't force it
|
||||
// then mapModifier would think shift is already down
|
||||
// and ignore the request.
|
||||
forceShift = wantShift;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -952,12 +969,11 @@ CXWindowsKeyState::adjustModifiers(Keystrokes& keys,
|
|||
}
|
||||
|
||||
// get shift set correctly
|
||||
const bool wantShift = ((desiredMask & KeyModifierShift) != 0);
|
||||
const bool haveShift = ((currentMask & KeyModifierShift) != 0);
|
||||
bool haveShift = ((currentMask & KeyModifierShift) != 0);
|
||||
if (wantShift != haveShift) {
|
||||
// add shift keystrokes
|
||||
LOG((CLOG_DEBUG2 "fix shift"));
|
||||
if (!mapModifier(keys, undo, KeyModifierShift, wantShift)) {
|
||||
if (!mapModifier(keys, undo, KeyModifierShift, wantShift, forceShift)) {
|
||||
return false;
|
||||
}
|
||||
currentMask ^= KeyModifierShift;
|
||||
|
|
|
@ -295,7 +295,7 @@ CKeyState::addModifier(KeyModifierMask modifier, const KeyButtons& buttons)
|
|||
|
||||
bool
|
||||
CKeyState::mapModifier(Keystrokes& keys, Keystrokes& undo,
|
||||
KeyModifierMask mask, bool desireActive) const
|
||||
KeyModifierMask mask, bool desireActive, bool force) const
|
||||
{
|
||||
// look up modifier
|
||||
const KeyButtons& buttons = m_maskToKeys[getIndexForModifier(mask)];
|
||||
|
@ -304,7 +304,7 @@ CKeyState::mapModifier(Keystrokes& keys, Keystrokes& undo,
|
|||
}
|
||||
|
||||
// ignore if already in desired state
|
||||
if (isModifierActive(mask) == desireActive) {
|
||||
if (!force && isModifierActive(mask) == desireActive) {
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
@ -102,16 +102,19 @@ protected:
|
|||
|
||||
//! Get key events to change modifier state
|
||||
/*!
|
||||
Retrieves the key events necessary to activate (\c desireActive is true)
|
||||
or deactivate (\c desireActive is false) the modifier given by \c mask
|
||||
by pushing them onto the back of \c keys. \c mask must specify exactly
|
||||
one modifier. \c undo receives the key events necessary to restore the
|
||||
modifier's previous state. They're pushed onto \c undo in the reverse
|
||||
order they should be executed. Returns true if the modifier can be
|
||||
adjusted, false otherwise.
|
||||
Retrieves the key events necessary to activate (\p desireActive is true)
|
||||
or deactivate (\p desireActive is false) the modifier given by \p mask
|
||||
by pushing them onto the back of \p keys. \p mask must specify exactly
|
||||
one modifier. \p undo receives the key events necessary to restore the
|
||||
modifier's previous state. They're pushed onto \p undo in the reverse
|
||||
order they should be executed. If \p force is false then \p keys and
|
||||
\p undo are only changed if the modifier is not currently in the
|
||||
desired state. If \p force is true then \p keys and \p undo are always
|
||||
changed. Returns true if the modifier can be adjusted, false otherwise.
|
||||
*/
|
||||
bool mapModifier(Keystrokes& keys, Keystrokes& undo,
|
||||
KeyModifierMask mask, bool desireActive) const;
|
||||
KeyModifierMask mask, bool desireActive,
|
||||
bool force = false) const;
|
||||
|
||||
//! Update the key state
|
||||
/*!
|
||||
|
|
Loading…
Reference in New Issue