mirror of https://github.com/libsdl-org/SDL.git
wayland: Remove all references to destroyed outputs from windows
The removal of a wl_output may not be accompanied by leave events for the surfaces present on it. Ensure that no window continues to hold a reference to a removed output.
This commit is contained in:
parent
9a65d123a7
commit
9eaf7d8cc8
|
|
@ -732,6 +732,7 @@ static void Wayland_free_display(SDL_VideoData *d, uint32_t id)
|
|||
int num_displays = SDL_GetNumVideoDisplays();
|
||||
SDL_VideoDisplay *display;
|
||||
SDL_WaylandOutputData *data;
|
||||
SDL_Window *window;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < num_displays; i += 1) {
|
||||
|
|
@ -751,6 +752,14 @@ static void Wayland_free_display(SDL_VideoData *d, uint32_t id)
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Surface leave events may be implicit when an output is destroyed, so make sure that
|
||||
* no windows retain a reference to a destroyed output.
|
||||
*/
|
||||
for (window = SDL_GetVideoDevice()->windows; window; window = window->next) {
|
||||
Wayland_RemoveOutputFromWindow(window->driverdata, data->output);
|
||||
}
|
||||
|
||||
SDL_DelVideoDisplay(i);
|
||||
if (data->xdg_output) {
|
||||
zxdg_output_v1_destroy(data->xdg_output);
|
||||
|
|
|
|||
|
|
@ -1098,39 +1098,11 @@ static void Wayland_move_window(SDL_Window *window,
|
|||
}
|
||||
}
|
||||
|
||||
static void handle_surface_enter(void *data, struct wl_surface *surface,
|
||||
struct wl_output *output)
|
||||
void Wayland_RemoveOutputFromWindow(SDL_WindowData *window, struct wl_output *output)
|
||||
{
|
||||
SDL_WindowData *window = data;
|
||||
SDL_WaylandOutputData *driverdata = wl_output_get_user_data(output);
|
||||
|
||||
if (!SDL_WAYLAND_own_output(output) || !SDL_WAYLAND_own_surface(surface)) {
|
||||
return;
|
||||
}
|
||||
|
||||
window->outputs = SDL_realloc(window->outputs,
|
||||
sizeof(SDL_WaylandOutputData *) * (window->num_outputs + 1));
|
||||
window->outputs[window->num_outputs++] = driverdata;
|
||||
|
||||
/* Update the scale factor after the move so that fullscreen outputs are updated. */
|
||||
Wayland_move_window(window->sdlwindow, driverdata);
|
||||
|
||||
if (!window->fractional_scale) {
|
||||
update_scale_factor(window);
|
||||
}
|
||||
}
|
||||
|
||||
static void handle_surface_leave(void *data, struct wl_surface *surface,
|
||||
struct wl_output *output)
|
||||
{
|
||||
SDL_WindowData *window = data;
|
||||
int i, send_move_event = 0;
|
||||
SDL_WaylandOutputData *driverdata = wl_output_get_user_data(output);
|
||||
|
||||
if (!SDL_WAYLAND_own_output(output) || !SDL_WAYLAND_own_surface(surface)) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (i = 0; i < window->num_outputs; i++) {
|
||||
if (window->outputs[i] == driverdata) { /* remove this one */
|
||||
if (i == (window->num_outputs - 1)) {
|
||||
|
|
@ -1159,6 +1131,40 @@ static void handle_surface_leave(void *data, struct wl_surface *surface,
|
|||
}
|
||||
}
|
||||
|
||||
static void handle_surface_enter(void *data, struct wl_surface *surface,
|
||||
struct wl_output *output)
|
||||
{
|
||||
SDL_WindowData *window = data;
|
||||
SDL_WaylandOutputData *driverdata = wl_output_get_user_data(output);
|
||||
|
||||
if (!SDL_WAYLAND_own_output(output) || !SDL_WAYLAND_own_surface(surface)) {
|
||||
return;
|
||||
}
|
||||
|
||||
window->outputs = SDL_realloc(window->outputs,
|
||||
sizeof(SDL_WaylandOutputData *) * (window->num_outputs + 1));
|
||||
window->outputs[window->num_outputs++] = driverdata;
|
||||
|
||||
/* Update the scale factor after the move so that fullscreen outputs are updated. */
|
||||
Wayland_move_window(window->sdlwindow, driverdata);
|
||||
|
||||
if (!window->fractional_scale) {
|
||||
update_scale_factor(window);
|
||||
}
|
||||
}
|
||||
|
||||
static void handle_surface_leave(void *data, struct wl_surface *surface,
|
||||
struct wl_output *output)
|
||||
{
|
||||
SDL_WindowData *window = (SDL_WindowData *)data;
|
||||
|
||||
if (!SDL_WAYLAND_own_output(output) || !SDL_WAYLAND_own_surface(surface)) {
|
||||
return;
|
||||
}
|
||||
|
||||
Wayland_RemoveOutputFromWindow(window, output);
|
||||
}
|
||||
|
||||
static const struct wl_surface_listener surface_listener = {
|
||||
handle_surface_enter,
|
||||
handle_surface_leave
|
||||
|
|
|
|||
|
|
@ -146,6 +146,7 @@ extern SDL_bool
|
|||
Wayland_GetWindowWMInfo(_THIS, SDL_Window * window, SDL_SysWMinfo * info);
|
||||
extern int Wayland_SetWindowHitTest(SDL_Window *window, SDL_bool enabled);
|
||||
extern int Wayland_FlashWindow(_THIS, SDL_Window *window, SDL_FlashOperation operation);
|
||||
extern void Wayland_RemoveOutputFromWindow(SDL_WindowData *window, struct wl_output *output);
|
||||
|
||||
extern void Wayland_InitWin(SDL_VideoData *data);
|
||||
extern void Wayland_QuitWin(SDL_VideoData *data);
|
||||
|
|
|
|||
Loading…
Reference in New Issue