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 ...@@ -55,6 +55,8 @@ static void xdg_surface_handle_configure(void *data, struct xdg_surface *xdg_sur
uint32_t serial) uint32_t serial)
{ {
struct wayland_surface *surface; struct wayland_surface *surface;
BOOL initial_configure = FALSE;
HWND hwnd;
TRACE("serial=%u\n", serial); TRACE("serial=%u\n", serial);
...@@ -63,9 +65,18 @@ static void xdg_surface_handle_configure(void *data, struct xdg_surface *xdg_sur ...@@ -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 /* Handle this event only if wayland_surface is still associated with
* the target xdg_surface. */ * the target xdg_surface. */
if (surface->xdg_surface == 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); xdg_surface_ack_configure(xdg_surface, serial);
}
pthread_mutex_unlock(&surface->mutex); 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 = static const struct xdg_surface_listener xdg_surface_listener =
...@@ -78,7 +89,7 @@ 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. * 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; struct wayland_surface *surface;
...@@ -93,6 +104,7 @@ struct wayland_surface *wayland_surface_create(void) ...@@ -93,6 +104,7 @@ struct wayland_surface *wayland_surface_create(void)
pthread_mutex_init(&surface->mutex, NULL); pthread_mutex_init(&surface->mutex, NULL);
surface->hwnd = hwnd;
surface->wl_surface = wl_compositor_create_surface(process_wayland.wl_compositor); surface->wl_surface = wl_compositor_create_surface(process_wayland.wl_compositor);
if (!surface->wl_surface) if (!surface->wl_surface)
{ {
...@@ -196,6 +208,8 @@ void wayland_surface_clear_role(struct wayland_surface *surface) ...@@ -196,6 +208,8 @@ void wayland_surface_clear_role(struct wayland_surface *surface)
surface->xdg_surface = NULL; surface->xdg_surface = NULL;
} }
surface->current_serial = 0;
/* Ensure no buffer is attached, otherwise future role assignments may fail. */ /* Ensure no buffer is attached, otherwise future role assignments may fail. */
wl_surface_attach(surface->wl_surface, NULL, 0, 0); wl_surface_attach(surface->wl_surface, NULL, 0, 0);
wl_surface_commit(surface->wl_surface); wl_surface_commit(surface->wl_surface);
......
...@@ -97,10 +97,12 @@ struct wayland_output ...@@ -97,10 +97,12 @@ struct wayland_output
struct wayland_surface struct wayland_surface
{ {
HWND hwnd;
struct wl_surface *wl_surface; struct wl_surface *wl_surface;
struct xdg_surface *xdg_surface; struct xdg_surface *xdg_surface;
struct xdg_toplevel *xdg_toplevel; struct xdg_toplevel *xdg_toplevel;
pthread_mutex_t mutex; pthread_mutex_t mutex;
uint32_t current_serial;
}; };
struct wayland_shm_buffer struct wayland_shm_buffer
...@@ -130,7 +132,7 @@ void wayland_output_use_xdg_extension(struct wayland_output *output) DECLSPEC_HI ...@@ -130,7 +132,7 @@ void wayland_output_use_xdg_extension(struct wayland_output *output) DECLSPEC_HI
* Wayland surface * 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_destroy(struct wayland_surface *surface) DECLSPEC_HIDDEN;
void wayland_surface_make_toplevel(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; 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_ ...@@ -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; 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, void wayland_window_surface_update_wayland_surface(struct window_surface *surface,
struct wayland_surface *wayland_surface) DECLSPEC_HIDDEN; struct wayland_surface *wayland_surface) DECLSPEC_HIDDEN;
void wayland_window_flush(HWND hwnd) DECLSPEC_HIDDEN;
/********************************************************************** /**********************************************************************
* USER driver functions * USER driver functions
......
...@@ -165,7 +165,7 @@ static void wayland_win_data_update_wayland_surface(struct wayland_win_data *dat ...@@ -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. */ /* 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; visible = (NtUserGetWindowLongW(data->hwnd, GWL_STYLE) & WS_VISIBLE) == WS_VISIBLE;
xdg_visible = surface->xdg_toplevel != NULL; xdg_visible = surface->xdg_toplevel != NULL;
...@@ -321,3 +321,20 @@ LRESULT WAYLAND_DesktopWindowProc(HWND hwnd, UINT msg, WPARAM wp, LPARAM lp) ...@@ -321,3 +321,20 @@ LRESULT WAYLAND_DesktopWindowProc(HWND hwnd, UINT msg, WPARAM wp, LPARAM lp)
return NtUserMessageCall(hwnd, msg, wp, lp, 0, NtUserDefWindowProc, FALSE); 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) ...@@ -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); memcpy(shm_buffer->map_data, wws->bits, shm_buffer->map_size);
pthread_mutex_lock(&wws->wayland_surface->mutex); pthread_mutex_lock(&wws->wayland_surface->mutex);
wayland_surface_attach_shm(wws->wayland_surface, shm_buffer); if (wws->wayland_surface->current_serial)
wl_surface_commit(wws->wayland_surface->wl_surface); {
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); pthread_mutex_unlock(&wws->wayland_surface->mutex);
wl_display_flush(process_wayland.wl_display); wl_display_flush(process_wayland.wl_display);
flushed = TRUE;
done: done:
if (flushed) reset_bounds(&wws->bounds); 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