diff --git a/src/video/wayland/SDL_waylandevents.c b/src/video/wayland/SDL_waylandevents.c index b69116a07e..ee1378dec2 100644 --- a/src/video/wayland/SDL_waylandevents.c +++ b/src/video/wayland/SDL_waylandevents.c @@ -671,20 +671,8 @@ void Wayland_PumpEvents(SDL_VideoDevice *_this) } connection_error: - if (ret < 0 && !d->display_disconnected) { - /* Something has failed with the Wayland connection -- for example, - * the compositor may have shut down and closed its end of the socket, - * or there is a library-specific error. - * - * Try to recover once, then quit. - */ - if (!Wayland_VideoReconnect(_this)) { - d->display_disconnected = 1; - SDL_LogError(SDL_LOG_CATEGORY_VIDEO, "Wayland display connection closed by server (fatal)"); - - // Only send a single quit message, as application shutdown might call SDL_PumpEvents(). - SDL_SendQuit(); - } + if (ret < 0) { + Wayland_HandleDisplayDisconnected(_this); } } diff --git a/src/video/wayland/SDL_waylandvideo.c b/src/video/wayland/SDL_waylandvideo.c index bddf90320c..848e43740a 100644 --- a/src/video/wayland/SDL_waylandvideo.c +++ b/src/video/wayland/SDL_waylandvideo.c @@ -1681,7 +1681,7 @@ static void Wayland_VideoCleanup(SDL_VideoDevice *_this) } } -bool Wayland_VideoReconnect(SDL_VideoDevice *_this) +static bool Wayland_VideoReconnect(SDL_VideoDevice *_this) { #if 0 // TODO RECONNECT: Uncomment all when https://invent.kde.org/plasma/kwin/-/wikis/Restarting is completed SDL_VideoData *data = _this->internal; @@ -1728,6 +1728,33 @@ bool Wayland_VideoReconnect(SDL_VideoDevice *_this) #endif // 0 } +bool Wayland_HandleDisplayDisconnected(SDL_VideoDevice *_this) +{ + SDL_VideoData *video_data = _this->internal; + + /* Something has failed with the Wayland connection -- for example, + * the compositor may have shut down and closed its end of the socket, + * or there is a library-specific error. + * + * Try to recover once, then quit. + */ + if (video_data->display_disconnected) { + return false; + } + + if (Wayland_VideoReconnect(_this)) { + return true; + } + + video_data->display_disconnected = true; + SDL_LogError(SDL_LOG_CATEGORY_VIDEO, "Wayland display connection closed by server (fatal)"); + + // Only send a single quit message, as application shutdown might call SDL_PumpEvents(). + SDL_SendQuit(); + + return false; +} + void Wayland_VideoQuit(SDL_VideoDevice *_this) { Wayland_VideoCleanup(_this); diff --git a/src/video/wayland/SDL_waylandvideo.h b/src/video/wayland/SDL_waylandvideo.h index e2ae097dec..bab5d51d92 100644 --- a/src/video/wayland/SDL_waylandvideo.h +++ b/src/video/wayland/SDL_waylandvideo.h @@ -48,9 +48,7 @@ typedef struct struct SDL_VideoData { - bool initializing; struct wl_display *display; - int display_disconnected; struct wl_registry *registry; struct wl_compositor *compositor; struct wl_shm *shm; @@ -99,6 +97,8 @@ struct SDL_VideoData int output_count; int output_max; + bool initializing; + bool display_disconnected; bool display_externally_owned; bool scale_to_display_enabled; }; @@ -140,6 +140,6 @@ struct wl_event_queue *Wayland_DisplayCreateQueue(struct wl_display *display, co extern bool Wayland_LoadLibdecor(SDL_VideoData *data, bool ignore_xdg); -extern bool Wayland_VideoReconnect(SDL_VideoDevice *_this); +extern bool Wayland_HandleDisplayDisconnected(SDL_VideoDevice *_this); #endif // SDL_waylandvideo_h_ diff --git a/src/video/wayland/SDL_waylandwindow.c b/src/video/wayland/SDL_waylandwindow.c index 7eb6d104af..5fddec7221 100644 --- a/src/video/wayland/SDL_waylandwindow.c +++ b/src/video/wayland/SDL_waylandwindow.c @@ -2036,8 +2036,16 @@ void Wayland_ShowWindow(SDL_VideoDevice *_this, SDL_Window *window) if (data->shell_surface_type == WAYLAND_SHELL_SURFACE_TYPE_LIBDECOR) { if (data->shell_surface.libdecor.frame) { while (data->shell_surface_status == WAYLAND_SHELL_SURFACE_STATUS_WAITING_FOR_CONFIGURE) { - libdecor_dispatch(c->shell.libdecor, -1); - WAYLAND_wl_display_dispatch_pending(c->display); + if (libdecor_dispatch(c->shell.libdecor, -1) < 0) { + if (!Wayland_HandleDisplayDisconnected(_this)) { + return; + } + } + if (WAYLAND_wl_display_dispatch_pending(c->display) < 0) { + if (!Wayland_HandleDisplayDisconnected(_this)) { + return; + } + } } } } else @@ -2050,7 +2058,11 @@ void Wayland_ShowWindow(SDL_VideoDevice *_this, SDL_Window *window) wl_surface_commit(data->surface); if (data->shell_surface.xdg.surface) { while (data->shell_surface_status == WAYLAND_SHELL_SURFACE_STATUS_WAITING_FOR_CONFIGURE) { - WAYLAND_wl_display_dispatch(c->display); + if (WAYLAND_wl_display_dispatch(c->display) < 0) { + if (!Wayland_HandleDisplayDisconnected(_this)) { + return; + } + } } } } else {