src/gui/embedded/qkbd_qws.cpp
changeset 0 1918ee327afb
child 4 3b1da2848fc7
equal deleted inserted replaced
-1:000000000000 0:1918ee327afb
       
     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