[MPlayer-dev-eng] Stuck mouse buttons

Marius Gedminas mgedmin at b4net.lt
Tue Mar 30 19:29:26 CEST 2004


Hi,

(resending this to mplayer-dev-eng as requested)

Occasionally (but often enough to get annoying) when I click a mouse
button on an mplayer window the button gets stuck -- hitting any key
afterwards produces messages like

  No bind found for key MOUSE_BTN1-SPACE

although MOUSE_BTN1 is *not* held down.  It is easy for me to reproduce
the problem by hitting a mouse button for a very brief period of time.
It is even easier with tp-scroll[1], which is a gpm-like program that
lets me emulate the mouse wheel on a ThinkPad with its 3-button
trackpoint.  Tp-scroll emits the middle button release event immediately
after the press event and always triggers the problem.

  [1] http://rsim.cs.uiuc.edu/~sachs/tp-scroll/

More than one mouse button can get stuck.  I managed all three of them.

I've traced the problem to mplayer_put_key in fifo.c.  After
uncommenting the line that warns about dropped key events (FIFO full) I
started seeing these messages every time a button got stuck.  While
ignoring keypresses on a full FIFO buffer is a sensible thing to do
with normal keys, it does not work well with mouse button release events...

I should mention that HAVE_NO_POSIX_SELECT is not defined here and thus
the first version of mplayer_put_key is used (the one which uses select
on a pipe).  This is a Debian system (mixed stable/testing/unstable)
with glibc 2.3.2 (libc6 2.3.2.ds1-11), and kernel 2.4.24.  I do not use
the mplayer GUI.

What seems strange to me is that the FIFO becomes full with just one key
event in it.  Apparently trying to use a Unix pipe as a generic FIFO
buffer does not work as expected.  When I defined HAVE_NO_POSIX_SELECT
in config.h and recompiled mplayer the problem went away.

I suspect that select on a pipe will not say the fd is ready for writing
if the buffer is not completely empty.  Normally you can write up to
PIPE_BUF bytes without blocking, but if the buffer already contains
something, then writing PIPE_BUF bytes would block.  IOW using select
for a generic FIFO buffer does not work well.

I think a better solution would be to use nonblocking writes.  Something
like the attached patch (tested here, but not tested for portability --
and the #ifdef with HAVE_NO_POSIX_SELECT should be changed to something
different as well).

Or maybe it would be simplest to always use the in-memory array solution
(mplayer_put_key + mplayer_get_key).  I expect it to be marginally
faster as well (no syscalls, no context switches).

Marius Gedminas
-- 
QOTD:
        "A child of 5 could understand this!  Fetch me a child of 5."
-------------- next part --------------
diff -up ./fifo.c.orig ./fifo.c
--- ./fifo.c.orig	2004-03-29 12:21:29.000000000 +0300
+++ ./fifo.c	2004-03-29 12:38:04.000000000 +0300
@@ -12,23 +12,21 @@ static void make_pipe(int* pr,int* pw){
   *pw=temp[1];
 }
 
-void mplayer_put_key(int code){
-           fd_set rfds;
-           struct timeval tv;
+static void set_nonblock_flag(int fd) {
+  int oldflags = fcntl(fd, F_GETFL, 0);
+  if (oldflags == -1) {
+    printf("Cannot get file status flags for fd %d!\n", fd);
+  } else {
+    if (fcntl(keyb_fifo_put, F_SETFL, oldflags | O_NONBLOCK) == -1) {
+      printf("Cannot set nonblocking mode for fd %d!\n", fd);
+    }
+  }
+}
 
-           /* Watch stdin (fd 0) to see when it has input. */
-           FD_ZERO(&rfds);
-           FD_SET(keyb_fifo_put, &rfds);
-           tv.tv_sec = 0;
-           tv.tv_usec = 0;
-
-           //retval = select(keyb_fifo_put+1, &rfds, NULL, NULL, &tv);
-           if(select(keyb_fifo_put+1, NULL, &rfds, NULL, &tv)>0){
-             write(keyb_fifo_put,&code,4);
-//             printf("*** key event %d sent ***\n",code);
-           } else {
-//             printf("*** key event dropped (FIFO is full) ***\n");
-           }
+void mplayer_put_key(int code){
+  if (write(keyb_fifo_put,&code,4) == -1) {
+    printf("*** key event dropped (FIFO is full) ***\n");
+  }
 }
 
 #else

diff -up ./mplayer.c.orig ./mplayer.c
--- ./mplayer.c.orig	2004-03-29 12:27:02.000000000 +0300
+++ ./mplayer.c	2004-03-29 12:29:43.000000000 +0300
@@ -1127,6 +1127,7 @@ current_module = "init_input";
 mp_input_init();
 #ifndef HAVE_NO_POSIX_SELECT
 make_pipe(&keyb_fifo_get,&keyb_fifo_put);
+set_nonblock_flag(keyb_fifo_put);
 
 if(keyb_fifo_get > 0)
   mp_input_add_key_fd(keyb_fifo_get,1,NULL,NULL);


-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 189 bytes
Desc: Digital signature
URL: <http://lists.mplayerhq.hu/pipermail/mplayer-dev-eng/attachments/20040330/bdca1bfa/attachment.pgp>


More information about the MPlayer-dev-eng mailing list