You are not logged in.
Hello,
Since the last version of dunst, keyboard shortcuts can't be set from the config file (dunstrc) ; they have to be set via dunstctl.
I was used to closing my notifications with the Escape key, but now I can't do this anymore: I use Openbox as a window manager, and if I set a shortcut for the Escape key in the rc.xml file of Openbox (which is the file that deals with system shortcuts) then obviously the Escape key can't be used anymore by my terminal emulator (e.g. to exit insert mode in vim; I know I could use C-c for this exact case, but this is just an example).
So my question is: is there a way to use the Escape key to close dunst notifications, without preventing this key to be used by other programs?
I had thought that maybe I could remap another key to send the Escape keycode (using xmodmap, maybe), and then launch a script each time the Escape key is pressed to check whether a notification is displayed or not; if a notification is displayed, then close it; if there's no notification, then emulate the Escape keycode... It seems over-complicated, and I'm not even sure it would work (wouldn't Openbox catch the keycode and understand it as an Escape keypress? In which case I'd enter an infinite loop...)
Thanx very much for any help!
Last edited by LithoUser (2021-10-24 08:56:47)
Offline
As additional data points, I've tried this with both i3wm and sxhkd, and the same behavior happens. I wonder if this is a limitation of X11.
One workaround I would suggest that doesn't disrupt your muscle memory too much is to map $mod + Escape instead (either Alt + Escape or Win/Super + Escape).
Offline
Ftr: https://github.com/dunst-project/dunst/issues/941
You'd have to intercept, fire a command and replay the key.
That's not typically a feature to be found in shortcut daemons.
gcc -lX11 -lXi -o fuckoffdunst fuckoffdunst.c#include <X11/XKBlib.h>
#include <X11/extensions/XInput2.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char * argv[]) {
// Connect to X display
Display *dpy = XOpenDisplay(NULL);
if (!dpy) {
printf("Cannot open X display\n");
exit(1);
}
int xiOpcode;
{ // Test for XInput 2 extension
int queryEvent, queryError;
if (!XQueryExtension(dpy, "XInputExtension", &xiOpcode, &queryEvent, &queryError)) {
printf("X Input extension not available\n");
exit(2);
}
}
{ // Request XInput 2.0, to guard against changes in future versions
int major = 2, minor = 0;
int queryResult = XIQueryVersion(dpy, &major, &minor);
if (queryResult == BadRequest) {
printf("Need XI 2.0 support (got %d.%d)\n", major, minor);
exit(3);
} else if (queryResult != Success) {
printf("XIQueryVersion failed!\n");
exit(4);
}
}
{ // Register to receive XInput events
Window root = DefaultRootWindow(dpy);
XIEventMask m;
m.deviceid = XIAllMasterDevices;
m.mask_len = XIMaskLen(XI_LASTEVENT);
m.mask = calloc(m.mask_len, sizeof(char));
XISetMask(m.mask, XI_RawKeyPress);
XISelectEvents(dpy, root, &m, 1 /*number of masks*/);
XSync(dpy, False);
free(m.mask);
}
while (True) {
XEvent event;
XGenericEventCookie *cookie = (XGenericEventCookie*)&event.xcookie;
XNextEvent(dpy, &event);
if (XGetEventData(dpy, cookie) && cookie->type == GenericEvent &&
cookie->extension == xiOpcode && cookie->evtype == XI_RawKeyPress) {
XIRawEvent *ev = cookie->data;
// Ask X what it calls that key; skip if it doesn't know
if (ev->detail == 9)
system("dunstctl close");
}
}
}Code lifted from the xkbcat example (hence all the fancy caution stuff on the top)
I hardcoded the keycode for escape ("9")
Offline
Thanx for your answers!
You'd have to intercept, fire a command and replay the key.
Yes, that's what I'd tried to do, but it didn't work. Here's what I've done:
1. In the rc.xml file of Openbox, I created the following shortcut:
<keybind key="Escape">
<action name="Execute">
<command>dunst-close-notifications-with-escape</command>
</action>
</keybind>2. Then I also created the following bash script dunst-close-notifications-with-escape:
#!/bin/bash
is_notification=$(dunstctl count | grep -oiP '(?<=Currently displayed: )[[:digit:]]+')
if [ "$is_notification" -gt "0" ]; then
dunstctl close
else
xdotool key "Escape"
fiBut it doesn't work (if a notification exists, it's closed; but if no notification is displayed, nothing happens: the Esc key doesn't work in my terminal or in any other app); I'm pretty much sure it's because of the last line (xdotool key "Escape") that makes me enter in an infinite loop, since when the key is replayed Openbox catches it again... Or am I wrong?
seth> If it can't be done that way, I'll use your script; thanx very much for sharing it!
Last edited by LithoUser (2021-10-24 06:28:55)
Offline
Not only will this cause a recursion (you'd have to un- and re-register the shortcut w/ openbox around the xdotool call), the other nasty thing I ran into when writig a daemon that does this on a passive grab (what shortcut daemons will typically do, but w/ XAllowEvents(., ReplayKeyboard) ) is that (other) popups will want to grab the escape key to close themselves and that doesn't work either anymore.
That's why I went for the XI2 code and there's no other way if you want to use dunstctl.
Offline
Thanx for the detailed explanations. It makes more sense for me now.
That's why I went for the XI2 code and there's no other way if you want to use dunstctl.
Done some research, but haven't found any good alternative, unfortunately... So, I'll use the code you shared. Thank you for your help!
Offline