| 113 | } |
| 114 | |
| 115 | std::uint32_t EiKeyState::convertModMask(xkb_mod_mask_t xkbModMaskIn) const |
| 116 | { |
| 117 | // This is our own modifier mask, not xkb's. |
| 118 | std::uint32_t modMaskOut = 0; |
| 119 | |
| 120 | for (xkb_mod_index_t xkbModIdx = 0; xkbModIdx < xkb_keymap_num_mods(m_xkbKeymap); xkbModIdx++) { |
| 121 | const char *name = xkb_keymap_mod_get_name(m_xkbKeymap, xkbModIdx); |
| 122 | |
| 123 | #ifdef HAVE_XKB_KEYMAP_MOD_GET_MASK |
| 124 | // Available since xkbcommon v1.10 |
| 125 | // Note: xkb_keymap_mod_get_mask2 was added in v1.11 which accepts xkb_mod_index_t. |
| 126 | const auto xkbModMask = xkb_keymap_mod_get_mask(m_xkbKeymap, name); |
| 127 | #else |
| 128 | // HACK: in older xkbcommon we need to create the mask manually from the index. |
| 129 | const xkb_mod_mask_t xkbModMask = (1 << xkbModIdx); |
| 130 | #endif |
| 131 | |
| 132 | // Skip modifiers that have no XKB mask (not mapped to any real modifier) |
| 133 | // or are inactive. Without the xkbModMask == 0 check, modifiers with mask 0 |
| 134 | // incorrectly pass the test (0 & 0 == 0) and get processed as "active". |
| 135 | if (xkbModMask == 0 || (xkbModMaskIn & xkbModMask) != xkbModMask) |
| 136 | continue; |
| 137 | |
| 138 | /* added in libxkbcommon 1.8.0 in the same commit so we have all or none */ |
| 139 | #ifndef XKB_VMOD_NAME_ALT |
| 140 | static const auto XKB_VMOD_NAME_ALT = "Alt"; |
| 141 | static const auto XKB_VMOD_NAME_LEVEL3 = "LevelThree"; |
| 142 | static const auto XKB_VMOD_NAME_LEVEL5 = "LevelFive"; |
| 143 | static const auto XKB_VMOD_NAME_META = "Meta"; |
| 144 | static const auto XKB_VMOD_NAME_NUM = "NumLock"; |
| 145 | static const auto XKB_VMOD_NAME_SCROLL = "ScrollLock"; |
| 146 | static const auto XKB_VMOD_NAME_SUPER = "Super"; |
| 147 | static const auto XKB_VMOD_NAME_HYPER = "Hyper"; |
| 148 | static const auto XKB_MOD_NAME_MOD2 = "Mod2"; |
| 149 | static const auto XKB_MOD_NAME_MOD3 = "Mod3"; |
| 150 | static const auto XKB_MOD_NAME_MOD5 = "Mod5"; |
| 151 | #endif |
| 152 | |
| 153 | // From wismill (xkbcommon maintainer): |
| 154 | // Meta is usually encoded like Alt, i.e. to Mod1. In that case, both share the same state. |
| 155 | // Added to that, if KDE interprets Meta as Super (the logo key), then it might explain the mess. |
| 156 | |
| 157 | if (strcmp(XKB_MOD_NAME_SHIFT, name) == 0) |
| 158 | modMaskOut |= (1 << kKeyModifierBitShift); |
| 159 | else if (strcmp(XKB_MOD_NAME_CAPS, name) == 0) |
| 160 | modMaskOut |= (1 << kKeyModifierBitCapsLock); |
| 161 | else if (strcmp(XKB_MOD_NAME_CTRL, name) == 0) |
| 162 | modMaskOut |= (1 << kKeyModifierBitControl); |
| 163 | else if (strcmp(XKB_MOD_NAME_ALT, name) == 0 || strcmp(XKB_VMOD_NAME_ALT, name) == 0) |
| 164 | modMaskOut |= (1 << kKeyModifierBitAlt); |
| 165 | else if (strcmp(XKB_MOD_NAME_LOGO, name) == 0 || // aka windows/command key |
| 166 | strcmp(XKB_VMOD_NAME_SUPER, name) == 0 || // virtual; usually mapped to logo key |
| 167 | strcmp(XKB_VMOD_NAME_HYPER, name) == 0) // virtual; often mapped to caps lock key |
| 168 | modMaskOut |= (1 << kKeyModifierBitSuper); |
| 169 | else if (strcmp(XKB_MOD_NAME_MOD5, name) == 0 || strcmp(XKB_VMOD_NAME_LEVEL3, name) == 0) |
| 170 | modMaskOut |= (1 << kKeyModifierBitAltGr); |
| 171 | else if (strcmp(XKB_VMOD_NAME_LEVEL5, name) == 0) |
| 172 | modMaskOut |= (1 << kKeyModifierBitLevel5Lock); |
nothing calls this directly
no outgoing calls
no test coverage detected