| 790 | } |
| 791 | |
| 792 | bool XWindowsKeyState::hasModifiersXKB() const |
| 793 | { |
| 794 | #if HAVE_XKB_EXTENSION |
| 795 | // iterate over all keycodes |
| 796 | for (int i = m_xkb->min_key_code; i <= m_xkb->max_key_code; ++i) { |
| 797 | auto keycode = static_cast<KeyCode>(i); |
| 798 | if (XkbKeyHasActions(m_xkb, keycode) == True) { |
| 799 | // iterate over all groups |
| 800 | int numGroups = XkbKeyNumGroups(m_xkb, keycode); |
| 801 | for (int group = 0; group < numGroups; ++group) { |
| 802 | // iterate over all shift levels for the button (including none) |
| 803 | const XkbKeyTypePtr type = XkbKeyKeyType(m_xkb, keycode, group); |
| 804 | for (int j = -1; j < type->map_count; ++j) { |
| 805 | if (j != -1 && !type->map[j].active) { |
| 806 | continue; |
| 807 | } |
| 808 | int level = ((j == -1) ? 0 : type->map[j].level); |
| 809 | const XkbAction *action = XkbKeyActionEntry(m_xkb, keycode, level, group); |
| 810 | if (action->type == XkbSA_SetMods || action->type == XkbSA_LockMods) { |
| 811 | return true; |
| 812 | } |
| 813 | } |
| 814 | } |
| 815 | } |
| 816 | } |
| 817 | #endif |
| 818 | return false; |
| 819 | } |
| 820 | |
| 821 | int XWindowsKeyState::getEffectiveGroup(KeyCode keycode, int group) const |
| 822 | { |
nothing calls this directly
no outgoing calls
no test coverage detected