The square markers, block meters and hard-cornered fills read as boxy next to the porthole. The desktop is now soft throughout: the porthole is the shape everything is built around and every smaller surface echoes it. - Theme gains radiusS / radiusM / radiusL. radiusL is frameRadius - padS, so anything inset padS inside one of the frame's curves is concentric with it. - P5Panel and Skew draw rounded rectangles (Geom.roundedRect) whenever they neither lean nor are chopped, which is always now; the polygon path is kept for shapes brought back on purpose. - Markers are dots; workspace pips, toggles, transport and media chips, notification actions and today's date are pills or discs; the slider handle is round. Meters are one continuous rounded line that glides to its level instead of a row of segments. - Album art is rounded with ClippingRectangle in the bar, the media popout and the dashboard. - Free-standing panels (launcher, ask) drop the corner brackets and take the frame radius. - Fix: a hovered notification's wash was a full-bleed square, so in the drawer's bottom corner it ran past the drawer's curve. It is inset by padS/2 and rounded by radiusL, which keeps it inside the curve. Hyprland: the discord special workspace and its window rule are gone, SUPER+S stays the only scratchpad, and SUPER+D now opens the dashboard (it was on SUPER+I). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
130 lines
3.6 KiB
QML
130 lines
3.6 KiB
QML
import QtQuick
|
|
import "root:/config"
|
|
import "root:/components"
|
|
|
|
// Hairline slider with a round handle. Drag or click anywhere on the rail.
|
|
Item {
|
|
id: root
|
|
|
|
property real value: 0 // 0..1
|
|
property color accent: Theme.primary
|
|
property real stepSize: 0.05
|
|
|
|
signal moved(real value)
|
|
|
|
implicitHeight: 18
|
|
implicitWidth: 200
|
|
focusPolicy: root.enabled ? Qt.StrongFocus : Qt.NoFocus
|
|
|
|
readonly property real _lean: Theme.skew * height
|
|
|
|
function commit(nextValue: real): void {
|
|
if (!root.enabled)
|
|
return;
|
|
root.moved(Math.max(0, Math.min(1, nextValue)));
|
|
}
|
|
|
|
// Rail
|
|
Skew {
|
|
id: rail
|
|
anchors.verticalCenter: parent.verticalCenter
|
|
anchors.left: parent.left
|
|
anchors.right: parent.right
|
|
height: root.activeFocus ? 4 : 2
|
|
// Focus widens the rail and rings it in the accent rather than filling
|
|
// it: the level fill is often the accent itself, and a solid accent
|
|
// rail swallowed it.
|
|
color: root.activeFocus
|
|
? Theme.surfaceAlt
|
|
: Theme.alpha(root.enabled ? Theme.outline : Theme.treatmentDisabledMark, 0.7)
|
|
borderColor: root.activeFocus ? Theme.accent : "transparent"
|
|
borderWidth: root.activeFocus ? Theme.stroke : 0
|
|
|
|
Behavior on height {
|
|
NumberAnimation { duration: Theme.durFast }
|
|
}
|
|
}
|
|
|
|
// Fill
|
|
Skew {
|
|
anchors.verticalCenter: parent.verticalCenter
|
|
anchors.left: parent.left
|
|
width: Math.max(0, Math.min(1, root.value)) * root.width
|
|
height: root.activeFocus ? 4 : 2
|
|
color: root.enabled ? root.accent : Theme.treatmentDisabledText
|
|
|
|
Behavior on width {
|
|
enabled: !drag.active
|
|
NumberAnimation { duration: Theme.durFast }
|
|
}
|
|
|
|
Behavior on color {
|
|
ColorAnimation { duration: Theme.durBase }
|
|
}
|
|
}
|
|
|
|
// Handle
|
|
Skew {
|
|
id: handle
|
|
width: height
|
|
radius: height / 2
|
|
height: root.activeFocus || hover.hovered || drag.active ? 12 : 10
|
|
color: root.enabled ? Theme.text : Theme.treatmentDisabledText
|
|
anchors.verticalCenter: parent.verticalCenter
|
|
x: Math.max(0, Math.min(1, root.value)) * root.width - width / 2
|
|
|
|
Behavior on height {
|
|
NumberAnimation { duration: Theme.durFast; easing.type: Easing.OutCubic }
|
|
}
|
|
Behavior on x {
|
|
enabled: !drag.active
|
|
NumberAnimation { duration: Theme.durFast }
|
|
}
|
|
}
|
|
|
|
HoverHandler {
|
|
id: hover
|
|
enabled: root.enabled
|
|
cursorShape: Qt.PointingHandCursor
|
|
}
|
|
|
|
TapHandler {
|
|
enabled: root.enabled
|
|
onPressedChanged: if (pressed) root.forceActiveFocus(Qt.MouseFocusReason)
|
|
onTapped: event => root.commit(event.position.x / root.width)
|
|
}
|
|
|
|
DragHandler {
|
|
id: drag
|
|
enabled: root.enabled
|
|
target: null
|
|
xAxis.enabled: true
|
|
yAxis.enabled: false
|
|
onCentroidChanged: {
|
|
if (!active) return;
|
|
root.forceActiveFocus(Qt.MouseFocusReason);
|
|
root.commit(centroid.position.x / root.width);
|
|
}
|
|
}
|
|
|
|
Keys.onPressed: event => {
|
|
switch (event.key) {
|
|
case Qt.Key_Left:
|
|
root.commit(root.value - root.stepSize);
|
|
break;
|
|
case Qt.Key_Right:
|
|
root.commit(root.value + root.stepSize);
|
|
break;
|
|
case Qt.Key_Home:
|
|
root.commit(0);
|
|
break;
|
|
case Qt.Key_End:
|
|
root.commit(1);
|
|
break;
|
|
default:
|
|
return;
|
|
}
|
|
event.accepted = true;
|
|
}
|
|
}
|