From 00663792004f25bc79344594758228a663992202 Mon Sep 17 00:00:00 2001 From: Alexandros Frantzis Date: Wed, 3 May 2023 13:10:50 +0300 Subject: [PATCH] winewayland.drv: Introduce per-window driver data. Create and manage an internal driver data structure for each non-desktop, non-message window. --- dlls/winewayland.drv/waylanddrv.h | 4 + dlls/winewayland.drv/waylanddrv_main.c | 4 +- dlls/winewayland.drv/window.c | 139 +++++++++++++++++++++++++ 3 files changed, 146 insertions(+), 1 deletion(-) diff --git a/dlls/winewayland.drv/waylanddrv.h b/dlls/winewayland.drv/waylanddrv.h index 57125e011cb..ed1d3ea0be2 100644 --- a/dlls/winewayland.drv/waylanddrv.h +++ b/dlls/winewayland.drv/waylanddrv.h @@ -111,8 +111,12 @@ void wayland_output_use_xdg_extension(struct wayland_output *output) DECLSPEC_HI */ LRESULT WAYLAND_DesktopWindowProc(HWND hwnd, UINT msg, WPARAM wp, LPARAM lp) DECLSPEC_HIDDEN; +void WAYLAND_DestroyWindow(HWND hwnd) DECLSPEC_HIDDEN; BOOL WAYLAND_UpdateDisplayDevices(const struct gdi_device_manager *device_manager, BOOL force, void *param) DECLSPEC_HIDDEN; LRESULT WAYLAND_WindowMessage(HWND hwnd, UINT msg, WPARAM wp, LPARAM lp) DECLSPEC_HIDDEN; +BOOL WAYLAND_WindowPosChanging(HWND hwnd, HWND insert_after, UINT swp_flags, + const RECT *window_rect, const RECT *client_rect, + RECT *visible_rect, struct window_surface **surface) DECLSPEC_HIDDEN; #endif /* __WINE_WAYLANDDRV_H */ diff --git a/dlls/winewayland.drv/waylanddrv_main.c b/dlls/winewayland.drv/waylanddrv_main.c index 2a7bed9d1d8..3ef03e16d0b 100644 --- a/dlls/winewayland.drv/waylanddrv_main.c +++ b/dlls/winewayland.drv/waylanddrv_main.c @@ -32,8 +32,10 @@ static const struct user_driver_funcs waylanddrv_funcs = { .pDesktopWindowProc = WAYLAND_DesktopWindowProc, + .pDestroyWindow = WAYLAND_DestroyWindow, .pUpdateDisplayDevices = WAYLAND_UpdateDisplayDevices, - .pWindowMessage = WAYLAND_WindowMessage + .pWindowMessage = WAYLAND_WindowMessage, + .pWindowPosChanging = WAYLAND_WindowPosChanging }; static NTSTATUS waylanddrv_unix_init(void *arg) diff --git a/dlls/winewayland.drv/window.c b/dlls/winewayland.drv/window.c index ea5ac22a8a2..1ea8c77934d 100644 --- a/dlls/winewayland.drv/window.c +++ b/dlls/winewayland.drv/window.c @@ -24,12 +24,151 @@ #include "config.h" +#include +#include + #include "waylanddrv.h" #include "wine/debug.h" WINE_DEFAULT_DEBUG_CHANNEL(waylanddrv); +/* private window data */ +struct wayland_win_data +{ + struct rb_entry entry; + /* hwnd that this private data belongs to */ + HWND hwnd; +}; + +static int wayland_win_data_cmp_rb(const void *key, + const struct rb_entry *entry) +{ + HWND key_hwnd = (HWND)key; /* cast to work around const */ + const struct wayland_win_data *entry_win_data = + RB_ENTRY_VALUE(entry, const struct wayland_win_data, entry); + + if (key_hwnd < entry_win_data->hwnd) return -1; + if (key_hwnd > entry_win_data->hwnd) return 1; + return 0; +} + +static pthread_mutex_t win_data_mutex = PTHREAD_MUTEX_INITIALIZER; +static struct rb_tree win_data_rb = { wayland_win_data_cmp_rb }; + +/*********************************************************************** + * wayland_win_data_create + * + * Create a data window structure for an existing window. + */ +static struct wayland_win_data *wayland_win_data_create(HWND hwnd) +{ + struct wayland_win_data *data; + struct rb_entry *rb_entry; + HWND parent; + + /* Don't create win data for desktop or HWND_MESSAGE windows. */ + if (!(parent = NtUserGetAncestor(hwnd, GA_PARENT))) return NULL; + if (parent != NtUserGetDesktopWindow() && !NtUserGetAncestor(parent, GA_PARENT)) + return NULL; + + if (!(data = calloc(1, sizeof(*data)))) return NULL; + + data->hwnd = hwnd; + + pthread_mutex_lock(&win_data_mutex); + + /* Check that another thread hasn't already created the wayland_win_data. */ + if ((rb_entry = rb_get(&win_data_rb, hwnd))) + { + free(data); + return RB_ENTRY_VALUE(rb_entry, struct wayland_win_data, entry); + } + + rb_put(&win_data_rb, hwnd, &data->entry); + + TRACE("hwnd=%p\n", data->hwnd); + + return data; +} + +/*********************************************************************** + * wayland_win_data_destroy + */ +static void wayland_win_data_destroy(struct wayland_win_data *data) +{ + TRACE("hwnd=%p\n", data->hwnd); + + rb_remove(&win_data_rb, &data->entry); + + pthread_mutex_unlock(&win_data_mutex); + + free(data); +} + +/*********************************************************************** + * wayland_win_data_get + * + * Lock and return the data structure associated with a window. + */ +static struct wayland_win_data *wayland_win_data_get(HWND hwnd) +{ + struct rb_entry *rb_entry; + + pthread_mutex_lock(&win_data_mutex); + + if ((rb_entry = rb_get(&win_data_rb, hwnd))) + return RB_ENTRY_VALUE(rb_entry, struct wayland_win_data, entry); + + pthread_mutex_unlock(&win_data_mutex); + + return NULL; +} + +/*********************************************************************** + * wayland_win_data_release + * + * Release the data returned by wayland_win_data_get. + */ +static void wayland_win_data_release(struct wayland_win_data *data) +{ + assert(data); + pthread_mutex_unlock(&win_data_mutex); +} + +/*********************************************************************** + * WAYLAND_DestroyWindow + */ +void WAYLAND_DestroyWindow(HWND hwnd) +{ + struct wayland_win_data *data; + + TRACE("%p\n", hwnd); + + if (!(data = wayland_win_data_get(hwnd))) return; + wayland_win_data_destroy(data); +} + +/*********************************************************************** + * WAYLAND_WindowPosChanging + */ +BOOL WAYLAND_WindowPosChanging(HWND hwnd, HWND insert_after, UINT swp_flags, + const RECT *window_rect, const RECT *client_rect, + RECT *visible_rect, struct window_surface **surface) +{ + struct wayland_win_data *data = wayland_win_data_get(hwnd); + + TRACE("hwnd %p window %s client %s visible %s after %p flags %08x\n", + hwnd, wine_dbgstr_rect(window_rect), wine_dbgstr_rect(client_rect), + wine_dbgstr_rect(visible_rect), insert_after, swp_flags); + + if (!data && !(data = wayland_win_data_create(hwnd))) return TRUE; + + wayland_win_data_release(data); + + return TRUE; +} + static void wayland_resize_desktop(void) { RECT virtual_rect = NtUserGetVirtualScreenRect();