Skip to content

fix(desktop): Group Linux windows under the installed launcher - #10895

Open
mwolson wants to merge 1 commit into
pingdotgg:mainfrom
mwolson:fix/linux-wayland-desktop-icon
Open

mwolson wants to merge 1 commit into
pingdotgg:mainfrom
mwolson:fix/linux-wayland-desktop-icon

Conversation

@mwolson

@mwolson mwolson commented Sep 9, 2026 •

Copy link
Copy Markdown
Contributor

What Changed

On Linux, the running T3 Code window now groups under its installed launcher
instead of showing up as a second dock icon that cannot be pinned. This covers
the AppImage, .deb and AUR packages.

Fixes #13975 deb-duplicate-dock-icon and addresses #10894
linux-wayland-desktop-icon.

Why

The window's X11 class and Wayland app id come from
setDesktopName("com.t3tools.T3Code.desktop"), but the installed launchers
advertised StartupWMClass=t3code. GNOME, Cinnamon and similar shells
therefore matched the window to the hidden URL-handler entry, which they will
not pin, and showed it next to the pinned launcher. The electron-builder
desktop entry and both AUR launchers now advertise
StartupWMClass=com.t3tools.T3Code. The window identity and capture bindings
are unchanged.

Theme icons named after the app id, the other half of the earlier version of
this PR, move to a follow-up PR.

UI Changes

The screenshots use Ubuntu 26.04 with GNOME Shell 50.1 on Wayland and Ubuntu
Dock. T3 Code is pinned, launched from the pin, closed, and relaunched from the
pin. Before is the 0.0.45-nightly.20260930.2493 .deb; after is this
change's .deb. The icon artwork differs only because the before build is a
Nightly. GNOME's window tracker assigned the window to the hidden
com.t3tools.T3Code.desktop entry before, and to the pinned
t3code.desktop after, on both launches.

Ubuntu Dock before and after

Before: the running window appears as a second dock entry.

Before: nightly .deb

After: the running window is grouped under the pinned launcher.

After: this PR's .deb

After: relaunched from the pinned launcher, still one entry.

After: relaunched from the pin

Reporters also confirmed the metadata change on Ubuntu GNOME/X11 with an
AppImage, Ubuntu 26.04 GNOME 50 Wayland with the .deb, and Linux Mint
Cinnamon on X11.

Known Limitations

Existing AppImageLauncher entries need re-integration to pick up the corrected
metadata. This does not migrate stale pinned IDs or remove entries for older
AppImages.

Checklist

  • This PR is small and focused
  • I explained what changed and why
  • I included before/after screenshots for any UI changes
  • I included a video for animation/interaction changes

Summary by CodeRabbit

  • New Features

    • Improved Linux desktop integration with consistent application icons for production and development installations.
    • Packaged icons are now installed in the appropriate user icon directories and refreshed when needed.
    • Desktop entries now reference the correct application icon and Wayland identity.
  • Bug Fixes

    • Prevented unnecessary icon copying and cache refreshes when the installed icons are already current.
    • Icon setup failures no longer prevent the desktop application from starting.

@github-actions github-actions Bot added vouch:trusted PR author is trusted by repo permissions or the VOUCHED list. size:L 100-499 changed lines (additions + deletions). labels Sep 9, 2026
@mwolson
mwolson force-pushed the fix/linux-wayland-desktop-icon branch from c72c0cc to 2bfde97 Compare September 9, 2026 05:15
@mwolson
mwolson marked this pull request as ready for review September 9, 2026 05:23
Comment thread apps/desktop/gnome-extension/metadata.json Outdated
@macroscopeapp

macroscopeapp Bot commented Sep 9, 2026 •

Copy link
Copy Markdown
Contributor

Approvability

Verdict: Approved at 473c734

Macroscope's review found this PR approvable — This is a small, self-contained Linux desktop integration fix that aligns launcher metadata with the existing runtime app identity and validates the generated configuration with a test. Its impact is limited to correct dock/window grouping, with no schema, security, deployment, or static-analysis changes.

