Windows QPA: Fix restore geometry after dragging from maximised

Start tracking the window geometry before a mouse drag, so that we can
revert back to that geometry when we restore from maximised. Previously,
when dragging from maximised to maximised, the restore geometry would
end up being the final drag place before snapping to maximised, instead
of where the window was before the first maximised.

Fixes: QTBUG-112814
Pick-to: 6.5 6.2
Change-Id: Ic2ddf29d6c4abdc9e8b0c5161b17aa6ee9474ea3
Reviewed-by: Oliver Wolff <oliver.wolff@qt.io>
This commit is contained in:
Timothée Keller 2023-04-18 16:00:04 +02:00
parent eec5a016d3
commit 21e4116874
3 changed files with 26 additions and 0 deletions

View File

@ -1219,11 +1219,15 @@ bool QWindowsContext::windowsProc(HWND hwnd, UINT message,
break; break;
case QtWindows::EnterSizeMoveEvent: case QtWindows::EnterSizeMoveEvent:
platformWindow->setFlag(QWindowsWindow::ResizeMoveActive); platformWindow->setFlag(QWindowsWindow::ResizeMoveActive);
if (!IsZoomed(hwnd))
platformWindow->updateRestoreGeometry();
return true; return true;
case QtWindows::ExitSizeMoveEvent: case QtWindows::ExitSizeMoveEvent:
platformWindow->clearFlag(QWindowsWindow::ResizeMoveActive); platformWindow->clearFlag(QWindowsWindow::ResizeMoveActive);
platformWindow->checkForScreenChanged(); platformWindow->checkForScreenChanged();
handleExitSizeMove(platformWindow->window()); handleExitSizeMove(platformWindow->window());
if (!IsZoomed(hwnd))
platformWindow->updateRestoreGeometry();
return true; return true;
case QtWindows::ScrollEvent: case QtWindows::ScrollEvent:
if (!(d->m_systemInfo & QWindowsContext::SI_SupportsPointer)) if (!(d->m_systemInfo & QWindowsContext::SI_SupportsPointer))

View File

@ -932,6 +932,7 @@ QWindowsWindowData
QRect obtainedGeometry(context->obtainedPos, context->obtainedSize); QRect obtainedGeometry(context->obtainedPos, context->obtainedSize);
result.geometry = obtainedGeometry; result.geometry = obtainedGeometry;
result.restoreGeometry = frameGeometry(result.hwnd, topLevel);
result.fullFrameMargins = context->margins; result.fullFrameMargins = context->margins;
result.embedded = embedded; result.embedded = embedded;
result.hasFrame = hasFrame; result.hasFrame = hasFrame;
@ -1972,6 +1973,11 @@ void QWindowsWindow::handleDpiScaledSize(WPARAM wParam, LPARAM lParam, LRESULT *
// are currently doing. // are currently doing.
m_data.customMargins *= scale; m_data.customMargins *= scale;
} }
if (!m_data.restoreGeometry.isEmpty()) {
m_data.restoreGeometry.setWidth(m_data.restoreGeometry.width() * scale);
m_data.restoreGeometry.setHeight(m_data.restoreGeometry.height() * scale);
}
const QSize windowSize = (geometry().size() * scale).grownBy(margins + customMargins()); const QSize windowSize = (geometry().size() * scale).grownBy(margins + customMargins());
SIZE *size = reinterpret_cast<SIZE *>(lParam); SIZE *size = reinterpret_cast<SIZE *>(lParam);
size->cx = windowSize.width(); size->cx = windowSize.width();
@ -2435,6 +2441,14 @@ void QWindowsWindow::handleWindowStateChange(Qt::WindowStates state)
handleHidden(); handleHidden();
QWindowSystemInterface::flushWindowSystemEvents(QEventLoop::ExcludeUserInputEvents); // Tell QQuickWindow to stop rendering now. QWindowSystemInterface::flushWindowSystemEvents(QEventLoop::ExcludeUserInputEvents); // Tell QQuickWindow to stop rendering now.
} else { } else {
if (state & Qt::WindowMaximized) {
WINDOWPLACEMENT windowPlacement{};
windowPlacement.length = sizeof(WINDOWPLACEMENT);
GetWindowPlacement(m_data.hwnd, &windowPlacement);
const RECT geometry = RECTfromQRect(m_data.restoreGeometry);
windowPlacement.rcNormalPosition = geometry;
SetWindowPlacement(m_data.hwnd, &windowPlacement);
}
// QTBUG-17548: We send expose events when receiving WM_Paint, but for // QTBUG-17548: We send expose events when receiving WM_Paint, but for
// layered windows and transient children, we won't receive any WM_Paint. // layered windows and transient children, we won't receive any WM_Paint.
QWindow *w = window(); QWindow *w = window();
@ -2458,6 +2472,11 @@ void QWindowsWindow::handleWindowStateChange(Qt::WindowStates state)
} }
} }
void QWindowsWindow::updateRestoreGeometry()
{
m_data.restoreGeometry = normalFrameGeometry(m_data.hwnd);
}
void QWindowsWindow::setWindowState(Qt::WindowStates state) void QWindowsWindow::setWindowState(Qt::WindowStates state)
{ {
if (m_data.hwnd) { if (m_data.hwnd) {

View File

@ -78,6 +78,7 @@ struct QWindowsWindowData
{ {
Qt::WindowFlags flags; Qt::WindowFlags flags;
QRect geometry; QRect geometry;
QRect restoreGeometry;
QMargins fullFrameMargins; // Do not use directly for windows, see FrameDirty. QMargins fullFrameMargins; // Do not use directly for windows, see FrameDirty.
QMargins customMargins; // User-defined, additional frame for NCCALCSIZE QMargins customMargins; // User-defined, additional frame for NCCALCSIZE
HWND hwnd = nullptr; HWND hwnd = nullptr;
@ -218,6 +219,8 @@ public:
void setGeometry(const QRect &rect) override; void setGeometry(const QRect &rect) override;
QRect geometry() const override { return m_data.geometry; } QRect geometry() const override { return m_data.geometry; }
QRect normalGeometry() const override; QRect normalGeometry() const override;
QRect restoreGeometry() const { return m_data.restoreGeometry; }
void updateRestoreGeometry();
void setVisible(bool visible) override; void setVisible(bool visible) override;
bool isVisible() const; bool isVisible() const;