Skip to content

feat(flet build linux): show the app's icon and name in the dock with a desktop entry while it runs - #7001

Open
ndonkoHenri wants to merge 2 commits into
flet-1.1.0from
feat/linux-desktop-entry
Open

ndonkoHenri wants to merge 2 commits into
flet-1.1.0from
feat/linux-desktop-entry

Conversation

@ndonkoHenri

@ndonkoHenri ndonkoHenri commented Oct 26, 2026 •

Copy link
Copy Markdown
Contributor

#6799 gave flet build linux apps a window icon and shipped a desktop entry in the bundle, under share/. But most desktops never read that window icon:

  • Wayland: the protocol has no window icon. The dock looks the app up by its app id in the installed .desktop entries.
  • X11 on GNOME Shell 46+ (Ubuntu 24.04): GNOME looks the app up the same way and ignores _NET_WM_ICON.

Until the user copies share/ into ~/.local/share by hand, the dock shows a generic icon, and its tooltip shows the bundle id (com.example.my_app) instead of the product name.

This PR makes the app install that entry for the current user while it runs.

What the app does

  • On start: it writes $XDG_DATA_HOME/applications/<bundle_id>.desktop (~/.local/share by default), built from the entry in the bundle. Exec= gets the executable's absolute path ($APPIMAGE for an AppImage), and Icon= gets a copy of the icon in $XDG_RUNTIME_DIR/flet/<bundle_id>/. The dock picks it up live, with no relaunch.
  • Hidden from launchers: the entry has NoDisplay=true, so the app doesn't appear in the app grid or launcher search. Launchers still list its open window.
  • Removed on exit: the last running instance deletes the entry, on a normal quit, on atexit, and on SIGTERM, SIGINT and SIGHUP. Per-instance markers in the runtime dir track whether another instance is still running. If the app is killed hard, or calls sys.exit() (which skips cleanup), the next start rewrites the entry.
  • The file name must be <bundle_id>.desktop. I tested a separately named entry with StartupWMClass, and GNOME on Wayland didn't match it.

What the app leaves alone

  • An entry the user installed themselves with the same name (no X-Flet-Generated key). Also an unreadable entry or a symlink, which is checked with lstat.
  • An entry a package installed system-wide (e.g. a .deb app). If one exists, the app removes its own user entry, which would otherwise hide the system one. The bundle's own share/ is excluded from that scan by st_dev/st_ino.
  • Flatpak and Snap, which register their own entries (FLATPAK_ID / SNAP).
  • Paths containing %. GLib checks that Exec= exists using the raw path, so the escaped %% makes it reject the entry.

Apps can turn this off:

[tool.flet.linux]
desktop_entry = false

Trade-off: an entry that only exists while the app runs means pinning a portable app to the dock lasts only while it runs. Users who want a permanent pin or an app-grid entry can still install the entry and icon from share/. The docs cover this, as does the AppImage note.

Screenshots

All shots are from the same arm64 test app (flet build linux, product "Icon Probe"). Before is the same app built with desktop_entry = false, which installs no entry: that's what flet-1.1.0 apps get today. Its product name is therefore "Icon Probe Optout".

Ubuntu 24.04, GNOME 46, Wayland. The icon and the tooltip name are both fixed:

Ubuntu 24.04 GNOME 46 dock before and after

Fedora 44, GNOME 50, Wayland (overview dash):

Fedora 44 GNOME 50 dash before and after

Fedora 44, KDE Plasma, Wayland:

Fedora 44 KDE Plasma taskbar before and after

Pop!_OS 24.04, COSMIC, Wayland:

Pop!_OS 24.04 COSMIC dock before and after

Kali, Xfce, X11. This one already worked from the window icon, and nothing changes:

Kali Xfce panel before and after

Testing

All on VMs (arm64), with a bundle built on Ubuntu 24.04:

  • The dock and launchers on the five desktops above, both ways. With the entry, the app is hidden from every launcher: the GNOME grid, the COSMIC launcher, the KDE menu and the Xfce menu.
  • A scripted run of 18 checks on Ubuntu, all passing:
    • the entry, instance marker and icon copy are created while the app runs, and all removed on SIGTERM;
    • an unreadable user entry and a dangling symlink are left unchanged;
    • a % path gets no entry, and the app still runs;
    • the entry is still installed when the bundle's own share/ is in XDG_DATA_DIRS;
    • with two AppImage instances, Exec= is the AppImage file, and the entry stays until the last one exits;
    • with a system-wide entry, the app installs no user entry and removes its own.
  • AppImage (the docs recipe, FUSE mount): the dock shows the logo.
  • desktop_entry = false writes no entry.
  • Closing the window with × removes the entry, on GNOME and KDE.

The flet run / flet pack desktop client (client/linux) is unchanged.

Summary by Sourcery

Make Linux builds register their app identity with desktop environments while running so docks show the correct name and icon without adding the app to launchers.

New Features:

  • Install a hidden, user-scoped Linux desktop entry while flet build linux apps run so desktop docks can display the product name and icon across supported Wayland and GNOME environments.
  • Allow Linux apps to disable the runtime desktop entry with [tool.flet.linux] desktop_entry = false.

Bug Fixes:

  • Ensure runtime desktop entries and their temporary icons are cleaned up when the final app instance exits, while preserving user- or package-owned entries.

Documentation:

  • Document runtime desktop-entry behavior, opt-out configuration, launcher visibility, AppImage behavior, and manual installation for permanent launcher entries.

@sourcery-ai sourcery-ai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Hey - I've reviewed your changes and they look great!


Sourcery is free for open source - if you like our reviews please consider sharing them ✨

@cloudflare-workers-and-pages

cloudflare-workers-and-pages Bot commented Oct 26, 2026 •

Copy link
Copy Markdown

Deploying flet-website-v2 with  Cloudflare Pages  Cloudflare Pages

Latest commit: 019356c
Status: ✅  Deploy successful!
Preview URL: https://884b1f2f.flet-website-v2.pages.dev
Branch Preview URL: https://feat-linux-desktop-entry.flet-website-v2.pages.dev

View logs

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant