From 738530e62ee48f7326cd5a610b90b47344b701f1 Mon Sep 17 00:00:00 2001 From: Dashie Date: Sun, 16 Jun 2024 20:01:08 +0200 Subject: [PATCH] xdg-shell: Continue transform of popup until size fits (#6521) --- src/protocols/XDGShell.cpp | 47 ++++++++++++++++++++------------------ 1 file changed, 25 insertions(+), 22 deletions(-) diff --git a/src/protocols/XDGShell.cpp b/src/protocols/XDGShell.cpp index dddc3bca..c16ebb9d 100644 --- a/src/protocols/XDGShell.cpp +++ b/src/protocols/XDGShell.cpp @@ -539,30 +539,33 @@ CBox CXDGPositionerRules::getPosition(const CBox& constraint, const Vector2D& pa if (success) return predictedBox.translate(-parentCoord - constraint.pos()); + CBox test = predictedBox; + if (state.constraintAdjustment & (XDG_POSITIONER_CONSTRAINT_ADJUSTMENT_FLIP_X | XDG_POSITIONER_CONSTRAINT_ADJUSTMENT_FLIP_Y)) { // attempt to flip - const bool flipX = state.constraintAdjustment & XDG_POSITIONER_CONSTRAINT_ADJUSTMENT_FLIP_X; - const bool flipY = state.constraintAdjustment & XDG_POSITIONER_CONSTRAINT_ADJUSTMENT_FLIP_Y; + const bool flipX = state.constraintAdjustment & XDG_POSITIONER_CONSTRAINT_ADJUSTMENT_FLIP_X; + const bool flipY = state.constraintAdjustment & XDG_POSITIONER_CONSTRAINT_ADJUSTMENT_FLIP_Y; + auto countEdges = [constraint](const CBox& test) -> int { + int edgeCount = 0; + edgeCount += test.x < constraint.x ? 1 : 0; + edgeCount += test.x + test.w > constraint.x + constraint.w ? 1 : 0; + edgeCount += test.y < constraint.y ? 1 : 0; + edgeCount += test.y + test.h > constraint.y + constraint.h ? 1 : 0; + return edgeCount; + }; + int edgeCount = countEdges(test); - CBox test = predictedBox; - success = true; - if (flipX && test.copy().translate(Vector2D{-predictedBox.w - state.anchorRect.w, 0}).expand(-1).inside(constraint)) + if (flipX && edgeCount > countEdges(test.copy().translate(Vector2D{-predictedBox.w - state.anchorRect.w, 0}))) test.translate(Vector2D{-predictedBox.w - state.anchorRect.w, 0}); - else if (flipY && test.copy().translate(Vector2D{0, -predictedBox.h - state.anchorRect.h}).expand(-1).inside(constraint)) + if (flipY && edgeCount > countEdges(test.copy().translate(Vector2D{0, -predictedBox.h - state.anchorRect.h}))) test.translate(Vector2D{0, -predictedBox.h - state.anchorRect.h}); - else if (flipX && flipY && test.copy().translate(Vector2D{-predictedBox.w - state.anchorRect.w, -predictedBox.h - state.anchorRect.h}).expand(-1).inside(constraint)) - test.translate(Vector2D{-predictedBox.w - state.anchorRect.w, -predictedBox.h - state.anchorRect.h}); - else - success = false; + + success = test.copy().expand(-1).inside(constraint); if (success) return test.translate(-parentCoord - constraint.pos()); } - // if flips fail, we will slide and remember. - // if the positioner is allowed to resize, then resize the slid thing. - CBox test = predictedBox; - // for slide and resize, defines the padding around the edge for the positioned // surface. constexpr int EDGE_PADDING = 4; @@ -575,10 +578,10 @@ CBox CXDGPositionerRules::getPosition(const CBox& constraint, const Vector2D& pa //const bool gravityLeft = state.gravity == XDG_POSITIONER_GRAVITY_NONE || state.gravity == XDG_POSITIONER_GRAVITY_LEFT || state.gravity == XDG_POSITIONER_GRAVITY_TOP_LEFT || state.gravity == XDG_POSITIONER_GRAVITY_BOTTOM_LEFT; //const bool gravityTop = state.gravity == XDG_POSITIONER_GRAVITY_NONE || state.gravity == XDG_POSITIONER_GRAVITY_TOP || state.gravity == XDG_POSITIONER_GRAVITY_TOP_LEFT || state.gravity == XDG_POSITIONER_GRAVITY_TOP_RIGHT; - const bool leftEdgeOut = predictedBox.x < constraint.x; - const bool topEdgeOut = predictedBox.y < constraint.y; - const bool rightEdgeOut = predictedBox.x + predictedBox.w > constraint.x + constraint.w; - const bool bottomEdgeOut = predictedBox.y + predictedBox.h > constraint.y + constraint.h; + const bool leftEdgeOut = test.x < constraint.x; + const bool topEdgeOut = test.y < constraint.y; + const bool rightEdgeOut = test.x + test.w > constraint.x + constraint.w; + const bool bottomEdgeOut = test.y + test.h > constraint.y + constraint.h; // TODO: this isn't truly conformant. if (leftEdgeOut && slideX) @@ -600,10 +603,10 @@ CBox CXDGPositionerRules::getPosition(const CBox& constraint, const Vector2D& pa const bool resizeX = state.constraintAdjustment & XDG_POSITIONER_CONSTRAINT_ADJUSTMENT_RESIZE_X; const bool resizeY = state.constraintAdjustment & XDG_POSITIONER_CONSTRAINT_ADJUSTMENT_RESIZE_Y; - const bool leftEdgeOut = predictedBox.x < constraint.x; - const bool topEdgeOut = predictedBox.y < constraint.y; - const bool rightEdgeOut = predictedBox.x + predictedBox.w > constraint.x + constraint.w; - const bool bottomEdgeOut = predictedBox.y + predictedBox.h > constraint.y + constraint.h; + const bool leftEdgeOut = test.x < constraint.x; + const bool topEdgeOut = test.y < constraint.y; + const bool rightEdgeOut = test.x + test.w > constraint.x + constraint.w; + const bool bottomEdgeOut = test.y + test.h > constraint.y + constraint.h; // TODO: this isn't truly conformant. if (leftEdgeOut && resizeX) {