Changeset View
Changeset View
Standalone View
Standalone View
shell_client.cpp
Show First 20 Lines • Show All 1589 Lines • ▼ Show 20 Line(s) | |||||
1590 | 1590 | | |||
1591 | QRect ShellClient::transientPlacement(const QRect &bounds) const | 1591 | QRect ShellClient::transientPlacement(const QRect &bounds) const | ||
1592 | { | 1592 | { | ||
1593 | QRect anchorRect; | 1593 | QRect anchorRect; | ||
1594 | Qt::Edges anchorEdge; | 1594 | Qt::Edges anchorEdge; | ||
1595 | Qt::Edges gravity; | 1595 | Qt::Edges gravity; | ||
1596 | QPoint offset; | 1596 | QPoint offset; | ||
1597 | PositionerConstraints constraintAdjustments; | 1597 | PositionerConstraints constraintAdjustments; | ||
1598 | QSize size = geometry().size(); | ||||
1598 | 1599 | | |||
1599 | const QPoint parentClientPos = transientFor()->pos() + transientFor()->clientPos(); | 1600 | const QPoint parentClientPos = transientFor()->pos() + transientFor()->clientPos(); | ||
1600 | QRect popupPosition; | 1601 | QRect popupPosition; | ||
1601 | 1602 | | |||
1602 | // returns if a target is within the supplied bounds, optional edges argument states which side to check | 1603 | // returns if a target is within the supplied bounds, optional edges argument states which side to check | ||
1603 | auto inBounds = [bounds](const QRect &target, Qt::Edges edges = Qt::LeftEdge | Qt::RightEdge | Qt::TopEdge | Qt::BottomEdge) -> bool { | 1604 | auto inBounds = [bounds](const QRect &target, Qt::Edges edges = Qt::LeftEdge | Qt::RightEdge | Qt::TopEdge | Qt::BottomEdge) -> bool { | ||
1604 | if (edges & Qt::LeftEdge && target.left() < bounds.left()) { | 1605 | if (edges & Qt::LeftEdge && target.left() < bounds.left()) { | ||
1605 | return false; | 1606 | return false; | ||
Show All 17 Lines | 1621 | if (m_shellSurface) { | |||
1623 | gravity = Qt::BottomEdge | Qt::RightEdge; //our single point represents the top left of the popup | 1624 | gravity = Qt::BottomEdge | Qt::RightEdge; //our single point represents the top left of the popup | ||
1624 | constraintAdjustments = (PositionerConstraint::SlideX | PositionerConstraint::SlideY); | 1625 | constraintAdjustments = (PositionerConstraint::SlideX | PositionerConstraint::SlideY); | ||
1625 | } else if (m_xdgShellPopup) { | 1626 | } else if (m_xdgShellPopup) { | ||
1626 | anchorRect = m_xdgShellPopup->anchorRect(); | 1627 | anchorRect = m_xdgShellPopup->anchorRect(); | ||
1627 | anchorEdge = m_xdgShellPopup->anchorEdge(); | 1628 | anchorEdge = m_xdgShellPopup->anchorEdge(); | ||
1628 | gravity = m_xdgShellPopup->gravity(); | 1629 | gravity = m_xdgShellPopup->gravity(); | ||
1629 | offset = m_xdgShellPopup->anchorOffset(); | 1630 | offset = m_xdgShellPopup->anchorOffset(); | ||
1630 | constraintAdjustments = m_xdgShellPopup->constraintAdjustments(); | 1631 | constraintAdjustments = m_xdgShellPopup->constraintAdjustments(); | ||
1632 | if (!size.isValid()) { | ||||
1633 | size = m_xdgShellPopup->initialSize(); | ||||
1634 | } | ||||
1631 | } else { | 1635 | } else { | ||
1632 | Q_UNREACHABLE(); | 1636 | Q_UNREACHABLE(); | ||
1633 | } | 1637 | } | ||
1634 | 1638 | | |||
1639 | | ||||
1635 | //initial position | 1640 | //initial position | ||
1636 | popupPosition = QRect(popupOffset(anchorRect, anchorEdge, gravity) + offset + parentClientPos, geometry().size()); | 1641 | popupPosition = QRect(popupOffset(anchorRect, anchorEdge, gravity, size) + offset + parentClientPos, size); | ||
1637 | 1642 | | |||
1638 | //if that fits, we don't need to do anything | 1643 | //if that fits, we don't need to do anything | ||
1639 | if (inBounds(popupPosition)) { | 1644 | if (inBounds(popupPosition)) { | ||
1640 | return popupPosition; | 1645 | return popupPosition; | ||
1641 | } | 1646 | } | ||
1642 | //otherwise apply constraint adjustment per axis in order XDG Shell Popup states | 1647 | //otherwise apply constraint adjustment per axis in order XDG Shell Popup states | ||
1643 | 1648 | | |||
1644 | if (constraintAdjustments & PositionerConstraint::FlipX) { | 1649 | if (constraintAdjustments & PositionerConstraint::FlipX) { | ||
1645 | if (!inBounds(popupPosition, Qt::LeftEdge | Qt::RightEdge)) { | 1650 | if (!inBounds(popupPosition, Qt::LeftEdge | Qt::RightEdge)) { | ||
1646 | //flip both edges (if either bit is set, XOR both) | 1651 | //flip both edges (if either bit is set, XOR both) | ||
1647 | auto flippedAnchorEdge = anchorEdge; | 1652 | auto flippedAnchorEdge = anchorEdge; | ||
1648 | if (flippedAnchorEdge & (Qt::LeftEdge | Qt::RightEdge)) { | 1653 | if (flippedAnchorEdge & (Qt::LeftEdge | Qt::RightEdge)) { | ||
1649 | flippedAnchorEdge ^= (Qt::LeftEdge | Qt::RightEdge); | 1654 | flippedAnchorEdge ^= (Qt::LeftEdge | Qt::RightEdge); | ||
1650 | } | 1655 | } | ||
1651 | auto flippedGravity = gravity; | 1656 | auto flippedGravity = gravity; | ||
1652 | if (flippedGravity & (Qt::LeftEdge | Qt::RightEdge)) { | 1657 | if (flippedGravity & (Qt::LeftEdge | Qt::RightEdge)) { | ||
1653 | flippedGravity ^= (Qt::LeftEdge | Qt::RightEdge); | 1658 | flippedGravity ^= (Qt::LeftEdge | Qt::RightEdge); | ||
1654 | } | 1659 | } | ||
1655 | auto flippedPopupPosition = QRect(popupOffset(anchorRect, flippedAnchorEdge, flippedGravity) + offset + parentClientPos, geometry().size()); | 1660 | auto flippedPopupPosition = QRect(popupOffset(anchorRect, flippedAnchorEdge, flippedGravity, size) + offset + parentClientPos, size); | ||
1656 | 1661 | | |||
1657 | //if it still doesn't fit we should continue with the unflipped version | 1662 | //if it still doesn't fit we should continue with the unflipped version | ||
1658 | if (inBounds(flippedPopupPosition, Qt::LeftEdge | Qt::RightEdge)) { | 1663 | if (inBounds(flippedPopupPosition, Qt::LeftEdge | Qt::RightEdge)) { | ||
1659 | popupPosition.setX(flippedPopupPosition.x()); | 1664 | popupPosition.moveLeft(flippedPopupPosition.x()); | ||
1660 | } | 1665 | } | ||
1661 | } | 1666 | } | ||
1662 | } | 1667 | } | ||
1663 | if (constraintAdjustments & PositionerConstraint::SlideX) { | 1668 | if (constraintAdjustments & PositionerConstraint::SlideX) { | ||
1664 | if (!inBounds(popupPosition, Qt::LeftEdge)) { | 1669 | if (!inBounds(popupPosition, Qt::LeftEdge)) { | ||
1665 | popupPosition.setX(bounds.x()); | 1670 | popupPosition.moveLeft(bounds.x()); | ||
1666 | } | 1671 | } | ||
1667 | if (!inBounds(popupPosition, Qt::RightEdge)) { | 1672 | if (!inBounds(popupPosition, Qt::RightEdge)) { | ||
1668 | popupPosition.setX(bounds.x() + bounds.width() - geometry().width()); | 1673 | // moveRight suffers from the classic QRect off by one issue | ||
1674 | popupPosition.moveLeft(bounds.x() + bounds.width() - size.width()); | ||||
1669 | } | 1675 | } | ||
1670 | } | 1676 | } | ||
1671 | if (constraintAdjustments & PositionerConstraint::ResizeX) { | 1677 | if (constraintAdjustments & PositionerConstraint::ResizeX) { | ||
1672 | //TODO | 1678 | //TODO | ||
1673 | //but we need to sort out when this is run as resize should only happen before first configure | 1679 | //but we need to sort out when this is run as resize should only happen before first configure | ||
1674 | } | 1680 | } | ||
1675 | 1681 | | |||
1676 | if (constraintAdjustments & PositionerConstraint::FlipY) { | 1682 | if (constraintAdjustments & PositionerConstraint::FlipY) { | ||
1677 | if (!inBounds(popupPosition, Qt::TopEdge | Qt::BottomEdge)) { | 1683 | if (!inBounds(popupPosition, Qt::TopEdge | Qt::BottomEdge)) { | ||
1678 | //flip both edges (if either bit is set, XOR both) | 1684 | //flip both edges (if either bit is set, XOR both) | ||
1679 | auto flippedAnchorEdge = anchorEdge; | 1685 | auto flippedAnchorEdge = anchorEdge; | ||
1680 | if (flippedAnchorEdge & (Qt::TopEdge | Qt::BottomEdge)) { | 1686 | if (flippedAnchorEdge & (Qt::TopEdge | Qt::BottomEdge)) { | ||
1681 | flippedAnchorEdge ^= (Qt::TopEdge | Qt::BottomEdge); | 1687 | flippedAnchorEdge ^= (Qt::TopEdge | Qt::BottomEdge); | ||
1682 | } | 1688 | } | ||
1683 | auto flippedGravity = gravity; | 1689 | auto flippedGravity = gravity; | ||
1684 | if (flippedGravity & (Qt::TopEdge | Qt::BottomEdge)) { | 1690 | if (flippedGravity & (Qt::TopEdge | Qt::BottomEdge)) { | ||
1685 | flippedGravity ^= (Qt::TopEdge | Qt::BottomEdge); | 1691 | flippedGravity ^= (Qt::TopEdge | Qt::BottomEdge); | ||
1686 | } | 1692 | } | ||
1687 | auto flippedPopupPosition = QRect(popupOffset(anchorRect, flippedAnchorEdge, flippedGravity) + offset + parentClientPos, geometry().size()); | 1693 | auto flippedPopupPosition = QRect(popupOffset(anchorRect, flippedAnchorEdge, flippedGravity, size) + offset + parentClientPos, size); | ||
1688 | 1694 | | |||
1689 | //if it still doesn't fit we should continue with the unflipped version | 1695 | //if it still doesn't fit we should continue with the unflipped version | ||
1690 | if (inBounds(flippedPopupPosition, Qt::TopEdge | Qt::BottomEdge)) { | 1696 | if (inBounds(flippedPopupPosition, Qt::TopEdge | Qt::BottomEdge)) { | ||
1691 | popupPosition.setY(flippedPopupPosition.y()); | 1697 | popupPosition.moveTop(flippedPopupPosition.y()); | ||
1692 | } | 1698 | } | ||
1693 | } | 1699 | } | ||
1694 | } | 1700 | } | ||
1695 | if (constraintAdjustments & PositionerConstraint::SlideY) { | 1701 | if (constraintAdjustments & PositionerConstraint::SlideY) { | ||
1696 | if (!inBounds(popupPosition, Qt::TopEdge)) { | 1702 | if (!inBounds(popupPosition, Qt::TopEdge)) { | ||
1697 | popupPosition.setY(bounds.y()); | 1703 | popupPosition.moveTop(bounds.y()); | ||
1698 | } | 1704 | } | ||
1699 | if (!inBounds(popupPosition, Qt::BottomEdge)) { | 1705 | if (!inBounds(popupPosition, Qt::BottomEdge)) { | ||
1700 | popupPosition.setY(bounds.y() + bounds.height() - geometry().height()); | 1706 | popupPosition.moveTop(bounds.y() + bounds.height() - size.height()); | ||
1701 | } | 1707 | } | ||
1702 | } | 1708 | } | ||
1703 | if (constraintAdjustments & PositionerConstraint::ResizeY) { | 1709 | if (constraintAdjustments & PositionerConstraint::ResizeY) { | ||
1704 | //TODO | 1710 | //TODO | ||
1705 | } | 1711 | } | ||
1706 | 1712 | | |||
1707 | return popupPosition; | 1713 | return popupPosition; | ||
1708 | } | 1714 | } | ||
1709 | 1715 | | |||
1710 | QPoint ShellClient::popupOffset(const QRect &anchorRect, const Qt::Edges anchorEdge, const Qt::Edges gravity) const | 1716 | QPoint ShellClient::popupOffset(const QRect &anchorRect, const Qt::Edges anchorEdge, const Qt::Edges gravity, const QSize popupSize) const | ||
1711 | { | 1717 | { | ||
1712 | const QSize popupSize = geometry().size(); | | |||
1713 | QPoint anchorPoint; | 1718 | QPoint anchorPoint; | ||
1714 | switch (anchorEdge & (Qt::LeftEdge | Qt::RightEdge)) { | 1719 | switch (anchorEdge & (Qt::LeftEdge | Qt::RightEdge)) { | ||
1715 | case Qt::LeftEdge: | 1720 | case Qt::LeftEdge: | ||
1716 | anchorPoint.setX(anchorRect.x()); | 1721 | anchorPoint.setX(anchorRect.x()); | ||
1717 | break; | 1722 | break; | ||
1718 | case Qt::RightEdge: | 1723 | case Qt::RightEdge: | ||
1719 | anchorPoint.setX(anchorRect.x() + anchorRect.width()); | 1724 | anchorPoint.setX(anchorRect.x() + anchorRect.width()); | ||
1720 | break; | 1725 | break; | ||
▲ Show 20 Lines • Show All 267 Lines • Show Last 20 Lines |