Module: wine Branch: master Commit: ddc4cfe238bae4c2ad86c6e06cd10c80c3d2b803 URL: https://gitlab.winehq.org/wine/wine/-/commit/ddc4cfe238bae4c2ad86c6e06cd10c8...
Author: Alexandros Frantzis alexandros.frantzis@collabora.com Date: Mon Sep 18 13:02:06 2023 +0300
winewayland.drv: Handle client-initiated user-driven window move.
When we are notified by Wine core that the user wants to interactively move the window, forward the request to compositor, so it can take over and move the window according to user input.
Note that the move does *not* affect the position of the window in the Wine virtual screen space.
---
dlls/winewayland.drv/wayland.c | 24 ++++++++++++++------- dlls/winewayland.drv/wayland_pointer.c | 6 ++++++ dlls/winewayland.drv/waylanddrv.h | 10 ++++++++- dlls/winewayland.drv/waylanddrv_main.c | 1 + dlls/winewayland.drv/window.c | 39 ++++++++++++++++++++++++++++++++++ 5 files changed, 71 insertions(+), 9 deletions(-)
diff --git a/dlls/winewayland.drv/wayland.c b/dlls/winewayland.drv/wayland.c index 51e36b5ba60..700eb41fee7 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 = { + .seat.mutex = PTHREAD_MUTEX_INITIALIZER, .pointer.mutex = PTHREAD_MUTEX_INITIALIZER, .output_list = {&process_wayland.output_list, &process_wayland.output_list}, .output_mutex = PTHREAD_MUTEX_INITIALIZER @@ -124,14 +125,17 @@ static void registry_handle_global(void *data, struct wl_registry *registry, } else if (strcmp(interface, "wl_seat") == 0) { - if (process_wayland.wl_seat) + struct wayland_seat *seat = &process_wayland.seat; + if (seat->wl_seat) { WARN("Only a single seat is currently supported, ignoring additional seats.\n"); return; } - process_wayland.wl_seat = wl_registry_bind(registry, id, &wl_seat_interface, - version < 5 ? version : 5); - wl_seat_add_listener(process_wayland.wl_seat, &seat_listener, NULL); + pthread_mutex_lock(&seat->mutex); + seat->wl_seat = wl_registry_bind(registry, id, &wl_seat_interface, + version < 5 ? version : 5); + wl_seat_add_listener(seat->wl_seat, &seat_listener, NULL); + pthread_mutex_unlock(&seat->mutex); } }
@@ -139,6 +143,7 @@ static void registry_handle_global_remove(void *data, struct wl_registry *regist uint32_t id) { struct wayland_output *output, *tmp; + struct wayland_seat *seat;
TRACE("id=%u\n", id);
@@ -152,13 +157,16 @@ static void registry_handle_global_remove(void *data, struct wl_registry *regist } }
- if (process_wayland.wl_seat && - wl_proxy_get_id((struct wl_proxy *)process_wayland.wl_seat) == id) + seat = &process_wayland.seat; + if (seat->wl_seat && + wl_proxy_get_id((struct wl_proxy *)seat->wl_seat) == id) { TRACE("removing seat\n"); if (process_wayland.pointer.wl_pointer) wayland_pointer_deinit(); - wl_seat_release(process_wayland.wl_seat); - process_wayland.wl_seat = NULL; + pthread_mutex_lock(&seat->mutex); + wl_seat_release(seat->wl_seat); + seat->wl_seat = NULL; + pthread_mutex_unlock(&seat->mutex); } }
diff --git a/dlls/winewayland.drv/wayland_pointer.c b/dlls/winewayland.drv/wayland_pointer.c index 69f3a7c16a7..ff376882d73 100644 --- a/dlls/winewayland.drv/wayland_pointer.c +++ b/dlls/winewayland.drv/wayland_pointer.c @@ -129,6 +129,7 @@ static void pointer_handle_button(void *data, struct wl_pointer *wl_pointer, uint32_t serial, uint32_t time, uint32_t button, uint32_t state) { + struct wayland_pointer *pointer = &process_wayland.pointer; INPUT input = {0}; HWND hwnd;
@@ -146,6 +147,11 @@ static void pointer_handle_button(void *data, struct wl_pointer *wl_pointer,
if (state == WL_POINTER_BUTTON_STATE_RELEASED) input.mi.dwFlags <<= 1;
+ pthread_mutex_lock(&pointer->mutex); + pointer->button_serial = state == WL_POINTER_BUTTON_STATE_PRESSED ? + serial : 0; + pthread_mutex_unlock(&pointer->mutex); + TRACE("hwnd=%p button=%#x state=%u\n", hwnd, button, state);
__wine_send_input(hwnd, &input, NULL); diff --git a/dlls/winewayland.drv/waylanddrv.h b/dlls/winewayland.drv/waylanddrv.h index 51e958c85f8..bb78883c539 100644 --- a/dlls/winewayland.drv/waylanddrv.h +++ b/dlls/winewayland.drv/waylanddrv.h @@ -74,10 +74,17 @@ struct wayland_pointer struct wl_pointer *wl_pointer; HWND focused_hwnd; uint32_t enter_serial; + uint32_t button_serial; struct wayland_cursor cursor; pthread_mutex_t mutex; };
+struct wayland_seat +{ + struct wl_seat *wl_seat; + pthread_mutex_t mutex; +}; + struct wayland { BOOL initialized; @@ -88,7 +95,7 @@ struct wayland struct wl_compositor *wl_compositor; struct xdg_wm_base *xdg_wm_base; struct wl_shm *wl_shm; - struct wl_seat *wl_seat; + struct wayland_seat seat; struct wayland_pointer pointer; struct wl_list output_list; /* Protects the output_list and the wayland_output.current states. */ @@ -230,6 +237,7 @@ RGNDATA *get_region_data(HRGN region) DECLSPEC_HIDDEN; LRESULT WAYLAND_DesktopWindowProc(HWND hwnd, UINT msg, WPARAM wp, LPARAM lp) DECLSPEC_HIDDEN; void WAYLAND_DestroyWindow(HWND hwnd) DECLSPEC_HIDDEN; void WAYLAND_SetCursor(HWND hwnd, HCURSOR hcursor) DECLSPEC_HIDDEN; +LRESULT WAYLAND_SysCommand(HWND hwnd, WPARAM wparam, LPARAM lparam) 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; diff --git a/dlls/winewayland.drv/waylanddrv_main.c b/dlls/winewayland.drv/waylanddrv_main.c index eb54efe1180..7151d7b931a 100644 --- a/dlls/winewayland.drv/waylanddrv_main.c +++ b/dlls/winewayland.drv/waylanddrv_main.c @@ -34,6 +34,7 @@ static const struct user_driver_funcs waylanddrv_funcs = .pDesktopWindowProc = WAYLAND_DesktopWindowProc, .pDestroyWindow = WAYLAND_DestroyWindow, .pSetCursor = WAYLAND_SetCursor, + .pSysCommand = WAYLAND_SysCommand, .pUpdateDisplayDevices = WAYLAND_UpdateDisplayDevices, .pWindowMessage = WAYLAND_WindowMessage, .pWindowPosChanged = WAYLAND_WindowPosChanged, diff --git a/dlls/winewayland.drv/window.c b/dlls/winewayland.drv/window.c index 194568e0228..881ba24d01d 100644 --- a/dlls/winewayland.drv/window.c +++ b/dlls/winewayland.drv/window.c @@ -415,6 +415,45 @@ LRESULT WAYLAND_DesktopWindowProc(HWND hwnd, UINT msg, WPARAM wp, LPARAM lp) return NtUserMessageCall(hwnd, msg, wp, lp, 0, NtUserDefWindowProc, FALSE); }
+/*********************************************************************** + * WAYLAND_SysCommand + */ +LRESULT WAYLAND_SysCommand(HWND hwnd, WPARAM wparam, LPARAM lparam) +{ + LRESULT ret = -1; + WPARAM command = wparam & 0xfff0; + uint32_t button_serial; + struct wl_seat *wl_seat; + struct wayland_surface *surface; + + TRACE("cmd=%lx hwnd=%p, %lx, %lx\n", + (long)command, hwnd, (long)wparam, lparam); + + pthread_mutex_lock(&process_wayland.pointer.mutex); + if (process_wayland.pointer.focused_hwnd == hwnd) + button_serial = process_wayland.pointer.button_serial; + else + button_serial = 0; + pthread_mutex_unlock(&process_wayland.pointer.mutex); + + if (command == SC_MOVE) + { + if ((surface = wayland_surface_lock_hwnd(hwnd))) + { + pthread_mutex_lock(&process_wayland.seat.mutex); + wl_seat = process_wayland.seat.wl_seat; + if (wl_seat && surface->xdg_toplevel && button_serial) + xdg_toplevel_move(surface->xdg_toplevel, wl_seat, button_serial); + pthread_mutex_unlock(&process_wayland.seat.mutex); + pthread_mutex_unlock(&surface->mutex); + ret = 0; + } + } + + wl_display_flush(process_wayland.wl_display); + return ret; +} + /********************************************************************** * wayland_window_flush *