Repository navigation
Pin the paste to a window from the compact pill - #15
Merged
Merged
Conversation
Asked for by the owner, who was writing feedback in Notepad while reading the site it was about: every dictation pasted into the browser in front, not into Notepad. Paste last could move it afterwards, one paste at a time. The compact pill now has a pin at the right end of the capsule, in the room the meter leaves there. A tap on it pins the paste to the window you were in: paste_target, which the pill tracks and which a tap does not move, since the pill never takes the foreground. While it is pinned: - **Every paste goes there, whatever is in front.** That covers a Type paste, Refine's Send, Paste last and a spoken correction. `_hand` brings the pinned window to the front, pastes, waits PIN_SETTLE_SEC for the keystrokes to arrive, and gives the foreground back to where you were. `inject.paste` still refuses a window that is not in front; the pinned one simply is, by then. - **The pin wears the mic's tint,** where it is grey unpinned, and the strip says once which window it holds. A second tap lets it go, and so does closing the window. A hold on the pin still talks; only a tap there is the pin's. - **A pinned paste stays changeable while you are elsewhere.** Keys go to the window in front, and a click on the pinned window brings it there, so nothing done elsewhere can move its caret. The run ends by the usual rules once you are back in that window. So "change X to Y", and the space between one note and the next, still work after you have clicked around the browser. Windows lets only the process with the last input event move the foreground, and after the talk keys that is not Flow: the chord runs on a keyboard hook. So `inject.bring_forward` asks plainly first. When that is refused, it shares the front thread's input for one SetForegroundWindow and detaches straight after. It restores a minimised window first. `inject.window_alive` checks the process id as well as the handle, because Windows reuses a closed window's handle. The pin is also in `_draw_key`: a frame redraws only when the key moves, and without it a pinned Type pill was photographed still grey. Lite draws no pin, because it has no windows to tell apart. The Classic pill is unchanged. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Samar tried the pin on real windows ("it works great") and asked for two changes.
**The line stays.** "pinned to Notepad - words go there wherever you are" was the
strip's usual three seconds, and where the words are going is the one thing the pill
cannot show by colour alone. While a window is pinned the strip is never empty. The
line comes back whenever another one ("not pasted: ...") has had its turn, and once
unpinned the strip goes as it always did.
**The icon is the pushpin Samar sent**, a solid pin lying head up and right, and the
same pin slashed for "not pinned":
- **Unpinned:** slashed and grey.
- **Pinned:** whole, in the mic's tint.
- **The cut:** a line over a solid shape in its own colour disappears into it, so
the slashed pin is cut into two pieces around the slash. The cut is sized by the
stroke in pixels, so it stays open at every size.
- **Geometry:** drawn upright in its own units and turned 45 degrees into the box,
so the numbers are the pin a person would sketch.
It is the one filled mark in glyphs.py beyond a dot. test_glyphs names it as the
fill rule's only exception (FILLED), and the pin still meets every other rule of the
language: colour, tags, box and stroke weight.
**Size and place:** 14 px rather than 12, which read as a smudge. It sits 9 px from
the capsule's end, so the needle clears the last meter bar; at 94 the photograph
had the two touching. The test for it now reads the capsule's round end rather than
a margin. The meter's test helper tells a bar from the pin's grey body by width.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Codex Review SummaryThis comment shows the latest Codex review activity on this pull request.
ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings. |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 3df5497e00
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
… the pin at the paste Codex's three findings on #15, and the macOS leg's one error. - A tray Paste last while pinned first gave the foreground to `paste_target`, which pinned is the pinned window, so `_hand` had nowhere to go back to and Notepad stayed in front of the site you were reading. While pinned, `_track_target` now keeps `_last_front` (never Flow's, never the taskbar, `classify` on the edge only), and the tray's restore uses it. Pinning starts it at the pinned window, not one from an older pin. - `_hand` asks `window_alive` with the pid again right before the paste. A window closed since the last frame, its handle maybe another's already, gets nothing, and the pin lets it go. - The hand-back after PIN_SETTLE_SEC only happens while the pinned window still has the foreground, so a window you picked meanwhile stays in front. - The test Desk fakes `classify` too. Unpinned, a frame asked the real one, and on a Mac that imports `flow.inject`, which has no WinDLL to bind. Suite 3243, the 13 known test_refine failures only (codex.CMD on this machine). Each new test fails on the previous commit. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
The compact pill gets a pin. Tap it and every paste goes to the window you were in, whatever's in front when you speak.
The case it came from: writing feedback in Notepad while reading the site it was about. Every dictation pasted into the browser, and Paste last could only move it afterwards, one paste at a time.
What it does
The pin sits at the right end of the capsule. A tap pins
paste_target, the window the pill already tracks. While it's pinned, a Type paste, Refine's Send, Paste last and a spoken correction all land in that window._handbrings it forward, pastes, waitsPIN_SETTLE_SEC(0.12 s) and hands the foreground back to where you were.Windows only lets the process with the last input event move the foreground, and after the talk keys that isn't Flow. So
inject.bring_forwardasks plainly first, and when that's refused it attaches to the front thread's input for oneSetForegroundWindow, then detaches. It restores a minimised window first.inject.window_alivechecks the pid as well as the handle, because Windows reuses a closed window's handle, and closing the pinned window unpins it.A pinned paste run survives keys and clicks elsewhere, so "change X to Y" and joins still work after you've clicked around the browser.
How it looks
The icon is a solid pushpin, head up and right. Unpinned it's slashed and grey, pinned it's whole and in the mic's tint. It's the one filled mark in glyphs.py, and test_glyphs lists it as the fill rule's only exception. It's 14 px, 9 px from the capsule's end, so the needle clears the last meter bar.
While a window is pinned the strip always says "pinned to X - words go there wherever you are", coming back after any other notice.
Lite draws no pin, and the Classic pill and the right-click menu are unchanged.
Tested
Samar tried it on real windows: "it works great". The full suite ran on this branch rebased onto d7a9d4b (3239 tests). The only failures were the 13 known test_refine ones from this machine's
codex.CMDshim, plus the sdist size guard, which trips locally on an untracked folder. The committed tree's sdist is 1,939,421 B, under the 2 MB guard.Still to come in a later change: a guide.md section and a decisions.md entry, since this adds a gesture to the pill.
🤖 Generated with Claude Code