wayland: Use libdecor visibility toggle for hiding/showing the window

The current method of toggling the libdecor window visibility by destroying and recreating the frame results in a race where a use-after-free bug can manifest itself within libdecor when window visibility is toggled quickly. Instead, use the libdecor function for toggling visibility instead of destroying and recreating the frame every time.
main
Frank Praznik 2022-08-06 12:31:06 -04:00 committed by Sam Lantinga
parent fbb440d167
commit dd2e318211
1 changed files with 14 additions and 10 deletions

View File

@ -1228,6 +1228,10 @@ void Wayland_ShowWindow(_THIS, SDL_Window *window)
/* Create the shell surface and map the toplevel/popup */ /* Create the shell surface and map the toplevel/popup */
#ifdef HAVE_LIBDECOR_H #ifdef HAVE_LIBDECOR_H
if (WINDOW_IS_LIBDECOR(c, window)) { if (WINDOW_IS_LIBDECOR(c, window)) {
if (data->shell_surface.libdecor.frame) {
/* If the frame already exists, just set the visibility. */
libdecor_frame_set_visibility(data->shell_surface.libdecor.frame, true);
} else {
data->shell_surface.libdecor.frame = libdecor_decorate(c->shell.libdecor, data->shell_surface.libdecor.frame = libdecor_decorate(c->shell.libdecor,
data->surface, data->surface,
&libdecor_frame_interface, &libdecor_frame_interface,
@ -1238,6 +1242,7 @@ void Wayland_ShowWindow(_THIS, SDL_Window *window)
libdecor_frame_set_app_id(data->shell_surface.libdecor.frame, c->classname); libdecor_frame_set_app_id(data->shell_surface.libdecor.frame, c->classname);
libdecor_frame_map(data->shell_surface.libdecor.frame); libdecor_frame_map(data->shell_surface.libdecor.frame);
} }
}
} else } else
#endif #endif
if (c->shell.xdg) { if (c->shell.xdg) {
@ -1425,8 +1430,7 @@ void Wayland_HideWindow(_THIS, SDL_Window *window)
#ifdef HAVE_LIBDECOR_H #ifdef HAVE_LIBDECOR_H
if (WINDOW_IS_LIBDECOR(data, window)) { if (WINDOW_IS_LIBDECOR(data, window)) {
if (wind->shell_surface.libdecor.frame) { if (wind->shell_surface.libdecor.frame) {
libdecor_frame_unref(wind->shell_surface.libdecor.frame); libdecor_frame_set_visibility(wind->shell_surface.libdecor.frame, false);
wind->shell_surface.libdecor.frame = NULL;
} }
} else } else
#endif #endif