Warning: That file was not part of the compilation database. It may have many parsing errors.
1 | /**************************************************************************** |
---|---|
2 | ** |
3 | ** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies). |
4 | ** Contact: http://www.qt-project.org/legal |
5 | ** |
6 | ** This file is part of the tools module of the Qt Toolkit. |
7 | ** |
8 | ** $QT_BEGIN_LICENSE:LGPL$ |
9 | ** Commercial License Usage |
10 | ** Licensees holding valid commercial Qt licenses may use this file in |
11 | ** accordance with the commercial license agreement provided with the |
12 | ** Software or, alternatively, in accordance with the terms contained in |
13 | ** a written agreement between you and Digia. For licensing terms and |
14 | ** conditions see http://qt.digia.com/licensing. For further information |
15 | ** use the contact form at http://qt.digia.com/contact-us. |
16 | ** |
17 | ** GNU Lesser General Public License Usage |
18 | ** Alternatively, this file may be used under the terms of the GNU Lesser |
19 | ** General Public License version 2.1 as published by the Free Software |
20 | ** Foundation and appearing in the file LICENSE.LGPL included in the |
21 | ** packaging of this file. Please review the following information to |
22 | ** ensure the GNU Lesser General Public License version 2.1 requirements |
23 | ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. |
24 | ** |
25 | ** In addition, as a special exception, Digia gives you certain additional |
26 | ** rights. These rights are described in the Digia Qt LGPL Exception |
27 | ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. |
28 | ** |
29 | ** GNU General Public License Usage |
30 | ** Alternatively, this file may be used under the terms of the GNU |
31 | ** General Public License version 3.0 as published by the Free Software |
32 | ** Foundation and appearing in the file LICENSE.GPL included in the |
33 | ** packaging of this file. Please review the following information to |
34 | ** ensure the GNU General Public License version 3.0 requirements will be |
35 | ** met: http://www.gnu.org/copyleft/gpl.html. |
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 |
628 |
Warning: That file was not part of the compilation database. It may have many parsing errors.