File indexing completed on 2024-05-05 12:24:27
0001 /* 0002 SPDX-FileCopyrightText: 2001 Ellis Whitehead <ellis@kde.org> 0003 0004 Win32 port: 0005 SPDX-FileCopyrightText: 2004 Jarosław Staniek <staniek@kde.org> 0006 0007 SPDX-License-Identifier: LGPL-2.1-or-later 0008 */ 0009 0010 #include "kkeyserver.h" 0011 #include "kkeyserver_x11.h" 0012 0013 #include "platforms/xcb/kwindowsystem_xcb_debug.h" 0014 0015 #if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) 0016 #include <private/qtx11extras_p.h> 0017 #else 0018 #include <QX11Info> 0019 #endif 0020 0021 #define XK_MISCELLANY 0022 #define XK_XKB_KEYS 0023 #include <X11/X.h> 0024 #include <X11/Xlib.h> 0025 #include <X11/Xutil.h> 0026 #include <X11/keysymdef.h> 0027 #include <xcb/xcb_keysyms.h> 0028 #define X11_ONLY(arg) arg, // allows to omit an argument 0029 0030 // #define KKEYSERVER_DEBUG 1 0031 0032 namespace KKeyServer 0033 { 0034 //--------------------------------------------------------------------- 0035 // Data Structures 0036 //--------------------------------------------------------------------- 0037 0038 struct Mod { 0039 int m_mod; 0040 }; 0041 0042 //--------------------------------------------------------------------- 0043 // Array Structures 0044 //--------------------------------------------------------------------- 0045 0046 struct X11ModInfo { 0047 int modQt; 0048 int modX; 0049 }; 0050 0051 struct SymVariation { 0052 uint sym, symVariation; 0053 bool bActive; 0054 }; 0055 0056 struct SymName { 0057 uint sym; 0058 const char *psName; 0059 }; 0060 0061 struct TransKey { 0062 int keySymQt; 0063 uint keySymX; 0064 }; 0065 0066 //--------------------------------------------------------------------- 0067 // Arrays 0068 //--------------------------------------------------------------------- 0069 // clang-format off 0070 0071 static X11ModInfo g_rgX11ModInfo[4] = { 0072 { Qt::SHIFT, X11_ONLY(ShiftMask) }, 0073 { Qt::CTRL, X11_ONLY(ControlMask) }, 0074 { Qt::ALT, X11_ONLY(Mod1Mask) }, 0075 { Qt::META, X11_ONLY(Mod4Mask) } 0076 }; 0077 0078 // These are the X equivalents to the Qt keycodes 0x1000 - 0x1026 0079 static const TransKey g_rgQtToSymX[] = { 0080 { Qt::Key_Escape, XK_Escape }, 0081 { Qt::Key_Tab, XK_Tab }, 0082 { Qt::Key_Backtab, XK_ISO_Left_Tab }, 0083 { Qt::Key_Backspace, XK_BackSpace }, 0084 { Qt::Key_Return, XK_Return }, 0085 { Qt::Key_Insert, XK_Insert }, 0086 { Qt::Key_Delete, XK_Delete }, 0087 { Qt::Key_Pause, XK_Pause }, 0088 #ifdef sun 0089 { Qt::Key_Print, XK_F22 }, 0090 #else 0091 { Qt::Key_Print, XK_Print }, 0092 #endif 0093 { Qt::Key_SysReq, XK_Sys_Req }, 0094 { Qt::Key_Home, XK_Home }, 0095 { Qt::Key_End, XK_End }, 0096 { Qt::Key_Left, XK_Left }, 0097 { Qt::Key_Up, XK_Up }, 0098 { Qt::Key_Right, XK_Right }, 0099 { Qt::Key_Down, XK_Down }, 0100 { Qt::Key_PageUp, XK_Prior }, 0101 { Qt::Key_PageDown, XK_Next }, 0102 //{ Qt::Key_Shift, 0 }, 0103 //{ Qt::Key_Control, 0 }, 0104 //{ Qt::Key_Meta, 0 }, 0105 //{ Qt::Key_Alt, 0 }, 0106 { Qt::Key_CapsLock, XK_Caps_Lock }, 0107 { Qt::Key_NumLock, XK_Num_Lock }, 0108 { Qt::Key_ScrollLock, XK_Scroll_Lock }, 0109 { Qt::Key_F1, XK_F1 }, 0110 { Qt::Key_F2, XK_F2 }, 0111 { Qt::Key_F3, XK_F3 }, 0112 { Qt::Key_F4, XK_F4 }, 0113 { Qt::Key_F5, XK_F5 }, 0114 { Qt::Key_F6, XK_F6 }, 0115 { Qt::Key_F7, XK_F7 }, 0116 { Qt::Key_F8, XK_F8 }, 0117 { Qt::Key_F9, XK_F9 }, 0118 { Qt::Key_F10, XK_F10 }, 0119 { Qt::Key_F11, XK_F11 }, 0120 { Qt::Key_F12, XK_F12 }, 0121 { Qt::Key_F13, XK_F13 }, 0122 { Qt::Key_F14, XK_F14 }, 0123 { Qt::Key_F15, XK_F15 }, 0124 { Qt::Key_F16, XK_F16 }, 0125 { Qt::Key_F17, XK_F17 }, 0126 { Qt::Key_F18, XK_F18 }, 0127 { Qt::Key_F19, XK_F19 }, 0128 { Qt::Key_F20, XK_F20 }, 0129 { Qt::Key_F21, XK_F21 }, 0130 { Qt::Key_F22, XK_F22 }, 0131 { Qt::Key_F23, XK_F23 }, 0132 { Qt::Key_F24, XK_F24 }, 0133 { Qt::Key_F25, XK_F25 }, 0134 { Qt::Key_F26, XK_F26 }, 0135 { Qt::Key_F27, XK_F27 }, 0136 { Qt::Key_F28, XK_F28 }, 0137 { Qt::Key_F29, XK_F29 }, 0138 { Qt::Key_F30, XK_F30 }, 0139 { Qt::Key_F31, XK_F31 }, 0140 { Qt::Key_F32, XK_F32 }, 0141 { Qt::Key_F33, XK_F33 }, 0142 { Qt::Key_F34, XK_F34 }, 0143 { Qt::Key_F35, XK_F35 }, 0144 { Qt::Key_Super_L, XK_Super_L }, 0145 { Qt::Key_Super_R, XK_Super_R }, 0146 { Qt::Key_Menu, XK_Menu }, 0147 { Qt::Key_Hyper_L, XK_Hyper_L }, 0148 { Qt::Key_Hyper_R, XK_Hyper_R }, 0149 { Qt::Key_Help, XK_Help }, 0150 //{ Qt::Key_Direction_L, XK_Direction_L }, These keys don't exist in X11 0151 //{ Qt::Key_Direction_R, XK_Direction_R }, 0152 0153 { Qt::Key_Space, XK_KP_Space }, 0154 { Qt::Key_Tab, XK_KP_Tab }, 0155 { Qt::Key_Enter, XK_KP_Enter }, 0156 { Qt::Key_Home, XK_KP_Home }, 0157 { Qt::Key_Left, XK_KP_Left }, 0158 { Qt::Key_Up, XK_KP_Up }, 0159 { Qt::Key_Right, XK_KP_Right }, 0160 { Qt::Key_Down, XK_KP_Down }, 0161 { Qt::Key_PageUp, XK_KP_Prior }, 0162 { Qt::Key_PageDown, XK_KP_Next }, 0163 { Qt::Key_End, XK_KP_End }, 0164 { Qt::Key_Clear, XK_KP_Begin }, 0165 { Qt::Key_Insert, XK_KP_Insert }, 0166 { Qt::Key_Delete, XK_KP_Delete }, 0167 { Qt::Key_Equal, XK_KP_Equal }, 0168 { Qt::Key_Asterisk, XK_KP_Multiply }, 0169 { Qt::Key_Plus, XK_KP_Add }, 0170 { Qt::Key_Comma, XK_KP_Separator }, 0171 { Qt::Key_Minus, XK_KP_Subtract }, 0172 { Qt::Key_Period, XK_KP_Decimal }, 0173 { Qt::Key_Slash, XK_KP_Divide }, 0174 0175 // the next lines are taken on 10/2009 from X.org (X11/XF86keysym.h), defining some special 0176 // multimedia keys. They are included here as not every system has them. 0177 #define XF86XK_MonBrightnessUp 0x1008FF02 0178 #define XF86XK_MonBrightnessDown 0x1008FF03 0179 #define XF86XK_KbdLightOnOff 0x1008FF04 0180 #define XF86XK_KbdBrightnessUp 0x1008FF05 0181 #define XF86XK_KbdBrightnessDown 0x1008FF06 0182 #define XF86XK_Standby 0x1008FF10 0183 #define XF86XK_AudioLowerVolume 0x1008FF11 0184 #define XF86XK_AudioMute 0x1008FF12 0185 #define XF86XK_AudioRaiseVolume 0x1008FF13 0186 #define XF86XK_AudioPlay 0x1008FF14 0187 #define XF86XK_AudioStop 0x1008FF15 0188 #define XF86XK_AudioPrev 0x1008FF16 0189 #define XF86XK_AudioNext 0x1008FF17 0190 #define XF86XK_HomePage 0x1008FF18 0191 #define XF86XK_Mail 0x1008FF19 0192 #define XF86XK_Start 0x1008FF1A 0193 #define XF86XK_Search 0x1008FF1B 0194 #define XF86XK_AudioRecord 0x1008FF1C 0195 #define XF86XK_Calculator 0x1008FF1D 0196 #define XF86XK_Memo 0x1008FF1E 0197 #define XF86XK_ToDoList 0x1008FF1F 0198 #define XF86XK_Calendar 0x1008FF20 0199 #define XF86XK_PowerDown 0x1008FF21 0200 #define XF86XK_ContrastAdjust 0x1008FF22 0201 #define XF86XK_Back 0x1008FF26 0202 #define XF86XK_Forward 0x1008FF27 0203 #define XF86XK_Stop 0x1008FF28 0204 #define XF86XK_Refresh 0x1008FF29 0205 #define XF86XK_PowerOff 0x1008FF2A 0206 #define XF86XK_WakeUp 0x1008FF2B 0207 #define XF86XK_Eject 0x1008FF2C 0208 #define XF86XK_ScreenSaver 0x1008FF2D 0209 #define XF86XK_WWW 0x1008FF2E 0210 #define XF86XK_Sleep 0x1008FF2F 0211 #define XF86XK_Favorites 0x1008FF30 0212 #define XF86XK_AudioPause 0x1008FF31 0213 #define XF86XK_AudioMedia 0x1008FF32 0214 #define XF86XK_MyComputer 0x1008FF33 0215 #define XF86XK_LightBulb 0x1008FF35 0216 #define XF86XK_Shop 0x1008FF36 0217 #define XF86XK_History 0x1008FF37 0218 #define XF86XK_OpenURL 0x1008FF38 0219 #define XF86XK_AddFavorite 0x1008FF39 0220 #define XF86XK_HotLinks 0x1008FF3A 0221 #define XF86XK_BrightnessAdjust 0x1008FF3B 0222 #define XF86XK_Finance 0x1008FF3C 0223 #define XF86XK_Community 0x1008FF3D 0224 #define XF86XK_AudioRewind 0x1008FF3E 0225 #define XF86XK_BackForward 0x1008FF3F 0226 #define XF86XK_Launch0 0x1008FF40 0227 #define XF86XK_Launch1 0x1008FF41 0228 #define XF86XK_Launch2 0x1008FF42 0229 #define XF86XK_Launch3 0x1008FF43 0230 #define XF86XK_Launch4 0x1008FF44 0231 #define XF86XK_Launch5 0x1008FF45 0232 #define XF86XK_Launch6 0x1008FF46 0233 #define XF86XK_Launch7 0x1008FF47 0234 #define XF86XK_Launch8 0x1008FF48 0235 #define XF86XK_Launch9 0x1008FF49 0236 #define XF86XK_LaunchA 0x1008FF4A 0237 #define XF86XK_LaunchB 0x1008FF4B 0238 #define XF86XK_LaunchC 0x1008FF4C 0239 #define XF86XK_LaunchD 0x1008FF4D 0240 #define XF86XK_LaunchE 0x1008FF4E 0241 #define XF86XK_LaunchF 0x1008FF4F 0242 #define XF86XK_ApplicationLeft 0x1008FF50 0243 #define XF86XK_ApplicationRight 0x1008FF51 0244 #define XF86XK_Book 0x1008FF52 0245 #define XF86XK_CD 0x1008FF53 0246 #define XF86XK_Calculater 0x1008FF54 0247 #define XF86XK_Clear 0x1008FF55 0248 #define XF86XK_ClearGrab 0x1008FE21 0249 #define XF86XK_Close 0x1008FF56 0250 #define XF86XK_Copy 0x1008FF57 0251 #define XF86XK_Cut 0x1008FF58 0252 #define XF86XK_Display 0x1008FF59 0253 #define XF86XK_DOS 0x1008FF5A 0254 #define XF86XK_Documents 0x1008FF5B 0255 #define XF86XK_Excel 0x1008FF5C 0256 #define XF86XK_Explorer 0x1008FF5D 0257 #define XF86XK_Game 0x1008FF5E 0258 #define XF86XK_Go 0x1008FF5F 0259 #define XF86XK_iTouch 0x1008FF60 0260 #define XF86XK_LogOff 0x1008FF61 0261 #define XF86XK_Market 0x1008FF62 0262 #define XF86XK_Meeting 0x1008FF63 0263 #define XF86XK_MenuKB 0x1008FF65 0264 #define XF86XK_MenuPB 0x1008FF66 0265 #define XF86XK_MySites 0x1008FF67 0266 #define XF86XK_News 0x1008FF69 0267 #define XF86XK_OfficeHome 0x1008FF6A 0268 #define XF86XK_Option 0x1008FF6C 0269 #define XF86XK_Paste 0x1008FF6D 0270 #define XF86XK_Phone 0x1008FF6E 0271 #define XF86XK_Reply 0x1008FF72 0272 #define XF86XK_Reload 0x1008FF73 0273 #define XF86XK_RotateWindows 0x1008FF74 0274 #define XF86XK_RotationPB 0x1008FF75 0275 #define XF86XK_RotationKB 0x1008FF76 0276 #define XF86XK_Save 0x1008FF77 0277 #define XF86XK_Send 0x1008FF7B 0278 #define XF86XK_Spell 0x1008FF7C 0279 #define XF86XK_SplitScreen 0x1008FF7D 0280 #define XF86XK_Support 0x1008FF7E 0281 #define XF86XK_TaskPane 0x1008FF7F 0282 #define XF86XK_Terminal 0x1008FF80 0283 #define XF86XK_Tools 0x1008FF81 0284 #define XF86XK_Travel 0x1008FF82 0285 #define XF86XK_Video 0x1008FF87 0286 #define XF86XK_Word 0x1008FF89 0287 #define XF86XK_Xfer 0x1008FF8A 0288 #define XF86XK_ZoomIn 0x1008FF8B 0289 #define XF86XK_ZoomOut 0x1008FF8C 0290 #define XF86XK_Away 0x1008FF8D 0291 #define XF86XK_Messenger 0x1008FF8E 0292 #define XF86XK_WebCam 0x1008FF8F 0293 #define XF86XK_MailForward 0x1008FF90 0294 #define XF86XK_Pictures 0x1008FF91 0295 #define XF86XK_Music 0x1008FF92 0296 #define XF86XK_Battery 0x1008FF93 0297 #define XF86XK_Bluetooth 0x1008FF94 0298 #define XF86XK_WLAN 0x1008FF95 0299 #define XF86XK_UWB 0x1008FF96 0300 #define XF86XK_AudioForward 0x1008FF97 0301 #define XF86XK_AudioRepeat 0x1008FF98 0302 #define XF86XK_AudioRandomPlay 0x1008FF99 0303 #define XF86XK_Subtitle 0x1008FF9A 0304 #define XF86XK_AudioCycleTrack 0x1008FF9B 0305 #define XF86XK_Time 0x1008FF9F 0306 #define XF86XK_Select 0x1008FFA0 0307 #define XF86XK_View 0x1008FFA1 0308 #define XF86XK_TopMenu 0x1008FFA2 0309 #define XF86XK_Suspend 0x1008FFA7 0310 #define XF86XK_Hibernate 0x1008FFA8 0311 #define XF86XK_TouchpadToggle 0x1008FFA9 0312 #define XF86XK_TouchpadOn 0x1008FFB0 0313 #define XF86XK_TouchpadOff 0x1008FFB1 0314 #define XF86XK_AudioMicMute 0x1008FFB2 0315 // end of XF86keysyms.h 0316 0317 // All of the stuff below really has to match qxcbkeyboard.cpp in Qt! 0318 { Qt::Key_Back, XF86XK_Back }, 0319 { Qt::Key_Forward, XF86XK_Forward }, 0320 { Qt::Key_Stop, XF86XK_Stop }, 0321 { Qt::Key_Refresh, XF86XK_Refresh }, 0322 { Qt::Key_Favorites, XF86XK_Favorites }, 0323 { Qt::Key_LaunchMedia, XF86XK_AudioMedia }, 0324 { Qt::Key_OpenUrl, XF86XK_OpenURL }, 0325 { Qt::Key_HomePage, XF86XK_HomePage }, 0326 { Qt::Key_Search, XF86XK_Search }, 0327 { Qt::Key_VolumeDown, XF86XK_AudioLowerVolume }, 0328 { Qt::Key_VolumeMute, XF86XK_AudioMute }, 0329 { Qt::Key_VolumeUp, XF86XK_AudioRaiseVolume }, 0330 { Qt::Key_MediaPlay, XF86XK_AudioPlay }, 0331 { Qt::Key_MediaStop, XF86XK_AudioStop }, 0332 { Qt::Key_MediaPrevious, XF86XK_AudioPrev }, 0333 { Qt::Key_MediaNext, XF86XK_AudioNext }, 0334 { Qt::Key_MediaRecord, XF86XK_AudioRecord }, 0335 { Qt::Key_MediaPause, XF86XK_AudioPause }, 0336 { Qt::Key_LaunchMail, XF86XK_Mail }, 0337 { Qt::Key_Launch0, XF86XK_MyComputer }, 0338 { Qt::Key_Launch1, XF86XK_Calculator }, 0339 { Qt::Key_Memo, XF86XK_Memo }, 0340 { Qt::Key_ToDoList, XF86XK_ToDoList }, 0341 { Qt::Key_Calendar, XF86XK_Calendar }, 0342 { Qt::Key_PowerDown, XF86XK_PowerDown }, 0343 { Qt::Key_ContrastAdjust, XF86XK_ContrastAdjust }, 0344 { Qt::Key_Standby, XF86XK_Standby }, 0345 { Qt::Key_MonBrightnessUp, XF86XK_MonBrightnessUp }, 0346 { Qt::Key_MonBrightnessDown, XF86XK_MonBrightnessDown }, 0347 { Qt::Key_KeyboardLightOnOff, XF86XK_KbdLightOnOff }, 0348 { Qt::Key_KeyboardBrightnessUp, XF86XK_KbdBrightnessUp }, 0349 { Qt::Key_KeyboardBrightnessDown, XF86XK_KbdBrightnessDown }, 0350 { Qt::Key_PowerOff, XF86XK_PowerOff }, 0351 { Qt::Key_WakeUp, XF86XK_WakeUp }, 0352 { Qt::Key_Eject, XF86XK_Eject }, 0353 { Qt::Key_ScreenSaver, XF86XK_ScreenSaver }, 0354 { Qt::Key_WWW, XF86XK_WWW }, 0355 { Qt::Key_Sleep, XF86XK_Sleep }, 0356 { Qt::Key_LightBulb, XF86XK_LightBulb }, 0357 { Qt::Key_Shop, XF86XK_Shop }, 0358 { Qt::Key_History, XF86XK_History }, 0359 { Qt::Key_AddFavorite, XF86XK_AddFavorite }, 0360 { Qt::Key_HotLinks, XF86XK_HotLinks }, 0361 { Qt::Key_BrightnessAdjust, XF86XK_BrightnessAdjust }, 0362 { Qt::Key_Finance, XF86XK_Finance }, 0363 { Qt::Key_Community, XF86XK_Community }, 0364 { Qt::Key_AudioRewind, XF86XK_AudioRewind }, 0365 { Qt::Key_BackForward, XF86XK_BackForward }, 0366 { Qt::Key_ApplicationLeft, XF86XK_ApplicationLeft }, 0367 { Qt::Key_ApplicationRight, XF86XK_ApplicationRight }, 0368 { Qt::Key_Book, XF86XK_Book }, 0369 { Qt::Key_CD, XF86XK_CD }, 0370 { Qt::Key_Calculator, XF86XK_Calculater }, 0371 { Qt::Key_Clear, XF86XK_Clear }, 0372 { Qt::Key_ClearGrab, XF86XK_ClearGrab }, 0373 { Qt::Key_Close, XF86XK_Close }, 0374 { Qt::Key_Copy, XF86XK_Copy }, 0375 { Qt::Key_Cut, XF86XK_Cut }, 0376 { Qt::Key_Display, XF86XK_Display }, 0377 { Qt::Key_DOS, XF86XK_DOS }, 0378 { Qt::Key_Documents, XF86XK_Documents }, 0379 { Qt::Key_Excel, XF86XK_Excel }, 0380 { Qt::Key_Explorer, XF86XK_Explorer }, 0381 { Qt::Key_Game, XF86XK_Game }, 0382 { Qt::Key_Go, XF86XK_Go }, 0383 { Qt::Key_iTouch, XF86XK_iTouch }, 0384 { Qt::Key_LogOff, XF86XK_LogOff }, 0385 { Qt::Key_Market, XF86XK_Market }, 0386 { Qt::Key_Meeting, XF86XK_Meeting }, 0387 { Qt::Key_MenuKB, XF86XK_MenuKB }, 0388 { Qt::Key_MenuPB, XF86XK_MenuPB }, 0389 { Qt::Key_MySites, XF86XK_MySites }, 0390 { Qt::Key_News, XF86XK_News }, 0391 { Qt::Key_OfficeHome, XF86XK_OfficeHome }, 0392 { Qt::Key_Option, XF86XK_Option }, 0393 { Qt::Key_Paste, XF86XK_Paste }, 0394 { Qt::Key_Phone, XF86XK_Phone }, 0395 { Qt::Key_Reply, XF86XK_Reply }, 0396 { Qt::Key_Reload, XF86XK_Reload }, 0397 { Qt::Key_RotateWindows, XF86XK_RotateWindows }, 0398 { Qt::Key_RotationPB, XF86XK_RotationPB }, 0399 { Qt::Key_RotationKB, XF86XK_RotationKB }, 0400 { Qt::Key_Save, XF86XK_Save }, 0401 { Qt::Key_Send, XF86XK_Send }, 0402 { Qt::Key_Spell, XF86XK_Spell }, 0403 { Qt::Key_SplitScreen, XF86XK_SplitScreen }, 0404 { Qt::Key_Support, XF86XK_Support }, 0405 { Qt::Key_TaskPane, XF86XK_TaskPane }, 0406 { Qt::Key_Terminal, XF86XK_Terminal }, 0407 { Qt::Key_Tools, XF86XK_Tools }, 0408 { Qt::Key_Travel, XF86XK_Travel }, 0409 { Qt::Key_Video, XF86XK_Video }, 0410 { Qt::Key_Word, XF86XK_Word }, 0411 { Qt::Key_Xfer, XF86XK_Xfer }, 0412 { Qt::Key_ZoomIn, XF86XK_ZoomIn }, 0413 { Qt::Key_ZoomOut, XF86XK_ZoomOut }, 0414 { Qt::Key_Away, XF86XK_Away }, 0415 { Qt::Key_Messenger, XF86XK_Messenger }, 0416 { Qt::Key_WebCam, XF86XK_WebCam }, 0417 { Qt::Key_MailForward, XF86XK_MailForward }, 0418 { Qt::Key_Pictures, XF86XK_Pictures }, 0419 { Qt::Key_Music, XF86XK_Music }, 0420 { Qt::Key_Battery, XF86XK_Battery }, 0421 { Qt::Key_Bluetooth, XF86XK_Bluetooth }, 0422 { Qt::Key_WLAN, XF86XK_WLAN }, 0423 { Qt::Key_UWB, XF86XK_UWB }, 0424 { Qt::Key_AudioForward, XF86XK_AudioForward }, 0425 { Qt::Key_AudioRepeat, XF86XK_AudioRepeat }, 0426 { Qt::Key_AudioRandomPlay, XF86XK_AudioRandomPlay }, 0427 { Qt::Key_Subtitle, XF86XK_Subtitle }, 0428 { Qt::Key_AudioCycleTrack, XF86XK_AudioCycleTrack }, 0429 { Qt::Key_Time, XF86XK_Time }, 0430 { Qt::Key_Select, XF86XK_Select }, 0431 { Qt::Key_View, XF86XK_View }, 0432 { Qt::Key_TopMenu, XF86XK_TopMenu }, 0433 { Qt::Key_Bluetooth, XF86XK_Bluetooth }, 0434 { Qt::Key_Suspend, XF86XK_Suspend }, 0435 { Qt::Key_Hibernate, XF86XK_Hibernate }, 0436 { Qt::Key_TouchpadToggle, XF86XK_TouchpadToggle }, 0437 { Qt::Key_TouchpadOn, XF86XK_TouchpadOn }, 0438 { Qt::Key_TouchpadOff, XF86XK_TouchpadOff }, 0439 { Qt::Key_MicMute, XF86XK_AudioMicMute }, 0440 { Qt::Key_Launch2, XF86XK_Launch0 }, 0441 { Qt::Key_Launch3, XF86XK_Launch1 }, 0442 { Qt::Key_Launch4, XF86XK_Launch2 }, 0443 { Qt::Key_Launch5, XF86XK_Launch3 }, 0444 { Qt::Key_Launch6, XF86XK_Launch4 }, 0445 { Qt::Key_Launch7, XF86XK_Launch5 }, 0446 { Qt::Key_Launch8, XF86XK_Launch6 }, 0447 { Qt::Key_Launch9, XF86XK_Launch7 }, 0448 { Qt::Key_LaunchA, XF86XK_Launch8 }, 0449 { Qt::Key_LaunchB, XF86XK_Launch9 }, 0450 { Qt::Key_LaunchC, XF86XK_LaunchA }, 0451 { Qt::Key_LaunchD, XF86XK_LaunchB }, 0452 { Qt::Key_LaunchE, XF86XK_LaunchC }, 0453 { Qt::Key_LaunchF, XF86XK_LaunchD }, 0454 }; 0455 // clang-format on 0456 0457 //--------------------------------------------------------------------- 0458 // Debugging 0459 //--------------------------------------------------------------------- 0460 #ifndef NDEBUG 0461 inline void checkDisplay() 0462 { 0463 // Some non-GUI apps might try to use us. 0464 if (!QX11Info::display()) { 0465 qCCritical(LOG_KKEYSERVER_X11) << "QX11Info::display() returns 0. I'm probably going to crash now."; 0466 qCCritical(LOG_KKEYSERVER_X11) << "If this is a KApplication initialized without GUI stuff, change it to be " 0467 "initialized with GUI stuff."; 0468 } 0469 } 0470 #else // NDEBUG 0471 #define checkDisplay() 0472 #endif 0473 0474 //--------------------------------------------------------------------- 0475 // Initialization 0476 //--------------------------------------------------------------------- 0477 0478 static bool g_bInitializedMods; 0479 static uint g_modXNumLock, g_modXScrollLock, g_modXModeSwitch, g_alt_mask, g_meta_mask, g_super_mask, g_hyper_mask; 0480 0481 bool initializeMods() 0482 { 0483 // Reinitialize the masks 0484 g_modXNumLock = 0; 0485 g_modXScrollLock = 0; 0486 g_modXModeSwitch = 0; 0487 g_alt_mask = 0; 0488 g_meta_mask = 0; 0489 g_super_mask = 0; 0490 g_hyper_mask = 0; 0491 0492 if (!QX11Info::isPlatformX11()) { 0493 qCWarning(LOG_KKEYSERVER_X11) << "X11 implementation of KKeyServer accessed from non-X11 platform! This is an application bug."; 0494 g_bInitializedMods = true; 0495 return false; 0496 } 0497 0498 checkDisplay(); 0499 xcb_key_symbols_t *symbols = xcb_key_symbols_alloc(QX11Info::connection()); 0500 XModifierKeymap *xmk = XGetModifierMapping(QX11Info::display()); 0501 0502 int min_keycode; 0503 int max_keycode; 0504 int keysyms_per_keycode = 0; 0505 0506 XDisplayKeycodes(QX11Info::display(), &min_keycode, &max_keycode); 0507 XFree(XGetKeyboardMapping(QX11Info::display(), min_keycode, 1, &keysyms_per_keycode)); 0508 0509 for (int i = Mod1MapIndex; i < 8; i++) { 0510 uint mask = (1 << i); 0511 uint keySymX = NoSymbol; 0512 0513 // This used to be only XKeycodeToKeysym( ... , 0 ), but that fails with XFree4.3.99 0514 // and X.org R6.7 , where for some reason only ( ... , 1 ) works. I have absolutely no 0515 // idea what the problem is, but searching all possibilities until something valid is 0516 // found fixes the problem. 0517 for (int j = 0; j < xmk->max_keypermod; ++j) { 0518 for (int k = 0; k < keysyms_per_keycode; ++k) { 0519 keySymX = xcb_key_symbols_get_keysym(symbols, xmk->modifiermap[xmk->max_keypermod * i + j], k); 0520 0521 switch (keySymX) { 0522 case XK_Alt_L: 0523 case XK_Alt_R: 0524 g_alt_mask |= mask; 0525 break; 0526 0527 case XK_Super_L: 0528 case XK_Super_R: 0529 g_super_mask |= mask; 0530 break; 0531 0532 case XK_Hyper_L: 0533 case XK_Hyper_R: 0534 g_hyper_mask |= mask; 0535 break; 0536 0537 case XK_Meta_L: 0538 case XK_Meta_R: 0539 g_meta_mask |= mask; 0540 break; 0541 0542 case XK_Num_Lock: 0543 g_modXNumLock |= mask; 0544 break; 0545 case XK_Scroll_Lock: 0546 g_modXScrollLock |= mask; 0547 break; 0548 case XK_Mode_switch: 0549 g_modXModeSwitch |= mask; 0550 break; 0551 } 0552 } 0553 } 0554 } 0555 0556 #ifdef KKEYSERVER_DEBUG 0557 qCDebug(LOG_KKEYSERVER_X11) << "Alt:" << g_alt_mask; 0558 qCDebug(LOG_KKEYSERVER_X11) << "Meta:" << g_meta_mask; 0559 qCDebug(LOG_KKEYSERVER_X11) << "Super:" << g_super_mask; 0560 qCDebug(LOG_KKEYSERVER_X11) << "Hyper:" << g_hyper_mask; 0561 qCDebug(LOG_KKEYSERVER_X11) << "NumLock:" << g_modXNumLock; 0562 qCDebug(LOG_KKEYSERVER_X11) << "ScrollLock:" << g_modXScrollLock; 0563 qCDebug(LOG_KKEYSERVER_X11) << "ModeSwitch:" << g_modXModeSwitch; 0564 #endif 0565 0566 // Check if hyper overlaps with super or meta or alt 0567 if (g_hyper_mask & (g_super_mask | g_meta_mask | g_alt_mask)) { 0568 #ifdef KKEYSERVER_DEBUG 0569 qCDebug(LOG_KKEYSERVER_X11) << "Hyper conflicts with super, meta or alt."; 0570 #endif 0571 // Remove the conflicting masks 0572 g_hyper_mask &= ~(g_super_mask | g_meta_mask | g_alt_mask); 0573 } 0574 0575 // Check if super overlaps with meta or alt 0576 if (g_super_mask & (g_meta_mask | g_alt_mask)) { 0577 #ifdef KKEYSERVER_DEBUG 0578 qCDebug(LOG_KKEYSERVER_X11) << "Super conflicts with meta or alt."; 0579 #endif 0580 // Remove the conflicting masks 0581 g_super_mask &= ~(g_meta_mask | g_alt_mask); 0582 } 0583 0584 // Check if meta overlaps with alt 0585 if (g_meta_mask | g_alt_mask) { 0586 #ifdef KKEYSERVER_DEBUG 0587 qCDebug(LOG_KKEYSERVER_X11) << "Meta conflicts with alt."; 0588 #endif 0589 // Remove the conflicting masks 0590 g_meta_mask &= ~(g_alt_mask); 0591 } 0592 0593 if (!g_meta_mask) { 0594 #ifdef KKEYSERVER_DEBUG 0595 qCDebug(LOG_KKEYSERVER_X11) << "Meta is not set or conflicted with alt."; 0596 #endif 0597 if (g_super_mask) { 0598 #ifdef KKEYSERVER_DEBUG 0599 qCDebug(LOG_KKEYSERVER_X11) << "Using super for meta"; 0600 #endif 0601 // Use Super 0602 g_meta_mask = g_super_mask; 0603 } else if (g_hyper_mask) { 0604 #ifdef KKEYSERVER_DEBUG 0605 qCDebug(LOG_KKEYSERVER_X11) << "Using hyper for meta"; 0606 #endif 0607 // User Hyper 0608 g_meta_mask = g_hyper_mask; 0609 } else { 0610 // ???? Nothing left 0611 g_meta_mask = 0; 0612 } 0613 } 0614 0615 #ifdef KKEYSERVER_DEBUG 0616 qCDebug(LOG_KKEYSERVER_X11) << "Alt:" << g_alt_mask; 0617 qCDebug(LOG_KKEYSERVER_X11) << "Meta:" << g_meta_mask; 0618 qCDebug(LOG_KKEYSERVER_X11) << "Super:" << g_super_mask; 0619 qCDebug(LOG_KKEYSERVER_X11) << "Hyper:" << g_hyper_mask; 0620 qCDebug(LOG_KKEYSERVER_X11) << "NumLock:" << g_modXNumLock; 0621 qCDebug(LOG_KKEYSERVER_X11) << "ScrollLock:" << g_modXScrollLock; 0622 qCDebug(LOG_KKEYSERVER_X11) << "ModeSwitch:" << g_modXModeSwitch; 0623 #endif 0624 0625 if (!g_meta_mask) { 0626 qCWarning(LOG_KKEYSERVER_X11) << "Your keyboard setup doesn't provide a key to use for meta. See 'xmodmap -pm' or 'xkbcomp $DISPLAY'"; 0627 } 0628 0629 g_rgX11ModInfo[2].modX = g_alt_mask; 0630 g_rgX11ModInfo[3].modX = g_meta_mask; 0631 0632 xcb_key_symbols_free(symbols); 0633 XFreeModifiermap(xmk); 0634 g_bInitializedMods = true; 0635 0636 return true; 0637 } 0638 0639 //--------------------------------------------------------------------- 0640 // Helper functions 0641 //--------------------------------------------------------------------- 0642 0643 static bool is_keypad_key(xcb_keysym_t keysym) 0644 { 0645 return keysym >= XK_KP_Space && keysym <= XK_KP_9; 0646 } 0647 0648 //--------------------------------------------------------------------- 0649 // Public functions 0650 //--------------------------------------------------------------------- 0651 0652 uint modXShift() 0653 { 0654 return ShiftMask; 0655 } 0656 uint modXCtrl() 0657 { 0658 return ControlMask; 0659 } 0660 uint modXAlt() 0661 { 0662 if (!g_bInitializedMods) { 0663 initializeMods(); 0664 } 0665 return g_alt_mask; 0666 } 0667 uint modXMeta() 0668 { 0669 if (!g_bInitializedMods) { 0670 initializeMods(); 0671 } 0672 return g_meta_mask; 0673 } 0674 0675 uint modXNumLock() 0676 { 0677 if (!g_bInitializedMods) { 0678 initializeMods(); 0679 } 0680 return g_modXNumLock; 0681 } 0682 uint modXLock() 0683 { 0684 return LockMask; 0685 } 0686 uint modXScrollLock() 0687 { 0688 if (!g_bInitializedMods) { 0689 initializeMods(); 0690 } 0691 return g_modXScrollLock; 0692 } 0693 uint modXModeSwitch() 0694 { 0695 if (!g_bInitializedMods) { 0696 initializeMods(); 0697 } 0698 return g_modXModeSwitch; 0699 } 0700 0701 bool keyboardHasMetaKey() 0702 { 0703 return modXMeta() != 0; 0704 } 0705 0706 uint getModsRequired(uint sym) 0707 { 0708 if (!QX11Info::isPlatformX11()) { 0709 qCWarning(LOG_KKEYSERVER_X11) << "X11 implementation of KKeyServer accessed from non-X11 platform! This is an application bug."; 0710 return 0; 0711 } 0712 uint mod = 0; 0713 0714 // FIXME: This might not be true on all keyboard layouts! 0715 if (sym == XK_Sys_Req) { 0716 return Qt::ALT; 0717 } 0718 if (sym == XK_Break) { 0719 return Qt::CTRL; 0720 } 0721 0722 if (sym < 0x3000) { 0723 QChar c(sym); 0724 if (c.isLetter() && c.toLower() != c.toUpper() && sym == c.toUpper().unicode()) { 0725 return Qt::SHIFT; 0726 } 0727 } 0728 0729 uchar code = XKeysymToKeycode(QX11Info::display(), sym); 0730 if (code) { 0731 // need to check index 0 before the others, so that a null-mod 0732 // can take precedence over the others, in case the modified 0733 // key produces the same symbol. 0734 if (sym == XKeycodeToKeysym(QX11Info::display(), code, 0)) { 0735 ; 0736 } else if (sym == XKeycodeToKeysym(QX11Info::display(), code, 1)) { 0737 mod = Qt::SHIFT; 0738 } else if (sym == XKeycodeToKeysym(QX11Info::display(), code, 2)) { 0739 mod = MODE_SWITCH; 0740 } else if (sym == XKeycodeToKeysym(QX11Info::display(), code, 3)) { 0741 mod = Qt::SHIFT | MODE_SWITCH; 0742 } 0743 } 0744 return mod; 0745 } 0746 0747 bool keyQtToCodeX(int keyQt, int *keyCode) 0748 { 0749 if (!QX11Info::isPlatformX11()) { 0750 qCWarning(LOG_KKEYSERVER_X11) << "X11 implementation of KKeyServer accessed from non-X11 platform! This is an application bug."; 0751 return false; 0752 } 0753 int sym; 0754 uint mod; 0755 keyQtToSymX(keyQt, &sym); 0756 keyQtToModX(keyQt, &mod); 0757 0758 // Get any extra mods required by the sym. 0759 // E.g., XK_Plus requires SHIFT on the en layout. 0760 uint modExtra = getModsRequired(sym); 0761 // Get the X modifier equivalent. 0762 if (!sym || !keyQtToModX((keyQt & Qt::KeyboardModifierMask) | modExtra, &mod)) { 0763 *keyCode = 0; 0764 return false; 0765 } 0766 0767 *keyCode = XKeysymToKeycode(QX11Info::display(), sym); 0768 return true; 0769 } 0770 0771 bool keyQtToSymX(int keyQt, int *keySym) 0772 { 0773 int symQt = keyQt & ~Qt::KeyboardModifierMask; 0774 0775 if (keyQt & Qt::KeypadModifier) { 0776 if (symQt >= Qt::Key_0 && symQt <= Qt::Key_9) { 0777 *keySym = XK_KP_0 + (symQt - Qt::Key_0); 0778 return true; 0779 } 0780 } else { 0781 if (symQt < 0x1000) { 0782 *keySym = QChar(symQt).toUpper().unicode(); 0783 return true; 0784 } 0785 } 0786 0787 for (const TransKey &tk : g_rgQtToSymX) { 0788 if (tk.keySymQt == symQt) { 0789 if ((keyQt & Qt::KeypadModifier) && !is_keypad_key(tk.keySymX)) { 0790 continue; 0791 } 0792 *keySym = tk.keySymX; 0793 return true; 0794 } 0795 } 0796 0797 *keySym = 0; 0798 if (symQt != Qt::Key_Shift && symQt != Qt::Key_Control && symQt != Qt::Key_Alt && symQt != Qt::Key_Meta && symQt != Qt::Key_Direction_L 0799 && symQt != Qt::Key_Direction_R) { 0800 // qCDebug(LOG_KKEYSERVER_X11) << "Sym::initQt( " << QString::number(keyQt,16) << " ): failed to convert key."; 0801 } 0802 return false; 0803 } 0804 0805 bool symXModXToKeyQt(uint32_t keySym, uint16_t modX, int *keyQt) 0806 { 0807 int keyModQt = 0; 0808 *keyQt = Qt::Key_unknown; 0809 0810 if (keySym >= XK_KP_0 && keySym <= XK_KP_9) { 0811 // numeric keypad keys 0812 *keyQt = Qt::Key_0 + ((int)keySym - XK_KP_0); 0813 } else if (keySym < 0x1000) { 0814 if (keySym >= 'a' && keySym <= 'z') { 0815 *keyQt = QChar(keySym).toUpper().unicode(); 0816 } else { 0817 *keyQt = keySym; 0818 } 0819 } 0820 0821 else if (keySym < 0x3000) { 0822 *keyQt = keySym; 0823 } 0824 0825 else { 0826 for (const TransKey &tk : g_rgQtToSymX) { 0827 if (tk.keySymX == keySym) { 0828 *keyQt = tk.keySymQt; 0829 break; 0830 } 0831 } 0832 } 0833 0834 if (*keyQt == Qt::Key_unknown) { 0835 return false; 0836 } 0837 0838 if (modXToQt(modX, &keyModQt)) { 0839 *keyQt |= keyModQt; 0840 if (is_keypad_key(keySym)) { 0841 *keyQt |= Qt::KeypadModifier; 0842 } 0843 return true; 0844 } 0845 return false; 0846 } 0847 0848 #if KWINDOWSYSTEM_BUILD_DEPRECATED_SINCE(5, 38) 0849 bool symXToKeyQt(uint keySym, int *keyQt) 0850 { 0851 return symXModXToKeyQt(keySym, 0, keyQt) & ~Qt::KeyboardModifierMask; 0852 } 0853 #endif 0854 0855 bool keyQtToModX(int modQt, uint *modX) 0856 { 0857 if (!g_bInitializedMods) { 0858 initializeMods(); 0859 } 0860 0861 *modX = 0; 0862 for (int i = 0; i < 4; i++) { 0863 if (modQt & g_rgX11ModInfo[i].modQt) { 0864 if (g_rgX11ModInfo[i].modX) { 0865 *modX |= g_rgX11ModInfo[i].modX; 0866 } else { 0867 // The qt modifier has no x equivalent. Return false 0868 return false; 0869 } 0870 } 0871 } 0872 return true; 0873 } 0874 0875 bool modXToQt(uint modX, int *modQt) 0876 { 0877 if (!g_bInitializedMods) { 0878 initializeMods(); 0879 } 0880 0881 *modQt = 0; 0882 for (int i = 0; i < 4; i++) { 0883 if (modX & g_rgX11ModInfo[i].modX) { 0884 *modQt |= g_rgX11ModInfo[i].modQt; 0885 continue; 0886 } 0887 } 0888 return true; 0889 } 0890 0891 bool codeXToSym(uchar codeX, uint modX, uint *sym) 0892 { 0893 if (!QX11Info::isPlatformX11()) { 0894 qCWarning(LOG_KKEYSERVER_X11) << "X11 implementation of KKeyServer accessed from non-X11 platform! This is an application bug."; 0895 return false; 0896 } 0897 KeySym keySym; 0898 XKeyPressedEvent event; 0899 0900 checkDisplay(); 0901 0902 event.type = KeyPress; 0903 event.display = QX11Info::display(); 0904 event.state = modX; 0905 event.keycode = codeX; 0906 0907 XLookupString(&event, nullptr, 0, &keySym, nullptr); 0908 *sym = (uint)keySym; 0909 return true; 0910 } 0911 0912 uint accelModMaskX() 0913 { 0914 return modXShift() | modXCtrl() | modXAlt() | modXMeta(); 0915 } 0916 0917 bool xEventToQt(XEvent *e, int *keyQt) 0918 { 0919 Q_ASSERT(e->type == KeyPress || e->type == KeyRelease); 0920 0921 uchar keyCodeX = e->xkey.keycode; 0922 uint keyModX = e->xkey.state & (accelModMaskX() | MODE_SWITCH); 0923 0924 KeySym keySym; 0925 char buffer[16]; 0926 XLookupString((XKeyEvent *)e, buffer, 15, &keySym, nullptr); 0927 uint keySymX = (uint)keySym; 0928 0929 // If numlock is active and a keypad key is pressed, XOR the SHIFT state. 0930 // e.g., KP_4 => Shift+KP_Left, and Shift+KP_4 => KP_Left. 0931 if (e->xkey.state & modXNumLock()) { 0932 uint sym = XKeycodeToKeysym(QX11Info::display(), keyCodeX, 0); 0933 // TODO: what's the xor operator in c++? 0934 // If this is a keypad key, 0935 if (sym >= XK_KP_Space && sym <= XK_KP_9) { 0936 switch (sym) { 0937 // Leave the following keys unaltered 0938 // FIXME: The proper solution is to see which keysyms don't change when shifted. 0939 case XK_KP_Multiply: 0940 case XK_KP_Add: 0941 case XK_KP_Subtract: 0942 case XK_KP_Divide: 0943 break; 0944 default: 0945 if (keyModX & modXShift()) { 0946 keyModX &= ~modXShift(); 0947 } else { 0948 keyModX |= modXShift(); 0949 } 0950 } 0951 } 0952 } 0953 0954 return KKeyServer::symXModXToKeyQt(keySymX, keyModX, keyQt); 0955 } 0956 0957 bool xcbKeyPressEventToQt(xcb_generic_event_t *e, int *keyQt) 0958 { 0959 if ((e->response_type & ~0x80) != XCB_KEY_PRESS && (e->response_type & ~0x80) != XCB_KEY_RELEASE) { 0960 return false; 0961 } 0962 return xcbKeyPressEventToQt(reinterpret_cast<xcb_key_press_event_t *>(e), keyQt); 0963 } 0964 0965 bool xcbKeyPressEventToQt(xcb_key_press_event_t *e, int *keyQt) 0966 { 0967 const uint16_t keyModX = e->state & (accelModMaskX() | MODE_SWITCH); 0968 0969 xcb_key_symbols_t *symbols = xcb_key_symbols_alloc(QX11Info::connection()); 0970 0971 // We might have to use 4,5 instead of 0,1 here when mode_switch is active, just not sure how to test that. 0972 const xcb_keysym_t keySym0 = xcb_key_press_lookup_keysym(symbols, e, 0); 0973 const xcb_keysym_t keySym1 = xcb_key_press_lookup_keysym(symbols, e, 1); 0974 xcb_keysym_t keySymX; 0975 0976 if ((e->state & KKeyServer::modXNumLock()) && is_keypad_key(keySym1)) { 0977 if ((e->state & XCB_MOD_MASK_SHIFT)) { 0978 keySymX = keySym0; 0979 } else { 0980 keySymX = keySym1; 0981 } 0982 } else { 0983 keySymX = keySym0; 0984 } 0985 0986 bool ok = KKeyServer::symXModXToKeyQt(keySymX, keyModX, keyQt); 0987 0988 if ((*keyQt & Qt::ShiftModifier) && !KKeyServer::isShiftAsModifierAllowed(*keyQt)) { 0989 if (*keyQt != Qt::Key_Tab) { // KKeySequenceWidget does not map shift+tab to backtab 0990 static const int FirstLevelShift = 1; 0991 keySymX = xcb_key_symbols_get_keysym(symbols, e->detail, FirstLevelShift); 0992 KKeyServer::symXModXToKeyQt(keySymX, keyModX, keyQt); 0993 } 0994 *keyQt &= ~Qt::ShiftModifier; 0995 } 0996 0997 xcb_key_symbols_free(symbols); 0998 return ok; 0999 } 1000 1001 } // end of namespace KKeyServer block