From 9420190d60fe4d7a69992920c366aa07632cb842 Mon Sep 17 00:00:00 2001 From: Sunderland93 Date: Mon, 18 Sep 2023 12:40:28 +0400 Subject: [PATCH] Provide river-xdg-autostart target --- debian/control | 4 +- etc/skel/.config/river/init | 5 ++ .../systemd/user/river-xdg-autostart.target | 10 +++ usr/share/river/scripts/wait-sni-ready | 61 +++++++++++++++++++ 4 files changed, 78 insertions(+), 2 deletions(-) create mode 100644 usr/lib/systemd/user/river-xdg-autostart.target create mode 100755 usr/share/river/scripts/wait-sni-ready diff --git a/debian/control b/debian/control index 9434c42..2da9940 100644 --- a/debian/control +++ b/debian/control @@ -2,13 +2,13 @@ Source: tileos-settings-river Section: x11 Priority: optional Maintainer: Aleksey Samoilov -Build-Depends: debhelper-compat (= 13) +Build-Depends: debhelper-compat (= 13), Standards-Version: 4.6.0 Homepage: https://github.com/Tile-OS/tileos-settings-river.git Rules-Requires-Root: no Package: tileos-settings-river Architecture: any -Depends: ${shlibs:Depends}, ${misc:Depends} +Depends: ${misc:Depends}, python3-tenacity, python3-dbus-next Conflicts: tileos-settings-sway Description: default settings for River on TileOS diff --git a/etc/skel/.config/river/init b/etc/skel/.config/river/init index 1594ee7..cab9def 100755 --- a/etc/skel/.config/river/init +++ b/etc/skel/.config/river/init @@ -7,6 +7,8 @@ VARIABLES="DESKTOP_SESSION XDG_CURRENT_DESKTOP XDG_SESSION_DESKTOP XDG_SESSION_T VARIABLES="${VARIABLES} DISPLAY WAYLAND_DISPLAY" SESSION_TARGET="river-session.target" SESSION_SHUTDOWN_TARGET="river-session-shutdown.target" +SESSION_XDG_AUTOSTART_TARGET="river-xdg-autostart.target" +SNI_CHECK="/usr/share/river/scripts/wait-sni-ready" if hash dbus-update-activation-environment 2>/dev/null; then # shellcheck disable=SC2086 @@ -31,6 +33,9 @@ session_cleanup () { } trap session_cleanup EXIT INT TERM +# Wait for StatusNotifierWatcher is available and start XDG Autostart target +"$SNI_CHECK" && systemctl --user start "$SESSION_XDG_AUTOSTART_TARGET" + # Set keyboard layout. See man riverctl # riverctl keyboard-layout -options "grp:caps_toggle" "us,ru" diff --git a/usr/lib/systemd/user/river-xdg-autostart.target b/usr/lib/systemd/user/river-xdg-autostart.target new file mode 100644 index 0000000..c2d1841 --- /dev/null +++ b/usr/lib/systemd/user/river-xdg-autostart.target @@ -0,0 +1,10 @@ +# Systemd provides xdg-desktop-autostart.target as a way to process XDG autostart +# desktop files. The target sets RefuseManualStart though, and thus cannot be +# used from scripts. +# +[Unit] +Description=XDG autostart for River session +Documentation=man:systemd.special(7) man:systemd-xdg-autostart-generator(8) +BindsTo=xdg-desktop-autostart.target +PartOf=river-session.target +After=river-session.target diff --git a/usr/share/river/scripts/wait-sni-ready b/usr/share/river/scripts/wait-sni-ready new file mode 100755 index 0000000..68f7be6 --- /dev/null +++ b/usr/share/river/scripts/wait-sni-ready @@ -0,0 +1,61 @@ +#!/usr/bin/python3 +""" +A simple script for waiting until an org.kde.StatusNotifierItem host implementation +is available and ready. + +Dependencies: dbus-next, tenacity +""" +import asyncio +import logging +import os + +from dbus_next.aio import MessageBus +from tenacity import retry, stop_after_delay, wait_fixed + +LOG = logging.getLogger("wait-sni-host") +TIMEOUT = int(os.environ.get("SNI_WAIT_TIMEOUT", default=25)) + + +@retry(reraise=True, stop=stop_after_delay(TIMEOUT), wait=wait_fixed(0.5)) +async def get_service(bus, name, object_path, interface_name): + """Wait until the service appears on the bus""" + introspection = await bus.introspect(name, object_path) + proxy = bus.get_proxy_object(name, object_path, introspection) + return proxy.get_interface(interface_name) + + +async def wait_sni_host(bus: MessageBus): + """Wait until a StatusNotifierWatcher service is available and has a + StatusNotifierHost instance""" + future = asyncio.get_event_loop().create_future() + + async def on_host_registered(): + value = await sni_watcher.get_is_status_notifier_host_registered() + LOG.debug("StatusNotifierHostRegistered: %s", value) + if value: + future.set_result(value) + + sni_watcher = await get_service(bus, "org.kde.StatusNotifierWatcher", + "/StatusNotifierWatcher", + "org.kde.StatusNotifierWatcher") + sni_watcher.on_status_notifier_host_registered(on_host_registered) + # fetch initial value + await on_host_registered() + return await asyncio.wait_for(future, timeout=TIMEOUT) + + +async def main(): + """asyncio entrypoint""" + bus = await MessageBus().connect() + try: + await wait_sni_host(bus) + LOG.info("Successfully waited for org.kde.StatusNotifierHost") + # pylint: disable=broad-except + except Exception as err: + LOG.error("Failed to wait for org.kde.StatusNotifierHost: %s", + str(err)) + + +if __name__ == "__main__": + logging.basicConfig(level=logging.INFO) + asyncio.run(main())