1 /*
2 Copyright (C) 2002-2010 Karl J. Runge <runge@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 */
get_keystate(int * keystate)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 */
clear_modifiers(int init)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
track_mod_state(rfbKeySym keysym,rfbBool down,rfbBool set)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 */
clear_keys(void)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
clear_locks(void)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
get_autorepeat_state(void)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
get_initial_autorepeat_state(void)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
autorepeat(int restore,int bequiet)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 */
check_add_keysyms(void)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
add_keysym(KeySym keysym)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
delete_keycode(KeyCode kc,int bequiet)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
count_added_keycodes(void)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
delete_added_keycodes(int bequiet)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
add_remap(char * line)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
add_dead_keysyms(char * str)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 */
initialize_remap(char * infile)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
sloppy_key_check(int key,rfbBool down,rfbKeySym keysym,int * new_kc)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 */
initialize_xkb_modtweak(void)972 static void initialize_xkb_modtweak(void) {}
xkb_tweak_keyboard(rfbBool down,rfbKeySym keysym,rfbClientPtr client)973 static void xkb_tweak_keyboard(rfbBool down, rfbKeySym keysym,
974 rfbClientPtr client) {
975 if (!client || !down || !keysym) {} /* unused vars warning: */
976 }
switch_to_xkb_if_better(void)977 void switch_to_xkb_if_better(void) {}
978
979 #else
980
switch_to_xkb_if_better(void)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
initialize_xkb_modtweak(void)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 */
xkb_tweak_keyboard(rfbBool down,rfbKeySym keysym,rfbClientPtr client)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
short_kmbcf(char * str)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
initialize_allowed_input(void)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
initialize_modtweak(void)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 */
tweak_mod(signed char mod,rfbBool down)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 */
modifier_tweak_keyboard(rfbBool down,rfbKeySym keysym,rfbClientPtr client)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
initialize_keyboard_and_pointer(void)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
get_allowed_input(rfbClientPtr client,allowed_input_t * input)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
apply_remap(rfbKeySym * keysym,int * isbutton)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 */
pipe_keyboard(rfbBool down,rfbKeySym keysym,rfbClientPtr client)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
typing_rate(double time_window,int * repeating)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
skip_cr_when_scaling(char * mode)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
keyboard(rfbBool down,rfbKeySym keysym,rfbClientPtr client)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