Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 10 additions & 3 deletions shell/Ui/PanelSlider.qml
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,13 @@ Item {
property int tickCount: 0
property color tickColor: bar ? bar.background : Color.background

// Corner rounding for the three drawn parts. The defaults are the pill shape
// the panels have always used; a caller that wants square controls sets them
// to 0 rather than copying this component.
property real trackRadius: trackHeight / 2
property real tickRadius: 1
property real knobRadius: knobSize / 2

onValueChanged: if (!dragging) liveValue = value

signal moved(real value)
Expand All @@ -47,7 +54,7 @@ Item {
anchors.left: parent.left
anchors.right: parent.right
height: root.trackHeight
radius: height / 2
radius: root.trackRadius
color: root.trackColor
}

Expand All @@ -72,7 +79,7 @@ Item {
required property int index
width: Math.max(1, Style.space(2))
height: root.trackHeight + Style.space(4)
radius: 1
radius: root.tickRadius
color: root.tickColor
anchors.verticalCenter: track.verticalCenter
x: Math.max(0, Math.min(track.width - width,
Expand All @@ -84,7 +91,7 @@ Item {
id: knob
width: root.knobSize
height: root.knobSize
radius: root.knobSize / 2
radius: root.knobRadius
color: root.knobColor
borderSpec: Border.flat(root.bar ? root.bar.background : "#101315", Math.max(1, Style.space(2)))
anchors.verticalCenter: track.verticalCenter
Expand Down
140 changes: 140 additions & 0 deletions test/shell.d/panel-slider-radius-test.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,140 @@
#!/bin/bash
source "$(dirname "$0")/base-test.sh"

run_node_test <<'JS'
const fs = require('fs')

const sliderQml = fs.readFileSync(path.join(root, 'shell/Ui/PanelSlider.qml'), 'utf8')

assert(
/property real trackRadius:\s*trackHeight \/ 2/.test(sliderQml) &&
/property real tickRadius:\s*1/.test(sliderQml) &&
/property real knobRadius:\s*knobSize \/ 2/.test(sliderQml),
'PanelSlider radius defaults reproduce the pill shape callers already render'
)

assert(
!/radius:\s*height \/ 2/.test(sliderQml) && !/radius:\s*root\.knobSize \/ 2/.test(sliderQml),
'PanelSlider draws from the radius properties instead of hardcoded expressions'
)
JS

require_compositor "PanelSlider radius runtime test"

if ! command -v quickshell >/dev/null 2>&1; then
pass "quickshell not installed; skipping PanelSlider radius runtime test"
exit 0
fi

TMPDIR=$(mktemp -d)
cleanup() {
if [[ -d $TMPDIR ]]; then
rm -rf "$TMPDIR"
fi
}
trap cleanup EXIT

ln -s "$ROOT/shell/Ui" "$TMPDIR/Ui"
ln -s "$ROOT/shell/Commons" "$TMPDIR/Commons"

cat >"$TMPDIR/shell.qml" <<'QML'
import QtQuick
import Quickshell
import qs.Commons
import qs.Ui

ShellRoot {
id: root

function fail(message) {
console.log("RESULT fail " + message)
Qt.quit()
}

// Track, fill, ticks and knob are internal, so collect every drawn radius
// rather than depending on the order children happen to be declared in.
function drawnRadii(item, out) {
for (var i = 0; i < item.children.length; i++) {
var child = item.children[i]
if (child.radius !== undefined) out.push(child.radius)
root.drawnRadii(child, out)
}
return out
}

function runChecks() {
if (defaultSlider.trackRadius !== defaultSlider.trackHeight / 2) {
root.fail("default trackRadius is " + defaultSlider.trackRadius + ", expected " + defaultSlider.trackHeight / 2)
return
}
if (defaultSlider.knobRadius !== defaultSlider.knobSize / 2) {
root.fail("default knobRadius is " + defaultSlider.knobRadius + ", expected " + defaultSlider.knobSize / 2)
return
}
if (defaultSlider.tickRadius !== 1) {
root.fail("default tickRadius is " + defaultSlider.tickRadius + ", expected 1")
return
}

var rounded = root.drawnRadii(defaultSlider, [])
if (rounded.length === 0) {
root.fail("default slider drew nothing with a radius")
return
}
for (var i = 0; i < rounded.length; i++) {
if (rounded[i] <= 0) {
root.fail("default slider drew a square corner: radius " + rounded[i])
return
}
}

var squared = root.drawnRadii(squaredSlider, [])
if (squared.length !== rounded.length) {
root.fail("squared slider drew " + squared.length + " radii, default drew " + rounded.length)
return
}
for (var j = 0; j < squared.length; j++) {
if (squared[j] !== 0) {
root.fail("squared slider kept a rounded corner: radius " + squared[j])
return
}
}

console.log("RESULT pass")
Qt.quit()
}

Component.onCompleted: Qt.callLater(runChecks)

Item {
PanelSlider {
id: defaultSlider
width: 200
value: 0.5
tickCount: 5
}

PanelSlider {
id: squaredSlider
width: 200
value: 0.5
tickCount: 5
trackRadius: 0
tickRadius: 0
knobRadius: 0
}
}
}
QML

output=$(timeout 15 quickshell -p "$TMPDIR" --no-color 2>&1) || {
printf '%s\n' "$output" >&2
fail "PanelSlider radius runtime fixture exits cleanly"
}

if ! grep -q "RESULT pass" <<<"$output"; then
printf '%s\n' "$output" >&2
fail "PanelSlider radius properties drive the drawn corners"
fi

pass "PanelSlider radius properties drive the drawn corners"