forked from github_mirror/framelesshelper
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
|
||||
{
|
||||
int major = 0;
|
||||
int minor = 0;
|
||||
int patch = 0;
|
||||
int tweak = 0;
|
||||
const int major = 0;
|
||||
const int minor = 0;
|
||||
const int patch = 0;
|
||||
const int tweak = 0;
|
||||
|
||||
[[nodiscard]] friend constexpr bool operator==(const VersionNumber &lhs, const VersionNumber &rhs) noexcept
|
||||
{
|
||||
|
@ -571,6 +571,23 @@ struct SystemParameters
|
|||
}
|
||||
};
|
||||
|
||||
struct VersionInfo
|
||||
{
|
||||
const int version = 0;
|
||||
const char *version_str = nullptr;
|
||||
const char *commit = nullptr;
|
||||
const char *compileDateTime = nullptr;
|
||||
const char *compiler = nullptr;
|
||||
const bool isDebug = 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[] =
|
||||
{
|
||||
|
@ -604,17 +621,6 @@ struct SystemParameters
|
|||
};
|
||||
#endif // Q_OS_WINDOWS
|
||||
|
||||
struct VersionInfo
|
||||
{
|
||||
const int version = 0;
|
||||
const char *version_str = nullptr;
|
||||
const char *commit = nullptr;
|
||||
const char *compileDateTime = nullptr;
|
||||
const char *compiler = nullptr;
|
||||
const bool isDebug = false;
|
||||
const bool isStatic = false;
|
||||
};
|
||||
|
||||
} // namespace Global
|
||||
|
||||
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)::SystemParameters)
|
||||
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,
|
||||
const bool horizontal,
|
||||
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 getFrameBorderThickness(const WId windowId,
|
||||
const bool scaled);
|
||||
|
|
|
@ -531,8 +531,8 @@ void FramelessHelperWin::addWindow(const SystemParameters ¶ms)
|
|||
qApp->installNativeEventFilter(g_win32Helper()->nativeEventFilter.data());
|
||||
}
|
||||
g_win32Helper()->mutex.unlock();
|
||||
DEBUG.nospace().noquote() << "The DPI of window " << hwnd2str(windowId) << " is: QDpi("
|
||||
<< Utils::getWindowDpi(windowId, true) << ", " << Utils::getWindowDpi(windowId, false) << ").";
|
||||
const Dpi dpi = {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.
|
||||
Utils::maybeFixupQtInternals(windowId);
|
||||
// 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;
|
||||
#endif
|
||||
case WM_DPICHANGED: {
|
||||
const UINT dpiX = LOWORD(wParam);
|
||||
const UINT dpiY = HIWORD(wParam);
|
||||
DEBUG.nospace().noquote() << "New DPI for window "
|
||||
<< hwnd2str(hWnd) << ": QDpi(" << dpiX << ", " << dpiY << ").";
|
||||
const Dpi dpi = {UINT(LOWORD(wParam)), UINT(HIWORD(wParam))};
|
||||
DEBUG.noquote() << "New DPI for window" << hwnd2str(hWnd) << "is" << dpi;
|
||||
// Sync the internal window frame margins with the latest DPI.
|
||||
Utils::updateInternalWindowFrameMargins(data.params.getWindowHandle(), true);
|
||||
// Here we need a little delay because event filters are processed before
|
||||
// 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
|
||||
// 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
|
||||
// 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
|
||||
// change it back, just give Qt our current window size is sufficient enough.
|
||||
data.params.setWindowSize(data.params.getWindowSize());
|
||||
// event manually.
|
||||
// For some reason the window will always expand for some pixels after the DPI
|
||||
// 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;
|
||||
case WM_DWMCOMPOSITIONCHANGED: {
|
||||
|
|
|
@ -46,7 +46,7 @@
|
|||
#endif
|
||||
#include <QtCore/qmutex.h>
|
||||
#include <QtCore/qiodevice.h>
|
||||
#include <QtGui/qguiapplication.h>
|
||||
#include <QtCore/qcoreapplication.h>
|
||||
|
||||
#ifndef COMPILER_STRING
|
||||
# ifdef Q_CC_CLANG // Must be before GNU, because Clang claims to be GNU too.
|
||||
|
@ -72,6 +72,46 @@
|
|||
# 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
|
||||
|
||||
Q_LOGGING_CATEGORY(lcCoreGlobal, "wangwenx190.framelesshelper.core.global")
|
||||
|
@ -172,15 +212,6 @@ void initialize()
|
|||
QCoreApplication::setAttribute(Qt::AA_UseHighDpiPixmaps);
|
||||
#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<SystemTheme>();
|
||||
qRegisterMetaType<SystemButtonType>();
|
||||
|
@ -206,6 +237,7 @@ void initialize()
|
|||
qRegisterMetaType<VersionNumber>();
|
||||
qRegisterMetaType<SystemParameters>();
|
||||
qRegisterMetaType<VersionInfo>();
|
||||
qRegisterMetaType<Dpi>();
|
||||
#if (QT_VERSION >= QT_VERSION_CHECK(6, 0, 0))
|
||||
qRegisterMetaType<FramelessManager>();
|
||||
# ifdef Q_OS_WINDOWS
|
||||
|
|
|
@ -220,7 +220,7 @@ void FramelessManagerPrivate::addWindow(const SystemParameters ¶ms)
|
|||
Q_UNUSED(screen);
|
||||
// Add a little delay here, make sure it happens after Qt has processed the window
|
||||
// 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,
|
||||
// this is only necessary when the window is being moved cross monitors.
|
||||
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);
|
||||
if (!windowId) {
|
||||
|
@ -1750,7 +1750,7 @@ quint32 Utils::getTitleBarHeight(const WId windowId, const bool scaled)
|
|||
if (!windowId) {
|
||||
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)
|
||||
|
|
Loading…
Reference in New Issue