summaryrefslogtreecommitdiffstats
path: root/src/gui
diff options
context:
space:
mode:
authorRitt Konstantin <qnx@ics.com>2011-06-21 11:51:12 (GMT)
committerHarald Fernengel <harald.fernengel@nokia.com>2011-06-21 12:05:45 (GMT)
commit47b8e218aaa50714871a789ce257c0845d04b219 (patch)
tree6489b930e0396f394941cc681a3176776f86d22d /src/gui
parent608c6090eda5579cc6325c3b91172614da1a464d (diff)
downloadQt-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.cpp257
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.