fix: ctrl+alt+fn issue
This commit is contained in:
parent
42b90a2b14
commit
5fc4e9dba6
1 changed files with 50 additions and 16 deletions
|
|
@ -235,28 +235,49 @@ void EiKeyState::getKeyMap(deskflow::KeyMap &keyMap)
|
||||||
if (nsyms > 1)
|
if (nsyms > 1)
|
||||||
LOG_WARN("multiple keysyms per keycode are not supported, keycode %d", keycode);
|
LOG_WARN("multiple keysyms per keycode are not supported, keycode %d", keycode);
|
||||||
|
|
||||||
deskflow::KeyMap::KeyItem item{};
|
|
||||||
xkb_keysym_t keysym = syms[0];
|
xkb_keysym_t keysym = syms[0];
|
||||||
KeySym sym = keysym;
|
|
||||||
item.m_id = XWindowsUtil::mapKeySymToKeyID(sym);
|
|
||||||
item.m_button = static_cast<KeyButton>(keycode) - 8; // X keycode offset
|
|
||||||
item.m_group = group;
|
|
||||||
|
|
||||||
// For debugging only
|
// For debugging only
|
||||||
char keysymName[128] = {0};
|
char keysymName[128] = {0};
|
||||||
xkb_keysym_get_name(keysym, keysymName, sizeof(keysymName));
|
xkb_keysym_get_name(keysym, keysymName, sizeof(keysymName));
|
||||||
|
|
||||||
// Set to all modifiers this key may be affected by
|
// Skip XF86_Switch_VT_* keysyms - these are local VT switching actions
|
||||||
|
// that shouldn't be sent over the network. They appear in newer
|
||||||
|
// xkeyboard-config on level 5 of function keys with CTRL+ALT type.
|
||||||
|
if (strncmp(keysymName, "XF86_Switch_VT_", 15) == 0) {
|
||||||
|
LOG_DEBUG2("skipping VT switch keysym %s for keycode %d", keysymName, keycode);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
deskflow::KeyMap::KeyItem item{};
|
||||||
|
KeySym sym = keysym;
|
||||||
|
item.m_id = XWindowsUtil::mapKeySymToKeyID(sym);
|
||||||
|
item.m_button = static_cast<KeyButton>(keycode) - 8; // X keycode offset
|
||||||
|
item.m_group = group;
|
||||||
|
|
||||||
|
// xkb_keymap_key_get_mods_for_level() returns ALL modifier combinations
|
||||||
|
// that lead to this level. For example, with CTRL+ALT type, Level1 (F1) can
|
||||||
|
// be accessed via None, Control, or Alt. We want the SIMPLEST (fewest bits)
|
||||||
|
// combination, not the OR of all combinations.
|
||||||
|
//
|
||||||
|
// For modSensitive, we only OR modifiers from this level, not all levels.
|
||||||
|
// This prevents marking F1 as sensitive to Ctrl+Alt just because Level5
|
||||||
|
// (which we skip) uses those modifiers.
|
||||||
uint32_t modSensitive = 0;
|
uint32_t modSensitive = 0;
|
||||||
for (auto n = 0U; n < nmasks; n++) {
|
uint32_t modRequired = 0xFFFFFFFF;
|
||||||
modSensitive |= masks[n];
|
int minBits = 32;
|
||||||
|
for (std::size_t m = 0; m < nmasks; m++) {
|
||||||
|
modSensitive |= masks[m];
|
||||||
|
int bits = __builtin_popcount(masks[m]);
|
||||||
|
if (bits < minBits) {
|
||||||
|
minBits = bits;
|
||||||
|
modRequired = masks[m];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (modRequired == 0xFFFFFFFF) {
|
||||||
|
modRequired = 0; // No masks found, use no modifiers
|
||||||
}
|
}
|
||||||
item.m_sensitive = convertModMask(modSensitive);
|
item.m_sensitive = convertModMask(modSensitive);
|
||||||
|
|
||||||
uint32_t modRequired = 0;
|
|
||||||
for (std::size_t m = 0; m < nmasks; m++) {
|
|
||||||
modRequired |= masks[m];
|
|
||||||
}
|
|
||||||
item.m_required = convertModMask(modRequired);
|
item.m_required = convertModMask(modRequired);
|
||||||
|
|
||||||
assignGeneratedModifiers(keycode, item);
|
assignGeneratedModifiers(keycode, item);
|
||||||
|
|
@ -293,10 +314,23 @@ void EiKeyState::fakeKey(const Keystroke &keystroke)
|
||||||
|
|
||||||
KeyID EiKeyState::mapKeyFromKeyval(uint32_t keyval) const
|
KeyID EiKeyState::mapKeyFromKeyval(uint32_t keyval) const
|
||||||
{
|
{
|
||||||
// FIXME: That might be a bit crude...?
|
// Get the base keysym from level 0, ignoring current modifiers.
|
||||||
xkb_keysym_t xkbKeysym = xkb_state_key_get_one_sym(m_xkbState, keyval);
|
// We need this because with newer xkeyboard-config, function keys use CTRL+ALT type,
|
||||||
auto keysym = static_cast<KeySym>(xkbKeysym);
|
// and xkb_state_key_get_one_sym() would return XF86_Switch_VT_* when Ctrl+Alt are
|
||||||
|
// pressed, instead of F1. We want to send F1 + modifiers to the server, not the
|
||||||
|
// VT switch action.
|
||||||
|
const xkb_keysym_t *syms;
|
||||||
|
int nsyms = xkb_keymap_key_get_syms_by_level(m_xkbKeymap, keyval, 0, 0, &syms);
|
||||||
|
|
||||||
|
xkb_keysym_t xkbKeysym;
|
||||||
|
if (nsyms > 0) {
|
||||||
|
xkbKeysym = syms[0];
|
||||||
|
} else {
|
||||||
|
// Fallback to state-based lookup if level 0 has no symbols
|
||||||
|
xkbKeysym = xkb_state_key_get_one_sym(m_xkbState, keyval);
|
||||||
|
}
|
||||||
|
|
||||||
|
auto keysym = static_cast<KeySym>(xkbKeysym);
|
||||||
KeyID keyid = XWindowsUtil::mapKeySymToKeyID(keysym);
|
KeyID keyid = XWindowsUtil::mapKeySymToKeyID(keysym);
|
||||||
LOG_DEBUG1("mapped key: code=%d keysym=0x%04lx to keyID=%d", keyval, keysym, keyid);
|
LOG_DEBUG1("mapped key: code=%d keysym=0x%04lx to keyID=%d", keyval, keysym, keyid);
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue