SDL: [KMSDRM] Improve cursor management.

From 100166d7d7b9ed2e486841498bbc585975630e02 Mon Sep 17 00:00:00 2001
From: vanfanel <[EMAIL REDACTED]>
Date: Mon, 22 Mar 2021 18:00:41 +0100
Subject: [PATCH] [KMSDRM] Improve cursor management.

---
 src/video/kmsdrm/SDL_kmsdrmmouse.c | 26 ++++++-----------------
 src/video/kmsdrm/SDL_kmsdrmvideo.c | 33 +++++++++---------------------
 src/video/kmsdrm/SDL_kmsdrmvideo.h |  2 +-
 3 files changed, 17 insertions(+), 44 deletions(-)

diff --git a/src/video/kmsdrm/SDL_kmsdrmmouse.c b/src/video/kmsdrm/SDL_kmsdrmmouse.c
index 334f54478..57cb35c75 100644
--- a/src/video/kmsdrm/SDL_kmsdrmmouse.c
+++ b/src/video/kmsdrm/SDL_kmsdrmmouse.c
@@ -341,24 +341,6 @@ KMSDRM_CreateCursor(SDL_Surface * surface, int hot_x, int hot_y)
     return ret;
 }
 
-/* When we create a window, we have to test if we have to show the cursor,
-   and explicily do so if necessary.
-   This is because when we destroy a window, we take the cursor away from the
-   cursor plane, and destroy the cusror GBM BO. So we have to re-show it,
-   so to say. */
-void
-KMSDRM_InitCursor()
-{
-    SDL_Mouse *mouse = SDL_GetMouse();
-
-    if (!mouse || !mouse->cur_cursor || !mouse->cursor_shown) {
-        return;
-    }
-
-    /* Re-dump cursor buffer to the GBM BO of the focused window display. */
-    KMSDRM_ShowCursor(mouse->cur_cursor);
-}
-
 /* Show the specified cursor, or hide if cursor is NULL or has no focus. */
 static int
 KMSDRM_ShowCursor(SDL_Cursor * cursor)
@@ -477,8 +459,12 @@ KMSDRM_InitMouse(_THIS, SDL_VideoDisplay *display)
     mouse->WarpMouse = KMSDRM_WarpMouse;
     mouse->WarpMouseGlobal = KMSDRM_WarpMouseGlobal;
 
-    SDL_SetDefaultCursor(KMSDRM_CreateDefaultCursor());
-    dispdata->set_default_cursor_pending = SDL_FALSE;
+    /* Only create the default cursor for this display if we haven't done so before,
+       we don't want several cursors to be created for the same display. */
+    if (!dispdata->default_cursor_init) {
+        SDL_SetDefaultCursor(KMSDRM_CreateDefaultCursor());
+        dispdata->default_cursor_init = SDL_TRUE;
+    }
 }
 
 void
diff --git a/src/video/kmsdrm/SDL_kmsdrmvideo.c b/src/video/kmsdrm/SDL_kmsdrmvideo.c
index da9967102..4d1bc7ae6 100644
--- a/src/video/kmsdrm/SDL_kmsdrmvideo.c
+++ b/src/video/kmsdrm/SDL_kmsdrmvideo.c
@@ -540,7 +540,7 @@ void KMSDRM_AddDisplay (_THIS, drmModeConnector *connector, drmModeRes *resource
        if the display used by the window already has a default cursor or not.
        If we don't, new default cursors would stack up on mouse->cursors and SDL
        would have to hide and delete them at quit, not to mention the memory leak... */
-    dispdata->set_default_cursor_pending = SDL_TRUE;
+    dispdata->default_cursor_init = SDL_FALSE;
 
     /* Try to find the connector's current encoder */
     for (i = 0; i < resources->count_encoders; i++) {
@@ -1081,7 +1081,7 @@ KMSDRM_DestroyWindow(_THIS, SDL_Window *window)
 
     if ( !is_vulkan && viddata->gbm_init) {
 
-        /* Destroy the window display's cursor GBM BO. */
+        /* Destroy cursor GBM BO of the display of this window. */
         KMSDRM_DestroyCursorBO(_this, SDL_GetDisplayForWindow(window));
 
         /* Destroy GBM surface and buffers. */
@@ -1207,27 +1207,13 @@ KMSDRM_CreateWindow(_THIS, SDL_Window * window)
 
 	}
 
-        /* Init the cursor stuff for the window display, but ONLY if we haven't done so
-           on this display before. */
-        if (!dispdata->set_default_cursor_pending) {
+	/* Create the cursor BO for the display of this window,
+	   now that we know this is not a VK window. */
+	KMSDRM_CreateCursorBO(display);
 
-	    /* Create the cursor BO for the display of this window,
-               now that we know this is not a VK window. */
-            KMSDRM_CreateCursorBO(display);
-
-            /* Create and set the default cursor now that we know
-               this is not a VK window. */
-            KMSDRM_InitMouse(_this, display);
-
-            /* When we destroy a window, we remove the cursor buffer from
-               the cursor plane and destroy the cursor GBM BO, but SDL expects
-               that we keep showing the visible cursors bewteen window
-               destruction/creation cycles. So we must manually re-show the
-               visible cursors, if necessary, when we create a window. */
-            KMSDRM_InitCursor();
-
-            dispdata->set_default_cursor_pending = SDL_TRUE;
-        }
+	/* Create and set the default cursor for the display
+           of this window, now that we know this is not a VK window. */
+	KMSDRM_InitMouse(_this, display);
 
         /* The FULLSCREEN flags are cut out from window->flags at this point,
            so we can't know if a window is fullscreen or not, hence all windows
@@ -1283,7 +1269,8 @@ KMSDRM_CreateWindow(_THIS, SDL_Window * window)
     /* If we have just created a Vulkan window, establish that we are in Vulkan mode now. */
     viddata->vulkan_mode = is_vulkan;
 
-    /* Focus on the newly created window */
+    /* Focus on the newly created window.
+       SDL_SetMouseFocus() also takes care of calling KMSDRM_ShowCursor() if necessary. */
     SDL_SetMouseFocus(window);
     SDL_SetKeyboardFocus(window);
 
diff --git a/src/video/kmsdrm/SDL_kmsdrmvideo.h b/src/video/kmsdrm/SDL_kmsdrmvideo.h
index f6f8410f8..1006ee99c 100644
--- a/src/video/kmsdrm/SDL_kmsdrmvideo.h
+++ b/src/video/kmsdrm/SDL_kmsdrmvideo.h
@@ -79,7 +79,7 @@ typedef struct SDL_DisplayData
     struct gbm_bo *cursor_bo;
     uint64_t cursor_w, cursor_h;
 
-    SDL_bool set_default_cursor_pending;
+    SDL_bool default_cursor_init;
     SDL_bool modeset_pending;
 
 } SDL_DisplayData;