Added missing properties.
[AROS.git] / arch / all-hosted / hidd / x11 / x11kbd.c
blob813a84337bb3e3b3691c67d07f93ecdc1075671a
1 /*
2 Copyright © 1995-2010, The AROS Development Team. All rights reserved.
3 $Id$
5 Desc: X11 hidd handling keypresses.
6 Lang: English.
7 */
8 #define DEBUG 0
10 #define __OOP_NOATTRBASES__
12 #include <dos/dos.h>
14 #include <proto/dos.h>
15 #include <proto/utility.h>
16 #include <proto/oop.h>
17 #include <oop/oop.h>
19 #define timeval sys_timeval
20 #include <X11/Xlib.h>
21 #include <X11/keysym.h>
22 #include <X11/Xutil.h>
24 #include <stdio.h>
25 #undef timeval
27 #include <hidd/hidd.h>
28 #include <hidd/keyboard.h>
30 #include <devices/inputevent.h>
32 #include <aros/symbolsets.h>
34 //#define DEBUG 1
35 #include <aros/debug.h>
37 #include LC_LIBDEFS_FILE
39 #include "x11.h"
41 /****************************************************************************************/
43 long xkey2hidd (XKeyEvent *xk, struct x11_staticdata *xsd);
45 static OOP_AttrBase HiddKbdAB;
47 static struct OOP_ABDescr attrbases[] =
49 { IID_Hidd_Kbd , &HiddKbdAB },
50 { NULL , NULL }
53 /****************************************************************************************/
55 static struct _keytable
57 KeySym keysym;
58 WORD hiddcode;
60 keytable[] =
62 {XK_Return, 0x44 },
63 {XK_Right, 0x4e },
64 {XK_Up, 0x4c },
65 {XK_Left, 0x4f },
66 {XK_Down, 0x4d },
67 {XK_Help, 0x5f },
69 {XK_BackSpace, 0x41 },
70 {XK_Delete, 0x46 },
71 {XK_space, 0x40 },
72 {XK_Shift_L, 0x60 },
73 {XK_Shift_R, 0x61 },
74 {XK_Caps_Lock, 0x62 },
75 {XK_Alt_L, 0x64 },
76 {XK_Alt_R, 0x65 },
77 {XK_Escape, 0x45 },
78 {XK_Tab, 0x42 },
80 {XK_F1, 0x50 },
81 {XK_F2, 0x51 },
82 {XK_F3, 0x52 },
83 {XK_F4, 0x53 },
84 {XK_F5, 0x54 },
85 {XK_F6, 0x55 },
86 {XK_F7, 0x56 },
87 {XK_F8, 0x57 },
88 {XK_F9, 0x58 },
89 {XK_F10, 0x59 },
91 {XK_F11, 0x4B },
92 {XK_F12, 0x5f }, /* HELP, F12 would be 0x6F */
93 {XK_Home, 0x70 },
94 {XK_End, 0x71 },
95 {XK_Insert, 0x47 },
96 {XK_Prior, 0x48 }, /* PageUP */
97 {XK_Next, 0x49 }, /* PageDown */
98 {XK_Print, 0x6c },
99 {XK_Scroll_Lock, 0x6b },
100 {XK_Pause, 0x6e },
102 {XK_KP_Enter, 0x43 },
103 {XK_KP_Subtract, 0x4a },
104 {XK_KP_Decimal, 0x3c },
105 {XK_KP_Separator, 0x3c },
106 {XK_KP_Delete, 0x3c },
107 {XK_KP_Add, 0x5e },
108 {XK_KP_Subtract, 0x4a },
109 {XK_KP_Multiply, 0x5d },
110 {XK_KP_Divide, 0x5c },
112 {XK_KP_0, 0x0f },
113 {XK_KP_Insert, 0x0f },
114 {XK_KP_1, 0x1d },
115 {XK_KP_End, 0x1d },
116 {XK_KP_2, 0x1e },
117 {XK_KP_Down, 0x1e },
118 {XK_KP_3, 0x1f },
119 {XK_KP_Page_Down, 0x1f },
120 {XK_KP_4, 0x2d },
121 {XK_KP_Left, 0x2d },
122 {XK_KP_5, 0x2e },
123 {XK_KP_Begin, 0x2e },
124 {XK_KP_6, 0x2f },
125 {XK_KP_Right, 0x2f },
126 {XK_KP_7, 0x3d },
127 {XK_KP_Home, 0x3d },
128 {XK_KP_8, 0x3e },
129 {XK_KP_Up, 0x3e },
130 {XK_KP_9, 0x3f },
131 {XK_KP_Page_Up, 0x3f },
133 {XK_E, 0x12 },
134 {XK_e, 0x12 },
135 {XK_R, 0x13 },
136 {XK_r, 0x13 },
137 {XK_T, 0x14 },
138 {XK_t, 0x14 },
139 {XK_U, 0x16 },
140 {XK_u, 0x16 },
141 {XK_I, 0x17 },
142 {XK_i, 0x17 },
143 {XK_O, 0x18 },
144 {XK_o, 0x18 },
145 {XK_P, 0x19 },
146 {XK_p, 0x19 },
148 {XK_S, 0x21 },
149 {XK_s, 0x21 },
150 {XK_D, 0x22 },
151 {XK_d, 0x22 },
152 {XK_F, 0x23 },
153 {XK_f, 0x23 },
154 {XK_G, 0x24 },
155 {XK_g, 0x24 },
156 {XK_H, 0x25 },
157 {XK_h, 0x25 },
158 {XK_J, 0x26 },
159 {XK_j, 0x26 },
160 {XK_K, 0x27 },
161 {XK_k, 0x27 },
162 {XK_L, 0x28 },
163 {XK_l, 0x28 },
165 {XK_X, 0x32 },
166 {XK_x, 0x32 },
167 {XK_c, 0x33 },
168 {XK_C, 0x33 },
169 {XK_V, 0x34 },
170 {XK_v, 0x34 },
171 {XK_B, 0x35 },
172 {XK_b, 0x35 },
173 {XK_N, 0x36 },
174 {XK_n, 0x36 },
176 {XK_1, 0x01 },
177 {XK_2, 0x02 },
178 {XK_3, 0x03 },
179 {XK_4, 0x04 },
180 {XK_5, 0x05 },
181 {XK_6, 0x06 },
182 {XK_7, 0x07 },
183 {XK_8, 0x08 },
184 {XK_9, 0x09 },
185 {XK_0, 0x0A },
186 {0, - 1 }
189 /****************************************************************************************/
191 /* English keyboard */
192 static struct _keytable english_keytable[] =
194 {XK_Control_L, 0x63 }, /* left control = control */
195 {XK_Multi_key, 0x63 }, /* right control = control */
196 {XK_Super_L, 0x66 }, /* left win = LAMIGA */
197 {XK_Super_R, 0x67 }, /* right win = RAMIGA */
198 {XK_Menu, 0x67 }, /* menu key = RAMIGA */
199 {XK_Meta_L, 0x64 }, /* left Alt = LALT */
200 {XK_Mode_switch, 0x65 }, /* right Alt = RALT */
202 /* Key left of S */
203 {XK_A, 0x20 },
204 {XK_a, 0x20 },
206 /* Key right of N */
207 {XK_M, 0x37 },
208 {XK_m, 0x37 },
210 /* Key right of TAB */
211 {XK_Q, 0x10 },
212 {XK_q, 0x10 },
214 /* Key between T and U */
215 {XK_y, 0x15 },
216 {XK_Y, 0x15 },
218 /* Key left of E */
219 {XK_W, 0x11 },
220 {XK_w, 0x11 },
222 /* Key left of X */
223 {XK_z, 0x31 },
224 {XK_Z, 0x31 },
227 /* Key left of 1 */
228 {XK_grave, 0x00 },
230 /* Keys right of 0 */
231 {XK_minus, 0x0B },
232 {XK_equal, 0x0C },
234 /* Keys right of P */
235 {XK_bracketleft, 0x1A },
236 {XK_bracketright, 0x1B },
238 /* Keys right of L */
239 {XK_semicolon, 0x29 },
240 {XK_apostrophe, 0x2A },
241 {XK_backslash, 0x2B }, /* Third key right of L might not be present */
243 /* Key right of shift and 2nd left of X (might not be present) */
244 {XK_less, 0x30 },
246 /* Keys 2nd right of N (= usually right of M) */
247 {XK_comma, 0x38 },
248 {XK_period, 0x39 },
249 {XK_slash, 0x3A },
251 {0, -1 }
254 /****************************************************************************************/
256 #if 0
257 /* German keyboard */
258 static struct _keytable german_keytable[] =
260 {XK_Control_L, 0x63 }, /* linke STRG = control */
261 {XK_Multi_key, 0x63 }, /* rechte STRG = control */
262 {XK_Super_L, 0x66 }, /* Linke Win = LAMIGA */
263 {XK_Super_R, 0x67 }, /* Rechte Win = RAMIGA */
264 {XK_Meta_L, 0x64 }, /* Linke Alt = LALT */
265 {XK_Mode_switch, 0x65 }, /* Alt Gr = RALT */
267 /* Key left of S */
268 {XK_A, 0x20 },
269 {XK_a, 0x20 },
271 /* Key right of N */
272 {XK_M, 0x37 },
273 {XK_m, 0x37 },
275 /* Key right of TAB */
276 {XK_Q, 0x10 },
277 {XK_q, 0x10 },
279 /* Key between T and U */
280 {XK_Z, 0x15 },
281 {XK_z, 0x15 },
283 /* Key left of E */
284 {XK_W, 0x11 },
285 {XK_w, 0x11 },
287 /* Key left of X */
288 {XK_y, 0x31 },
289 {XK_Y, 0x31 },
291 /* Key left of 1 */
292 {XK_asciicircum, 0x00 }, /* Akzent links neben 1 Taste */
294 /* Keys right of 0 */
295 {XK_equal, 0x0A }, /* = */
296 {XK_ssharp, 0x0B }, /* scharfes s */
297 {XK_acute, 0x0C }, /* Akzent rechts von scharfem s */
299 /* Keys right of P */
300 {XK_udiaeresis, 0x1A }, /* Umlaut u */
301 {XK_Udiaeresis, 0x1A },
302 {XK_plus, 0x1B }, /* + */
304 /* Keys right of L */
305 {XK_odiaeresis, 0x29 }, /* Umlaut o */
306 {XK_Odiaeresis, 0x29 },
307 {XK_adiaeresis, 0x2A }, /* Umlaut a */
308 {XK_Adiaeresis, 0x2A },
309 {XK_numbersign, 0x2B }, /* # */
311 /* Key right of shift and 2nd left of X (might not be present) */
312 {XK_less, 0x30 }, /* < */
314 /* Keys 2nd right of N (= usually right of M) */
315 {XK_comma, 0x38 }, /* Komma */
316 {XK_period, 0x39 }, /* Punkt */
317 {XK_minus, 0x3A }, /* Minus */
319 {0, -1 }
321 #endif
323 #if 0
324 /* Italian keyboard */
325 static struct _keytable italian_keytable[] =
327 {XK_Control_L, 0x63 }, /* left CTRL = control */
328 {XK_Multi_key, 0x63 }, /* right CTRL = control */
329 {XK_Super_L, 0x66 }, /* left win = LAMIGA */
330 {XK_Super_R, 0x67 }, /* right win = RAMIGA */
331 {XK_Meta_L, 0x64 }, /* left alt = LALT */
332 {XK_Mode_switch, 0x65 }, /* right alt = RALT */
335 /* Key left of S */
336 {XK_A, 0x20 },
337 {XK_a, 0x20 },
339 /* Key right of N */
340 {XK_M, 0x37 },
341 {XK_m, 0x37 },
343 /* Key right of TAB */
344 {XK_Q, 0x10 },
345 {XK_q, 0x10 },
347 /* Key between T and U */
348 {XK_y, 0x15 },
349 {XK_Y, 0x15 },
351 /* Key left of E */
352 {XK_W, 0x11 },
353 {XK_w, 0x11 },
355 /* Key left of X */
356 {XK_z, 0x31 },
357 {XK_Z, 0x31 },
360 /* Key left of 1 */
361 {XK_backslash, 0x00 },
363 /* Keys right of 0 */
364 {XK_apostrophe, 0x0B },
365 {XK_Igrave, 0x0C },
366 {XK_igrave, 0x0C },
368 /* Keys right of P */
369 {XK_Egrave, 0x1A },
370 {XK_egrave, 0x1A },
371 {XK_plus, 0x1B }, /* + */
373 /* Keys right of L */
374 {XK_Ograve, 0x29 },
375 {XK_ograve, 0x29 },
376 {XK_Agrave, 0x2A },
377 {XK_agrave, 0x2A },
378 {XK_Ugrave, 0x2B }, /* Third key right of L might not be present */
379 {XK_ugrave, 0x2B },
381 /* Key right of shift and 2nd left of X (might not be present) */
382 {XK_less, 0x30 }, /* < */
384 /* Keys 2nd right of N (= usually right of M) */
385 {XK_comma, 0x38 },
386 {XK_period, 0x39 },
387 {XK_minus, 0x3A },
389 {0, -1 }
391 #endif
393 /****************************************************************************************/
395 #if 0
397 /* Use this template to create a keytable for your language:
399 Do not touch the right values (rawkey numbers). Only change
400 the XK's at the left side. To find out the XK_ names (keysym)
401 start "xev" and press the key the comment describes (for
402 example "Key left of S" in the xev window. In the Shell
403 window you will see output like this:
405 KeyPress event, serial 30, synthetic NO, window 0x5000001,
406 root 0x47, subw 0x5000002, time 3410089115, (24,45), root:(28,69),
407 state 0x0, keycode 50 (keysym 0xffe1, Shift_L), same_screen YES,
408 XLookupString gives 0 characters: "" |
410 This is the keysym name _______________/
412 So in this case you would have to write "XK_Shift_L"
414 Check all keys, not just the ones with "XK_????"!!!
417 static struct _keytable template_keytable[] =
419 {XK_Control_L, 0x63 }, /* left control = control */
420 {XK_Multi_key, 0x63 }, /* right control = control */
421 {XK_Super_L, 0x66 }, /* left win = LAMIGA */
422 {XK_Super_R, 0x67 }, /* right win = RAMIGA */
423 {XK_Meta_L, 0x64 }, /* left Alt = LALT */
424 {XK_Mode_switch, 0x65 }, /* right Alt = RALT */
426 /* Key left of S */
427 {XK_A, 0x20 },
428 {XK_a, 0x20 },
430 /* Key right of N */
431 {XK_M, 0x37 },
432 {XK_m, 0x37 },
434 /* Key right of TAB */
435 {XK_Q, 0x10 },
436 {XK_q, 0x10 },
438 /* Key between T and U */
439 {XK_????, 0x15 },
440 {XK_????, 0x15 },
442 /* Key left of E */
443 {XK_W, 0x11 },
444 {XK_w, 0x11 },
446 /* Key left of X */
447 {XK_????, 0x31 },
448 {XK_????, 0x31 },
451 /* Key left of 1 */
452 {XK_????, 0x00 },
454 /* Keys right of 0 */
455 {XK_????, 0x0B },
456 {XK_????, 0x0C },
458 /* Keys right of P */
459 {XK_????, 0x1A },
460 {XK_????, 0x1B },
462 /* Keys right of L */
463 {XK_????, 0x29 },
464 {XK_????, 0x2A },
465 {XK_????, 0x2B }, /* Third key right of L might not be present */
467 /* Key right of shift and 2nd left of X (might not be present) */
468 {XK_less, 0x30 },
470 /* Keys 2nd right of N (= usually right of M) */
471 {XK_comma, 0x38 },
472 {XK_period, 0x39 },
473 {XK_slash, 0x3A },
475 {0, -1 }
478 #endif
480 /****************************************************************************************/
482 OOP_Object * X11Kbd__Root__New(OOP_Class *cl, OOP_Object *o, struct pRoot_New *msg)
484 BOOL has_kbd_hidd = FALSE;
485 struct TagItem *tag, *tstate;
486 APTR callback = NULL;
487 APTR callbackdata = NULL;
489 EnterFunc(bug("X11Kbd::New()\n"));
491 ObtainSemaphoreShared( &XSD(cl)->sema);
493 if (XSD(cl)->kbdhidd)
494 has_kbd_hidd = TRUE;
496 ReleaseSemaphore( &XSD(cl)->sema);
498 if (has_kbd_hidd) { /* Cannot open twice */
499 D(bug("[X11Kbd] Attempt to create second instance\n"));
500 ReturnPtr("X11Kbd::New", OOP_Object *, NULL); /* Should have some error code here */
503 tstate = msg->attrList;
504 D(bug("tstate: %p, tag=%x\n", tstate, tstate->ti_Tag));
506 while ((tag = NextTagItem(&tstate)))
508 ULONG idx;
510 D(bug("Got tag %d, data %x\n", tag->ti_Tag, tag->ti_Data));
512 if (IS_HIDDKBD_ATTR(tag->ti_Tag, idx))
514 D(bug("Kbd hidd tag\n"));
515 switch (idx)
517 case aoHidd_Kbd_IrqHandler:
518 callback = (APTR)tag->ti_Data;
519 D(bug("Got callback %p\n", (APTR)tag->ti_Data));
520 break;
522 case aoHidd_Kbd_IrqHandlerData:
523 callbackdata = (APTR)tag->ti_Data;
524 D(bug("Got data %p\n", (APTR)tag->ti_Data));
525 break;
529 } /* while (tags to process) */
531 if (NULL == callback)
532 ReturnPtr("X11Kbd::New", OOP_Object *, NULL); /* Should have some error code here */
534 o = (OOP_Object *)OOP_DoSuperMethod(cl, o, (OOP_Msg)msg);
535 if (o)
537 struct x11kbd_data *data = OOP_INST_DATA(cl, o);
539 data->kbd_callback = (VOID (*)(APTR, UWORD))callback;
540 data->callbackdata = callbackdata;
541 data->prev_keycode = 0xFFFF;
543 ObtainSemaphore( &XSD(cl)->sema);
544 XSD(cl)->kbdhidd = o;
545 ReleaseSemaphore( &XSD(cl)->sema);
548 ReturnPtr("X11Kbd::New", OOP_Object *, o);
551 /****************************************************************************************/
553 VOID X11Kbd__Root__Dispose(OOP_Class *cl, OOP_Object *o, OOP_Msg msg)
555 EnterFunc(bug("[X11Kbd] Dispose()\n"));
557 ObtainSemaphore( &XSD(cl)->sema);
558 XSD(cl)->kbdhidd = NULL;
559 ReleaseSemaphore( &XSD(cl)->sema);
560 OOP_DoSuperMethod(cl, o, msg);
563 /****************************************************************************************/
565 VOID X11Kbd__Hidd_X11Kbd__HandleEvent(OOP_Class *cl, OOP_Object *o, struct pHidd_X11Kbd_HandleEvent *msg)
567 struct x11kbd_data *data;
568 XKeyEvent *xk;
569 long keycode;
571 EnterFunc(bug("x11kbd_handleevent()\n"));
573 data = OOP_INST_DATA(cl, o);
574 xk = &(msg->event->xkey);
576 keycode = xkey2hidd(xk, XSD(cl));
577 if (keycode == -1)
579 ReturnVoid("X11Kbd::HandleEvent: Unknown key!");
582 if (msg->event->type == KeyRelease)
584 keycode |= IECODE_UP_PREFIX;
587 if (keycode != data->prev_keycode)
589 data->kbd_callback(data->callbackdata, keycode);
590 data->prev_keycode = keycode;
593 ReturnVoid("X11Kbd::HandleEvent");
596 /****************************************************************************************/
598 #undef XSD
599 #define XSD(cl) xsd
601 /****************************************************************************************/
603 WORD lookup_keytable(KeySym *ks, struct _keytable *keytable)
605 short t;
606 WORD result = -1;
608 for (t = 0; keytable[t].hiddcode != -1; t++)
610 if (*ks == keytable[t].keysym)
612 D(bug("xktac: found in key table\n"));
613 result = keytable[t].hiddcode;
614 break;
618 return result;
621 /****************************************************************************************/
623 long xkey2hidd (XKeyEvent *xk, struct x11_staticdata *xsd)
625 char buffer[10];
626 KeySym ks;
627 D(int count;)
628 long result;
630 D(bug("xkey2hidd\n"));
632 if (xsd->havetable)
634 result = -1;
635 if ((xk->keycode >= 0) && (xk->keycode < 256))
637 result = xsd->keycode2rawkey[xk->keycode];
638 if (result == 255) result = -1;
641 return result;
644 LOCK_X11
645 xk->state = 0;
646 D(count =) XCALL(XLookupString, xk, buffer, 10, &ks, NULL);
647 UNLOCK_X11
649 D(bug("xk2h: Code %d (0x%x). Event was decoded into %d chars: %d (0x%x)\n",xk->keycode, xk->keycode, count,ks,ks));
651 result = lookup_keytable(&ks, keytable);
652 if (result == -1) result = lookup_keytable(&ks, english_keytable);
654 ReturnInt ("xk2h", long, result);
656 } /* XKeyToAmigaCode */
659 /****************************************************************************************/
661 #undef XSD
662 #define XSD(cl) (&LIBBASE->xsd)
664 /****************************************************************************************/
666 static int kbd_init(LIBBASETYPEPTR LIBBASE)
669 return OOP_ObtainAttrBases(attrbases);
672 /****************************************************************************************/
674 static int kbd_expunge(LIBBASETYPEPTR LIBBASE)
676 OOP_ReleaseAttrBases(attrbases);
677 return TRUE;
680 /****************************************************************************************/
682 ADD2INITLIB(kbd_init, 0);
683 ADD2EXPUNGELIB(kbd_expunge, 0);
685 /****************************************************************************************/