quickshell: bury a full joint's depth, toast keeps one width
Toast is back to a fixed 320 — it is the same card wherever it appears and should not restyle itself around whatever menu is open. The residual indent was never the width step: two rounded boxes stacked on one edge each contribute a corner that curves away over exactly one radius, so the outline pinches and bulges at the joint. The curves only cancel at 2*radius of overlap, where the corner circles coincide. Burying that deep would drive the cards together, so a fused panel grows by what it buries. Content is pinned 12px from the panel top, not centred, so the extra height lands entirely below the cards and the clearance stays 12px. Geometry now derives from baseH, keeping height (which depends on fused) out of the position that decides it.
This commit is contained in:
parent
9eb728ca10
commit
7caf7f2541
1 changed files with 53 additions and 65 deletions
|
|
@ -4983,49 +4983,54 @@ in
|
|||
// it in (see meltTop/meltBot). Outer max wins when a panel
|
||||
// is taller than the space (yMax < yMin).
|
||||
readonly property real yMin: Theme.frameWidth
|
||||
readonly property real yMax: bar.height - Theme.frameWidth - height
|
||||
// A visible toast owns its band, so the space a panel has
|
||||
// to sit in ends short of it. Only the band the toast is
|
||||
// actually on shrinks; the other one is still the frame.
|
||||
readonly property real yMax: bar.height - Theme.frameWidth - baseH
|
||||
|
||||
// Height with no toast in play. `height` adds the burial on
|
||||
// top of this, so every position below is worked out from
|
||||
// baseH — using `height` would make it depend on `fused`,
|
||||
// which depends on the position. That is the loop.
|
||||
readonly property real baseH: fullHeight + 24
|
||||
|
||||
// Where the panel sits with no toast: on its widget,
|
||||
// clamped, then snapped to a band it very nearly reaches.
|
||||
readonly property real freeY: Math.max(yMin, Math.min(yMax, dropdownY - baseH / 2))
|
||||
readonly property real snappedY:
|
||||
freeY - yMin <= Theme.snapDist ? yMin
|
||||
: yMax - freeY <= Theme.snapDist ? Math.max(yMin, yMax)
|
||||
: freeY
|
||||
|
||||
// Two rounded boxes stacked on one edge leave a waist: each
|
||||
// contributes a corner that curves away over exactly one
|
||||
// radius, so the outline pinches in and bulges back out at
|
||||
// the joint. The curves only cancel when the boxes overlap
|
||||
// by 2×radius — then the two corner circles coincide and
|
||||
// the shared edge runs straight through. Anything less is
|
||||
// the indent, no matter how the shader smins it.
|
||||
readonly property real fuseDepth: 2 * Theme.radius
|
||||
|
||||
// Burying that deep would drive the panel's cards into the
|
||||
// notification's, so the panel grows by the same amount it
|
||||
// buries. Content is pinned 12px from the panel's TOP (see
|
||||
// dropdownContent.y), not centred, so the extra height all
|
||||
// lands below the cards: the surface reaches further down
|
||||
// and the clearance between the two sets of cards stays put
|
||||
// at 12px. y then works out free of fuseDepth entirely.
|
||||
readonly property bool toastBlocks: toastItem.visible && toastItem.isPrimary
|
||||
readonly property real toastMerge: Theme.radius / 2
|
||||
// Only fuse with a toast that will match this width.
|
||||
readonly property bool canFuse: fullWidth >= toastItem.minFuseW
|
||||
readonly property real lo: !toastBlocks || toastItem.atBottom ? yMin
|
||||
: Math.max(yMin, canFuse
|
||||
? toastItem.y + toastItem.height - 16 - toastMerge
|
||||
: toastItem.y + toastItem.height + Theme.panelGap)
|
||||
// Panel surface spans [y + 8, y + height - 8]; the toast's
|
||||
// starts at its y + 8. Landing the first ON the second (plus
|
||||
// a half-radius of burial, the fillet scale the shader smins
|
||||
// at) merges them into one outline with a shared waist,
|
||||
// rather than parking two surfaces a hairline apart. The
|
||||
// cards inside still clear each other by ~14px: 12 of panel
|
||||
// padding, 8 of toast inset, less the burial.
|
||||
readonly property real hi: !toastBlocks || !toastItem.atBottom ? yMax
|
||||
: Math.min(yMax, canFuse
|
||||
? toastItem.y + 16 + toastMerge - height
|
||||
: toastItem.y - Theme.panelGap - height)
|
||||
// Where the panel lands when it just tracks its widget.
|
||||
// hi < lo means the panel is taller than what the toast
|
||||
// leaves — nothing to be done, so it takes the frame and
|
||||
// the toast rides over it for its five seconds.
|
||||
readonly property real yTracked: Math.max(lo, Math.min(hi, dropdownY - height / 2))
|
||||
// Last clause: a panel with no room above the toast
|
||||
// can't clear it however it is placed, so it stops trying —
|
||||
// it takes the frame and the toast rides over it for its
|
||||
// five seconds rather than being shoved off screen.
|
||||
readonly property bool fused: toastBlocks && toastItem.atBottom
|
||||
&& snappedY + baseH - 8 > toastItem.y + 8
|
||||
&& toastItem.y + 16 - baseH >= yMin
|
||||
x: Theme.barWidth
|
||||
// Snap to whichever band is within reach, and only then.
|
||||
// Proximity rather than an alignTop/alignBottom flag per
|
||||
// dropdown: a panel that gains a card later starts fusing
|
||||
// with the frame on its own, and one that loses a card
|
||||
// stops — no flag to remember to flip. A panel taller than
|
||||
// the screen has yMax < yMin, so yTracked pins to yMin and
|
||||
// the first branch catches it.
|
||||
// Snapping still tests against the FRAME. A panel held off
|
||||
// a band by a toast is already fused to the toast, which is
|
||||
// itself fused to that band — one outline either way.
|
||||
y: Math.round(
|
||||
yTracked - yMin <= Theme.snapDist ? yMin
|
||||
: yMax - yTracked <= Theme.snapDist ? Math.max(yMin, yMax)
|
||||
: yTracked)
|
||||
// Snapping (in snappedY) is proximity to the FRAME rather
|
||||
// than an alignTop/alignBottom flag per dropdown: a panel
|
||||
// that gains a card later starts fusing with the frame on
|
||||
// its own, and one that loses a card stops. A panel taller
|
||||
// than the screen has yMax < yMin, so freeY pins to yMin
|
||||
// and the first branch catches it.
|
||||
y: Math.round(fused ? toastItem.y + 16 - baseH : snappedY)
|
||||
|
||||
// No Behavior here on purpose: _dropdownRect is positioned
|
||||
// off chrome.y, and chrome already eases to whatever this
|
||||
|
|
@ -5037,7 +5042,7 @@ in
|
|||
// bottom, so +16 left the panel edge flush with the content
|
||||
// (0 padding) while the growth axis overhung by 4. The
|
||||
// extra 8 gives 4px above and below, matching the right.
|
||||
height: fullHeight + 24
|
||||
height: baseH + (fused ? fuseDepth : 0)
|
||||
visible: false
|
||||
|
||||
onVisibleChanged: {
|
||||
|
|
@ -7633,27 +7638,10 @@ in
|
|||
readonly property var mutedApps: ["discord", "Discord", "Vesktop", "vesktop", "Spotify", "spotify", "vlc", "mpv"]
|
||||
readonly property bool isPrimary: bar.screen === Quickshell.screens[0]
|
||||
|
||||
// The toast and an open dropdown are both left-anchored to
|
||||
// the bar, so any width difference between them is a step
|
||||
// on the shared right edge — and smin fillets a step into
|
||||
// an S-curve waist, which is the warp at the junction.
|
||||
// Take the panel's drawn width (fullWidth + 4, what chrome
|
||||
// renders) and the fused outline is a straight edge.
|
||||
//
|
||||
// Keyed off the dropdown's DECLARED fullWidth and nothing
|
||||
// else. Reading its live y or height here would close a
|
||||
// loop: a panel's y depends on this toast's height, which
|
||||
// depends on its width, which would depend on that y.
|
||||
//
|
||||
// Below the floor there is no width worth matching — the
|
||||
// power menu is a 64px icon strip — so those keep their
|
||||
// own width and stand off instead (BarDropdown.canFuse).
|
||||
readonly property real minFuseW: 200
|
||||
readonly property real fuseW: {
|
||||
const d = bar.activeDropdown;
|
||||
if (!d || !d.visible || d.fullWidth < minFuseW) return 320;
|
||||
return d.fullWidth + 4;
|
||||
}
|
||||
// One width, always. The toast is the same card wherever
|
||||
// it appears; a panel fusing with it is the side that
|
||||
// gives (see BarDropdown.fuseDepth).
|
||||
readonly property real cardW: 320
|
||||
|
||||
// Which frame band the toast lives against: the one the
|
||||
// clock sits nearest, so it lands on the same side as the
|
||||
|
|
@ -7748,7 +7736,7 @@ in
|
|||
// Reveals rightward now, so width is the animated axis
|
||||
// and the card inside keeps a fixed width (otherwise it
|
||||
// would squash instead of being wiped in).
|
||||
width: toastItem.toastOpen ? toastItem.fuseW : 0
|
||||
width: toastItem.toastOpen ? toastItem.cardW : 0
|
||||
height: toastCard.height + 2 * Theme.panelGap
|
||||
clip: true
|
||||
|
||||
|
|
@ -7763,7 +7751,7 @@ in
|
|||
anchors.top: parent.top
|
||||
anchors.left: parent.left
|
||||
anchors.margins: Theme.panelGap
|
||||
width: toastItem.fuseW - 2 * Theme.panelGap
|
||||
width: toastItem.cardW - 2 * Theme.panelGap
|
||||
height: Math.max(toastPreview.visible ? 48 : 0, toastCol.height) + 16
|
||||
radius: Theme.radiusCard
|
||||
color: Theme.cardBg
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue