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