[*] Restore Windows 7 support [pt 2]
Change-Id: Iae61503a4aa2f788fe76b9e9b7a7c1ad1abfae36
This commit is contained in:
parent
a050d42ef2
commit
dfb37c4e24
@ -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(¤tMode);
|
||||
if (SUCCEEDED(hr))
|
||||
result = currentMode == 1; // Touch, 1
|
||||
viewSettings->Release();
|
||||
}
|
||||
uiViewSettingsInterop->Release();
|
||||
return result;
|
||||
return false;
|
||||
}
|
||||
|
||||
QT_END_NAMESPACE
|
||||
|
@ -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;
|
||||
}
|
||||
PROCESS_DPI_AWARENESS result;
|
||||
|
||||
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;
|
||||
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;
|
||||
}
|
||||
#endif
|
||||
|
||||
bool QWindowsContext::setProcessDpiAwareness(QtWindows::DpiAwareness dpiAwareness)
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
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();
|
||||
|
@ -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)
|
||||
|
@ -48,6 +48,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();
|
||||
return false;
|
||||
@ -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()
|
||||
|
@ -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
Loading…
Reference in New Issue
Block a user