1 | /****************************************************************************
|
---|
2 | **
|
---|
3 | ** Copyright (C) 2011 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 | ** Commercial Usage
|
---|
11 | ** Licensees holding valid Qt Commercial licenses may use this file in
|
---|
12 | ** accordance with the Qt Commercial License Agreement provided with the
|
---|
13 | ** Software or, alternatively, in accordance with the terms contained in
|
---|
14 | ** a written agreement between you and Nokia.
|
---|
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 | ** GNU General Public License Usage
|
---|
29 | ** Alternatively, this file may be used under the terms of the GNU
|
---|
30 | ** General Public License version 3.0 as published by the Free Software
|
---|
31 | ** Foundation and appearing in the file LICENSE.GPL included in the
|
---|
32 | ** packaging of this file. Please review the following information to
|
---|
33 | ** ensure the GNU General Public License version 3.0 requirements will be
|
---|
34 | ** met: http://www.gnu.org/copyleft/gpl.html.
|
---|
35 | **
|
---|
36 | ** If you have questions regarding the use of this file, please contact
|
---|
37 | ** Nokia at qt-info@nokia.com.
|
---|
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 | \since 4.6
|
---|
454 |
|
---|
455 | Maps \a keycode according to a keymap and sends that key event to the
|
---|
456 | \l{Qt for Embedded Linux} server application.
|
---|
457 |
|
---|
458 | Please see the \l{Qt for Embedded Linux Character Input} and the \l
|
---|
459 | {kmap2qmap} documentations for a description on how to create and use
|
---|
460 | keymap files.
|
---|
461 |
|
---|
462 | The key event is identified by its \a keycode value and the \a isPress
|
---|
463 | and \a autoRepeat parameters.
|
---|
464 |
|
---|
465 | The \a keycode parameter is \bold NOT the Qt keycode value as defined by
|
---|
466 | the Qt::Key enum. This functions expects a standard Linux 16 bit kernel
|
---|
467 | keycode as it is used in the Linux Input Event sub-system. This
|
---|
468 | \a keycode is transformed to a Qt::Key code by using either a
|
---|
469 | compiled-in US keyboard layout or by dynamically loading a keymap at
|
---|
470 | startup which can be specified via the QWS_KEYBOARD environment
|
---|
471 | variable.
|
---|
472 |
|
---|
473 | The \a isPress parameter is true if the event is a key press event and
|
---|
474 | \a autoRepeat is true if the event is caused by an auto-repeat mechanism
|
---|
475 | and not an actual key press.
|
---|
476 |
|
---|
477 | The return value indicates if the actual QWSKeyboardHandler
|
---|
478 | implementation needs to take care of a special action, like console
|
---|
479 | switching or LED handling.
|
---|
480 |
|
---|
481 | If standard Linux console keymaps are used, \a keycode must be one of the
|
---|
482 | standardized values defined in \c /usr/include/linux/input.h
|
---|
483 |
|
---|
484 | \sa processKeyEvent(), KeycodeAction
|
---|
485 | */
|
---|
486 |
|
---|
487 | QWSKeyboardHandler::KeycodeAction QWSKeyboardHandler::processKeycode(quint16 keycode, bool pressed, bool autorepeat)
|
---|
488 | {
|
---|
489 | KeycodeAction result = None;
|
---|
490 | bool first_press = pressed && !autorepeat;
|
---|
491 |
|
---|
492 | const QWSKeyboard::Mapping *map_plain = 0;
|
---|
493 | const QWSKeyboard::Mapping *map_withmod = 0;
|
---|
494 |
|
---|
495 | // get a specific and plain mapping for the keycode and the current modifiers
|
---|
496 | for (int i = 0; i < d->m_keymap_size && !(map_plain && map_withmod); ++i) {
|
---|
497 | const QWSKeyboard::Mapping *m = d->m_keymap + i;
|
---|
498 | if (m->keycode == keycode) {
|
---|
499 | if (m->modifiers == 0)
|
---|
500 | map_plain = m;
|
---|
501 |
|
---|
502 | quint8 testmods = d->m_modifiers;
|
---|
503 | if (d->m_locks[0] /*CapsLock*/ && (m->flags & QWSKeyboard::IsLetter))
|
---|
504 | testmods ^= QWSKeyboard::ModShift;
|
---|
505 | if (m->modifiers == testmods)
|
---|
506 | map_withmod = m;
|
---|
507 | }
|
---|
508 | }
|
---|
509 |
|
---|
510 | #ifdef QT_DEBUG_KEYMAP
|
---|
511 | qWarning("Processing key event: keycode=%3d, modifiers=%02x pressed=%d, autorepeat=%d | plain=%d, withmod=%d, size=%d", \
|
---|
512 | keycode, d->m_modifiers, pressed ? 1 : 0, autorepeat ? 1 : 0, \
|
---|
513 | map_plain ? map_plain - d->m_keymap : -1, \
|
---|
514 | map_withmod ? map_withmod - d->m_keymap : -1, \
|
---|
515 | d->m_keymap_size);
|
---|
516 | #endif
|
---|
517 |
|
---|
518 | const QWSKeyboard::Mapping *it = map_withmod ? map_withmod : map_plain;
|
---|
519 |
|
---|
520 | if (!it) {
|
---|
521 | #ifdef QT_DEBUG_KEYMAP
|
---|
522 | // we couldn't even find a plain mapping
|
---|
523 | qWarning("Could not find a suitable mapping for keycode: %3d, modifiers: %02x", keycode, d->m_modifiers);
|
---|
524 | #endif
|
---|
525 | return result;
|
---|
526 | }
|
---|
527 |
|
---|
528 | bool skip = false;
|
---|
529 | quint16 unicode = it->unicode;
|
---|
530 | quint32 qtcode = it->qtcode;
|
---|
531 |
|
---|
532 | if ((it->flags & QWSKeyboard::IsModifier) && it->special) {
|
---|
533 | // this is a modifier, i.e. Shift, Alt, ...
|
---|
534 | if (pressed)
|
---|
535 | d->m_modifiers |= quint8(it->special);
|
---|
536 | else
|
---|
537 | d->m_modifiers &= ~quint8(it->special);
|
---|
538 | } else if (qtcode >= Qt::Key_CapsLock && qtcode <= Qt::Key_ScrollLock) {
|
---|
539 | // (Caps|Num|Scroll)Lock
|
---|
540 | if (first_press) {
|
---|
541 | quint8 &lock = d->m_locks[qtcode - Qt::Key_CapsLock];
|
---|
542 | lock ^= 1;
|
---|
543 |
|
---|
544 | switch (qtcode) {
|
---|
545 | case Qt::Key_CapsLock : result = lock ? CapsLockOn : CapsLockOff; break;
|
---|
546 | case Qt::Key_NumLock : result = lock ? NumLockOn : NumLockOff; break;
|
---|
547 | case Qt::Key_ScrollLock: result = lock ? ScrollLockOn : ScrollLockOff; break;
|
---|
548 | default : break;
|
---|
549 | }
|
---|
550 | }
|
---|
551 | } else if ((it->flags & QWSKeyboard::IsSystem) && it->special && first_press) {
|
---|
552 | switch (it->special) {
|
---|
553 | case QWSKeyboard::SystemReboot:
|
---|
554 | result = Reboot;
|
---|
555 | break;
|
---|
556 |
|
---|
557 | case QWSKeyboard::SystemZap:
|
---|
558 | if (!d->m_no_zap)
|
---|
559 | qApp->quit();
|
---|
560 | break;
|
---|
561 |
|
---|
562 | case QWSKeyboard::SystemConsolePrevious:
|
---|
563 | result = PreviousConsole;
|
---|
564 | break;
|
---|
565 |
|
---|
566 | case QWSKeyboard::SystemConsoleNext:
|
---|
567 | result = NextConsole;
|
---|
568 | break;
|
---|
569 |
|
---|
570 | default:
|
---|
571 | if (it->special >= QWSKeyboard::SystemConsoleFirst &&
|
---|
572 | it->special <= QWSKeyboard::SystemConsoleLast) {
|
---|
573 | result = KeycodeAction(SwitchConsoleFirst + ((it->special & QWSKeyboard::SystemConsoleMask) & SwitchConsoleMask));
|
---|
574 | }
|
---|
575 | break;
|
---|
576 | }
|
---|
577 |
|
---|
578 | skip = true; // no need to tell QWS about it
|
---|
579 | } else if ((qtcode == Qt::Key_Multi_key) && d->m_do_compose) {
|
---|
580 | // the Compose key was pressed
|
---|
581 | if (first_press)
|
---|
582 | d->m_composing = 2;
|
---|
583 | skip = true;
|
---|
584 | } else if ((it->flags & QWSKeyboard::IsDead) && d->m_do_compose) {
|
---|
585 | // a Dead key was pressed
|
---|
586 | if (first_press && d->m_composing == 1 && d->m_dead_unicode == unicode) { // twice
|
---|
587 | d->m_composing = 0;
|
---|
588 | qtcode = Qt::Key_unknown; // otherwise it would be Qt::Key_Dead...
|
---|
589 | } else if (first_press && unicode != 0xffff) {
|
---|
590 | d->m_dead_unicode = unicode;
|
---|
591 | d->m_composing = 1;
|
---|
592 | skip = true;
|
---|
593 | } else {
|
---|
594 | skip = true;
|
---|
595 | }
|
---|
596 | }
|
---|
597 |
|
---|
598 | if (!skip) {
|
---|
599 | // a normal key was pressed
|
---|
600 | const int modmask = Qt::ShiftModifier | Qt::ControlModifier | Qt::AltModifier | Qt::MetaModifier | Qt::KeypadModifier;
|
---|
601 |
|
---|
602 | // we couldn't find a specific mapping for the current modifiers,
|
---|
603 | // or that mapping didn't have special modifiers:
|
---|
604 | // so just report the plain mapping with additional modifiers.
|
---|
605 | if ((it == map_plain && it != map_withmod) ||
|
---|
606 | (map_withmod && !(map_withmod->qtcode & modmask))) {
|
---|
607 | qtcode |= QWSKbPrivate::toQtModifiers(d->m_modifiers);
|
---|
608 | }
|
---|
609 |
|
---|
610 | if (d->m_composing == 2 && first_press && !(it->flags & QWSKeyboard::IsModifier)) {
|
---|
611 | // the last key press was the Compose key
|
---|
612 | if (unicode != 0xffff) {
|
---|
613 | int idx = 0;
|
---|
614 | // check if this code is in the compose table at all
|
---|
615 | for ( ; idx < d->m_keycompose_size; ++idx) {
|
---|
616 | if (d->m_keycompose[idx].first == unicode)
|
---|
617 | break;
|
---|
618 | }
|
---|
619 | if (idx < d->m_keycompose_size) {
|
---|
620 | // found it -> simulate a Dead key press
|
---|
621 | d->m_dead_unicode = unicode;
|
---|
622 | unicode = 0xffff;
|
---|
623 | d->m_composing = 1;
|
---|
624 | skip = true;
|
---|
625 | } else {
|
---|
626 | d->m_composing = 0;
|
---|
627 | }
|
---|
628 | } else {
|
---|
629 | d->m_composing = 0;
|
---|
630 | }
|
---|
631 | } else if (d->m_composing == 1 && first_press && !(it->flags & QWSKeyboard::IsModifier)) {
|
---|
632 | // the last key press was a Dead key
|
---|
633 | bool valid = false;
|
---|
634 | if (unicode != 0xffff) {
|
---|
635 | int idx = 0;
|
---|
636 | // check if this code is in the compose table at all
|
---|
637 | for ( ; idx < d->m_keycompose_size; ++idx) {
|
---|
638 | if (d->m_keycompose[idx].first == d->m_dead_unicode && d->m_keycompose[idx].second == unicode)
|
---|
639 | break;
|
---|
640 | }
|
---|
641 | if (idx < d->m_keycompose_size) {
|
---|
642 | quint16 composed = d->m_keycompose[idx].result;
|
---|
643 | if (composed != 0xffff) {
|
---|
644 | unicode = composed;
|
---|
645 | qtcode = Qt::Key_unknown;
|
---|
646 | valid = true;
|
---|
647 | }
|
---|
648 | }
|
---|
649 | }
|
---|
650 | if (!valid) {
|
---|
651 | unicode = d->m_dead_unicode;
|
---|
652 | qtcode = Qt::Key_unknown;
|
---|
653 | }
|
---|
654 | d->m_composing = 0;
|
---|
655 | }
|
---|
656 |
|
---|
657 | if (!skip) {
|
---|
658 | #ifdef QT_DEBUG_KEYMAP
|
---|
659 | qWarning("Processing: uni=%04x, qt=%08x, qtmod=%08x", unicode, qtcode & ~modmask, (qtcode & modmask));
|
---|
660 | #endif
|
---|
661 |
|
---|
662 | // send the result to the QWS server
|
---|
663 | processKeyEvent(unicode, qtcode & ~modmask, Qt::KeyboardModifiers(qtcode & modmask), pressed, autorepeat);
|
---|
664 | }
|
---|
665 | }
|
---|
666 | return result;
|
---|
667 | }
|
---|
668 |
|
---|
669 | QT_END_NAMESPACE
|
---|
670 |
|
---|
671 | #include "qkbd_qws.moc"
|
---|
672 |
|
---|
673 | #endif // QT_NO_QWS_KEYBOARD
|
---|