From 04ba6fbed900403ef8892820fa93925a8e21f7b1 Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Tue, 5 Aug 2014 10:19:41 +0200 Subject: Windows/QGuiApplication::topLevelAt(): Skip mouse-transparent windows of other processes. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Search again when a non-Qt window with WS_EX_TRANSPARENT set is found. Task-number: QTBUG-40555 Change-Id: I3f53be626f52dc25429661ac8ea5e9f6bb163596 Reviewed-by: Björn Breitmeyer Reviewed-by: Joerg Bornemann --- src/plugins/platforms/windows/qwindowscontext.cpp | 55 +++++++++++++++++------ 1 file changed, 42 insertions(+), 13 deletions(-) (limited to 'src/plugins/platforms/windows/qwindowscontext.cpp') diff --git a/src/plugins/platforms/windows/qwindowscontext.cpp b/src/plugins/platforms/windows/qwindowscontext.cpp index 9706615047..dc861c963d 100644 --- a/src/plugins/platforms/windows/qwindowscontext.cpp +++ b/src/plugins/platforms/windows/qwindowscontext.cpp @@ -681,25 +681,54 @@ void QWindowsContext::clearWindowUnderMouse() \a parent is the parent window, pass GetDesktopWindow() for top levels. */ +static inline bool findPlatformWindowHelper(const POINT &screenPoint, unsigned cwexFlags, + const QWindowsContext *context, + HWND *hwnd, QWindowsWindow **result) +{ + POINT point = screenPoint; + ScreenToClient(*hwnd, &point); + // Returns parent if inside & none matched. +#ifndef Q_OS_WINCE + const HWND child = ChildWindowFromPointEx(*hwnd, point, cwexFlags); +#else + Q_UNUSED(cwexFlags) + const HWND child = ChildWindowFromPoint(*hwnd, point); +#endif + if (!child || child == *hwnd) + return false; + if (QWindowsWindow *window = context->findPlatformWindow(child)) { + *result = window; + *hwnd = child; + return true; + } +#ifndef Q_OS_WINCE // Does not have WS_EX_TRANSPARENT . + // QTBUG-40555: despite CWP_SKIPINVISIBLE, it is possible to hit on invisible + // full screen windows of other applications that have WS_EX_TRANSPARENT set + // (for example created by screen sharing applications). In that case, try to + // find a Qt window by searching again with CWP_SKIPTRANSPARENT. + // Note that Qt 5 uses WS_EX_TRANSPARENT for Qt::WindowTransparentForInput + // as well. + if (!(cwexFlags & CWP_SKIPTRANSPARENT) + && (GetWindowLongPtr(child, GWL_EXSTYLE) & WS_EX_TRANSPARENT)) { + const HWND nonTransparentChild = ChildWindowFromPointEx(*hwnd, point, cwexFlags | CWP_SKIPTRANSPARENT); + if (QWindowsWindow *nonTransparentWindow = context->findPlatformWindow(nonTransparentChild)) { + *result = nonTransparentWindow; + *hwnd = nonTransparentChild; + return true; + } + } +#endif // !Q_OS_WINCE + *hwnd = child; + return true; +} + QWindowsWindow *QWindowsContext::findPlatformWindowAt(HWND parent, const QPoint &screenPointIn, unsigned cwex_flags) const { QWindowsWindow *result = 0; const POINT screenPoint = { screenPointIn.x(), screenPointIn.y() }; - while (true) { - POINT point = screenPoint; - ScreenToClient(parent, &point); - // Returns parent if inside & none matched. - const HWND child = ChildWindowFromPointEx(parent, point, cwex_flags); - if (child && child != parent) { - if (QWindowsWindow *window = findPlatformWindow(child)) - result = window; - parent = child; - } else { - break; - } - } + while (findPlatformWindowHelper(screenPoint, cwex_flags, this, &parent, &result)) {} return result; } -- cgit v1.2.3