quickshell: bury melt joints by a full corner radius

Panels buried only 8px into the bar while their corner radius was 24,
so 16px of rounded corner stuck out past the joint: the outline pinched
where the corner turned, then the fillet bulged back out. That is the
balloon at the connection point.

meltInto now tracks Theme.radius, so the whole corner ends up inside
the band it merges with and only straight edges reach the junction —
which is what smin is meant to fillet. Applies to the panel, toast and
launcher. meltK follows radius / 2 so the fillet scales with the one
rounding knob instead of drifting out of step.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
rope 2026-07-28 14:05:39 +01:00
parent b2e4e9863b
commit 0a6a23aa8a

View file

@ -975,21 +975,27 @@ in
// be left/right is top/bottom.
readonly property real rawTop: chrome.y + 8
readonly property real rawBottom: chrome.y + chrome.height - 8
// A surface that comes within snapDist of a frame band is
// extended 4px INTO it, so the SDF fuses the two into one
// swollen shape rather than leaving a visible seam and a
// stranded rounded corner. The launcher has always done
// this via launchBot; this generalises it to every panel.
readonly property real meltTop: Theme.frameWidth - 4
readonly property real meltBot: bar.height - Theme.frameWidth + 4
// How deep a surface buries itself in the band it merges
// with. This MUST be >= the panel corner radius. A rounded
// corner curves away from the edge over exactly panelR
// pixels, so burying less than that leaves part of the
// curve sticking out past the joint: the outline pinches in
// where the corner turns, then the fillet bulges back out
// the "ballooned at the connection point" look. Bury the
// whole corner and only straight edges reach the junction,
// which is what smin is meant to fillet.
readonly property real meltInto: Theme.radius
readonly property real meltTop: Theme.frameWidth - meltInto
readonly property real meltBot: bar.height - Theme.frameWidth + meltInto
// Trigger distance is about proximity, not burial depth.
readonly property real snapDist: Theme.panelGap + 4
readonly property real panelTop: rawTop <= Theme.frameWidth + snapDist
? meltTop : rawTop
readonly property real panelBottom: rawBottom >= bar.height - Theme.frameWidth - snapDist
? meltBot : rawBottom
// The panel/toast/session centre-x uses (barWidth 4): the
// surface overlaps 4px into the bar so the two melt.
readonly property real surfLeftX: Theme.barWidth - 4
// Left edge lands at (barWidth meltInto): the surface
// buries a full corner radius inside the bar column.
readonly property real surfLeftX: Theme.barWidth - meltInto / 2
property vector4d cutout: Qt.vector4d(
(Theme.barWidth + bar.width - Theme.frameWidth) / 2,
bar.height / 2,
@ -997,17 +1003,17 @@ in
bar.height / 2 - Theme.frameWidth)
property vector4d panel: chrome.visible
? Qt.vector4d(surfLeftX + chrome.width / 2, (panelTop + panelBottom) / 2,
4 + chrome.width / 2, (panelBottom - panelTop) / 2)
meltInto / 2 + chrome.width / 2, (panelBottom - panelTop) / 2)
: Qt.vector4d(0, 0, 0, 0)
// Toast sits under the top frame band and melts up into it.
readonly property real toastBot: toastItem.y + 8 + _toastRect.height
property vector4d toast: toastItem.visible && _toastRect.width > 0.5
? Qt.vector4d(surfLeftX + _toastRect.width / 2, (meltTop + toastBot) / 2,
4 + _toastRect.width / 2, (toastBot - meltTop) / 2)
meltInto / 2 + _toastRect.width / 2, (toastBot - meltTop) / 2)
: Qt.vector4d(0, 0, 0, 0)
// The launcher is the one surface that stays put: it still
// grows from the bottom frame band at screen centre.
readonly property real launchBot: bar.height - Theme.frameWidth + 4
readonly property real launchBot: bar.height - Theme.frameWidth + meltInto
property vector4d launcher: launcherPanel.visible
? Qt.vector4d(launcherPanel.x + launcherPanel.width / 2, (launcherPanel.y + launchBot) / 2,
launcherPanel.width / 2, (launchBot - launcherPanel.y) / 2)
@ -1017,7 +1023,9 @@ in
property vector2d res: Qt.vector2d(width, height)
property real cutoutR: Theme.radius
property real panelR: Theme.radius
property real meltK: 12
// Half the corner radius: the fillet scales with the
// one rounding knob instead of drifting out of step.
property real meltK: Theme.radius / 2
property real borderW: Theme.borderWidth
fragmentShader: "file://${chromeShader}"
}