Skip to content

[Linux] Wayland: window has an empty app_id, so taskbars and docks cannot resolve an icon #738

Description

@zucram

App version

linux-rust @ 672e65ad (nightly librepods-x86_64.AppImage, built 2026-06-12)

Variant

Rust rewrite (linux-rust branch)

Distro and version

CachyOS (rolling)

Desktop environment / compositor

niri 26.04 (Wayland)

Install method (only official sources)

AppImage

AirPods model

Other / not sure — the bug is device-independent; it only concerns the window's Wayland app_id.

What happened

On Wayland the LibrePods toplevel advertises an empty app_id. Panels and docks key their icon lookup off app_id.desktop entry, so LibrePods shows a blank placeholder instead of an icon. It also means any other app_id-less window on the system (a browser picture-in-picture window, for instance) gets grouped into the same taskbar entry.

Settings { id: Some("librepods") } is set in start_ui, but on Linux iced never reads that field — it only reads the per-window window::Settings::platform_specific.application_id, which is left at its Default value of "".

Expected: app_id == "librepods".
Actual: app_id == "".

Reproduction

  1. Launch LibrePods under any Wayland compositor.
  2. Query the toplevel's app_id:
$ niri msg -j windows | jq -r '.[] | "\(.app_id // "<null>")\t\(.title)"'
md.obsidian.Obsidian	Today's Meetings - obsidian - Obsidian 1.13.7
t3code	T3 Code (Nightly)
localsend	LocalSend
	LibrePods          <-- empty app_id
helium	Inbox | Fastmail - Helium

Cause

linux-rust/src/ui/window.rs:54-59 sets the application-level id:

.settings(Settings {
    id: Some("librepods".to_string()),
    ...
})

In iced 0.14 that id reaches iced_winit::conversion::window_attributes as the _id parameter — and the only block that consumes _id is gated to the BSDs (winit/src/conversion.rs#L78-L89):

#[cfg(any(
    target_os = "dragonfly",
    target_os = "freebsd",
    target_os = "netbsd",
    target_os = "openbsd"
))]
{
    use ::winit::platform::wayland::WindowAttributesExtWayland;

    if let Some(id) = _id {
        attributes = attributes.with_name(id.clone(), id);
    }
}

The block that actually compiles on Linux reads a different field — the per-window one (winit/src/conversion.rs#L137-L163):

#[cfg(target_os = "linux")]
{
    #[cfg(feature = "wayland")]
    {
        use winit::platform::wayland::WindowAttributesExtWayland;

        attributes = attributes.with_name(
            &settings.platform_specific.application_id,
            &settings.platform_specific.application_id,
        );
    }
}

core/src/window/settings/linux.rs declares application_id: String under #[derive(Default)], so an untouched window::Settings::default() produces with_name("", "").

Suggested fix

Set it on the window settings at both window::Settings::default() sites in linux-rust/src/ui/window.rs (lines 143 and 280):

let mut settings = window::Settings::default();
settings.min_size = Some(Size::new(400.0, 300.0));
settings.platform_specific.application_id = "librepods".to_string();

librepods matches the basename of librepods.desktop, which is what iced's own docs recommend and what panels expect.

Additional context

Two related things I ran into while tracking this down:

1. The window icon path is relative and resolved at runtime. At window.rs:145 and window.rs:282:

settings.icon = window::icon::from_file("../../assets/icon.png").ok();

That resolves against the process working directory, so it fails for any normal launch, and .ok() swallows the error silently. include_bytes! plus window::icon::from_file_data would embed it the same way the font already is on line 56.

2. The AUR package ships no icon or desktop entry. librepods-git installs only usr/bin/librepods and the licence, so packaged installs have nothing for an Icon= key to point at even once app_id is correct. The AppImage already carries a good 256×256 me.kavishdevar.librepods.png and a librepods.desktop; installing those into usr/share/icons/hicolor/ and usr/share/applications/ would cover it. (Related: #384.)

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions