Added missing properties.
[tangerine.git] / arch / all-x11 / hidd / x11kbd.c
blob8ab7a801a9d65b063ea8424c468e1c645f1413e6
1 /*
2 Copyright © 1995-2006, The AROS Development Team. All rights reserved.
3 $Id$
5 Desc: X11 hidd handling keypresses.
6 Lang: English.
7 */
9 #define __OOP_NOATTRBASES__
11 #include <dos/dos.h>
13 #include <proto/dos.h>
14 #include <proto/utility.h>
15 #include <proto/oop.h>
16 #include <oop/oop.h>
18 #define timeval sys_timeval
19 #include <X11/Xlib.h>
20 #include <X11/keysym.h>
21 #include <X11/Xutil.h>
23 #include <stdio.h>
24 #undef timeval
26 #include <hidd/hidd.h>
27 #include <hidd/keyboard.h>
29 #include <devices/inputevent.h>
31 #include <aros/symbolsets.h>
33 //#define DEBUG 1
34 #include <aros/debug.h>
36 #include LC_LIBDEFS_FILE
38 #include "x11.h"
40 /****************************************************************************************/
42 static UBYTE keycode2rawkey[256];
43 static BOOL havetable;
45 long xkey2hidd (XKeyEvent *xk, struct x11_staticdata *xsd);
47 static OOP_AttrBase HiddKbdAB;
49 static struct OOP_ABDescr attrbases[] =
51 { IID_Hidd_Kbd , &HiddKbdAB },
52 { NULL , NULL }
55 /****************************************************************************************/
57 static struct _keytable
59 KeySym keysym;
60 WORD hiddcode;
62 keytable[] =
64 {XK_Return, 0x44 },
65 {XK_Right, 0x4e },
66 {XK_Up, 0x4c },
67 {XK_Left, 0x4f },
68 {XK_Down, 0x4d },
69 {XK_Help, 0x5f },
71 {XK_BackSpace, 0x41 },
72 {XK_Delete, 0x46 },
73 {XK_space, 0x40 },
74 {XK_Shift_L, 0x60 },
75 {XK_Shift_R, 0x61 },
76 {XK_Alt_L, 0x64 },
77 {XK_Alt_R, 0x65 },
78 {XK_Escape, 0x45 },
79 {XK_Tab, 0x42 },
81 {XK_F1, 0x50 },
82 {XK_F2, 0x51 },
83 {XK_F3, 0x52 },
84 {XK_F4, 0x53 },
85 {XK_F5, 0x54 },
86 {XK_F6, 0x55 },
87 {XK_F7, 0x56 },
88 {XK_F8, 0x57 },
89 {XK_F9, 0x58 },
90 {XK_F10, 0x59 },
92 {XK_F11, 0x4B },
93 {XK_F12, 0x5f }, /* HELP, F12 would be 0x6F */
94 {XK_Home, 0x70 },
95 {XK_End, 0x71 },
96 {XK_Insert, 0x47 },
97 {XK_Prior, 0x48 }, /* PageUP */
98 {XK_Next, 0x49 }, /* PageDown */
99 {XK_Pause, 0x6e },
101 {XK_KP_Enter, 0x43 },
102 {XK_KP_Subtract, 0x4a },
103 {XK_KP_Decimal, 0x3c },
104 {XK_KP_Separator, 0x3c },
105 {XK_KP_Delete, 0x3c },
106 {XK_KP_Add, 0x5e },
107 {XK_KP_Subtract, 0x4a },
108 {XK_KP_Multiply, 0x5d },
109 {XK_KP_Divide, 0x5c },
111 {XK_KP_0, 0x0f },
112 {XK_KP_Insert, 0x0f },
113 {XK_KP_1, 0x1d },
114 {XK_KP_End, 0x1d },
115 {XK_KP_2, 0x1e },
116 {XK_KP_Down, 0x1e },
117 {XK_KP_3, 0x1f },
118 {XK_KP_Page_Down, 0x1f },
119 {XK_KP_4, 0x2d },
120 {XK_KP_Left, 0x2d },
121 {XK_KP_5, 0x2e },
122 {XK_KP_Begin, 0x2e },
123 {XK_KP_6, 0x2f },
124 {XK_KP_Right, 0x2f },
125 {XK_KP_7, 0x3d },
126 {XK_KP_Home, 0x3d },
127 {XK_KP_8, 0x3e },
128 {XK_KP_Up, 0x3e },
129 {XK_KP_9, 0x3f },
130 {XK_KP_Page_Up, 0x3f },
132 {XK_E, 0x12 },
133 {XK_e, 0x12 },
134 {XK_R, 0x13 },
135 {XK_r, 0x13 },
136 {XK_T, 0x14 },
137 {XK_t, 0x14 },
138 {XK_U, 0x16 },
139 {XK_u, 0x16 },
140 {XK_I, 0x17 },
141 {XK_i, 0x17 },
142 {XK_O, 0x18 },
143 {XK_o, 0x18 },
144 {XK_P, 0x19 },
145 {XK_p, 0x19 },
147 {XK_S, 0x21 },
148 {XK_s, 0x21 },
149 {XK_D, 0x22 },
150 {XK_d, 0x22 },
151 {XK_F, 0x23 },
152 {XK_f, 0x23 },
153 {XK_G, 0x24 },
154 {XK_g, 0x24 },
155 {XK_H, 0x25 },
156 {XK_h, 0x25 },
157 {XK_J, 0x26 },
158 {XK_j, 0x26 },
159 {XK_K, 0x27 },
160 {XK_k, 0x27 },
161 {XK_L, 0x28 },
162 {XK_l, 0x28 },
164 {XK_X, 0x32 },
165 {XK_x, 0x32 },
166 {XK_c, 0x33 },
167 {XK_C, 0x33 },
168 {XK_V, 0x34 },
169 {XK_v, 0x34 },
170 {XK_B, 0x35 },
171 {XK_b, 0x35 },
172 {XK_N, 0x36 },
173 {XK_n, 0x36 },
175 {XK_1, 0x01 },
176 {XK_2, 0x02 },
177 {XK_3, 0x03 },
178 {XK_4, 0x04 },
179 {XK_5, 0x05 },
180 {XK_6, 0x06 },
181 {XK_7, 0x07 },
182 {XK_8, 0x08 },
183 {XK_9, 0x09 },
184 {XK_0, 0x0A },
185 {0, - 1 }
188 /****************************************************************************************/
190 /* English keyboard */
191 static struct _keytable english_keytable[] =
193 {XK_Control_L, 0x63 }, /* left control = control */
194 {XK_Multi_key, 0x63 }, /* right control = control */
195 {XK_Super_L, 0x66 }, /* left win = LAMIGA */
196 {XK_Super_R, 0x67 }, /* right win = RAMIGA */
197 {XK_Meta_L, 0x64 }, /* left Alt = LALT */
198 {XK_Mode_switch, 0x65 }, /* right Alt = RALT */
200 /* Key left of S */
201 {XK_A, 0x20 },
202 {XK_a, 0x20 },
204 /* Key right of N */
205 {XK_M, 0x37 },
206 {XK_m, 0x37 },
208 /* Key right of TAB */
209 {XK_Q, 0x10 },
210 {XK_q, 0x10 },
212 /* Key between T and U */
213 {XK_y, 0x15 },
214 {XK_Y, 0x15 },
216 /* Key left of E */
217 {XK_W, 0x11 },
218 {XK_w, 0x11 },
220 /* Key left of X */
221 {XK_z, 0x31 },
222 {XK_Z, 0x31 },
225 /* Key left of 1 */
226 {XK_grave, 0x00 },
228 /* Keys right of 0 */
229 {XK_minus, 0x0B },
230 {XK_equal, 0x0C },
232 /* Keys right of P */
233 {XK_bracketleft, 0x1A },
234 {XK_bracketright, 0x1B },
236 /* Keys right of L */
237 {XK_semicolon, 0x29 },
238 {XK_apostrophe, 0x2A },
239 {XK_backslash, 0x2B }, /* Third key right of L might not be present */
241 /* Key right of shift and 2nd left of X (might not be present) */
242 {XK_less, 0x30 },
244 /* Keys 2nd right of N (= usually right of M) */
245 {XK_comma, 0x38 },
246 {XK_period, 0x39 },
247 {XK_slash, 0x3A },
249 {0, -1 }
252 /****************************************************************************************/
254 /* German keyboard */
255 static struct _keytable german_keytable[] =
257 {XK_Control_L, 0x63 }, /* linke STRG = control */
258 {XK_Multi_key, 0x63 }, /* rechte STRG = control */
259 {XK_Super_L, 0x66 }, /* Linke Win = LAMIGA */
260 {XK_Super_R, 0x67 }, /* Rechte Win = RAMIGA */
261 {XK_Meta_L, 0x64 }, /* Linke Alt = LALT */
262 {XK_Mode_switch, 0x65 }, /* Alt Gr = RALT */
264 /* Key left of S */
265 {XK_A, 0x20 },
266 {XK_a, 0x20 },
268 /* Key right of N */
269 {XK_M, 0x37 },
270 {XK_m, 0x37 },
272 /* Key right of TAB */
273 {XK_Q, 0x10 },
274 {XK_q, 0x10 },
276 /* Key between T and U */
277 {XK_Z, 0x15 },
278 {XK_z, 0x15 },
280 /* Key left of E */
281 {XK_W, 0x11 },
282 {XK_w, 0x11 },
284 /* Key left of X */
285 {XK_y, 0x31 },
286 {XK_Y, 0x31 },
288 /* Key left of 1 */
289 {XK_asciicircum, 0x00 }, /* Akzent links neben 1 Taste */
291 /* Keys right of 0 */
292 {XK_equal, 0x0A }, /* = */
293 {XK_ssharp, 0x0B }, /* scharfes s */
294 {XK_acute, 0x0C }, /* Akzent rechts von scharfem s */
296 /* Keys right of P */
297 {XK_udiaeresis, 0x1A }, /* Umlaut u */
298 {XK_Udiaeresis, 0x1A },
299 {XK_plus, 0x1B }, /* + */
301 /* Keys right of L */
302 {XK_odiaeresis, 0x29 }, /* Umlaut o */
303 {XK_Odiaeresis, 0x29 },
304 {XK_adiaeresis, 0x2A }, /* Umlaut a */
305 {XK_Adiaeresis, 0x2A },
306 {XK_numbersign, 0x2B }, /* # */
308 /* Key right of shift and 2nd left of X (might not be present) */
309 {XK_less, 0x30 }, /* < */
311 /* Keys 2nd right of N (= usually right of M) */
312 {XK_comma, 0x38 }, /* Komma */
313 {XK_period, 0x39 }, /* Punkt */
314 {XK_minus, 0x3A }, /* Minus */
316 {0, -1 }
319 /* Itialian keyboard */
320 static struct _keytable italian_keytable[] =
322 {XK_Control_L, 0x63 }, /* left CTRL = control */
323 {XK_Multi_key, 0x63 }, /* right CTRL = control */
324 {XK_Super_L, 0x66 }, /* left win = LAMIGA */
325 {XK_Super_R, 0x67 }, /* right win = RAMIGA */
326 {XK_Meta_L, 0x64 }, /* left alt = LALT */
327 {XK_Mode_switch, 0x65 }, /* right alt = RALT */
330 /* Key left of S */
331 {XK_A, 0x20 },
332 {XK_a, 0x20 },
334 /* Key right of N */
335 {XK_M, 0x37 },
336 {XK_m, 0x37 },
338 /* Key right of TAB */
339 {XK_Q, 0x10 },
340 {XK_q, 0x10 },
342 /* Key between T and U */
343 {XK_y, 0x15 },
344 {XK_Y, 0x15 },
346 /* Key left of E */
347 {XK_W, 0x11 },
348 {XK_w, 0x11 },
350 /* Key left of X */
351 {XK_z, 0x31 },
352 {XK_Z, 0x31 },
355 /* Key left of 1 */
356 {XK_backslash, 0x00 },
358 /* Keys right of 0 */
359 {XK_apostrophe, 0x0B },
360 {XK_Igrave, 0x0C },
361 {XK_igrave, 0x0C },
363 /* Keys right of P */
364 {XK_Egrave, 0x1A },
365 {XK_egrave, 0x1A },
366 {XK_plus, 0x1B }, /* + */
368 /* Keys right of L */
369 {XK_Ograve, 0x29 },
370 {XK_ograve, 0x29 },
371 {XK_Agrave, 0x2A },
372 {XK_agrave, 0x2A },
373 {XK_Ugrave, 0x2B }, /* Third key right of L might not be present */
374 {XK_ugrave, 0x2B },
376 /* Key right of shift and 2nd left of X (might not be present) */
377 {XK_less, 0x30 }, /* < */
379 /* Keys 2nd right of N (= usually right of M) */
380 {XK_comma, 0x38 },
381 {XK_period, 0x39 },
382 {XK_minus, 0x3A },
384 {0, -1 }
387 /****************************************************************************************/
389 #if 0
391 /* Use this template to create a keytable for your language:
393 Do not touch the right values (rawkey numbers). Only change
394 the XK's at the left side. To find out the XK_ names (keysym)
395 start "xev" and press the key the comment describes (for
396 example "Key left of S" in the xev window. In the Shell
397 window you will see output like this:
399 KeyPress event, serial 30, synthetic NO, window 0x5000001,
400 root 0x47, subw 0x5000002, time 3410089115, (24,45), root:(28,69),
401 state 0x0, keycode 50 (keysym 0xffe1, Shift_L), same_screen YES,
402 XLookupString gives 0 characters: "" |
404 This is the keysym name _______________/
406 So in this case you would have to write "XK_Shift_L"
408 Check all keys, not just the ones with "XK_????"!!!
411 static struct _keytable template_keytable[] =
413 {XK_Control_L, 0x63 }, /* left control = control */
414 {XK_Multi_key, 0x63 }, /* right control = control */
415 {XK_Super_L, 0x66 }, /* left win = LAMIGA */
416 {XK_Super_R, 0x67 }, /* right win = RAMIGA */
417 {XK_Meta_L, 0x64 }, /* left Alt = LALT */
418 {XK_Mode_switch, 0x65 }, /* right Alt = RALT */
420 /* Key left of S */
421 {XK_A, 0x20 },
422 {XK_a, 0x20 },
424 /* Key right of N */
425 {XK_M, 0x37 },
426 {XK_m, 0x37 },
428 /* Key right of TAB */
429 {XK_Q, 0x10 },
430 {XK_q, 0x10 },
432 /* Key between T and U */
433 {XK_????, 0x15 },
434 {XK_????, 0x15 },
436 /* Key left of E */
437 {XK_W, 0x11 },
438 {XK_w, 0x11 },
440 /* Key left of X */
441 {XK_????, 0x31 },
442 {XK_????, 0x31 },
445 /* Key left of 1 */
446 {XK_????, 0x00 },
448 /* Keys right of 0 */
449 {XK_????, 0x0B },
450 {XK_????, 0x0C },
452 /* Keys right of P */
453 {XK_????, 0x1A },
454 {XK_????, 0x1B },
456 /* Keys right of L */
457 {XK_????, 0x29 },
458 {XK_????, 0x2A },
459 {XK_????, 0x2B }, /* Third key right of L might not be present */
461 /* Key right of shift and 2nd left of X (might not be present) */
462 {XK_less, 0x30 },
464 /* Keys 2nd right of N (= usually right of M) */
465 {XK_comma, 0x38 },
466 {XK_period, 0x39 },
467 {XK_slash, 0x3A },
469 {0, -1 }
472 #endif
474 /****************************************************************************************/
476 OOP_Object * X11Kbd__Root__New(OOP_Class *cl, OOP_Object *o, struct pRoot_New *msg)
478 BOOL has_kbd_hidd = FALSE;
479 struct TagItem *tag, *tstate;
480 APTR callback = NULL;
481 APTR callbackdata = NULL;
483 EnterFunc(bug("X11Kbd::New()\n"));
485 ObtainSemaphoreShared( &XSD(cl)->sema);
487 if (XSD(cl)->kbdhidd)
488 has_kbd_hidd = TRUE;
490 ReleaseSemaphore( &XSD(cl)->sema);
492 if (has_kbd_hidd) /* Cannot open twice */
493 ReturnPtr("X11Kbd::New", OOP_Object *, NULL); /* Should have some error code here */
495 tstate = msg->attrList;
496 D(bug("tstate: %p, tag=%x\n", tstate, tstate->ti_Tag));
498 while ((tag = NextTagItem((const struct TagItem **)&tstate)))
500 ULONG idx;
502 D(bug("Got tag %d, data %x\n", tag->ti_Tag, tag->ti_Data));
504 if (IS_HIDDKBD_ATTR(tag->ti_Tag, idx))
506 D(bug("Kbd hidd tag\n"));
507 switch (idx)
509 case aoHidd_Kbd_IrqHandler:
510 callback = (APTR)tag->ti_Data;
511 D(bug("Got callback %p\n", (APTR)tag->ti_Data));
512 break;
514 case aoHidd_Kbd_IrqHandlerData:
515 callbackdata = (APTR)tag->ti_Data;
516 D(bug("Got data %p\n", (APTR)tag->ti_Data));
517 break;
521 } /* while (tags to process) */
523 if (NULL == callback)
524 ReturnPtr("X11Kbd::New", OOP_Object *, NULL); /* Should have some error code here */
526 o = (OOP_Object *)OOP_DoSuperMethod(cl, o, (OOP_Msg)msg);
527 if (o)
529 struct x11kbd_data *data = OOP_INST_DATA(cl, o);
531 data->kbd_callback = (VOID (*)(APTR, UWORD))callback;
532 data->callbackdata = callbackdata;
533 data->prev_keycode = 0xFFFF;
535 ObtainSemaphore( &XSD(cl)->sema);
536 XSD(cl)->kbdhidd = o;
537 ReleaseSemaphore( &XSD(cl)->sema);
540 ReturnPtr("X11Kbd::New", OOP_Object *, o);
543 /****************************************************************************************/
545 VOID X11Kbd__Hidd_X11Kbd__HandleEvent(OOP_Class *cl, OOP_Object *o, struct pHidd_X11Kbd_HandleEvent *msg)
547 struct x11kbd_data *data;
548 XKeyEvent *xk;
549 UWORD keycode;
551 EnterFunc(bug("x11kbd_handleevent()\n"));
553 data = OOP_INST_DATA(cl, o);
554 xk = &(msg->event->xkey);
556 keycode = (UWORD)xkey2hidd(xk, XSD(cl));
558 if (msg->event->type == KeyRelease)
560 keycode |= IECODE_UP_PREFIX;
563 if (keycode != data->prev_keycode)
565 data->kbd_callback(data->callbackdata, keycode);
566 data->prev_keycode = keycode;
569 ReturnVoid("X11Kbd::HandleEvent");
572 /****************************************************************************************/
574 #undef XSD
575 #define XSD(cl) xsd
577 /****************************************************************************************/
579 WORD lookup_keytable(KeySym *ks, struct _keytable *keytable)
581 short t;
582 WORD result = -1;
584 for (t = 0; keytable[t].hiddcode != -1; t++)
586 if (*ks == keytable[t].keysym)
588 D(bug("xktac: found in key table\n"));
589 result = keytable[t].hiddcode;
590 break;
594 return result;
597 /****************************************************************************************/
599 long xkey2hidd (XKeyEvent *xk, struct x11_staticdata *xsd)
601 char buffer[10];
602 KeySym ks;
603 int count;
604 long result;
606 D(bug("xkey2hidd\n"));
608 if (havetable)
610 result = -1;
611 if ((xk->keycode >= 0) && (xk->keycode < 256))
613 result = keycode2rawkey[xk->keycode];
614 if (result == 255) result = -1;
617 return result;
620 LOCK_X11
621 xk->state = 0;
622 count = XCALL(XLookupString, xk, buffer, 10, &ks, NULL);
623 UNLOCK_X11
625 D(bug("xk2h: Code %d (0x%x). Event was decoded into %d chars: %d (0x%x)\n",xk->keycode, xk->keycode, count,ks,ks));
627 result = lookup_keytable(&ks, keytable);
628 if (result == -1) result = lookup_keytable(&ks, english_keytable);
630 if (result != -1)
632 ReturnInt ("xk2h", long, result);
635 D(bug("xk2h: Passing X keycode\n", xk->keycode & 0xffff));
637 result = xk->keycode & 0xffff;
639 ReturnInt ("xk2h", long, result);
641 } /* XKeyToAmigaCode */
643 /****************************************************************************************/
645 #if X11_LOAD_KEYMAPTABLE
647 /****************************************************************************************/
649 static void LoadKeyCode2RawKeyTable(struct x11_staticdata *xsd)
651 char *filename = "DEVS:Keymaps/X11/keycode2rawkey.table";
652 BPTR fh;
653 struct DosLibrary *DOSBase;
655 DOSBase = (struct DosLibrary *)OpenLibrary(DOSNAME, 37);
656 if (DOSBase == NULL)
658 bug("LoadKeyCode2RawKeyTable: Opening %s failed\n", DOSNAME);
659 return;
662 if ((fh = Open(filename, MODE_OLDFILE)))
664 if ((256 == Read(fh, keycode2rawkey, 256)))
666 bug("LoadKeyCode2RawKeyTable: keycode2rawkey.table successfully loaded!\n");
667 havetable = TRUE;
669 else
671 bug("LoadKeyCode2RawKeyTable: Reading from \"%s\" failed!\n", filename);
673 Close(fh);
675 else
677 bug("\nLoadKeyCode2RawKeyTable: Loading \"%s\" failed!\n"
678 "\n"
679 "This means that many/most/all keys on your keyboard won't work as you\n"
680 "would expect in AROS. Therefore you should create this table by either\n"
681 "using the default table:\n"
682 "\n"
683 " mmake .default-x11keymaptable\n"
684 "\n"
685 "or generating your own one:\n"
686 "\n"
687 " mmake .change-x11keymaptable\n"
688 "\n"
689 "The default keymaptable probably works with most PCs having a 105 key\n"
690 "keyboard if you are using XFree86 as X Server (might also work with\n"
691 "others). So try that one first!\n"
692 "\n"
693 "Since the keymap table will be deleted when you do a \"make clean\" you\n"
694 "might want to make a backup of it. Then you will be able to restor it later:\n"
695 "\n"
696 " mmake .backup-x11keymaptable\n"
697 " mmake .restore-x11keymaptable\n"
698 "\n"
699 "The keymap table will be backuped in your HOME directory.\n"
700 "\n"
701 "Note that the keymaptable only makes sure that your keyboard looks as\n"
702 "much as possible like an Amiga keyboard to AROS. So with the keymaptable\n"
703 "alone the keyboard will behave like an Amiga keyboard with American layout\n."
704 "For other layouts you must activate the correct keymap just like in AmigaOS.\n",
705 filename);
708 CloseLibrary((struct Library *)DOSBase);
711 /****************************************************************************************/
713 #endif
715 /****************************************************************************************/
717 #undef XSD
718 #define XSD(cl) (&LIBBASE->xsd)
720 /****************************************************************************************/
722 static int kbd_init(LIBBASETYPEPTR LIBBASE)
724 #if X11_LOAD_KEYMAPTABLE
725 LoadKeyCode2RawKeyTable(&LIBBASE->xsd);
726 #endif
728 return OOP_ObtainAttrBases(attrbases);
731 /****************************************************************************************/
733 static int kbd_expunge(LIBBASETYPEPTR LIBBASE)
735 OOP_ReleaseAttrBases(attrbases);
736 return TRUE;
739 /****************************************************************************************/
741 ADD2INITLIB(kbd_init, 0);
742 ADD2EXPUNGELIB(kbd_expunge, 0);
744 /****************************************************************************************/