1  /*
2   * UAE - The Un*x Amiga Emulator
3   *
4   * X keysym support
5   *
6   * Copyright 1995, 1996 Bernd Schmidt
7   * Copyright 1996 Ed Hanway, Andre Beck, Samuel Devulder, Bruno Coste
8   * Copyright 1998 Marcus Sundberg
9   * DGA support by Kai Kollmorgen
10   * X11/DGA merge, hotkeys and grabmouse by Marcus Sundberg
11   * Copyright 2003-2004 Richard Drummond
12   */
13 
14 #include "sysconfig.h"
15 #include "sysdeps.h"
16 
17 #include <X11/Xlib.h>
18 #include <X11/keysym.h>
19 
20 #include "options.h"
21 #include "inputdevice.h"
22 #include "keyboard.h"
23 #include "hotkeys.h"
24 
25 
26 /* Decode KeySyms. This function knows about all keys that are common
27  * between different keyboard languages. */
kc_decode(KeySym ks)28 static int kc_decode (KeySym ks)
29 {
30     switch (ks) {
31      case XK_B: case XK_b: return AK_B;
32      case XK_C: case XK_c: return AK_C;
33      case XK_D: case XK_d: return AK_D;
34      case XK_E: case XK_e: return AK_E;
35      case XK_F: case XK_f: return AK_F;
36      case XK_G: case XK_g: return AK_G;
37      case XK_H: case XK_h: return AK_H;
38      case XK_I: case XK_i: return AK_I;
39      case XK_J: case XK_j: return AK_J;
40      case XK_K: case XK_k: return AK_K;
41      case XK_L: case XK_l: return AK_L;
42      case XK_N: case XK_n: return AK_N;
43      case XK_O: case XK_o: return AK_O;
44      case XK_P: case XK_p: return AK_P;
45      case XK_R: case XK_r: return AK_R;
46      case XK_S: case XK_s: return AK_S;
47      case XK_T: case XK_t: return AK_T;
48      case XK_U: case XK_u: return AK_U;
49      case XK_V: case XK_v: return AK_V;
50      case XK_X: case XK_x: return AK_X;
51 
52      case XK_0: return AK_0;
53      case XK_1: return AK_1;
54      case XK_2: return AK_2;
55      case XK_3: return AK_3;
56      case XK_4: return AK_4;
57      case XK_5: return AK_5;
58      case XK_6: return AK_6;
59      case XK_7: return AK_7;
60      case XK_8: return AK_8;
61      case XK_9: return AK_9;
62 
63 	/* You never know which Keysyms might be missing on some workstation
64 	 * This #ifdef should be enough. */
65 #if defined(XK_KP_Prior) && defined(XK_KP_Left) && defined(XK_KP_Insert) && defined (XK_KP_End)
66      case XK_KP_0: case XK_KP_Insert: return AK_NP0;
67      case XK_KP_1: case XK_KP_End: return AK_NP1;
68      case XK_KP_2: case XK_KP_Down: return AK_NP2;
69      case XK_KP_3: case XK_KP_Next: return AK_NP3;
70      case XK_KP_4: case XK_KP_Left: return AK_NP4;
71      case XK_KP_5: case XK_KP_Begin: return AK_NP5;
72      case XK_KP_6: case XK_KP_Right: return AK_NP6;
73      case XK_KP_7: case XK_KP_Home: return AK_NP7;
74      case XK_KP_8: case XK_KP_Up: return AK_NP8;
75      case XK_KP_9: case XK_KP_Prior: return AK_NP9;
76 #else
77      case XK_KP_0: return AK_NP0;
78      case XK_KP_1: return AK_NP1;
79      case XK_KP_2: return AK_NP2;
80      case XK_KP_3: return AK_NP3;
81      case XK_KP_4: return AK_NP4;
82      case XK_KP_5: return AK_NP5;
83      case XK_KP_6: return AK_NP6;
84      case XK_KP_7: return AK_NP7;
85      case XK_KP_8: return AK_NP8;
86      case XK_KP_9: return AK_NP9;
87 #endif
88      case XK_KP_Divide: return AK_NPDIV;
89      case XK_KP_Multiply: return AK_NPMUL;
90      case XK_KP_Subtract: return AK_NPSUB;
91      case XK_KP_Add: return AK_NPADD;
92      case XK_KP_Decimal: return AK_NPDEL;
93      case XK_KP_Enter: return AK_ENT;
94 
95      case XK_F1: return AK_F1;
96      case XK_F2: return AK_F2;
97      case XK_F3: return AK_F3;
98      case XK_F4: return AK_F4;
99      case XK_F5: return AK_F5;
100      case XK_F6: return AK_F6;
101      case XK_F7: return AK_F7;
102      case XK_F8: return AK_F8;
103      case XK_F9: return AK_F9;
104      case XK_F10: return AK_F10;
105 
106      case XK_BackSpace: return AK_BS;
107      case XK_Delete: return AK_DEL;
108      case XK_Control_L: return AK_CTRL;
109      case XK_Control_R: return AK_RCTRL;
110      case XK_Tab: return AK_TAB;
111      case XK_Alt_L: return AK_LALT;
112      case XK_Alt_R: return AK_RALT;
113      case XK_Meta_R: case XK_Hyper_R: return AK_RAMI;
114      case XK_Meta_L: case XK_Hyper_L: return AK_LAMI;
115      case XK_Return: return AK_RET;
116      case XK_space: return AK_SPC;
117      case XK_Shift_L: return AK_LSH;
118      case XK_Shift_R: return AK_RSH;
119      case XK_Escape: return AK_ESC;
120 
121      case XK_Insert: return AK_HELP;
122      case XK_Home: return AK_NPLPAREN;
123      case XK_End: return AK_NPRPAREN;
124      case XK_Caps_Lock: return AK_CAPSLOCK;
125 
126      case XK_Up: return AK_UP;
127      case XK_Down: return AK_DN;
128      case XK_Left: return AK_LF;
129      case XK_Right: return AK_RT;
130 
131 #ifdef XK_Page_Up /* These are missing occasionally */
132      case XK_Page_Up: return AK_RAMI;          /* PgUp mapped to right amiga */
133      case XK_Page_Down: return AK_LAMI;        /* PgDn mapped to left amiga */
134 #endif
135 
136 #ifdef XK_Super_L
137      case XK_Super_L: return AK_LAMI;
138      case XK_Super_R: return AK_RAMI;
139 #endif
140      case XK_Scroll_Lock: return AKS_INHIBITSCREEN;
141      case XK_Print: return AKS_SCREENSHOT;
142     }
143     return -1;
144 }
145 
decode_fr(KeySym ks)146 static int decode_fr (KeySym ks)
147 {
148     switch(ks) {        /* FR specific */
149      case XK_A: case XK_a: return AK_Q;
150      case XK_M: case XK_m: return AK_SEMICOLON;
151      case XK_Q: case XK_q: return AK_A;
152      case XK_Y: case XK_y: return AK_Y;
153      case XK_W: case XK_w: return AK_Z;
154      case XK_Z: case XK_z: return AK_W;
155 #if 0
156      case XK_bracketleft: return AK_LBRACKET;
157      case XK_bracketright: return AK_RBRACKET;
158      case XK_comma: return AK_M;
159      case XK_less: case XK_greater: return AK_LTGT;
160      case XK_period: return AK_COMMA;
161      case XK_parenright: return AK_MINUS;
162      case XK_equal: return AK_SLASH;
163      case XK_numbersign: return AK_NUMBERSIGN;
164      case XK_slash: return AK_PERIOD;
165      case XK_minus: return AK_EQUAL;
166      case XK_backslash: return AK_BACKSLASH;
167 #else
168      /* not sure for this one: my X 3.3 server doesn't handle this key always
169       * correctly... But anyway, on new french keyboards, no more bracket key
170       * at this place.
171       */
172      case XK_dead_circumflex:
173      case XK_dead_diaeresis: return AK_LBRACKET;
174      case XK_dollar:
175      case XK_sterling: return AK_RBRACKET;
176      case XK_comma: case XK_question: return AK_M;
177      case XK_less: case XK_greater: return AK_LTGT;
178      case XK_semicolon: case XK_period: return AK_COMMA;
179      case XK_parenright: case XK_degree: return AK_MINUS;
180      case XK_equal: case XK_plus: return AK_SLASH;
181      case XK_numbersign: return AK_NUMBERSIGN;
182      case XK_colon: case XK_slash: return AK_PERIOD;
183      case XK_minus: case XK_6: return AK_6;
184      case XK_ugrave: case XK_percent: return AK_QUOTE;
185      /* found a spare key - I hope it deserves this place. */
186      case XK_asterisk: case XK_mu: return AK_BACKSLASH;
187      case XK_exclam: case XK_section: return AK_EQUAL;
188      case XK_twosuperior: case XK_asciitilde: return AK_BACKQUOTE;
189      case XK_Multi_key: return AK_RAMI;
190      case XK_Mode_switch: return AK_RALT;
191 #endif
192     }
193 
194     return -1;
195 }
196 
decode_us(KeySym ks)197 static int decode_us (KeySym ks)
198 {
199     switch(ks) {	/* US specific */
200      case XK_A: case XK_a: return AK_A;
201      case XK_M: case XK_m: return AK_M;
202      case XK_Q: case XK_q: return AK_Q;
203      case XK_Y: case XK_y: return AK_Y;
204      case XK_W: case XK_w: return AK_W;
205      case XK_Z: case XK_z: return AK_Z;
206      case XK_bracketleft: return AK_LBRACKET;
207      case XK_bracketright: return AK_RBRACKET;
208      case XK_comma: return AK_COMMA;
209      case XK_period: return AK_PERIOD;
210      case XK_slash: return AK_SLASH;
211      case XK_semicolon: return AK_SEMICOLON;
212      case XK_minus: return AK_MINUS;
213      case XK_equal: return AK_EQUAL;
214 	/* this doesn't work: */
215      case XK_quoteright: return AK_QUOTE;
216      case XK_quoteleft: return AK_BACKQUOTE;
217      case XK_backslash: return AK_BACKSLASH;
218     }
219 
220     return -1;
221 }
222 
decode_de(KeySym ks)223 static int decode_de (KeySym ks)
224 {
225     switch(ks) {
226 	/* DE specific */
227      case XK_A: case XK_a: return AK_A;
228      case XK_M: case XK_m: return AK_M;
229      case XK_Q: case XK_q: return AK_Q;
230      case XK_W: case XK_w: return AK_W;
231      case XK_Y: case XK_y: return AK_Z;
232      case XK_Z: case XK_z: return AK_Y;
233      case XK_Odiaeresis: case XK_odiaeresis: return AK_SEMICOLON;
234      case XK_Adiaeresis: case XK_adiaeresis: return AK_QUOTE;
235      case XK_Udiaeresis: case XK_udiaeresis: return AK_LBRACKET;
236      case XK_plus: case XK_asterisk: return AK_RBRACKET;
237      case XK_comma: return AK_COMMA;
238      case XK_period: return AK_PERIOD;
239      case XK_less: case XK_greater: return AK_LTGT;
240      case XK_numbersign: return AK_NUMBERSIGN;
241      case XK_ssharp: return AK_MINUS;
242      case XK_apostrophe: return AK_EQUAL;
243      case XK_asciicircum: return AK_BACKQUOTE;
244      case XK_minus: return AK_SLASH;
245     }
246 
247     return -1;
248 }
249 
decode_dk(KeySym ks)250 static int decode_dk (KeySym ks)
251 {
252     switch(ks) {
253 	/* DK specific */
254     case XK_A: case XK_a: return AK_A;
255     case XK_M: case XK_m: return AK_M;
256     case XK_Q: case XK_q: return AK_Q;
257     case XK_W: case XK_w: return AK_W;
258     case XK_Y: case XK_y: return AK_Y;
259     case XK_Z: case XK_z: return AK_Z;
260     case XK_AE: case XK_ae: return AK_SEMICOLON;
261     case XK_Ooblique: case XK_oslash: return AK_QUOTE;
262     case XK_Aring: case XK_aring: return AK_LBRACKET;
263     case XK_apostrophe: case XK_asterisk: return AK_NUMBERSIGN;
264     case XK_dead_diaeresis: case XK_dead_circumflex: return AK_RBRACKET;
265     case XK_dead_acute: case XK_dead_grave: return AK_BACKSLASH;
266     case XK_onehalf: case XK_section: return AK_BACKQUOTE;
267     case XK_comma: return AK_COMMA;
268     case XK_period: return AK_PERIOD;
269     case XK_less: case XK_greater: return AK_LTGT;
270     case XK_numbersign: return AK_NUMBERSIGN;
271     case XK_plus: return AK_MINUS;
272     case XK_asciicircum: return AK_BACKQUOTE;
273     case XK_minus: return AK_SLASH;
274     }
275 
276     return -1;
277 }
278 
decode_se(KeySym ks)279 static int decode_se (KeySym ks)
280 {
281     switch(ks) {
282 	/* SE specific */
283      case XK_A: case XK_a: return AK_A;
284      case XK_M: case XK_m: return AK_M;
285      case XK_Q: case XK_q: return AK_Q;
286      case XK_W: case XK_w: return AK_W;
287      case XK_Y: case XK_y: return AK_Y;
288      case XK_Z: case XK_z: return AK_Z;
289      case XK_Odiaeresis: case XK_odiaeresis: return AK_SEMICOLON;
290      case XK_Adiaeresis: case XK_adiaeresis: return AK_QUOTE;
291      case XK_Aring: case XK_aring: return AK_LBRACKET;
292      case XK_comma: return AK_COMMA;
293      case XK_period: return AK_PERIOD;
294      case XK_minus: return AK_SLASH;
295      case XK_less: case XK_greater: return AK_LTGT;
296      case XK_plus: case XK_question: return AK_EQUAL;
297      case XK_at: case XK_onehalf: return AK_BACKQUOTE;
298      case XK_asciitilde: case XK_asciicircum: return AK_RBRACKET;
299      case XK_backslash: case XK_bar: return AK_MINUS;
300 
301      case XK_numbersign: return AK_NUMBERSIGN;
302     }
303 
304     return -1;
305  }
306 
decode_it(KeySym ks)307 static int decode_it (KeySym ks)
308 {
309     switch(ks) {
310 	/* IT specific */
311      case XK_A: case XK_a: return AK_A;
312      case XK_M: case XK_m: return AK_M;
313      case XK_Q: case XK_q: return AK_Q;
314      case XK_W: case XK_w: return AK_W;
315      case XK_Y: case XK_y: return AK_Y;
316      case XK_Z: case XK_z: return AK_Z;
317      case XK_Ograve: case XK_ograve: return AK_SEMICOLON;
318      case XK_Agrave: case XK_agrave: return AK_QUOTE;
319      case XK_Egrave: case XK_egrave: return AK_LBRACKET;
320      case XK_plus: case XK_asterisk: return AK_RBRACKET;
321      case XK_comma: return AK_COMMA;
322      case XK_period: return AK_PERIOD;
323      case XK_less: case XK_greater: return AK_LTGT;
324      case XK_backslash: case XK_bar: return AK_BACKQUOTE;
325      case XK_apostrophe: return AK_MINUS;
326      case XK_Igrave: case XK_igrave: return AK_EQUAL;
327      case XK_minus: return AK_SLASH;
328      case XK_numbersign: return AK_NUMBERSIGN;
329     }
330 
331     return -1;
332 }
333 
decode_es(KeySym ks)334 static int decode_es (KeySym ks)
335 {
336     switch(ks) {
337 	/* ES specific */
338      case XK_A: case XK_a: return AK_A;
339      case XK_M: case XK_m: return AK_M;
340      case XK_Q: case XK_q: return AK_Q;
341      case XK_W: case XK_w: return AK_W;
342      case XK_Y: case XK_y: return AK_Y;
343      case XK_Z: case XK_z: return AK_Z;
344      case XK_ntilde: case XK_Ntilde: return AK_SEMICOLON;
345 #ifdef XK_dead_acute
346      case XK_dead_acute: case XK_dead_diaeresis: return AK_QUOTE;
347      case XK_dead_grave: case XK_dead_circumflex: return AK_LBRACKET;
348 #endif
349      case XK_plus: case XK_asterisk: return AK_RBRACKET;
350      case XK_comma: return AK_COMMA;
351      case XK_period: return AK_PERIOD;
352      case XK_less: case XK_greater: return AK_LTGT;
353      case XK_backslash: case XK_bar: return AK_BACKQUOTE;
354      case XK_apostrophe: return AK_MINUS;
355      case XK_Igrave: case XK_igrave: return AK_EQUAL;
356      case XK_minus: return AK_SLASH;
357      case XK_numbersign: return AK_NUMBERSIGN;
358     }
359 
360     return -1;
361 }
362 
xkeysym2amiga(KeySym ks)363 int xkeysym2amiga (KeySym ks)
364 {
365     int as = kc_decode (ks);
366 
367     if (as == -1) {
368 	switch (currprefs.keyboard_lang) {
369 	    case KBD_LANG_FR:
370 		as = decode_fr (ks); break;
371 	    case KBD_LANG_US:
372 		as = decode_us (ks); break;
373 	    case KBD_LANG_DE:
374 		as = decode_de (ks); break;
375 	    case KBD_LANG_DK:
376 		as = decode_dk (ks); break;
377 	    case KBD_LANG_SE:
378 		as = decode_se (ks); break;
379 	    case KBD_LANG_IT:
380 		as = decode_it (ks); break;
381 	    case KBD_LANG_ES:
382 		as = decode_es (ks); break;
383 	}
384     }
385     return as;
386 }
387 
388 /*
389  * Default hotkeys
390  *
391  * We need a better way of doing this. ;-)
392  */
393 static struct uae_hotkeyseq x11_hotkeys[] =
394 {
395     { MAKE_HOTKEYSEQ (XK_F12, XK_q, -1, -1,           INPUTEVENT_SPC_QUIT) },
396     { MAKE_HOTKEYSEQ (XK_F12, XK_r, -1, -1,           INPUTEVENT_SPC_SOFTRESET) },
397     { MAKE_HOTKEYSEQ (XK_F12, XK_Shift_L, XK_r, -1,   INPUTEVENT_SPC_HARDRESET) },
398     { MAKE_HOTKEYSEQ (XK_F12, XK_d, -1, -1,           INPUTEVENT_SPC_ENTERDEBUGGER) },
399     { MAKE_HOTKEYSEQ (XK_F12, XK_s, -1, -1,           INPUTEVENT_SPC_TOGGLEFULLSCREEN) },
400     { MAKE_HOTKEYSEQ (XK_F12, XK_g, -1, -1,           INPUTEVENT_SPC_TOGGLEMOUSEGRAB) },
401     { MAKE_HOTKEYSEQ (XK_F12, XK_i, -1, -1,           INPUTEVENT_SPC_INHIBITSCREEN) },
402     { MAKE_HOTKEYSEQ (XK_F12, XK_p, -1, -1,           INPUTEVENT_SPC_SCREENSHOT) },
403     { MAKE_HOTKEYSEQ (XK_F12, XK_a, -1, -1,           INPUTEVENT_SPC_SWITCHINTERPOL) },
404     { MAKE_HOTKEYSEQ (XK_F12, XK_KP_Add, -1, -1,      INPUTEVENT_SPC_INCREASE_REFRESHRATE) },
405     { MAKE_HOTKEYSEQ (XK_F12, XK_KP_Subtract, -1, -1, INPUTEVENT_SPC_DECREASE_REFRESHRATE) },
406     { MAKE_HOTKEYSEQ (XK_F12, XK_F1, -1, -1,	      INPUTEVENT_SPC_FLOPPY0) },
407     { MAKE_HOTKEYSEQ (XK_F12, XK_F2, -1, -1,	      INPUTEVENT_SPC_FLOPPY1) },
408     { MAKE_HOTKEYSEQ (XK_F12, XK_F3, -1, -1,	      INPUTEVENT_SPC_FLOPPY2) },
409     { MAKE_HOTKEYSEQ (XK_F12, XK_F4, -1, -1,	      INPUTEVENT_SPC_FLOPPY3) },
410     { MAKE_HOTKEYSEQ (XK_F12, XK_Shift_L, XK_F1, -1,  INPUTEVENT_SPC_EFLOPPY0) },
411     { MAKE_HOTKEYSEQ (XK_F12, XK_Shift_L, XK_F2, -1,  INPUTEVENT_SPC_EFLOPPY1) },
412     { MAKE_HOTKEYSEQ (XK_F12, XK_Shift_L, XK_F3, -1,  INPUTEVENT_SPC_EFLOPPY2) },
413     { MAKE_HOTKEYSEQ (XK_F12, XK_Shift_L, XK_F4, -1,  INPUTEVENT_SPC_EFLOPPY3) },
414     { MAKE_HOTKEYSEQ (XK_F12, XK_Return, -1, -1,      INPUTEVENT_SPC_ENTERGUI) },
415     { MAKE_HOTKEYSEQ (XK_F12, XK_f, -1, -1,           INPUTEVENT_SPC_FREEZEBUTTON) },
416     { HOTKEYS_END }
417 };
418 
get_x11_default_hotkeys(void)419 struct uae_hotkeyseq *get_x11_default_hotkeys (void)
420 {
421     return x11_hotkeys;
422 }
423