source: trunk/src/gui/kernel/qkeymapper_x11.cpp@ 769

Last change on this file since 769 was 769, checked in by Dmitry A. Kuminov, 15 years ago

trunk: Merged in qt 4.6.3 sources from branches/vendor/nokia/qt.

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