From af77ae7011ef7581f155e8a543888da1deb0e58f Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Tue, 5 Apr 2011 09:35:56 -0700 Subject: [PATCH] Fixed bug 1173 (No mouse wheel event on linux/x11) Matthias 2011-03-20 23:07:02 PDT On X11, SDL 1.3 does not generate a mouse wheel event. Instead, button down/buttton up events are generated by SDL. After looking at the code in SDL_x11events.c, I assume this is due to the fact that X11 does not have a dedicated mouse wheel event. I did a little research on the behavior of mouse wheel events on X11 systems. Apparently, mouse wheel events generate a button down/button up event with the same time, i.e. with exact same timestamp. Attached you can find my changes to SDL_x11events.c, which generates SDL mouse wheel events for those button down events that have a button release event immediately following it (for the same button, and with the same timestamp). I did have to make an assumption: As standard X11 implementations know only 5 buttons, I have mapped Button4 to "wheel up" (i.e. +1), and Button5 to "wheel down" (i.e. -1). Note that if you include this patch, no SDL button down/up events will be generated on X11 platforms for mouse wheel events (which is probably a significant change for those that have programmed their code to work with them). --- src/video/x11/SDL_x11events.c | 39 ++++++++++++++++++++++++++++++++++- 1 file changed, 38 insertions(+), 1 deletion(-) diff --git a/src/video/x11/SDL_x11events.c b/src/video/x11/SDL_x11events.c index 646c58ca2..03ce86af9 100644 --- a/src/video/x11/SDL_x11events.c +++ b/src/video/x11/SDL_x11events.c @@ -65,6 +65,37 @@ static SDL_bool X11_KeyRepeat(Display *display, XEvent *event) return SDL_FALSE; } +static SDL_bool X11_IsWheelEvent(Display * display,XEvent * event,int * ticks) +{ + XEvent peekevent; + if (XPending(display)) { + /* according to the xlib docs, no specific mouse wheel events exist. + however, mouse wheel events trigger a button press and a button release + immediately. thus, checking if the same button was released at the same + time as it was pressed, should be an adequate hack to derive a mouse + wheel event. */ + XPeekEvent(display,&peekevent); + if ((peekevent.type == ButtonRelease) && + (peekevent.xbutton.button == event->xbutton.button) && + (peekevent.xbutton.time == event->xbutton.time)) { + + /* by default, X11 only knows 5 buttons. on most 3 button + wheel mouse, + Button4 maps to wheel up, Button5 maps to wheel down. */ + if (event->xbutton.button == Button4) { + *ticks = 1; + } + else { + *ticks = -1; + } + + /* remove the following release event, as this is now a wheel event */ + XNextEvent(display,&peekevent); + return SDL_TRUE; + } + } + return SDL_FALSE; +} + static void X11_DispatchEvent(_THIS) { @@ -316,7 +347,13 @@ X11_DispatchEvent(_THIS) break; case ButtonPress:{ - SDL_SendMouseButton(data->window, SDL_PRESSED, xevent.xbutton.button); + int ticks = 0; + if (X11_IsWheelEvent(display,&xevent,&ticks) == SDL_TRUE) { + SDL_SendMouseWheel(data->window, 0, ticks); + } + else { + SDL_SendMouseButton(data->window, SDL_PRESSED, xevent.xbutton.button); + } } break;