Skip to content

Default tray icon behavior is lackluster #5432

@brodmo

Description

@brodmo

Current implementation of handle_tray_icon_event in app.rs is this

    #[cfg(any(target_os = "windows", target_os = "linux", target_os = "macos"))]
    pub fn handle_tray_icon_event(&mut self, event: tray_icon::TrayIconEvent) {
        if let tray_icon::TrayIconEvent::Click {
            id: _,
            position: _,
            rect: _,
            button,
            button_state: _,
        } = event
        {
            if button == tray_icon::MouseButton::Left && self.tray_icon_show_window_on_click {
                for webview in self.webviews.values() {
                    webview.desktop_context.window.set_visible(true);
                    webview.desktop_context.window.set_focus();
                }
            }
        }
    }

I'm in the process of building a macOS menu bar app and I haven't found this default implementation helpful, quite the opposite. Now thankfully, #5361 adds a flag to disable it, so that solves the issue for me. Still, I think this default implementation should be improved. Here are my issues with it.

It fires twice

Since button_state is a wildcard, the logic runs twice, on button down and button up. It should be just button down.

It shows, but doesn't hide

This might be constrained to macOS, but I think that clicking the icon again to hide the window is expected behavior. Since visibility detection is tricky adding window hiding without disabling the default implementation requires an ungodly workaround. I think it should hide or show depending on visibility instead of always hide.

It focuses multiple windows in a non-deterministic order

This is my biggest gripe. The webview iteration order is non-deterministic, so it's random which window ends up with the final focus. Especially for a keyboard-driven app this is lethal. For me, it would randomly focus my invisible pop-up, which was really hard to debug. I don't have a good solution to this, though. Maybe the default implementation should just do nothing if there are multiple webviews? I'm not sure.

I'm willing to implement a solution to this, but since it mainly boils down to design questions I would like some input first.

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