summaryrefslogtreecommitdiffstats
path: root/x11vnc/keyboard.c
diff options
context:
space:
mode:
authorrunge <runge>2007-08-19 19:13:12 +0000
committerrunge <runge>2007-08-19 19:13:12 +0000
commit222ecab5cae7add1186bbfe3bf50608b0d90b0c1 (patch)
tree6c0580cc8c4dd6fffd6492e67017cc10738e89c4 /x11vnc/keyboard.c
parenta69ed666eb66fc9a4d93a2fd9496c99d82e0d4d3 (diff)
downloadlibvncserver-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.c152
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 */
OpenPOWER on IntegriCloud