bar: allow setting custom workspace app icons in shell.json (#1214)

* bar: allow setting custom workspace app icons in shell.json

* rename to windowIcons and use regex field for regex

Also allow specifying regex flags and exact name

* add default config (fix steam icons)

---------

Co-authored-by: 2 * r + 2 * t <61896496+soramanew@users.noreply.github.com>
This commit is contained in:
Xavier Lhinares 2026-03-15 16:17:49 +08:00 committed by GitHub
parent 197eafdadc
commit 63c86e950b
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 40 additions and 5 deletions

View file

@ -420,6 +420,12 @@ default, you must create it manually.
"name": "steam",
"icon": "sports_esports"
}
],
"windowIcons": [
{
"regex": "steam(_app_(default|[0-9]+))?",
"icon": "sports_esports"
}
]
},
"excludedScreens": [""],

View file

@ -79,6 +79,12 @@ JsonObject {
property string activeLabel: "󰮯"
property string capitalisation: "preserve" // upper, lower, or preserve - relevant only if label is empty
property list<var> specialWorkspaceIcons: []
property list<var> windowIcons: [
{
regex: "steam(_app_(default|[0-9]+))?",
icon: "sports_esports"
}
]
}
component ActiveWindow: JsonObject {

View file

@ -176,7 +176,8 @@ Singleton {
occupiedLabel: bar.workspaces.occupiedLabel,
activeLabel: bar.workspaces.activeLabel,
capitalisation: bar.workspaces.capitalisation,
specialWorkspaceIcons: bar.workspaces.specialWorkspaceIcons
specialWorkspaceIcons: bar.workspaces.specialWorkspaceIcons,
windowIcons: bar.workspaces.windowIcons
},
activeWindow: {
compact: bar.activeWindow.compact,

View file

@ -79,6 +79,26 @@ Singleton {
Office: "content_paste"
})
// Checks if a name matches an icon config. Icon configs can have the following keys:
// - name: The exact name of the icon
// - regex: A regex to match against the name (takes priority over name)
// - flags: The regex flags (only used if regex is set)
// - icon: The icon to use
function matchIconConfig(name: string, iconConfig: var): bool {
if (!iconConfig.icon)
return false;
if (iconConfig.regex) {
const re = new RegExp(iconConfig.regex, iconConfig.flags ?? "");
if (re.test(name))
return true;
} else if (iconConfig.name === name) {
return true;
}
return false;
}
function getAppIcon(name: string, fallback: string): string {
const icon = DesktopEntries.heuristicLookup(name)?.icon;
if (fallback !== "undefined")
@ -87,6 +107,10 @@ Singleton {
}
function getAppCategoryIcon(name: string, fallback: string): string {
for (const iconConfig of Config.bar.workspaces.windowIcons)
if (matchIconConfig(name, iconConfig))
return iconConfig.icon;
const categories = DesktopEntries.heuristicLookup(name)?.categories;
if (categories)
@ -188,11 +212,9 @@ Singleton {
function getSpecialWsIcon(name: string): string {
name = name.toLowerCase().slice("special:".length);
for (const iconConfig of Config.bar.workspaces.specialWorkspaceIcons) {
if (iconConfig.name === name) {
for (const iconConfig of Config.bar.workspaces.specialWorkspaceIcons)
if (matchIconConfig(name, iconConfig))
return iconConfig.icon;
}
}
if (name === "special")
return "star";