diff --git a/src/video/wayland/SDL_waylandvideo.c b/src/video/wayland/SDL_waylandvideo.c index 5a32d8a74..ea5e5b283 100644 --- a/src/video/wayland/SDL_waylandvideo.c +++ b/src/video/wayland/SDL_waylandvideo.c @@ -249,10 +249,10 @@ display_handle_geometry(void *data, int transform) { - SDL_VideoDisplay *display = data; + SDL_WaylandOutputData *driverdata = data; - display->name = SDL_strdup(model); - ((SDL_WaylandOutputData*)display->driverdata)->transform = transform; + driverdata->placeholder.name = SDL_strdup(model); + driverdata->transform = transform; } static void @@ -263,8 +263,7 @@ display_handle_mode(void *data, int height, int refresh) { - SDL_VideoDisplay *display = data; - SDL_WaylandOutputData* driverdata = display->driverdata; + SDL_WaylandOutputData* driverdata = data; SDL_DisplayMode mode; if (flags & WL_OUTPUT_MODE_CURRENT) { @@ -290,15 +289,14 @@ display_handle_mode(void *data, } mode.refresh_rate = refresh / 1000; /* mHz to Hz */ mode.driverdata = driverdata->output; - SDL_AddDisplayMode(display, &mode); + SDL_AddDisplayMode(&driverdata->placeholder, &mode); } static void display_handle_done(void *data, struct wl_output *output) { - SDL_VideoDisplay *display = data; - SDL_WaylandOutputData* driverdata = display->driverdata; + SDL_WaylandOutputData* driverdata = data; SDL_DisplayMode mode; if (driverdata->done) @@ -317,12 +315,13 @@ display_handle_done(void *data, } mode.refresh_rate = driverdata->refresh / 1000; /* mHz to Hz */ mode.driverdata = driverdata->output; - SDL_AddDisplayMode(display, &mode); - display->current_mode = mode; - display->desktop_mode = mode; + SDL_AddDisplayMode(&driverdata->placeholder, &mode); + driverdata->placeholder.current_mode = mode; + driverdata->placeholder.desktop_mode = mode; - SDL_AddVideoDisplay(display, SDL_FALSE); - SDL_free(display->name); + driverdata->placeholder.driverdata = driverdata; + SDL_AddVideoDisplay(&driverdata->placeholder, SDL_FALSE); + SDL_zero(driverdata->placeholder); } static void @@ -330,8 +329,8 @@ display_handle_scale(void *data, struct wl_output *output, int32_t factor) { - SDL_VideoDisplay *display = data; - ((SDL_WaylandOutputData*)display->driverdata)->scale_factor = factor; + SDL_WaylandOutputData *driverdata = data; + driverdata->scale_factor = factor; } static const struct wl_output_listener output_listener = { @@ -346,26 +345,18 @@ Wayland_add_display(SDL_VideoData *d, uint32_t id) { struct wl_output *output; SDL_WaylandOutputData *data; - SDL_VideoDisplay *display = SDL_malloc(sizeof *display); - if (!display) { - SDL_OutOfMemory(); - return; - } - SDL_zero(*display); output = wl_registry_bind(d->registry, id, &wl_output_interface, 2); if (!output) { SDL_SetError("Failed to retrieve output."); - SDL_free(display); return; } data = SDL_malloc(sizeof *data); + SDL_zerop(data); data->output = output; data->scale_factor = 1.0; - data->done = SDL_FALSE; - display->driverdata = data; - wl_output_add_listener(output, &output_listener, display); + wl_output_add_listener(output, &output_listener, data); } #ifdef SDL_VIDEO_DRIVER_WAYLAND_QT_TOUCH diff --git a/src/video/wayland/SDL_waylandvideo.h b/src/video/wayland/SDL_waylandvideo.h index 7f5a60ae1..1c01dfd9d 100644 --- a/src/video/wayland/SDL_waylandvideo.h +++ b/src/video/wayland/SDL_waylandvideo.h @@ -39,6 +39,7 @@ #include #include "wayland-util.h" +#include "../SDL_sysvideo.h" #include "../../core/linux/SDL_dbus.h" #include "../../core/linux/SDL_ime.h" @@ -93,6 +94,7 @@ typedef struct { struct wl_output *output; float scale_factor; int width, height, refresh, transform; + SDL_VideoDisplay placeholder; SDL_bool done; } SDL_WaylandOutputData; diff --git a/src/video/wayland/SDL_waylandwindow.c b/src/video/wayland/SDL_waylandwindow.c index 7f9031081..a3029f033 100644 --- a/src/video/wayland/SDL_waylandwindow.c +++ b/src/video/wayland/SDL_waylandwindow.c @@ -467,8 +467,7 @@ update_scale_factor(SDL_WindowData *window) { } for (i = 0; i < window->num_outputs; i++) { - SDL_VideoDisplay *display = wl_output_get_user_data(window->outputs[i]); - SDL_WaylandOutputData* driverdata = display->driverdata; + SDL_WaylandOutputData* driverdata = wl_output_get_user_data(window->outputs[i]); float factor = driverdata->scale_factor; if (factor > new_factor) { new_factor = factor; @@ -487,26 +486,50 @@ update_scale_factor(SDL_WindowData *window) { } } +/* While we can't get window position from the compositor, we do at least know + * what monitor we're on, so let's send move events that put the window at the + * center of the whatever display the wl_surface_listener events give us. + */ +static void +Wayland_move_window(SDL_Window *window, + SDL_WaylandOutputData *driverdata) +{ + int i, numdisplays = SDL_GetNumVideoDisplays(); + for (i = 0; i < numdisplays; i += 1) { + if (SDL_GetDisplay(i)->driverdata == driverdata) { + SDL_SendWindowEvent(window, SDL_WINDOWEVENT_MOVED, + SDL_WINDOWPOS_CENTERED_DISPLAY(i), + SDL_WINDOWPOS_CENTERED_DISPLAY(i)); + break; + } + } +} + static void handle_surface_enter(void *data, struct wl_surface *surface, - struct wl_output *output) { + struct wl_output *output) +{ SDL_WindowData *window = data; window->outputs = SDL_realloc(window->outputs, (window->num_outputs + 1) * sizeof *window->outputs); window->outputs[window->num_outputs++] = output; update_scale_factor(window); + + Wayland_move_window(window->sdlwindow, wl_output_get_user_data(output)); } static void handle_surface_leave(void *data, struct wl_surface *surface, - struct wl_output *output) { + struct wl_output *output) +{ SDL_WindowData *window = data; - int i; + int i, send_move_event = 0; for (i = 0; i < window->num_outputs; i++) { if (window->outputs[i] == output) { /* remove this one */ if (i == (window->num_outputs-1)) { window->outputs[i] = NULL; + send_move_event = 1; } else { SDL_memmove(&window->outputs[i], &window->outputs[i+1], sizeof (output) * ((window->num_outputs - i) - 1)); } @@ -518,6 +541,9 @@ handle_surface_leave(void *data, struct wl_surface *surface, if (window->num_outputs == 0) { SDL_free(window->outputs); window->outputs = NULL; + } else if (send_move_event) { + Wayland_move_window(window->sdlwindow, + wl_output_get_user_data(window->outputs[window->num_outputs - 1])); } update_scale_factor(window);