fondle
is a notification daemon designed for minimal window managers and status bars.
It works well with any system in which you would normally use a script to generate your status bar (dwm, spectrwm, lemonbar) and was designed such that it can be implemented with minimal disturbance to your other configurations.
In most non-minimal window managers (XFCE, KDE, Gnome), notifications are implemented as small pop-up windows that appear for a few seconds before fading away. They contain text, an icon and the user can often interact with them in some way. They can convey all sort of information, ranging from new emails to battery status. Dunst is a very popular (and capable) notification daemon for minimal systems that uses the traditional popup style to notifications. For some users, popups are overkill and distracting. As far as I know, statnot was the first system to integrate notifications unobtrusively into the status bar. Qtile implemented a notification widget in their window manager which operates similarly. Rofication took this a step further by only displaying the number of notifications in the bar and relying on rofi to display them when the user desires. Each of the above systems has limitation (at least for my particular use-case):
- Rofication is only currently implemented for i3-blocks (although implementations for other window managers is possible) and depends on rofi.
- Qtile's notify widget only works in Qtile.
- statnot was originally implemented for dwm and it proved sufficiently complex to modify it to work well in spectrwm to warrant a full rewrite.
fondle
operates under a similar philosophy to statnot but tries to be more system agnostic.
In particular it has a few nice features:
fondle
doesn't have any configuration file.
Like dmenu, all options are set when you start the service.
More involved configuration requires modification of the source code.
Each notification implemented with the Desktop Notification standard contains several fields with information about the notification (content, urgency, icon, etc.). We only display the summary (effectively a header) and the body. However, you can control what, if anything, should be prepended before the summary, what separates the summary and body, how many characters the body should be limited to, and what, if anything should be appended at the end of the body. This makes it possible (with a compatible bar) to implement emojis and different colors for notifications in the bar.
đźš© battery status: low
fondle
integrates with the status script you've already written to generate the status for your bar.
The only requirements are that the script echoes or prints the output and isn't inside a permanent while loop.
For most users this will mean they just have to remove the while loop from their script.
fondle
can work with any script as long as you point it to the executable to run it (sh, bash, python, etc.).
Does your bar (lemonbar) want you pipe the output of your status script directly into it?
No problem.
Just tell fondle
to echo it's output and pipe it into your bar directly.
Running dwm which requires you to use xsetroot -name
to change the bar?
No problem.
Tell fondle
to use xsetroot -name
instead.
Don't have a bar at all and want your notifications in a terminal window?
fondle
can do that too.
Each time you start fondle
, it resets a simple notification log ("/tmp/notification.log") that you can manipulate using other tools.
At it's simplest, you can do something like this to display your most recent notifications chronologically:
tac /tmp/notifications.log | dmenu -l 50
fondle
has been implemented entirely in a few hundred lines of python with quite a few comments.
Hopefully it's quite easy to modify it to better suite your individual needs if you so desire.
To install fondle
, first install the required dependencies:
- python 3.5+
- dbus-python
- PyGObject
- gtk3 - (not for GUI support)
Follow the PyGObject installation instructions for your system. That should take care of most of your dependencies.
Next, adjust the target directories in the config.mk
file to fit your setup.
To install, run as root:
make install
fondle
should be the only notification tool running.
You can run the following to ensure notification-daemon
is not running:
killall notification-daemon &> /dev/null
usage: fondle [-h] [-x EXECUTABLE] [-c COMMAND] [-t DEFAULT_TIMEOUT] [-m MAX_TIMEOUT] [-l MAX_LENGTH] [-u UPDATE_INTERVAL] [-r] [-s SEPARATOR] [-p PREPEND] [-a APPEND] [script]
positional arguments:
script script to generate status
optional arguments:
-h, --help show this help message and exit
-x EXECUTABLE, --executable EXECUTABLE
executable (on PATH) to run the status script
(default: 'sh')
use this flag without argument if using conky to generate status
-c COMMAND, --command COMMAND
shell command to update status (default: 'echo')
-t DEFAULT_TIMEOUT, --default-timeout DEFAULT_TIMEOUT
default notification timeout (default: 3.0)
-m MAX_TIMEOUT, --max-timeout MAX_TIMEOUT
max notification timeout (default: 5.0s)
-l MAX_LENGTH, --max-length MAX_LENGTH
max display length of notification body
-u UPDATE_INTERVAL, --update-interval UPDATE_INTERVAL
status update interval (default: 2.0)
-r, --replace-status replace the status information with notification
-s SEPARATOR, --separator SEPARATOR
separator between summary and body of notification
(default: ': ')
-p PREPEND, --prepend PREPEND
prepend before notification (default: '')
-a APPEND, --append APPEND
append after notification (default: ' ')
Path to any script which echoes or prints.
Script must not run in a loop for it's final output.
The script can be in any language as long as you specify the appropriate executable with the --executable
flag.
This is the executable (which must be on PATH) with which the script should be run.
It defaults to sh
but you can easily write your status script in python and change it to python
(or any other language).
If you add this flag without an argument, it assumes the "script" is an executable.
If you use conky to generate your status, you can use this flag: fondle /usr/bin/conky -x
.
fondle
generates the full status bar as a combination of notifications and your status script.
That final output is a string which can be passed as the argument to any command.
By default this is set to echo
which results in echo my-bar-contents
.
If you're using dwm, you should change this to xsetroot -name
.
This is the default time a notification will be displayed.
It's set to 3.0
seconds by default.
If a notification is received that has a very long timeout, this is max it is allowed to remain displayed.
It's set to 5.0
seconds by default.
Notifications are displayed as PREPEND + SUMMARY + SEPARATOR + BODY + APPEND
.
With default settings, a notification might look like this: warning: battery is running low
.
This setting allows you to limit the length of the body of a notification.
This is mostly useful if you have limited bar space.
For example, limiting the body to -l 7
would result in warning: battery...
.
If you set -l 0
, no body or separator will be displayed at all: warning
.
This is the interval with which you want the status to update.
It defaults to 2.0
seconds.
This is a flag which determines if the notification just pops up on your status bar or if it completely replaces your status when it is present.
statnot replaced the status entirely while qtile integrates it with the bar.
Here is an example without this flag: warning: battery low | status text here
.
While with the -r
flag: warning: battery low
.
Of course, the status returns as soon as the notification expires.
This separates the summary and body of the notification.
By default it is :
: summary: body
.
If the --max-length
is set to 0
, this separator is not used.
This is a string that appears before the summary of the notification. It defaults to an empty string. You can use it to apply formatting options in spectrwm bar for example.
This is a string that appears after the body of the notification.
It defaults to a single space:
.
You may want to change it to something like |
.
Depending on your setup, you can run fondle
in a variety of ways.
Just as an example, we'll assume you have a script to generate your status stored in .config/mybar.sh
.
We'll keep the options as simple as possible.
Need to specify echo -e
so that that escape codes work.
fondle ~/.config/mybar.sh -c "echo -e" -p "\e[41m " -a "\e[0m | "
If you want to replicate the functionality of rofication, it isn't hard at all. You don't even need to use fondle to manage your status. In your current status script, add the following to record the number of notifications:
NOTI=`cat /tmp/notification.log | wc -l`
And then just echo this in your while loop:
echo -n "[${NOTI}]"
Now you'll have the number of notifications updated in your current status bar. But you want to remove/acknowledge notifications to reduce the number?
Bind this to a key:
tac /tmp/notification.log | dmenu -l 50 | while read noti; do sed -i "/$noti/d" /tmp/notification.log ; done
This will launch dmenu with all of the notifications. Selecting a notification deletes it from the log and reduces the number in your status bar.
Simple conky.conf
:
conky.config = {
out_to_console = true,
out_to_x = false,
background = false,
update_interval = 0,
total_run_times = 1,
use_spacer = 'none',
}
conky.text = [[
RAM Usage: $mem/$memmax
]]
Then use the -x
flag without argument since conky is an executable already:
fondle /usr/bin/conky -x
Note that some of conky's built in functions will not work well if it only run once. In particular RAM and network functions seem to be affected. You'll have to resort to hacks to get around this.
fondle ~/.config/mybar.sh -c "xsetroot -name"
Ratpoison has it's own messaging system which provides message boxes. We can interface with it quite easily by prepending the necessary command to our notification:
fondle -c "ratpoison -c" -p "echo "
As it stands currently, fondle cannot display regular status messages in ratpoison. This is due to how I've implemented the output format. I could modify fondle to allow this specific use-case if there is demand but I suspect that most ratpoison users don't want a persistent repeating popup notification.
spectrwm seems to require a shell script for its bar_action
configuration option.
That's no problem.
We can create a simple script containing our options and then add that to the configuration:
#!/usr/bin/sh
fondle ~/.config/mybar.sh
spectrwm also supports using colors in the bar by setting bar_action_expand = 1
in its configuration.
We can then add the spectrwm bar markup directly in our fondle
options:
#!/usr/bin/sh
fondle ~/.config/mybar.sh --prepend '+@bg=1;+@fg=1; ' --append ' +@fg=0;+@bg=0; '
Maybe you even want to use different markup for the summary and the body of the notification:
#!/usr/bin/sh
fondle ~/.config/mybar.sh --prepend '+@bg=1;' --separator '+@bg=0;: +@bg=2;' --append '+@bg=0;'
fondle ~/.config/mybar.sh | lemonbar
You can replace the i3status command entirely via the bar config:
bar {
status_command fondle ~/.config/mybar.sh
}
I'm still testing the best way to combine the output of i3status with fondle
.
For now, the best I can do is replace the output of i3status when you get a notification but the timing isn't correct.
To do this, you need to add output_format = none
in your general block of the i3status configuration.
Then you can replace the i3status command in the bar config like this:
bar {
status_command fondle & i3status
}
If you find a better way, let me know.
This is untested but I believe you can just pipe the output into xmobar like this:
fondle ~/.config/mybar.sh | xmobar -o -t "%StdinReader%" -c "[Run StdinReader]"
I'd love to reimplement the dbus communication with python-dbus-next. Since it's a pure python implementation, it reduce the size of the dependencies and make it much easier to install. Unfortunately, I'm still too inexperienced with the dbus interface to get this working right now.
Write a proper manpage.
There are method of cleverly using notifications to display important information only when relevant with fondle
.
I'll try to expand this section as soon as possible.
Released under the GNU General Public License v3.0