Qt 6.6.2 support (brought changes from 6.6.2)

This commit is contained in:
kleuter 2024-03-01 17:54:10 +01:00
parent 626b955ffc
commit 3ea96bc104
8 changed files with 81 additions and 42 deletions

View File

@ -1,7 +1,7 @@
This is Qt 6.6.1 backport that runs on Windows 7 (what?). The repository contains patched source files from the qtbase module. This is Qt 6.6.2 backport that runs on Windows 7 (what?). The repository contains patched source files from the qtbase module.
Approach is based on this [forum thread](https://forum.qt.io/topic/133002/qt-creator-6-0-1-and-qt-6-2-2-running-on-windows-7/60) but better: many improvements amongst important fallbacks to default Qt 6 behaviour when running on newer Windows. Approach is based on this [forum thread](https://forum.qt.io/topic/133002/qt-creator-6-0-1-and-qt-6-2-2-running-on-windows-7/60) but better: many improvements amongst important fallbacks to default Qt 6 behaviour when running on newer Windows.
You can use [our prebuild binaries](https://github.com/crystalidea/qt6windows7/releases) (we used Visual C++ 2019 with OpenSSL 1.1.1k statically linked, see [compile_win.pl](https://github.com/crystalidea/qt-build-tools/tree/master/6.6.1) script) or compile Qt yourself. You can use [our prebuild binaries](https://github.com/crystalidea/qt6windows7/releases) (we used Visual C++ 2019 with OpenSSL 3.0.13 statically linked, see [compile_win.pl](https://github.com/crystalidea/qt-build-tools/tree/master/6.6.2) script) or compile Qt yourself.
Known issues: Known issues:

Binary file not shown.

View File

@ -192,10 +192,21 @@ bool QRhiD3D12::create(QRhi::Flags flags)
factoryFlags |= DXGI_CREATE_FACTORY_DEBUG; factoryFlags |= DXGI_CREATE_FACTORY_DEBUG;
HRESULT hr = myCreateDXGIFactory2(factoryFlags, __uuidof(IDXGIFactory2), reinterpret_cast<void **>(&dxgiFactory)); HRESULT hr = myCreateDXGIFactory2(factoryFlags, __uuidof(IDXGIFactory2), reinterpret_cast<void **>(&dxgiFactory));
if (FAILED(hr)) { if (FAILED(hr)) {
// retry without debug, if it was requested (to match D3D11 backend behavior)
if (debugLayer) {
qCDebug(QRHI_LOG_INFO, "Debug layer was requested but is not available. "
"Attempting to create DXGIFactory2 without it.");
factoryFlags &= ~DXGI_CREATE_FACTORY_DEBUG;
hr = myCreateDXGIFactory2(factoryFlags, __uuidof(IDXGIFactory2), reinterpret_cast<void **>(&dxgiFactory));
}
if (SUCCEEDED(hr)) {
debugLayer = false;
} else {
qWarning("CreateDXGIFactory2() failed to create DXGI factory: %s", qWarning("CreateDXGIFactory2() failed to create DXGI factory: %s",
qPrintable(QSystemError::windowsComString(hr))); qPrintable(QSystemError::windowsComString(hr)));
return false; return false;
} }
}
supportsAllowTearing = false; supportsAllowTearing = false;
IDXGIFactory5 *factory5 = nullptr; IDXGIFactory5 *factory5 = nullptr;

View File

@ -1222,7 +1222,7 @@ bool QWindowsContext::windowsProc(HWND hwnd, UINT message,
d->m_creationContext->applyToMinMaxInfo(reinterpret_cast<MINMAXINFO *>(lParam)); d->m_creationContext->applyToMinMaxInfo(reinterpret_cast<MINMAXINFO *>(lParam));
return true; return true;
case QtWindows::ResizeEvent: 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; return true;
case QtWindows::MoveEvent: case QtWindows::MoveEvent:
d->m_creationContext->obtainedPos = QPoint(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam)); d->m_creationContext->obtainedPos = QPoint(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam));

View File

@ -649,7 +649,8 @@ IDropTargetHelper* QWindowsDrag::dropHelper() {
static HRESULT startDoDragDrop(LPDATAOBJECT pDataObj, LPDROPSOURCE pDropSource, DWORD dwOKEffects, LPDWORD pdwEffect) static HRESULT startDoDragDrop(LPDATAOBJECT pDataObj, LPDROPSOURCE pDropSource, DWORD dwOKEffects, LPDWORD pdwEffect)
{ {
QWindow *underMouse = QWindowsContext::instance()->windowUnderMouse(); QWindow *underMouse = QWindowsContext::instance()->windowUnderMouse();
const HWND hwnd = underMouse ? reinterpret_cast<HWND>(underMouse->winId()) : ::GetFocus(); const bool hasMouseCapture = underMouse && static_cast<QWindowsWindow *>(underMouse->handle())->hasMouseCapture();
const HWND hwnd = hasMouseCapture ? reinterpret_cast<HWND>(underMouse->winId()) : ::GetFocus();
bool starting = false; bool starting = false;
for (;;) { for (;;) {

View File

@ -990,7 +990,7 @@ bool QWindowsKeyMapper::translateKeyEventInternal(QWindow *window, MSG msg,
// A multi-character key or a Input method character // A multi-character key or a Input method character
// not found by our look-ahead // not found by our look-ahead
if (msgType == WM_CHAR || msgType == WM_IME_CHAR) { if (msgType == WM_CHAR || msgType == WM_IME_CHAR) {
sendExtendedPressRelease(receiver, 0, Qt::KeyboardModifier(state), scancode, vk_key, nModifiers, messageKeyText(msg), false); sendExtendedPressRelease(receiver, 0, Qt::KeyboardModifier(state), scancode, 0, nModifiers, messageKeyText(msg), false);
return true; return true;
} }

View File

@ -19,6 +19,7 @@
#include <private/qhighdpiscaling_p.h> #include <private/qhighdpiscaling_p.h>
#include <private/qwindowsfontdatabasebase_p.h> #include <private/qwindowsfontdatabasebase_p.h>
#include <private/qpixmap_win_p.h> #include <private/qpixmap_win_p.h>
#include <private/quniquehandle_p.h>
#include <QtGui/qscreen.h> #include <QtGui/qscreen.h>
@ -118,16 +119,22 @@ static float getMonitorSDRWhiteLevel(DISPLAYCONFIG_PATH_TARGET_INFO *targetInfo)
using WindowsScreenDataList = QList<QWindowsScreenData>; using WindowsScreenDataList = QList<QWindowsScreenData>;
struct RegistryHandleDeleter namespace {
struct DiRegKeyHandleTraits
{ {
void operator()(HKEY handle) const noexcept using Type = HKEY;
static Type invalidValue()
{ {
if (handle != nullptr && handle != INVALID_HANDLE_VALUE) // The setupapi.h functions return INVALID_HANDLE_VALUE when failing to open a registry key
RegCloseKey(handle); return reinterpret_cast<HKEY>(INVALID_HANDLE_VALUE);
} }
static bool close(Type handle) { return RegCloseKey(handle) == ERROR_SUCCESS; }
}; };
using RegistryHandlePtr = std::unique_ptr<std::remove_pointer_t<HKEY>, RegistryHandleDeleter>; using DiRegKeyHandle = QUniqueHandle<DiRegKeyHandleTraits>;
}
static void setMonitorDataFromSetupApi(QWindowsScreenData &data, static void setMonitorDataFromSetupApi(QWindowsScreenData &data,
const std::vector<DISPLAYCONFIG_PATH_INFO> &pathGroup) const std::vector<DISPLAYCONFIG_PATH_INFO> &pathGroup)
@ -209,10 +216,10 @@ static void setMonitorDataFromSetupApi(QWindowsScreenData &data,
continue; continue;
} }
const RegistryHandlePtr edidRegistryKey{ SetupDiOpenDevRegKey( const DiRegKeyHandle edidRegistryKey{ SetupDiOpenDevRegKey(
devInfo, &deviceInfoData, DICS_FLAG_GLOBAL, 0, DIREG_DEV, KEY_READ) }; devInfo, &deviceInfoData, DICS_FLAG_GLOBAL, 0, DIREG_DEV, KEY_READ) };
if (!edidRegistryKey || edidRegistryKey.get() == INVALID_HANDLE_VALUE) if (!edidRegistryKey.isValid())
continue; continue;
DWORD edidDataSize{ 0 }; DWORD edidDataSize{ 0 };

View File

@ -1025,6 +1025,21 @@ static QSize toNativeSizeConstrained(QSize dip, const QScreen *s)
return dip; return dip;
} }
// Helper for checking if frame adjustment needs to be skipped
// NOTE: Unmaximized frameless windows will skip margins calculation
static bool shouldOmitFrameAdjustment(const Qt::WindowFlags flags, DWORD style)
{
return flags.testFlag(Qt::FramelessWindowHint) && !(style & WS_MAXIMIZE);
}
// Helper for checking if frame adjustment needs to be skipped
// NOTE: Unmaximized frameless windows will skip margins calculation
static bool shouldOmitFrameAdjustment(const Qt::WindowFlags flags, HWND hwnd)
{
DWORD style = hwnd != nullptr ? DWORD(GetWindowLongPtr(hwnd, GWL_STYLE)) : 0;
return flags.testFlag(Qt::FramelessWindowHint) && !(style & WS_MAXIMIZE);
}
/*! /*!
\class QWindowsGeometryHint \class QWindowsGeometryHint
\brief Stores geometry constraints and provides utility functions. \brief Stores geometry constraints and provides utility functions.
@ -1037,7 +1052,7 @@ static QSize toNativeSizeConstrained(QSize dip, const QScreen *s)
QMargins QWindowsGeometryHint::frameOnPrimaryScreen(const QWindow *w, DWORD style, DWORD exStyle) QMargins QWindowsGeometryHint::frameOnPrimaryScreen(const QWindow *w, DWORD style, DWORD exStyle)
{ {
if (!w->isTopLevel() || w->flags().testFlag(Qt::FramelessWindowHint)) if (!w->isTopLevel() || shouldOmitFrameAdjustment(w->flags(), style))
return {}; return {};
RECT rect = {0,0,0,0}; RECT rect = {0,0,0,0};
style &= ~DWORD(WS_OVERLAPPED); // Not permitted, see docs. style &= ~DWORD(WS_OVERLAPPED); // Not permitted, see docs.
@ -1053,15 +1068,13 @@ QMargins QWindowsGeometryHint::frameOnPrimaryScreen(const QWindow *w, DWORD styl
QMargins QWindowsGeometryHint::frameOnPrimaryScreen(const QWindow *w, HWND hwnd) QMargins QWindowsGeometryHint::frameOnPrimaryScreen(const QWindow *w, HWND hwnd)
{ {
if (!w->isTopLevel() || w->flags().testFlag(Qt::FramelessWindowHint))
return {};
return frameOnPrimaryScreen(w, DWORD(GetWindowLongPtr(hwnd, GWL_STYLE)), return frameOnPrimaryScreen(w, DWORD(GetWindowLongPtr(hwnd, GWL_STYLE)),
DWORD(GetWindowLongPtr(hwnd, GWL_EXSTYLE))); DWORD(GetWindowLongPtr(hwnd, GWL_EXSTYLE)));
} }
QMargins QWindowsGeometryHint::frame(const QWindow *w, DWORD style, DWORD exStyle, qreal dpi) QMargins QWindowsGeometryHint::frame(const QWindow *w, DWORD style, DWORD exStyle, qreal dpi)
{ {
if (!w->isTopLevel() || w->flags().testFlag(Qt::FramelessWindowHint)) if (!w->isTopLevel() || shouldOmitFrameAdjustment(w->flags(), style))
return {}; return {};
RECT rect = {0,0,0,0}; RECT rect = {0,0,0,0};
style &= ~DWORD(WS_OVERLAPPED); // Not permitted, see docs. style &= ~DWORD(WS_OVERLAPPED); // Not permitted, see docs.
@ -1080,7 +1093,7 @@ QMargins QWindowsGeometryHint::frame(const QWindow *w, DWORD style, DWORD exStyl
QMargins QWindowsGeometryHint::frame(const QWindow *w, HWND hwnd, DWORD style, DWORD exStyle) QMargins QWindowsGeometryHint::frame(const QWindow *w, HWND hwnd, DWORD style, DWORD exStyle)
{ {
if (!w->isTopLevel() || w->flags().testFlag(Qt::FramelessWindowHint)) if (!w->isTopLevel() || shouldOmitFrameAdjustment(w->flags(), style))
return {}; return {};
if (QWindowsScreenManager::isSingleScreen()) if (QWindowsScreenManager::isSingleScreen())
return frameOnPrimaryScreen(w, style, exStyle); return frameOnPrimaryScreen(w, style, exStyle);
@ -1094,8 +1107,6 @@ QMargins QWindowsGeometryHint::frame(const QWindow *w, HWND hwnd, DWORD style, D
QMargins QWindowsGeometryHint::frame(const QWindow *w, HWND hwnd) QMargins QWindowsGeometryHint::frame(const QWindow *w, HWND hwnd)
{ {
if (!w->isTopLevel() || w->flags().testFlag(Qt::FramelessWindowHint))
return {};
return frame(w, hwnd, DWORD(GetWindowLongPtr(hwnd, GWL_STYLE)), return frame(w, hwnd, DWORD(GetWindowLongPtr(hwnd, GWL_STYLE)),
DWORD(GetWindowLongPtr(hwnd, GWL_EXSTYLE))); DWORD(GetWindowLongPtr(hwnd, GWL_EXSTYLE)));
} }
@ -1104,7 +1115,7 @@ QMargins QWindowsGeometryHint::frame(const QWindow *w, HWND hwnd)
QMargins QWindowsGeometryHint::frame(const QWindow *w, const QRect &geometry, QMargins QWindowsGeometryHint::frame(const QWindow *w, const QRect &geometry,
DWORD style, DWORD exStyle) DWORD style, DWORD exStyle)
{ {
if (!w->isTopLevel() || w->flags().testFlag(Qt::FramelessWindowHint)) if (!w->isTopLevel() || shouldOmitFrameAdjustment(w->flags(), style))
return {}; return {};
if (QWindowsScreenManager::isSingleScreen() if (QWindowsScreenManager::isSingleScreen()
|| !QWindowsContext::shouldHaveNonClientDpiScaling(w)) { || !QWindowsContext::shouldHaveNonClientDpiScaling(w)) {
@ -2042,7 +2053,7 @@ void QWindowsWindow::handleDpiChanged(HWND hwnd, WPARAM wParam, LPARAM lParam)
// If the window does not have a frame, WM_MOVE and WM_SIZE won't be // If the window does not have a frame, WM_MOVE and WM_SIZE won't be
// called which prevents the content from being scaled appropriately // called which prevents the content from being scaled appropriately
// after a DPI change. // after a DPI change.
if (m_data.flags & Qt::FramelessWindowHint) if (shouldOmitFrameAdjustment(m_data.flags, m_data.hwnd))
handleGeometryChange(); handleGeometryChange();
} }
@ -2575,26 +2586,26 @@ void QWindowsWindow::setWindowState_sys(Qt::WindowStates newState)
if (testFlag(HasBorderInFullScreen)) if (testFlag(HasBorderInFullScreen))
newStyle |= WS_BORDER; newStyle |= WS_BORDER;
setStyle(newStyle); setStyle(newStyle);
// Use geometry of QWindow::screen() within creation or the virtual screen the const HMONITOR monitor = MonitorFromWindow(m_data.hwnd, MONITOR_DEFAULTTONEAREST);
// window is in (QTBUG-31166, QTBUG-30724). MONITORINFO monitorInfo = {};
const QScreen *screen = window()->screen(); monitorInfo.cbSize = sizeof(MONITORINFO);
if (!screen) GetMonitorInfoW(monitor, &monitorInfo);
screen = QGuiApplication::primaryScreen(); const QRect screenGeometry(monitorInfo.rcMonitor.left, monitorInfo.rcMonitor.top,
const QRect r = screen ? QHighDpi::toNativePixels(screen->geometry(), window()) : m_savedFrameGeometry; monitorInfo.rcMonitor.right - monitorInfo.rcMonitor.left,
monitorInfo.rcMonitor.bottom - monitorInfo.rcMonitor.top);
if (newState & Qt::WindowMinimized) { if (newState & Qt::WindowMinimized) {
setMinimizedGeometry(m_data.hwnd, r); setMinimizedGeometry(m_data.hwnd, screenGeometry);
if (stateChange & Qt::WindowMaximized) if (stateChange & Qt::WindowMaximized)
setRestoreMaximizedFlag(m_data.hwnd, newState & Qt::WindowMaximized); setRestoreMaximizedFlag(m_data.hwnd, newState & Qt::WindowMaximized);
} else { } else {
const UINT swpf = SWP_FRAMECHANGED | SWP_NOACTIVATE; const UINT swpf = SWP_FRAMECHANGED | SWP_NOACTIVATE;
const bool wasSync = testFlag(SynchronousGeometryChangeEvent); const bool wasSync = testFlag(SynchronousGeometryChangeEvent);
setFlag(SynchronousGeometryChangeEvent); setFlag(SynchronousGeometryChangeEvent);
SetWindowPos(m_data.hwnd, HWND_TOP, r.left(), r.top(), r.width(), r.height(), swpf); SetWindowPos(m_data.hwnd, HWND_TOP, screenGeometry.left(), screenGeometry.top(), screenGeometry.width(), screenGeometry.height(), swpf);
if (!wasSync) if (!wasSync)
clearFlag(SynchronousGeometryChangeEvent); clearFlag(SynchronousGeometryChangeEvent);
clearFlag(MaximizeToFullScreen); clearFlag(MaximizeToFullScreen);
QWindowSystemInterface::handleGeometryChange(window(), r); QWindowSystemInterface::handleGeometryChange(window(), screenGeometry);
QWindowSystemInterface::flushWindowSystemEvents(QEventLoop::ExcludeUserInputEvents); QWindowSystemInterface::flushWindowSystemEvents(QEventLoop::ExcludeUserInputEvents);
} }
} else { } else {
@ -2761,7 +2772,7 @@ bool QWindowsWindow::handleGeometryChanging(MSG *message) const
void QWindowsWindow::setFullFrameMargins(const QMargins &newMargins) void QWindowsWindow::setFullFrameMargins(const QMargins &newMargins)
{ {
if (m_data.flags & Qt::FramelessWindowHint) if (shouldOmitFrameAdjustment(m_data.flags, m_data.hwnd))
return; return;
if (m_data.fullFrameMargins != newMargins) { if (m_data.fullFrameMargins != newMargins) {
qCDebug(lcQpaWindow) << __FUNCTION__ << window() << m_data.fullFrameMargins << "->" << newMargins; qCDebug(lcQpaWindow) << __FUNCTION__ << window() << m_data.fullFrameMargins << "->" << newMargins;
@ -2780,13 +2791,8 @@ void QWindowsWindow::updateFullFrameMargins()
void QWindowsWindow::calculateFullFrameMargins() void QWindowsWindow::calculateFullFrameMargins()
{ {
if (m_data.flags & Qt::FramelessWindowHint) if (shouldOmitFrameAdjustment(m_data.flags, m_data.hwnd))
return; return;
// Normally obtained from WM_NCCALCSIZE. This calculation only works
// when no native menu is present.
const auto systemMargins = testFlag(DisableNonClientScaling)
? QWindowsGeometryHint::frameOnPrimaryScreen(window(), m_data.hwnd)
: frameMargins_sys();
// QTBUG-113736: systemMargins depends on AdjustWindowRectExForDpi. This doesn't take into // QTBUG-113736: systemMargins depends on AdjustWindowRectExForDpi. This doesn't take into
// account possible external modifications to the titlebar, as with ExtendsContentIntoTitleBar() // account possible external modifications to the titlebar, as with ExtendsContentIntoTitleBar()
@ -2800,6 +2806,20 @@ void QWindowsWindow::calculateFullFrameMargins()
RECT clientRect{}; RECT clientRect{};
GetWindowRect(handle(), &windowRect); GetWindowRect(handle(), &windowRect);
GetClientRect(handle(), &clientRect); GetClientRect(handle(), &clientRect);
// QTBUG-117704 It is also possible that the user has manually removed the frame (for example
// by handling WM_NCCALCSIZE). If that is the case, i.e., the client area and the window area
// have identical sizes, we don't want to override the user-defined margins.
if (qrectFromRECT(windowRect).size() == qrectFromRECT(clientRect).size())
return;
// Normally obtained from WM_NCCALCSIZE. This calculation only works
// when no native menu is present.
const auto systemMargins = testFlag(DisableNonClientScaling)
? QWindowsGeometryHint::frameOnPrimaryScreen(window(), m_data.hwnd)
: frameMargins_sys();
const int yDiff = (windowRect.bottom - windowRect.top) - (clientRect.bottom - clientRect.top); const int yDiff = (windowRect.bottom - windowRect.top) - (clientRect.bottom - clientRect.top);
const bool typicalFrame = (systemMargins.left() == systemMargins.right()) const bool typicalFrame = (systemMargins.left() == systemMargins.right())
&& (systemMargins.right() == systemMargins.bottom()); && (systemMargins.right() == systemMargins.bottom());
@ -2822,7 +2842,7 @@ QMargins QWindowsWindow::frameMargins() const
QMargins QWindowsWindow::fullFrameMargins() const QMargins QWindowsWindow::fullFrameMargins() const
{ {
if (m_data.flags & Qt::FramelessWindowHint) if (shouldOmitFrameAdjustment(m_data.flags, m_data.hwnd))
return {}; return {};
return m_data.fullFrameMargins; return m_data.fullFrameMargins;
} }