Notes:

  • Diff unchanged. Approvability was decided on eligibility alone.

You can add or adjust custom eligibility rules. Learn more.

@mwolson
mwolson force-pushed the fix/linux-wayland-desktop-icon branch from 2bfde97 to 532afb5 Compare September 9, 2026 05:25
@cursor

cursor Bot commented Sep 9, 2026

Copy link
Copy Markdown
Contributor

Bugbot is paused — on-demand spend limit reached

Bugbot uses usage-based billing for this team and has hit its on-demand spend limit.

A team admin can raise the spend limit in the Cursor dashboard, or wait for the next billing cycle to continue.

@coderabbitai

coderabbitai Bot commented Sep 9, 2026 •

Copy link
Copy Markdown

Review Change StackReview Change Stack

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Essentials

Run ID: 7179063b-a3ec-4cf1-a5c3-13953861ac3a

📥 Commits

Reviewing files that changed from the base of the PR and between e16b8b0 and e23c2b8b5686346bf351f379a4deb10de3e89ed1.

📒 Files selected for processing (4)
  • apps/desktop/src/app/DesktopLinuxUrlHandler.test.ts
  • apps/desktop/src/app/DesktopLinuxUrlHandler.ts
  • apps/desktop/src/app/DesktopPreReadyPlatform.test.ts
  • apps/desktop/src/app/DesktopPreReadyPlatform.ts

📝 Walkthrough

Walkthrough

Linux desktop entries now use Icon=t3code. Linux pre-ready setup copies packaged hicolor icons into the user data directory and refreshes the icon cache when needed. Tests cover icon naming, copying, cache refresh behavior, and startup ordering.

Changes

Linux icon integration

Layer / File(s) Summary
Desktop entry and icon mapping
apps/desktop/src/app/DesktopLinuxUrlHandler.ts, apps/desktop/src/app/DesktopLinuxUrlHandler.test.ts
The hidden Linux desktop entry declares Icon=t3code. Helpers derive lowercase icon names and generate hicolor installation operations. Tests cover mixed-case desktop IDs and generated targets.
AppImage icon installation
apps/desktop/src/app/DesktopPreReadyPlatform.ts, apps/desktop/src/app/DesktopPreReadyPlatform.test.ts
Linux pre-ready setup copies changed AppImage icons, skips matching destinations, refreshes gtk-update-icon-cache, and completes copies before asynchronous layer work. Installation failures remain nonfatal.

Estimated code review effort: 3 (Moderate) | ~20 minutes

Priority: ➖ Normal

Severity of issue fixed: Low

Suggested reviewers: bil0000, juliusmarminge

Sequence Diagram(s)

sequenceDiagram
  participant DesktopPreReadyPlatform
  participant linuxDesktopIconInstallOperations
  participant APPDIR
  participant UserHicolorTree
  participant gtk-update-icon-cache
  DesktopPreReadyPlatform->>linuxDesktopIconInstallOperations: Build icon installation operations
  linuxDesktopIconInstallOperations-->>DesktopPreReadyPlatform: Return packaged and user icon paths
  DesktopPreReadyPlatform->>APPDIR: Read packaged icon metadata
  DesktopPreReadyPlatform->>UserHicolorTree: Copy changed icons
  DesktopPreReadyPlatform->>gtk-update-icon-cache: Refresh the icon cache
Loading

Merge Risk: ⚪ Minimal · up to fc4ce

Linux AppImage startup now installs the lowercase desktop identity and icon aliases needed for Wayland compositor icon lookup. The desktop-entry and icon-copy behavior are covered, with no current merge-blocking risk identified.

🚥 Pre-merge checks | ✅ 3 | ❌ 2

