The recent accent-colour setting only reached part of the desktop. looks.lua still hardcoded the focused-window border and glow to blue, so any hyprctl reload -- or every fresh session, for about a second -- reverted a chosen accent; it now reads accentName the same way it already read colorScheme. The lock screen and terminal stayed blue regardless of the chosen accent despite the setting's own description claiming otherwise; panama-lock and panama-theme-apps now resolve and apply the real accent. AccentPicker built its swatch model from Theme.accents directly instead of the schema's own options list, so the two could drift silently; switched it to read the schema. Its hit target only covered the swatch, not the name label added specifically for colour-vision accessibility -- extended to the whole row. Settings search had no route for the "appearance" group, so searching for the accent or colour scheme landed on Home. ColorScheme's hex-to-Hyprland helper assumed 6-digit colours and would silently corrupt a future translucent one; fixed it to read from the end of the string instead of the start. An accent-only change no longer reruns the full colour-scheme pipeline. The gradient it builds for the focused border now goes through SystemSettings' existing serialiser instead of a second, under-escaped copy of the same logic. The settings-ownership contract test enforced the old rule that ColorScheme must never touch the focused border; updated it to verify the real, intended rule instead of contradicting the code. Claude-Session: https://claude.ai/code/session_01E6TJUAh41HaP25MVHWkhRZ
101 lines
4.0 KiB
QML
101 lines
4.0 KiB
QML
// Choosing the desktop accent.
|
|
//
|
|
// Each swatch is drawn as the GRADIENT it will actually produce, not a flat
|
|
// dot, because the gradient is the thing being chosen -- the focused window
|
|
// border, the bar hairline and every active state are the two colours meeting.
|
|
// A row of flat circles would misrepresent all of them.
|
|
//
|
|
// Named accents rather than a colour wheel: each name carries a curated pair
|
|
// per scheme, so every choice stays legible in both light and dark. See
|
|
// config/Theme.qml for the palette and the reasoning.
|
|
|
|
import QtQuick
|
|
import qs.config
|
|
import qs.services
|
|
|
|
Flow {
|
|
id: root
|
|
|
|
spacing: 10
|
|
|
|
readonly property string current: DesktopPreferences.get("accentName") || "blue"
|
|
|
|
// The schema's own option list, not Theme.accents directly -- two lists
|
|
// hand-kept in sync is how they drift. This is the same pattern
|
|
// ChoiceRow.qml uses for every other enum row.
|
|
readonly property var spec: PreferenceSchema.spec("accentName")
|
|
readonly property var options: root.spec && root.spec.options ? root.spec.options : []
|
|
|
|
Repeater {
|
|
// The schema's option order is the palette's order, so blue is first
|
|
// because it is what Panama ships.
|
|
model: root.options
|
|
|
|
Column {
|
|
id: entry
|
|
|
|
required property var modelData
|
|
|
|
readonly property string name: entry.modelData.value
|
|
readonly property var pair: Theme.accents[entry.name]
|
|
readonly property bool selected: entry.name === root.current
|
|
readonly property color start: Theme.dark ? entry.pair.dark : entry.pair.light
|
|
readonly property color end: Theme.dark ? entry.pair.darkSecondary : entry.pair.lightSecondary
|
|
|
|
spacing: 5
|
|
|
|
// The hit target is the whole swatch+label unit, not just the
|
|
// 46px circle: the label exists specifically so someone with a
|
|
// colour vision deficiency can identify an accent without it, and
|
|
// a label that cannot itself be tapped defeats that.
|
|
HoverHandler {
|
|
cursorShape: Qt.PointingHandCursor
|
|
}
|
|
|
|
TapHandler {
|
|
onTapped: {
|
|
if (!SystemSettings.commitPreference("accentName", entry.name))
|
|
console.warn("AccentPicker: commitPreference rejected accent", entry.name);
|
|
}
|
|
}
|
|
|
|
Rectangle {
|
|
width: 46
|
|
height: 46
|
|
radius: 23
|
|
anchors.horizontalCenter: parent.horizontalCenter
|
|
color: "transparent"
|
|
// The ring sits outside the gradient rather than over it, so a
|
|
// selected swatch still shows its true colours.
|
|
border.width: entry.selected ? 2 : 1
|
|
border.color: entry.selected ? Theme.fg : Theme.alpha(Theme.fg, 0.14)
|
|
|
|
Rectangle {
|
|
anchors.fill: parent
|
|
anchors.margins: entry.selected ? 4 : 3
|
|
radius: width / 2
|
|
border.width: 0
|
|
gradient: Gradient {
|
|
orientation: Gradient.Horizontal
|
|
GradientStop { position: 0.0; color: entry.start }
|
|
GradientStop { position: 1.0; color: entry.end }
|
|
}
|
|
}
|
|
}
|
|
|
|
// Always shown, not a tooltip. Telling swatches apart by colour is
|
|
// exactly what someone with a colour vision deficiency cannot do,
|
|
// and it is the reason the palette is named rather than freeform --
|
|
// hiding the names behind a hover would waste that.
|
|
Text {
|
|
anchors.horizontalCenter: parent.horizontalCenter
|
|
text: entry.modelData.label
|
|
color: entry.selected ? Theme.fg : Theme.fgMuted
|
|
font.family: Theme.fontFamily
|
|
font.pixelSize: Theme.fontSizeSmall
|
|
font.weight: entry.selected ? Font.DemiBold : Font.Normal
|
|
}
|
|
}
|
|
}
|
|
}
|