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 |
|
---|
54 | QT_BEGIN_NAMESPACE
|
---|
55 |
|
---|
56 | X11KeyFaker::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 |
|
---|
68 | X11KeyFaker::~X11KeyFaker()
|
---|
69 | {
|
---|
70 | if (dpy)
|
---|
71 | XCloseDisplay(dpy);
|
---|
72 | }
|
---|
73 |
|
---|
74 | void 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.
|
---|
505 | static 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.
|
---|
515 | static 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 |
|
---|
532 | void 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 |
|
---|
611 | void 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 |
|
---|
626 | QT_END_NAMESPACE
|
---|