From 85264a759d1de319402e83febf2f736d1b4c3a48 Mon Sep 17 00:00:00 2001 From: Robbert van der Helm Date: Mon, 26 Jul 2021 13:59:55 +0200 Subject: [PATCH] Move check for cursor within Wine window to editor We'll reuse this for the LeaveNotify check instead to avoid having to ignore all `NonVirtual` events. --- src/wine-host/editor.cpp | 27 +++++++++++++++++++++++++++ src/wine-host/editor.h | 9 +++++++++ src/wine-host/xdnd-proxy.cpp | 27 ++++----------------------- 3 files changed, 40 insertions(+), 23 deletions(-) diff --git a/src/wine-host/editor.cpp b/src/wine-host/editor.cpp index 7cbf4fa9..df322e78 100644 --- a/src/wine-host/editor.cpp +++ b/src/wine-host/editor.cpp @@ -1245,4 +1245,31 @@ ATOM get_window_class() noexcept { return window_class_handle; } +bool is_cursor_in_wine_window() noexcept { + static const HWND windows_desktop_window = GetDesktopWindow(); + + POINT windows_pointer_pos; + GetCursorPos(&windows_pointer_pos); + if (HWND windows_window = WindowFromPoint(windows_pointer_pos); + windows_window && windows_window != windows_desktop_window) { + // NOTE: Because resizing reparented Wine windows without XEmbed is + // a bit janky, yabridge creates windows with client areas + // large enough to fit the entire screen, and the plugin then + // embeds its own GUI in a portion of that. The result is that + // `WindowFromPoint()` will still return that same huge window + // when we hover over an area to the right or to the bottom of + // a plugin GUI. We can easily detect and skip that though, + // since the embedded plugin windows won't have an X11 window + // ID property. + const xcb_window_t x11_window = + static_cast(reinterpret_cast( + GetProp(windows_window, "__wine_x11_whole_window"))); + if (x11_window == XCB_NONE) { + return true; + } + } + + return false; +} + #undef THROW_X11_ERROR diff --git a/src/wine-host/editor.h b/src/wine-host/editor.h index 39c88cfb..0f7c6299 100644 --- a/src/wine-host/editor.h +++ b/src/wine-host/editor.h @@ -69,6 +69,15 @@ constexpr char xdnd_aware_property_name[] = "XdndAware"; xcb_atom_t get_atom_by_name(xcb_connection_t& x11_connection, const char* atom_name); +/** + * Check if the cursor is within a Wine window. We can of course only detect + * Wine applications within the current prefix. This ignores the extended client + * area of yabridge windows (which might mean that this function will spuriously + * return false if another window on the bottom right of an editor window is + * 'obstructed' by this clipped, invisible window). + */ +bool is_cursor_in_wine_window() noexcept; + /** * Used to store the maximum width and height of a screen. */ diff --git a/src/wine-host/xdnd-proxy.cpp b/src/wine-host/xdnd-proxy.cpp index 202c0420..aa34414f 100644 --- a/src/wine-host/xdnd-proxy.cpp +++ b/src/wine-host/xdnd-proxy.cpp @@ -283,8 +283,6 @@ void WineXdndProxy::end_xdnd() { #endif void WineXdndProxy::run_xdnd_loop() { - const HWND windows_desktop_window = GetDesktopWindow(); - std::optional last_xdnd_window; // Position and status messages should be sent in lockstep, which makes // everything a bit more complicated. Because of that we may need to spool @@ -428,27 +426,10 @@ void WineXdndProxy::run_xdnd_loop() { // We want to ignore all Wine windows (within this prefix), since Wine // will be able to handle the drag-and-drop better than we can - POINT windows_pointer_pos; - GetCursorPos(&windows_pointer_pos); - if (HWND windows_window = WindowFromPoint(windows_pointer_pos); - windows_window && windows_window != windows_desktop_window) { - // NOTE: Because resizing reparented Wine windows without XEmbed is - // a bit janky, yabridge creates windows with client areas - // large enough to fit the entire screen, and the plugin then - // embeds its own GUI in a portion of that. The result is that - // `WindowFromPoint()` will still return that same huge window - // when we hover over an area to the right or to the bottom of - // a plugin GUI. We can easily detect and skip that though, - // since the embedded plugin windows won't have an X11 window - // ID property. - const xcb_window_t x11_window = - static_cast(reinterpret_cast( - GetProp(windows_window, "__wine_x11_whole_window"))); - if (x11_window == XCB_NONE) { - maybe_leave_last_window(); - last_xdnd_window.reset(); - continue; - } + if (is_cursor_in_wine_window()) { + maybe_leave_last_window(); + last_xdnd_window.reset(); + continue; } // When transitioning between windows we need to announce this to