summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorrunge <runge>2004-07-29 01:04:27 +0000
committerrunge <runge>2004-07-29 01:04:27 +0000
commitc41ab764b8557eb888ab5acfcac281b1d9e4822f (patch)
treeb5c182f4d4174105eccc0f2451176caaf522a4cf
parenteb9a6928b0164b1cb2207e505176c037eaf5ab02 (diff)
downloadlibtdevnc-c41ab764b8557eb888ab5acfcac281b1d9e4822f.tar.gz
libtdevnc-c41ab764b8557eb888ab5acfcac281b1d9e4822f.zip
x11vnc: -add_keysyms dynamically add missing keysyms to X server
-rw-r--r--ChangeLog3
-rw-r--r--x11vnc/ChangeLog3
-rw-r--r--x11vnc/x11vnc.c147
3 files changed, 152 insertions, 1 deletions
diff --git a/ChangeLog b/ChangeLog
index 43a7407..9f81ac6 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,6 @@
+2004-07-28 Karl Runge <runge@karlrunge.com>
+ * x11vnc: -add_keysyms dynamically add missing keysyms to X server
+
2004-07-26 Karl Runge <runge@karlrunge.com>
* 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 <runge@karlrunge.com>
+ * -add_keysyms dynamically add missing keysyms to X server
+
2004-07-26 Karl Runge <runge@karlrunge.com>
* 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