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