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