From 2d1b4f905d8169632ceaeb6e8d9ea065f5f56ccc Mon Sep 17 00:00:00 2001 From: bbedward Date: Mon, 21 Sep 2026 22:51:49 -0400 Subject: [PATCH] bar/goth: fix inverse radius override --- quickshell/Modules/DankBar/BarOutline.js | 22 +++++++---- quickshell/Modules/DankBar/BarSurface.qml | 21 +++++++--- quickshell/Modules/DankBar/DankBarBody.qml | 2 +- .../Modules/SurfaceWidgets/GothCorner.qml | 38 +++++++++++-------- 4 files changed, 52 insertions(+), 31 deletions(-) diff --git a/quickshell/Modules/DankBar/BarOutline.js b/quickshell/Modules/DankBar/BarOutline.js index 4b465a45c..fa8de3ef7 100644 --- a/quickshell/Modules/DankBar/BarOutline.js +++ b/quickshell/Modules/DankBar/BarOutline.js @@ -41,6 +41,7 @@ function frame(g, start, end, thickness, attachedStart, attachedEnd, farStart, f thickness, inset, wing: Math.max(0, g.wing), + wingCross: Math.max(0, g.wingCross ?? g.wing), attachedStart: shrink(attachedStart), attachedEnd: shrink(attachedEnd), farStart: shrink(farStart), @@ -136,9 +137,10 @@ function alongOps(f) { const p = pen(); const i = f.inset; const r = f.wing; + const rc = f.wingCross; const T = f.thickness; - // the offset of a wing arc meets the offset attached edge 2*sqrt(r*i) short of the wing tip - const reach = 2 * Math.sqrt(r * i); + // the offset of a wing arc meets the offset attached edge 2*sqrt(rc*i) short of the tip, stretched by the along/cross ratio + const reach = rc + i > 0 ? (r + i) * 2 * Math.sqrt(rc * i) / (rc + i) : 0; const startTip = f.start - r; const endTip = f.end + r; if (r > 0) { @@ -146,7 +148,7 @@ function alongOps(f) { p.at(startTip + reach, i).at(endTip - reach, i); else p.at(endTip, -i); - p.arc(r + i, 0, f.end - i, r); + p.arc(r + i, 0, f.end - i, rc, rc + i); } else { if (f.attachedVisible) p.at(f.start + i + f.attachedStart, i); @@ -155,11 +157,11 @@ function alongOps(f) { p.at(f.end - i, T - i - f.farEnd).corner(f.farEnd, f.end - i - f.farEnd, T - i); p.at(f.start + i + f.farStart, T - i).corner(f.farStart, f.start + i, T - i - f.farStart); if (r > 0) { - p.at(f.start + i, r); + p.at(f.start + i, rc); if (f.attachedVisible) - p.arc(r + i, 0, startTip + reach, i); + p.arc(r + i, 0, startTip + reach, i, rc + i); else - p.arc(r + i, 0, startTip, -i); + p.arc(r + i, 0, startTip, -i, rc + i); } else { p.at(f.start + i, i + f.attachedStart).corner(f.attachedStart, f.start + i + f.attachedStart, i); } @@ -182,10 +184,11 @@ function pen() { self.down = true; return self; }, - arc(radius, sweep, a, c) { + arc(radius, sweep, a, c, crossRadius) { self.ops.push({ op: "A", radius, + crossRadius: crossRadius ?? radius, sweep, a, c @@ -215,6 +218,7 @@ function pen() { function serialize(ops, position, width, height) { const map = mapper(position, width, height); const flipSweep = position === "bottom" || position === "left"; + const vertical = position === "left" || position === "right"; return ops.map(op => { if (op.op === "Z") return "Z"; @@ -223,7 +227,9 @@ function serialize(ops, position, width, height) { if (op.op !== "A") return `${op.op} ${target}`; const sweep = flipSweep ? 1 - op.sweep : op.sweep; - return `A ${num(op.radius)} ${num(op.radius)} 0 0 ${sweep} ${target}`; + const rx = vertical ? op.crossRadius : op.radius; + const ry = vertical ? op.radius : op.crossRadius; + return `A ${num(rx)} ${num(ry)} 0 0 ${sweep} ${target}`; }).join(" "); } diff --git a/quickshell/Modules/DankBar/BarSurface.qml b/quickshell/Modules/DankBar/BarSurface.qml index a3dcf66a3..790517853 100644 --- a/quickshell/Modules/DankBar/BarSurface.qml +++ b/quickshell/Modules/DankBar/BarSurface.qml @@ -22,7 +22,11 @@ Item { readonly property bool farEdge: isBottom || isRight readonly property bool edgeAttached: (barConfig?.attachToScreenEdge ?? false) && !frameShapesBar readonly property bool alongWings: !(barWindow.spansEdge ?? true) + readonly property real crossSize: axis.isVertical ? (parent?.width ?? 0) : (parent?.height ?? 0) + readonly property real wingCrossCap: Math.max(0, crossSize - Math.min(rt, crossSize / 2)) readonly property real wing: gothEnabled ? barWindow._wingR : 0 + readonly property real wingAlong: Math.max(0, motion.currentOffsetAlong) + readonly property real wingCross: alongWings ? Math.min(wingAlong, wingCrossCap) : wingAlong readonly property real windowLength: axis.isVertical ? barWindow.height : barWindow.width readonly property string startSide: axis.isVertical ? "top" : "left" readonly property string endSide: axis.isVertical ? "bottom" : "right" @@ -216,21 +220,25 @@ Item { GothCorner { id: leadingWing - radius: Math.max(0, motion.currentOffsetAlong) + radius: root.wingAlong + radiusX: root.axis.isVertical ? root.wingCross : radius + radiusY: root.axis.isVertical ? radius : root.wingCross color: root.barWindow._bgColor visible: root.gothEnabled && radius > 0 && root.startCover <= 0 - x: root.alongWings ? (root.axis.isVertical && root.isRight ? root.width - radius : 0) : (root.isLeft ? body.width : 0) - y: root.alongWings ? (!root.axis.isVertical && root.isBottom ? root.height - radius : 0) : (root.isTop ? body.height : 0) + x: root.alongWings ? (root.axis.isVertical && root.isRight ? root.width - width : 0) : (root.isLeft ? body.width : 0) + y: root.alongWings ? (!root.axis.isVertical && root.isBottom ? root.height - height : 0) : (root.isTop ? body.height : 0) corner: root.alongWings ? root.alongWingCorner(true) : root.isTop ? "bottomRight" : root.isBottom ? "topRight" : root.isLeft ? "bottomRight" : "bottomLeft" } GothCorner { id: trailingWing - radius: Math.max(0, motion.currentOffsetAlong) + radius: root.wingAlong + radiusX: root.axis.isVertical ? root.wingCross : radius + radiusY: root.axis.isVertical ? radius : root.wingCross color: root.barWindow._bgColor visible: root.gothEnabled && radius > 0 && root.endCover <= 0 - x: root.axis.isVertical ? (root.alongWings ? (root.isRight ? root.width - radius : 0) : (root.isLeft ? body.width : 0)) : root.width - radius - y: root.axis.isVertical ? root.height - radius : (root.alongWings ? (root.isBottom ? root.height - radius : 0) : (root.isTop ? body.height : 0)) + x: root.axis.isVertical ? (root.alongWings ? (root.isRight ? root.width - width : 0) : (root.isLeft ? body.width : 0)) : root.width - width + y: root.axis.isVertical ? root.height - height : (root.alongWings ? (root.isBottom ? root.height - height : 0) : (root.isTop ? body.height : 0)) corner: root.alongWings ? root.alongWingCorner(false) : root.isTop ? "bottomLeft" : root.isBottom ? "topLeft" : root.isLeft ? "topRight" : "topLeft" } @@ -257,6 +265,7 @@ Item { bottomRight: body.bottomRightRadius }, wing: root.gothEnabled ? leadingWing.radius : 0, + wingCross: root.gothEnabled ? root.wingCross : 0, alongWings: root.alongWings, inset: thickness / 2, open: !showFullBorder, diff --git a/quickshell/Modules/DankBar/DankBarBody.qml b/quickshell/Modules/DankBar/DankBarBody.qml index d6a9cee55..97f40b351 100644 --- a/quickshell/Modules/DankBar/DankBarBody.qml +++ b/quickshell/Modules/DankBar/DankBarBody.qml @@ -225,7 +225,7 @@ Item { Region { intersection: Intersection.Subtract - radius: wingRegion.wing.radius + shape: RegionShape.Ellipse x: wingRegion.x + wingRegion.wing.discRect.x y: wingRegion.y + wingRegion.wing.discRect.y width: wingRegion.wing.discRect.width diff --git a/quickshell/Modules/SurfaceWidgets/GothCorner.qml b/quickshell/Modules/SurfaceWidgets/GothCorner.qml index 865506c34..41256d8d0 100644 --- a/quickshell/Modules/SurfaceWidgets/GothCorner.qml +++ b/quickshell/Modules/SurfaceWidgets/GothCorner.qml @@ -5,42 +5,48 @@ Item { id: root property real radius: 0 + property real radiusX: radius + property real radiusY: radius property color color: "transparent" property string corner: "topLeft" - readonly property real rotationAngle: { + readonly property rect discRect: { + const rx = radiusX; + const ry = radiusY; switch (corner) { case "topRight": - return 90; + return Qt.rect(0, -ry, rx * 2, ry * 2); case "bottomRight": - return 180; + return Qt.rect(0, 0, rx * 2, ry * 2); case "bottomLeft": - return 270; + return Qt.rect(-rx, 0, rx * 2, ry * 2); default: - return 0; + return Qt.rect(-rx, -ry, rx * 2, ry * 2); } } - readonly property rect discRect: { - const r = radius; + readonly property string path: { + const rx = radiusX; + const ry = radiusY; + if (rx <= 0 || ry <= 0) + return ""; switch (corner) { case "topRight": - return Qt.rect(0, -r, r * 2, r * 2); + return `M 0 0 L 0 ${ry} L ${rx} ${ry} A ${rx} ${ry} 0 0 1 0 0 Z`; case "bottomRight": - return Qt.rect(0, 0, r * 2, r * 2); + return `M 0 ${ry} L 0 0 L ${rx} 0 A ${rx} ${ry} 0 0 0 0 ${ry} Z`; case "bottomLeft": - return Qt.rect(-r, 0, r * 2, r * 2); + return `M ${rx} ${ry} L ${rx} 0 L 0 0 A ${rx} ${ry} 0 0 1 ${rx} ${ry} Z`; default: - return Qt.rect(-r, -r, r * 2, r * 2); + return `M ${rx} 0 L ${rx} ${ry} L 0 ${ry} A ${rx} ${ry} 0 0 0 ${rx} 0 Z`; } } - width: Math.max(0, radius) - height: Math.max(0, radius) - visible: radius > 0 + width: Math.max(0, radiusX) + height: Math.max(0, radiusY) + visible: radiusX > 0 && radiusY > 0 Shape { anchors.fill: parent - rotation: root.rotationAngle preferredRendererType: Shape.CurveRenderer ShapePath { @@ -49,7 +55,7 @@ Item { strokeWidth: 0 PathSvg { - path: root.radius > 0 ? `M ${root.radius} 0 L ${root.radius} ${root.radius} L 0 ${root.radius} A ${root.radius} ${root.radius} 0 0 0 ${root.radius} 0 Z` : "" + path: root.path } } }