7 Commits

Author SHA1 Message Date
7cd5e9532e update to Qt 6.8.3 2025-04-21 18:20:29 +02:00
a1fc369ce9 Merge pull request #39 from wsxarcher/patch-4
Fix mingw GCC compilation with explicit cast of function pointer to void*
2025-04-21 18:01:31 +02:00
f77cd07e31 Explicit cast qwin10helpers.cpp GetProcAddress 2025-03-23 01:08:17 +01:00
ff167a036d v6.8.1 2025-03-21 13:11:05 +01:00
b149cc3eb2 one more change from Qt 6.8.2 2025-03-17 18:15:19 +01:00
97ed722167 update to Qt 6.8.2 2025-03-17 18:04:27 +01:00
15d5fb5382 turn off directwrite fonts on Windows prior to Windows 10 (issue https://github.com/crystalidea/qt6windows7/issues/33) 2025-03-17 17:22:31 +01:00
14 changed files with 71 additions and 58 deletions

View File

@ -1,10 +1,12 @@
This repository provides a backport of the Qt 6.8.1 qtbase module, tailored for compatibility with Windows 7, 8 and 8.1. 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 qtbase module, tailored for compatibility with Windows 7, 8 and 8.1. 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.
The most recent supported version is **6.8.3** however many older versions are supported as well (see **Older versions** section).
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 can compile it yourself using your preferred compiler and build options or can 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.1 designer running on Windows 7**:
**Qt 6.8.3 designer running on Windows 7**:
![Qt Designer](designer.png)
@ -23,6 +25,8 @@ Many of other Qt 6 modules are known to work fine on Windows 7 without modificat
### Older versions:
- [Qt 6.8.2](https://github.com/crystalidea/qt6windows7/releases/tag/v6.8.2)
- [Qt 6.8.1](https://github.com/crystalidea/qt6windows7/releases/tag/v6.8.1)
- [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)

Binary file not shown.

Before

Width:  |  Height:  |  Size: 54 KiB

After

Width:  |  Height:  |  Size: 51 KiB

View File

@ -637,6 +637,7 @@ void QRecursiveMutex::unlock() noexcept
/*!
\internal helper for lock()
*/
Q_NEVER_INLINE
void QBasicMutex::lockInternal() QT_MUTEX_LOCK_NOEXCEPT
{
if (futexAvailable()) {
@ -650,7 +651,7 @@ void QBasicMutex::lockInternal() QT_MUTEX_LOCK_NOEXCEPT
}
Q_ASSERT(d_ptr.loadRelaxed());
} else {
lockInternal(-1);
lockInternal(QDeadlineTimer::Forever);
}
}
@ -670,6 +671,7 @@ bool QBasicMutex::lockInternal(int timeout) QT_MUTEX_LOCK_NOEXCEPT
/*!
\internal helper for tryLock(QDeadlineTimer)
*/
Q_NEVER_INLINE
bool QBasicMutex::lockInternal(QDeadlineTimer deadlineTimer) QT_MUTEX_LOCK_NOEXCEPT
{
if (deadlineTimer.hasExpired())
@ -809,6 +811,7 @@ bool QBasicMutex::lockInternal(QDeadlineTimer deadlineTimer) QT_MUTEX_LOCK_NOEXC
/*!
\internal
*/
Q_NEVER_INLINE
void QBasicMutex::unlockInternal() noexcept
{
QMutexPrivate *copy = d_ptr.loadAcquire();

View File

@ -11,6 +11,7 @@
#include <private/qcoreapplication_p.h>
#include <private/qeventdispatcher_win_p.h>
#include "qloggingcategory.h"
#include <qt_windows.h>
@ -352,7 +353,6 @@ void QThreadPrivate::finish(bool lockAnyway) noexcept
if (lockAnyway)
locker.unlock();
emit thr->finished(QThread::QPrivateSignal());
qCDebug(lcDeleteLater) << "Sending deferred delete events as part of finishing thread" << thr;
QCoreApplicationPrivate::sendPostedEvents(nullptr, QEvent::DeferredDelete, d->data);
QThreadStorageData::finish(tls_data);
if (lockAnyway)

View File

@ -3609,6 +3609,7 @@ ID3D11UnorderedAccessView *QD3D11Texture::unorderedAccessViewForLevel(int level)
} else if (is3D) {
desc.ViewDimension = D3D11_UAV_DIMENSION_TEXTURE3D;
desc.Texture3D.MipSlice = UINT(level);
desc.Texture3D.WSize = UINT(m_depth);
} else {
desc.ViewDimension = D3D11_UAV_DIMENSION_TEXTURE2D;
desc.Texture2D.MipSlice = UINT(level);

View File

@ -1006,6 +1006,7 @@ void QD3D12CommandBuffer::visitStorageImage(QD3D12Stage s,
} else if (is3D) {
uavDesc.ViewDimension = D3D12_UAV_DIMENSION_TEXTURE3D;
uavDesc.Texture3D.MipSlice = UINT(d.level);
uavDesc.Texture3D.WSize = UINT(-1);
} else {
uavDesc.ViewDimension = D3D12_UAV_DIMENSION_TEXTURE2D;
uavDesc.Texture2D.MipSlice = UINT(d.level);
@ -3659,7 +3660,7 @@ void QRhiD3D12::finishActiveReadbacks(bool forced)
if (readback.result->completed)
completedCallbacks.append(readback.result->completed);
activeReadbacks.removeLast();
activeReadbacks.remove(i);
}
}
@ -5697,7 +5698,16 @@ bool QD3D12GraphicsPipeline::create()
}
QD3D12RenderPassDescriptor *rpD = QRHI_RES(QD3D12RenderPassDescriptor, m_renderPassDesc);
const DXGI_SAMPLE_DESC sampleDesc = rhiD->effectiveSampleDesc(m_sampleCount, DXGI_FORMAT(rpD->colorFormat[0]));
DXGI_FORMAT format = DXGI_FORMAT_UNKNOWN;
if (rpD->colorAttachmentCount > 0) {
format = DXGI_FORMAT(rpD->colorFormat[0]);
} else if (rpD->hasDepthStencil) {
format = DXGI_FORMAT(rpD->dsFormat);
} else {
qWarning("Cannot create graphics pipeline state without color or depthStencil format");
return false;
}
const DXGI_SAMPLE_DESC sampleDesc = rhiD->effectiveSampleDesc(m_sampleCount, format);
struct {
QD3D12PipelineStateSubObject<ID3D12RootSignature *, D3D12_PIPELINE_STATE_SUBOBJECT_TYPE_ROOT_SIGNATURE> rootSig;

View File

@ -71,7 +71,7 @@ void * WIN_LoadComBaseFunction(const char *name)
s_bLoaded = true;
}
if (s_hComBase) {
return ::GetProcAddress(s_hComBase, name);
return (void *) ::GetProcAddress(s_hComBase, name);
} else {
return NULL;
}

View File

@ -105,7 +105,7 @@ struct QWindowsIntegrationPrivate
#if QT_CONFIG(accessibility)
QWindowsUiaAccessibility m_accessibility;
#endif
QWindowsServices m_services;
mutable QScopedPointer<QWindowsServices> m_services;
};
template <typename IntType>
@ -134,29 +134,6 @@ bool parseIntOption(const QString &parameter,const QLatin1StringView &option,
using DarkModeHandlingFlag = QNativeInterface::Private::QWindowsApplication::DarkModeHandlingFlag;
using DarkModeHandling = QNativeInterface::Private::QWindowsApplication::DarkModeHandling;
typedef LONG (WINAPI *RtlGetVersionPtr)(PRTL_OSVERSIONINFOW);
bool isWindows81() {
HMODULE hNtdll = GetModuleHandleA("ntdll.dll");
if (!hNtdll) {
return false; // Failed to load ntdll.dll
}
RtlGetVersionPtr RtlGetVersion = (RtlGetVersionPtr)GetProcAddress(hNtdll, "RtlGetVersion");
if (!RtlGetVersion) {
return false; // Failed to get RtlGetVersion
}
RTL_OSVERSIONINFOW rovi = {0};
rovi.dwOSVersionInfoSize = sizeof(rovi);
if (RtlGetVersion(&rovi) == 0) { // STATUS_SUCCESS
return (rovi.dwMajorVersion == 6 && rovi.dwMinorVersion == 3);
}
return false; // Unknown version
}
static inline unsigned parseOptions(const QStringList &paramList,
int *tabletAbsoluteRange,
QtWindows::DpiAwareness *dpiAwareness,
@ -164,12 +141,6 @@ static inline unsigned parseOptions(const QStringList &paramList,
{
unsigned options = 0;
// for some reason DirectWrite fonts don't work on Windows 8.1
// https://github.com/crystalidea/qt6windows7/issues/26
if (isWindows81())
options |= QWindowsIntegration::DontUseDirectWriteFonts;
for (const QString &param : paramList) {
if (param.startsWith(u"fontengine=")) {
if (param.endsWith(u"gdi")) {
@ -515,7 +486,14 @@ QPlatformFontDatabase *QWindowsIntegration::fontDatabase() const
else
#endif // QT_NO_FREETYPE
#if QT_CONFIG(directwrite3)
if (!(d->m_options & (QWindowsIntegration::FontDatabaseGDI | QWindowsIntegration::DontUseDirectWriteFonts)))
/* IDWriteFontFace3 is only reportedly available starting with Windows 10. This change is necessary starting
with Qt 6.8, where DirectWrite is used by default to populate the font database.
More info: https://github.com/videolan/vlc/blob/master/contrib/src/qt/0001-Use-DirectWrite-font-database-only-with-Windows-10-a.patch
*/
if (QOperatingSystemVersion::current() >= QOperatingSystemVersion::Windows10 &&
!(d->m_options & (QWindowsIntegration::FontDatabaseGDI | QWindowsIntegration::DontUseDirectWriteFonts)))
d->m_fontDatabase = new QWindowsDirectWriteFontDatabase;
else
#endif
@ -628,7 +606,10 @@ QPlatformTheme *QWindowsIntegration::createPlatformTheme(const QString &name) co
QPlatformServices *QWindowsIntegration::services() const
{
return &d->m_services;
if (d->m_services.isNull())
d->m_services.reset(new QWindowsServices);
return d->m_services.data();
}
void QWindowsIntegration::beep() const

View File

@ -1359,6 +1359,11 @@ QList<QKeyCombination> QWindowsKeyMapper::possibleKeyCombinations(const QKeyEven
return result;
}
// If Key_Tab+Shift is pressed we add Key_Backtab without
// shift modifier as a possible combination too
if (baseKey == Qt::Key_Tab && (keyMods & Qt::ShiftModifier))
result << (Qt::Key_Backtab | (keyMods & ~Qt::ShiftModifier));
// The base key is _always_ valid, of course
result << QKeyCombination::fromCombined(int(baseKey) + int(keyMods));

View File

@ -132,12 +132,12 @@ namespace {
struct DiRegKeyHandleTraits
{
using Type = HKEY;
static Type invalidValue()
static Type invalidValue() noexcept
{
// The setupapi.h functions return INVALID_HANDLE_VALUE when failing to open a registry key
return reinterpret_cast<HKEY>(INVALID_HANDLE_VALUE);
}
static bool close(Type handle) { return RegCloseKey(handle) == ERROR_SUCCESS; }
static bool close(Type handle) noexcept { return RegCloseKey(handle) == ERROR_SUCCESS; }
};
using DiRegKeyHandle = QUniqueHandle<DiRegKeyHandleTraits>;
@ -145,11 +145,11 @@ using DiRegKeyHandle = QUniqueHandle<DiRegKeyHandleTraits>;
struct DevInfoHandleTraits
{
using Type = HDEVINFO;
static Type invalidValue()
static Type invalidValue() noexcept
{
return reinterpret_cast<HDEVINFO>(INVALID_HANDLE_VALUE);
}
static bool close(Type handle) { return SetupDiDestroyDeviceInfoList(handle) == TRUE; }
static bool close(Type handle) noexcept { return SetupDiDestroyDeviceInfoList(handle) == TRUE; }
};
using DevInfoHandle = QUniqueHandle<DevInfoHandleTraits>;

View File

@ -306,6 +306,7 @@ void QWindowsTheme::populateLightSystemBasePalette(QPalette &result)
const QColor background = getSysColor(COLOR_BTNFACE);
const QColor textColor = getSysColor(COLOR_WINDOWTEXT);
const QColor accent = qt_accentColor(AccentColorNormal);
const QColor accentDark = qt_accentColor(AccentColorDark);
const QColor accentDarker = qt_accentColor(AccentColorDarker);
const QColor accentDarkest = qt_accentColor(AccentColorDarkest);
@ -314,7 +315,7 @@ void QWindowsTheme::populateLightSystemBasePalette(QPalette &result)
const QColor btnFace = background;
const QColor btnHighlight = getSysColor(COLOR_BTNHIGHLIGHT);
result.setColor(QPalette::Highlight, getSysColor(COLOR_HIGHLIGHT));
result.setColor(QPalette::Highlight, accent);
result.setColor(QPalette::WindowText, getSysColor(COLOR_WINDOWTEXT));
result.setColor(QPalette::Button, btnFace);
result.setColor(QPalette::Light, btnHighlight);
@ -843,7 +844,6 @@ QPixmap QWindowsTheme::standardPixmap(StandardPixmap sp, const QSizeF &pixmapSiz
{
int resourceId = -1;
SHSTOCKICONID stockId = SIID_INVALID;
UINT stockFlags = 0;
LPCTSTR iconName = nullptr;
switch (sp) {
case DriveCDIcon:
@ -867,14 +867,12 @@ QPixmap QWindowsTheme::standardPixmap(StandardPixmap sp, const QSizeF &pixmapSiz
resourceId = 7;
break;
case FileLinkIcon:
stockFlags = SHGSI_LINKOVERLAY;
Q_FALLTHROUGH();
case FileIcon:
stockId = SIID_DOCNOASSOC;
resourceId = 1;
break;
case DirLinkIcon:
stockFlags = SHGSI_LINKOVERLAY;
Q_FALLTHROUGH();
case DirClosedIcon:
case DirIcon:
@ -888,7 +886,6 @@ QPixmap QWindowsTheme::standardPixmap(StandardPixmap sp, const QSizeF &pixmapSiz
resourceId = 16;
break;
case DirLinkOpenIcon:
stockFlags = SHGSI_LINKOVERLAY;
Q_FALLTHROUGH();
case DirOpenIcon:
stockId = SIID_FOLDEROPEN;
@ -928,18 +925,34 @@ QPixmap QWindowsTheme::standardPixmap(StandardPixmap sp, const QSizeF &pixmapSiz
break;
}
// Even with SHGSI_LINKOVERLAY flag set, loaded Icon with SHDefExtractIcon doesn't have
// any overlay, so we avoid SHGSI_LINKOVERLAY flag and draw it manually (QTBUG-131843)
const auto drawLinkOverlayIconIfNeeded = [](StandardPixmap sp, QPixmap &pixmap, QSizeF pixmapSize) {
if (sp == FileLinkIcon || sp == DirLinkIcon || sp == DirLinkOpenIcon) {
QPainter painter(&pixmap);
const QSizeF linkSize = pixmapSize / (pixmapSize.height() >= 48 ? 3 : 2);
static constexpr auto LinkOverlayIconId = 16769;
const QPixmap link = loadIconFromShell32(LinkOverlayIconId, linkSize.toSize());
const int yPos = pixmap.height() - link.size().height();
painter.drawPixmap(0, yPos, int(linkSize.width()), int(linkSize.height()), link);
}
};
if (stockId != SIID_INVALID) {
SHSTOCKICONINFO iconInfo;
memset(&iconInfo, 0, sizeof(iconInfo));
iconInfo.cbSize = sizeof(iconInfo);
stockFlags |= SHGSI_ICONLOCATION;
constexpr UINT stockFlags = SHGSI_ICONLOCATION;
if (SHGetStockIconInfo(stockId, stockFlags, &iconInfo) == S_OK) {
const auto iconSize = pixmapSize.width();
HICON icon;
if (SHDefExtractIcon(iconInfo.szPath, iconInfo.iIcon, 0, &icon, nullptr, iconSize) == S_OK) {
QPixmap pixmap = qt_pixmapFromWinHICON(icon);
DestroyIcon(icon);
return pixmap;
if (!pixmap.isNull()) {
drawLinkOverlayIconIfNeeded(sp, pixmap, pixmap.size());
return pixmap;
}
}
}
}
@ -947,11 +960,7 @@ QPixmap QWindowsTheme::standardPixmap(StandardPixmap sp, const QSizeF &pixmapSiz
if (resourceId != -1) {
QPixmap pixmap = loadIconFromShell32(resourceId, pixmapSize);
if (!pixmap.isNull()) {
if (sp == FileLinkIcon || sp == DirLinkIcon || sp == DirLinkOpenIcon) {
QPainter painter(&pixmap);
QPixmap link = loadIconFromShell32(30, pixmapSize);
painter.drawPixmap(0, 0, int(pixmapSize.width()), int(pixmapSize.height()), link);
}
drawLinkOverlayIconIfNeeded(sp, pixmap, pixmapSize);
return pixmap;
}
}

View File

@ -1405,7 +1405,7 @@ void QWindowsForeignWindow::setParent(const QPlatformWindow *newParentWindow)
qCDebug(lcQpaWindow) << __FUNCTION__ << window() << "newParent="
<< newParentWindow << newParent << "oldStyle=" << debugWinStyle(oldStyle);
auto updateWindowFlags = [=]{
auto updateWindowFlags = [&]{
// Top level window flags need to be set/cleared manually.
DWORD newStyle = oldStyle;
if (isTopLevel) {

View File

@ -363,7 +363,7 @@ void QWindowsUiaMainProvider::fillVariantArrayForRelation(QAccessibleInterface*
{
Q_ASSERT(accessible);
typedef QPair<QAccessibleInterface*, QAccessible::Relation> RelationPair;
typedef std::pair<QAccessibleInterface*, QAccessible::Relation> RelationPair;
const QList<RelationPair> relationInterfaces = accessible->relations(relation);
if (relationInterfaces.empty())
return;

View File

@ -798,7 +798,7 @@ void QWindowsStyle::drawPrimitive(PrimitiveElement pe, const QStyleOption *opt,
case PE_FrameFocusRect:
if (const QStyleOptionFocusRect *fropt = qstyleoption_cast<const QStyleOptionFocusRect *>(opt)) {
//### check for d->alt_down
if (!(fropt->state & State_KeyboardFocusChange) && !proxy()->styleHint(SH_UnderlineShortcut, opt))
if (!(fropt->state & State_KeyboardFocusChange) && !proxy()->styleHint(SH_UnderlineShortcut, opt, w))
return;
QRect r = opt->rect;
p->save();