Alexays / Waybar

Highly customizable Wayland bar for Sway and Wlroots based compositors. :v: :tada:
MIT License
6.42k stars 696 forks source link

Missing DBus service for tray #2437

Open Mikilio opened 1 year ago

Mikilio commented 1 year ago

DBus service file I'm using:

# /usr/share/dbus-1/services/org.kde.StatusNotifierWatcher.service
[D-BUS Service]
Name=org.kde.StatusNotifierWatcher
Exec=/usr/bin/waybar
# comment SystemdService to start waybar directly
SystemdService=waybar.service

While testing this, I found that Qt apps may fail to display icon when waybar is started with dbus service. This happens because Qt5 expects both org.kde.StatusNotifierWatcher and org.kde.StatusNotifierHost to be ready by the moment of QSystemTrayIcon initialization. Since there's an obvious time lag between the registration of those interfaces, only Watcher is ready when the Qt app checks IsStatusNotifierHostRegistered. As a result, we get qt.qpa.menu: StatusNotifierHost is not registered instead of the icon.

tl;dr: exec 'sleep 1; nextcloud' in sway config actually has higher chance to work :disappointed:

Originally posted by @alebastr in https://github.com/Alexays/Waybar/issues/483#issuecomment-542528145

Ideally this should be added to the project.

mutoroglin commented 1 year ago

I do have the same issue with the nextcloud-client whenever I launch waybar. Thanks for the workaround @Mikilio and it would be great if this is corrected in waybar

pshirshov commented 1 year ago

This is an extremely annoying issue. We need some way to check that the tray is initialized and ready to use.

Relevant: https://github.com/Alexays/Waybar/issues/1864

pshirshov commented 1 year ago

https://github.com/Alexays/Waybar/issues/2197

pshirshov commented 1 year ago

There seems to be a reliable workaround:

  systemd.user.services.hyprland-tray-init-shim = {
    Unit = {
      Description = "hyprland-tray-init-shim";
      StopWhenUnneeded = true;
      ConditionEnvironment = "WAYLAND_DISPLAY";
      Requires = [ "waybar.service" ];
      After = [ "waybar.service" ];
    };

    Service = {
      ExecStart =
        "${pkgs.bash}/bin/bash -c 'while ! dbus-send --session --dest=org.freedesktop.DBus --type=method_call --print-reply /org/freedesktop/DBus org.freedesktop.DBus.ListNames | grep org.kde.StatusNotifierWatcher; do sleep 0.1; done'";
      RemainAfterExit = true;
      Type = "oneshot";
      Environment = [ "PATH=/run/current-system/sw/bin" ];
    };

    Install.WantedBy = [ "hyprland-session.target" ];
  };

This systemd unit waits until waybar tray is ready (by checking that a dbus service is advertised) then exits. This check seems be more reliable than sleeps.

genevieve-me commented 1 year ago

This systemd unit waits until waybar tray is ready ... then exits.

Having my systemd user services launch after this service does work for me, but causes up to a 15 second delay before waybar appears and my tray apps start. Edit: Waybar doesn't actually have a long delay before advertising StatusNotifierWatcher : tested by running the above bash snippet and cold starting waybar, and the bash job exits almost immediately. However, when sway is first started, waybar is waiting for something before finishing startup. Even when manually launched from a CLI during that 15 second period after sway starts, it just emits [info] Using configuration file ... and hangs. Based on the output of systemctl --user list-jobs I suspect it's the XDG desktop portal:

42  graphical-session.target                         start waiting
83  xdg-desktop-portal.service                       start running
138 xdg-desktop-portal-wlr.service                   start waiting
61  nextcloud-client.service                         start waiting
41  sway-session.target                              start waiting

While this unfortunately makes the workaround less usable for me, I think this is an issue with my (home-manager's) systemd setup, not with waybar itself. In general, if programs have previously connected to the system bus to provide tray icons, and the StatusNotifierHost is stopped and started later, the tray icons will persist (waybar will pick them up). But here, programs decide on launch that no tray is available and therefore won't connect to dbus to provide them for the rest of their lifespan.

Regardless, even after I patched waybar to support dbus activation, I observed the following : when waybar was not running and I restarted nextcloud-client, waybar was started (so the dbus service file was in effect) but nextcloud-client still didn't show any tray icon. I'm not sure why this occurs : I would have thought that the dbus server would "wai[t] for the application to finish launching and then (if all goes well) delive[r] the message" to set up a tray icon, as described in the KDE docs.

Waybar patch for dbus activation service file

``` From 0e27aa8b6159cba5af5f480697e92bc6d50485fc Mon Sep 17 00:00:00 2001 From: Genevieve Date: Sun, 24 Sep 2023 15:01:45 -0400 Subject: [PATCH] Enable dbus activation Waybar takes a while to advertise its tray capabilities, so applications will act as though no tray is available even if they are started AFTER waybar is finished launching (for example, systemd services with `After=waybar.service`. This change registers waybar for dbus activation, so it will be started if not present when an application requests a tray. Ideally it should also tell applications to wait for waybar's tray to be ready when they request one. [1] https://dbus.freedesktop.org/doc/dbus-specification.html [2] https://develop.kde.org/docs/features/d-bus/dbus_autostart_services/ --- meson.build | 6 ++++++ resources/org.kde.StatusNotifierWatcher.service.in | 4 ++++ 2 files changed, 10 insertions(+) create mode 100644 resources/org.kde.StatusNotifierWatcher.service.in diff --git a/meson.build b/meson.build index 9ccd83d..1fc7f0e 100644 --- a/meson.build +++ b/meson.build @@ -292,6 +292,12 @@ if dbusmenu_gtk.found() 'src/modules/sni/host.cpp', 'src/modules/sni/item.cpp' ) + configure_file( + configuration: conf_data, + input: './resources/org.kde.StatusNotifierWatcher.service.in', + output: '@BASENAME@', + install_dir: get_option('datadir') + '/dbus-1/services' + ) endif if libudev.found() and (is_linux or libepoll.found()) diff --git a/resources/org.kde.StatusNotifierWatcher.service.in b/resources/org.kde.StatusNotifierWatcher.service.in new file mode 100644 index 0000000..544fedd --- /dev/null +++ b/resources/org.kde.StatusNotifierWatcher.service.in @@ -0,0 +1,4 @@ +[D-BUS Service] +Name=org.kde.StatusNotifierWatcher +Exec=@prefix@/bin/waybar +SystemdService=waybar.service -- 2.42.0 ```

(It's also probably worth linking to https://github.com/Alexays/Waybar/issues/2221 and noting the work to codify a replacement XDG spec, since StatusNotifierItem is old and not well loved, but it doesn't appear to me that work will be finished for a while.)