summaryrefslogtreecommitdiffstats
path: root/src/plugins/platforms/windows/qwindowscontext.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/plugins/platforms/windows/qwindowscontext.cpp')
-rw-r--r--src/plugins/platforms/windows/qwindowscontext.cpp241
1 files changed, 155 insertions, 86 deletions
diff --git a/src/plugins/platforms/windows/qwindowscontext.cpp b/src/plugins/platforms/windows/qwindowscontext.cpp
index e11bb5e335..8c0261d568 100644
--- a/src/plugins/platforms/windows/qwindowscontext.cpp
+++ b/src/plugins/platforms/windows/qwindowscontext.cpp
@@ -45,10 +45,13 @@
#include <QtCore/qscopedpointer.h>
#include <QtCore/quuid.h>
#include <QtCore/private/qwinregistry_p.h>
-#include <QtCore/private/qfactorycacheregistration_p.h>
+#if QT_CONFIG(cpp_winrt)
+# include <QtCore/private/qfactorycacheregistration_p.h>
+#endif
#include <QtCore/private/qsystemerror_p.h>
#include <QtGui/private/qwindowsguieventdispatcher_p.h>
+#include <QtGui/private/qwindowsthemecache_p.h>
#include <stdlib.h>
#include <stdio.h>
@@ -118,26 +121,6 @@ static inline bool sessionManagerInteractionBlocked()
static inline bool sessionManagerInteractionBlocked() { return false; }
#endif
-static inline int windowDpiAwareness(HWND hwnd)
-{
- return static_cast<int>(GetAwarenessFromDpiAwarenessContext(GetWindowDpiAwarenessContext(hwnd)));
-}
-
-// Note: This only works within WM_NCCREATE
-static bool enableNonClientDpiScaling(HWND hwnd)
-{
- bool result = false;
- if (windowDpiAwareness(hwnd) == 2) {
- result = EnableNonClientDpiScaling(hwnd) != FALSE;
- if (!result) {
- const DWORD errorCode = GetLastError();
- qErrnoWarning(int(errorCode), "EnableNonClientDpiScaling() failed for HWND %p (%lu)",
- hwnd, errorCode);
- }
- }
- return result;
-}
-
QWindowsContext *QWindowsContext::m_instance = nullptr;
/*!
@@ -171,11 +154,9 @@ struct QWindowsContextPrivate {
bool m_asyncExpose = false;
HPOWERNOTIFY m_powerNotification = nullptr;
HWND m_powerDummyWindow = nullptr;
- static bool m_darkMode;
static bool m_v2DpiAware;
};
-bool QWindowsContextPrivate::m_darkMode = false;
bool QWindowsContextPrivate::m_v2DpiAware = false;
QWindowsContextPrivate::QWindowsContextPrivate()
@@ -189,7 +170,6 @@ QWindowsContextPrivate::QWindowsContextPrivate()
m_systemInfo |= QWindowsContext::SI_RTL_Extensions;
m_keyMapper.setUseRTLExtensions(true);
}
- m_darkMode = QWindowsTheme::queryDarkMode();
if (FAILED(m_oleInitializeResult)) {
qWarning() << "QWindowsContext: OleInitialize() failed: "
<< QSystemError::windowsComString(m_oleInitializeResult);
@@ -221,6 +201,8 @@ QWindowsContext::~QWindowsContext()
if (d->m_powerDummyWindow)
DestroyWindow(d->m_powerDummyWindow);
+ d->m_screenManager.destroyWindow();
+
unregisterWindowClasses();
if (d->m_oleInitializeResult == S_OK || d->m_oleInitializeResult == S_FALSE) {
#ifdef QT_USE_FACTORY_CACHE_REGISTRATION
@@ -366,52 +348,121 @@ void QWindowsContext::setDetectAltGrModifier(bool a)
d->m_keyMapper.setDetectAltGrModifier(a);
}
-int QWindowsContext::processDpiAwareness()
-{
- PROCESS_DPI_AWARENESS result;
- if (SUCCEEDED(GetProcessDpiAwareness(nullptr, &result))) {
- return static_cast<int>(result);
+[[nodiscard]] static inline QtWindows::DpiAwareness
+ dpiAwarenessContextToQtDpiAwareness(DPI_AWARENESS_CONTEXT context)
+{
+ // IsValidDpiAwarenessContext() will handle the NULL pointer case.
+ if (!IsValidDpiAwarenessContext(context))
+ return QtWindows::DpiAwareness::Invalid;
+ if (AreDpiAwarenessContextsEqual(context, DPI_AWARENESS_CONTEXT_UNAWARE_GDISCALED))
+ return QtWindows::DpiAwareness::Unaware_GdiScaled;
+ if (AreDpiAwarenessContextsEqual(context, DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2))
+ return QtWindows::DpiAwareness::PerMonitorVersion2;
+ if (AreDpiAwarenessContextsEqual(context, DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE))
+ return QtWindows::DpiAwareness::PerMonitor;
+ if (AreDpiAwarenessContextsEqual(context, DPI_AWARENESS_CONTEXT_SYSTEM_AWARE))
+ return QtWindows::DpiAwareness::System;
+ if (AreDpiAwarenessContextsEqual(context, DPI_AWARENESS_CONTEXT_UNAWARE))
+ return QtWindows::DpiAwareness::Unaware;
+ return QtWindows::DpiAwareness::Invalid;
+}
+
+QtWindows::DpiAwareness QWindowsContext::windowDpiAwareness(HWND hwnd)
+{
+ if (!hwnd)
+ return QtWindows::DpiAwareness::Invalid;
+ const auto context = GetWindowDpiAwarenessContext(hwnd);
+ return dpiAwarenessContextToQtDpiAwareness(context);
+}
+
+QtWindows::DpiAwareness QWindowsContext::processDpiAwareness()
+{
+ // Although we have GetDpiAwarenessContextForProcess(), however,
+ // it's only available on Win10 1903+, which is a little higher
+ // than Qt's minimum supported version (1809), so we can't use it.
+ // Luckily, MS docs said GetThreadDpiAwarenessContext() will also
+ // return the default DPI_AWARENESS_CONTEXT for the process if
+ // SetThreadDpiAwarenessContext() was never called. So we can use
+ // it as an equivalent.
+ const auto context = GetThreadDpiAwarenessContext();
+ return dpiAwarenessContextToQtDpiAwareness(context);
+}
+
+[[nodiscard]] static inline DPI_AWARENESS_CONTEXT
+ qtDpiAwarenessToDpiAwarenessContext(QtWindows::DpiAwareness dpiAwareness)
+{
+ switch (dpiAwareness) {
+ case QtWindows::DpiAwareness::Invalid:
+ return nullptr;
+ case QtWindows::DpiAwareness::Unaware:
+ return DPI_AWARENESS_CONTEXT_UNAWARE;
+ case QtWindows::DpiAwareness::System:
+ return DPI_AWARENESS_CONTEXT_SYSTEM_AWARE;
+ case QtWindows::DpiAwareness::PerMonitor:
+ return DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE;
+ case QtWindows::DpiAwareness::PerMonitorVersion2:
+ return DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2;
+ case QtWindows::DpiAwareness::Unaware_GdiScaled:
+ return DPI_AWARENESS_CONTEXT_UNAWARE_GDISCALED;
}
- return -1;
+ return nullptr;
}
-void QWindowsContext::setProcessDpiAwareness(QtWindows::ProcessDpiAwareness dpiAwareness)
+#ifndef QT_NO_DEBUG_STREAM
+QDebug operator<<(QDebug d, QtWindows::DpiAwareness dpiAwareness)
{
- qCDebug(lcQpaWindow) << __FUNCTION__ << dpiAwareness;
- const HRESULT hr = SetProcessDpiAwareness(static_cast<PROCESS_DPI_AWARENESS>(dpiAwareness));
- // E_ACCESSDENIED means set externally (MSVC manifest or external app loading Qt plugin).
- // Silence warning in that case unless debug is enabled.
- if (FAILED(hr) && hr != E_ACCESSDENIED) {
- qCWarning(lcQpaWindow).noquote().nospace() << "SetProcessDpiAwareness("
- << dpiAwareness << ") failed: " << QSystemError::windowsComString(hr)
- << ", using " << QWindowsContext::processDpiAwareness();
+ const QDebugStateSaver saver(d);
+ QString message = u"QtWindows::DpiAwareness::"_s;
+ switch (dpiAwareness) {
+ case QtWindows::DpiAwareness::Invalid:
+ message += u"Invalid"_s;
+ break;
+ case QtWindows::DpiAwareness::Unaware:
+ message += u"Unaware"_s;
+ break;
+ case QtWindows::DpiAwareness::System:
+ message += u"System"_s;
+ break;
+ case QtWindows::DpiAwareness::PerMonitor:
+ message += u"PerMonitor"_s;
+ break;
+ case QtWindows::DpiAwareness::PerMonitorVersion2:
+ message += u"PerMonitorVersion2"_s;
+ break;
+ case QtWindows::DpiAwareness::Unaware_GdiScaled:
+ message += u"Unaware_GdiScaled"_s;
+ break;
}
+ d.nospace().noquote() << message;
+ return d;
}
+#endif
-bool QWindowsContext::setProcessDpiV2Awareness()
+bool QWindowsContext::setProcessDpiAwareness(QtWindows::DpiAwareness dpiAwareness)
{
- qCDebug(lcQpaWindow) << __FUNCTION__;
- const BOOL ok = SetProcessDpiAwarenessContext(DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2);
- if (!ok) {
- const DWORD dwError = GetLastError();
- // ERROR_ACCESS_DENIED means set externally (MSVC manifest or external app loading Qt plugin).
- // Silence warning in that case unless debug is enabled.
- if (dwError != ERROR_ACCESS_DENIED) {
- qCWarning(lcQpaWindow).noquote().nospace()
- << "SetProcessDpiAwarenessContext(DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2) failed: "
- << QSystemError::windowsComString(HRESULT(dwError));
- return false;
- }
+ qCDebug(lcQpaWindow) << __FUNCTION__ << dpiAwareness;
+ if (processDpiAwareness() == dpiAwareness)
+ return true;
+ const auto context = qtDpiAwarenessToDpiAwarenessContext(dpiAwareness);
+ if (!IsValidDpiAwarenessContext(context)) {
+ qCWarning(lcQpaWindow) << dpiAwareness << "is not supported by current system.";
+ return false;
}
- QWindowsContextPrivate::m_v2DpiAware = true;
+ if (!SetProcessDpiAwarenessContext(context)) {
+ qCWarning(lcQpaWindow).noquote().nospace()
+ << "SetProcessDpiAwarenessContext() failed: "
+ << QSystemError::windowsString()
+ << "\nQt's default DPI awareness context is "
+ << "DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2. If you know what you "
+ << "are doing, you can overwrite this default using qt.conf "
+ << "(https://doc.qt.io/qt-6/highdpi.html#configuring-windows).";
+ return false;
+ }
+ QWindowsContextPrivate::m_v2DpiAware
+ = processDpiAwareness() == QtWindows::DpiAwareness::PerMonitorVersion2;
return true;
}
-bool QWindowsContext::isDarkMode()
-{
- return QWindowsContextPrivate::m_darkMode;
-}
-
QWindowsContext *QWindowsContext::instance()
{
return m_instance;
@@ -427,9 +478,9 @@ bool QWindowsContext::useRTLExtensions() const
return d->m_keyMapper.useRTLExtensions();
}
-QList<int> QWindowsContext::possibleKeys(const QKeyEvent *e) const
+QPlatformKeyMapper *QWindowsContext::keyMapper() const
{
- return d->m_keyMapper.possibleKeys(e);
+ return &d->m_keyMapper;
}
QWindowsContext::HandleBaseWindowHash &QWindowsContext::windows()
@@ -481,6 +532,8 @@ QString QWindowsContext::classNamePrefix()
# define xstr(s) str(s)
# define str(s) #s
str << xstr(QT_NAMESPACE);
+# undef str
+# undef xstr
#endif
}
return result;
@@ -541,7 +594,7 @@ QString QWindowsContext::registerWindowClass(const QWindow *w)
if (icon)
cname += "Icon"_L1;
- return registerWindowClass(cname, qWindowsWndProc, style, GetSysColorBrush(COLOR_WINDOW), icon);
+ return registerWindowClass(cname, qWindowsWndProc, style, nullptr, icon);
}
QString QWindowsContext::registerWindowClass(QString cname,
@@ -916,6 +969,21 @@ static inline bool isInputMessage(UINT m)
|| (m >= WM_KEYFIRST && m <= WM_KEYLAST);
}
+// Note: This only works within WM_NCCREATE
+static bool enableNonClientDpiScaling(HWND hwnd)
+{
+ bool result = false;
+ if (QWindowsContext::windowDpiAwareness(hwnd) == QtWindows::DpiAwareness::PerMonitor) {
+ result = EnableNonClientDpiScaling(hwnd) != FALSE;
+ if (!result) {
+ const DWORD errorCode = GetLastError();
+ qErrnoWarning(int(errorCode), "EnableNonClientDpiScaling() failed for HWND %p (%lu)",
+ hwnd, errorCode);
+ }
+ }
+ return result;
+}
+
/*!
\brief Main windows procedure registered for windows.
@@ -932,9 +1000,10 @@ bool QWindowsContext::windowsProc(HWND hwnd, UINT message,
MSG msg;
msg.hwnd = hwnd; // re-create MSG structure
- msg.message = message; // time and pt fields ignored
+ msg.message = message;
msg.wParam = wParam;
msg.lParam = lParam;
+ msg.time = GetMessageTime();
msg.pt.x = msg.pt.y = 0;
if (et != QtWindows::CursorEvent && (et & (QtWindows::MouseEventFlag | QtWindows::NonClientEventFlag))) {
msg.pt.x = GET_X_LPARAM(lParam);
@@ -1018,20 +1087,7 @@ bool QWindowsContext::windowsProc(HWND hwnd, UINT message,
// Only refresh the window theme if the user changes the personalize settings.
if ((wParam == 0) && (lParam != 0) // lParam sometimes may be NULL.
&& (wcscmp(reinterpret_cast<LPCWSTR>(lParam), L"ImmersiveColorSet") == 0)) {
- const bool darkMode = QWindowsTheme::queryDarkMode();
- const bool darkModeChanged = darkMode != QWindowsContextPrivate::m_darkMode;
- QWindowsContextPrivate::m_darkMode = darkMode;
- auto integration = QWindowsIntegration::instance();
- if (integration->darkModeHandling().testFlag(QWindowsApplication::DarkModeStyle)) {
- QWindowsTheme::instance()->refresh();
- QWindowSystemInterface::handleThemeChange();
- }
- if (darkModeChanged) {
- if (integration->darkModeHandling().testFlag(QWindowsApplication::DarkModeWindowFrames)) {
- for (QWindowsWindow *w : d->m_windows)
- w->setDarkBorder(QWindowsContextPrivate::m_darkMode);
- }
- }
+ QWindowsTheme::handleSettingsChanged();
}
return d->m_screenManager.handleScreenChanges();
}
@@ -1048,7 +1104,7 @@ bool QWindowsContext::windowsProc(HWND hwnd, UINT message,
d->m_creationContext->applyToMinMaxInfo(reinterpret_cast<MINMAXINFO *>(lParam));
return true;
case QtWindows::ResizeEvent:
- d->m_creationContext->obtainedSize = QSize(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam));
+ d->m_creationContext->obtainedSize = QSize(LOWORD(lParam), HIWORD(lParam));
return true;
case QtWindows::MoveEvent:
d->m_creationContext->obtainedPos = QPoint(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam));
@@ -1091,7 +1147,7 @@ bool QWindowsContext::windowsProc(HWND hwnd, UINT message,
if (wParam == DBT_DEVNODES_CHANGED)
initTouch();
break;
- case QtWindows::KeyboardLayoutChangeEvent:
+ case QtWindows::InputLanguageChangeEvent:
if (QWindowsInputContext *wic = windowsInputContext())
wic->handleInputLanguageChanged(wParam, lParam);
Q_FALLTHROUGH();
@@ -1121,7 +1177,7 @@ bool QWindowsContext::windowsProc(HWND hwnd, UINT message,
platformWindow->handleMoved();
return true;
case QtWindows::ResizeEvent:
- platformWindow->handleResized(static_cast<int>(wParam));
+ platformWindow->handleResized(static_cast<int>(wParam), lParam);
return true;
case QtWindows::QuerySizeHints:
platformWindow->getSizeHints(reinterpret_cast<MINMAXINFO *>(lParam));
@@ -1135,21 +1191,29 @@ bool QWindowsContext::windowsProc(HWND hwnd, UINT message,
case QtWindows::ExposeEvent:
return platformWindow->handleWmPaint(hwnd, message, wParam, lParam, result);
case QtWindows::NonClientMouseEvent:
- if ((d->m_systemInfo & QWindowsContext::SI_SupportsPointer) && platformWindow->frameStrutEventsEnabled())
+ if (!platformWindow->frameStrutEventsEnabled())
+ break;
+ if ((d->m_systemInfo & QWindowsContext::SI_SupportsPointer))
return sessionManagerInteractionBlocked() || d->m_pointerHandler.translateMouseEvent(platformWindow->window(), hwnd, et, msg, result);
else
return sessionManagerInteractionBlocked() || d->m_mouseHandler.translateMouseEvent(platformWindow->window(), hwnd, et, msg, result);
case QtWindows::NonClientPointerEvent:
- if ((d->m_systemInfo & QWindowsContext::SI_SupportsPointer) && platformWindow->frameStrutEventsEnabled())
+ if (!platformWindow->frameStrutEventsEnabled())
+ break;
+ if ((d->m_systemInfo & QWindowsContext::SI_SupportsPointer))
return sessionManagerInteractionBlocked() || d->m_pointerHandler.translatePointerEvent(platformWindow->window(), hwnd, et, msg, result);
break;
case QtWindows::EnterSizeMoveEvent:
platformWindow->setFlag(QWindowsWindow::ResizeMoveActive);
+ if (!IsZoomed(hwnd))
+ platformWindow->updateRestoreGeometry();
return true;
case QtWindows::ExitSizeMoveEvent:
platformWindow->clearFlag(QWindowsWindow::ResizeMoveActive);
platformWindow->checkForScreenChanged();
handleExitSizeMove(platformWindow->window());
+ if (!IsZoomed(hwnd))
+ platformWindow->updateRestoreGeometry();
return true;
case QtWindows::ScrollEvent:
if (!(d->m_systemInfo & QWindowsContext::SI_SupportsPointer))
@@ -1195,6 +1259,7 @@ bool QWindowsContext::windowsProc(HWND hwnd, UINT message,
QWindowSystemInterface::handleCloseEvent(platformWindow->window());
return true;
case QtWindows::ThemeChanged: {
+ QWindowsThemeCache::clearThemeCache(platformWindow->handle());
// Switch from Aero to Classic changes margins.
if (QWindowsTheme *theme = QWindowsTheme::instance())
theme->windowsThemeChanged(platformWindow->window());
@@ -1286,6 +1351,11 @@ bool QWindowsContext::windowsProc(HWND hwnd, UINT message,
return true;
}
#endif // !defined(QT_NO_SESSIONMANAGER)
+ case QtWindows::TaskbarButtonCreated:
+ // Apply application badge if this is the first time we have a taskbar
+ // button, or after Explorer restart.
+ QWindowsIntegration::instance()->updateApplicationBadge();
+ break;
default:
break;
}
@@ -1328,7 +1398,7 @@ void QWindowsContext::handleFocusEvent(QtWindows::WindowsEventType et,
}
if (nextActiveWindow != d->m_lastActiveWindow) {
d->m_lastActiveWindow = nextActiveWindow;
- QWindowSystemInterface::handleWindowActivated(nextActiveWindow, Qt::ActiveWindowFocusReason);
+ QWindowSystemInterface::handleFocusWindowChanged(nextActiveWindow, Qt::ActiveWindowFocusReason);
}
}
@@ -1358,7 +1428,7 @@ bool QWindowsContext::handleContextMenuEvent(QWindow *window, const MSG &msg)
}
QWindowSystemInterface::handleContextMenuEvent(window, mouseTriggered, pos, globalPos,
- QWindowsKeyMapper::queryKeyboardModifiers());
+ keyMapper()->queryKeyboardModifiers());
return true;
}
#endif
@@ -1379,7 +1449,7 @@ void QWindowsContext::handleExitSizeMove(QWindow *window)
const Qt::MouseButtons appButtons = QGuiApplication::mouseButtons();
if (currentButtons == appButtons)
return;
- const Qt::KeyboardModifiers keyboardModifiers = QWindowsKeyMapper::queryKeyboardModifiers();
+ const Qt::KeyboardModifiers keyboardModifiers = keyMapper()->queryKeyboardModifiers();
const QPoint globalPos = QWindowsCursor::mousePosition();
const QPlatformWindow *platWin = window->handle();
const QPoint localPos = platWin->mapFromGlobal(globalPos);
@@ -1388,8 +1458,7 @@ void QWindowsContext::handleExitSizeMove(QWindow *window)
for (Qt::MouseButton button : {Qt::LeftButton, Qt::RightButton, Qt::MiddleButton}) {
if (appButtons.testFlag(button) && !currentButtons.testFlag(button)) {
QWindowSystemInterface::handleMouseEvent(window, localPos, globalPos,
- currentButtons, button, type,
- keyboardModifiers);
+ currentButtons, button, type, keyboardModifiers);
}
}
if (d->m_systemInfo & QWindowsContext::SI_SupportsPointer)