2652e887553be821be3205471e046b34bf4ad32e
[profile/ivi/qtbase.git] / src / plugins / platforms / xcb / qxcbkeyboard.cpp
1 /****************************************************************************
2 **
3 ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
4 ** Contact: http://www.qt-project.org/
5 **
6 ** This file is part of the plugins of the Qt Toolkit.
7 **
8 ** $QT_BEGIN_LICENSE:LGPL$
9 ** GNU Lesser General Public License Usage
10 ** This file may be used under the terms of the GNU Lesser General Public
11 ** License version 2.1 as published by the Free Software Foundation and
12 ** appearing in the file LICENSE.LGPL included in the packaging of this
13 ** file. Please review the following information to ensure the GNU Lesser
14 ** General Public License version 2.1 requirements will be met:
15 ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
16 **
17 ** In addition, as a special exception, Nokia gives you certain additional
18 ** rights. These rights are described in the Nokia Qt LGPL Exception
19 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
20 **
21 ** GNU General Public License Usage
22 ** Alternatively, this file may be used under the terms of the GNU General
23 ** Public License version 3.0 as published by the Free Software Foundation
24 ** and appearing in the file LICENSE.GPL included in the packaging of this
25 ** file. Please review the following information to ensure the GNU General
26 ** Public License version 3.0 requirements will be met:
27 ** http://www.gnu.org/copyleft/gpl.html.
28 **
29 ** Other Usage
30 ** Alternatively, this file may be used in accordance with the terms and
31 ** conditions contained in a signed written agreement between you and Nokia.
32 **
33 **
34 **
35 **
36 **
37 **
38 ** $QT_END_LICENSE$
39 **
40 ****************************************************************************/
41
42 #include "qxcbkeyboard.h"
43 #include "qxcbwindow.h"
44 #include "qxcbscreen.h"
45 #include <xcb/xcb_keysyms.h>
46 #include <X11/keysym.h>
47 #include <QtGui/qwindowsysteminterface.h>
48 #include <QtCore/QTextCodec>
49 #include <QtCore/QMetaMethod>
50 #include <private/qguiapplication_p.h>
51 #include <stdio.h>
52
53 #include <qpa/qplatforminputcontext.h>
54 #include <qpa/qplatformintegration.h>
55
56 #ifndef XK_ISO_Left_Tab
57 #define XK_ISO_Left_Tab         0xFE20
58 #endif
59
60 #ifndef XK_dead_hook
61 #define XK_dead_hook            0xFE61
62 #endif
63
64 #ifndef XK_dead_horn
65 #define XK_dead_horn            0xFE62
66 #endif
67
68 #ifndef XK_Codeinput
69 #define XK_Codeinput            0xFF37
70 #endif
71
72 #ifndef XK_Kanji_Bangou
73 #define XK_Kanji_Bangou         0xFF37 /* same as codeinput */
74 #endif
75
76 // Fix old X libraries
77 #ifndef XK_KP_Home
78 #define XK_KP_Home              0xFF95
79 #endif
80 #ifndef XK_KP_Left
81 #define XK_KP_Left              0xFF96
82 #endif
83 #ifndef XK_KP_Up
84 #define XK_KP_Up                0xFF97
85 #endif
86 #ifndef XK_KP_Right
87 #define XK_KP_Right             0xFF98
88 #endif
89 #ifndef XK_KP_Down
90 #define XK_KP_Down              0xFF99
91 #endif
92 #ifndef XK_KP_Prior
93 #define XK_KP_Prior             0xFF9A
94 #endif
95 #ifndef XK_KP_Next
96 #define XK_KP_Next              0xFF9B
97 #endif
98 #ifndef XK_KP_End
99 #define XK_KP_End               0xFF9C
100 #endif
101 #ifndef XK_KP_Insert
102 #define XK_KP_Insert            0xFF9E
103 #endif
104 #ifndef XK_KP_Delete
105 #define XK_KP_Delete            0xFF9F
106 #endif
107
108 // the next lines are taken on 10/2009 from X.org (X11/XF86keysym.h), defining some special
109 // multimedia keys. They are included here as not every system has them.
110 #define XF86XK_MonBrightnessUp     0x1008FF02
111 #define XF86XK_MonBrightnessDown   0x1008FF03
112 #define XF86XK_KbdLightOnOff       0x1008FF04
113 #define XF86XK_KbdBrightnessUp     0x1008FF05
114 #define XF86XK_KbdBrightnessDown   0x1008FF06
115 #define XF86XK_Standby             0x1008FF10
116 #define XF86XK_AudioLowerVolume    0x1008FF11
117 #define XF86XK_AudioMute           0x1008FF12
118 #define XF86XK_AudioRaiseVolume    0x1008FF13
119 #define XF86XK_AudioPlay           0x1008FF14
120 #define XF86XK_AudioStop           0x1008FF15
121 #define XF86XK_AudioPrev           0x1008FF16
122 #define XF86XK_AudioNext           0x1008FF17
123 #define XF86XK_HomePage            0x1008FF18
124 #define XF86XK_Mail                0x1008FF19
125 #define XF86XK_Start               0x1008FF1A
126 #define XF86XK_Search              0x1008FF1B
127 #define XF86XK_AudioRecord         0x1008FF1C
128 #define XF86XK_Calculator          0x1008FF1D
129 #define XF86XK_Memo                0x1008FF1E
130 #define XF86XK_ToDoList            0x1008FF1F
131 #define XF86XK_Calendar            0x1008FF20
132 #define XF86XK_PowerDown           0x1008FF21
133 #define XF86XK_ContrastAdjust      0x1008FF22
134 #define XF86XK_Back                0x1008FF26
135 #define XF86XK_Forward             0x1008FF27
136 #define XF86XK_Stop                0x1008FF28
137 #define XF86XK_Refresh             0x1008FF29
138 #define XF86XK_PowerOff            0x1008FF2A
139 #define XF86XK_WakeUp              0x1008FF2B
140 #define XF86XK_Eject               0x1008FF2C
141 #define XF86XK_ScreenSaver         0x1008FF2D
142 #define XF86XK_WWW                 0x1008FF2E
143 #define XF86XK_Sleep               0x1008FF2F
144 #define XF86XK_Favorites           0x1008FF30
145 #define XF86XK_AudioPause          0x1008FF31
146 #define XF86XK_AudioMedia          0x1008FF32
147 #define XF86XK_MyComputer          0x1008FF33
148 #define XF86XK_LightBulb           0x1008FF35
149 #define XF86XK_Shop                0x1008FF36
150 #define XF86XK_History             0x1008FF37
151 #define XF86XK_OpenURL             0x1008FF38
152 #define XF86XK_AddFavorite         0x1008FF39
153 #define XF86XK_HotLinks            0x1008FF3A
154 #define XF86XK_BrightnessAdjust    0x1008FF3B
155 #define XF86XK_Finance             0x1008FF3C
156 #define XF86XK_Community           0x1008FF3D
157 #define XF86XK_AudioRewind         0x1008FF3E
158 #define XF86XK_BackForward         0x1008FF3F
159 #define XF86XK_Launch0             0x1008FF40
160 #define XF86XK_Launch1             0x1008FF41
161 #define XF86XK_Launch2             0x1008FF42
162 #define XF86XK_Launch3             0x1008FF43
163 #define XF86XK_Launch4             0x1008FF44
164 #define XF86XK_Launch5             0x1008FF45
165 #define XF86XK_Launch6             0x1008FF46
166 #define XF86XK_Launch7             0x1008FF47
167 #define XF86XK_Launch8             0x1008FF48
168 #define XF86XK_Launch9             0x1008FF49
169 #define XF86XK_LaunchA             0x1008FF4A
170 #define XF86XK_LaunchB             0x1008FF4B
171 #define XF86XK_LaunchC             0x1008FF4C
172 #define XF86XK_LaunchD             0x1008FF4D
173 #define XF86XK_LaunchE             0x1008FF4E
174 #define XF86XK_LaunchF             0x1008FF4F
175 #define XF86XK_ApplicationLeft     0x1008FF50
176 #define XF86XK_ApplicationRight    0x1008FF51
177 #define XF86XK_Book                0x1008FF52
178 #define XF86XK_CD                  0x1008FF53
179 #define XF86XK_Calculater          0x1008FF54
180 #define XF86XK_Clear               0x1008FF55
181 #define XF86XK_ClearGrab           0x1008FE21
182 #define XF86XK_Close               0x1008FF56
183 #define XF86XK_Copy                0x1008FF57
184 #define XF86XK_Cut                 0x1008FF58
185 #define XF86XK_Display             0x1008FF59
186 #define XF86XK_DOS                 0x1008FF5A
187 #define XF86XK_Documents           0x1008FF5B
188 #define XF86XK_Excel               0x1008FF5C
189 #define XF86XK_Explorer            0x1008FF5D
190 #define XF86XK_Game                0x1008FF5E
191 #define XF86XK_Go                  0x1008FF5F
192 #define XF86XK_iTouch              0x1008FF60
193 #define XF86XK_LogOff              0x1008FF61
194 #define XF86XK_Market              0x1008FF62
195 #define XF86XK_Meeting             0x1008FF63
196 #define XF86XK_MenuKB              0x1008FF65
197 #define XF86XK_MenuPB              0x1008FF66
198 #define XF86XK_MySites             0x1008FF67
199 #define XF86XK_News                0x1008FF69
200 #define XF86XK_OfficeHome          0x1008FF6A
201 #define XF86XK_Option              0x1008FF6C
202 #define XF86XK_Paste               0x1008FF6D
203 #define XF86XK_Phone               0x1008FF6E
204 #define XF86XK_Reply               0x1008FF72
205 #define XF86XK_Reload              0x1008FF73
206 #define XF86XK_RotateWindows       0x1008FF74
207 #define XF86XK_RotationPB          0x1008FF75
208 #define XF86XK_RotationKB          0x1008FF76
209 #define XF86XK_Save                0x1008FF77
210 #define XF86XK_Send                0x1008FF7B
211 #define XF86XK_Spell               0x1008FF7C
212 #define XF86XK_SplitScreen         0x1008FF7D
213 #define XF86XK_Support             0x1008FF7E
214 #define XF86XK_TaskPane            0x1008FF7F
215 #define XF86XK_Terminal            0x1008FF80
216 #define XF86XK_Tools               0x1008FF81
217 #define XF86XK_Travel              0x1008FF82
218 #define XF86XK_Video               0x1008FF87
219 #define XF86XK_Word                0x1008FF89
220 #define XF86XK_Xfer                0x1008FF8A
221 #define XF86XK_ZoomIn              0x1008FF8B
222 #define XF86XK_ZoomOut             0x1008FF8C
223 #define XF86XK_Away                0x1008FF8D
224 #define XF86XK_Messenger           0x1008FF8E
225 #define XF86XK_WebCam              0x1008FF8F
226 #define XF86XK_MailForward         0x1008FF90
227 #define XF86XK_Pictures            0x1008FF91
228 #define XF86XK_Music               0x1008FF92
229 #define XF86XK_Battery             0x1008FF93
230 #define XF86XK_Bluetooth           0x1008FF94
231 #define XF86XK_WLAN                0x1008FF95
232 #define XF86XK_UWB                 0x1008FF96
233 #define XF86XK_AudioForward        0x1008FF97
234 #define XF86XK_AudioRepeat         0x1008FF98
235 #define XF86XK_AudioRandomPlay     0x1008FF99
236 #define XF86XK_Subtitle            0x1008FF9A
237 #define XF86XK_AudioCycleTrack     0x1008FF9B
238 #define XF86XK_Time                0x1008FF9F
239 #define XF86XK_Select              0x1008FFA0
240 #define XF86XK_View                0x1008FFA1
241 #define XF86XK_TopMenu             0x1008FFA2
242 #define XF86XK_Suspend             0x1008FFA7
243 #define XF86XK_Hibernate           0x1008FFA8
244 #define XF86XK_TouchpadToggle      0x1008FFA9
245 #define XF86XK_TouchpadOn          0x1008FFB0
246 #define XF86XK_TouchpadOff         0x1008FFB1
247
248
249 // end of XF86keysyms.h
250
251 QT_BEGIN_NAMESPACE
252
253 // keyboard mapping table
254 static const unsigned int KeyTbl[] = {
255
256     // misc keys
257
258     XK_Escape,                  Qt::Key_Escape,
259     XK_Tab,                     Qt::Key_Tab,
260     XK_ISO_Left_Tab,            Qt::Key_Backtab,
261     XK_BackSpace,               Qt::Key_Backspace,
262     XK_Return,                  Qt::Key_Return,
263     XK_Insert,                  Qt::Key_Insert,
264     XK_Delete,                  Qt::Key_Delete,
265     XK_Clear,                   Qt::Key_Delete,
266     XK_Pause,                   Qt::Key_Pause,
267     XK_Print,                   Qt::Key_Print,
268     0x1005FF60,                 Qt::Key_SysReq,         // hardcoded Sun SysReq
269     0x1007ff00,                 Qt::Key_SysReq,         // hardcoded X386 SysReq
270
271     // cursor movement
272
273     XK_Home,                    Qt::Key_Home,
274     XK_End,                     Qt::Key_End,
275     XK_Left,                    Qt::Key_Left,
276     XK_Up,                      Qt::Key_Up,
277     XK_Right,                   Qt::Key_Right,
278     XK_Down,                    Qt::Key_Down,
279     XK_Prior,                   Qt::Key_PageUp,
280     XK_Next,                    Qt::Key_PageDown,
281
282     // modifiers
283
284     XK_Shift_L,                 Qt::Key_Shift,
285     XK_Shift_R,                 Qt::Key_Shift,
286     XK_Shift_Lock,              Qt::Key_Shift,
287     XK_Control_L,               Qt::Key_Control,
288     XK_Control_R,               Qt::Key_Control,
289     XK_Meta_L,                  Qt::Key_Meta,
290     XK_Meta_R,                  Qt::Key_Meta,
291     XK_Alt_L,                   Qt::Key_Alt,
292     XK_Alt_R,                   Qt::Key_Alt,
293     XK_Caps_Lock,               Qt::Key_CapsLock,
294     XK_Num_Lock,                Qt::Key_NumLock,
295     XK_Scroll_Lock,             Qt::Key_ScrollLock,
296     XK_Super_L,                 Qt::Key_Super_L,
297     XK_Super_R,                 Qt::Key_Super_R,
298     XK_Menu,                    Qt::Key_Menu,
299     XK_Hyper_L,                 Qt::Key_Hyper_L,
300     XK_Hyper_R,                 Qt::Key_Hyper_R,
301     XK_Help,                    Qt::Key_Help,
302     0x1000FF74,                 Qt::Key_Backtab,        // hardcoded HP backtab
303     0x1005FF10,                 Qt::Key_F11,            // hardcoded Sun F36 (labeled F11)
304     0x1005FF11,                 Qt::Key_F12,            // hardcoded Sun F37 (labeled F12)
305
306     // numeric and function keypad keys
307
308     XK_KP_Space,                Qt::Key_Space,
309     XK_KP_Tab,                  Qt::Key_Tab,
310     XK_KP_Enter,                Qt::Key_Enter,
311     //XK_KP_F1,                 Qt::Key_F1,
312     //XK_KP_F2,                 Qt::Key_F2,
313     //XK_KP_F3,                 Qt::Key_F3,
314     //XK_KP_F4,                 Qt::Key_F4,
315     XK_KP_Home,                 Qt::Key_Home,
316     XK_KP_Left,                 Qt::Key_Left,
317     XK_KP_Up,                   Qt::Key_Up,
318     XK_KP_Right,                Qt::Key_Right,
319     XK_KP_Down,                 Qt::Key_Down,
320     XK_KP_Prior,                Qt::Key_PageUp,
321     XK_KP_Next,                 Qt::Key_PageDown,
322     XK_KP_End,                  Qt::Key_End,
323     XK_KP_Begin,                Qt::Key_Clear,
324     XK_KP_Insert,               Qt::Key_Insert,
325     XK_KP_Delete,               Qt::Key_Delete,
326     XK_KP_Equal,                Qt::Key_Equal,
327     XK_KP_Multiply,             Qt::Key_Asterisk,
328     XK_KP_Add,                  Qt::Key_Plus,
329     XK_KP_Separator,            Qt::Key_Comma,
330     XK_KP_Subtract,             Qt::Key_Minus,
331     XK_KP_Decimal,              Qt::Key_Period,
332     XK_KP_Divide,               Qt::Key_Slash,
333
334     // International input method support keys
335
336     // International & multi-key character composition
337     XK_ISO_Level3_Shift,        Qt::Key_AltGr,
338     XK_Multi_key,               Qt::Key_Multi_key,
339     XK_Codeinput,               Qt::Key_Codeinput,
340     XK_SingleCandidate,         Qt::Key_SingleCandidate,
341     XK_MultipleCandidate,       Qt::Key_MultipleCandidate,
342     XK_PreviousCandidate,       Qt::Key_PreviousCandidate,
343
344     // Misc Functions
345     XK_Mode_switch,             Qt::Key_Mode_switch,
346     XK_script_switch,           Qt::Key_Mode_switch,
347
348     // Japanese keyboard support
349     XK_Kanji,                   Qt::Key_Kanji,
350     XK_Muhenkan,                Qt::Key_Muhenkan,
351     //XK_Henkan_Mode,           Qt::Key_Henkan_Mode,
352     XK_Henkan_Mode,             Qt::Key_Henkan,
353     XK_Henkan,                  Qt::Key_Henkan,
354     XK_Romaji,                  Qt::Key_Romaji,
355     XK_Hiragana,                Qt::Key_Hiragana,
356     XK_Katakana,                Qt::Key_Katakana,
357     XK_Hiragana_Katakana,       Qt::Key_Hiragana_Katakana,
358     XK_Zenkaku,                 Qt::Key_Zenkaku,
359     XK_Hankaku,                 Qt::Key_Hankaku,
360     XK_Zenkaku_Hankaku,         Qt::Key_Zenkaku_Hankaku,
361     XK_Touroku,                 Qt::Key_Touroku,
362     XK_Massyo,                  Qt::Key_Massyo,
363     XK_Kana_Lock,               Qt::Key_Kana_Lock,
364     XK_Kana_Shift,              Qt::Key_Kana_Shift,
365     XK_Eisu_Shift,              Qt::Key_Eisu_Shift,
366     XK_Eisu_toggle,             Qt::Key_Eisu_toggle,
367     //XK_Kanji_Bangou,          Qt::Key_Kanji_Bangou,
368     //XK_Zen_Koho,              Qt::Key_Zen_Koho,
369     //XK_Mae_Koho,              Qt::Key_Mae_Koho,
370     XK_Kanji_Bangou,            Qt::Key_Codeinput,
371     XK_Zen_Koho,                Qt::Key_MultipleCandidate,
372     XK_Mae_Koho,                Qt::Key_PreviousCandidate,
373
374 #ifdef XK_KOREAN
375     // Korean keyboard support
376     XK_Hangul,                  Qt::Key_Hangul,
377     XK_Hangul_Start,            Qt::Key_Hangul_Start,
378     XK_Hangul_End,              Qt::Key_Hangul_End,
379     XK_Hangul_Hanja,            Qt::Key_Hangul_Hanja,
380     XK_Hangul_Jamo,             Qt::Key_Hangul_Jamo,
381     XK_Hangul_Romaja,           Qt::Key_Hangul_Romaja,
382     //XK_Hangul_Codeinput,      Qt::Key_Hangul_Codeinput,
383     XK_Hangul_Codeinput,        Qt::Key_Codeinput,
384     XK_Hangul_Jeonja,           Qt::Key_Hangul_Jeonja,
385     XK_Hangul_Banja,            Qt::Key_Hangul_Banja,
386     XK_Hangul_PreHanja,         Qt::Key_Hangul_PreHanja,
387     XK_Hangul_PostHanja,        Qt::Key_Hangul_PostHanja,
388     //XK_Hangul_SingleCandidate,Qt::Key_Hangul_SingleCandidate,
389     //XK_Hangul_MultipleCandidate,Qt::Key_Hangul_MultipleCandidate,
390     //XK_Hangul_PreviousCandidate,Qt::Key_Hangul_PreviousCandidate,
391     XK_Hangul_SingleCandidate,  Qt::Key_SingleCandidate,
392     XK_Hangul_MultipleCandidate,Qt::Key_MultipleCandidate,
393     XK_Hangul_PreviousCandidate,Qt::Key_PreviousCandidate,
394     XK_Hangul_Special,          Qt::Key_Hangul_Special,
395     //XK_Hangul_switch,         Qt::Key_Hangul_switch,
396     XK_Hangul_switch,           Qt::Key_Mode_switch,
397 #endif  // XK_KOREAN
398
399     // dead keys
400     XK_dead_grave,              Qt::Key_Dead_Grave,
401     XK_dead_acute,              Qt::Key_Dead_Acute,
402     XK_dead_circumflex,         Qt::Key_Dead_Circumflex,
403     XK_dead_tilde,              Qt::Key_Dead_Tilde,
404     XK_dead_macron,             Qt::Key_Dead_Macron,
405     XK_dead_breve,              Qt::Key_Dead_Breve,
406     XK_dead_abovedot,           Qt::Key_Dead_Abovedot,
407     XK_dead_diaeresis,          Qt::Key_Dead_Diaeresis,
408     XK_dead_abovering,          Qt::Key_Dead_Abovering,
409     XK_dead_doubleacute,        Qt::Key_Dead_Doubleacute,
410     XK_dead_caron,              Qt::Key_Dead_Caron,
411     XK_dead_cedilla,            Qt::Key_Dead_Cedilla,
412     XK_dead_ogonek,             Qt::Key_Dead_Ogonek,
413     XK_dead_iota,               Qt::Key_Dead_Iota,
414     XK_dead_voiced_sound,       Qt::Key_Dead_Voiced_Sound,
415     XK_dead_semivoiced_sound,   Qt::Key_Dead_Semivoiced_Sound,
416     XK_dead_belowdot,           Qt::Key_Dead_Belowdot,
417     XK_dead_hook,               Qt::Key_Dead_Hook,
418     XK_dead_horn,               Qt::Key_Dead_Horn,
419
420     // Special keys from X.org - This include multimedia keys,
421         // wireless/bluetooth/uwb keys, special launcher keys, etc.
422     XF86XK_Back,                Qt::Key_Back,
423     XF86XK_Forward,             Qt::Key_Forward,
424     XF86XK_Stop,                Qt::Key_Stop,
425     XF86XK_Refresh,             Qt::Key_Refresh,
426     XF86XK_Favorites,           Qt::Key_Favorites,
427     XF86XK_AudioMedia,          Qt::Key_LaunchMedia,
428     XF86XK_OpenURL,             Qt::Key_OpenUrl,
429     XF86XK_HomePage,            Qt::Key_HomePage,
430     XF86XK_Search,              Qt::Key_Search,
431     XF86XK_AudioLowerVolume,    Qt::Key_VolumeDown,
432     XF86XK_AudioMute,           Qt::Key_VolumeMute,
433     XF86XK_AudioRaiseVolume,    Qt::Key_VolumeUp,
434     XF86XK_AudioPlay,           Qt::Key_MediaPlay,
435     XF86XK_AudioStop,           Qt::Key_MediaStop,
436     XF86XK_AudioPrev,           Qt::Key_MediaPrevious,
437     XF86XK_AudioNext,           Qt::Key_MediaNext,
438     XF86XK_AudioRecord,         Qt::Key_MediaRecord,
439     XF86XK_Mail,                Qt::Key_LaunchMail,
440     XF86XK_MyComputer,          Qt::Key_Launch0,  // ### Qt 6: remap properly
441     XF86XK_Calculator,          Qt::Key_Launch1,
442     XF86XK_Memo,                Qt::Key_Memo,
443     XF86XK_ToDoList,            Qt::Key_ToDoList,
444     XF86XK_Calendar,            Qt::Key_Calendar,
445     XF86XK_PowerDown,           Qt::Key_PowerDown,
446     XF86XK_ContrastAdjust,      Qt::Key_ContrastAdjust,
447     XF86XK_Standby,             Qt::Key_Standby,
448     XF86XK_MonBrightnessUp,     Qt::Key_MonBrightnessUp,
449     XF86XK_MonBrightnessDown,   Qt::Key_MonBrightnessDown,
450     XF86XK_KbdLightOnOff,       Qt::Key_KeyboardLightOnOff,
451     XF86XK_KbdBrightnessUp,     Qt::Key_KeyboardBrightnessUp,
452     XF86XK_KbdBrightnessDown,   Qt::Key_KeyboardBrightnessDown,
453     XF86XK_PowerOff,            Qt::Key_PowerOff,
454     XF86XK_WakeUp,              Qt::Key_WakeUp,
455     XF86XK_Eject,               Qt::Key_Eject,
456     XF86XK_ScreenSaver,         Qt::Key_ScreenSaver,
457     XF86XK_WWW,                 Qt::Key_WWW,
458     XF86XK_Sleep,               Qt::Key_Sleep,
459     XF86XK_LightBulb,           Qt::Key_LightBulb,
460     XF86XK_Shop,                Qt::Key_Shop,
461     XF86XK_History,             Qt::Key_History,
462     XF86XK_AddFavorite,         Qt::Key_AddFavorite,
463     XF86XK_HotLinks,            Qt::Key_HotLinks,
464     XF86XK_BrightnessAdjust,    Qt::Key_BrightnessAdjust,
465     XF86XK_Finance,             Qt::Key_Finance,
466     XF86XK_Community,           Qt::Key_Community,
467     XF86XK_AudioRewind,         Qt::Key_AudioRewind,
468     XF86XK_BackForward,         Qt::Key_BackForward,
469     XF86XK_ApplicationLeft,     Qt::Key_ApplicationLeft,
470     XF86XK_ApplicationRight,    Qt::Key_ApplicationRight,
471     XF86XK_Book,                Qt::Key_Book,
472     XF86XK_CD,                  Qt::Key_CD,
473     XF86XK_Calculater,          Qt::Key_Calculator,
474     XF86XK_Clear,               Qt::Key_Clear,
475     XF86XK_ClearGrab,           Qt::Key_ClearGrab,
476     XF86XK_Close,               Qt::Key_Close,
477     XF86XK_Copy,                Qt::Key_Copy,
478     XF86XK_Cut,                 Qt::Key_Cut,
479     XF86XK_Display,             Qt::Key_Display,
480     XF86XK_DOS,                 Qt::Key_DOS,
481     XF86XK_Documents,           Qt::Key_Documents,
482     XF86XK_Excel,               Qt::Key_Excel,
483     XF86XK_Explorer,            Qt::Key_Explorer,
484     XF86XK_Game,                Qt::Key_Game,
485     XF86XK_Go,                  Qt::Key_Go,
486     XF86XK_iTouch,              Qt::Key_iTouch,
487     XF86XK_LogOff,              Qt::Key_LogOff,
488     XF86XK_Market,              Qt::Key_Market,
489     XF86XK_Meeting,             Qt::Key_Meeting,
490     XF86XK_MenuKB,              Qt::Key_MenuKB,
491     XF86XK_MenuPB,              Qt::Key_MenuPB,
492     XF86XK_MySites,             Qt::Key_MySites,
493     XF86XK_News,                Qt::Key_News,
494     XF86XK_OfficeHome,          Qt::Key_OfficeHome,
495     XF86XK_Option,              Qt::Key_Option,
496     XF86XK_Paste,               Qt::Key_Paste,
497     XF86XK_Phone,               Qt::Key_Phone,
498     XF86XK_Reply,               Qt::Key_Reply,
499     XF86XK_Reload,              Qt::Key_Reload,
500     XF86XK_RotateWindows,       Qt::Key_RotateWindows,
501     XF86XK_RotationPB,          Qt::Key_RotationPB,
502     XF86XK_RotationKB,          Qt::Key_RotationKB,
503     XF86XK_Save,                Qt::Key_Save,
504     XF86XK_Send,                Qt::Key_Send,
505     XF86XK_Spell,               Qt::Key_Spell,
506     XF86XK_SplitScreen,         Qt::Key_SplitScreen,
507     XF86XK_Support,             Qt::Key_Support,
508     XF86XK_TaskPane,            Qt::Key_TaskPane,
509     XF86XK_Terminal,            Qt::Key_Terminal,
510     XF86XK_Tools,               Qt::Key_Tools,
511     XF86XK_Travel,              Qt::Key_Travel,
512     XF86XK_Video,               Qt::Key_Video,
513     XF86XK_Word,                Qt::Key_Word,
514     XF86XK_Xfer,                Qt::Key_Xfer,
515     XF86XK_ZoomIn,              Qt::Key_ZoomIn,
516     XF86XK_ZoomOut,             Qt::Key_ZoomOut,
517     XF86XK_Away,                Qt::Key_Away,
518     XF86XK_Messenger,           Qt::Key_Messenger,
519     XF86XK_WebCam,              Qt::Key_WebCam,
520     XF86XK_MailForward,         Qt::Key_MailForward,
521     XF86XK_Pictures,            Qt::Key_Pictures,
522     XF86XK_Music,               Qt::Key_Music,
523     XF86XK_Battery,             Qt::Key_Battery,
524     XF86XK_Bluetooth,           Qt::Key_Bluetooth,
525     XF86XK_WLAN,                Qt::Key_WLAN,
526     XF86XK_UWB,                 Qt::Key_UWB,
527     XF86XK_AudioForward,        Qt::Key_AudioForward,
528     XF86XK_AudioRepeat,         Qt::Key_AudioRepeat,
529     XF86XK_AudioRandomPlay,     Qt::Key_AudioRandomPlay,
530     XF86XK_Subtitle,            Qt::Key_Subtitle,
531     XF86XK_AudioCycleTrack,     Qt::Key_AudioCycleTrack,
532     XF86XK_Time,                Qt::Key_Time,
533     XF86XK_Select,              Qt::Key_Select,
534     XF86XK_View,                Qt::Key_View,
535     XF86XK_TopMenu,             Qt::Key_TopMenu,
536     XF86XK_Bluetooth,           Qt::Key_Bluetooth,
537     XF86XK_Suspend,             Qt::Key_Suspend,
538     XF86XK_Hibernate,           Qt::Key_Hibernate,
539     XF86XK_TouchpadToggle,      Qt::Key_TouchpadToggle,
540     XF86XK_TouchpadOn,          Qt::Key_TouchpadOn,
541     XF86XK_TouchpadOff,         Qt::Key_TouchpadOff,
542     XF86XK_Launch0,             Qt::Key_Launch2, // ### Qt 6: remap properly
543     XF86XK_Launch1,             Qt::Key_Launch3,
544     XF86XK_Launch2,             Qt::Key_Launch4,
545     XF86XK_Launch3,             Qt::Key_Launch5,
546     XF86XK_Launch4,             Qt::Key_Launch6,
547     XF86XK_Launch5,             Qt::Key_Launch7,
548     XF86XK_Launch6,             Qt::Key_Launch8,
549     XF86XK_Launch7,             Qt::Key_Launch9,
550     XF86XK_Launch8,             Qt::Key_LaunchA,
551     XF86XK_Launch9,             Qt::Key_LaunchB,
552     XF86XK_LaunchA,             Qt::Key_LaunchC,
553     XF86XK_LaunchB,             Qt::Key_LaunchD,
554     XF86XK_LaunchC,             Qt::Key_LaunchE,
555     XF86XK_LaunchD,             Qt::Key_LaunchF,
556     XF86XK_LaunchE,             Qt::Key_LaunchG,
557     XF86XK_LaunchF,             Qt::Key_LaunchH,
558
559     0,                          0
560 };
561
562 static const unsigned short katakanaKeysymsToUnicode[] = {
563     0x0000, 0x3002, 0x300C, 0x300D, 0x3001, 0x30FB, 0x30F2, 0x30A1,
564     0x30A3, 0x30A5, 0x30A7, 0x30A9, 0x30E3, 0x30E5, 0x30E7, 0x30C3,
565     0x30FC, 0x30A2, 0x30A4, 0x30A6, 0x30A8, 0x30AA, 0x30AB, 0x30AD,
566     0x30AF, 0x30B1, 0x30B3, 0x30B5, 0x30B7, 0x30B9, 0x30BB, 0x30BD,
567     0x30BF, 0x30C1, 0x30C4, 0x30C6, 0x30C8, 0x30CA, 0x30CB, 0x30CC,
568     0x30CD, 0x30CE, 0x30CF, 0x30D2, 0x30D5, 0x30D8, 0x30DB, 0x30DE,
569     0x30DF, 0x30E0, 0x30E1, 0x30E2, 0x30E4, 0x30E6, 0x30E8, 0x30E9,
570     0x30EA, 0x30EB, 0x30EC, 0x30ED, 0x30EF, 0x30F3, 0x309B, 0x309C
571 };
572
573 static const unsigned short cyrillicKeysymsToUnicode[] = {
574     0x0000, 0x0452, 0x0453, 0x0451, 0x0454, 0x0455, 0x0456, 0x0457,
575     0x0458, 0x0459, 0x045a, 0x045b, 0x045c, 0x0000, 0x045e, 0x045f,
576     0x2116, 0x0402, 0x0403, 0x0401, 0x0404, 0x0405, 0x0406, 0x0407,
577     0x0408, 0x0409, 0x040a, 0x040b, 0x040c, 0x0000, 0x040e, 0x040f,
578     0x044e, 0x0430, 0x0431, 0x0446, 0x0434, 0x0435, 0x0444, 0x0433,
579     0x0445, 0x0438, 0x0439, 0x043a, 0x043b, 0x043c, 0x043d, 0x043e,
580     0x043f, 0x044f, 0x0440, 0x0441, 0x0442, 0x0443, 0x0436, 0x0432,
581     0x044c, 0x044b, 0x0437, 0x0448, 0x044d, 0x0449, 0x0447, 0x044a,
582     0x042e, 0x0410, 0x0411, 0x0426, 0x0414, 0x0415, 0x0424, 0x0413,
583     0x0425, 0x0418, 0x0419, 0x041a, 0x041b, 0x041c, 0x041d, 0x041e,
584     0x041f, 0x042f, 0x0420, 0x0421, 0x0422, 0x0423, 0x0416, 0x0412,
585     0x042c, 0x042b, 0x0417, 0x0428, 0x042d, 0x0429, 0x0427, 0x042a
586 };
587
588 static const unsigned short greekKeysymsToUnicode[] = {
589     0x0000, 0x0386, 0x0388, 0x0389, 0x038a, 0x03aa, 0x0000, 0x038c,
590     0x038e, 0x03ab, 0x0000, 0x038f, 0x0000, 0x0000, 0x0385, 0x2015,
591     0x0000, 0x03ac, 0x03ad, 0x03ae, 0x03af, 0x03ca, 0x0390, 0x03cc,
592     0x03cd, 0x03cb, 0x03b0, 0x03ce, 0x0000, 0x0000, 0x0000, 0x0000,
593     0x0000, 0x0391, 0x0392, 0x0393, 0x0394, 0x0395, 0x0396, 0x0397,
594     0x0398, 0x0399, 0x039a, 0x039b, 0x039c, 0x039d, 0x039e, 0x039f,
595     0x03a0, 0x03a1, 0x03a3, 0x0000, 0x03a4, 0x03a5, 0x03a6, 0x03a7,
596     0x03a8, 0x03a9, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
597     0x0000, 0x03b1, 0x03b2, 0x03b3, 0x03b4, 0x03b5, 0x03b6, 0x03b7,
598     0x03b8, 0x03b9, 0x03ba, 0x03bb, 0x03bc, 0x03bd, 0x03be, 0x03bf,
599     0x03c0, 0x03c1, 0x03c3, 0x03c2, 0x03c4, 0x03c5, 0x03c6, 0x03c7,
600     0x03c8, 0x03c9, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000
601 };
602
603 static const unsigned short technicalKeysymsToUnicode[] = {
604     0x0000, 0x23B7, 0x250C, 0x2500, 0x2320, 0x2321, 0x2502, 0x23A1,
605     0x23A3, 0x23A4, 0x23A6, 0x239B, 0x239D, 0x239E, 0x23A0, 0x23A8,
606     0x23AC, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
607     0x0000, 0x0000, 0x0000, 0x0000, 0x2264, 0x2260, 0x2265, 0x222B,
608     0x2234, 0x221D, 0x221E, 0x0000, 0x0000, 0x2207, 0x0000, 0x0000,
609     0x223C, 0x2243, 0x0000, 0x0000, 0x0000, 0x21D4, 0x21D2, 0x2261,
610     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x221A, 0x0000,
611     0x0000, 0x0000, 0x2282, 0x2283, 0x2229, 0x222A, 0x2227, 0x2228,
612     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
613     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x2202,
614     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0192, 0x0000,
615     0x0000, 0x0000, 0x0000, 0x2190, 0x2191, 0x2192, 0x2193, 0x0000
616 };
617
618 static const unsigned short specialKeysymsToUnicode[] = {
619     0x25C6, 0x2592, 0x2409, 0x240C, 0x240D, 0x240A, 0x0000, 0x0000,
620     0x2424, 0x240B, 0x2518, 0x2510, 0x250C, 0x2514, 0x253C, 0x23BA,
621     0x23BB, 0x2500, 0x23BC, 0x23BD, 0x251C, 0x2524, 0x2534, 0x252C,
622     0x2502, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000
623 };
624
625 static const unsigned short publishingKeysymsToUnicode[] = {
626     0x0000, 0x2003, 0x2002, 0x2004, 0x2005, 0x2007, 0x2008, 0x2009,
627     0x200a, 0x2014, 0x2013, 0x0000, 0x0000, 0x0000, 0x2026, 0x2025,
628     0x2153, 0x2154, 0x2155, 0x2156, 0x2157, 0x2158, 0x2159, 0x215a,
629     0x2105, 0x0000, 0x0000, 0x2012, 0x2329, 0x0000, 0x232a, 0x0000,
630     0x0000, 0x0000, 0x0000, 0x215b, 0x215c, 0x215d, 0x215e, 0x0000,
631     0x0000, 0x2122, 0x2613, 0x0000, 0x25c1, 0x25b7, 0x25cb, 0x25af,
632     0x2018, 0x2019, 0x201c, 0x201d, 0x211e, 0x0000, 0x2032, 0x2033,
633     0x0000, 0x271d, 0x0000, 0x25ac, 0x25c0, 0x25b6, 0x25cf, 0x25ae,
634     0x25e6, 0x25ab, 0x25ad, 0x25b3, 0x25bd, 0x2606, 0x2022, 0x25aa,
635     0x25b2, 0x25bc, 0x261c, 0x261e, 0x2663, 0x2666, 0x2665, 0x0000,
636     0x2720, 0x2020, 0x2021, 0x2713, 0x2717, 0x266f, 0x266d, 0x2642,
637     0x2640, 0x260e, 0x2315, 0x2117, 0x2038, 0x201a, 0x201e, 0x0000
638 };
639
640 static const unsigned short aplKeysymsToUnicode[] = {
641     0x0000, 0x0000, 0x0000, 0x003c, 0x0000, 0x0000, 0x003e, 0x0000,
642     0x2228, 0x2227, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
643     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
644     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
645     0x00af, 0x0000, 0x22a5, 0x2229, 0x230a, 0x0000, 0x005f, 0x0000,
646     0x0000, 0x0000, 0x2218, 0x0000, 0x2395, 0x0000, 0x22a4, 0x25cb,
647     0x0000, 0x0000, 0x0000, 0x2308, 0x0000, 0x0000, 0x222a, 0x0000,
648     0x2283, 0x0000, 0x2282, 0x0000, 0x22a2, 0x0000, 0x0000, 0x0000,
649     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
650     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
651     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
652     0x0000, 0x0000, 0x0000, 0x0000, 0x22a3, 0x0000, 0x0000, 0x0000
653 };
654
655 static const unsigned short koreanKeysymsToUnicode[] = {
656     0x0000, 0x3131, 0x3132, 0x3133, 0x3134, 0x3135, 0x3136, 0x3137,
657     0x3138, 0x3139, 0x313a, 0x313b, 0x313c, 0x313d, 0x313e, 0x313f,
658     0x3140, 0x3141, 0x3142, 0x3143, 0x3144, 0x3145, 0x3146, 0x3147,
659     0x3148, 0x3149, 0x314a, 0x314b, 0x314c, 0x314d, 0x314e, 0x314f,
660     0x3150, 0x3151, 0x3152, 0x3153, 0x3154, 0x3155, 0x3156, 0x3157,
661     0x3158, 0x3159, 0x315a, 0x315b, 0x315c, 0x315d, 0x315e, 0x315f,
662     0x3160, 0x3161, 0x3162, 0x3163, 0x11a8, 0x11a9, 0x11aa, 0x11ab,
663     0x11ac, 0x11ad, 0x11ae, 0x11af, 0x11b0, 0x11b1, 0x11b2, 0x11b3,
664     0x11b4, 0x11b5, 0x11b6, 0x11b7, 0x11b8, 0x11b9, 0x11ba, 0x11bb,
665     0x11bc, 0x11bd, 0x11be, 0x11bf, 0x11c0, 0x11c1, 0x11c2, 0x316d,
666     0x3171, 0x3178, 0x317f, 0x3181, 0x3184, 0x3186, 0x318d, 0x318e,
667     0x11eb, 0x11f0, 0x11f9, 0x0000, 0x0000, 0x0000, 0x0000, 0x20a9
668 };
669
670 static QChar keysymToUnicode(unsigned char byte3, unsigned char byte4)
671 {
672     switch (byte3) {
673     case 0x04:
674         // katakana
675         if (byte4 > 0xa0 && byte4 < 0xe0)
676             return QChar(katakanaKeysymsToUnicode[byte4 - 0xa0]);
677         else if (byte4 == 0x7e)
678             return QChar(0x203e); // Overline
679         break;
680     case 0x06:
681         // russian, use lookup table
682         if (byte4 > 0xa0)
683             return QChar(cyrillicKeysymsToUnicode[byte4 - 0xa0]);
684         break;
685     case 0x07:
686         // greek
687         if (byte4 > 0xa0)
688             return QChar(greekKeysymsToUnicode[byte4 - 0xa0]);
689         break;
690     case 0x08:
691         // technical
692         if (byte4 > 0xa0)
693             return QChar(technicalKeysymsToUnicode[byte4 - 0xa0]);
694         break;
695     case 0x09:
696         // special
697         if (byte4 >= 0xe0)
698             return QChar(specialKeysymsToUnicode[byte4 - 0xe0]);
699         break;
700     case 0x0a:
701         // publishing
702         if (byte4 > 0xa0)
703             return QChar(publishingKeysymsToUnicode[byte4 - 0xa0]);
704         break;
705     case 0x0b:
706         // APL
707         if (byte4 > 0xa0)
708             return QChar(aplKeysymsToUnicode[byte4 - 0xa0]);
709         break;
710     case 0x0e:
711         // Korean
712         if (byte4 > 0xa0)
713             return QChar(koreanKeysymsToUnicode[byte4 - 0xa0]);
714         break;
715     default:
716         break;
717     }
718     return QChar(0x0);
719 }
720
721 Qt::KeyboardModifiers QXcbKeyboard::translateModifiers(int s)
722 {
723     Qt::KeyboardModifiers ret = 0;
724     if (s & XCB_MOD_MASK_SHIFT)
725         ret |= Qt::ShiftModifier;
726     if (s & XCB_MOD_MASK_CONTROL)
727         ret |= Qt::ControlModifier;
728     if (s & m_alt_mask)
729         ret |= Qt::AltModifier;
730     if (s & m_meta_mask)
731         ret |= Qt::MetaModifier;
732     return ret;
733 }
734
735 int QXcbKeyboard::translateKeySym(uint key) const
736 {
737     int code = -1;
738     int i = 0;                                // any other keys
739     while (KeyTbl[i]) {
740         if (key == KeyTbl[i]) {
741             code = (int)KeyTbl[i+1];
742             break;
743         }
744         i += 2;
745     }
746     if (m_meta_mask) {
747         // translate Super/Hyper keys to Meta if we're using them as the MetaModifier
748         if (m_meta_mask == m_super_mask && (code == Qt::Key_Super_L || code == Qt::Key_Super_R)) {
749             code = Qt::Key_Meta;
750         } else if (m_meta_mask == m_hyper_mask && (code == Qt::Key_Hyper_L || code == Qt::Key_Hyper_R)) {
751             code = Qt::Key_Meta;
752         }
753     }
754     return code;
755 }
756
757 QString QXcbKeyboard::translateKeySym(xcb_keysym_t keysym, uint xmodifiers,
758                                       int &code, Qt::KeyboardModifiers &modifiers,
759                                       QByteArray &chars, int &count)
760 {
761     // all keysyms smaller than 0xff00 are actally keys that can be mapped to unicode chars
762
763     QTextCodec *mapper = QTextCodec::codecForLocale();
764     QChar converted;
765
766     if (/*count == 0 &&*/ keysym < 0xff00) {
767         unsigned char byte3 = (unsigned char)(keysym >> 8);
768         int mib = -1;
769         switch(byte3) {
770         case 0: // Latin 1
771         case 1: // Latin 2
772         case 2: //latin 3
773         case 3: // latin4
774             mib = byte3 + 4; break;
775         case 5: // arabic
776             mib = 82; break;
777         case 12: // Hebrew
778             mib = 85; break;
779         case 13: // Thai
780             mib = 2259; break;
781         case 4: // kana
782         case 6: // cyrillic
783         case 7: // greek
784         case 8: // technical, no mapping here at the moment
785         case 9: // Special
786         case 10: // Publishing
787         case 11: // APL
788         case 14: // Korean, no mapping
789             mib = -1; // manual conversion
790             mapper= 0;
791 #if !defined(QT_NO_XIM)
792             converted = keysymToUnicode(byte3, keysym & 0xff);
793 #endif
794         case 0x20:
795             // currency symbols
796             if (keysym >= 0x20a0 && keysym <= 0x20ac) {
797                 mib = -1; // manual conversion
798                 mapper = 0;
799                 converted = (uint)keysym;
800             }
801             break;
802         default:
803             break;
804         }
805         if (mib != -1) {
806             mapper = QTextCodec::codecForMib(mib);
807             if (chars.isEmpty())
808                 chars.resize(1);
809             chars[0] = (unsigned char) (keysym & 0xff); // get only the fourth bit for conversion later
810             count = 1;
811         }
812     } else if (keysym >= 0x1000000 && keysym <= 0x100ffff) {
813         converted = (ushort) (keysym - 0x1000000);
814         mapper = 0;
815     }
816     if (count < (int)chars.size()-1)
817         chars[count] = '\0';
818
819     QString text;
820     if (!mapper && converted.unicode() != 0x0) {
821         text = converted;
822     } else if (!chars.isEmpty()) {
823         // convert chars (8bit) to text (unicode).
824         if (mapper)
825             text = mapper->toUnicode(chars.data(), count, 0);
826         if (text.isEmpty()) {
827             // no mapper, or codec couldn't convert to unicode (this
828             // can happen when running in the C locale or with no LANG
829             // set). try converting from latin-1
830             text = QString::fromLatin1(chars);
831         }
832     }
833
834     modifiers = translateModifiers(xmodifiers);
835
836     // Commentary in X11/keysymdef says that X codes match ASCII, so it
837     // is safe to use the locale functions to process X codes in ISO8859-1.
838     //
839     // This is mainly for compatibility - applications should not use the
840     // Qt keycodes between 128 and 255, but should rather use the
841     // QKeyEvent::text().
842     //
843     if (keysym < 128 || (keysym < 256 && (!mapper || mapper->mibEnum()==4))) {
844         // upper-case key, if known
845         code = isprint((int)keysym) ? toupper((int)keysym) : 0;
846     } else if (keysym >= XK_F1 && keysym <= XK_F35) {
847         // function keys
848         code = Qt::Key_F1 + ((int)keysym - XK_F1);
849     } else if (keysym >= XK_KP_Space && keysym <= XK_KP_9) {
850         if (keysym >= XK_KP_0) {
851             // numeric keypad keys
852             code = Qt::Key_0 + ((int)keysym - XK_KP_0);
853         } else {
854             code = translateKeySym(keysym);
855         }
856         modifiers |= Qt::KeypadModifier;
857     } else if (text.length() == 1 && text.unicode()->unicode() > 0x1f && text.unicode()->unicode() != 0x7f && !(keysym >= XK_dead_grave && keysym <= XK_dead_horn)) {
858         code = text.unicode()->toUpper().unicode();
859     } else {
860         // any other keys
861         code = translateKeySym(keysym);
862
863         if (code == Qt::Key_Tab && (modifiers & Qt::ShiftModifier)) {
864             // map shift+tab to shift+backtab, QShortcutMap knows about it
865             // and will handle it.
866             code = Qt::Key_Backtab;
867             text = QString();
868         }
869     }
870
871     return text;
872 }
873
874 QXcbKeyboard::QXcbKeyboard(QXcbConnection *connection)
875     : QXcbObject(connection)
876     , m_autorepeat_code(0)
877 {
878     m_key_symbols = xcb_key_symbols_alloc(xcb_connection());
879     setupModifiers();
880 }
881
882 QXcbKeyboard::~QXcbKeyboard()
883 {
884     xcb_key_symbols_free(m_key_symbols);
885 }
886
887 void QXcbKeyboard::setupModifiers()
888 {
889     m_alt_mask = 0;
890     m_super_mask = 0;
891     m_hyper_mask = 0;
892     m_meta_mask = 0;
893     m_mode_switch_mask = 0;
894     m_num_lock_mask = 0;
895     m_caps_lock_mask = 0;
896
897     xcb_generic_error_t *error = 0;
898     xcb_connection_t *conn = xcb_connection();
899     xcb_get_modifier_mapping_cookie_t modMapCookie = xcb_get_modifier_mapping(conn);
900     xcb_get_modifier_mapping_reply_t *modMapReply =
901         xcb_get_modifier_mapping_reply(conn, modMapCookie, &error);
902     if (error) {
903         qWarning("QXcbKeyboard: failed to get modifier mapping");
904         free(error);
905         return;
906     }
907
908     // for Alt and Meta L and R are the same
909     static const xcb_keysym_t symbols[] = {
910         XK_Alt_L, XK_Meta_L, XK_Super_L, XK_Super_R,
911         XK_Hyper_L, XK_Hyper_R, XK_Num_Lock, XK_Mode_switch, XK_Caps_Lock,
912     };
913     static const size_t numSymbols = sizeof symbols / sizeof *symbols;
914
915     // Figure out the modifier mapping, ICCCM 6.6
916     xcb_keycode_t* modKeyCodes[numSymbols];
917     for (size_t i = 0; i < numSymbols; ++i)
918         modKeyCodes[i] = xcb_key_symbols_get_keycode(m_key_symbols, symbols[i]);
919
920     xcb_keycode_t *modMap = xcb_get_modifier_mapping_keycodes(modMapReply);
921     const int w = modMapReply->keycodes_per_modifier;
922     for (size_t i = 0; i < numSymbols; ++i) {
923         for (int bit = 0; bit < 8; ++bit) {
924             uint mask = 1 << bit;
925             for (int x = 0; x < w; ++x) {
926                 xcb_keycode_t keyCode = modMap[x + bit * w];
927                 xcb_keycode_t *itk = modKeyCodes[i];
928                 while (itk && *itk != XCB_NO_SYMBOL)
929                     if (*itk++ == keyCode)
930                         setMask(symbols[i], mask);
931             }
932         }
933     }
934
935     for (size_t i = 0; i < numSymbols; ++i)
936         free(modKeyCodes[i]);
937     free(modMapReply);
938 }
939
940 void QXcbKeyboard::setMask(uint sym, uint mask)
941 {
942     if (m_alt_mask == 0
943         && m_meta_mask != mask
944         && m_super_mask != mask
945         && m_hyper_mask != mask
946         && (sym == XK_Alt_L || sym == XK_Alt_R))
947         m_alt_mask = mask;
948
949     if (m_meta_mask == 0
950         && m_alt_mask != mask
951         && m_super_mask != mask
952         && m_hyper_mask != mask
953         && (sym == XK_Meta_L || sym == XK_Meta_R))
954         m_meta_mask = mask;
955
956     if (m_super_mask == 0
957         && m_alt_mask != mask
958         && m_meta_mask != mask
959         && m_hyper_mask != mask
960         && (sym == XK_Super_L || sym == XK_Super_R))
961         m_super_mask = mask;
962
963     if (m_hyper_mask == 0
964         && m_alt_mask != mask
965         && m_meta_mask != mask
966         && m_super_mask != mask
967         && (sym == XK_Hyper_L || sym == XK_Hyper_R))
968         m_hyper_mask = mask;
969
970     if (m_mode_switch_mask == 0
971         && m_alt_mask != mask
972         && m_meta_mask != mask
973         && m_super_mask != mask
974         && m_hyper_mask != mask
975         && sym == XK_Mode_switch)
976         m_mode_switch_mask = mask;
977
978     if (m_num_lock_mask == 0 && sym == XK_Num_Lock)
979         m_num_lock_mask = mask;
980
981     if (m_caps_lock_mask == 0 && sym == XK_Caps_Lock)
982         m_caps_lock_mask = mask;
983 }
984
985 // #define XCB_KEYBOARD_DEBUG
986
987 class KeyChecker
988 {
989 public:
990     KeyChecker(xcb_window_t window, xcb_keycode_t code, xcb_timestamp_t time)
991         : m_window(window)
992         , m_code(code)
993         , m_time(time)
994         , m_error(false)
995         , m_release(true)
996     {
997     }
998
999     bool checkEvent(xcb_generic_event_t *ev)
1000     {
1001         if (m_error || !ev)
1002             return false;
1003
1004         int type = ev->response_type & ~0x80;
1005         if (type != XCB_KEY_PRESS && type != XCB_KEY_RELEASE)
1006             return false;
1007
1008         xcb_key_press_event_t *event = (xcb_key_press_event_t *)ev;
1009
1010         if (event->event != m_window || event->detail != m_code) {
1011             m_error = true;
1012             return false;
1013         }
1014
1015         if (type == XCB_KEY_PRESS) {
1016             m_error = !m_release || event->time - m_time > 10;
1017             return !m_error;
1018         }
1019
1020         if (m_release) {
1021             m_error = true;
1022             return false;
1023         }
1024
1025         m_release = true;
1026         m_time = event->time;
1027
1028         return false;
1029     }
1030
1031     bool release() const { return m_release; }
1032     xcb_timestamp_t time() const { return m_time; }
1033
1034 private:
1035     xcb_window_t m_window;
1036     xcb_keycode_t m_code;
1037     xcb_timestamp_t m_time;
1038
1039     bool m_error;
1040     bool m_release;
1041 };
1042
1043 void QXcbKeyboard::handleKeyEvent(QWindow *window, QEvent::Type type, xcb_keycode_t code,
1044                                   quint16 state, xcb_timestamp_t time)
1045 {
1046     Q_XCB_NOOP(connection());
1047 #ifdef XCB_KEYBOARD_DEBUG
1048     printf("key code: %d, state: %d, syms: ", code, state);
1049     for (int i = 0; i <= 5; ++i) {
1050         printf("%d ", xcb_key_symbols_get_keysym(m_key_symbols, code, i));
1051     }
1052     printf("\n");
1053 #endif
1054
1055     QByteArray chars;
1056     xcb_keysym_t sym = lookupString(window, state, code, type, &chars);
1057     QPlatformInputContext *inputContext = QGuiApplicationPrivate::platformIntegration()->inputContext();
1058     QMetaMethod method;
1059
1060     if (inputContext) {
1061         int methodIndex = inputContext->metaObject()->indexOfMethod("x11FilterEvent(uint,uint,uint,bool)");
1062         if (methodIndex != -1)
1063             method = inputContext->metaObject()->method(methodIndex);
1064     }
1065
1066     if (method.isValid()) {
1067         bool retval = false;
1068         method.invoke(inputContext, Qt::DirectConnection,
1069                       Q_RETURN_ARG(bool, retval),
1070                       Q_ARG(uint, sym),
1071                       Q_ARG(uint, code),
1072                       Q_ARG(uint, state),
1073                       Q_ARG(bool, type == QEvent::KeyPress));
1074         if (retval)
1075             return;
1076     }
1077
1078     Qt::KeyboardModifiers modifiers;
1079     int qtcode = 0;
1080     int count = chars.count();
1081     QString string = translateKeySym(sym, state, qtcode, modifiers, chars, count);
1082
1083     bool isAutoRepeat = false;
1084
1085     if (type == QEvent::KeyPress) {
1086         if (m_autorepeat_code == code) {
1087             isAutoRepeat = true;
1088             m_autorepeat_code = 0;
1089         }
1090     } else {
1091         // look ahead for auto-repeat
1092         KeyChecker checker(((QXcbWindow *)window->handle())->xcb_window(), code, time);
1093         xcb_generic_event_t *event = connection()->checkEvent(checker);
1094         if (event) {
1095             isAutoRepeat = true;
1096             free(event);
1097         }
1098         m_autorepeat_code = isAutoRepeat ? code : 0;
1099     }
1100
1101     bool filtered = false;
1102     if (inputContext) {
1103         QKeyEvent event(type, qtcode, modifiers, string, isAutoRepeat);
1104         event.setTimestamp(time);
1105         filtered = inputContext->filterEvent(&event);
1106     }
1107
1108     if (!filtered)
1109         QWindowSystemInterface::handleExtendedKeyEvent(window, time, type, qtcode, modifiers,
1110                                                        code, 0, state, string.left(count), isAutoRepeat);
1111
1112     if (isAutoRepeat && type == QEvent::KeyRelease) {
1113         // since we removed it from the event queue using checkEvent we need to send the key press here
1114         filtered = false;
1115         if (method.isValid()) {
1116             method.invoke(inputContext, Qt::DirectConnection,
1117                           Q_RETURN_ARG(bool, filtered),
1118                           Q_ARG(uint, sym),
1119                           Q_ARG(uint, code),
1120                           Q_ARG(uint, state),
1121                           Q_ARG(bool, true));
1122         }
1123
1124         if (!filtered && inputContext) {
1125             QKeyEvent event(QEvent::KeyPress, qtcode, modifiers, string, isAutoRepeat);
1126             event.setTimestamp(time);
1127             filtered = inputContext->filterEvent(&event);
1128         }
1129         if (!filtered)
1130             QWindowSystemInterface::handleExtendedKeyEvent(window, time, QEvent::KeyPress, qtcode, modifiers,
1131                                                            code, 0, state, string.left(count), isAutoRepeat);
1132     }
1133 }
1134
1135 #ifdef XCB_USE_XLIB
1136 extern "C" {
1137     int XLookupString(void *event, char *buf, int count, void *keysym, void *comp);
1138 }
1139 typedef struct { // must match XKeyEvent in Xlib.h
1140     int type;
1141     unsigned long serial;
1142     int send_event;
1143     void *display;
1144     unsigned long window;
1145     unsigned long root;
1146     unsigned long subwindow;
1147     unsigned long time;
1148     int x, y;
1149     int x_root, y_root;
1150     unsigned int state;
1151     unsigned int keycode;
1152     int same_screen;
1153 } FakeXKeyEvent;
1154 #endif
1155
1156 xcb_keysym_t QXcbKeyboard::lookupString(QWindow *window, uint state, xcb_keycode_t code,
1157                                         QEvent::Type type, QByteArray *chars)
1158 {
1159 #ifdef XCB_USE_XLIB
1160
1161     xcb_keysym_t sym = XCB_NO_SYMBOL;
1162     chars->resize(512);
1163     FakeXKeyEvent event;
1164     memset(&event, 0, sizeof(event));
1165     event.type = (type == QEvent::KeyRelease ? 3 : 2);
1166     event.display = connection()->xlib_display();
1167     event.window = static_cast<QXcbWindow *>(window->handle())->xcb_window();
1168     event.root = connection()->screens().at(0)->root();
1169     event.state = state;
1170     event.keycode = code;
1171     int count = XLookupString(&event, chars->data(), chars->size(), &sym, 0);
1172     chars->resize(count);
1173     return sym;
1174
1175 #else
1176
1177     // No XLookupString available. The following is really incomplete...
1178
1179     int col = state & XCB_MOD_MASK_SHIFT ? 1 : 0;
1180     const int altGrOffset = 4;
1181     if (state & 128)
1182         col += altGrOffset;
1183     xcb_keysym_t sym = xcb_key_symbols_get_keysym(m_key_symbols, code, col);
1184     if (sym == XCB_NO_SYMBOL)
1185         sym = xcb_key_symbols_get_keysym(m_key_symbols, code, col ^ 0x1);
1186     if (state & XCB_MOD_MASK_LOCK && sym <= 0x7f && isprint(sym)) {
1187         if (isupper(sym))
1188             sym = tolower(sym);
1189         else
1190             sym = toupper(sym);
1191     }
1192     return sym;
1193
1194 #endif
1195 }
1196
1197 void QXcbKeyboard::handleKeyPressEvent(QXcbWindow *window, const xcb_key_press_event_t *event)
1198 {
1199     window->updateNetWmUserTime(event->time);
1200     handleKeyEvent(window->window(), QEvent::KeyPress, event->detail, event->state, event->time);
1201 }
1202
1203 void QXcbKeyboard::handleKeyReleaseEvent(QXcbWindow *window, const xcb_key_release_event_t *event)
1204 {
1205     handleKeyEvent(window->window(), QEvent::KeyRelease, event->detail, event->state, event->time);
1206 }
1207
1208 void QXcbKeyboard::handleMappingNotifyEvent(const xcb_mapping_notify_event_t *event)
1209 {
1210     xcb_refresh_keyboard_mapping(m_key_symbols, const_cast<xcb_mapping_notify_event_t *>(event));
1211     setupModifiers();
1212 }
1213
1214 QT_END_NAMESPACE