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 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* 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 83 skin_keyboard_set_rotation( SkinKeyboard* keyboard, 84 SkinRotation rotation ) 85 { 86 keyboard->rotation = (rotation & 3); 87 } 88 89 void 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 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 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 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 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* 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 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 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 196 skin_keyboard_clear_last( SkinKeyboard* keyboard ) 197 { 198 keyboard->last_count = 0; 199 } 200 201 static int 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 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 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 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 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 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 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* 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* 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* 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 637 skin_keyboard_free( SkinKeyboard* keyboard ) 638 { 639 if (keyboard) { 640 AFREE(keyboard); 641 } 642 } 643