quickshell: match mono icons by name, iconPath returns a URI

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
rope 2026-08-21 16:47:36 +01:00
parent d6dd93ea5a
commit 7c89ab366d

View file

@ -19,6 +19,33 @@ let
defaultWall = config.fred.theming.defaultWall; defaultWall = config.fred.theming.defaultWall;
themeApply = config.fred.theming.apply; themeApply = config.fred.theming.apply;
monoIcons = config.fred.theming.monoIcons; monoIcons = config.fred.theming.monoIcons;
# The set of app icons YAMIS actually ships, as a QML singleton.
#
# AppIcon needs to know whether a given icon came from the monochrome set
# (safe to flatten to one colour) or fell through to Papirus (not — see the
# component). It cannot tell from the resolved source: Quickshell.iconPath
# returns an "image://icon/<name>" provider URI, never a filesystem path,
# so there is no store path or theme directory in it to match on. The name
# is all we get, so the name is what we test.
#
# Built here rather than listed at eval time: reading the icon tree during
# evaluation would mean IFD, and hosts evaluate this straight from the
# Forgejo remote.
monoIconNames = pkgs.runCommand "MonoIcons.qml" { } ''
{
echo "pragma Singleton"
echo "import QtQuick"
echo "QtObject {"
printf ' readonly property var names: ['
for f in ${monoIcons}/apps/16/*.svg ${monoIcons}/apps/scalable/*.svg; do
[ -e "$f" ] || continue
basename "$f" .svg
done | sort -u | while read -r n; do printf '"%s",' "$n"; done
printf ']\n'
echo "}"
} > $out
'';
in in
{ {
config = lib.mkIf (lib.elem config.networking.hostName [ "FredOS-Gaming" "FredOS-Macbook" ]) { config = lib.mkIf (lib.elem config.networking.hostName [ "FredOS-Gaming" "FredOS-Macbook" ]) {
@ -386,11 +413,17 @@ in
channels = mono channels = mono
''; '';
in { in {
"quickshell/MonoIcons.qml" = {
onChange = qsRestart;
source = monoIconNames;
};
"quickshell/qmldir" = { "quickshell/qmldir" = {
onChange = qsRestart; onChange = qsRestart;
text = '' text = ''
singleton Theme 1.0 Theme.qml singleton Theme 1.0 Theme.qml
singleton Commands 1.0 Commands.qml singleton Commands 1.0 Commands.qml
singleton MonoIcons 1.0 MonoIcons.qml
Bar 1.0 Bar.qml Bar 1.0 Bar.qml
Lock 1.0 Lock.qml Lock 1.0 Lock.qml
Cheatsheet 1.0 Cheatsheet.qml Cheatsheet 1.0 Cheatsheet.qml
@ -1318,13 +1351,6 @@ in
readonly property string wxFetch: "${wxFetchScript}" readonly property string wxFetch: "${wxFetchScript}"
readonly property string xdgOpen: "${pkgs.xdg-utils}/bin/xdg-open" readonly property string xdgOpen: "${pkgs.xdg-utils}/bin/xdg-open"
readonly property string themeApply: "${themeApply}" readonly property string themeApply: "${themeApply}"
// Directory name of the monochrome icon theme. AppIcon tests
// a resolved icon path against this to decide whether it may
// be tinted see the component for why that is not blanket.
// A name, not the store path: lookups resolve through the
// /run/current-system/sw symlink farm, whose paths never
// contain the store prefix.
readonly property string monoIconDir: "/${baseNameOf monoIcons}/"
} }
''; '';
}; };
@ -1764,8 +1790,17 @@ in
id: _ai id: _ai
property string path: "" property string path: ""
property int size: 32 property int size: 32
readonly property bool mono: // iconPath hands back "image://icon/<name>", so the name
_ai.path !== "" && _ai.path.indexOf(Commands.monoIconDir) !== -1 // is the only thing to go on MonoIcons lists what YAMIS
// ships. Anything else (a real file path, a notification
// carrying its own image) is not ours to recolour.
readonly property bool mono: {
if (_ai.path.indexOf("image://icon/") !== 0) return false;
var n = _ai.path.substring(13);
var q = n.indexOf("?");
if (q !== -1) n = n.substring(0, q);
return MonoIcons.names.indexOf(n) !== -1;
}
width: size width: size
height: size height: size