[*] Restore Windows 7 support [pt 2]

Change-Id: Iae61503a4aa2f788fe76b9e9b7a7c1ad1abfae36
This commit is contained in:
Reece Wilson 2023-11-24 02:35:42 +00:00
parent a050d42ef2
commit dfb37c4e24
6 changed files with 534 additions and 500 deletions

View File

@ -63,38 +63,8 @@ QT_BEGIN_NAMESPACE
// Return tablet mode, note: Does not work for GetDesktopWindow().
bool qt_windowsIsTabletMode(HWND hwnd)
{
bool result = false;
const wchar_t uiViewSettingsId[] = L"Windows.UI.ViewManagement.UIViewSettings";
HSTRING_HEADER uiViewSettingsIdRefHeader;
HSTRING uiViewSettingsIdHs = nullptr;
const auto uiViewSettingsIdLen = UINT32(sizeof(uiViewSettingsId) / sizeof(uiViewSettingsId[0]) - 1);
if (FAILED(WindowsCreateStringReference(uiViewSettingsId, uiViewSettingsIdLen, &uiViewSettingsIdRefHeader, &uiViewSettingsIdHs)))
return false;
IUIViewSettingsInterop *uiViewSettingsInterop = nullptr;
// __uuidof(IUIViewSettingsInterop);
const GUID uiViewSettingsInteropRefId = {0x3694dbf9, 0x8f68, 0x44be,{0x8f, 0xf5, 0x19, 0x5c, 0x98, 0xed, 0xe8, 0xa6}};
HRESULT hr = RoGetActivationFactory(uiViewSettingsIdHs, uiViewSettingsInteropRefId,
reinterpret_cast<void **>(&uiViewSettingsInterop));
if (FAILED(hr))
return false;
// __uuidof(ABI::Windows::UI::ViewManagement::IUIViewSettings);
const GUID uiViewSettingsRefId = {0xc63657f6, 0x8850, 0x470d,{0x88, 0xf8, 0x45, 0x5e, 0x16, 0xea, 0x2c, 0x26}};
ABI::Windows::UI::ViewManagement::IUIViewSettings *viewSettings = nullptr;
hr = uiViewSettingsInterop->GetForWindow(hwnd, uiViewSettingsRefId,
reinterpret_cast<void **>(&viewSettings));
if (SUCCEEDED(hr)) {
ABI::Windows::UI::ViewManagement::UserInteractionMode currentMode;
hr = viewSettings->get_UserInteractionMode(&currentMode);
if (SUCCEEDED(hr))
result = currentMode == 1; // Touch, 1
viewSettings->Release();
}
uiViewSettingsInterop->Release();
return result;
return false;
}
QT_END_NAMESPACE

View File

