Skip to content

A hotkey opens the pastes you keep, and the number key is a position - #32

Merged
JIRPOS merged 3 commits into
masterfrom
quickpaste
Aug 10, 2026
Merged

A hotkey opens the pastes you keep, and the number key is a position#32
JIRPOS merged 3 commits into
masterfrom
quickpaste

Conversation

@JIRPOS

@JIRPOS JIRPOS commented Aug 10, 2026

Copy link
Copy Markdown
Owner

Release notes

ADDED: QuickPaste. Alt+V opens your saved snippets at the cursor — a map regex, a vendor
search, the whisper you send twenty times an evening. Click one or press its number and it is on
your clipboard. It does not press Ctrl+V for you: you paste it yourself, in the field you meant, at
your own time.

ADDED: the number keys go by the key's position, so the top row picks a paste whatever your
layout prints on it.

ADDED: nine at a time, because that is how many number keys there are. Keep as many as you like —
the ones beyond nine are simply switched off until you switch something else off. Nothing to read,
nothing refused.

ADDED: a QuickPaste tab in Settings to write them, drag them into the order you want them
offered in, and switch them in and out. Adding and editing happen in a dialog; nothing is kept
until you Save, so a delete you did not mean is undone by closing Settings.

ADDED: the popup opens at your cursor, growing down, up, or from somewhere between the two,
whichever fits.

CHANGED: no panel of ours stays on screen when you alt-tab to another application, and one that
was open takes the keyboard again when you come back to the game.

CHANGED: a config.json that has been edited by hand into something unreadable no longer stops
the tool from starting. It keeps what it could read and defaults the rest.

Review notes

ADDED: clipboard_set_text as a platform seam, never SDL_SetClipboardText.

ADDED: an X11 selection owner on a thread of its own — its own Display, poked through a
self-pipe, serving TARGETS, TIMESTAMP, UTF8_STRING, the two text/plain forms and STRING for the
life of the process.

  • A selection is a live window answering SelectionRequest, not a place to put bytes: the owner
    has to still be there when the paste happens.
  • STRING is served the same UTF-8 bytes deliberately. It is nominally Latin-1, but everything that
    can read UTF-8 asks for UTF8_STRING first, and refusing STRING leaves the rest with nothing.

ADDED: the Windows write, OpenClipboard/CF_UNICODETEXT, retried while another application holds
the lock.

ADDED: kMaxClipboardWrite, 64KB — one XChangeProperty, no INCR on this side.

ADDED: QuickPaste — the model in ppc_core (src/quickpaste.{hpp,cpp}), the popup
(quickpaste_screen.cpp), the Settings tab (quickpaste_tab), and docs/quickpaste.md.

ADDED: the entries in config.json under pastes, and in PRIVACY.md, since they are text the user
typed.

ADDED: picking by number key, read as SDL_Scancode.

  • A keycode test would leave the feature unusable by number outside a US layout: the same physical
    keys print ěščřžýáíé on a Czech one.

ADDED: nine active slots. Storage is unbounded and enabled is what competes for a number;
limit_enabled holds the ceiling on config load as well as in the UI.

ADDED: drag-to-reorder on a grip handle, measured in pixels of travel rather than in rows crossed,
and tracked by us rather than by ImGui's held-item id.

  • Asking which row the pointer is over only holds while every row is the same height; these are
    two lines and the second wraps, so a move drops the pointer back over the row it came from and
    the list flickers between the two.
  • A row's ImGui id is its index, so the frame a move lands ImGui is holding the handle of whatever
    slid into the vacated place.

ADDED: four Font Awesome glyphs — grip-lines, pen, trash-can, square-plus.

ADDED: quickpaste_test — slot ordering, the ceiling, move_paste, the one-line preview on a
UTF-8 boundary, and a config round trip.

CHANGED: the write blocks until the server reports us as the owner, bounded at 250ms.

  • The caller hands the focus back to the game immediately afterwards and Wine re-reads the
    selection around that focus change, so returning early is a first paste of the previous
    clipboard. Measured at 0.1-0.7ms.

