From aec87a3514616ab83b698b85490357b7eeca4d56 Mon Sep 17 00:00:00 2001 From: Luca Bacci Date: Fri, 6 Nov 2020 22:43:45 +0100 Subject: [PATCH] GdkWin32: Fix mouse events in presence of transparent windows on the desktop In gdkdevice-win32.c we are interested in knowing which window receives mouse input at a specific location. Only WindowFromPoint is the right API for the task, other API's (such as (Real)ChildWindowFromPoint(Ex)) have shortcomings because they are really designed for other purposes. For example, only WindowFromPoint is able to look through transparent layered windows. So even if we want to find a direct child we have to use WindowFromPoint and then walk up the hierarchy. Fixes: #370, #417 See: !2800 --- gdk/win32/gdkdevice-win32.c | 41 +++++++++++++------------------------ 1 file changed, 14 insertions(+), 27 deletions(-) diff --git a/gdk/win32/gdkdevice-win32.c b/gdk/win32/gdkdevice-win32.c index 90fae48ac1..35802b93a2 100644 --- a/gdk/win32/gdkdevice-win32.c +++ b/gdk/win32/gdkdevice-win32.c @@ -174,38 +174,25 @@ _gdk_device_win32_surface_at_position (GdkDevice *device, GdkSurface *window = NULL; GdkWin32Surface *impl = NULL; POINT screen_pt, client_pt; - HWND hwnd, hwndc; + HWND hwnd; RECT rect; - GetCursorPos (&screen_pt); + if (!GetCursorPos (&screen_pt)) + return NULL; - /* Only consider visible children of the desktop to avoid the various - * non-visible windows you often find on a running Windows box. These - * might overlap our windows and cause our walk to fail. As we assume - * WindowFromPoint() can find our windows, we follow similar logic - * here, and ignore invisible and disabled windows. - */ - hwnd = GetDesktopWindow (); - do { - window = gdk_win32_handle_table_lookup (hwnd); + /* Use WindowFromPoint instead of ChildWindowFromPoint(Ex). + * Only WindowFromPoint is able to look through transparent + * layered windows. + */ + hwnd = GetAncestor (WindowFromPoint (screen_pt), GA_ROOT); - if (window != NULL) - break; + /* Verify that we're really inside the client area of the window */ + GetClientRect (hwnd, &rect); + screen_to_client (hwnd, screen_pt, &client_pt); + if (!PtInRect (&rect, client_pt)) + hwnd = NULL; - screen_to_client (hwnd, screen_pt, &client_pt); - hwndc = ChildWindowFromPointEx (hwnd, client_pt, CWP_SKIPDISABLED | - CWP_SKIPINVISIBLE); - - /* Verify that we're really inside the client area of the window */ - if (hwndc != hwnd) - { - GetClientRect (hwndc, &rect); - screen_to_client (hwndc, screen_pt, &client_pt); - if (!PtInRect (&rect, client_pt)) - hwndc = hwnd; - } - - } while (hwndc != hwnd && (hwnd = hwndc, 1)); + window = gdk_win32_handle_table_lookup (hwnd); if (window && (win_x || win_y)) {