From c41ab764b8557eb888ab5acfcac281b1d9e4822f Mon Sep 17 00:00:00 2001 From: runge Date: Thu, 29 Jul 2004 01:04:27 +0000 Subject: [PATCH] x11vnc: -add_keysyms dynamically add missing keysyms to X server --- ChangeLog | 3 + x11vnc/ChangeLog | 3 + x11vnc/x11vnc.c | 147 ++++++++++++++++++++++++++++++++++++++++++++++- 3 files changed, 152 insertions(+), 1 deletion(-) diff --git a/ChangeLog b/ChangeLog index 43a7407..9f81ac6 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,6 @@ +2004-07-28 Karl Runge + * x11vnc: -add_keysyms dynamically add missing keysyms to X server + 2004-07-26 Karl Runge * x11vnc: first pass at doing modtweak via XKEYBOARD extension (-xkb) * -skip_keycodes; reset modtweaks on event MappingNotify. diff --git a/x11vnc/ChangeLog b/x11vnc/ChangeLog index 51e517a..ceeeb97 100644 --- a/x11vnc/ChangeLog +++ b/x11vnc/ChangeLog @@ -1,3 +1,6 @@ +2004-07-28 Karl Runge + * -add_keysyms dynamically add missing keysyms to X server + 2004-07-26 Karl Runge * first pass at doing modtweak via XKEYBOARD extension (-xkb) * -skip_keycodes option for use with -xkb diff --git a/x11vnc/x11vnc.c b/x11vnc/x11vnc.c index 44bcb80..f2f3b2b 100644 --- a/x11vnc/x11vnc.c +++ b/x11vnc/x11vnc.c @@ -156,7 +156,7 @@ #endif /* date +'"lastmod: %Y-%m-%d";' */ -char lastmod[] = "lastmod: 2004-07-26"; +char lastmod[] = "lastmod: 2004-07-28"; /* X display info */ Display *dpy = 0; @@ -257,6 +257,10 @@ void clear_modifiers(int init); void clear_keys(void); void copy_screen(void); +int add_keysym(KeySym); +void delete_keycode(KeyCode); +void delete_added_keycodes(void); + double dtime(double *); void initialize_blackout(char *); @@ -347,6 +351,7 @@ int xkbcompat = 0; /* ignore XKEYBOARD extension */ int use_xkb = 0; /* try to open Xkb connection (for bell or other) */ int use_xkb_modtweak = 0; /* -xkb */ char *skip_keycodes = NULL; +int add_keysyms = 0; /* automatically add keysyms to X server */ int old_pointer = 0; /* use the old way of updating the pointer */ int single_copytile = 0; /* use the old way copy_tiles() */ @@ -476,6 +481,9 @@ void clean_up_exit (int ret) { } } + /* X keyboard cleanups */ + delete_added_keycodes(); + if (clear_mods == 1) { clear_modifiers(0); } else if (clear_mods == 2) { @@ -537,6 +545,10 @@ static void interrupted (int sig) { break; } } + + /* X keyboard cleanups */ + delete_added_keycodes(); + if (clear_mods == 1) { clear_modifiers(0); } else if (clear_mods == 2) { @@ -1810,6 +1822,107 @@ void clear_keys(void) { XFlush(dpy); } +static KeySym added_keysyms[0x100]; + +int add_keysym(KeySym keysym) { + int minkey, maxkey, syms_per_keycode; + int kc, n, ret = 0; + static int first = 1; + KeySym *keymap; + + if (first) { + for (n=0; n < 0x100; n++) { + added_keysyms[n] = NoSymbol; + } + first = 0; + } + if (keysym == NoSymbol) { + return 0; + } + + XDisplayKeycodes(dpy, &minkey, &maxkey); + keymap = XGetKeyboardMapping(dpy, minkey, (maxkey - minkey + 1), + &syms_per_keycode); + + for (kc = minkey+1; kc <= maxkey; kc++) { + int i, is_empty = 1; + char *str; + KeySym new[8]; + + for (n=0; n < syms_per_keycode; n++) { + if (keymap[ (kc-minkey) * syms_per_keycode + n] + != NoSymbol) { + is_empty = 0; + break; + } + } + if (! is_empty) { + continue; + } + + for (i=0; i<8; i++) { + new[i] = NoSymbol; + } + if (add_keysyms == 2) { + for(i=0; i < syms_per_keycode; i++) { + new[i] = keysym; + if (i >= 7) break; + } + } else { + new[0] = keysym; + + } + + XChangeKeyboardMapping(dpy, kc, syms_per_keycode, + new, 1); + + str = XKeysymToString(keysym); + rfbLog("added missing keysym to X display: %03d 0x%x \"%s\"\n", + kc, keysym, str ? str : "null"); + + XFlush(dpy); + added_keysyms[kc] = keysym; + ret = kc; + break; + } + XFree(keymap); + return ret; +} + +void delete_keycode(KeyCode kc) { + int minkey, maxkey, syms_per_keycode, i; + KeySym *keymap; + KeySym ksym, new[8]; + char *str; + + XDisplayKeycodes(dpy, &minkey, &maxkey); + keymap = XGetKeyboardMapping(dpy, minkey, (maxkey - minkey + 1), + &syms_per_keycode); + + for (i=0; i<8; i++) { + new[i] = NoSymbol; + } + XChangeKeyboardMapping(dpy, kc, syms_per_keycode, new, 1); + + ksym = XKeycodeToKeysym(dpy, kc, 0); + str = XKeysymToString(ksym); + rfbLog("deleted keycode from X display: %03d 0x%x \"%s\"\n", + kc, ksym, str ? str : "null"); + + XFree(keymap); + XFlush(dpy); +} + +void delete_added_keycodes(void) { + int kc; + for (kc = 0; kc < 0x100; kc++) { + if (added_keysyms[kc] != NoSymbol) { + delete_keycode(kc); + added_keysyms[kc] = NoSymbol; + } + } +} + /* * The following is for an experimental -remap option to allow the user * to remap keystrokes. It is currently confusing wrt modifiers... @@ -2337,6 +2450,18 @@ static void xkb_tweak_keyboard(rfbBool down, rfbKeySym keysym, got_kbstate = 1; PKBSTATE } + + if (!found && add_keysyms && keysym && ! IsModifierKey(keysym)) { + int new_kc = add_keysym(keysym); + if (new_kc != 0) { + found = 1; + kc_f[0] = new_kc; + grp_f[0] = 0; + lvl_f[0] = 0; + state_f[0] = 0; + } + } + if (!found && debug_keyboard) { char *str = XKeysymToString(keysym); fprintf(stderr, " *** NO key found for: 0x%x %s " @@ -2889,6 +3014,12 @@ static void modifier_tweak_keyboard(rfbBool down, rfbKeySym keysym, k = XKeysymToKeycode(dpy, (KeySym) keysym); X_UNLOCK; } + if (k == NoSymbol && add_keysyms && ! IsModifierKey(keysym)) { + int new_kc = add_keysym(keysym); + if (new_kc) { + k = new_kc; + } + } if (debug_keyboard) { rfbLog("modifier_tweak_keyboard: KeySym 0x%x \"%s\" -> " "KeyCode 0x%x%s\n", (int) keysym, XKeysymToString(keysym), @@ -2993,6 +3124,12 @@ void keyboard(rfbBool down, rfbKeySym keysym, rfbClientPtr client) { k = XKeysymToKeycode(dpy, (KeySym) keysym); + if (k == NoSymbol && add_keysyms && ! IsModifierKey(keysym)) { + int new_kc = add_keysym(keysym); + if (new_kc) { + k = new_kc; + } + } if (debug_keyboard) { char *str = XKeysymToString(keysym); rfbLog("keyboard(): KeySym 0x%x \"%s\" -> KeyCode 0x%x%s\n", @@ -3846,6 +3983,7 @@ void watch_xevents(void) { } if (XCheckTypedEvent(dpy, MappingNotify, &xev)) { + XRefreshKeyboardMapping((XMappingEvent *) &xev); if (use_modifier_tweak) { X_UNLOCK; initialize_modtweak(); @@ -7838,6 +7976,10 @@ static void print_help(void) { " keycodes. Use this option to help x11vnc in the reverse\n" " problem it tries to solve: Keysym -> Keycode(s) when\n" " ambiguities exist. E.g. -skip_keycodes 94,114\n" +"-add_keysyms If a keysym is received from a VNC viewer, but\n" +" that keysym does not exist in the X server, then\n" +" add the keysym to the X server's keyboard mapping.\n" +" Added keysyms will be removed when exiting.\n" #if 0 "-xkbcompat Ignore the XKEYBOARD extension. Use as a workaround for\n" " some keyboard mapping problems. E.g. if you are using\n" @@ -8394,6 +8536,8 @@ int main(int argc, char* argv[]) { skip_keycodes = argv[++i]; } else if (!strcmp(arg, "-xkbcompat")) { xkbcompat = 1; + } else if (!strcmp(arg, "-add_keysyms")) { + add_keysyms++; } else if (!strcmp(arg, "-clear_mods")) { clear_mods = 1; } else if (!strcmp(arg, "-clear_keys")) { @@ -8751,6 +8895,7 @@ int main(int argc, char* argv[]) { fprintf(stderr, "xkb: %d\n", use_xkb_modtweak); fprintf(stderr, "skipkeys: %s\n", skip_keycodes ? skip_keycodes : "null"); + fprintf(stderr, "addkeysyms: %d\n", add_keysyms); fprintf(stderr, "xkbcompat: %d\n", xkbcompat); fprintf(stderr, "clearmods: %d\n", clear_mods); fprintf(stderr, "remap: %s\n", remap_file ? remap_file