SDL: Implement mouse input on RISC OS

From 1268984edce4184d932edb13fc7e1e7333a8f912 Mon Sep 17 00:00:00 2001
From: Cameron Cawley <[EMAIL REDACTED]>
Date: Thu, 9 Sep 2021 21:09:50 +0100
Subject: [PATCH] Implement mouse input on RISC OS

---
 src/video/riscos/SDL_riscosevents.c | 43 +++++++++++++++++++++++++++++
 src/video/riscos/SDL_riscosmodes.c  |  3 ++
 src/video/riscos/SDL_riscosvideo.h  |  1 +
 3 files changed, 47 insertions(+)

diff --git a/src/video/riscos/SDL_riscosevents.c b/src/video/riscos/SDL_riscosevents.c
index b571d759b5..3dbc3d0dc4 100644
--- a/src/video/riscos/SDL_riscosevents.c
+++ b/src/video/riscos/SDL_riscosevents.c
@@ -30,6 +30,7 @@
 #include "scancodes_riscos.h"
 
 #include <kernel.h>
+#include <swis.h>
 
 static SDL_Scancode
 SDL_RISCOS_translate_keycode(int keycode)
@@ -104,6 +105,47 @@ RISCOS_PollKeyboard(_THIS)
     }
 }
 
+static const Uint8 mouse_button_map[] = {
+    SDL_BUTTON_RIGHT,
+    SDL_BUTTON_MIDDLE,
+    SDL_BUTTON_LEFT,
+    SDL_BUTTON_X1,
+    SDL_BUTTON_X2,
+    SDL_BUTTON_X2 + 1,
+    SDL_BUTTON_X2 + 2,
+    SDL_BUTTON_X2 + 3
+};
+
+void
+RISCOS_PollMouse(_THIS)
+{
+    SDL_VideoData *driverdata = (SDL_VideoData *)_this->driverdata;
+    SDL_Mouse *mouse = SDL_GetMouse();
+    SDL_Rect rect;
+    _kernel_swi_regs regs;
+    int i, x, y, buttons;
+
+    if (SDL_GetDisplayBounds(0, &rect) < 0) {
+        return;
+    }
+
+    _kernel_swi(OS_Mouse, &regs, &regs);
+    x = (regs.r[0] >> 1);
+    y = rect.h - (regs.r[1] >> 1);
+    buttons = regs.r[2];
+
+    if (mouse->x != x || mouse->y != y) {
+        SDL_SendMouseMotion(mouse->focus, mouse->mouseID, 0, x, y);
+    }
+
+    if (driverdata->last_mouse_buttons != buttons) {
+        for (i = 0; i < SDL_arraysize(mouse_button_map); i++) {
+            SDL_SendMouseButton(mouse->focus, mouse->mouseID, (buttons & (1 << i)) ? SDL_PRESSED : SDL_RELEASED, mouse_button_map[i]);
+        }
+        driverdata->last_mouse_buttons = buttons;
+    }
+}
+
 int
 RISCOS_InitEvents(_THIS)
 {
@@ -126,6 +168,7 @@ RISCOS_InitEvents(_THIS)
 void
 RISCOS_PumpEvents(_THIS)
 {
+    RISCOS_PollMouse(_this);
     RISCOS_PollKeyboard(_this);
 }
 
diff --git a/src/video/riscos/SDL_riscosmodes.c b/src/video/riscos/SDL_riscosmodes.c
index be723907be..7b35c5d935 100644
--- a/src/video/riscos/SDL_riscosmodes.c
+++ b/src/video/riscos/SDL_riscosmodes.c
@@ -247,6 +247,9 @@ RISCOS_SetDisplayMode(_THIS, SDL_VideoDisplay * display, SDL_DisplayMode * mode)
         _kernel_oswrch(disable_cursor[i]);
     }
 
+    /* Turn the mouse pointer on */
+    _kernel_osbyte(106, 1, 0);
+
     return 0;
 }
 
diff --git a/src/video/riscos/SDL_riscosvideo.h b/src/video/riscos/SDL_riscosvideo.h
index 7be93afc37..a7480d8b13 100644
--- a/src/video/riscos/SDL_riscosvideo.h
+++ b/src/video/riscos/SDL_riscosvideo.h
@@ -29,6 +29,7 @@
 
 typedef struct SDL_VideoData
 {
+    int last_mouse_buttons;
     Uint8 key_pressed[RISCOS_MAX_KEYS_PRESSED];
 } SDL_VideoData;