This commit is contained in:
kleuter 2024-12-13 13:51:13 +01:00
parent a9966ab3ae
commit 8c8f9a4e87
8 changed files with 139 additions and 50 deletions

View File

@ -1,15 +1,15 @@
This repository provides a backport of the Qt 6.8.0 qtbase module, tailored for compatibility with Windows 7 and 8. It contains patched source files from the qtbase module, along with some additional required files. To apply the backport, simply copy the contents of the src folder into your qtbase/src directory, replacing the existing files.
This repository provides a backport of the Qt 6.8.1 qtbase module, tailored for compatibility with Windows 7 and 8. It contains patched source files from the qtbase module, along with some additional required files. To apply the backport, simply copy the contents of the src folder into your qtbase/src directory, replacing the existing files.
This approach builds upon the methodology discussed in 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 offers significant enhancements, including important fallbacks to the default Qt 6 behavior when running on newer versions of Windows.
You have two options for compiling Qt:
- Compile it yourself using your preferred compiler and build options.
- Use our [compile_win.pl](https://github.com/crystalidea/qt-build-tools/tree/master/6.8.0) build script, which utilizes Visual C++ 2022 and includes OpenSSL 3.0.13 statically linked.
- Use our [compile_win.pl](https://github.com/crystalidea/qt-build-tools/tree/master/6.8.1) build script, which utilizes Visual C++ 2022 and includes OpenSSL 3.0.13 statically linked.
Alternatively, you can download our [prebuild Qt dlls](https://github.com/crystalidea/qt6windows7/releases), which also include the Qt Designer binary for demonstration purposes.
**Qt 6.8.0 designer running on Windows 7**:
**Qt 6.8.1 designer running on Windows 7**:
![Qt Designer](designer.png)
@ -28,7 +28,7 @@ Many of other Qt 6 modules are known to work fine on Windows 7 without modificat
### Older versions:
- [Qt 6.7.3](https://github.com/crystalidea/qt6windows7/releases/tag/v6.7.3)
- [Qt 6.8.0](https://github.com/crystalidea/qt6windows7/releases/tag/v6.8.0)
- [Qt 6.7.2](https://github.com/crystalidea/qt6windows7/releases/tag/v6.7.2)
- [Qt 6.6.3](https://github.com/crystalidea/qt6windows7/releases/tag/v6.6.3)
- [Qt 6.6.2](https://github.com/crystalidea/qt6windows7/releases/tag/v6.6.2)

Binary file not shown.

Before

Width:  |  Height:  |  Size: 72 KiB

After

Width:  |  Height:  |  Size: 54 KiB

View File

@ -76,7 +76,7 @@ QThreadData *QThreadData::current(bool createIfNecessary)
// avoid recursion.
TlsSetValue(qt_current_thread_data_tls_index, threadData);
QT_TRY {
threadData->thread = new QAdoptedThread(threadData);
threadData->thread.storeRelease(new QAdoptedThread(threadData));
} QT_CATCH(...) {
TlsSetValue(qt_current_thread_data_tls_index, 0);
threadData->deref();
@ -101,7 +101,7 @@ QThreadData *QThreadData::current(bool createIfNecessary)
0,
FALSE,
DUPLICATE_SAME_ACCESS);
qt_watch_adopted_thread(realHandle, threadData->thread);
qt_watch_adopted_thread(realHandle, threadData->thread.loadRelaxed());
}
}
return threadData;
@ -209,7 +209,7 @@ DWORD WINAPI qt_adopted_thread_watcher_function(LPVOID)
auto thread_p = static_cast<QThreadPrivate *>(QObjectPrivate::get(thread));
Q_UNUSED(thread_p);
Q_ASSERT(!thread_p->finished);
QThreadPrivate::finish(thread);
thread_p->finish();
}
data->deref();
@ -282,7 +282,6 @@ void qt_set_thread_name(HANDLE threadId, const QString &name)
}
}
/**************************************************************************
** QThreadPrivate
*************************************************************************/
@ -326,7 +325,7 @@ unsigned int __stdcall QT_ENSURE_STACK_ALIGNED_FOR_SSE QThreadPrivate::start(voi
QThread::setTerminationEnabled(true);
thr->run();
finish(arg);
thr->d_func()->finish();
return 0;
}
@ -341,10 +340,10 @@ unsigned int __stdcall QT_ENSURE_STACK_ALIGNED_FOR_SSE QThreadPrivate::start(voi
In those cases, \a arg will not be the current thread.
*/
void QThreadPrivate::finish(void *arg, bool lockAnyway) noexcept
void QThreadPrivate::finish(bool lockAnyway) noexcept
{
QThread *thr = reinterpret_cast<QThread *>(arg);
QThreadPrivate *d = thr->d_func();
QThreadPrivate *d = this;
QThread *thr = q_func();
QMutexLocker locker(lockAnyway ? &d->mutex : nullptr);
d->isInFinish = true;
@ -538,7 +537,7 @@ void QThread::terminate()
}
TerminateThread(d->handle, 0);
QThreadPrivate::finish(this, false);
d->finish(false);
}
bool QThread::wait(QDeadlineTimer deadline)
@ -552,6 +551,13 @@ bool QThread::wait(QDeadlineTimer deadline)
}
if (d->finished || !d->running)
return true;
return d->wait(locker, deadline);
}
bool QThreadPrivate::wait(QMutexLocker<QMutex> &locker, QDeadlineTimer deadline)
{
Q_ASSERT(locker.isLocked());
QThreadPrivate *d = this;
++d->waiters;
locker.mutex()->unlock();
@ -576,7 +582,7 @@ bool QThread::wait(QDeadlineTimer deadline)
if (ret && !d->finished) {
// thread was terminated by someone else
QThreadPrivate::finish(this, false);
d->finish(false);
}
if (d->finished && !d->waiters) {
@ -596,7 +602,7 @@ void QThread::setTerminationEnabled(bool enabled)
QMutexLocker locker(&d->mutex);
d->terminationEnabled = enabled;
if (enabled && d->terminatePending) {
QThreadPrivate::finish(thr, false);
d->finish(false);
locker.unlock(); // don't leave the mutex locked!
_endthreadex(0);
}

View File

@ -3312,6 +3312,10 @@ bool QD3D11Texture::prepareCreate(QSize *adjustedSize)
if (tex || tex3D || tex1D)
destroy();
QRHI_RES_RHI(QRhiD3D11);
if (!rhiD->isTextureFormatSupported(m_format, m_flags))
return false;
const bool isDepth = isDepthTextureFormat(m_format);
const bool isCube = m_flags.testFlag(CubeMap);
const bool is3D = m_flags.testFlag(ThreeDimensional);
@ -3322,7 +3326,6 @@ bool QD3D11Texture::prepareCreate(QSize *adjustedSize)
const QSize size = is1D ? QSize(qMax(1, m_pixelSize.width()), 1)
: (m_pixelSize.isEmpty() ? QSize(1, 1) : m_pixelSize);
QRHI_RES_RHI(QRhiD3D11);
dxgiFormat = toD3DTextureFormat(m_format, m_flags);
mipLevelCount = uint(hasMipMaps ? rhiD->q->mipLevelsForSize(size) : 1);
sampleDesc = rhiD->effectiveSampleDesc(m_sampleCount);

View File

@ -4210,6 +4210,10 @@ bool QD3D12Texture::prepareCreate(QSize *adjustedSize)
if (!handle.isNull())
destroy();
QRHI_RES_RHI(QRhiD3D12);
if (!rhiD->isTextureFormatSupported(m_format, m_flags))
return false;
const bool isDepth = isDepthTextureFormat(m_format);
const bool isCube = m_flags.testFlag(CubeMap);
const bool is3D = m_flags.testFlag(ThreeDimensional);
@ -4240,7 +4244,7 @@ bool QD3D12Texture::prepareCreate(QSize *adjustedSize)
else
srvFormat = toD3DTextureFormat(m_readViewFormat.format, m_readViewFormat.srgb ? sRGB : Flags());
}
QRHI_RES_RHI(QRhiD3D12);
mipLevelCount = uint(hasMipMaps ? rhiD->q->mipLevelsForSize(size) : 1);
sampleDesc = rhiD->effectiveSampleDesc(m_sampleCount, dxgiFormat);
if (sampleDesc.Count > 1) {

View File

@ -1562,11 +1562,9 @@ void QWindowsContext::setAsyncExpose(bool value)
DWORD QWindowsContext::readAdvancedExplorerSettings(const wchar_t *subKey, DWORD defaultValue)
{
const auto value =
QWinRegistryKey(HKEY_CURRENT_USER,
LR"(Software\Microsoft\Windows\CurrentVersion\Explorer\Advanced)")
.dwordValue(subKey);
return value.second ? value.first : defaultValue;
const auto advancedSettings = QWinRegistryKey(
HKEY_CURRENT_USER, LR"(Software\Microsoft\Windows\CurrentVersion\Explorer\Advanced)");
return advancedSettings.value<DWORD>(subKey).value_or(defaultValue);
}
static inline bool isEmptyRect(const RECT &rect)

View File

@ -501,7 +501,8 @@ QWindowsTheme *QWindowsTheme::m_instance = nullptr;
QWindowsTheme::QWindowsTheme()
{
m_instance = this;
s_colorScheme = QWindowsTheme::queryColorScheme();
s_colorScheme = Qt::ColorScheme::Unknown; // Used inside QWindowsTheme::effectiveColorScheme();
s_colorScheme = QWindowsTheme::effectiveColorScheme();
std::fill(m_fonts, m_fonts + NFonts, nullptr);
std::fill(m_palettes, m_palettes + NPalettes, nullptr);
refresh();
@ -596,12 +597,15 @@ Qt::ColorScheme QWindowsTheme::colorScheme() const
Qt::ColorScheme QWindowsTheme::effectiveColorScheme()
{
auto integration = QWindowsIntegration::instance();
if (queryHighContrast())
return Qt::ColorScheme::Unknown;
if (s_colorSchemeOverride != Qt::ColorScheme::Unknown)
return s_colorSchemeOverride;
if (s_colorScheme != Qt::ColorScheme::Unknown)
return s_colorScheme;
if (!integration->darkModeHandling().testFlag(QWindowsApplication::DarkModeStyle))
return Qt::ColorScheme::Light;
return queryColorScheme();
}
@ -1186,9 +1190,11 @@ Qt::ColorScheme QWindowsTheme::queryColorScheme()
if (queryHighContrast())
return Qt::ColorScheme::Unknown;
const auto setting = QWinRegistryKey(HKEY_CURRENT_USER, LR"(Software\Microsoft\Windows\CurrentVersion\Themes\Personalize)")
.dwordValue(L"AppsUseLightTheme");
return setting.second && setting.first == 0 ? Qt::ColorScheme::Dark : Qt::ColorScheme::Light;
QWinRegistryKey personalizeKey{
HKEY_CURRENT_USER, LR"(Software\Microsoft\Windows\CurrentVersion\Themes\Personalize)"
};
const bool useDarkTheme = personalizeKey.value<DWORD>(L"AppsUseLightTheme") == 0;
return useDarkTheme ? Qt::ColorScheme::Dark : Qt::ColorScheme::Light;
}
bool QWindowsTheme::queryHighContrast()

View File

@ -1401,10 +1401,12 @@ void QWindowsForeignWindow::setParent(const QPlatformWindow *newParentWindow)
const HWND newParent = newParentWindow ? reinterpret_cast<HWND>(newParentWindow->winId()) : HWND(nullptr);
const bool isTopLevel = !newParent;
const DWORD oldStyle = style();
qCDebug(lcQpaWindow) << __FUNCTION__ << window() << "newParent="
<< newParentWindow << newParent << "oldStyle=" << debugWinStyle(oldStyle);
SetParent(m_hwnd, newParent);
if (wasTopLevel != isTopLevel) { // Top level window flags need to be set/cleared manually.
auto updateWindowFlags = [=]{
// Top level window flags need to be set/cleared manually.
DWORD newStyle = oldStyle;
if (isTopLevel) {
newStyle = m_topLevelStyle;
@ -1414,6 +1416,20 @@ void QWindowsForeignWindow::setParent(const QPlatformWindow *newParentWindow)
newStyle |= WS_CHILD;
}
SetWindowLongPtr(m_hwnd, GWL_STYLE, newStyle);
};
if (wasTopLevel && !isTopLevel) {
// Becoming a child window requires the style
// flags to be updated before reparenting.
updateWindowFlags();
}
SetParent(m_hwnd, newParent);
if (!wasTopLevel && isTopLevel) {
// Becoming a top level window requires the style
// flags to be updated after reparenting.
updateWindowFlags();
}
}
@ -2496,12 +2512,6 @@ QWindowsWindowData QWindowsWindow::setWindowFlags_sys(Qt::WindowFlags wt,
return result;
}
inline bool QWindowsBaseWindow::hasMaximumSize() const
{
const auto maximumSize = window()->maximumSize();
return maximumSize.width() != QWINDOWSIZE_MAX || maximumSize.height() != QWINDOWSIZE_MAX;
}
void QWindowsWindow::handleWindowStateChange(Qt::WindowStates state)
{
qCDebug(lcQpaWindow) << __FUNCTION__ << this << window()
@ -2518,20 +2528,7 @@ void QWindowsWindow::handleWindowStateChange(Qt::WindowStates state)
GetWindowPlacement(m_data.hwnd, &windowPlacement);
const RECT geometry = RECTfromQRect(m_data.restoreGeometry);
windowPlacement.rcNormalPosition = geometry;
// A bug in windows 10 grows
// - ptMaxPosition.x by the task bar's width, if it's on the left
// - ptMaxPosition.y by the task bar's height, if it's on the top
// each time GetWindowPlacement() is called.
// The offset of the screen's left edge (as per frameMargins_sys().left()) is ignored.
// => Check for windows 10 and correct.
static const auto windows11 = QOperatingSystemVersion::Windows11_21H2;
static const bool isWindows10 = QOperatingSystemVersion::current() < windows11;
if (isWindows10 && hasMaximumSize()) {
const QMargins margins = frameMargins_sys();
const QPoint topLeft = window()->screen()->geometry().topLeft();
windowPlacement.ptMaxPosition = POINT{ topLeft.x() - margins.left(), topLeft.y() };
}
correctWindowPlacement(windowPlacement);
// Even if the window is hidden, windowPlacement's showCmd is not SW_HIDE, so change it
// manually to avoid unhiding a hidden window with the subsequent call to
@ -2563,6 +2560,65 @@ void QWindowsWindow::handleWindowStateChange(Qt::WindowStates state)
}
}
// Apply corrections to window placement in Windows 10
// Related to task bar on top or left.
inline bool QWindowsBaseWindow::hasMaximumHeight() const
{
return window()->maximumHeight() != QWINDOWSIZE_MAX;
}
inline bool QWindowsBaseWindow::hasMaximumWidth() const
{
return window()->maximumWidth() != QWINDOWSIZE_MAX;
}
inline bool QWindowsBaseWindow::hasMaximumSize() const
{
return hasMaximumHeight() || hasMaximumWidth();
}
void QWindowsWindow::correctWindowPlacement(WINDOWPLACEMENT &windowPlacement)
{
static const auto windows11 = QOperatingSystemVersion::Windows11_21H2;
static const bool isWindows10 = QOperatingSystemVersion::current() < windows11;
if (!isWindows10)
return;
// Correct normal position by placement offset on Windows 10
// (where task bar can be on any side of the screen)
const QPoint offset = windowPlacementOffset(m_data.hwnd, m_data.restoreGeometry.topLeft());
windowPlacement.rcNormalPosition = RECTfromQRect(m_data.restoreGeometry.translated(-offset));
qCDebug(lcQpaWindow) << "Corrected normal position by" << -offset;
// A bug in windows 10 grows
// - ptMaxPosition.x by the task bar's width, if it's on the left
// - ptMaxPosition.y by the task bar's height, if it's on the top
// each time GetWindowPlacement() is called.
// The offset of the screen's left edge (as per frameMargins_sys().left()) is ignored.
// => Check for windows 10 and correct.
if (hasMaximumSize()) {
const QMargins margins = frameMargins_sys();
const QPoint topLeft = window()->screen()->geometry().topLeft();
windowPlacement.ptMaxPosition = POINT{ topLeft.x() - margins.left(), topLeft.y() };
qCDebug(lcQpaWindow) << "Window has maximum size. Corrected topLeft by"
<< -margins.left();
// If there is a placement offset correct width/height unless restricted,
// in order to fit window onto the screen.
if (offset.x() > 0 && !hasMaximumWidth()) {
const int adjust = offset.x() / window()->devicePixelRatio();
window()->setWidth(window()->width() - adjust);
qCDebug(lcQpaWindow) << "Width shortened by" << adjust << "logical pixels.";
}
if (offset.y() > 0 && !hasMaximumHeight()) {
const int adjust = offset.y() / window()->devicePixelRatio();
window()->setHeight(window()->height() - adjust);
qCDebug(lcQpaWindow) << "Height shortened by" << adjust << "logical pixels.";
}
}
}
void QWindowsWindow::updateRestoreGeometry()
{
m_data.restoreGeometry = normalFrameGeometry(m_data.hwnd);
@ -2707,8 +2763,24 @@ void QWindowsWindow::setWindowState_sys(Qt::WindowStates newState)
setFlag(WithinMaximize);
if (newState & Qt::WindowFullScreen)
setFlag(MaximizeToFullScreen);
if (m_data.flags & Qt::FramelessWindowHint) {
if (newState == Qt::WindowNoState) {
const QRect &rect = m_savedFrameGeometry;
MoveWindow(m_data.hwnd, rect.x(), rect.y(), rect.width(), rect.height(), true);
} else {
HMONITOR monitor = MonitorFromWindow(m_data.hwnd, MONITOR_DEFAULTTONEAREST);
MONITORINFO monitorInfo = {};
monitorInfo.cbSize = sizeof(MONITORINFO);
GetMonitorInfo(monitor, &monitorInfo);
const RECT &rect = monitorInfo.rcWork;
m_savedFrameGeometry = geometry();
MoveWindow(m_data.hwnd, rect.left, rect.top,
rect.right - rect.left, rect.bottom - rect.top, true);
}
} else {
ShowWindow(m_data.hwnd,
(newState & Qt::WindowMaximized) ? SW_MAXIMIZE : SW_SHOWNOACTIVATE);
}
clearFlag(WithinMaximize);
clearFlag(MaximizeToFullScreen);
} else if (visible && (oldState & newState & Qt::WindowMinimized)) {