quickshell: tint YAMIS app icons to the wallpaper palette
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_017EHJfY5Q72punsWX38nY1w
This commit is contained in:
parent
cb7b576a71
commit
1bea54f30c
2 changed files with 81 additions and 23 deletions
|
|
@ -18,6 +18,7 @@ let
|
|||
wallsJson = builtins.toJSON config.fred.theming.walls;
|
||||
defaultWall = config.fred.theming.defaultWall;
|
||||
themeApply = config.fred.theming.apply;
|
||||
monoIcons = config.fred.theming.monoIcons;
|
||||
in
|
||||
{
|
||||
config = lib.mkIf (lib.elem config.networking.hostName [ "FredOS-Gaming" "FredOS-Macbook" ]) {
|
||||
|
|
@ -1312,6 +1313,10 @@ in
|
|||
readonly property string wxFetch: "${wxFetchScript}"
|
||||
readonly property string xdgOpen: "${pkgs.xdg-utils}/bin/xdg-open"
|
||||
readonly property string themeApply: "${themeApply}"
|
||||
// Prefix of the monochrome app-icon tree. AppIcon tests a
|
||||
// resolved icon path against this to decide whether it may
|
||||
// be tinted — see the component for why that is not blanket.
|
||||
readonly property string monoIconDir: "${monoIcons}"
|
||||
}
|
||||
'';
|
||||
};
|
||||
|
|
@ -1730,6 +1735,53 @@ in
|
|||
// act on. Stroke weight is fixed by the design.
|
||||
}
|
||||
|
||||
// ── AppIcon: an application icon in a square slot, tinted to
|
||||
// the wallpaper's text colour when — and only when — it came
|
||||
// from the monochrome set.
|
||||
//
|
||||
// YAMIS declares FollowsColorScheme=true, which is a KDE key:
|
||||
// only Plasma rewrites the <style> block inside each SVG, so
|
||||
// here every icon would otherwise render at the fixed #d8dee9
|
||||
// baked into the file and sit dead against a themed bar.
|
||||
// Overlaying at draw time follows the palette live and costs
|
||||
// no disk copy (the same hidden-Image trick as the tray).
|
||||
//
|
||||
// The test is deliberately narrow rather than tinting every
|
||||
// icon. A few apps have no YAMIS icon and fall through to
|
||||
// Papirus, whose artwork encodes its detail as colour
|
||||
// separation — Spotify's waves are white-on-green, not cut
|
||||
// out of the shape. Flatten one of those and you get a
|
||||
// featureless blob, so full-colour fallbacks are left alone.
|
||||
component AppIcon: Item {
|
||||
id: _ai
|
||||
property string path: ""
|
||||
property int size: 32
|
||||
readonly property bool mono:
|
||||
_ai.path !== "" && _ai.path.indexOf(Commands.monoIconDir) !== -1
|
||||
|
||||
width: size
|
||||
height: size
|
||||
|
||||
Image {
|
||||
id: _aiImg
|
||||
anchors.fill: parent
|
||||
source: _ai.path
|
||||
sourceSize.width: _ai.size
|
||||
sourceSize.height: _ai.size
|
||||
smooth: true
|
||||
mipmap: true
|
||||
// Hidden only when the overlay is drawing in its
|
||||
// place; ColorOverlay reads it as a texture either way.
|
||||
visible: _ai.path !== "" && !_ai.mono
|
||||
}
|
||||
ColorOverlay {
|
||||
anchors.fill: _aiImg
|
||||
source: _aiImg
|
||||
visible: _ai.mono
|
||||
color: Theme.base05
|
||||
}
|
||||
}
|
||||
|
||||
// ── BarSep: extra whitespace between widget groups. Groups are
|
||||
// separated by air, not by lines — a drawn rule read as clutter
|
||||
// in a 46px column.
|
||||
|
|
@ -1981,14 +2033,13 @@ in
|
|||
Row {
|
||||
width: parent.width
|
||||
spacing: 4
|
||||
visible: _nc.notif && (_nc.notif.appName !== "" || _appIcon.source != "")
|
||||
Image {
|
||||
visible: _nc.notif && (_nc.notif.appName !== "" || _appIcon.path != "")
|
||||
AppIcon {
|
||||
id: _appIcon
|
||||
width: 14; height: 14
|
||||
sourceSize.width: 14; sourceSize.height: 14
|
||||
size: 14
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
source: _nc.notif && _nc.notif.appIcon ? Quickshell.iconPath(_nc.notif.appIcon, true) : ""
|
||||
visible: source != ""
|
||||
path: _nc.notif && _nc.notif.appIcon ? Quickshell.iconPath(_nc.notif.appIcon, true) : ""
|
||||
visible: path != ""
|
||||
}
|
||||
SText {
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
|
|
@ -3320,14 +3371,10 @@ in
|
|||
anchors.centerIn: parent
|
||||
spacing: 4
|
||||
|
||||
Image {
|
||||
AppIcon {
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
visible: source != ""
|
||||
width: 28
|
||||
height: 28
|
||||
sourceSize.width: 28
|
||||
sourceSize.height: 28
|
||||
source: pinCell.icon
|
||||
path: pinCell.icon
|
||||
size: 28
|
||||
}
|
||||
SText {
|
||||
width: pinCell.width - 12
|
||||
|
|
@ -3490,12 +3537,10 @@ in
|
|||
width: 32
|
||||
height: 32
|
||||
|
||||
Image {
|
||||
AppIcon {
|
||||
anchors.fill: parent
|
||||
visible: source != ""
|
||||
sourceSize.width: 32
|
||||
sourceSize.height: 32
|
||||
source: icon
|
||||
path: icon
|
||||
size: 32
|
||||
}
|
||||
SIcon {
|
||||
anchors.centerIn: parent
|
||||
|
|
|
|||
|
|
@ -304,11 +304,19 @@ let
|
|||
# so the "build" is a copy into the directory name the spec resolves by.
|
||||
#
|
||||
# FollowsColorScheme=true is a KDE key: only Plasma rewrites the embedded
|
||||
# <style id="current-color-scheme"> block. Anywhere else — quickshell and
|
||||
# GTK here — the icons render at that block's literal fallback, #d8dee9,
|
||||
# a cool light grey that reads on every wallpaper's dark bar. Tinting per
|
||||
# wallpaper would mean a sed over all 6101 files per theme, so the app
|
||||
# icons deliberately stay one fixed colour while the folders track.
|
||||
# <style id="current-color-scheme"> block. Anywhere else the icons render
|
||||
# at that block's literal fallback, #d8dee9, and never track the wallpaper.
|
||||
#
|
||||
# Rewriting that string on disk would mean a copy of all 6101 files per
|
||||
# wallpaper — 75MB across the set, and a 15MB rm -rf + cp inside
|
||||
# theme-apply on every switch, which is the one path that has to stay
|
||||
# quick. quickshell tints these at draw time instead (ColorOverlay against
|
||||
# base05, the same trick the tray uses), so the launcher follows the
|
||||
# palette live and nothing is copied. monoIcons below hands it the prefix
|
||||
# that identifies a YAMIS icon.
|
||||
#
|
||||
# Consequence: GTK apps still see #d8dee9. That is fine on these dark
|
||||
# themes, and it is the only consumer that reads these files directly.
|
||||
yamisIcons = pkgs.runCommand "yamis-icon-theme" { } ''
|
||||
mkdir -p $out/share/icons
|
||||
cp -r ${pkgs.fetchgit {
|
||||
|
|
@ -569,6 +577,10 @@ in
|
|||
};
|
||||
defaultWall = lib.mkOption { internal = true; type = lib.types.str; };
|
||||
apply = lib.mkOption { internal = true; type = lib.types.path; };
|
||||
# The installed YAMIS tree. quickshell needs the prefix to tell a
|
||||
# monochrome icon from a Papirus fallback at draw time — see the tint
|
||||
# note on yamisIcons above.
|
||||
monoIcons = lib.mkOption { internal = true; type = lib.types.str; };
|
||||
};
|
||||
|
||||
config = lib.mkMerge [{
|
||||
|
|
@ -603,6 +615,7 @@ in
|
|||
fred.theming = {
|
||||
inherit walls defaultWall;
|
||||
apply = themeApply;
|
||||
monoIcons = "${yamisIcons}/share/icons/yet-another-monochrome-icon-set";
|
||||
};
|
||||
|
||||
# Papirus-Fred inherits this by name, so it has to be on the icon search
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue