From f9dc49c21c99cd6eb63d80d60b6e706a51234b46 Mon Sep 17 00:00:00 2001
From: Frank Praznik <[EMAIL REDACTED]>
Date: Fri, 29 Sep 2023 12:55:09 -0400
Subject: [PATCH] Fix automated tests using the dummy video driver
Manual backport of b8d9125
---
src/events/SDL_mouse.c | 70 +++++++++++++++++++++++++++++----
src/events/SDL_mouse_c.h | 3 +-
src/video/SDL_video.c | 24 +++++++++--
src/video/dummy/SDL_nullvideo.c | 9 +----
test/testautomation_video.c | 2 +
5 files changed, 88 insertions(+), 20 deletions(-)
diff --git a/src/events/SDL_mouse.c b/src/events/SDL_mouse.c
index 000b22deb5b7..d609fdefd756 100644
--- a/src/events/SDL_mouse.c
+++ b/src/events/SDL_mouse.c
@@ -171,7 +171,7 @@ static void SDLCALL SDL_MouseRelativeWarpMotionChanged(void *userdata, const cha
}
/* Public functions */
-int SDL_MouseInit(void)
+int SDL_MousePreInit(void)
{
SDL_Mouse *mouse = SDL_GetMouse();
@@ -216,11 +216,62 @@ int SDL_MouseInit(void)
return 0;
}
+void SDL_MousePostInit(void)
+{
+ SDL_Mouse *mouse = SDL_GetMouse();
+
+ /* Create a dummy mouse cursor for video backends that don't support true cursors,
+ * so that mouse grab and focus functionality will work.
+ */
+ if (!mouse->def_cursor) {
+ SDL_Surface *surface = SDL_CreateRGBSurface(0, 1, 1, 32, 0xFF, 0xFF, 0xFF, 0xFF);
+ if (surface) {
+ SDL_memset(surface->pixels, 0, (size_t)surface->h * surface->pitch);
+ SDL_SetDefaultCursor(SDL_CreateColorCursor(surface, 0, 0));
+ SDL_FreeSurface(surface);
+ }
+ }
+}
+
void SDL_SetDefaultCursor(SDL_Cursor *cursor)
{
SDL_Mouse *mouse = SDL_GetMouse();
+ if (cursor == mouse->def_cursor) {
+ return;
+ }
+
+ if (mouse->def_cursor) {
+ SDL_Cursor *default_cursor = mouse->def_cursor;
+ SDL_Cursor *prev, *curr;
+
+ if (mouse->cur_cursor == mouse->def_cursor) {
+ mouse->cur_cursor = NULL;
+ }
+ mouse->def_cursor = NULL;
+
+ for (prev = NULL, curr = mouse->cursors; curr;
+ prev = curr, curr = curr->next) {
+ if (curr == default_cursor) {
+ if (prev) {
+ prev->next = curr->next;
+ } else {
+ mouse->cursors = curr->next;
+ }
+
+ break;
+ }
+ }
+
+ if (mouse->FreeCursor && default_cursor->driverdata) {
+ mouse->FreeCursor(default_cursor);
+ } else {
+ SDL_free(default_cursor);
+ }
+ }
+
mouse->def_cursor = cursor;
+
if (!mouse->cur_cursor) {
SDL_SetCursor(cursor);
}
@@ -1271,11 +1322,6 @@ SDL_Cursor *SDL_CreateColorCursor(SDL_Surface *surface, int hot_x, int hot_y)
return NULL;
}
- if (!mouse->CreateCursor) {
- SDL_SetError("Cursors are not currently supported");
- return NULL;
- }
-
/* Sanity check the hot spot */
if ((hot_x < 0) || (hot_y < 0) ||
(hot_x >= surface->w) || (hot_y >= surface->h)) {
@@ -1291,7 +1337,15 @@ SDL_Cursor *SDL_CreateColorCursor(SDL_Surface *surface, int hot_x, int hot_y)
surface = temp;
}
- cursor = mouse->CreateCursor(surface, hot_x, hot_y);
+ if (mouse->CreateCursor) {
+ cursor = mouse->CreateCursor(surface, hot_x, hot_y);
+ } else {
+ cursor = SDL_calloc(1, sizeof(*cursor));
+ if (!cursor) {
+ SDL_OutOfMemory();
+ }
+ }
+
if (cursor) {
cursor->next = mouse->cursors;
mouse->cursors = cursor;
@@ -1416,6 +1470,8 @@ void SDL_FreeCursor(SDL_Cursor *cursor)
if (mouse->FreeCursor) {
mouse->FreeCursor(curr);
+ } else {
+ SDL_free(curr);
}
return;
}
diff --git a/src/events/SDL_mouse_c.h b/src/events/SDL_mouse_c.h
index 64e82ab8ed74..71337e4e12f7 100644
--- a/src/events/SDL_mouse_c.h
+++ b/src/events/SDL_mouse_c.h
@@ -131,7 +131,8 @@ typedef struct
} SDL_Mouse;
/* Initialize the mouse subsystem */
-extern int SDL_MouseInit(void);
+extern int SDL_MousePreInit(void);
+extern void SDL_MousePostInit(void);
/* Get the mouse state structure */
SDL_Mouse *SDL_GetMouse(void);
diff --git a/src/video/SDL_video.c b/src/video/SDL_video.c
index 9a09a902136e..23ce7b1a7adf 100644
--- a/src/video/SDL_video.c
+++ b/src/video/SDL_video.c
@@ -454,7 +454,7 @@ int SDL_VideoInit(const char *driver_name)
goto pre_driver_error;
}
init_keyboard = SDL_TRUE;
- if (SDL_MouseInit() < 0) {
+ if (SDL_MousePreInit() < 0) {
goto pre_driver_error;
}
init_mouse = SDL_TRUE;
@@ -550,6 +550,8 @@ int SDL_VideoInit(const char *driver_name)
SDL_StartTextInput();
}
+ SDL_MousePostInit();
+
/* We're ready to go! */
return 0;
@@ -1335,6 +1337,7 @@ static int SDL_UpdateFullscreenMode(SDL_Window *window, SDL_bool fullscreen)
{
SDL_VideoDisplay *display;
SDL_Window *other;
+ SDL_bool resized = SDL_FALSE;
CHECK_WINDOW_MAGIC(window, -1);
@@ -1443,7 +1446,7 @@ static int SDL_UpdateFullscreenMode(SDL_Window *window, SDL_bool fullscreen)
SDL_zero(fullscreen_mode);
if (SDL_GetWindowDisplayMode(other, &fullscreen_mode) == 0) {
- SDL_bool resized = SDL_TRUE;
+ resized = SDL_TRUE;
if (other->w == fullscreen_mode.w && other->h == fullscreen_mode.h) {
resized = SDL_FALSE;
@@ -1498,11 +1501,18 @@ static int SDL_UpdateFullscreenMode(SDL_Window *window, SDL_bool fullscreen)
if (_this->SetWindowFullscreen) {
_this->SetWindowFullscreen(_this, window, display, SDL_FALSE);
+ } else {
+ resized = SDL_TRUE;
}
display->fullscreen_window = NULL;
- /* Generate a mode change event here */
- SDL_OnWindowResized(window);
+ if (!resized) {
+ /* Generate a mode change event here */
+ SDL_OnWindowResized(window);
+ } else {
+ SDL_SendWindowEvent(window, SDL_WINDOWEVENT_RESIZED,
+ window->windowed.w, window->windowed.h);
+ }
/* Restore the cursor position */
SDL_RestoreMousePosition(window);
@@ -2473,6 +2483,9 @@ void SDL_ShowWindow(SDL_Window *window)
if (_this->ShowWindow) {
_this->ShowWindow(_this, window);
+ } else {
+ SDL_SetMouseFocus(window);
+ SDL_SetKeyboardFocus(window);
}
SDL_SendWindowEvent(window, SDL_WINDOWEVENT_SHOWN, 0, 0);
}
@@ -2490,6 +2503,9 @@ void SDL_HideWindow(SDL_Window *window)
if (_this->HideWindow) {
_this->HideWindow(_this, window);
+ } else {
+ SDL_SetMouseFocus(NULL);
+ SDL_SetKeyboardFocus(NULL);
}
window->is_hiding = SDL_FALSE;
SDL_SendWindowEvent(window, SDL_WINDOWEVENT_HIDDEN, 0, 0);
diff --git a/src/video/dummy/SDL_nullvideo.c b/src/video/dummy/SDL_nullvideo.c
index 109066d35901..41dcf1b84787 100644
--- a/src/video/dummy/SDL_nullvideo.c
+++ b/src/video/dummy/SDL_nullvideo.c
@@ -53,7 +53,6 @@
/* Initialization/Query functions */
static int DUMMY_VideoInit(_THIS);
-static int DUMMY_SetDisplayMode(_THIS, SDL_VideoDisplay *display, SDL_DisplayMode *mode);
static void DUMMY_VideoQuit(_THIS);
#if SDL_INPUT_LINUXEV
@@ -104,7 +103,6 @@ static SDL_VideoDevice *DUMMY_CreateDevice(void)
/* Set the function pointers */
device->VideoInit = DUMMY_VideoInit;
device->VideoQuit = DUMMY_VideoQuit;
- device->SetDisplayMode = DUMMY_SetDisplayMode;
device->PumpEvents = DUMMY_PumpEvents;
#if SDL_INPUT_LINUXEV
if (evdev) {
@@ -149,7 +147,7 @@ int DUMMY_VideoInit(_THIS)
mode.format = SDL_PIXELFORMAT_RGB888;
mode.w = 1024;
mode.h = 768;
- mode.refresh_rate = 0;
+ mode.refresh_rate = 60;
mode.driverdata = NULL;
if (SDL_AddBasicVideoDisplay(&mode) < 0) {
return -1;
@@ -165,11 +163,6 @@ int DUMMY_VideoInit(_THIS)
return 0;
}
-static int DUMMY_SetDisplayMode(_THIS, SDL_VideoDisplay *display, SDL_DisplayMode *mode)
-{
- return 0;
-}
-
void DUMMY_VideoQuit(_THIS)
{
#if SDL_INPUT_LINUXEV
diff --git a/test/testautomation_video.c b/test/testautomation_video.c
index aa9e7b92b360..b8e548b26f5a 100644
--- a/test/testautomation_video.c
+++ b/test/testautomation_video.c
@@ -278,6 +278,8 @@ int video_createWindowVariousFlags(void *arg)
break;
case 2:
flags = SDL_WINDOW_OPENGL;
+ /* Skip - not every video driver supports OpenGL; comment out next line to run test */
+ continue;
break;
case 3:
flags = SDL_WINDOW_SHOWN;