SDL: wayland: Fix memory leaks

From fb68e8464638976e13c6a31eb8d3a7884e4b833e Mon Sep 17 00:00:00 2001
From: Frank Praznik <[EMAIL REDACTED]>
Date: Sun, 30 Jul 2023 11:58:50 -0400
Subject: [PATCH] wayland: Fix memory leaks

Fix some memory leaks reported by Valgrind due to not destroying objects.
---
 src/video/wayland/SDL_waylandevents.c | 20 ++++++++++++++++++--
 src/video/wayland/SDL_waylandvideo.c  |  4 ++++
 2 files changed, 22 insertions(+), 2 deletions(-)

diff --git a/src/video/wayland/SDL_waylandevents.c b/src/video/wayland/SDL_waylandevents.c
index 87b3c05863f9..9ee285f899f1 100644
--- a/src/video/wayland/SDL_waylandevents.c
+++ b/src/video/wayland/SDL_waylandevents.c
@@ -311,12 +311,25 @@ static SDL_bool keyboard_repeat_key_is_set(SDL_WaylandKeyboardRepeat *repeat_inf
     return repeat_info->is_initialized && repeat_info->is_key_down && key == repeat_info->key;
 }
 
+static void sync_done_handler(void *data, struct wl_callback *callback, uint32_t callback_data)
+{
+    /* Nothing to do, just destroy the callback */
+    wl_callback_destroy(callback);
+}
+
+static struct wl_callback_listener sync_listener = {
+    sync_done_handler
+};
+
 void Wayland_SendWakeupEvent(SDL_VideoDevice *_this, SDL_Window *window)
 {
     SDL_VideoData *d = _this->driverdata;
 
-    /* TODO: Maybe use a pipe to avoid the compositor roundtrip? */
-    wl_display_sync(d->display);
+    /* Queue a sync event to unblock the event queue fd if it's empty and being waited on.
+     * TODO: Maybe use a pipe to avoid the compositor roundtrip?
+     */
+    struct wl_callback *cb = wl_display_sync(d->display);
+    wl_callback_add_listener(cb, &sync_listener, NULL);
     WAYLAND_wl_display_flush(d->display);
 }
 
@@ -2705,6 +2718,9 @@ void Wayland_display_destroy_input(SDL_VideoData *d)
         if (input->primary_selection_device->selection_source != NULL) {
             Wayland_primary_selection_source_destroy(input->primary_selection_device->selection_source);
         }
+        if (input->primary_selection_device->primary_selection_device != NULL) {
+            zwp_primary_selection_device_v1_destroy(input->primary_selection_device->primary_selection_device);
+        }
         SDL_free(input->primary_selection_device);
     }
 
diff --git a/src/video/wayland/SDL_waylandvideo.c b/src/video/wayland/SDL_waylandvideo.c
index cc95df21fe9f..2cd4495e48a6 100644
--- a/src/video/wayland/SDL_waylandvideo.c
+++ b/src/video/wayland/SDL_waylandvideo.c
@@ -672,6 +672,10 @@ static void Wayland_free_display(SDL_VideoDisplay *display)
         SDL_DisplayData *display_data = display->driverdata;
         int i;
 
+        if (display_data->xdg_output) {
+            zxdg_output_v1_destroy(display_data->xdg_output);
+        }
+
         if (wl_output_get_version(display_data->output) >= WL_OUTPUT_RELEASE_SINCE_VERSION) {
             wl_output_release(display_data->output);
         } else {