]> git.karo-electronics.de Git - karo-tx-redboot.git/blob - packages/services/gfx/mw/v2_0/src/drivers/kbd_x11.c
Initial revision
[karo-tx-redboot.git] / packages / services / gfx / mw / v2_0 / src / drivers / kbd_x11.c
1 /*
2  * Copyright (c) 1999, 2000 Greg Haerr <greg@censoft.com>
3  * Author: Tony Rogvall <tony@bluetail.com>
4  *
5  * Converted to scancode mode by Greg Haerr
6  *
7  * X11 Keyboard driver
8  */
9 #include <stdio.h>
10 #include <unistd.h>
11 #include <errno.h>
12 #include <X11/Xlib.h>
13 #include <X11/Xutil.h>
14 #include <X11/keysym.h>
15 #include <X11/XKBlib.h>
16 #include "device.h"
17
18 static int  X11_Open(KBDDEVICE *pkd);
19 static void X11_Close(void);
20 static void X11_GetModifierInfo(MWKEYMOD *modifiers, MWKEYMOD *curmodifiers);
21 static int  X11_Read(MWKEY *kbuf, MWKEYMOD *modifiers, MWSCANCODE *scancode);
22
23 static int init_modstate();
24
25 static MWKEYMOD key_modstate;
26 extern int escape_quits;
27
28 extern Display*     x11_dpy;
29 extern int          x11_scr;
30 extern Visual*      x11_vis;
31 extern Window       x11_win;
32 extern GC           x11_gc;
33 extern int          x11_setup_display();
34
35 #define X_SCR_MASK 0x80
36 #define X_CAP_MASK 0x2
37 #define X_NUM_MASK 0x10
38
39 KBDDEVICE kbddev = {
40     X11_Open,
41     X11_Close,
42     X11_GetModifierInfo,
43     X11_Read,
44     NULL
45 };
46
47 /*
48  * Open the keyboard.
49  * This is real simple, we just use a special file handle
50  * that allows non-blocking I/O, and put the terminal into
51  * character mode.
52  */
53 static int
54 X11_Open(KBDDEVICE *pkd)
55 {
56     if (x11_setup_display() < 0)
57         return -1;
58
59     if(init_modstate() < 0)
60         return -1;
61     
62     /* return the x11 file descriptor for select */
63     return ConnectionNumber(x11_dpy);  
64 }
65
66 /*
67  * Close the keyboard.
68  * This resets the terminal modes.
69  */
70 static void
71 X11_Close(void)
72 {
73     /* nop */
74 }
75
76 /*
77  * Return the possible modifiers for the keyboard.
78  */
79 static  void
80 X11_GetModifierInfo(MWKEYMOD *modifiers, MWKEYMOD *curmodifiers)
81 {
82         if (modifiers)
83                 *modifiers = MWKMOD_SHIFT | MWKMOD_CTRL | MWKMOD_ALT;
84         if (curmodifiers)
85                 *curmodifiers = key_modstate;
86 }
87
88 /*
89  * This reads one keystroke from the keyboard, and the current state of
90  * the modifier keys (ALT, SHIFT, etc).  Returns -1 on error, 0 if no data
91  * is ready, 1 on a keypress, and 2 on keyrelease.
92  * This is a non-blocking call.
93  */
94 static int
95 X11_Read(MWKEY *kbuf, MWKEYMOD *modifiers, MWSCANCODE *scancode)
96 {
97         XEvent ev;
98         MWKEY mwkey;
99
100         static int grabbed = 0;
101         static int x11_accel_num;
102         static int x11_accel_den;
103         static int x11_thres;
104
105     /* check if we have a KeyPressedEvent */
106     if (XCheckMaskEvent(x11_dpy, KeyPressMask|KeyReleaseMask, &ev)) {
107         KeySym sym = XKeycodeToKeysym(x11_dpy, ev.xkey.keycode, 0);
108
109         if (sym == NoSymbol)
110             return -1;
111
112         /* calculate kbd modifiers*/
113         key_modstate &= (MWKMOD_NUM|MWKMOD_CAPS|MWKMOD_SCR); 
114         if (ev.xkey.state & ControlMask)
115                 key_modstate |= MWKMOD_CTRL; 
116         if (ev.xkey.state & ShiftMask)
117                 key_modstate |= MWKMOD_SHIFT;
118         if (ev.xkey.state & Mod1Mask)
119                 key_modstate |= MWKMOD_ALT;
120         if (ev.xkey.state & X_CAP_MASK)
121                 key_modstate |= MWKMOD_CAPS;
122         if (ev.xkey.state & X_SCR_MASK)
123                 key_modstate |= MWKMOD_SCR;
124         if (ev.xkey.state & X_NUM_MASK)
125                 key_modstate |= MWKMOD_NUM;
126
127         if (sym == XK_Escape) {
128             mwkey = MWKEY_ESCAPE;
129
130             if (ev.xkey.state & ControlMask) {
131                 /* toggle grab control */
132                 if (grabbed) {
133                     XUngrabPointer(x11_dpy, CurrentTime);
134                     XUngrabKeyboard(x11_dpy, CurrentTime);
135                     XChangePointerControl(x11_dpy, True, False, x11_accel_num, 
136                           x11_accel_den, 0);
137                     grabbed = 0;
138                 }
139                 else {
140                     /* save pointer config */
141                     XGetPointerControl(x11_dpy, &x11_accel_num, &x11_accel_den,
142                             &x11_thres);
143                     XChangePointerControl(x11_dpy, True, False, 1, 1, 0);
144                     XGrabKeyboard(x11_dpy, x11_win,
145                             True,  /* only to this window */
146                             GrabModeAsync, GrabModeAsync, CurrentTime);
147                     XGrabPointer(x11_dpy, x11_win, False,
148                                  PointerMotionMask | ButtonPressMask,
149                                  GrabModeAsync, GrabModeAsync, None, None,
150                                  CurrentTime);
151                     grabbed = 1;
152                 }
153                 return 0;
154             } else if (grabbed)
155                 XChangePointerControl(x11_dpy, True, False, x11_accel_num, 
156                       x11_accel_den, 0);
157             *kbuf = mwkey;
158             *modifiers = key_modstate;
159             *scancode = ev.xkey.keycode;
160             return (ev.xkey.type == KeyPress)? 1: 2;
161         } else {
162             switch (sym) {
163             case XK_Delete:
164                     mwkey = MWKEY_DELETE;
165                     break;
166             case XK_Home:
167                     mwkey = MWKEY_HOME;
168                     break;
169             case XK_Left:
170                     mwkey = MWKEY_LEFT;
171                     break;
172             case XK_Up:
173                     mwkey = MWKEY_UP;
174                     break;
175             case XK_Right:
176                     mwkey = MWKEY_RIGHT;
177                     break;
178             case XK_Down:
179                     mwkey = MWKEY_DOWN;
180                     break;
181             case XK_Page_Up:
182                     mwkey = MWKEY_PAGEUP;
183                     break;
184             case XK_Page_Down:
185                     mwkey = MWKEY_PAGEDOWN;
186                     break;
187             case XK_End:
188                     mwkey = MWKEY_END;
189                     break;
190             case XK_Insert:
191                     mwkey = MWKEY_INSERT;
192                     break;
193             case XK_Pause:
194             case XK_Break:
195                     mwkey = MWKEY_QUIT;
196                     break;
197             case XK_Print:
198             case XK_Sys_Req:
199                     mwkey = MWKEY_PRINT;
200                     break;
201             case XK_Menu:
202                     mwkey = MWKEY_MENU;
203                     break;
204             case XK_Cancel:
205                     mwkey = MWKEY_CANCEL;
206                     break;
207             case XK_KP_Enter:
208                     mwkey = MWKEY_KP_ENTER;
209                     break;
210             case XK_KP_Home:
211                     mwkey = MWKEY_KP7;
212                     break;
213             case XK_KP_Left:
214                     mwkey = MWKEY_KP4;
215                     break;
216             case XK_KP_Up:
217                     mwkey = MWKEY_KP8;
218                     break;
219             case XK_KP_Right:
220                     mwkey = MWKEY_KP6;
221                     break;
222             case XK_KP_Down:
223                     mwkey = MWKEY_KP2;
224                     break;
225             case XK_KP_Page_Up:
226                     mwkey = MWKEY_KP9;
227                     break;
228             case XK_KP_Page_Down:
229                     mwkey = MWKEY_KP3;
230                     break;
231             case XK_KP_End:
232                     mwkey = MWKEY_KP1;
233                     break;
234             case XK_KP_Insert:
235                     mwkey = MWKEY_KP0;
236                     break;
237             case XK_KP_Delete:
238                     mwkey = MWKEY_KP_PERIOD;
239                     break;
240             case XK_KP_Equal:
241                     mwkey = MWKEY_KP_EQUALS;
242                     break;
243             case XK_KP_Multiply:
244                     mwkey = MWKEY_KP_MULTIPLY;
245                     break;
246             case XK_KP_Add:
247                     mwkey = MWKEY_KP_PLUS;
248                     break;
249             case XK_KP_Subtract:
250                     mwkey = MWKEY_KP_MINUS;
251                     break;
252             case XK_KP_Decimal:
253                     mwkey = MWKEY_KP_PERIOD;
254                     break;
255             case XK_KP_Divide:
256                     mwkey = MWKEY_KP_DIVIDE;
257                     break;
258             case XK_KP_5:
259             case XK_KP_Begin:
260                     mwkey = MWKEY_KP5;
261                     break;
262             case XK_F1:
263                     mwkey = MWKEY_F1;
264                     break;
265             case XK_F2:
266                     mwkey = MWKEY_F2;
267                     break;
268             case XK_F3:
269                     mwkey = MWKEY_F3;
270                     break;
271             case XK_F4:
272                     mwkey = MWKEY_F4;
273                     break;
274             case XK_F5:
275                     mwkey = MWKEY_F5;
276                     break;
277             case XK_F6:
278                     mwkey = MWKEY_F6;
279                     break;
280             case XK_F7:
281                     mwkey = MWKEY_F7;
282                     break;
283             case XK_F8:
284                     mwkey = MWKEY_F8;
285                     break;
286             case XK_F9:
287                     mwkey = MWKEY_F9;
288                     break;
289             case XK_F10:
290                     mwkey = MWKEY_F10;
291                     break;
292             case XK_F11:
293                     mwkey = MWKEY_F11;
294                     break;
295             case XK_F12:
296                     mwkey = MWKEY_F12;
297                     break;
298
299             /* state modifiers*/
300             case XK_Num_Lock:
301                     /* not sent, used only for state*/
302                     if (ev.xkey.type == KeyRelease)
303                         key_modstate ^= MWKMOD_NUM;
304                     return 0;
305             case XK_Shift_Lock:
306             case XK_Caps_Lock:
307                     /* not sent, used only for state*/
308                     if (ev.xkey.type == KeyRelease)
309                         key_modstate ^= MWKMOD_CAPS;
310                     return 0;
311             case XK_Scroll_Lock:
312                     /* not sent, used only for state*/
313                     if (ev.xkey.type == KeyRelease)
314                         key_modstate ^= MWKMOD_SCR;
315                     return 0;
316                     break;
317             case XK_Shift_L:
318                     mwkey = MWKEY_LSHIFT;
319                     break;
320             case XK_Shift_R:
321                     mwkey = MWKEY_RSHIFT;
322                     break;
323             case XK_Control_L:
324                     mwkey = MWKEY_LCTRL;
325                     break;
326             case XK_Control_R:
327                     mwkey = MWKEY_RCTRL;
328                     break;
329             case XK_Alt_L:
330                     mwkey = MWKEY_LALT;
331                     break;
332             case XK_Alt_R:
333                     mwkey = MWKEY_RALT;
334                     break;
335             case XK_Meta_L:
336             case XK_Super_L:
337             case XK_Hyper_L:
338                     mwkey = MWKEY_LMETA;
339                     break;
340             case XK_Meta_R:
341             case XK_Super_R:
342             case XK_Hyper_R:
343                     mwkey = MWKEY_RMETA;
344                     break;
345             default:
346                     switch (sym) {
347                     case XK_BackSpace:
348                     case XK_Tab:
349                     case XK_Return:
350                         break;
351                     default:
352                         if (sym & 0xFF00)
353                             fprintf(stderr, "Unhandled X11 keysym: %04x\n", (int)sym);
354                     }
355
356                     XLookupString(&ev.xkey, &mwkey, 1, &sym, NULL );
357
358                     if (key_modstate & MWKMOD_CTRL)
359                                 mwkey = sym & 0x1f;     /* Control code */ 
360                         else
361                                 mwkey = sym & 0xff;     /* ASCII*/
362
363                     break;
364
365             }
366             if (key_modstate & MWKMOD_NUM) {
367                 switch (mwkey) {
368                 case MWKEY_KP0:
369                 case MWKEY_KP1:
370                 case MWKEY_KP2:
371                 case MWKEY_KP3:
372                 case MWKEY_KP4:
373                 case MWKEY_KP5:
374                 case MWKEY_KP6:
375                 case MWKEY_KP7:
376                 case MWKEY_KP8:
377                 case MWKEY_KP9:
378                         mwkey = mwkey - MWKEY_KP0 + '0';
379                         break;
380                 case MWKEY_KP_PERIOD:
381                         mwkey = '.';
382                         break;
383                 case MWKEY_KP_DIVIDE:
384                         mwkey = '/';
385                         break;
386                 case MWKEY_KP_MULTIPLY:
387                         mwkey = '*';
388                         break;
389                 case MWKEY_KP_MINUS:
390                         mwkey = '-';
391                         break;
392                 case MWKEY_KP_PLUS:
393                         mwkey = '+';
394                         break;
395                 case MWKEY_KP_ENTER:
396                         mwkey = MWKEY_ENTER;
397                         break;
398                 case MWKEY_KP_EQUALS:
399                         mwkey = '-';
400                         break;
401                 }
402             }
403             *modifiers = key_modstate;
404             *scancode = ev.xkey.keycode;
405             *kbuf = mwkey;
406
407             //printf("mods: 0x%x  scan: 0x%x  key: 0x%x\n",*modifiers
408             //                                          ,*scancode
409             //                                          ,*kbuf);
410             return (ev.xkey.type == KeyPress)? 1 : 2;
411         }
412     }
413     return 0;
414 }
415
416 #define NUM_LOCK_MASK    0x00000002
417 #define CAPS_LOCK_MASK   0x00000001
418 #define SCROLL_LOCK_MASK 0x00000004
419
420 /* initialise key_modstate */ 
421 static int init_modstate ()
422 {
423         unsigned int state;
424         int capsl, numl, scrolll;
425
426         if(XkbGetIndicatorState (x11_dpy, XkbUseCoreKbd, &state) != Success) {
427                 fprintf(stderr, "Error reading Indicator status\n");
428                 return -1; 
429         } 
430         capsl = state & CAPS_LOCK_MASK;
431         numl = state & NUM_LOCK_MASK;
432         scrolll = state & SCROLL_LOCK_MASK;
433
434         if(numl != 0)
435                 key_modstate |= MWKMOD_NUM;
436
437         if(capsl != 0)
438                 key_modstate |= MWKMOD_CAPS;
439
440         if(scrolll != 0)
441                 key_modstate |= MWKMOD_SCR;
442
443         return 0;
444 }
445