CHANGED: kOnlyGlyphs is derived from kGlyphCodepoints rather than hand-written.

  • The old range covered U+F00C..U+F0E2 because that was where the first two glyphs happened to sit,
    so all four new ones baked as nothing.

CHANGED: nothing of ours stays on screen when the game is present and a third application is in
front — panels included, not only the idle marker. Panels stay up when the game is gone, or they
would be unreachable.

CHANGED: the keyboard focus is re-claimed when the game comes back to the front and on a click into
a panel, not only when the panel opens.

  • Our window is override-redirect, so the window manager will never focus it: a panel that lost the
    focus to an alt-tab was left on screen taking no input.

CHANGED: Config::load reads every field inside one try.

  • config.json is hand-editable and nlohmann throws as readily on a field of the wrong type as on
    a truncated file, so an object where a string belongs was an uncaught exception before the first
    window.

CHANGED: VERSION to 0.5, in its own commit.

🤖 Generated with Claude Code

JIRPOS added 3 commits August 10, 2026 21:04
ADDED: `clipboard_set_text` as a platform seam, never `SDL_SetClipboardText`.

ADDED: an X11 selection owner on a thread of its own — its own `Display`, poked
through a self-pipe, serving TARGETS, TIMESTAMP, UTF8_STRING, the two text/plain
forms and STRING for the life of the process.

- A selection is a live window answering `SelectionRequest`, not a place to put
  bytes: the owner has to still be there when the paste happens.
- STRING is served the same UTF-8 bytes deliberately. It is nominally Latin-1,
  but everything that can read UTF-8 asks for UTF8_STRING first, and refusing
  STRING leaves the rest with nothing.

ADDED: the Windows write, `OpenClipboard`/`CF_UNICODETEXT`, retried while
another application holds the lock.

ADDED: `kMaxClipboardWrite`, 64KB — one `XChangeProperty`, no INCR on this side.

CHANGED: the write blocks until the server reports us as the owner, bounded at
250ms.

- The caller hands the focus back to the game immediately afterwards and Wine
  re-reads the selection around that focus change, so returning early is a first
  paste of the previous clipboard. Measured at 0.1-0.7ms.
ADDED: QuickPaste — Alt+V opens a list of saved snippets at the cursor; picking
one puts its text on the clipboard, closes the popup and gives the game back the
foreground. Nothing presses Ctrl+V.

ADDED: the entries themselves, heading and multi-line body, in `config.json`
under `pastes` and in PRIVACY.md, since they are text the user typed.

ADDED: a QuickPaste tab in Settings — a read-only list to arrange, with adding
and editing in a modal dialog on a draft, and drag-to-reorder on a grip handle.

ADDED: picking by number key, read as `SDL_Scancode`.

- A keycode test would leave the feature unusable by number outside a US layout:
  the same physical keys print `ěščřžýáíé` on a Czech one.

ADDED: nine active slots, which is how many number keys there are. Storage is
unbounded and `enabled` is what competes for a number; the ceiling holds on
config load too, and the tenth checkbox is disabled rather than refused.

ADDED: four Font Awesome glyphs — grip-lines, pen, trash-can, square-plus.

CHANGED: `kOnlyGlyphs` is derived from `kGlyphCodepoints` rather than
hand-written.

- The old range covered U+F00C..U+F0E2 because that was where the first two
  glyphs happened to sit, so all four new ones baked as nothing.

CHANGED: nothing of ours stays on screen when the game is present and a third
application is in front — panels included, not only the idle marker. Panels stay
up when the game is *gone*, or they would be unreachable.

CHANGED: the keyboard focus is re-claimed when the game comes back to the front
and on a click into a panel, not only when the panel opens.

- Our window is override-redirect, so the window manager will never focus it: a
  panel that lost the focus to an alt-tab was left on screen taking no input.

CHANGED: `Config::load` reads every field inside one `try`.

- `config.json` is hand-editable and nlohmann throws as readily on a field of
  the wrong type as on a truncated file, so an object where a string belongs was
  an uncaught exception before the first window.
@JIRPOS
JIRPOS merged commit 5e2e25f into master Aug 10, 2026
9 checks passed
@JIRPOS
JIRPOS deleted the quickpaste branch August 10, 2026 19:13
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant