tools/qvfb/x11keyfaker.cpp
changeset 0 1918ee327afb
child 4 3b1da2848fc7
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 tools 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 "x11keyfaker.h"
       
    43 #include <QTimer>
       
    44 #include <QSocketNotifier>
       
    45 #include <QDebug>
       
    46 #include <X11/Xlib.h>
       
    47 #include <X11/cursorfont.h>
       
    48 #include <X11/extensions/XTest.h>
       
    49 #include <X11/keysym.h>
       
    50 #include <X11/XF86keysym.h>
       
    51 #include "qtopiakeysym.h"
       
    52 #include <unistd.h>
       
    53 #include <fcntl.h>
       
    54 
       
    55 QT_BEGIN_NAMESPACE
       
    56 
       
    57 X11KeyFaker::X11KeyFaker(const QString& displayName, QObject *parent)
       
    58     : QObject(parent)
       
    59 {
       
    60     this->displayName = displayName;
       
    61     this->dpy = 0;
       
    62     this->retryCount = 0;
       
    63     this->shiftKeycode = 0;
       
    64     this->modeSwitchKeycode = 0;
       
    65     this->modifiers = 0;
       
    66     connect();
       
    67 }
       
    68 
       
    69 X11KeyFaker::~X11KeyFaker()
       
    70 {
       
    71     if (dpy)
       
    72 	XCloseDisplay(dpy);
       
    73 }
       
    74 
       
    75 void X11KeyFaker::sendKeyEvent(int qtCode, bool isPress)
       
    76 {
       
    77     if (!dpy)
       
    78 	return;
       
    79 
       
    80     // Convert the Qt key code into an X keysym.
       
    81     KeySym keysym = NoSymbol;
       
    82     switch (qtCode) {
       
    83         case Qt::Key_Escape: keysym = XK_Escape; break;
       
    84         case Qt::Key_Tab: keysym = XK_Tab; break;
       
    85         case Qt::Key_Backtab: keysym = XK_ISO_Left_Tab; break;
       
    86         case Qt::Key_Backspace: keysym = XK_BackSpace; break;
       
    87         case Qt::Key_Return: keysym = XK_Return; break;
       
    88         case Qt::Key_Enter: keysym = XK_KP_Enter; break;
       
    89         case Qt::Key_Insert: keysym = XK_KP_Insert; break;
       
    90         case Qt::Key_Delete: keysym = XK_KP_Delete; break;
       
    91         case Qt::Key_Pause: keysym = XK_Pause; break;
       
    92         case Qt::Key_Print: keysym = XK_Print; break;
       
    93         case Qt::Key_SysReq: keysym = 0x1005FF60; break;
       
    94         case Qt::Key_Clear: keysym = XK_KP_Begin; break;
       
    95         case Qt::Key_Home: keysym = XK_Home; break;
       
    96         case Qt::Key_End: keysym = XK_End; break;
       
    97         case Qt::Key_Left: keysym = XK_Left; break;
       
    98         case Qt::Key_Up: keysym = XK_Up; break;
       
    99         case Qt::Key_Right: keysym = XK_Right; break;
       
   100         case Qt::Key_Down: keysym = XK_Down; break;
       
   101         case Qt::Key_PageUp: keysym = XK_Prior; break;
       
   102         case Qt::Key_PageDown: keysym = XK_Next; break;
       
   103         case Qt::Key_Shift: keysym = XK_Shift_L; break;
       
   104         case Qt::Key_Control: keysym = XK_Control_L; break;
       
   105         case Qt::Key_Meta: keysym = XK_Meta_L; break;
       
   106         case Qt::Key_Alt: keysym = XK_Alt_L; break;
       
   107         case Qt::Key_CapsLock: keysym = XK_Caps_Lock; break;
       
   108         case Qt::Key_NumLock: keysym = XK_Num_Lock; break;
       
   109         case Qt::Key_ScrollLock: keysym = XK_Scroll_Lock; break;
       
   110         case Qt::Key_F1: keysym = XK_F1; break;
       
   111         case Qt::Key_F2: keysym = XK_F2; break;
       
   112         case Qt::Key_F3: keysym = XK_F3; break;
       
   113         case Qt::Key_F4: keysym = XK_F4; break;
       
   114         case Qt::Key_F5: keysym = XK_F5; break;
       
   115         case Qt::Key_F6: keysym = XK_F6; break;
       
   116         case Qt::Key_F7: keysym = XK_F7; break;
       
   117         case Qt::Key_F8: keysym = XK_F8; break;
       
   118         case Qt::Key_F9: keysym = XK_F9; break;
       
   119         case Qt::Key_F10: keysym = XK_F10; break;
       
   120         case Qt::Key_F11: keysym = XK_F11; break;
       
   121         case Qt::Key_F12: keysym = XK_F12; break;
       
   122         case Qt::Key_F13: keysym = XK_F13; break;
       
   123         case Qt::Key_F14: keysym = XK_F14; break;
       
   124         case Qt::Key_F15: keysym = XK_F15; break;
       
   125         case Qt::Key_F16: keysym = XK_F16; break;
       
   126         case Qt::Key_F17: keysym = XK_F17; break;
       
   127         case Qt::Key_F18: keysym = XK_F18; break;
       
   128         case Qt::Key_F19: keysym = XK_F19; break;
       
   129         case Qt::Key_F20: keysym = XK_F20; break;
       
   130         case Qt::Key_F21: keysym = XK_F21; break;
       
   131         case Qt::Key_F22: keysym = XK_F22; break;
       
   132         case Qt::Key_F23: keysym = XK_F23; break;
       
   133         case Qt::Key_F24: keysym = XK_F24; break;
       
   134         case Qt::Key_F25: keysym = XK_F25; break;
       
   135         case Qt::Key_F26: keysym = XK_F26; break;
       
   136         case Qt::Key_F27: keysym = XK_F27; break;
       
   137         case Qt::Key_F28: keysym = XK_F28; break;
       
   138         case Qt::Key_F29: keysym = XK_F29; break;
       
   139         case Qt::Key_F30: keysym = XK_F30; break;
       
   140         case Qt::Key_F31: keysym = XK_F31; break;
       
   141         case Qt::Key_F32: keysym = XK_F32; break;
       
   142         case Qt::Key_F33: keysym = XK_F33; break;
       
   143         case Qt::Key_F34: keysym = XK_F34; break;
       
   144         case Qt::Key_F35: keysym = XK_F35; break;
       
   145         case Qt::Key_Super_L: keysym = XK_Super_L; break;
       
   146         case Qt::Key_Super_R: keysym = XK_Super_R; break;
       
   147         case Qt::Key_Menu: keysym = XK_Menu; break;
       
   148         case Qt::Key_Hyper_L: keysym = XK_Hyper_L; break;
       
   149         case Qt::Key_Hyper_R: keysym = XK_Hyper_R; break;
       
   150         case Qt::Key_Help: keysym = XK_Help; break;
       
   151         case Qt::Key_Direction_L: keysym = NoSymbol; break; // ???
       
   152         case Qt::Key_Direction_R: keysym = NoSymbol; break; // ???
       
   153         case Qt::Key_Space: keysym = XK_space; break;
       
   154         case Qt::Key_Exclam: keysym = XK_exclam; break;
       
   155         case Qt::Key_QuoteDbl: keysym = XK_quotedbl; break;
       
   156         case Qt::Key_NumberSign: keysym = XK_numbersign; break;
       
   157         case Qt::Key_Dollar: keysym = XK_dollar; break;
       
   158         case Qt::Key_Percent: keysym = XK_percent; break;
       
   159         case Qt::Key_Ampersand: keysym = XK_ampersand; break;
       
   160         case Qt::Key_Apostrophe: keysym = XK_apostrophe; break;
       
   161         case Qt::Key_ParenLeft: keysym = XK_parenleft; break;
       
   162         case Qt::Key_ParenRight: keysym = XK_parenright; break;
       
   163         case Qt::Key_Asterisk: keysym = XK_asterisk; break;
       
   164         case Qt::Key_Plus: keysym = XK_plus; break;
       
   165         case Qt::Key_Comma: keysym = XK_comma; break;
       
   166         case Qt::Key_Minus: keysym = XK_minus; break;
       
   167         case Qt::Key_Period: keysym = XK_period; break;
       
   168         case Qt::Key_Slash: keysym = XK_slash; break;
       
   169         case Qt::Key_0: keysym = XK_0; break;
       
   170         case Qt::Key_1: keysym = XK_1; break;
       
   171         case Qt::Key_2: keysym = XK_2; break;
       
   172         case Qt::Key_3: keysym = XK_3; break;
       
   173         case Qt::Key_4: keysym = XK_4; break;
       
   174         case Qt::Key_5: keysym = XK_5; break;
       
   175         case Qt::Key_6: keysym = XK_6; break;
       
   176         case Qt::Key_7: keysym = XK_7; break;
       
   177         case Qt::Key_8: keysym = XK_8; break;
       
   178         case Qt::Key_9: keysym = XK_9; break;
       
   179         case Qt::Key_Colon: keysym = XK_colon; break;
       
   180         case Qt::Key_Semicolon: keysym = XK_semicolon; break;
       
   181         case Qt::Key_Less: keysym = XK_less; break;
       
   182         case Qt::Key_Equal: keysym = XK_equal; break;
       
   183         case Qt::Key_Greater: keysym = XK_greater; break;
       
   184         case Qt::Key_Question: keysym = XK_question; break;
       
   185         case Qt::Key_At: keysym = XK_at; break;
       
   186         case Qt::Key_A: keysym = XK_a; break; // Must be lower case keysyms
       
   187         case Qt::Key_B: keysym = XK_b; break; // for correct shift handling.
       
   188         case Qt::Key_C: keysym = XK_c; break;
       
   189         case Qt::Key_D: keysym = XK_d; break;
       
   190         case Qt::Key_E: keysym = XK_e; break;
       
   191         case Qt::Key_F: keysym = XK_f; break;
       
   192         case Qt::Key_G: keysym = XK_g; break;
       
   193         case Qt::Key_H: keysym = XK_h; break;
       
   194         case Qt::Key_I: keysym = XK_i; break;
       
   195         case Qt::Key_J: keysym = XK_j; break;
       
   196         case Qt::Key_K: keysym = XK_k; break;
       
   197         case Qt::Key_L: keysym = XK_l; break;
       
   198         case Qt::Key_M: keysym = XK_m; break;
       
   199         case Qt::Key_N: keysym = XK_n; break;
       
   200         case Qt::Key_O: keysym = XK_o; break;
       
   201         case Qt::Key_P: keysym = XK_p; break;
       
   202         case Qt::Key_Q: keysym = XK_q; break;
       
   203         case Qt::Key_R: keysym = XK_r; break;
       
   204         case Qt::Key_S: keysym = XK_s; break;
       
   205         case Qt::Key_T: keysym = XK_t; break;
       
   206         case Qt::Key_U: keysym = XK_u; break;
       
   207         case Qt::Key_V: keysym = XK_v; break;
       
   208         case Qt::Key_W: keysym = XK_w; break;
       
   209         case Qt::Key_X: keysym = XK_x; break;
       
   210         case Qt::Key_Y: keysym = XK_y; break;
       
   211         case Qt::Key_Z: keysym = XK_z; break;
       
   212         case Qt::Key_BracketLeft: keysym = XK_bracketleft; break;
       
   213         case Qt::Key_Backslash: keysym = XK_backslash; break;
       
   214         case Qt::Key_BracketRight: keysym = XK_bracketright; break;
       
   215         case Qt::Key_AsciiCircum: keysym = XK_asciicircum; break;
       
   216         case Qt::Key_Underscore: keysym = XK_underscore; break;
       
   217         case Qt::Key_QuoteLeft: keysym = XK_quoteleft; break;
       
   218         case Qt::Key_BraceLeft: keysym = XK_braceleft; break;
       
   219         case Qt::Key_Bar: keysym = XK_bar; break;
       
   220         case Qt::Key_BraceRight: keysym = XK_braceright; break;
       
   221         case Qt::Key_AsciiTilde: keysym = XK_asciitilde; break;
       
   222 
       
   223         case Qt::Key_nobreakspace: keysym = XK_nobreakspace; break;
       
   224         case Qt::Key_exclamdown: keysym = XK_exclamdown; break;
       
   225         case Qt::Key_cent: keysym = XK_cent; break;
       
   226         case Qt::Key_sterling: keysym = XK_sterling; break;
       
   227         case Qt::Key_currency: keysym = XK_currency; break;
       
   228         case Qt::Key_yen: keysym = XK_yen; break;
       
   229         case Qt::Key_brokenbar: keysym = XK_brokenbar; break;
       
   230         case Qt::Key_section: keysym = XK_section; break;
       
   231         case Qt::Key_diaeresis: keysym = XK_diaeresis; break;
       
   232         case Qt::Key_copyright: keysym = XK_copyright; break;
       
   233         case Qt::Key_ordfeminine: keysym = XK_ordfeminine; break;
       
   234         case Qt::Key_guillemotleft: keysym = XK_guillemotleft; break;
       
   235         case Qt::Key_notsign: keysym = XK_notsign; break;
       
   236         case Qt::Key_hyphen: keysym = XK_hyphen; break;
       
   237         case Qt::Key_registered: keysym = XK_registered; break;
       
   238         case Qt::Key_macron: keysym = XK_macron; break;
       
   239         case Qt::Key_degree: keysym = XK_degree; break;
       
   240         case Qt::Key_plusminus: keysym = XK_plusminus; break;
       
   241         case Qt::Key_twosuperior: keysym = XK_twosuperior; break;
       
   242         case Qt::Key_threesuperior: keysym = XK_threesuperior; break;
       
   243         case Qt::Key_acute: keysym = XK_acute; break;
       
   244         case Qt::Key_mu: keysym = XK_mu; break;
       
   245         case Qt::Key_paragraph: keysym = XK_paragraph; break;
       
   246         case Qt::Key_periodcentered: keysym = XK_periodcentered; break;
       
   247         case Qt::Key_cedilla: keysym = XK_cedilla; break;
       
   248         case Qt::Key_onesuperior: keysym = XK_onesuperior; break;
       
   249         case Qt::Key_masculine: keysym = XK_masculine; break;
       
   250         case Qt::Key_guillemotright: keysym = XK_guillemotright; break;
       
   251         case Qt::Key_onequarter: keysym = XK_onequarter; break;
       
   252         case Qt::Key_onehalf: keysym = XK_onehalf; break;
       
   253         case Qt::Key_threequarters: keysym = XK_threequarters; break;
       
   254         case Qt::Key_questiondown: keysym = XK_questiondown; break;
       
   255         case Qt::Key_Agrave: keysym = XK_agrave; break;	// Lower case keysyms
       
   256         case Qt::Key_Aacute: keysym = XK_aacute; break; // for shift handling.
       
   257         case Qt::Key_Acircumflex: keysym = XK_acircumflex; break;
       
   258         case Qt::Key_Atilde: keysym = XK_atilde; break;
       
   259         case Qt::Key_Adiaeresis: keysym = XK_adiaeresis; break;
       
   260         case Qt::Key_Aring: keysym = XK_aring; break;
       
   261         case Qt::Key_AE: keysym = XK_ae; break;
       
   262         case Qt::Key_Ccedilla: keysym = XK_ccedilla; break;
       
   263         case Qt::Key_Egrave: keysym = XK_egrave; break;
       
   264         case Qt::Key_Eacute: keysym = XK_eacute; break;
       
   265         case Qt::Key_Ecircumflex: keysym = XK_ecircumflex; break;
       
   266         case Qt::Key_Ediaeresis: keysym = XK_ediaeresis; break;
       
   267         case Qt::Key_Igrave: keysym = XK_igrave; break;
       
   268         case Qt::Key_Iacute: keysym = XK_iacute; break;
       
   269         case Qt::Key_Icircumflex: keysym = XK_icircumflex; break;
       
   270         case Qt::Key_Idiaeresis: keysym = XK_idiaeresis; break;
       
   271         case Qt::Key_ETH: keysym = XK_eth; break;
       
   272         case Qt::Key_Ntilde: keysym = XK_ntilde; break;
       
   273         case Qt::Key_Ograve: keysym = XK_ograve; break;
       
   274         case Qt::Key_Oacute: keysym = XK_oacute; break;
       
   275         case Qt::Key_Ocircumflex: keysym = XK_ocircumflex; break;
       
   276         case Qt::Key_Otilde: keysym = XK_otilde; break;
       
   277         case Qt::Key_Odiaeresis: keysym = XK_odiaeresis; break;
       
   278         case Qt::Key_multiply: keysym = XK_multiply; break;
       
   279         case Qt::Key_Ooblique: keysym = XK_ooblique; break;
       
   280         case Qt::Key_Ugrave: keysym = XK_ugrave; break;
       
   281         case Qt::Key_Uacute: keysym = XK_uacute; break;
       
   282         case Qt::Key_Ucircumflex: keysym = XK_ucircumflex; break;
       
   283         case Qt::Key_Udiaeresis: keysym = XK_udiaeresis; break;
       
   284         case Qt::Key_Yacute: keysym = XK_yacute; break;
       
   285         case Qt::Key_THORN: keysym = XK_thorn; break;
       
   286         case Qt::Key_ssharp: keysym = XK_ssharp; break;
       
   287         case Qt::Key_division: keysym = XK_division; break;
       
   288         case Qt::Key_ydiaeresis: keysym = XK_ydiaeresis; break;
       
   289 
       
   290         case Qt::Key_AltGr: keysym = XK_ISO_Level3_Shift; break;
       
   291 	case Qt::Key_Multi_key: keysym = XK_Multi_key; break;
       
   292 	case Qt::Key_Codeinput: keysym = XK_Codeinput; break;
       
   293 	case Qt::Key_SingleCandidate: keysym = XK_SingleCandidate; break;
       
   294 	case Qt::Key_MultipleCandidate: keysym = XK_MultipleCandidate; break;
       
   295 	case Qt::Key_PreviousCandidate: keysym = XK_PreviousCandidate; break;
       
   296 
       
   297 	case Qt::Key_Mode_switch: keysym = XK_Mode_switch; break;
       
   298 
       
   299 	case Qt::Key_Kanji: keysym = XK_Kanji; break;
       
   300 	case Qt::Key_Muhenkan: keysym = XK_Muhenkan; break;
       
   301 	case Qt::Key_Henkan: keysym = XK_Henkan; break;
       
   302 	case Qt::Key_Romaji: keysym = XK_Romaji; break;
       
   303 	case Qt::Key_Hiragana: keysym = XK_Hiragana; break;
       
   304 	case Qt::Key_Katakana: keysym = XK_Katakana; break;
       
   305 	case Qt::Key_Hiragana_Katakana: keysym = XK_Hiragana_Katakana; break;
       
   306 	case Qt::Key_Zenkaku: keysym = XK_Zenkaku; break;
       
   307 	case Qt::Key_Hankaku: keysym = XK_Hankaku; break;
       
   308 	case Qt::Key_Zenkaku_Hankaku: keysym = XK_Zenkaku_Hankaku; break;
       
   309 	case Qt::Key_Touroku: keysym = XK_Touroku; break;
       
   310 	case Qt::Key_Massyo: keysym = XK_Massyo; break;
       
   311 	case Qt::Key_Kana_Lock: keysym = XK_Kana_Lock; break;
       
   312 	case Qt::Key_Kana_Shift: keysym = XK_Kana_Shift; break;
       
   313 	case Qt::Key_Eisu_Shift: keysym = XK_Eisu_Shift; break;
       
   314 	case Qt::Key_Eisu_toggle: keysym = XK_Eisu_toggle; break;
       
   315 
       
   316 	case Qt::Key_Hangul: keysym = XK_Hangul; break;
       
   317 	case Qt::Key_Hangul_Start: keysym = XK_Hangul_Start; break;
       
   318 	case Qt::Key_Hangul_End: keysym = XK_Hangul_End; break;
       
   319 	case Qt::Key_Hangul_Hanja: keysym = XK_Hangul_Hanja; break;
       
   320 	case Qt::Key_Hangul_Jamo: keysym = XK_Hangul_Jamo; break;
       
   321 	case Qt::Key_Hangul_Romaja: keysym = XK_Hangul_Romaja; break;
       
   322 	case Qt::Key_Hangul_Jeonja: keysym = XK_Hangul_Jeonja; break;
       
   323 	case Qt::Key_Hangul_Banja: keysym = XK_Hangul_Banja; break;
       
   324 	case Qt::Key_Hangul_PreHanja: keysym = XK_Hangul_PreHanja; break;
       
   325 	case Qt::Key_Hangul_PostHanja: keysym = XK_Hangul_PostHanja; break;
       
   326 	case Qt::Key_Hangul_Special: keysym = XK_Hangul_Special; break;
       
   327 
       
   328         case Qt::Key_Dead_Grave: keysym = XK_dead_grave; break;
       
   329         case Qt::Key_Dead_Acute: keysym = XK_dead_acute; break;
       
   330         case Qt::Key_Dead_Circumflex: keysym = XK_dead_circumflex; break;
       
   331         case Qt::Key_Dead_Tilde: keysym = XK_dead_tilde; break;
       
   332         case Qt::Key_Dead_Macron: keysym = XK_dead_macron; break;
       
   333         case Qt::Key_Dead_Breve: keysym = XK_dead_breve; break;
       
   334         case Qt::Key_Dead_Abovedot: keysym = XK_dead_abovedot; break;
       
   335         case Qt::Key_Dead_Diaeresis: keysym = XK_dead_diaeresis; break;
       
   336         case Qt::Key_Dead_Abovering: keysym = XK_dead_abovering; break;
       
   337         case Qt::Key_Dead_Doubleacute: keysym = XK_dead_doubleacute; break;
       
   338         case Qt::Key_Dead_Caron: keysym = XK_dead_caron; break;
       
   339         case Qt::Key_Dead_Cedilla: keysym = XK_dead_cedilla; break;
       
   340         case Qt::Key_Dead_Ogonek: keysym = XK_dead_ogonek; break;
       
   341         case Qt::Key_Dead_Iota: keysym = XK_dead_iota; break;
       
   342         case Qt::Key_Dead_Voiced_Sound: keysym = XK_dead_voiced_sound; break;
       
   343         case Qt::Key_Dead_Semivoiced_Sound: keysym = XK_dead_semivoiced_sound; break;
       
   344         case Qt::Key_Dead_Belowdot: keysym = XK_dead_belowdot; break;
       
   345         case Qt::Key_Dead_Hook: keysym = XK_dead_hook; break;
       
   346         case Qt::Key_Dead_Horn: keysym = XK_dead_horn; break;
       
   347 
       
   348         case Qt::Key_Back: keysym = XF86XK_Back; break;
       
   349         case Qt::Key_Forward: keysym = XF86XK_Forward; break;
       
   350         case Qt::Key_Stop: keysym = XF86XK_Stop; break;
       
   351         case Qt::Key_Refresh: keysym = XF86XK_Refresh; break;
       
   352 
       
   353         case Qt::Key_VolumeDown: keysym = XF86XK_AudioLowerVolume; break;
       
   354         case Qt::Key_VolumeMute: keysym = XF86XK_AudioMute; break;
       
   355         case Qt::Key_VolumeUp: keysym = XF86XK_AudioRaiseVolume; break;
       
   356         case Qt::Key_BassBoost: keysym = NoSymbol; break;	// ???
       
   357         case Qt::Key_BassUp: keysym = NoSymbol; break;		// ???
       
   358         case Qt::Key_BassDown: keysym = NoSymbol; break;	// ???
       
   359         case Qt::Key_TrebleUp: keysym = NoSymbol; break;	// ???
       
   360         case Qt::Key_TrebleDown: keysym = NoSymbol; break;	// ???
       
   361 
       
   362         case Qt::Key_MediaPlay: keysym = XF86XK_AudioPlay; break;
       
   363         case Qt::Key_MediaStop: keysym = XF86XK_AudioStop; break;
       
   364         case Qt::Key_MediaPrevious: keysym = XF86XK_AudioPrev; break;
       
   365         case Qt::Key_MediaNext: keysym = XF86XK_AudioNext; break;
       
   366         case Qt::Key_MediaRecord: keysym = XF86XK_AudioRecord; break;
       
   367 
       
   368         case Qt::Key_HomePage: keysym = XF86XK_HomePage; break;
       
   369         case Qt::Key_Favorites: keysym = XF86XK_Favorites; break;
       
   370         case Qt::Key_Search: keysym = XF86XK_Search; break;
       
   371         case Qt::Key_Standby: keysym = XF86XK_Standby; break;
       
   372         case Qt::Key_OpenUrl: keysym = XF86XK_OpenURL; break;
       
   373 
       
   374         case Qt::Key_LaunchMail: keysym = XF86XK_Mail; break;
       
   375         case Qt::Key_LaunchMedia: keysym = XF86XK_AudioMedia; break;
       
   376         case Qt::Key_Launch0: keysym = XF86XK_Launch0; break;
       
   377         case Qt::Key_Launch1: keysym = XF86XK_Launch1; break;
       
   378         case Qt::Key_Launch2: keysym = XF86XK_Launch2; break;
       
   379         case Qt::Key_Launch3: keysym = XF86XK_Launch3; break;
       
   380         case Qt::Key_Launch4: keysym = XF86XK_Launch4; break;
       
   381         case Qt::Key_Launch5: keysym = XF86XK_Launch5; break;
       
   382         case Qt::Key_Launch6: keysym = XF86XK_Launch6; break;
       
   383         case Qt::Key_Launch7: keysym = XF86XK_Launch7; break;
       
   384         case Qt::Key_Launch8: keysym = XF86XK_Launch8; break;
       
   385         case Qt::Key_Launch9: keysym = XF86XK_Launch9; break;
       
   386         case Qt::Key_LaunchA: keysym = XF86XK_LaunchA; break;
       
   387         case Qt::Key_LaunchB: keysym = XF86XK_LaunchB; break;
       
   388         case Qt::Key_LaunchC: keysym = XF86XK_LaunchC; break;
       
   389         case Qt::Key_LaunchD: keysym = XF86XK_LaunchD; break;
       
   390         case Qt::Key_LaunchE: keysym = XF86XK_LaunchE; break;
       
   391         case Qt::Key_LaunchF: keysym = XF86XK_LaunchF; break;
       
   392 
       
   393         case Qt::Key_MediaLast: keysym = NoSymbol; break;   // ???
       
   394 
       
   395         case Qt::Key_Select: keysym = QTOPIAXK_Select; break;
       
   396         case Qt::Key_Yes: keysym = QTOPIAXK_Yes; break;
       
   397         case Qt::Key_No: keysym = QTOPIAXK_No; break;
       
   398 
       
   399         case Qt::Key_Cancel: keysym = QTOPIAXK_Cancel; break;
       
   400         case Qt::Key_Printer: keysym = QTOPIAXK_Printer; break;
       
   401         case Qt::Key_Execute: keysym = QTOPIAXK_Execute; break;
       
   402         case Qt::Key_Sleep: keysym = QTOPIAXK_Sleep; break;
       
   403         case Qt::Key_Play: keysym = QTOPIAXK_Play; break;
       
   404         case Qt::Key_Zoom: keysym = QTOPIAXK_Zoom; break;
       
   405 
       
   406         case Qt::Key_Context1: keysym = QTOPIAXK_Context1; break;
       
   407         case Qt::Key_Context2: keysym = QTOPIAXK_Context2; break;
       
   408         case Qt::Key_Context3: keysym = QTOPIAXK_Context3; break;
       
   409         case Qt::Key_Context4: keysym = QTOPIAXK_Context4; break;
       
   410         case Qt::Key_Call: keysym = QTOPIAXK_Call; break;
       
   411         case Qt::Key_Hangup: keysym = QTOPIAXK_Hangup; break;
       
   412         case Qt::Key_Flip: keysym = QTOPIAXK_Flip; break;
       
   413 
       
   414         case Qt::Key_unknown: keysym = NoSymbol; break;
       
   415     }
       
   416     if (keysym == NoSymbol)
       
   417 	return;
       
   418 
       
   419     // Convert the X keysym into an X keycode.
       
   420     KeyCode keycode = XKeysymToKeycode(dpy, keysym);
       
   421     if (keycode == NoSymbol)
       
   422 	return;
       
   423 
       
   424     // Determine if we need to fake shift keys as well.
       
   425     int index = 0;
       
   426     while (index < 4 && XKeycodeToKeysym(dpy, keycode, index) != keysym)
       
   427 	++index;
       
   428     int extraModifiers = 0;
       
   429     if ((index & 1) != 0)
       
   430 	extraModifiers |= ShiftMask;
       
   431     if ((index & 2) != 0)
       
   432 	extraModifiers |= Mod2Mask;
       
   433     if ((modifiers & LockMask) != 0) {
       
   434 	// If Caps Lock is set, then flip the shift state for alphabetic keys.
       
   435 	if (qtCode >= Qt::Key_A && qtCode <= Qt::Key_Z)
       
   436 	    extraModifiers ^= ShiftMask;
       
   437 	if (qtCode >= Qt::Key_Agrave && qtCode <= Qt::Key_THORN &&
       
   438 	    qtCode != Qt::Key_multiply)
       
   439 	    extraModifiers ^= ShiftMask;
       
   440     }
       
   441 
       
   442     // Adjust modifier keys for the shift states.  This is needed for
       
   443     // things like the * and # phone keys, which need Shift to be pressed
       
   444     // when entering from a keyboard, but don't need Shift from a skin.
       
   445     unsigned long delay = 0;
       
   446     if (extraModifiers != 0) {
       
   447 	if ((extraModifiers & ShiftMask) != 0) {
       
   448 	    if ((modifiers & ShiftMask) == 0)
       
   449 		XTestFakeKeyEvent(dpy, shiftKeycode, true, delay++);
       
   450 	} else {
       
   451 	    if ((modifiers & ShiftMask) != 0)
       
   452 		XTestFakeKeyEvent(dpy, shiftKeycode, false, delay++);
       
   453 	}
       
   454 	if ((extraModifiers & Mod2Mask) != 0) {
       
   455 	    if ((modifiers & Mod2Mask) == 0)
       
   456 		XTestFakeKeyEvent(dpy, modeSwitchKeycode, true, delay++);
       
   457 	} else {
       
   458 	    if ((modifiers & Mod2Mask) != 0)
       
   459 		XTestFakeKeyEvent(dpy, modeSwitchKeycode, false, delay++);
       
   460 	}
       
   461     }
       
   462 
       
   463     // Fake the actual key.
       
   464     XTestFakeKeyEvent(dpy, keycode, (Bool)isPress, delay++);
       
   465 
       
   466     // Adjust the modifiers back.
       
   467     if (extraModifiers != 0) {
       
   468 	if ((extraModifiers & ShiftMask) != 0) {
       
   469 	    if ((modifiers & ShiftMask) == 0)
       
   470 		XTestFakeKeyEvent(dpy, shiftKeycode, false, delay++);
       
   471 	} else {
       
   472 	    if ((modifiers & ShiftMask) != 0)
       
   473 		XTestFakeKeyEvent(dpy, shiftKeycode, true, delay++);
       
   474 	}
       
   475 	if ((extraModifiers & Mod2Mask) != 0) {
       
   476 	    if ((modifiers & Mod2Mask) == 0)
       
   477 		XTestFakeKeyEvent(dpy, modeSwitchKeycode, false, delay++);
       
   478 	} else {
       
   479 	    if ((modifiers & Mod2Mask) != 0)
       
   480 		XTestFakeKeyEvent(dpy, modeSwitchKeycode, true, delay++);
       
   481 	}
       
   482     }
       
   483 
       
   484     // Flush the key events.
       
   485     XFlush(dpy);
       
   486 
       
   487     // Update the modifiers if this was a shift key.
       
   488     if (isPress) {
       
   489 	if (qtCode == Qt::Key_Shift)
       
   490 	    modifiers |= ShiftMask;
       
   491 	if (qtCode == Qt::Key_CapsLock)
       
   492 	    modifiers |= LockMask;
       
   493 	if (qtCode == Qt::Key_Mode_switch)
       
   494 	    modifiers |= Mod2Mask;
       
   495     } else {
       
   496 	if (qtCode == Qt::Key_Shift)
       
   497 	    modifiers &= ~ShiftMask;
       
   498 	if (qtCode == Qt::Key_CapsLock)
       
   499 	    modifiers &= ~LockMask;
       
   500 	if (qtCode == Qt::Key_Mode_switch)
       
   501 	    modifiers &= ~Mod2Mask;
       
   502     }
       
   503 }
       
   504 
       
   505 // Determine if an X11 keycode is currently mapped to one or more keysyms.
       
   506 static bool keycodeInUse(Display *dpy, int keycode)
       
   507 {
       
   508     for (int index = 0; index < 8; ++index) {
       
   509 	if (XKeycodeToKeysym(dpy, keycode, index) != NoSymbol)
       
   510 	    return true;
       
   511     }
       
   512     return false;
       
   513 }
       
   514 
       
   515 // Allocate a keycode for a special keysym.
       
   516 static bool allocateSpecialKeysym
       
   517 	(Display *dpy, int& min_keycode, int& max_keycode, KeySym key)
       
   518 {
       
   519     if (XKeysymToKeycode(dpy, key) != NoSymbol)
       
   520 	return true; // There is already a mapping for this key.  Good!
       
   521     while (max_keycode >= min_keycode) {
       
   522 	if (!keycodeInUse(dpy, max_keycode))
       
   523 	    break;
       
   524 	--max_keycode;
       
   525     }
       
   526     if (max_keycode < min_keycode)
       
   527 	return false;
       
   528     XChangeKeyboardMapping(dpy, max_keycode, 1, &key, 1);
       
   529     --max_keycode;
       
   530     return true;
       
   531 }
       
   532 
       
   533 void X11KeyFaker::connect()
       
   534 {
       
   535     // Open the display.
       
   536     dpy = XOpenDisplay(displayName.toLatin1().data());
       
   537     if (!dpy) {
       
   538 	// Try again in a few milliseconds.  Xnest may not be alive yet.
       
   539 	// Give up after 10 seconds.
       
   540 	if (++retryCount < 50)
       
   541 	    QTimer::singleShot(200, this, SLOT(connect()));
       
   542 	else
       
   543 	    QTimer::singleShot(0, this, SIGNAL(couldNotConnect()));
       
   544 	return;
       
   545     }
       
   546 
       
   547     // Query the XTest extension, which we need to fake the key events.
       
   548     int event_base, error_base, major, minor;
       
   549     if (!XTestQueryExtension
       
   550 	    (dpy, &event_base, &error_base, &major, &minor)) {
       
   551 	XCloseDisplay(dpy);
       
   552 	dpy = 0;
       
   553 	QTimer::singleShot(0, this, SIGNAL(couldNotConnect()));
       
   554 	return;
       
   555     }
       
   556 
       
   557     // Modify the Xnest's keyboard mappings to add Qtopia's special keysyms.
       
   558     int min_keycode = 1, max_keycode = 255;
       
   559     XDisplayKeycodes(dpy, &min_keycode, &max_keycode);
       
   560     bool ok = true;
       
   561     for (KeySym key = QTOPIAXK_Max; key >= QTOPIAXK_Min; --key) {
       
   562 	// This is an extension keysym, not part of the standard X11 set.
       
   563 	if (!allocateSpecialKeysym(dpy, min_keycode, max_keycode, key)) {
       
   564 	    ok = false;
       
   565 	    break;
       
   566 	}
       
   567     }
       
   568     static const KeySym specials[] = {
       
   569 	XF86XK_Back,		    // Qt::Key_Back
       
   570         XF86XK_AudioLowerVolume,    // Qt::Key_VolumeUp
       
   571         XF86XK_AudioRaiseVolume,    // Qt::Key_VolumeDown
       
   572 	XK_F28,			    // Qt::Key_F28
       
   573 	NoSymbol
       
   574     };
       
   575     int index = 0;
       
   576     while (ok && specials[index] != NoSymbol) {
       
   577 	// This is a standard X11/XFree86 keysym that Qtopia uses,
       
   578 	// but it may not be on the user's physical keyboard.
       
   579 	if (!allocateSpecialKeysym
       
   580 		(dpy, min_keycode, max_keycode, specials[index]))
       
   581 	    ok = false;
       
   582 	++index;
       
   583     }
       
   584     if (!ok)
       
   585 	qWarning() << "There are insufficient spare X11 keycodes to allocate the special Qtopia keys";
       
   586 
       
   587     // Change the root cursor to something more reasonable than "X".
       
   588     Cursor cursor = XCreateFontCursor(dpy, XC_left_ptr);
       
   589     XDefineCursor(dpy, RootWindow(dpy, DefaultScreen(dpy)), cursor);
       
   590 
       
   591     // Look up the shift keys.
       
   592     shiftKeycode = XKeysymToKeycode(dpy, XK_Shift_L);
       
   593     if (shiftKeycode == NoSymbol)
       
   594 	shiftKeycode = XKeysymToKeycode(dpy, XK_Shift_R);
       
   595     modeSwitchKeycode = XKeysymToKeycode(dpy, XK_Mode_switch);
       
   596 
       
   597     // Make sure all of the above changes are flushed.
       
   598     XFlush(dpy);
       
   599 
       
   600     // Set up event handling for the display.
       
   601     QSocketNotifier *notifier = new QSocketNotifier
       
   602 	(ConnectionNumber(dpy), QSocketNotifier::Read, this);
       
   603     QObject::connect(notifier, SIGNAL(activated(int)), this, SLOT(readyRead()));
       
   604 
       
   605     // Make sure the file descriptor is not inherited across exec's.
       
   606     fcntl(ConnectionNumber(dpy), F_SETFD, 1);
       
   607 
       
   608     // Notify interested parties that we are now connected to the X display.
       
   609     QTimer::singleShot(0, this, SIGNAL(connected()));
       
   610 }
       
   611 
       
   612 void X11KeyFaker::readyRead()
       
   613 {
       
   614     if (dpy) {
       
   615 	// Read incoming events and discard them.  The only event
       
   616 	// we care about is keyboard mapping changes.  Since we
       
   617 	// don't have any active windows, there's nothing more to do.
       
   618 	while (XEventsQueued(dpy, QueuedAfterFlush)) {
       
   619 	    XEvent event;
       
   620 	    XNextEvent(dpy, &event);
       
   621 	    if (event.xany.type == MappingNotify)
       
   622 		XRefreshKeyboardMapping(&event.xmapping);
       
   623 	}
       
   624     }
       
   625 }
       
   626 
       
   627 QT_END_NAMESPACE