Fixed bug 1173 (No mouse wheel event on linux/x11)
authorSam Lantinga <slouken@libsdl.org>
Tue, 05 Apr 2011 09:35:56 -0700
changeset 55304e46a7b6773d
parent 5529 8c0d15077360
child 5531 477f550f6efd
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
     1.1 --- a/src/video/x11/SDL_x11events.c	Mon Apr 04 23:38:15 2011 -0400
     1.2 +++ b/src/video/x11/SDL_x11events.c	Tue Apr 05 09:35:56 2011 -0700
     1.3 @@ -65,6 +65,37 @@
     1.4      return SDL_FALSE;
     1.5  }
     1.6  
     1.7 +static SDL_bool X11_IsWheelEvent(Display * display,XEvent * event,int * ticks)
     1.8 +{
     1.9 +    XEvent peekevent;
    1.10 +    if (XPending(display)) {
    1.11 +        /* according to the xlib docs, no specific mouse wheel events exist.
    1.12 +           however, mouse wheel events trigger a button press and a button release
    1.13 +           immediately. thus, checking if the same button was released at the same
    1.14 +           time as it was pressed, should be an adequate hack to derive a mouse 
    1.15 +           wheel event. */
    1.16 +        XPeekEvent(display,&peekevent);
    1.17 +        if ((peekevent.type           == ButtonRelease) &&
    1.18 +            (peekevent.xbutton.button == event->xbutton.button) &&
    1.19 +            (peekevent.xbutton.time   == event->xbutton.time)) {
    1.20 +
    1.21 +            /* by default, X11 only knows 5 buttons. on most 3 button + wheel mouse,
    1.22 +               Button4 maps to wheel up, Button5 maps to wheel down. */
    1.23 +            if (event->xbutton.button == Button4) {
    1.24 +                *ticks = 1;
    1.25 +            }
    1.26 +            else {
    1.27 +                *ticks = -1;
    1.28 +            }
    1.29 +
    1.30 +            /* remove the following release event, as this is now a wheel event */
    1.31 +            XNextEvent(display,&peekevent);
    1.32 +            return SDL_TRUE;
    1.33 +        }
    1.34 +    }
    1.35 +    return SDL_FALSE;
    1.36 +}
    1.37 +
    1.38  static void
    1.39  X11_DispatchEvent(_THIS)
    1.40  {
    1.41 @@ -316,7 +347,13 @@
    1.42          break;
    1.43  
    1.44      case ButtonPress:{
    1.45 -            SDL_SendMouseButton(data->window, SDL_PRESSED, xevent.xbutton.button);
    1.46 +            int ticks = 0;
    1.47 +            if (X11_IsWheelEvent(display,&xevent,&ticks) == SDL_TRUE) {
    1.48 +                SDL_SendMouseWheel(data->window, 0, ticks);
    1.49 +            }
    1.50 +            else {
    1.51 +                SDL_SendMouseButton(data->window, SDL_PRESSED, xevent.xbutton.button);
    1.52 +            }
    1.53          }
    1.54          break;
    1.55