SDL: 3DS: Ensure that touchscreen events are associated with a window

From 4df852cbbfb11bcb5345e17ea13cc63af79a9dde Mon Sep 17 00:00:00 2001
From: Cameron Cawley <[EMAIL REDACTED]>
Date: Sat, 13 Apr 2024 23:21:33 +0100
Subject: [PATCH] 3DS: Ensure that touchscreen events are associated with a
 window

---
 src/video/n3ds/SDL_n3dsevents.c |  2 +-
 src/video/n3ds/SDL_n3dstouch.c  | 14 +++++++++++---
 src/video/n3ds/SDL_n3dstouch.h  |  2 +-
 src/video/n3ds/SDL_n3dsvideo.c  | 31 +++++++++++++++++++++++--------
 src/video/n3ds/SDL_n3dsvideo.h  |  7 +++++++
 5 files changed, 43 insertions(+), 13 deletions(-)

diff --git a/src/video/n3ds/SDL_n3dsevents.c b/src/video/n3ds/SDL_n3dsevents.c
index c45bb8089570c..c155b7e164ec3 100644
--- a/src/video/n3ds/SDL_n3dsevents.c
+++ b/src/video/n3ds/SDL_n3dsevents.c
@@ -31,7 +31,7 @@
 void N3DS_PumpEvents(_THIS)
 {
     hidScanInput();
-    N3DS_PollTouch();
+    N3DS_PollTouch(_this);
 
     if (!aptMainLoop()) {
         SDL_Event ev;
diff --git a/src/video/n3ds/SDL_n3dstouch.c b/src/video/n3ds/SDL_n3dstouch.c
index 982c578ac1869..10eea258b1ab8 100644
--- a/src/video/n3ds/SDL_n3dstouch.c
+++ b/src/video/n3ds/SDL_n3dstouch.c
@@ -26,7 +26,9 @@
 #include <3ds.h>
 
 #include "../../events/SDL_touch_c.h"
+#include "../SDL_sysvideo.h"
 #include "SDL_n3dstouch.h"
+#include "SDL_n3dsvideo.h"
 
 #define N3DS_TOUCH_ID 0
 
@@ -49,19 +51,25 @@ void N3DS_QuitTouch(void)
     SDL_DelTouch(N3DS_TOUCH_ID);
 }
 
-void N3DS_PollTouch(void)
+void N3DS_PollTouch(_THIS)
 {
+    SDL_VideoData *driverdata = (SDL_VideoData *)_this->driverdata;
     touchPosition touch;
+    SDL_Window *window;
+    SDL_VideoDisplay *display;
     static SDL_bool was_pressed = SDL_FALSE;
     SDL_bool pressed;
     hidTouchRead(&touch);
     pressed = (touch.px != 0 || touch.py != 0);
 
+    display = SDL_GetDisplay(driverdata->touch_display);
+    window = display ? display->fullscreen_window : NULL;
+
     if (pressed != was_pressed) {
         was_pressed = pressed;
         SDL_SendTouch(N3DS_TOUCH_ID,
                       0,
-                      NULL,
+                      window,
                       pressed,
                       touch.px * TOUCHSCREEN_SCALE_X,
                       touch.py * TOUCHSCREEN_SCALE_Y,
@@ -69,7 +77,7 @@ void N3DS_PollTouch(void)
     } else if (pressed) {
         SDL_SendTouchMotion(N3DS_TOUCH_ID,
                             0,
-                            NULL,
+                            window,
                             touch.px * TOUCHSCREEN_SCALE_X,
                             touch.py * TOUCHSCREEN_SCALE_Y,
                             1.0f);
diff --git a/src/video/n3ds/SDL_n3dstouch.h b/src/video/n3ds/SDL_n3dstouch.h
index d99e5a32152f7..5a32d71971bd1 100644
--- a/src/video/n3ds/SDL_n3dstouch.h
+++ b/src/video/n3ds/SDL_n3dstouch.h
@@ -24,7 +24,7 @@
 
 void N3DS_InitTouch(void);
 void N3DS_QuitTouch(void);
-void N3DS_PollTouch(void);
+void N3DS_PollTouch(_THIS);
 
 #endif /* SDL_n3dstouch_h_ */
 
diff --git a/src/video/n3ds/SDL_n3dsvideo.c b/src/video/n3ds/SDL_n3dsvideo.c
index fc875d3ce5202..70868da4bc9dc 100644
--- a/src/video/n3ds/SDL_n3dsvideo.c
+++ b/src/video/n3ds/SDL_n3dsvideo.c
@@ -31,7 +31,7 @@
 
 #define N3DSVID_DRIVER_NAME "n3ds"
 
-SDL_FORCE_INLINE void AddN3DSDisplay(gfxScreen_t screen);
+SDL_FORCE_INLINE int AddN3DSDisplay(gfxScreen_t screen);
 
 static int N3DS_VideoInit(_THIS);
 static void N3DS_VideoQuit(_THIS);
@@ -56,12 +56,26 @@ static void N3DS_DeleteDevice(SDL_VideoDevice *device)
 
 static SDL_VideoDevice *N3DS_CreateDevice(void)
 {
-    SDL_VideoDevice *device = (SDL_VideoDevice *)SDL_calloc(1, sizeof(SDL_VideoDevice));
+    SDL_VideoDevice *device;
+    SDL_VideoData *phdata;
+
+    /* Initialize all variables that we clean on shutdown */
+    device = (SDL_VideoDevice *)SDL_calloc(1, sizeof(SDL_VideoDevice));
     if (!device) {
         SDL_OutOfMemory();
         return 0;
     }
 
+    /* Initialize internal data */
+    phdata = (SDL_VideoData *)SDL_calloc(1, sizeof(SDL_VideoData));
+    if (!phdata) {
+        SDL_OutOfMemory();
+        SDL_free(device);
+        return NULL;
+    }
+
+    device->driverdata = phdata;
+
     device->VideoInit = N3DS_VideoInit;
     device->VideoQuit = N3DS_VideoQuit;
 
@@ -90,11 +104,13 @@ VideoBootStrap N3DS_bootstrap = { N3DSVID_DRIVER_NAME, "N3DS Video Driver", N3DS
 
 static int N3DS_VideoInit(_THIS)
 {
+    SDL_VideoData *driverdata = (SDL_VideoData *)_this->driverdata;
+
     gfxInit(GSP_RGBA8_OES, GSP_RGBA8_OES, false);
     hidInit();
 
-    AddN3DSDisplay(GFX_TOP);
-    AddN3DSDisplay(GFX_BOTTOM);
+    driverdata->top_display = AddN3DSDisplay(GFX_TOP);
+    driverdata->touch_display = AddN3DSDisplay(GFX_BOTTOM);
 
     N3DS_InitTouch();
     N3DS_SwkbInit();
@@ -102,15 +118,14 @@ static int N3DS_VideoInit(_THIS)
     return 0;
 }
 
-SDL_FORCE_INLINE void
+SDL_FORCE_INLINE int
 AddN3DSDisplay(gfxScreen_t screen)
 {
     SDL_DisplayMode mode;
     SDL_VideoDisplay display;
     DisplayDriverData *display_driver_data = SDL_calloc(1, sizeof(DisplayDriverData));
     if (!display_driver_data) {
-        SDL_OutOfMemory();
-        return;
+        return SDL_OutOfMemory();
     }
 
     SDL_zero(mode);
@@ -129,7 +144,7 @@ AddN3DSDisplay(gfxScreen_t screen)
     display.current_mode = mode;
     display.driverdata = display_driver_data;
 
-    SDL_AddVideoDisplay(&display, SDL_FALSE);
+    return SDL_AddVideoDisplay(&display, SDL_FALSE);
 }
 
 static void N3DS_VideoQuit(_THIS)
diff --git a/src/video/n3ds/SDL_n3dsvideo.h b/src/video/n3ds/SDL_n3dsvideo.h
index 455eaf425ef0f..696d40b562bfb 100644
--- a/src/video/n3ds/SDL_n3dsvideo.h
+++ b/src/video/n3ds/SDL_n3dsvideo.h
@@ -26,6 +26,13 @@
 #include <3ds.h>
 
 #include "../SDL_sysvideo.h"
+
+typedef struct SDL_VideoData
+{
+    int top_display;
+    int touch_display;
+} SDL_VideoData;
+
 typedef struct SDL_WindowData
 {
     gfxScreen_t screen; /**< Keeps track of which N3DS screen is targetted */