❌ Failed checks (2 warnings)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 22.22% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 9 functions across 19 files. Write docstrings for the functions missing them to satisfy the coverage threshold.
Description check ⚠️ Warning The description is largely inconsistent with the changes. It states that the window identity and capture bindings are unchanged and describes StartupWMClass changes, while the changes update Linux app… Rewrite the description to accurately document the lowercase com.t3tools.t3code app ID migration, renamed desktop entries, Icon=t3code metadata, packaged icon installation into the user theme, icon-cache refresh, affected Linux environments…
✅ Passed checks (3 passed)
Check name Status Explanation
Linked Issues check ✅ Passed The changes satisfy issue #10894 by updating the Wayland app ID, adding Icon=t3code, and copying packaged hicolor icons into the user icon theme.
Out of Scope Changes check ✅ Passed The changes remain focused on Linux desktop integration. Identifier updates in related runtime code, tests, documentation, and GNOME integration support the stated objectives.
Title check ✅ Passed The title clearly describes the Linux launcher-grouping goal addressed by the changes, although it does not mention the app ID and icon integration updates.
Full details: Description check

Explanation

The description is largely inconsistent with the changes. It states that the window identity and capture bindings are unchanged and describes StartupWMClass changes, while the changes update Linux app IDs, desktop entries, icon installation, and GNOME trust patterns.

Resolution

Rewrite the description to accurately document the lowercase com.t3tools.t3code app ID migration, renamed desktop entries, Icon=t3code metadata, packaged icon installation into the user theme, icon-cache refresh, affected Linux environments, and known limitations. Update the Why and UI Changes sections to match the actual implementation.

  • Fix all pre-merge checks with AI
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Comment @coderabbitai help to get the list of available commands.

@mwolson
mwolson force-pushed the fix/linux-wayland-desktop-icon branch 2 times, most recently from bc99164 to b395768 Compare September 9, 2026 05:39
macroscopeapp[bot]
macroscopeapp Bot previously approved these changes Sep 9, 2026
@mwolson
mwolson force-pushed the fix/linux-wayland-desktop-icon branch from b395768 to fc4ce90 Compare September 9, 2026 05:58
@cursor

cursor Bot commented Sep 9, 2026

Copy link
Copy Markdown
Contributor

Bugbot is paused — on-demand spend limit reached

Bugbot uses usage-based billing for this team and has hit its on-demand spend limit.

A team admin can raise the spend limit in the Cursor dashboard, or wait for the next billing cycle to continue.

@macroscopeapp
macroscopeapp Bot dismissed their stale review September 9, 2026 05:58

Dismissing prior approval to re-evaluate fc4ce90

Comment thread apps/desktop/src/app/DesktopPreReadyPlatform.ts Outdated
@mwolson
mwolson force-pushed the fix/linux-wayland-desktop-icon branch 4 times, most recently from a73be9a to 958ff97 Compare September 9, 2026 16:16
@mwolson mwolson changed the title fix(desktop): Use lowercase Linux Wayland app id and install icons fix(desktop): Install lowercase Linux icons for Wayland overview Sep 9, 2026
@mwolson
mwolson force-pushed the fix/linux-wayland-desktop-icon branch from 958ff97 to 28ff6c3 Compare September 9, 2026 16:28
@mwolson
mwolson marked this pull request as draft September 9, 2026 16:30
@mwolson
mwolson force-pushed the fix/linux-wayland-desktop-icon branch 5 times, most recently from d637097 to e23c2b8 Compare September 9, 2026 18:29
@mwolson
mwolson marked this pull request as ready for review September 9, 2026 18:40
@cursor

cursor Bot commented Sep 9, 2026

Copy link
Copy Markdown
Contributor

Bugbot is paused — on-demand spend limit reached

Bugbot uses usage-based billing for this team and has hit its on-demand spend limit.

A team admin can raise the spend limit in the Cursor dashboard, or wait for the next billing cycle to continue.

@mwolson
mwolson force-pushed the fix/linux-wayland-desktop-icon branch from e23c2b8 to 7a18e2a Compare September 9, 2026 22:07
@mwolson mwolson changed the title fix(desktop): Install lowercase Linux icons for Wayland overview fix(desktop): Restore Linux icons and GNOME dock pinning Sep 9, 2026
Comment thread scripts/build-desktop-artifact.ts

