omarchy-webapp-install: set StartupWMClass so app switchers find the icon#5934
Open
andyjeffries wants to merge 1 commit into
Open
omarchy-webapp-install: set StartupWMClass so app switchers find the icon#5934andyjeffries wants to merge 1 commit into
andyjeffries wants to merge 1 commit into
Conversation
App switchers (hyprswitch, plank, etc.) and launchers resolve a window's icon by matching its WM_CLASS against StartupWMClass= in installed .desktop files. Web apps created by omarchy-webapp-install currently omit StartupWMClass, so they show a generic fallback (cog) icon in the switcher instead of the icon configured in the .desktop file. Chromium-family browsers derive WM_CLASS for --app=<URL> as <prefix>-<host>/<path>-Default with the port stripped, '/' replaced with '_', and an empty path normalized to '/'. We compute that string from APP_URL and write it into the .desktop file. The browser prefix is taken from the current xdg default-web-browser; unknown browsers are skipped silently so the .desktop file is unchanged from today's behavior in those cases. Note: this is best-effort. Two web apps on the same host that differ only by port will collide on a single WM_CLASS (a Chromium limitation in --app= mode). For most webapps (one per host), the icon resolves correctly.
Contributor
There was a problem hiding this comment.
Copilot wasn't able to review any files in this pull request.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
App switchers and launchers that look up window icons via
StartupWMClass(e.g. hyprswitch, plank, others) show a generic fallback icon — typically a cog — for windows created byomarchy-webapp-install. The icon is configured in the.desktopfile'sIcon=line, but without aStartupWMClass=entry there's no way for the switcher to map the running window's class to the.desktopfile, so the configured icon is never used.Reproduction on current
dev:omarchy-webapp-install Figma https://figma.com/ <icon-url>Super+Tab(or any switcher that does icon lookup via XDG). The Figma window shows the fallback cog instead of the configured Figma icon.hyprswitch debug search --class brave-figma.com__-Defaultconfirms the cause:After this PR, the same lookup resolves:
Fix
Chromium-family browsers derive
WM_CLASSfor--app=<URL>deterministically aswith the port stripped, every
/replaced with_, and an empty path normalized to/. We compute that string fromAPP_URLand appendStartupWMClass=<class>to the generated.desktopfile.The browser prefix is taken from
xdg-settings get default-web-browserand mapped to one of the prefixes Chromium-family browsers use (brave,google-chrome,microsoft-edge,vivaldi,opera,helium,chromium). Unknown browsers are skipped silently so the.desktopfile is unchanged in those cases — no regression risk.The block is also skipped when
CUSTOM_EXECis set, since the resulting class is not predictable fromAPP_URLalone in that case.Verification
Encoding was checked against eight live web-app windows (
hyprctl clients) running under Brave 148:https://discord.com/channels/@mebrave-discord.com__channels_@me-Defaulthttps://www.icloud.com/calendar/brave-www.icloud.com__calendar_-Defaulthttps://web.whatsapp.com/brave-web.whatsapp.com__-Defaulthttps://claude.ai/brave-claude.ai__-Defaulthttp://media.local:8636brave-media.local__-Defaulthttps://calendar.google.com/calendar/u/1/r?pli=1brave-calendar.google.com__calendar_u_1_r-Defaulthttps://figma.com/brave-figma.com__-Defaulthttp://media.local:32400/webbrave-media.local__web-DefaultImplementation is pure bash parameter expansion — no new dependencies.
Known limitation
Chromium strips the port from
WM_CLASSfor--app=windows, and--class=is silently ignored when the browser is already running with the same user-data-dir. So two web apps on the same host that differ only by port will collide on a singleStartupWMClass. The icon resolved will be whichever.desktopfile the cache finds first. Window titles still differentiate them in the switcher; only the icon collides. This is unchanged from today's behavior (today it's broken for everyone; after this PR it's correct for the common single-host case and unchanged for the multi-port case).A possible follow-up would be to opt into per-app
--user-data-dir+--classfor cases where shared login state isn't needed (e.g. internal services); happy to send a separate PR if that's of interest.