1 | // LAF OS Library |
---|---|
2 | // Copyright (C) 2016-2018 David Capello |
3 | // |
4 | // This file is released under the terms of the MIT license. |
5 | // Read LICENSE.txt for more information. |
6 | |
7 | #ifdef HAVE_CONFIG_H |
8 | #include "config.h" |
9 | #endif |
10 | |
11 | #include "base/ints.h" |
12 | #include "os/x11/keys.h" |
13 | #include "os/x11/x11.h" |
14 | |
15 | #include <X11/Xlib.h> |
16 | #include <X11/keysym.h> |
17 | |
18 | namespace os { |
19 | |
20 | bool g_spaceBarIsPressed = false; |
21 | |
22 | KeyScancode x11_keysym_to_scancode(const KeySym keysym) |
23 | { |
24 | switch (keysym) { |
25 | case XK_BackSpace: return kKeyBackspace; |
26 | case XK_Tab: return kKeyTab; |
27 | case XK_Linefeed: return kKeyEnter; |
28 | case XK_Clear: return kKeyDel; |
29 | case XK_Return: return kKeyEnter; |
30 | case XK_Pause: |
31 | case XK_Break: return kKeyPause; |
32 | case XK_Scroll_Lock: return kKeyScrLock; |
33 | case XK_Escape: return kKeyEsc; |
34 | case XK_Delete: return kKeyDel; |
35 | case XK_Home: return kKeyHome; |
36 | case XK_Left: return kKeyLeft; |
37 | case XK_Up: return kKeyUp; |
38 | case XK_Right: return kKeyRight; |
39 | case XK_Down: return kKeyDown; |
40 | case XK_Page_Up: return kKeyPageUp; |
41 | case XK_Page_Down: return kKeyPageDown; |
42 | case XK_End: return kKeyEnd; |
43 | case XK_Sys_Req: |
44 | case XK_Print: return kKeyPrtscr; |
45 | case XK_Insert: return kKeyInsert; |
46 | case XK_Menu: return kKeyMenu; |
47 | case XK_Num_Lock: return kKeyNumLock; |
48 | case XK_KP_Space: return kKeySpace; |
49 | case XK_KP_Tab: return kKeyTab; |
50 | case XK_KP_Enter: return kKeyEnterPad; |
51 | case XK_KP_0: case XK_KP_Insert: return kKey0Pad; |
52 | case XK_KP_1: case XK_KP_End: return kKey1Pad; |
53 | case XK_KP_2: case XK_KP_Down: return kKey2Pad; |
54 | case XK_KP_3: case XK_KP_Page_Down: return kKey3Pad; |
55 | case XK_KP_4: case XK_KP_Left: return kKey4Pad; |
56 | case XK_KP_5: case XK_KP_Begin: return kKey5Pad; |
57 | case XK_KP_6: case XK_KP_Right: return kKey6Pad; |
58 | case XK_KP_7: case XK_KP_Home: return kKey7Pad; |
59 | case XK_KP_8: case XK_KP_Up: return kKey8Pad; |
60 | case XK_KP_9: case XK_KP_Page_Up: return kKey9Pad; |
61 | case XK_KP_Decimal: |
62 | case XK_KP_Delete: return kKeyDelPad; |
63 | case XK_KP_Equal: return kKeyEqualsPad; |
64 | case XK_KP_Multiply: return kKeyAsterisk; |
65 | case XK_KP_Add: return kKeyPlusPad; |
66 | case XK_KP_Subtract: return kKeyMinusPad; |
67 | case XK_KP_Divide: return kKeySlashPad; |
68 | case XK_F1: return kKeyF1; |
69 | case XK_F2: return kKeyF2; |
70 | case XK_F3: return kKeyF3; |
71 | case XK_F4: return kKeyF4; |
72 | case XK_F5: return kKeyF5; |
73 | case XK_F6: return kKeyF6; |
74 | case XK_F7: return kKeyF7; |
75 | case XK_F8: return kKeyF8; |
76 | case XK_F9: return kKeyF9; |
77 | case XK_F10: return kKeyF10; |
78 | case XK_F11: return kKeyF11; |
79 | case XK_F12: return kKeyF12; |
80 | case XK_Shift_L: return kKeyLShift; |
81 | case XK_Shift_R: return kKeyRShift; |
82 | case XK_Control_L: return kKeyLControl; |
83 | case XK_Control_R: return kKeyRControl; |
84 | case XK_Caps_Lock: return kKeyCapsLock; |
85 | case XK_Alt_L: return kKeyAlt; |
86 | case XK_Alt_R: return kKeyAltGr; |
87 | case XK_Meta_L: |
88 | case XK_Super_L: return kKeyLWin; |
89 | case XK_Meta_R: |
90 | case XK_Super_R: return kKeyRWin; |
91 | case XK_space: return kKeySpace; |
92 | case XK_apostrophe: return kKeyQuote; |
93 | case XK_comma: return kKeyComma; |
94 | case XK_minus: return kKeyMinus; |
95 | case XK_period: return kKeyStop; |
96 | case XK_slash: return kKeySlash; |
97 | case XK_0: return kKey0; |
98 | case XK_1: return kKey1; |
99 | case XK_2: return kKey2; |
100 | case XK_3: return kKey3; |
101 | case XK_4: return kKey4; |
102 | case XK_5: return kKey5; |
103 | case XK_6: return kKey6; |
104 | case XK_7: return kKey7; |
105 | case XK_8: return kKey8; |
106 | case XK_9: return kKey9; |
107 | case XK_semicolon: return kKeyColon; |
108 | case XK_less: return kKeyBackslash2; |
109 | case XK_A: return kKeyA; |
110 | case XK_B: return kKeyB; |
111 | case XK_C: return kKeyC; |
112 | case XK_D: return kKeyD; |
113 | case XK_E: return kKeyE; |
114 | case XK_F: return kKeyF; |
115 | case XK_G: return kKeyG; |
116 | case XK_H: return kKeyH; |
117 | case XK_I: return kKeyI; |
118 | case XK_J: return kKeyJ; |
119 | case XK_K: return kKeyK; |
120 | case XK_L: return kKeyL; |
121 | case XK_M: return kKeyM; |
122 | case XK_N: return kKeyN; |
123 | case XK_O: return kKeyO; |
124 | case XK_P: return kKeyP; |
125 | case XK_Q: return kKeyQ; |
126 | case XK_R: return kKeyR; |
127 | case XK_S: return kKeyS; |
128 | case XK_T: return kKeyT; |
129 | case XK_U: return kKeyU; |
130 | case XK_V: return kKeyV; |
131 | case XK_W: return kKeyW; |
132 | case XK_X: return kKeyX; |
133 | case XK_Y: return kKeyY; |
134 | case XK_Z: return kKeyZ; |
135 | case XK_bracketleft: return kKeyOpenbrace; |
136 | case XK_backslash: return kKeyBackslash; |
137 | case XK_bracketright: return kKeyClosebrace; |
138 | case XK_grave: return kKeyTilde; |
139 | case XK_a: return kKeyA; |
140 | case XK_b: return kKeyB; |
141 | case XK_c: return kKeyC; |
142 | case XK_d: return kKeyD; |
143 | case XK_e: return kKeyE; |
144 | case XK_f: return kKeyF; |
145 | case XK_g: return kKeyG; |
146 | case XK_h: return kKeyH; |
147 | case XK_i: return kKeyI; |
148 | case XK_j: return kKeyJ; |
149 | case XK_k: return kKeyK; |
150 | case XK_l: return kKeyL; |
151 | case XK_m: return kKeyM; |
152 | case XK_n: return kKeyN; |
153 | case XK_o: return kKeyO; |
154 | case XK_p: return kKeyP; |
155 | case XK_q: return kKeyQ; |
156 | case XK_r: return kKeyR; |
157 | case XK_s: return kKeyS; |
158 | case XK_t: return kKeyT; |
159 | case XK_u: return kKeyU; |
160 | case XK_v: return kKeyV; |
161 | case XK_w: return kKeyW; |
162 | case XK_x: return kKeyX; |
163 | case XK_y: return kKeyY; |
164 | case XK_z: return kKeyZ; |
165 | } |
166 | return kKeyNil; |
167 | } |
168 | |
169 | KeySym x11_keysym_to_scancode(const KeyScancode scancode) |
170 | { |
171 | switch (scancode) { |
172 | case kKeyBackspace: return XK_BackSpace; |
173 | case kKeyTab: return XK_Tab; |
174 | case kKeyEnter: return XK_Return; |
175 | case kKeyPause: return XK_Pause; |
176 | case kKeyScrLock: return XK_Scroll_Lock; |
177 | case kKeyEsc: return XK_Escape; |
178 | case kKeyDel: return XK_Delete; |
179 | case kKeyHome: return XK_Home; |
180 | case kKeyLeft: return XK_Left; |
181 | case kKeyUp: return XK_Up; |
182 | case kKeyRight: return XK_Right; |
183 | case kKeyDown: return XK_Down; |
184 | case kKeyPageUp: return XK_Page_Up; |
185 | case kKeyPageDown: return XK_Page_Down; |
186 | case kKeyEnd: return XK_End; |
187 | case kKeyPrtscr: return XK_Print; |
188 | case kKeyInsert: return XK_Insert; |
189 | case kKeyMenu: return XK_Menu; |
190 | case kKeyNumLock: return XK_Num_Lock; |
191 | case kKeyEnterPad: return XK_KP_Enter; |
192 | case kKey0Pad: return XK_KP_0; |
193 | case kKey1Pad: return XK_KP_1; |
194 | case kKey2Pad: return XK_KP_2; |
195 | case kKey3Pad: return XK_KP_3; |
196 | case kKey4Pad: return XK_KP_4; |
197 | case kKey5Pad: return XK_KP_5; |
198 | case kKey6Pad: return XK_KP_6; |
199 | case kKey7Pad: return XK_KP_7; |
200 | case kKey8Pad: return XK_KP_8; |
201 | case kKey9Pad: return XK_KP_9; |
202 | case kKeyDelPad: return XK_KP_Delete; |
203 | case kKeyEqualsPad: return XK_KP_Equal; |
204 | case kKeyAsterisk: return XK_KP_Multiply; |
205 | case kKeyPlusPad: return XK_KP_Add; |
206 | case kKeyMinusPad: return XK_KP_Subtract; |
207 | case kKeySlashPad: return XK_KP_Divide; |
208 | case kKeyF1: return XK_F1; |
209 | case kKeyF2: return XK_F2; |
210 | case kKeyF3: return XK_F3; |
211 | case kKeyF4: return XK_F4; |
212 | case kKeyF5: return XK_F5; |
213 | case kKeyF6: return XK_F6; |
214 | case kKeyF7: return XK_F7; |
215 | case kKeyF8: return XK_F8; |
216 | case kKeyF9: return XK_F9; |
217 | case kKeyF10: return XK_F10; |
218 | case kKeyF11: return XK_F11; |
219 | case kKeyF12: return XK_F12; |
220 | case kKeyLShift: return XK_Shift_L; |
221 | case kKeyRShift: return XK_Shift_R; |
222 | case kKeyLControl: return XK_Control_L; |
223 | case kKeyRControl: return XK_Control_R; |
224 | case kKeyCapsLock: return XK_Caps_Lock; |
225 | case kKeyAlt: return XK_Alt_L; |
226 | case kKeyAltGr: return XK_Alt_R; |
227 | case kKeyLWin: return XK_Super_L; |
228 | case kKeyRWin: return XK_Super_R; |
229 | case kKeySpace: return XK_space; |
230 | case kKeyQuote: return XK_apostrophe; |
231 | case kKeyComma: return XK_comma; |
232 | case kKeyMinus: return XK_minus; |
233 | case kKeyStop: return XK_period; |
234 | case kKeySlash: return XK_slash; |
235 | case kKey0: return XK_0; |
236 | case kKey1: return XK_1; |
237 | case kKey2: return XK_2; |
238 | case kKey3: return XK_3; |
239 | case kKey4: return XK_4; |
240 | case kKey5: return XK_5; |
241 | case kKey6: return XK_6; |
242 | case kKey7: return XK_7; |
243 | case kKey8: return XK_8; |
244 | case kKey9: return XK_9; |
245 | case kKeyColon: return XK_semicolon; |
246 | case kKeyBackslash2: return XK_less; |
247 | case kKeyOpenbrace: return XK_bracketleft; |
248 | case kKeyBackslash: return XK_backslash; |
249 | case kKeyClosebrace: return XK_bracketright; |
250 | case kKeyTilde: return XK_grave; |
251 | case kKeyA: return XK_a; |
252 | case kKeyB: return XK_b; |
253 | case kKeyC: return XK_c; |
254 | case kKeyD: return XK_d; |
255 | case kKeyE: return XK_e; |
256 | case kKeyF: return XK_f; |
257 | case kKeyG: return XK_g; |
258 | case kKeyH: return XK_h; |
259 | case kKeyI: return XK_i; |
260 | case kKeyJ: return XK_j; |
261 | case kKeyK: return XK_k; |
262 | case kKeyL: return XK_l; |
263 | case kKeyM: return XK_m; |
264 | case kKeyN: return XK_n; |
265 | case kKeyO: return XK_o; |
266 | case kKeyP: return XK_p; |
267 | case kKeyQ: return XK_q; |
268 | case kKeyR: return XK_r; |
269 | case kKeyS: return XK_s; |
270 | case kKeyT: return XK_t; |
271 | case kKeyU: return XK_u; |
272 | case kKeyV: return XK_v; |
273 | case kKeyW: return XK_w; |
274 | case kKeyX: return XK_x; |
275 | case kKeyY: return XK_y; |
276 | case kKeyZ: return XK_z; |
277 | } |
278 | return 0; |
279 | } |
280 | |
281 | bool x11_is_key_pressed(const KeyScancode scancode) |
282 | { |
283 | ::Display* display = X11::instance()->display(); |
284 | const KeySym keysym = x11_keysym_to_scancode(scancode); |
285 | const KeyCode keycode = XKeysymToKeycode(display, keysym); |
286 | if (!keycode) |
287 | return false; |
288 | |
289 | // TODO several platforms have this kind of API to get the whole |
290 | // keyboard state, it would be a lot better if we expose this |
291 | // API to the user (so we don't have to call XQueryKeymap for |
292 | // each key). |
293 | char keys[32]; |
294 | XQueryKeymap(display, keys); |
295 | |
296 | return (keys[keycode/8] & (1 << (keycode%8)) ? true: false); |
297 | } |
298 | |
299 | // TODO I guess that this code should be common to all platforms, but |
300 | // osx/win_get_unicode_from_scancode() work in a different way: |
301 | // the Unicode is returned only if the scancode key is pressed |
302 | // (and that's the case anyway in the only part we are using |
303 | // System::getUnicodeFromScancode(), a System::isKeyPressed() is |
304 | // tested before). |
305 | int x11_get_unicode_from_scancode(const KeyScancode scancode) |
306 | { |
307 | switch (scancode) { |
308 | case kKeyEqualsPad: return '='; |
309 | case kKeyAsterisk: return '*'; |
310 | case kKeyPlusPad: return '+'; |
311 | case kKeyMinusPad: return '-'; |
312 | case kKeySlashPad: return '/'; |
313 | case kKeySpace: return ' '; |
314 | case kKeyQuote: return '\''; |
315 | case kKeyComma: return ','; |
316 | case kKeyMinus: return '-'; |
317 | case kKeyStop: return '.'; |
318 | case kKeySlash: return '/'; |
319 | case kKey0: case kKey0Pad: return '0'; |
320 | case kKey1: case kKey1Pad: return '1'; |
321 | case kKey2: case kKey2Pad: return '2'; |
322 | case kKey3: case kKey3Pad: return '3'; |
323 | case kKey4: case kKey4Pad: return '4'; |
324 | case kKey5: case kKey5Pad: return '5'; |
325 | case kKey6: case kKey6Pad: return '6'; |
326 | case kKey7: case kKey7Pad: return '7'; |
327 | case kKey8: case kKey8Pad: return '8'; |
328 | case kKey9: case kKey9Pad: return '9'; |
329 | case kKeyColon: return ':'; |
330 | case kKeyBackslash: case kKeyBackslash2: return '\\'; |
331 | case kKeyOpenbrace: return '['; |
332 | case kKeyClosebrace: return ']'; |
333 | case kKeyTilde: return '~'; |
334 | case kKeyA: return 'a'; |
335 | case kKeyB: return 'b'; |
336 | case kKeyC: return 'c'; |
337 | case kKeyD: return 'd'; |
338 | case kKeyE: return 'e'; |
339 | case kKeyF: return 'f'; |
340 | case kKeyG: return 'g'; |
341 | case kKeyH: return 'h'; |
342 | case kKeyI: return 'i'; |
343 | case kKeyJ: return 'j'; |
344 | case kKeyK: return 'k'; |
345 | case kKeyL: return 'l'; |
346 | case kKeyM: return 'm'; |
347 | case kKeyN: return 'n'; |
348 | case kKeyO: return 'o'; |
349 | case kKeyP: return 'p'; |
350 | case kKeyQ: return 'q'; |
351 | case kKeyR: return 'r'; |
352 | case kKeyS: return 's'; |
353 | case kKeyT: return 't'; |
354 | case kKeyU: return 'u'; |
355 | case kKeyV: return 'v'; |
356 | case kKeyW: return 'w'; |
357 | case kKeyX: return 'x'; |
358 | case kKeyY: return 'y'; |
359 | case kKeyZ: return 'z'; |
360 | } |
361 | return 0; |
362 | } |
363 | |
364 | KeyModifiers get_modifiers_from_x(const int state) |
365 | { |
366 | int modifiers = kKeyNoneModifier; |
367 | if (state & ShiftMask) modifiers |= kKeyShiftModifier; |
368 | if (state & ControlMask) modifiers |= kKeyCtrlModifier; |
369 | // Mod1Mask is Alt, and Mod5Mask is AltGr |
370 | if (state & (Mod1Mask | Mod5Mask)) modifiers |= kKeyAltModifier; |
371 | // Mod4Mask is Windows key |
372 | if (state & Mod4Mask) modifiers |= kKeyWinModifier; |
373 | if (g_spaceBarIsPressed) modifiers |= kKeySpaceModifier; |
374 | return (KeyModifiers)modifiers; |
375 | } |
376 | |
377 | } // namespace os |
378 |