From: Alexandros Frantzis alexandros.frantzis@collabora.com
Instead of querying the window config for a wayland_surface on demand, query it and store it only when it is applied through SetWindowPos. In addition to being more efficient, this prevents deadlocks by avoiding calling NtUser functions that require the user lock, while holding the window_surface lock. --- dlls/winewayland.drv/wayland_surface.c | 20 ++++++----------- dlls/winewayland.drv/waylanddrv.h | 7 ++++++ dlls/winewayland.drv/window.c | 30 +++++++++++++++----------- 3 files changed, 32 insertions(+), 25 deletions(-)
diff --git a/dlls/winewayland.drv/wayland_surface.c b/dlls/winewayland.drv/wayland_surface.c index ddb10be6e06..5bb8c959537 100644 --- a/dlls/winewayland.drv/wayland_surface.c +++ b/dlls/winewayland.drv/wayland_surface.c @@ -349,22 +349,16 @@ static BOOL wayland_surface_configure_is_compatible(struct wayland_surface_confi */ BOOL wayland_surface_reconfigure(struct wayland_surface *surface) { - RECT window_rect; + struct wayland_window_config *window = &surface->window; int width, height; - enum wayland_surface_config_state window_state;
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; + width = surface->window.rect.right - surface->window.rect.left; + height = surface->window.rect.bottom - surface->window.rect.top;
TRACE("hwnd=%p window=%dx%d,%#x processing=%dx%d,%#x current=%dx%d,%#x\n", - surface->hwnd, width, height, window_state, + surface->hwnd, width, height, window->state, surface->processing.width, surface->processing.height, surface->processing.state, surface->current.width, surface->current.height, surface->current.state); @@ -373,7 +367,7 @@ BOOL wayland_surface_reconfigure(struct wayland_surface *surface) if (surface->processing.serial && surface->processing.processed && wayland_surface_configure_is_compatible(&surface->processing, width, height, - window_state)) + window->state)) { surface->current = surface->processing; memset(&surface->processing, 0, sizeof(surface->processing)); @@ -385,7 +379,7 @@ BOOL wayland_surface_reconfigure(struct wayland_surface *surface) else if (!surface->current.serial && surface->requested.serial && wayland_surface_configure_is_compatible(&surface->requested, width, height, - window_state)) + window->state)) { surface->current = surface->requested; memset(&surface->requested, 0, sizeof(surface->requested)); @@ -394,7 +388,7 @@ BOOL wayland_surface_reconfigure(struct wayland_surface *surface) else if (!surface->current.serial || !wayland_surface_configure_is_compatible(&surface->current, width, height, - window_state)) + window->state)) { return FALSE; } diff --git a/dlls/winewayland.drv/waylanddrv.h b/dlls/winewayland.drv/waylanddrv.h index fcfc187925d..4b74b674ea6 100644 --- a/dlls/winewayland.drv/waylanddrv.h +++ b/dlls/winewayland.drv/waylanddrv.h @@ -141,6 +141,12 @@ struct wayland_surface_config BOOL processed; };
+struct wayland_window_config +{ + RECT rect; + enum wayland_surface_config_state state; +}; + struct wayland_surface { HWND hwnd; @@ -151,6 +157,7 @@ struct wayland_surface struct wayland_surface_config pending, requested, processing, current; struct wayland_shm_buffer *latest_window_buffer; BOOL resizing; + struct wayland_window_config window; };
struct wayland_shm_buffer diff --git a/dlls/winewayland.drv/window.c b/dlls/winewayland.drv/window.c index 23f4c89ea0b..bf1a286b17d 100644 --- a/dlls/winewayland.drv/window.c +++ b/dlls/winewayland.drv/window.c @@ -146,6 +146,14 @@ static void wayland_win_data_release(struct wayland_win_data *data) pthread_mutex_unlock(&win_data_mutex); }
+static BOOL wayland_window_get_config(HWND hwnd, struct wayland_window_config *conf) +{ + if (!NtUserGetWindowRect(hwnd, &conf->rect)) return FALSE; + conf->state = (NtUserGetWindowLongW(hwnd, GWL_STYLE) & WS_MAXIMIZE) ? + WAYLAND_SURFACE_CONFIG_STATE_MAXIMIZED : 0; + return TRUE; +} + static void wayland_win_data_update_wayland_surface(struct wayland_win_data *data) { struct wayland_surface *surface = data->wayland_surface; @@ -170,20 +178,23 @@ static void wayland_win_data_update_wayland_surface(struct wayland_win_data *dat visible = (NtUserGetWindowLongW(data->hwnd, GWL_STYLE) & WS_VISIBLE) == WS_VISIBLE; xdg_visible = surface->xdg_toplevel != NULL;
+ pthread_mutex_lock(&surface->mutex); + if (visible != xdg_visible) { - pthread_mutex_lock(&surface->mutex); - /* If we have a pre-existing surface ensure it has no role. */ if (data->wayland_surface) wayland_surface_clear_role(surface); /* If the window is a visible toplevel make it a wayland * xdg_toplevel. Otherwise keep it role-less to avoid polluting the * compositor with empty xdg_toplevels. */ if (visible) wayland_surface_make_toplevel(surface); - - pthread_mutex_unlock(&surface->mutex); }
+ if (!wayland_window_get_config(data->hwnd, &surface->window)) + WARN("failed to get window config for hwnd=%p\n", data->hwnd); + + pthread_mutex_unlock(&surface->mutex); + if (data->window_surface) wayland_window_surface_update_wayland_surface(data->window_surface, surface);
@@ -195,22 +206,17 @@ 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; BOOL processing_config;
pthread_mutex_lock(&surface->mutex);
if (!surface->xdg_toplevel) goto out;
- window_state = - (NtUserGetWindowLongW(surface->hwnd, GWL_STYLE) & WS_MAXIMIZE) ? - WAYLAND_SURFACE_CONFIG_STATE_MAXIMIZED : 0; - processing_config = surface->processing.serial && !surface->processing.processed;
TRACE("hwnd=%p window_state=%#x %s->state=%#x\n", - data->hwnd, window_state, + data->hwnd, surface->window.state, processing_config ? "processing" : "current", processing_config ? surface->processing.state : surface->current.state);
@@ -218,12 +224,12 @@ static void wayland_win_data_update_wayland_state(struct wayland_win_data *data) * window state to determine and update the Wayland state. */ if (!processing_config) { - if ((window_state & WAYLAND_SURFACE_CONFIG_STATE_MAXIMIZED) && + if ((surface->window.state & WAYLAND_SURFACE_CONFIG_STATE_MAXIMIZED) && !(surface->current.state & WAYLAND_SURFACE_CONFIG_STATE_MAXIMIZED)) { xdg_toplevel_set_maximized(surface->xdg_toplevel); } - else if (!(window_state & WAYLAND_SURFACE_CONFIG_STATE_MAXIMIZED) && + else if (!(surface->window.state & WAYLAND_SURFACE_CONFIG_STATE_MAXIMIZED) && (surface->current.state & WAYLAND_SURFACE_CONFIG_STATE_MAXIMIZED)) { xdg_toplevel_unset_maximized(surface->xdg_toplevel);