author | Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com> |
Fri, 19 Feb 2010 23:40:16 +0200 | |
branch | RCL_3 |
changeset 4 | 3b1da2848fc7 |
parent 0 | 1918ee327afb |
permissions | -rw-r--r-- |
0 | 1 |
/**************************************************************************** |
2 |
** |
|
4
3b1da2848fc7
Revision: 201003
Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
parents:
0
diff
changeset
|
3 |
** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). |
0 | 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 |