source: trunk/tools/qvfb/x11keyfaker.cpp@ 280

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

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

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