win: fix the multi monitor window expand issue
#141 #184 Signed-off-by: Yuhang Zhao <2546789017@qq.com>
This commit is contained in:
parent
3961ecb505
commit
ebd3d6573f
|
@ -415,10 +415,10 @@ Q_ENUM_NS(WindowCornerStyle)
|
||||||
|
|
||||||
struct VersionNumber
|
struct VersionNumber
|
||||||
{
|
{
|
||||||
int major = 0;
|
const int major = 0;
|
||||||
int minor = 0;
|
const int minor = 0;
|
||||||
int patch = 0;
|
const int patch = 0;
|
||||||
int tweak = 0;
|
const int tweak = 0;
|
||||||
|
|
||||||
[[nodiscard]] friend constexpr bool operator==(const VersionNumber &lhs, const VersionNumber &rhs) noexcept
|
[[nodiscard]] friend constexpr bool operator==(const VersionNumber &lhs, const VersionNumber &rhs) noexcept
|
||||||
{
|
{
|
||||||
|
@ -571,39 +571,6 @@ struct SystemParameters
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
#ifdef Q_OS_WINDOWS
|
|
||||||
[[maybe_unused]] inline constexpr const VersionNumber WindowsVersions[] =
|
|
||||||
{
|
|
||||||
{ 5, 0, 2195}, // Windows 2000
|
|
||||||
{ 5, 1, 2600}, // Windows XP
|
|
||||||
{ 5, 2, 3790}, // Windows XP x64 Edition or Windows Server 2003
|
|
||||||
{ 6, 0, 6000}, // Windows Vista
|
|
||||||
{ 6, 0, 6001}, // Windows Vista with Service Pack 1 or Windows Server 2008
|
|
||||||
{ 6, 0, 6002}, // Windows Vista with Service Pack 2
|
|
||||||
{ 6, 1, 7600}, // Windows 7 or Windows Server 2008 R2
|
|
||||||
{ 6, 1, 7601}, // Windows 7 with Service Pack 1 or Windows Server 2008 R2 with Service Pack 1
|
|
||||||
{ 6, 2, 9200}, // Windows 8 or Windows Server 2012
|
|
||||||
{ 6, 3, 9200}, // Windows 8.1 or Windows Server 2012 R2
|
|
||||||
{ 6, 3, 9600}, // Windows 8.1 with Update 1
|
|
||||||
{10, 0, 10240}, // Windows 10 Version 1507 (TH1)
|
|
||||||
{10, 0, 10586}, // Windows 10 Version 1511 (November Update) (TH2)
|
|
||||||
{10, 0, 14393}, // Windows 10 Version 1607 (Anniversary Update) (RS1) or Windows Server 2016
|
|
||||||
{10, 0, 15063}, // Windows 10 Version 1703 (Creators Update) (RS2)
|
|
||||||
{10, 0, 16299}, // Windows 10 Version 1709 (Fall Creators Update) (RS3)
|
|
||||||
{10, 0, 17134}, // Windows 10 Version 1803 (April 2018 Update) (RS4)
|
|
||||||
{10, 0, 17763}, // Windows 10 Version 1809 (October 2018 Update) (RS5) or Windows Server 2019
|
|
||||||
{10, 0, 18362}, // Windows 10 Version 1903 (May 2019 Update) (19H1)
|
|
||||||
{10, 0, 18363}, // Windows 10 Version 1909 (November 2019 Update) (19H2)
|
|
||||||
{10, 0, 19041}, // Windows 10 Version 2004 (May 2020 Update) (20H1)
|
|
||||||
{10, 0, 19042}, // Windows 10 Version 20H2 (October 2020 Update) (20H2)
|
|
||||||
{10, 0, 19043}, // Windows 10 Version 21H1 (May 2021 Update) (21H1)
|
|
||||||
{10, 0, 19044}, // Windows 10 Version 21H2 (November 2021 Update) (21H2)
|
|
||||||
{10, 0, 19045}, // Windows 10 Version 22H2 (October 2022 Update) (22H2)
|
|
||||||
{10, 0, 22000}, // Windows 11 Version 21H2 (21H2)
|
|
||||||
{10, 0, 22621} // Windows 11 Version 22H2 (October 2022 Update) (22H2)
|
|
||||||
};
|
|
||||||
#endif // Q_OS_WINDOWS
|
|
||||||
|
|
||||||
struct VersionInfo
|
struct VersionInfo
|
||||||
{
|
{
|
||||||
const int version = 0;
|
const int version = 0;
|
||||||
|
@ -615,6 +582,45 @@ struct VersionInfo
|
||||||
const bool isStatic = false;
|
const bool isStatic = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct Dpi
|
||||||
|
{
|
||||||
|
const quint32 x = 0;
|
||||||
|
const quint32 y = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
#ifdef Q_OS_WINDOWS
|
||||||
|
[[maybe_unused]] inline constexpr const VersionNumber WindowsVersions[] =
|
||||||
|
{
|
||||||
|
{ 5, 0, 2195}, // Windows 2000
|
||||||
|
{ 5, 1, 2600}, // Windows XP
|
||||||
|
{ 5, 2, 3790}, // Windows XP x64 Edition or Windows Server 2003
|
||||||
|
{ 6, 0, 6000}, // Windows Vista
|
||||||
|
{ 6, 0, 6001}, // Windows Vista with Service Pack 1 or Windows Server 2008
|
||||||
|
{ 6, 0, 6002}, // Windows Vista with Service Pack 2
|
||||||
|
{ 6, 1, 7600}, // Windows 7 or Windows Server 2008 R2
|
||||||
|
{ 6, 1, 7601}, // Windows 7 with Service Pack 1 or Windows Server 2008 R2 with Service Pack 1
|
||||||
|
{ 6, 2, 9200}, // Windows 8 or Windows Server 2012
|
||||||
|
{ 6, 3, 9200}, // Windows 8.1 or Windows Server 2012 R2
|
||||||
|
{ 6, 3, 9600}, // Windows 8.1 with Update 1
|
||||||
|
{10, 0, 10240}, // Windows 10 Version 1507 (TH1)
|
||||||
|
{10, 0, 10586}, // Windows 10 Version 1511 (November Update) (TH2)
|
||||||
|
{10, 0, 14393}, // Windows 10 Version 1607 (Anniversary Update) (RS1) or Windows Server 2016
|
||||||
|
{10, 0, 15063}, // Windows 10 Version 1703 (Creators Update) (RS2)
|
||||||
|
{10, 0, 16299}, // Windows 10 Version 1709 (Fall Creators Update) (RS3)
|
||||||
|
{10, 0, 17134}, // Windows 10 Version 1803 (April 2018 Update) (RS4)
|
||||||
|
{10, 0, 17763}, // Windows 10 Version 1809 (October 2018 Update) (RS5) or Windows Server 2019
|
||||||
|
{10, 0, 18362}, // Windows 10 Version 1903 (May 2019 Update) (19H1)
|
||||||
|
{10, 0, 18363}, // Windows 10 Version 1909 (November 2019 Update) (19H2)
|
||||||
|
{10, 0, 19041}, // Windows 10 Version 2004 (May 2020 Update) (20H1)
|
||||||
|
{10, 0, 19042}, // Windows 10 Version 20H2 (October 2020 Update) (20H2)
|
||||||
|
{10, 0, 19043}, // Windows 10 Version 21H1 (May 2021 Update) (21H1)
|
||||||
|
{10, 0, 19044}, // Windows 10 Version 21H2 (November 2021 Update) (21H2)
|
||||||
|
{10, 0, 19045}, // Windows 10 Version 22H2 (October 2022 Update) (22H2)
|
||||||
|
{10, 0, 22000}, // Windows 11 Version 21H2 (21H2)
|
||||||
|
{10, 0, 22621} // Windows 11 Version 22H2 (October 2022 Update) (22H2)
|
||||||
|
};
|
||||||
|
#endif // Q_OS_WINDOWS
|
||||||
|
|
||||||
} // namespace Global
|
} // namespace Global
|
||||||
|
|
||||||
namespace FramelessHelper::Core
|
namespace FramelessHelper::Core
|
||||||
|
@ -633,3 +639,10 @@ FRAMELESSHELPER_END_NAMESPACE
|
||||||
Q_DECLARE_METATYPE(FRAMELESSHELPER_PREPEND_NAMESPACE(Global)::VersionNumber)
|
Q_DECLARE_METATYPE(FRAMELESSHELPER_PREPEND_NAMESPACE(Global)::VersionNumber)
|
||||||
Q_DECLARE_METATYPE(FRAMELESSHELPER_PREPEND_NAMESPACE(Global)::SystemParameters)
|
Q_DECLARE_METATYPE(FRAMELESSHELPER_PREPEND_NAMESPACE(Global)::SystemParameters)
|
||||||
Q_DECLARE_METATYPE(FRAMELESSHELPER_PREPEND_NAMESPACE(Global)::VersionInfo)
|
Q_DECLARE_METATYPE(FRAMELESSHELPER_PREPEND_NAMESPACE(Global)::VersionInfo)
|
||||||
|
Q_DECLARE_METATYPE(FRAMELESSHELPER_PREPEND_NAMESPACE(Global)::Dpi);
|
||||||
|
|
||||||
|
#ifndef QT_NO_DEBUG_STREAM
|
||||||
|
FRAMELESSHELPER_CORE_API QDebug operator<<(QDebug, const FRAMELESSHELPER_PREPEND_NAMESPACE(Global)::VersionNumber &);
|
||||||
|
FRAMELESSHELPER_CORE_API QDebug operator<<(QDebug, const FRAMELESSHELPER_PREPEND_NAMESPACE(Global)::VersionInfo &);
|
||||||
|
FRAMELESSHELPER_CORE_API QDebug operator<<(QDebug, const FRAMELESSHELPER_PREPEND_NAMESPACE(Global)::Dpi &);
|
||||||
|
#endif // QT_NO_DEBUG_STREAM
|
||||||
|
|
|
@ -92,7 +92,7 @@ FRAMELESSHELPER_CORE_API void showSystemMenu(
|
||||||
[[nodiscard]] FRAMELESSHELPER_CORE_API quint32 getResizeBorderThickness(const WId windowId,
|
[[nodiscard]] FRAMELESSHELPER_CORE_API quint32 getResizeBorderThickness(const WId windowId,
|
||||||
const bool horizontal,
|
const bool horizontal,
|
||||||
const bool scaled);
|
const bool scaled);
|
||||||
[[nodiscard]] FRAMELESSHELPER_CORE_API quint32 getCaptionHeight(const WId windowId, const bool scaled);
|
[[nodiscard]] FRAMELESSHELPER_CORE_API quint32 getCaptionBarHeight(const WId windowId, const bool scaled);
|
||||||
[[nodiscard]] FRAMELESSHELPER_CORE_API quint32 getTitleBarHeight(const WId windowId, const bool scaled);
|
[[nodiscard]] FRAMELESSHELPER_CORE_API quint32 getTitleBarHeight(const WId windowId, const bool scaled);
|
||||||
[[nodiscard]] FRAMELESSHELPER_CORE_API quint32 getFrameBorderThickness(const WId windowId,
|
[[nodiscard]] FRAMELESSHELPER_CORE_API quint32 getFrameBorderThickness(const WId windowId,
|
||||||
const bool scaled);
|
const bool scaled);
|
||||||
|
|
|
@ -531,8 +531,8 @@ void FramelessHelperWin::addWindow(const SystemParameters ¶ms)
|
||||||
qApp->installNativeEventFilter(g_win32Helper()->nativeEventFilter.data());
|
qApp->installNativeEventFilter(g_win32Helper()->nativeEventFilter.data());
|
||||||
}
|
}
|
||||||
g_win32Helper()->mutex.unlock();
|
g_win32Helper()->mutex.unlock();
|
||||||
DEBUG.nospace().noquote() << "The DPI of window " << hwnd2str(windowId) << " is: QDpi("
|
const Dpi dpi = {Utils::getWindowDpi(windowId, true), Utils::getWindowDpi(windowId, false)};
|
||||||
<< Utils::getWindowDpi(windowId, true) << ", " << Utils::getWindowDpi(windowId, false) << ").";
|
DEBUG.noquote() << "The DPI of window" << hwnd2str(windowId) << "is" << dpi;
|
||||||
// Some Qt internals have to be corrected.
|
// Some Qt internals have to be corrected.
|
||||||
Utils::maybeFixupQtInternals(windowId);
|
Utils::maybeFixupQtInternals(windowId);
|
||||||
// Qt maintains a frame margin internally, we need to update it accordingly
|
// Qt maintains a frame margin internally, we need to update it accordingly
|
||||||
|
@ -1122,22 +1122,30 @@ bool FramelessHelperWin::nativeEventFilter(const QByteArray &eventType, void *me
|
||||||
} break;
|
} break;
|
||||||
#endif
|
#endif
|
||||||
case WM_DPICHANGED: {
|
case WM_DPICHANGED: {
|
||||||
const UINT dpiX = LOWORD(wParam);
|
const Dpi dpi = {UINT(LOWORD(wParam)), UINT(HIWORD(wParam))};
|
||||||
const UINT dpiY = HIWORD(wParam);
|
DEBUG.noquote() << "New DPI for window" << hwnd2str(hWnd) << "is" << dpi;
|
||||||
DEBUG.nospace().noquote() << "New DPI for window "
|
|
||||||
<< hwnd2str(hWnd) << ": QDpi(" << dpiX << ", " << dpiY << ").";
|
|
||||||
// Sync the internal window frame margins with the latest DPI.
|
// Sync the internal window frame margins with the latest DPI.
|
||||||
Utils::updateInternalWindowFrameMargins(data.params.getWindowHandle(), true);
|
Utils::updateInternalWindowFrameMargins(data.params.getWindowHandle(), true);
|
||||||
// Here we need a little delay because event filters are processed before
|
// Here we need a little delay because event filters are processed before
|
||||||
// Qt's own window message handlers.
|
// Qt's own window message handlers.
|
||||||
QTimer::singleShot(50, [data](){ // Copy "data" intentionally, otherwise it'll go out of scope when Qt finally use it.
|
QTimer::singleShot(0, qApp, [data, windowId](){ // Copy the variables intentionally, otherwise they'll go out of scope when Qt finally use it.
|
||||||
// For some unknown reason, Qt sometimes won't re-paint the window contents after
|
// For some unknown reason, Qt sometimes won't re-paint the window contents after
|
||||||
// the DPI changes, and in my experiments the controls should be moved to our
|
// the DPI changes, and in my experiments the controls should be moved to our
|
||||||
// desired geometry already, the only issue is we don't get the updated appearance
|
// desired geometry already, the only issue is we don't get the updated appearance
|
||||||
// of our window. And we can workaround this issue by simply triggering a resize
|
// of our window. And we can workaround this issue by simply triggering a resize
|
||||||
// event manually. There's no need to increase/decrease the window size and then
|
// event manually.
|
||||||
// change it back, just give Qt our current window size is sufficient enough.
|
// For some reason the window will always expand for some pixels after the DPI
|
||||||
data.params.setWindowSize(data.params.getWindowSize());
|
// changes, and normal Qt windows don't have this issue. It's probably caused
|
||||||
|
// by the custom margins we set, QPA may calculate a wrong frame size. It will
|
||||||
|
// always add a title bar height to the window, while it should not due to we
|
||||||
|
// have hide the title bar. For now we can simply workaround it by restoring
|
||||||
|
// to the original window size after the DPI change, but it's not ideal. Maybe
|
||||||
|
// we should reset the custom margins first and then restore it instead, but
|
||||||
|
// sadly this solution doesn't work as expected. Still need investigating.
|
||||||
|
const int titleBarHeight = Utils::getTitleBarHeight(windowId, false);
|
||||||
|
const QSize expandedSize = data.params.getWindowSize();
|
||||||
|
const QSize correctedSize = {expandedSize.width(), expandedSize.height() - titleBarHeight};
|
||||||
|
data.params.setWindowSize(correctedSize);
|
||||||
});
|
});
|
||||||
} break;
|
} break;
|
||||||
case WM_DWMCOMPOSITIONCHANGED: {
|
case WM_DWMCOMPOSITIONCHANGED: {
|
||||||
|
|
|
@ -46,7 +46,7 @@
|
||||||
#endif
|
#endif
|
||||||
#include <QtCore/qmutex.h>
|
#include <QtCore/qmutex.h>
|
||||||
#include <QtCore/qiodevice.h>
|
#include <QtCore/qiodevice.h>
|
||||||
#include <QtGui/qguiapplication.h>
|
#include <QtCore/qcoreapplication.h>
|
||||||
|
|
||||||
#ifndef COMPILER_STRING
|
#ifndef COMPILER_STRING
|
||||||
# ifdef Q_CC_CLANG // Must be before GNU, because Clang claims to be GNU too.
|
# ifdef Q_CC_CLANG // Must be before GNU, because Clang claims to be GNU too.
|
||||||
|
@ -72,6 +72,46 @@
|
||||||
# endif
|
# endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifndef QT_NO_DEBUG_STREAM
|
||||||
|
QDebug operator<<(QDebug d, const FRAMELESSHELPER_PREPEND_NAMESPACE(Global)::VersionNumber &ver)
|
||||||
|
{
|
||||||
|
const QDebugStateSaver saver(d);
|
||||||
|
d.nospace().noquote() << "VersionNumber("
|
||||||
|
<< ver.major << ", "
|
||||||
|
<< ver.minor << ", "
|
||||||
|
<< ver.patch << ", "
|
||||||
|
<< ver.tweak << ')';
|
||||||
|
return d;
|
||||||
|
}
|
||||||
|
|
||||||
|
QDebug operator<<(QDebug d, const FRAMELESSHELPER_PREPEND_NAMESPACE(Global)::VersionInfo &ver)
|
||||||
|
{
|
||||||
|
const QDebugStateSaver saver(d);
|
||||||
|
int major = 0, minor = 0, patch = 0, tweak = 0;
|
||||||
|
FRAMELESSHELPER_EXTRACT_VERSION(ver.version, major, minor, patch, tweak)
|
||||||
|
const auto ver_num = FRAMELESSHELPER_PREPEND_NAMESPACE(Global)::VersionNumber{major, minor, patch, tweak};
|
||||||
|
d.nospace().noquote() << "VersionInfo("
|
||||||
|
<< "version number: " << ver_num << ", "
|
||||||
|
<< "version string: " << ver.version_str << ", "
|
||||||
|
<< "commit hash: " << ver.commit << ", "
|
||||||
|
<< "compiler: " << ver.compiler << ", "
|
||||||
|
<< "debug build: " << ver.isDebug << ", "
|
||||||
|
<< "static build: " << ver.isStatic << ')';
|
||||||
|
return d;
|
||||||
|
}
|
||||||
|
|
||||||
|
QDebug operator<<(QDebug d, const FRAMELESSHELPER_PREPEND_NAMESPACE(Global)::Dpi &dpi)
|
||||||
|
{
|
||||||
|
const QDebugStateSaver saver(d);
|
||||||
|
const qreal scaleFactor = (qreal(dpi.x) / qreal(96));
|
||||||
|
d.nospace().noquote() << "Dpi("
|
||||||
|
<< "x: " << dpi.x << ", "
|
||||||
|
<< "y: " << dpi.y << ", "
|
||||||
|
<< "scale factor: " << scaleFactor << ')';
|
||||||
|
return d;
|
||||||
|
}
|
||||||
|
#endif // QT_NO_DEBUG_STREAM
|
||||||
|
|
||||||
FRAMELESSHELPER_BEGIN_NAMESPACE
|
FRAMELESSHELPER_BEGIN_NAMESPACE
|
||||||
|
|
||||||
Q_LOGGING_CATEGORY(lcCoreGlobal, "wangwenx190.framelesshelper.core.global")
|
Q_LOGGING_CATEGORY(lcCoreGlobal, "wangwenx190.framelesshelper.core.global")
|
||||||
|
@ -172,15 +212,6 @@ void initialize()
|
||||||
QCoreApplication::setAttribute(Qt::AA_UseHighDpiPixmaps);
|
QCoreApplication::setAttribute(Qt::AA_UseHighDpiPixmaps);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if (QT_VERSION >= QT_VERSION_CHECK(5, 14, 0))
|
|
||||||
// Non-integer scale factors will cause Qt have some painting defects
|
|
||||||
// for both Qt Widgets and Qt Quick applications, and it's still not
|
|
||||||
// totally fixed till now (Qt 6.5), so we round the scale factors to
|
|
||||||
// get a better looking. Non-integer scale factors will also cause
|
|
||||||
// flicker and jitter during window resizing.
|
|
||||||
QGuiApplication::setHighDpiScaleFactorRoundingPolicy(Qt::HighDpiScaleFactorRoundingPolicy::Round);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
qRegisterMetaType<Option>();
|
qRegisterMetaType<Option>();
|
||||||
qRegisterMetaType<SystemTheme>();
|
qRegisterMetaType<SystemTheme>();
|
||||||
qRegisterMetaType<SystemButtonType>();
|
qRegisterMetaType<SystemButtonType>();
|
||||||
|
@ -206,6 +237,7 @@ void initialize()
|
||||||
qRegisterMetaType<VersionNumber>();
|
qRegisterMetaType<VersionNumber>();
|
||||||
qRegisterMetaType<SystemParameters>();
|
qRegisterMetaType<SystemParameters>();
|
||||||
qRegisterMetaType<VersionInfo>();
|
qRegisterMetaType<VersionInfo>();
|
||||||
|
qRegisterMetaType<Dpi>();
|
||||||
#if (QT_VERSION >= QT_VERSION_CHECK(6, 0, 0))
|
#if (QT_VERSION >= QT_VERSION_CHECK(6, 0, 0))
|
||||||
qRegisterMetaType<FramelessManager>();
|
qRegisterMetaType<FramelessManager>();
|
||||||
# ifdef Q_OS_WINDOWS
|
# ifdef Q_OS_WINDOWS
|
||||||
|
|
|
@ -220,7 +220,7 @@ void FramelessManagerPrivate::addWindow(const SystemParameters ¶ms)
|
||||||
Q_UNUSED(screen);
|
Q_UNUSED(screen);
|
||||||
// Add a little delay here, make sure it happens after Qt has processed the window
|
// Add a little delay here, make sure it happens after Qt has processed the window
|
||||||
// messages.
|
// messages.
|
||||||
QTimer::singleShot(50, window, [windowId, window](){
|
QTimer::singleShot(0, window, [windowId, window](){
|
||||||
// Force a WM_NCCALCSIZE event to inform Windows about our custom window frame,
|
// Force a WM_NCCALCSIZE event to inform Windows about our custom window frame,
|
||||||
// this is only necessary when the window is being moved cross monitors.
|
// this is only necessary when the window is being moved cross monitors.
|
||||||
Utils::triggerFrameChange(windowId);
|
Utils::triggerFrameChange(windowId);
|
||||||
|
|
|
@ -1735,7 +1735,7 @@ quint32 Utils::getResizeBorderThickness(const WId windowId, const bool horizonta
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
quint32 Utils::getCaptionHeight(const WId windowId, const bool scaled)
|
quint32 Utils::getCaptionBarHeight(const WId windowId, const bool scaled)
|
||||||
{
|
{
|
||||||
Q_ASSERT(windowId);
|
Q_ASSERT(windowId);
|
||||||
if (!windowId) {
|
if (!windowId) {
|
||||||
|
@ -1750,7 +1750,7 @@ quint32 Utils::getTitleBarHeight(const WId windowId, const bool scaled)
|
||||||
if (!windowId) {
|
if (!windowId) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
return (getCaptionHeight(windowId, scaled) + getResizeBorderThickness(windowId, false, scaled));
|
return (getCaptionBarHeight(windowId, scaled) + getResizeBorderThickness(windowId, false, scaled));
|
||||||
}
|
}
|
||||||
|
|
||||||
quint32 Utils::getFrameBorderThickness(const WId windowId, const bool scaled)
|
quint32 Utils::getFrameBorderThickness(const WId windowId, const bool scaled)
|
||||||
|
|
Loading…
Reference in New Issue