mirror of
git://source.winehq.org/git/wine.git
synced 2024-10-04 18:57:38 +00:00
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.
This commit is contained in:
parent
6b0a84c8d9
commit
fc8570a1a6
|
@ -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);
|
||||
|
|
Loading…
Reference in a new issue