Commit 36ecb876 authored by Alexandros Frantzis's avatar Alexandros Frantzis Committed by Alexandre Julliard

winewayland.drv: Handle xdg_toplevel maximized state.

A request for the maximized state has two potential origins: 1. The compositor, through an xdg_toplevel configure event. In this case we update the window state and size accordingly. 2. The application or Wine itself, by changing the window style. When we detect such a style, we make a request to the compositor to set the maximized state. The compositor will then eventually reply with a configure event, and we continue with case (1). Note that the compositor may deny our request, in which case we will also sync the window style accordingly. An acknowledged maximized state imposes very strict constraints on the size of surface content we can present. We are careful to not violate these constraints, since otherwise the compositor will disconnect us.
parent 6e903b79
......@@ -78,8 +78,22 @@ static void xdg_toplevel_handle_configure(void *data,
{
struct wayland_surface *surface;
HWND hwnd = data;
uint32_t *state;
enum wayland_surface_config_state config_state = 0;
TRACE("hwnd=%p %dx%d\n", hwnd, width, height);
wl_array_for_each(state, states)
{
switch(*state)
{
case XDG_TOPLEVEL_STATE_MAXIMIZED:
config_state |= WAYLAND_SURFACE_CONFIG_STATE_MAXIMIZED;
break;
default:
break;
}
}
TRACE("hwnd=%p %dx%d,%#x\n", hwnd, width, height, config_state);
if (!(surface = wayland_surface_lock_hwnd(hwnd))) return;
......@@ -87,6 +101,7 @@ static void xdg_toplevel_handle_configure(void *data,
{
surface->pending.width = width;
surface->pending.height = height;
surface->pending.state = config_state;
}
pthread_mutex_unlock(&surface->mutex);
......@@ -292,6 +307,32 @@ void wayland_surface_attach_shm(struct wayland_surface *surface,
}
/**********************************************************************
* wayland_surface_configure_is_compatible
*
* Checks whether a wayland_surface_configure object is compatible with the
* the provided arguments.
*/
static BOOL wayland_surface_configure_is_compatible(struct wayland_surface_config *conf,
int width, int height,
enum wayland_surface_config_state state)
{
static enum wayland_surface_config_state mask =
WAYLAND_SURFACE_CONFIG_STATE_MAXIMIZED;
/* We require the same state. */
if ((state & mask) != (conf->state & mask)) return FALSE;
/* The maximized state requires the configured size. */
if ((conf->state & WAYLAND_SURFACE_CONFIG_STATE_MAXIMIZED) &&
(width != conf->width || height != conf->height))
{
return FALSE;
}
return TRUE;
}
/**********************************************************************
* wayland_surface_reconfigure
*
* Reconfigures the wayland surface as needed to match the latest requested
......@@ -299,27 +340,52 @@ void wayland_surface_attach_shm(struct wayland_surface *surface,
*/
BOOL wayland_surface_reconfigure(struct wayland_surface *surface)
{
if (!surface->xdg_toplevel) return TRUE;
RECT window_rect;
int width, height;
enum wayland_surface_config_state window_state;
TRACE("hwnd=%p\n", surface->hwnd);
/* Acknowledge any processed config. */
if (surface->processing.serial && surface->processing.processed)
if (!surface->xdg_toplevel) return TRUE;
if (!NtUserGetWindowRect(surface->hwnd, &window_rect)) return FALSE;
width = window_rect.right - window_rect.left;
height = window_rect.bottom - window_rect.top;
window_state =
(NtUserGetWindowLongW(surface->hwnd, GWL_STYLE) & WS_MAXIMIZE) ?
WAYLAND_SURFACE_CONFIG_STATE_MAXIMIZED : 0;
TRACE("hwnd=%p window=%dx%d,%#x processing=%dx%d,%#x current=%dx%d,%#x\n",
surface->hwnd, width, height, window_state,
surface->processing.width, surface->processing.height,
surface->processing.state, surface->current.width,
surface->current.height, surface->current.state);
/* Acknowledge any compatible processed config. */
if (surface->processing.serial && surface->processing.processed &&
wayland_surface_configure_is_compatible(&surface->processing,
width, height,
window_state))
{
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)
/* If this is the initial configure, and we have a compatible 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 &&
wayland_surface_configure_is_compatible(&surface->requested,
width, height,
window_state))
{
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)
else if (!surface->current.serial ||
!wayland_surface_configure_is_compatible(&surface->current,
width, height,
window_state))
{
return FALSE;
}
......
......@@ -57,6 +57,11 @@ enum wayland_window_message
WM_WAYLAND_CONFIGURE = 0x80001001
};
enum wayland_surface_config_state
{
WAYLAND_SURFACE_CONFIG_STATE_MAXIMIZED = (1 << 0)
};
struct wayland_cursor
{
struct wayland_shm_buffer *shm_buffer;
......@@ -121,6 +126,7 @@ struct wayland_output
struct wayland_surface_config
{
int32_t width, height;
enum wayland_surface_config_state state;
uint32_t serial;
BOOL processed;
};
......
......@@ -195,15 +195,38 @@ out:
static void wayland_win_data_update_wayland_state(struct wayland_win_data *data)
{
struct wayland_surface *surface = data->wayland_surface;
uint32_t window_state;
struct wayland_surface_config *conf;
pthread_mutex_lock(&surface->mutex);
if (!surface->xdg_toplevel) goto out;
if (surface->processing.serial) surface->processing.processed = TRUE;
window_state =
(NtUserGetWindowLongW(surface->hwnd, GWL_STYLE) & WS_MAXIMIZE) ?
WAYLAND_SURFACE_CONFIG_STATE_MAXIMIZED : 0;
conf = surface->processing.serial ? &surface->processing : &surface->current;
TRACE("hwnd=%p window_state=%#x conf->state=%#x\n",
data->hwnd, window_state, conf->state);
if ((window_state & WAYLAND_SURFACE_CONFIG_STATE_MAXIMIZED) &&
!(conf->state & WAYLAND_SURFACE_CONFIG_STATE_MAXIMIZED))
{
xdg_toplevel_set_maximized(surface->xdg_toplevel);
}
else if (!(window_state & WAYLAND_SURFACE_CONFIG_STATE_MAXIMIZED) &&
(conf->state & WAYLAND_SURFACE_CONFIG_STATE_MAXIMIZED))
{
xdg_toplevel_unset_maximized(surface->xdg_toplevel);
}
conf->processed = TRUE;
out:
pthread_mutex_unlock(&surface->mutex);
wl_display_flush(process_wayland.wl_display);
}
/***********************************************************************
......@@ -310,6 +333,8 @@ static void wayland_configure_window(HWND hwnd)
struct wayland_surface *surface;
INT width, height;
UINT flags;
uint32_t state;
DWORD style;
if (!(surface = wayland_surface_lock_hwnd(hwnd))) return;
......@@ -332,12 +357,26 @@ static void wayland_configure_window(HWND hwnd)
width = surface->processing.width;
height = surface->processing.height;
state = surface->processing.state;
pthread_mutex_unlock(&surface->mutex);
TRACE("processing=%dx%d,%#x\n", width, height, state);
flags = SWP_NOACTIVATE | SWP_NOZORDER | SWP_NOOWNERZORDER | SWP_NOMOVE;
if (width == 0 || height == 0) flags |= SWP_NOSIZE;
style = NtUserGetWindowLongW(hwnd, GWL_STYLE);
if (!(state & WAYLAND_SURFACE_CONFIG_STATE_MAXIMIZED) != !(style & WS_MAXIMIZE))
{
NtUserSetWindowLong(hwnd, GWL_STYLE, style ^ WS_MAXIMIZE, FALSE);
flags |= SWP_FRAMECHANGED;
}
/* The Wayland maximized state is very strict about surface size, so don't
* let the application override it. */
if (state & WAYLAND_SURFACE_CONFIG_STATE_MAXIMIZED) flags |= SWP_NOSENDCHANGING;
NtUserSetWindowPos(hwnd, 0, 0, 0, width, height, flags);
}
......
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