Qt 4.8
qkbdqnx_qws.cpp
Go to the documentation of this file.
1 /****************************************************************************
2 **
3 ** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
4 ** Contact: http://www.qt-project.org/legal
5 **
6 ** This file is part of the QtGui module of the Qt Toolkit.
7 **
8 ** $QT_BEGIN_LICENSE:LGPL$
9 ** Commercial License Usage
10 ** Licensees holding valid commercial Qt licenses may use this file in
11 ** accordance with the commercial license agreement provided with the
12 ** Software or, alternatively, in accordance with the terms contained in
13 ** a written agreement between you and Digia. For licensing terms and
14 ** conditions see http://qt.digia.com/licensing. For further information
15 ** use the contact form at http://qt.digia.com/contact-us.
16 **
17 ** GNU Lesser General Public License Usage
18 ** Alternatively, this file may be used under the terms of the GNU Lesser
19 ** General Public License version 2.1 as published by the Free Software
20 ** Foundation and appearing in the file LICENSE.LGPL included in the
21 ** packaging of this file. Please review the following information to
22 ** ensure the GNU Lesser General Public License version 2.1 requirements
23 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
24 **
25 ** In addition, as a special exception, Digia gives you certain additional
26 ** rights. These rights are described in the Digia Qt LGPL Exception
27 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
28 **
29 ** GNU General Public License Usage
30 ** Alternatively, this file may be used under the terms of the GNU
31 ** General Public License version 3.0 as published by the Free Software
32 ** Foundation and appearing in the file LICENSE.GPL included in the
33 ** packaging of this file. Please review the following information to
34 ** ensure the GNU General Public License version 3.0 requirements will be
35 ** met: http://www.gnu.org/copyleft/gpl.html.
36 **
37 **
38 ** $QT_END_LICENSE$
39 **
40 ****************************************************************************/
41 
42 #include "qkbdqnx_qws.h"
43 
44 #include "qplatformdefs.h"
45 #include "qsocketnotifier.h"
46 #include "private/qcore_unix_p.h"
47 #include "QtCore/qdebug.h"
48 
49 #include <sys/dcmd_input.h>
50 #include <sys/keycodes.h>
51 #include <errno.h>
52 
54 
100 {
101  // open the keyboard device
102  keyboardFD = QT_OPEN(device.isEmpty() ? "/dev/devi/keyboard0" : device.toLatin1().constData(),
103  QT_OPEN_RDONLY);
104  if (keyboardFD == -1) {
105  qErrnoWarning(errno, "QWSQnxKeyboardHandler: Unable to open device");
106  } else {
107  // create a socket notifier so we'll wake up whenever keyboard input is detected.
109  connect(notifier, SIGNAL(activated(int)), SLOT(socketActivated()));
110 
111  qDebug("QWSQnxKeyboardHandler: connected.");
112  }
113 }
114 
119 {
120  if (keyboardFD != -1)
122 }
123 
124 // similar to PhKeyToMb
125 static inline bool key_sym_displayable(unsigned long sym)
126 {
127  if (sym >= 0xF000)
128  return sym >= 0xF100 && (sizeof(wchar_t) > 2 || sym < 0x10000);
129  return (sym & ~0x9F) != 0; // exclude 0...0x1F and 0x80...0x9F
130 }
131 
136 {
137  _keyboard_packet packet;
138 
139  // read one keyboard event
140  int bytesRead = QT_READ(keyboardFD, &packet, sizeof(_keyboard_packet));
141  if (bytesRead == -1) {
142  qErrnoWarning(errno, "QWSQnxKeyboardHandler::socketActivated(): Unable to read data.");
143  return;
144  }
145 
146  // the bytes read must be the size of a keyboard packet
147  Q_ASSERT(bytesRead == sizeof(_keyboard_packet));
148 
149  if (packet.data.flags & KEY_SYM_VALID_EX)
150  packet.data.flags |= KEY_SYM_VALID;
151  else if (!(packet.data.flags & (KEY_SYM_VALID | KEY_CAP_VALID)))
152  return;
153 
154 #if 0
155  qDebug() << "keyboard got scancode"
156  << hex << packet.data.modifiers
157  << packet.data.flags
158  << packet.data.key_cap
159  << packet.data.key_sym
160  << packet.data.key_scan;
161 #endif
162 
163  // QNX is nice enough to translate the raw keyboard data into generic format for us.
164  // Now we just have to translate it into a format Qt understands.
165 
166  // figure out the modifiers that are currently pressed
167  Qt::KeyboardModifiers modifiers = Qt::NoModifier;
168  if (packet.data.modifiers & KEYMOD_SHIFT)
169  modifiers |= Qt::ShiftModifier;
170  if (packet.data.modifiers & KEYMOD_CTRL)
171  modifiers |= Qt::ControlModifier;
172  if (packet.data.modifiers & KEYMOD_ALT)
173  modifiers |= Qt::AltModifier;
174  if (packet.data.modifiers & KEYMOD_NUM_LOCK)
175  modifiers |= Qt::KeypadModifier;
176 #if 0
177  // special case for AltGr
178  if (packet.data.modifiers & KEYMOD_ALTGR)
179  key = Qt::Key_AltGr;
180 #endif
181 
182  // figure out whether it's a press
183  bool isPress = packet.data.flags & KEY_DOWN;
184  // figure out whether the key is still pressed and the key event is repeated
185  bool isRepeat = packet.data.flags & KEY_REPEAT;
186 
187  int key = Qt::Key_unknown;
188  int unicode = 0;
189 
190  if (((packet.data.flags & KEY_SYM_VALID) && key_sym_displayable(unicode = packet.data.key_sym))
191  || ((packet.data.flags & KEY_CAP_VALID) && key_sym_displayable(unicode = packet.data.key_cap))) {
192  if (unicode <= 0x0ff) {
193  if (unicode >= 'a' && unicode <= 'z')
194  key = Qt::Key_A + unicode - 'a';
195  else
196  key = unicode;
197  }
198  // Ctrl<something> or Alt<something> is not a displayable character
199  if (modifiers & (Qt::ControlModifier | Qt::AltModifier))
200  unicode = 0;
201  } else {
202  unicode = 0;
203 
204  unsigned long sym = 0;
205  if (packet.data.flags & KEY_SYM_VALID)
206  sym = packet.data.key_sym;
207  else if (packet.data.flags & KEY_CAP_VALID)
208  sym = packet.data.key_cap;
209 
210  switch (sym) {
211  case KEYCODE_ESCAPE: key = Qt::Key_Escape; unicode = 27; break;
212  case KEYCODE_TAB: key = Qt::Key_Tab; unicode = 9; break;
213  case KEYCODE_BACK_TAB: key = Qt::Key_Backtab; break;
214  case KEYCODE_BACKSPACE: key = Qt::Key_Backspace; unicode = 127; break;
215  case KEYCODE_RETURN: key = Qt::Key_Return; break;
216  case KEYCODE_KP_ENTER: key = Qt::Key_Enter; break;
217  case KEYCODE_INSERT:
218  case KEYCODE_KP_INSERT:
219  key = Qt::Key_Insert; break;
220  case KEYCODE_KP_DELETE:
221  if (modifiers & Qt::KeypadModifier) {
222  key = Qt::Key_Comma;
223  break;
224  }
225  // fall through
226  case KEYCODE_DELETE:
227  key = Qt::Key_Delete; break;
228  case KEYCODE_PAUSE:
229  case KEYCODE_BREAK:
230  if (modifiers & (Qt::ControlModifier | Qt::AltModifier))
231  return; // sometimes occurs at the middle of a key sequence
232  key = Qt::Key_Pause; break;
233  case KEYCODE_PRINT:
234  if (modifiers & (Qt::ControlModifier | Qt::AltModifier))
235  return; // sometimes occurs at the middle of a key sequence
236  key = Qt::Key_Print; break;
237  case KEYCODE_SYSREQ:
238  key = Qt::Key_SysReq; break;
239  case KEYCODE_HOME:
240  case KEYCODE_KP_HOME:
241  key = Qt::Key_Home; break;
242  case KEYCODE_END:
243  case KEYCODE_KP_END:
244  key = Qt::Key_End; break;
245  case KEYCODE_LEFT:
246  case KEYCODE_KP_LEFT:
247  key = Qt::Key_Left; break;
248  case KEYCODE_UP:
249  case KEYCODE_KP_UP:
250  key = Qt::Key_Up; break;
251  case KEYCODE_RIGHT:
252  case KEYCODE_KP_RIGHT:
253  key = Qt::Key_Right; break;
254  case KEYCODE_DOWN:
255  case KEYCODE_KP_DOWN:
256  key = Qt::Key_Down; break;
257  case KEYCODE_PG_UP:
258  case KEYCODE_KP_PG_UP:
259  key = Qt::Key_PageUp; break;
260  case KEYCODE_PG_DOWN:
261  case KEYCODE_KP_PG_DOWN:
262  key = Qt::Key_PageDown; break;
263 
264  case KEYCODE_LEFT_SHIFT:
265  case KEYCODE_RIGHT_SHIFT:
266  key = Qt::Key_Shift; break;
267  case KEYCODE_LEFT_CTRL:
268  case KEYCODE_RIGHT_CTRL:
269  key = Qt::Key_Control; break;
270  case KEYCODE_LEFT_ALT:
271  case KEYCODE_RIGHT_ALT:
272  key = Qt::Key_Alt; break;
273  case KEYCODE_CAPS_LOCK:
274  key = Qt::Key_CapsLock; break;
275  case KEYCODE_NUM_LOCK:
276  key = Qt::Key_NumLock; break;
277  case KEYCODE_SCROLL_LOCK:
278  key = Qt::Key_ScrollLock; break;
279 
280  case KEYCODE_F1:
281  case KEYCODE_F2:
282  case KEYCODE_F3:
283  case KEYCODE_F4:
284  case KEYCODE_F5:
285  case KEYCODE_F6:
286  case KEYCODE_F7:
287  case KEYCODE_F8:
288  case KEYCODE_F9:
289  case KEYCODE_F10:
290  case KEYCODE_F11:
291  case KEYCODE_F12:
292  key = Qt::Key_F1 + sym - KEYCODE_F1; break;
293 
294  case KEYCODE_MENU: key = Qt::Key_Menu; break;
295  case KEYCODE_LEFT_HYPER: key = Qt::Key_Hyper_L; break;
296  case KEYCODE_RIGHT_HYPER: key = Qt::Key_Hyper_R; break;
297 
298  case KEYCODE_KP_PLUS: key = Qt::Key_Plus; break;
299  case KEYCODE_KP_MINUS: key = Qt::Key_Minus; break;
300  case KEYCODE_KP_MULTIPLY: key = Qt::Key_multiply; break;
301  case KEYCODE_KP_DIVIDE: key = Qt::Key_Slash; break;
302  case KEYCODE_KP_FIVE:
303  if (!(modifiers & Qt::KeypadModifier))
304  key = Qt::Key_5;
305  break;
306 
307  default: // none of the above
308  break;
309  }
310  }
311 
312  if (key == Qt::Key_unknown && unicode == 0)
313  return;
314 
315  // call processKeyEvent. This is where all the magic happens to insert a
316  // key event into Qt's event loop.
317  // Note that for repeated key events, isPress must be true
318  // (on QNX, isPress is not set when the key event is repeated).
319  processKeyEvent(unicode, key, modifiers, isPress || isRepeat, isRepeat);
320 }
321 
#define QT_END_NAMESPACE
This macro expands to.
Definition: qglobal.h:90
#define SLOT(a)
Definition: qobjectdefs.h:226
The QString class provides a Unicode character string.
Definition: qstring.h:83
#define Q_ASSERT(cond)
Definition: qglobal.h:1823
Q_CORE_EXPORT QTextStream & hex(QTextStream &s)
#define QT_READ
Definition: qcore_unix_p.h:280
The QSocketNotifier class provides support for monitoring activity on a file descriptor.
QWSQnxKeyboardHandler(const QString &device)
Constructs a keyboard handler for the specified device, defaulting to /dev/devi/keyboard0.
Definition: qkbdqnx_qws.cpp:99
Q_CORE_EXPORT void qDebug(const char *,...)
#define SIGNAL(a)
Definition: qobjectdefs.h:227
#define QT_BEGIN_NAMESPACE
This macro expands to.
Definition: qglobal.h:89
static bool connect(const QObject *sender, const char *signal, const QObject *receiver, const char *member, Qt::ConnectionType=Qt::AutoConnection)
Creates a connection of the given type from the signal in the sender object to the method in the rece...
Definition: qobject.cpp:2580
bool isEmpty() const
Returns true if the string has no characters; otherwise returns false.
Definition: qstring.h:704
QByteArray toLatin1() const Q_REQUIRED_RESULT
Returns a Latin-1 representation of the string as a QByteArray.
Definition: qstring.cpp:3993
static bool key_sym_displayable(unsigned long sym)
const char * constData() const
Returns a pointer to the data stored in the byte array.
Definition: qbytearray.h:433
#define QT_OPEN
Definition: qcore_unix_p.h:186
int key
~QWSQnxKeyboardHandler()
Destroys this keyboard handler and closes the connection to the keyboard device.
virtual void processKeyEvent(int unicode, int keycode, Qt::KeyboardModifiers modifiers, bool isPress, bool autoRepeat)
Sends a key event to the Qt for Embedded Linux server application.
Definition: qkbd_qws.cpp:363
int errno
void qErrnoWarning(const char *msg,...)
Definition: qglobal.cpp:2954
#define QT_CLOSE
Definition: qcore_unix_p.h:304