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