Commit e862856e6f8c56ec2d3aba5168c9b8b3958561a7

Sebastian Krzyszkowiak 2021-02-01T08:57:39

wayland: Don't crash when the properties of already existing wl_output change

diff --git a/src/video/wayland/SDL_waylandvideo.c b/src/video/wayland/SDL_waylandvideo.c
index e8315da..aec6cc2 100644
--- a/src/video/wayland/SDL_waylandvideo.c
+++ b/src/video/wayland/SDL_waylandvideo.c
@@ -273,11 +273,15 @@ static void
 display_handle_done(void *data,
                     struct wl_output *output)
 {
-    /* !!! FIXME: this will fail on any further property changes! */
     SDL_VideoDisplay *display = data;
     SDL_WaylandOutputData* driverdata = display->driverdata;
     SDL_DisplayMode mode;
 
+    if (driverdata->done)
+        return;
+
+    driverdata->done = SDL_TRUE;
+
     SDL_zero(mode);
     mode.format = SDL_PIXELFORMAT_RGB888;
     mode.w = driverdata->width / driverdata->scale_factor;
@@ -293,9 +297,7 @@ display_handle_done(void *data,
     display->desktop_mode = mode;
 
     SDL_AddVideoDisplay(display, SDL_FALSE);
-    wl_output_set_user_data(output, display->driverdata);
     SDL_free(display->name);
-    SDL_free(display);
 }
 
 static void
@@ -335,6 +337,7 @@ Wayland_add_display(SDL_VideoData *d, uint32_t id)
     data = SDL_malloc(sizeof *data);
     data->output = output;
     data->scale_factor = 1.0;
+    data->done = SDL_FALSE;
     display->driverdata = data;
 
     wl_output_add_listener(output, &output_listener, display);
diff --git a/src/video/wayland/SDL_waylandvideo.h b/src/video/wayland/SDL_waylandvideo.h
index 04083bf..3549474 100644
--- a/src/video/wayland/SDL_waylandvideo.h
+++ b/src/video/wayland/SDL_waylandvideo.h
@@ -20,6 +20,7 @@
 */
 
 #include "../../SDL_internal.h"
+#include "SDL_stdinc.h"
 
 #ifndef SDL_waylandvideo_h_
 #define SDL_waylandvideo_h_
@@ -91,6 +92,7 @@ typedef struct {
     struct wl_output *output;
     float scale_factor;
     int width, height, refresh, transform;
+    SDL_bool done;
 } SDL_WaylandOutputData;
 
 #endif /* SDL_waylandvideo_h_ */
diff --git a/src/video/wayland/SDL_waylandwindow.c b/src/video/wayland/SDL_waylandwindow.c
index ab158d2..fc43735 100644
--- a/src/video/wayland/SDL_waylandwindow.c
+++ b/src/video/wayland/SDL_waylandwindow.c
@@ -414,11 +414,15 @@ update_scale_factor(SDL_WindowData *window) {
    }
 
    if (FULLSCREEN_VISIBLE(window->sdlwindow) && window->sdlwindow->fullscreen_mode.driverdata) {
-       new_factor = ((SDL_WaylandOutputData*)(wl_output_get_user_data(window->sdlwindow->fullscreen_mode.driverdata)))->scale_factor;
+       SDL_VideoDisplay *display = wl_output_get_user_data(window->sdlwindow->fullscreen_mode.driverdata);
+       SDL_WaylandOutputData* driverdata = display->driverdata;
+       new_factor = driverdata->scale_factor;
    }
 
    for (i = 0; i < window->num_outputs; i++) {
-       float factor = ((SDL_WaylandOutputData*)(wl_output_get_user_data(window->outputs[i])))->scale_factor;
+       SDL_VideoDisplay *display = wl_output_get_user_data(window->outputs[i]);
+       SDL_WaylandOutputData* driverdata = display->driverdata;
+       float factor = driverdata->scale_factor;
        if (factor > new_factor) {
            new_factor = factor;
        }