Commit 6e903b79 authored by Alexandros Frantzis's avatar Alexandros Frantzis Committed by Alexandre Julliard

winewayland.drv: Handle xdg_toplevel configure event size hint.

Use the size hint provided by the compositor to resize the window associated with a Wayland toplevel surface. A surface config moves through the following stages (each stage may hold a different event): 1. Pending: In the process of being populated from separate Wayland events. 2. Requested: A fully formed config which hasn't been handled yet. A new finalized Pending event will always be promoted to a Requested event (so we will skip previous events if new ones arrive quickly enough). 3. Processing: A config that is being processed. When processing is done, we mark it with `wayland_surface_config.processed = TRUE`. 4. Current: The config has been acknowledged, i.e., we are promising to respect any implied content constraints.
parent 76eecdb2
...@@ -48,9 +48,15 @@ static void xdg_surface_handle_configure(void *data, struct xdg_surface *xdg_sur ...@@ -48,9 +48,15 @@ static void xdg_surface_handle_configure(void *data, struct xdg_surface *xdg_sur
* 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; /* If we have a previously requested config, we have already sent a
surface->current_serial = serial; * WM_WAYLAND_CONFIGURE which hasn't been handled yet. In that case,
xdg_surface_ack_configure(xdg_surface, serial); * avoid sending another message to reduce message queue traffic. */
BOOL should_post = surface->requested.serial == 0;
initial_configure = surface->current.serial == 0;
surface->pending.serial = serial;
surface->requested = surface->pending;
memset(&surface->pending, 0, sizeof(surface->pending));
if (should_post) NtUserPostMessage(hwnd, WM_WAYLAND_CONFIGURE, 0, 0);
} }
pthread_mutex_unlock(&surface->mutex); pthread_mutex_unlock(&surface->mutex);
...@@ -70,6 +76,20 @@ static void xdg_toplevel_handle_configure(void *data, ...@@ -70,6 +76,20 @@ static void xdg_toplevel_handle_configure(void *data,
int32_t width, int32_t height, int32_t width, int32_t height,
struct wl_array *states) struct wl_array *states)
{ {
struct wayland_surface *surface;
HWND hwnd = data;
TRACE("hwnd=%p %dx%d\n", hwnd, width, height);
if (!(surface = wayland_surface_lock_hwnd(hwnd))) return;
if (surface->xdg_toplevel == xdg_toplevel)
{
surface->pending.width = width;
surface->pending.height = height;
}
pthread_mutex_unlock(&surface->mutex);
} }
static void xdg_toplevel_handle_close(void *data, struct xdg_toplevel *xdg_toplevel) static void xdg_toplevel_handle_close(void *data, struct xdg_toplevel *xdg_toplevel)
...@@ -217,7 +237,10 @@ void wayland_surface_clear_role(struct wayland_surface *surface) ...@@ -217,7 +237,10 @@ void wayland_surface_clear_role(struct wayland_surface *surface)
surface->xdg_surface = NULL; surface->xdg_surface = NULL;
} }
surface->current_serial = 0; memset(&surface->pending, 0, sizeof(surface->pending));
memset(&surface->requested, 0, sizeof(surface->requested));
memset(&surface->processing, 0, sizeof(surface->processing));
memset(&surface->current, 0, sizeof(surface->current));
/* 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);
...@@ -269,6 +292,42 @@ void wayland_surface_attach_shm(struct wayland_surface *surface, ...@@ -269,6 +292,42 @@ void wayland_surface_attach_shm(struct wayland_surface *surface,
} }
/********************************************************************** /**********************************************************************
* wayland_surface_reconfigure
*
* Reconfigures the wayland surface as needed to match the latest requested
* state.
*/
BOOL wayland_surface_reconfigure(struct wayland_surface *surface)
{
if (!surface->xdg_toplevel) return TRUE;
TRACE("hwnd=%p\n", surface->hwnd);
/* Acknowledge any processed config. */
if (surface->processing.serial && surface->processing.processed)
{
surface->current = surface->processing;
memset(&surface->processing, 0, sizeof(surface->processing));
xdg_surface_ack_configure(surface->xdg_surface, surface->current.serial);
}
/* If this is the initial configure, and we have a requested config,
* use that, in order to draw windows that don't go through the message
* loop (e.g., some splash screens). */
else if (!surface->current.serial && surface->requested.serial)
{
surface->current = surface->requested;
memset(&surface->requested, 0, sizeof(surface->requested));
xdg_surface_ack_configure(surface->xdg_surface, surface->current.serial);
}
else if (!surface->current.serial)
{
return FALSE;
}
return TRUE;
}
/**********************************************************************
* wayland_shm_buffer_ref * wayland_shm_buffer_ref
* *
* Increases the reference count of a SHM buffer. * Increases the reference count of a SHM buffer.
......
...@@ -53,7 +53,8 @@ extern struct wayland process_wayland DECLSPEC_HIDDEN; ...@@ -53,7 +53,8 @@ extern struct wayland process_wayland DECLSPEC_HIDDEN;
enum wayland_window_message enum wayland_window_message
{ {
WM_WAYLAND_INIT_DISPLAY_DEVICES = 0x80001000 WM_WAYLAND_INIT_DISPLAY_DEVICES = 0x80001000,
WM_WAYLAND_CONFIGURE = 0x80001001
}; };
struct wayland_cursor struct wayland_cursor
...@@ -117,6 +118,13 @@ struct wayland_output ...@@ -117,6 +118,13 @@ struct wayland_output
struct wayland_output_state current; struct wayland_output_state current;
}; };
struct wayland_surface_config
{
int32_t width, height;
uint32_t serial;
BOOL processed;
};
struct wayland_surface struct wayland_surface
{ {
HWND hwnd; HWND hwnd;
...@@ -124,7 +132,7 @@ struct wayland_surface ...@@ -124,7 +132,7 @@ struct wayland_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_surface_config pending, requested, processing, current;
struct wayland_shm_buffer *latest_window_buffer; struct wayland_shm_buffer *latest_window_buffer;
}; };
...@@ -167,6 +175,7 @@ void wayland_surface_attach_shm(struct wayland_surface *surface, ...@@ -167,6 +175,7 @@ void wayland_surface_attach_shm(struct wayland_surface *surface,
struct wayland_shm_buffer *shm_buffer, struct wayland_shm_buffer *shm_buffer,
HRGN surface_damage_region) DECLSPEC_HIDDEN; HRGN surface_damage_region) DECLSPEC_HIDDEN;
struct wayland_surface *wayland_surface_lock_hwnd(HWND hwnd) DECLSPEC_HIDDEN; struct wayland_surface *wayland_surface_lock_hwnd(HWND hwnd) DECLSPEC_HIDDEN;
BOOL wayland_surface_reconfigure(struct wayland_surface *surface) DECLSPEC_HIDDEN;
/********************************************************************** /**********************************************************************
* Wayland SHM buffer * Wayland SHM buffer
......
...@@ -192,6 +192,20 @@ out: ...@@ -192,6 +192,20 @@ out:
data->wayland_surface = surface; data->wayland_surface = surface;
} }
static void wayland_win_data_update_wayland_state(struct wayland_win_data *data)
{
struct wayland_surface *surface = data->wayland_surface;
pthread_mutex_lock(&surface->mutex);
if (!surface->xdg_toplevel) goto out;
if (surface->processing.serial) surface->processing.processed = TRUE;
out:
pthread_mutex_unlock(&surface->mutex);
}
/*********************************************************************** /***********************************************************************
* WAYLAND_DestroyWindow * WAYLAND_DestroyWindow
*/ */
...@@ -276,6 +290,7 @@ void WAYLAND_WindowPosChanged(HWND hwnd, HWND insert_after, UINT swp_flags, ...@@ -276,6 +290,7 @@ void WAYLAND_WindowPosChanged(HWND hwnd, HWND insert_after, UINT swp_flags,
data->window_surface = surface; data->window_surface = surface;
wayland_win_data_update_wayland_surface(data); wayland_win_data_update_wayland_surface(data);
if (data->wayland_surface) wayland_win_data_update_wayland_state(data);
wayland_win_data_release(data); wayland_win_data_release(data);
} }
...@@ -290,6 +305,42 @@ static void wayland_resize_desktop(void) ...@@ -290,6 +305,42 @@ static void wayland_resize_desktop(void)
SWP_NOZORDER | SWP_NOACTIVATE | SWP_DEFERERASE); SWP_NOZORDER | SWP_NOACTIVATE | SWP_DEFERERASE);
} }
static void wayland_configure_window(HWND hwnd)
{
struct wayland_surface *surface;
INT width, height;
UINT flags;
if (!(surface = wayland_surface_lock_hwnd(hwnd))) return;
if (!surface->xdg_toplevel)
{
TRACE("missing xdg_toplevel, returning");
pthread_mutex_unlock(&surface->mutex);
return;
}
if (!surface->requested.serial)
{
TRACE("requested configure event already handled, returning\n");
pthread_mutex_unlock(&surface->mutex);
return;
}
surface->processing = surface->requested;
memset(&surface->requested, 0, sizeof(surface->requested));
width = surface->processing.width;
height = surface->processing.height;
pthread_mutex_unlock(&surface->mutex);
flags = SWP_NOACTIVATE | SWP_NOZORDER | SWP_NOOWNERZORDER | SWP_NOMOVE;
if (width == 0 || height == 0) flags |= SWP_NOSIZE;
NtUserSetWindowPos(hwnd, 0, 0, 0, width, height, flags);
}
/********************************************************************** /**********************************************************************
* WAYLAND_WindowMessage * WAYLAND_WindowMessage
*/ */
...@@ -301,6 +352,9 @@ LRESULT WAYLAND_WindowMessage(HWND hwnd, UINT msg, WPARAM wp, LPARAM lp) ...@@ -301,6 +352,9 @@ LRESULT WAYLAND_WindowMessage(HWND hwnd, UINT msg, WPARAM wp, LPARAM lp)
wayland_init_display_devices(TRUE); wayland_init_display_devices(TRUE);
wayland_resize_desktop(); wayland_resize_desktop();
return 0; return 0;
case WM_WAYLAND_CONFIGURE:
wayland_configure_window(hwnd);
return 0;
default: default:
FIXME("got window msg %x hwnd %p wp %lx lp %lx\n", msg, hwnd, (long)wp, lp); FIXME("got window msg %x hwnd %p wp %lx lp %lx\n", msg, hwnd, (long)wp, lp);
return 0; return 0;
......
...@@ -444,7 +444,7 @@ static void wayland_window_surface_flush(struct window_surface *window_surface) ...@@ -444,7 +444,7 @@ static void wayland_window_surface_flush(struct window_surface *window_surface)
wayland_window_surface_copy_to_buffer(wws, shm_buffer, copy_from_window_region); wayland_window_surface_copy_to_buffer(wws, shm_buffer, copy_from_window_region);
pthread_mutex_lock(&wws->wayland_surface->mutex); pthread_mutex_lock(&wws->wayland_surface->mutex);
if (wws->wayland_surface->current_serial) if (wayland_surface_reconfigure(wws->wayland_surface))
{ {
wayland_surface_attach_shm(wws->wayland_surface, shm_buffer, wayland_surface_attach_shm(wws->wayland_surface, shm_buffer,
surface_damage_region); surface_damage_region);
......
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