96 lines
6.1 KiB
Markdown
96 lines
6.1 KiB
Markdown
# clipmenu
|
|
|
|
The clipboard manager as a module (novox/hq ADR 0208, research 026/04).
|
|
|
|
- Installs `clipmenu` from the official repositories. It brings `clipnotify`, `xsel`, `xdotool` and
|
|
`dmenu` as its own dependencies.
|
|
- Claims the mesh's `node-clipboard` seat and serves its verbs `history` and `copy`. Requires
|
|
`x11-display` on its own machine.
|
|
- **Declares `rofi-greenclip` absent** (ADR 0180). This module replaces it.
|
|
- Declares `clipmenud.service` as a **user unit of the operator's account**, enabled and running
|
|
(`scope: user`, ADR 0177; issue 743), so `$mod+.` shows the history again. It is the only starter: the
|
|
session's `xinitrc` line is gone. A drop-in (`~/.config/systemd/user/clipmenud.service.d/mesh.conf`)
|
|
replaces `ExecStart` with the module's launcher, which finds the X display from its socket (the account's
|
|
service manager has no `DISPLAY`) and puts the text-only `xsel` first on the `PATH`; until the display is up
|
|
it waits (a quick exit would run into the start limit, which the drop-in also switches off, with `RestartSec=2s`). `DISPLAY` and `XAUTHORITY` come from the user manager when the session's xinitrc has handed them over (module xorg); with several X servers and no `DISPLAY` yet, it waits for them. The store is in the account's runtime directory (mode 0700),
|
|
so no other account reads it.
|
|
**After delivery the operator logs in again**: the running session keeps the `clipmenud` its xinitrc
|
|
started, and the new unit waits on clipmenud's session lock until that one ends.
|
|
- Binds `$mod+period` to `clipmenu`, as its own i3 drop-in (`50-clipmenu.conf`). clipmenu shows the
|
|
history through `dmenu`, the seat command of `node-launcher`, so it looks like every other menu.
|
|
- Its settings are environment contributions (ADR 0203), read by the daemon, the menu and the tools
|
|
alike:
|
|
- `CM_SELECTIONS=clipboard`: what was copied, not every highlighted word. The found greenclip did
|
|
the same.
|
|
- `CM_MAX_CLIPS=500`: how many clips are kept.
|
|
- `CM_HISTLENGTH=15`: how many lines the menu shows.
|
|
|
|
## Tools
|
|
|
|
| tool | does |
|
|
|---|---|
|
|
| `node-clipboard.history` | the history, newest first: count, time and length of each entry, and whether the daemon collects. **Never a text, a first line or an id** (issue 750); the text is read through clipmenu on the operator's own screen |
|
|
| `node-clipboard.copy` | put text on the clipboard, then read it back; an error with the reason (no `DISPLAY`, `xsel` exited, other contents) when it does not hold the text. It enters the history like any copy |
|
|
| `clipmenu_paste` | how many bytes of text the clipboard holds now, never the text |
|
|
| `clipmenu_clear` | forget the history; the daemon's locks stay |
|
|
| `clipmenu_delete` | forget one entry, by its place in the history (1 is the newest) and the time the history gave it, refused if the history changed since; not by text or id |
|
|
|
|
The history is read from clipmenu's own store, in the account's runtime directory, under clipmenu's
|
|
own lock, so a copy arriving meanwhile is neither lost nor half-written. `copy` hands the text to an
|
|
owner (`xsel`) under the account's service manager. As a child of the tools runtime, the clipboard
|
|
would empty whenever the runtime restarted.
|
|
|
|
## What it improves on what was found
|
|
|
|
- **No AUR package.** greenclip came from the user repository. clipmenu is in the official one.
|
|
- **Started once.** greenclip was started by the window manager on both workstations, and on the
|
|
desktop by an enabled user unit as well.
|
|
- **No absolute home path** in any configuration. greenclip's named one.
|
|
- **The history does not outlive a reboot.** greenclip kept it in `~/.cache`, so every password ever
|
|
copied stayed on disk. clipmenu keeps it in the runtime directory, which is memory.
|
|
- **One menu.** The history appears in the launcher's own menu, through the seat's `dmenu` command,
|
|
instead of a theme from a cloned theme repository.
|
|
|
|
## What it leaves as found
|
|
|
|
- `~/.config/greenclip.toml` and greenclip's history, `~/.cache/greenclip.history`.
|
|
- On the desktop: greenclip's enabled user unit link
|
|
(`~/.config/systemd/user/default.target.wants/greenclip.service`). It dangles once the package is
|
|
gone.
|
|
|
|
## Migration (ADR 0182)
|
|
|
|
1. After the first push, delete `~/.config/greenclip.toml` and `~/.cache/greenclip.history`.
|
|
2. On the desktop: `systemctl --user disable greenclip.service`, before the push if you can. The
|
|
package's removal takes the unit file with it.
|
|
3. Until the `i3` module carries the main configuration, the found `exec --no-startup-id greenclip
|
|
daemon` and `$mod+period` lines stay in `~/.config/i3/config`. i3 reports `$mod+period` as bound
|
|
twice. The `i3` module's configuration carries neither.
|
|
|
|
## Blockers
|
|
|
|
- `node-clipboard`, `x11-display` and the `xinitrc` slot are ADR 0208's. Until the controller knows
|
|
them, `mctl` reads them as unknown.
|
|
- `CM_*` reach the session through `node-env` (ADR 0203), so the account's environment module must
|
|
be assigned too. Without it clipmenu runs on its defaults: both selections, 1000 clips, 8 lines.
|
|
|
|
## Only text is read (added 2026-10-04)
|
|
|
|
clipmenud reads a selection with `timeout 1 xsel -o`. A selection holding an image, such as a
|
|
screenshot copied as `image/png`, arrives in pieces. One second is too short for megabytes, so
|
|
`timeout` kills xsel half way, and the program owning the image waits for ever for a reader that is
|
|
gone. From then on every paste hangs, and an app asking on its main thread (Electron: Slack) freezes.
|
|
The first screenshot after this module was assigned did exactly that.
|
|
|
|
So clipmenud runs with the module's own `xsel` first on its `PATH`
|
|
(`/usr/local/lib/mesh-clipmenu/xsel`). Before a read it asks the selection for its `TARGETS` and goes
|
|
ahead only when the selection offers text. It uses `xclip` for that question, which the `xclip`
|
|
module installs on every workstation.
|
|
|
|
## Its i3 lines are a contribution (changed 2026-10-05, novox/hq ADR 0212)
|
|
|
|
The module no longer writes a file into i3's `config.d`. Its window-manager lines (the source is still
|
|
under `files/i3/` where it had one) are a contribution to `node-display-session`. The i3 module places
|
|
them in its own configuration under a `# <module>` line, so this module depends on a window manager
|
|
being assigned beside it.
|