Skip to content

Commit

Permalink
Qt 6.8.1
Browse files Browse the repository at this point in the history
  • Loading branch information
kleuter committed Dec 13, 2024
1 parent a9966ab commit 8c8f9a4
Show file tree
Hide file tree
Showing 8 changed files with 139 additions and 50 deletions.
8 changes: 4 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
@@ -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)

Expand All @@ -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)
Expand Down
Binary file modified designer.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
28 changes: 17 additions & 11 deletions qtbase/src/corelib/thread/qthread_win.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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();
Expand All @@ -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;
Expand Down Expand Up @@ -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();

Expand Down Expand Up @@ -282,7 +282,6 @@ void qt_set_thread_name(HANDLE threadId, const QString &name)
}
}


/**************************************************************************
** QThreadPrivate
*************************************************************************/
Expand Down Expand Up @@ -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;
}

Expand All @@ -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;
Expand Down Expand Up @@ -538,7 +537,7 @@ void QThread::terminate()
}

TerminateThread(d->handle, 0);
QThreadPrivate::finish(this, false);
d->finish(false);
}

bool QThread::wait(QDeadlineTimer deadline)
Expand All @@ -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();
Expand All @@ -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) {
Expand All @@ -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);
}
Expand Down
5 changes: 4 additions & 1 deletion qtbase/src/gui/rhi/qrhid3d11.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand All @@ -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);
Expand Down
6 changes: 5 additions & 1 deletion qtbase/src/gui/rhi/qrhid3d12.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down Expand Up @@ -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) {
Expand Down
8 changes: 3 additions & 5 deletions qtbase/src/plugins/platforms/windows/qwindowscontext.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
14 changes: 10 additions & 4 deletions qtbase/src/plugins/platforms/windows/qwindowstheme.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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();
Expand Down Expand Up @@ -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();
}

Expand Down Expand Up @@ -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()
Expand Down
120 changes: 96 additions & 24 deletions qtbase/src/plugins/platforms/windows/qwindowswindow.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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();
}
}

Expand Down Expand Up @@ -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()
Expand All @@ -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
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -2707,8 +2763,24 @@ void QWindowsWindow::setWindowState_sys(Qt::WindowStates newState)
setFlag(WithinMaximize);
if (newState & Qt::WindowFullScreen)
setFlag(MaximizeToFullScreen);
ShowWindow(m_data.hwnd,
(newState & Qt::WindowMaximized) ? SW_MAXIMIZE : SW_SHOWNOACTIVATE);
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)) {
Expand Down

0 comments on commit 8c8f9a4

Please sign in to comment.