aurorad8a41c4
aurora: theme from matugen, scheme/contrast settings
+83 −99
5 files changed
- M .config/quickshell/aurora/SetAppearance.qml +20 −31
- M .config/quickshell/aurora/Settings.qml +5 −3
- M .config/quickshell/aurora/Theme.qml +33 −61
- M .config/quickshell/aurora/Wall.qml +24 −3
- M .config/quickshell/aurora/shell.qml +1 −1
| @@ -1,7 +1,7 @@ | |||
| 1 | 1 | import QtQuick | |
| 2 | 2 | import QtQuick.Layouts | |
| 3 | 3 | ||
| 4 | − | // Settings app > Appearance: wallpaper, accent, sizes and transparency (all in Settings, applied live). | |
| 4 | + | // Settings app > Appearance: wallpaper, colour scheme, sizes and transparency (all in Settings, applied live). | |
| 5 | 5 | Flickable { | |
| 6 | 6 | id: flick | |
| 7 | 7 | signal overlayRequested(string name) | |
| @@ -63,41 +63,30 @@ Flickable { | |||
| 63 | 63 | } | |
| 64 | 64 | } | |
| 65 | 65 | ||
| 66 | − | SectionLabel { text: "accent" } | |
| 67 | − | GridLayout { | |
| 66 | + | SectionLabel { text: "colours" } | |
| 67 | + | Text { | |
| 68 | 68 | Layout.fillWidth: true | |
| 69 | − | columns: 17 | |
| 70 | − | columnSpacing: 4 | |
| 71 | − | rowSpacing: 4 | |
| 69 | + | text: "matugen scheme from the wallpaper, accent = its primary" | |
| 70 | + | elide: Text.ElideRight | |
| 71 | + | color: Theme.dim | |
| 72 | + | font.family: Theme.font | |
| 73 | + | font.pixelSize: Theme.fontSize - 1 | |
| 74 | + | } | |
| 75 | + | Flow { | |
| 76 | + | Layout.fillWidth: true | |
| 77 | + | spacing: 4 | |
| 72 | 78 | Repeater { | |
| 73 | − | model: 17 // "auto" + color0..color15 | |
| 74 | − | delegate: Rectangle { | |
| 75 | − | id: sw | |
| 76 | − | required property int index | |
| 77 | − | readonly property int ci: index - 1 // -1 = auto | |
| 78 | − | readonly property bool current: Settings.accentIndex === ci | |
| 79 | − | Layout.fillWidth: true | |
| 80 | − | Layout.preferredHeight: 28 | |
| 81 | − | color: ci < 0 ? Theme.surface : Theme.pal[ci] | |
| 82 | − | border.width: current ? 2 : 1 | |
| 83 | − | border.color: current ? Theme.fg : Theme.line | |
| 84 | − | Text { | |
| 85 | − | anchors.centerIn: parent | |
| 86 | − | visible: sw.ci < 0 || sw.current | |
| 87 | − | text: sw.ci < 0 ? "auto" : Theme.iCheck | |
| 88 | − | color: sw.ci < 0 ? Theme.fg : Theme.bg | |
| 89 | − | font.family: Theme.font | |
| 90 | − | font.pixelSize: Theme.fontSize - 2 | |
| 91 | − | font.bold: true | |
| 92 | − | } | |
| 93 | − | MouseArea { | |
| 94 | − | anchors.fill: parent | |
| 95 | − | cursorShape: Qt.PointingHandCursor | |
| 96 | − | onClicked: Settings.accentIndex = sw.ci | |
| 97 | − | } | |
| 79 | + | model: ["tonal-spot", "vibrant", "expressive", "fidelity", "content", "fruit-salad", "rainbow", "neutral", "monochrome"] | |
| 80 | + | delegate: IconBtn { | |
| 81 | + | required property string modelData | |
| 82 | + | implicitHeight: 26 | |
| 83 | + | label: modelData | |
| 84 | + | active: Settings.matuScheme === "scheme-" + modelData | |
| 85 | + | onClicked: Settings.matuScheme = "scheme-" + modelData | |
| 98 | 86 | } | |
| 99 | 87 | } | |
| 100 | 88 | } | |
| 89 | + | Knob { label: "contrast"; from: -1; to: 1; decimals: 2; value: Settings.matuContrast; onMoved: v => Settings.matuContrast = v } | |
| 101 | 90 | ||
| 102 | 91 | SectionLabel { text: "sizes" } | |
| 103 | 92 | Knob { label: "font size"; from: 9; to: 18; value: Settings.fontSize; onMoved: v => Settings.fontSize = v } | |
| @@ -11,7 +11,7 @@ Singleton { | |||
| 11 | 11 | ||
| 12 | 12 | // defaults live here; reset() puts them back | |
| 13 | 13 | readonly property var defaults: ({ | |
| 14 | − | fontSize: 12, wsFontSize: 11, barHeight: 22, barAlpha: 1.0, panelAlpha: 0.88, accentIndex: 14, | |
| 14 | + | fontSize: 12, wsFontSize: 11, barHeight: 22, barAlpha: 1.0, panelAlpha: 0.88, matuScheme: "scheme-tonal-spot", matuContrast: 0.0, | |
| 15 | 15 | osdTimeout: 1500, desktopClock: true, desktopViz: true, vizBars: 64, | |
| 16 | 16 | dock: true, dockPinned: ["foot", "librewolf", "pcmanfm", "obsidian"], wallFolder: "dusky-dark", | |
| 17 | 17 | notifSound: true, notifVolume: 0.7, | |
| @@ -25,7 +25,8 @@ Singleton { | |||
| 25 | 25 | property alias barHeight: a.barHeight | |
| 26 | 26 | property alias barAlpha: a.barAlpha | |
| 27 | 27 | property alias panelAlpha: a.panelAlpha | |
| 28 | − | property alias accentIndex: a.accentIndex | |
| 28 | + | property alias matuScheme: a.matuScheme | |
| 29 | + | property alias matuContrast: a.matuContrast | |
| 29 | 30 | property alias osdTimeout: a.osdTimeout | |
| 30 | 31 | property alias desktopClock: a.desktopClock | |
| 31 | 32 | property alias desktopViz: a.desktopViz | |
| @@ -75,7 +76,8 @@ Singleton { | |||
| 75 | 76 | property int barHeight: 22 | |
| 76 | 77 | property real barAlpha: 1.0 | |
| 77 | 78 | property real panelAlpha: 0.88 | |
| 78 | − | property int accentIndex: 14 | |
| 79 | + | property string matuScheme: "scheme-tonal-spot" // matugen -t (Wall.qml), accent = its primary | |
| 80 | + | property real matuContrast: 0.0 // matugen --contrast, -1..1 | |
| 79 | 81 | property int osdTimeout: 1500 | |
| 80 | 82 | property bool desktopClock: true | |
| 81 | 83 | property bool desktopViz: true | |
| @@ -3,7 +3,7 @@ import QtQuick | |||
| 3 | 3 | import Quickshell | |
| 4 | 4 | import Quickshell.Io | |
| 5 | 5 | ||
| 6 | − | // pywal16 colours (~/.cache/wal/colors.json), hot-reloaded whenever `wal` runs. | |
| 6 | + | // matugen colours (~/.cache/matugen/aurora.json, written by Wall.apply/recolor), hot-reloaded on every run. | |
| 7 | 7 | Singleton { | |
| 8 | 8 | id: root | |
| 9 | 9 | ||
| @@ -12,79 +12,51 @@ Singleton { | |||
| 12 | 12 | readonly property int fontSize: Settings.fontSize | |
| 13 | 13 | readonly property int wsFontSize: Settings.wsFontSize // workspace icons only; everything else uses fontSize | |
| 14 | 14 | readonly property real panelAlpha: Settings.panelAlpha | |
| 15 | − | // your waybar uses @color14 for underlines/active workspace, so that is the default. | |
| 16 | − | // -1 auto-picks the most vivid of color1..color6 instead | |
| 17 | − | readonly property int accentIndex: Settings.accentIndex | |
| 18 | 15 | readonly property int barHeight: Settings.barHeight | |
| 19 | 16 | readonly property real barAlpha: Settings.barAlpha | |
| 20 | 17 | ||
| 21 | − | readonly property string walFile: Quickshell.env("HOME") + "/.cache/wal/colors.json" | |
| 18 | + | readonly property string matFile: Quickshell.env("HOME") + "/.cache/matugen/aurora.json" | |
| 22 | 19 | ||
| 20 | + | // flat keys from ~/.config/matugen/templates/aurora.json; defaults = a dark teal scheme for a fresh install | |
| 23 | 21 | FileView { | |
| 24 | − | path: root.walFile | |
| 22 | + | path: root.matFile | |
| 25 | 23 | watchChanges: true | |
| 26 | 24 | onFileChanged: reload() | |
| 27 | 25 | adapter: JsonAdapter { | |
| 28 | − | id: wal | |
| 29 | − | property JsonObject special: JsonObject { | |
| 30 | − | property string background: "#0b1514" | |
| 31 | − | property string foreground: "#cfe3df" | |
| 32 | − | property string cursor: "#cfe3df" | |
| 33 | − | } | |
| 34 | − | property JsonObject colors: JsonObject { | |
| 35 | − | property string color0: "#0b1514" | |
| 36 | − | property string color1: "#c0616b" | |
| 37 | − | property string color2: "#3fa593" | |
| 38 | − | property string color3: "#7fb6a8" | |
| 39 | − | property string color4: "#3a8f8a" | |
| 40 | − | property string color5: "#5f9f9a" | |
| 41 | − | property string color6: "#4fbfae" | |
| 42 | − | property string color7: "#cfe3df" | |
| 43 | − | property string color8: "#4a5f5c" | |
| 44 | − | property string color9: "#d97a84" | |
| 45 | − | property string color10: "#52c2ae" | |
| 46 | − | property string color11: "#9ad0c3" | |
| 47 | − | property string color12: "#4fb0a9" | |
| 48 | − | property string color13: "#78b8b2" | |
| 49 | − | property string color14: "#6fd6c5" | |
| 50 | − | property string color15: "#e3f2ef" | |
| 51 | − | } | |
| 26 | + | id: mat | |
| 27 | + | property string bg: "#0e1514" | |
| 28 | + | property string fg: "#dde4e2" | |
| 29 | + | property string primary: "#80d5cb" | |
| 30 | + | property string primaryFg: "#003733" | |
| 31 | + | property string primaryContainer: "#00504a" | |
| 32 | + | property string secondary: "#b1ccc7" | |
| 33 | + | property string tertiary: "#adcae6" | |
| 34 | + | property string surfaceLow: "#161d1c" | |
| 35 | + | property string surface: "#1a2120" | |
| 36 | + | property string surfaceHigh: "#252b2a" | |
| 37 | + | property string surfaceHighest: "#2f3635" | |
| 38 | + | property string outline: "#889391" | |
| 39 | + | property string outlineVariant: "#3f4947" | |
| 40 | + | property string surfaceVariantFg: "#bec9c6" | |
| 41 | + | property string err: "#ffb4ab" // no "error"/"onX" names: JsonAdapter signal / QML handler syntax | |
| 52 | 42 | } | |
| 53 | 43 | } | |
| 54 | 44 | ||
| 55 | − | readonly property var pal: [ | |
| 56 | − | wal.colors.color0, wal.colors.color1, wal.colors.color2, wal.colors.color3, | |
| 57 | − | wal.colors.color4, wal.colors.color5, wal.colors.color6, wal.colors.color7, | |
| 58 | − | wal.colors.color8, wal.colors.color9, wal.colors.color10, wal.colors.color11, | |
| 59 | − | wal.colors.color12, wal.colors.color13, wal.colors.color14, wal.colors.color15 | |
| 60 | − | ] | |
| 61 | − | ||
| 62 | − | function mix(a, b, t) { | |
| 63 | − | return Qt.rgba(a.r + (b.r - a.r) * t, a.g + (b.g - a.g) * t, a.b + (b.b - a.b) * t, 1) | |
| 64 | − | } | |
| 65 | − | ||
| 66 | − | function autoAccent() { | |
| 67 | − | var best = 4, score = -1 | |
| 68 | − | for (var i = 1; i <= 6; i++) { | |
| 69 | − | var c = Qt.color(pal[i]) | |
| 70 | − | var s = c.hsvSaturation * c.hsvValue | |
| 71 | − | if (s > score) { score = s; best = i } | |
| 72 | − | } | |
| 73 | − | return Qt.color(pal[best]) | |
| 74 | − | } | |
| 75 | − | ||
| 76 | 45 | // ---- palette ------------------------------------------------------ | |
| 77 | − | readonly property color bg: wal.special.background | |
| 78 | − | readonly property color fg: wal.special.foreground | |
| 79 | − | readonly property color accent: accentIndex >= 0 ? Qt.color(pal[accentIndex]) : autoAccent() | |
| 80 | − | readonly property color accentDim: mix(bg, accent, 0.45) | |
| 81 | − | readonly property color surface: mix(bg, fg, 0.06) | |
| 82 | − | readonly property color surfaceHi: mix(bg, fg, 0.14) | |
| 83 | − | readonly property color line: mix(bg, accent, 0.35) | |
| 84 | − | readonly property color dim: mix(bg, fg, 0.55) | |
| 85 | − | readonly property color err: Qt.color(pal[1]) | |
| 46 | + | readonly property color bg: mat.bg | |
| 47 | + | readonly property color fg: mat.fg | |
| 48 | + | readonly property color accent: mat.primary | |
| 49 | + | readonly property color accentFg: mat.primaryFg | |
| 50 | + | readonly property color accentDim: mat.primaryContainer | |
| 51 | + | readonly property color secondary: mat.secondary | |
| 52 | + | readonly property color tertiary: mat.tertiary | |
| 53 | + | readonly property color surface: mat.surface | |
| 54 | + | readonly property color surfaceHi: mat.surfaceHigh | |
| 55 | + | readonly property color line: mat.outlineVariant | |
| 56 | + | readonly property color dim: mat.surfaceVariantFg | |
| 57 | + | readonly property color err: mat.err | |
| 86 | 58 | readonly property color barBg: Qt.rgba(bg.r, bg.g, bg.b, barAlpha) | |
| 87 | − | readonly property color cursorC: wal.special.cursor | |
| 59 | + | readonly property color cursorC: mat.primary | |
| 88 | 60 | readonly property color bgA: Qt.rgba(bg.r, bg.g, bg.b, panelAlpha) | |
| 89 | 61 | ||
| 90 | 62 | // ---- hyprlock ----------------------------------------------------- | |
| @@ -4,7 +4,8 @@ import Quickshell | |||
| 4 | 4 | import Quickshell.Io | |
| 5 | 5 | ||
| 6 | 6 | // Wallpapers: folder listing, cached thumbnails, and applying them. aurora owns the wallpaper: | |
| 7 | − | // apply() writes hyprpaper.conf, switches hyprpaper live and runs `wal -i` (Theme then recolours itself). | |
| 7 | + | // apply() writes hyprpaper.conf, switches hyprpaper live, runs matugen (UI colours, Theme then recolours itself) | |
| 8 | + | // and pywal16 (terminal colours only). recolor() re-runs just matugen when the scheme/contrast setting changes. | |
| 8 | 9 | // ~/.local/bin/setwall is only a CLI front-end for the IPC calls (wallrandom / wall / wallset). | |
| 9 | 10 | Singleton { | |
| 10 | 11 | id: root | |
| @@ -21,6 +22,7 @@ Singleton { | |||
| 21 | 22 | property string current: "" // wallpaper hyprpaper is showing | |
| 22 | 23 | property bool loading: false | |
| 23 | 24 | property bool pendingRandom: false // random() asked before the folder was listed | |
| 25 | + | property bool checkedColours: false // matugen output checked once at startup | |
| 24 | 26 | ||
| 25 | 27 | function dirOf(name) { return name === "" ? rootDir : rootDir + "/" + name } | |
| 26 | 28 | function thumbOf(path) { return thumbDir + "/" + Qt.md5(path) + ".jpg" } | |
| @@ -46,11 +48,29 @@ Singleton { | |||
| 46 | 48 | 'printf "splash = false\\nwallpaper {\\n monitor =\\n path = %s\\n}\\n" "$p" > "$c"; ' + | |
| 47 | 49 | 'if pgrep -x hyprpaper >/dev/null; then hyprctl hyprpaper wallpaper ",$p"; ' + | |
| 48 | 50 | 'else hyprctl dispatch \'hl.dsp.exec_cmd("hyprpaper")\'; fi; ' + | |
| 49 | − | 'wal -i "$p" -n' | |
| 51 | + | 'matugen image "$p" -m dark -t "$3" --contrast="$4" --prefer saturation -q; ' + | |
| 52 | + | 'wal -i "$p" -n -q' | |
| 50 | 53 | function apply(path) { | |
| 51 | 54 | if (!path) return | |
| 52 | 55 | current = path | |
| 53 | − | Quickshell.execDetached(["sh", "-c", applyJob, "sh", path, conf]) | |
| 56 | + | Quickshell.execDetached(["sh", "-c", applyJob, "sh", path, conf, Settings.matuScheme, String(Settings.matuContrast)]) | |
| 57 | + | } | |
| 58 | + | ||
| 59 | + | // matugen only (UI colours). --prefer: v4 otherwise asks on stdin when the image has several source colours. | |
| 60 | + | // With "missing", only if there is no output yet (fresh install). | |
| 61 | + | readonly property string matuJob: | |
| 62 | + | '[ "$4" = missing ] && [ -f "$HOME/.cache/matugen/aurora.json" ] && exit 0; ' + | |
| 63 | + | 'matugen image "$1" -m dark -t "$2" --contrast="$3" --prefer saturation -q' | |
| 64 | + | function recolor(onlyIfMissing) { | |
| 65 | + | if (!current) return | |
| 66 | + | Quickshell.execDetached(["sh", "-c", matuJob, "sh", current, Settings.matuScheme, | |
| 67 | + | String(Settings.matuContrast), onlyIfMissing ? "missing" : ""]) | |
| 68 | + | } | |
| 69 | + | Timer { id: recolorLater; interval: 400; onTriggered: root.recolor(false) } | |
| 70 | + | Connections { | |
| 71 | + | target: Settings | |
| 72 | + | function onMatuSchemeChanged() { recolorLater.restart() } | |
| 73 | + | function onMatuContrastChanged() { recolorLater.restart() } | |
| 54 | 74 | } | |
| 55 | 75 | // random from the picker's folder (Settings.wallFolder), never the one already shown | |
| 56 | 76 | function random() { | |
| @@ -141,6 +161,7 @@ Singleton { | |||
| 141 | 161 | onLoaded: { | |
| 142 | 162 | var m = text().match(/^\s*path\s*=\s*(.+)$/m) | |
| 143 | 163 | if (m) root.current = m[1].trim() | |
| 164 | + | if (!root.checkedColours) { root.checkedColours = true; root.recolor(true) } | |
| 144 | 165 | } | |
| 145 | 166 | } | |
| 146 | 167 | } | |
| @@ -6,7 +6,7 @@ import Quickshell.Io | |||
| 6 | 6 | import Quickshell.Hyprland | |
| 7 | 7 | import Quickshell.Services.Pipewire | |
| 8 | 8 | ||
| 9 | − | // aurora: bar + control panel + notifications, themed from pywal16. | |
| 9 | + | // aurora: bar + control panel + notifications, themed from matugen. | |
| 10 | 10 | ShellRoot { | |
| 11 | 11 | id: root | |
| 12 | 12 | ||