Skip to content

Commit

Permalink
Wayland: Reconnect using the new approach using a new wl_display
Browse files Browse the repository at this point in the history
In the case of a reconnect, application code is notified via
SDL_EVENT_RENDER_DEVICE_RESET.
  • Loading branch information
davidedmundson committed Sep 17, 2023
1 parent 52efefc commit c73d1a5
Show file tree
Hide file tree
Showing 6 changed files with 49 additions and 33 deletions.
9 changes: 0 additions & 9 deletions src/events/SDL_mouse.c
Original file line number Diff line number Diff line change
Expand Up @@ -292,14 +292,6 @@ SDL_Window *SDL_GetMouseFocus(void)
return mouse->focus;
}

/* TODO RECONNECT: Hello from the Wayland video driver!
* This was once removed from SDL, but it's been added back in comment form
* because we will need it when Wayland adds compositor reconnect support.
* If you need this before we do, great! Otherwise, leave this alone, we'll
* uncomment it at the right time.
* -flibit
*/
#if 0
void SDL_ResetMouse(void)
{
SDL_Mouse *mouse = SDL_GetMouse();
Expand All @@ -313,7 +305,6 @@ void SDL_ResetMouse(void)
}
SDL_assert(GetButtonState(mouse, SDL_FALSE) == 0);
}
#endif /* 0 */

void SDL_SetMouseFocus(SDL_Window *window)
{
Expand Down
3 changes: 0 additions & 3 deletions src/events/SDL_mouse_c.h
Original file line number Diff line number Diff line change
Expand Up @@ -158,10 +158,7 @@ extern int SDL_SendMouseWheel(Uint64 timestamp, SDL_Window *window, SDL_MouseID
/* Warp the mouse within the window, potentially overriding relative mode */
extern void SDL_PerformWarpMouseInWindow(SDL_Window *window, float x, float y, SDL_bool ignore_relative_mode);

/* TODO RECONNECT: Set mouse state to "zero" */
#if 0
extern void SDL_ResetMouse(void);
#endif /* 0 */

/* Shutdown the mouse subsystem */
extern void SDL_QuitMouse(void);
Expand Down
9 changes: 8 additions & 1 deletion src/video/wayland/SDL_waylandevents.c
Original file line number Diff line number Diff line change
Expand Up @@ -475,7 +475,14 @@ void Wayland_PumpEvents(SDL_VideoDevice *_this)
*
* Try to recover once, then quit.
*/
if (!Wayland_VideoReconnect(_this)) {
int errCode = WAYLAND_wl_display_get_error(d->display);
SDL_bool reconnected = SDL_FALSE;

if (SDL_getenv("SDL_VIDEO_WAYLAND_RECONNECT") && (errCode == EPIPE || errCode == ECONNRESET)) {
reconnected = Wayland_VideoReconnect(_this);
}

if (!reconnected) {
d->display_disconnected = 1;

/* Only send a single quit message, as application shutdown might call
Expand Down
2 changes: 0 additions & 2 deletions src/video/wayland/SDL_waylandmouse.c
Original file line number Diff line number Diff line change
Expand Up @@ -696,7 +696,6 @@ static Uint32 SDLCALL Wayland_GetGlobalMouseState(float *x, float *y)
return ret;
}

#if 0 /* TODO RECONNECT: See waylandvideo.c for more information! */
static void Wayland_RecreateCursor(SDL_Cursor *cursor, SDL_VideoData *vdata)
{
Wayland_CursorData *cdata = (Wayland_CursorData *) cursor->driverdata;
Expand Down Expand Up @@ -750,7 +749,6 @@ void Wayland_RecreateCursors(void)
}
}
}
#endif /* 0 */

void Wayland_InitMouse(void)
{
Expand Down
2 changes: 0 additions & 2 deletions src/video/wayland/SDL_waylandmouse.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,6 @@

extern void Wayland_InitMouse(void);
extern void Wayland_FiniMouse(SDL_VideoData *data);
#if 0 /* TODO RECONNECT: See waylandvideo.c for more information! */
extern void Wayland_RecreateCursors(void);
#endif /* 0 */

#endif
57 changes: 41 additions & 16 deletions src/video/wayland/SDL_waylandvideo.c
Original file line number Diff line number Diff line change
Expand Up @@ -888,7 +888,9 @@ int Wayland_VideoInit(SDL_VideoDevice *_this)
wl_registry_add_listener(data->registry, &registry_listener, data);

// First roundtrip to receive all registry objects.
WAYLAND_wl_display_roundtrip(data->display);
if (WAYLAND_wl_display_roundtrip(data->display) < 0) {
return SDL_SetError("Failed to load Wayland initial globals");
}

/* Now that we have all the protocols, load libdecor if applicable */
Wayland_LoadLibdecor(data, SDL_FALSE);
Expand Down Expand Up @@ -1047,49 +1049,72 @@ static void Wayland_VideoCleanup(SDL_VideoDevice *_this)

SDL_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->driverdata;

SDL_Window *window = NULL;

SDL_GLContext current_ctx = SDL_GL_GetCurrentContext();
SDL_Window *current_window = SDL_GL_GetCurrentWindow();
struct wl_display *new_display = WAYLAND_wl_display_connect(NULL);
struct wl_display *old_display = data->display;

SDL_Event event;

if (!new_display) {
return SDL_FALSE;
}
if (WAYLAND_wl_display_roundtrip(new_display) < 0) {
WAYLAND_wl_display_disconnect(new_display);
return SDL_FALSE;
}

SDL_GL_MakeCurrent(NULL, NULL);

Wayland_VideoCleanup(_this);

window = _this->windows;
while (window) {
SDL_free(window->outputs);
window->outputs = NULL;
window = window->next;
}

SDL_ResetKeyboard();
SDL_ResetMouse();
if (WAYLAND_wl_display_reconnect(data->display) < 0) {

data->display = new_display;
data->initializing = SDL_TRUE;

if (Wayland_VideoInit(_this) != 0) {
return SDL_FALSE;
}

Wayland_VideoInit(_this);

/* When EGL supports migrating displays across connections we need to
* enable the following code.
*/
#if 0
window = _this->windows;
while (window) {
/* We're going to cheat _just_ for a second and strip the OpenGL flag.
/*
* We're going to cheat _just_ for a second and strip the OpenGL flag.
* The Wayland driver actually forces it in CreateWindow, and
* RecreateWindow does a bunch of unloading/loading of libGL, so just
* strip the flag so RecreateWindow doesn't mess with the GL context,
* and CreateWindow will add it right back!
* -flibit
* window->flags &= ~SDL_WINDOW_OPENGL;
*/
window->flags &= ~SDL_WINDOW_OPENGL;

SDL_RecreateWindow(window, window->flags);
window = window->next;
}
#endif

event.type = SDL_EVENT_RENDER_DEVICE_RESET;
SDL_PushEvent(&event);

Wayland_RecreateCursors();

if (current_window && current_ctx) {
SDL_GL_MakeCurrent (current_window, current_ctx);
}
WAYLAND_wl_display_disconnect(old_display);

return SDL_TRUE;
#else
return SDL_FALSE;
#endif /* 0 */
}

void Wayland_VideoQuit(SDL_VideoDevice *_this)
Expand Down

0 comments on commit c73d1a5

Please sign in to comment.