]> pilppa.org Git - familiar-h63xx-build.git/blob - org.handhelds.familiar/packages/qte/qte-2.3.10/openmn/qkeyboard_qws.cpp
OE tree imported from monotone branch org.openembedded.oz354fam083 at revision 8b12e3...
[familiar-h63xx-build.git] / org.handhelds.familiar / packages / qte / qte-2.3.10 / openmn / qkeyboard_qws.cpp
1 /****************************************************************************
2 ** $Id: qt/src/kernel/qkeyboard_qws.cpp   2.3.7   edited 2003-05-30 $
3 **
4 ** Implementation of Qt/Embedded keyboard drivers
5 **
6 ** Created : 991025
7 **
8 ** Copyright (C) 1992-2000 Trolltech AS.  All rights reserved.
9 **
10 ** This file is part of the kernel module of the Qt GUI Toolkit.
11 **
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.
16 **
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.
20 **
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.
23 **
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.
27 **
28 ** Contact info@trolltech.com if any conditions of this licensing are
29 ** not clear to you.
30 **
31 **********************************************************************/
32
33 #include "qwindowsystem_qws.h"
34 #include "qwsutils_qws.h"
35 #include "qgfx_qws.h"
36
37 #include <qapplication.h>
38 #include <qsocketnotifier.h>
39 #include <qnamespace.h>
40 #include <qtimer.h>
41
42 #include <stdlib.h>
43 #include <stdio.h>
44 #include <ctype.h>
45
46 #include <unistd.h>
47 #include <linux/kd.h>
48 #include <sys/ioctl.h>
49 #include <sys/types.h>
50 #include <sys/stat.h>
51 #include <fcntl.h>
52 #include <errno.h>
53 #include <signal.h>
54
55 #ifndef QT_NO_QWS_KEYBOARD
56
57 #include <termios.h>
58 #include <sys/kd.h>
59 #include <sys/vt.h>
60 #include <sys/wait.h>
61 #include <linux/keyboard.h>
62
63 #define VTSWITCHSIG SIGUSR2
64
65 static bool vtActive = true;
66 static int  vtQws = 0;
67 static int  kbdFD = -1;
68
69 static QIntDict<QWSServer::KeyMap> *overrideMap = 0;
70
71 /*!
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.
76
77   Passing a null pointer for \a map will revert to the default keymap.
78 */
79
80 void QWSServer::setOverrideKeys( QIntDict<QWSServer::KeyMap> *map )
81 {
82     delete overrideMap;
83     overrideMap = map;
84 }
85
86 /*!
87   \class QWSKeyboardHandler qkeyboard_qws.h
88   \brief Keyboard driver/handler for Qt/Embedded
89
90   The keyboard driver/handler handles events from system devices and
91   generates key events.
92
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.
97 */
98
99 /*!
100   Subclasses call this to send a key event. The server may additionally
101   filter it before sending it on to applications.
102
103   <ul>
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.
111   </ul>
112 */
113 void QWSKeyboardHandler::processKeyEvent(int unicode, int keycode, int modifiers,
114                         bool isPress, bool autoRepeat)
115 {
116     qwsServer->processKeyEvent( unicode, keycode, modifiers, isPress, autoRepeat );
117 }
118
119
120 bool qwsSetKeyboardAutoRepeat( int /* delay */ , int /* period */ )
121 {
122     return FALSE;
123 }
124
125 bool qwsGetKeyboardAutoRepeat( int /* delay */ , int /* period */ )
126 {
127     return FALSE;
128 }
129
130 void qwsRestoreKeyboardLeds()
131 {
132 }
133
134
135
136
137
138 /*
139  * Virtual framebuffer keyboard driver
140  */
141
142 class QWSVFbKeyboardHandler : public QWSKeyboardHandler
143 {
144     Q_OBJECT
145 public:
146     QWSVFbKeyboardHandler();
147     virtual ~QWSVFbKeyboardHandler();
148
149     bool isOpen() { return fd > 0; }
150
151 private slots:
152     void readKeyboardData();
153
154 private:
155     QString terminalName;
156     int fd;
157     int kbdIdx;
158     int kbdBufferLen;
159     unsigned char *kbdBuffer;
160     QSocketNotifier *notifier;
161 };
162
163 #ifndef QT_NO_QWS_VFB
164 #include "qvfbhdr.h"
165 extern int qws_display_id;
166 #endif
167
168 QWSVFbKeyboardHandler::QWSVFbKeyboardHandler()
169 {
170     kbdFD = -1;
171 #ifndef QT_NO_QWS_VFB
172     kbdIdx = 0;
173     kbdBufferLen = sizeof( QVFbKeyData ) * 5;
174     kbdBuffer = new unsigned char [kbdBufferLen];
175
176     terminalName = QString(QT_VFB_KEYBOARD_PIPE).arg(qws_display_id);
177
178     if ((kbdFD = open( terminalName.local8Bit(), O_RDWR | O_NDELAY)) < 0) {
179         qDebug( "Cannot open %s (%s)", terminalName.latin1(),
180         strerror(errno));
181     } else {
182         // Clear pending input
183         char buf[2];
184         while (read(kbdFD, buf, 1) > 0) { }
185
186         notifier = new QSocketNotifier( kbdFD, QSocketNotifier::Read, this );
187         connect(notifier, SIGNAL(activated(int)),this, SLOT(readKeyboardData()));
188     }
189 #endif
190 }
191
192 QWSVFbKeyboardHandler::~QWSVFbKeyboardHandler()
193 {
194 #ifndef QT_NO_QWS_VFB
195     if ( kbdFD >= 0 )
196         close( kbdFD );
197     delete [] kbdBuffer;
198 #endif
199 }
200
201
202 void QWSVFbKeyboardHandler::readKeyboardData()
203 {
204 #ifndef QT_NO_QWS_VFB
205     int n;
206     do {
207         n  = read(kbdFD, kbdBuffer+kbdIdx, kbdBufferLen - kbdIdx );
208         if ( n > 0 )
209             kbdIdx += n;
210     } while ( n > 0 );
211
212     int idx = 0;
213     while ( kbdIdx - idx >= (int)sizeof( QVFbKeyData ) ) {
214         QVFbKeyData *kd = (QVFbKeyData *)(kbdBuffer + idx);
215         if ( kd->unicode == 0 && kd->modifiers == 0 && kd->press ) {
216             // magic exit key
217             qWarning( "Instructed to quit by Virtual Keyboard" );
218             qApp->quit();
219         }
220         processKeyEvent( kd->unicode&0xffff, kd->unicode>>16,
221                                  kd->modifiers, kd->press, kd->repeat );
222         idx += sizeof( QVFbKeyData );
223     }
224
225     int surplus = kbdIdx - idx;
226     for ( int i = 0; i < surplus; i++ )
227         kbdBuffer[i] = kbdBuffer[idx+i];
228     kbdIdx = surplus;
229 #endif
230 }
231
232
233
234
235 struct termios origTermData;
236
237 static void init_kbd(void)
238 {
239     struct termios termdata;
240
241     tcgetattr( kbdFD, &origTermData );
242     tcgetattr( kbdFD, &termdata );
243
244     ioctl(kbdFD, KDSKBMODE, K_XLATE);
245
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);
255 }
256
257 static void done_kbd(void)
258 {
259     if (kbdFD >= 0) {
260         tcsetattr(kbdFD, TCSANOW, &origTermData);
261     }
262 }
263
264 static void vtSwitchHandler(int /*sig*/)
265 {
266     if (vtActive) {
267         qwsServer->enablePainting(false);
268         qt_screen->save();
269         if (ioctl(kbdFD, VT_RELDISP, VT_ACKACQ) == 0) {
270             vtActive = false;
271             qwsServer->closeMouse();
272             done_kbd();
273         }
274         else {
275             qwsServer->enablePainting(true);
276         }
277         usleep(200000);
278     }
279     else {
280         if (ioctl(kbdFD, VT_RELDISP, VT_ACKACQ) == 0) {
281             init_kbd();
282             qwsServer->enablePainting(true);
283             vtActive = true;
284             qt_screen->restore();
285             qwsServer->openMouse();
286             qwsServer->refresh();
287         }
288     }
289     signal(VTSWITCHSIG, vtSwitchHandler);
290 }
291
292
293
294 class QWSRamsesKbPrivate;
295 class QWSRamsesKeyboardHandler : public QWSKeyboardHandler
296 {
297 public:
298     QWSRamsesKeyboardHandler( const QString& );
299     virtual ~QWSRamsesKeyboardHandler();
300
301     virtual void processKeyEvent(int unicode, int keycode, int modifiers,
302                                 bool isPress, bool autoRepeat);
303
304 private:
305     QWSRamsesKbPrivate *d;
306 };
307
308
309 class QWSRamsesKbPrivate : public QObject
310 {
311     Q_OBJECT
312 public:
313     QWSRamsesKbPrivate( QWSRamsesKeyboardHandler *, const QString &device );
314     ~QWSRamsesKbPrivate();
315
316 private slots:
317     void readKeyboardData();
318
319 private:
320     void handleKey(unsigned char code, int n);
321
322     QWSRamsesKeyboardHandler *handler;
323     char rbuf[255];
324     int  rptr;
325 };
326
327 QWSRamsesKbPrivate::QWSRamsesKbPrivate( QWSRamsesKeyboardHandler *h, const QString &device )
328   : handler(h), rptr(0)
329 {
330 #ifdef QT_QWS_DEVFS
331     kbdFD = ::open(device.isEmpty()?"/dev/vc/2":device.latin1(), O_RDWR|O_NDELAY, 0);
332 #else
333     kbdFD = ::open(device.isEmpty()?"/dev/tty2":device.latin1(), O_RDWR|O_NDELAY, 0);
334 #endif
335
336     if ( kbdFD >= 0 ) {
337         QSocketNotifier *notifier;
338         notifier = new QSocketNotifier( kbdFD, QSocketNotifier::Read, this );
339         connect( notifier, SIGNAL(activated(int)),this, SLOT(readKeyboardData()) );
340     } else {
341         qDebug( "Cannot open keyboard" );
342     }
343     init_kbd();
344
345     struct vt_mode vtMode;
346     ioctl(kbdFD, VT_GETMODE, &vtMode);
347
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);
353
354     struct vt_stat vtStat;
355     ioctl(kbdFD, VT_GETSTATE, &vtStat);
356     vtQws = vtStat.v_active;
357
358     signal(VTSWITCHSIG, vtSwitchHandler);
359 }
360
361 QWSRamsesKbPrivate::~QWSRamsesKbPrivate()
362 {
363     signal(VTSWITCHSIG, 0);
364
365     done_kbd();
366
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
371      *               kind of thinking!
372      */
373     vtMode.mode = VT_AUTO;
374     vtMode.relsig = 0;
375     vtMode.acqsig = 0;
376     ioctl(kbdFD, VT_SETMODE, &vtMode);
377
378     ::close(kbdFD);
379     kbdFD = -1;
380 }
381
382
383 static inline int map_to_modif(int current_map)
384 {
385     int modifiers = 0;
386
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;
393
394     return modifiers;
395 }
396
397 struct {
398         const char *code;
399         unsigned short qtcode;
400 } qtesc_lookup[] = {
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 },
409
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 },
422
423         // { "\ex",   Qt::FieldExit },
424         // { "\er",   Qt::FieldReset },
425
426 };
427
428 struct {
429         unsigned char code;
430         unsigned short qtcode;
431 } qtkey_lookup[] = {
432         { 0x08,  Qt::Key_Backspace },
433         { 0x09,  Qt::Key_Tab },
434         { 0x0d,  Qt::Key_Enter },
435         { 0x1b,  Qt::Key_Escape },
436 };
437
438 void QWSRamsesKbPrivate::handleKey(unsigned char code, int n)
439 {
440         int qtKeyCode = Qt::Key_unknown;
441         unsigned int i;
442
443         //qDebug("\nhandleKey %02x %d %c", code, n, code >= ' ' ? code : ' ');
444
445         // Single keys
446         if ((n==1) && (rptr==0)) {
447                 qtKeyCode = code;
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;
451                                 code = 0;
452                                 break;
453                         }
454                 }
455         } else
456
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);
464                 rptr = 0;
465                 return;
466         } else
467
468         // End of a function key sequence
469         if ((n==1) && (rptr!=0)) {
470                 rbuf[rptr++] = code;
471                 rbuf[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;
475                                 code = 0;
476                                 break;
477                         }
478                 }
479                 if (code != 0) {
480                         //qWarning("no entry in key sequence table for %s", &rbuf[1]);
481                         int oldrptr = rptr;
482                         rptr = 0;
483                         for (i=0; i <= oldrptr; i++) {
484                                 handleKey(rbuf[i], 1);
485                         }
486                         return;
487                 }
488                 rptr = 0;
489         } else
490
491         // Middle of a function key sequence
492         {
493                 if (rptr < sizeof(rbuf))
494                         rbuf[rptr++] = code;
495                 return;
496         }
497
498         //qDebug(" code 0x%2x %d -> qtKeyCode 0x%04x", code, code, qtKeyCode);
499
500         handler->processKeyEvent(code, qtKeyCode, 0, 1, 0);
501         handler->processKeyEvent(code, qtKeyCode, 0, 0, 0);
502 }
503
504
505 void QWSRamsesKbPrivate::readKeyboardData()
506 {
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);
511     }
512 }
513
514
515
516
517
518 QWSRamsesKeyboardHandler::QWSRamsesKeyboardHandler( const QString &device )
519 {
520     d = new QWSRamsesKbPrivate( this, device );
521 }
522
523 QWSRamsesKeyboardHandler::~QWSRamsesKeyboardHandler()
524 {
525     delete d;
526 }
527
528 void QWSRamsesKeyboardHandler::processKeyEvent(int unicode, int keycode,
529                     int modifiers, bool isPress, bool autoRepeat)
530 {
531     // Virtual console switching
532     int term = 0;
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);
543         return;
544     }
545
546     QWSKeyboardHandler::processKeyEvent( unicode, keycode, modifiers, isPress, autoRepeat );
547 }
548
549
550
551 /*
552  * keyboard driver instantiation
553  */
554
555 QWSKeyboardHandler *QWSServer::newKeyboardHandler( const QString &spec )
556 {
557     QWSKeyboardHandler *handler = 0;
558
559     QString device;
560     QString type;
561     int colon=spec.find(':');
562     if ( colon>=0 ) {
563         type = spec.left(colon);
564         device = spec.mid(colon+1);
565     } else {
566         type = spec;
567     }
568
569     if ( type == "QVFbKeyboard" ) {
570         handler = new QWSVFbKeyboardHandler();
571     } else if ( type == "TTY" ) {
572         handler = new QWSRamsesKeyboardHandler(device);
573     } else {
574         qWarning( "Keyboard type %s:%s unsupported", spec.latin1(), device.latin1() );
575     }
576
577     return handler;
578 }
579
580 #include "qkeyboard_qws.moc"
581
582 #endif // QT_NO_QWS_KEYBOARD
583
584