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