Getting Linux System Notifications under Openbox (Shallow Thoughts)

Akkana's Musings on Open Source Computing and Technology, Science, and Nature.

Mon, 21 Aug 2023

Getting Linux System Notifications under Openbox

I've been a fan of Linux's lightweight window managers, particularly Openbox, for many years.

But admittedly, there are some things they don't generally handle. One of those is system notifications.

Mostly, I've been happy to go without notifications. Firefox is forever asking me whether I want to turn them on for particular websites (which wouldn't work, but Firefox doesn't know that), usually websites I'm visiting for the first time and probably don't ever want to visit again, let alone let them spam me with ads as notifications outside my browser.

But every now and then it would be handy. Yesterday afternoon, I thought of something I needed to do this morning and I wanted to set up something that would remind me. On my phone, the only way to set that up would be to set it as an event in my calendar, where it would then live forever after. On Linux, for a reminder the same day, I use my eggtimer script, which has a lot of nice features like being able to add and subtract time from a running timer. But eggtimer doesn't persist across reboots, and for a reminder tomorrow morning, although the at command would let me set up a reminder for tomorrow, there's no easy way for the at job to pop up an alert, because the at job tomorrow won't be running as a child of tomorrow's X11 session. The best it could do is email me.

I had other things going on and didn't have time to investigate, so I scrawled a note on the back of an envelope and wedged it in the dashboard of the car so I'd see it before I left to go to the flying field. That old school method worked fine. But when I came back I decided I wanted to figure out notifications.

Note: There's actually a much easier way to do this than notifications. Jump to A Much Easier Way if you just want a quick solution.

First, Choose a Notification Server

There are many notification servers to choose from on Linux. Many of the pages I found when I first started searching pointed to notify-osd as a basic, no-frills option, which sounded ideal at least for a first try. But after spending an hour in web searches and manual reading, I was never able to figure out how one actually runs notify-osd, and I finally gave up on it.

During the search, I saw several positive comments about dunst, so I tried that next. It has the same problem: it has documentation, but the doc only covers the contents of the configuration file, and never touches on how to actually run dunst.

Web searching found a lot of pages recommending commands like systemctl start --user dunst.service , but that didn't work for me with Debian's dunst package. I got a variety of errors (systemctl start doesn't tell you the errors, you have to read them separately using systemctl --user status dunst.service), from "Can't find service" to "Unable to open display" (the cure for that turned out to be systemctl --user import-environment) to "start operation timed out" (I still have no clue why it was timing out, it never gave me any hints).

How to Actually Start dunst

But it turns out you don't need to use systemd at all. When I ran

dunst &
from the commandline, it ran and worked fine, and it worked just as well when I put that in my ~/.config/openbox/autostart file.

How to Generate a Notification

The easy way to generate a notification to see if your notification server is working — or to pop up a notification in your at or cron job — is to apt install libnotify-bin, which installs libnotify and also gives you the notify-send program. Then you can run something like

notify-send 'Hello world!' 'This is an example notification.' -u normal

-u is the urgency, which can be low, normal or critical. You can configure things like the color dunst will use for each urgency and how long each one will stay on your screen (you can dismiss a dunst notification manually by clicking on it).

The notification text can also have simple HTML formatting, e.g.

notify-send 'Formatting!' 'This is <b>bold</b> and this is <i>italic</i>.' -u normal

What if you want a notification on a system that doesn't have libnotify? That's a little harder, but still doable:

gdbus call --session \
    --dest=org.freedesktop.Notifications \
    --object-path=/org/freedesktop/Notifications \
    --method=org.freedesktop.Notifications.Notify \
    "" 0 "" 'Hello world!' 'This is an example notification.' \
    '[]' '{"urgency": <1>}' 5000

The 5000 is number of milliseconds the alert should stay up. The <1> is supposedly urgency, but in practice it's actually ignored: <0>, <1>, and <2> all give the same result and none of them shows up in red as a critical alert. I never did find out how to really specify urgency via gdbus call.

You can also do this low-level notification from Python:

import dbus

name = "org.freedesktop.Notifications"
notify_intf = dbus.Interface(dbus.SessionBus().get_object(
                     name, "/" + name.replace(".", "/")), name)
notify_intf.Notify("", 0, "",
                   "Hello world!", "This is the notification body.",
                   [], {"urgency": 2}, 3000)

As with the command-line version, no matter what you set "urgency" to, 2, '2', 2000, 'critical', it all gives the same result and doesn't send a critical notification.

Sending a Notification via at

So let's try an actual notification using at, for a few minutes from now.

$ at 9:15
warning: commands will be executed using /bin/sh
at Sun Aug 20 09:15:00 2023
at> notify-send 'Notification' 'Sent via at' -u critical
job 28 at Sun Aug 20 09:15:00 2023

Wait for 9:15 and ... nothing happens. Why?

It turns out that these notifications don't actually work from anywhere other than the X session where you're running the notification server. To test that, first you need a new shell that doesn't have any information about your X session. Either su - yourusername or ssh localhost will work.

Now, from that shell, try a notification:

$ notify-send 'Title' 'This is an example notification.'
Cannot autolaunch D-Bus without X11 $DISPLAY

But not needing to know the X session details was the whole point of wanting to use notifications in the first place!

Fiddling around a bit, I saw suggestions to let systemd and dbus know my environment variables under X using systemctl --user import-environment and dbus-update-activation-environment, but neither one made any difference.

It turns out the variable the system needs is $DBUS_SESSION_BUS_ADDRESS. Unfortunately, I don't know of any way of getting the $DBUS_SESSION_BUS_ADDRESS for the running X session. One thing you can do is add this to .config/openbox/autostart, right before or after you run dunst:

echo $DBUS_SESSION_BUS_ADDRESS > $HOME/.config/dunst/dbus-session-address
(I just picked that location out of a hat. Put it wherever you want, since there's no standard place for this.)

Then, when you want to send a notification, use this:

DBUS_SESSION_BUS_ADDRESS=$(cat $HOME/.config/dunst/dbus-session-address) notify-send 'Title' 'This is an example notification.'

This works, but it seems like a ridiculously byzantine set of hoops to jump through just to pop up an alert.

And in fact there's a much easier way that doesn't need the system's notification framework at all.

A Much Easier Way: Forget About Notifications

If you set XAUTHORITY to point to ~/.Xauthority, then set your display to whatever display you're using, you can run any X client. For instance, you can use zenity to pop up a dialog box:

 XAUTHORITY=~/.Xauthority DISPLAY=:0 zenity --title "Hello" --info --text="Hello world"

That works without needing any setup, special files, services or anything else. It works through at, too:

$  at 13:23                                                            ~
warning: commands will be executed using /bin/sh
at Sun Aug 20 13:23:00 2023
at> XAUTHORITY=~/.Xauthority DISPLAY=:0 zenity --title "Hello" --info --text="Hello world"
job 30 at Sun Aug 20 13:23:00 2023
... and, sure enough, the dialog pops up at the indicated time.

So, having wasted way too much time figuring out how to send and receive notifications, I'm going to forget all that and just use the simpler approach.

But customizing zenity (so that it's more attention-getting) turned out to be trickier than expected. So I'll save those details for a separate article.

Tags: , ,
[ 14:03 Aug 21, 2023    More linux | permalink to this entry | ]

Comments via Disqus:

blog comments powered by Disqus