Files
mesh-catalog/modules/clipmenu/README.md
T
jochen 493651776c lemurs, clipmenu: X keeps its resources, and an image in the clipboard is never read as text
X reset twice during the session start and threw away the resources xrdb had just merged, so
xterm came up in the bitmap fixed font. clipmenud's one-second xsel read of a screenshot was
killed mid-transfer and left the image's owner hung, so every paste after it hung.
2026-10-04 16:34:02 +02:00

83 lines
4.5 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.
- Starts `clipmenud` **once per session**, from the session's start (the `xinitrc` slot `normal`).
It is not a user unit as well. Its packaged unit needs user-scoped units (mesh-host #72, not
merged), and the session start alone is one starter.
- 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, each entry once with its id, first line, time, size and text (cut) |
| `node-clipboard.copy` | put text on the clipboard; it enters the history like any copy |
| `clipmenu_paste` | what the clipboard holds now |
| `clipmenu_clear` | forget the history; the daemon's locks stay |
| `clipmenu_delete` | forget one entry, by id or first line |
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.