KWindowSystem

platforms/xcb/kkeyserver.cpp
1 /*
2  SPDX-FileCopyrightText: 2001 Ellis Whitehead <[email protected]>
3 
4  Win32 port:
5  SPDX-FileCopyrightText: 2004 JarosÅ‚aw Staniek <[email protected]>
6 
7  SPDX-License-Identifier: LGPL-2.1-or-later
8 */
9 
10 #include "kkeyserver.h"
11 #include "kkeyserver_x11.h"
12 
13 #include "platforms/xcb/kwindowsystem_xcb_debug.h"
14 
15 #include <QX11Info>
16 #define XK_MISCELLANY
17 #define XK_XKB_KEYS
18 #include <X11/X.h>
19 #include <X11/Xlib.h>
20 #include <X11/Xutil.h>
21 #include <X11/keysymdef.h>
22 #include <xcb/xcb_keysyms.h>
23 #define X11_ONLY(arg) arg, // allows to omit an argument
24 
25 // #define KKEYSERVER_DEBUG 1
26 
27 namespace KKeyServer
28 {
29 //---------------------------------------------------------------------
30 // Data Structures
31 //---------------------------------------------------------------------
32 
33 struct Mod {
34  int m_mod;
35 };
36 
37 //---------------------------------------------------------------------
38 // Array Structures
39 //---------------------------------------------------------------------
40 
41 struct X11ModInfo {
42  int modQt;
43  int modX;
44 };
45 
46 struct SymVariation {
47  uint sym, symVariation;
48  bool bActive;
49 };
50 
51 struct SymName {
52  uint sym;
53  const char *psName;
54 };
55 
56 struct TransKey {
57  int keySymQt;
58  uint keySymX;
59 };
60 
61 //---------------------------------------------------------------------
62 // Arrays
63 //---------------------------------------------------------------------
64 // clang-format off
65 
66 static X11ModInfo g_rgX11ModInfo[4] = {
67  { Qt::SHIFT, X11_ONLY(ShiftMask) },
68  { Qt::CTRL, X11_ONLY(ControlMask) },
69  { Qt::ALT, X11_ONLY(Mod1Mask) },
70  { Qt::META, X11_ONLY(Mod4Mask) }
71 };
72 
73 // These are the X equivalents to the Qt keycodes 0x1000 - 0x1026
74 static const TransKey g_rgQtToSymX[] = {
75  { Qt::Key_Escape, XK_Escape },
76  { Qt::Key_Tab, XK_Tab },
77  { Qt::Key_Backtab, XK_ISO_Left_Tab },
78  { Qt::Key_Backspace, XK_BackSpace },
79  { Qt::Key_Return, XK_Return },
80  { Qt::Key_Insert, XK_Insert },
81  { Qt::Key_Delete, XK_Delete },
82  { Qt::Key_Pause, XK_Pause },
83 #ifdef sun
84  { Qt::Key_Print, XK_F22 },
85 #else
86  { Qt::Key_Print, XK_Print },
87 #endif
88  { Qt::Key_SysReq, XK_Sys_Req },
89  { Qt::Key_Home, XK_Home },
90  { Qt::Key_End, XK_End },
91  { Qt::Key_Left, XK_Left },
92  { Qt::Key_Up, XK_Up },
93  { Qt::Key_Right, XK_Right },
94  { Qt::Key_Down, XK_Down },
95  { Qt::Key_PageUp, XK_Prior },
96  { Qt::Key_PageDown, XK_Next },
97  //{ Qt::Key_Shift, 0 },
98  //{ Qt::Key_Control, 0 },
99  //{ Qt::Key_Meta, 0 },
100  //{ Qt::Key_Alt, 0 },
101  { Qt::Key_CapsLock, XK_Caps_Lock },
102  { Qt::Key_NumLock, XK_Num_Lock },
103  { Qt::Key_ScrollLock, XK_Scroll_Lock },
104  { Qt::Key_F1, XK_F1 },
105  { Qt::Key_F2, XK_F2 },
106  { Qt::Key_F3, XK_F3 },
107  { Qt::Key_F4, XK_F4 },
108  { Qt::Key_F5, XK_F5 },
109  { Qt::Key_F6, XK_F6 },
110  { Qt::Key_F7, XK_F7 },
111  { Qt::Key_F8, XK_F8 },
112  { Qt::Key_F9, XK_F9 },
113  { Qt::Key_F10, XK_F10 },
114  { Qt::Key_F11, XK_F11 },
115  { Qt::Key_F12, XK_F12 },
116  { Qt::Key_F13, XK_F13 },
117  { Qt::Key_F14, XK_F14 },
118  { Qt::Key_F15, XK_F15 },
119  { Qt::Key_F16, XK_F16 },
120  { Qt::Key_F17, XK_F17 },
121  { Qt::Key_F18, XK_F18 },
122  { Qt::Key_F19, XK_F19 },
123  { Qt::Key_F20, XK_F20 },
124  { Qt::Key_F21, XK_F21 },
125  { Qt::Key_F22, XK_F22 },
126  { Qt::Key_F23, XK_F23 },
127  { Qt::Key_F24, XK_F24 },
128  { Qt::Key_F25, XK_F25 },
129  { Qt::Key_F26, XK_F26 },
130  { Qt::Key_F27, XK_F27 },
131  { Qt::Key_F28, XK_F28 },
132  { Qt::Key_F29, XK_F29 },
133  { Qt::Key_F30, XK_F30 },
134  { Qt::Key_F31, XK_F31 },
135  { Qt::Key_F32, XK_F32 },
136  { Qt::Key_F33, XK_F33 },
137  { Qt::Key_F34, XK_F34 },
138  { Qt::Key_F35, XK_F35 },
139  { Qt::Key_Super_L, XK_Super_L },
140  { Qt::Key_Super_R, XK_Super_R },
141  { Qt::Key_Menu, XK_Menu },
142  { Qt::Key_Hyper_L, XK_Hyper_L },
143  { Qt::Key_Hyper_R, XK_Hyper_R },
144  { Qt::Key_Help, XK_Help },
145  //{ Qt::Key_Direction_L, XK_Direction_L }, These keys don't exist in X11
146  //{ Qt::Key_Direction_R, XK_Direction_R },
147 
148  { Qt::Key_Space, XK_KP_Space },
149  { Qt::Key_Tab, XK_KP_Tab },
150  { Qt::Key_Enter, XK_KP_Enter },
151  { Qt::Key_Home, XK_KP_Home },
152  { Qt::Key_Left, XK_KP_Left },
153  { Qt::Key_Up, XK_KP_Up },
154  { Qt::Key_Right, XK_KP_Right },
155  { Qt::Key_Down, XK_KP_Down },
156  { Qt::Key_PageUp, XK_KP_Prior },
157  { Qt::Key_PageDown, XK_KP_Next },
158  { Qt::Key_End, XK_KP_End },
159  { Qt::Key_Clear, XK_KP_Begin },
160  { Qt::Key_Insert, XK_KP_Insert },
161  { Qt::Key_Delete, XK_KP_Delete },
162  { Qt::Key_Equal, XK_KP_Equal },
163  { Qt::Key_Asterisk, XK_KP_Multiply },
164  { Qt::Key_Plus, XK_KP_Add },
165  { Qt::Key_Comma, XK_KP_Separator },
166  { Qt::Key_Minus, XK_KP_Subtract },
167  { Qt::Key_Period, XK_KP_Decimal },
168  { Qt::Key_Slash, XK_KP_Divide },
169 
170 // the next lines are taken on 10/2009 from X.org (X11/XF86keysym.h), defining some special
171 // multimedia keys. They are included here as not every system has them.
172 #define XF86XK_MonBrightnessUp 0x1008FF02
173 #define XF86XK_MonBrightnessDown 0x1008FF03
174 #define XF86XK_KbdLightOnOff 0x1008FF04
175 #define XF86XK_KbdBrightnessUp 0x1008FF05
176 #define XF86XK_KbdBrightnessDown 0x1008FF06
177 #define XF86XK_Standby 0x1008FF10
178 #define XF86XK_AudioLowerVolume 0x1008FF11
179 #define XF86XK_AudioMute 0x1008FF12
180 #define XF86XK_AudioRaiseVolume 0x1008FF13
181 #define XF86XK_AudioPlay 0x1008FF14
182 #define XF86XK_AudioStop 0x1008FF15
183 #define XF86XK_AudioPrev 0x1008FF16
184 #define XF86XK_AudioNext 0x1008FF17
185 #define XF86XK_HomePage 0x1008FF18
186 #define XF86XK_Mail 0x1008FF19
187 #define XF86XK_Start 0x1008FF1A
188 #define XF86XK_Search 0x1008FF1B
189 #define XF86XK_AudioRecord 0x1008FF1C
190 #define XF86XK_Calculator 0x1008FF1D
191 #define XF86XK_Memo 0x1008FF1E
192 #define XF86XK_ToDoList 0x1008FF1F
193 #define XF86XK_Calendar 0x1008FF20
194 #define XF86XK_PowerDown 0x1008FF21
195 #define XF86XK_ContrastAdjust 0x1008FF22
196 #define XF86XK_Back 0x1008FF26
197 #define XF86XK_Forward 0x1008FF27
198 #define XF86XK_Stop 0x1008FF28
199 #define XF86XK_Refresh 0x1008FF29
200 #define XF86XK_PowerOff 0x1008FF2A
201 #define XF86XK_WakeUp 0x1008FF2B
202 #define XF86XK_Eject 0x1008FF2C
203 #define XF86XK_ScreenSaver 0x1008FF2D
204 #define XF86XK_WWW 0x1008FF2E
205 #define XF86XK_Sleep 0x1008FF2F
206 #define XF86XK_Favorites 0x1008FF30
207 #define XF86XK_AudioPause 0x1008FF31
208 #define XF86XK_AudioMedia 0x1008FF32
209 #define XF86XK_MyComputer 0x1008FF33
210 #define XF86XK_LightBulb 0x1008FF35
211 #define XF86XK_Shop 0x1008FF36
212 #define XF86XK_History 0x1008FF37
213 #define XF86XK_OpenURL 0x1008FF38
214 #define XF86XK_AddFavorite 0x1008FF39
215 #define XF86XK_HotLinks 0x1008FF3A
216 #define XF86XK_BrightnessAdjust 0x1008FF3B
217 #define XF86XK_Finance 0x1008FF3C
218 #define XF86XK_Community 0x1008FF3D
219 #define XF86XK_AudioRewind 0x1008FF3E
220 #define XF86XK_BackForward 0x1008FF3F
221 #define XF86XK_Launch0 0x1008FF40
222 #define XF86XK_Launch1 0x1008FF41
223 #define XF86XK_Launch2 0x1008FF42
224 #define XF86XK_Launch3 0x1008FF43
225 #define XF86XK_Launch4 0x1008FF44
226 #define XF86XK_Launch5 0x1008FF45
227 #define XF86XK_Launch6 0x1008FF46
228 #define XF86XK_Launch7 0x1008FF47
229 #define XF86XK_Launch8 0x1008FF48
230 #define XF86XK_Launch9 0x1008FF49
231 #define XF86XK_LaunchA 0x1008FF4A
232 #define XF86XK_LaunchB 0x1008FF4B
233 #define XF86XK_LaunchC 0x1008FF4C
234 #define XF86XK_LaunchD 0x1008FF4D
235 #define XF86XK_LaunchE 0x1008FF4E
236 #define XF86XK_LaunchF 0x1008FF4F
237 #define XF86XK_ApplicationLeft 0x1008FF50
238 #define XF86XK_ApplicationRight 0x1008FF51
239 #define XF86XK_Book 0x1008FF52
240 #define XF86XK_CD 0x1008FF53
241 #define XF86XK_Calculater 0x1008FF54
242 #define XF86XK_Clear 0x1008FF55
243 #define XF86XK_ClearGrab 0x1008FE21
244 #define XF86XK_Close 0x1008FF56
245 #define XF86XK_Copy 0x1008FF57
246 #define XF86XK_Cut 0x1008FF58
247 #define XF86XK_Display 0x1008FF59
248 #define XF86XK_DOS 0x1008FF5A
249 #define XF86XK_Documents 0x1008FF5B
250 #define XF86XK_Excel 0x1008FF5C
251 #define XF86XK_Explorer 0x1008FF5D
252 #define XF86XK_Game 0x1008FF5E
253 #define XF86XK_Go 0x1008FF5F
254 #define XF86XK_iTouch 0x1008FF60
255 #define XF86XK_LogOff 0x1008FF61
256 #define XF86XK_Market 0x1008FF62
257 #define XF86XK_Meeting 0x1008FF63
258 #define XF86XK_MenuKB 0x1008FF65
259 #define XF86XK_MenuPB 0x1008FF66
260 #define XF86XK_MySites 0x1008FF67
261 #define XF86XK_News 0x1008FF69
262 #define XF86XK_OfficeHome 0x1008FF6A
263 #define XF86XK_Option 0x1008FF6C
264 #define XF86XK_Paste 0x1008FF6D
265 #define XF86XK_Phone 0x1008FF6E
266 #define XF86XK_Reply 0x1008FF72
267 #define XF86XK_Reload 0x1008FF73
268 #define XF86XK_RotateWindows 0x1008FF74
269 #define XF86XK_RotationPB 0x1008FF75
270 #define XF86XK_RotationKB 0x1008FF76
271 #define XF86XK_Save 0x1008FF77
272 #define XF86XK_Send 0x1008FF7B
273 #define XF86XK_Spell 0x1008FF7C
274 #define XF86XK_SplitScreen 0x1008FF7D
275 #define XF86XK_Support 0x1008FF7E
276 #define XF86XK_TaskPane 0x1008FF7F
277 #define XF86XK_Terminal 0x1008FF80
278 #define XF86XK_Tools 0x1008FF81
279 #define XF86XK_Travel 0x1008FF82
280 #define XF86XK_Video 0x1008FF87
281 #define XF86XK_Word 0x1008FF89
282 #define XF86XK_Xfer 0x1008FF8A
283 #define XF86XK_ZoomIn 0x1008FF8B
284 #define XF86XK_ZoomOut 0x1008FF8C
285 #define XF86XK_Away 0x1008FF8D
286 #define XF86XK_Messenger 0x1008FF8E
287 #define XF86XK_WebCam 0x1008FF8F
288 #define XF86XK_MailForward 0x1008FF90
289 #define XF86XK_Pictures 0x1008FF91
290 #define XF86XK_Music 0x1008FF92
291 #define XF86XK_Battery 0x1008FF93
292 #define XF86XK_Bluetooth 0x1008FF94
293 #define XF86XK_WLAN 0x1008FF95
294 #define XF86XK_UWB 0x1008FF96
295 #define XF86XK_AudioForward 0x1008FF97
296 #define XF86XK_AudioRepeat 0x1008FF98
297 #define XF86XK_AudioRandomPlay 0x1008FF99
298 #define XF86XK_Subtitle 0x1008FF9A
299 #define XF86XK_AudioCycleTrack 0x1008FF9B
300 #define XF86XK_Time 0x1008FF9F
301 #define XF86XK_Select 0x1008FFA0
302 #define XF86XK_View 0x1008FFA1
303 #define XF86XK_TopMenu 0x1008FFA2
304 #define XF86XK_Suspend 0x1008FFA7
305 #define XF86XK_Hibernate 0x1008FFA8
306 #define XF86XK_TouchpadToggle 0x1008FFA9
307 #define XF86XK_TouchpadOn 0x1008FFB0
308 #define XF86XK_TouchpadOff 0x1008FFB1
309 #define XF86XK_AudioMicMute 0x1008FFB2
310 // end of XF86keysyms.h
311 
312  // All of the stuff below really has to match qxcbkeyboard.cpp in Qt!
313  { Qt::Key_Back, XF86XK_Back },
314  { Qt::Key_Forward, XF86XK_Forward },
315  { Qt::Key_Stop, XF86XK_Stop },
316  { Qt::Key_Refresh, XF86XK_Refresh },
317  { Qt::Key_Favorites, XF86XK_Favorites },
318  { Qt::Key_LaunchMedia, XF86XK_AudioMedia },
319  { Qt::Key_OpenUrl, XF86XK_OpenURL },
320  { Qt::Key_HomePage, XF86XK_HomePage },
321  { Qt::Key_Search, XF86XK_Search },
322  { Qt::Key_VolumeDown, XF86XK_AudioLowerVolume },
323  { Qt::Key_VolumeMute, XF86XK_AudioMute },
324  { Qt::Key_VolumeUp, XF86XK_AudioRaiseVolume },
325  { Qt::Key_MediaPlay, XF86XK_AudioPlay },
326  { Qt::Key_MediaStop, XF86XK_AudioStop },
327  { Qt::Key_MediaPrevious, XF86XK_AudioPrev },
328  { Qt::Key_MediaNext, XF86XK_AudioNext },
329  { Qt::Key_MediaRecord, XF86XK_AudioRecord },
330  { Qt::Key_MediaPause, XF86XK_AudioPause },
331  { Qt::Key_LaunchMail, XF86XK_Mail },
332  { Qt::Key_Launch0, XF86XK_MyComputer },
333  { Qt::Key_Launch1, XF86XK_Calculator },
334  { Qt::Key_Memo, XF86XK_Memo },
335  { Qt::Key_ToDoList, XF86XK_ToDoList },
336  { Qt::Key_Calendar, XF86XK_Calendar },
337  { Qt::Key_PowerDown, XF86XK_PowerDown },
338  { Qt::Key_ContrastAdjust, XF86XK_ContrastAdjust },
339  { Qt::Key_Standby, XF86XK_Standby },
340  { Qt::Key_MonBrightnessUp, XF86XK_MonBrightnessUp },
341  { Qt::Key_MonBrightnessDown, XF86XK_MonBrightnessDown },
342  { Qt::Key_KeyboardLightOnOff, XF86XK_KbdLightOnOff },
343  { Qt::Key_KeyboardBrightnessUp, XF86XK_KbdBrightnessUp },
344  { Qt::Key_KeyboardBrightnessDown, XF86XK_KbdBrightnessDown },
345  { Qt::Key_PowerOff, XF86XK_PowerOff },
346  { Qt::Key_WakeUp, XF86XK_WakeUp },
347  { Qt::Key_Eject, XF86XK_Eject },
348  { Qt::Key_ScreenSaver, XF86XK_ScreenSaver },
349  { Qt::Key_WWW, XF86XK_WWW },
350  { Qt::Key_Sleep, XF86XK_Sleep },
351  { Qt::Key_LightBulb, XF86XK_LightBulb },
352  { Qt::Key_Shop, XF86XK_Shop },
353  { Qt::Key_History, XF86XK_History },
354  { Qt::Key_AddFavorite, XF86XK_AddFavorite },
355  { Qt::Key_HotLinks, XF86XK_HotLinks },
356  { Qt::Key_BrightnessAdjust, XF86XK_BrightnessAdjust },
357  { Qt::Key_Finance, XF86XK_Finance },
358  { Qt::Key_Community, XF86XK_Community },
359  { Qt::Key_AudioRewind, XF86XK_AudioRewind },
360  { Qt::Key_BackForward, XF86XK_BackForward },
361  { Qt::Key_ApplicationLeft, XF86XK_ApplicationLeft },
362  { Qt::Key_ApplicationRight, XF86XK_ApplicationRight },
363  { Qt::Key_Book, XF86XK_Book },
364  { Qt::Key_CD, XF86XK_CD },
365  { Qt::Key_Calculator, XF86XK_Calculater },
366  { Qt::Key_Clear, XF86XK_Clear },
367  { Qt::Key_ClearGrab, XF86XK_ClearGrab },
368  { Qt::Key_Close, XF86XK_Close },
369  { Qt::Key_Copy, XF86XK_Copy },
370  { Qt::Key_Cut, XF86XK_Cut },
371  { Qt::Key_Display, XF86XK_Display },
372  { Qt::Key_DOS, XF86XK_DOS },
373  { Qt::Key_Documents, XF86XK_Documents },
374  { Qt::Key_Excel, XF86XK_Excel },
375  { Qt::Key_Explorer, XF86XK_Explorer },
376  { Qt::Key_Game, XF86XK_Game },
377  { Qt::Key_Go, XF86XK_Go },
378  { Qt::Key_iTouch, XF86XK_iTouch },
379  { Qt::Key_LogOff, XF86XK_LogOff },
380  { Qt::Key_Market, XF86XK_Market },
381  { Qt::Key_Meeting, XF86XK_Meeting },
382  { Qt::Key_MenuKB, XF86XK_MenuKB },
383  { Qt::Key_MenuPB, XF86XK_MenuPB },
384  { Qt::Key_MySites, XF86XK_MySites },
385  { Qt::Key_News, XF86XK_News },
386  { Qt::Key_OfficeHome, XF86XK_OfficeHome },
387  { Qt::Key_Option, XF86XK_Option },
388  { Qt::Key_Paste, XF86XK_Paste },
389  { Qt::Key_Phone, XF86XK_Phone },
390  { Qt::Key_Reply, XF86XK_Reply },
391  { Qt::Key_Reload, XF86XK_Reload },
392  { Qt::Key_RotateWindows, XF86XK_RotateWindows },
393  { Qt::Key_RotationPB, XF86XK_RotationPB },
394  { Qt::Key_RotationKB, XF86XK_RotationKB },
395  { Qt::Key_Save, XF86XK_Save },
396  { Qt::Key_Send, XF86XK_Send },
397  { Qt::Key_Spell, XF86XK_Spell },
398  { Qt::Key_SplitScreen, XF86XK_SplitScreen },
399  { Qt::Key_Support, XF86XK_Support },
400  { Qt::Key_TaskPane, XF86XK_TaskPane },
401  { Qt::Key_Terminal, XF86XK_Terminal },
402  { Qt::Key_Tools, XF86XK_Tools },
403  { Qt::Key_Travel, XF86XK_Travel },
404  { Qt::Key_Video, XF86XK_Video },
405  { Qt::Key_Word, XF86XK_Word },
406  { Qt::Key_Xfer, XF86XK_Xfer },
407  { Qt::Key_ZoomIn, XF86XK_ZoomIn },
408  { Qt::Key_ZoomOut, XF86XK_ZoomOut },
409  { Qt::Key_Away, XF86XK_Away },
410  { Qt::Key_Messenger, XF86XK_Messenger },
411  { Qt::Key_WebCam, XF86XK_WebCam },
412  { Qt::Key_MailForward, XF86XK_MailForward },
413  { Qt::Key_Pictures, XF86XK_Pictures },
414  { Qt::Key_Music, XF86XK_Music },
415  { Qt::Key_Battery, XF86XK_Battery },
416  { Qt::Key_Bluetooth, XF86XK_Bluetooth },
417  { Qt::Key_WLAN, XF86XK_WLAN },
418  { Qt::Key_UWB, XF86XK_UWB },
419  { Qt::Key_AudioForward, XF86XK_AudioForward },
420  { Qt::Key_AudioRepeat, XF86XK_AudioRepeat },
421  { Qt::Key_AudioRandomPlay, XF86XK_AudioRandomPlay },
422  { Qt::Key_Subtitle, XF86XK_Subtitle },
423  { Qt::Key_AudioCycleTrack, XF86XK_AudioCycleTrack },
424  { Qt::Key_Time, XF86XK_Time },
425  { Qt::Key_Select, XF86XK_Select },
426  { Qt::Key_View, XF86XK_View },
427  { Qt::Key_TopMenu, XF86XK_TopMenu },
428  { Qt::Key_Bluetooth, XF86XK_Bluetooth },
429  { Qt::Key_Suspend, XF86XK_Suspend },
430  { Qt::Key_Hibernate, XF86XK_Hibernate },
431  { Qt::Key_TouchpadToggle, XF86XK_TouchpadToggle },
432  { Qt::Key_TouchpadOn, XF86XK_TouchpadOn },
433  { Qt::Key_TouchpadOff, XF86XK_TouchpadOff },
434  { Qt::Key_MicMute, XF86XK_AudioMicMute },
435  { Qt::Key_Launch2, XF86XK_Launch0 },
436  { Qt::Key_Launch3, XF86XK_Launch1 },
437  { Qt::Key_Launch4, XF86XK_Launch2 },
438  { Qt::Key_Launch5, XF86XK_Launch3 },
439  { Qt::Key_Launch6, XF86XK_Launch4 },
440  { Qt::Key_Launch7, XF86XK_Launch5 },
441  { Qt::Key_Launch8, XF86XK_Launch6 },
442  { Qt::Key_Launch9, XF86XK_Launch7 },
443  { Qt::Key_LaunchA, XF86XK_Launch8 },
444  { Qt::Key_LaunchB, XF86XK_Launch9 },
445  { Qt::Key_LaunchC, XF86XK_LaunchA },
446  { Qt::Key_LaunchD, XF86XK_LaunchB },
447  { Qt::Key_LaunchE, XF86XK_LaunchC },
448  { Qt::Key_LaunchF, XF86XK_LaunchD },
449 };
450 // clang-format on
451 
452 //---------------------------------------------------------------------
453 // Debugging
454 //---------------------------------------------------------------------
455 #ifndef NDEBUG
456 inline void checkDisplay()
457 {
458  // Some non-GUI apps might try to use us.
459  if (!QX11Info::display()) {
460  qCCritical(LOG_KKEYSERVER_X11) << "QX11Info::display() returns 0. I'm probably going to crash now.";
461  qCCritical(LOG_KKEYSERVER_X11) << "If this is a KApplication initialized without GUI stuff, change it to be "
462  "initialized with GUI stuff.";
463  }
464 }
465 #else // NDEBUG
466 #define checkDisplay()
467 #endif
468 
469 //---------------------------------------------------------------------
470 // Initialization
471 //---------------------------------------------------------------------
472 
473 static bool g_bInitializedMods;
474 static uint g_modXNumLock, g_modXScrollLock, g_modXModeSwitch, g_alt_mask, g_meta_mask, g_super_mask, g_hyper_mask;
475 
477 {
478  // Reinitialize the masks
479  g_modXNumLock = 0;
480  g_modXScrollLock = 0;
481  g_modXModeSwitch = 0;
482  g_alt_mask = 0;
483  g_meta_mask = 0;
484  g_super_mask = 0;
485  g_hyper_mask = 0;
486 
487  if (!QX11Info::isPlatformX11()) {
488  qCWarning(LOG_KKEYSERVER_X11) << "X11 implementation of KKeyServer accessed from non-X11 platform! This is an application bug.";
489  g_bInitializedMods = true;
490  return false;
491  }
492 
493  checkDisplay();
494  XModifierKeymap *xmk = XGetModifierMapping(QX11Info::display());
495 
496  int min_keycode;
497  int max_keycode;
498  int keysyms_per_keycode = 0;
499 
500  XDisplayKeycodes(QX11Info::display(), &min_keycode, &max_keycode);
501  XFree(XGetKeyboardMapping(QX11Info::display(), min_keycode, 1, &keysyms_per_keycode));
502 
503  for (int i = Mod1MapIndex; i < 8; i++) {
504  uint mask = (1 << i);
505  uint keySymX = NoSymbol;
506 
507  // This used to be only XKeycodeToKeysym( ... , 0 ), but that fails with XFree4.3.99
508  // and X.org R6.7 , where for some reason only ( ... , 1 ) works. I have absolutely no
509  // idea what the problem is, but searching all possibilities until something valid is
510  // found fixes the problem.
511  for (int j = 0; j < xmk->max_keypermod; ++j) {
512  for (int k = 0; k < keysyms_per_keycode; ++k) {
513  keySymX = XKeycodeToKeysym(QX11Info::display(), xmk->modifiermap[xmk->max_keypermod * i + j], k);
514 
515  switch (keySymX) {
516  case XK_Alt_L:
517  case XK_Alt_R:
518  g_alt_mask |= mask;
519  break;
520 
521  case XK_Super_L:
522  case XK_Super_R:
523  g_super_mask |= mask;
524  break;
525 
526  case XK_Hyper_L:
527  case XK_Hyper_R:
528  g_hyper_mask |= mask;
529  break;
530 
531  case XK_Meta_L:
532  case XK_Meta_R:
533  g_meta_mask |= mask;
534  break;
535 
536  case XK_Num_Lock:
537  g_modXNumLock |= mask;
538  break;
539  case XK_Scroll_Lock:
540  g_modXScrollLock |= mask;
541  break;
542  case XK_Mode_switch:
543  g_modXModeSwitch |= mask;
544  break;
545  }
546  }
547  }
548  }
549 
550 #ifdef KKEYSERVER_DEBUG
551  qCDebug(LOG_KKEYSERVER_X11) << "Alt:" << g_alt_mask;
552  qCDebug(LOG_KKEYSERVER_X11) << "Meta:" << g_meta_mask;
553  qCDebug(LOG_KKEYSERVER_X11) << "Super:" << g_super_mask;
554  qCDebug(LOG_KKEYSERVER_X11) << "Hyper:" << g_hyper_mask;
555  qCDebug(LOG_KKEYSERVER_X11) << "NumLock:" << g_modXNumLock;
556  qCDebug(LOG_KKEYSERVER_X11) << "ScrollLock:" << g_modXScrollLock;
557  qCDebug(LOG_KKEYSERVER_X11) << "ModeSwitch:" << g_modXModeSwitch;
558 #endif
559 
560  // Check if hyper overlaps with super or meta or alt
561  if (g_hyper_mask & (g_super_mask | g_meta_mask | g_alt_mask)) {
562 #ifdef KKEYSERVER_DEBUG
563  qCDebug(LOG_KKEYSERVER_X11) << "Hyper conflicts with super, meta or alt.";
564 #endif
565  // Remove the conflicting masks
566  g_hyper_mask &= ~(g_super_mask | g_meta_mask | g_alt_mask);
567  }
568 
569  // Check if super overlaps with meta or alt
570  if (g_super_mask & (g_meta_mask | g_alt_mask)) {
571 #ifdef KKEYSERVER_DEBUG
572  qCDebug(LOG_KKEYSERVER_X11) << "Super conflicts with meta or alt.";
573 #endif
574  // Remove the conflicting masks
575  g_super_mask &= ~(g_meta_mask | g_alt_mask);
576  }
577 
578  // Check if meta overlaps with alt
579  if (g_meta_mask | g_alt_mask) {
580 #ifdef KKEYSERVER_DEBUG
581  qCDebug(LOG_KKEYSERVER_X11) << "Meta conflicts with alt.";
582 #endif
583  // Remove the conflicting masks
584  g_meta_mask &= ~(g_alt_mask);
585  }
586 
587  if (!g_meta_mask) {
588 #ifdef KKEYSERVER_DEBUG
589  qCDebug(LOG_KKEYSERVER_X11) << "Meta is not set or conflicted with alt.";
590 #endif
591  if (g_super_mask) {
592 #ifdef KKEYSERVER_DEBUG
593  qCDebug(LOG_KKEYSERVER_X11) << "Using super for meta";
594 #endif
595  // Use Super
596  g_meta_mask = g_super_mask;
597  } else if (g_hyper_mask) {
598 #ifdef KKEYSERVER_DEBUG
599  qCDebug(LOG_KKEYSERVER_X11) << "Using hyper for meta";
600 #endif
601  // User Hyper
602  g_meta_mask = g_hyper_mask;
603  } else {
604  // ???? Nothing left
605  g_meta_mask = 0;
606  }
607  }
608 
609 #ifdef KKEYSERVER_DEBUG
610  qCDebug(LOG_KKEYSERVER_X11) << "Alt:" << g_alt_mask;
611  qCDebug(LOG_KKEYSERVER_X11) << "Meta:" << g_meta_mask;
612  qCDebug(LOG_KKEYSERVER_X11) << "Super:" << g_super_mask;
613  qCDebug(LOG_KKEYSERVER_X11) << "Hyper:" << g_hyper_mask;
614  qCDebug(LOG_KKEYSERVER_X11) << "NumLock:" << g_modXNumLock;
615  qCDebug(LOG_KKEYSERVER_X11) << "ScrollLock:" << g_modXScrollLock;
616  qCDebug(LOG_KKEYSERVER_X11) << "ModeSwitch:" << g_modXModeSwitch;
617 #endif
618 
619  if (!g_meta_mask) {
620  qCWarning(LOG_KKEYSERVER_X11) << "Your keyboard setup doesn't provide a key to use for meta. See 'xmodmap -pm' or 'xkbcomp $DISPLAY'";
621  }
622 
623  g_rgX11ModInfo[2].modX = g_alt_mask;
624  g_rgX11ModInfo[3].modX = g_meta_mask;
625 
626  XFreeModifiermap(xmk);
627  g_bInitializedMods = true;
628 
629  return true;
630 }
631 
632 //---------------------------------------------------------------------
633 // Helper functions
634 //---------------------------------------------------------------------
635 
636 static bool is_keypad_key(xcb_keysym_t keysym)
637 {
638  return keysym >= XK_KP_Space && keysym <= XK_KP_9;
639 }
640 
641 //---------------------------------------------------------------------
642 // Public functions
643 //---------------------------------------------------------------------
644 
645 uint modXShift()
646 {
647  return ShiftMask;
648 }
649 uint modXCtrl()
650 {
651  return ControlMask;
652 }
653 uint modXAlt()
654 {
655  if (!g_bInitializedMods) {
656  initializeMods();
657  }
658  return g_alt_mask;
659 }
660 uint modXMeta()
661 {
662  if (!g_bInitializedMods) {
663  initializeMods();
664  }
665  return g_meta_mask;
666 }
667 
669 {
670  if (!g_bInitializedMods) {
671  initializeMods();
672  }
673  return g_modXNumLock;
674 }
675 uint modXLock()
676 {
677  return LockMask;
678 }
680 {
681  if (!g_bInitializedMods) {
682  initializeMods();
683  }
684  return g_modXScrollLock;
685 }
687 {
688  if (!g_bInitializedMods) {
689  initializeMods();
690  }
691  return g_modXModeSwitch;
692 }
693 
695 {
696  return modXMeta() != 0;
697 }
698 
699 uint getModsRequired(uint sym)
700 {
701  if (!QX11Info::isPlatformX11()) {
702  qCWarning(LOG_KKEYSERVER_X11) << "X11 implementation of KKeyServer accessed from non-X11 platform! This is an application bug.";
703  return 0;
704  }
705  uint mod = 0;
706 
707  // FIXME: This might not be true on all keyboard layouts!
708  if (sym == XK_Sys_Req) {
709  return Qt::ALT;
710  }
711  if (sym == XK_Break) {
712  return Qt::CTRL;
713  }
714 
715  if (sym < 0x3000) {
716  QChar c(sym);
717  if (c.isLetter() && c.toLower() != c.toUpper() && sym == c.toUpper().unicode()) {
718  return Qt::SHIFT;
719  }
720  }
721 
722  uchar code = XKeysymToKeycode(QX11Info::display(), sym);
723  if (code) {
724  // need to check index 0 before the others, so that a null-mod
725  // can take precedence over the others, in case the modified
726  // key produces the same symbol.
727  if (sym == XKeycodeToKeysym(QX11Info::display(), code, 0)) {
728  ;
729  } else if (sym == XKeycodeToKeysym(QX11Info::display(), code, 1)) {
730  mod = Qt::SHIFT;
731  } else if (sym == XKeycodeToKeysym(QX11Info::display(), code, 2)) {
732  mod = MODE_SWITCH;
733  } else if (sym == XKeycodeToKeysym(QX11Info::display(), code, 3)) {
734  mod = Qt::SHIFT | MODE_SWITCH;
735  }
736  }
737  return mod;
738 }
739 
740 bool keyQtToCodeX(int keyQt, int *keyCode)
741 {
742  if (!QX11Info::isPlatformX11()) {
743  qCWarning(LOG_KKEYSERVER_X11) << "X11 implementation of KKeyServer accessed from non-X11 platform! This is an application bug.";
744  return false;
745  }
746  int sym;
747  uint mod;
748  keyQtToSymX(keyQt, &sym);
749  keyQtToModX(keyQt, &mod);
750 
751  // Get any extra mods required by the sym.
752  // E.g., XK_Plus requires SHIFT on the en layout.
753  uint modExtra = getModsRequired(sym);
754  // Get the X modifier equivalent.
755  if (!sym || !keyQtToModX((keyQt & Qt::KeyboardModifierMask) | modExtra, &mod)) {
756  *keyCode = 0;
757  return false;
758  }
759 
760  *keyCode = XKeysymToKeycode(QX11Info::display(), sym);
761  return true;
762 }
763 
764 bool keyQtToSymX(int keyQt, int *keySym)
765 {
766  int symQt = keyQt & ~Qt::KeyboardModifierMask;
767 
768  if (keyQt & Qt::KeypadModifier) {
769  if (symQt >= Qt::Key_0 && symQt <= Qt::Key_9) {
770  *keySym = XK_KP_0 + (symQt - Qt::Key_0);
771  return true;
772  }
773  } else {
774  if (symQt < 0x1000) {
775  *keySym = QChar(symQt).toUpper().unicode();
776  return true;
777  }
778  }
779 
780  for (const TransKey &tk : g_rgQtToSymX) {
781  if (tk.keySymQt == symQt) {
782  if ((keyQt & Qt::KeypadModifier) && !is_keypad_key(tk.keySymX)) {
783  continue;
784  }
785  *keySym = tk.keySymX;
786  return true;
787  }
788  }
789 
790  *keySym = 0;
791  if (symQt != Qt::Key_Shift && symQt != Qt::Key_Control && symQt != Qt::Key_Alt && symQt != Qt::Key_Meta && symQt != Qt::Key_Direction_L
792  && symQt != Qt::Key_Direction_R) {
793  // qCDebug(LOG_KKEYSERVER_X11) << "Sym::initQt( " << QString::number(keyQt,16) << " ): failed to convert key.";
794  }
795  return false;
796 }
797 
798 bool symXModXToKeyQt(uint32_t keySym, uint16_t modX, int *keyQt)
799 {
800  int keyModQt = 0;
801  *keyQt = Qt::Key_unknown;
802 
803  if (keySym >= XK_KP_0 && keySym <= XK_KP_9) {
804  // numeric keypad keys
805  *keyQt = Qt::Key_0 + ((int)keySym - XK_KP_0);
806  } else if (keySym < 0x1000) {
807  if (keySym >= 'a' && keySym <= 'z') {
808  *keyQt = QChar(keySym).toUpper().unicode();
809  } else {
810  *keyQt = keySym;
811  }
812  }
813 
814  else if (keySym < 0x3000) {
815  *keyQt = keySym;
816  }
817 
818  else {
819  for (const TransKey &tk : g_rgQtToSymX) {
820  if (tk.keySymX == keySym) {
821  *keyQt = tk.keySymQt;
822  break;
823  }
824  }
825  }
826 
827  if (*keyQt == Qt::Key_unknown) {
828  return false;
829  }
830 
831  if (modXToQt(modX, &keyModQt)) {
832  *keyQt |= keyModQt;
833  if (is_keypad_key(keySym)) {
834  *keyQt |= Qt::KeypadModifier;
835  }
836  return true;
837  }
838  return false;
839 }
840 
841 #if KWINDOWSYSTEM_BUILD_DEPRECATED_SINCE(5, 38)
842 bool symXToKeyQt(uint keySym, int *keyQt)
843 {
844  return symXModXToKeyQt(keySym, 0, keyQt) & ~Qt::KeyboardModifierMask;
845 }
846 #endif
847 
848 bool keyQtToModX(int modQt, uint *modX)
849 {
850  if (!g_bInitializedMods) {
851  initializeMods();
852  }
853 
854  *modX = 0;
855  for (int i = 0; i < 4; i++) {
856  if (modQt & g_rgX11ModInfo[i].modQt) {
857  if (g_rgX11ModInfo[i].modX) {
858  *modX |= g_rgX11ModInfo[i].modX;
859  } else {
860  // The qt modifier has no x equivalent. Return false
861  return false;
862  }
863  }
864  }
865  return true;
866 }
867 
868 bool modXToQt(uint modX, int *modQt)
869 {
870  if (!g_bInitializedMods) {
871  initializeMods();
872  }
873 
874  *modQt = 0;
875  for (int i = 0; i < 4; i++) {
876  if (modX & g_rgX11ModInfo[i].modX) {
877  *modQt |= g_rgX11ModInfo[i].modQt;
878  continue;
879  }
880  }
881  return true;
882 }
883 
884 bool codeXToSym(uchar codeX, uint modX, uint *sym)
885 {
886  if (!QX11Info::isPlatformX11()) {
887  qCWarning(LOG_KKEYSERVER_X11) << "X11 implementation of KKeyServer accessed from non-X11 platform! This is an application bug.";
888  return false;
889  }
890  KeySym keySym;
891  XKeyPressedEvent event;
892 
893  checkDisplay();
894 
895  event.type = KeyPress;
896  event.display = QX11Info::display();
897  event.state = modX;
898  event.keycode = codeX;
899 
900  XLookupString(&event, nullptr, 0, &keySym, nullptr);
901  *sym = (uint)keySym;
902  return true;
903 }
904 
906 {
907  return modXShift() | modXCtrl() | modXAlt() | modXMeta();
908 }
909 
910 bool xEventToQt(XEvent *e, int *keyQt)
911 {
912  Q_ASSERT(e->type == KeyPress || e->type == KeyRelease);
913 
914  uchar keyCodeX = e->xkey.keycode;
915  uint keyModX = e->xkey.state & (accelModMaskX() | MODE_SWITCH);
916 
917  KeySym keySym;
918  char buffer[16];
919  XLookupString((XKeyEvent *)e, buffer, 15, &keySym, nullptr);
920  uint keySymX = (uint)keySym;
921 
922  // If numlock is active and a keypad key is pressed, XOR the SHIFT state.
923  // e.g., KP_4 => Shift+KP_Left, and Shift+KP_4 => KP_Left.
924  if (e->xkey.state & modXNumLock()) {
925  uint sym = XKeycodeToKeysym(QX11Info::display(), keyCodeX, 0);
926  // TODO: what's the xor operator in c++?
927  // If this is a keypad key,
928  if (sym >= XK_KP_Space && sym <= XK_KP_9) {
929  switch (sym) {
930  // Leave the following keys unaltered
931  // FIXME: The proper solution is to see which keysyms don't change when shifted.
932  case XK_KP_Multiply:
933  case XK_KP_Add:
934  case XK_KP_Subtract:
935  case XK_KP_Divide:
936  break;
937  default:
938  if (keyModX & modXShift()) {
939  keyModX &= ~modXShift();
940  } else {
941  keyModX |= modXShift();
942  }
943  }
944  }
945  }
946 
947  return KKeyServer::symXModXToKeyQt(keySymX, keyModX, keyQt);
948 }
949 
950 bool xcbKeyPressEventToQt(xcb_generic_event_t *e, int *keyQt)
951 {
952  if ((e->response_type & ~0x80) != XCB_KEY_PRESS && (e->response_type & ~0x80) != XCB_KEY_RELEASE) {
953  return false;
954  }
955  return xcbKeyPressEventToQt(reinterpret_cast<xcb_key_press_event_t *>(e), keyQt);
956 }
957 
958 bool xcbKeyPressEventToQt(xcb_key_press_event_t *e, int *keyQt)
959 {
960  const uint16_t keyModX = e->state & (accelModMaskX() | MODE_SWITCH);
961 
962  xcb_key_symbols_t *symbols = xcb_key_symbols_alloc(QX11Info::connection());
963 
964  // We might have to use 4,5 instead of 0,1 here when mode_switch is active, just not sure how to test that.
965  const xcb_keysym_t keySym0 = xcb_key_press_lookup_keysym(symbols, e, 0);
966  const xcb_keysym_t keySym1 = xcb_key_press_lookup_keysym(symbols, e, 1);
967  xcb_keysym_t keySymX;
968 
969  if ((e->state & KKeyServer::modXNumLock()) && is_keypad_key(keySym1)) {
970  if ((e->state & XCB_MOD_MASK_SHIFT)) {
971  keySymX = keySym0;
972  } else {
973  keySymX = keySym1;
974  }
975  } else {
976  keySymX = keySym0;
977  }
978 
979  bool ok = KKeyServer::symXModXToKeyQt(keySymX, keyModX, keyQt);
980 
981  if ((*keyQt & Qt::ShiftModifier) && !KKeyServer::isShiftAsModifierAllowed(*keyQt)) {
982  if (*keyQt != Qt::Key_Tab) { // KKeySequenceWidget does not map shift+tab to backtab
983  static const int FirstLevelShift = 1;
984  keySymX = xcb_key_symbols_get_keysym(symbols, e->detail, FirstLevelShift);
985  KKeyServer::symXModXToKeyQt(keySymX, keyModX, keyQt);
986  }
987  *keyQt &= ~Qt::ShiftModifier;
988  }
989 
990  xcb_key_symbols_free(symbols);
991  return ok;
992 }
993 
994 } // end of namespace KKeyServer block
KeyboardModifierMask
uint modXShift()
Returns the X11 Shift modifier mask/flag.
bool keyQtToSymX(int keyQt, int *keySym)
Extracts the symbol from the given Qt key and converts it to an X11 symbol + modifiers.
A collection of functions for the conversion of key presses and their modifiers from the window syste...
Definition: kkeyserver.cpp:14
bool isShiftAsModifierAllowed(int keyQt)
Test if the shift modifier should be recorded for a given key.
Definition: kkeyserver.cpp:93
bool initializeMods()
Initialises the values to return for the mod*() functions below.
uint modXAlt()
Returns the X11 Alt (Mod1) modifier mask/flag.
uint accelModMaskX()
Returns bitwise OR&#39;ed mask containing Shift, Ctrl, Alt, and Win (if available).
uint modXCtrl()
Returns the X11 Ctrl modifier mask/flag.
bool isLetter() const const
bool keyQtToCodeX(int keyQt, int *keyCode)
Extracts the code from the given Qt key.
bool symXModXToKeyQt(uint32_t keySym, uint16_t modX, int *keyQt)
Converts the given symbol and modifier combination to a Qt key code.
bool symXToKeyQt(uint keySym, int *keyQt)
Converts the given symbol to a Qt key code.
bool keyQtToModX(int modQt, uint *modX)
Extracts the modifiers from the given Qt key and converts them in a mask of X11 modifiers.
ushort unicode() const const
QChar toLower() const const
uint modXLock()
Returns the X11 Lock modifier mask/flag.
bool xcbKeyPressEventToQt(xcb_generic_event_t *e, int *keyQt)
Converts an XCB keypress event into a Qt key + modifier code.
uint modXScrollLock()
Returns the X11 ScrollLock modifier mask/flag.
QChar toUpper() const const
bool keyboardHasMetaKey()
Returns true if the current keyboard layout supports the Meta key.
uint modXNumLock()
Returns the X11 NumLock modifier mask/flag.
uint modXMeta()
Returns the X11 Win (Mod3) modifier mask/flag.
bool modXToQt(uint modX, int *modQt)
Converts the mask of ORed X11 modifiers to a mask of ORed Qt key code modifiers.
uint modXModeSwitch()
Returns the X11 Mode_switch modifier mask/flag.
Key_Escape
bool xEventToQt(XEvent *e, int *keyQt)
Converts an X keypress event into a Qt key + modifier code.
This file is part of the KDE documentation.
Documentation copyright © 1996-2021 The KDE developers.
Generated on Fri Oct 15 2021 22:41:49 by doxygen 1.8.11 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.