6c112464b0ba33fa247656e2d9389644be5fa298
[framework/uifw/ecore.git] / src / lib / ecore_x / xcb / ecore_xcb_keymap.c
1 #include "ecore_xcb_private.h"
2 #define NEED_KEYSYM_TABLE
3 #define NEED_VTABLE
4 #include "ecore_xcb_keysym_table.h"
5 #include <xcb/xcb_keysyms.h>
6 #include <X11/keysym.h>
7
8 /* local function prototypes */
9 static int          _ecore_xcb_keymap_mask_get(void        *reply,
10                                                xcb_keysym_t sym);
11 static xcb_keysym_t _ecore_xcb_keymap_string_to_keysym(const char *str);
12 static int          _ecore_xcb_keymap_translate_key(xcb_keycode_t keycode,
13                                                     unsigned int  modifiers,
14                                                     unsigned int *modifiers_return,
15                                                     xcb_keysym_t *keysym_return);
16 static int _ecore_xcb_keymap_translate_keysym(xcb_keysym_t keysym,
17                                               unsigned int modifiers,
18                                               char        *buffer,
19                                               int          bytes);
20
21 /* local variables */
22 static xcb_key_symbols_t *_ecore_xcb_keysyms;
23 static int _ecore_xcb_mode_switch = 0;
24
25 /* public variables */
26 EAPI int ECORE_X_MODIFIER_SHIFT = 0;
27 EAPI int ECORE_X_MODIFIER_CTRL = 0;
28 EAPI int ECORE_X_MODIFIER_ALT = 0;
29 EAPI int ECORE_X_MODIFIER_WIN = 0;
30 EAPI int ECORE_X_MODIFIER_ALTGR = 0;
31 EAPI int ECORE_X_LOCK_SCROLL = 0;
32 EAPI int ECORE_X_LOCK_NUM = 0;
33 EAPI int ECORE_X_LOCK_CAPS = 0;
34 EAPI int ECORE_X_LOCK_SHIFT = 0;
35
36 void
37 _ecore_xcb_keymap_init(void)
38 {
39    LOGFN(__FILE__, __LINE__, __FUNCTION__);
40
41    _ecore_xcb_keysyms = xcb_key_symbols_alloc(_ecore_xcb_conn);
42 }
43
44 void
45 _ecore_xcb_keymap_finalize(void)
46 {
47    xcb_get_modifier_mapping_cookie_t cookie;
48    xcb_get_modifier_mapping_reply_t *reply;
49
50    LOGFN(__FILE__, __LINE__, __FUNCTION__);
51    CHECK_XCB_CONN;
52
53    cookie = xcb_get_modifier_mapping_unchecked(_ecore_xcb_conn);
54    reply = xcb_get_modifier_mapping_reply(_ecore_xcb_conn, cookie, NULL);
55    if (!reply)
56      {
57         xcb_key_symbols_free(_ecore_xcb_keysyms);
58         return;
59      }
60
61    _ecore_xcb_mode_switch = _ecore_xcb_keymap_mask_get(reply, XK_Mode_switch);
62
63    ECORE_X_MODIFIER_SHIFT = _ecore_xcb_keymap_mask_get(reply, XK_Shift_L);
64    ECORE_X_MODIFIER_CTRL = _ecore_xcb_keymap_mask_get(reply, XK_Control_L);
65
66    ECORE_X_MODIFIER_ALT = _ecore_xcb_keymap_mask_get(reply, XK_Alt_L);
67    if (!ECORE_X_MODIFIER_ALT)
68      ECORE_X_MODIFIER_ALT = _ecore_xcb_keymap_mask_get(reply, XK_Meta_L);
69    if (!ECORE_X_MODIFIER_ALT)
70      ECORE_X_MODIFIER_ALT = _ecore_xcb_keymap_mask_get(reply, XK_Super_L);
71
72    ECORE_X_MODIFIER_WIN = _ecore_xcb_keymap_mask_get(reply, XK_Super_L);
73    if (!ECORE_X_MODIFIER_WIN)
74      ECORE_X_MODIFIER_WIN = _ecore_xcb_keymap_mask_get(reply, XK_Meta_L);
75
76    ECORE_X_MODIFIER_ALTGR = _ecore_xcb_keymap_mask_get(reply, XK_Mode_switch);
77
78    if (ECORE_X_MODIFIER_WIN == ECORE_X_MODIFIER_ALT)
79      ECORE_X_MODIFIER_WIN = 0;
80    if (ECORE_X_MODIFIER_ALT == ECORE_X_MODIFIER_CTRL)
81      ECORE_X_MODIFIER_ALT = 0;
82
83    ECORE_X_LOCK_SCROLL = _ecore_xcb_keymap_mask_get(reply, XK_Scroll_Lock);
84    ECORE_X_LOCK_NUM = _ecore_xcb_keymap_mask_get(reply, XK_Num_Lock);
85    ECORE_X_LOCK_CAPS = _ecore_xcb_keymap_mask_get(reply, XK_Caps_Lock);
86    ECORE_X_LOCK_SHIFT = _ecore_xcb_keymap_mask_get(reply, XK_Shift_Lock);
87 }
88
89 void
90 _ecore_xcb_modifiers_get(void)
91 {
92    _ecore_xcb_keymap_finalize();
93 }
94
95 void
96 _ecore_xcb_keymap_shutdown(void)
97 {
98    LOGFN(__FILE__, __LINE__, __FUNCTION__);
99
100    if (_ecore_xcb_keysyms) xcb_key_symbols_free(_ecore_xcb_keysyms);
101 }
102
103 void
104 _ecore_xcb_keymap_refresh(xcb_mapping_notify_event_t *event)
105 {
106    CHECK_XCB_CONN;
107    xcb_refresh_keyboard_mapping(_ecore_xcb_keysyms, event);
108 }
109
110 xcb_keysym_t
111 _ecore_xcb_keymap_keycode_to_keysym(xcb_keycode_t keycode,
112                                     int           col)
113 {
114    xcb_keysym_t key0, key1;
115
116    CHECK_XCB_CONN;
117    if (col & _ecore_xcb_mode_switch)
118      {
119         key0 = xcb_key_symbols_get_keysym(_ecore_xcb_keysyms, keycode, 4);
120         key1 = xcb_key_symbols_get_keysym(_ecore_xcb_keysyms, keycode, 5);
121      }
122    else
123      {
124         key0 = xcb_key_symbols_get_keysym(_ecore_xcb_keysyms, keycode, 0);
125         key1 = xcb_key_symbols_get_keysym(_ecore_xcb_keysyms, keycode, 1);
126      }
127
128    if (key1 == XCB_NO_SYMBOL)
129      key1 = key0;
130
131    if ((col & ECORE_X_LOCK_NUM) &&
132        ((xcb_is_keypad_key(key1)) || (xcb_is_private_keypad_key(key1))))
133      {
134         if ((col & XCB_MOD_MASK_SHIFT) ||
135             ((col & XCB_MOD_MASK_LOCK) && (col & ECORE_X_LOCK_SHIFT)))
136           return key0;
137         else
138           return key1;
139      }
140    else if (!(col & XCB_MOD_MASK_SHIFT) && !(col & XCB_MOD_MASK_LOCK))
141      return key0;
142    else if (!(col & XCB_MOD_MASK_SHIFT) &&
143             (col & XCB_MOD_MASK_LOCK && (col & ECORE_X_LOCK_CAPS)))
144      return key1;
145    else if ((col & XCB_MOD_MASK_SHIFT) &&
146             (col & XCB_MOD_MASK_LOCK) && (col & ECORE_X_LOCK_CAPS))
147      return key0;
148    else if ((col & XCB_MOD_MASK_SHIFT) ||
149             (col & XCB_MOD_MASK_LOCK && (col & ECORE_X_LOCK_SHIFT)))
150      return key1;
151
152    return XCB_NO_SYMBOL;
153 }
154
155 xcb_keycode_t *
156 _ecore_xcb_keymap_keysym_to_keycode(xcb_keysym_t keysym)
157 {
158    CHECK_XCB_CONN;
159    return xcb_key_symbols_get_keycode(_ecore_xcb_keysyms, keysym);
160 }
161
162 char *
163 _ecore_xcb_keymap_keysym_to_string(xcb_keysym_t keysym)
164 {
165    int i = 0, n = 0, h = 0, idx = 0;
166    const unsigned char *entry;
167    unsigned char val1, val2, val3, val4;
168
169    CHECK_XCB_CONN;
170    if (!keysym) return NULL;
171    if (keysym == XK_VoidSymbol) keysym = 0;
172    if (keysym <= 0x1fffffff)
173      {
174         val1 = (keysym >> 24);
175         val2 = ((keysym >> 16) & 0xff);
176         val3 = ((keysym >> 8) & 0xff);
177         val4 = (keysym & 0xff);
178         i = keysym % VTABLESIZE;
179         h = i + 1;
180         n = VMAXHASH;
181         while ((idx = hashKeysym[i]))
182           {
183              entry = &_ecore_xcb_keytable[idx];
184              if ((entry[0] == val1) && (entry[1] == val2) &&
185                  (entry[2] == val3) && (entry[3] == val4))
186                return (char *)entry + 4;
187              if (!--n) break;
188              i += h;
189              if (i >= VTABLESIZE) i -= VTABLESIZE;
190           }
191      }
192
193    if ((keysym >= 0x01000100) && (keysym <= 0x0110ffff))
194      {
195         xcb_keysym_t val;
196         char *s = NULL;
197         int i = 0;
198
199         val = (keysym & 0xffffff);
200         if (val & 0xff0000)
201           i = 10;
202         else
203           i = 6;
204
205         if (!(s = malloc(i))) return NULL;
206         i--;
207         s[i--] = '\0';
208         for (; i; i--)
209           {
210              val1 = (val & 0xf);
211              val >>= 4;
212              if (val1 < 10)
213                s[i] = '0' + val1;
214              else
215                s[i] = 'A' + val1 - 10;
216           }
217         s[i] = 'U';
218         return s;
219      }
220
221    return NULL;
222 }
223
224 xcb_keycode_t
225 _ecore_xcb_keymap_string_to_keycode(const char *key)
226 {
227    if (!strncmp(key, "Keycode-", 8))
228      return atoi(key + 8);
229    else
230      {
231         xcb_keysym_t keysym = XCB_NO_SYMBOL;
232         xcb_keycode_t *keycodes, keycode = 0;
233         int i = 0;
234
235         CHECK_XCB_CONN;
236
237         keysym = _ecore_xcb_keymap_string_to_keysym(key);
238         if (keysym == XCB_NO_SYMBOL) return XCB_NO_SYMBOL;
239
240         keycodes = _ecore_xcb_keymap_keysym_to_keycode(keysym);
241         if (!keycodes) return XCB_NO_SYMBOL;
242
243         while (keycodes[i] != XCB_NO_SYMBOL)
244           {
245              if (keycodes[i] != 0)
246                {
247                   keycode = keycodes[i];
248                   break;
249                }
250              i++;
251           }
252         return keycode;
253      }
254 }
255
256 int
257 _ecore_xcb_keymap_lookup_string(xcb_keycode_t keycode,
258                                 int           state,
259                                 char         *buffer,
260                                 int           bytes,
261                                 xcb_keysym_t *sym)
262 {
263    unsigned int modifiers = 0;
264    xcb_keysym_t keysym;
265
266    CHECK_XCB_CONN;
267    if (!_ecore_xcb_keymap_translate_key(keycode, state, &modifiers, &keysym))
268      return 0;
269
270    if (sym) *sym = keysym;
271
272    return _ecore_xcb_keymap_translate_keysym(keysym, state, buffer, bytes);
273 }
274
275 EAPI const char *
276 ecore_x_keysym_string_get(int keysym)
277 {
278    LOGFN(__FILE__, __LINE__, __FUNCTION__);
279
280    return _ecore_xcb_keymap_keysym_to_string(keysym);
281 }
282
283 EAPI int 
284 ecore_x_keysym_keycode_get(const char *keyname)
285 {
286    LOGFN(__FILE__, __LINE__, __FUNCTION__);
287
288    return _ecore_xcb_keymap_string_to_keycode(keyname);
289 }
290
291 /* local functions */
292 static int
293 _ecore_xcb_keymap_mask_get(void        *reply,
294                            xcb_keysym_t sym)
295 {
296    xcb_get_modifier_mapping_reply_t *rep;
297    xcb_keysym_t sym2;
298    int mask = 0;
299    const int masks[8] =
300    {
301       XCB_MOD_MASK_SHIFT, XCB_MOD_MASK_LOCK, XCB_MOD_MASK_CONTROL,
302       XCB_MOD_MASK_1, XCB_MOD_MASK_2, XCB_MOD_MASK_3, XCB_MOD_MASK_4,
303       XCB_MOD_MASK_5
304    };
305
306    LOGFN(__FILE__, __LINE__, __FUNCTION__);
307    CHECK_XCB_CONN;
308
309    rep = (xcb_get_modifier_mapping_reply_t *)reply;
310    if ((rep) && (rep->keycodes_per_modifier > 0))
311      {
312         int i = 0;
313         xcb_keycode_t *modmap;
314
315         modmap = xcb_get_modifier_mapping_keycodes(rep);
316         for (i = 0; i < (8 * rep->keycodes_per_modifier); i++)
317           {
318              int j = 0;
319
320              for (j = 0; j < 8; j++)
321                {
322                   sym2 =
323                     xcb_key_symbols_get_keysym(_ecore_xcb_keysyms,
324                                                modmap[i], j);
325                   if (sym2 != 0) break;
326                }
327              if (sym2 == sym)
328                {
329                   mask = masks[i / rep->keycodes_per_modifier];
330                   break;
331                }
332           }
333      }
334
335    return mask;
336 }
337
338 static xcb_keysym_t
339 _ecore_xcb_keymap_string_to_keysym(const char *str)
340 {
341    int i = 0, n = 0, h = 0;
342    unsigned long sig = 0;
343    const char *p = NULL;
344    int c = 0, idx = 0;
345    const unsigned char *entry;
346    unsigned char sig1, sig2;
347    long unsigned int val;
348
349    p = str;
350    while ((c = *p++))
351      sig = (sig << 1) + c;
352
353    i = (sig % KTABLESIZE);
354    h = i + 1;
355    sig1 = (sig >> 8) & 0xff;
356    sig2 = sig & 0xff;
357    n = KMAXHASH;
358
359    while ((idx = hashString[i]))
360      {
361         entry = &_ecore_xcb_keytable[idx];
362         if ((entry[0] == sig1) && (entry[1] == sig2) &&
363             !strcmp(str, (char *)entry + 6))
364           {
365              val = ((entry[2] << 24) | (entry[3] << 16) |
366                     (entry[4] << 8) | (entry[5]));
367              if (!val) val = 0xffffff;
368              return val;
369           }
370         if (!--n) break;
371         i += h;
372         if (i >= KTABLESIZE) i -= KTABLESIZE;
373      }
374
375    if (*str == 'U')
376      {
377         val = 0;
378         for (p = &str[1]; *p; p++)
379           {
380              c = *p;
381              if (('0' <= c) && (c <= '9'))
382                val = (val << 4) + c - '0';
383              else if (('a' <= c) && (c <= 'f'))
384                val = (val << 4) + c - 'a' + 10;
385              else if (('A' <= c) && (c <= 'F'))
386                val = (val << 4) + c - 'A' + 10;
387              else
388                return XCB_NO_SYMBOL;
389              if (val > 0x10ffff) return XCB_NO_SYMBOL;
390           }
391         if ((val < 0x20) || ((val > 0x7e) && (val < 0xa0)))
392           return XCB_NO_SYMBOL;
393         if (val < 0x100) return val;
394         return val | 0x01000000;
395      }
396
397    if ((strlen(str) > 2) && (str[0] == '0') && (str[1] == 'x'))
398      {
399         char *tmp = NULL;
400
401         val = strtoul(str, &tmp, 16);
402         if ((val == ULONG_MAX) || ((tmp) && (*tmp != '\0')))
403           return XCB_NO_SYMBOL;
404         else
405           return val;
406      }
407
408    if (!strncmp(str, "XF86_", 5))
409      {
410         long unsigned int ret;
411         char *tmp;
412
413         tmp = strdup(str);
414         if (!tmp) return XCB_NO_SYMBOL;
415         memmove(&tmp[4], &tmp[5], strlen(str) - 5 + 1);
416         ret = _ecore_xcb_keymap_string_to_keysym(tmp);
417         free(tmp);
418         return ret;
419      }
420
421    return XCB_NO_SYMBOL;
422 }
423
424 static int
425 _ecore_xcb_keymap_translate_key(xcb_keycode_t keycode,
426                                 unsigned int  modifiers,
427                                 unsigned int *modifiers_return,
428                                 xcb_keysym_t *keysym_return)
429 {
430    xcb_keysym_t sym;
431
432    if (!_ecore_xcb_keysyms) return 0;
433
434    sym = _ecore_xcb_keymap_keycode_to_keysym(keycode, modifiers);
435
436    if (modifiers_return)
437      *modifiers_return = ((XCB_MOD_MASK_SHIFT | XCB_MOD_MASK_LOCK) |
438                           _ecore_xcb_mode_switch | ECORE_X_LOCK_NUM);
439    if (keysym_return)
440      *keysym_return = sym;
441
442    return 1;
443 }
444
445 static int
446 _ecore_xcb_keymap_translate_keysym(xcb_keysym_t keysym,
447                                    unsigned int modifiers,
448                                    char        *buffer,
449                                    int          bytes)
450 {
451    unsigned long hbytes = 0;
452    unsigned char c;
453
454    if (!keysym) return 0;
455    hbytes = (keysym >> 8);
456
457    if (!(bytes &&
458          ((hbytes == 0) ||
459           ((hbytes == 0xFF) &&
460            (((keysym >= XK_BackSpace) && (keysym <= XK_Clear)) ||
461             (keysym == XK_Return) || (keysym == XK_Escape) ||
462             (keysym == XK_KP_Space) || (keysym == XK_KP_Tab) ||
463             (keysym == XK_KP_Enter) ||
464             ((keysym >= XK_KP_Multiply) && (keysym <= XK_KP_9)) ||
465             (keysym == XK_KP_Equal) || (keysym == XK_Delete))))))
466      return 0;
467
468    if (keysym == XK_KP_Space)
469      c = (XK_space & 0x7F);
470    else if (hbytes == 0xFF)
471      c = (keysym & 0x7F);
472    else
473      c = (keysym & 0xFF);
474
475    if (modifiers & ECORE_X_MODIFIER_CTRL)
476      {
477         if (((c >= '@') && (c < '\177')) || c == ' ')
478           c &= 0x1F;
479         else if (c == '2')
480           c = '\000';
481         else if ((c >= '3') && (c <= '7'))
482           c -= ('3' - '\033');
483         else if (c == '8')
484           c = '\177';
485         else if (c == '/')
486           c = '_' & 0x1F;
487      }
488    buffer[0] = c;
489    return 1;
490 }
491