diff --git a/placement.cpp b/placement.cpp --- a/placement.cpp +++ b/placement.cpp @@ -500,8 +500,9 @@ { const auto parent = c->transientFor(); const QRect screen = Workspace::self()->clientArea(parent->isFullScreen() ? FullScreenArea : PlacementArea, parent); - const QPoint popupPos = c->transientPlacement(screen).topLeft(); - c->move(popupPos); + const QRect popupGeometry = c->transientPlacement(screen); + c->setGeometry(popupGeometry); + // Potentially a client could set no constraint adjustments // and we'll be offscreen. diff --git a/shell_client.h b/shell_client.h --- a/shell_client.h +++ b/shell_client.h @@ -210,7 +210,7 @@ void updateMaximizeMode(MaximizeMode maximizeMode); // called on surface commit and processes all m_pendingConfigureRequests up to m_lastAckedConfigureReqest void updatePendingGeometry(); - QPoint popupOffset(const QRect &anchorRect, const Qt::Edges anchorEdge, const Qt::Edges gravity) const; + QPoint popupOffset(const QRect &anchorRect, const Qt::Edges anchorEdge, const Qt::Edges gravity, const QSize popupSize) const; static void deleteClient(ShellClient *c); KWayland::Server::ShellSurfaceInterface *m_shellSurface; diff --git a/shell_client.cpp b/shell_client.cpp --- a/shell_client.cpp +++ b/shell_client.cpp @@ -1453,6 +1453,7 @@ Qt::Edges gravity; QPoint offset; PositionerConstraints constraintAdjustments; + QSize size = geometry().size(); const QPoint parentClientPos = transientFor()->pos() + transientFor()->clientPos(); QRect popupPosition; @@ -1486,12 +1487,16 @@ gravity = m_xdgShellPopup->gravity(); offset = m_xdgShellPopup->anchorOffset(); constraintAdjustments = m_xdgShellPopup->constraintAdjustments(); + if (!size.isValid()) { + size = m_xdgShellPopup->initialSize(); + } } else { Q_UNREACHABLE(); } + //initial position - popupPosition = QRect(popupOffset(anchorRect, anchorEdge, gravity) + offset + parentClientPos, geometry().size()); + popupPosition = QRect(popupOffset(anchorRect, anchorEdge, gravity, size) + offset + parentClientPos, size); //if that fits, we don't need to do anything if (inBounds(popupPosition)) { @@ -1510,20 +1515,21 @@ if (flippedGravity & (Qt::LeftEdge | Qt::RightEdge)) { flippedGravity ^= (Qt::LeftEdge | Qt::RightEdge); } - auto flippedPopupPosition = QRect(popupOffset(anchorRect, flippedAnchorEdge, flippedGravity) + offset + parentClientPos, geometry().size()); + auto flippedPopupPosition = QRect(popupOffset(anchorRect, flippedAnchorEdge, flippedGravity, size) + offset + parentClientPos, size); //if it still doesn't fit we should continue with the unflipped version if (inBounds(flippedPopupPosition, Qt::LeftEdge | Qt::RightEdge)) { - popupPosition.setX(flippedPopupPosition.x()); + popupPosition.moveLeft(flippedPopupPosition.x()); } } } if (constraintAdjustments & PositionerConstraint::SlideX) { if (!inBounds(popupPosition, Qt::LeftEdge)) { - popupPosition.setX(bounds.x()); + popupPosition.moveLeft(bounds.x()); } if (!inBounds(popupPosition, Qt::RightEdge)) { - popupPosition.setX(bounds.x() + bounds.width() - geometry().width()); + // moveRight suffers from the classic QRect off by one issue + popupPosition.moveLeft(bounds.x() + bounds.width() - size.width()); } } if (constraintAdjustments & PositionerConstraint::ResizeX) { @@ -1542,20 +1548,20 @@ if (flippedGravity & (Qt::TopEdge | Qt::BottomEdge)) { flippedGravity ^= (Qt::TopEdge | Qt::BottomEdge); } - auto flippedPopupPosition = QRect(popupOffset(anchorRect, flippedAnchorEdge, flippedGravity) + offset + parentClientPos, geometry().size()); + auto flippedPopupPosition = QRect(popupOffset(anchorRect, flippedAnchorEdge, flippedGravity, size) + offset + parentClientPos, size); //if it still doesn't fit we should continue with the unflipped version if (inBounds(flippedPopupPosition, Qt::TopEdge | Qt::BottomEdge)) { - popupPosition.setY(flippedPopupPosition.y()); + popupPosition.moveTop(flippedPopupPosition.y()); } } } if (constraintAdjustments & PositionerConstraint::SlideY) { if (!inBounds(popupPosition, Qt::TopEdge)) { - popupPosition.setY(bounds.y()); + popupPosition.moveTop(bounds.y()); } if (!inBounds(popupPosition, Qt::BottomEdge)) { - popupPosition.setY(bounds.y() + bounds.height() - geometry().height()); + popupPosition.moveTop(bounds.y() + bounds.height() - size.height()); } } if (constraintAdjustments & PositionerConstraint::ResizeY) { @@ -1565,9 +1571,8 @@ return popupPosition; } -QPoint ShellClient::popupOffset(const QRect &anchorRect, const Qt::Edges anchorEdge, const Qt::Edges gravity) const +QPoint ShellClient::popupOffset(const QRect &anchorRect, const Qt::Edges anchorEdge, const Qt::Edges gravity, const QSize popupSize) const { - const QSize popupSize = geometry().size(); QPoint anchorPoint; switch (anchorEdge & (Qt::LeftEdge | Qt::RightEdge)) { case Qt::LeftEdge: