1 /****************************************************************************
2 ** $Id: qt/src/kernel/qkeyboard_qws.cpp 2.3.7 edited 2003-05-30 $
4 ** Implementation of Qt/Embedded keyboard drivers
8 ** Copyright (C) 1992-2000 Trolltech AS. All rights reserved.
10 ** This file is part of the kernel module of the Qt GUI Toolkit.
12 ** This file may be distributed and/or modified under the terms of the
13 ** GNU General Public License version 2 as published by the Free Software
14 ** Foundation and appearing in the file LICENSE.GPL included in the
15 ** packaging of this file.
17 ** Licensees holding valid Qt Enterprise Edition or Qt Professional Edition
18 ** licenses for Qt/Embedded may use this file in accordance with the
19 ** Qt Embedded Commercial License Agreement provided with the Software.
21 ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
22 ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
24 ** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for
25 ** information about Qt Commercial License Agreements.
26 ** See http://www.trolltech.com/gpl/ for GPL licensing information.
28 ** Contact info@trolltech.com if any conditions of this licensing are
31 **********************************************************************/
33 #include "qwindowsystem_qws.h"
34 #include "qwsutils_qws.h"
37 #include <qapplication.h>
38 #include <qsocketnotifier.h>
39 #include <qnamespace.h>
48 #include <sys/ioctl.h>
49 #include <sys/types.h>
55 #ifndef QT_NO_QWS_KEYBOARD
61 #include <linux/keyboard.h>
63 #define VTSWITCHSIG SIGUSR2
65 static bool vtActive = true;
67 static int kbdFD = -1;
69 static QIntDict<QWSServer::KeyMap> *overrideMap = 0;
72 Changes the mapping of the keyboard; adding the scancode to Unicode
73 mappings from \a map. The server takes over ownership of \a map
74 and will delete it. Use QCollection::setAutoDelete() to control
75 whether the contents of \a map should be deleted.
77 Passing a null pointer for \a map will revert to the default keymap.
80 void QWSServer::setOverrideKeys( QIntDict<QWSServer::KeyMap> *map )
87 \class QWSKeyboardHandler qkeyboard_qws.h
88 \brief Keyboard driver/handler for Qt/Embedded
90 The keyboard driver/handler handles events from system devices and
93 A QWSKeyboardHandler will usually open some system device in its
94 constructor, create a QSocketNotifier on that opened device and when
95 it receives data, it will call processKeyEvent() to send the event
96 to Qt/Embedded for relaying to clients.
100 Subclasses call this to send a key event. The server may additionally
101 filter it before sending it on to applications.
104 <li>\a unicode is the Unicode value for the key, or 0xffff if none is appropriate.
105 <li>\a keycode is the Qt keycode for the key (see Qt::Key).
106 for the list of codes).
107 <li>\a modifiers is the set of modifier keys (see Qt::Modifier).
108 <li>\a isPress says whether this is a press or a release.
109 <li>\a autoRepeat says whether this event was generated by an auto-repeat
110 mechanism, or an actual key press.
113 void QWSKeyboardHandler::processKeyEvent(int unicode, int keycode, int modifiers,
114 bool isPress, bool autoRepeat)
116 qwsServer->processKeyEvent( unicode, keycode, modifiers, isPress, autoRepeat );
120 bool qwsSetKeyboardAutoRepeat( int /* delay */ , int /* period */ )
125 bool qwsGetKeyboardAutoRepeat( int /* delay */ , int /* period */ )
130 void qwsRestoreKeyboardLeds()
139 * Virtual framebuffer keyboard driver
142 class QWSVFbKeyboardHandler : public QWSKeyboardHandler
146 QWSVFbKeyboardHandler();
147 virtual ~QWSVFbKeyboardHandler();
149 bool isOpen() { return fd > 0; }
152 void readKeyboardData();
155 QString terminalName;
159 unsigned char *kbdBuffer;
160 QSocketNotifier *notifier;
163 #ifndef QT_NO_QWS_VFB
165 extern int qws_display_id;
168 QWSVFbKeyboardHandler::QWSVFbKeyboardHandler()
171 #ifndef QT_NO_QWS_VFB
173 kbdBufferLen = sizeof( QVFbKeyData ) * 5;
174 kbdBuffer = new unsigned char [kbdBufferLen];
176 terminalName = QString(QT_VFB_KEYBOARD_PIPE).arg(qws_display_id);
178 if ((kbdFD = open( terminalName.local8Bit(), O_RDWR | O_NDELAY)) < 0) {
179 qDebug( "Cannot open %s (%s)", terminalName.latin1(),
182 // Clear pending input
184 while (read(kbdFD, buf, 1) > 0) { }
186 notifier = new QSocketNotifier( kbdFD, QSocketNotifier::Read, this );
187 connect(notifier, SIGNAL(activated(int)),this, SLOT(readKeyboardData()));
192 QWSVFbKeyboardHandler::~QWSVFbKeyboardHandler()
194 #ifndef QT_NO_QWS_VFB
202 void QWSVFbKeyboardHandler::readKeyboardData()
204 #ifndef QT_NO_QWS_VFB
207 n = read(kbdFD, kbdBuffer+kbdIdx, kbdBufferLen - kbdIdx );
213 while ( kbdIdx - idx >= (int)sizeof( QVFbKeyData ) ) {
214 QVFbKeyData *kd = (QVFbKeyData *)(kbdBuffer + idx);
215 if ( kd->unicode == 0 && kd->modifiers == 0 && kd->press ) {
217 qWarning( "Instructed to quit by Virtual Keyboard" );
220 processKeyEvent( kd->unicode&0xffff, kd->unicode>>16,
221 kd->modifiers, kd->press, kd->repeat );
222 idx += sizeof( QVFbKeyData );
225 int surplus = kbdIdx - idx;
226 for ( int i = 0; i < surplus; i++ )
227 kbdBuffer[i] = kbdBuffer[idx+i];
235 struct termios origTermData;
237 static void init_kbd(void)
239 struct termios termdata;
241 tcgetattr( kbdFD, &origTermData );
242 tcgetattr( kbdFD, &termdata );
244 ioctl(kbdFD, KDSKBMODE, K_XLATE);
246 termdata.c_iflag = (IGNPAR | IGNBRK) & (~PARMRK) & (~ISTRIP);
247 termdata.c_oflag = 0;
248 termdata.c_cflag = CREAD | CS8;
249 termdata.c_lflag = 0;
250 termdata.c_cc[VTIME]=0;
251 termdata.c_cc[VMIN]=1;
252 cfsetispeed(&termdata, 9600);
253 cfsetospeed(&termdata, 9600);
254 tcsetattr(kbdFD, TCSANOW, &termdata);
257 static void done_kbd(void)
260 tcsetattr(kbdFD, TCSANOW, &origTermData);
264 static void vtSwitchHandler(int /*sig*/)
267 qwsServer->enablePainting(false);
269 if (ioctl(kbdFD, VT_RELDISP, VT_ACKACQ) == 0) {
271 qwsServer->closeMouse();
275 qwsServer->enablePainting(true);
280 if (ioctl(kbdFD, VT_RELDISP, VT_ACKACQ) == 0) {
282 qwsServer->enablePainting(true);
284 qt_screen->restore();
285 qwsServer->openMouse();
286 qwsServer->refresh();
289 signal(VTSWITCHSIG, vtSwitchHandler);
294 class QWSRamsesKbPrivate;
295 class QWSRamsesKeyboardHandler : public QWSKeyboardHandler
298 QWSRamsesKeyboardHandler( const QString& );
299 virtual ~QWSRamsesKeyboardHandler();
301 virtual void processKeyEvent(int unicode, int keycode, int modifiers,
302 bool isPress, bool autoRepeat);
305 QWSRamsesKbPrivate *d;
309 class QWSRamsesKbPrivate : public QObject
313 QWSRamsesKbPrivate( QWSRamsesKeyboardHandler *, const QString &device );
314 ~QWSRamsesKbPrivate();
317 void readKeyboardData();
320 void handleKey(unsigned char code, int n);
322 QWSRamsesKeyboardHandler *handler;
327 QWSRamsesKbPrivate::QWSRamsesKbPrivate( QWSRamsesKeyboardHandler *h, const QString &device )
328 : handler(h), rptr(0)
331 kbdFD = ::open(device.isEmpty()?"/dev/vc/2":device.latin1(), O_RDWR|O_NDELAY, 0);
333 kbdFD = ::open(device.isEmpty()?"/dev/tty2":device.latin1(), O_RDWR|O_NDELAY, 0);
337 QSocketNotifier *notifier;
338 notifier = new QSocketNotifier( kbdFD, QSocketNotifier::Read, this );
339 connect( notifier, SIGNAL(activated(int)),this, SLOT(readKeyboardData()) );
341 qDebug( "Cannot open keyboard" );
345 struct vt_mode vtMode;
346 ioctl(kbdFD, VT_GETMODE, &vtMode);
348 // let us control VT switching
349 vtMode.mode = VT_PROCESS;
350 vtMode.relsig = VTSWITCHSIG;
351 vtMode.acqsig = VTSWITCHSIG;
352 ioctl(kbdFD, VT_SETMODE, &vtMode);
354 struct vt_stat vtStat;
355 ioctl(kbdFD, VT_GETSTATE, &vtStat);
356 vtQws = vtStat.v_active;
358 signal(VTSWITCHSIG, vtSwitchHandler);
361 QWSRamsesKbPrivate::~QWSRamsesKbPrivate()
363 signal(VTSWITCHSIG, 0);
367 struct vt_mode vtMode;
368 ioctl(kbdFD, VT_GETMODE, &vtMode);
369 /* Mickey says: "Better give up control of VT switching.
370 * Hey, I really hate that OS-will-reacquire-resources on process-death
373 vtMode.mode = VT_AUTO;
376 ioctl(kbdFD, VT_SETMODE, &vtMode);
383 static inline int map_to_modif(int current_map)
387 if (current_map & KG_ALT)
388 modifiers |= Qt::ALT;
389 else if (current_map & KG_CTRL)
390 modifiers |= Qt::CTRL;
391 else if (current_map & KG_SHIFT)
392 modifiers |= Qt::SHIFT;
399 unsigned short qtcode;
401 { "\e[A", Qt::Key_Up },
402 { "\e[B", Qt::Key_Down },
403 { "\e[C", Qt::Key_Right },
404 { "\e[D", Qt::Key_Left },
405 { "\e[1~", Qt::Key_Home },
406 { "\e[4~", Qt::Key_End },
407 { "\e[5~", Qt::Key_PageUp },
408 { "\e[6~", Qt::Key_PageDown },
410 { "\e[[A", Qt::Key_F1 },
411 { "\e[[B", Qt::Key_F2 },
412 { "\e[[C", Qt::Key_F3 },
413 { "\e[[D", Qt::Key_F4 },
414 { "\e[[E", Qt::Key_F5 },
415 { "\e[17~", Qt::Key_F6 },
416 { "\e[18~", Qt::Key_F7 },
417 { "\e[19~", Qt::Key_F8 },
418 { "\e[20~", Qt::Key_F9 },
419 { "\e[21~", Qt::Key_F10 },
420 { "\e[23~", Qt::Key_F11 },
421 { "\e[24~", Qt::Key_F12 },
423 // { "\ex", Qt::FieldExit },
424 // { "\er", Qt::FieldReset },
430 unsigned short qtcode;
432 { 0x08, Qt::Key_Backspace },
433 { 0x09, Qt::Key_Tab },
434 { 0x0d, Qt::Key_Enter },
435 { 0x1b, Qt::Key_Escape },
438 void QWSRamsesKbPrivate::handleKey(unsigned char code, int n)
440 int qtKeyCode = Qt::Key_unknown;
443 //qDebug("\nhandleKey %02x %d %c", code, n, code >= ' ' ? code : ' ');
446 if ((n==1) && (rptr==0)) {
448 for (i=0; i < sizeof(qtkey_lookup)/sizeof(qtkey_lookup[0]); i++) {
449 if (qtkey_lookup[i].code == code) {
450 qtKeyCode = qtkey_lookup[i].qtcode;
457 // Alt-<KEY> sequence
458 if ((n==1) && (rptr==1) && (rbuf[0] == '\e')) {
459 //qDebug("alt-key %d", code);
460 handler->processKeyEvent(0, Qt::Key_Alt, 0, 1, 0);
461 handler->processKeyEvent(0, code-32, Qt::ALT, 1, 0);
462 handler->processKeyEvent(0, code-32, Qt::ALT, 0, 0);
463 handler->processKeyEvent(0, Qt::Key_Alt, 0, 0, 0);
468 // End of a function key sequence
469 if ((n==1) && (rptr!=0)) {
472 for (i=0; i < sizeof(qtesc_lookup)/sizeof(qtesc_lookup[0]); i++) {
473 if (strncmp(rbuf, qtesc_lookup[i].code, sizeof(rbuf)) == 0) {
474 qtKeyCode = qtesc_lookup[i].qtcode;
480 //qWarning("no entry in key sequence table for %s", &rbuf[1]);
483 for (i=0; i <= oldrptr; i++) {
484 handleKey(rbuf[i], 1);
491 // Middle of a function key sequence
493 if (rptr < sizeof(rbuf))
498 //qDebug(" code 0x%2x %d -> qtKeyCode 0x%04x", code, code, qtKeyCode);
500 handler->processKeyEvent(code, qtKeyCode, 0, 1, 0);
501 handler->processKeyEvent(code, qtKeyCode, 0, 0, 0);
505 void QWSRamsesKbPrivate::readKeyboardData()
507 unsigned char buf[81];
508 int n = read(kbdFD, buf, 80 );
509 for ( int loop = 0; loop < n; loop++ ) {
510 handleKey(buf[loop], n-loop);
518 QWSRamsesKeyboardHandler::QWSRamsesKeyboardHandler( const QString &device )
520 d = new QWSRamsesKbPrivate( this, device );
523 QWSRamsesKeyboardHandler::~QWSRamsesKeyboardHandler()
528 void QWSRamsesKeyboardHandler::processKeyEvent(int unicode, int keycode,
529 int modifiers, bool isPress, bool autoRepeat)
531 // Virtual console switching
533 bool ctrl = modifiers & Qt::ControlButton;
534 bool alt = modifiers & Qt::AltButton;
535 if (ctrl && alt && keycode >= Qt::Key_F1 && keycode <= Qt::Key_F10)
536 term = keycode - Qt::Key_F1 + 1;
537 else if (ctrl && alt && keycode == Qt::Key_Left)
538 term = QMAX(vtQws - 1, 1);
539 else if (ctrl && alt && keycode == Qt::Key_Right)
540 term = QMIN(vtQws + 1, 10);
541 if (term && !isPress) {
542 ioctl(kbdFD, VT_ACTIVATE, term);
546 QWSKeyboardHandler::processKeyEvent( unicode, keycode, modifiers, isPress, autoRepeat );
552 * keyboard driver instantiation
555 QWSKeyboardHandler *QWSServer::newKeyboardHandler( const QString &spec )
557 QWSKeyboardHandler *handler = 0;
561 int colon=spec.find(':');
563 type = spec.left(colon);
564 device = spec.mid(colon+1);
569 if ( type == "QVFbKeyboard" ) {
570 handler = new QWSVFbKeyboardHandler();
571 } else if ( type == "TTY" ) {
572 handler = new QWSRamsesKeyboardHandler(device);
574 qWarning( "Keyboard type %s:%s unsupported", spec.latin1(), device.latin1() );
580 #include "qkeyboard_qws.moc"
582 #endif // QT_NO_QWS_KEYBOARD