diff options
Diffstat (limited to 'src/plugins/platforms/windows/qwindowscontext.cpp')
-rw-r--r-- | src/plugins/platforms/windows/qwindowscontext.cpp | 115 |
1 files changed, 97 insertions, 18 deletions
diff --git a/src/plugins/platforms/windows/qwindowscontext.cpp b/src/plugins/platforms/windows/qwindowscontext.cpp index f2f285f0f6..dc861c963d 100644 --- a/src/plugins/platforms/windows/qwindowscontext.cpp +++ b/src/plugins/platforms/windows/qwindowscontext.cpp @@ -191,7 +191,8 @@ QWindowsUser32DLL::QWindowsUser32DLL() : updateLayeredWindowIndirect(0), isHungAppWindow(0), registerTouchWindow(0), unregisterTouchWindow(0), - getTouchInputInfo(0), closeTouchInputHandle(0), setProcessDPIAware(0) + getTouchInputInfo(0), closeTouchInputHandle(0), setProcessDPIAware(0), + addClipboardFormatListener(0), removeClipboardFormatListener(0) { } @@ -207,6 +208,11 @@ void QWindowsUser32DLL::init() updateLayeredWindowIndirect = (UpdateLayeredWindowIndirect)(library.resolve("UpdateLayeredWindowIndirect")); isHungAppWindow = (IsHungAppWindow)library.resolve("IsHungAppWindow"); setProcessDPIAware = (SetProcessDPIAware)library.resolve("SetProcessDPIAware"); + + if (QSysInfo::windowsVersion() >= QSysInfo::WV_VISTA) { + addClipboardFormatListener = (AddClipboardFormatListener)library.resolve("AddClipboardFormatListener"); + removeClipboardFormatListener = (RemoveClipboardFormatListener)library.resolve("RemoveClipboardFormatListener"); + } } bool QWindowsUser32DLL::initTouch() @@ -247,8 +253,26 @@ void QWindowsShell32DLL::init() sHGetImageList = (SHGetImageList)library.resolve("SHGetImageList"); } +QWindowsShcoreDLL::QWindowsShcoreDLL() + : getProcessDpiAwareness(0) + , setProcessDpiAwareness(0) + , getDpiForMonitor(0) +{ +} + +void QWindowsShcoreDLL::init() +{ + if (QSysInfo::windowsVersion() < QSysInfo::WV_WINDOWS8_1) + return; + QSystemLibrary library(QStringLiteral("SHCore")); + getProcessDpiAwareness = (GetProcessDpiAwareness)library.resolve("GetProcessDpiAwareness"); + setProcessDpiAwareness = (SetProcessDpiAwareness)library.resolve("SetProcessDpiAwareness"); + getDpiForMonitor = (GetDpiForMonitor)library.resolve("GetDpiForMonitor"); +} + QWindowsUser32DLL QWindowsContext::user32dll; QWindowsShell32DLL QWindowsContext::shell32dll; +QWindowsShcoreDLL QWindowsContext::shcoredll; #endif // !Q_OS_WINCE @@ -299,9 +323,7 @@ QWindowsContextPrivate::QWindowsContextPrivate() #ifndef Q_OS_WINCE QWindowsContext::user32dll.init(); QWindowsContext::shell32dll.init(); - // Ensure metrics functions report correct data, QTBUG-30063. - if (QWindowsContext::user32dll.setProcessDPIAware) - QWindowsContext::user32dll.setProcessDPIAware(); + QWindowsContext::shcoredll.init(); if (hasTouchSupport(ver) && QWindowsContext::user32dll.initTouch()) m_systemInfo |= QWindowsContext::SI_SupportsTouch; @@ -358,6 +380,25 @@ void QWindowsContext::setTabletAbsoluteRange(int a) #endif } +void QWindowsContext::setProcessDpiAwareness(QtWindows::ProcessDpiAwareness dpiAwareness) +{ +#ifndef Q_OS_WINCE + qCDebug(lcQpaWindows) << __FUNCTION__ << dpiAwareness; + if (QWindowsContext::shcoredll.isValid()) { + const HRESULT hr = QWindowsContext::shcoredll.setProcessDpiAwareness(dpiAwareness); + if (FAILED(hr)) + qWarning() << "SetProcessDpiAwareness failed:" << QWindowsContext::comErrorString(hr); + } else { + if (dpiAwareness != QtWindows::ProcessDpiUnaware && QWindowsContext::user32dll.setProcessDPIAware) { + if (!QWindowsContext::user32dll.setProcessDPIAware()) + qErrnoWarning("SetProcessDPIAware() failed"); + } + } +#else // !Q_OS_WINCE + Q_UNUSED(dpiAwareness) +#endif +} + QWindowsContext *QWindowsContext::instance() { return m_instance; @@ -419,9 +460,17 @@ QString QWindowsContext::registerWindowClass(const QWindow *w, bool isGL) && (type == Qt::Popup || w->property("_q_windowsDropShadow").toBool())) { style |= CS_DROPSHADOW; } - if (type == Qt::Tool || type == Qt::ToolTip || type == Qt::Popup) { + switch (type) { + case Qt::Tool: + case Qt::ToolTip: + case Qt::Popup: style |= CS_SAVEBITS; // Save/restore background icon = false; + break; + case Qt::Dialog: + if (!(flags & Qt::WindowSystemMenuHint)) + icon = false; // QTBUG-2027, dialogs without system menu. + break; } // Create a unique name for the flag combination QString cname = QStringLiteral("Qt5QWindow"); @@ -632,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; } @@ -913,6 +991,7 @@ bool QWindowsContext::windowsProc(HWND hwnd, UINT message, case QtWindows::InputMethodKeyEvent: case QtWindows::InputMethodKeyDownEvent: case QtWindows::KeyboardLayoutChangeEvent: + case QtWindows::AppCommandEvent: #if !defined(Q_OS_WINCE) && !defined(QT_NO_SESSIONMANAGER) return platformSessionManager()->isInteractionBlocked() ? true : d->m_keyMapper.translateKeyEvent(platformWindow->window(), hwnd, msg, result); #else |