1 /* 2 Copyright (C) 2002-2010 Karl J. Runge <runge (at) karlrunge.com> 3 All rights reserved. 4 5 This file is part of x11vnc. 6 7 x11vnc is free software; you can redistribute it and/or modify 8 it under the terms of the GNU General Public License as published by 9 the Free Software Foundation; either version 2 of the License, or (at 10 your option) any later version. 11 12 x11vnc is distributed in the hope that it will be useful, 13 but WITHOUT ANY WARRANTY; without even the implied warranty of 14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 GNU General Public License for more details. 16 17 You should have received a copy of the GNU General Public License 18 along with x11vnc; if not, write to the Free Software 19 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA 20 or see <http://www.gnu.org/licenses/>. 21 22 In addition, as a special exception, Karl J. Runge 23 gives permission to link the code of its release of x11vnc with the 24 OpenSSL project's "OpenSSL" library (or with modified versions of it 25 that use the same license as the "OpenSSL" library), and distribute 26 the linked executables. You must obey the GNU General Public License 27 in all respects for all of the code used other than "OpenSSL". If you 28 modify this file, you may extend this exception to your version of the 29 file, but you are not obligated to do so. If you do not wish to do 30 so, delete this exception statement from your version. 31 */ 32 33 /* -- keyboard.c -- */ 34 35 #include "x11vnc.h" 36 #include "xwrappers.h" 37 #include "xrecord.h" 38 #include "xinerama.h" 39 #include "pointer.h" 40 #include "userinput.h" 41 #include "win_utils.h" 42 #include "rates.h" 43 #include "cleanup.h" 44 #include "allowed_input_t.h" 45 #include "unixpw.h" 46 #include "v4l.h" 47 #include "linuxfb.h" 48 #include "uinput.h" 49 #include "macosx.h" 50 #include "screen.h" 51 52 void get_keystate(int *keystate); 53 void clear_modifiers(int init); 54 int track_mod_state(rfbKeySym keysym, rfbBool down, rfbBool set); 55 void clear_keys(void); 56 void clear_locks(void); 57 int get_autorepeat_state(void); 58 int get_initial_autorepeat_state(void); 59 void autorepeat(int restore, int bequiet); 60 void check_add_keysyms(void); 61 int add_keysym(KeySym keysym); 62 void delete_added_keycodes(int bequiet); 63 void initialize_remap(char *infile); 64 int sloppy_key_check(int key, rfbBool down, rfbKeySym keysym, int *new_kc); 65 void switch_to_xkb_if_better(void); 66 char *short_kmbcf(char *str); 67 void initialize_allowed_input(void); 68 void initialize_modtweak(void); 69 void initialize_keyboard_and_pointer(void); 70 void get_allowed_input(rfbClientPtr client, allowed_input_t *input); 71 double typing_rate(double time_window, int *repeating); 72 int skip_cr_when_scaling(char *mode); 73 void keyboard(rfbBool down, rfbKeySym keysym, rfbClientPtr client); 74 75 76 static void delete_keycode(KeyCode kc, int bequiet); 77 static int count_added_keycodes(void); 78 static void add_remap(char *line); 79 static void add_dead_keysyms(char *str); 80 static void initialize_xkb_modtweak(void); 81 static void xkb_tweak_keyboard(rfbBool down, rfbKeySym keysym, 82 rfbClientPtr client); 83 static void tweak_mod(signed char mod, rfbBool down); 84 static void modifier_tweak_keyboard(rfbBool down, rfbKeySym keysym, 85 rfbClientPtr client); 86 static void pipe_keyboard(rfbBool down, rfbKeySym keysym, rfbClientPtr client); 87 88 89 /* 90 * Routine to retreive current state keyboard. 1 means down, 0 up. 91 */ 92 void get_keystate(int *keystate) { 93 #if NO_X11 94 RAWFB_RET_VOID 95 if (!keystate) {} 96 return; 97 #else 98 int i, k; 99 char keys[32]; 100 101 RAWFB_RET_VOID 102 103 /* n.b. caller decides to X_LOCK or not. */ 104 XQueryKeymap(dpy, keys); 105 for (i=0; i<32; i++) { 106 char c = keys[i]; 107 108 for (k=0; k < 8; k++) { 109 if (c & 0x1) { 110 keystate[8*i + k] = 1; 111 } else { 112 keystate[8*i + k] = 0; 113 } 114 c = c >> 1; 115 } 116 } 117 #endif /* NO_X11 */ 118 } 119 120 /* 121 * Try to KeyRelease any non-Lock modifiers that are down. 122 */ 123 void clear_modifiers(int init) { 124 #if NO_X11 125 RAWFB_RET_VOID 126 if (!init) {} 127 return; 128 #else 129 static KeyCode keycodes[256]; 130 static KeySym keysyms[256]; 131 static char *keystrs[256]; 132 static int kcount = 0, first = 1; 133 int keystate[256]; 134 int i, j, minkey, maxkey, syms_per_keycode; 135 KeySym *keymap; 136 KeySym keysym; 137 KeyCode keycode; 138 139 RAWFB_RET_VOID 140 141 /* n.b. caller decides to X_LOCK or not. */ 142 if (first) { 143 /* 144 * we store results in static arrays, to aid interrupted 145 * case, but modifiers could have changed during session... 146 */ 147 XDisplayKeycodes(dpy, &minkey, &maxkey); 148 149 keymap = XGetKeyboardMapping(dpy, minkey, (maxkey - minkey + 1), 150 &syms_per_keycode); 151 152 for (i = minkey; i <= maxkey; i++) { 153 for (j = 0; j < syms_per_keycode; j++) { 154 char *str; 155 keysym = keymap[ (i - minkey) * syms_per_keycode + j ]; 156 if (keysym == NoSymbol || ! ismodkey(keysym)) { 157 continue; 158 } 159 keycode = XKeysymToKeycode(dpy, keysym); 160 if (keycode == NoSymbol) { 161 continue; 162 } 163 keycodes[kcount] = keycode; 164 keysyms[kcount] = keysym; 165 str = XKeysymToString(keysym); 166 if (! str) str = "null"; 167 keystrs[kcount] = strdup(str); 168 kcount++; 169 } 170 } 171 XFree_wr((void *) keymap); 172 first = 0; 173 } 174 if (init) { 175 return; 176 } 177 178 get_keystate(keystate); 179 for (i=0; i < kcount; i++) { 180 keysym = keysyms[i]; 181 keycode = keycodes[i]; 182 183 if (! keystate[(int) keycode]) { 184 continue; 185 } 186 187 if (clear_mods) { 188 rfbLog("clear_modifiers: up: %-10s (0x%x) " 189 "keycode=0x%x\n", keystrs[i], keysym, keycode); 190 } 191 XTestFakeKeyEvent_wr(dpy, keycode, False, CurrentTime); 192 } 193 XFlush_wr(dpy); 194 #endif /* NO_X11 */ 195 } 196 197 static KeySym simple_mods[] = { 198 XK_Shift_L, XK_Shift_R, 199 XK_Control_L, XK_Control_R, 200 XK_Meta_L, XK_Meta_R, 201 XK_Alt_L, XK_Alt_R, 202 XK_Super_L, XK_Super_R, 203 XK_Hyper_L, XK_Hyper_R, 204 XK_Mode_switch, 205 NoSymbol 206 }; 207 #define NSIMPLE_MODS 13 208 209 int track_mod_state(rfbKeySym keysym, rfbBool down, rfbBool set) { 210 KeySym sym = (KeySym) keysym; 211 static rfbBool isdown[NSIMPLE_MODS]; 212 static int first = 1; 213 int i, cnt = 0; 214 215 /* 216 * simple tracking method for the modifier state without 217 * contacting the Xserver. Ignores, of course what keys are 218 * pressed on the physical display. 219 * 220 * This is unrelated to our mod_tweak and xkb stuff. 221 * Just a simple thing for wireframe/scroll heuristics, 222 * sloppy keys etc. 223 */ 224 225 if (first) { 226 for (i=0; i<NSIMPLE_MODS; i++) { 227 isdown[i] = FALSE; 228 } 229 first = 0; 230 } 231 232 if (sym != NoSymbol) { 233 for (i=0; i<NSIMPLE_MODS; i++) { 234 if (sym == simple_mods[i]) { 235 if (set) { 236 isdown[i] = down; 237 return 1; 238 } else { 239 if (isdown[i]) { 240 return 1; 241 } else { 242 return 0; 243 } 244 } 245 break; 246 } 247 } 248 /* not a modifier */ 249 if (set) { 250 return 0; 251 } else { 252 return -1; 253 } 254 } 255 256 /* called with NoSymbol: return number currently pressed: */ 257 for (i=0; i<NSIMPLE_MODS; i++) { 258 if (isdown[i]) { 259 cnt++; 260 } 261 } 262 return cnt; 263 } 264 265 /* 266 * Attempt to set all keys to Up position. Can mess up typing at the 267 * physical keyboard so use with caution. 268 */ 269 void clear_keys(void) { 270 int k, keystate[256]; 271 272 RAWFB_RET_VOID 273 274 /* n.b. caller decides to X_LOCK or not. */ 275 get_keystate(keystate); 276 for (k=0; k<256; k++) { 277 if (keystate[k]) { 278 KeyCode keycode = (KeyCode) k; 279 rfbLog("clear_keys: keycode=%d\n", keycode); 280 XTestFakeKeyEvent_wr(dpy, keycode, False, CurrentTime); 281 } 282 } 283 XFlush_wr(dpy); 284 } 285 286 287 void clear_locks(void) { 288 #if NO_X11 289 RAWFB_RET_VOID 290 return; 291 #else 292 XModifierKeymap *map; 293 int i, j, k = 0; 294 unsigned int state = 0; 295 296 RAWFB_RET_VOID 297 298 /* n.b. caller decides to X_LOCK or not. */ 299 #if LIBVNCSERVER_HAVE_XKEYBOARD 300 if (xkb_present) { 301 XkbStateRec kbstate; 302 XkbGetState(dpy, XkbUseCoreKbd, &kbstate); 303 rfbLog("locked: 0x%x\n", kbstate.locked_mods); 304 rfbLog("latched: 0x%x\n", kbstate.latched_mods); 305 rfbLog("compat: 0x%x\n", kbstate.compat_state); 306 state = kbstate.locked_mods; 307 if (! state) { 308 state = kbstate.compat_state; 309 } 310 } else 311 #endif 312 { 313 state = mask_state(); 314 /* this may contain non-locks too... */ 315 rfbLog("state: 0x%x\n", state); 316 } 317 if (! state) { 318 return; 319 } 320 map = XGetModifierMapping(dpy); 321 if (! map) { 322 return; 323 } 324 for (i = 0; i < 8; i++) { 325 int did = 0; 326 for (j = 0; j < map->max_keypermod; j++) { 327 if (! did && state & (0x1 << i)) { 328 if (map->modifiermap[k]) { 329 KeyCode key = map->modifiermap[k]; 330 KeySym ks = XKeycodeToKeysym(dpy, key, 0); 331 char *nm = XKeysymToString(ks); 332 rfbLog("toggling: %03d / %03d -- %s\n", key, ks, nm ? nm : "BadKey"); 333 did = 1; 334 XTestFakeKeyEvent_wr(dpy, key, True, CurrentTime); 335 usleep(10*1000); 336 XTestFakeKeyEvent_wr(dpy, key, False, CurrentTime); 337 XFlush_wr(dpy); 338 } 339 } 340 k++; 341 } 342 } 343 XFreeModifiermap(map); 344 XFlush_wr(dpy); 345 rfbLog("state: 0x%x\n", mask_state()); 346 #endif 347 } 348 349 /* 350 * Kludge for -norepeat option: we turn off keystroke autorepeat in 351 * the X server when clients are connected. This may annoy people at 352 * the physical display. We do this because 'key down' and 'key up' 353 * user input events may be separated by 100s of ms due to screen fb 354 * processing or link latency, thereby inducing the X server to apply 355 * autorepeat when it should not. Since the *client* is likely doing 356 * keystroke autorepeating as well, it kind of makes sense to shut it 357 * off if no one is at the physical display... 358 */ 359 static int save_auto_repeat = -1; 360 361 int get_autorepeat_state(void) { 362 #if NO_X11 363 RAWFB_RET(0) 364 return 0; 365 #else 366 XKeyboardState kstate; 367 368 RAWFB_RET(0) 369 370 X_LOCK; 371 XGetKeyboardControl(dpy, &kstate); 372 X_UNLOCK; 373 return kstate.global_auto_repeat; 374 #endif /* NO_X11 */ 375 } 376 377 int get_initial_autorepeat_state(void) { 378 if (save_auto_repeat < 0) { 379 save_auto_repeat = get_autorepeat_state(); 380 } 381 return save_auto_repeat; 382 } 383 384 void autorepeat(int restore, int bequiet) { 385 #if NO_X11 386 RAWFB_RET_VOID 387 if (!restore || !bequiet) {} 388 return; 389 #else 390 int global_auto_repeat; 391 XKeyboardControl kctrl; 392 393 RAWFB_RET_VOID 394 395 if (restore) { 396 if (save_auto_repeat < 0) { 397 return; /* nothing to restore */ 398 } 399 global_auto_repeat = get_autorepeat_state(); 400 /* read state and skip restore if equal (e.g. no clients) */ 401 if (global_auto_repeat == save_auto_repeat) { 402 return; 403 } 404 405 X_LOCK; 406 kctrl.auto_repeat_mode = save_auto_repeat; 407 XChangeKeyboardControl(dpy, KBAutoRepeatMode, &kctrl); 408 XFlush_wr(dpy); 409 X_UNLOCK; 410 411 if (! bequiet && ! quiet) { 412 rfbLog("Restored X server key autorepeat to: %d\n", 413 save_auto_repeat); 414 } 415 } else { 416 global_auto_repeat = get_autorepeat_state(); 417 if (save_auto_repeat < 0) { 418 /* 419 * we only remember the state at startup 420 * to avoid confusing ourselves later on. 421 */ 422 save_auto_repeat = global_auto_repeat; 423 } 424 425 X_LOCK; 426 kctrl.auto_repeat_mode = AutoRepeatModeOff; 427 XChangeKeyboardControl(dpy, KBAutoRepeatMode, &kctrl); 428 XFlush_wr(dpy); 429 X_UNLOCK; 430 431 if (! bequiet && ! quiet) { 432 rfbLog("Disabled X server key autorepeat.\n"); 433 if (no_repeat_countdown >= 0) { 434 rfbLog(" to force back on run: 'xset r on' (%d " 435 "times)\n", no_repeat_countdown+1); 436 } 437 } 438 } 439 #endif /* NO_X11 */ 440 } 441 442 /* 443 * We periodically delete any keysyms we have added, this is to 444 * lessen our effect on the X server state if we are terminated abruptly 445 * and cannot clear them and also to clear out any strange little used 446 * ones that would just fill up the keymapping. 447 */ 448 void check_add_keysyms(void) { 449 static time_t last_check = 0; 450 int clear_freq = 300, quiet = 1, count; 451 time_t now = time(NULL); 452 453 if (unixpw_in_progress) return; 454 455 if (now > last_check + clear_freq) { 456 count = count_added_keycodes(); 457 /* 458 * only really delete if they have not typed recently 459 * and we have added 8 or more. 460 */ 461 if (now > last_keyboard_input + 5 && count >= 8) { 462 X_LOCK; 463 delete_added_keycodes(quiet); 464 X_UNLOCK; 465 } 466 last_check = now; 467 } 468 } 469 470 static KeySym added_keysyms[0x100]; 471 472 /* these are just for rfbLog messages: */ 473 static KeySym alltime_added_keysyms[1024]; 474 static int alltime_len = 1024; 475 static int alltime_num = 0; 476 477 int add_keysym(KeySym keysym) { 478 static int first = 1; 479 int n; 480 #if NO_X11 481 if (first) { 482 for (n=0; n < 0x100; n++) { 483 added_keysyms[n] = NoSymbol; 484 } 485 first = 0; 486 } 487 RAWFB_RET(0) 488 if (!keysym) {} 489 return 0; 490 #else 491 int minkey, maxkey, syms_per_keycode; 492 int kc, ret = 0; 493 KeySym *keymap; 494 495 if (first) { 496 for (n=0; n < 0x100; n++) { 497 added_keysyms[n] = NoSymbol; 498 } 499 first = 0; 500 } 501 502 RAWFB_RET(0) 503 504 if (keysym == NoSymbol) { 505 return 0; 506 } 507 /* there can be a race before MappingNotify */ 508 for (n=0; n < 0x100; n++) { 509 if (added_keysyms[n] == keysym) { 510 return n; 511 } 512 } 513 514 XDisplayKeycodes(dpy, &minkey, &maxkey); 515 keymap = XGetKeyboardMapping(dpy, minkey, (maxkey - minkey + 1), 516 &syms_per_keycode); 517 518 for (kc = minkey+1; kc <= maxkey; kc++) { 519 int i, j, didmsg = 0, is_empty = 1; 520 char *str; 521 KeySym newks[8]; 522 523 for (n=0; n < syms_per_keycode; n++) { 524 if (keymap[ (kc-minkey) * syms_per_keycode + n] 525 != NoSymbol) { 526 is_empty = 0; 527 break; 528 } 529 } 530 if (! is_empty) { 531 continue; 532 } 533 534 for (i=0; i<8; i++) { 535 newks[i] = NoSymbol; 536 } 537 if (add_keysyms == 2) { 538 newks[0] = keysym; /* XXX remove me */ 539 } else { 540 for(i=0; i < syms_per_keycode; i++) { 541 newks[i] = keysym; 542 if (i >= 7) break; 543 } 544 } 545 546 XChangeKeyboardMapping(dpy, kc, syms_per_keycode, 547 newks, 1); 548 549 if (alltime_num >= alltime_len) { 550 didmsg = 1; /* something weird */ 551 } else { 552 for (j=0; j<alltime_num; j++) { 553 if (alltime_added_keysyms[j] == keysym) { 554 didmsg = 1; 555 break; 556 } 557 } 558 } 559 if (! didmsg) { 560 str = XKeysymToString(keysym); 561 rfbLog("added missing keysym to X display: %03d " 562 "0x%x \"%s\"\n", kc, keysym, str ? str : "null"); 563 564 if (alltime_num < alltime_len) { 565 alltime_added_keysyms[alltime_num++] = keysym; 566 } 567 } 568 569 XFlush_wr(dpy); 570 added_keysyms[kc] = keysym; 571 ret = kc; 572 break; 573 } 574 XFree_wr(keymap); 575 return ret; 576 #endif /* NO_X11 */ 577 } 578 579 static void delete_keycode(KeyCode kc, int bequiet) { 580 #if NO_X11 581 RAWFB_RET_VOID 582 if (!kc || !bequiet) {} 583 return; 584 #else 585 int minkey, maxkey, syms_per_keycode, i; 586 KeySym *keymap; 587 KeySym ksym, newks[8]; 588 char *str; 589 590 RAWFB_RET_VOID 591 592 XDisplayKeycodes(dpy, &minkey, &maxkey); 593 keymap = XGetKeyboardMapping(dpy, minkey, (maxkey - minkey + 1), 594 &syms_per_keycode); 595 596 for (i=0; i<8; i++) { 597 newks[i] = NoSymbol; 598 } 599 600 XChangeKeyboardMapping(dpy, kc, syms_per_keycode, newks, 1); 601 602 if (! bequiet && ! quiet) { 603 ksym = XKeycodeToKeysym(dpy, kc, 0); 604 str = XKeysymToString(ksym); 605 rfbLog("deleted keycode from X display: %03d 0x%x \"%s\"\n", 606 kc, ksym, str ? str : "null"); 607 } 608 609 XFree_wr(keymap); 610 XFlush_wr(dpy); 611 #endif /* NO_X11 */ 612 } 613 614 static int count_added_keycodes(void) { 615 int kc, count = 0; 616 for (kc = 0; kc < 0x100; kc++) { 617 if (added_keysyms[kc] != NoSymbol) { 618 count++; 619 } 620 } 621 return count; 622 } 623 624 void delete_added_keycodes(int bequiet) { 625 int kc; 626 for (kc = 0; kc < 0x100; kc++) { 627 if (added_keysyms[kc] != NoSymbol) { 628 delete_keycode(kc, bequiet); 629 added_keysyms[kc] = NoSymbol; 630 } 631 } 632 } 633 634 /* 635 * The following is for an experimental -remap option to allow the user 636 * to remap keystrokes. It is currently confusing wrt modifiers... 637 */ 638 typedef struct keyremap { 639 KeySym before; 640 KeySym after; 641 int isbutton; 642 struct keyremap *next; 643 } keyremap_t; 644 645 static keyremap_t *keyremaps = NULL; 646 647 static void add_remap(char *line) { 648 char str1[256], str2[256]; 649 KeySym ksym1, ksym2; 650 int isbtn = 0; 651 unsigned int i; 652 static keyremap_t *current = NULL; 653 keyremap_t *remap; 654 655 if (sscanf(line, "%s %s", str1, str2) != 2) { 656 rfbLogEnable(1); 657 rfbLog("remap: invalid line: %s\n", line); 658 clean_up_exit(1); 659 } 660 if (sscanf(str1, "0x%x", &i) == 1) { 661 ksym1 = (KeySym) i; 662 } else { 663 ksym1 = XStringToKeysym(str1); 664 } 665 if (sscanf(str2, "0x%x", &i) == 1) { 666 ksym2 = (KeySym) i; 667 } else { 668 ksym2 = XStringToKeysym(str2); 669 } 670 if (ksym2 == NoSymbol) { 671 if (sscanf(str2, "Button%u", &i) == 1) { 672 ksym2 = (KeySym) i; 673 isbtn = 1; 674 } 675 } 676 if (ksym1 == NoSymbol || ksym2 == NoSymbol) { 677 if (strcasecmp(str2, "NoSymbol") && strcasecmp(str2, "None")) { 678 rfbLog("warning: skipping invalid remap line: %s", line); 679 return; 680 } 681 } 682 remap = (keyremap_t *) malloc((size_t) sizeof(keyremap_t)); 683 remap->before = ksym1; 684 remap->after = ksym2; 685 remap->isbutton = isbtn; 686 remap->next = NULL; 687 688 rfbLog("remapping: (%s, 0x%x) -> (%s, 0x%x) isbtn=%d\n", str1, 689 ksym1, str2, ksym2, isbtn); 690 691 if (keyremaps == NULL) { 692 keyremaps = remap; 693 } else { 694 current->next = remap; 695 } 696 current = remap; 697 } 698 699 static void add_dead_keysyms(char *str) { 700 char *p, *q; 701 int i; 702 char *list[] = { 703 "g grave dead_grave", 704 "a acute dead_acute", 705 "c asciicircum dead_circumflex", 706 "t asciitilde dead_tilde", 707 "m macron dead_macron", 708 "b breve dead_breve", 709 "D abovedot dead_abovedot", 710 "d diaeresis dead_diaeresis", 711 "o degree dead_abovering", 712 "A doubleacute dead_doubleacute", 713 "r caron dead_caron", 714 "e cedilla dead_cedilla", 715 /* "x XXX-ogonek dead_ogonek", */ 716 /* "x XXX-belowdot dead_belowdot", */ 717 /* "x XXX-hook dead_hook", */ 718 /* "x XXX-horn dead_horn", */ 719 NULL 720 }; 721 722 p = str; 723 724 while (*p != '\0') { 725 if (isspace((unsigned char) (*p))) { 726 *p = '\0'; 727 } 728 p++; 729 } 730 731 if (!strcmp(str, "DEAD")) { 732 for (i = 0; list[i] != NULL; i++) { 733 p = list[i] + 2; 734 add_remap(p); 735 } 736 } else if (!strcmp(str, "DEAD=missing")) { 737 for (i = 0; list[i] != NULL; i++) { 738 KeySym ksym, ksym2; 739 int inmap = 0; 740 741 p = strdup(list[i] + 2); 742 q = strchr(p, ' '); 743 if (q == NULL) { 744 free(p); 745 continue; 746 } 747 *q = '\0'; 748 ksym = XStringToKeysym(p); 749 *q = ' '; 750 if (ksym == NoSymbol) { 751 free(p); 752 continue; 753 } 754 if (XKeysymToKeycode(dpy, ksym)) { 755 inmap = 1; 756 } 757 #if LIBVNCSERVER_HAVE_XKEYBOARD 758 if (! inmap && xkb_present && dpy) { 759 int kc, grp, lvl; 760 for (kc = 0; kc < 0x100; kc++) { 761 for (grp = 0; grp < 4; grp++) { 762 for (lvl = 0; lvl < 8; lvl++) { 763 ksym2 = XkbKeycodeToKeysym(dpy, 764 kc, grp, lvl); 765 if (ksym2 == NoSymbol) { 766 continue; 767 } 768 if (ksym2 == ksym) { 769 inmap = 1; 770 break; 771 } 772 } 773 } 774 } 775 } 776 #else 777 if ((ksym2 = 0)) {} 778 #endif 779 if (! inmap) { 780 add_remap(p); 781 } 782 free(p); 783 } 784 } else if ((p = strchr(str, '=')) != NULL) { 785 while (*p != '\0') { 786 for (i = 0; list[i] != NULL; i++) { 787 q = list[i]; 788 if (*p == *q) { 789 q += 2; 790 add_remap(q); 791 break; 792 } 793 } 794 p++; 795 } 796 } 797 } 798 799 /* 800 * process the -remap string (file or mapping string) 801 */ 802 void initialize_remap(char *infile) { 803 FILE *in; 804 char *p, *q, line[256]; 805 806 if (keyremaps != NULL) { 807 /* free last remapping */ 808 keyremap_t *next_remap, *curr_remap = keyremaps; 809 while (curr_remap != NULL) { 810 next_remap = curr_remap->next; 811 free(curr_remap); 812 curr_remap = next_remap; 813 } 814 keyremaps = NULL; 815 } 816 if (infile == NULL || *infile == '\0') { 817 /* just unset remapping */ 818 return; 819 } 820 821 in = fopen(infile, "r"); 822 if (in == NULL) { 823 /* assume cmd line key1-key2,key3-key4 */ 824 if (strstr(infile, "DEAD") == infile) { 825 ; 826 } else if (!strchr(infile, '-')) { 827 rfbLogEnable(1); 828 rfbLog("remap: cannot open: %s\n", infile); 829 rfbLogPerror("fopen"); 830 clean_up_exit(1); 831 } 832 if ((in = tmpfile()) == NULL) { 833 rfbLogEnable(1); 834 rfbLog("remap: cannot open tmpfile for %s\n", infile); 835 rfbLogPerror("tmpfile"); 836 clean_up_exit(1); 837 } 838 839 /* copy in the string to file format */ 840 p = infile; 841 while (*p) { 842 if (*p == '-') { 843 fprintf(in, " "); 844 } else if (*p == ',' || *p == ' ' || *p == '\t') { 845 fprintf(in, "\n"); 846 } else { 847 fprintf(in, "%c", *p); 848 } 849 p++; 850 } 851 fprintf(in, "\n"); 852 fflush(in); 853 rewind(in); 854 } 855 856 while (fgets(line, 256, in) != NULL) { 857 p = lblanks(line); 858 if (*p == '\0') { 859 continue; 860 } 861 if (strchr(line, '#')) { 862 continue; 863 } 864 865 if (strstr(p, "DEAD") == p) { 866 add_dead_keysyms(p); 867 continue; 868 } 869 if ((q = strchr(line, '-')) != NULL) { 870 /* allow Keysym1-Keysym2 notation */ 871 *q = ' '; 872 } 873 add_remap(p); 874 } 875 fclose(in); 876 } 877 878 /* 879 * preliminary support for using the Xkb (XKEYBOARD) extension for handling 880 * user input. inelegant, slow, and incomplete currently... but initial 881 * tests show it is useful for some setups. 882 */ 883 typedef struct keychar { 884 KeyCode code; 885 int group; 886 int level; 887 } keychar_t; 888 889 /* max number of key groups and shift levels we consider */ 890 #define GRP 4 891 #define LVL 8 892 static int lvl_max, grp_max, kc_min, kc_max; 893 static KeySym xkbkeysyms[0x100][GRP][LVL]; 894 static unsigned int xkbstate[0x100][GRP][LVL]; 895 static unsigned int xkbignore[0x100][GRP][LVL]; 896 static unsigned int xkbmodifiers[0x100][GRP][LVL]; 897 static int multi_key[0x100], mode_switch[0x100], skipkeycode[0x100]; 898 static int shift_keys[0x100]; 899 900 /* 901 * for trying to order the keycodes to avoid problems, note the 902 * *first* keycode bound to it. kc_vec will be a permutation 903 * of 1...256 to get them in the preferred order. 904 */ 905 static int kc_vec[0x100]; 906 static int kc1_shift, kc1_control, kc1_caplock, kc1_alt; 907 static int kc1_meta, kc1_numlock, kc1_super, kc1_hyper; 908 static int kc1_mode_switch, kc1_iso_level3_shift, kc1_multi_key; 909 910 int sloppy_key_check(int key, rfbBool down, rfbKeySym keysym, int *new_kc) { 911 if (!sloppy_keys) { 912 return 0; 913 } 914 915 RAWFB_RET(0) 916 #if NO_X11 917 if (!key || !down || !keysym || !new_kc) {} 918 return 0; 919 #else 920 921 if (!down && !keycode_state[key] && !IsModifierKey(keysym)) { 922 int i, cnt = 0, downkey = -1; 923 int nmods_down = track_mod_state(NoSymbol, FALSE, FALSE); 924 int mods_down[256]; 925 926 if (nmods_down) { 927 /* tracking to skip down modifier keycodes. */ 928 for(i=0; i<256; i++) { 929 mods_down[i] = 0; 930 } 931 i = 0; 932 while (simple_mods[i] != NoSymbol) { 933 KeySym ksym = simple_mods[i]; 934 KeyCode k = XKeysymToKeycode(dpy, ksym); 935 if (k != NoSymbol && keycode_state[(int) k]) { 936 mods_down[(int) k] = 1; 937 } 938 939 i++; 940 } 941 } 942 /* 943 * the keycode is already up... look for a single one 944 * (non modifier) that is down 945 */ 946 for (i=0; i<256; i++) { 947 if (keycode_state[i]) { 948 if (nmods_down && mods_down[i]) { 949 continue; 950 } 951 cnt++; 952 downkey = i; 953 } 954 } 955 if (cnt == 1) { 956 if (debug_keyboard) { 957 fprintf(stderr, " sloppy_keys: %d/0x%x " 958 "-> %d/0x%x (nmods: %d)\n", (int) key, 959 (int) key, downkey, downkey, nmods_down); 960 } 961 *new_kc = downkey; 962 return 1; 963 } 964 } 965 return 0; 966 #endif /* NO_X11 */ 967 } 968 969 #if !LIBVNCSERVER_HAVE_XKEYBOARD || SKIP_XKB 970 971 /* empty functions for no xkb */ 972 static void initialize_xkb_modtweak(void) {} 973 static void xkb_tweak_keyboard(rfbBool down, rfbKeySym keysym, 974 rfbClientPtr client) { 975 if (!client || !down || !keysym) {} /* unused vars warning: */ 976 } 977 void switch_to_xkb_if_better(void) {} 978 979 #else 980 981 void switch_to_xkb_if_better(void) { 982 KeySym keysym, *keymap; 983 int miss_noxkb[256], miss_xkb[256], missing_noxkb = 0, missing_xkb = 0; 984 int i, j, k, n, minkey, maxkey, syms_per_keycode; 985 int syms_gt_4 = 0; 986 int kc, grp, lvl; 987 988 /* non-alphanumeric on us keyboard */ 989 KeySym must_have[] = { 990 XK_exclam, 991 XK_at, 992 XK_numbersign, 993 XK_dollar, 994 XK_percent, 995 /* XK_asciicircum, */ 996 XK_ampersand, 997 XK_asterisk, 998 XK_parenleft, 999 XK_parenright, 1000 XK_underscore, 1001 XK_plus, 1002 XK_minus, 1003 XK_equal, 1004 XK_bracketleft, 1005 XK_bracketright, 1006 XK_braceleft, 1007 XK_braceright, 1008 XK_bar, 1009 XK_backslash, 1010 XK_semicolon, 1011 /* XK_apostrophe, */ 1012 XK_colon, 1013 XK_quotedbl, 1014 XK_comma, 1015 XK_period, 1016 XK_less, 1017 XK_greater, 1018 XK_slash, 1019 XK_question, 1020 /* XK_asciitilde, */ 1021 /* XK_grave, */ 1022 NoSymbol 1023 }; 1024 1025 if (! use_modifier_tweak || got_noxkb) { 1026 return; 1027 } 1028 if (use_xkb_modtweak) { 1029 /* already using it */ 1030 return; 1031 } 1032 RAWFB_RET_VOID 1033 1034 XDisplayKeycodes(dpy, &minkey, &maxkey); 1035 1036 keymap = XGetKeyboardMapping(dpy, minkey, (maxkey - minkey + 1), 1037 &syms_per_keycode); 1038 1039 /* handle alphabetic char with only one keysym (no upper + lower) */ 1040 for (i = minkey; i <= maxkey; i++) { 1041 KeySym lower, upper; 1042 /* 2nd one */ 1043 keysym = keymap[(i - minkey) * syms_per_keycode + 1]; 1044 if (keysym != NoSymbol) { 1045 continue; 1046 } 1047 /* 1st one */ 1048 keysym = keymap[(i - minkey) * syms_per_keycode + 0]; 1049 if (keysym == NoSymbol) { 1050 continue; 1051 } 1052 XConvertCase(keysym, &lower, &upper); 1053 if (lower != upper) { 1054 keymap[(i - minkey) * syms_per_keycode + 0] = lower; 1055 keymap[(i - minkey) * syms_per_keycode + 1] = upper; 1056 } 1057 } 1058 1059 k = 0; 1060 while (must_have[k] != NoSymbol) { 1061 int gotit = 0; 1062 KeySym must = must_have[k]; 1063 for (i = minkey; i <= maxkey; i++) { 1064 for (j = 0; j < syms_per_keycode; j++) { 1065 keysym = keymap[(i-minkey) * syms_per_keycode + j]; 1066 if (j >= 4) { 1067 if (k == 0 && keysym != NoSymbol) { 1068 /* for k=0 count the high keysyms */ 1069 syms_gt_4++; 1070 if (debug_keyboard > 1) { 1071 char *str = XKeysymToString(keysym); 1072 fprintf(stderr, "- high keysym mapping" 1073 ": at %3d j=%d " 1074 "'%s'\n", i, j, str ? str : "null"); 1075 } 1076 } 1077 continue; 1078 } 1079 if (keysym == must) { 1080 if (debug_keyboard > 1) { 1081 char *str = XKeysymToString(must); 1082 fprintf(stderr, "- at %3d j=%d found " 1083 "'%s'\n", i, j, str ? str : "null"); 1084 } 1085 /* n.b. do not break, see syms_gt_4 above. */ 1086 gotit = 1; 1087 } 1088 } 1089 } 1090 if (! gotit) { 1091 if (debug_keyboard > 1) { 1092 char *str = XKeysymToString(must); 1093 KeyCode kc = XKeysymToKeycode(dpy, must); 1094 fprintf(stderr, "- did not find 0x%lx '%s'\t" 1095 "Ks2Kc: %d\n", must, str ? str:"null", kc); 1096 if (kc != None) { 1097 int j2; 1098 for(j2=0; j2<syms_per_keycode; j2++) { 1099 keysym = keymap[(kc-minkey) * 1100 syms_per_keycode + j2]; 1101 fprintf(stderr, " %d=0x%lx", 1102 j2, keysym); 1103 } 1104 fprintf(stderr, "\n"); 1105 } 1106 } 1107 missing_noxkb++; 1108 miss_noxkb[k] = 1; 1109 } else { 1110 miss_noxkb[k] = 0; 1111 } 1112 k++; 1113 } 1114 n = k; 1115 1116 XFree_wr(keymap); 1117 if (missing_noxkb == 0 && syms_per_keycode > 4 && syms_gt_4 >= 0) { 1118 /* we used to have syms_gt_4 >= 8, now always on. */ 1119 if (! raw_fb_str) { 1120 rfbLog("\n"); 1121 rfbLog("XKEYBOARD: number of keysyms per keycode %d is greater\n", syms_per_keycode); 1122 rfbLog(" than 4 and %d keysyms are mapped above 4.\n", syms_gt_4); 1123 rfbLog(" Automatically switching to -xkb mode.\n"); 1124 rfbLog(" If this makes the key mapping worse you can\n"); 1125 rfbLog(" disable it with the \"-noxkb\" option.\n"); 1126 rfbLog(" Also, remember \"-remap DEAD\" for accenting characters.\n"); 1127 rfbLog("\n"); 1128 } 1129 1130 use_xkb_modtweak = 1; 1131 return; 1132 1133 } else if (missing_noxkb == 0) { 1134 if (! raw_fb_str) { 1135 rfbLog("\n"); 1136 rfbLog("XKEYBOARD: all %d \"must have\" keysyms accounted for.\n", n); 1137 rfbLog(" Not automatically switching to -xkb mode.\n"); 1138 rfbLog(" If some keys still cannot be typed, try using -xkb.\n"); 1139 rfbLog(" Also, remember \"-remap DEAD\" for accenting characters.\n"); 1140 rfbLog("\n"); 1141 } 1142 return; 1143 } 1144 1145 for (k=0; k<n; k++) { 1146 miss_xkb[k] = 1; 1147 } 1148 1149 for (kc = 0; kc < 0x100; kc++) { 1150 for (grp = 0; grp < GRP; grp++) { 1151 for (lvl = 0; lvl < LVL; lvl++) { 1152 /* look up the Keysym, if any */ 1153 keysym = XkbKeycodeToKeysym(dpy, kc, grp, lvl); 1154 if (keysym == NoSymbol) { 1155 continue; 1156 } 1157 for (k=0; k<n; k++) { 1158 if (keysym == must_have[k]) { 1159 miss_xkb[k] = 0; 1160 } 1161 } 1162 } 1163 } 1164 } 1165 1166 for (k=0; k<n; k++) { 1167 if (miss_xkb[k]) { 1168 missing_xkb++; 1169 } 1170 } 1171 1172 rfbLog("\n"); 1173 if (missing_xkb < missing_noxkb) { 1174 rfbLog("XKEYBOARD:\n"); 1175 rfbLog("Switching to -xkb mode to recover these keysyms:\n"); 1176 } else { 1177 rfbLog("XKEYBOARD: \"must have\" keysyms better accounted" 1178 " for\n"); 1179 rfbLog("under -noxkb mode: not switching to -xkb mode:\n"); 1180 } 1181 1182 rfbLog(" xkb noxkb Keysym (\"X\" means present)\n"); 1183 rfbLog(" --- ----- -----------------------------\n"); 1184 for (k=0; k<n; k++) { 1185 char *xx, *xn, *name; 1186 1187 keysym = must_have[k]; 1188 if (keysym == NoSymbol) { 1189 continue; 1190 } 1191 if (!miss_xkb[k] && !miss_noxkb[k]) { 1192 continue; 1193 } 1194 if (miss_xkb[k]) { 1195 xx = " "; 1196 } else { 1197 xx = " X "; 1198 } 1199 if (miss_noxkb[k]) { 1200 xn = " "; 1201 } else { 1202 xn = " X "; 1203 } 1204 name = XKeysymToString(keysym); 1205 rfbLog(" %s %s 0x%lx %s\n", xx, xn, keysym, 1206 name ? name : "null"); 1207 } 1208 rfbLog("\n"); 1209 1210 if (missing_xkb < missing_noxkb) { 1211 rfbLog(" If this makes the key mapping worse you can\n"); 1212 rfbLog(" disable it with the \"-noxkb\" option.\n"); 1213 rfbLog("\n"); 1214 1215 use_xkb_modtweak = 1; 1216 1217 } else { 1218 rfbLog(" If some keys still cannot be typed, try using" 1219 " -xkb.\n"); 1220 rfbLog(" Also, remember \"-remap DEAD\" for accenting" 1221 " characters.\n"); 1222 } 1223 rfbLog("\n"); 1224 } 1225 1226 /* sets up all the keymapping info via Xkb API */ 1227 1228 static void initialize_xkb_modtweak(void) { 1229 KeySym ks; 1230 int kc, grp, lvl, k; 1231 unsigned int state; 1232 1233 /* 1234 * Here is a guide: 1235 1236 Workarounds arrays: 1237 1238 multi_key[] indicates which keycodes have Multi_key (Compose) 1239 bound to them. 1240 mode_switch[] indicates which keycodes have Mode_switch (AltGr) 1241 bound to them. 1242 shift_keys[] indicates which keycodes have Shift bound to them. 1243 skipkeycode[] indicates which keycodes are to be skipped 1244 for any lookups from -skip_keycodes option. 1245 1246 Groups and Levels, here is an example: 1247 1248 ^ -------- 1249 | L2 | A AE | 1250 shift | | 1251 level L1 | a ae | 1252 -------- 1253 G1 G2 1254 1255 group -> 1256 1257 Traditionally this it all a key could do. L1 vs. L2 selected via Shift 1258 and G1 vs. G2 selected via Mode_switch. Up to 4 Keysyms could be bound 1259 to a key. See initialize_modtweak() for an example of using that type 1260 of keymap from XGetKeyboardMapping(). 1261 1262 Xkb gives us up to 4 groups and 63 shift levels per key, with the 1263 situation being potentially different for each key. This is complicated, 1264 and I don't claim to understand it all, but in the following we just think 1265 of ranging over the group and level indices as covering all of the cases. 1266 This gives us an accurate view of the keymap. The main tricky part 1267 is mapping between group+level and modifier state. 1268 1269 On current linux/XFree86 setups (Xkb is enabled by default) the 1270 information from XGetKeyboardMapping() (evidently the compat map) 1271 is incomplete and inaccurate, so we are really forced to use the 1272 Xkb API. 1273 1274 xkbkeysyms[] For a (keycode,group,level) holds the KeySym (0 for none) 1275 xkbstate[] For a (keycode,group,level) holds the corresponding 1276 modifier state needed to get that KeySym 1277 xkbignore[] For a (keycode,group,level) which modifiers can be 1278 ignored (the 0 bits can be ignored). 1279 xkbmodifiers[] For the KeySym bound to this (keycode,group,level) store 1280 the modifier mask. 1281 * 1282 */ 1283 1284 RAWFB_RET_VOID 1285 1286 /* initialize all the arrays: */ 1287 for (kc = 0; kc < 0x100; kc++) { 1288 multi_key[kc] = 0; 1289 mode_switch[kc] = 0; 1290 skipkeycode[kc] = 0; 1291 shift_keys[kc] = 0; 1292 1293 for (grp = 0; grp < GRP; grp++) { 1294 for (lvl = 0; lvl < LVL; lvl++) { 1295 xkbkeysyms[kc][grp][lvl] = NoSymbol; 1296 xkbmodifiers[kc][grp][lvl] = -1; 1297 xkbstate[kc][grp][lvl] = -1; 1298 } 1299 } 1300 } 1301 1302 /* 1303 * the array is 256*LVL*GRP, but we can make the searched region 1304 * smaller by computing the actual ranges. 1305 */ 1306 lvl_max = 0; 1307 grp_max = 0; 1308 kc_max = 0; 1309 kc_min = 0x100; 1310 1311 /* first keycode for a modifier type (multi_key too) */ 1312 kc1_shift = -1; 1313 kc1_control = -1; 1314 kc1_caplock = -1; 1315 kc1_alt = -1; 1316 kc1_meta = -1; 1317 kc1_numlock = -1; 1318 kc1_super = -1; 1319 kc1_hyper = -1; 1320 kc1_mode_switch = -1; 1321 kc1_iso_level3_shift = -1; 1322 kc1_multi_key = -1; 1323 1324 /* 1325 * loop over all possible (keycode, group, level) triples 1326 * and record what we find for it: 1327 */ 1328 if (debug_keyboard) { 1329 rfbLog("initialize_xkb_modtweak: XKB keycode -> keysyms " 1330 "mapping info:\n"); 1331 } 1332 for (kc = 0; kc < 0x100; kc++) { 1333 for (grp = 0; grp < GRP; grp++) { 1334 for (lvl = 0; lvl < LVL; lvl++) { 1335 unsigned int ms, mods; 1336 int state_save = -1, mods_save = -1; 1337 KeySym ks2; 1338 1339 /* look up the Keysym, if any */ 1340 ks = XkbKeycodeToKeysym(dpy, kc, grp, lvl); 1341 xkbkeysyms[kc][grp][lvl] = ks; 1342 1343 /* if no Keysym, on to next */ 1344 if (ks == NoSymbol) { 1345 continue; 1346 } 1347 /* 1348 * for various workarounds, note where these special 1349 * keys are bound to. 1350 */ 1351 if (ks == XK_Multi_key) { 1352 multi_key[kc] = lvl+1; 1353 } 1354 if (ks == XK_Mode_switch) { 1355 mode_switch[kc] = lvl+1; 1356 } 1357 if (ks == XK_Shift_L || ks == XK_Shift_R) { 1358 shift_keys[kc] = lvl+1; 1359 } 1360 1361 if (ks == XK_Shift_L || ks == XK_Shift_R) { 1362 if (kc1_shift == -1) { 1363 kc1_shift = kc; 1364 } 1365 } 1366 if (ks == XK_Control_L || ks == XK_Control_R) { 1367 if (kc1_control == -1) { 1368 kc1_control = kc; 1369 } 1370 } 1371 if (ks == XK_Caps_Lock || ks == XK_Caps_Lock) { 1372 if (kc1_caplock == -1) { 1373 kc1_caplock = kc; 1374 } 1375 } 1376 if (ks == XK_Alt_L || ks == XK_Alt_R) { 1377 if (kc1_alt == -1) { 1378 kc1_alt = kc; 1379 } 1380 } 1381 if (ks == XK_Meta_L || ks == XK_Meta_R) { 1382 if (kc1_meta == -1) { 1383 kc1_meta = kc; 1384 } 1385 } 1386 if (ks == XK_Num_Lock) { 1387 if (kc1_numlock == -1) { 1388 kc1_numlock = kc; 1389 } 1390 } 1391 if (ks == XK_Super_L || ks == XK_Super_R) { 1392 if (kc1_super == -1) { 1393 kc1_super = kc; 1394 } 1395 } 1396 if (ks == XK_Hyper_L || ks == XK_Hyper_R) { 1397 if (kc1_hyper == -1) { 1398 kc1_hyper = kc; 1399 } 1400 } 1401 if (ks == XK_Mode_switch) { 1402 if (kc1_mode_switch == -1) { 1403 kc1_mode_switch = kc; 1404 } 1405 } 1406 if (ks == XK_ISO_Level3_Shift) { 1407 if (kc1_iso_level3_shift == -1) { 1408 kc1_iso_level3_shift = kc; 1409 } 1410 } 1411 if (ks == XK_Multi_key) { /* not a modifier.. */ 1412 if (kc1_multi_key == -1) { 1413 kc1_multi_key = kc; 1414 } 1415 } 1416 1417 /* 1418 * record maximum extent for group/level indices 1419 * and keycode range: 1420 */ 1421 if (grp > grp_max) { 1422 grp_max = grp; 1423 } 1424 if (lvl > lvl_max) { 1425 lvl_max = lvl; 1426 } 1427 if (kc > kc_max) { 1428 kc_max = kc; 1429 } 1430 if (kc < kc_min) { 1431 kc_min = kc; 1432 } 1433 1434 /* 1435 * lookup on *keysym* (i.e. not kc, grp, lvl) 1436 * and get the modifier mask. this is 0 for 1437 * most keysyms, only non zero for modifiers. 1438 */ 1439 ms = XkbKeysymToModifiers(dpy, ks); 1440 xkbmodifiers[kc][grp][lvl] = ms; 1441 1442 /* 1443 * Amusing heuristic (may have bugs). There are 1444 * 8 modifier bits, so 256 possible modifier 1445 * states. We loop over all of them for this 1446 * keycode (simulating Key "events") and ask 1447 * XkbLookupKeySym to tell us the Keysym. Once it 1448 * matches the Keysym we have for this (keycode, 1449 * group, level), gotten via XkbKeycodeToKeysym() 1450 * above, we then (hopefully...) know that state 1451 * of modifiers needed to generate this keysym. 1452 * 1453 * Yes... keep your fingers crossed. 1454 * 1455 * Note that many of the 256 states give the 1456 * Keysym, we just need one, and we take the 1457 * first one found. 1458 */ 1459 state = 0; 1460 while(state < 256) { 1461 if (XkbLookupKeySym(dpy, kc, state, &mods, 1462 &ks2)) { 1463 1464 /* save these for workaround below */ 1465 if (state_save == -1) { 1466 state_save = state; 1467 mods_save = mods; 1468 } 1469 if (ks2 == ks) { 1470 /* 1471 * zero the irrelevant bits 1472 * by anding with mods. 1473 */ 1474 xkbstate[kc][grp][lvl] 1475 = state & mods; 1476 /* 1477 * also remember the irrelevant 1478 * bits since it is handy. 1479 */ 1480 xkbignore[kc][grp][lvl] = mods; 1481 1482 break; 1483 } 1484 } 1485 state++; 1486 } 1487 if (xkbstate[kc][grp][lvl] == (unsigned int) -1 1488 && grp == 1) { 1489 /* 1490 * Hack on Solaris 9 for Mode_switch 1491 * for Group2 characters. We force the 1492 * Mode_switch modifier bit on. 1493 * XXX Need to figure out better what is 1494 * happening here. Is compat on somehow?? 1495 */ 1496 unsigned int ms2; 1497 ms2 = XkbKeysymToModifiers(dpy, XK_Mode_switch); 1498 1499 xkbstate[kc][grp][lvl] 1500 = (state_save & mods_save) | ms2; 1501 1502 xkbignore[kc][grp][lvl] = mods_save | ms2; 1503 } 1504 1505 if (debug_keyboard) { 1506 char *str; 1507 fprintf(stderr, " %03d G%d L%d mod=%s ", 1508 kc, grp+1, lvl+1, bitprint(ms, 8)); 1509 fprintf(stderr, "state=%s ", 1510 bitprint(xkbstate[kc][grp][lvl], 8)); 1511 fprintf(stderr, "ignore=%s ", 1512 bitprint(xkbignore[kc][grp][lvl], 8)); 1513 str = XKeysymToString(ks); 1514 fprintf(stderr, " ks=0x%08lx \"%s\"\n", 1515 ks, str ? str : "null"); 1516 } 1517 } 1518 } 1519 } 1520 1521 /* 1522 * kc_vec will be used in some places to find modifiers, etc 1523 * we apply some permutations to it as workarounds. 1524 */ 1525 for (kc = 0; kc < 0x100; kc++) { 1526 kc_vec[kc] = kc; 1527 } 1528 1529 if (kc1_mode_switch != -1 && kc1_iso_level3_shift != -1) { 1530 if (kc1_mode_switch < kc1_iso_level3_shift) { 1531 /* we prefer XK_ISO_Level3_Shift: */ 1532 kc_vec[kc1_mode_switch] = kc1_iso_level3_shift; 1533 kc_vec[kc1_iso_level3_shift] = kc1_mode_switch; 1534 } 1535 } 1536 /* any more? need to watch for undoing the above. */ 1537 1538 /* 1539 * process the user supplied -skip_keycodes string. 1540 * This is presumably a list if "ghost" keycodes, the X server 1541 * thinks they exist, but they do not. ghosts can lead to 1542 * ambiguities in the reverse map: Keysym -> KeyCode + Modstate, 1543 * so if we can ignore them so much the better. Presumably the 1544 * user can never generate them from the physical keyboard. 1545 * There may be other reasons to deaden some keys. 1546 */ 1547 if (skip_keycodes != NULL) { 1548 char *p, *str = strdup(skip_keycodes); 1549 p = strtok(str, ", \t\n\r"); 1550 while (p) { 1551 k = 1; 1552 if (sscanf(p, "%d", &k) != 1 || k < 0 || k >= 0x100) { 1553 rfbLogEnable(1); 1554 rfbLog("invalid skip_keycodes: %s %s\n", 1555 skip_keycodes, p); 1556 clean_up_exit(1); 1557 } 1558 skipkeycode[k] = 1; 1559 p = strtok(NULL, ", \t\n\r"); 1560 } 1561 free(str); 1562 } 1563 if (debug_keyboard) { 1564 fprintf(stderr, "grp_max=%d lvl_max=%d\n", grp_max, lvl_max); 1565 } 1566 } 1567 1568 static short **score_hint = NULL; 1569 /* 1570 * Called on user keyboard input. Try to solve the reverse mapping 1571 * problem: KeySym (from VNC client) => KeyCode(s) to press to generate 1572 * it. The one-to-many KeySym => KeyCode mapping makes it difficult, as 1573 * does working out what changes to the modifier keypresses are needed. 1574 */ 1575 static void xkb_tweak_keyboard(rfbBool down, rfbKeySym keysym, 1576 rfbClientPtr client) { 1577 1578 int kc, grp, lvl, i, kci; 1579 int kc_f[0x100], grp_f[0x100], lvl_f[0x100], state_f[0x100], found; 1580 int ignore_f[0x100]; 1581 unsigned int state = 0; 1582 1583 1584 /* these are used for finding modifiers, etc */ 1585 XkbStateRec kbstate; 1586 int got_kbstate = 0; 1587 int Kc_f, Grp_f = 0, Lvl_f = 0; 1588 # define KLAST 10 1589 static int Kc_last_down[KLAST]; 1590 static KeySym Ks_last_down[KLAST]; 1591 static int klast = 0, khints = 1, anydown = 1; 1592 static int cnt = 0; 1593 1594 if (!client || !down || !keysym) {} /* unused vars warning: */ 1595 1596 RAWFB_RET_VOID 1597 1598 X_LOCK; 1599 1600 if (klast == 0) { 1601 int i, j; 1602 for (i=0; i<KLAST; i++) { 1603 Kc_last_down[i] = -1; 1604 Ks_last_down[i] = NoSymbol; 1605 } 1606 if (getenv("NOKEYHINTS")) { 1607 khints = 0; 1608 } 1609 if (getenv("NOANYDOWN")) { 1610 anydown = 0; 1611 } 1612 if (getenv("KEYSDOWN")) { 1613 klast = atoi(getenv("KEYSDOWN")); 1614 if (klast < 1) klast = 1; 1615 if (klast > KLAST) klast = KLAST; 1616 } else { 1617 klast = 3; 1618 } 1619 if (khints && score_hint == NULL) { 1620 score_hint = (short **) malloc(0x100 * sizeof(short *)); 1621 for (i=0; i<0x100; i++) { 1622 score_hint[i] = (short *) malloc(0x100 * sizeof(short)); 1623 } 1624 1625 for (i=0; i<0x100; i++) { 1626 for (j=0; j<0x100; j++) { 1627 score_hint[i][j] = -1; 1628 } 1629 } 1630 } 1631 } 1632 cnt++; 1633 if (cnt % 100 && khints && score_hint != NULL) { 1634 int i, j; 1635 for (i=0; i<0x100; i++) { 1636 for (j=0; j<0x100; j++) { 1637 score_hint[i][j] = -1; 1638 } 1639 } 1640 } 1641 1642 if (debug_keyboard) { 1643 char *str = XKeysymToString(keysym); 1644 1645 if (debug_keyboard > 1) { 1646 rfbLog("----------start-xkb_tweak_keyboard (%s) " 1647 "--------\n", down ? "DOWN" : "UP"); 1648 } 1649 1650 rfbLog("xkb_tweak_keyboard: %s keysym=0x%x \"%s\"\n", 1651 down ? "down" : "up", (int) keysym, str ? str : "null"); 1652 } 1653 1654 /* 1655 * set everything to not-yet-found. 1656 * these "found" arrays (*_f) let us dynamically consider the 1657 * one-to-many Keysym -> Keycode issue. we set the size at 256, 1658 * but of course only very few will be found. 1659 */ 1660 for (i = 0; i < 0x100; i++) { 1661 kc_f[i] = -1; 1662 grp_f[i] = -1; 1663 lvl_f[i] = -1; 1664 state_f[i] = -1; 1665 ignore_f[i] = -1; 1666 } 1667 found = 0; 1668 1669 /* 1670 * loop over all (keycode, group, level) triples looking for 1671 * matching keysyms. Amazingly this isn't slow (but maybe if 1672 * you type really fast...). Hash lookup into a linked list of 1673 * (keycode,grp,lvl) triples would be the way to improve this 1674 * in the future if needed. 1675 */ 1676 for (kc = kc_min; kc <= kc_max; kc++) { 1677 for (grp = 0; grp < grp_max+1; grp++) { 1678 for (lvl = 0; lvl < lvl_max+1; lvl++) { 1679 if (keysym != xkbkeysyms[kc][grp][lvl]) { 1680 continue; 1681 } 1682 /* got a keysym match */ 1683 state = xkbstate[kc][grp][lvl]; 1684 1685 if (debug_keyboard > 1) { 1686 char *s1, *s2; 1687 s1 = XKeysymToString(XKeycodeToKeysym(dpy, 1688 kc, 0)); 1689 if (! s1) s1 = "null"; 1690 s2 = XKeysymToString(keysym); 1691 if (! s2) s2 = "null"; 1692 fprintf(stderr, " got match kc=%03d=0x%02x G%d" 1693 " L%d ks=0x%x \"%s\" (basesym: \"%s\")\n", 1694 kc, kc, grp+1, lvl+1, keysym, s2, s1); 1695 fprintf(stderr, " need state: %s\n", 1696 bitprint(state, 8)); 1697 fprintf(stderr, " ignorable : %s\n", 1698 bitprint(xkbignore[kc][grp][lvl], 8)); 1699 } 1700 1701 /* save it if state is OK and not told to skip */ 1702 if (state == (unsigned int) -1) { 1703 continue; 1704 } 1705 if (skipkeycode[kc] && debug_keyboard) { 1706 fprintf(stderr, " xxx skipping keycode: %d " 1707 "G%d/L%d\n", kc, grp+1, lvl+1); 1708 } 1709 if (skipkeycode[kc]) { 1710 continue; 1711 } 1712 if (found > 0 && kc == kc_f[found-1]) { 1713 /* ignore repeats for same keycode */ 1714 continue; 1715 } 1716 kc_f[found] = kc; 1717 grp_f[found] = grp; 1718 lvl_f[found] = lvl; 1719 state_f[found] = state; 1720 ignore_f[found] = xkbignore[kc][grp][lvl]; 1721 found++; 1722 } 1723 } 1724 } 1725 1726 #define PKBSTATE \ 1727 fprintf(stderr, " --- current mod state:\n"); \ 1728 fprintf(stderr, " mods : %s\n", bitprint(kbstate.mods, 8)); \ 1729 fprintf(stderr, " base_mods : %s\n", bitprint(kbstate.base_mods, 8)); \ 1730 fprintf(stderr, " latch_mods: %s\n", bitprint(kbstate.latched_mods, 8)); \ 1731 fprintf(stderr, " lock_mods : %s\n", bitprint(kbstate.locked_mods, 8)); \ 1732 fprintf(stderr, " compat : %s\n", bitprint(kbstate.compat_state, 8)); 1733 1734 /* 1735 * Now get the current state of the keyboard from the X server. 1736 * This seems to be the safest way to go as opposed to our 1737 * keeping track of the modifier state on our own. Again, 1738 * this is fortunately not too slow. 1739 */ 1740 1741 if (debug_keyboard > 1) { 1742 /* get state early for debug output */ 1743 XkbGetState(dpy, XkbUseCoreKbd, &kbstate); 1744 got_kbstate = 1; 1745 PKBSTATE 1746 } 1747 1748 if (!found && add_keysyms && keysym && ! IsModifierKey(keysym)) { 1749 int new_kc = add_keysym(keysym); 1750 if (new_kc != 0) { 1751 found = 1; 1752 kc_f[0] = new_kc; 1753 grp_f[0] = 0; 1754 lvl_f[0] = 0; 1755 state_f[0] = 0; 1756 } 1757 } 1758 1759 if (!found && debug_keyboard) { 1760 char *str = XKeysymToString(keysym); 1761 fprintf(stderr, " *** NO key found for: 0x%x %s " 1762 "*keystroke ignored*\n", keysym, str ? str : "null"); 1763 } 1764 if (!found) { 1765 X_UNLOCK; 1766 return; 1767 } 1768 1769 /* 1770 * we try to optimize here if found > 1 1771 * e.g. minimize lvl or grp, or other things to give 1772 * "safest" scenario to simulate the keystrokes. 1773 */ 1774 1775 if (found > 1) { 1776 if (down) { 1777 int l, score[0x100]; 1778 int best = 0, best_score = -1; 1779 /* need to break the tie... */ 1780 if (! got_kbstate) { 1781 XkbGetState(dpy, XkbUseCoreKbd, &kbstate); 1782 got_kbstate = 1; 1783 } 1784 if (khints && keysym < 0x100) { 1785 int ks = (int) keysym, j; 1786 for (j=0; j< 0x100; j++) { 1787 score_hint[ks][j] = -1; 1788 } 1789 } 1790 for (l=0; l < found; l++) { 1791 int myscore = 0, b = 0x1, i; 1792 int curr, curr_state = kbstate.mods; 1793 int need, need_state = state_f[l]; 1794 int ignore_state = ignore_f[l]; 1795 1796 /* see how many modifiers need to be changed */ 1797 for (i=0; i<8; i++) { 1798 curr = b & curr_state; 1799 need = b & need_state; 1800 if (! (b & ignore_state)) { 1801 ; 1802 } else if (curr == need) { 1803 ; 1804 } else { 1805 myscore++; 1806 } 1807 b = b << 1; 1808 } 1809 myscore *= 100; 1810 1811 /* throw in some minimization of lvl too: */ 1812 myscore += 2*lvl_f[l] + grp_f[l]; 1813 1814 /* 1815 * XXX since we now internally track 1816 * keycode_state[], we could throw that into 1817 * the score as well. I.e. if it is already 1818 * down, it is pointless to think we can 1819 * press it down further! E.g. 1820 * myscore += 1000 * keycode_state[kc_f[l]]; 1821 * Also could watch multiple modifier 1822 * problem, e.g. Shift+key -> Alt 1823 * keycode = 125 on my keyboard. 1824 */ 1825 1826 score[l] = myscore; 1827 if (debug_keyboard > 1) { 1828 fprintf(stderr, " *** score for " 1829 "keycode %03d: %4d\n", 1830 kc_f[l], myscore); 1831 } 1832 if (khints && keysym < 0x100 && kc_f[l] < 0x100) { 1833 score_hint[(int) keysym][kc_f[l]] = (short) score[l]; 1834 } 1835 } 1836 for (l=0; l < found; l++) { 1837 int myscore = score[l]; 1838 if (best_score == -1 || myscore < best_score) { 1839 best = l; 1840 best_score = myscore; 1841 } 1842 } 1843 Kc_f = kc_f[best]; 1844 Grp_f = grp_f[best]; 1845 Lvl_f = lvl_f[best]; 1846 state = state_f[best]; 1847 1848 } else { 1849 /* up */ 1850 int i, Kc_loc = -1; 1851 Kc_f = -1; 1852 1853 /* first try the scores we remembered when the key went down: */ 1854 if (khints && keysym < 0x100) { 1855 /* low keysyms, ascii, only */ 1856 int ks = (int) keysym; 1857 int ok = 1, lbest = 0, l; 1858 short sbest = -1; 1859 for (l=0; l < found; l++) { 1860 if (kc_f[l] < 0x100) { 1861 int key = (int) kc_f[l]; 1862 if (! keycode_state[key]) { 1863 continue; 1864 } 1865 if (score_hint[ks][key] < 0) { 1866 ok = 0; 1867 break; 1868 } 1869 if (sbest < 0 || score_hint[ks][key] < sbest) { 1870 sbest = score_hint[ks][key]; 1871 lbest = l; 1872 } 1873 } else { 1874 ok = 0; 1875 break; 1876 } 1877 } 1878 if (ok && sbest != -1) { 1879 Kc_f = kc_f[lbest]; 1880 } 1881 if (debug_keyboard && Kc_f != -1) { 1882 fprintf(stderr, " UP: found via score_hint, s/l=%d/%d\n", 1883 sbest, lbest); 1884 } 1885 } 1886 1887 /* next look at our list of recently pressed down keys */ 1888 if (Kc_f == -1) { 1889 for (i=klast-1; i>=0; i--) { 1890 /* 1891 * some people type really fast and leave 1892 * lots of keys down before releasing 1893 * them. this gives problem on weird 1894 * qwerty+dvorak keymappings where each 1895 * alpha character is on TWO keys. 1896 */ 1897 if (keysym == Ks_last_down[i]) { 1898 int l; 1899 for (l=0; l < found; l++) { 1900 if (Kc_last_down[i] == kc_f[l]) { 1901 int key = (int) kc_f[l]; 1902 if (keycode_state[key]) { 1903 Kc_f = Kc_last_down[i]; 1904 Kc_loc = i; 1905 break; 1906 } 1907 } 1908 } 1909 } 1910 if (Kc_f != -1) { 1911 break; 1912 } 1913 } 1914 if (debug_keyboard && Kc_f != -1) { 1915 fprintf(stderr, " UP: found via klast, i=%d\n", Kc_loc); 1916 } 1917 } 1918 1919 /* next just check for "best" one that is down */ 1920 if (Kc_f == -1 && anydown) { 1921 int l; 1922 int best = -1, lbest = 0; 1923 /* 1924 * If it is already down, that is 1925 * a great hint. Use it. 1926 * 1927 * note: keycode_state is internal and 1928 * ignores someone pressing keys on the 1929 * physical display (but is updated 1930 * periodically to clean out stale info). 1931 */ 1932 for (l=0; l < found; l++) { 1933 int key = (int) kc_f[l]; 1934 int j, jmatch = -1; 1935 1936 if (! keycode_state[key]) { 1937 continue; 1938 } 1939 /* break ties based on lowest XKeycodeToKeysym index */ 1940 for (j=0; j<8; j++) { 1941 KeySym ks = XKeycodeToKeysym(dpy, kc_f[l], j); 1942 if (ks != NoSymbol && ks == keysym) { 1943 jmatch = j; 1944 break; 1945 } 1946 } 1947 if (jmatch == -1) { 1948 continue; 1949 } 1950 if (best == -1 || jmatch < best) { 1951 best = jmatch; 1952 lbest = l; 1953 } 1954 } 1955 if (best != -1) { 1956 Kc_f = kc_f[lbest]; 1957 } 1958 if (debug_keyboard && Kc_f != -1) { 1959 fprintf(stderr, " UP: found via downlist, l=%d\n", lbest); 1960 } 1961 } 1962 1963 /* next, use the first one found that is down */ 1964 if (Kc_f == -1) { 1965 int l; 1966 for (l=0; l < found; l++) { 1967 int key = (int) kc_f[l]; 1968 if (keycode_state[key]) { 1969 Kc_f = kc_f[l]; 1970 break; 1971 } 1972 } 1973 if (debug_keyboard && Kc_f != -1) { 1974 fprintf(stderr, " UP: set to first one down, kc_f[%d]!!\n", l); 1975 } 1976 } 1977 1978 /* last, use the first one found */ 1979 if (Kc_f == -1) { 1980 /* hope for the best... XXX check mods */ 1981 Kc_f = kc_f[0]; 1982 if (debug_keyboard && Kc_f != -1) { 1983 fprintf(stderr, " UP: set to first one at all, kc_f[0]!!\n"); 1984 } 1985 } 1986 } 1987 } else { 1988 Kc_f = kc_f[0]; 1989 Grp_f = grp_f[0]; 1990 Lvl_f = lvl_f[0]; 1991 state = state_f[0]; 1992 } 1993 1994 if (debug_keyboard && found > 1) { 1995 int l; 1996 char *str; 1997 fprintf(stderr, " *** found more than one keycode: "); 1998 for (l = 0; l < found; l++) { 1999 fprintf(stderr, "%03d ", kc_f[l]); 2000 } 2001 for (l = 0; l < found; l++) { 2002 str = XKeysymToString(XKeycodeToKeysym(dpy,kc_f[l],0)); 2003 fprintf(stderr, " \"%s\"", str ? str : "null"); 2004 } 2005 fprintf(stderr, ", picked this one: %03d (last down: %03d)\n", 2006 Kc_f, Kc_last_down[0]); 2007 } 2008 2009 if (sloppy_keys) { 2010 int new_kc; 2011 if (sloppy_key_check(Kc_f, down, keysym, &new_kc)) { 2012 Kc_f = new_kc; 2013 } 2014 } 2015 2016 if (down) { 2017 /* 2018 * need to set up the mods for tweaking and other workarounds 2019 */ 2020 int needmods[8], sentmods[8], Ilist[8], keystate[256]; 2021 int involves_multi_key, shift_is_down; 2022 int i, j, b, curr, need; 2023 unsigned int ms; 2024 KeySym ks; 2025 Bool dn; 2026 2027 /* remember these to aid the subsequent up case: */ 2028 for (i=KLAST-1; i >= 1; i--) { 2029 Ks_last_down[i] = Ks_last_down[i-1]; 2030 Kc_last_down[i] = Kc_last_down[i-1]; 2031 } 2032 Ks_last_down[0] = keysym; 2033 Kc_last_down[0] = Kc_f; 2034 2035 if (! got_kbstate) { 2036 /* get the current modifier state if we haven't yet */ 2037 XkbGetState(dpy, XkbUseCoreKbd, &kbstate); 2038 got_kbstate = 1; 2039 } 2040 2041 /* 2042 * needmods[] whether or not that modifier bit needs 2043 * something done to it. 2044 * < 0 means no, 2045 * 0 means needs to go up. 2046 * 1 means needs to go down. 2047 * 2048 * -1, -2, -3 are used for debugging info to indicate 2049 * why nothing needs to be done with the modifier, see below. 2050 * 2051 * sentmods[] is the corresponding keycode to use 2052 * to achieve the needmods[] requirement for the bit. 2053 */ 2054 2055 for (i=0; i<8; i++) { 2056 needmods[i] = -1; 2057 sentmods[i] = 0; 2058 } 2059 2060 /* 2061 * Loop over the 8 modifier bits and check if the current 2062 * setting is what we need it to be or whether it should 2063 * be changed (by us sending some keycode event) 2064 * 2065 * If nothing needs to be done to it record why: 2066 * -1 the modifier bit is ignored. 2067 * -2 the modifier bit is ignored, but is correct anyway. 2068 * -3 the modifier bit is correct. 2069 */ 2070 2071 b = 0x1; 2072 for (i=0; i<8; i++) { 2073 curr = b & kbstate.mods; 2074 need = b & state; 2075 2076 if (! (b & xkbignore[Kc_f][Grp_f][Lvl_f])) { 2077 /* irrelevant modifier bit */ 2078 needmods[i] = -1; 2079 if (curr == need) needmods[i] = -2; 2080 } else if (curr == need) { 2081 /* already correct */ 2082 needmods[i] = -3; 2083 } else if (! curr && need) { 2084 /* need it down */ 2085 needmods[i] = 1; 2086 } else if (curr && ! need) { 2087 /* need it up */ 2088 needmods[i] = 0; 2089 } 2090 2091 b = b << 1; 2092 } 2093 2094 /* 2095 * Again we dynamically probe the X server for information, 2096 * this time for the state of all the keycodes. Useful 2097 * info, and evidently is not too slow... 2098 */ 2099 get_keystate(keystate); 2100 2101 /* 2102 * We try to determine if Shift is down (since that can 2103 * screw up ISO_Level3_Shift manipulations). 2104 */ 2105 shift_is_down = 0; 2106 2107 for (kc = kc_min; kc <= kc_max; kc++) { 2108 if (skipkeycode[kc] && debug_keyboard) { 2109 fprintf(stderr, " xxx skipping keycode: " 2110 "%d\n", kc); 2111 } 2112 if (skipkeycode[kc]) { 2113 continue; 2114 } 2115 if (shift_keys[kc] && keystate[kc]) { 2116 shift_is_down = kc; 2117 break; 2118 } 2119 } 2120 2121 /* 2122 * Now loop over the modifier bits and try to deduce the 2123 * keycode presses/release require to match the desired 2124 * state. 2125 */ 2126 for (i=0; i<8; i++) { 2127 if (needmods[i] < 0 && debug_keyboard > 1) { 2128 int k = -needmods[i] - 1; 2129 char *words[] = {"ignorable", 2130 "bitset+ignorable", "bitset"}; 2131 fprintf(stderr, " +++ needmods: mod=%d is " 2132 "OK (%s)\n", i, words[k]); 2133 } 2134 if (needmods[i] < 0) { 2135 continue; 2136 } 2137 2138 b = 1 << i; 2139 2140 if (debug_keyboard > 1) { 2141 fprintf(stderr, " +++ needmods: mod=%d %s " 2142 "need it to be: %d %s\n", i, bitprint(b, 8), 2143 needmods[i], needmods[i] ? "down" : "up"); 2144 } 2145 2146 /* 2147 * Again, an inefficient loop, this time just 2148 * looking for modifiers... 2149 * 2150 * note the use of kc_vec to prefer XK_ISO_Level3_Shift 2151 * over XK_Mode_switch. 2152 */ 2153 for (kci = kc_min; kci <= kc_max; kci++) { 2154 for (grp = 0; grp < grp_max+1; grp++) { 2155 for (lvl = 0; lvl < lvl_max+1; lvl++) { 2156 int skip = 1, dbmsg = 0; 2157 2158 kc = kc_vec[kci]; 2159 2160 ms = xkbmodifiers[kc][grp][lvl]; 2161 if (! ms || ms != (unsigned int) b) { 2162 continue; 2163 } 2164 2165 if (skipkeycode[kc] && debug_keyboard) { 2166 fprintf(stderr, " xxx skipping keycode:" 2167 " %d G%d/L%d\n", kc, grp+1, lvl+1); 2168 } 2169 if (skipkeycode[kc]) { 2170 continue; 2171 } 2172 2173 ks = xkbkeysyms[kc][grp][lvl]; 2174 if (! ks) { 2175 continue; 2176 } 2177 2178 if (ks == XK_Shift_L) { 2179 skip = 0; 2180 } else if (ks == XK_Shift_R) { 2181 skip = 0; 2182 } else if (ks == XK_Mode_switch) { 2183 skip = 0; 2184 } else if (ks == XK_ISO_Level3_Shift) { 2185 skip = 0; 2186 } 2187 2188 if (watch_capslock && kbstate.locked_mods & LockMask) { 2189 if (keysym >= 'A' && keysym <= 'Z') { 2190 if (ks == XK_Shift_L || ks == XK_Shift_R) { 2191 if (debug_keyboard > 1) { 2192 fprintf(stderr, " A-Z caplock skip Shift\n"); 2193 } 2194 skip = 1; 2195 } else if (ks == XK_Caps_Lock) { 2196 if (debug_keyboard > 1) { 2197 fprintf(stderr, " A-Z caplock noskip CapsLock\n"); 2198 } 2199 skip = 0; 2200 } 2201 } 2202 } 2203 /* 2204 * Alt, Meta, Control, Super, 2205 * Hyper, Num, Caps are skipped. 2206 * 2207 * XXX need more work on Locks, 2208 * and non-standard modifiers. 2209 * (e.g. XF86_Next_VMode using 2210 * Ctrl+Alt) 2211 */ 2212 if (debug_keyboard > 1) { 2213 char *str = XKeysymToString(ks); 2214 int kt = keystate[kc]; 2215 fprintf(stderr, " === for mod=%s " 2216 "found kc=%03d/G%d/L%d it is %d " 2217 "%s skip=%d (%s)\n", bitprint(b,8), 2218 kc, grp+1, lvl+1, kt, kt ? 2219 "down" : "up ", skip, str ? 2220 str : "null"); 2221 } 2222 2223 if (! skip && needmods[i] != 2224 keystate[kc] && sentmods[i] == 0) { 2225 sentmods[i] = kc; 2226 dbmsg = 1; 2227 } 2228 2229 if (debug_keyboard > 1 && dbmsg) { 2230 int nm = needmods[i]; 2231 fprintf(stderr, " >>> we choose " 2232 "kc=%03d=0x%02x to change it to: " 2233 "%d %s\n", kc, kc, nm, nm ? 2234 "down" : "up"); 2235 } 2236 2237 } 2238 } 2239 } 2240 } 2241 for (i=0; i<8; i++) { 2242 /* 2243 * reverse order is useful for tweaking 2244 * ISO_Level3_Shift before Shift, but assumes they 2245 * are in that order (i.e. Shift is first bit). 2246 */ 2247 int reverse = 1; 2248 if (reverse) { 2249 Ilist[i] = 7 - i; 2250 } else { 2251 Ilist[i] = i; 2252 } 2253 } 2254 2255 /* 2256 * check to see if Multi_key is bound to one of the Mods 2257 * we have to tweak 2258 */ 2259 involves_multi_key = 0; 2260 for (j=0; j<8; j++) { 2261 i = Ilist[j]; 2262 if (sentmods[i] == 0) continue; 2263 dn = (Bool) needmods[i]; 2264 if (!dn) continue; 2265 if (multi_key[sentmods[i]]) { 2266 involves_multi_key = i+1; 2267 } 2268 } 2269 2270 if (involves_multi_key && shift_is_down && needmods[0] < 0) { 2271 /* 2272 * Workaround for Multi_key and shift. 2273 * Assumes Shift is bit 1 (needmods[0]) 2274 */ 2275 if (debug_keyboard) { 2276 fprintf(stderr, " ^^^ trying to avoid " 2277 "inadvertent Multi_key from Shift " 2278 "(doing %03d up now)\n", shift_is_down); 2279 } 2280 XTestFakeKeyEvent_wr(dpy, shift_is_down, False, 2281 CurrentTime); 2282 } else { 2283 involves_multi_key = 0; 2284 } 2285 2286 for (j=0; j<8; j++) { 2287 /* do the Mod ups */ 2288 i = Ilist[j]; 2289 if (sentmods[i] == 0) continue; 2290 dn = (Bool) needmods[i]; 2291 if (dn) continue; 2292 XTestFakeKeyEvent_wr(dpy, sentmods[i], dn, CurrentTime); 2293 } 2294 for (j=0; j<8; j++) { 2295 /* next, do the Mod downs */ 2296 i = Ilist[j]; 2297 if (sentmods[i] == 0) continue; 2298 dn = (Bool) needmods[i]; 2299 if (!dn) continue; 2300 XTestFakeKeyEvent_wr(dpy, sentmods[i], dn, CurrentTime); 2301 } 2302 2303 if (involves_multi_key) { 2304 /* 2305 * Reverse workaround for Multi_key and shift. 2306 */ 2307 if (debug_keyboard) { 2308 fprintf(stderr, " vvv trying to avoid " 2309 "inadvertent Multi_key from Shift " 2310 "(doing %03d down now)\n", shift_is_down); 2311 } 2312 XTestFakeKeyEvent_wr(dpy, shift_is_down, True, 2313 CurrentTime); 2314 } 2315 2316 /* 2317 * With the above modifier work done, send the actual keycode: 2318 */ 2319 XTestFakeKeyEvent_wr(dpy, Kc_f, (Bool) down, CurrentTime); 2320 2321 /* 2322 * Now undo the modifier work: 2323 */ 2324 for (j=7; j>=0; j--) { 2325 /* reverse Mod downs we did */ 2326 i = Ilist[j]; 2327 if (sentmods[i] == 0) continue; 2328 dn = (Bool) needmods[i]; 2329 if (!dn) continue; 2330 XTestFakeKeyEvent_wr(dpy, sentmods[i], !dn, 2331 CurrentTime); 2332 } 2333 for (j=7; j>=0; j--) { 2334 /* finally reverse the Mod ups we did */ 2335 i = Ilist[j]; 2336 if (sentmods[i] == 0) continue; 2337 dn = (Bool) needmods[i]; 2338 if (dn) continue; 2339 XTestFakeKeyEvent_wr(dpy, sentmods[i], !dn, 2340 CurrentTime); 2341 } 2342 2343 } else { /* for up case, hopefully just need to pop it up: */ 2344 2345 XTestFakeKeyEvent_wr(dpy, Kc_f, (Bool) down, CurrentTime); 2346 } 2347 X_UNLOCK; 2348 } 2349 #endif 2350 2351 /* 2352 * For tweaking modifiers wrt the Alt-Graph key, etc. 2353 */ 2354 #define LEFTSHIFT 1 2355 #define RIGHTSHIFT 2 2356 #define ALTGR 4 2357 static char mod_state = 0; 2358 2359 static char modifiers[0x100]; 2360 static KeyCode keycodes[0x100]; 2361 static KeyCode left_shift_code, right_shift_code, altgr_code, iso_level3_code; 2362 2363 /* workaround for X11R5, Latin 1 only */ 2364 #ifndef XConvertCase 2365 #define XConvertCase(sym, lower, upper) \ 2366 *(lower) = sym; \ 2367 *(upper) = sym; \ 2368 if (sym >> 8 == 0) { \ 2369 if ((sym >= XK_A) && (sym <= XK_Z)) \ 2370 *(lower) += (XK_a - XK_A); \ 2371 else if ((sym >= XK_a) && (sym <= XK_z)) \ 2372 *(upper) -= (XK_a - XK_A); \ 2373 else if ((sym >= XK_Agrave) && (sym <= XK_Odiaeresis)) \ 2374 *(lower) += (XK_agrave - XK_Agrave); \ 2375 else if ((sym >= XK_agrave) && (sym <= XK_odiaeresis)) \ 2376 *(upper) -= (XK_agrave - XK_Agrave); \ 2377 else if ((sym >= XK_Ooblique) && (sym <= XK_Thorn)) \ 2378 *(lower) += (XK_oslash - XK_Ooblique); \ 2379 else if ((sym >= XK_oslash) && (sym <= XK_thorn)) \ 2380 *(upper) -= (XK_oslash - XK_Ooblique); \ 2381 } 2382 #endif 2383 2384 char *short_kmbcf(char *str) { 2385 int i, saw_k = 0, saw_m = 0, saw_b = 0, saw_c = 0, saw_f = 0, n = 10; 2386 char *p, tmp[10]; 2387 2388 for (i=0; i<n; i++) { 2389 tmp[i] = '\0'; 2390 } 2391 2392 p = str; 2393 i = 0; 2394 while (*p) { 2395 if ((*p == 'K' || *p == 'k') && !saw_k) { 2396 tmp[i++] = 'K'; 2397 saw_k = 1; 2398 } else if ((*p == 'M' || *p == 'm') && !saw_m) { 2399 tmp[i++] = 'M'; 2400 saw_m = 1; 2401 } else if ((*p == 'B' || *p == 'b') && !saw_b) { 2402 tmp[i++] = 'B'; 2403 saw_b = 1; 2404 } else if ((*p == 'C' || *p == 'c') && !saw_c) { 2405 tmp[i++] = 'C'; 2406 saw_c = 1; 2407 } else if ((*p == 'F' || *p == 'f') && !saw_f) { 2408 tmp[i++] = 'F'; 2409 saw_f = 1; 2410 } 2411 p++; 2412 } 2413 return(strdup(tmp)); 2414 } 2415 2416 void initialize_allowed_input(void) { 2417 char *str; 2418 2419 if (allowed_input_normal) { 2420 free(allowed_input_normal); 2421 allowed_input_normal = NULL; 2422 } 2423 if (allowed_input_view_only) { 2424 free(allowed_input_view_only); 2425 allowed_input_view_only = NULL; 2426 } 2427 2428 if (! allowed_input_str) { 2429 allowed_input_normal = strdup("KMBCF"); 2430 allowed_input_view_only = strdup(""); 2431 } else { 2432 char *p, *str = strdup(allowed_input_str); 2433 p = strchr(str, ','); 2434 if (p) { 2435 allowed_input_view_only = strdup(p+1); 2436 *p = '\0'; 2437 allowed_input_normal = strdup(str); 2438 } else { 2439 allowed_input_normal = strdup(str); 2440 allowed_input_view_only = strdup(""); 2441 } 2442 free(str); 2443 } 2444 2445 /* shorten them */ 2446 str = short_kmbcf(allowed_input_normal); 2447 free(allowed_input_normal); 2448 allowed_input_normal = str; 2449 2450 str = short_kmbcf(allowed_input_view_only); 2451 free(allowed_input_view_only); 2452 allowed_input_view_only = str; 2453 2454 if (screen) { 2455 rfbClientIteratorPtr iter; 2456 rfbClientPtr cl; 2457 2458 iter = rfbGetClientIterator(screen); 2459 while( (cl = rfbClientIteratorNext(iter)) ) { 2460 ClientData *cd = (ClientData *) cl->clientData; 2461 2462 if (! cd) { 2463 continue; 2464 } 2465 #if 0 2466 rfbLog("cd: %p\n", cd); 2467 rfbLog("cd->input: %s\n", cd->input); 2468 rfbLog("cd->login_viewonly: %d\n", cd->login_viewonly); 2469 rfbLog("allowed_input_view_only: %s\n", allowed_input_view_only); 2470 #endif 2471 2472 if (cd->input[0] == '=') { 2473 ; /* custom setting */ 2474 } else if (cd->login_viewonly) { 2475 if (*allowed_input_view_only != '\0') { 2476 cl->viewOnly = FALSE; 2477 cd->input[0] = '\0'; 2478 strncpy(cd->input, 2479 allowed_input_view_only, CILEN); 2480 } else { 2481 cl->viewOnly = TRUE; 2482 } 2483 } else { 2484 if (allowed_input_normal) { 2485 cd->input[0] = '\0'; 2486 strncpy(cd->input, 2487 allowed_input_normal, CILEN); 2488 } 2489 } 2490 } 2491 rfbReleaseClientIterator(iter); 2492 } 2493 } 2494 2495 void initialize_modtweak(void) { 2496 #if NO_X11 2497 RAWFB_RET_VOID 2498 return; 2499 #else 2500 KeySym keysym, *keymap; 2501 int i, j, minkey, maxkey, syms_per_keycode; 2502 int use_lowest_index = 0; 2503 2504 if (use_xkb_modtweak) { 2505 initialize_xkb_modtweak(); 2506 return; 2507 } 2508 memset(modifiers, -1, sizeof(modifiers)); 2509 for (i=0; i<0x100; i++) { 2510 keycodes[i] = NoSymbol; 2511 } 2512 2513 RAWFB_RET_VOID 2514 2515 if (getenv("MODTWEAK_LOWEST")) { 2516 use_lowest_index = 1; 2517 } 2518 2519 X_LOCK; 2520 XDisplayKeycodes(dpy, &minkey, &maxkey); 2521 2522 keymap = XGetKeyboardMapping(dpy, minkey, (maxkey - minkey + 1), 2523 &syms_per_keycode); 2524 2525 /* handle alphabetic char with only one keysym (no upper + lower) */ 2526 for (i = minkey; i <= maxkey; i++) { 2527 KeySym lower, upper; 2528 /* 2nd one */ 2529 keysym = keymap[(i - minkey) * syms_per_keycode + 1]; 2530 if (keysym != NoSymbol) { 2531 continue; 2532 } 2533 /* 1st one */ 2534 keysym = keymap[(i - minkey) * syms_per_keycode + 0]; 2535 if (keysym == NoSymbol) { 2536 continue; 2537 } 2538 XConvertCase(keysym, &lower, &upper); 2539 if (lower != upper) { 2540 keymap[(i - minkey) * syms_per_keycode + 0] = lower; 2541 keymap[(i - minkey) * syms_per_keycode + 1] = upper; 2542 } 2543 } 2544 for (i = minkey; i <= maxkey; i++) { 2545 if (debug_keyboard) { 2546 if (i == minkey) { 2547 rfbLog("initialize_modtweak: keycode -> " 2548 "keysyms mapping info:\n"); 2549 } 2550 fprintf(stderr, " %03d ", i); 2551 } 2552 for (j = 0; j < syms_per_keycode; j++) { 2553 if (debug_keyboard) { 2554 char *sym; 2555 #if 0 2556 sym =XKeysymToString(XKeycodeToKeysym(dpy,i,j)); 2557 #else 2558 keysym = keymap[(i-minkey)*syms_per_keycode+j]; 2559 sym = XKeysymToString(keysym); 2560 #endif 2561 fprintf(stderr, "%-18s ", sym ? sym : "null"); 2562 if (j == syms_per_keycode - 1) { 2563 fprintf(stderr, "\n"); 2564 } 2565 } 2566 if (j >= 4) { 2567 /* 2568 * Something wacky in the keymapping. 2569 * Ignore these non Shift/AltGr chords 2570 * for now... n.b. we try to automatically 2571 * switch to -xkb for this case. 2572 */ 2573 continue; 2574 } 2575 keysym = keymap[ (i - minkey) * syms_per_keycode + j ]; 2576 if ( keysym >= ' ' && keysym < 0x100 2577 && i == XKeysymToKeycode(dpy, keysym) ) { 2578 if (use_lowest_index && keycodes[keysym] != NoSymbol) { 2579 continue; 2580 } 2581 keycodes[keysym] = i; 2582 modifiers[keysym] = j; 2583 } 2584 } 2585 } 2586 2587 left_shift_code = XKeysymToKeycode(dpy, XK_Shift_L); 2588 right_shift_code = XKeysymToKeycode(dpy, XK_Shift_R); 2589 altgr_code = XKeysymToKeycode(dpy, XK_Mode_switch); 2590 iso_level3_code = NoSymbol; 2591 #ifdef XK_ISO_Level3_Shift 2592 iso_level3_code = XKeysymToKeycode(dpy, XK_ISO_Level3_Shift); 2593 #endif 2594 2595 XFree_wr ((void *) keymap); 2596 2597 X_UNLOCK; 2598 #endif /* NO_X11 */ 2599 } 2600 2601 /* 2602 * does the actual tweak: 2603 */ 2604 static void tweak_mod(signed char mod, rfbBool down) { 2605 rfbBool is_shift = mod_state & (LEFTSHIFT|RIGHTSHIFT); 2606 Bool dn = (Bool) down; 2607 KeyCode altgr = altgr_code; 2608 2609 RAWFB_RET_VOID 2610 2611 if (mod < 0) { 2612 if (debug_keyboard) { 2613 rfbLog("tweak_mod: Skip: down=%d index=%d\n", down, 2614 (int) mod); 2615 } 2616 return; 2617 } 2618 if (debug_keyboard) { 2619 rfbLog("tweak_mod: Start: down=%d index=%d mod_state=0x%x" 2620 " is_shift=%d\n", down, (int) mod, (int) mod_state, 2621 is_shift); 2622 } 2623 2624 if (use_iso_level3 && iso_level3_code) { 2625 altgr = iso_level3_code; 2626 } 2627 2628 X_LOCK; 2629 if (is_shift && mod != 1) { 2630 if (mod_state & LEFTSHIFT) { 2631 XTestFakeKeyEvent_wr(dpy, left_shift_code, !dn, CurrentTime); 2632 } 2633 if (mod_state & RIGHTSHIFT) { 2634 XTestFakeKeyEvent_wr(dpy, right_shift_code, !dn, CurrentTime); 2635 } 2636 } 2637 if ( ! is_shift && mod == 1 ) { 2638 XTestFakeKeyEvent_wr(dpy, left_shift_code, dn, CurrentTime); 2639 } 2640 if ( altgr && (mod_state & ALTGR) && mod != 2 ) { 2641 XTestFakeKeyEvent_wr(dpy, altgr, !dn, CurrentTime); 2642 } 2643 if ( altgr && ! (mod_state & ALTGR) && mod == 2 ) { 2644 XTestFakeKeyEvent_wr(dpy, altgr, dn, CurrentTime); 2645 } 2646 X_UNLOCK; 2647 2648 if (debug_keyboard) { 2649 rfbLog("tweak_mod: Finish: down=%d index=%d mod_state=0x%x" 2650 " is_shift=%d\n", down, (int) mod, (int) mod_state, 2651 is_shift); 2652 } 2653 } 2654 2655 /* 2656 * tweak the modifier under -modtweak 2657 */ 2658 static void modifier_tweak_keyboard(rfbBool down, rfbKeySym keysym, 2659 rfbClientPtr client) { 2660 #if NO_X11 2661 RAWFB_RET_VOID 2662 if (!down || !keysym || !client) {} 2663 return; 2664 #else 2665 KeyCode k; 2666 int tweak = 0; 2667 2668 RAWFB_RET_VOID 2669 2670 if (use_xkb_modtweak) { 2671 xkb_tweak_keyboard(down, keysym, client); 2672 return; 2673 } 2674 if (debug_keyboard) { 2675 rfbLog("modifier_tweak_keyboard: %s keysym=0x%x\n", 2676 down ? "down" : "up", (int) keysym); 2677 } 2678 2679 #define ADJUSTMOD(sym, state) \ 2680 if (keysym == sym) { \ 2681 if (down) { \ 2682 mod_state |= state; \ 2683 } else { \ 2684 mod_state &= ~state; \ 2685 } \ 2686 } 2687 2688 ADJUSTMOD(XK_Shift_L, LEFTSHIFT) 2689 ADJUSTMOD(XK_Shift_R, RIGHTSHIFT) 2690 ADJUSTMOD(XK_Mode_switch, ALTGR) 2691 2692 if ( down && keysym >= ' ' && keysym < 0x100 ) { 2693 unsigned int state = 0; 2694 tweak = 1; 2695 if (watch_capslock && keysym >= 'A' && keysym <= 'Z') { 2696 X_LOCK; 2697 state = mask_state(); 2698 X_UNLOCK; 2699 } 2700 if (state & LockMask) { 2701 /* capslock set for A-Z, so no tweak */ 2702 X_LOCK; 2703 k = XKeysymToKeycode(dpy, (KeySym) keysym); 2704 X_UNLOCK; 2705 tweak = 0; 2706 } else { 2707 tweak_mod(modifiers[keysym], True); 2708 k = keycodes[keysym]; 2709 } 2710 } else { 2711 X_LOCK; 2712 k = XKeysymToKeycode(dpy, (KeySym) keysym); 2713 X_UNLOCK; 2714 } 2715 if (k == NoSymbol && add_keysyms && ! IsModifierKey(keysym)) { 2716 int new_kc = add_keysym(keysym); 2717 if (new_kc) { 2718 k = new_kc; 2719 } 2720 } 2721 2722 if (sloppy_keys) { 2723 int new_kc; 2724 if (sloppy_key_check((int) k, down, keysym, &new_kc)) { 2725 k = (KeyCode) new_kc; 2726 } 2727 } 2728 2729 if (debug_keyboard) { 2730 char *str = XKeysymToString(keysym); 2731 rfbLog("modifier_tweak_keyboard: KeySym 0x%x \"%s\" -> " 2732 "KeyCode 0x%x%s\n", (int) keysym, str ? str : "null", 2733 (int) k, k ? "" : " *ignored*"); 2734 } 2735 if ( k != NoSymbol ) { 2736 X_LOCK; 2737 XTestFakeKeyEvent_wr(dpy, k, (Bool) down, CurrentTime); 2738 X_UNLOCK; 2739 } 2740 2741 if ( tweak ) { 2742 tweak_mod(modifiers[keysym], False); 2743 } 2744 #endif /* NO_X11 */ 2745 } 2746 2747 void initialize_keyboard_and_pointer(void) { 2748 2749 #ifdef MACOSX 2750 if (macosx_console) { 2751 initialize_remap(remap_file); 2752 initialize_pointer_map(pointer_remap); 2753 } 2754 #endif 2755 2756 RAWFB_RET_VOID 2757 2758 if (use_modifier_tweak) { 2759 initialize_modtweak(); 2760 } 2761 2762 initialize_remap(remap_file); 2763 initialize_pointer_map(pointer_remap); 2764 2765 X_LOCK; 2766 clear_modifiers(1); 2767 if (clear_mods == 1) { 2768 clear_modifiers(0); 2769 } 2770 if (clear_mods == 3) { 2771 clear_locks(); 2772 } 2773 X_UNLOCK; 2774 } 2775 2776 void get_allowed_input(rfbClientPtr client, allowed_input_t *input) { 2777 ClientData *cd; 2778 char *str; 2779 2780 input->keystroke = 0; 2781 input->motion = 0; 2782 input->button = 0; 2783 input->clipboard = 0; 2784 input->files = 0; 2785 2786 if (! client) { 2787 input->keystroke = 1; 2788 input->motion = 1; 2789 input->button = 1; 2790 input->clipboard = 1; 2791 input->files = 1; 2792 return; 2793 } 2794 2795 cd = (ClientData *) client->clientData; 2796 2797 if (! cd) { 2798 return; 2799 } 2800 2801 if (cd->input[0] != '-') { 2802 str = cd->input; 2803 } else if (client->viewOnly) { 2804 if (allowed_input_view_only) { 2805 str = allowed_input_view_only; 2806 } else { 2807 str = ""; 2808 } 2809 } else { 2810 if (allowed_input_normal) { 2811 str = allowed_input_normal; 2812 } else { 2813 str = "KMBCF"; 2814 } 2815 } 2816 if (0) fprintf(stderr, "GAI: %s - %s\n", str, cd->input); 2817 2818 while (*str) { 2819 if (*str == 'K') { 2820 input->keystroke = 1; 2821 } else if (*str == 'M') { 2822 input->motion = 1; 2823 } else if (*str == 'B') { 2824 input->button = 1; 2825 } else if (*str == 'C') { 2826 input->clipboard = 1; 2827 } else if (*str == 'F') { 2828 input->files = 1; 2829 } 2830 str++; 2831 } 2832 } 2833 2834 static void apply_remap(rfbKeySym *keysym, int *isbutton) { 2835 if (keyremaps) { 2836 keyremap_t *remap = keyremaps; 2837 while (remap != NULL) { 2838 if (remap->before == *keysym) { 2839 *keysym = remap->after; 2840 *isbutton = remap->isbutton; 2841 if (debug_keyboard) { 2842 char *str1, *str2; 2843 X_LOCK; 2844 str1 = XKeysymToString(remap->before); 2845 str2 = XKeysymToString(remap->after); 2846 rfbLog("keyboard(): remapping keysym: " 2847 "0x%x \"%s\" -> 0x%x \"%s\"\n", 2848 (int) remap->before, 2849 str1 ? str1 : "null", 2850 (int) remap->after, 2851 remap->isbutton ? "button" : 2852 str2 ? str2 : "null"); 2853 X_UNLOCK; 2854 } 2855 break; 2856 } 2857 remap = remap->next; 2858 } 2859 } 2860 } 2861 2862 /* for -pipeinput mode */ 2863 static void pipe_keyboard(rfbBool down, rfbKeySym keysym, rfbClientPtr client) { 2864 int can_input = 0, uid = 0, isbutton = 0; 2865 allowed_input_t input; 2866 char *name; 2867 ClientData *cd = (ClientData *) client->clientData; 2868 2869 apply_remap(&keysym, &isbutton); 2870 2871 if (isbutton) { 2872 int mask, button = (int) keysym; 2873 int x = cursor_x, y = cursor_y; 2874 char *b, bstr[32]; 2875 2876 if (!down) { 2877 return; 2878 } 2879 if (debug_keyboard) { 2880 rfbLog("keyboard(): remapping keystroke to button %d" 2881 " click\n", button); 2882 } 2883 dtime0(&last_key_to_button_remap_time); 2884 2885 /* 2886 * This in principle can be a little dicey... i.e. even 2887 * remap the button click to keystroke sequences! 2888 * Usually just will simulate the button click. 2889 */ 2890 2891 /* loop over possible multiclicks: Button123 */ 2892 sprintf(bstr, "%d", button); 2893 b = bstr; 2894 while (*b != '\0') { 2895 char t[2]; 2896 int butt; 2897 t[0] = *b; 2898 t[1] = '\0'; 2899 if (sscanf(t, "%d", &butt) == 1) { 2900 mask = 1<<(butt-1); 2901 pointer_event(mask, x, y, client); 2902 mask = 0; 2903 pointer_event(mask, x, y, client); 2904 } 2905 b++; 2906 } 2907 return; 2908 } 2909 2910 if (pipeinput_int == PIPEINPUT_VID) { 2911 v4l_key_command(down, keysym, client); 2912 } else if (pipeinput_int == PIPEINPUT_CONSOLE) { 2913 console_key_command(down, keysym, client); 2914 } else if (pipeinput_int == PIPEINPUT_UINPUT) { 2915 uinput_key_command(down, keysym, client); 2916 } else if (pipeinput_int == PIPEINPUT_MACOSX) { 2917 macosx_key_command(down, keysym, client); 2918 } else if (pipeinput_int == PIPEINPUT_VNC) { 2919 vnc_reflect_send_key((uint32_t) keysym, down); 2920 } 2921 if (pipeinput_fh == NULL) { 2922 return; 2923 } 2924 2925 if (! view_only) { 2926 get_allowed_input(client, &input); 2927 if (input.keystroke) { 2928 can_input = 1; /* XXX distinguish later */ 2929 } 2930 } 2931 if (cd) { 2932 uid = cd->uid; 2933 } 2934 if (! can_input) { 2935 uid = -uid; 2936 } 2937 2938 X_LOCK; 2939 name = XKeysymToString(keysym); 2940 X_UNLOCK; 2941 2942 fprintf(pipeinput_fh, "Keysym %d %d %u %s %s\n", uid, down, 2943 keysym, name ? name : "null", down ? "KeyPress" : "KeyRelease"); 2944 2945 fflush(pipeinput_fh); 2946 check_pipeinput(); 2947 } 2948 2949 typedef struct keyevent { 2950 rfbKeySym sym; 2951 rfbBool down; 2952 double time; 2953 } keyevent_t; 2954 2955 #define KEY_HIST 256 2956 static int key_history_idx = -1; 2957 static keyevent_t key_history[KEY_HIST]; 2958 2959 double typing_rate(double time_window, int *repeating) { 2960 double dt = 1.0, now = dnow(); 2961 KeySym key = NoSymbol; 2962 int i, idx, cnt = 0, repeat_keys = 0; 2963 2964 if (key_history_idx == -1) { 2965 if (repeating) { 2966 *repeating = 0; 2967 } 2968 return 0.0; 2969 } 2970 if (time_window > 0.0) { 2971 dt = time_window; 2972 } 2973 for (i=0; i<KEY_HIST; i++) { 2974 idx = key_history_idx - i; 2975 if (idx < 0) { 2976 idx += KEY_HIST; 2977 } 2978 if (! key_history[idx].down) { 2979 continue; 2980 } 2981 if (now > key_history[idx].time + dt) { 2982 break; 2983 } 2984 cnt++; 2985 if (key == NoSymbol) { 2986 key = key_history[idx].sym; 2987 repeat_keys = 1; 2988 } else if (key == key_history[idx].sym) { 2989 repeat_keys++; 2990 } 2991 } 2992 2993 if (repeating) { 2994 if (repeat_keys >= 2) { 2995 *repeating = repeat_keys; 2996 } else { 2997 *repeating = 0; 2998 } 2999 } 3000 3001 /* 3002 * n.b. keyrate could seem very high with libvncserver buffering them 3003 * so avoid using small dt. 3004 */ 3005 return ((double) cnt)/dt; 3006 } 3007 3008 int skip_cr_when_scaling(char *mode) { 3009 int got = 0; 3010 3011 if (!scaling) { 3012 return 0; 3013 } 3014 3015 if (scaling_copyrect != scaling_copyrect0) { 3016 /* user override via -scale: */ 3017 if (! scaling_copyrect) { 3018 return 1; 3019 } else { 3020 return 0; 3021 } 3022 } 3023 if (*mode == 's') { 3024 got = got_scrollcopyrect; 3025 } else if (*mode == 'w') { 3026 got = got_wirecopyrect; 3027 } 3028 if (scaling_copyrect || got) { 3029 int lat, rate; 3030 int link = link_rate(&lat, &rate); 3031 if (link == LR_DIALUP) { 3032 return 1; 3033 } else if (rate < 25) { 3034 /* the fill-in of the repair may be too slow */ 3035 return 1; 3036 } else { 3037 return 0; 3038 } 3039 } else { 3040 return 1; 3041 } 3042 } 3043 3044 /* 3045 * key event handler. See the above functions for contortions for 3046 * running under -modtweak. 3047 */ 3048 static rfbClientPtr last_keyboard_client = NULL; 3049 3050 void keyboard(rfbBool down, rfbKeySym keysym, rfbClientPtr client) { 3051 KeyCode k; 3052 int idx, isbutton = 0; 3053 allowed_input_t input; 3054 time_t now = time(NULL); 3055 double tnow; 3056 static int skipped_last_down; 3057 static rfbBool last_down; 3058 static rfbKeySym last_keysym = NoSymbol; 3059 static rfbKeySym max_keyrepeat_last_keysym = NoSymbol; 3060 static double max_keyrepeat_last_time = 0.0; 3061 static double max_keyrepeat_always = -1.0; 3062 3063 if (threads_drop_input) { 3064 return; 3065 } 3066 3067 dtime0(&tnow); 3068 got_keyboard_calls++; 3069 3070 if (debug_keyboard) { 3071 char *str; 3072 X_LOCK; 3073 str = XKeysymToString((KeySym) keysym); 3074 X_UNLOCK; 3075 rfbLog("# keyboard(%s, 0x%x \"%s\") uip=%d %.4f\n", 3076 down ? "down":"up", (int) keysym, str ? str : "null", 3077 unixpw_in_progress, tnow - x11vnc_start); 3078 } 3079 3080 if (keysym <= 0) { 3081 rfbLog("keyboard: skipping 0x0 keysym\n"); 3082 return; 3083 } 3084 3085 if (unixpw_in_progress) { 3086 if (unixpw_denied) { 3087 rfbLog("keyboard: ignoring keystroke 0x%x in " 3088 "unixpw_denied=1 state\n", (int) keysym); 3089 return; 3090 } 3091 if (client != unixpw_client) { 3092 rfbLog("keyboard: skipping other client in unixpw\n"); 3093 return; 3094 } 3095 3096 unixpw_keystroke(down, keysym, 0); 3097 3098 return; 3099 } 3100 3101 if (skip_duplicate_key_events) { 3102 if (keysym == last_keysym && down == last_down) { 3103 if (debug_keyboard) { 3104 rfbLog("skipping dup key event: %d 0x%x\n", 3105 down, keysym); 3106 } 3107 return; 3108 } 3109 } 3110 3111 if (skip_lockkeys) { 3112 /* we don't handle XK_ISO*_Lock or XK_Kana_Lock ... */ 3113 if (keysym == XK_Scroll_Lock || keysym == XK_Num_Lock || 3114 keysym == XK_Caps_Lock || keysym == XK_Shift_Lock) { 3115 if (debug_keyboard) { 3116 rfbLog("skipping lock key event: %d 0x%x\n", 3117 down, keysym); 3118 } 3119 return; 3120 } else if (keysym >= XK_KP_0 && keysym <= XK_KP_9) { 3121 /* ugh this is probably what they meant... assume NumLock. */ 3122 if (debug_keyboard) { 3123 rfbLog("changed KP digit to regular digit: %d 0x%x\n", 3124 down, keysym); 3125 } 3126 keysym = (keysym - XK_KP_0) + XK_0; 3127 } else if (keysym == XK_KP_Decimal) { 3128 if (debug_keyboard) { 3129 rfbLog("changed XK_KP_Decimal to XK_period: %d 0x%x\n", 3130 down, keysym); 3131 } 3132 keysym = XK_period; 3133 } 3134 } 3135 3136 INPUT_LOCK; 3137 3138 last_down = down; 3139 last_keysym = keysym; 3140 last_keyboard_time = tnow; 3141 3142 last_rfb_down = down; 3143 last_rfb_keysym = keysym; 3144 last_rfb_keytime = tnow; 3145 last_rfb_key_accepted = FALSE; 3146 3147 if (key_history_idx == -1) { 3148 for (idx=0; idx<KEY_HIST; idx++) { 3149 key_history[idx].sym = NoSymbol; 3150 key_history[idx].down = FALSE; 3151 key_history[idx].time = 0.0; 3152 } 3153 } 3154 idx = ++key_history_idx; 3155 if (key_history_idx >= KEY_HIST) { 3156 key_history_idx = 0; 3157 idx = 0; 3158 } 3159 key_history[idx].sym = keysym; 3160 key_history[idx].down = down; 3161 key_history[idx].time = tnow; 3162 3163 if (down && (keysym == XK_Alt_L || keysym == XK_Super_L)) { 3164 int i, k, run = 0, ups = 0; 3165 double delay = 1.0; 3166 KeySym ks; 3167 for (i=0; i<16; i++) { 3168 k = idx - i; 3169 if (k < 0) k += KEY_HIST; 3170 if (!key_history[k].down) { 3171 ups++; 3172 continue; 3173 } 3174 ks = key_history[k].sym; 3175 if (key_history[k].time < tnow - delay) { 3176 break; 3177 } else if (ks == keysym && ks == XK_Alt_L) { 3178 run++; 3179 } else if (ks == keysym && ks == XK_Super_L) { 3180 run++; 3181 } else { 3182 break; 3183 } 3184 } 3185 if (ups < 2) { 3186 ; 3187 } else if (run == 3 && keysym == XK_Alt_L) { 3188 rfbLog("3*Alt_L, calling: refresh_screen(0)\n"); 3189 refresh_screen(0); 3190 } else if (run == 4 && keysym == XK_Alt_L) { 3191 rfbLog("4*Alt_L, setting: do_copy_screen\n"); 3192 do_copy_screen = 1; 3193 } else if (run == 5 && keysym == XK_Alt_L) { 3194 ; 3195 } else if (run == 3 && keysym == XK_Super_L) { 3196 rfbLog("3*Super_L, calling: set_xdamage_mark()\n"); 3197 set_xdamage_mark(0, 0, dpy_x, dpy_y); 3198 } else if (run == 4 && keysym == XK_Super_L) { 3199 rfbLog("4*Super_L, calling: check_xrecord_reset()\n"); 3200 check_xrecord_reset(1); 3201 } else if (run == 5 && keysym == XK_Super_L) { 3202 rfbLog("5*Super_L, calling: push_black_screen(0)\n"); 3203 push_black_screen(0); 3204 } 3205 } 3206 3207 #ifdef MAX_KEYREPEAT 3208 if (max_keyrepeat_always < 0.0) { 3209 if (getenv("MAX_KEYREPEAT")) { 3210 max_keyrepeat_always = atof(getenv("MAX_KEYREPEAT")); 3211 } else { 3212 max_keyrepeat_always = 0.0; 3213 } 3214 } 3215 if (max_keyrepeat_always > 0.0) { 3216 max_keyrepeat_time = max_keyrepeat_always; 3217 } 3218 #else 3219 if (0) {max_keyrepeat_always=0;} 3220 #endif 3221 if (!down && skipped_last_down) { 3222 int db = debug_scroll; 3223 if (keysym == max_keyrepeat_last_keysym) { 3224 skipped_last_down = 0; 3225 if (db) rfbLog("--- scroll keyrate skipping 0x%lx %s " 3226 "%.4f %.4f\n", keysym, down ? "down":"up ", 3227 tnow - x11vnc_start, tnow - max_keyrepeat_last_time); 3228 INPUT_UNLOCK; 3229 return; 3230 } 3231 } 3232 if (down && max_keyrepeat_time > 0.0) { 3233 int skip = 0; 3234 int db = debug_scroll; 3235 3236 if (max_keyrepeat_last_keysym != NoSymbol && 3237 max_keyrepeat_last_keysym != keysym) { 3238 ; 3239 } else { 3240 if (tnow < max_keyrepeat_last_time+max_keyrepeat_time) { 3241 skip = 1; 3242 } 3243 } 3244 max_keyrepeat_time = 0.0; 3245 if (skip) { 3246 if (db) rfbLog("--- scroll keyrate skipping 0x%lx %s " 3247 "%.4f %.4f\n", keysym, down ? "down":"up ", 3248 tnow - x11vnc_start, tnow - max_keyrepeat_last_time); 3249 max_keyrepeat_last_keysym = keysym; 3250 skipped_last_down = 1; 3251 INPUT_UNLOCK; 3252 return; 3253 } else { 3254 if (db) rfbLog("--- scroll keyrate KEEPING 0x%lx %s " 3255 "%.4f %.4f\n", keysym, down ? "down":"up ", 3256 tnow - x11vnc_start, tnow - max_keyrepeat_last_time); 3257 } 3258 } 3259 max_keyrepeat_last_keysym = keysym; 3260 max_keyrepeat_last_time = tnow; 3261 skipped_last_down = 0; 3262 last_rfb_key_accepted = TRUE; 3263 3264 if (pipeinput_fh != NULL || pipeinput_int) { 3265 pipe_keyboard(down, keysym, client); /* MACOSX here. */ 3266 if (! pipeinput_tee) { 3267 if (! view_only || raw_fb) { /* raw_fb hack */ 3268 last_keyboard_client = client; 3269 last_event = last_input = now; 3270 last_keyboard_input = now; 3271 3272 last_keysym = keysym; 3273 3274 last_rfb_down = down; 3275 last_rfb_keysym = keysym; 3276 last_rfb_keytime = tnow; 3277 last_rfb_key_injected = dnow(); 3278 3279 got_user_input++; 3280 got_keyboard_input++; 3281 } 3282 INPUT_UNLOCK; 3283 return; 3284 } 3285 } 3286 3287 if (view_only) { 3288 INPUT_UNLOCK; 3289 return; 3290 } 3291 get_allowed_input(client, &input); 3292 if (! input.keystroke) { 3293 INPUT_UNLOCK; 3294 return; 3295 } 3296 3297 track_mod_state(keysym, down, TRUE); /* ignores remaps */ 3298 3299 last_keyboard_client = client; 3300 last_event = last_input = now; 3301 last_keyboard_input = now; 3302 3303 last_keysym = keysym; 3304 3305 last_rfb_down = down; 3306 last_rfb_keysym = keysym; 3307 last_rfb_keytime = tnow; 3308 last_rfb_key_injected = dnow(); 3309 3310 got_user_input++; 3311 got_keyboard_input++; 3312 3313 RAWFB_RET_VOID 3314 3315 3316 apply_remap(&keysym, &isbutton); 3317 3318 if (use_xrecord && ! xrecording && down) { 3319 3320 if (!strcmp(scroll_copyrect, "never")) { 3321 ; 3322 } else if (!strcmp(scroll_copyrect, "mouse")) { 3323 ; 3324 } else if (skip_cr_when_scaling("scroll")) { 3325 ; 3326 } else if (! xrecord_skip_keysym(keysym)) { 3327 snapshot_stack_list(0, 0.25); 3328 xrecord_watch(1, SCR_KEY); 3329 xrecord_set_by_keys = 1; 3330 xrecord_keysym = keysym; 3331 } else { 3332 if (debug_scroll) { 3333 char *str = XKeysymToString(keysym); 3334 rfbLog("xrecord_skip_keysym: %s\n", 3335 str ? str : "NoSymbol"); 3336 } 3337 } 3338 } 3339 3340 if (isbutton) { 3341 int mask, button = (int) keysym; 3342 char *b, bstr[32]; 3343 3344 if (! down) { 3345 INPUT_UNLOCK; 3346 return; /* nothing to send */ 3347 } 3348 if (debug_keyboard) { 3349 rfbLog("keyboard(): remapping keystroke to button %d" 3350 " click\n", button); 3351 } 3352 dtime0(&last_key_to_button_remap_time); 3353 3354 X_LOCK; 3355 /* 3356 * This in principle can be a little dicey... i.e. even 3357 * remap the button click to keystroke sequences! 3358 * Usually just will simulate the button click. 3359 */ 3360 3361 /* loop over possible multiclicks: Button123 */ 3362 sprintf(bstr, "%d", button); 3363 b = bstr; 3364 while (*b != '\0') { 3365 char t[2]; 3366 int butt; 3367 t[0] = *b; 3368 t[1] = '\0'; 3369 if (sscanf(t, "%d", &butt) == 1) { 3370 mask = 1<<(butt-1); 3371 do_button_mask_change(mask, butt); /* down */ 3372 mask = 0; 3373 do_button_mask_change(mask, butt); /* up */ 3374 } 3375 b++; 3376 } 3377 XFlush_wr(dpy); 3378 X_UNLOCK; 3379 INPUT_UNLOCK; 3380 return; 3381 } 3382 3383 if (use_modifier_tweak) { 3384 modifier_tweak_keyboard(down, keysym, client); 3385 X_LOCK; 3386 XFlush_wr(dpy); 3387 X_UNLOCK; 3388 INPUT_UNLOCK; 3389 return; 3390 } 3391 3392 X_LOCK; 3393 3394 k = XKeysymToKeycode(dpy, (KeySym) keysym); 3395 3396 if (k == NoSymbol && add_keysyms && ! IsModifierKey(keysym)) { 3397 int new_kc = add_keysym(keysym); 3398 if (new_kc) { 3399 k = new_kc; 3400 } 3401 } 3402 if (debug_keyboard) { 3403 char *str = XKeysymToString(keysym); 3404 rfbLog("keyboard(): KeySym 0x%x \"%s\" -> KeyCode 0x%x%s\n", 3405 (int) keysym, str ? str : "null", (int) k, 3406 k ? "" : " *ignored*"); 3407 } 3408 3409 if ( k != NoSymbol ) { 3410 XTestFakeKeyEvent_wr(dpy, k, (Bool) down, CurrentTime); 3411 XFlush_wr(dpy); 3412 } 3413 3414 X_UNLOCK; 3415 INPUT_UNLOCK; 3416 } 3417 3418 3419