diff options
author | Ritt Konstantin <qnx@ics.com> | 2011-06-21 11:51:12 (GMT) |
---|---|---|
committer | Harald Fernengel <harald.fernengel@nokia.com> | 2011-06-21 12:05:45 (GMT) |
commit | 47b8e218aaa50714871a789ce257c0845d04b219 (patch) | |
tree | 6489b930e0396f394941cc681a3176776f86d22d /src/gui | |
parent | 608c6090eda5579cc6325c3b91172614da1a464d (diff) | |
download | Qt-47b8e218aaa50714871a789ce257c0845d04b219.zip Qt-47b8e218aaa50714871a789ce257c0845d04b219.tar.gz Qt-47b8e218aaa50714871a789ce257c0845d04b219.tar.bz2 |
massive improvements for the QNX keyboard driver
update the code to work on recent QNXs (6.4 and newer);
support all keycodes defined in sys/keycodes.h;
support unicodes as well as scancodes
Merge-request: 1259
Reviewed-by: Harald Fernengel <harald.fernengel@nokia.com>
Diffstat (limited to 'src/gui')
-rw-r--r-- | src/gui/embedded/qkbdqnx_qws.cpp | 257 |
1 files changed, 170 insertions, 87 deletions
diff --git a/src/gui/embedded/qkbdqnx_qws.cpp b/src/gui/embedded/qkbdqnx_qws.cpp index 5a8118d..ad76446 100644 --- a/src/gui/embedded/qkbdqnx_qws.cpp +++ b/src/gui/embedded/qkbdqnx_qws.cpp @@ -40,16 +40,16 @@ ****************************************************************************/ #include "qkbdqnx_qws.h" -#include "QtCore/qsocketnotifier.h" + +#include "qplatformdefs.h" +#include "qsocketnotifier.h" +#include "private/qcore_unix_p.h" #include "QtCore/qdebug.h" #include <sys/dcmd_input.h> -#include <photon/keycodes.h> - -#include "qplatformdefs.h" +#include <sys/keycodes.h> #include <errno.h> - QT_BEGIN_NAMESPACE /*! @@ -72,7 +72,7 @@ QT_BEGIN_NAMESPACE Example invocation from command line: \c{/usr/photon/bin/devi-hid -Pr kbd mouse} Note that after running \c{devi-hid}, you will not be able to use the local - shell anymore. It is suggested to run the command in a shell scrip, that launches + shell anymore. It is suggested to run the command in a shell script, that launches a Qt application after invocation of \c{devi-hid}. To make \l{Qt for Embedded Linux} explicitly choose the qnx keyboard @@ -100,15 +100,13 @@ QWSQnxKeyboardHandler::QWSQnxKeyboardHandler(const QString &device) QT_OPEN_RDONLY); if (keyboardFD == -1) { qErrnoWarning(errno, "QWSQnxKeyboardHandler: Unable to open device"); - return; - } - - // create a socket notifier so we'll wake up whenever keyboard input is detected. - QSocketNotifier *notifier = new QSocketNotifier(keyboardFD, QSocketNotifier::Read, this); - connect(notifier, SIGNAL(activated(int)), SLOT(socketActivated())); - - qDebug() << "QWSQnxKeyboardHandler: connected."; + } else { + // create a socket notifier so we'll wake up whenever keyboard input is detected. + QSocketNotifier *notifier = new QSocketNotifier(keyboardFD, QSocketNotifier::Read, this); + connect(notifier, SIGNAL(activated(int)), SLOT(socketActivated())); + qDebug("QWSQnxKeyboardHandler: connected."); + } } /*! @@ -116,7 +114,16 @@ QWSQnxKeyboardHandler::QWSQnxKeyboardHandler(const QString &device) */ QWSQnxKeyboardHandler::~QWSQnxKeyboardHandler() { - QT_CLOSE(keyboardFD); + if (keyboardFD != -1) + QT_CLOSE(keyboardFD); +} + +// similar to PhKeyToMb +static inline bool key_sym_displayable(unsigned long sym) +{ + if (sym >= 0xF000) + return sym >= 0xF100 && (sizeof(wchar_t) > 2 || sym < 0x10000); + return (sym & ~0x9F) != 0; // exclude 0...0x1F and 0x80...0x9F } /*! \internal @@ -136,6 +143,11 @@ void QWSQnxKeyboardHandler::socketActivated() // the bytes read must be the size of a keyboard packet Q_ASSERT(bytesRead == sizeof(_keyboard_packet)); + if (packet.data.flags & KEY_SYM_VALID_EX) + packet.data.flags |= KEY_SYM_VALID; + else if (!(packet.data.flags & (KEY_SYM_VALID | KEY_CAP_VALID))) + return; + #if 0 qDebug() << "keyboard got scancode" << hex << packet.data.modifiers @@ -145,86 +157,157 @@ void QWSQnxKeyboardHandler::socketActivated() << packet.data.key_scan; #endif - // QNX is nice enough to translate the raw keyboard data into a QNX data structure + // QNX is nice enough to translate the raw keyboard data into generic format for us. // Now we just have to translate it into a format Qt understands. - // figure out whether it's a press - bool isPress = packet.data.key_cap & KEY_DOWN; - // figure out whether the key is still pressed and the key event is repeated - bool isRepeat = packet.data.key_cap & KEY_REPEAT; - - Qt::Key key = Qt::Key_unknown; - int unicode = 0xffff; - - // TODO - this switch is not complete! - switch (packet.data.key_scan) { - case KEYCODE_SPACE: key = Qt::Key_Space; unicode = 0x20; break; - case KEYCODE_F1: key = Qt::Key_F1; break; - case KEYCODE_F2: key = Qt::Key_F2; break; - case KEYCODE_F3: key = Qt::Key_F3; break; - case KEYCODE_F4: key = Qt::Key_F4; break; - case KEYCODE_F5: key = Qt::Key_F5; break; - case KEYCODE_F6: key = Qt::Key_F6; break; - case KEYCODE_F7: key = Qt::Key_F7; break; - case KEYCODE_F8: key = Qt::Key_F8; break; - case KEYCODE_F9: key = Qt::Key_F9; break; - case KEYCODE_F10: key = Qt::Key_F10; break; - case KEYCODE_F11: key = Qt::Key_F11; break; - case KEYCODE_F12: key = Qt::Key_F12; break; - case KEYCODE_BACKSPACE: key = Qt::Key_Backspace; break; - case KEYCODE_TAB: key = Qt::Key_Tab; break; - case KEYCODE_RETURN: key = Qt::Key_Return; break; - case KEYCODE_KP_ENTER: key = Qt::Key_Enter; break; - case KEYCODE_UP: - case KEYCODE_KP_UP: - key = Qt::Key_Up; break; - case KEYCODE_DOWN: - case KEYCODE_KP_DOWN: - key = Qt::Key_Down; break; - case KEYCODE_LEFT: - case KEYCODE_KP_LEFT: - key = Qt::Key_Left; break; - case KEYCODE_RIGHT: - case KEYCODE_KP_RIGHT: - key = Qt::Key_Right; break; - case KEYCODE_HOME: - case KEYCODE_KP_HOME: - key = Qt::Key_Home; break; - case KEYCODE_END: - case KEYCODE_KP_END: - key = Qt::Key_End; break; - case KEYCODE_PG_UP: - case KEYCODE_KP_PG_UP: - key = Qt::Key_PageUp; break; - case KEYCODE_PG_DOWN: - case KEYCODE_KP_PG_DOWN: - key = Qt::Key_PageDown; break; - case KEYCODE_INSERT: - case KEYCODE_KP_INSERT: - key = Qt::Key_Insert; break; - case KEYCODE_DELETE: - case KEYCODE_KP_DELETE: - key = Qt::Key_Delete; break; - case KEYCODE_ESCAPE: - key = Qt::Key_Escape; break; - default: // none of the above, try the key_scan directly - unicode = packet.data.key_scan; - break; - } - // figure out the modifiers that are currently pressed Qt::KeyboardModifiers modifiers = Qt::NoModifier; - if (packet.data.flags & KEYMOD_SHIFT) + if (packet.data.modifiers & KEYMOD_SHIFT) modifiers |= Qt::ShiftModifier; - if (packet.data.flags & KEYMOD_CTRL) + if (packet.data.modifiers & KEYMOD_CTRL) modifiers |= Qt::ControlModifier; - if (packet.data.flags & KEYMOD_ALT) + if (packet.data.modifiers & KEYMOD_ALT) modifiers |= Qt::AltModifier; + if (packet.data.modifiers & KEYMOD_NUM_LOCK) + modifiers |= Qt::KeypadModifier; +#if 0 + // special case for AltGr + if (packet.data.modifiers & KEYMOD_ALTGR) + key = Qt::Key_AltGr; +#endif + + // figure out whether it's a press + bool isPress = packet.data.flags & KEY_DOWN; + // figure out whether the key is still pressed and the key event is repeated + bool isRepeat = packet.data.flags & KEY_REPEAT; + + int key = Qt::Key_unknown; + int unicode = 0; + + if (((packet.data.flags & KEY_SYM_VALID) && key_sym_displayable(unicode = packet.data.key_sym)) + || ((packet.data.flags & KEY_CAP_VALID) && key_sym_displayable(unicode = packet.data.key_cap))) { + if (unicode <= 0x0ff) { + if (unicode >= 'a' && unicode <= 'z') + key = Qt::Key_A + unicode - 'a'; + else + key = unicode; + } + // Ctrl<something> or Alt<something> is not a displayable character + if (modifiers & (Qt::ControlModifier | Qt::AltModifier)) + unicode = 0; + } else { + unicode = 0; + + unsigned long sym = 0; + if (packet.data.flags & KEY_SYM_VALID) + sym = packet.data.key_sym; + else if (packet.data.flags & KEY_CAP_VALID) + sym = packet.data.key_cap; - // if the unicode value is not ascii, we ignore it. - // TODO - do a complete mapping between all QNX scan codes and Qt codes - if (unicode != 0xffff && !isascii(unicode)) - return; // unprintable character + switch (sym) { + case KEYCODE_ESCAPE: key = Qt::Key_Escape; unicode = 27; break; + case KEYCODE_TAB: key = Qt::Key_Tab; unicode = 9; break; + case KEYCODE_BACK_TAB: key = Qt::Key_Backtab; break; + case KEYCODE_BACKSPACE: key = Qt::Key_Backspace; unicode = 127; break; + case KEYCODE_RETURN: key = Qt::Key_Return; break; + case KEYCODE_KP_ENTER: key = Qt::Key_Enter; break; + case KEYCODE_INSERT: + case KEYCODE_KP_INSERT: + key = Qt::Key_Insert; break; + case KEYCODE_KP_DELETE: + if (modifiers & Qt::KeypadModifier) { + key = Qt::Key_Comma; + break; + } + // fall through + case KEYCODE_DELETE: + key = Qt::Key_Delete; break; + case KEYCODE_PAUSE: + case KEYCODE_BREAK: + if (modifiers & (Qt::ControlModifier | Qt::AltModifier)) + return; // sometimes occurs at the middle of a key sequence + key = Qt::Key_Pause; break; + case KEYCODE_PRINT: + if (modifiers & (Qt::ControlModifier | Qt::AltModifier)) + return; // sometimes occurs at the middle of a key sequence + key = Qt::Key_Print; break; + case KEYCODE_SYSREQ: + key = Qt::Key_SysReq; break; + case KEYCODE_HOME: + case KEYCODE_KP_HOME: + key = Qt::Key_Home; break; + case KEYCODE_END: + case KEYCODE_KP_END: + key = Qt::Key_End; break; + case KEYCODE_LEFT: + case KEYCODE_KP_LEFT: + key = Qt::Key_Left; break; + case KEYCODE_UP: + case KEYCODE_KP_UP: + key = Qt::Key_Up; break; + case KEYCODE_RIGHT: + case KEYCODE_KP_RIGHT: + key = Qt::Key_Right; break; + case KEYCODE_DOWN: + case KEYCODE_KP_DOWN: + key = Qt::Key_Down; break; + case KEYCODE_PG_UP: + case KEYCODE_KP_PG_UP: + key = Qt::Key_PageUp; break; + case KEYCODE_PG_DOWN: + case KEYCODE_KP_PG_DOWN: + key = Qt::Key_PageDown; break; + + case KEYCODE_LEFT_SHIFT: + case KEYCODE_RIGHT_SHIFT: + key = Qt::Key_Shift; break; + case KEYCODE_LEFT_CTRL: + case KEYCODE_RIGHT_CTRL: + key = Qt::Key_Control; break; + case KEYCODE_LEFT_ALT: + case KEYCODE_RIGHT_ALT: + key = Qt::Key_Alt; break; + case KEYCODE_CAPS_LOCK: + key = Qt::Key_CapsLock; break; + case KEYCODE_NUM_LOCK: + key = Qt::Key_NumLock; break; + case KEYCODE_SCROLL_LOCK: + key = Qt::Key_ScrollLock; break; + + case KEYCODE_F1: + case KEYCODE_F2: + case KEYCODE_F3: + case KEYCODE_F4: + case KEYCODE_F5: + case KEYCODE_F6: + case KEYCODE_F7: + case KEYCODE_F8: + case KEYCODE_F9: + case KEYCODE_F10: + case KEYCODE_F11: + case KEYCODE_F12: + key = Qt::Key_F1 + sym - KEYCODE_F1; break; + + case KEYCODE_MENU: key = Qt::Key_Menu; break; + case KEYCODE_LEFT_HYPER: key = Qt::Key_Hyper_L; break; + case KEYCODE_RIGHT_HYPER: key = Qt::Key_Hyper_R; break; + + case KEYCODE_KP_PLUS: key = Qt::Key_Plus; break; + case KEYCODE_KP_MINUS: key = Qt::Key_Minus; break; + case KEYCODE_KP_MULTIPLY: key = Qt::Key_multiply; break; + case KEYCODE_KP_DIVIDE: key = Qt::Key_Slash; break; + case KEYCODE_KP_FIVE: + if (!(modifiers & Qt::KeypadModifier)) + key = Qt::Key_5; + break; + + default: // none of the above + break; + } + } + + if (key == Qt::Key_unknown && unicode == 0) + return; // call processKeyEvent. This is where all the magic happens to insert a // key event into Qt's event loop. |