foxygit / doom Log in
commit 2435f5bb4de3a31c38748a0cab70d654c3bd4a8f
Author:     Jonathan Dowland <jon+github@alcopop.org>
AuthorDate: Sat Jul 2 22:22:25 2016 +0100
Commit:     Jonathan Dowland <jon+github@alcopop.org>
CommitDate: Mon Jul 4 09:10:53 2016 +0100

    Fix mousewheel for SDL2 by synthesising buttons

    SDL2 treats mouse wheel events as different from buttons.

    Assuming we want the wheel to emulate buttons as per SDL1,
    map the mouse wheel events to buttons. Use the mappings in
    textscreen (down = 3, up = 4).

    Fixes #722.
---
 src/i_input.c        | 45 +++++++++++++++++++++++++++++++++++++++++++++
 src/i_video.c        |  1 +
 textscreen/txt_sdl.c | 27 +++++++++++++++++++++++++++
 3 files changed, 73 insertions(+)

diff --git a/src/i_input.c b/src/i_input.c
index 44c03302..ca321234 100644
--- a/src/i_input.c
+++ b/src/i_input.c
@@ -355,6 +355,47 @@ static void UpdateMouseButtonState(unsigned int button, boolean on)
     D_PostEvent(&event);
 }

+static void MapMouseWheelToButtons(SDL_MouseWheelEvent *wheel)
+{
+    // SDL2 distinguishes button events from mouse wheel events.
+    // We want to treat the mouse wheel as two buttons, as per
+    // SDL1
+    event_t event1, event2;
+    int y = wheel->y;
+    int button;
+
+#if !(SDL_MAJOR_VERSION == 2 && SDL_MINOR_VERSION == 0 && SDL_PATCHLEVEL < 4)
+    // Ignore OS axis inversion (so up is always up)
+    if (wheel->direction == SDL_MOUSEWHEEL_FLIPPED)
+    {
+        y *= -1;
+    }
+#endif
+
+    if (y <= 0)
+    {   // scroll down
+        button = 3;
+    }
+    else
+    {   // scroll up
+        button = 4;
+    }
+
+    // post a button down event
+    mouse_button_state |= (1 << button);
+    event1.type = ev_mouse;
+    event1.data1 = mouse_button_state;
+    event1.data2 = event1.data3 = 0;
+    D_PostEvent(&event1);
+
+    // post a button up event
+    mouse_button_state &= ~(1 << button);
+    event2.type = ev_mouse;
+    event2.data1 = mouse_button_state;
+    event2.data2 = event2.data3 = 0;
+    D_PostEvent(&event2);
+}
+
 void I_HandleMouseEvent(SDL_Event *sdlevent)
 {
     switch (sdlevent->type)
@@ -367,6 +408,10 @@ void I_HandleMouseEvent(SDL_Event *sdlevent)
             UpdateMouseButtonState(sdlevent->button.button, false);
             break;

+        case SDL_MOUSEWHEEL:
+            MapMouseWheelToButtons(&(sdlevent->wheel));
+            break;
+
         default:
             break;
     }
diff --git a/src/i_video.c b/src/i_video.c
index d13786e5..aa1cbb4a 100644
--- a/src/i_video.c
+++ b/src/i_video.c
@@ -418,6 +418,7 @@ void I_GetEvent(void)

             case SDL_MOUSEBUTTONDOWN:
             case SDL_MOUSEBUTTONUP:
+            case SDL_MOUSEWHEEL:
                 if (usemouse && !nomouse && window_focused)
                 {
                     I_HandleMouseEvent(&sdlevent);
diff --git a/textscreen/txt_sdl.c b/textscreen/txt_sdl.c
index e53b25fe..cb1da17a 100644
--- a/textscreen/txt_sdl.c
+++ b/textscreen/txt_sdl.c
@@ -531,6 +531,30 @@ static int SDLButtonToTXTButton(int button)
     }
 }

+// Convert an SDL wheel motion to a textscreen button index.
+
+static int SDLWheelToTXTButton(SDL_MouseWheelEvent *wheel)
+{
+    int y = wheel->y;
+
+#if !(SDL_MAJOR_VERSION == 2 && SDL_MINOR_VERSION == 0 && SDL_PATCHLEVEL < 4)
+    // Ignore OS axis inversion (so up is always up)
+    if (wheel->direction == SDL_MOUSEWHEEL_FLIPPED)
+    {
+        y *= -1;
+    }
+#endif
+
+    if (y <= 0)
+    {
+        return TXT_MOUSE_SCROLLDOWN;
+    }
+    else
+    {
+        return TXT_MOUSE_SCROLLUP;
+    }
+}
+
 static int MouseHasMoved(void)
 {
     static int last_x = 0, last_y = 0;
@@ -615,6 +639,9 @@ signed int TXT_GetChar(void)
                 }
                 break;

+            case SDL_MOUSEWHEEL:
+                return SDLWheelToTXTButton(&ev.wheel);
+
             case SDL_KEYDOWN:
                 UpdateModifierState(&ev.key.keysym, 1);