diff options
author | runge <runge> | 2007-08-19 19:13:12 +0000 |
---|---|---|
committer | runge <runge> | 2007-08-19 19:13:12 +0000 |
commit | 222ecab5cae7add1186bbfe3bf50608b0d90b0c1 (patch) | |
tree | 6c0580cc8c4dd6fffd6492e67017cc10738e89c4 /x11vnc/keyboard.c | |
parent | a69ed666eb66fc9a4d93a2fd9496c99d82e0d4d3 (diff) | |
download | libvncserver-222ecab5cae7add1186bbfe3bf50608b0d90b0c1.zip libvncserver-222ecab5cae7add1186bbfe3bf50608b0d90b0c1.tar.gz |
x11vnc: better -xkb tie-breaking for up keystrokes. Add Xsrv/FD_XSRV custom server to FINDCREATEDISPLAY list.
Diffstat (limited to 'x11vnc/keyboard.c')
-rw-r--r-- | x11vnc/keyboard.c | 152 |
1 files changed, 140 insertions, 12 deletions
diff --git a/x11vnc/keyboard.c b/x11vnc/keyboard.c index c7eaa97..15e7c70 100644 --- a/x11vnc/keyboard.c +++ b/x11vnc/keyboard.c @@ -1466,6 +1466,7 @@ xkbmodifiers[] For the KeySym bound to this (keycode,group,level) store } } +static int score_hint[0x100][0x100]; /* * Called on user keyboard input. Try to solve the reverse mapping * problem: KeySym (from VNC client) => KeyCode(s) to press to generate @@ -1485,8 +1486,10 @@ static void xkb_tweak_keyboard(rfbBool down, rfbKeySym keysym, XkbStateRec kbstate; int got_kbstate = 0; int Kc_f, Grp_f = 0, Lvl_f = 0; - static int Kc_last_down = -1; - static KeySym Ks_last_down = NoSymbol; +# define KLAST 10 + static int Kc_last_down[KLAST]; + static KeySym Ks_last_down[KLAST]; + static int klast = 0, khints = 1, anydown = 1; if (!client || !down || !keysym) {} /* unused vars warning: */ @@ -1494,6 +1497,32 @@ static void xkb_tweak_keyboard(rfbBool down, rfbKeySym keysym, X_LOCK; + if (klast == 0) { + int i, j; + for (i=0; i<KLAST; i++) { + Kc_last_down[i] = -1; + Ks_last_down[i] = NoSymbol; + } + if (getenv("NOKEYHINTS")) { + khints = 0; + } + if (getenv("NOANYDOWN")) { + anydown = 0; + } + if (getenv("KEYSDOWN")) { + klast = atoi(getenv("KEYSDOWN")); + if (klast < 1) klast = 1; + if (klast > KLAST) klast = KLAST; + } else { + klast = 3; + } + for (i=0; i<0x100; i++) { + for (j=0; j<0x100; j++) { + score_hint[i][j] = -1; + } + } + } + if (debug_keyboard) { char *str = XKeysymToString(keysym); @@ -1636,6 +1665,12 @@ static void xkb_tweak_keyboard(rfbBool down, rfbKeySym keysym, XkbGetState(dpy, XkbUseCoreKbd, &kbstate); got_kbstate = 1; } + if (khints && keysym < 0x100) { + int ks = (int) keysym, j; + for (j=0; j< 0x100; j++) { + score_hint[ks][j] = -1; + } + } for (l=0; l < found; l++) { int myscore = 0, b = 0x1, i; int curr, curr_state = kbstate.mods; @@ -1678,6 +1713,9 @@ static void xkb_tweak_keyboard(rfbBool down, rfbKeySym keysym, "keycode %03d: %4d\n", kc_f[l], myscore); } + if (khints && keysym < 0x100 && kc_f[l] < 0x100) { + score_hint[(int) keysym][kc_f[l]] = score[l]; + } } for (l=0; l < found; l++) { int myscore = score[l]; @@ -1693,39 +1731,125 @@ static void xkb_tweak_keyboard(rfbBool down, rfbKeySym keysym, } else { /* up */ + int i, Kc_loc = -1; Kc_f = -1; - if (keysym == Ks_last_down) { - int l; + + /* first try the scores we remembered when the key went down: */ + if (khints && keysym < 0x100) { + /* low keysyms, ascii, only */ + int ks = (int) keysym; + int ok = 1, sbest = -1, lbest, l; for (l=0; l < found; l++) { - if (Kc_last_down == kc_f[l]) { - Kc_f = Kc_last_down; + if (kc_f[l] < 0x100) { + int key = (int) kc_f[l]; + if (! keycode_state[key]) { + continue; + } + if (score_hint[ks][key] < 0) { + ok = 0; + break; + } + if (sbest < 0 || score_hint[ks][key] < sbest) { + sbest = score_hint[ks][key]; + lbest = l; + } + } else { + ok = 0; break; } } + if (ok && sbest != -1) { + Kc_f = kc_f[lbest]; + } + if (debug_keyboard && Kc_f != -1) { + fprintf(stderr, " UP: found via score_hint, s/l=%d/%d\n", + sbest, lbest); + } } + + /* next look at our list of recently pressed down keys */ if (Kc_f == -1) { + for (i=klast-1; i>=0; i--) { + /* + * some people type really fast and leave + * lots of keys down before releasing + * them. this gives problem on weird + * qwerty+dvorak keymappings where each + * alpha character is on TWO keys. + */ + if (keysym == Ks_last_down[i]) { + int l; + for (l=0; l < found; l++) { + if (Kc_last_down[i] == kc_f[l]) { + int key = (int) kc_f[l]; + if (keycode_state[key]) { + Kc_f = Kc_last_down[i]; + Kc_loc = i; + break; + } + } + } + } + if (Kc_f != -1) { + break; + } + } + if (debug_keyboard && Kc_f != -1) { + fprintf(stderr, " UP: found via klast, i=%d\n", Kc_loc); + } + } + + /* next just check for any one that is down */ + if (Kc_f == -1 && anydown) { int l; + int best = -1, lbest; /* * If it is already down, that is * a great hint. Use it. * - * note: keycode_state in internal and + * note: keycode_state is internal and * ignores someone pressing keys on the * physical display (but is updated * periodically to clean out stale info). */ + /* we could probably break ties based on lowest XKeycodeToKeysym index */ for (l=0; l < found; l++) { int key = (int) kc_f[l]; + int j, jmatch = -1; + if (keycode_state[key]) { - Kc_f = kc_f[l]; - break; + continue; + } + for (j=0; j<8; j++) { + KeySym ks = XKeycodeToKeysym(dpy, kc_f[l], j); + if (ks != NoSymbol && ks == keysym) { + jmatch = j; + break; + } + } + if (jmatch == -1) { + continue; } + if (best == -1 || jmatch < best) { + best = jmatch; + lbest = l; + } + } + if (best != -1) { + Kc_f = kc_f[lbest]; + } + if (debug_keyboard && Kc_f != -1) { + fprintf(stderr, " UP: found via downlist, l=%d\n", lbest); } } + /* last, use the first one found */ if (Kc_f == -1) { /* hope for the best... XXX check mods */ Kc_f = kc_f[0]; + if (debug_keyboard && Kc_f != -1) { + fprintf(stderr, " UP: set to first one, kc_f[0]!!\n"); + } } } } else { @@ -1747,7 +1871,7 @@ static void xkb_tweak_keyboard(rfbBool down, rfbKeySym keysym, fprintf(stderr, " \"%s\"", str ? str : "null"); } fprintf(stderr, ", picked this one: %03d (last down: %03d)\n", - Kc_f, Kc_last_down); + Kc_f, Kc_last_down[0]); } if (sloppy_keys) { @@ -1769,8 +1893,12 @@ static void xkb_tweak_keyboard(rfbBool down, rfbKeySym keysym, Bool dn; /* remember these to aid the subsequent up case: */ - Ks_last_down = keysym; - Kc_last_down = Kc_f; + for (i=KLAST-1; i >= 1; i--) { + Ks_last_down[i] = Ks_last_down[i-1]; + Kc_last_down[i] = Kc_last_down[i-1]; + } + Ks_last_down[0] = keysym; + Kc_last_down[0] = Kc_f; if (! got_kbstate) { /* get the current modifier state if we haven't yet */ |