|
1 /**************************************************************************** |
|
2 ** |
|
3 ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). |
|
4 ** All rights reserved. |
|
5 ** Contact: Nokia Corporation (qt-info@nokia.com) |
|
6 ** |
|
7 ** This file is part of the QtGui 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 "qkbd_qws.h" |
|
43 #include "qkbd_qws_p.h" |
|
44 |
|
45 #ifndef QT_NO_QWS_KEYBOARD |
|
46 |
|
47 #include <QFile> |
|
48 #include <QDataStream> |
|
49 #include <QStringList> |
|
50 |
|
51 #include "qwindowsystem_qws.h" |
|
52 #include "qscreen_qws.h" |
|
53 #include "qtimer.h" |
|
54 #include <stdlib.h> |
|
55 |
|
56 //#define QT_DEBUG_KEYMAP |
|
57 |
|
58 |
|
59 QT_BEGIN_NAMESPACE |
|
60 |
|
61 class QWSKbPrivate : public QObject |
|
62 { |
|
63 Q_OBJECT |
|
64 public: |
|
65 QWSKbPrivate(QWSKeyboardHandler *h, const QString &device) |
|
66 : m_handler(h), m_modifiers(0), m_composing(0), m_dead_unicode(0xffff), |
|
67 m_no_zap(false), m_do_compose(false), |
|
68 m_keymap(0), m_keymap_size(0), m_keycompose(0), m_keycompose_size(0) |
|
69 { |
|
70 m_ar_timer = new QTimer(this); |
|
71 m_ar_timer->setSingleShot(true); |
|
72 connect(m_ar_timer, SIGNAL(timeout()), SLOT(autoRepeat())); |
|
73 m_ar_delay = 400; |
|
74 m_ar_period = 80; |
|
75 |
|
76 memset(m_locks, 0, sizeof(m_locks)); |
|
77 |
|
78 QString keymap; |
|
79 QStringList args = device.split(QLatin1Char(':')); |
|
80 foreach (const QString &arg, args) { |
|
81 if (arg.startsWith(QLatin1String("keymap="))) |
|
82 keymap = arg.mid(7); |
|
83 else if (arg == QLatin1String("disable-zap")) |
|
84 m_no_zap = true; |
|
85 else if (arg == QLatin1String("enable-compose")) |
|
86 m_do_compose = true; |
|
87 else if (arg.startsWith(QLatin1String("repeat-delay="))) |
|
88 m_ar_delay = arg.mid(13).toInt(); |
|
89 else if (arg.startsWith(QLatin1String("repeat-rate="))) |
|
90 m_ar_period = arg.mid(12).toInt(); |
|
91 } |
|
92 |
|
93 if (keymap.isEmpty() || !loadKeymap(keymap)) |
|
94 unloadKeymap(); |
|
95 } |
|
96 |
|
97 ~QWSKbPrivate() |
|
98 { |
|
99 unloadKeymap(); |
|
100 } |
|
101 |
|
102 void beginAutoRepeat(int uni, int code, Qt::KeyboardModifiers mod) |
|
103 { |
|
104 m_ar_unicode = uni; |
|
105 m_ar_keycode = code; |
|
106 m_ar_modifier = mod; |
|
107 m_ar_timer->start(m_ar_delay); |
|
108 } |
|
109 |
|
110 void endAutoRepeat() |
|
111 { |
|
112 m_ar_timer->stop(); |
|
113 } |
|
114 |
|
115 static Qt::KeyboardModifiers toQtModifiers(quint8 mod) |
|
116 { |
|
117 Qt::KeyboardModifiers qtmod = Qt::NoModifier; |
|
118 |
|
119 if (mod & (QWSKeyboard::ModShift | QWSKeyboard::ModShiftL | QWSKeyboard::ModShiftR)) |
|
120 qtmod |= Qt::ShiftModifier; |
|
121 if (mod & (QWSKeyboard::ModControl | QWSKeyboard::ModCtrlL | QWSKeyboard::ModCtrlR)) |
|
122 qtmod |= Qt::ControlModifier; |
|
123 if (mod & QWSKeyboard::ModAlt) |
|
124 qtmod |= Qt::AltModifier; |
|
125 |
|
126 return qtmod; |
|
127 } |
|
128 |
|
129 void unloadKeymap(); |
|
130 bool loadKeymap(const QString &file); |
|
131 |
|
132 private slots: |
|
133 void autoRepeat() |
|
134 { |
|
135 m_handler->processKeyEvent(m_ar_unicode, m_ar_keycode, m_ar_modifier, false, true); |
|
136 m_handler->processKeyEvent(m_ar_unicode, m_ar_keycode, m_ar_modifier, true, true); |
|
137 m_ar_timer->start(m_ar_period); |
|
138 } |
|
139 |
|
140 private: |
|
141 QWSKeyboardHandler *m_handler; |
|
142 |
|
143 // auto repeat simulation |
|
144 int m_ar_unicode; |
|
145 int m_ar_keycode; |
|
146 Qt::KeyboardModifiers m_ar_modifier; |
|
147 int m_ar_delay; |
|
148 int m_ar_period; |
|
149 QTimer *m_ar_timer; |
|
150 |
|
151 // keymap handling |
|
152 quint8 m_modifiers; |
|
153 quint8 m_locks[3]; |
|
154 int m_composing; |
|
155 quint16 m_dead_unicode; |
|
156 |
|
157 bool m_no_zap; |
|
158 bool m_do_compose; |
|
159 |
|
160 const QWSKeyboard::Mapping *m_keymap; |
|
161 int m_keymap_size; |
|
162 const QWSKeyboard::Composing *m_keycompose; |
|
163 int m_keycompose_size; |
|
164 |
|
165 static const QWSKeyboard::Mapping s_keymap_default[]; |
|
166 static const QWSKeyboard::Composing s_keycompose_default[]; |
|
167 |
|
168 friend class QWSKeyboardHandler; |
|
169 }; |
|
170 |
|
171 // simple builtin US keymap |
|
172 #include "qkbd_defaultmap_qws_p.h" |
|
173 |
|
174 // the unloadKeymap() function needs to be AFTER the defaultmap include, |
|
175 // since the sizeof(s_keymap_default) wouldn't work otherwise. |
|
176 |
|
177 void QWSKbPrivate::unloadKeymap() |
|
178 { |
|
179 if (m_keymap && m_keymap != s_keymap_default) |
|
180 delete [] m_keymap; |
|
181 if (m_keycompose && m_keycompose != s_keycompose_default) |
|
182 delete [] m_keycompose; |
|
183 |
|
184 m_keymap = s_keymap_default; |
|
185 m_keymap_size = sizeof(s_keymap_default) / sizeof(s_keymap_default[0]); |
|
186 m_keycompose = s_keycompose_default; |
|
187 m_keycompose_size = sizeof(s_keycompose_default) / sizeof(s_keycompose_default[0]); |
|
188 |
|
189 // reset state, so we could switch keymaps at runtime |
|
190 m_modifiers = 0; |
|
191 memset(m_locks, 0, sizeof(m_locks)); |
|
192 m_composing = 0; |
|
193 m_dead_unicode = 0xffff; |
|
194 } |
|
195 |
|
196 bool QWSKbPrivate::loadKeymap(const QString &file) |
|
197 { |
|
198 QFile f(file); |
|
199 |
|
200 if (!f.open(QIODevice::ReadOnly)) { |
|
201 qWarning("Could not open keymap file '%s'", qPrintable(file)); |
|
202 return false; |
|
203 } |
|
204 |
|
205 // .qmap files have a very simple structure: |
|
206 // quint32 magic (QWSKeyboard::FileMagic) |
|
207 // quint32 version (1) |
|
208 // quint32 keymap_size (# of struct QWSKeyboard::Mappings) |
|
209 // quint32 keycompose_size (# of struct QWSKeyboard::Composings) |
|
210 // all QWSKeyboard::Mappings via QDataStream::operator(<<|>>) |
|
211 // all QWSKeyboard::Composings via QDataStream::operator(<<|>>) |
|
212 |
|
213 quint32 qmap_magic, qmap_version, qmap_keymap_size, qmap_keycompose_size; |
|
214 |
|
215 QDataStream ds(&f); |
|
216 |
|
217 ds >> qmap_magic >> qmap_version >> qmap_keymap_size >> qmap_keycompose_size; |
|
218 |
|
219 if (ds.status() != QDataStream::Ok || qmap_magic != QWSKeyboard::FileMagic || qmap_version != 1 || qmap_keymap_size == 0) { |
|
220 qWarning("'%s' is ot a valid.qmap keymap file.", qPrintable(file)); |
|
221 return false; |
|
222 } |
|
223 |
|
224 QWSKeyboard::Mapping *qmap_keymap = new QWSKeyboard::Mapping[qmap_keymap_size]; |
|
225 QWSKeyboard::Composing *qmap_keycompose = qmap_keycompose_size ? new QWSKeyboard::Composing[qmap_keycompose_size] : 0; |
|
226 |
|
227 for (quint32 i = 0; i < qmap_keymap_size; ++i) |
|
228 ds >> qmap_keymap[i]; |
|
229 for (quint32 i = 0; i < qmap_keycompose_size; ++i) |
|
230 ds >> qmap_keycompose[i]; |
|
231 |
|
232 if (ds.status() != QDataStream::Ok) { |
|
233 delete [] qmap_keymap; |
|
234 delete [] qmap_keycompose; |
|
235 |
|
236 qWarning("Keymap file '%s' can not be loaded.", qPrintable(file)); |
|
237 return false; |
|
238 } |
|
239 |
|
240 // unload currently active and clear state |
|
241 unloadKeymap(); |
|
242 |
|
243 m_keymap = qmap_keymap; |
|
244 m_keymap_size = qmap_keymap_size; |
|
245 m_keycompose = qmap_keycompose; |
|
246 m_keycompose_size = qmap_keycompose_size; |
|
247 |
|
248 m_do_compose = true; |
|
249 |
|
250 return true; |
|
251 } |
|
252 |
|
253 |
|
254 /*! |
|
255 \class QWSKeyboardHandler |
|
256 \ingroup qws |
|
257 |
|
258 \brief The QWSKeyboardHandler class is a base class for keyboard |
|
259 drivers in Qt for Embedded Linux. |
|
260 |
|
261 Note that this class is only available in \l{Qt for Embedded Linux}. |
|
262 |
|
263 \l{Qt for Embedded Linux} provides ready-made drivers for several keyboard |
|
264 protocols, see the \l{Qt for Embedded Linux Character Input}{character |
|
265 input} documentation for details. Custom keyboard drivers can be |
|
266 implemented by subclassing the QWSKeyboardHandler class and |
|
267 creating a keyboard driver plugin (derived from |
|
268 QKbdDriverPlugin). The default implementation of the |
|
269 QKbdDriverFactory class will automatically detect the plugin, and |
|
270 load the driver into the server application at run-time using Qt's |
|
271 \l{How to Create Qt Plugins}{plugin system}. |
|
272 |
|
273 The keyboard driver receives keyboard events from the system |
|
274 device and encapsulates each event with an instance of the |
|
275 QWSEvent class which it then passes to the server application (the |
|
276 server is responsible for propagating the event to the appropriate |
|
277 client). To receive keyboard events, a QWSKeyboardHandler object |
|
278 will usually create a QSocketNotifier object for the given |
|
279 device. The QSocketNotifier class provides support for monitoring |
|
280 activity on a file descriptor. When the socket notifier receives |
|
281 data, it will call the keyboard driver's processKeyEvent() |
|
282 function to send the event to the \l{Qt for Embedded Linux} server |
|
283 application for relaying to clients. |
|
284 |
|
285 |
|
286 QWSKeyboardHandler also provides functions to control |
|
287 auto-repetion of key sequences, beginAutoRepeat() and |
|
288 endAutoRepeat(), and the transformDirKey() function enabling |
|
289 transformation of arrow keys according to the display orientation. |
|
290 |
|
291 \sa QKbdDriverPlugin, QKbdDriverFactory, {Qt for Embedded Linux Character Input} |
|
292 */ |
|
293 |
|
294 |
|
295 /*! |
|
296 Constructs a keyboard driver. The \a device argument is passed by the |
|
297 QWS_KEYBOARD environment variable. |
|
298 |
|
299 Call the QWSServer::setKeyboardHandler() function to make the |
|
300 newly created keyboard driver, the primary driver. Note that the |
|
301 primary driver is controlled by the system, i.e., the system will |
|
302 delete it upon exit. |
|
303 */ |
|
304 QWSKeyboardHandler::QWSKeyboardHandler(const QString &device) |
|
305 { |
|
306 d = new QWSKbPrivate(this, device); |
|
307 } |
|
308 |
|
309 /*! |
|
310 \overload |
|
311 */ |
|
312 QWSKeyboardHandler::QWSKeyboardHandler() |
|
313 { |
|
314 d = new QWSKbPrivate(this, QString()); |
|
315 } |
|
316 |
|
317 |
|
318 |
|
319 /*! |
|
320 Destroys this keyboard driver. |
|
321 |
|
322 Do not call this function if this driver is the primary keyboard |
|
323 handler, i.e., if QWSServer::setKeyboardHandler() function has |
|
324 been called passing this driver as argument. The primary keyboard |
|
325 driver is deleted by the system. |
|
326 */ |
|
327 QWSKeyboardHandler::~QWSKeyboardHandler() |
|
328 { |
|
329 delete d; |
|
330 } |
|
331 |
|
332 |
|
333 /*! |
|
334 Sends a key event to the \l{Qt for Embedded Linux} server application. |
|
335 |
|
336 The key event is identified by its \a unicode value and the \a |
|
337 keycode, \a modifiers, \a isPress and \a autoRepeat parameters. |
|
338 |
|
339 The \a keycode parameter is the Qt keycode value as defined by the |
|
340 Qt::Key enum. The \a modifiers is an OR combination of |
|
341 Qt::KeyboardModifier values, indicating whether \gui |
|
342 Shift/Alt/Ctrl keys are pressed. The \a isPress parameter is true |
|
343 if the event is a key press event and \a autoRepeat is true if the |
|
344 event is caused by an auto-repeat mechanism and not an actual key |
|
345 press. |
|
346 |
|
347 Note that this function does not handle key mapping. Please use |
|
348 processKeycode() if you need that functionality. |
|
349 |
|
350 \sa processKeycode(), beginAutoRepeat(), endAutoRepeat(), transformDirKey() |
|
351 */ |
|
352 void QWSKeyboardHandler::processKeyEvent(int unicode, int keycode, Qt::KeyboardModifiers modifiers, |
|
353 bool isPress, bool autoRepeat) |
|
354 { |
|
355 qwsServer->processKeyEvent(unicode, keycode, modifiers, isPress, autoRepeat); |
|
356 } |
|
357 |
|
358 /*! |
|
359 \fn int QWSKeyboardHandler::transformDirKey(int keycode) |
|
360 |
|
361 Transforms the arrow key specified by the given \a keycode, to the |
|
362 orientation of the display and returns the transformed keycode. |
|
363 |
|
364 The \a keycode is a Qt::Key value. The values identifying arrow |
|
365 keys are: |
|
366 |
|
367 \list |
|
368 \o Qt::Key_Left |
|
369 \o Qt::Key_Up |
|
370 \o Qt::Key_Right |
|
371 \o Qt::Key_Down |
|
372 \endlist |
|
373 |
|
374 \sa processKeyEvent() |
|
375 */ |
|
376 int QWSKeyboardHandler::transformDirKey(int key) |
|
377 { |
|
378 static int dir_keyrot = -1; |
|
379 if (dir_keyrot < 0) { |
|
380 // get the rotation |
|
381 switch (qgetenv("QWS_CURSOR_ROTATION").toInt()) { |
|
382 case 90: dir_keyrot = 1; break; |
|
383 case 180: dir_keyrot = 2; break; |
|
384 case 270: dir_keyrot = 3; break; |
|
385 default: dir_keyrot = 0; break; |
|
386 } |
|
387 } |
|
388 int xf = qt_screen->transformOrientation() + dir_keyrot; |
|
389 return (key-Qt::Key_Left+xf)%4+Qt::Key_Left; |
|
390 } |
|
391 |
|
392 /*! |
|
393 \fn void QWSKeyboardHandler::beginAutoRepeat(int unicode, int keycode, Qt::KeyboardModifiers modifier) |
|
394 |
|
395 Begins auto-repeating the specified key press; after a short delay |
|
396 the key press is sent periodically until the endAutoRepeat() |
|
397 function is called. |
|
398 |
|
399 The key press is specified by its \a unicode, \a keycode and \a |
|
400 modifier state. |
|
401 |
|
402 \sa endAutoRepeat(), processKeyEvent() |
|
403 */ |
|
404 void QWSKeyboardHandler::beginAutoRepeat(int uni, int code, Qt::KeyboardModifiers mod) |
|
405 { |
|
406 d->beginAutoRepeat(uni, code, mod); |
|
407 } |
|
408 |
|
409 /*! |
|
410 Stops auto-repeating a key press. |
|
411 |
|
412 \sa beginAutoRepeat(), processKeyEvent() |
|
413 */ |
|
414 void QWSKeyboardHandler::endAutoRepeat() |
|
415 { |
|
416 d->endAutoRepeat(); |
|
417 } |
|
418 |
|
419 /*! |
|
420 \enum QWSKeyboardHandler::KeycodeAction |
|
421 |
|
422 This enum describes the various special actions that actual |
|
423 QWSKeyboardHandler implementations have to take care of. |
|
424 |
|
425 \value None No further action required. |
|
426 |
|
427 \value CapsLockOn Set the state of the Caps lock LED to on. |
|
428 \value CapsLockOff Set the state of the Caps lock LED to off. |
|
429 \value NumLockOn Set the state of the Num lock LED to on. |
|
430 \value NumLockOff Set the state of the Num lock LED to off. |
|
431 \value ScrollLockOn Set the state of the Scroll lock LED to on. |
|
432 \value ScrollLockOff Set the state of the Scroll lock LED to off. |
|
433 |
|
434 \value PreviousConsole Switch to the previous virtual console (by |
|
435 default Ctrl+Alt+Left on Linux). |
|
436 \value NextConsole Switch to the next virtual console (by default |
|
437 Ctrl+Alt+Right on Linux). |
|
438 \value SwitchConsoleFirst Switch to the first virtual console (0). |
|
439 \value SwitchConsoleLast Switch to the last virtual console (255). |
|
440 \value SwitchConsoleMask If the KeyAction value is between SwitchConsoleFirst |
|
441 and SwitchConsoleLast, you can use this mask to get |
|
442 the specific virtual console number to switch to. |
|
443 |
|
444 \value Reboot Reboot the machine - this is ignored in both the TTY and |
|
445 LinuxInput handlers though (by default Ctrl+Alt+Del on Linux). |
|
446 |
|
447 \sa processKeycode() |
|
448 */ |
|
449 |
|
450 /*! |
|
451 \fn QWSKeyboardHandler::KeycodeAction QWSKeyboardHandler::processKeycode(quint16 keycode, bool isPress, bool autoRepeat) |
|
452 |
|
453 Maps \a keycode according to a keymap and sends that key event to the |
|
454 \l{Qt for Embedded Linux} server application. |
|
455 |
|
456 Please see the \l{Qt for Embedded Linux Character Input} and the \l |
|
457 {kmap2qmap} documentations for a description on how to create and use |
|
458 keymap files. |
|
459 |
|
460 The key event is identified by its \a keycode value and the \a isPress |
|
461 and \a autoRepeat parameters. |
|
462 |
|
463 The \a keycode parameter is \bold NOT the Qt keycode value as defined by |
|
464 the Qt::Key enum. This functions expects a standard Linux 16 bit kernel |
|
465 keycode as it is used in the Linux Input Event sub-system. This |
|
466 \a keycode is transformed to a Qt::Key code by using either a |
|
467 compiled-in US keyboard layout or by dynamically loading a keymap at |
|
468 startup which can be specified via the QWS_KEYBOARD environment |
|
469 variable. |
|
470 |
|
471 The \a isPress parameter is true if the event is a key press event and |
|
472 \a autoRepeat is true if the event is caused by an auto-repeat mechanism |
|
473 and not an actual key press. |
|
474 |
|
475 The return value indicates if the actual QWSKeyboardHandler |
|
476 implementation needs to take care of a special action, like console |
|
477 switching or LED handling. |
|
478 |
|
479 If standard Linux console keymaps are used, \a keycode must be one of the |
|
480 standardized values defined in \c /usr/include/linux/input.h |
|
481 |
|
482 \sa processKeyEvent(), KeycodeAction |
|
483 */ |
|
484 |
|
485 QWSKeyboardHandler::KeycodeAction QWSKeyboardHandler::processKeycode(quint16 keycode, bool pressed, bool autorepeat) |
|
486 { |
|
487 KeycodeAction result = None; |
|
488 bool first_press = pressed && !autorepeat; |
|
489 |
|
490 const QWSKeyboard::Mapping *map_plain = 0; |
|
491 const QWSKeyboard::Mapping *map_withmod = 0; |
|
492 |
|
493 // get a specific and plain mapping for the keycode and the current modifiers |
|
494 for (int i = 0; i < d->m_keymap_size && !(map_plain && map_withmod); ++i) { |
|
495 const QWSKeyboard::Mapping *m = d->m_keymap + i; |
|
496 if (m->keycode == keycode) { |
|
497 if (m->modifiers == 0) |
|
498 map_plain = m; |
|
499 |
|
500 quint8 testmods = d->m_modifiers; |
|
501 if (d->m_locks[0] /*CapsLock*/ && (m->flags & QWSKeyboard::IsLetter)) |
|
502 testmods ^= QWSKeyboard::ModShift; |
|
503 if (m->modifiers == testmods) |
|
504 map_withmod = m; |
|
505 } |
|
506 } |
|
507 |
|
508 #ifdef QT_DEBUG_KEYMAP |
|
509 qWarning("Processing key event: keycode=%3d, modifiers=%02x pressed=%d, autorepeat=%d | plain=%d, withmod=%d, size=%d", \ |
|
510 keycode, d->m_modifiers, pressed ? 1 : 0, autorepeat ? 1 : 0, \ |
|
511 map_plain ? map_plain - d->m_keymap : -1, \ |
|
512 map_withmod ? map_withmod - d->m_keymap : -1, \ |
|
513 d->m_keymap_size); |
|
514 #endif |
|
515 |
|
516 const QWSKeyboard::Mapping *it = map_withmod ? map_withmod : map_plain; |
|
517 |
|
518 if (!it) { |
|
519 #ifdef QT_DEBUG_KEYMAP |
|
520 // we couldn't even find a plain mapping |
|
521 qWarning("Could not find a suitable mapping for keycode: %3d, modifiers: %02x", keycode, d->m_modifiers); |
|
522 #endif |
|
523 return result; |
|
524 } |
|
525 |
|
526 bool skip = false; |
|
527 quint16 unicode = it->unicode; |
|
528 quint32 qtcode = it->qtcode; |
|
529 |
|
530 if ((it->flags & QWSKeyboard::IsModifier) && it->special) { |
|
531 // this is a modifier, i.e. Shift, Alt, ... |
|
532 if (pressed) |
|
533 d->m_modifiers |= quint8(it->special); |
|
534 else |
|
535 d->m_modifiers &= ~quint8(it->special); |
|
536 } else if (qtcode >= Qt::Key_CapsLock && qtcode <= Qt::Key_ScrollLock) { |
|
537 // (Caps|Num|Scroll)Lock |
|
538 if (first_press) { |
|
539 quint8 &lock = d->m_locks[qtcode - Qt::Key_CapsLock]; |
|
540 lock ^= 1; |
|
541 |
|
542 switch (qtcode) { |
|
543 case Qt::Key_CapsLock : result = lock ? CapsLockOn : CapsLockOff; break; |
|
544 case Qt::Key_NumLock : result = lock ? NumLockOn : NumLockOff; break; |
|
545 case Qt::Key_ScrollLock: result = lock ? ScrollLockOn : ScrollLockOff; break; |
|
546 default : break; |
|
547 } |
|
548 } |
|
549 } else if ((it->flags & QWSKeyboard::IsSystem) && it->special && first_press) { |
|
550 switch (it->special) { |
|
551 case QWSKeyboard::SystemReboot: |
|
552 result = Reboot; |
|
553 break; |
|
554 |
|
555 case QWSKeyboard::SystemZap: |
|
556 if (!d->m_no_zap) |
|
557 qApp->quit(); |
|
558 break; |
|
559 |
|
560 case QWSKeyboard::SystemConsolePrevious: |
|
561 result = PreviousConsole; |
|
562 break; |
|
563 |
|
564 case QWSKeyboard::SystemConsoleNext: |
|
565 result = NextConsole; |
|
566 break; |
|
567 |
|
568 default: |
|
569 if (it->special >= QWSKeyboard::SystemConsoleFirst && |
|
570 it->special <= QWSKeyboard::SystemConsoleLast) { |
|
571 result = KeycodeAction(SwitchConsoleFirst + ((it->special & QWSKeyboard::SystemConsoleMask) & SwitchConsoleMask)); |
|
572 } |
|
573 break; |
|
574 } |
|
575 |
|
576 skip = true; // no need to tell QWS about it |
|
577 } else if ((qtcode == Qt::Key_Multi_key) && d->m_do_compose) { |
|
578 // the Compose key was pressed |
|
579 if (first_press) |
|
580 d->m_composing = 2; |
|
581 skip = true; |
|
582 } else if ((it->flags & QWSKeyboard::IsDead) && d->m_do_compose) { |
|
583 // a Dead key was pressed |
|
584 if (first_press && d->m_composing == 1 && d->m_dead_unicode == unicode) { // twice |
|
585 d->m_composing = 0; |
|
586 qtcode = Qt::Key_unknown; // otherwise it would be Qt::Key_Dead... |
|
587 } else if (first_press && unicode != 0xffff) { |
|
588 d->m_dead_unicode = unicode; |
|
589 d->m_composing = 1; |
|
590 skip = true; |
|
591 } else { |
|
592 skip = true; |
|
593 } |
|
594 } |
|
595 |
|
596 if (!skip) { |
|
597 // a normal key was pressed |
|
598 const int modmask = Qt::ShiftModifier | Qt::ControlModifier | Qt::AltModifier | Qt::MetaModifier | Qt::KeypadModifier; |
|
599 |
|
600 // we couldn't find a specific mapping for the current modifiers, |
|
601 // or that mapping didn't have special modifiers: |
|
602 // so just report the plain mapping with additional modifiers. |
|
603 if ((it == map_plain && it != map_withmod) || |
|
604 (map_withmod && !(map_withmod->qtcode & modmask))) { |
|
605 qtcode |= QWSKbPrivate::toQtModifiers(d->m_modifiers); |
|
606 } |
|
607 |
|
608 if (d->m_composing == 2 && first_press && !(it->flags & QWSKeyboard::IsModifier)) { |
|
609 // the last key press was the Compose key |
|
610 if (unicode != 0xffff) { |
|
611 int idx = 0; |
|
612 // check if this code is in the compose table at all |
|
613 for ( ; idx < d->m_keycompose_size; ++idx) { |
|
614 if (d->m_keycompose[idx].first == unicode) |
|
615 break; |
|
616 } |
|
617 if (idx < d->m_keycompose_size) { |
|
618 // found it -> simulate a Dead key press |
|
619 d->m_dead_unicode = unicode; |
|
620 unicode = 0xffff; |
|
621 d->m_composing = 1; |
|
622 skip = true; |
|
623 } else { |
|
624 d->m_composing = 0; |
|
625 } |
|
626 } else { |
|
627 d->m_composing = 0; |
|
628 } |
|
629 } else if (d->m_composing == 1 && first_press && !(it->flags & QWSKeyboard::IsModifier)) { |
|
630 // the last key press was a Dead key |
|
631 bool valid = false; |
|
632 if (unicode != 0xffff) { |
|
633 int idx = 0; |
|
634 // check if this code is in the compose table at all |
|
635 for ( ; idx < d->m_keycompose_size; ++idx) { |
|
636 if (d->m_keycompose[idx].first == d->m_dead_unicode && d->m_keycompose[idx].second == unicode) |
|
637 break; |
|
638 } |
|
639 if (idx < d->m_keycompose_size) { |
|
640 quint16 composed = d->m_keycompose[idx].result; |
|
641 if (composed != 0xffff) { |
|
642 unicode = composed; |
|
643 qtcode = Qt::Key_unknown; |
|
644 valid = true; |
|
645 } |
|
646 } |
|
647 } |
|
648 if (!valid) { |
|
649 unicode = d->m_dead_unicode; |
|
650 qtcode = Qt::Key_unknown; |
|
651 } |
|
652 d->m_composing = 0; |
|
653 } |
|
654 |
|
655 if (!skip) { |
|
656 #ifdef QT_DEBUG_KEYMAP |
|
657 qWarning("Processing: uni=%04x, qt=%08x, qtmod=%08x", unicode, qtcode & ~modmask, (qtcode & modmask)); |
|
658 #endif |
|
659 |
|
660 // send the result to the QWS server |
|
661 processKeyEvent(unicode, qtcode & ~modmask, Qt::KeyboardModifiers(qtcode & modmask), pressed, autorepeat); |
|
662 } |
|
663 } |
|
664 return result; |
|
665 } |
|
666 |
|
667 QT_END_NAMESPACE |
|
668 |
|
669 #include "qkbd_qws.moc" |
|
670 |
|
671 #endif // QT_NO_QWS_KEYBOARD |