@eliath eliath left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reproduced on Ubuntu GNOME/X11 with nightly AppImage 0.0.41-nightly.20260911.1551

The root cause mentioned here matches my investigation: the generated com.t3tools.T3Code.desktop is rewritten on each launch without Icon=. This change fixes it.

@denniskasper

Copy link
Copy Markdown

Built and tested this branch on GNOME 46 with an AppImage. One finding.

Ubuntu 24.04.5, GNOME Shell 46.0 on X11, Ubuntu Dock v90. I fetched the PR head, rebased onto current main (d7819c1881, clean — your base was 12 days back), built the Linux AppImage, and launched it with an isolated HOME so it could not touch my daily install.

Everything the PR claims, it does. The entry it wrote carries Icon=t3code, and both names land in the theme:

hicolor/256x256/apps/t3code.png                20991
hicolor/256x256/apps/com.t3tools.t3code.png    20991
hicolor/icon-theme.cache                       160

GTK resolves them, so this is not just files in the right place:

t3code             -> …/hicolor/256x256/apps/t3code.png
com.t3tools.t3code -> …/hicolor/256x256/apps/com.t3tools.t3code.png
com.t3tools.T3Code -> NOT FOUND

The finding is that third line. The window's identity is mixed-case com.t3tools.T3Code (WM_CLASS = "com.t3tools.t3code", "com.t3tools.T3Code"), but linuxDesktopIconNames lowercases before installing. Icon theme lookups are case-sensitive, so a shell that uses the literal app id as an icon name — rather than lowercasing it like Noctalia, or resolving through the desktop file like GNOME — still finds nothing. Adding the un-lowercased name looks like a one-line change.

Scope limits, so this isn't read as more than it is: the isolated HOME means GNOME's own dash never saw these files, so I did not verify pinning or favorites, only that the files are installed and resolvable. X11, not Wayland. I also did not test AppImageLauncher re-integration.

Separately: _NET_WM_ICON on the main window is present but empty, on this build and on the released one. The window carries no icon of its own, so the entry and theme are doing all the work. Possibly relevant for X11 shells that prefer the window property.

I hit this bug independently before finding #10894 and reached the same diagnosis.

Prepared with Claude Opus 5 via Claude Code.

@TonybynMp4

TonybynMp4 commented Sep 27, 2026 •

Copy link
Copy Markdown
Contributor

