File indexing completed on 2024-05-26 04:30:15
0001 /* 0002 * SPDX-FileCopyrightText: 2013 Dmitry Kazakov <dimula73@gmail.com> 0003 * 0004 * SPDX-License-Identifier: GPL-2.0-or-later 0005 */ 0006 0007 #include "kis_extended_modifiers_mapper.h" 0008 0009 #include <QApplication> 0010 #include <QKeyEvent> 0011 #include "kis_debug.h" 0012 0013 #ifdef Q_OS_MACOS 0014 0015 #include "kis_extended_modifiers_mapper_osx.h" 0016 0017 #endif /* Q_OS_MACOS */ 0018 0019 #ifdef Q_OS_WIN 0020 0021 #include <windows.h> 0022 #include <commctrl.h> 0023 #include <winuser.h> 0024 0025 #include "krita_container_utils.h" 0026 0027 0028 QVector<Qt::Key> queryPressedKeysWin() 0029 { 0030 QVector<Qt::Key> result; 0031 BYTE vkeys[256]; 0032 0033 if (GetKeyboardState(vkeys)) { 0034 for (int i = 0; i < 256; i++) { 0035 if (vkeys[i] & 0x80) { 0036 if (i == VK_SHIFT) { 0037 result << Qt::Key_Shift; 0038 } else if (i == VK_CONTROL) { 0039 result << Qt::Key_Control; 0040 } else if (i == VK_MENU) { 0041 result << Qt::Key_Alt; 0042 } else if (i == VK_LWIN || i == VK_RWIN) { 0043 result << Qt::Key_Meta; 0044 } else if (i == VK_SPACE) { 0045 result << Qt::Key_Space; 0046 } else if (i >= 0x30 && i <= 0x39) { 0047 result << static_cast<Qt::Key>(Qt::Key_0 + i - 0x30); 0048 } else if (i >= 0x41 && i <= 0x5A) { 0049 result << static_cast<Qt::Key>(Qt::Key_A + i - 0x41); 0050 } else if (i >= 0x60 && i <= 0x69) { 0051 result << static_cast<Qt::Key>(Qt::Key_0 + i - 0x60); 0052 } else if (i >= 0x70 && i <= 0x87) { 0053 result << static_cast<Qt::Key>(Qt::Key_F1 + i - 0x70); 0054 } 0055 } 0056 } 0057 } 0058 0059 KritaUtils::makeContainerUnique(result); 0060 0061 return result; 0062 } 0063 0064 #elif defined HAVE_X11 0065 0066 #include <QX11Info> 0067 #include <X11/X.h> 0068 #include <X11/Xlib.h> 0069 #include <X11/keysym.h> 0070 #include <krita_container_utils.h> 0071 #include <X11/XKBlib.h> 0072 0073 struct KeyMapping { 0074 KeyMapping() {} 0075 KeyMapping(KeySym sym, Qt::Key key) : x11KeySym(sym), qtKey(key) {} 0076 KeySym x11KeySym {0}; 0077 Qt::Key qtKey {Qt::Key_unknown}; 0078 }; 0079 0080 #endif /* HAVE_X11 */ 0081 0082 struct KisExtendedModifiersMapper::Private 0083 { 0084 Private(); 0085 0086 #ifdef HAVE_X11 0087 0088 QVector<KeyMapping> mapping; 0089 char keysState[32]; 0090 int minKeyCode = 0; 0091 int maxKeyCode = 0; 0092 0093 bool checkKeyCodePressedX11(KeyCode key); 0094 bool checkKeySymPressedX11(KeySym sym); 0095 #endif /* HAVE_X11 */ 0096 }; 0097 0098 #ifdef HAVE_X11 0099 0100 KisExtendedModifiersMapper::Private::Private() 0101 { 0102 XDisplayKeycodes(QX11Info::display(), &minKeyCode, &maxKeyCode); 0103 XQueryKeymap(QX11Info::display(), keysState); 0104 0105 mapping.append(KeyMapping(XK_Shift_L, Qt::Key_Shift)); 0106 mapping.append(KeyMapping(XK_Shift_R, Qt::Key_Shift)); 0107 0108 mapping.append(KeyMapping(XK_Control_L, Qt::Key_Control)); 0109 mapping.append(KeyMapping(XK_Control_R, Qt::Key_Control)); 0110 0111 mapping.append(KeyMapping(XK_Meta_L, Qt::Key_Alt)); 0112 mapping.append(KeyMapping(XK_Meta_R, Qt::Key_Alt)); 0113 mapping.append(KeyMapping(XK_Mode_switch, Qt::Key_AltGr)); 0114 mapping.append(KeyMapping(XK_ISO_Level3_Shift, Qt::Key_AltGr)); 0115 0116 mapping.append(KeyMapping(XK_Alt_L, Qt::Key_Alt)); 0117 mapping.append(KeyMapping(XK_Alt_R, Qt::Key_Alt)); 0118 0119 mapping.append(KeyMapping(XK_Super_L, Qt::Key_Meta)); 0120 mapping.append(KeyMapping(XK_Super_R, Qt::Key_Meta)); 0121 0122 mapping.append(KeyMapping(XK_Hyper_L, Qt::Key_Hyper_L)); 0123 mapping.append(KeyMapping(XK_Hyper_R, Qt::Key_Hyper_R)); 0124 0125 0126 mapping.append(KeyMapping(XK_space, Qt::Key_Space)); 0127 0128 for (int qtKey = Qt::Key_0, x11Sym = XK_0; 0129 qtKey <= Qt::Key_9; 0130 qtKey++, x11Sym++) { 0131 0132 mapping.append(KeyMapping(x11Sym, Qt::Key(qtKey))); 0133 } 0134 0135 for (int qtKey = Qt::Key_A, x11Sym = XK_a; 0136 qtKey <= Qt::Key_Z; 0137 qtKey++, x11Sym++) { 0138 0139 mapping.append(KeyMapping(x11Sym, Qt::Key(qtKey))); 0140 } 0141 } 0142 0143 bool KisExtendedModifiersMapper::Private::checkKeyCodePressedX11(KeyCode key) 0144 { 0145 int byte = key / 8; 0146 char mask = 1 << (key % 8); 0147 0148 return keysState[byte] & mask; 0149 } 0150 0151 bool KisExtendedModifiersMapper::Private::checkKeySymPressedX11(KeySym sym) 0152 { 0153 KeyCode key = XKeysymToKeycode(QX11Info::display(), sym); 0154 return key != 0 ? checkKeyCodePressedX11(key) : false; 0155 } 0156 0157 #else /* HAVE_X11 */ 0158 0159 KisExtendedModifiersMapper::Private::Private() 0160 { 0161 } 0162 0163 #endif /* HAVE_X11 */ 0164 0165 0166 KisExtendedModifiersMapper::KisExtendedModifiersMapper() 0167 : m_d(new Private) 0168 { 0169 } 0170 0171 KisExtendedModifiersMapper::~KisExtendedModifiersMapper() 0172 { 0173 } 0174 0175 #ifdef Q_OS_MACOS 0176 void KisExtendedModifiersMapper::setLocalMonitor(bool activate, KisShortcutMatcher *matcher) 0177 { 0178 Q_UNUSED(matcher); 0179 activateLocalMonitor(activate); 0180 } 0181 #endif 0182 0183 KisExtendedModifiersMapper::ExtendedModifiers 0184 KisExtendedModifiersMapper::queryExtendedModifiers() 0185 { 0186 ExtendedModifiers modifiers; 0187 0188 #ifdef HAVE_X11 0189 0190 { 0191 for (int keyCode = m_d->minKeyCode; keyCode <= m_d->maxKeyCode; keyCode++) { 0192 if (m_d->checkKeyCodePressedX11(keyCode)) { 0193 0194 KeySym sym = XkbKeycodeToKeysym(QX11Info::display(), keyCode, 0195 0, 0); 0196 Q_FOREACH (const KeyMapping &map, m_d->mapping) { 0197 if (map.x11KeySym == sym) { 0198 modifiers << map.qtKey; 0199 break; 0200 } 0201 } 0202 } 0203 } 0204 } 0205 0206 // in X11 some keys may have multiple keysyms, 0207 // (Alt Key == XK_Meta_{L,R}, XK_Meta_{L,R}) 0208 KritaUtils::makeContainerUnique(modifiers); 0209 0210 #elif defined Q_OS_WIN 0211 0212 modifiers = queryPressedKeysWin(); 0213 0214 #elif defined Q_OS_MACOS 0215 modifiers = queryPressedKeysMac(); 0216 #else 0217 0218 Qt::KeyboardModifiers standardModifiers = queryStandardModifiers(); 0219 0220 if (standardModifiers & Qt::ShiftModifier) { 0221 modifiers << Qt::Key_Shift; 0222 } 0223 0224 if (standardModifiers & Qt::ControlModifier) { 0225 modifiers << Qt::Key_Control; 0226 } 0227 0228 if (standardModifiers & Qt::AltModifier) { 0229 modifiers << Qt::Key_Alt; 0230 } 0231 0232 if (standardModifiers & Qt::MetaModifier) { 0233 modifiers << Qt::Key_Meta; 0234 } 0235 0236 #endif 0237 0238 return modifiers; 0239 } 0240 0241 Qt::KeyboardModifiers KisExtendedModifiersMapper::queryStandardModifiers() 0242 { 0243 return QApplication::queryKeyboardModifiers(); 0244 } 0245 0246 Qt::Key KisExtendedModifiersMapper::workaroundShiftAltMetaHell(const QKeyEvent *keyEvent) 0247 { 0248 Qt::Key key = (Qt::Key)keyEvent->key(); 0249 0250 if (keyEvent->key() == Qt::Key_Meta && 0251 keyEvent->modifiers().testFlag(Qt::ShiftModifier)) { 0252 0253 key = Qt::Key_Alt; 0254 } 0255 0256 return key; 0257 }