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

Last change on this file since 744 was 651, checked in by Dmitry A. Kuminov, 16 years ago

trunk: Merged in qt 4.6.2 sources.

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