Skip to content

Commit ecdc6f2

Browse files
committed
wayland: Ensure that the xdg_surface is always configured after creation
The spec states that xdg_surface must have seen an initial configure event before attaching a buffer, however, this was only being done when initially showing the window, and not after show->hide->show cycle. Always wait for the initial configure event when (re)creating an xdg_surface as part of the show window sequence.
1 parent 7c11a8c commit ecdc6f2

File tree

2 files changed

+23
-33
lines changed

2 files changed

+23
-33
lines changed

src/video/wayland/SDL_waylandwindow.c

Lines changed: 23 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -181,7 +181,7 @@ static void SetMinMaxDimensions(SDL_Window *window)
181181

182182
#ifdef HAVE_LIBDECOR_H
183183
if (wind->shell_surface_type == WAYLAND_SHELL_SURFACE_TYPE_LIBDECOR) {
184-
if (!wind->shell_surface.libdecor.initial_configure_seen || !wind->shell_surface.libdecor.frame) {
184+
if (!wind->shell_surface.libdecor.frame) {
185185
return; // Can't do anything yet, wait for ShowWindow
186186
}
187187
/* No need to change these values if the window is non-resizable,
@@ -198,7 +198,7 @@ static void SetMinMaxDimensions(SDL_Window *window)
198198
} else
199199
#endif
200200
if (wind->shell_surface_type == WAYLAND_SHELL_SURFACE_TYPE_XDG_TOPLEVEL) {
201-
if (wind->shell_surface.xdg.toplevel.xdg_toplevel == NULL) {
201+
if (!wind->shell_surface.xdg.toplevel.xdg_toplevel) {
202202
return; // Can't do anything yet, wait for ShowWindow
203203
}
204204
xdg_toplevel_set_min_size(wind->shell_surface.xdg.toplevel.xdg_toplevel,
@@ -750,7 +750,9 @@ static void handle_configure_xdg_shell_surface(void *data, struct xdg_surface *x
750750
xdg_surface_ack_configure(xdg, serial);
751751
}
752752

753-
wind->shell_surface.xdg.initial_configure_seen = true;
753+
if (wind->shell_surface_status == WAYLAND_SHELL_SURFACE_STATUS_WAITING_FOR_CONFIGURE) {
754+
wind->shell_surface_status = WAYLAND_SHELL_SURFACE_STATUS_WAITING_FOR_FRAME;
755+
}
754756
}
755757

756758
static const struct xdg_surface_listener shell_surface_listener_xdg = {
@@ -980,10 +982,6 @@ static void handle_configure_xdg_toplevel(void *data,
980982
wind->active = active;
981983
window->tiled = tiled;
982984
wind->resizing = resizing;
983-
984-
if (wind->shell_surface_status == WAYLAND_SHELL_SURFACE_STATUS_WAITING_FOR_CONFIGURE) {
985-
wind->shell_surface_status = WAYLAND_SHELL_SURFACE_STATUS_WAITING_FOR_FRAME;
986-
}
987985
}
988986

989987
static void handle_close_xdg_toplevel(void *data, struct xdg_toplevel *xdg_toplevel)
@@ -1132,9 +1130,7 @@ static void handle_configure_zxdg_decoration(void *data,
11321130
WAYLAND_wl_display_roundtrip(internal->waylandData->display);
11331131

11341132
Wayland_HideWindow(device, window);
1135-
SDL_zero(internal->shell_surface);
11361133
internal->shell_surface_type = WAYLAND_SHELL_SURFACE_TYPE_LIBDECOR;
1137-
11381134
Wayland_ShowWindow(device, window);
11391135
}
11401136
}
@@ -1417,11 +1413,8 @@ static void decoration_frame_configure(struct libdecor_frame *frame,
14171413
libdecor_state_free(state);
14181414
}
14191415

1420-
if (!wind->shell_surface.libdecor.initial_configure_seen) {
1421-
LibdecorGetMinContentSize(frame, &wind->system_limits.min_width, &wind->system_limits.min_height);
1422-
wind->shell_surface.libdecor.initial_configure_seen = true;
1423-
}
14241416
if (wind->shell_surface_status == WAYLAND_SHELL_SURFACE_STATUS_WAITING_FOR_CONFIGURE) {
1417+
LibdecorGetMinContentSize(frame, &wind->system_limits.min_width, &wind->system_limits.min_height);
14251418
wind->shell_surface_status = WAYLAND_SHELL_SURFACE_STATUS_WAITING_FOR_FRAME;
14261419
}
14271420

@@ -1830,12 +1823,10 @@ void Wayland_ShowWindow(SDL_VideoDevice *_this, SDL_Window *window)
18301823
}
18311824
}
18321825

1833-
/* The window was hidden, but the sync point hasn't yet been reached.
1834-
* Pump events to avoid a possible protocol violation.
1835-
*/
1836-
if (data->show_hide_sync_required) {
1826+
// Always roundtrip to ensure there are no pending buffer attachments.
1827+
do {
18371828
WAYLAND_wl_display_roundtrip(c->display);
1838-
}
1829+
} while (data->show_hide_sync_required);
18391830

18401831
data->shell_surface_status = WAYLAND_SHELL_SURFACE_STATUS_WAITING_FOR_CONFIGURE;
18411832

@@ -1996,7 +1987,7 @@ void Wayland_ShowWindow(SDL_VideoDevice *_this, SDL_Window *window)
19961987
#ifdef HAVE_LIBDECOR_H
19971988
if (data->shell_surface_type == WAYLAND_SHELL_SURFACE_TYPE_LIBDECOR) {
19981989
if (data->shell_surface.libdecor.frame) {
1999-
while (!data->shell_surface.libdecor.initial_configure_seen) {
1990+
while (data->shell_surface_status == WAYLAND_SHELL_SURFACE_STATUS_WAITING_FOR_CONFIGURE) {
20001991
WAYLAND_wl_display_flush(c->display);
20011992
WAYLAND_wl_display_dispatch(c->display);
20021993
}
@@ -2010,7 +2001,7 @@ void Wayland_ShowWindow(SDL_VideoDevice *_this, SDL_Window *window)
20102001
*/
20112002
wl_surface_commit(data->surface);
20122003
if (data->shell_surface.xdg.surface) {
2013-
while (!data->shell_surface.xdg.initial_configure_seen) {
2004+
while (data->shell_surface_status == WAYLAND_SHELL_SURFACE_STATUS_WAITING_FOR_CONFIGURE) {
20142005
WAYLAND_wl_display_flush(c->display);
20152006
WAYLAND_wl_display_dispatch(c->display);
20162007
}
@@ -2159,26 +2150,27 @@ void Wayland_HideWindow(SDL_VideoDevice *_this, SDL_Window *window)
21592150
if (wind->shell_surface_type == WAYLAND_SHELL_SURFACE_TYPE_LIBDECOR) {
21602151
if (wind->shell_surface.libdecor.frame) {
21612152
libdecor_frame_unref(wind->shell_surface.libdecor.frame);
2162-
wind->shell_surface.libdecor.frame = NULL;
21632153

21642154
SDL_SetPointerProperty(props, SDL_PROP_WINDOW_WAYLAND_XDG_SURFACE_POINTER, NULL);
21652155
SDL_SetPointerProperty(props, SDL_PROP_WINDOW_WAYLAND_XDG_TOPLEVEL_POINTER, NULL);
21662156
}
21672157
} else
21682158
#endif
2159+
{
21692160
if (wind->shell_surface_type == WAYLAND_SHELL_SURFACE_TYPE_XDG_POPUP) {
2170-
Wayland_ReleasePopup(_this, window);
2171-
} else if (wind->shell_surface.xdg.toplevel.xdg_toplevel) {
2172-
xdg_toplevel_destroy(wind->shell_surface.xdg.toplevel.xdg_toplevel);
2173-
wind->shell_surface.xdg.toplevel.xdg_toplevel = NULL;
2174-
SDL_SetPointerProperty(props, SDL_PROP_WINDOW_WAYLAND_XDG_TOPLEVEL_POINTER, NULL);
2175-
}
2176-
if (wind->shell_surface.xdg.surface) {
2177-
xdg_surface_destroy(wind->shell_surface.xdg.surface);
2178-
wind->shell_surface.xdg.surface = NULL;
2179-
SDL_SetPointerProperty(props, SDL_PROP_WINDOW_WAYLAND_XDG_SURFACE_POINTER, NULL);
2161+
Wayland_ReleasePopup(_this, window);
2162+
} else if (wind->shell_surface.xdg.toplevel.xdg_toplevel) {
2163+
xdg_toplevel_destroy(wind->shell_surface.xdg.toplevel.xdg_toplevel);
2164+
SDL_SetPointerProperty(props, SDL_PROP_WINDOW_WAYLAND_XDG_TOPLEVEL_POINTER, NULL);
2165+
}
2166+
2167+
if (wind->shell_surface.xdg.surface) {
2168+
xdg_surface_destroy(wind->shell_surface.xdg.surface);
2169+
SDL_SetPointerProperty(props, SDL_PROP_WINDOW_WAYLAND_XDG_SURFACE_POINTER, NULL);
2170+
}
21802171
}
21812172

2173+
SDL_zero(wind->shell_surface);
21822174
wind->show_hide_sync_required = true;
21832175
struct wl_callback *cb = wl_display_sync(_this->internal->display);
21842176
wl_callback_add_listener(cb, &show_hide_sync_listener, (void *)((uintptr_t)window->id));

src/video/wayland/SDL_waylandwindow.h

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,6 @@ struct SDL_WindowData
4646
struct
4747
{
4848
struct libdecor_frame *frame;
49-
bool initial_configure_seen;
5049
} libdecor;
5150
#endif
5251
struct
@@ -64,7 +63,6 @@ struct SDL_WindowData
6463
struct xdg_positioner *xdg_positioner;
6564
} popup;
6665
};
67-
bool initial_configure_seen;
6866
} xdg;
6967
} shell_surface;
7068
enum

0 commit comments

Comments
 (0)