1 /****************************************************************************
2 **
3 ** Copyright (C) 2015 The Qt Company Ltd.
4 ** Contact: http://www.qt.io/licensing/
5 **
6 ** This file is part of the QtGui module of the Qt Toolkit.
7 **
8 ** $QT_BEGIN_LICENSE:LGPL$
9 ** Commercial License Usage
10 ** Licensees holding valid commercial Qt licenses may use this file in
11 ** accordance with the commercial license agreement provided with the
12 ** Software or, alternatively, in accordance with the terms contained in
13 ** a written agreement between you and The Qt Company. For licensing terms
14 ** and conditions see http://www.qt.io/terms-conditions. For further
15 ** information use the contact form at http://www.qt.io/contact-us.
16 **
17 ** GNU Lesser General Public License Usage
18 ** Alternatively, this file may be used under the terms of the GNU Lesser
19 ** General Public License version 2.1 or version 3 as published by the Free
20 ** Software Foundation and appearing in the file LICENSE.LGPLv21 and
21 ** LICENSE.LGPLv3 included in the packaging of this file. Please review the
22 ** following information to ensure the GNU Lesser General Public License
23 ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
24 ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
25 **
26 ** As a special exception, The Qt Company gives you certain additional
27 ** rights. These rights are described in The Qt Company LGPL Exception
28 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
29 **
30 ** GNU General Public License Usage
31 ** Alternatively, this file may be used under the terms of the GNU
32 ** General Public License version 3.0 as published by the Free Software
33 ** Foundation and appearing in the file LICENSE.GPL included in the
34 ** packaging of this file.  Please review the following information to
35 ** ensure the GNU General Public License version 3.0 requirements will be
36 ** met: http://www.gnu.org/copyleft/gpl.html.
37 **
38 ** $QT_END_LICENSE$
39 **
40 ****************************************************************************/
41 
42 #include "qkeymapper_p.h"
43 
44 #include "qdebug.h"
45 #include "qtextcodec.h"
46 #include "qwidget.h"
47 
48 #include "qapplication_p.h"
49 #include "qevent_p.h"
50 #include "qt_x11_p.h"
51 
52 #ifndef QT_NO_XKB
53 #  include <X11/XKBlib.h>
54 #endif
55 
56 #define XK_MISCELLANY
57 #define XK_LATIN1
58 #define XK_KOREAN
59 #define XK_XKB_KEYS
60 #include <X11/keysymdef.h>
61 
62 #include <ctype.h>
63 
64 #ifdef QT_LINUXBASE
65 // LSB's IsKeypadKey define is wrong - see
66 // http://bugs.linuxbase.org/show_bug.cgi?id=2521
67 #undef IsKeypadKey
68 #define IsKeypadKey(keysym) \
69       (((KeySym)(keysym) >= XK_KP_Space) && ((KeySym)(keysym) <= XK_KP_Equal))
70 
71 #undef IsPrivateKeypadKey
72 #define IsPrivateKeypadKey(keysym) \
73       (((KeySym)(keysym) >= 0x11000000) && ((KeySym)(keysym) <= 0x1100FFFF))
74 #endif
75 
76 QT_BEGIN_NAMESPACE
77 
78 #ifndef QT_NO_XKB
79 
80 // bring in the auto-generated xkbLayoutData
81 #include "qkeymapper_x11_p.cpp"
82 
q_getKeyboardLocale(const QByteArray & layoutName,const QByteArray & variantName)83 QLocale q_getKeyboardLocale(const QByteArray &layoutName, const QByteArray &variantName)
84 {
85     int i = 0;
86     while (xkbLayoutData[i].layout != 0) {
87         if (layoutName == xkbLayoutData[i].layout && variantName == xkbLayoutData[i].variant)
88             return QLocale(xkbLayoutData[i].language, xkbLayoutData[i].country);
89         ++i;
90     }
91     return QLocale::c();
92 }
93 #endif // QT_NO_XKB
94 
95 // from qapplication_x11.cpp
96 extern uchar qt_alt_mask;
97 extern uchar qt_meta_mask;
98 extern uchar qt_super_mask;
99 extern uchar qt_hyper_mask;
100 extern uchar qt_mode_switch_mask;
101 uchar qt_num_lock_mask = 0;
102 extern bool qt_sendSpontaneousEvent(QObject*, QEvent*);
103 
104 // ### we should really resolve conflicts with other masks by
105 // ### decomposing the Qt::KeyboardModifers in possibleKeys()
106 #define SETMASK(sym, mask)                                              \
107     do {                                                                \
108         if (qt_alt_mask == 0                                            \
109             && qt_meta_mask != mask                                     \
110             && qt_super_mask != mask                                    \
111             && qt_hyper_mask != mask                                    \
112             && (sym == XK_Alt_L || sym == XK_Alt_R)) {                  \
113             qt_alt_mask = mask;                                         \
114         }                                                               \
115         if (qt_meta_mask == 0                                           \
116             && qt_alt_mask != mask                                      \
117             && qt_super_mask != mask                                    \
118             && qt_hyper_mask != mask                                    \
119             && (sym == XK_Meta_L || sym == XK_Meta_R)) {                \
120             qt_meta_mask = mask;                                        \
121         }                                                               \
122         if (qt_super_mask == 0                                          \
123             && qt_alt_mask != mask                                      \
124             && qt_meta_mask != mask                                     \
125             && qt_hyper_mask != mask                                    \
126             && (sym == XK_Super_L || sym == XK_Super_R)) {              \
127             qt_super_mask = mask;                                       \
128         }                                                               \
129         if (qt_hyper_mask == 0                                          \
130             && qt_alt_mask != mask                                      \
131             && qt_meta_mask != mask                                     \
132             && qt_super_mask != mask                                    \
133             && (sym == XK_Hyper_L || sym == XK_Hyper_R)) {              \
134             qt_hyper_mask = mask;                                       \
135         }                                                               \
136         if (qt_mode_switch_mask == 0                                    \
137             && qt_alt_mask != mask                                      \
138             && qt_meta_mask != mask                                     \
139             && qt_super_mask != mask                                    \
140             && qt_hyper_mask != mask                                    \
141             && sym == XK_Mode_switch) {                                 \
142             qt_mode_switch_mask = mask;                                 \
143         }                                                               \
144         if (qt_num_lock_mask == 0                                       \
145             && sym == XK_Num_Lock) {                                    \
146             qt_num_lock_mask = mask;                                    \
147         }                                                               \
148     } while(false)
149 
150 // qt_XTranslateKey() is based on _XTranslateKey() taken from:
151 
152 /* $Xorg: KeyBind.c,v 1.4 2001/02/09 02:03:34 xorgcvs Exp $ */
153 
154 /*
155 
156 Copyright 1985, 1987, 1998  The Open Group
157 
158 Permission to use, copy, modify, distribute, and sell this software and its
159 documentation for any purpose is hereby granted without fee, provided that
160 the above copyright notice appear in all copies and that both that
161 copyright notice and this permission notice appear in supporting
162 documentation.
163 
164 The above copyright notice and this permission notice shall be included in
165 all copies or substantial portions of the Software.
166 
167 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
168 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
169 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
170 OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
171 AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
172 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
173 
174 Except as contained in this notice, the name of The Open Group shall not be
175 used in advertising or otherwise to promote the sale, use or other dealings
176 in this Software without prior written authorization from The Open Group.
177 
178 */
179 static int
qt_XTranslateKey(register QXCoreDesc * dpy,KeyCode keycode,register unsigned int modifiers,unsigned int * modifiers_return,KeySym * keysym_return)180 qt_XTranslateKey(register QXCoreDesc *dpy,
181                  KeyCode keycode,
182                  register unsigned int modifiers,
183                  unsigned int *modifiers_return,
184                  KeySym *keysym_return)
185 {
186     int per;
187     register KeySym *syms;
188     KeySym sym, lsym, usym;
189 
190     if (! dpy->keysyms)
191 	return 0;
192     *modifiers_return = ((ShiftMask|LockMask)
193 			 | dpy->mode_switch | dpy->num_lock);
194     if (((int)keycode < dpy->min_keycode) || ((int)keycode > dpy->max_keycode))
195     {
196 	*keysym_return = NoSymbol;
197 	return 1;
198     }
199     per = dpy->keysyms_per_keycode;
200     syms = &dpy->keysyms[(keycode - dpy->min_keycode) * per];
201     while ((per > 2) && (syms[per - 1] == NoSymbol))
202 	per--;
203     if ((per > 2) && (modifiers & dpy->mode_switch)) {
204 	syms += 2;
205 	per -= 2;
206     }
207     if ((modifiers & dpy->num_lock) &&
208 	(per > 1 && (IsKeypadKey(syms[1]) || IsPrivateKeypadKey(syms[1])))) {
209 	if ((modifiers & ShiftMask) ||
210 	    ((modifiers & LockMask) && (dpy->lock_meaning == XK_Shift_Lock)))
211 	    *keysym_return = syms[0];
212 	else
213 	    *keysym_return = syms[1];
214     } else if (!(modifiers & ShiftMask) &&
215 	(!(modifiers & LockMask) || (dpy->lock_meaning == NoSymbol))) {
216 	if ((per == 1) || (syms[1] == NoSymbol))
217 	    XConvertCase(syms[0], keysym_return, &usym);
218 	else
219 	    *keysym_return = syms[0];
220     } else if (!(modifiers & LockMask) ||
221 	       (dpy->lock_meaning != XK_Caps_Lock)) {
222 	if ((per == 1) || ((usym = syms[1]) == NoSymbol))
223 	    XConvertCase(syms[0], &lsym, &usym);
224 	*keysym_return = usym;
225     } else {
226 	if ((per == 1) || ((sym = syms[1]) == NoSymbol))
227 	    sym = syms[0];
228 	XConvertCase(sym, &lsym, &usym);
229 	if (!(modifiers & ShiftMask) && (sym != syms[0]) &&
230 	    ((sym != usym) || (lsym == usym)))
231 	    XConvertCase(syms[0], &lsym, &usym);
232 	*keysym_return = usym;
233     }
234     if (*keysym_return == XK_VoidSymbol)
235 	*keysym_return = NoSymbol;
236     return 1;
237 }
238 
239 
240 
241 
QKeyMapperPrivate()242 QKeyMapperPrivate::QKeyMapperPrivate()
243     : keyboardInputDirection(Qt::LeftToRight), xkb_currentGroup(0)
244 {
245     memset(&coreDesc, 0, sizeof(coreDesc));
246 
247 #ifndef QT_NO_XKB
248     if (X11->use_xkb) {
249         // get the current group
250         XkbStateRec xkbState;
251         if (XkbGetState(X11->display, XkbUseCoreKbd, &xkbState) == Success)
252             xkb_currentGroup = xkbState.group;
253     }
254 #endif
255 }
256 
~QKeyMapperPrivate()257 QKeyMapperPrivate::~QKeyMapperPrivate()
258 {
259     if (coreDesc.keysyms)
260         XFree(coreDesc.keysyms);
261 }
262 
possibleKeys(QKeyEvent * event)263 QList<int> QKeyMapperPrivate::possibleKeys(QKeyEvent *event)
264 {
265 #ifndef QT_NO_XKB
266     if (X11->use_xkb)
267         return possibleKeysXKB(event);
268 #endif
269     return possibleKeysCore(event);
270 }
271 
272 enum { MaxBits = sizeof(uint) * 8 };
273 static QString translateKeySym(KeySym keysym, uint xmodifiers,
274                                int &code, Qt::KeyboardModifiers &modifiers,
275                                QByteArray &chars, int &count);
276 
possibleKeysXKB(QKeyEvent * event)277 QList<int> QKeyMapperPrivate::possibleKeysXKB(QKeyEvent *event)
278 {
279 #ifndef QT_NO_XKB
280     const int xkeycode = event->nativeScanCode();
281     const uint xmodifiers = event->nativeModifiers();
282 
283     // first, translate key only using lock modifiers (there are no Qt equivalents for these, so we must
284     // always use them when determining the baseKeySym)
285     KeySym baseKeySym;
286     uint consumedModifiers;
287     if (!XkbLookupKeySym(X11->display, xkeycode, (xmodifiers & (LockMask | qt_num_lock_mask)),
288                          &consumedModifiers, &baseKeySym))
289         return QList<int>();
290 
291     QList<int> result;
292 
293     // translate sym -> code
294     Qt::KeyboardModifiers baseModifiers = 0;
295     int baseCode = -1;
296     QByteArray chars;
297     int count = 0;
298     QString text = translateKeySym(baseKeySym, xmodifiers, baseCode, baseModifiers, chars, count);
299     if (baseCode == -1) {
300         if (text.isEmpty())
301             return QList<int>();
302         baseCode = text.at(0).unicode();
303     }
304 
305     if (baseCode && baseCode < 0xfffe)
306         baseCode = QChar(baseCode).toUpper().unicode();
307     result += (baseCode | baseModifiers);
308 
309     int pos1Bits[MaxBits];
310     int num1Bits = 0;
311 
312     for (int i = 0; i < MaxBits; ++i) {
313         if (consumedModifiers & (1 << i))
314             pos1Bits[num1Bits++] = i;
315     }
316 
317     const int numPerms = (1 << num1Bits);
318 
319     // translate the key again using each permutation of consumedModifiers
320     for (int i = 1; i < numPerms; ++i) {
321         uint val = 0;
322         for (int j = 0; j < num1Bits; ++j) {
323             if (i & (1 << j))
324                 val |= (1 << pos1Bits[j]);
325         }
326 
327         if ((xmodifiers & val) != val)
328             continue;
329 
330         KeySym sym;
331         uint mods;
332         if (!XkbLookupKeySym(X11->display, xkeycode, val, &mods, &sym))
333             continue;
334 
335         // translate sym -> code
336         Qt::KeyboardModifiers modifiers = 0;
337         int code = -1;
338         chars.clear();
339         count = 0;
340         // mask out the modifiers needed to translate keycode
341         text = translateKeySym(sym, xmodifiers & ~val, code, modifiers, chars, count);
342         if (code == -1) {
343             if (text.isEmpty())
344                 continue;
345             code = text.at(0).unicode();
346         }
347 
348         if (code && code < 0xfffe)
349             code = QChar(code).toUpper().unicode();
350 
351         if (code == Qt::Key_Tab && (baseModifiers & Qt::ShiftModifier)) {
352             // map shift+tab to shift+backtab
353             code = Qt::Key_Backtab;
354             text = QString();
355         }
356 
357         if (code == baseCode)
358             continue;
359 
360         result += (code | modifiers);
361     }
362 
363 #if 0
364     qDebug() << "possibleKeysXKB()" << hex << result;
365 #endif
366     return result;
367 #else
368     Q_UNUSED(event);
369     return QList<int>();
370 #endif // QT_NO_XKB
371 }
372 
possibleKeysCore(QKeyEvent * event)373 QList<int> QKeyMapperPrivate::possibleKeysCore(QKeyEvent *event)
374 {
375     const int xkeycode = event->nativeScanCode();
376     const uint xmodifiers = event->nativeModifiers();
377 
378     // first, translate key only using lock modifiers (there are no Qt equivalents for these, so we must
379     // always use them when determining the baseKeySym)
380     KeySym baseKeySym;
381     uint consumedModifiers;
382     if (!qt_XTranslateKey(&coreDesc, xkeycode, (xmodifiers & (LockMask | qt_num_lock_mask)),
383                           &consumedModifiers, &baseKeySym))
384         return QList<int>();
385 
386     QList<int> result;
387 
388     // translate sym -> code
389     Qt::KeyboardModifiers baseModifiers = 0;
390     int baseCode = -1;
391     QByteArray chars;
392     int count = 0;
393     QString text = translateKeySym(baseKeySym, xmodifiers, baseCode, baseModifiers, chars, count);
394     if (baseCode == -1) {
395         if (text.isEmpty())
396             return QList<int>();
397         baseCode = text.at(0).unicode();
398     }
399 
400     if (baseCode && baseCode < 0xfffe)
401         baseCode = QChar(baseCode).toUpper().unicode();
402     result += (baseCode | baseModifiers);
403 
404     int pos1Bits[MaxBits];
405     int num1Bits = 0;
406 
407     for (int i = 0; i < MaxBits; ++i) {
408         if (consumedModifiers & (1 << i))
409             pos1Bits[num1Bits++] = i;
410     }
411 
412     const int numPerms = (1 << num1Bits);
413 
414     // translate the key again using each permutation of consumedModifiers
415     for (int i = 1; i < numPerms; ++i) {
416         uint val = 0;
417         for (int j = 0; j < num1Bits; ++j) {
418             if (i & (1 << j))
419                 val |= (1 << pos1Bits[j]);
420         }
421 
422         if ((xmodifiers & val) != val)
423             continue;
424 
425         KeySym sym;
426         uint mods;
427         if (!qt_XTranslateKey(&coreDesc, xkeycode, val, &mods, &sym))
428             continue;
429 
430         // translate sym -> code
431         Qt::KeyboardModifiers modifiers = 0;
432         int code = -1;
433         chars.clear();
434         count = 0;
435         // mask out the modifiers needed to translate keycode
436         text = translateKeySym(sym, xmodifiers & ~val, code, modifiers, chars, count);
437         if (code == -1) {
438             if (text.isEmpty())
439                 continue;
440             code = text.at(0).unicode();
441         }
442 
443         if (code && code < 0xfffe)
444             code = QChar(code).toUpper().unicode();
445 
446         if (code == Qt::Key_Tab && (baseModifiers & Qt::ShiftModifier)) {
447             // map shift+tab to shift+backtab
448             code = Qt::Key_Backtab;
449             text = QString();
450         }
451 
452         if (code == baseCode)
453             continue;
454 
455         result += (code | modifiers);
456     }
457 
458 #if 0
459     qDebug() << "possibleKeysCore()" << hex << result;
460 #endif
461     return result;
462 }
463 
464 // for parsing the _XKB_RULES_NAMES property
465 enum {
466     RulesFileIndex = 0,
467     ModelIndex = 1,
468     LayoutIndex = 2,
469     VariantIndex = 3,
470     OptionsIndex = 4
471 };
472 
clearMappings()473 void QKeyMapperPrivate::clearMappings()
474 {
475 #ifndef QT_NO_XKB
476     if (X11->use_xkb) {
477         // try to determine the layout name and input direction by reading the _XKB_RULES_NAMES property off
478         // the root window
479         QByteArray layoutName;
480         QByteArray variantName;
481 
482         Atom type = XNone;
483         int format = 0;
484         ulong nitems = 0;
485         ulong bytesAfter = 0;
486         uchar *data = 0;
487         if (XGetWindowProperty(X11->display, RootWindow(X11->display, 0), ATOM(_XKB_RULES_NAMES), 0, 1024,
488                                false, XA_STRING, &type, &format, &nitems, &bytesAfter, &data) == Success
489             && type == XA_STRING && format == 8 && nitems > 2) {
490             /*
491               index 0 == rules file name
492               index 1 == model name
493               index 2 == layout name
494               index 3 == variant name
495               index 4 == options
496             */
497             char *names[5] = { 0, 0, 0, 0, 0 };
498             char *p = reinterpret_cast<char *>(data), *end = p + nitems;
499             int i = 0;
500             do {
501                 names[i++] = p;
502                 p += qstrlen(p) + 1;
503             } while (p < end);
504 
505             // the layout names and variants are saved in the _XKB_RULES_NAMES property as a comma separated list
506             QList<QByteArray> layoutNames = QByteArray::fromRawData(names[2], qstrlen(names[2])).split(',');
507             if (uint(xkb_currentGroup) < uint(layoutNames.count()))
508                 layoutName = layoutNames.at(xkb_currentGroup);
509             QList<QByteArray> variantNames = QByteArray::fromRawData(names[3], qstrlen(names[3])).split(',');
510             if (uint(xkb_currentGroup) < uint(variantNames.count()))
511                 variantName = variantNames.at(xkb_currentGroup);
512         }
513 
514         // ### ???
515         // if (keyboardLayoutName.isEmpty())
516         //     qWarning("Qt: unable to determine keyboard layout, please talk to qt-bugs@trolltech.com"); ?
517 
518         keyboardInputLocale = q_getKeyboardLocale(layoutName, variantName);
519         keyboardInputDirection = keyboardInputLocale.textDirection();
520 
521 #if 0
522         qDebug() << "keyboard input locale ="
523                  << keyboardInputLocale.name()
524                  << "direction ="
525                  << keyboardInputDirection;
526 #endif
527         if (data)
528             XFree(data);
529     } else
530 #endif // QT_NO_XKB
531         {
532             if (coreDesc.keysyms)
533                 XFree(coreDesc.keysyms);
534 
535             coreDesc.min_keycode = 8;
536             coreDesc.max_keycode = 255;
537             XDisplayKeycodes(X11->display, &coreDesc.min_keycode, &coreDesc.max_keycode);
538 
539             coreDesc.keysyms_per_keycode = 0;
540             coreDesc.keysyms = XGetKeyboardMapping(X11->display,
541                                                    coreDesc.min_keycode,
542                                                    coreDesc.max_keycode - coreDesc.min_keycode + 1,
543                                                    &coreDesc.keysyms_per_keycode);
544 
545 #if 0
546             qDebug() << "min_keycode =" << coreDesc.min_keycode;
547             qDebug() << "max_keycode =" << coreDesc.max_keycode;
548             qDebug() << "keysyms_per_keycode =" << coreDesc.keysyms_per_keycode;
549             qDebug() << "keysyms =" << coreDesc.keysyms;
550 #endif
551 
552             // ### cannot get/guess the locale with the core protocol
553             keyboardInputLocale = QLocale::c();
554             // ### could examine group 0 for RTL keys
555             keyboardInputDirection = Qt::LeftToRight;
556         }
557 
558     qt_alt_mask = 0;
559     qt_meta_mask = 0;
560     qt_super_mask = 0;
561     qt_hyper_mask = 0;
562     qt_mode_switch_mask = 0;
563 
564     // look at the modifier mapping, and get the correct masks for alt, meta, super, hyper, and mode_switch
565 #ifndef QT_NO_XKB
566     if (X11->use_xkb) {
567         XkbDescPtr xkbDesc = XkbGetMap(X11->display, XkbAllClientInfoMask, XkbUseCoreKbd);
568         for (int i = xkbDesc->min_key_code; i < xkbDesc->max_key_code; ++i) {
569             const uint mask = xkbDesc->map->modmap ? xkbDesc->map->modmap[i] : 0;
570             if (mask == 0) {
571                 // key is not bound to a modifier
572                 continue;
573             }
574 
575             for (int j = 0; j < XkbKeyGroupsWidth(xkbDesc, i); ++j) {
576                 KeySym keySym = XkbKeySym(xkbDesc, i, j);
577                 if (keySym == NoSymbol)
578                     continue;
579                 SETMASK(keySym, mask);
580             }
581         }
582         XkbFreeKeyboard(xkbDesc, XkbAllComponentsMask, true);
583     } else
584 #endif // QT_NO_XKB
585         {
586             coreDesc.lock_meaning = NoSymbol;
587 
588             XModifierKeymap *map = XGetModifierMapping(X11->display);
589 
590             if (map) {
591                 int i, maskIndex = 0, mapIndex = 0;
592                 for (maskIndex = 0; maskIndex < 8; maskIndex++) {
593                     for (i = 0; i < map->max_keypermod; i++) {
594                         if (map->modifiermap[mapIndex]) {
595                             KeySym sym;
596                             int x = 0;
597                             do {
598                                 sym = XKeycodeToKeysym(X11->display, map->modifiermap[mapIndex], x++);
599                             } while (sym == NoSymbol && x < coreDesc.keysyms_per_keycode);
600                             const uchar mask = 1 << maskIndex;
601                             SETMASK(sym, mask);
602                         }
603                         mapIndex++;
604                     }
605                 }
606 
607                 // determine the meaning of the Lock modifier
608                 for (i = 0; i < map->max_keypermod; ++i) {
609                     for (int x = 0; x < coreDesc.keysyms_per_keycode; ++x) {
610                         KeySym sym = XKeycodeToKeysym(X11->display, map->modifiermap[LockMapIndex], x);
611                         if (sym == XK_Caps_Lock || sym == XK_ISO_Lock) {
612                             coreDesc.lock_meaning = XK_Caps_Lock;
613                             break;
614                         } else if (sym == XK_Shift_Lock) {
615                             coreDesc.lock_meaning = XK_Shift_Lock;
616                         }
617                     }
618                 }
619 
620                 XFreeModifiermap(map);
621             }
622 
623             // for qt_XTranslateKey()
624             coreDesc.num_lock = qt_num_lock_mask;
625             coreDesc.mode_switch = qt_mode_switch_mask;
626 
627 #if 0
628             qDebug() << "lock_meaning =" << coreDesc.lock_meaning;
629             qDebug() << "num_lock =" << coreDesc.num_lock;
630             qDebug() << "mode_switch =" << coreDesc.mode_switch;
631 #endif
632         }
633 
634     // set default modifier masks if needed
635     if( qt_alt_mask == 0 )
636         qt_alt_mask = Mod1Mask;
637     if( qt_meta_mask == 0 )
638         qt_meta_mask = Mod4Mask;
639 
640     // if we don't have a meta key (or it's hidden behind alt), use super or hyper to generate
641     // Qt::Key_Meta and Qt::MetaModifier, since most newer XFree86/Xorg installations map the Windows
642     // key to Super
643     if (qt_meta_mask == 0 || qt_meta_mask == qt_alt_mask) {
644         // no meta keys... s,meta,super,
645         qt_meta_mask = qt_super_mask;
646         if (qt_meta_mask == 0 || qt_meta_mask == qt_alt_mask) {
647             // no super keys either? guess we'll use hyper then
648             qt_meta_mask = qt_hyper_mask;
649         }
650     }
651 
652 #if 0
653     qDebug() << "qt_alt_mask =" << hex << qt_alt_mask;
654     qDebug() << "qt_meta_mask =" << hex << qt_meta_mask;
655     qDebug() << "qt_super_mask =" << hex << qt_super_mask;
656     qDebug() << "qt_hyper_mask =" << hex << qt_hyper_mask;
657     qDebug() << "qt_mode_switch_mask =" << hex << qt_mode_switch_mask;
658     qDebug() << "qt_num_lock_mask =" << hex << qt_num_lock_mask;
659 #endif
660 }
661 
662 extern bool qt_sm_blockUserInput;
663 
664 //
665 // Keyboard event translation
666 //
667 
668 #ifndef XK_ISO_Left_Tab
669 #define XK_ISO_Left_Tab         0xFE20
670 #endif
671 
672 #ifndef XK_dead_hook
673 #define XK_dead_hook            0xFE61
674 #endif
675 
676 #ifndef XK_dead_horn
677 #define XK_dead_horn            0xFE62
678 #endif
679 
680 #ifndef XK_Codeinput
681 #define XK_Codeinput            0xFF37
682 #endif
683 
684 #ifndef XK_Kanji_Bangou
685 #define XK_Kanji_Bangou         0xFF37 /* same as codeinput */
686 #endif
687 
688 // Fix old X libraries
689 #ifndef XK_KP_Home
690 #define XK_KP_Home              0xFF95
691 #endif
692 #ifndef XK_KP_Left
693 #define XK_KP_Left              0xFF96
694 #endif
695 #ifndef XK_KP_Up
696 #define XK_KP_Up                0xFF97
697 #endif
698 #ifndef XK_KP_Right
699 #define XK_KP_Right             0xFF98
700 #endif
701 #ifndef XK_KP_Down
702 #define XK_KP_Down              0xFF99
703 #endif
704 #ifndef XK_KP_Prior
705 #define XK_KP_Prior             0xFF9A
706 #endif
707 #ifndef XK_KP_Next
708 #define XK_KP_Next              0xFF9B
709 #endif
710 #ifndef XK_KP_End
711 #define XK_KP_End               0xFF9C
712 #endif
713 #ifndef XK_KP_Insert
714 #define XK_KP_Insert            0xFF9E
715 #endif
716 #ifndef XK_KP_Delete
717 #define XK_KP_Delete            0xFF9F
718 #endif
719 
720 // the next lines are taken on 10/2009 from X.org (X11/XF86keysym.h), defining some special
721 // multimedia keys. They are included here as not every system has them.
722 #define XF86XK_MonBrightnessUp     0x1008FF02
723 #define XF86XK_MonBrightnessDown   0x1008FF03
724 #define XF86XK_KbdLightOnOff       0x1008FF04
725 #define XF86XK_KbdBrightnessUp     0x1008FF05
726 #define XF86XK_KbdBrightnessDown   0x1008FF06
727 #define XF86XK_Standby             0x1008FF10
728 #define XF86XK_AudioLowerVolume	   0x1008FF11
729 #define XF86XK_AudioMute           0x1008FF12
730 #define XF86XK_AudioRaiseVolume    0x1008FF13
731 #define XF86XK_AudioPlay           0x1008FF14
732 #define XF86XK_AudioStop           0x1008FF15
733 #define XF86XK_AudioPrev           0x1008FF16
734 #define XF86XK_AudioNext           0x1008FF17
735 #define XF86XK_HomePage            0x1008FF18
736 #define XF86XK_Mail                0x1008FF19
737 #define XF86XK_Start               0x1008FF1A
738 #define XF86XK_Search              0x1008FF1B
739 #define XF86XK_AudioRecord         0x1008FF1C
740 #define XF86XK_Calculator          0x1008FF1D
741 #define XF86XK_Memo                0x1008FF1E
742 #define XF86XK_ToDoList            0x1008FF1F
743 #define XF86XK_Calendar            0x1008FF20
744 #define XF86XK_PowerDown           0x1008FF21
745 #define XF86XK_ContrastAdjust      0x1008FF22
746 #define XF86XK_Back                0x1008FF26
747 #define XF86XK_Forward             0x1008FF27
748 #define XF86XK_Stop                0x1008FF28
749 #define XF86XK_Refresh             0x1008FF29
750 #define XF86XK_PowerOff            0x1008FF2A
751 #define XF86XK_WakeUp              0x1008FF2B
752 #define XF86XK_Eject               0x1008FF2C
753 #define XF86XK_ScreenSaver         0x1008FF2D
754 #define XF86XK_WWW                 0x1008FF2E
755 #define XF86XK_Sleep               0x1008FF2F
756 #define XF86XK_Favorites           0x1008FF30
757 #define XF86XK_AudioPause          0x1008FF31
758 #define XF86XK_AudioMedia          0x1008FF32
759 #define XF86XK_MyComputer          0x1008FF33
760 #define XF86XK_LightBulb           0x1008FF35
761 #define XF86XK_Shop                0x1008FF36
762 #define XF86XK_History             0x1008FF37
763 #define XF86XK_OpenURL             0x1008FF38
764 #define XF86XK_AddFavorite         0x1008FF39
765 #define XF86XK_HotLinks            0x1008FF3A
766 #define XF86XK_BrightnessAdjust    0x1008FF3B
767 #define XF86XK_Finance             0x1008FF3C
768 #define XF86XK_Community           0x1008FF3D
769 #define XF86XK_AudioRewind         0x1008FF3E
770 #define XF86XK_BackForward         0x1008FF3F
771 #define XF86XK_Launch0             0x1008FF40
772 #define XF86XK_Launch1             0x1008FF41
773 #define XF86XK_Launch2             0x1008FF42
774 #define XF86XK_Launch3             0x1008FF43
775 #define XF86XK_Launch4             0x1008FF44
776 #define XF86XK_Launch5             0x1008FF45
777 #define XF86XK_Launch6             0x1008FF46
778 #define XF86XK_Launch7             0x1008FF47
779 #define XF86XK_Launch8             0x1008FF48
780 #define XF86XK_Launch9             0x1008FF49
781 #define XF86XK_LaunchA             0x1008FF4A
782 #define XF86XK_LaunchB             0x1008FF4B
783 #define XF86XK_LaunchC             0x1008FF4C
784 #define XF86XK_LaunchD             0x1008FF4D
785 #define XF86XK_LaunchE             0x1008FF4E
786 #define XF86XK_LaunchF             0x1008FF4F
787 #define XF86XK_ApplicationLeft     0x1008FF50
788 #define XF86XK_ApplicationRight    0x1008FF51
789 #define XF86XK_Book                0x1008FF52
790 #define XF86XK_CD                  0x1008FF53
791 #define XF86XK_Calculater          0x1008FF54
792 #define XF86XK_Clear               0x1008FF55
793 #define XF86XK_ClearGrab           0x1008FE21
794 #define XF86XK_Close               0x1008FF56
795 #define XF86XK_Copy                0x1008FF57
796 #define XF86XK_Cut                 0x1008FF58
797 #define XF86XK_Display             0x1008FF59
798 #define XF86XK_DOS                 0x1008FF5A
799 #define XF86XK_Documents           0x1008FF5B
800 #define XF86XK_Excel               0x1008FF5C
801 #define XF86XK_Explorer            0x1008FF5D
802 #define XF86XK_Game                0x1008FF5E
803 #define XF86XK_Go                  0x1008FF5F
804 #define XF86XK_iTouch              0x1008FF60
805 #define XF86XK_LogOff              0x1008FF61
806 #define XF86XK_Market              0x1008FF62
807 #define XF86XK_Meeting             0x1008FF63
808 #define XF86XK_MenuKB              0x1008FF65
809 #define XF86XK_MenuPB              0x1008FF66
810 #define XF86XK_MySites             0x1008FF67
811 #define XF86XK_News                0x1008FF69
812 #define XF86XK_OfficeHome          0x1008FF6A
813 #define XF86XK_Option              0x1008FF6C
814 #define XF86XK_Paste               0x1008FF6D
815 #define XF86XK_Phone               0x1008FF6E
816 #define XF86XK_Reply               0x1008FF72
817 #define XF86XK_Reload              0x1008FF73
818 #define XF86XK_RotateWindows       0x1008FF74
819 #define XF86XK_RotationPB          0x1008FF75
820 #define XF86XK_RotationKB          0x1008FF76
821 #define XF86XK_Save                0x1008FF77
822 #define XF86XK_Send                0x1008FF7B
823 #define XF86XK_Spell               0x1008FF7C
824 #define XF86XK_SplitScreen         0x1008FF7D
825 #define XF86XK_Support             0x1008FF7E
826 #define XF86XK_TaskPane            0x1008FF7F
827 #define XF86XK_Terminal            0x1008FF80
828 #define XF86XK_Tools               0x1008FF81
829 #define XF86XK_Travel              0x1008FF82
830 #define XF86XK_Video               0x1008FF87
831 #define XF86XK_Word                0x1008FF89
832 #define XF86XK_Xfer                0x1008FF8A
833 #define XF86XK_ZoomIn              0x1008FF8B
834 #define XF86XK_ZoomOut             0x1008FF8C
835 #define XF86XK_Away                0x1008FF8D
836 #define XF86XK_Messenger           0x1008FF8E
837 #define XF86XK_WebCam              0x1008FF8F
838 #define XF86XK_MailForward         0x1008FF90
839 #define XF86XK_Pictures            0x1008FF91
840 #define XF86XK_Music               0x1008FF92
841 #define XF86XK_Battery             0x1008FF93
842 #define XF86XK_Bluetooth           0x1008FF94
843 #define XF86XK_WLAN                0x1008FF95
844 #define XF86XK_UWB                 0x1008FF96
845 #define XF86XK_AudioForward        0x1008FF97
846 #define XF86XK_AudioRepeat         0x1008FF98
847 #define XF86XK_AudioRandomPlay     0x1008FF99
848 #define XF86XK_Subtitle            0x1008FF9A
849 #define XF86XK_AudioCycleTrack     0x1008FF9B
850 #define XF86XK_Time                0x1008FF9F
851 #define XF86XK_Select              0x1008FFA0
852 #define XF86XK_View                0x1008FFA1
853 #define XF86XK_TopMenu             0x1008FFA2
854 #define XF86XK_Suspend             0x1008FFA7
855 #define XF86XK_Hibernate           0x1008FFA8
856 
857 
858 // end of XF86keysyms.h
859 
860 // Special keys used by Qtopia, mapped into the X11 private keypad range.
861 #define QTOPIAXK_Select         0x11000601
862 #define QTOPIAXK_Yes            0x11000602
863 #define QTOPIAXK_No             0x11000603
864 #define QTOPIAXK_Cancel         0x11000604
865 #define QTOPIAXK_Printer        0x11000605
866 #define QTOPIAXK_Execute        0x11000606
867 #define QTOPIAXK_Sleep          0x11000607
868 #define QTOPIAXK_Play           0x11000608
869 #define QTOPIAXK_Zoom           0x11000609
870 #define QTOPIAXK_Context1       0x1100060A
871 #define QTOPIAXK_Context2       0x1100060B
872 #define QTOPIAXK_Context3       0x1100060C
873 #define QTOPIAXK_Context4       0x1100060D
874 #define QTOPIAXK_Call           0x1100060E
875 #define QTOPIAXK_Hangup         0x1100060F
876 #define QTOPIAXK_Flip           0x11000610
877 
878 // keyboard mapping table
879 static const unsigned int KeyTbl[] = {
880 
881     // misc keys
882 
883     XK_Escape,                  Qt::Key_Escape,
884     XK_Tab,                     Qt::Key_Tab,
885     XK_ISO_Left_Tab,            Qt::Key_Backtab,
886     XK_BackSpace,               Qt::Key_Backspace,
887     XK_Return,                  Qt::Key_Return,
888     XK_Insert,                  Qt::Key_Insert,
889     XK_Delete,                  Qt::Key_Delete,
890     XK_Clear,                   Qt::Key_Delete,
891     XK_Pause,                   Qt::Key_Pause,
892     XK_Print,                   Qt::Key_Print,
893     0x1005FF60,                 Qt::Key_SysReq,         // hardcoded Sun SysReq
894     0x1007ff00,                 Qt::Key_SysReq,         // hardcoded X386 SysReq
895 
896     // cursor movement
897 
898     XK_Home,                    Qt::Key_Home,
899     XK_End,                     Qt::Key_End,
900     XK_Left,                    Qt::Key_Left,
901     XK_Up,                      Qt::Key_Up,
902     XK_Right,                   Qt::Key_Right,
903     XK_Down,                    Qt::Key_Down,
904     XK_Prior,                   Qt::Key_PageUp,
905     XK_Next,                    Qt::Key_PageDown,
906 
907     // modifiers
908 
909     XK_Shift_L,                 Qt::Key_Shift,
910     XK_Shift_R,                 Qt::Key_Shift,
911     XK_Shift_Lock,              Qt::Key_Shift,
912     XK_Control_L,               Qt::Key_Control,
913     XK_Control_R,               Qt::Key_Control,
914     XK_Meta_L,                  Qt::Key_Meta,
915     XK_Meta_R,                  Qt::Key_Meta,
916     XK_Alt_L,                   Qt::Key_Alt,
917     XK_Alt_R,                   Qt::Key_Alt,
918     XK_Caps_Lock,               Qt::Key_CapsLock,
919     XK_Num_Lock,                Qt::Key_NumLock,
920     XK_Scroll_Lock,             Qt::Key_ScrollLock,
921     XK_Super_L,                 Qt::Key_Super_L,
922     XK_Super_R,                 Qt::Key_Super_R,
923     XK_Menu,                    Qt::Key_Menu,
924     XK_Hyper_L,                 Qt::Key_Hyper_L,
925     XK_Hyper_R,                 Qt::Key_Hyper_R,
926     XK_Help,                    Qt::Key_Help,
927     0x1000FF74,                 Qt::Key_Backtab,        // hardcoded HP backtab
928     0x1005FF10,                 Qt::Key_F11,            // hardcoded Sun F36 (labeled F11)
929     0x1005FF11,                 Qt::Key_F12,            // hardcoded Sun F37 (labeled F12)
930 
931     // numeric and function keypad keys
932 
933     XK_KP_Space,                Qt::Key_Space,
934     XK_KP_Tab,                  Qt::Key_Tab,
935     XK_KP_Enter,                Qt::Key_Enter,
936     //XK_KP_F1,                 Qt::Key_F1,
937     //XK_KP_F2,                 Qt::Key_F2,
938     //XK_KP_F3,                 Qt::Key_F3,
939     //XK_KP_F4,                 Qt::Key_F4,
940     XK_KP_Home,                 Qt::Key_Home,
941     XK_KP_Left,                 Qt::Key_Left,
942     XK_KP_Up,                   Qt::Key_Up,
943     XK_KP_Right,                Qt::Key_Right,
944     XK_KP_Down,                 Qt::Key_Down,
945     XK_KP_Prior,                Qt::Key_PageUp,
946     XK_KP_Next,                 Qt::Key_PageDown,
947     XK_KP_End,                  Qt::Key_End,
948     XK_KP_Begin,                Qt::Key_Clear,
949     XK_KP_Insert,               Qt::Key_Insert,
950     XK_KP_Delete,               Qt::Key_Delete,
951     XK_KP_Equal,                Qt::Key_Equal,
952     XK_KP_Multiply,             Qt::Key_Asterisk,
953     XK_KP_Add,                  Qt::Key_Plus,
954     XK_KP_Separator,            Qt::Key_Comma,
955     XK_KP_Subtract,             Qt::Key_Minus,
956     XK_KP_Decimal,              Qt::Key_Period,
957     XK_KP_Divide,               Qt::Key_Slash,
958 
959     // International input method support keys
960 
961     // International & multi-key character composition
962     XK_ISO_Level3_Shift,        Qt::Key_AltGr,
963     XK_Multi_key,		Qt::Key_Multi_key,
964     XK_Codeinput,		Qt::Key_Codeinput,
965     XK_SingleCandidate,		Qt::Key_SingleCandidate,
966     XK_MultipleCandidate,	Qt::Key_MultipleCandidate,
967     XK_PreviousCandidate,	Qt::Key_PreviousCandidate,
968 
969     // Misc Functions
970     XK_Mode_switch,		Qt::Key_Mode_switch,
971     XK_script_switch,		Qt::Key_Mode_switch,
972 
973     // Japanese keyboard support
974     XK_Kanji,			Qt::Key_Kanji,
975     XK_Muhenkan,		Qt::Key_Muhenkan,
976     //XK_Henkan_Mode,		Qt::Key_Henkan_Mode,
977     XK_Henkan_Mode,		Qt::Key_Henkan,
978     XK_Henkan,			Qt::Key_Henkan,
979     XK_Romaji,			Qt::Key_Romaji,
980     XK_Hiragana,		Qt::Key_Hiragana,
981     XK_Katakana,		Qt::Key_Katakana,
982     XK_Hiragana_Katakana,	Qt::Key_Hiragana_Katakana,
983     XK_Zenkaku,			Qt::Key_Zenkaku,
984     XK_Hankaku,			Qt::Key_Hankaku,
985     XK_Zenkaku_Hankaku,		Qt::Key_Zenkaku_Hankaku,
986     XK_Touroku,			Qt::Key_Touroku,
987     XK_Massyo,			Qt::Key_Massyo,
988     XK_Kana_Lock,		Qt::Key_Kana_Lock,
989     XK_Kana_Shift,		Qt::Key_Kana_Shift,
990     XK_Eisu_Shift,		Qt::Key_Eisu_Shift,
991     XK_Eisu_toggle,		Qt::Key_Eisu_toggle,
992     //XK_Kanji_Bangou,		Qt::Key_Kanji_Bangou,
993     //XK_Zen_Koho,		Qt::Key_Zen_Koho,
994     //XK_Mae_Koho,		Qt::Key_Mae_Koho,
995     XK_Kanji_Bangou,		Qt::Key_Codeinput,
996     XK_Zen_Koho,		Qt::Key_MultipleCandidate,
997     XK_Mae_Koho,		Qt::Key_PreviousCandidate,
998 
999 #ifdef XK_KOREAN
1000     // Korean keyboard support
1001     XK_Hangul,			Qt::Key_Hangul,
1002     XK_Hangul_Start,		Qt::Key_Hangul_Start,
1003     XK_Hangul_End,		Qt::Key_Hangul_End,
1004     XK_Hangul_Hanja,		Qt::Key_Hangul_Hanja,
1005     XK_Hangul_Jamo,		Qt::Key_Hangul_Jamo,
1006     XK_Hangul_Romaja,		Qt::Key_Hangul_Romaja,
1007     //XK_Hangul_Codeinput,	Qt::Key_Hangul_Codeinput,
1008     XK_Hangul_Codeinput,	Qt::Key_Codeinput,
1009     XK_Hangul_Jeonja,		Qt::Key_Hangul_Jeonja,
1010     XK_Hangul_Banja,		Qt::Key_Hangul_Banja,
1011     XK_Hangul_PreHanja,		Qt::Key_Hangul_PreHanja,
1012     XK_Hangul_PostHanja,	Qt::Key_Hangul_PostHanja,
1013     //XK_Hangul_SingleCandidate,Qt::Key_Hangul_SingleCandidate,
1014     //XK_Hangul_MultipleCandidate,Qt::Key_Hangul_MultipleCandidate,
1015     //XK_Hangul_PreviousCandidate,Qt::Key_Hangul_PreviousCandidate,
1016     XK_Hangul_SingleCandidate,	Qt::Key_SingleCandidate,
1017     XK_Hangul_MultipleCandidate,Qt::Key_MultipleCandidate,
1018     XK_Hangul_PreviousCandidate,Qt::Key_PreviousCandidate,
1019     XK_Hangul_Special,		Qt::Key_Hangul_Special,
1020     //XK_Hangul_switch,		Qt::Key_Hangul_switch,
1021     XK_Hangul_switch,		Qt::Key_Mode_switch,
1022 #endif  // XK_KOREAN
1023 
1024     // dead keys
1025     XK_dead_grave,              Qt::Key_Dead_Grave,
1026     XK_dead_acute,              Qt::Key_Dead_Acute,
1027     XK_dead_circumflex,         Qt::Key_Dead_Circumflex,
1028     XK_dead_tilde,              Qt::Key_Dead_Tilde,
1029     XK_dead_macron,             Qt::Key_Dead_Macron,
1030     XK_dead_breve,              Qt::Key_Dead_Breve,
1031     XK_dead_abovedot,           Qt::Key_Dead_Abovedot,
1032     XK_dead_diaeresis,          Qt::Key_Dead_Diaeresis,
1033     XK_dead_abovering,          Qt::Key_Dead_Abovering,
1034     XK_dead_doubleacute,        Qt::Key_Dead_Doubleacute,
1035     XK_dead_caron,              Qt::Key_Dead_Caron,
1036     XK_dead_cedilla,            Qt::Key_Dead_Cedilla,
1037     XK_dead_ogonek,             Qt::Key_Dead_Ogonek,
1038     XK_dead_iota,               Qt::Key_Dead_Iota,
1039     XK_dead_voiced_sound,       Qt::Key_Dead_Voiced_Sound,
1040     XK_dead_semivoiced_sound,   Qt::Key_Dead_Semivoiced_Sound,
1041     XK_dead_belowdot,           Qt::Key_Dead_Belowdot,
1042     XK_dead_hook,               Qt::Key_Dead_Hook,
1043     XK_dead_horn,               Qt::Key_Dead_Horn,
1044 
1045     // Special keys from X.org - This include multimedia keys,
1046 	// wireless/bluetooth/uwb keys, special launcher keys, etc.
1047     XF86XK_Back,                Qt::Key_Back,
1048     XF86XK_Forward,             Qt::Key_Forward,
1049     XF86XK_Stop,                Qt::Key_Stop,
1050     XF86XK_Refresh,             Qt::Key_Refresh,
1051     XF86XK_Favorites,           Qt::Key_Favorites,
1052     XF86XK_AudioMedia,          Qt::Key_LaunchMedia,
1053     XF86XK_OpenURL,             Qt::Key_OpenUrl,
1054     XF86XK_HomePage,            Qt::Key_HomePage,
1055     XF86XK_Search,              Qt::Key_Search,
1056     XF86XK_AudioLowerVolume,    Qt::Key_VolumeDown,
1057     XF86XK_AudioMute,           Qt::Key_VolumeMute,
1058     XF86XK_AudioRaiseVolume,    Qt::Key_VolumeUp,
1059     XF86XK_AudioPlay,           Qt::Key_MediaPlay,
1060     XF86XK_AudioStop,           Qt::Key_MediaStop,
1061     XF86XK_AudioPrev,           Qt::Key_MediaPrevious,
1062     XF86XK_AudioNext,           Qt::Key_MediaNext,
1063     XF86XK_AudioRecord,         Qt::Key_MediaRecord,
1064     XF86XK_Mail,                Qt::Key_LaunchMail,
1065     XF86XK_MyComputer,          Qt::Key_Launch0,  // ### Qt 5: remap properly
1066     XF86XK_Calculator,          Qt::Key_Launch1,
1067     XF86XK_Memo,                Qt::Key_Memo,
1068     XF86XK_ToDoList,            Qt::Key_ToDoList,
1069     XF86XK_Calendar,            Qt::Key_Calendar,
1070     XF86XK_PowerDown,           Qt::Key_PowerDown,
1071     XF86XK_ContrastAdjust,      Qt::Key_ContrastAdjust,
1072     XF86XK_Standby,             Qt::Key_Standby,
1073     XF86XK_MonBrightnessUp,     Qt::Key_MonBrightnessUp,
1074     XF86XK_MonBrightnessDown,   Qt::Key_MonBrightnessDown,
1075     XF86XK_KbdLightOnOff,       Qt::Key_KeyboardLightOnOff,
1076     XF86XK_KbdBrightnessUp,     Qt::Key_KeyboardBrightnessUp,
1077     XF86XK_KbdBrightnessDown,   Qt::Key_KeyboardBrightnessDown,
1078     XF86XK_PowerOff,            Qt::Key_PowerOff,
1079     XF86XK_WakeUp,              Qt::Key_WakeUp,
1080     XF86XK_Eject,               Qt::Key_Eject,
1081     XF86XK_ScreenSaver,         Qt::Key_ScreenSaver,
1082     XF86XK_WWW,                 Qt::Key_WWW,
1083     XF86XK_Sleep,               Qt::Key_Sleep,
1084     XF86XK_LightBulb,           Qt::Key_LightBulb,
1085     XF86XK_Shop,                Qt::Key_Shop,
1086     XF86XK_History,             Qt::Key_History,
1087     XF86XK_AddFavorite,         Qt::Key_AddFavorite,
1088     XF86XK_HotLinks,            Qt::Key_HotLinks,
1089     XF86XK_BrightnessAdjust,    Qt::Key_BrightnessAdjust,
1090     XF86XK_Finance,             Qt::Key_Finance,
1091     XF86XK_Community,           Qt::Key_Community,
1092     XF86XK_AudioRewind,         Qt::Key_AudioRewind,
1093     XF86XK_BackForward,         Qt::Key_BackForward,
1094     XF86XK_ApplicationLeft,     Qt::Key_ApplicationLeft,
1095     XF86XK_ApplicationRight,    Qt::Key_ApplicationRight,
1096     XF86XK_Book,                Qt::Key_Book,
1097     XF86XK_CD,                  Qt::Key_CD,
1098     XF86XK_Calculater,          Qt::Key_Calculator,
1099     XF86XK_Clear,               Qt::Key_Clear,
1100     XF86XK_ClearGrab,           Qt::Key_ClearGrab,
1101     XF86XK_Close,               Qt::Key_Close,
1102     XF86XK_Copy,                Qt::Key_Copy,
1103     XF86XK_Cut,                 Qt::Key_Cut,
1104     XF86XK_Display,             Qt::Key_Display,
1105     XF86XK_DOS,                 Qt::Key_DOS,
1106     XF86XK_Documents,           Qt::Key_Documents,
1107     XF86XK_Excel,               Qt::Key_Excel,
1108     XF86XK_Explorer,            Qt::Key_Explorer,
1109     XF86XK_Game,                Qt::Key_Game,
1110     XF86XK_Go,                  Qt::Key_Go,
1111     XF86XK_iTouch,              Qt::Key_iTouch,
1112     XF86XK_LogOff,              Qt::Key_LogOff,
1113     XF86XK_Market,              Qt::Key_Market,
1114     XF86XK_Meeting,             Qt::Key_Meeting,
1115     XF86XK_MenuKB,              Qt::Key_MenuKB,
1116     XF86XK_MenuPB,              Qt::Key_MenuPB,
1117     XF86XK_MySites,             Qt::Key_MySites,
1118     XF86XK_News,                Qt::Key_News,
1119     XF86XK_OfficeHome,          Qt::Key_OfficeHome,
1120     XF86XK_Option,              Qt::Key_Option,
1121     XF86XK_Paste,               Qt::Key_Paste,
1122     XF86XK_Phone,               Qt::Key_Phone,
1123     XF86XK_Reply,               Qt::Key_Reply,
1124     XF86XK_Reload,              Qt::Key_Reload,
1125     XF86XK_RotateWindows,       Qt::Key_RotateWindows,
1126     XF86XK_RotationPB,          Qt::Key_RotationPB,
1127     XF86XK_RotationKB,          Qt::Key_RotationKB,
1128     XF86XK_Save,                Qt::Key_Save,
1129     XF86XK_Send,                Qt::Key_Send,
1130     XF86XK_Spell,               Qt::Key_Spell,
1131     XF86XK_SplitScreen,         Qt::Key_SplitScreen,
1132     XF86XK_Support,             Qt::Key_Support,
1133     XF86XK_TaskPane,            Qt::Key_TaskPane,
1134     XF86XK_Terminal,            Qt::Key_Terminal,
1135     XF86XK_Tools,               Qt::Key_Tools,
1136     XF86XK_Travel,              Qt::Key_Travel,
1137     XF86XK_Video,               Qt::Key_Video,
1138     XF86XK_Word,                Qt::Key_Word,
1139     XF86XK_Xfer,                Qt::Key_Xfer,
1140     XF86XK_ZoomIn,              Qt::Key_ZoomIn,
1141     XF86XK_ZoomOut,             Qt::Key_ZoomOut,
1142     XF86XK_Away,                Qt::Key_Away,
1143     XF86XK_Messenger,           Qt::Key_Messenger,
1144     XF86XK_WebCam,              Qt::Key_WebCam,
1145     XF86XK_MailForward,         Qt::Key_MailForward,
1146     XF86XK_Pictures,            Qt::Key_Pictures,
1147     XF86XK_Music,               Qt::Key_Music,
1148     XF86XK_Battery,             Qt::Key_Battery,
1149     XF86XK_Bluetooth,           Qt::Key_Bluetooth,
1150     XF86XK_WLAN,                Qt::Key_WLAN,
1151     XF86XK_UWB,                 Qt::Key_UWB,
1152     XF86XK_AudioForward,        Qt::Key_AudioForward,
1153     XF86XK_AudioRepeat,         Qt::Key_AudioRepeat,
1154     XF86XK_AudioRandomPlay,     Qt::Key_AudioRandomPlay,
1155     XF86XK_Subtitle,            Qt::Key_Subtitle,
1156     XF86XK_AudioCycleTrack,     Qt::Key_AudioCycleTrack,
1157     XF86XK_Time,                Qt::Key_Time,
1158     XF86XK_Select,              Qt::Key_Select,
1159     XF86XK_View,                Qt::Key_View,
1160     XF86XK_TopMenu,             Qt::Key_TopMenu,
1161     XF86XK_Bluetooth,           Qt::Key_Bluetooth,
1162     XF86XK_Suspend,             Qt::Key_Suspend,
1163     XF86XK_Hibernate,           Qt::Key_Hibernate,
1164     XF86XK_Launch0,             Qt::Key_Launch2, // ### Qt 5: remap properly
1165     XF86XK_Launch1,             Qt::Key_Launch3,
1166     XF86XK_Launch2,             Qt::Key_Launch4,
1167     XF86XK_Launch3,             Qt::Key_Launch5,
1168     XF86XK_Launch4,             Qt::Key_Launch6,
1169     XF86XK_Launch5,             Qt::Key_Launch7,
1170     XF86XK_Launch6,             Qt::Key_Launch8,
1171     XF86XK_Launch7,             Qt::Key_Launch9,
1172     XF86XK_Launch8,             Qt::Key_LaunchA,
1173     XF86XK_Launch9,             Qt::Key_LaunchB,
1174     XF86XK_LaunchA,             Qt::Key_LaunchC,
1175     XF86XK_LaunchB,             Qt::Key_LaunchD,
1176     XF86XK_LaunchC,             Qt::Key_LaunchE,
1177     XF86XK_LaunchD,             Qt::Key_LaunchF,
1178     XF86XK_LaunchE,             Qt::Key_LaunchG,
1179     XF86XK_LaunchF,             Qt::Key_LaunchH,
1180 
1181     // Qtopia keys
1182     QTOPIAXK_Select,            Qt::Key_Select,
1183     QTOPIAXK_Yes,               Qt::Key_Yes,
1184     QTOPIAXK_No,                Qt::Key_No,
1185     QTOPIAXK_Cancel,            Qt::Key_Cancel,
1186     QTOPIAXK_Printer,           Qt::Key_Printer,
1187     QTOPIAXK_Execute,           Qt::Key_Execute,
1188     QTOPIAXK_Sleep,             Qt::Key_Sleep,
1189     QTOPIAXK_Play,              Qt::Key_Play,
1190     QTOPIAXK_Zoom,              Qt::Key_Zoom,
1191     QTOPIAXK_Context1,          Qt::Key_Context1,
1192     QTOPIAXK_Context2,          Qt::Key_Context2,
1193     QTOPIAXK_Context3,          Qt::Key_Context3,
1194     QTOPIAXK_Context4,          Qt::Key_Context4,
1195     QTOPIAXK_Call,              Qt::Key_Call,
1196     QTOPIAXK_Hangup,            Qt::Key_Hangup,
1197     QTOPIAXK_Flip,              Qt::Key_Flip,
1198 
1199     0,                          0
1200 };
1201 
translateKeySym(uint key)1202 static int translateKeySym(uint key)
1203 {
1204     int code = -1;
1205     int i = 0;                                // any other keys
1206     while (KeyTbl[i]) {
1207         if (key == KeyTbl[i]) {
1208             code = (int)KeyTbl[i+1];
1209             break;
1210         }
1211         i += 2;
1212     }
1213     if (qt_meta_mask) {
1214         // translate Super/Hyper keys to Meta if we're using them as the MetaModifier
1215         if (qt_meta_mask == qt_super_mask && (code == Qt::Key_Super_L || code == Qt::Key_Super_R)) {
1216             code = Qt::Key_Meta;
1217         } else if (qt_meta_mask == qt_hyper_mask && (code == Qt::Key_Hyper_L || code == Qt::Key_Hyper_R)) {
1218             code = Qt::Key_Meta;
1219         }
1220     }
1221     return code;
1222 }
1223 
1224 #if !defined(QT_NO_XIM)
1225 static const unsigned short katakanaKeysymsToUnicode[] = {
1226     0x0000, 0x3002, 0x300C, 0x300D, 0x3001, 0x30FB, 0x30F2, 0x30A1,
1227     0x30A3, 0x30A5, 0x30A7, 0x30A9, 0x30E3, 0x30E5, 0x30E7, 0x30C3,
1228     0x30FC, 0x30A2, 0x30A4, 0x30A6, 0x30A8, 0x30AA, 0x30AB, 0x30AD,
1229     0x30AF, 0x30B1, 0x30B3, 0x30B5, 0x30B7, 0x30B9, 0x30BB, 0x30BD,
1230     0x30BF, 0x30C1, 0x30C4, 0x30C6, 0x30C8, 0x30CA, 0x30CB, 0x30CC,
1231     0x30CD, 0x30CE, 0x30CF, 0x30D2, 0x30D5, 0x30D8, 0x30DB, 0x30DE,
1232     0x30DF, 0x30E0, 0x30E1, 0x30E2, 0x30E4, 0x30E6, 0x30E8, 0x30E9,
1233     0x30EA, 0x30EB, 0x30EC, 0x30ED, 0x30EF, 0x30F3, 0x309B, 0x309C
1234 };
1235 
1236 static const unsigned short cyrillicKeysymsToUnicode[] = {
1237     0x0000, 0x0452, 0x0453, 0x0451, 0x0454, 0x0455, 0x0456, 0x0457,
1238     0x0458, 0x0459, 0x045a, 0x045b, 0x045c, 0x0000, 0x045e, 0x045f,
1239     0x2116, 0x0402, 0x0403, 0x0401, 0x0404, 0x0405, 0x0406, 0x0407,
1240     0x0408, 0x0409, 0x040a, 0x040b, 0x040c, 0x0000, 0x040e, 0x040f,
1241     0x044e, 0x0430, 0x0431, 0x0446, 0x0434, 0x0435, 0x0444, 0x0433,
1242     0x0445, 0x0438, 0x0439, 0x043a, 0x043b, 0x043c, 0x043d, 0x043e,
1243     0x043f, 0x044f, 0x0440, 0x0441, 0x0442, 0x0443, 0x0436, 0x0432,
1244     0x044c, 0x044b, 0x0437, 0x0448, 0x044d, 0x0449, 0x0447, 0x044a,
1245     0x042e, 0x0410, 0x0411, 0x0426, 0x0414, 0x0415, 0x0424, 0x0413,
1246     0x0425, 0x0418, 0x0419, 0x041a, 0x041b, 0x041c, 0x041d, 0x041e,
1247     0x041f, 0x042f, 0x0420, 0x0421, 0x0422, 0x0423, 0x0416, 0x0412,
1248     0x042c, 0x042b, 0x0417, 0x0428, 0x042d, 0x0429, 0x0427, 0x042a
1249 };
1250 
1251 static const unsigned short greekKeysymsToUnicode[] = {
1252     0x0000, 0x0386, 0x0388, 0x0389, 0x038a, 0x03aa, 0x0000, 0x038c,
1253     0x038e, 0x03ab, 0x0000, 0x038f, 0x0000, 0x0000, 0x0385, 0x2015,
1254     0x0000, 0x03ac, 0x03ad, 0x03ae, 0x03af, 0x03ca, 0x0390, 0x03cc,
1255     0x03cd, 0x03cb, 0x03b0, 0x03ce, 0x0000, 0x0000, 0x0000, 0x0000,
1256     0x0000, 0x0391, 0x0392, 0x0393, 0x0394, 0x0395, 0x0396, 0x0397,
1257     0x0398, 0x0399, 0x039a, 0x039b, 0x039c, 0x039d, 0x039e, 0x039f,
1258     0x03a0, 0x03a1, 0x03a3, 0x0000, 0x03a4, 0x03a5, 0x03a6, 0x03a7,
1259     0x03a8, 0x03a9, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
1260     0x0000, 0x03b1, 0x03b2, 0x03b3, 0x03b4, 0x03b5, 0x03b6, 0x03b7,
1261     0x03b8, 0x03b9, 0x03ba, 0x03bb, 0x03bc, 0x03bd, 0x03be, 0x03bf,
1262     0x03c0, 0x03c1, 0x03c3, 0x03c2, 0x03c4, 0x03c5, 0x03c6, 0x03c7,
1263     0x03c8, 0x03c9, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000
1264 };
1265 
1266 static const unsigned short technicalKeysymsToUnicode[] = {
1267     0x0000, 0x23B7, 0x250C, 0x2500, 0x2320, 0x2321, 0x2502, 0x23A1,
1268     0x23A3, 0x23A4, 0x23A6, 0x239B, 0x239D, 0x239E, 0x23A0, 0x23A8,
1269     0x23AC, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
1270     0x0000, 0x0000, 0x0000, 0x0000, 0x2264, 0x2260, 0x2265, 0x222B,
1271     0x2234, 0x221D, 0x221E, 0x0000, 0x0000, 0x2207, 0x0000, 0x0000,
1272     0x223C, 0x2243, 0x0000, 0x0000, 0x0000, 0x21D4, 0x21D2, 0x2261,
1273     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x221A, 0x0000,
1274     0x0000, 0x0000, 0x2282, 0x2283, 0x2229, 0x222A, 0x2227, 0x2228,
1275     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
1276     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x2202,
1277     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0192, 0x0000,
1278     0x0000, 0x0000, 0x0000, 0x2190, 0x2191, 0x2192, 0x2193, 0x0000
1279 };
1280 
1281 static const unsigned short specialKeysymsToUnicode[] = {
1282     0x25C6, 0x2592, 0x2409, 0x240C, 0x240D, 0x240A, 0x0000, 0x0000,
1283     0x2424, 0x240B, 0x2518, 0x2510, 0x250C, 0x2514, 0x253C, 0x23BA,
1284     0x23BB, 0x2500, 0x23BC, 0x23BD, 0x251C, 0x2524, 0x2534, 0x252C,
1285     0x2502, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000
1286 };
1287 
1288 static const unsigned short publishingKeysymsToUnicode[] = {
1289     0x0000, 0x2003, 0x2002, 0x2004, 0x2005, 0x2007, 0x2008, 0x2009,
1290     0x200a, 0x2014, 0x2013, 0x0000, 0x0000, 0x0000, 0x2026, 0x2025,
1291     0x2153, 0x2154, 0x2155, 0x2156, 0x2157, 0x2158, 0x2159, 0x215a,
1292     0x2105, 0x0000, 0x0000, 0x2012, 0x2329, 0x0000, 0x232a, 0x0000,
1293     0x0000, 0x0000, 0x0000, 0x215b, 0x215c, 0x215d, 0x215e, 0x0000,
1294     0x0000, 0x2122, 0x2613, 0x0000, 0x25c1, 0x25b7, 0x25cb, 0x25af,
1295     0x2018, 0x2019, 0x201c, 0x201d, 0x211e, 0x0000, 0x2032, 0x2033,
1296     0x0000, 0x271d, 0x0000, 0x25ac, 0x25c0, 0x25b6, 0x25cf, 0x25ae,
1297     0x25e6, 0x25ab, 0x25ad, 0x25b3, 0x25bd, 0x2606, 0x2022, 0x25aa,
1298     0x25b2, 0x25bc, 0x261c, 0x261e, 0x2663, 0x2666, 0x2665, 0x0000,
1299     0x2720, 0x2020, 0x2021, 0x2713, 0x2717, 0x266f, 0x266d, 0x2642,
1300     0x2640, 0x260e, 0x2315, 0x2117, 0x2038, 0x201a, 0x201e, 0x0000
1301 };
1302 
1303 static const unsigned short aplKeysymsToUnicode[] = {
1304     0x0000, 0x0000, 0x0000, 0x003c, 0x0000, 0x0000, 0x003e, 0x0000,
1305     0x2228, 0x2227, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
1306     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
1307     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
1308     0x00af, 0x0000, 0x22a5, 0x2229, 0x230a, 0x0000, 0x005f, 0x0000,
1309     0x0000, 0x0000, 0x2218, 0x0000, 0x2395, 0x0000, 0x22a4, 0x25cb,
1310     0x0000, 0x0000, 0x0000, 0x2308, 0x0000, 0x0000, 0x222a, 0x0000,
1311     0x2283, 0x0000, 0x2282, 0x0000, 0x22a2, 0x0000, 0x0000, 0x0000,
1312     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
1313     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
1314     0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
1315     0x0000, 0x0000, 0x0000, 0x0000, 0x22a3, 0x0000, 0x0000, 0x0000
1316 };
1317 
1318 static const unsigned short koreanKeysymsToUnicode[] = {
1319     0x0000, 0x3131, 0x3132, 0x3133, 0x3134, 0x3135, 0x3136, 0x3137,
1320     0x3138, 0x3139, 0x313a, 0x313b, 0x313c, 0x313d, 0x313e, 0x313f,
1321     0x3140, 0x3141, 0x3142, 0x3143, 0x3144, 0x3145, 0x3146, 0x3147,
1322     0x3148, 0x3149, 0x314a, 0x314b, 0x314c, 0x314d, 0x314e, 0x314f,
1323     0x3150, 0x3151, 0x3152, 0x3153, 0x3154, 0x3155, 0x3156, 0x3157,
1324     0x3158, 0x3159, 0x315a, 0x315b, 0x315c, 0x315d, 0x315e, 0x315f,
1325     0x3160, 0x3161, 0x3162, 0x3163, 0x11a8, 0x11a9, 0x11aa, 0x11ab,
1326     0x11ac, 0x11ad, 0x11ae, 0x11af, 0x11b0, 0x11b1, 0x11b2, 0x11b3,
1327     0x11b4, 0x11b5, 0x11b6, 0x11b7, 0x11b8, 0x11b9, 0x11ba, 0x11bb,
1328     0x11bc, 0x11bd, 0x11be, 0x11bf, 0x11c0, 0x11c1, 0x11c2, 0x316d,
1329     0x3171, 0x3178, 0x317f, 0x3181, 0x3184, 0x3186, 0x318d, 0x318e,
1330     0x11eb, 0x11f0, 0x11f9, 0x0000, 0x0000, 0x0000, 0x0000, 0x20a9
1331 };
1332 
keysymToUnicode(unsigned char byte3,unsigned char byte4)1333 static QChar keysymToUnicode(unsigned char byte3, unsigned char byte4)
1334 {
1335     switch (byte3) {
1336     case 0x04:
1337         // katakana
1338         if (byte4 > 0xa0 && byte4 < 0xe0)
1339             return QChar(katakanaKeysymsToUnicode[byte4 - 0xa0]);
1340         else if (byte4 == 0x7e)
1341             return QChar(0x203e); // Overline
1342         break;
1343     case 0x06:
1344         // russian, use lookup table
1345         if (byte4 > 0xa0)
1346             return QChar(cyrillicKeysymsToUnicode[byte4 - 0xa0]);
1347         break;
1348     case 0x07:
1349         // greek
1350         if (byte4 > 0xa0)
1351             return QChar(greekKeysymsToUnicode[byte4 - 0xa0]);
1352         break;
1353     case 0x08:
1354         // technical
1355         if (byte4 > 0xa0)
1356             return QChar(technicalKeysymsToUnicode[byte4 - 0xa0]);
1357         break;
1358     case 0x09:
1359         // special
1360         if (byte4 >= 0xe0)
1361             return QChar(specialKeysymsToUnicode[byte4 - 0xe0]);
1362         break;
1363     case 0x0a:
1364         // publishing
1365         if (byte4 > 0xa0)
1366             return QChar(publishingKeysymsToUnicode[byte4 - 0xa0]);
1367         break;
1368     case 0x0b:
1369         // APL
1370         if (byte4 > 0xa0)
1371             return QChar(aplKeysymsToUnicode[byte4 - 0xa0]);
1372         break;
1373     case 0x0e:
1374         // Korean
1375         if (byte4 > 0xa0)
1376             return QChar(koreanKeysymsToUnicode[byte4 - 0xa0]);
1377         break;
1378     default:
1379         break;
1380     }
1381     return QChar(0x0);
1382 }
1383 #endif
1384 
translateKeySym(KeySym keysym,uint xmodifiers,int & code,Qt::KeyboardModifiers & modifiers,QByteArray & chars,int & count)1385 static QString translateKeySym(KeySym keysym, uint xmodifiers,
1386                                int &code, Qt::KeyboardModifiers &modifiers,
1387                                QByteArray &chars, int &count)
1388 {
1389     // all keysyms smaller than 0xff00 are actally keys that can be mapped to unicode chars
1390 
1391     extern QTextCodec *qt_input_mapper; // from qapplication_x11.cpp
1392     QTextCodec *mapper = qt_input_mapper;
1393     QChar converted;
1394 
1395     if (count == 0 && keysym < 0xff00) {
1396         unsigned char byte3 = (unsigned char)(keysym >> 8);
1397         int mib = -1;
1398         switch(byte3) {
1399         case 0: // Latin 1
1400         case 1: // Latin 2
1401         case 2: //latin 3
1402         case 3: // latin4
1403             mib = byte3 + 4; break;
1404         case 5: // arabic
1405             mib = 82; break;
1406         case 12: // Hebrew
1407             mib = 85; break;
1408         case 13: // Thai
1409             mib = 2259; break;
1410         case 4: // kana
1411         case 6: // cyrillic
1412         case 7: // greek
1413         case 8: // technical, no mapping here at the moment
1414         case 9: // Special
1415         case 10: // Publishing
1416         case 11: // APL
1417         case 14: // Korean, no mapping
1418             mib = -1; // manual conversion
1419             mapper = 0;
1420 #if !defined(QT_NO_XIM)
1421             converted = keysymToUnicode(byte3, keysym & 0xff);
1422 #endif
1423         case 0x20:
1424             // currency symbols
1425             if (keysym >= 0x20a0 && keysym <= 0x20ac) {
1426                 mib = -1; // manual conversion
1427                 mapper = 0;
1428                 converted = (uint)keysym;
1429             }
1430             break;
1431         default:
1432             break;
1433         }
1434         if (mib != -1) {
1435             mapper = QTextCodec::codecForMib(mib);
1436             if (chars.isEmpty())
1437                 chars.resize(1);
1438             chars[0] = (unsigned char) (keysym & 0xff); // get only the fourth bit for conversion later
1439             count++;
1440         }
1441     } else if (keysym >= 0x1000000 && keysym <= 0x100ffff) {
1442         converted = (ushort) (keysym - 0x1000000);
1443         mapper = 0;
1444     }
1445     if (count < (int)chars.size()-1)
1446         chars[count] = '\0';
1447 
1448     QString text;
1449     if (!mapper && converted.unicode() != 0x0) {
1450         text = converted;
1451     } else if (!chars.isEmpty()) {
1452         // convert chars (8bit) to text (unicode).
1453         if (mapper)
1454             text = mapper->toUnicode(chars.data(), count, 0);
1455         if (text.isEmpty()) {
1456             // no mapper, or codec couldn't convert to unicode (this
1457             // can happen when running in the C locale or with no LANG
1458             // set). try converting from latin-1
1459             text = QString::fromLatin1(chars);
1460         }
1461     }
1462 
1463     modifiers = X11->translateModifiers(xmodifiers);
1464 
1465     // Commentary in X11/keysymdef says that X codes match ASCII, so it
1466     // is safe to use the locale functions to process X codes in ISO8859-1.
1467     //
1468     // This is mainly for compatibility - applications should not use the
1469     // Qt keycodes between 128 and 255, but should rather use the
1470     // QKeyEvent::text().
1471     //
1472     extern QTextCodec *qt_input_mapper; // from qapplication_x11.cpp
1473     if (keysym < 128 || (keysym < 256 && (!qt_input_mapper || qt_input_mapper->mibEnum()==4))) {
1474         // upper-case key, if known
1475         code = isprint((int)keysym) ? toupper((int)keysym) : 0;
1476     } else if (keysym >= XK_F1 && keysym <= XK_F35) {
1477         // function keys
1478         code = Qt::Key_F1 + ((int)keysym - XK_F1);
1479     } else if (keysym >= XK_KP_Space && keysym <= XK_KP_9) {
1480         if (keysym >= XK_KP_0) {
1481             // numeric keypad keys
1482             code = Qt::Key_0 + ((int)keysym - XK_KP_0);
1483         } else {
1484             code = translateKeySym(keysym);
1485         }
1486         modifiers |= Qt::KeypadModifier;
1487     } else if (text.length() == 1 && text.unicode()->unicode() > 0x1f && text.unicode()->unicode() != 0x7f && !(keysym >= XK_dead_grave && keysym <= XK_dead_horn)) {
1488         code = text.unicode()->toUpper().unicode();
1489     } else {
1490         // any other keys
1491         code = translateKeySym(keysym);
1492 
1493         if (code == Qt::Key_Tab && (modifiers & Qt::ShiftModifier)) {
1494             // map shift+tab to shift+backtab, QShortcutMap knows about it
1495             // and will handle it.
1496             code = Qt::Key_Backtab;
1497             text = QString();
1498         }
1499     }
1500 
1501     return text;
1502 }
1503 
1504 extern bool qt_use_rtl_extensions; // from qapplication_x11.cpp
1505 
translateKeyEventInternal(QWidget * keyWidget,const XEvent * event,KeySym & keysym,int & count,QString & text,Qt::KeyboardModifiers & modifiers,int & code,QEvent::Type & type,bool statefulTranslation)1506 bool QKeyMapperPrivate::translateKeyEventInternal(QWidget *keyWidget,
1507                                                   const XEvent *event,
1508                                                   KeySym &keysym,
1509                                                   int& count,
1510                                                   QString& text,
1511                                                   Qt::KeyboardModifiers &modifiers,
1512                                                   int& code,
1513                                                   QEvent::Type &type,
1514                                                   bool statefulTranslation)
1515 {
1516     XKeyEvent xkeyevent = event->xkey;
1517     int keycode = event->xkey.keycode;
1518     // save the modifier state, we will use the keystate uint later by passing
1519     // it to translateButtonState
1520     uint keystate = event->xkey.state;
1521 
1522     type = (event->type == XKeyPress) ? QEvent::KeyPress : QEvent::KeyRelease;
1523 
1524     static int directionKeyEvent = 0;
1525     static unsigned int lastWinId = 0;
1526 
1527     // translate pending direction change
1528     if (statefulTranslation && qt_use_rtl_extensions && type == QEvent::KeyRelease) {
1529         if (directionKeyEvent == Qt::Key_Direction_R || directionKeyEvent == Qt::Key_Direction_L) {
1530             type = QEvent::KeyPress;
1531             code = directionKeyEvent;
1532             text = QString();
1533             directionKeyEvent = 0;
1534 	    lastWinId = 0;
1535             return true;
1536         } else {
1537             directionKeyEvent = 0;
1538 	    lastWinId = 0;
1539         }
1540     }
1541 
1542     // some XmbLookupString implementations don't return buffer overflow correctly,
1543     // so we increase the input buffer to allow for long strings...
1544     // 256 chars * 2 bytes + 1 null-term == 513 bytes
1545     QByteArray chars;
1546     chars.resize(513);
1547 
1548     count = XLookupString(&xkeyevent, chars.data(), chars.size(), &keysym, 0);
1549     if (count && !keycode) {
1550         extern int qt_ximComposingKeycode; // from qapplication_x11.cpp
1551         keycode = qt_ximComposingKeycode;
1552         qt_ximComposingKeycode = 0;
1553     }
1554 
1555     // translate the keysym + xmodifiers to Qt::Key_* + Qt::KeyboardModifiers
1556     text = translateKeySym(keysym, keystate, code, modifiers, chars, count);
1557 
1558     // Watch for keypresses and if its a key belonging to the Ctrl-Shift
1559     // direction-changing accel, remember it.
1560     // We keep track of those keys instead of using the event's state
1561     // (to figure out whether the Ctrl modifier is held while Shift is pressed,
1562     // or Shift is held while Ctrl is pressed) since the 'state' doesn't tell
1563     // us whether the modifier held is Left or Right.
1564     if (statefulTranslation && qt_use_rtl_extensions && type == QEvent::KeyPress) {
1565         if (keysym == XK_Control_L || keysym == XK_Control_R
1566             || keysym == XK_Shift_L || keysym == XK_Shift_R) {
1567 	    if (!directionKeyEvent) {
1568 		directionKeyEvent = keysym;
1569 		// This code exists in order to check that
1570 		// the event is occurred in the same widget.
1571 		lastWinId = keyWidget->internalWinId();
1572 	    }
1573         } else {
1574             // this can no longer be a direction-changing accel.
1575             // if any other key was pressed.
1576             directionKeyEvent = Qt::Key_Space;
1577         }
1578 
1579         if (directionKeyEvent && lastWinId == keyWidget->internalWinId()) {
1580             if ((keysym == XK_Shift_L && directionKeyEvent == XK_Control_L)
1581                 || (keysym == XK_Control_L && directionKeyEvent == XK_Shift_L)) {
1582                 directionKeyEvent = Qt::Key_Direction_L;
1583             } else if ((keysym == XK_Shift_R && directionKeyEvent == XK_Control_R)
1584                        || (keysym == XK_Control_R && directionKeyEvent == XK_Shift_R)) {
1585                 directionKeyEvent = Qt::Key_Direction_R;
1586             }
1587         } else if (directionKeyEvent == Qt::Key_Direction_L
1588                    || directionKeyEvent == Qt::Key_Direction_R) {
1589             directionKeyEvent = Qt::Key_Space; // invalid
1590         }
1591     }
1592 
1593     return true;
1594 }
1595 
1596 
1597 struct qt_auto_repeat_data
1598 {
1599     // match the window and keycode with timestamp delta of 10 ms
1600     Window window;
1601     KeyCode keycode;
1602     Time timestamp;
1603 
1604     // queue scanner state
1605     bool release;
1606     bool error;
1607 };
1608 
1609 #if defined(Q_C_CALLBACKS)
1610 extern "C" {
1611 #endif
1612 
qt_keypress_scanner(Display *,XEvent * event,XPointer arg)1613 static Bool qt_keypress_scanner(Display *, XEvent *event, XPointer arg)
1614 {
1615     if (event->type != XKeyPress && event->type != XKeyRelease)
1616         return false;
1617 
1618     qt_auto_repeat_data *data = (qt_auto_repeat_data *) arg;
1619     if (data->error)
1620         return false;
1621 
1622     if (event->xkey.window  != data->window ||
1623         event->xkey.keycode != data->keycode) {
1624         // deal breakers: key events in a different window or an event
1625         // with a different key code
1626         data->error = true;
1627         return false;
1628     }
1629 
1630     if (event->type == XKeyPress) {
1631         data->error = (! data->release || event->xkey.time - data->timestamp > 10);
1632         return (! data->error);
1633     }
1634 
1635     // must be XKeyRelease event
1636     if (data->release) {
1637         // found a second release
1638         data->error = true;
1639         return false;
1640     }
1641 
1642     // found a single release
1643     data->release = true;
1644     data->timestamp = event->xkey.time;
1645 
1646     return false;
1647 }
1648 
qt_keyrelease_scanner(Display *,XEvent * event,XPointer arg)1649 static Bool qt_keyrelease_scanner(Display *, XEvent *event, XPointer arg)
1650 {
1651     const qt_auto_repeat_data *data = (const qt_auto_repeat_data *) arg;
1652     return (event->type == XKeyRelease &&
1653             event->xkey.window  == data->window &&
1654             event->xkey.keycode == data->keycode);
1655 }
1656 
1657 #if defined(Q_C_CALLBACKS)
1658 }
1659 #endif
1660 
translateKeyEvent(QWidget * keyWidget,const XEvent * event,bool grab)1661 bool QKeyMapperPrivate::translateKeyEvent(QWidget *keyWidget, const XEvent *event, bool grab)
1662 {
1663     int           code = -1;
1664     int           count = 0;
1665     Qt::KeyboardModifiers modifiers;
1666 
1667     if (qt_sm_blockUserInput) // block user interaction during session management
1668         return true;
1669 
1670     Display *dpy = X11->display;
1671 
1672     if (!keyWidget->isEnabled())
1673         return true;
1674 
1675     QEvent::Type type;
1676     bool    autor = false;
1677     QString text;
1678 
1679     KeySym keysym = 0;
1680     translateKeyEventInternal(keyWidget, event, keysym, count, text, modifiers, code, type);
1681 
1682     // was this the last auto-repeater?
1683     qt_auto_repeat_data auto_repeat_data;
1684     auto_repeat_data.window = event->xkey.window;
1685     auto_repeat_data.keycode = event->xkey.keycode;
1686     auto_repeat_data.timestamp = event->xkey.time;
1687 
1688     static uint curr_autorep = 0;
1689     if (event->type == XKeyPress) {
1690         if (curr_autorep == event->xkey.keycode) {
1691             autor = true;
1692             curr_autorep = 0;
1693         }
1694     } else {
1695         // look ahead for auto-repeat
1696         XEvent nextpress;
1697 
1698         auto_repeat_data.release = true;
1699         auto_repeat_data.error = false;
1700         if (XCheckIfEvent(dpy, &nextpress, &qt_keypress_scanner,
1701                           (XPointer) &auto_repeat_data)) {
1702             autor = true;
1703 
1704             // Put it back... we COULD send the event now and not need
1705             // the static curr_autorep variable.
1706             XPutBackEvent(dpy,&nextpress);
1707         }
1708         curr_autorep = autor ? event->xkey.keycode : 0;
1709     }
1710 
1711 #if defined QT3_SUPPORT && !defined(QT_NO_SHORTCUT)
1712     // process accelerators before doing key compression
1713     if (type == QEvent::KeyPress && !grab
1714         && QApplicationPrivate::instance()->use_compat()) {
1715         // send accel events if the keyboard is not grabbed
1716         QKeyEventEx a(type, code, modifiers, text, autor, qMax(qMax(count,1), int(text.length())),
1717                       event->xkey.keycode, keysym, event->xkey.state);
1718         if (QApplicationPrivate::instance()->qt_tryAccelEvent(keyWidget, &a))
1719             return true;
1720     }
1721 #endif
1722 
1723 #ifndef QT_NO_IM
1724     QInputContext *qic = keyWidget->inputContext();
1725 #endif
1726 
1727     // compress keys
1728     if (!text.isEmpty() && keyWidget->testAttribute(Qt::WA_KeyCompression) &&
1729 #ifndef QT_NO_IM
1730         // Ordinary input methods require discrete key events to work
1731         // properly, so key compression has to be disabled when input
1732         // context exists.
1733         //
1734         // And further consideration, some complex input method
1735         // require all key press/release events discretely even if
1736         // the input method awares of key compression and compressed
1737         // keys are ordinary alphabets. For example, the uim project
1738         // is planning to implement "combinational shift" feature for
1739         // a Japanese input method, uim-skk. It will work as follows.
1740         //
1741         // 1. press "r"
1742         // 2. press "u"
1743         // 3. release both "r" and "u" in arbitrary order
1744         // 4. above key sequence generates "Ru"
1745         //
1746         // Of course further consideration about other participants
1747         // such as key repeat mechanism is required to implement such
1748         // feature.
1749         !qic &&
1750 #endif // QT_NO_IM
1751         // do not compress keys if the key event we just got above matches
1752         // one of the key ranges used to compute stopCompression
1753         !((code >= Qt::Key_Escape && code <= Qt::Key_SysReq)
1754           || (code >= Qt::Key_Home && code <= Qt::Key_PageDown)
1755           || (code >= Qt::Key_Super_L && code <= Qt::Key_Direction_R)
1756           || (code == 0)
1757           || (text.length() == 1 && text.unicode()->unicode() == '\n'))) {
1758         // the widget wants key compression so it gets it
1759 
1760         // sync the event queue, this makes key compress work better
1761         XSync(dpy, false);
1762 
1763         for (;;) {
1764             XEvent        evRelease;
1765             XEvent        evPress;
1766             if (!XCheckTypedWindowEvent(dpy,event->xkey.window,
1767                                         XKeyRelease,&evRelease))
1768                 break;
1769             if (!XCheckTypedWindowEvent(dpy,event->xkey.window,
1770                                         XKeyPress,&evPress)) {
1771                 XPutBackEvent(dpy, &evRelease);
1772                 break;
1773             }
1774             QString textIntern;
1775             int codeIntern = -1;
1776             int countIntern = 0;
1777             Qt::KeyboardModifiers modifiersIntern;
1778             QEvent::Type t;
1779             KeySym keySymIntern;
1780             translateKeyEventInternal(keyWidget, &evPress, keySymIntern, countIntern, textIntern,
1781                                       modifiersIntern, codeIntern, t);
1782             // use stopCompression to stop key compression for the following
1783             // key event ranges:
1784             bool stopCompression =
1785                 // 1) misc keys
1786                 (codeIntern >= Qt::Key_Escape && codeIntern <= Qt::Key_SysReq)
1787                 // 2) cursor movement
1788                 || (codeIntern >= Qt::Key_Home && codeIntern <= Qt::Key_PageDown)
1789                 // 3) extra keys
1790                 || (codeIntern >= Qt::Key_Super_L && codeIntern <= Qt::Key_Direction_R)
1791                 // 4) something that a) doesn't translate to text or b) translates
1792                 //    to newline text
1793                 || (codeIntern == 0)
1794                 || (textIntern.length() == 1 && textIntern.unicode()->unicode() == '\n')
1795                 || (codeIntern == Qt::Key_unknown);
1796 
1797             if (modifiersIntern == modifiers && !textIntern.isEmpty() && !stopCompression) {
1798                 text += textIntern;
1799                 count += countIntern;
1800             } else {
1801                 XPutBackEvent(dpy, &evPress);
1802                 XPutBackEvent(dpy, &evRelease);
1803                 break;
1804             }
1805         }
1806     }
1807 
1808     // autorepeat compression makes sense for all widgets (Windows
1809     // does it automatically ....)
1810     if (event->type == XKeyPress && text.length() <= 1
1811 #ifndef QT_NO_IM
1812         // input methods need discrete key events
1813         && !qic
1814 #endif// QT_NO_IM
1815 	) {
1816         XEvent dummy;
1817 
1818         for (;;) {
1819             auto_repeat_data.release = false;
1820             auto_repeat_data.error = false;
1821             if (! XCheckIfEvent(dpy, &dummy, &qt_keypress_scanner,
1822                                 (XPointer) &auto_repeat_data))
1823                 break;
1824             if (! XCheckIfEvent(dpy, &dummy, &qt_keyrelease_scanner,
1825                                 (XPointer) &auto_repeat_data))
1826                 break;
1827 
1828             count++;
1829             if (!text.isEmpty())
1830                 text += text[0];
1831         }
1832     }
1833 
1834     return QKeyMapper::sendKeyEvent(keyWidget, grab, type, code, modifiers, text, autor,
1835                                     qMax(qMax(count,1), int(text.length())),
1836                                     event->xkey.keycode, keysym, event->xkey.state);
1837 }
1838 
sendKeyEvent(QWidget * keyWidget,bool grab,QEvent::Type type,int code,Qt::KeyboardModifiers modifiers,const QString & text,bool autorepeat,int count,quint32 nativeScanCode,quint32 nativeVirtualKey,quint32 nativeModifiers,bool *)1839 bool QKeyMapper::sendKeyEvent(QWidget *keyWidget, bool grab,
1840                               QEvent::Type type, int code, Qt::KeyboardModifiers modifiers,
1841                               const QString &text, bool autorepeat, int count,
1842                               quint32 nativeScanCode, quint32 nativeVirtualKey, quint32 nativeModifiers,
1843                               bool *)
1844 {
1845     // try the menukey first
1846     if (type == QEvent::KeyPress && code == Qt::Key_Menu) {
1847         QVariant v = keyWidget->inputMethodQuery(Qt::ImMicroFocus);
1848         QPoint globalPos;
1849         QPoint pos;
1850         if (v.isNull()) {
1851             globalPos = QCursor::pos();
1852             pos = keyWidget->mapFromGlobal(globalPos);
1853         } else {
1854             pos = v.toRect().center();
1855             globalPos = keyWidget->mapToGlobal(pos);
1856         }
1857         QContextMenuEvent e(QContextMenuEvent::Keyboard, pos, globalPos);
1858         qt_sendSpontaneousEvent(keyWidget, &e);
1859         if(e.isAccepted())
1860             return true;
1861     }
1862 
1863     Q_UNUSED(grab);
1864     QKeyEventEx e(type, code, modifiers, text, autorepeat, qMax(qMax(count,1), int(text.length())),
1865                   nativeScanCode, nativeVirtualKey, nativeModifiers);
1866     return qt_sendSpontaneousEvent(keyWidget, &e);
1867 }
1868 
1869 QT_END_NAMESPACE
1870