Commit fc8570a1 authored by Alexandros Frantzis's avatar Alexandros Frantzis Committed by Alexandre Julliard

winewayland.drv: Do not commit buffers to unconfigured surfaces.

The xdg-shell protocol disallows buffer commits to a wl_surface with an xdg_surface based role before we ack the first configure event. Failing to adhere to this requirement will get our client disconnected by the compositor with a protocol error.
parent 6b0a84c8
......@@ -55,6 +55,8 @@ static void xdg_surface_handle_configure(void *data, struct xdg_surface *xdg_sur
uint32_t serial)
{
struct wayland_surface *surface;
BOOL initial_configure = FALSE;
HWND hwnd;
TRACE("serial=%u\n", serial);
......@@ -63,9 +65,18 @@ static void xdg_surface_handle_configure(void *data, struct xdg_surface *xdg_sur
/* Handle this event only if wayland_surface is still associated with
* the target xdg_surface. */
if (surface->xdg_surface == xdg_surface)
{
initial_configure = surface->current_serial == 0;
hwnd = surface->hwnd;
surface->current_serial = serial;
xdg_surface_ack_configure(xdg_surface, serial);
}
pthread_mutex_unlock(&surface->mutex);
/* Flush the window surface in case there is content that we weren't
* able to flush before due to the lack of the initial configure. */
if (initial_configure) wayland_window_flush(hwnd);
}
static const struct xdg_surface_listener xdg_surface_listener =
......@@ -78,7 +89,7 @@ static const struct xdg_surface_listener xdg_surface_listener =
*
* Creates a role-less wayland surface.
*/
struct wayland_surface *wayland_surface_create(void)
struct wayland_surface *wayland_surface_create(HWND hwnd)
{
struct wayland_surface *surface;
......@@ -93,6 +104,7 @@ struct wayland_surface *wayland_surface_create(void)
pthread_mutex_init(&surface->mutex, NULL);
surface->hwnd = hwnd;
surface->wl_surface = wl_compositor_create_surface(process_wayland.wl_compositor);
if (!surface->wl_surface)
{
......@@ -196,6 +208,8 @@ void wayland_surface_clear_role(struct wayland_surface *surface)
surface->xdg_surface = NULL;
}
surface->current_serial = 0;
/* Ensure no buffer is attached, otherwise future role assignments may fail. */
wl_surface_attach(surface->wl_surface, NULL, 0, 0);
wl_surface_commit(surface->wl_surface);
......
......@@ -97,10 +97,12 @@ struct wayland_output
struct wayland_surface
{
HWND hwnd;
struct wl_surface *wl_surface;
struct xdg_surface *xdg_surface;
struct xdg_toplevel *xdg_toplevel;
pthread_mutex_t mutex;
uint32_t current_serial;
};
struct wayland_shm_buffer
......@@ -130,7 +132,7 @@ void wayland_output_use_xdg_extension(struct wayland_output *output) DECLSPEC_HI
* Wayland surface
*/
struct wayland_surface *wayland_surface_create(void) DECLSPEC_HIDDEN;
struct wayland_surface *wayland_surface_create(HWND hwnd) DECLSPEC_HIDDEN;
void wayland_surface_destroy(struct wayland_surface *surface) DECLSPEC_HIDDEN;
void wayland_surface_make_toplevel(struct wayland_surface *surface) DECLSPEC_HIDDEN;
void wayland_surface_clear_role(struct wayland_surface *surface) DECLSPEC_HIDDEN;
......@@ -152,6 +154,7 @@ void wayland_shm_buffer_destroy(struct wayland_shm_buffer *shm_buffer) DECLSPEC_
struct window_surface *wayland_window_surface_create(HWND hwnd, const RECT *rect) DECLSPEC_HIDDEN;
void wayland_window_surface_update_wayland_surface(struct window_surface *surface,
struct wayland_surface *wayland_surface) DECLSPEC_HIDDEN;
void wayland_window_flush(HWND hwnd) DECLSPEC_HIDDEN;
/**********************************************************************
* USER driver functions
......
......@@ -165,7 +165,7 @@ static void wayland_win_data_update_wayland_surface(struct wayland_win_data *dat
}
/* Otherwise ensure that we have a wayland surface. */
if (!surface && !(surface = wayland_surface_create())) return;
if (!surface && !(surface = wayland_surface_create(data->hwnd))) return;
visible = (NtUserGetWindowLongW(data->hwnd, GWL_STYLE) & WS_VISIBLE) == WS_VISIBLE;
xdg_visible = surface->xdg_toplevel != NULL;
......@@ -321,3 +321,20 @@ LRESULT WAYLAND_DesktopWindowProc(HWND hwnd, UINT msg, WPARAM wp, LPARAM lp)
return NtUserMessageCall(hwnd, msg, wp, lp, 0, NtUserDefWindowProc, FALSE);
}
/**********************************************************************
* wayland_window_flush
*
* Flush the window_surface associated with a HWND.
*/
void wayland_window_flush(HWND hwnd)
{
struct wayland_win_data *data = wayland_win_data_get(hwnd);
if (!data) return;
if (data->window_surface)
data->window_surface->funcs->flush(data->window_surface);
wayland_win_data_release(data);
}
......@@ -149,11 +149,19 @@ static void wayland_window_surface_flush(struct window_surface *window_surface)
memcpy(shm_buffer->map_data, wws->bits, shm_buffer->map_size);
pthread_mutex_lock(&wws->wayland_surface->mutex);
wayland_surface_attach_shm(wws->wayland_surface, shm_buffer);
wl_surface_commit(wws->wayland_surface->wl_surface);
if (wws->wayland_surface->current_serial)
{
wayland_surface_attach_shm(wws->wayland_surface, shm_buffer);
wl_surface_commit(wws->wayland_surface->wl_surface);
flushed = TRUE;
}
else
{
TRACE("Wayland surface not configured yet, not flushing\n");
wayland_shm_buffer_destroy(shm_buffer);
}
pthread_mutex_unlock(&wws->wayland_surface->mutex);
wl_display_flush(process_wayland.wl_display);
flushed = TRUE;
done:
if (flushed) reset_bounds(&wws->bounds);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment