win32: fix restore geometry bug
The upstream fix has not been merged yet, however, it will be in 6.5.1 for sure. Fixes: #20 Signed-off-by: Yuhang Zhao <2546789017@qq.com>
This commit is contained in:
parent
8930ea128f
commit
a203e2c3ca
|
@ -161,10 +161,10 @@ if(NOT FRAMELESSHELPER_NO_SUMMARY)
|
||||||
message("Toolchain file: ${CMAKE_TOOLCHAIN_FILE}")
|
message("Toolchain file: ${CMAKE_TOOLCHAIN_FILE}")
|
||||||
message("------------------------------ Qt -------------------------------")
|
message("------------------------------ Qt -------------------------------")
|
||||||
query_qt_paths(SDK_DIR __qt_inst_dir)
|
query_qt_paths(SDK_DIR __qt_inst_dir)
|
||||||
|
query_qt_library_info(VERSION __qt_version STATIC __qt_static_lib)
|
||||||
message("Qt SDK installation directory: ${__qt_inst_dir}")
|
message("Qt SDK installation directory: ${__qt_inst_dir}")
|
||||||
message("Qt SDK version: ${QT_VERSION}")
|
message("Qt SDK version: ${__qt_version}")
|
||||||
query_qt_library_info(STATIC __qt_lib_type)
|
if(__qt_static_lib)
|
||||||
if(__qt_lib_type)
|
|
||||||
message("Qt SDK library type: static")
|
message("Qt SDK library type: static")
|
||||||
else()
|
else()
|
||||||
message("Qt SDK library type: shared")
|
message("Qt SDK library type: shared")
|
||||||
|
|
2
cmake
2
cmake
|
@ -1 +1 @@
|
||||||
Subproject commit 60329b55dcfaf41da63f134a90ddce82dc9b6c4a
|
Subproject commit be821fca7e90858343540a487d663dca52bf0cd5
|
|
@ -135,6 +135,8 @@ FRAMELESSHELPER_CORE_API void fixupChildWindowsDpiMessage(const WId windowId);
|
||||||
FRAMELESSHELPER_CORE_API void fixupDialogsDpiScaling();
|
FRAMELESSHELPER_CORE_API void fixupDialogsDpiScaling();
|
||||||
FRAMELESSHELPER_CORE_API void setDarkModeAllowedForApp(const bool allow = true);
|
FRAMELESSHELPER_CORE_API void setDarkModeAllowedForApp(const bool allow = true);
|
||||||
FRAMELESSHELPER_CORE_API void bringWindowToFront(const WId windowId);
|
FRAMELESSHELPER_CORE_API void bringWindowToFront(const WId windowId);
|
||||||
|
[[nodiscard]] FRAMELESSHELPER_CORE_API QPoint getWindowPlacementOffset(const WId windowId);
|
||||||
|
[[nodiscard]] FRAMELESSHELPER_CORE_API QRect getWindowRestoreFrameGeometry(const WId windowId);
|
||||||
#endif // Q_OS_WINDOWS
|
#endif // Q_OS_WINDOWS
|
||||||
|
|
||||||
#ifdef Q_OS_LINUX
|
#ifdef Q_OS_LINUX
|
||||||
|
|
|
@ -84,6 +84,8 @@ FRAMELESSHELPER_STRING_CONSTANT(TrackMouseEvent)
|
||||||
FRAMELESSHELPER_STRING_CONSTANT(FindWindowW)
|
FRAMELESSHELPER_STRING_CONSTANT(FindWindowW)
|
||||||
FRAMELESSHELPER_STRING_CONSTANT(UnregisterClassW)
|
FRAMELESSHELPER_STRING_CONSTANT(UnregisterClassW)
|
||||||
FRAMELESSHELPER_STRING_CONSTANT(DestroyWindow)
|
FRAMELESSHELPER_STRING_CONSTANT(DestroyWindow)
|
||||||
|
FRAMELESSHELPER_STRING_CONSTANT(GetWindowPlacement)
|
||||||
|
FRAMELESSHELPER_STRING_CONSTANT(SetWindowPlacement)
|
||||||
[[maybe_unused]] static constexpr const char kFallbackTitleBarErrorMessage[] =
|
[[maybe_unused]] static constexpr const char kFallbackTitleBarErrorMessage[] =
|
||||||
"FramelessHelper is unable to create the fallback title bar window, and thus the snap layout feature will be disabled"
|
"FramelessHelper is unable to create the fallback title bar window, and thus the snap layout feature will be disabled"
|
||||||
" unconditionally. You can ignore this error and continue running your application, nothing else will be affected, "
|
" unconditionally. You can ignore this error and continue running your application, nothing else will be affected, "
|
||||||
|
@ -98,6 +100,7 @@ struct Win32HelperData
|
||||||
bool trackingMouse = false;
|
bool trackingMouse = false;
|
||||||
WId fallbackTitleBarWindowId = 0;
|
WId fallbackTitleBarWindowId = 0;
|
||||||
Dpi dpi = {};
|
Dpi dpi = {};
|
||||||
|
QRect restoreGeometry = {};
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Win32Helper
|
struct Win32Helper
|
||||||
|
@ -1184,10 +1187,11 @@ bool FramelessHelperWin::nativeEventFilter(const QByteArray &eventType, void *me
|
||||||
#if (QT_VERSION <= QT_VERSION_CHECK(6, 4, 2))
|
#if (QT_VERSION <= QT_VERSION_CHECK(6, 4, 2))
|
||||||
// We need to wait until Qt has handled this message, otherwise everything
|
// We need to wait until Qt has handled this message, otherwise everything
|
||||||
// we have done here will always be overwritten.
|
// we have done here will always be overwritten.
|
||||||
QTimer::singleShot(0, qApp, [data](){ // Copy the variables intentionally, otherwise they'll go out of scope when Qt finally use them.
|
QWindow *window = data.params.getWindowHandle();
|
||||||
|
QTimer::singleShot(0, qApp, [window](){
|
||||||
// Sync the internal window frame margins with the latest DPI, otherwise
|
// Sync the internal window frame margins with the latest DPI, otherwise
|
||||||
// we will get wrong window sizes after the DPI change.
|
// we will get wrong window sizes after the DPI change.
|
||||||
Utils::updateInternalWindowFrameMargins(data.params.getWindowHandle(), true);
|
Utils::updateInternalWindowFrameMargins(window, true);
|
||||||
});
|
});
|
||||||
#endif // (QT_VERSION <= QT_VERSION_CHECK(6, 4, 2))
|
#endif // (QT_VERSION <= QT_VERSION_CHECK(6, 4, 2))
|
||||||
} break;
|
} break;
|
||||||
|
@ -1195,6 +1199,50 @@ bool FramelessHelperWin::nativeEventFilter(const QByteArray &eventType, void *me
|
||||||
// Re-apply the custom window frame if recovered from the basic theme.
|
// Re-apply the custom window frame if recovered from the basic theme.
|
||||||
Utils::updateWindowFrameMargins(windowId, false);
|
Utils::updateWindowFrameMargins(windowId, false);
|
||||||
} break;
|
} break;
|
||||||
|
#if (QT_VERSION < QT_VERSION_CHECK(6, 5, 1))
|
||||||
|
case WM_ENTERSIZEMOVE:
|
||||||
|
case WM_EXITSIZEMOVE: {
|
||||||
|
if (!Utils::isWindowNoState(windowId)) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
const QRect rect = Utils::getWindowRestoreFrameGeometry(windowId);
|
||||||
|
if (rect.isNull() || !rect.isValid()) {
|
||||||
|
WARNING << "The calculated restore geometry is invalid.";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
const QMutexLocker locker(&g_win32Helper()->mutex);
|
||||||
|
g_win32Helper()->data[windowId].restoreGeometry = rect;
|
||||||
|
} break;
|
||||||
|
case WM_SIZE: {
|
||||||
|
if (wParam != SIZE_MAXIMIZED) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (data.restoreGeometry.isNull() || !data.restoreGeometry.isValid()) {
|
||||||
|
const QRect rect = Utils::getWindowRestoreFrameGeometry(windowId);
|
||||||
|
if (rect.isValid() && !rect.isNull()) {
|
||||||
|
const QMutexLocker locker(&g_win32Helper()->mutex);
|
||||||
|
g_win32Helper()->data[windowId].restoreGeometry = rect;
|
||||||
|
} else {
|
||||||
|
WARNING << "The calculated restore geometry is invalid.";
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
WINDOWPLACEMENT wp;
|
||||||
|
SecureZeroMemory(&wp, sizeof(wp));
|
||||||
|
wp.length = sizeof(wp);
|
||||||
|
if (GetWindowPlacement(hWnd, &wp) == FALSE) {
|
||||||
|
WARNING << Utils::getSystemErrorMessage(kGetWindowPlacement);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
wp.rcNormalPosition = {
|
||||||
|
data.restoreGeometry.left(), data.restoreGeometry.top(),
|
||||||
|
data.restoreGeometry.right(), data.restoreGeometry.bottom()
|
||||||
|
};
|
||||||
|
if (SetWindowPlacement(hWnd, &wp) == FALSE) {
|
||||||
|
WARNING << Utils::getSystemErrorMessage(kSetWindowPlacement);
|
||||||
|
}
|
||||||
|
} break;
|
||||||
|
#endif // (QT_VERSION < QT_VERSION_CHECK(6, 5, 1))
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
|
@ -2390,4 +2390,57 @@ void Utils::bringWindowToFront(const WId windowId)
|
||||||
moveWindowToMonitor(hwnd, activeMonitor.value());
|
moveWindowToMonitor(hwnd, activeMonitor.value());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QPoint Utils::getWindowPlacementOffset(const WId windowId)
|
||||||
|
{
|
||||||
|
Q_ASSERT(windowId);
|
||||||
|
if (!windowId) {
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
const auto hwnd = reinterpret_cast<HWND>(windowId);
|
||||||
|
SetLastError(ERROR_SUCCESS);
|
||||||
|
const auto exStyle = static_cast<DWORD>(GetWindowLongPtrW(hwnd, GWL_EXSTYLE));
|
||||||
|
if (exStyle == 0) {
|
||||||
|
WARNING << getSystemErrorMessage(kGetWindowLongPtrW);
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
// Tool windows are special and they don't need any offset.
|
||||||
|
if (exStyle & WS_EX_TOOLWINDOW) {
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
const HMONITOR mon = MonitorFromWindow(hwnd, MONITOR_DEFAULTTOPRIMARY);
|
||||||
|
if (!mon) {
|
||||||
|
WARNING << getSystemErrorMessage(kMonitorFromWindow);
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
MONITORINFOEXW mi;
|
||||||
|
SecureZeroMemory(&mi, sizeof(mi));
|
||||||
|
mi.cbSize = sizeof(mi);
|
||||||
|
if (GetMonitorInfoW(mon, &mi) == FALSE) {
|
||||||
|
WARNING << getSystemErrorMessage(kGetMonitorInfoW);
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
return {mi.rcWork.left - mi.rcMonitor.left, mi.rcWork.top - mi.rcMonitor.top};
|
||||||
|
}
|
||||||
|
|
||||||
|
QRect Utils::getWindowRestoreFrameGeometry(const WId windowId)
|
||||||
|
{
|
||||||
|
Q_ASSERT(windowId);
|
||||||
|
if (!windowId) {
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
const auto hwnd = reinterpret_cast<HWND>(windowId);
|
||||||
|
WINDOWPLACEMENT wp;
|
||||||
|
SecureZeroMemory(&wp, sizeof(wp));
|
||||||
|
wp.length = sizeof(wp);
|
||||||
|
if (GetWindowPlacement(hwnd, &wp) == FALSE) {
|
||||||
|
WARNING << getSystemErrorMessage(kGetWindowPlacement);
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
const RECT rawRect = wp.rcNormalPosition;
|
||||||
|
const QPoint topLeft = {rawRect.left, rawRect.top};
|
||||||
|
const QSize size = {rawRect.right - rawRect.left, rawRect.bottom - rawRect.top};
|
||||||
|
const QPoint offset = getWindowPlacementOffset(windowId);
|
||||||
|
return QRect{topLeft, size}.translated(offset);
|
||||||
|
}
|
||||||
|
|
||||||
FRAMELESSHELPER_END_NAMESPACE
|
FRAMELESSHELPER_END_NAMESPACE
|
||||||
|
|
Loading…
Reference in New Issue