From: Alexandros Frantzis alexandros.frantzis@collabora.com
Handle wl_pointer enter/leave events and maintain information about the focused wayland_surface. Since pointer information will be accessed by any UI capable thread, ensure proper proper locking is in place. --- dlls/winewayland.drv/wayland.c | 7 ++-- dlls/winewayland.drv/wayland_pointer.c | 44 +++++++++++++++++++++++--- dlls/winewayland.drv/wayland_surface.c | 25 +++++++++------ dlls/winewayland.drv/waylanddrv.h | 8 ++++- 4 files changed, 67 insertions(+), 17 deletions(-)
diff --git a/dlls/winewayland.drv/wayland.c b/dlls/winewayland.drv/wayland.c index 6ea4a94551d..51e36b5ba60 100644 --- a/dlls/winewayland.drv/wayland.c +++ b/dlls/winewayland.drv/wayland.c @@ -34,6 +34,7 @@ WINE_DEFAULT_DEBUG_CHANNEL(waylanddrv);
struct wayland process_wayland = { + .pointer.mutex = PTHREAD_MUTEX_INITIALIZER, .output_list = {&process_wayland.output_list, &process_wayland.output_list}, .output_mutex = PTHREAD_MUTEX_INITIALIZER }; @@ -60,9 +61,9 @@ static const struct xdg_wm_base_listener xdg_wm_base_listener = static void wl_seat_handle_capabilities(void *data, struct wl_seat *seat, enum wl_seat_capability caps) { - if ((caps & WL_SEAT_CAPABILITY_POINTER) && !process_wayland.wl_pointer) + if ((caps & WL_SEAT_CAPABILITY_POINTER) && !process_wayland.pointer.wl_pointer) wayland_pointer_init(wl_seat_get_pointer(seat)); - else if (!(caps & WL_SEAT_CAPABILITY_POINTER) && process_wayland.wl_pointer) + else if (!(caps & WL_SEAT_CAPABILITY_POINTER) && process_wayland.pointer.wl_pointer) wayland_pointer_deinit(); }
@@ -155,7 +156,7 @@ static void registry_handle_global_remove(void *data, struct wl_registry *regist wl_proxy_get_id((struct wl_proxy *)process_wayland.wl_seat) == id) { TRACE("removing seat\n"); - if (process_wayland.wl_pointer) wayland_pointer_deinit(); + if (process_wayland.pointer.wl_pointer) wayland_pointer_deinit(); wl_seat_release(process_wayland.wl_seat); process_wayland.wl_seat = NULL; } diff --git a/dlls/winewayland.drv/wayland_pointer.c b/dlls/winewayland.drv/wayland_pointer.c index 10dacfa03b0..1476c2369a9 100644 --- a/dlls/winewayland.drv/wayland_pointer.c +++ b/dlls/winewayland.drv/wayland_pointer.c @@ -25,6 +25,9 @@ #include "config.h"
#include "waylanddrv.h" +#include "wine/debug.h" + +WINE_DEFAULT_DEBUG_CHANNEL(waylanddrv);
static void pointer_handle_motion(void *data, struct wl_pointer *wl_pointer, uint32_t time, wl_fixed_t sx, wl_fixed_t sy) @@ -35,11 +38,38 @@ static void pointer_handle_enter(void *data, struct wl_pointer *wl_pointer, uint32_t serial, struct wl_surface *wl_surface, wl_fixed_t sx, wl_fixed_t sy) { + struct wayland_surface *surface; + + if (!wl_surface) return; + + pthread_mutex_lock(&process_wayland.pointer.mutex); + if ((surface = wayland_surface_lock_proxy((struct wl_proxy *)wl_surface))) + { + TRACE("surface=%p hwnd=%p\n", surface, surface->hwnd); + process_wayland.pointer.surface = surface; + pthread_mutex_unlock(&surface->mutex); + } + pthread_mutex_unlock(&process_wayland.pointer.mutex); }
static void pointer_handle_leave(void *data, struct wl_pointer *wl_pointer, uint32_t serial, struct wl_surface *wl_surface) { + struct wayland_surface *surface; + + if (!wl_surface) return; + + pthread_mutex_lock(&process_wayland.pointer.mutex); + if ((surface = wayland_surface_lock_proxy((struct wl_proxy *)wl_surface))) + { + if (process_wayland.pointer.surface == surface) + { + TRACE("surface=%p hwnd=%p\n", surface, surface->hwnd); + process_wayland.pointer.surface = NULL; + } + pthread_mutex_unlock(&surface->mutex); + } + pthread_mutex_unlock(&process_wayland.pointer.mutex); }
static void pointer_handle_button(void *data, struct wl_pointer *wl_pointer, @@ -87,12 +117,18 @@ static const struct wl_pointer_listener pointer_listener =
void wayland_pointer_init(struct wl_pointer *wl_pointer) { - process_wayland.wl_pointer = wl_pointer; - wl_pointer_add_listener(process_wayland.wl_pointer, &pointer_listener, NULL); + pthread_mutex_lock(&process_wayland.pointer.mutex); + process_wayland.pointer.wl_pointer = wl_pointer; + process_wayland.pointer.surface = NULL; + pthread_mutex_unlock(&process_wayland.pointer.mutex); + wl_pointer_add_listener(process_wayland.pointer.wl_pointer, &pointer_listener, NULL); }
void wayland_pointer_deinit(void) { - wl_pointer_release(process_wayland.wl_pointer); - process_wayland.wl_pointer = NULL; + pthread_mutex_lock(&process_wayland.pointer.mutex); + wl_pointer_release(process_wayland.pointer.wl_pointer); + process_wayland.pointer.wl_pointer = NULL; + process_wayland.pointer.surface = NULL; + pthread_mutex_unlock(&process_wayland.pointer.mutex); } diff --git a/dlls/winewayland.drv/wayland_surface.c b/dlls/winewayland.drv/wayland_surface.c index fbc49191d9e..6f637516078 100644 --- a/dlls/winewayland.drv/wayland_surface.c +++ b/dlls/winewayland.drv/wayland_surface.c @@ -33,17 +33,17 @@
WINE_DEFAULT_DEBUG_CHANNEL(waylanddrv);
-/* Protects access to the user data of xdg_surface */ -static pthread_mutex_t xdg_data_mutex = PTHREAD_MUTEX_INITIALIZER; +/* Protects access to the wayland_surface user data of wayland objects */ +static pthread_mutex_t user_data_mutex = PTHREAD_MUTEX_INITIALIZER;
-static struct wayland_surface *wayland_surface_lock_xdg(struct xdg_surface *xdg_surface) +struct wayland_surface *wayland_surface_lock_proxy(struct wl_proxy *wl_proxy) { struct wayland_surface *surface;
- pthread_mutex_lock(&xdg_data_mutex); - surface = xdg_surface_get_user_data(xdg_surface); + pthread_mutex_lock(&user_data_mutex); + surface = wl_proxy_get_user_data(wl_proxy); if (surface) pthread_mutex_lock(&surface->mutex); - pthread_mutex_unlock(&xdg_data_mutex); + pthread_mutex_unlock(&user_data_mutex);
return surface; } @@ -57,7 +57,7 @@ static void xdg_surface_handle_configure(void *data, struct xdg_surface *xdg_sur
TRACE("serial=%u\n", serial);
- if (!(surface = wayland_surface_lock_xdg(xdg_surface))) return; + if (!(surface = wayland_surface_lock_proxy((struct wl_proxy *)xdg_surface))) return;
/* Handle this event only if wayland_surface is still associated with * the target xdg_surface. */ @@ -108,6 +108,7 @@ struct wayland_surface *wayland_surface_create(HWND hwnd) ERR("Failed to create wl_surface Wayland surface\n"); goto err; } + wl_surface_set_user_data(surface->wl_surface, surface);
return surface;
@@ -123,7 +124,7 @@ err: */ void wayland_surface_destroy(struct wayland_surface *surface) { - pthread_mutex_lock(&xdg_data_mutex); + pthread_mutex_lock(&user_data_mutex); pthread_mutex_lock(&surface->mutex);
if (surface->xdg_toplevel) @@ -141,12 +142,18 @@ void wayland_surface_destroy(struct wayland_surface *surface)
if (surface->wl_surface) { + wl_surface_set_user_data(surface->wl_surface, NULL); wl_surface_destroy(surface->wl_surface); surface->wl_surface = NULL; }
pthread_mutex_unlock(&surface->mutex); - pthread_mutex_unlock(&xdg_data_mutex); + pthread_mutex_unlock(&user_data_mutex); + + pthread_mutex_lock(&process_wayland.pointer.mutex); + if (process_wayland.pointer.surface == surface) + process_wayland.pointer.surface = NULL; + pthread_mutex_unlock(&process_wayland.pointer.mutex);
if (surface->latest_window_buffer) wayland_shm_buffer_unref(surface->latest_window_buffer); diff --git a/dlls/winewayland.drv/waylanddrv.h b/dlls/winewayland.drv/waylanddrv.h index 8932c2c9e8d..14d0c7e5575 100644 --- a/dlls/winewayland.drv/waylanddrv.h +++ b/dlls/winewayland.drv/waylanddrv.h @@ -67,7 +67,12 @@ struct wayland struct xdg_wm_base *xdg_wm_base; struct wl_shm *wl_shm; struct wl_seat *wl_seat; - struct wl_pointer *wl_pointer; + struct + { + struct wl_pointer *wl_pointer; + struct wayland_surface *surface; + pthread_mutex_t mutex; + } pointer; struct wl_list output_list; /* Protects the output_list and the wayland_output.current states. */ pthread_mutex_t output_mutex; @@ -150,6 +155,7 @@ void wayland_surface_clear_role(struct wayland_surface *surface) DECLSPEC_HIDDEN void wayland_surface_attach_shm(struct wayland_surface *surface, struct wayland_shm_buffer *shm_buffer, HRGN surface_damage_region) DECLSPEC_HIDDEN; +struct wayland_surface *wayland_surface_lock_proxy(struct wl_proxy *wl_proxy) DECLSPEC_HIDDEN;
/********************************************************************** * Wayland SHM buffer