Windows/QGuiApplication::topLevelAt(): Skip mouse-transparent windows of other processes.

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 <bjoern.breitmeyer@kdab.com>
Reviewed-by: Joerg Bornemann <joerg.bornemann@digia.com>
This commit is contained in:
Friedemann Kleint 2014-08-05 10:19:41 +02:00
parent 2f1ab7156a
commit 04ba6fbed9
2 changed files with 42 additions and 18 deletions

View File

@ -75,7 +75,6 @@
#ifndef CWP_SKIPINVISIBLE
#define CWP_SKIPINVISIBLE 0x0001
#define CWP_SKIPTRANSPARENT 0x0004
#define findPlatformWindowAt(a, b, c) findPlatformWindowAt(a, b)
#endif
#ifndef CS_OWNDC
@ -95,10 +94,6 @@
#define SW_SHOWMINIMIZED SW_MINIMIZE
#define SW_SHOWMINNOACTIVE SW_MINIMIZE
#ifndef ChildWindowFromPointEx
#define ChildWindowFromPointEx(a, b, c) ChildWindowFromPoint(a, b)
#endif
#ifndef CF_DIBV5
#define CF_DIBV5 17
#endif

View File

@ -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;
}