From e18fb7883ff8bfec716524ce7361ac7f553975b0 Mon Sep 17 00:00:00 2001 From: Ilya Fedin Date: Wed, 22 Feb 2023 22:20:06 +0400 Subject: client: Unify margins handling Currently all the shell integrations except of xdg-shell pass full surface size to resizeFromApplyConfigure. xdg-shell behavior is not even consistent between the first and the consequent calls to resizeFromApplyConfigure. This replaces QWaylandWindow::customMargins with QWaylandWindow::windowContentMargins in order to being able to retrieve set_window_geometry margins separately from the geometry itself and makes xdg-shell passing the geometry consistently as full surface size removing the need in special casing. This also makes QWaylandWindow::clientSizeMargins public so e.g. xdg-shell can compute out absolute position for window content geometry without special casing decorations Change-Id: I1b98afc8b5c867ecb7cc586267b13f7ec4b1a88c Reviewed-by: David Edmundson (cherry picked from commit ae026d6ac7b7910b9f3934a1df2b69d3fce344bc) Reviewed-by: Qt Cherry-pick Bot --- src/client/qwaylandwindow.cpp | 37 +++++++--------------- src/client/qwaylandwindow_p.h | 4 +-- .../xdg-shell/qwaylandxdgshell.cpp | 21 ++++++------ 3 files changed, 24 insertions(+), 38 deletions(-) diff --git a/src/client/qwaylandwindow.cpp b/src/client/qwaylandwindow.cpp index a109126d..a1c3a58e 100644 --- a/src/client/qwaylandwindow.cpp +++ b/src/client/qwaylandwindow.cpp @@ -455,20 +455,6 @@ void QWaylandWindow::repositionFromApplyConfigure(const QPoint &globalPosition) void QWaylandWindow::resizeFromApplyConfigure(const QSize &sizeWithMargins, const QPoint &offset) { QMargins margins = clientSideMargins(); - - // Exclude shadows from margins once they are excluded from window geometry - // 1) First resizeFromApplyConfigure() call will have sizeWithMargins equal to surfaceSize() - // which has full margins (shadows included). - // 2) Following resizeFromApplyConfigure() calls should have sizeWithMargins equal to - // windowContentGeometry() which excludes shadows, therefore in this case we have to - // exclude them too in order not to accidentally apply smaller size to the window. - if (sizeWithMargins != surfaceSize()) { - if (mWindowDecorationEnabled) - margins = mWindowDecoration->margins(QWaylandAbstractDecoration::ShadowsExcluded); - if (!mCustomMargins.isNull()) - margins -= mCustomMargins; - } - int widthWithoutMargins = qMax(sizeWithMargins.width() - (margins.left() + margins.right()), 1); int heightWithoutMargins = qMax(sizeWithMargins.height() - (margins.top() + margins.bottom()), 1); QRect geometry(windowGeometry().topLeft(), QSize(widthWithoutMargins, heightWithoutMargins)); @@ -803,11 +789,6 @@ QMargins QWaylandWindow::clientSideMargins() const return mWindowDecorationEnabled ? mWindowDecoration->margins() : QMargins{}; } -QMargins QWaylandWindow::customMargins() const -{ - return mCustomMargins; -} - void QWaylandWindow::setCustomMargins(const QMargins &margins) { const QMargins oldMargins = mCustomMargins; mCustomMargins = margins; @@ -822,11 +803,7 @@ QSize QWaylandWindow::surfaceSize() const return geometry().marginsAdded(clientSideMargins()).size(); } -/*! - * Window geometry as defined by the xdg-shell spec (in wl_surface coordinates) - * topLeft is where the shadow stops and the decorations border start. - */ -QRect QWaylandWindow::windowContentGeometry() const +QMargins QWaylandWindow::windowContentMargins() const { QMargins shadowMargins; @@ -836,7 +813,17 @@ QRect QWaylandWindow::windowContentGeometry() const if (!mCustomMargins.isNull()) shadowMargins += mCustomMargins; - return QRect(QPoint(shadowMargins.left(), shadowMargins.top()), surfaceSize().shrunkBy(shadowMargins)); + return shadowMargins; +} + +/*! + * Window geometry as defined by the xdg-shell spec (in wl_surface coordinates) + * topLeft is where the shadow stops and the decorations border start. + */ +QRect QWaylandWindow::windowContentGeometry() const +{ + const QMargins margins = windowContentMargins(); + return QRect(QPoint(margins.left(), margins.top()), surfaceSize().shrunkBy(margins)); } /*! diff --git a/src/client/qwaylandwindow_p.h b/src/client/qwaylandwindow_p.h index 185de69a..22b42a9a 100644 --- a/src/client/qwaylandwindow_p.h +++ b/src/client/qwaylandwindow_p.h @@ -118,9 +118,10 @@ public: bool waitForFrameSync(int timeout); QMargins frameMargins() const override; - QMargins customMargins() const; + QMargins clientSideMargins() const; void setCustomMargins(const QMargins &margins) override; QSize surfaceSize() const; + QMargins windowContentMargins() const; QRect windowContentGeometry() const; QPointF mapFromWlSurface(const QPointF &surfacePosition) const; @@ -239,7 +240,6 @@ protected: virtual void doHandleFrameCallback(); virtual QRect defaultGeometry() const; void sendExposeEvent(const QRect &rect); - QMargins clientSideMargins() const; QWaylandDisplay *mDisplay = nullptr; diff --git a/src/plugins/shellintegration/xdg-shell/qwaylandxdgshell.cpp b/src/plugins/shellintegration/xdg-shell/qwaylandxdgshell.cpp index 6a4acf86..6303fbc9 100644 --- a/src/plugins/shellintegration/xdg-shell/qwaylandxdgshell.cpp +++ b/src/plugins/shellintegration/xdg-shell/qwaylandxdgshell.cpp @@ -45,7 +45,7 @@ QWaylandXdgSurface::Toplevel::~Toplevel() void QWaylandXdgSurface::Toplevel::applyConfigure() { if (!(m_applied.states & (Qt::WindowMaximized|Qt::WindowFullScreen))) - m_normalSize = m_xdgSurface->m_window->windowFrameGeometry().size(); + m_normalSize = m_xdgSurface->m_window->windowContentGeometry().size(); if ((m_pending.states & Qt::WindowActive) && !(m_applied.states & Qt::WindowActive) && !m_xdgSurface->m_window->display()->isKeyboardAvailable()) @@ -88,7 +88,7 @@ void QWaylandXdgSurface::Toplevel::applyConfigure() } if (!surfaceSize.isEmpty()) - m_xdgSurface->m_window->resizeFromApplyConfigure(surfaceSize); + m_xdgSurface->m_window->resizeFromApplyConfigure(surfaceSize.grownBy(m_xdgSurface->m_window->windowContentMargins())); m_applied = m_pending; qCDebug(lcQpaWayland) << "Applied pending xdg_toplevel configure event:" << m_applied.size << m_applied.states; @@ -446,18 +446,17 @@ void QWaylandXdgSurface::setPopup(QWaylandWindow *parent) auto positioner = new QtWayland::xdg_positioner(m_shell->create_positioner()); // set_popup expects a position relative to the parent - QPoint topLeftMargins = QPoint(m_window->customMargins().left(), m_window->customMargins().top()); - QPoint parentMargins = QPoint(parent->customMargins().left(), parent->customMargins().top()); - QPoint transientPos = m_window->geometry().topLeft() + topLeftMargins; // this is absolute - transientPos -= parent->geometry().topLeft() + parentMargins; - if (parent->decoration()) { - transientPos.setX(transientPos.x() + parent->decoration()->margins(QWaylandAbstractDecoration::ShadowsExcluded).left()); - transientPos.setY(transientPos.y() + parent->decoration()->margins(QWaylandAbstractDecoration::ShadowsExcluded).top()); - } + QRect windowGeometry = m_window->windowContentGeometry(); + QMargins windowMargins = m_window->windowContentMargins() - m_window->clientSideMargins(); + QMargins parentMargins = parent->windowContentMargins() - parent->clientSideMargins(); + QPoint transientPos = m_window->geometry().topLeft(); // this is absolute + transientPos += QPoint(windowMargins.left(), windowMargins.top()); + transientPos -= parent->geometry().topLeft(); + transientPos -= QPoint(parentMargins.left(), parentMargins.top()); positioner->set_anchor_rect(transientPos.x(), transientPos.y(), 1, 1); positioner->set_anchor(QtWayland::xdg_positioner::anchor_top_left); positioner->set_gravity(QtWayland::xdg_positioner::gravity_bottom_right); - positioner->set_size(m_window->windowContentGeometry().width(), m_window->windowContentGeometry().height()); + positioner->set_size(windowGeometry.width(), windowGeometry.height()); positioner->set_constraint_adjustment(QtWayland::xdg_positioner::constraint_adjustment_slide_x | QtWayland::xdg_positioner::constraint_adjustment_slide_y); m_popup = new Popup(this, parent, positioner); -- cgit v1.2.1