2 Copyright © 1995-2006, The AROS Development Team. All rights reserved.
5 Desc: X11 hidd handling keypresses.
9 #define __OOP_NOATTRBASES__
13 #include <proto/dos.h>
14 #include <proto/utility.h>
15 #include <proto/oop.h>
18 #define timeval sys_timeval
20 #include <X11/keysym.h>
21 #include <X11/Xutil.h>
26 #include <hidd/hidd.h>
27 #include <hidd/keyboard.h>
29 #include <devices/inputevent.h>
31 #include <aros/symbolsets.h>
34 #include <aros/debug.h>
36 #include LC_LIBDEFS_FILE
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
},
55 /****************************************************************************************/
57 static struct _keytable
71 {XK_BackSpace
, 0x41 },
93 {XK_F12
, 0x5f }, /* HELP, F12 would be 0x6F */
97 {XK_Prior
, 0x48 }, /* PageUP */
98 {XK_Next
, 0x49 }, /* PageDown */
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 },
107 {XK_KP_Subtract
, 0x4a },
108 {XK_KP_Multiply
, 0x5d },
109 {XK_KP_Divide
, 0x5c },
112 {XK_KP_Insert
, 0x0f },
118 {XK_KP_Page_Down
, 0x1f },
122 {XK_KP_Begin
, 0x2e },
124 {XK_KP_Right
, 0x2f },
130 {XK_KP_Page_Up
, 0x3f },
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 */
208 /* Key right of TAB */
212 /* Key between T and U */
228 /* Keys right of 0 */
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) */
244 /* Keys 2nd right of N (= usually right of M) */
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 */
272 /* Key right of TAB */
276 /* Key between T and U */
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 */
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 */
338 /* Key right of TAB */
342 /* Key between T and U */
356 {XK_backslash
, 0x00 },
358 /* Keys right of 0 */
359 {XK_apostrophe
, 0x0B },
363 /* Keys right of P */
366 {XK_plus
, 0x1B }, /* + */
368 /* Keys right of L */
373 {XK_Ugrave
, 0x2B }, /* Third key right of L might not be present */
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) */
387 /****************************************************************************************/
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 */
428 /* Key right of TAB */
432 /* Key between T and U */
448 /* Keys right of 0 */
452 /* Keys right of P */
456 /* Keys right of L */
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) */
464 /* Keys 2nd right of N (= usually right of M) */
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
)
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
)))
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"));
509 case aoHidd_Kbd_IrqHandler
:
510 callback
= (APTR
)tag
->ti_Data
;
511 D(bug("Got callback %p\n", (APTR
)tag
->ti_Data
));
514 case aoHidd_Kbd_IrqHandlerData
:
515 callbackdata
= (APTR
)tag
->ti_Data
;
516 D(bug("Got data %p\n", (APTR
)tag
->ti_Data
));
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
);
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
;
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 /****************************************************************************************/
577 /****************************************************************************************/
579 WORD
lookup_keytable(KeySym
*ks
, struct _keytable
*keytable
)
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
;
597 /****************************************************************************************/
599 long xkey2hidd (XKeyEvent
*xk
, struct x11_staticdata
*xsd
)
606 D(bug("xkey2hidd\n"));
611 if ((xk
->keycode
>= 0) && (xk
->keycode
< 256))
613 result
= keycode2rawkey
[xk
->keycode
];
614 if (result
== 255) result
= -1;
622 count
= XCALL(XLookupString
, xk
, buffer
, 10, &ks
, NULL
);
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
);
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";
653 struct DosLibrary
*DOSBase
;
655 DOSBase
= (struct DosLibrary
*)OpenLibrary(DOSNAME
, 37);
658 bug("LoadKeyCode2RawKeyTable: Opening %s failed\n", DOSNAME
);
662 if ((fh
= Open(filename
, MODE_OLDFILE
)))
664 if ((256 == Read(fh
, keycode2rawkey
, 256)))
666 bug("LoadKeyCode2RawKeyTable: keycode2rawkey.table successfully loaded!\n");
671 bug("LoadKeyCode2RawKeyTable: Reading from \"%s\" failed!\n", filename
);
677 bug("\nLoadKeyCode2RawKeyTable: Loading \"%s\" failed!\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"
683 " mmake .default-x11keymaptable\n"
685 "or generating your own one:\n"
687 " mmake .change-x11keymaptable\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"
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"
696 " mmake .backup-x11keymaptable\n"
697 " mmake .restore-x11keymaptable\n"
699 "The keymap table will be backuped in your HOME directory.\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",
708 CloseLibrary((struct Library
*)DOSBase
);
711 /****************************************************************************************/
715 /****************************************************************************************/
718 #define XSD(cl) (&LIBBASE->xsd)
720 /****************************************************************************************/
722 static int kbd_init(LIBBASETYPEPTR LIBBASE
)
724 #if X11_LOAD_KEYMAPTABLE
725 LoadKeyCode2RawKeyTable(&LIBBASE
->xsd
);
728 return OOP_ObtainAttrBases(attrbases
);
731 /****************************************************************************************/
733 static int kbd_expunge(LIBBASETYPEPTR LIBBASE
)
735 OOP_ReleaseAttrBases(attrbases
);
739 /****************************************************************************************/
741 ADD2INITLIB(kbd_init
, 0);
742 ADD2EXPUNGELIB(kbd_expunge
, 0);
744 /****************************************************************************************/