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