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

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

Initially imported qt-all-opensource-src-4.5.1 from Trolltech.

File size: 61.9 KB
Line 
1/****************************************************************************
2**
3** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
4** Contact: Qt Software Information ([email protected])
5**
6** This file is part of the QtGui module of the Qt Toolkit.
7**
8** $QT_BEGIN_LICENSE:LGPL$
9** Commercial Usage
10** Licensees holding valid Qt Commercial licenses may use this file in
11** accordance with the Qt Commercial License Agreement provided with the
12** Software or, alternatively, in accordance with the terms contained in
13** a written agreement between you and Nokia.
14**
15** GNU Lesser General Public License Usage
16** Alternatively, this file may be used under the terms of the GNU Lesser
17** General Public License version 2.1 as published by the Free Software
18** Foundation and appearing in the file LICENSE.LGPL included in the
19** packaging of this file. Please review the following information to
20** ensure the GNU Lesser General Public License version 2.1 requirements
21** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
22**
23** In addition, as a special exception, Nokia gives you certain
24** additional rights. These rights are described in the Nokia Qt LGPL
25** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
26** 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 are unsure which license is appropriate for your use, please
37** contact the sales department 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,
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 from XFree > 4.0 (X11/XF86keysyms.h), defining some special
718// multimedia keys. They are included here as not every system has them.
719#define XF86XK_Standby 0x1008FF10
720#define XF86XK_AudioLowerVolume 0x1008FF11
721#define XF86XK_AudioMute 0x1008FF12
722#define XF86XK_AudioRaiseVolume 0x1008FF13
723#define XF86XK_AudioPlay 0x1008FF14
724#define XF86XK_AudioStop 0x1008FF15
725#define XF86XK_AudioPrev 0x1008FF16
726#define XF86XK_AudioNext 0x1008FF17
727#define XF86XK_HomePage 0x1008FF18
728#define XF86XK_Calculator 0x1008FF1D
729#define XF86XK_Mail 0x1008FF19
730#define XF86XK_Start 0x1008FF1A
731#define XF86XK_Search 0x1008FF1B
732#define XF86XK_AudioRecord 0x1008FF1C
733#define XF86XK_Back 0x1008FF26
734#define XF86XK_Forward 0x1008FF27
735#define XF86XK_Stop 0x1008FF28
736#define XF86XK_Refresh 0x1008FF29
737#define XF86XK_Favorites 0x1008FF30
738#define XF86XK_AudioPause 0x1008FF31
739#define XF86XK_AudioMedia 0x1008FF32
740#define XF86XK_MyComputer 0x1008FF33
741#define XF86XK_OpenURL 0x1008FF38
742#define XF86XK_Launch0 0x1008FF40
743#define XF86XK_Launch1 0x1008FF41
744#define XF86XK_Launch2 0x1008FF42
745#define XF86XK_Launch3 0x1008FF43
746#define XF86XK_Launch4 0x1008FF44
747#define XF86XK_Launch5 0x1008FF45
748#define XF86XK_Launch6 0x1008FF46
749#define XF86XK_Launch7 0x1008FF47
750#define XF86XK_Launch8 0x1008FF48
751#define XF86XK_Launch9 0x1008FF49
752#define XF86XK_LaunchA 0x1008FF4A
753#define XF86XK_LaunchB 0x1008FF4B
754#define XF86XK_LaunchC 0x1008FF4C
755#define XF86XK_LaunchD 0x1008FF4D
756#define XF86XK_LaunchE 0x1008FF4E
757#define XF86XK_LaunchF 0x1008FF4F
758// end of XF86keysyms.h
759
760// Special keys used by Qtopia, mapped into the X11 private keypad range.
761#define QTOPIAXK_Select 0x11000601
762#define QTOPIAXK_Yes 0x11000602
763#define QTOPIAXK_No 0x11000603
764#define QTOPIAXK_Cancel 0x11000604
765#define QTOPIAXK_Printer 0x11000605
766#define QTOPIAXK_Execute 0x11000606
767#define QTOPIAXK_Sleep 0x11000607
768#define QTOPIAXK_Play 0x11000608
769#define QTOPIAXK_Zoom 0x11000609
770#define QTOPIAXK_Context1 0x1100060A
771#define QTOPIAXK_Context2 0x1100060B
772#define QTOPIAXK_Context3 0x1100060C
773#define QTOPIAXK_Context4 0x1100060D
774#define QTOPIAXK_Call 0x1100060E
775#define QTOPIAXK_Hangup 0x1100060F
776#define QTOPIAXK_Flip 0x11000610
777
778// keyboard mapping table
779static const unsigned int KeyTbl[] = {
780
781 // misc keys
782
783 XK_Escape, Qt::Key_Escape,
784 XK_Tab, Qt::Key_Tab,
785 XK_ISO_Left_Tab, Qt::Key_Backtab,
786 XK_BackSpace, Qt::Key_Backspace,
787 XK_Return, Qt::Key_Return,
788 XK_Insert, Qt::Key_Insert,
789 XK_Delete, Qt::Key_Delete,
790 XK_Clear, Qt::Key_Delete,
791 XK_Pause, Qt::Key_Pause,
792 XK_Print, Qt::Key_Print,
793 0x1005FF60, Qt::Key_SysReq, // hardcoded Sun SysReq
794 0x1007ff00, Qt::Key_SysReq, // hardcoded X386 SysReq
795
796 // cursor movement
797
798 XK_Home, Qt::Key_Home,
799 XK_End, Qt::Key_End,
800 XK_Left, Qt::Key_Left,
801 XK_Up, Qt::Key_Up,
802 XK_Right, Qt::Key_Right,
803 XK_Down, Qt::Key_Down,
804 XK_Prior, Qt::Key_PageUp,
805 XK_Next, Qt::Key_PageDown,
806
807 // modifiers
808
809 XK_Shift_L, Qt::Key_Shift,
810 XK_Shift_R, Qt::Key_Shift,
811 XK_Shift_Lock, Qt::Key_Shift,
812 XK_Control_L, Qt::Key_Control,
813 XK_Control_R, Qt::Key_Control,
814 XK_Meta_L, Qt::Key_Meta,
815 XK_Meta_R, Qt::Key_Meta,
816 XK_Alt_L, Qt::Key_Alt,
817 XK_Alt_R, Qt::Key_Alt,
818 XK_Caps_Lock, Qt::Key_CapsLock,
819 XK_Num_Lock, Qt::Key_NumLock,
820 XK_Scroll_Lock, Qt::Key_ScrollLock,
821 XK_Super_L, Qt::Key_Super_L,
822 XK_Super_R, Qt::Key_Super_R,
823 XK_Menu, Qt::Key_Menu,
824 XK_Hyper_L, Qt::Key_Hyper_L,
825 XK_Hyper_R, Qt::Key_Hyper_R,
826 XK_Help, Qt::Key_Help,
827 0x1000FF74, Qt::Key_Backtab, // hardcoded HP backtab
828 0x1005FF10, Qt::Key_F11, // hardcoded Sun F36 (labeled F11)
829 0x1005FF11, Qt::Key_F12, // hardcoded Sun F37 (labeled F12)
830
831 // numeric and function keypad keys
832
833 XK_KP_Space, Qt::Key_Space,
834 XK_KP_Tab, Qt::Key_Tab,
835 XK_KP_Enter, Qt::Key_Enter,
836 //XK_KP_F1, Qt::Key_F1,
837 //XK_KP_F2, Qt::Key_F2,
838 //XK_KP_F3, Qt::Key_F3,
839 //XK_KP_F4, Qt::Key_F4,
840 XK_KP_Home, Qt::Key_Home,
841 XK_KP_Left, Qt::Key_Left,
842 XK_KP_Up, Qt::Key_Up,
843 XK_KP_Right, Qt::Key_Right,
844 XK_KP_Down, Qt::Key_Down,
845 XK_KP_Prior, Qt::Key_PageUp,
846 XK_KP_Next, Qt::Key_PageDown,
847 XK_KP_End, Qt::Key_End,
848 XK_KP_Begin, Qt::Key_Clear,
849 XK_KP_Insert, Qt::Key_Insert,
850 XK_KP_Delete, Qt::Key_Delete,
851 XK_KP_Equal, Qt::Key_Equal,
852 XK_KP_Multiply, Qt::Key_Asterisk,
853 XK_KP_Add, Qt::Key_Plus,
854 XK_KP_Separator, Qt::Key_Comma,
855 XK_KP_Subtract, Qt::Key_Minus,
856 XK_KP_Decimal, Qt::Key_Period,
857 XK_KP_Divide, Qt::Key_Slash,
858
859 // International input method support keys
860
861 // International & multi-key character composition
862 XK_ISO_Level3_Shift, Qt::Key_AltGr,
863 XK_Multi_key, Qt::Key_Multi_key,
864 XK_Codeinput, Qt::Key_Codeinput,
865 XK_SingleCandidate, Qt::Key_SingleCandidate,
866 XK_MultipleCandidate, Qt::Key_MultipleCandidate,
867 XK_PreviousCandidate, Qt::Key_PreviousCandidate,
868
869 // Misc Functions
870 XK_Mode_switch, Qt::Key_Mode_switch,
871 XK_script_switch, Qt::Key_Mode_switch,
872
873 // Japanese keyboard support
874 XK_Kanji, Qt::Key_Kanji,
875 XK_Muhenkan, Qt::Key_Muhenkan,
876 //XK_Henkan_Mode, Qt::Key_Henkan_Mode,
877 XK_Henkan_Mode, Qt::Key_Henkan,
878 XK_Henkan, Qt::Key_Henkan,
879 XK_Romaji, Qt::Key_Romaji,
880 XK_Hiragana, Qt::Key_Hiragana,
881 XK_Katakana, Qt::Key_Katakana,
882 XK_Hiragana_Katakana, Qt::Key_Hiragana_Katakana,
883 XK_Zenkaku, Qt::Key_Zenkaku,
884 XK_Hankaku, Qt::Key_Hankaku,
885 XK_Zenkaku_Hankaku, Qt::Key_Zenkaku_Hankaku,
886 XK_Touroku, Qt::Key_Touroku,
887 XK_Massyo, Qt::Key_Massyo,
888 XK_Kana_Lock, Qt::Key_Kana_Lock,
889 XK_Kana_Shift, Qt::Key_Kana_Shift,
890 XK_Eisu_Shift, Qt::Key_Eisu_Shift,
891 XK_Eisu_toggle, Qt::Key_Eisu_toggle,
892 //XK_Kanji_Bangou, Qt::Key_Kanji_Bangou,
893 //XK_Zen_Koho, Qt::Key_Zen_Koho,
894 //XK_Mae_Koho, Qt::Key_Mae_Koho,
895 XK_Kanji_Bangou, Qt::Key_Codeinput,
896 XK_Zen_Koho, Qt::Key_MultipleCandidate,
897 XK_Mae_Koho, Qt::Key_PreviousCandidate,
898
899#ifdef XK_KOREAN
900 // Korean keyboard support
901 XK_Hangul, Qt::Key_Hangul,
902 XK_Hangul_Start, Qt::Key_Hangul_Start,
903 XK_Hangul_End, Qt::Key_Hangul_End,
904 XK_Hangul_Hanja, Qt::Key_Hangul_Hanja,
905 XK_Hangul_Jamo, Qt::Key_Hangul_Jamo,
906 XK_Hangul_Romaja, Qt::Key_Hangul_Romaja,
907 //XK_Hangul_Codeinput, Qt::Key_Hangul_Codeinput,
908 XK_Hangul_Codeinput, Qt::Key_Codeinput,
909 XK_Hangul_Jeonja, Qt::Key_Hangul_Jeonja,
910 XK_Hangul_Banja, Qt::Key_Hangul_Banja,
911 XK_Hangul_PreHanja, Qt::Key_Hangul_PreHanja,
912 XK_Hangul_PostHanja, Qt::Key_Hangul_PostHanja,
913 //XK_Hangul_SingleCandidate,Qt::Key_Hangul_SingleCandidate,
914 //XK_Hangul_MultipleCandidate,Qt::Key_Hangul_MultipleCandidate,
915 //XK_Hangul_PreviousCandidate,Qt::Key_Hangul_PreviousCandidate,
916 XK_Hangul_SingleCandidate, Qt::Key_SingleCandidate,
917 XK_Hangul_MultipleCandidate,Qt::Key_MultipleCandidate,
918 XK_Hangul_PreviousCandidate,Qt::Key_PreviousCandidate,
919 XK_Hangul_Special, Qt::Key_Hangul_Special,
920 //XK_Hangul_switch, Qt::Key_Hangul_switch,
921 XK_Hangul_switch, Qt::Key_Mode_switch,
922#endif // XK_KOREAN
923
924 // dead keys
925 XK_dead_grave, Qt::Key_Dead_Grave,
926 XK_dead_acute, Qt::Key_Dead_Acute,
927 XK_dead_circumflex, Qt::Key_Dead_Circumflex,
928 XK_dead_tilde, Qt::Key_Dead_Tilde,
929 XK_dead_macron, Qt::Key_Dead_Macron,
930 XK_dead_breve, Qt::Key_Dead_Breve,
931 XK_dead_abovedot, Qt::Key_Dead_Abovedot,
932 XK_dead_diaeresis, Qt::Key_Dead_Diaeresis,
933 XK_dead_abovering, Qt::Key_Dead_Abovering,
934 XK_dead_doubleacute, Qt::Key_Dead_Doubleacute,
935 XK_dead_caron, Qt::Key_Dead_Caron,
936 XK_dead_cedilla, Qt::Key_Dead_Cedilla,
937 XK_dead_ogonek, Qt::Key_Dead_Ogonek,
938 XK_dead_iota, Qt::Key_Dead_Iota,
939 XK_dead_voiced_sound, Qt::Key_Dead_Voiced_Sound,
940 XK_dead_semivoiced_sound, Qt::Key_Dead_Semivoiced_Sound,
941 XK_dead_belowdot, Qt::Key_Dead_Belowdot,
942 XK_dead_hook, Qt::Key_Dead_Hook,
943 XK_dead_horn, Qt::Key_Dead_Horn,
944
945 // Special multimedia keys
946 // currently only tested with MS internet keyboard
947
948 // browsing keys
949 XF86XK_Back, Qt::Key_Back,
950 XF86XK_Forward, Qt::Key_Forward,
951 XF86XK_Stop, Qt::Key_Stop,
952 XF86XK_Refresh, Qt::Key_Refresh,
953 XF86XK_Favorites, Qt::Key_Favorites,
954 XF86XK_AudioMedia, Qt::Key_LaunchMedia,
955 XF86XK_OpenURL, Qt::Key_OpenUrl,
956 XF86XK_HomePage, Qt::Key_HomePage,
957 XF86XK_Search, Qt::Key_Search,
958
959 // media keys
960 XF86XK_AudioLowerVolume, Qt::Key_VolumeDown,
961 XF86XK_AudioMute, Qt::Key_VolumeMute,
962 XF86XK_AudioRaiseVolume, Qt::Key_VolumeUp,
963 XF86XK_AudioPlay, Qt::Key_MediaPlay,
964 XF86XK_AudioStop, Qt::Key_MediaStop,
965 XF86XK_AudioPrev, Qt::Key_MediaPrevious,
966 XF86XK_AudioNext, Qt::Key_MediaNext,
967 XF86XK_AudioRecord, Qt::Key_MediaRecord,
968
969 // launch keys
970 XF86XK_Mail, Qt::Key_LaunchMail,
971 XF86XK_MyComputer, Qt::Key_Launch0,
972 XF86XK_Calculator, Qt::Key_Launch1,
973 XF86XK_Standby, Qt::Key_Standby,
974
975 XF86XK_Launch0, Qt::Key_Launch2,
976 XF86XK_Launch1, Qt::Key_Launch3,
977 XF86XK_Launch2, Qt::Key_Launch4,
978 XF86XK_Launch3, Qt::Key_Launch5,
979 XF86XK_Launch4, Qt::Key_Launch6,
980 XF86XK_Launch5, Qt::Key_Launch7,
981 XF86XK_Launch6, Qt::Key_Launch8,
982 XF86XK_Launch7, Qt::Key_Launch9,
983 XF86XK_Launch8, Qt::Key_LaunchA,
984 XF86XK_Launch9, Qt::Key_LaunchB,
985 XF86XK_LaunchA, Qt::Key_LaunchC,
986 XF86XK_LaunchB, Qt::Key_LaunchD,
987 XF86XK_LaunchC, Qt::Key_LaunchE,
988 XF86XK_LaunchD, Qt::Key_LaunchF,
989
990 // Qtopia keys
991 QTOPIAXK_Select, Qt::Key_Select,
992 QTOPIAXK_Yes, Qt::Key_Yes,
993 QTOPIAXK_No, Qt::Key_No,
994 QTOPIAXK_Cancel, Qt::Key_Cancel,
995 QTOPIAXK_Printer, Qt::Key_Printer,
996 QTOPIAXK_Execute, Qt::Key_Execute,
997 QTOPIAXK_Sleep, Qt::Key_Sleep,
998 QTOPIAXK_Play, Qt::Key_Play,
999 QTOPIAXK_Zoom, Qt::Key_Zoom,
1000 QTOPIAXK_Context1, Qt::Key_Context1,
1001 QTOPIAXK_Context2, Qt::Key_Context2,
1002 QTOPIAXK_Context3, Qt::Key_Context3,
1003 QTOPIAXK_Context4, Qt::Key_Context4,
1004 QTOPIAXK_Call, Qt::Key_Call,
1005 QTOPIAXK_Hangup, Qt::Key_Hangup,
1006 QTOPIAXK_Flip, Qt::Key_Flip,
1007
1008 0, 0
1009};
1010
1011static int translateKeySym(uint key)
1012{
1013 int code = -1;
1014 int i = 0; // any other keys
1015 while (KeyTbl[i]) {
1016 if (key == KeyTbl[i]) {
1017 code = (int)KeyTbl[i+1];
1018 break;
1019 }
1020 i += 2;
1021 }
1022 if (qt_meta_mask) {
1023 // translate Super/Hyper keys to Meta if we're using them as the MetaModifier
1024 if (qt_meta_mask == qt_super_mask && (code == Qt::Key_Super_L || code == Qt::Key_Super_R)) {
1025 code = Qt::Key_Meta;
1026 } else if (qt_meta_mask == qt_hyper_mask && (code == Qt::Key_Hyper_L || code == Qt::Key_Hyper_R)) {
1027 code = Qt::Key_Meta;
1028 }
1029 }
1030 return code;
1031}
1032
1033#if !defined(QT_NO_XIM)
1034static const unsigned short katakanaKeysymsToUnicode[] = {
1035 0x0000, 0x3002, 0x300C, 0x300D, 0x3001, 0x30FB, 0x30F2, 0x30A1,
1036 0x30A3, 0x30A5, 0x30A7, 0x30A9, 0x30E3, 0x30E5, 0x30E7, 0x30C3,
1037 0x30FC, 0x30A2, 0x30A4, 0x30A6, 0x30A8, 0x30AA, 0x30AB, 0x30AD,
1038 0x30AF, 0x30B1, 0x30B3, 0x30B5, 0x30B7, 0x30B9, 0x30BB, 0x30BD,
1039 0x30BF, 0x30C1, 0x30C4, 0x30C6, 0x30C8, 0x30CA, 0x30CB, 0x30CC,
1040 0x30CD, 0x30CE, 0x30CF, 0x30D2, 0x30D5, 0x30D8, 0x30DB, 0x30DE,
1041 0x30DF, 0x30E0, 0x30E1, 0x30E2, 0x30E4, 0x30E6, 0x30E8, 0x30E9,
1042 0x30EA, 0x30EB, 0x30EC, 0x30ED, 0x30EF, 0x30F3, 0x309B, 0x309C
1043};
1044
1045static const unsigned short cyrillicKeysymsToUnicode[] = {
1046 0x0000, 0x0452, 0x0453, 0x0451, 0x0454, 0x0455, 0x0456, 0x0457,
1047 0x0458, 0x0459, 0x045a, 0x045b, 0x045c, 0x0000, 0x045e, 0x045f,
1048 0x2116, 0x0402, 0x0403, 0x0401, 0x0404, 0x0405, 0x0406, 0x0407,
1049 0x0408, 0x0409, 0x040a, 0x040b, 0x040c, 0x0000, 0x040e, 0x040f,
1050 0x044e, 0x0430, 0x0431, 0x0446, 0x0434, 0x0435, 0x0444, 0x0433,
1051 0x0445, 0x0438, 0x0439, 0x043a, 0x043b, 0x043c, 0x043d, 0x043e,
1052 0x043f, 0x044f, 0x0440, 0x0441, 0x0442, 0x0443, 0x0436, 0x0432,
1053 0x044c, 0x044b, 0x0437, 0x0448, 0x044d, 0x0449, 0x0447, 0x044a,
1054 0x042e, 0x0410, 0x0411, 0x0426, 0x0414, 0x0415, 0x0424, 0x0413,
1055 0x0425, 0x0418, 0x0419, 0x041a, 0x041b, 0x041c, 0x041d, 0x041e,
1056 0x041f, 0x042f, 0x0420, 0x0421, 0x0422, 0x0423, 0x0416, 0x0412,
1057 0x042c, 0x042b, 0x0417, 0x0428, 0x042d, 0x0429, 0x0427, 0x042a
1058};
1059
1060static const unsigned short greekKeysymsToUnicode[] = {
1061 0x0000, 0x0386, 0x0388, 0x0389, 0x038a, 0x03aa, 0x0000, 0x038c,
1062 0x038e, 0x03ab, 0x0000, 0x038f, 0x0000, 0x0000, 0x0385, 0x2015,
1063 0x0000, 0x03ac, 0x03ad, 0x03ae, 0x03af, 0x03ca, 0x0390, 0x03cc,
1064 0x03cd, 0x03cb, 0x03b0, 0x03ce, 0x0000, 0x0000, 0x0000, 0x0000,
1065 0x0000, 0x0391, 0x0392, 0x0393, 0x0394, 0x0395, 0x0396, 0x0397,
1066 0x0398, 0x0399, 0x039a, 0x039b, 0x039c, 0x039d, 0x039e, 0x039f,
1067 0x03a0, 0x03a1, 0x03a3, 0x0000, 0x03a4, 0x03a5, 0x03a6, 0x03a7,
1068 0x03a8, 0x03a9, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
1069 0x0000, 0x03b1, 0x03b2, 0x03b3, 0x03b4, 0x03b5, 0x03b6, 0x03b7,
1070 0x03b8, 0x03b9, 0x03ba, 0x03bb, 0x03bc, 0x03bd, 0x03be, 0x03bf,
1071 0x03c0, 0x03c1, 0x03c3, 0x03c2, 0x03c4, 0x03c5, 0x03c6, 0x03c7,
1072 0x03c8, 0x03c9, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000
1073};
1074
1075static const unsigned short technicalKeysymsToUnicode[] = {
1076 0x0000, 0x23B7, 0x250C, 0x2500, 0x2320, 0x2321, 0x2502, 0x23A1,
1077 0x23A3, 0x23A4, 0x23A6, 0x239B, 0x239D, 0x239E, 0x23A0, 0x23A8,
1078 0x23AC, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
1079 0x0000, 0x0000, 0x0000, 0x0000, 0x2264, 0x2260, 0x2265, 0x222B,
1080 0x2234, 0x221D, 0x221E, 0x0000, 0x0000, 0x2207, 0x0000, 0x0000,
1081 0x223C, 0x2243, 0x0000, 0x0000, 0x0000, 0x21D4, 0x21D2, 0x2261,
1082 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x221A, 0x0000,
1083 0x0000, 0x0000, 0x2282, 0x2283, 0x2229, 0x222A, 0x2227, 0x2228,
1084 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
1085 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x2202,
1086 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0192, 0x0000,
1087 0x0000, 0x0000, 0x0000, 0x2190, 0x2191, 0x2192, 0x2193, 0x0000
1088};
1089
1090static const unsigned short specialKeysymsToUnicode[] = {
1091 0x25C6, 0x2592, 0x2409, 0x240C, 0x240D, 0x240A, 0x0000, 0x0000,
1092 0x2424, 0x240B, 0x2518, 0x2510, 0x250C, 0x2514, 0x253C, 0x23BA,
1093 0x23BB, 0x2500, 0x23BC, 0x23BD, 0x251C, 0x2524, 0x2534, 0x252C,
1094 0x2502, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000
1095};
1096
1097static const unsigned short publishingKeysymsToUnicode[] = {
1098 0x0000, 0x2003, 0x2002, 0x2004, 0x2005, 0x2007, 0x2008, 0x2009,
1099 0x200a, 0x2014, 0x2013, 0x0000, 0x0000, 0x0000, 0x2026, 0x2025,
1100 0x2153, 0x2154, 0x2155, 0x2156, 0x2157, 0x2158, 0x2159, 0x215a,
1101 0x2105, 0x0000, 0x0000, 0x2012, 0x2329, 0x0000, 0x232a, 0x0000,
1102 0x0000, 0x0000, 0x0000, 0x215b, 0x215c, 0x215d, 0x215e, 0x0000,
1103 0x0000, 0x2122, 0x2613, 0x0000, 0x25c1, 0x25b7, 0x25cb, 0x25af,
1104 0x2018, 0x2019, 0x201c, 0x201d, 0x211e, 0x0000, 0x2032, 0x2033,
1105 0x0000, 0x271d, 0x0000, 0x25ac, 0x25c0, 0x25b6, 0x25cf, 0x25ae,
1106 0x25e6, 0x25ab, 0x25ad, 0x25b3, 0x25bd, 0x2606, 0x2022, 0x25aa,
1107 0x25b2, 0x25bc, 0x261c, 0x261e, 0x2663, 0x2666, 0x2665, 0x0000,
1108 0x2720, 0x2020, 0x2021, 0x2713, 0x2717, 0x266f, 0x266d, 0x2642,
1109 0x2640, 0x260e, 0x2315, 0x2117, 0x2038, 0x201a, 0x201e, 0x0000
1110};
1111
1112static const unsigned short aplKeysymsToUnicode[] = {
1113 0x0000, 0x0000, 0x0000, 0x003c, 0x0000, 0x0000, 0x003e, 0x0000,
1114 0x2228, 0x2227, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
1115 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
1116 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
1117 0x00af, 0x0000, 0x22a5, 0x2229, 0x230a, 0x0000, 0x005f, 0x0000,
1118 0x0000, 0x0000, 0x2218, 0x0000, 0x2395, 0x0000, 0x22a4, 0x25cb,
1119 0x0000, 0x0000, 0x0000, 0x2308, 0x0000, 0x0000, 0x222a, 0x0000,
1120 0x2283, 0x0000, 0x2282, 0x0000, 0x22a2, 0x0000, 0x0000, 0x0000,
1121 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
1122 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
1123 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
1124 0x0000, 0x0000, 0x0000, 0x0000, 0x22a3, 0x0000, 0x0000, 0x0000
1125};
1126
1127static const unsigned short koreanKeysymsToUnicode[] = {
1128 0x0000, 0x3131, 0x3132, 0x3133, 0x3134, 0x3135, 0x3136, 0x3137,
1129 0x3138, 0x3139, 0x313a, 0x313b, 0x313c, 0x313d, 0x313e, 0x313f,
1130 0x3140, 0x3141, 0x3142, 0x3143, 0x3144, 0x3145, 0x3146, 0x3147,
1131 0x3148, 0x3149, 0x314a, 0x314b, 0x314c, 0x314d, 0x314e, 0x314f,
1132 0x3150, 0x3151, 0x3152, 0x3153, 0x3154, 0x3155, 0x3156, 0x3157,
1133 0x3158, 0x3159, 0x315a, 0x315b, 0x315c, 0x315d, 0x315e, 0x315f,
1134 0x3160, 0x3161, 0x3162, 0x3163, 0x11a8, 0x11a9, 0x11aa, 0x11ab,
1135 0x11ac, 0x11ad, 0x11ae, 0x11af, 0x11b0, 0x11b1, 0x11b2, 0x11b3,
1136 0x11b4, 0x11b5, 0x11b6, 0x11b7, 0x11b8, 0x11b9, 0x11ba, 0x11bb,
1137 0x11bc, 0x11bd, 0x11be, 0x11bf, 0x11c0, 0x11c1, 0x11c2, 0x316d,
1138 0x3171, 0x3178, 0x317f, 0x3181, 0x3184, 0x3186, 0x318d, 0x318e,
1139 0x11eb, 0x11f0, 0x11f9, 0x0000, 0x0000, 0x0000, 0x0000, 0x20a9
1140};
1141
1142static QChar keysymToUnicode(unsigned char byte3, unsigned char byte4)
1143{
1144 switch (byte3) {
1145 case 0x04:
1146 // katakana
1147 if (byte4 > 0xa0 && byte4 < 0xe0)
1148 return QChar(katakanaKeysymsToUnicode[byte4 - 0xa0]);
1149 else if (byte4 == 0x7e)
1150 return QChar(0x203e); // Overline
1151 break;
1152 case 0x06:
1153 // russian, use lookup table
1154 if (byte4 > 0xa0)
1155 return QChar(cyrillicKeysymsToUnicode[byte4 - 0xa0]);
1156 break;
1157 case 0x07:
1158 // greek
1159 if (byte4 > 0xa0)
1160 return QChar(greekKeysymsToUnicode[byte4 - 0xa0]);
1161 break;
1162 case 0x08:
1163 // technical
1164 if (byte4 > 0xa0)
1165 return QChar(technicalKeysymsToUnicode[byte4 - 0xa0]);
1166 break;
1167 case 0x09:
1168 // special
1169 if (byte4 >= 0xe0)
1170 return QChar(specialKeysymsToUnicode[byte4 - 0xe0]);
1171 break;
1172 case 0x0a:
1173 // publishing
1174 if (byte4 > 0xa0)
1175 return QChar(publishingKeysymsToUnicode[byte4 - 0xa0]);
1176 break;
1177 case 0x0b:
1178 // APL
1179 if (byte4 > 0xa0)
1180 return QChar(aplKeysymsToUnicode[byte4 - 0xa0]);
1181 break;
1182 case 0x0e:
1183 // Korean
1184 if (byte4 > 0xa0)
1185 return QChar(koreanKeysymsToUnicode[byte4 - 0xa0]);
1186 break;
1187 default:
1188 break;
1189 }
1190 return QChar(0x0);
1191}
1192#endif
1193
1194static QString translateKeySym(KeySym keysym, uint xmodifiers,
1195 int &code, Qt::KeyboardModifiers &modifiers,
1196 QByteArray &chars, int &count)
1197{
1198 // all keysyms smaller than 0xff00 are actally keys that can be mapped to unicode chars
1199
1200 extern QTextCodec *qt_input_mapper; // from qapplication_x11.cpp
1201 QTextCodec *mapper = qt_input_mapper;
1202 QChar converted;
1203
1204 if (count == 0 && keysym < 0xff00) {
1205 unsigned char byte3 = (unsigned char)(keysym >> 8);
1206 int mib = -1;
1207 switch(byte3) {
1208 case 0: // Latin 1
1209 case 1: // Latin 2
1210 case 2: //latin 3
1211 case 3: // latin4
1212 mib = byte3 + 4; break;
1213 case 5: // arabic
1214 mib = 82; break;
1215 case 12: // Hebrew
1216 mib = 85; break;
1217 case 13: // Thai
1218 mib = 2259; break;
1219 case 4: // kana
1220 case 6: // cyrillic
1221 case 7: // greek
1222 case 8: // technical, no mapping here at the moment
1223 case 9: // Special
1224 case 10: // Publishing
1225 case 11: // APL
1226 case 14: // Korean, no mapping
1227 mib = -1; // manual conversion
1228 mapper = 0;
1229#if !defined(QT_NO_XIM)
1230 converted = keysymToUnicode(byte3, keysym & 0xff);
1231#endif
1232 case 0x20:
1233 // currency symbols
1234 if (keysym >= 0x20a0 && keysym <= 0x20ac) {
1235 mib = -1; // manual conversion
1236 mapper = 0;
1237 converted = (uint)keysym;
1238 }
1239 break;
1240 default:
1241 break;
1242 }
1243 if (mib != -1) {
1244 mapper = QTextCodec::codecForMib(mib);
1245 if (chars.isEmpty())
1246 chars.resize(1);
1247 chars[0] = (unsigned char) (keysym & 0xff); // get only the fourth bit for conversion later
1248 count++;
1249 }
1250 } else if (keysym >= 0x1000000 && keysym <= 0x100ffff) {
1251 converted = (ushort) (keysym - 0x1000000);
1252 mapper = 0;
1253 }
1254 if (count < (int)chars.size()-1)
1255 chars[count] = '\0';
1256
1257 QString text;
1258 if (!mapper && converted.unicode() != 0x0) {
1259 text = converted;
1260 } else if (!chars.isEmpty()) {
1261 // convert chars (8bit) to text (unicode).
1262 if (mapper)
1263 text = mapper->toUnicode(chars.data(), count, 0);
1264 if (text.isEmpty()) {
1265 // no mapper, or codec couldn't convert to unicode (this
1266 // can happen when running in the C locale or with no LANG
1267 // set). try converting from latin-1
1268 text = QString::fromLatin1(chars);
1269 }
1270 }
1271
1272 modifiers = X11->translateModifiers(xmodifiers);
1273
1274 // Commentary in X11/keysymdef says that X codes match ASCII, so it
1275 // is safe to use the locale functions to process X codes in ISO8859-1.
1276 //
1277 // This is mainly for compatibility - applications should not use the
1278 // Qt keycodes between 128 and 255, but should rather use the
1279 // QKeyEvent::text().
1280 //
1281 extern QTextCodec *qt_input_mapper; // from qapplication_x11.cpp
1282 if (keysym < 128 || (keysym < 256 && (!qt_input_mapper || qt_input_mapper->mibEnum()==4))) {
1283 // upper-case key, if known
1284 code = isprint((int)keysym) ? toupper((int)keysym) : 0;
1285 } else if (keysym >= XK_F1 && keysym <= XK_F35) {
1286 // function keys
1287 code = Qt::Key_F1 + ((int)keysym - XK_F1);
1288 } else if (keysym >= XK_KP_Space && keysym <= XK_KP_9) {
1289 if (keysym >= XK_KP_0) {
1290 // numeric keypad keys
1291 code = Qt::Key_0 + ((int)keysym - XK_KP_0);
1292 } else {
1293 code = translateKeySym(keysym);
1294 }
1295 modifiers |= Qt::KeypadModifier;
1296 } else if (text.length() == 1 && text.unicode()->unicode() > 0x1f && text.unicode()->unicode() != 0x7f && !(keysym >= XK_dead_grave && keysym <= XK_dead_horn)) {
1297 code = text.unicode()->toUpper().unicode();
1298 } else {
1299 // any other keys
1300 code = translateKeySym(keysym);
1301
1302 if (code == Qt::Key_Tab && (modifiers & Qt::ShiftModifier)) {
1303 // map shift+tab to shift+backtab, QShortcutMap knows about it
1304 // and will handle it.
1305 code = Qt::Key_Backtab;
1306 text = QString();
1307 }
1308 }
1309
1310 return text;
1311}
1312
1313extern bool qt_use_rtl_extensions; // from qapplication_x11.cpp
1314
1315bool QKeyMapperPrivate::translateKeyEventInternal(QWidget *keyWidget,
1316 const XEvent *event,
1317 KeySym &keysym,
1318 int& count,
1319 QString& text,
1320 Qt::KeyboardModifiers &modifiers,
1321 int& code,
1322 QEvent::Type &type,
1323 bool statefulTranslation)
1324{
1325 XKeyEvent xkeyevent = event->xkey;
1326 int keycode = event->xkey.keycode;
1327 // save the modifier state, we will use the keystate uint later by passing
1328 // it to translateButtonState
1329 uint keystate = event->xkey.state;
1330
1331 type = (event->type == XKeyPress) ? QEvent::KeyPress : QEvent::KeyRelease;
1332
1333 static int directionKeyEvent = 0;
1334 static unsigned int lastWinId = 0;
1335
1336 // translate pending direction change
1337 if (statefulTranslation && qt_use_rtl_extensions && type == QEvent::KeyRelease) {
1338 if (directionKeyEvent == Qt::Key_Direction_R || directionKeyEvent == Qt::Key_Direction_L) {
1339 type = QEvent::KeyPress;
1340 code = directionKeyEvent;
1341 text = QString();
1342 directionKeyEvent = 0;
1343 lastWinId = 0;
1344 return true;
1345 } else {
1346 directionKeyEvent = 0;
1347 lastWinId = 0;
1348 }
1349 }
1350
1351 // some XmbLookupString implementations don't return buffer overflow correctly,
1352 // so we increase the input buffer to allow for long strings...
1353 // 256 chars * 2 bytes + 1 null-term == 513 bytes
1354 QByteArray chars;
1355 chars.resize(513);
1356
1357 count = XLookupString(&xkeyevent, chars.data(), chars.size(), &keysym, 0);
1358 if (count && !keycode) {
1359 extern int qt_ximComposingKeycode; // from qapplication_x11.cpp
1360 keycode = qt_ximComposingKeycode;
1361 qt_ximComposingKeycode = 0;
1362 }
1363
1364 // translate the keysym + xmodifiers to Qt::Key_* + Qt::KeyboardModifiers
1365 text = translateKeySym(keysym, keystate, code, modifiers, chars, count);
1366
1367 // Watch for keypresses and if its a key belonging to the Ctrl-Shift
1368 // direction-changing accel, remember it.
1369 // We keep track of those keys instead of using the event's state
1370 // (to figure out whether the Ctrl modifier is held while Shift is pressed,
1371 // or Shift is held while Ctrl is pressed) since the 'state' doesn't tell
1372 // us whether the modifier held is Left or Right.
1373 if (statefulTranslation && qt_use_rtl_extensions && type == QEvent::KeyPress) {
1374 if (keysym == XK_Control_L || keysym == XK_Control_R
1375 || keysym == XK_Shift_L || keysym == XK_Shift_R) {
1376 if (!directionKeyEvent) {
1377 directionKeyEvent = keysym;
1378 // This code exists in order to check that
1379 // the event is occurred in the same widget.
1380 lastWinId = keyWidget->internalWinId();
1381 }
1382 } else {
1383 // this can no longer be a direction-changing accel.
1384 // if any other key was pressed.
1385 directionKeyEvent = Qt::Key_Space;
1386 }
1387
1388 if (directionKeyEvent && lastWinId == keyWidget->internalWinId()) {
1389 if ((keysym == XK_Shift_L && directionKeyEvent == XK_Control_L)
1390 || (keysym == XK_Control_L && directionKeyEvent == XK_Shift_L)) {
1391 directionKeyEvent = Qt::Key_Direction_L;
1392 } else if ((keysym == XK_Shift_R && directionKeyEvent == XK_Control_R)
1393 || (keysym == XK_Control_R && directionKeyEvent == XK_Shift_R)) {
1394 directionKeyEvent = Qt::Key_Direction_R;
1395 }
1396 } else if (directionKeyEvent == Qt::Key_Direction_L
1397 || directionKeyEvent == Qt::Key_Direction_R) {
1398 directionKeyEvent = Qt::Key_Space; // invalid
1399 }
1400 }
1401
1402 return true;
1403}
1404
1405
1406struct qt_auto_repeat_data
1407{
1408 // match the window and keycode with timestamp delta of 10 ms
1409 Window window;
1410 KeyCode keycode;
1411 Time timestamp;
1412
1413 // queue scanner state
1414 bool release;
1415 bool error;
1416};
1417
1418#if defined(Q_C_CALLBACKS)
1419extern "C" {
1420#endif
1421
1422static Bool qt_keypress_scanner(Display *, XEvent *event, XPointer arg)
1423{
1424 if (event->type != XKeyPress && event->type != XKeyRelease)
1425 return false;
1426
1427 qt_auto_repeat_data *data = (qt_auto_repeat_data *) arg;
1428 if (data->error)
1429 return false;
1430
1431 if (event->xkey.window != data->window ||
1432 event->xkey.keycode != data->keycode) {
1433 // deal breakers: key events in a different window or an event
1434 // with a different key code
1435 data->error = true;
1436 return false;
1437 }
1438
1439 if (event->type == XKeyPress) {
1440 data->error = (! data->release || event->xkey.time - data->timestamp > 10);
1441 return (! data->error);
1442 }
1443
1444 // must be XKeyRelease event
1445 if (data->release) {
1446 // found a second release
1447 data->error = true;
1448 return false;
1449 }
1450
1451 // found a single release
1452 data->release = true;
1453 data->timestamp = event->xkey.time;
1454
1455 return false;
1456}
1457
1458static Bool qt_keyrelease_scanner(Display *, XEvent *event, XPointer arg)
1459{
1460 const qt_auto_repeat_data *data = (const qt_auto_repeat_data *) arg;
1461 return (event->type == XKeyRelease &&
1462 event->xkey.window == data->window &&
1463 event->xkey.keycode == data->keycode);
1464}
1465
1466#if defined(Q_C_CALLBACKS)
1467}
1468#endif
1469
1470bool QKeyMapperPrivate::translateKeyEvent(QWidget *keyWidget, const XEvent *event, bool grab)
1471{
1472 int code = -1;
1473 int count = 0;
1474 Qt::KeyboardModifiers modifiers;
1475
1476 if (qt_sm_blockUserInput) // block user interaction during session management
1477 return true;
1478
1479 Display *dpy = X11->display;
1480
1481 if (!keyWidget->isEnabled())
1482 return true;
1483
1484 QEvent::Type type;
1485 bool autor = false;
1486 QString text;
1487
1488 KeySym keysym = 0;
1489 translateKeyEventInternal(keyWidget, event, keysym, count, text, modifiers, code, type);
1490
1491 // was this the last auto-repeater?
1492 qt_auto_repeat_data auto_repeat_data;
1493 auto_repeat_data.window = event->xkey.window;
1494 auto_repeat_data.keycode = event->xkey.keycode;
1495 auto_repeat_data.timestamp = event->xkey.time;
1496
1497 static uint curr_autorep = 0;
1498 if (event->type == XKeyPress) {
1499 if (curr_autorep == event->xkey.keycode) {
1500 autor = true;
1501 curr_autorep = 0;
1502 }
1503 } else {
1504 // look ahead for auto-repeat
1505 XEvent nextpress;
1506
1507 auto_repeat_data.release = true;
1508 auto_repeat_data.error = false;
1509 if (XCheckIfEvent(dpy, &nextpress, &qt_keypress_scanner,
1510 (XPointer) &auto_repeat_data)) {
1511 autor = true;
1512
1513 // Put it back... we COULD send the event now and not need
1514 // the static curr_autorep variable.
1515 XPutBackEvent(dpy,&nextpress);
1516 }
1517 curr_autorep = autor ? event->xkey.keycode : 0;
1518 }
1519
1520#if defined QT3_SUPPORT && !defined(QT_NO_SHORTCUT)
1521 // process accelerators before doing key compression
1522 if (type == QEvent::KeyPress && !grab
1523 && QApplicationPrivate::instance()->use_compat()) {
1524 // send accel events if the keyboard is not grabbed
1525 QKeyEventEx a(type, code, modifiers, text, autor, qMax(qMax(count,1), int(text.length())),
1526 event->xkey.keycode, keysym, event->xkey.state);
1527 if (QApplicationPrivate::instance()->qt_tryAccelEvent(keyWidget, &a))
1528 return true;
1529 }
1530#endif
1531
1532#ifndef QT_NO_IM
1533 QInputContext *qic = keyWidget->inputContext();
1534#endif
1535
1536 // compress keys
1537 if (!text.isEmpty() && keyWidget->testAttribute(Qt::WA_KeyCompression) &&
1538#ifndef QT_NO_IM
1539 // Ordinary input methods require discrete key events to work
1540 // properly, so key compression has to be disabled when input
1541 // context exists.
1542 //
1543 // And further consideration, some complex input method
1544 // require all key press/release events discretely even if
1545 // the input method awares of key compression and compressed
1546 // keys are ordinary alphabets. For example, the uim project
1547 // is planning to implement "combinational shift" feature for
1548 // a Japanese input method, uim-skk. It will work as follows.
1549 //
1550 // 1. press "r"
1551 // 2. press "u"
1552 // 3. release both "r" and "u" in arbitrary order
1553 // 4. above key sequence generates "Ru"
1554 //
1555 // Of course further consideration about other participants
1556 // such as key repeat mechanism is required to implement such
1557 // feature.
1558 !qic &&
1559#endif // QT_NO_IM
1560 // do not compress keys if the key event we just got above matches
1561 // one of the key ranges used to compute stopCompression
1562 !((code >= Qt::Key_Escape && code <= Qt::Key_SysReq)
1563 || (code >= Qt::Key_Home && code <= Qt::Key_PageDown)
1564 || (code >= Qt::Key_Super_L && code <= Qt::Key_Direction_R)
1565 || (code == 0)
1566 || (text.length() == 1 && text.unicode()->unicode() == '\n'))) {
1567 // the widget wants key compression so it gets it
1568
1569 // sync the event queue, this makes key compress work better
1570 XSync(dpy, false);
1571
1572 for (;;) {
1573 XEvent evRelease;
1574 XEvent evPress;
1575 if (!XCheckTypedWindowEvent(dpy,event->xkey.window,
1576 XKeyRelease,&evRelease))
1577 break;
1578 if (!XCheckTypedWindowEvent(dpy,event->xkey.window,
1579 XKeyPress,&evPress)) {
1580 XPutBackEvent(dpy, &evRelease);
1581 break;
1582 }
1583 QString textIntern;
1584 int codeIntern = -1;
1585 int countIntern = 0;
1586 Qt::KeyboardModifiers modifiersIntern;
1587 QEvent::Type t;
1588 KeySym keySymIntern;
1589 translateKeyEventInternal(keyWidget, &evPress, keySymIntern, countIntern, textIntern,
1590 modifiersIntern, codeIntern, t);
1591 // use stopCompression to stop key compression for the following
1592 // key event ranges:
1593 bool stopCompression =
1594 // 1) misc keys
1595 (codeIntern >= Qt::Key_Escape && codeIntern <= Qt::Key_SysReq)
1596 // 2) cursor movement
1597 || (codeIntern >= Qt::Key_Home && codeIntern <= Qt::Key_PageDown)
1598 // 3) extra keys
1599 || (codeIntern >= Qt::Key_Super_L && codeIntern <= Qt::Key_Direction_R)
1600 // 4) something that a) doesn't translate to text or b) translates
1601 // to newline text
1602 || (codeIntern == 0)
1603 || (textIntern.length() == 1 && textIntern.unicode()->unicode() == '\n')
1604 || (codeIntern == Qt::Key_unknown);
1605
1606 if (modifiersIntern == modifiers && !textIntern.isEmpty() && !stopCompression) {
1607 text += textIntern;
1608 count += countIntern;
1609 } else {
1610 XPutBackEvent(dpy, &evPress);
1611 XPutBackEvent(dpy, &evRelease);
1612 break;
1613 }
1614 }
1615 }
1616
1617 // autorepeat compression makes sense for all widgets (Windows
1618 // does it automatically ....)
1619 if (event->type == XKeyPress && text.length() <= 1
1620#ifndef QT_NO_IM
1621 // input methods need discrete key events
1622 && !qic
1623#endif// QT_NO_IM
1624 ) {
1625 XEvent dummy;
1626
1627 for (;;) {
1628 auto_repeat_data.release = false;
1629 auto_repeat_data.error = false;
1630 if (! XCheckIfEvent(dpy, &dummy, &qt_keypress_scanner,
1631 (XPointer) &auto_repeat_data))
1632 break;
1633 if (! XCheckIfEvent(dpy, &dummy, &qt_keyrelease_scanner,
1634 (XPointer) &auto_repeat_data))
1635 break;
1636
1637 count++;
1638 if (!text.isEmpty())
1639 text += text[0];
1640 }
1641 }
1642
1643 return QKeyMapper::sendKeyEvent(keyWidget, grab, type, code, modifiers, text, autor,
1644 qMax(qMax(count,1), int(text.length())),
1645 event->xkey.keycode, keysym, event->xkey.state);
1646}
1647
1648bool QKeyMapper::sendKeyEvent(QWidget *keyWidget, bool grab,
1649 QEvent::Type type, int code, Qt::KeyboardModifiers modifiers,
1650 const QString &text, bool autorepeat, int count,
1651 quint32 nativeScanCode, quint32 nativeVirtualKey, quint32 nativeModifiers,
1652 bool *)
1653{
1654 // try the menukey first
1655 if (type == QEvent::KeyPress && code == Qt::Key_Menu) {
1656 QVariant v = keyWidget->inputMethodQuery(Qt::ImMicroFocus);
1657 QPoint globalPos;
1658 QPoint pos;
1659 if (v.isNull()) {
1660 globalPos = QCursor::pos();
1661 pos = keyWidget->mapFromGlobal(globalPos);
1662 } else {
1663 pos = v.toRect().center();
1664 globalPos = keyWidget->mapToGlobal(pos);
1665 }
1666 QContextMenuEvent e(QContextMenuEvent::Keyboard, pos, globalPos);
1667 qt_sendSpontaneousEvent(keyWidget, &e);
1668 if(e.isAccepted())
1669 return true;
1670 }
1671
1672 Q_UNUSED(grab);
1673 QKeyEventEx e(type, code, modifiers, text, autorepeat, qMax(qMax(count,1), int(text.length())),
1674 nativeScanCode, nativeVirtualKey, nativeModifiers);
1675 return qt_sendSpontaneousEvent(keyWidget, &e);
1676}
1677
1678QT_END_NAMESPACE
Note: See TracBrowser for help on using the repository browser.