@ -11,7 +11,7 @@
#include "qwindowspointerhandler.h"
#include "qtwindowsglobal.h"
#include "qwindowsmenu.h"
#include "qwindowsmimeregistry.h"
#include "qwindowsmime.h"
#include "qwindowsinputcontext.h"
#if QT_CONFIG(tabletevent)
# include "qwindowstabletsupport.h"
@ -45,26 +45,29 @@
#include <QtCore/qscopedpointer.h>
#include <QtCore/quuid.h>
#include <QtCore/private/qwinregistry_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>
#include <windowsx.h>
#include <comdef.h>
#include <dbt.h>
#include <wtsapi32.h>
#include <shellscalingapi.h>
QT_BEGIN_NAMESPACE
typedef HRESULT(__stdcall * SetProcessDpiAwareness_f)(PROCESS_DPI_AWARENESS value);
typedef HRESULT(__stdcall * GetProcessDpiAwareness_f)(HANDLE hprocess, PROCESS_DPI_AWARENESS* value);
typedef BOOL(__stdcall * SetProcessDpiAwarenessContext_f)(DPI_AWARENESS_CONTEXT value);
typedef BOOL(__stdcall * EnableNonClientDpiScaling_f)(HWND hwnd);
typedef DPI_AWARENESS_CONTEXT (__stdcall * GetWindowDpiAwarenessContext_f)(HWND hwnd);
typedef DPI_AWARENESS (__stdcall * GetAwarenessFromDpiAwarenessContext_f)(DPI_AWARENESS_CONTEXT value);
using namespace Qt::StringLiterals;
Q_LOGGING_CATEGORY(lcQpaWindow, "qt.qpa.window")
Q_LOGGING_CATEGORY(lcQpaWindows, "qt.qpa.windows")
Q_LOGGING_CATEGORY(lcQpaEvents, "qt.qpa.events")
Q_LOGGING_CATEGORY(lcQpaGl, "qt.qpa.gl")
Q_LOGGING_CATEGORY(lcQpaMime, "qt.qpa.mime")
@ -121,6 +124,41 @@ static inline bool sessionManagerInteractionBlocked()
static inline bool sessionManagerInteractionBlocked() { return false; }
#endif
static inline int windowDpiAwareness(HWND hwnd)
{
auto pGetAwarenessFromDpiAwarenessContext = reinterpret_cast<GetAwarenessFromDpiAwarenessContext_f>(GetProcAddress(LoadLibraryW(L"USER32.dll"), "GetAwarenessFromDpiAwarenessContext"));
if (!pGetAwarenessFromDpiAwarenessContext) {
return false;
}
auto pGetWindowDpiAwarenessContext = reinterpret_cast<GetWindowDpiAwarenessContext_f>(GetProcAddress(LoadLibraryW(L"USER32.dll"), "GetWindowDpiAwarenessContext"));
if (!pGetWindowDpiAwarenessContext) {
return false;
}
return static_cast<int>(pGetAwarenessFromDpiAwarenessContext(pGetWindowDpiAwarenessContext(hwnd)));
}
// Note: This only works within WM_NCCREATE
static bool enableNonClientDpiScaling(HWND hwnd)
{
bool result = false;
if (windowDpiAwareness(hwnd) == 2) {
auto pEnableNonClientDpiScaling = reinterpret_cast<EnableNonClientDpiScaling_f>(GetProcAddress(LoadLibraryW(L"USER32.dll"), "EnableNonClientDpiScaling"));
if (!pEnableNonClientDpiScaling) {
return false;
}
result = pEnableNonClientDpiScaling(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;
/*!
@ -143,7 +181,7 @@ struct QWindowsContextPrivate {
QWindowsKeyMapper m_keyMapper;
QWindowsMouseHandler m_mouseHandler;
QWindowsPointerHandler m_pointerHandler;
QWindowsMimeRegistry m_mimeConverter;
QWindowsMimeConverter m_mimeConverter;
QWindowsScreenManager m_screenManager;
QSharedPointer<QWindowCreationContext> m_creationContext;
#if QT_CONFIG(tabletevent)
@ -175,7 +213,7 @@ QWindowsContextPrivate::QWindowsContextPrivate()
m_darkMode = QWindowsTheme::queryDarkMode();
if (FAILED(m_oleInitializeResult)) {
qWarning() << "QWindowsContext: OleInitialize() failed: "
<< QSystemError::windowsComString(m_oleInitializeResult);
<< QWindowsContext::comErrorString(m_oleInitializeResult);
}
}
@ -205,12 +243,8 @@ QWindowsContext::~QWindowsContext()
DestroyWindow(d->m_powerDummyWindow);
unregisterWindowClasses();
if (d->m_oleInitializeResult == S_OK || d->m_oleInitializeResult == S_FALSE) {
#ifdef QT_USE_FACTORY_CACHE_REGISTRATION
detail::QWinRTFactoryCacheRegistration::clearAllCaches();
#endif
if (d->m_oleInitializeResult == S_OK || d->m_oleInitializeResult == S_FALSE)
OleUninitialize();
}
d->m_screenManager.clearScreens(); // Order: Potentially calls back to the windows.
if (d->m_displayContext)
@ -252,7 +286,7 @@ void QWindowsContext::registerTouchWindows()
{
if (QGuiApplicationPrivate::is_app_running
&& (d->m_systemInfo & QWindowsContext::SI_SupportsTouch) != 0) {
for (QWindowsWindow *w : std::as_const(d->m_windows))
for (QWindowsWindow *w : qAsConst(d->m_windows))
w->registerTouchWindow();
}
}
@ -349,118 +383,60 @@ void QWindowsContext::setDetectAltGrModifier(bool a)
d->m_keyMapper.setDetectAltGrModifier(a);
}
[[nodiscard]] static inline QtWindows::DpiAwareness
dpiAwarenessContextToQtDpiAwareness(DPI_AWARENESS_CONTEXT context)
int QWindowsContext::processDpiAwareness()
{
// 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;
PROCESS_DPI_AWARENESS result;
auto pGetDPIAwareness = reinterpret_cast<GetProcessDpiAwareness_f>(GetProcAddress(LoadLibraryW(L"api-ms-win-shcore-scaling-l1-1-1.dll"), "GetProcessDpiAwareness"));
if (!pGetDPIAwareness) {
return 0;
}
return nullptr;
}
#ifndef QT_NO_DEBUG_STREAM
QDebug operator<<(QDebug d, QtWindows::DpiAwareness dpiAwareness)
{
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;
if (SUCCEEDED(pGetDPIAwareness(nullptr, &result))) {
return static_cast<int>(result);
}
d.nospace().noquote() << message;
return d;
return -1;
}
#endif
bool QWindowsContext::setProcessDpiAwareness(QtWindows::DpiAwareness dpiAwareness)
void QWindowsContext::setProcessDpiAwareness(QtWindows::ProcessDpiAwareness dpiAwareness)
{
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.";
PROCESS_DPI_AWARENESS result;
auto pSetProcessDpiAwareness = reinterpret_cast<SetProcessDpiAwareness_f>(GetProcAddress(LoadLibraryW(L"api-ms-win-shcore-scaling-l1-1-1.dll"), "SetProcessDpiAwareness"));
if (!pSetProcessDpiAwareness) {
return;
}
qCDebug(lcQpaWindows) << __FUNCTION__ << dpiAwareness;
const HRESULT hr = pSetProcessDpiAwareness(static_cast<PROCESS_DPI_AWARENESS>(dpiAwareness));
// E_ACCESSDENIED means set externally (MSVC manifest or external app loading Qt plugin).n
// Silence warning in that case unless debug is enabled.
if (FAILED(hr) && (hr != E_ACCESSDENIED || lcQpaWindows().isDebugEnabled())) {
qWarning().noquote().nospace() << "SetProcessDpiAwareness("
<< dpiAwareness << ") failed: " << QWindowsContext::comErrorString(hr)
<< ", using " << QWindowsContext::processDpiAwareness();
}
}
bool QWindowsContext::setProcessDpiV2Awareness()
{
auto pSetProcessDpiAwarenessContext = reinterpret_cast<SetProcessDpiAwarenessContext_f>(GetProcAddress(LoadLibraryW(L"USER32.dll"), "SetProcessDpiAwarenessContext"));
if (!pSetProcessDpiAwarenessContext) {
return false;
}
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).";
qCDebug(lcQpaWindows) << __FUNCTION__;
const BOOL ok = pSetProcessDpiAwarenessContext(DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2);
if (!ok) {
const HRESULT errorCode = GetLastError();
qCWarning(lcQpaWindows).noquote().nospace() << "setProcessDpiAwarenessContext(DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2) failed: "
<< QWindowsContext::comErrorString(errorCode);
return false;
}
QWindowsContextPrivate::m_v2DpiAware
= processDpiAwareness() == QtWindows::DpiAwareness::PerMonitorVersion2;
QWindowsContextPrivate::m_v2DpiAware = true;
return true;
}
@ -484,9 +460,9 @@ bool QWindowsContext::useRTLExtensions() const
return d->m_keyMapper.useRTLExtensions();
}
QPlatformKeyMapper *QWindowsContext::keyMapper() const
QList<int> QWindowsContext::possibleKeys(const QKeyEvent *e) const
{
return &d->m_keyMapper;
return d->m_keyMapper.possibleKeys(e);
}
QWindowsContext::HandleBaseWindowHash &QWindowsContext::windows()
@ -598,7 +574,7 @@ QString QWindowsContext::registerWindowClass(const QWindow *w)
if (icon)
cname += "Icon"_L1;
return registerWindowClass(cname, qWindowsWndProc, style, nullptr, icon);
return registerWindowClass(cname, qWindowsWndProc, style, GetSysColorBrush(COLOR_WINDOW), icon);
}
QString QWindowsContext::registerWindowClass(QString cname,
@ -657,7 +633,7 @@ QString QWindowsContext::registerWindowClass(QString cname,
qPrintable(cname));
d->m_registeredWindowClassNames.insert(cname);
qCDebug(lcQpaWindow).nospace() << __FUNCTION__ << ' ' << cname
qCDebug(lcQpaWindows).nospace() << __FUNCTION__ << ' ' << cname
<< " style=0x" << Qt::hex << style << Qt::dec
<< " brush=" << brush << " icon=" << icon << " atom=" << atom;
return cname;
@ -667,7 +643,7 @@ void QWindowsContext::unregisterWindowClasses()
{
const auto appInstance = static_cast<HINSTANCE>(GetModuleHandle(nullptr));
for (const QString &name : std::as_const(d->m_registeredWindowClassNames)) {
for (const QString &name : qAsConst(d->m_registeredWindowClassNames)) {
if (!UnregisterClass(reinterpret_cast<LPCWSTR>(name.utf16()), appInstance) && QWindowsContext::verbose)
qErrnoWarning("UnregisterClass failed for '%s'", qPrintable(name));
}
@ -679,6 +655,23 @@ int QWindowsContext::screenDepth() const
return GetDeviceCaps(d->m_displayContext, BITSPIXEL);
}
QString QWindowsContext::windowsErrorMessage(unsigned long errorCode)
{
QString rc = QString::fromLatin1("#%1: ").arg(errorCode);
char16_t *lpMsgBuf;
const DWORD len = FormatMessage(
FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
nullptr, errorCode, 0, reinterpret_cast<LPTSTR>(&lpMsgBuf), 0, nullptr);
if (len) {
rc = QString::fromUtf16(lpMsgBuf, int(len));
LocalFree(lpMsgBuf);
} else {
rc += QString::fromLatin1("<unknown error>");
}
return rc;
}
void QWindowsContext::addWindow(HWND hwnd, QWindowsWindow *w)
{
d->m_windows.insert(hwnd, w);
@ -841,7 +834,7 @@ bool QWindowsContext::isSessionLocked()
return result;
}
QWindowsMimeRegistry &QWindowsContext::mimeConverter() const
QWindowsMimeConverter &QWindowsContext::mimeConverter() const
{
return d->m_mimeConverter;
}
@ -879,6 +872,79 @@ HWND QWindowsContext::createDummyWindow(const QString &classNameIn,
HWND_MESSAGE, nullptr, static_cast<HINSTANCE>(GetModuleHandle(nullptr)), nullptr);
}
/*!
\brief Common COM error strings.
*/
QByteArray QWindowsContext::comErrorString(HRESULT hr)
{
QByteArray result = QByteArrayLiteral("COM error 0x")
+ QByteArray::number(quintptr(hr), 16) + ' ';
switch (hr) {
case S_OK:
result += QByteArrayLiteral("S_OK");
break;
case S_FALSE:
result += QByteArrayLiteral("S_FALSE");
break;
case E_UNEXPECTED:
result += QByteArrayLiteral("E_UNEXPECTED");
break;
case E_ACCESSDENIED:
result += QByteArrayLiteral("E_ACCESSDENIED");
break;
case CO_E_ALREADYINITIALIZED:
result += QByteArrayLiteral("CO_E_ALREADYINITIALIZED");
break;
case CO_E_NOTINITIALIZED:
result += QByteArrayLiteral("CO_E_NOTINITIALIZED");
break;
case RPC_E_CHANGED_MODE:
result += QByteArrayLiteral("RPC_E_CHANGED_MODE");
break;
case OLE_E_WRONGCOMPOBJ:
result += QByteArrayLiteral("OLE_E_WRONGCOMPOBJ");
break;
case CO_E_NOT_SUPPORTED:
result += QByteArrayLiteral("CO_E_NOT_SUPPORTED");
break;
case E_NOTIMPL:
result += QByteArrayLiteral("E_NOTIMPL");
break;
case E_INVALIDARG:
result += QByteArrayLiteral("E_INVALIDARG");
break;
case E_NOINTERFACE:
result += QByteArrayLiteral("E_NOINTERFACE");
break;
case E_POINTER:
result += QByteArrayLiteral("E_POINTER");
break;
case E_HANDLE:
result += QByteArrayLiteral("E_HANDLE");
break;
case E_ABORT:
result += QByteArrayLiteral("E_ABORT");
break;
case E_FAIL:
result += QByteArrayLiteral("E_FAIL");
break;
case RPC_E_WRONG_THREAD:
result += QByteArrayLiteral("RPC_E_WRONG_THREAD");
break;
case RPC_E_THREAD_NOT_INIT:
result += QByteArrayLiteral("RPC_E_THREAD_NOT_INIT");
break;
default:
break;
}
_com_error error(hr);
result += QByteArrayLiteral(" (");
result += QString::fromWCharArray(error.ErrorMessage()).toUtf8();
result += ')';
return result;
}
void QWindowsContext::forceNcCalcSize(HWND hwnd)
{
// Force WM_NCCALCSIZE to adjust margin
@ -886,11 +952,21 @@ void QWindowsContext::forceNcCalcSize(HWND hwnd)
SWP_FRAMECHANGED | SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | SWP_NOOWNERZORDER);
}
typedef BOOL (__stdcall *SystemParametersInfoForDpi_f)(
UINT uiAction,
UINT uiParam,
PVOID pvParam,
UINT fWinIni,
UINT dpi
);
bool QWindowsContext::systemParametersInfo(unsigned action, unsigned param, void *out,
unsigned dpi)
{
const BOOL result = dpi != 0
? SystemParametersInfoForDpi(action, param, out, 0, dpi)
auto pSystemParametersInfoForDpi = reinterpret_cast<SystemParametersInfoForDpi_f>(GetProcAddress(LoadLibraryW(L"USER32.dll"), "SystemParametersInfoForDpi"));
const BOOL result = dpi != 0 && pSystemParametersInfoForDpi
? pSystemParametersInfoForDpi(action, param, out, 0, dpi)
: SystemParametersInfo(action, param, out, 0);
return result == TRUE;
}
@ -973,21 +1049,6 @@ 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.
@ -1094,7 +1155,6 @@ bool QWindowsContext::windowsProc(HWND hwnd, UINT message,
const bool darkModeChanged = darkMode != QWindowsContextPrivate::m_darkMode;
QWindowsContextPrivate::m_darkMode = darkMode;
auto integration = QWindowsIntegration::instance();
integration->updateApplicationBadge();
if (integration->darkModeHandling().testFlag(QWindowsApplication::DarkModeStyle)) {
QWindowsTheme::instance()->refresh();
QWindowSystemInterface::handleThemeChange();
@ -1164,7 +1224,7 @@ bool QWindowsContext::windowsProc(HWND hwnd, UINT message,
if (wParam == DBT_DEVNODES_CHANGED)
initTouch();
break;
case QtWindows::InputLanguageChangeEvent:
case QtWindows::KeyboardLayoutChangeEvent:
if (QWindowsInputContext *wic = windowsInputContext())
wic->handleInputLanguageChanged(wParam, lParam);
Q_FALLTHROUGH();
@ -1194,7 +1254,7 @@ bool QWindowsContext::windowsProc(HWND hwnd, UINT message,
platformWindow->handleMoved();
return true;
case QtWindows::ResizeEvent:
platformWindow->handleResized(static_cast<int>(wParam), lParam);
platformWindow->handleResized(static_cast<int>(wParam));
return true;
case QtWindows::QuerySizeHints:
platformWindow->getSizeHints(reinterpret_cast<MINMAXINFO *>(lParam));
@ -1208,29 +1268,21 @@ bool QWindowsContext::windowsProc(HWND hwnd, UINT message,
case QtWindows::ExposeEvent:
return platformWindow->handleWmPaint(hwnd, message, wParam, lParam, result);
case QtWindows::NonClientMouseEvent:
if (!platformWindow->frameStrutEventsEnabled())
break;
if ((d->m_systemInfo & QWindowsContext::SI_SupportsPointer))
if ((d->m_systemInfo & QWindowsContext::SI_SupportsPointer) && platformWindow->frameStrutEventsEnabled())
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 (!platformWindow->frameStrutEventsEnabled())
break;
if ((d->m_systemInfo & QWindowsContext::SI_SupportsPointer))
if ((d->m_systemInfo & QWindowsContext::SI_SupportsPointer) && platformWindow->frameStrutEventsEnabled())
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))
@ -1276,7 +1328,6 @@ 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());
@ -1368,11 +1419,6 @@ 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;
}
@ -1415,7 +1461,7 @@ void QWindowsContext::handleFocusEvent(QtWindows::WindowsEventType et,
}
if (nextActiveWindow != d->m_lastActiveWindow) {
d->m_lastActiveWindow = nextActiveWindow;
QWindowSystemInterface::handleFocusWindowChanged(nextActiveWindow, Qt::ActiveWindowFocusReason);
QWindowSystemInterface::handleWindowActivated(nextActiveWindow, Qt::ActiveWindowFocusReason);
}
}
@ -1445,7 +1491,7 @@ bool QWindowsContext::handleContextMenuEvent(QWindow *window, const MSG &msg)
}
QWindowSystemInterface::handleContextMenuEvent(window, mouseTriggered, pos, globalPos,
keyMapper()->queryKeyboardModifiers());
QWindowsKeyMapper::queryKeyboardModifiers());
return true;
}
#endif
@ -1466,7 +1512,7 @@ void QWindowsContext::handleExitSizeMove(QWindow *window)
const Qt::MouseButtons appButtons = QGuiApplication::mouseButtons();
if (currentButtons == appButtons)
return;
const Qt::KeyboardModifiers keyboardModifiers = keyMapper()->queryKeyboardModifiers();
const Qt::KeyboardModifiers keyboardModifiers = QWindowsKeyMapper::queryKeyboardModifiers();
const QPoint globalPos = QWindowsCursor::mousePosition();
const QPlatformWindow *platWin = window->handle();
const QPoint localPos = platWin->mapFromGlobal(globalPos);
@ -1475,7 +1521,8 @@ 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)
@ -1569,7 +1616,7 @@ extern "C" LRESULT QT_WIN_CALLBACK qWindowsWndProc(HWND hwnd, UINT message, WPAR
marginsFromRects(ncCalcSizeFrame, rectFromNcCalcSize(message, wParam, lParam, 0));
if (margins.left() >= 0) {
if (platformWindow) {
qCDebug(lcQpaWindow) << __FUNCTION__ << "WM_NCCALCSIZE for" << hwnd << margins;
qCDebug(lcQpaWindows) << __FUNCTION__ << "WM_NCCALCSIZE for" << hwnd << margins;
platformWindow->setFullFrameMargins(margins);
} else {
const QSharedPointer<QWindowCreationContext> ctx = QWindowsContext::instance()->windowCreationContext();

View File

@ -730,17 +730,40 @@ static inline QString messageKeyText(const MSG &msg)
return ch.isNull() ? QString() : QString(ch);
}
UINT GetDpiForWindow2(HWND hwnd);
typedef int (__stdcall *GetSystemMetricsForDpi_f)(int, UINT);
typedef int (__stdcall *GetSystemMetrics_f)(int);
[[nodiscard]] static inline int getTitleBarHeight(const HWND hwnd)
{
const UINT dpi = GetDpiForWindow(hwnd);
const int captionHeight = GetSystemMetricsForDpi(SM_CYCAPTION, dpi);
if (IsZoomed(hwnd))
return captionHeight;
// The frame height should also be taken into account if the window
// is not maximized.
const int frameHeight = GetSystemMetricsForDpi(SM_CYSIZEFRAME, dpi)
+ GetSystemMetricsForDpi(SM_CXPADDEDBORDER, dpi);
return captionHeight + frameHeight;
const UINT dpi = GetDpiForWindow2(hwnd);
auto pGetSystemMetricsForDpi = reinterpret_cast<GetSystemMetricsForDpi_f>(GetProcAddress(LoadLibraryW(L"USER32.dll"), "GetSystemMetricsForDpi"));
auto pGetSystemMetrics = reinterpret_cast<GetSystemMetrics_f>(GetProcAddress(LoadLibraryW(L"USER32.dll"), "GetSystemMetrics"));
if (pGetSystemMetricsForDpi)
{
const int captionHeight = pGetSystemMetricsForDpi(SM_CYCAPTION, dpi);
if (IsZoomed(hwnd))
return captionHeight;
// The frame height should also be taken into account if the window
// is not maximized.
const int frameHeight = pGetSystemMetricsForDpi(SM_CYSIZEFRAME, dpi)
+ pGetSystemMetricsForDpi(SM_CXPADDEDBORDER, dpi);
return captionHeight + frameHeight;
}
else
{
const int captionHeight = pGetSystemMetrics(SM_CYCAPTION);
if (IsZoomed(hwnd))
return captionHeight;
// The frame height should also be taken into account if the window
// is not maximized.
const int frameHeight = pGetSystemMetrics(SM_CYSIZEFRAME)
+ pGetSystemMetrics(SM_CXPADDEDBORDER);
return captionHeight + frameHeight;
}
}
[[nodiscard]] static inline bool isSystemMenuOffsetNeeded(const Qt::WindowFlags flags)

View File

@ -47,6 +47,8 @@ bool QWindowsPointerHandler::translatePointerEvent(QWindow *window, HWND hwnd, Q
{
*result = 0;
const quint32 pointerId = GET_POINTERID_WPARAM(msg.wParam);
#if 0
if (!GetPointerType(pointerId, &m_pointerType)) {
qWarning() << "GetPointerType() failed:" << qt_error_string();
@ -129,6 +131,8 @@ bool QWindowsPointerHandler::translatePointerEvent(QWindow *window, HWND hwnd, Q
return translatePenEvent(window, hwnd, et, msg, &penInfo);
}
}
#endif
return false;
}
@ -560,6 +564,7 @@ QWindowsPointerHandler::QPointingDevicePtr QWindowsPointerHandler::findTabletDev
bool QWindowsPointerHandler::translatePenEvent(QWindow *window, HWND hwnd, QtWindows::WindowsEventType et,
MSG msg, PVOID vPenInfo)
{
#if 0
#if QT_CONFIG(tabletevent)
if (et & QtWindows::NonClientEventFlag)
return false; // Let DefWindowProc() handle Non Client messages.
@ -694,6 +699,8 @@ bool QWindowsPointerHandler::translatePenEvent(QWindow *window, HWND hwnd, QtWin
Q_UNUSED(vPenInfo);
return false;
#endif
#endif
return false;
}
static inline bool isMouseEventSynthesizedFromPenOrTouch()

View File

@ -36,6 +36,11 @@ QT_BEGIN_NAMESPACE
using namespace Qt::StringLiterals;
HRESULT GetDpiForMonitor2(HMONITOR hmonitor,
MONITOR_DPI_TYPE dpiType,
UINT *pDpiX,
UINT *pDpiY);
static inline QDpi deviceDPI(HDC hdc)
{
return QDpi(GetDeviceCaps(hdc, LOGPIXELSX), GetDeviceCaps(hdc, LOGPIXELSY));
@ -45,7 +50,7 @@ static inline QDpi monitorDPI(HMONITOR hMonitor)
{
UINT dpiX;
UINT dpiY;
if (SUCCEEDED(GetDpiForMonitor(hMonitor, MDT_EFFECTIVE_DPI, &dpiX, &dpiY)))
if (SUCCEEDED(GetDpiForMonitor2(hMonitor, MDT_EFFECTIVE_DPI, &dpiX, &dpiY)))
return QDpi(dpiX, dpiY);
return {0, 0};
}
@ -574,6 +579,10 @@ QRect QWindowsScreen::virtualGeometry(const QPlatformScreen *screen) // cf QScre
return result;
}
typedef BOOL (__stdcall *SetDisplayAutoRotationPreferences_f)(
ORIENTATION_PREFERENCE orientation
);
bool QWindowsScreen::setOrientationPreference(Qt::ScreenOrientation o)
{
bool result = false;
@ -593,8 +602,14 @@ bool QWindowsScreen::setOrientationPreference(Qt::ScreenOrientation o)
case Qt::InvertedLandscapeOrientation:
orientationPreference = ORIENTATION_PREFERENCE_LANDSCAPE_FLIPPED;
break;
}
result = SetDisplayAutoRotationPreferences(orientationPreference);
auto pSetDisplayAutoRotationPreferences = reinterpret_cast<SetDisplayAutoRotationPreferences_f>(GetProcAddress(LoadLibraryW(L"user32.dll"), "SetDisplayAutoRotationPreferences"));
if (pSetDisplayAutoRotationPreferences) {
result = pSetDisplayAutoRotationPreferences(orientationPreference);
}
return result;
}

File diff suppressed because it is too large Load Diff