Confirmed this fixes the duplicate dock icon for the official .deb too (#13975).

I merged this branch onto current main (it predates the .deb target but merges cleanly) and built a .deb. The packaged /usr/share/applications/t3code.desktop differs from the official nightly's (0.0.43-nightly.20260927.2344) only by StartupWMClass=t3code → StartupWMClass=com.t3tools.T3Code. The rest of the package outside /opt is identical.

I then applied that same .desktop on the installed official nightly .deb and relaunched from the pinned favourite. The window now groups under the pinned T3 Code icon, and the second generic icon is gone. Ubuntu 26.04.1, GNOME Shell 50.1, Wayland.

@mwolson
mwolson force-pushed the fix/linux-wayland-desktop-icon branch from 7a18e2a to 07f6c6c Compare September 30, 2026 03:23
Comment thread apps/desktop/src/app/DesktopPreReadyPlatform.ts Outdated
@mwolson
mwolson force-pushed the fix/linux-wayland-desktop-icon branch from 07f6c6c to 0f9f287 Compare September 30, 2026 13:17
@mwolson

mwolson commented Sep 30, 2026

Copy link
Copy Markdown
Contributor Author

Thanks for testing on GNOME 46. You're right that theme lookup is case-sensitive, and the branch now also installs com.t3tools.T3Code.png. GNOME and Ubuntu Dock don't use it: they take the icon from the matched desktop entry, so on your setup the StartupWMClass change is what matters.

Where the literal filename is used:

  • Noctalia 5.x (5.0.0 through 5.2.0) requires it. Its taskbar skips NoDisplay entries and, when no visible entry matches, falls back to a case-sensitive theme lookup of the app id. That happens with an AppImage run without integration, or an older integration still carrying StartupWMClass=t3code. Noctalia 4.x resolves the hidden entry first and doesn't need it.
  • LXQt panel 2.3.0 on wlroots looks up the app id as a theme icon, first exactly as given and then lowercased. It finds com.t3tools.T3Code.png first, but would also find com.t3tools.t3code.png, so it doesn't strictly need the new file.
  • DankMaterialShell 1.6.2 uses the literal app id as a theme icon when no desktop entry resolves.
  • Waybar 0.14.0 (wlr/taskbar, hyprland/workspaces) tries the matched entry's StartupWMClass as a theme icon before the entry's Icon. It uses com.t3tools.T3Code if the visible launcher is matched.

_NET_WM_ICON isn't actually empty: T3 sets a 1024×1024 icon (about 4 MB). xprop reads at most 500,000 bytes by default and prints nothing when the first icon is cut off; xprop -len 16000000 _NET_WM_ICON shows Icon (1024 x 1024). GNOME 46 doesn't read the property anyway.

@juliusmarminge juliusmarminge left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The code looks ready at this head. The 99 focused desktop/startup/packaging tests passed locally, and the earlier blocking-startup and same-size stale-icon findings are fixed. Electron's window identity behavior also supports the StartupWMClass change.

Please add before/after screenshots before merging, as required by this repository's UI-change instructions. Show the affected Linux dock/overview state, including the corrected icon and the running window grouped under the visible launcher. A short recording is useful if demonstrating pinning and relaunch rather than static screenshots. Existing reviewer reports are useful, but the PR currently explicitly omits visual evidence.

This request is for review evidence, not a code defect. I did not perform desktop visual verification.

Reviewed with GPT-6 in Codex.

@mwolson

mwolson commented Sep 30, 2026

Copy link
Copy Markdown
Contributor Author

Screenshots

@juliusmarminge Added before/after screenshots, also inlined in the description. Ubuntu 26.04, GNOME Shell 50.1 on Wayland, Ubuntu Dock. T3 Code is pinned, launched from the pin, closed, and relaunched from it. Before is today's nightly .deb (0.0.45-nightly.20260930.2493), after is this PR's .deb; the icon artwork differs only because the before build is a Nightly. GNOME's window tracker put the window on the hidden com.t3tools.T3Code.desktop before and on the pinned t3code.desktop after, on both launches.

Ubuntu Dock before and after

Before: the running window appears as a second dock entry.

Before: nightly .deb

After: the running window is grouped under the pinned launcher.

After: this PR's .deb

After: relaunched from the pinned launcher, still one entry.

After: relaunched from the pin

@juliusmarminge juliusmarminge left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The StartupWMClass=com.t3tools.T3Code change is correct: Electron derives the app id from setDesktopName, and electron-builder's desktop entry requires StartupWMClass to match. It is set everywhere it needs to be (the electron-builder entry for AppImage and .deb, plus both PKGBUILDs), and it fixes #13975 on its own. I'd happily merge that part now. Could you split it into its own PR? The icon-copy half needs changes first:

  1. Drop the t3code icon name (DesktopLinuxUrlHandler.ts#L94-L101). Stable and nightly both use executableName: "t3code". So running a nightly AppImage copies the nightly icon to ~/.local/share/icons/hicolor/256x256/apps/t3code.png, which hides the stable .deb/AUR icon in /usr/share. Stable and nightly AppImages then overwrite each other's copy on every launch, and nothing removes the copies afterwards. The shells this targets look up com.t3tools.t3code or com.t3tools.T3Code, never t3code, and the hidden handler entry already has an absolute Icon= since #8673.
  2. Don't create a user icon cache (DesktopPreReadyPlatform.ts#L38-L54). gtk-update-icon-cache -f -t usually creates ~/.local/share/icons/hicolor/icon-theme.cache where none existed. Only T3 then keeps it current, so GTK apps can miss icons that other tools add later. Please drop the refresh, or only run it when the cache already exists.
  3. Move the icon install out of pre-ready. The icons aren't needed until the window maps. Doing it next to the existing update-desktop-database call in DesktopLinuxUrlHandler lets it use Effect FileSystem/ChildProcessSpawner with a timeout. That also removes the node:child_process import, the raw setTimeout, the globalTimers:off opt-out and posixJoin, and takes the work off synchronous startup.
  4. Tests: the new DesktopPreReadyPlatform tests mock fs and child_process wholesale, and the spawn mock's on does nothing, so the timeout, kill and error handling go untested. After the move, one or two tests against a real temp directory would cover more with less code.

Small follow-up, not blocking: --class=t3code / linuxWmClass no longer affects the window class and could be removed.

The running window's X11 class and Wayland app id come from
setDesktopName("com.t3tools.T3Code.desktop"), but the AppImage, .deb and
AUR launchers advertised StartupWMClass=t3code. GNOME, Cinnamon and
similar shells then matched the window to the hidden URL-handler entry,
showing a second dock icon that cannot be pinned.

Advertise StartupWMClass=com.t3tools.T3Code in the electron-builder
desktop entry and both AUR launchers.
@mwolson
mwolson force-pushed the fix/linux-wayland-desktop-icon branch from 0f9f287 to 473c734 Compare September 30, 2026 18:18
@mwolson mwolson changed the title fix(desktop): Restore Linux icons and GNOME dock pinning fix(desktop): Group Linux windows under the installed launcher Sep 30, 2026
@mwolson

mwolson commented Sep 30, 2026

Copy link
Copy Markdown
Contributor Author

Split as suggested. This PR is now only StartupWMClass=com.t3tools.T3Code
(electron-builder entry for the AppImage and .deb, plus both PKGBUILDs), with
the dock screenshots. The theme icons moved to #14471 linux-app-id-theme-icons with your four
points addressed:

  1. Only com.t3tools.t3code and com.t3tools.T3Code are installed; no
    t3code.
  2. icon-theme.cache is never created. An existing one is refreshed after an
    icon changes, or when it is older than the installed icons, which also
    retries a refresh that failed on an earlier launch.
  3. The install runs in DesktopLinuxUrlHandler next to
    update-desktop-database, with Effect FileSystem and
    ChildProcessSpawner. Pre-ready is untouched.
  4. The tests use a real temp directory: fresh install, same-length stale
    icons, a failed then recovered refresh, a missing source, a missing cache
    tool, a stalled refresh, and a cache dated after the icons.

One thing I hit on the way: Effect.timeout on exitCode does not bound the
scope's release. Without forceKillAfter, a helper that ignores SIGTERM keeps
the scope waiting indefinitely; I checked this against the real spawner. The
new cache refresh sets forceKillAfter: "1 second". The existing
update-desktop-database and xdg-mime calls have the same gap, which I left
alone here.

I'll send the --class=t3code cleanup separately.

@github-actions github-actions Bot added size:XS 0-9 changed lines (additions + deletions). and removed size:L 100-499 changed lines (additions + deletions). labels Sep 30, 2026
@mwolson

mwolson commented Sep 30, 2026

Copy link
Copy Markdown
Contributor Author

Following up on the --class note: #14482 linux-drop-class-switch removes it. It no longer affects the main window, but it still set the X11 class of T3's own GTK folder picker when no file-chooser portal is running (t3code becomes T3code). The PR has before/after screenshots from GNOME on X11 and Wayland and from XFCE, with no visible difference. SnapShots are unaffected: they run only in Wayland sessions, take their identity from the desktop entry name, and find T3's window by process id and title.

@juliusmarminge juliusmarminge added the macroscope-review Opt PRs made by unvouched contributors in for Macroscope review. Vouched contributors auto-reviews label Oct 1, 2026 — with ChatGPT Codex Connector

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

macroscope-review Opt PRs made by unvouched contributors in for Macroscope review. Vouched contributors auto-reviews size:XS 0-9 changed lines (additions + deletions). vouch:trusted PR author is trusted by repo permissions or the VOUCHED list.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug]: .deb install on Wayland shows a second, generic dock icon

5 participants