fix: ctrl+alt+fn issue
This commit is contained in:
committed by
Chris Rizzitello
parent
42b90a2b14
commit
5fc4e9dba6
@ -235,28 +235,49 @@ void EiKeyState::getKeyMap(deskflow::KeyMap &keyMap)
|
||||
if (nsyms > 1)
|
||||
LOG_WARN("multiple keysyms per keycode are not supported, keycode %d", keycode);
|
||||
|
||||
deskflow::KeyMap::KeyItem item{};
|
||||
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
|
||||
char keysymName[128] = {0};
|
||||
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;
|
||||
for (auto n = 0U; n < nmasks; n++) {
|
||||
modSensitive |= masks[n];
|
||||
uint32_t modRequired = 0xFFFFFFFF;
|
||||
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);
|
||||
|
||||
uint32_t modRequired = 0;
|
||||
for (std::size_t m = 0; m < nmasks; m++) {
|
||||
modRequired |= masks[m];
|
||||
}
|
||||
item.m_required = convertModMask(modRequired);
|
||||
|
||||
assignGeneratedModifiers(keycode, item);
|
||||
@ -293,10 +314,23 @@ void EiKeyState::fakeKey(const Keystroke &keystroke)
|
||||
|
||||
KeyID EiKeyState::mapKeyFromKeyval(uint32_t keyval) const
|
||||
{
|
||||
// FIXME: That might be a bit crude...?
|
||||
xkb_keysym_t xkbKeysym = xkb_state_key_get_one_sym(m_xkbState, keyval);
|
||||
auto keysym = static_cast<KeySym>(xkbKeysym);
|
||||
// Get the base keysym from level 0, ignoring current modifiers.
|
||||
// We need this because with newer xkeyboard-config, function keys use CTRL+ALT type,
|
||||
// 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);
|
||||
LOG_DEBUG1("mapped key: code=%d keysym=0x%04lx to keyID=%d", keyval, keysym, keyid);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user