Issue 360: the operator cannot choose a notification's action on a touchpad
mesh/merge-gate pass: the change touches no module of the mesh's graph
mesh/repo-check pass: its merge-check.sh passed
mesh/delivery delivered

The desk's actions sit on dunst's middle click, which a touchpad cannot give, and the context menu
names a command dunst's PATH does not hold. Located in the dunst module; dunst's own code settles
what a tap with do_action does.
This commit is contained in:
jochen
2026-10-10 00:07:01 +02:00
parent c51aedea22
commit fe970e2f00
2 changed files with 86 additions and 0 deletions
@@ -0,0 +1,36 @@
---
status: located
opened: 2026-10-10
located-in: [mesh-catalog modules/dunst (the dunstrc's click lines and its context menu)]
fixed-by:
amended-design:
---
# 360. The operator cannot choose a notification's action on a touchpad
**Severity: medium.** The desk's answers ([ADR 0253](../../02-DECISIONS/0253-a-condition-says-itself-to-the-operator-in-plain-words-beside-its-summary.md),
[ADR 0258](../../02-DECISIONS/0258-a-desk-click-performs-only-an-acknowledgement-and-an-answer-is-a-one-time-ticket.md))
reach the screen and cannot be given there. Every notification with actions ends unanswered, or is answered
on another channel.
## Symptom
The operator works on the laptop and on the workstation with a touchpad, which gives a left and a right
click but no middle click. A desktop notification from the desk that carries actions (for example "Silence
for a week") shows dunst's mark for them, "(A)", and nothing the operator can do on it chooses one:
- a tap (left click) closes the notification, because the dunstrc the mesh writes says
`mouse_left_click = close_current`;
- the actions are bound to the middle click alone (`mouse_middle_click = do_action, close_current`), which
the touchpad cannot give;
- the context menu, the other way to an action, does not open either. The dunstrc names `dmenu`, the
node-launcher's command, which lives in the account's own `~/.local/bin`. dunst runs in the account's
service manager, and on the laptop on 2026-10-10 the running dunst's `PATH` held no such directory.
ADR 0253 states the desk's actions are offered "a middle click, or its context menu". On these two
machines neither is reachable, and nothing says so: the notification closes on a tap as if it had been read.
## Expected
On the laptop and the workstation: a tap on a notification with one action runs it; with several, a menu
(rofi) opens to choose one; a notification without actions closes on a tap, as today.
@@ -0,0 +1,50 @@
# Diagnosis — issue 360
## 2026-10-10 — what dunst does on each click, from its own documentation and code
dunst(5), for the version the machines run (1.13.2): `mouse_[left/middle/right]_click` takes a list of
`none`, `do_action`, `open_url`, `close_current`, `close_all`, `context` and `context_all`, run in order.
`do_action` "invokes the action determined by the action_name rule. If there is no such action, open the
context menu", and `action_name` defaults to `default`: "the action set as default action or the only
available action will be invoked."
dunst's source (`notification_do_action` in `src/notification.c`, the click handler in `src/input.c` and the
menu in `src/menu.c`, tag v1.13.2) settles the three cases:
| the notification has | `do_action` | then `close_current` |
|---|---|---|
| one action | runs it at once | closes it |
| several actions, none named `default` | opens the context menu for this notification and locks it | the close waits for the menu; it happens after the chosen action is sent, and not at all when the menu is dismissed |
| no action and no link | nothing | closes it |
| no action, one link | opens the link in the browser | closes it |
| several actions, one named `default` | runs `default` without a menu | closes it |
A touch on Wayland is also read as the left click (`BTN_TOUCH`).
So `mouse_left_click = do_action, close_current` gives the expected behaviour, with two edges: a link in a
notification without actions opens on a tap, and an action named `default` would be taken without the menu.
The desk's tokens are tickets, never `default`; the dunst module's `send` can refuse that token so the edge
cannot be reached.
## The context menu
The dunstrc's `dmenu = dmenu -p dunst` calls the node-launcher's dmenu-compatible command, a script the
launcher module places in the account's `~/.local/bin`. The `PATH` of the running dunst on the laptop was
read from its process environment on 2026-10-10 and held only system directories and a tool's own, not
`~/.local/bin`. dunst starts the menu with a search of that `PATH` (`g_spawn_async_with_pipes` with
`G_SPAWN_SEARCH_PATH`), and a command it cannot find is only a line in its log ("Cannot spawn dmenu"), so
the menu does not open and the operator sees nothing. Calling
`rofi -dmenu` (a system package) removes the dependency on the account's `PATH`; the dunst module then
declares the `rofi` package itself, since its file names it.
## Ruled out
- The keyboard: i3's configuration is the mesh's (the `i3` module, with other modules' lines placed from
their contributions to `node-display-session`, ADR 0212), so a key for `dunstctl context` can be one more
contribution, from the dunst module. It does not replace the tap, which is the operator's way on a
touchpad.
## Owner
mesh-catalog, `modules/dunst`: its dunstrc (the left click and the menu), its packages, its contribution to
i3, and the token check in its `send`.