mirror of
https://github.com/crystalidea/qt6windows7.git
synced 2025-01-22 20:04:29 +08:00
Qt 6.8.1
This commit is contained in:
parent
a9966ab3ae
commit
8c8f9a4e87
@ -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.
|
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:
|
You have two options for compiling Qt:
|
||||||
|
|
||||||
- Compile it yourself using your preferred compiler and build options.
|
- 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.
|
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)
|
![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:
|
### 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.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.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)
|
- [Qt 6.6.2](https://github.com/crystalidea/qt6windows7/releases/tag/v6.6.2)
|
||||||
|
BIN
designer.png
BIN
designer.png
Binary file not shown.
Before Width: | Height: | Size: 72 KiB After Width: | Height: | Size: 54 KiB |
@ -76,7 +76,7 @@ QThreadData *QThreadData::current(bool createIfNecessary)
|
|||||||
// avoid recursion.
|
// avoid recursion.
|
||||||
TlsSetValue(qt_current_thread_data_tls_index, threadData);
|
TlsSetValue(qt_current_thread_data_tls_index, threadData);
|
||||||
QT_TRY {
|
QT_TRY {
|
||||||
threadData->thread = new QAdoptedThread(threadData);
|
threadData->thread.storeRelease(new QAdoptedThread(threadData));
|
||||||
} QT_CATCH(...) {
|
} QT_CATCH(...) {
|
||||||
TlsSetValue(qt_current_thread_data_tls_index, 0);
|
TlsSetValue(qt_current_thread_data_tls_index, 0);
|
||||||
threadData->deref();
|
threadData->deref();
|
||||||
@ -101,7 +101,7 @@ QThreadData *QThreadData::current(bool createIfNecessary)
|
|||||||
0,
|
0,
|
||||||
FALSE,
|
FALSE,
|
||||||
DUPLICATE_SAME_ACCESS);
|
DUPLICATE_SAME_ACCESS);
|
||||||
qt_watch_adopted_thread(realHandle, threadData->thread);
|
qt_watch_adopted_thread(realHandle, threadData->thread.loadRelaxed());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return threadData;
|
return threadData;
|
||||||
@ -209,7 +209,7 @@ DWORD WINAPI qt_adopted_thread_watcher_function(LPVOID)
|
|||||||
auto thread_p = static_cast<QThreadPrivate *>(QObjectPrivate::get(thread));
|
auto thread_p = static_cast<QThreadPrivate *>(QObjectPrivate::get(thread));
|
||||||
Q_UNUSED(thread_p);
|
Q_UNUSED(thread_p);
|
||||||
Q_ASSERT(!thread_p->finished);
|
Q_ASSERT(!thread_p->finished);
|
||||||
QThreadPrivate::finish(thread);
|
thread_p->finish();
|
||||||
}
|
}
|
||||||
data->deref();
|
data->deref();
|
||||||
|
|
||||||
@ -282,7 +282,6 @@ void qt_set_thread_name(HANDLE threadId, const QString &name)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**************************************************************************
|
/**************************************************************************
|
||||||
** QThreadPrivate
|
** QThreadPrivate
|
||||||
*************************************************************************/
|
*************************************************************************/
|
||||||
@ -326,7 +325,7 @@ unsigned int __stdcall QT_ENSURE_STACK_ALIGNED_FOR_SSE QThreadPrivate::start(voi
|
|||||||
QThread::setTerminationEnabled(true);
|
QThread::setTerminationEnabled(true);
|
||||||
thr->run();
|
thr->run();
|
||||||
|
|
||||||
finish(arg);
|
thr->d_func()->finish();
|
||||||
return 0;
|
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.
|
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 = this;
|
||||||
QThreadPrivate *d = thr->d_func();
|
QThread *thr = q_func();
|
||||||
|
|
||||||
QMutexLocker locker(lockAnyway ? &d->mutex : nullptr);
|
QMutexLocker locker(lockAnyway ? &d->mutex : nullptr);
|
||||||
d->isInFinish = true;
|
d->isInFinish = true;
|
||||||
@ -538,7 +537,7 @@ void QThread::terminate()
|
|||||||
}
|
}
|
||||||
|
|
||||||
TerminateThread(d->handle, 0);
|
TerminateThread(d->handle, 0);
|
||||||
QThreadPrivate::finish(this, false);
|
d->finish(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool QThread::wait(QDeadlineTimer deadline)
|
bool QThread::wait(QDeadlineTimer deadline)
|
||||||
@ -552,6 +551,13 @@ bool QThread::wait(QDeadlineTimer deadline)
|
|||||||
}
|
}
|
||||||
if (d->finished || !d->running)
|
if (d->finished || !d->running)
|
||||||
return true;
|
return true;
|
||||||
|
return d->wait(locker, deadline);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool QThreadPrivate::wait(QMutexLocker<QMutex> &locker, QDeadlineTimer deadline)
|
||||||
|
{
|
||||||
|
Q_ASSERT(locker.isLocked());
|
||||||
|
QThreadPrivate *d = this;
|
||||||
|
|
||||||
++d->waiters;
|
++d->waiters;
|
||||||
locker.mutex()->unlock();
|
locker.mutex()->unlock();
|
||||||
@ -576,7 +582,7 @@ bool QThread::wait(QDeadlineTimer deadline)
|
|||||||
if (ret && !d->finished) {
|
if (ret && !d->finished) {
|
||||||
// thread was terminated by someone else
|
// thread was terminated by someone else
|
||||||
|
|
||||||
QThreadPrivate::finish(this, false);
|
d->finish(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (d->finished && !d->waiters) {
|
if (d->finished && !d->waiters) {
|
||||||
@ -596,7 +602,7 @@ void QThread::setTerminationEnabled(bool enabled)
|
|||||||
QMutexLocker locker(&d->mutex);
|
QMutexLocker locker(&d->mutex);
|
||||||
d->terminationEnabled = enabled;
|
d->terminationEnabled = enabled;
|
||||||
if (enabled && d->terminatePending) {
|
if (enabled && d->terminatePending) {
|
||||||
QThreadPrivate::finish(thr, false);
|
d->finish(false);
|
||||||
locker.unlock(); // don't leave the mutex locked!
|
locker.unlock(); // don't leave the mutex locked!
|
||||||
_endthreadex(0);
|
_endthreadex(0);
|
||||||
}
|
}
|
||||||
|
@ -3312,6 +3312,10 @@ bool QD3D11Texture::prepareCreate(QSize *adjustedSize)
|
|||||||
if (tex || tex3D || tex1D)
|
if (tex || tex3D || tex1D)
|
||||||
destroy();
|
destroy();
|
||||||
|
|
||||||
|
QRHI_RES_RHI(QRhiD3D11);
|
||||||
|
if (!rhiD->isTextureFormatSupported(m_format, m_flags))
|
||||||
|
return false;
|
||||||
|
|
||||||
const bool isDepth = isDepthTextureFormat(m_format);
|
const bool isDepth = isDepthTextureFormat(m_format);
|
||||||
const bool isCube = m_flags.testFlag(CubeMap);
|
const bool isCube = m_flags.testFlag(CubeMap);
|
||||||
const bool is3D = m_flags.testFlag(ThreeDimensional);
|
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)
|
const QSize size = is1D ? QSize(qMax(1, m_pixelSize.width()), 1)
|
||||||
: (m_pixelSize.isEmpty() ? QSize(1, 1) : m_pixelSize);
|
: (m_pixelSize.isEmpty() ? QSize(1, 1) : m_pixelSize);
|
||||||
|
|
||||||
QRHI_RES_RHI(QRhiD3D11);
|
|
||||||
dxgiFormat = toD3DTextureFormat(m_format, m_flags);
|
dxgiFormat = toD3DTextureFormat(m_format, m_flags);
|
||||||
mipLevelCount = uint(hasMipMaps ? rhiD->q->mipLevelsForSize(size) : 1);
|
mipLevelCount = uint(hasMipMaps ? rhiD->q->mipLevelsForSize(size) : 1);
|
||||||
sampleDesc = rhiD->effectiveSampleDesc(m_sampleCount);
|
sampleDesc = rhiD->effectiveSampleDesc(m_sampleCount);
|
||||||
|
@ -4210,6 +4210,10 @@ bool QD3D12Texture::prepareCreate(QSize *adjustedSize)
|
|||||||
if (!handle.isNull())
|
if (!handle.isNull())
|
||||||
destroy();
|
destroy();
|
||||||
|
|
||||||
|
QRHI_RES_RHI(QRhiD3D12);
|
||||||
|
if (!rhiD->isTextureFormatSupported(m_format, m_flags))
|
||||||
|
return false;
|
||||||
|
|
||||||
const bool isDepth = isDepthTextureFormat(m_format);
|
const bool isDepth = isDepthTextureFormat(m_format);
|
||||||
const bool isCube = m_flags.testFlag(CubeMap);
|
const bool isCube = m_flags.testFlag(CubeMap);
|
||||||
const bool is3D = m_flags.testFlag(ThreeDimensional);
|
const bool is3D = m_flags.testFlag(ThreeDimensional);
|
||||||
@ -4240,7 +4244,7 @@ bool QD3D12Texture::prepareCreate(QSize *adjustedSize)
|
|||||||
else
|
else
|
||||||
srvFormat = toD3DTextureFormat(m_readViewFormat.format, m_readViewFormat.srgb ? sRGB : Flags());
|
srvFormat = toD3DTextureFormat(m_readViewFormat.format, m_readViewFormat.srgb ? sRGB : Flags());
|
||||||
}
|
}
|
||||||
QRHI_RES_RHI(QRhiD3D12);
|
|
||||||
mipLevelCount = uint(hasMipMaps ? rhiD->q->mipLevelsForSize(size) : 1);
|
mipLevelCount = uint(hasMipMaps ? rhiD->q->mipLevelsForSize(size) : 1);
|
||||||
sampleDesc = rhiD->effectiveSampleDesc(m_sampleCount, dxgiFormat);
|
sampleDesc = rhiD->effectiveSampleDesc(m_sampleCount, dxgiFormat);
|
||||||
if (sampleDesc.Count > 1) {
|
if (sampleDesc.Count > 1) {
|
||||||
|
@ -1562,11 +1562,9 @@ void QWindowsContext::setAsyncExpose(bool value)
|
|||||||
|
|
||||||
DWORD QWindowsContext::readAdvancedExplorerSettings(const wchar_t *subKey, DWORD defaultValue)
|
DWORD QWindowsContext::readAdvancedExplorerSettings(const wchar_t *subKey, DWORD defaultValue)
|
||||||
{
|
{
|
||||||
const auto value =
|
const auto advancedSettings = QWinRegistryKey(
|
||||||
QWinRegistryKey(HKEY_CURRENT_USER,
|
HKEY_CURRENT_USER, LR"(Software\Microsoft\Windows\CurrentVersion\Explorer\Advanced)");
|
||||||
LR"(Software\Microsoft\Windows\CurrentVersion\Explorer\Advanced)")
|
return advancedSettings.value<DWORD>(subKey).value_or(defaultValue);
|
||||||
.dwordValue(subKey);
|
|
||||||
return value.second ? value.first : defaultValue;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline bool isEmptyRect(const RECT &rect)
|
static inline bool isEmptyRect(const RECT &rect)
|
||||||
|
@ -501,7 +501,8 @@ QWindowsTheme *QWindowsTheme::m_instance = nullptr;
|
|||||||
QWindowsTheme::QWindowsTheme()
|
QWindowsTheme::QWindowsTheme()
|
||||||
{
|
{
|
||||||
m_instance = this;
|
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_fonts, m_fonts + NFonts, nullptr);
|
||||||
std::fill(m_palettes, m_palettes + NPalettes, nullptr);
|
std::fill(m_palettes, m_palettes + NPalettes, nullptr);
|
||||||
refresh();
|
refresh();
|
||||||
@ -596,12 +597,15 @@ Qt::ColorScheme QWindowsTheme::colorScheme() const
|
|||||||
|
|
||||||
Qt::ColorScheme QWindowsTheme::effectiveColorScheme()
|
Qt::ColorScheme QWindowsTheme::effectiveColorScheme()
|
||||||
{
|
{
|
||||||
|
auto integration = QWindowsIntegration::instance();
|
||||||
if (queryHighContrast())
|
if (queryHighContrast())
|
||||||
return Qt::ColorScheme::Unknown;
|
return Qt::ColorScheme::Unknown;
|
||||||
if (s_colorSchemeOverride != Qt::ColorScheme::Unknown)
|
if (s_colorSchemeOverride != Qt::ColorScheme::Unknown)
|
||||||
return s_colorSchemeOverride;
|
return s_colorSchemeOverride;
|
||||||
if (s_colorScheme != Qt::ColorScheme::Unknown)
|
if (s_colorScheme != Qt::ColorScheme::Unknown)
|
||||||
return s_colorScheme;
|
return s_colorScheme;
|
||||||
|
if (!integration->darkModeHandling().testFlag(QWindowsApplication::DarkModeStyle))
|
||||||
|
return Qt::ColorScheme::Light;
|
||||||
return queryColorScheme();
|
return queryColorScheme();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1186,9 +1190,11 @@ Qt::ColorScheme QWindowsTheme::queryColorScheme()
|
|||||||
if (queryHighContrast())
|
if (queryHighContrast())
|
||||||
return Qt::ColorScheme::Unknown;
|
return Qt::ColorScheme::Unknown;
|
||||||
|
|
||||||
const auto setting = QWinRegistryKey(HKEY_CURRENT_USER, LR"(Software\Microsoft\Windows\CurrentVersion\Themes\Personalize)")
|
QWinRegistryKey personalizeKey{
|
||||||
.dwordValue(L"AppsUseLightTheme");
|
HKEY_CURRENT_USER, LR"(Software\Microsoft\Windows\CurrentVersion\Themes\Personalize)"
|
||||||
return setting.second && setting.first == 0 ? Qt::ColorScheme::Dark : Qt::ColorScheme::Light;
|
};
|
||||||
|
const bool useDarkTheme = personalizeKey.value<DWORD>(L"AppsUseLightTheme") == 0;
|
||||||
|
return useDarkTheme ? Qt::ColorScheme::Dark : Qt::ColorScheme::Light;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool QWindowsTheme::queryHighContrast()
|
bool QWindowsTheme::queryHighContrast()
|
||||||
|
@ -1401,10 +1401,12 @@ void QWindowsForeignWindow::setParent(const QPlatformWindow *newParentWindow)
|
|||||||
const HWND newParent = newParentWindow ? reinterpret_cast<HWND>(newParentWindow->winId()) : HWND(nullptr);
|
const HWND newParent = newParentWindow ? reinterpret_cast<HWND>(newParentWindow->winId()) : HWND(nullptr);
|
||||||
const bool isTopLevel = !newParent;
|
const bool isTopLevel = !newParent;
|
||||||
const DWORD oldStyle = style();
|
const DWORD oldStyle = style();
|
||||||
|
|
||||||
qCDebug(lcQpaWindow) << __FUNCTION__ << window() << "newParent="
|
qCDebug(lcQpaWindow) << __FUNCTION__ << window() << "newParent="
|
||||||
<< newParentWindow << newParent << "oldStyle=" << debugWinStyle(oldStyle);
|
<< 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;
|
DWORD newStyle = oldStyle;
|
||||||
if (isTopLevel) {
|
if (isTopLevel) {
|
||||||
newStyle = m_topLevelStyle;
|
newStyle = m_topLevelStyle;
|
||||||
@ -1414,6 +1416,20 @@ void QWindowsForeignWindow::setParent(const QPlatformWindow *newParentWindow)
|
|||||||
newStyle |= WS_CHILD;
|
newStyle |= WS_CHILD;
|
||||||
}
|
}
|
||||||
SetWindowLongPtr(m_hwnd, GWL_STYLE, newStyle);
|
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;
|
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)
|
void QWindowsWindow::handleWindowStateChange(Qt::WindowStates state)
|
||||||
{
|
{
|
||||||
qCDebug(lcQpaWindow) << __FUNCTION__ << this << window()
|
qCDebug(lcQpaWindow) << __FUNCTION__ << this << window()
|
||||||
@ -2518,20 +2528,7 @@ void QWindowsWindow::handleWindowStateChange(Qt::WindowStates state)
|
|||||||
GetWindowPlacement(m_data.hwnd, &windowPlacement);
|
GetWindowPlacement(m_data.hwnd, &windowPlacement);
|
||||||
const RECT geometry = RECTfromQRect(m_data.restoreGeometry);
|
const RECT geometry = RECTfromQRect(m_data.restoreGeometry);
|
||||||
windowPlacement.rcNormalPosition = geometry;
|
windowPlacement.rcNormalPosition = geometry;
|
||||||
|
correctWindowPlacement(windowPlacement);
|
||||||
// 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() };
|
|
||||||
}
|
|
||||||
|
|
||||||
// Even if the window is hidden, windowPlacement's showCmd is not SW_HIDE, so change it
|
// 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
|
// 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()
|
void QWindowsWindow::updateRestoreGeometry()
|
||||||
{
|
{
|
||||||
m_data.restoreGeometry = normalFrameGeometry(m_data.hwnd);
|
m_data.restoreGeometry = normalFrameGeometry(m_data.hwnd);
|
||||||
@ -2707,8 +2763,24 @@ void QWindowsWindow::setWindowState_sys(Qt::WindowStates newState)
|
|||||||
setFlag(WithinMaximize);
|
setFlag(WithinMaximize);
|
||||||
if (newState & Qt::WindowFullScreen)
|
if (newState & Qt::WindowFullScreen)
|
||||||
setFlag(MaximizeToFullScreen);
|
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,
|
ShowWindow(m_data.hwnd,
|
||||||
(newState & Qt::WindowMaximized) ? SW_MAXIMIZE : SW_SHOWNOACTIVATE);
|
(newState & Qt::WindowMaximized) ? SW_MAXIMIZE : SW_SHOWNOACTIVATE);
|
||||||
|
}
|
||||||
clearFlag(WithinMaximize);
|
clearFlag(WithinMaximize);
|
||||||
clearFlag(MaximizeToFullScreen);
|
clearFlag(MaximizeToFullScreen);
|
||||||
} else if (visible && (oldState & newState & Qt::WindowMinimized)) {
|
} else if (visible && (oldState & newState & Qt::WindowMinimized)) {
|
||||||
|
Loading…
Reference in New Issue
Block a user