Stop every popover double-counting the bar height
The control center fix applies to five more surfaces: the date menu, the clipboard panel, the activity panel, notification toasts, and the signal glass all opened 48 pixels under the bar while their own expression asked for 12. wlr-layer-shell has three behaviors and only the middle one is subtle. A positive exclusiveZone reserves space; a negative one ignores what others reserved; zero reserves nothing but RESPECTS what others reserved. Every popover here uses zero, so the compositor had already placed them below the bar before their own margin applied, and adding Theme.barHeight counted the bar twice. It is not a crash or a warning -- the surface simply opens lower than written -- so a contract now holds the rule mechanically: a surface with exclusiveZone 0 may not name Theme.barHeight in a margin. It also checks the premise it rests on, and fails if the bar ever stops reserving its own height rather than quietly checking the wrong thing. Measured after: date menu and clipboard at 12px, control center at 2px, each matching what its code asks for. Claude-Session: https://claude.ai/code/session_01BRvzt4H8XXLPVH5MyYdk9L
This commit is contained in:
@@ -15,7 +15,11 @@ PanelWindow {
|
|||||||
color: "transparent"
|
color: "transparent"
|
||||||
anchors.top: true
|
anchors.top: true
|
||||||
anchors.right: true
|
anchors.right: true
|
||||||
margins.top: Theme.barHeight + Theme.barGap * 2
|
// The gap ALONE, not the bar height plus the gap. exclusiveZone 0 means
|
||||||
|
// "reserve nothing, but respect what others reserved", so this surface
|
||||||
|
// already begins below the bar's zone -- adding the bar height here counted
|
||||||
|
// it twice and left the surface floating 48px under the bar instead of 12.
|
||||||
|
margins.top: Theme.barGap * 2
|
||||||
margins.right: Theme.barSideMargin
|
margins.right: Theme.barSideMargin
|
||||||
exclusiveZone: 0
|
exclusiveZone: 0
|
||||||
implicitWidth: 350
|
implicitWidth: 350
|
||||||
|
|||||||
@@ -20,8 +20,11 @@ PanelWindow {
|
|||||||
top: true
|
top: true
|
||||||
right: true
|
right: true
|
||||||
}
|
}
|
||||||
|
// The gap ALONE, not the bar height plus the gap -- see the note in
|
||||||
|
// QuickSettings.qml: exclusiveZone 0 already places this below the bar's
|
||||||
|
// reserved zone, so adding the bar height counted it twice.
|
||||||
margins {
|
margins {
|
||||||
top: Theme.barHeight + Theme.barGap * 2
|
top: Theme.barGap * 2
|
||||||
right: Theme.barSideMargin
|
right: Theme.barSideMargin
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -28,7 +28,11 @@ PanelWindow {
|
|||||||
color: "transparent"
|
color: "transparent"
|
||||||
|
|
||||||
anchors.top: true
|
anchors.top: true
|
||||||
margins.top: Theme.barHeight + Theme.barGap * 2
|
// The gap ALONE, not the bar height plus the gap. exclusiveZone 0 means
|
||||||
|
// "reserve nothing, but respect what others reserved", so this surface
|
||||||
|
// already begins below the bar's zone -- adding the bar height here counted
|
||||||
|
// it twice and left the surface floating 48px under the bar instead of 12.
|
||||||
|
margins.top: Theme.barGap * 2
|
||||||
exclusiveZone: 0
|
exclusiveZone: 0
|
||||||
|
|
||||||
implicitWidth: 760
|
implicitWidth: 760
|
||||||
|
|||||||
@@ -17,7 +17,11 @@ PanelWindow {
|
|||||||
|
|
||||||
anchors.top: true
|
anchors.top: true
|
||||||
anchors.right: true
|
anchors.right: true
|
||||||
margins.top: Theme.barHeight + Theme.barGap * 2
|
// The gap ALONE, not the bar height plus the gap. exclusiveZone 0 means
|
||||||
|
// "reserve nothing, but respect what others reserved", so this surface
|
||||||
|
// already begins below the bar's zone -- adding the bar height here counted
|
||||||
|
// it twice and left the surface floating 48px under the bar instead of 12.
|
||||||
|
margins.top: Theme.barGap * 2
|
||||||
margins.right: Theme.barSideMargin
|
margins.right: Theme.barSideMargin
|
||||||
exclusiveZone: 0
|
exclusiveZone: 0
|
||||||
|
|
||||||
|
|||||||
@@ -22,7 +22,11 @@ PanelWindow {
|
|||||||
|
|
||||||
screen: root.modelData
|
screen: root.modelData
|
||||||
anchors.top: true
|
anchors.top: true
|
||||||
margins.top: Theme.barHeight + Theme.barGap * 2
|
// The gap ALONE, not the bar height plus the gap. exclusiveZone 0 means
|
||||||
|
// "reserve nothing, but respect what others reserved", so this surface
|
||||||
|
// already begins below the bar's zone -- adding the bar height here counted
|
||||||
|
// it twice and left the surface floating 48px under the bar instead of 12.
|
||||||
|
margins.top: Theme.barGap * 2
|
||||||
exclusiveZone: 0
|
exclusiveZone: 0
|
||||||
implicitWidth: root.showingEvent ? 388 : 438
|
implicitWidth: root.showingEvent ? 388 : 438
|
||||||
implicitHeight: root.showingEvent ? 76 : 132
|
implicitHeight: root.showingEvent ? 76 : 132
|
||||||
|
|||||||
Executable
+74
@@ -0,0 +1,74 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
# A surface that respects the bar's reserved space must not also subtract it by
|
||||||
|
# hand.
|
||||||
|
#
|
||||||
|
# wlr-layer-shell has three behaviors and only the middle one is subtle:
|
||||||
|
#
|
||||||
|
# exclusiveZone > 0 reserve this much space; other surfaces are pushed out
|
||||||
|
# exclusiveZone = 0 reserve nothing, but RESPECT what others reserved
|
||||||
|
# exclusiveZone < 0 reserve nothing and ignore what others reserved
|
||||||
|
#
|
||||||
|
# Every popover here uses 0, so the compositor has already placed it below the
|
||||||
|
# bar before its own margin applies. Adding Theme.barHeight to that margin
|
||||||
|
# counts the bar twice. That is not a crash and not a warning -- the panel
|
||||||
|
# simply opens lower than intended, which is how the control center spent its
|
||||||
|
# life hanging 38px under a bar it was written to sit 2px below, and five other
|
||||||
|
# surfaces sat at 48px instead of 12px.
|
||||||
|
#
|
||||||
|
# The rule is mechanical, so a test can hold it: with exclusiveZone 0, a margin
|
||||||
|
# is the GAP, never the gap plus what someone else reserved.
|
||||||
|
#
|
||||||
|
# Static and read-only.
|
||||||
|
|
||||||
|
set -uo pipefail
|
||||||
|
|
||||||
|
repo_dir="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)"
|
||||||
|
modules="$repo_dir/config/dot/quickshell/modules"
|
||||||
|
|
||||||
|
fail() {
|
||||||
|
printf 'layer margin contract: %s\n' "$1" >&2
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
[[ -d "$modules" ]] || fail 'the modules directory is missing'
|
||||||
|
|
||||||
|
# The premise: the bar is what reserves space at the top. If that ever changes,
|
||||||
|
# the rule below stops being the right rule and this should be revisited rather
|
||||||
|
# than kept passing.
|
||||||
|
bar="$modules/bar/Bar.qml"
|
||||||
|
[[ -r "$bar" ]] || fail 'Bar.qml is missing'
|
||||||
|
grep -q 'exclusiveZone: Theme.barHeight' "$bar" \
|
||||||
|
|| fail 'the bar no longer reserves its own height, so what popovers should offset by has changed'
|
||||||
|
|
||||||
|
violations=""
|
||||||
|
checked=0
|
||||||
|
|
||||||
|
while read -r file; do
|
||||||
|
[[ -n "$file" ]] || continue
|
||||||
|
grep -q 'PanelWindow' "$file" || continue
|
||||||
|
|
||||||
|
# Only surfaces that respect other zones. A surface with a negative zone is
|
||||||
|
# positioned from the screen edge and SHOULD carry the bar height itself.
|
||||||
|
zone="$(grep -oE 'exclusiveZone:[[:space:]]*-?[0-9]+' "$file" | head -1 | grep -oE '\-?[0-9]+$')"
|
||||||
|
[[ "$zone" == "0" ]] || continue
|
||||||
|
checked=$((checked + 1))
|
||||||
|
|
||||||
|
# Margins only. Theme.barHeight is legitimate elsewhere -- sizing a row to
|
||||||
|
# match the bar, for instance -- so this looks at the placement lines.
|
||||||
|
offenders="$(grep -nE '^[[:space:]]*(margins\.(top|bottom)|top|bottom):.*Theme\.barHeight' "$file" || true)"
|
||||||
|
if [[ -n "$offenders" ]]; then
|
||||||
|
while IFS= read -r line; do
|
||||||
|
violations+=" ${file#$repo_dir/}:${line}"$'\n'
|
||||||
|
done <<<"$offenders"
|
||||||
|
fi
|
||||||
|
done < <(find "$modules" -name '*.qml' | sort)
|
||||||
|
|
||||||
|
(( checked > 0 )) || fail 'no surfaces with exclusiveZone 0 were found, so this checked nothing'
|
||||||
|
|
||||||
|
if [[ -n "$violations" ]]; then
|
||||||
|
printf 'layer margin contract: these surfaces respect the bar'"'"'s reserved space AND add it to their margin, so they open one bar-height too low:\n%s' "$violations" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
printf 'layer margin contract: PASS (%d surfaces respect the bar without double-counting it)\n' "$checked"
|
||||||
Reference in New Issue
Block a user