[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