• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* Copyright (C) 2007-2008 The Android Open Source Project
2 **
3 ** This software is licensed under the terms of the GNU General Public
4 ** License version 2, as published by the Free Software Foundation, and
5 ** may be copied, distributed, and modified under those terms.
6 **
7 ** This program is distributed in the hope that it will be useful,
8 ** but WITHOUT ANY WARRANTY; without even the implied warranty of
9 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
10 ** GNU General Public License for more details.
11 */
12 #include "android/skin/keyboard.h"
13 #include "android/utils/debug.h"
14 #include "android/utils/bufprint.h"
15 #include "android/utils/system.h"
16 #include "android/android.h"
17 
18 #define  DEBUG  1
19 
20 #if DEBUG
21 #  define  D(...)  VERBOSE_PRINT(keys,__VA_ARGS__)
22 #else
23 #  define  D(...)  ((void)0)
24 #endif
25 
26 
27 /** LAST PRESSED KEYS
28  ** a small buffer of last pressed keys, this is used to properly
29  ** implement the Unicode keyboard mode (SDL key up event always have
30  ** their .unicode field set to 0
31  **/
32 typedef struct {
33     int  unicode;  /* Unicode of last pressed key        */
34     int  sym;      /* SDL key symbol value (e.g. SDLK_a) */
35     int  mod;      /* SDL key modifier value             */
36 } LastKey;
37 
38 #define  MAX_LAST_KEYS  16
39 #define  MAX_KEYCODES   256*2
40 
41 struct SkinKeyboard {
42     const AKeyCharmap*  charmap;
43     SkinKeyset*         kset;
44     char                enabled;
45     char                raw_keys;
46     char                last_count;
47     int                 keycode_count;
48 
49     SkinRotation        rotation;
50 
51     SkinKeyCommandFunc  command_func;
52     void*               command_opaque;
53     SkinKeyEventFunc    press_func;
54     void*               press_opaque;
55 
56     LastKey             last_keys[ MAX_LAST_KEYS ];
57     int                 keycodes[ MAX_KEYCODES ];
58 };
59 
60 
61 void
skin_keyboard_set_keyset(SkinKeyboard * keyboard,SkinKeyset * kset)62 skin_keyboard_set_keyset( SkinKeyboard*  keyboard, SkinKeyset*  kset )
63 {
64     if (kset == NULL)
65         return;
66     if (keyboard->kset && keyboard->kset != android_keyset) {
67         skin_keyset_free(keyboard->kset);
68     }
69     keyboard->kset = kset;
70 }
71 
72 
73 const char*
skin_keyboard_charmap_name(SkinKeyboard * keyboard)74 skin_keyboard_charmap_name( SkinKeyboard*  keyboard )
75 {
76     if (keyboard && keyboard->charmap)
77         return keyboard->charmap->name;
78 
79     return "qwerty";
80 }
81 
82 void
skin_keyboard_set_rotation(SkinKeyboard * keyboard,SkinRotation rotation)83 skin_keyboard_set_rotation( SkinKeyboard*     keyboard,
84                             SkinRotation      rotation )
85 {
86     keyboard->rotation = (rotation & 3);
87 }
88 
89 void
skin_keyboard_on_command(SkinKeyboard * keyboard,SkinKeyCommandFunc cmd_func,void * cmd_opaque)90 skin_keyboard_on_command( SkinKeyboard*  keyboard, SkinKeyCommandFunc  cmd_func, void*  cmd_opaque )
91 {
92     keyboard->command_func   = cmd_func;
93     keyboard->command_opaque = cmd_opaque;
94 }
95 
96 void
skin_keyboard_on_key_press(SkinKeyboard * keyboard,SkinKeyEventFunc press_func,void * press_opaque)97 skin_keyboard_on_key_press( SkinKeyboard*  keyboard, SkinKeyEventFunc  press_func, void*  press_opaque )
98 {
99     keyboard->press_func   = press_func;
100     keyboard->press_opaque = press_opaque;
101 }
102 
103 void
skin_keyboard_add_key_event(SkinKeyboard * kb,unsigned code,unsigned down)104 skin_keyboard_add_key_event( SkinKeyboard*  kb,
105                              unsigned       code,
106                              unsigned       down )
107 {
108     if (code != 0 && kb->keycode_count < MAX_KEYCODES) {
109         //dprint("add keycode %d, down %d\n", code % 0x1ff, down );
110         kb->keycodes[(int)kb->keycode_count++] = ( (code & 0x1ff) | (down ? 0x200 : 0) );
111     }
112 }
113 
114 
115 void
skin_keyboard_flush(SkinKeyboard * kb)116 skin_keyboard_flush( SkinKeyboard*  kb )
117 {
118     if (kb->keycode_count > 0) {
119         if (VERBOSE_CHECK(keys)) {
120             int  nn;
121             printf(">> KEY" );
122             for (nn = 0; nn < kb->keycode_count; nn++) {
123                 int  code = kb->keycodes[nn];
124                 printf(" [0x%03x,%s]", (code & 0x1ff), (code & 0x200) ? "down" : " up " );
125             }
126             printf( "\n" );
127         }
128         kbd_put_keycodes(kb->keycodes, kb->keycode_count);
129         kb->keycode_count = 0;
130     }
131 }
132 
133 
134 static void
skin_keyboard_cmd(SkinKeyboard * keyboard,SkinKeyCommand command,int param)135 skin_keyboard_cmd( SkinKeyboard*   keyboard,
136                    SkinKeyCommand  command,
137                    int             param )
138 {
139     if (keyboard->command_func) {
140         keyboard->command_func( keyboard->command_opaque, command, param );
141     }
142 }
143 
144 
145 static LastKey*
skin_keyboard_find_last(SkinKeyboard * keyboard,int sym)146 skin_keyboard_find_last( SkinKeyboard*  keyboard,
147                          int            sym )
148 {
149     LastKey*  k   = keyboard->last_keys;
150     LastKey*  end = k + keyboard->last_count;
151 
152     for ( ; k < end; k++ ) {
153         if (k->sym == sym)
154             return k;
155     }
156     return NULL;
157 }
158 
159 static void
skin_keyboard_add_last(SkinKeyboard * keyboard,int sym,int mod,int unicode)160 skin_keyboard_add_last( SkinKeyboard*  keyboard,
161                         int            sym,
162                         int            mod,
163                         int            unicode )
164 {
165     LastKey*  k = keyboard->last_keys + keyboard->last_count;
166 
167     if (keyboard->last_count < MAX_LAST_KEYS) {
168         k->sym     = sym;
169         k->mod     = mod;
170         k->unicode = unicode;
171 
172         keyboard->last_count += 1;
173     }
174 }
175 
176 static void
skin_keyboard_remove_last(SkinKeyboard * keyboard,int sym)177 skin_keyboard_remove_last( SkinKeyboard*  keyboard,
178                            int            sym )
179 {
180     LastKey*  k   = keyboard->last_keys;
181     LastKey*  end = k + keyboard->last_count;
182 
183     for ( ; k < end; k++ ) {
184         if (k->sym == sym) {
185            /* we don't need a sorted array, so place the last
186             * element in place at the position of the removed
187             * one... */
188             k[0] = end[-1];
189             keyboard->last_count -= 1;
190             break;
191         }
192     }
193 }
194 
195 static void
skin_keyboard_clear_last(SkinKeyboard * keyboard)196 skin_keyboard_clear_last( SkinKeyboard*  keyboard )
197 {
198     keyboard->last_count = 0;
199 }
200 
201 static int
skin_keyboard_rotate_sym(SkinKeyboard * keyboard,int sym)202 skin_keyboard_rotate_sym( SkinKeyboard*  keyboard,
203                           int            sym )
204 {
205     switch (keyboard->rotation) {
206         case SKIN_ROTATION_90:
207             switch (sym) {
208                 case SDLK_LEFT:  sym = SDLK_DOWN; break;
209                 case SDLK_RIGHT: sym = SDLK_UP; break;
210                 case SDLK_UP:    sym = SDLK_LEFT; break;
211                 case SDLK_DOWN:  sym = SDLK_RIGHT; break;
212             }
213             break;
214 
215         case SKIN_ROTATION_180:
216             switch (sym) {
217                 case SDLK_LEFT:  sym = SDLK_RIGHT; break;
218                 case SDLK_RIGHT: sym = SDLK_LEFT; break;
219                 case SDLK_UP:    sym = SDLK_DOWN; break;
220                 case SDLK_DOWN:  sym = SDLK_UP; break;
221             }
222             break;
223 
224         case SKIN_ROTATION_270:
225             switch (sym) {
226                 case SDLK_LEFT:  sym = SDLK_UP; break;
227                 case SDLK_RIGHT: sym = SDLK_DOWN; break;
228                 case SDLK_UP:    sym = SDLK_RIGHT; break;
229                 case SDLK_DOWN:  sym = SDLK_LEFT; break;
230             }
231             break;
232 
233         default: ;
234     }
235     return  sym;
236 }
237 
238 static AndroidKeyCode
skin_keyboard_key_to_code(SkinKeyboard * keyboard,unsigned sym,int mod,int down)239 skin_keyboard_key_to_code( SkinKeyboard*  keyboard,
240                            unsigned       sym,
241                            int            mod,
242                            int            down )
243 {
244     AndroidKeyCode  code   = 0;
245     int             mod0   = mod;
246     SkinKeyCommand  command;
247 
248     /* first, handle the arrow keys directly */
249     /* rotate them if necessary */
250     sym  = skin_keyboard_rotate_sym(keyboard, sym);
251     mod &= (KMOD_CTRL | KMOD_ALT | KMOD_SHIFT);
252 
253     switch (sym) {
254         case SDLK_LEFT:       code = kKeyCodeDpadLeft; break;
255         case SDLK_RIGHT:      code = kKeyCodeDpadRight; break;
256         case SDLK_UP:         code = kKeyCodeDpadUp; break;
257         case SDLK_DOWN:       code = kKeyCodeDpadDown; break;
258         default: ;
259     }
260 
261     if (code != 0) {
262         D("handling arrow (sym=%d mod=%d)", sym, mod);
263         if (!keyboard->raw_keys) {
264             int  doCapL, doCapR, doAltL, doAltR;
265 
266             if (!down) {
267                 LastKey*  k = skin_keyboard_find_last(keyboard, sym);
268                 if (k != NULL) {
269                     mod = k->mod;
270                     skin_keyboard_remove_last( keyboard, sym );
271                 }
272             } else {
273                 skin_keyboard_add_last( keyboard, sym, mod, 0);
274             }
275 
276             doCapL = (mod & 0x7ff) & KMOD_LSHIFT;
277             doCapR = (mod & 0x7ff) & KMOD_RSHIFT;
278             doAltL = (mod & 0x7ff) & KMOD_LALT;
279             doAltR = (mod & 0x7ff) & KMOD_RALT;
280 
281             if (down) {
282                 if (doAltL) skin_keyboard_add_key_event( keyboard, kKeyCodeAltLeft, 1 );
283                 if (doAltR) skin_keyboard_add_key_event( keyboard, kKeyCodeAltRight, 1 );
284                 if (doCapL) skin_keyboard_add_key_event( keyboard, kKeyCodeCapLeft, 1 );
285                 if (doCapR) skin_keyboard_add_key_event( keyboard, kKeyCodeCapRight, 1 );
286             }
287             skin_keyboard_add_key_event(keyboard, code, down);
288 
289             if (!down) {
290                 if (doCapR) skin_keyboard_add_key_event( keyboard, kKeyCodeCapRight, 0 );
291                 if (doCapL) skin_keyboard_add_key_event( keyboard, kKeyCodeCapLeft, 0 );
292                 if (doAltR) skin_keyboard_add_key_event( keyboard, kKeyCodeAltRight, 0 );
293                 if (doAltL) skin_keyboard_add_key_event( keyboard, kKeyCodeAltLeft, 0 );
294             }
295             code = 0;
296         }
297         return code;
298     }
299 
300     /* special case for keypad keys, ignore them here if numlock is on */
301     if ((mod0 & KMOD_NUM) != 0) {
302         switch (sym) {
303             case SDLK_KP0:
304             case SDLK_KP1:
305             case SDLK_KP2:
306             case SDLK_KP3:
307             case SDLK_KP4:
308             case SDLK_KP5:
309             case SDLK_KP6:
310             case SDLK_KP7:
311             case SDLK_KP8:
312             case SDLK_KP9:
313             case SDLK_KP_PLUS:
314             case SDLK_KP_MINUS:
315             case SDLK_KP_MULTIPLY:
316             case SDLK_KP_DIVIDE:
317             case SDLK_KP_EQUALS:
318             case SDLK_KP_PERIOD:
319             case SDLK_KP_ENTER:
320                 return 0;
321         }
322     }
323 
324     /* now try all keyset combos */
325     command = skin_keyset_get_command( keyboard->kset, sym, mod );
326     if (command != SKIN_KEY_COMMAND_NONE) {
327         D("handling command %s from (sym=%d, mod=%d, str=%s)",
328           skin_key_command_to_str(command), sym, mod, skin_key_symmod_to_str(sym,mod));
329         skin_keyboard_cmd( keyboard, command, down );
330         return 0;
331     }
332     D("could not handle (sym=%d, mod=%d, str=%s)", sym, mod,
333       skin_key_symmod_to_str(sym,mod));
334     return -1;
335 }
336 
337 /* this gets called only if the reverse unicode mapping didn't work
338  * or wasn't used (when in raw keys mode)
339  */
340 static AndroidKeyCode
skin_keyboard_raw_key_to_code(SkinKeyboard * kb,unsigned sym,int down)341 skin_keyboard_raw_key_to_code(SkinKeyboard*  kb, unsigned sym, int  down)
342 {
343     switch(sym){
344     case SDLK_1:          return kKeyCode1;
345     case SDLK_2:          return kKeyCode2;
346     case SDLK_3:          return kKeyCode3;
347     case SDLK_4:          return kKeyCode4;
348     case SDLK_5:          return kKeyCode5;
349     case SDLK_6:          return kKeyCode6;
350     case SDLK_7:          return kKeyCode7;
351     case SDLK_8:          return kKeyCode8;
352     case SDLK_9:          return kKeyCode9;
353     case SDLK_0:          return kKeyCode0;
354 
355     case SDLK_q:          return kKeyCodeQ;
356     case SDLK_w:          return kKeyCodeW;
357     case SDLK_e:          return kKeyCodeE;
358     case SDLK_r:          return kKeyCodeR;
359     case SDLK_t:          return kKeyCodeT;
360     case SDLK_y:          return kKeyCodeY;
361     case SDLK_u:          return kKeyCodeU;
362     case SDLK_i:          return kKeyCodeI;
363     case SDLK_o:          return kKeyCodeO;
364     case SDLK_p:          return kKeyCodeP;
365     case SDLK_a:          return kKeyCodeA;
366     case SDLK_s:          return kKeyCodeS;
367     case SDLK_d:          return kKeyCodeD;
368     case SDLK_f:          return kKeyCodeF;
369     case SDLK_g:          return kKeyCodeG;
370     case SDLK_h:          return kKeyCodeH;
371     case SDLK_j:          return kKeyCodeJ;
372     case SDLK_k:          return kKeyCodeK;
373     case SDLK_l:          return kKeyCodeL;
374     case SDLK_z:          return kKeyCodeZ;
375     case SDLK_x:          return kKeyCodeX;
376     case SDLK_c:          return kKeyCodeC;
377     case SDLK_v:          return kKeyCodeV;
378     case SDLK_b:          return kKeyCodeB;
379     case SDLK_n:          return kKeyCodeN;
380     case SDLK_m:          return kKeyCodeM;
381     case SDLK_COMMA:      return kKeyCodeComma;
382     case SDLK_PERIOD:     return kKeyCodePeriod;
383     case SDLK_SPACE:      return kKeyCodeSpace;
384     case SDLK_SLASH:      return kKeyCodeSlash;
385     case SDLK_RETURN:     return kKeyCodeNewline;
386     case SDLK_BACKSPACE:  return kKeyCodeDel;
387 
388 /* these are qwerty keys not on a device keyboard */
389     case SDLK_TAB:        return kKeyCodeTab;
390     case SDLK_BACKQUOTE:  return kKeyCodeGrave;
391     case SDLK_MINUS:      return kKeyCodeMinus;
392     case SDLK_EQUALS:     return kKeyCodeEquals;
393     case SDLK_LEFTBRACKET: return kKeyCodeLeftBracket;
394     case SDLK_RIGHTBRACKET: return kKeyCodeRightBracket;
395     case SDLK_BACKSLASH:  return kKeyCodeBackslash;
396     case SDLK_SEMICOLON:  return kKeyCodeSemicolon;
397     case SDLK_QUOTE:      return kKeyCodeApostrophe;
398 
399     case SDLK_RSHIFT:     return kKeyCodeCapRight;
400     case SDLK_LSHIFT:     return kKeyCodeCapLeft;
401     case SDLK_RMETA:      return kKeyCodeSym;
402     case SDLK_LMETA:      return kKeyCodeSym;
403     case SDLK_RALT:       return kKeyCodeAltRight;
404     case SDLK_LALT:       return kKeyCodeAltLeft;
405     case SDLK_RCTRL:      return kKeyCodeSym;
406     case SDLK_LCTRL:      return kKeyCodeSym;
407 
408     default:
409         /* fprintf(stderr,"* unknown sdl keysym %d *\n", sym); */
410         return -1;
411     }
412 }
413 
414 
415 static void
skin_keyboard_do_key_event(SkinKeyboard * kb,AndroidKeyCode code,int down)416 skin_keyboard_do_key_event( SkinKeyboard*   kb,
417                             AndroidKeyCode  code,
418                             int             down )
419 {
420     if (kb->press_func) {
421         kb->press_func( kb->press_opaque, code, down );
422     }
423     skin_keyboard_add_key_event(kb, code, down);
424 }
425 
426 
427 int
skin_keyboard_process_unicode_event(SkinKeyboard * kb,unsigned int unicode,int down)428 skin_keyboard_process_unicode_event( SkinKeyboard*  kb,  unsigned int  unicode, int  down )
429 {
430     const AKeyCharmap*  cmap = kb->charmap;
431     int                 n;
432 
433     if (unicode == 0)
434         return 0;
435 
436     /* check base keys */
437     for (n = 0; n < cmap->num_entries; n++) {
438         if (cmap->entries[n].base == unicode) {
439             skin_keyboard_add_key_event(kb, cmap->entries[n].code, down);
440             return 1;
441         }
442     }
443 
444     /* check caps + keys */
445     for (n = 0; n < cmap->num_entries; n++) {
446         if (cmap->entries[n].caps == unicode) {
447             if (down)
448                 skin_keyboard_add_key_event(kb, kKeyCodeCapLeft, down);
449             skin_keyboard_add_key_event(kb, cmap->entries[n].code, down);
450             if (!down)
451                 skin_keyboard_add_key_event(kb, kKeyCodeCapLeft, down);
452             return 2;
453         }
454     }
455 
456     /* check fn + keys */
457     for (n = 0; n < cmap->num_entries; n++) {
458         if (cmap->entries[n].fn == unicode) {
459             if (down)
460                 skin_keyboard_add_key_event(kb, kKeyCodeAltLeft, down);
461             skin_keyboard_add_key_event(kb, cmap->entries[n].code, down);
462             if (!down)
463                 skin_keyboard_add_key_event(kb, kKeyCodeAltLeft, down);
464             return 2;
465         }
466     }
467 
468     /* check caps + fn + keys */
469     for (n = 0; n < cmap->num_entries; n++) {
470         if (cmap->entries[n].caps_fn == unicode) {
471             if (down) {
472                 skin_keyboard_add_key_event(kb, kKeyCodeAltLeft, down);
473                 skin_keyboard_add_key_event(kb, kKeyCodeCapLeft, down);
474             }
475             skin_keyboard_add_key_event(kb, cmap->entries[n].code, down);
476             if (!down) {
477                 skin_keyboard_add_key_event(kb, kKeyCodeCapLeft, down);
478                 skin_keyboard_add_key_event(kb, kKeyCodeAltLeft, down);
479             }
480             return 3;
481         }
482     }
483 
484     /* no match */
485     return 0;
486 }
487 
488 
489 void
skin_keyboard_enable(SkinKeyboard * keyboard,int enabled)490 skin_keyboard_enable( SkinKeyboard*  keyboard,
491                       int            enabled )
492 {
493     keyboard->enabled = enabled;
494     if (enabled) {
495         SDL_EnableUNICODE(!keyboard->raw_keys);
496         SDL_EnableKeyRepeat(0,0);
497     }
498 }
499 
500 void
skin_keyboard_process_event(SkinKeyboard * kb,SDL_Event * ev,int down)501 skin_keyboard_process_event( SkinKeyboard*  kb, SDL_Event*  ev, int  down )
502 {
503     unsigned         code;
504     int              unicode = ev->key.keysym.unicode;
505     int              sym     = ev->key.keysym.sym;
506     int              mod     = ev->key.keysym.mod;
507 
508     /* ignore key events if we're not enabled */
509     if (!kb->enabled) {
510         printf( "ignoring key event sym=%d mod=0x%x unicode=%d\n",
511                 sym, mod, unicode );
512         return;
513     }
514 
515     /* first, try the keyboard-mode-independent keys */
516     code = skin_keyboard_key_to_code( kb, sym, mod, down );
517     if (code == 0)
518         return;
519 
520     if ((int)code > 0) {
521         skin_keyboard_do_key_event(kb, code, down);
522         skin_keyboard_flush(kb);
523         return;
524     }
525 
526     /* Ctrl-K is used to switch between 'unicode' and 'raw' modes */
527     if (sym == SDLK_k)
528     {
529         int  mod2 = mod & 0x7ff;
530 
531         if ( mod2 == KMOD_LCTRL || mod2 == KMOD_RCTRL ) {
532             if (down) {
533                 skin_keyboard_clear_last(kb);
534                 kb->raw_keys = !kb->raw_keys;
535                 SDL_EnableUNICODE(!kb->raw_keys);
536                 D( "switching keyboard to %s mode", kb->raw_keys ? "raw" : "unicode" );
537             }
538             return;
539         }
540     }
541 
542     if (!kb->raw_keys) {
543        /* ev->key.keysym.unicode is only valid on keydown events, and will be 0
544         * on the corresponding keyup ones, so remember the set of last pressed key
545         * syms to "undo" the job
546         */
547         if ( !down && unicode == 0 ) {
548             LastKey*  k = skin_keyboard_find_last(kb, sym);
549             if (k != NULL) {
550                 unicode = k->unicode;
551                 skin_keyboard_remove_last(kb, sym);
552             }
553         }
554     }
555     if (!kb->raw_keys &&
556         skin_keyboard_process_unicode_event( kb, unicode, down ) > 0)
557     {
558         if (down)
559             skin_keyboard_add_last( kb, sym, mod, unicode );
560 
561         skin_keyboard_flush( kb );
562         return;
563     }
564 
565     code = skin_keyboard_raw_key_to_code( kb, sym, down );
566 
567     if ( !kb->raw_keys &&
568          (code == kKeyCodeAltLeft  || code == kKeyCodeAltRight ||
569           code == kKeyCodeCapLeft  || code == kKeyCodeCapRight ||
570           code == kKeyCodeSym) )
571         return;
572 
573     if (code == -1) {
574         D("ignoring keysym %d", sym );
575     } else if (code > 0) {
576         skin_keyboard_do_key_event(kb, code, down);
577         skin_keyboard_flush(kb);
578     }
579 }
580 
581 static SkinKeyboard*
skin_keyboard_create_from_charmap_name(const char * charmap_name,int use_raw_keys)582 skin_keyboard_create_from_charmap_name(const char*  charmap_name,
583                                        int  use_raw_keys)
584 {
585     SkinKeyboard*  kb;
586     int  nn;
587 
588     ANEW0(kb);
589 
590     // Find charmap by its name in the array of available charmaps.
591     for (nn = 0; nn < android_charmap_count; nn++) {
592         if (!strcmp(android_charmaps[nn]->name, charmap_name)) {
593             kb->charmap = android_charmaps[nn];
594             break;
595         }
596     }
597 
598     if (!kb->charmap) {
599         // Charmap name was not found. Default to the first charmap in the array.
600         fprintf(stderr, "### warning, skin requires unknown '%s' charmap, reverting to '%s'\n",
601                 charmap_name, android_charmaps[0]->name );
602         kb->charmap = android_charmaps[0];
603     }
604     kb->raw_keys = use_raw_keys;
605     kb->enabled  = 0;
606 
607     /* add default keyset */
608     if (android_keyset)
609         kb->kset = android_keyset;
610     else
611         kb->kset = skin_keyset_new_from_text( skin_keyset_get_default() );
612 
613     return kb;
614 }
615 
616 SkinKeyboard*
skin_keyboard_create_from_aconfig(AConfig * aconfig,int use_raw_keys)617 skin_keyboard_create_from_aconfig( AConfig*  aconfig, int  use_raw_keys )
618 {
619     const char*    charmap_name = "qwerty";
620     AConfig*       node = aconfig_find( aconfig, "keyboard" );
621     if (node != NULL) {
622         charmap_name = aconfig_str(node, "charmap", charmap_name);
623     }
624     return skin_keyboard_create_from_charmap_name(charmap_name, use_raw_keys);
625 }
626 
627 SkinKeyboard*
skin_keyboard_create_from_kcm(const char * kcm_file_path,int use_raw_keys)628 skin_keyboard_create_from_kcm( const char*  kcm_file_path, int  use_raw_keys )
629 {
630     char charmap_name[AKEYCHARMAP_NAME_SIZE];
631     kcm_extract_charmap_name(kcm_file_path, charmap_name,
632                              sizeof(charmap_name));
633     return skin_keyboard_create_from_charmap_name(charmap_name, use_raw_keys);
634 }
635 
636 void
skin_keyboard_free(SkinKeyboard * keyboard)637 skin_keyboard_free( SkinKeyboard*  keyboard )
638 {
639     if (keyboard) {
640         AFREE(keyboard);
641     }
642 }
643