Checkpoint for improving X11 client key handling. Should prevent
unintentional Pointer_EnableKeys (i.e. generating NumLock press and release around a shift press).
This commit is contained in:
parent
5ca0e026ab
commit
92539f2ccc
|
@ -700,65 +700,120 @@ CXWindowsSecondaryScreen::mapKey(Keystrokes& keys, KeyCode& keycode,
|
||||||
const KeyCodeMask& entry = keyIndex->second;
|
const KeyCodeMask& entry = keyIndex->second;
|
||||||
LOG((CLOG_DEBUG2 "keysym is 0x%08x", keysym));
|
LOG((CLOG_DEBUG2 "keysym is 0x%08x", keysym));
|
||||||
|
|
||||||
|
// note if the key is a modifier
|
||||||
|
unsigned int modifierBit;
|
||||||
|
unsigned int modifierIndex = keySymToModifierIndex(keysym);
|
||||||
|
if (modifierIndex != static_cast<unsigned int>(-1)) {
|
||||||
|
LOG((CLOG_DEBUG2 "keysym is modifier %d", modifierIndex));
|
||||||
|
modifierBit = (1 << modifierIndex);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
modifierBit = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// if the key is a modifier and that modifier is already in the
|
||||||
|
// desired state then ignore the request since there's nothing
|
||||||
|
// to do. never ignore a toggle modifier on press or release,
|
||||||
|
// though.
|
||||||
|
if (modifierBit != 0) {
|
||||||
|
if (action == kRepeat) {
|
||||||
|
LOG((CLOG_DEBUG2 "ignore repeating modifier"));
|
||||||
|
return m_mask;
|
||||||
|
}
|
||||||
|
if (getBits(m_toggleModifierMask, modifierBit) == 0) {
|
||||||
|
if ((action == kPress && (m_mask & modifierBit) != 0) ||
|
||||||
|
(action == kRelease && (m_mask & modifierBit) == 0)) {
|
||||||
|
LOG((CLOG_DEBUG2 "modifier in proper state: 0x%04x", m_mask));
|
||||||
|
return m_mask;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// sensitive notes the modifier keys that affect the synthesized
|
||||||
|
// key event. these modifiers must be in the expected state to
|
||||||
|
// get the correct keysym and we'll only try to match these
|
||||||
|
// modifiers.
|
||||||
|
//
|
||||||
|
// the shift and mode switch keys can modify any keycode. num
|
||||||
|
// lock and caps lock only affect certain keysyms and if a
|
||||||
|
// keysym is affected by num lock it is not affected by caps
|
||||||
|
// lock. no other modifiers have any effect.
|
||||||
|
//
|
||||||
|
// requested notes the modifiers requested by the server and
|
||||||
|
// desired notes the modifier state we ultimately want to match.
|
||||||
|
// only the bits in desired indicated by sensitive are relevant.
|
||||||
|
// we assign the num lock and caps lock bits here if relevant.
|
||||||
|
// we'll assign shift and mode switch later.
|
||||||
|
unsigned int sensitive = ShiftMask | m_modeSwitchMask;
|
||||||
|
unsigned int requested = maskToX(mask);
|
||||||
|
unsigned int desired = 0;
|
||||||
|
if (adjustForNumLock(keysym)) {
|
||||||
|
sensitive |= m_numLockMask;
|
||||||
|
desired = assignBits(desired, m_numLockMask, requested);
|
||||||
|
}
|
||||||
|
else if (adjustForCapsLock(keysym)) {
|
||||||
|
sensitive |= m_capsLockMask;
|
||||||
|
desired = assignBits(desired, m_capsLockMask, requested);
|
||||||
|
}
|
||||||
|
|
||||||
|
// we cannot be sensitive to the modifier we're pressing/releasing
|
||||||
|
sensitive = clearBits(sensitive, modifierBit);
|
||||||
|
|
||||||
// we can choose any of the available keycode/modifier states to
|
// we can choose any of the available keycode/modifier states to
|
||||||
// generate our keysym. the most desireable is the one most
|
// generate our keysym. the most desireable is the one most
|
||||||
// closely matching the input mask. determine the order we
|
// closely matching the current mask. determine the order we
|
||||||
// should try modifier states, from best match to worst. this
|
// should try modifier states, from best match to worst. this
|
||||||
// doesn't concern itself with whether or not a given modifier
|
// doesn't concern itself with whether or not a given modifier
|
||||||
// state has an associated keycode. we'll just skip those later
|
// state has an associated keycode. we'll just skip those later
|
||||||
// if necessary.
|
// if necessary. default is none, shift, mode switch, shift +
|
||||||
|
// mode switch.
|
||||||
// default is none, shift, mode switch, shift + mode switch
|
|
||||||
unsigned int desired = maskToX(mask);
|
|
||||||
unsigned int index[4];
|
unsigned int index[4];
|
||||||
index[0] = 0;
|
index[0] = 0;
|
||||||
index[1] = 1;
|
index[1] = 1;
|
||||||
index[2] = 2;
|
index[2] = 2;
|
||||||
index[3] = 3;
|
index[3] = 3;
|
||||||
|
|
||||||
// if mode switch is active then 2 and 3 are better than 0 and 1
|
|
||||||
if (getBits(desired, m_modeSwitchMask) != 0) {
|
|
||||||
LOG((CLOG_DEBUG2 "mode switch desired"));
|
|
||||||
index[0] ^= 2;
|
|
||||||
index[1] ^= 2;
|
|
||||||
index[2] ^= 2;
|
|
||||||
index[3] ^= 2;
|
|
||||||
}
|
|
||||||
|
|
||||||
// if shift is active then 1 and 3 are better than 0 and 2. however,
|
// if shift is active then 1 and 3 are better than 0 and 2. however,
|
||||||
// if the key is affected by NumLock and NumLock is active then 1 and
|
// if the key is affected by NumLock and NumLock is active then 1 and
|
||||||
// 3 are better if shift is *not* down (because NumLock acts like
|
// 3 are better if shift is *not* down (because NumLock acts like
|
||||||
// shift for those keysyms and shift cancels NumLock). similarly for
|
// shift for those keysyms and shift cancels NumLock). similarly for
|
||||||
// keys affected by CapsLock.
|
// keys affected by CapsLock. none of this is necessary if the key
|
||||||
bool desireShift = (getBits(desired, ShiftMask) != 0);
|
// is itself shift.
|
||||||
bool invertShift = false;
|
bool invertShift = false;
|
||||||
LOG((CLOG_DEBUG2 "desire shift: %s", desireShift ? "yes" : "no"));
|
if (modifierBit != ShiftMask) {
|
||||||
if (adjustForNumLock(keysym)) {
|
bool desireShift = (getBits(m_mask, ShiftMask) != 0);
|
||||||
LOG((CLOG_DEBUG2 "num lock sensitive"));
|
if ((sensitive & m_numLockMask) != 0) {
|
||||||
if (m_numLockMask != 0) {
|
LOG((CLOG_DEBUG2 "num lock sensitive"));
|
||||||
LOG((CLOG_DEBUG2 "we have a num lock"));
|
if (getBits(m_mask, m_numLockMask) != 0) {
|
||||||
if (getBits(desired, m_numLockMask) != 0) {
|
LOG((CLOG_DEBUG2 "num lock preferred, invert shift"));
|
||||||
LOG((CLOG_DEBUG2 "num lock desired, invert shift"));
|
|
||||||
invertShift = true;
|
invertShift = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
else if ((sensitive & m_capsLockMask) != 0) {
|
||||||
else if (adjustForCapsLock(keysym)) {
|
LOG((CLOG_DEBUG2 "caps lock sensitive"));
|
||||||
LOG((CLOG_DEBUG2 "caps lock sensitive"));
|
if (getBits(m_mask, m_capsLockMask) != 0) {
|
||||||
if (m_capsLockMask != 0) {
|
LOG((CLOG_DEBUG2 "caps lock preferred, invert shift"));
|
||||||
LOG((CLOG_DEBUG2 "we have a caps lock"));
|
|
||||||
if (getBits(desired, m_capsLockMask) != 0) {
|
|
||||||
LOG((CLOG_DEBUG2 "caps lock desired, invert shift"));
|
|
||||||
invertShift = true;
|
invertShift = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (desireShift != invertShift) {
|
||||||
|
LOG((CLOG_DEBUG2 "shift preferred"));
|
||||||
|
index[0] ^= 1;
|
||||||
|
index[1] ^= 1;
|
||||||
|
index[2] ^= 1;
|
||||||
|
index[3] ^= 1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (desireShift != invertShift) {
|
|
||||||
LOG((CLOG_DEBUG2 "shift desired"));
|
// if mode switch is active then 2 and 3 are better than 0 and 1,
|
||||||
index[0] ^= 1;
|
// unless the key is itself mode switch.
|
||||||
index[1] ^= 1;
|
if (modifierBit != m_modeSwitchMask &&
|
||||||
index[2] ^= 1;
|
getBits(m_mask, m_modeSwitchMask) != 0) {
|
||||||
index[3] ^= 1;
|
LOG((CLOG_DEBUG2 "mode switch preferred"));
|
||||||
|
index[0] ^= 2;
|
||||||
|
index[1] ^= 2;
|
||||||
|
index[2] ^= 2;
|
||||||
|
index[3] ^= 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
// find the first modifier state with a keycode we can generate.
|
// find the first modifier state with a keycode we can generate.
|
||||||
|
@ -784,37 +839,13 @@ CXWindowsSecondaryScreen::mapKey(Keystrokes& keys, KeyCode& keycode,
|
||||||
keycode = entry.m_keycode[bestIndex];
|
keycode = entry.m_keycode[bestIndex];
|
||||||
LOG((CLOG_DEBUG2 "bestIndex = %d, keycode = %d", bestIndex, keycode));
|
LOG((CLOG_DEBUG2 "bestIndex = %d, keycode = %d", bestIndex, keycode));
|
||||||
|
|
||||||
// note if the key is a modifier
|
// FIXME -- can remove bits from sensitive if keycode doesn't have
|
||||||
ModifierMap::const_iterator modIndex = m_keycodeToModifier.find(keycode);
|
// keysyms mapped to shift and/or mode switch.
|
||||||
unsigned int modifierBit = 0;
|
|
||||||
if (modIndex != m_keycodeToModifier.end()) {
|
|
||||||
LOG((CLOG_DEBUG2 "keysym is modifier %d", modIndex->second));
|
|
||||||
modifierBit = (1 << modIndex->second);
|
|
||||||
}
|
|
||||||
|
|
||||||
// if the key is a modifier and that modifier is already in the
|
|
||||||
// desired state then ignore the request since there's nothing
|
|
||||||
// to do. never ignore a toggle modifier on press or release,
|
|
||||||
// though.
|
|
||||||
if (modifierBit != 0) {
|
|
||||||
if (action == kRepeat) {
|
|
||||||
LOG((CLOG_DEBUG2 "ignore repeating modifier"));
|
|
||||||
return m_mask;
|
|
||||||
}
|
|
||||||
if (getBits(m_toggleModifierMask, modifierBit) == 0) {
|
|
||||||
if ((action == kPress && (m_mask & modifierBit) != 0) ||
|
|
||||||
(action == kRelease && (m_mask & modifierBit) == 0)) {
|
|
||||||
LOG((CLOG_DEBUG2 "modifier in proper state: 0x%04x", m_mask));
|
|
||||||
return m_mask;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// bestIndex tells us if shift and mode switch should be on or off,
|
// bestIndex tells us if shift and mode switch should be on or off,
|
||||||
// except if caps lock or num lock was down then we invert the sense
|
// except if caps lock or num lock was down then we invert the sense
|
||||||
// of bestIndex's lowest bit.
|
// of bestIndex's lowest bit.
|
||||||
// we must match both.
|
// we must match both.
|
||||||
unsigned int required = ShiftMask | m_modeSwitchMask;
|
|
||||||
if (((bestIndex & 1) == 0) != invertShift) {
|
if (((bestIndex & 1) == 0) != invertShift) {
|
||||||
desired = clearBits(desired, ShiftMask);
|
desired = clearBits(desired, ShiftMask);
|
||||||
}
|
}
|
||||||
|
@ -828,28 +859,8 @@ CXWindowsSecondaryScreen::mapKey(Keystrokes& keys, KeyCode& keycode,
|
||||||
desired = setBits(desired, m_modeSwitchMask);
|
desired = setBits(desired, m_modeSwitchMask);
|
||||||
}
|
}
|
||||||
|
|
||||||
// if the key is a modifier then remove it from the desired mask.
|
// we now know what modifiers we want
|
||||||
// we'll be matching the modifiers in the desired mask then adding
|
LOG((CLOG_DEBUG2 "modifiers: sensitive = 0x%04x, desired = 0x%04x, current = 0x%04x", sensitive, desired, m_mask));
|
||||||
// a key press or release for the keysym. if we don't clear the
|
|
||||||
// modifier bit from the desired mask we'll end up dealing with
|
|
||||||
// that key twice, once while matching modifiers and once while
|
|
||||||
// handling the keysym.
|
|
||||||
//
|
|
||||||
// note that instead of clearing the bit, we make it identical to
|
|
||||||
// the same bit in m_mask, meaning it's already in the right state.
|
|
||||||
desired = assignBits(desired, modifierBit, m_mask);
|
|
||||||
required = clearBits(required, modifierBit);
|
|
||||||
LOG((CLOG_DEBUG2 "desired = 0x%04x, current = 0x%04x", desired, m_mask));
|
|
||||||
|
|
||||||
// some modifiers never have an effect on keysym lookup. leave
|
|
||||||
// those modifiers alone by copying their state from m_mask to
|
|
||||||
// desired.
|
|
||||||
desired = assignBits(desired,
|
|
||||||
ControlMask |
|
|
||||||
m_altMask |
|
|
||||||
m_metaMask |
|
|
||||||
m_superMask |
|
|
||||||
m_scrollLockMask, m_mask);
|
|
||||||
|
|
||||||
// add the key events required to get to the modifier state
|
// add the key events required to get to the modifier state
|
||||||
// necessary to generate an event yielding id. also save the
|
// necessary to generate an event yielding id. also save the
|
||||||
|
@ -858,99 +869,100 @@ CXWindowsSecondaryScreen::mapKey(Keystrokes& keys, KeyCode& keycode,
|
||||||
// modify modifiers.
|
// modify modifiers.
|
||||||
Keystrokes undo;
|
Keystrokes undo;
|
||||||
Keystroke keystroke;
|
Keystroke keystroke;
|
||||||
if (desired != m_mask) {
|
for (unsigned int i = 0; i < 8; ++i) {
|
||||||
for (unsigned int i = 0; i < 8; ++i) {
|
// skip modifiers we don't care about
|
||||||
unsigned int bit = (1 << i);
|
unsigned int bit = (1 << i);
|
||||||
if (getBits(desired, bit) != getBits(m_mask, bit)) {
|
if ((bit & sensitive) == 0) {
|
||||||
LOG((CLOG_DEBUG2 "fix modifier %d", i));
|
continue;
|
||||||
// get the keycode we're using for this modifier. if
|
}
|
||||||
// there isn't one then bail if the modifier is required
|
|
||||||
// or ignore it if not required.
|
|
||||||
KeyCode modifierKey = m_modifierToKeycode[i];
|
|
||||||
if (modifierKey == 0) {
|
|
||||||
LOG((CLOG_DEBUG2 "no key mapped to modifier 0x%04x", bit));
|
|
||||||
if (getBits(required, bit) != 0) {
|
|
||||||
keys.clear();
|
|
||||||
return m_mask;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
keystroke.m_keycode = modifierKey;
|
// skip modifiers that are correct
|
||||||
keystroke.m_repeat = false;
|
if (getBits(desired, bit) == getBits(m_mask, bit)) {
|
||||||
if (getBits(desired, bit)) {
|
continue;
|
||||||
// modifier is not active but should be. if the
|
}
|
||||||
// modifier is a toggle then toggle it on with a
|
|
||||||
// press/release, otherwise activate it with a
|
|
||||||
// press. use the first keycode for the modifier.
|
|
||||||
LOG((CLOG_DEBUG2 "modifier 0x%04x is not active", bit));
|
|
||||||
if (getBits(m_toggleModifierMask, bit) != 0) {
|
|
||||||
LOG((CLOG_DEBUG2 "modifier 0x%04x is a toggle", bit));
|
|
||||||
if ((bit == m_capsLockMask && m_capsLockHalfDuplex) ||
|
|
||||||
(bit == m_numLockMask && m_numLockHalfDuplex)) {
|
|
||||||
keystroke.m_press = True;
|
|
||||||
keys.push_back(keystroke);
|
|
||||||
keystroke.m_press = False;
|
|
||||||
undo.push_back(keystroke);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
keystroke.m_press = True;
|
|
||||||
keys.push_back(keystroke);
|
|
||||||
keystroke.m_press = False;
|
|
||||||
keys.push_back(keystroke);
|
|
||||||
undo.push_back(keystroke);
|
|
||||||
keystroke.m_press = True;
|
|
||||||
undo.push_back(keystroke);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
keystroke.m_press = True;
|
|
||||||
keys.push_back(keystroke);
|
|
||||||
keystroke.m_press = False;
|
|
||||||
undo.push_back(keystroke);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
LOG((CLOG_DEBUG2 "fix modifier %d", i));
|
||||||
|
// get the keycode we're using for this modifier. if
|
||||||
|
// there isn't one then bail if the modifier is required
|
||||||
|
// or ignore it if not required.
|
||||||
|
KeyCode modifierKey = m_modifierToKeycode[i];
|
||||||
|
if (modifierKey == 0) {
|
||||||
|
LOG((CLOG_DEBUG2 "no key mapped to modifier 0x%04x", bit));
|
||||||
|
keys.clear();
|
||||||
|
return m_mask;
|
||||||
|
}
|
||||||
|
|
||||||
|
keystroke.m_keycode = modifierKey;
|
||||||
|
keystroke.m_repeat = false;
|
||||||
|
if (getBits(desired, bit)) {
|
||||||
|
// modifier is not active but should be. if the
|
||||||
|
// modifier is a toggle then toggle it on with a
|
||||||
|
// press/release, otherwise activate it with a
|
||||||
|
// press. use the first keycode for the modifier.
|
||||||
|
LOG((CLOG_DEBUG2 "modifier 0x%04x is not active but should be", bit));
|
||||||
|
if (getBits(m_toggleModifierMask, bit) != 0) {
|
||||||
|
LOG((CLOG_DEBUG2 "modifier 0x%04x is a toggle", bit));
|
||||||
|
if ((bit == m_capsLockMask && m_capsLockHalfDuplex) ||
|
||||||
|
(bit == m_numLockMask && m_numLockHalfDuplex)) {
|
||||||
|
keystroke.m_press = True;
|
||||||
|
keys.push_back(keystroke);
|
||||||
|
keystroke.m_press = False;
|
||||||
|
undo.push_back(keystroke);
|
||||||
|
}
|
||||||
else {
|
else {
|
||||||
// modifier is active but should not be. if the
|
keystroke.m_press = True;
|
||||||
// modifier is a toggle then toggle it off with a
|
keys.push_back(keystroke);
|
||||||
// press/release, otherwise deactivate it with a
|
keystroke.m_press = False;
|
||||||
// release. we must check each keycode for the
|
keys.push_back(keystroke);
|
||||||
// modifier if not a toggle.
|
undo.push_back(keystroke);
|
||||||
LOG((CLOG_DEBUG2 "modifier 0x%04x is active", bit));
|
keystroke.m_press = True;
|
||||||
if (getBits(m_toggleModifierMask, bit) != 0) {
|
undo.push_back(keystroke);
|
||||||
LOG((CLOG_DEBUG2 "modifier 0x%04x is a toggle", bit));
|
}
|
||||||
if ((bit == m_capsLockMask && m_capsLockHalfDuplex) ||
|
}
|
||||||
(bit == m_numLockMask && m_numLockHalfDuplex)) {
|
else {
|
||||||
keystroke.m_press = False;
|
keystroke.m_press = True;
|
||||||
keys.push_back(keystroke);
|
keys.push_back(keystroke);
|
||||||
keystroke.m_press = True;
|
keystroke.m_press = False;
|
||||||
undo.push_back(keystroke);
|
undo.push_back(keystroke);
|
||||||
}
|
}
|
||||||
else {
|
}
|
||||||
keystroke.m_press = True;
|
|
||||||
keys.push_back(keystroke);
|
else {
|
||||||
keystroke.m_press = False;
|
// modifier is active but should not be. if the
|
||||||
keys.push_back(keystroke);
|
// modifier is a toggle then toggle it off with a
|
||||||
undo.push_back(keystroke);
|
// press/release, otherwise deactivate it with a
|
||||||
keystroke.m_press = True;
|
// release. we must check each keycode for the
|
||||||
undo.push_back(keystroke);
|
// modifier if not a toggle.
|
||||||
}
|
LOG((CLOG_DEBUG2 "modifier 0x%04x is active", bit));
|
||||||
}
|
if (getBits(m_toggleModifierMask, bit) != 0) {
|
||||||
else {
|
LOG((CLOG_DEBUG2 "modifier 0x%04x is a toggle", bit));
|
||||||
for (unsigned int j = 0; j < m_keysPerModifier; ++j) {
|
if ((bit == m_capsLockMask && m_capsLockHalfDuplex) ||
|
||||||
const KeyCode key =
|
(bit == m_numLockMask && m_numLockHalfDuplex)) {
|
||||||
m_modifierToKeycodes[i * m_keysPerModifier + j];
|
keystroke.m_press = False;
|
||||||
if (key != 0 && m_keys[key]) {
|
keys.push_back(keystroke);
|
||||||
keystroke.m_keycode = key;
|
keystroke.m_press = True;
|
||||||
keystroke.m_press = False;
|
undo.push_back(keystroke);
|
||||||
keys.push_back(keystroke);
|
}
|
||||||
keystroke.m_press = True;
|
else {
|
||||||
undo.push_back(keystroke);
|
keystroke.m_press = True;
|
||||||
}
|
keys.push_back(keystroke);
|
||||||
}
|
keystroke.m_press = False;
|
||||||
|
keys.push_back(keystroke);
|
||||||
|
undo.push_back(keystroke);
|
||||||
|
keystroke.m_press = True;
|
||||||
|
undo.push_back(keystroke);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
for (unsigned int j = 0; j < m_keysPerModifier; ++j) {
|
||||||
|
const KeyCode key =
|
||||||
|
m_modifierToKeycodes[i * m_keysPerModifier + j];
|
||||||
|
if (key != 0 && m_keys[key]) {
|
||||||
|
keystroke.m_keycode = key;
|
||||||
|
keystroke.m_press = False;
|
||||||
|
keys.push_back(keystroke);
|
||||||
|
keystroke.m_press = True;
|
||||||
|
undo.push_back(keystroke);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1016,7 +1028,7 @@ CXWindowsSecondaryScreen::mapKey(Keystrokes& keys, KeyCode& keycode,
|
||||||
// scan those keys to see if any (except keycode) are pressed.
|
// scan those keys to see if any (except keycode) are pressed.
|
||||||
bool down = false;
|
bool down = false;
|
||||||
for (unsigned int j = 0; !down && j < m_keysPerModifier; ++j) {
|
for (unsigned int j = 0; !down && j < m_keysPerModifier; ++j) {
|
||||||
KeyCode modKeycode = m_modifierToKeycodes[modIndex->second *
|
KeyCode modKeycode = m_modifierToKeycodes[modifierIndex *
|
||||||
m_keysPerModifier + j];
|
m_keysPerModifier + j];
|
||||||
if (modKeycode != 0 && modKeycode != keycode) {
|
if (modKeycode != 0 && modKeycode != keycode) {
|
||||||
down = m_keys[modKeycode];
|
down = m_keys[modKeycode];
|
||||||
|
@ -1026,9 +1038,9 @@ CXWindowsSecondaryScreen::mapKey(Keystrokes& keys, KeyCode& keycode,
|
||||||
mask = clearBits(mask, modifierBit);
|
mask = clearBits(mask, modifierBit);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
LOG((CLOG_DEBUG2 "new mask: 0x%04x", mask));
|
||||||
}
|
}
|
||||||
|
|
||||||
LOG((CLOG_DEBUG2 "final mask: 0x%04x", mask));
|
|
||||||
return mask;
|
return mask;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1307,26 +1319,6 @@ CXWindowsSecondaryScreen::updateKeycodeMap(Display* display)
|
||||||
XFree(keysyms);
|
XFree(keysyms);
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned int
|
|
||||||
CXWindowsSecondaryScreen::indexToModifierMask(int index) const
|
|
||||||
{
|
|
||||||
assert(index >= 0 && index <= 3);
|
|
||||||
|
|
||||||
switch (index) {
|
|
||||||
case 0:
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
case 1:
|
|
||||||
return ShiftMask | LockMask;
|
|
||||||
|
|
||||||
case 2:
|
|
||||||
return m_modeSwitchMask;
|
|
||||||
|
|
||||||
case 3:
|
|
||||||
return ShiftMask | LockMask | m_modeSwitchMask;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
void
|
||||||
CXWindowsSecondaryScreen::updateModifierMap(Display* display)
|
CXWindowsSecondaryScreen::updateModifierMap(Display* display)
|
||||||
{
|
{
|
||||||
|
@ -1343,6 +1335,13 @@ CXWindowsSecondaryScreen::updateModifierMap(Display* display)
|
||||||
m_numLockMask = 0;
|
m_numLockMask = 0;
|
||||||
m_capsLockMask = 0;
|
m_capsLockMask = 0;
|
||||||
m_scrollLockMask = 0;
|
m_scrollLockMask = 0;
|
||||||
|
m_altIndex = static_cast<unsigned int>(-1);
|
||||||
|
m_metaIndex = static_cast<unsigned int>(-1);
|
||||||
|
m_superIndex = static_cast<unsigned int>(-1);
|
||||||
|
m_modeSwitchIndex = static_cast<unsigned int>(-1);
|
||||||
|
m_numLockIndex = static_cast<unsigned int>(-1);
|
||||||
|
m_capsLockIndex = static_cast<unsigned int>(-1);
|
||||||
|
m_scrollLockIndex = static_cast<unsigned int>(-1);
|
||||||
m_keysPerModifier = keymap->max_keypermod;
|
m_keysPerModifier = keymap->max_keypermod;
|
||||||
m_modifierToKeycode.clear();
|
m_modifierToKeycode.clear();
|
||||||
m_modifierToKeycode.resize(8);
|
m_modifierToKeycode.resize(8);
|
||||||
|
@ -1368,9 +1367,6 @@ CXWindowsSecondaryScreen::updateModifierMap(Display* display)
|
||||||
m_modifierToKeycode[i] = keycode;
|
m_modifierToKeycode[i] = keycode;
|
||||||
}
|
}
|
||||||
|
|
||||||
// save in keycode to modifier
|
|
||||||
m_keycodeToModifier.insert(std::make_pair(keycode, i));
|
|
||||||
|
|
||||||
// save bit in all-modifiers mask
|
// save bit in all-modifiers mask
|
||||||
m_modifierMask |= bit;
|
m_modifierMask |= bit;
|
||||||
|
|
||||||
|
@ -1384,33 +1380,41 @@ CXWindowsSecondaryScreen::updateModifierMap(Display* display)
|
||||||
switch (keysym) {
|
switch (keysym) {
|
||||||
case XK_Alt_L:
|
case XK_Alt_L:
|
||||||
case XK_Alt_R:
|
case XK_Alt_R:
|
||||||
|
m_altIndex = i;
|
||||||
m_altMask |= bit;
|
m_altMask |= bit;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case XK_Meta_L:
|
case XK_Meta_L:
|
||||||
case XK_Meta_R:
|
case XK_Meta_R:
|
||||||
|
m_metaIndex = i;
|
||||||
m_metaMask |= bit;
|
m_metaMask |= bit;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case XK_Super_L:
|
case XK_Super_L:
|
||||||
case XK_Super_R:
|
case XK_Super_R:
|
||||||
|
m_superIndex = i;
|
||||||
m_superMask |= bit;
|
m_superMask |= bit;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case XK_Mode_switch:
|
case XK_Mode_switch:
|
||||||
|
m_modeSwitchIndex = i;
|
||||||
m_modeSwitchMask |= bit;
|
m_modeSwitchMask |= bit;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case XK_Num_Lock:
|
case XK_Num_Lock:
|
||||||
|
m_numLockIndex = i;
|
||||||
m_numLockMask |= bit;
|
m_numLockMask |= bit;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case XK_Caps_Lock:
|
case XK_Caps_Lock:
|
||||||
|
m_capsLockIndex = i;
|
||||||
m_capsLockMask |= bit;
|
m_capsLockMask |= bit;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case XK_Scroll_Lock:
|
case XK_Scroll_Lock:
|
||||||
|
m_scrollLockIndex = i;
|
||||||
m_scrollLockMask |= bit;
|
m_scrollLockMask |= bit;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1418,6 +1422,46 @@ CXWindowsSecondaryScreen::updateModifierMap(Display* display)
|
||||||
XFreeModifiermap(keymap);
|
XFreeModifiermap(keymap);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
unsigned int
|
||||||
|
CXWindowsSecondaryScreen::keySymToModifierIndex(KeySym keysym) const
|
||||||
|
{
|
||||||
|
switch (keysym) {
|
||||||
|
case XK_Shift_L:
|
||||||
|
case XK_Shift_R:
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
case XK_Control_L:
|
||||||
|
case XK_Control_R:
|
||||||
|
return 2;
|
||||||
|
|
||||||
|
case XK_Alt_L:
|
||||||
|
case XK_Alt_R:
|
||||||
|
return m_altIndex;
|
||||||
|
|
||||||
|
case XK_Meta_L:
|
||||||
|
case XK_Meta_R:
|
||||||
|
return m_metaIndex;
|
||||||
|
|
||||||
|
case XK_Super_L:
|
||||||
|
case XK_Super_R:
|
||||||
|
return m_superIndex;
|
||||||
|
|
||||||
|
case XK_Mode_switch:
|
||||||
|
return m_modeSwitchIndex;
|
||||||
|
|
||||||
|
case XK_Num_Lock:
|
||||||
|
return m_numLockIndex;
|
||||||
|
|
||||||
|
case XK_Caps_Lock:
|
||||||
|
return m_capsLockIndex;
|
||||||
|
|
||||||
|
case XK_Scroll_Lock:
|
||||||
|
return m_scrollLockIndex;
|
||||||
|
}
|
||||||
|
|
||||||
|
return static_cast<unsigned int>(-1);
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
CXWindowsSecondaryScreen::toggleKey(Display* display,
|
CXWindowsSecondaryScreen::toggleKey(Display* display,
|
||||||
KeySym keysym, unsigned int mask)
|
KeySym keysym, unsigned int mask)
|
||||||
|
|
|
@ -93,7 +93,6 @@ private:
|
||||||
typedef std::vector<KeyCode> KeyCodes;
|
typedef std::vector<KeyCode> KeyCodes;
|
||||||
typedef std::map<KeySym, KeyCodeMask> KeyCodeMap;
|
typedef std::map<KeySym, KeyCodeMask> KeyCodeMap;
|
||||||
typedef KeyCodeMap::const_iterator KeyCodeIndex;
|
typedef KeyCodeMap::const_iterator KeyCodeIndex;
|
||||||
typedef std::map<KeyCode, unsigned int> ModifierMap;
|
|
||||||
typedef std::map<KeyButton, KeyCode> ServerKeyMap;
|
typedef std::map<KeyButton, KeyCode> ServerKeyMap;
|
||||||
|
|
||||||
unsigned int mapButton(ButtonID button) const;
|
unsigned int mapButton(ButtonID button) const;
|
||||||
|
@ -108,7 +107,7 @@ private:
|
||||||
void updateKeycodeMap(Display* display);
|
void updateKeycodeMap(Display* display);
|
||||||
void updateModifiers(Display* display);
|
void updateModifiers(Display* display);
|
||||||
void updateModifierMap(Display* display);
|
void updateModifierMap(Display* display);
|
||||||
unsigned int indexToModifierMask(int index) const;
|
unsigned int keySymToModifierIndex(KeySym) const;
|
||||||
void toggleKey(Display*, KeySym, unsigned int mask);
|
void toggleKey(Display*, KeySym, unsigned int mask);
|
||||||
static bool isToggleKeysym(KeySym);
|
static bool isToggleKeysym(KeySym);
|
||||||
|
|
||||||
|
@ -162,14 +161,20 @@ private:
|
||||||
unsigned int m_capsLockMask;
|
unsigned int m_capsLockMask;
|
||||||
unsigned int m_scrollLockMask;
|
unsigned int m_scrollLockMask;
|
||||||
|
|
||||||
|
// modifier indices
|
||||||
|
unsigned int m_altIndex;
|
||||||
|
unsigned int m_metaIndex;
|
||||||
|
unsigned int m_superIndex;
|
||||||
|
unsigned int m_modeSwitchIndex;
|
||||||
|
unsigned int m_numLockIndex;
|
||||||
|
unsigned int m_capsLockIndex;
|
||||||
|
unsigned int m_scrollLockIndex;
|
||||||
|
|
||||||
// map X modifier key indices to the key codes bound to them
|
// map X modifier key indices to the key codes bound to them
|
||||||
unsigned int m_keysPerModifier;
|
unsigned int m_keysPerModifier;
|
||||||
KeyCodes m_modifierToKeycode;
|
KeyCodes m_modifierToKeycode;
|
||||||
KeyCodes m_modifierToKeycodes;
|
KeyCodes m_modifierToKeycodes;
|
||||||
|
|
||||||
// maps keycodes to modifier indices
|
|
||||||
ModifierMap m_keycodeToModifier;
|
|
||||||
|
|
||||||
// map server key buttons to local keycodes
|
// map server key buttons to local keycodes
|
||||||
ServerKeyMap m_serverKeyMap;
|
ServerKeyMap m_serverKeyMap;
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue