mirror of
https://github.com/crystalidea/qt6windows7.git
synced 2025-07-01 06:41:52 +08:00
Compare commits
7 Commits
e92ba4dce4
...
v6.8.3
Author | SHA1 | Date | |
---|---|---|---|
7cd5e9532e | |||
a1fc369ce9 | |||
f77cd07e31 | |||
ff167a036d | |||
b149cc3eb2 | |||
97ed722167 | |||
15d5fb5382 |
@ -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**:
|
||||
|
||||

|
||||
|
||||
@ -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)
|
||||
|
BIN
designer.png
BIN
designer.png
Binary file not shown.
Before Width: | Height: | Size: 54 KiB After Width: | Height: | Size: 51 KiB |
@ -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();
|
||||
|
@ -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)
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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 ¶meter,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 ¶mList,
|
||||
int *tabletAbsoluteRange,
|
||||
QtWindows::DpiAwareness *dpiAwareness,
|
||||
@ -164,12 +141,6 @@ static inline unsigned parseOptions(const QStringList ¶mList,
|
||||
{
|
||||
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 ¶m : 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
|
||||
|
@ -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));
|
||||
|
||||
|
@ -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>;
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -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) {
|
||||
|
@ -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;
|
||||
|
@ -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();
|
||||
|
Reference in New Issue
Block a user