remote plugin ignoring some keys

Message ID 46351668.3050303@o2.pl
State New
Headers

Commit Message

Artur Skawina April 29, 2007, 10:04 p.m. UTC
  A while ago the remote plugins "telnet" server started acting strangely here; it would
sometimes ignore all cursor and function keys, yet other keys would work perfectly.
I'm not sure when exactly this began, most likely a newer kernel triggered this.
It does not happen always, but when it does it makes navigating the OSD practically
impossible.
Turns out the remote plugin gets confused when a read() call returns not a full
escape sequence, but just the first \0x27 byte and the next read() receives the
remaining two or three bytes. And this is exactly what happens (the client for some
reason actually sends two tcp packets containing just eg "\0x1b" and "\0x5b\0x43").
This quick patch made the remote osd usable again; it isn't perfect as keys can still
be lost (see comments), but it's a huge improvement - only some key repeats are dropped,
not all multibyte sequences.

artur
  

Patch

diff -urNp remote-0.3.9.org/remote.c remote-0.3.9/remote.c
--- remote-0.3.9.org/remote.c	2006-12-03 14:46:55.000000000 +0000
+++ remote-0.3.9/remote.c	2007-04-29 20:45:13.000000000 +0000
@@ -517,6 +517,27 @@  uint64_t cRemoteDevTty::getKey(void)
     uint64_t code = 0;

     n = read(fh, &code, sizeof code);
+
+    if (code==27 && n==1)
+    {
+	// Ugh. What happened: user pressed a key that generates an escape
+	// sequence (eg up/down) and we got only the first '\e'; now we have
+	// to fetch the remaining bytes as otherwise we end up ignoring almost
+	// every such key press and navigating the osd becomes impossible.
+	// We try to read more bytes and hope that the result makes sense;
+	// this often works, but not always. When eg holding down a key we
+	// can receive several (repeated) sequences and these are then ignored.
+	// Dropping a few key presses (mostly repeats) is still much better
+	// than dropping nearly _all_ of them...
+	// (Unfortunately the sequences do differ in length, hence either
+	// parsing them or matching them w/ the expected ones would be needed
+	// to avoid loosing sync here)
+	int m = read(fh, ((char*)&code)+1, sizeof code-1);
+	if (m > 0)
+	    n += m;
+    }
+    //dsyslog("cRemoteDevTty::getKey: %d %lld", n, code);
+
     return (n > 0) ? code : INVALID_KEY;
 }