diff --git a/ui-tui/packages/hermes-ink/src/ink/components/App.tsx b/ui-tui/packages/hermes-ink/src/ink/components/App.tsx index 3a0381a729..6eb295e056 100644 --- a/ui-tui/packages/hermes-ink/src/ink/components/App.tsx +++ b/ui-tui/packages/hermes-ink/src/ink/components/App.tsx @@ -617,6 +617,14 @@ export function handleMouseEvent(app: App, m: ParsedMouse): void { // Non-left press breaks the multi-click chain. app.clickCount = 0 + // Forward middle/right button presses to the DOM so components can + // react (e.g. right-click-to-paste on input fields). Middle/right + // don't participate in selection, multi-click, or hyperlink UX, so + // we just dispatch and exit without setting mouseCaptureTarget — + // the matching release (if any) falls through the release path and + // is ignored there because baseButton !== 0 && !sel.isDragging. + app.props.onMouseDownAt(col, row, baseButton) + return } diff --git a/ui-tui/src/components/textInput.tsx b/ui-tui/src/components/textInput.tsx index dff8121b5e..73710f87ff 100644 --- a/ui-tui/src/components/textInput.tsx +++ b/ui-tui/src/components/textInput.tsx @@ -671,6 +671,15 @@ export function TextInput({ setCur(next) curRef.current = next }} + onMouseDown={(e: { button: number }) => { + // Right-click to paste: route through the same hotkey path as + // Alt+V so the composer's clipboard RPC (text or image) handles it. + if (!focus || e.button !== 2) { + return + } + + emitPaste({ cursor: curRef.current, hotkey: true, text: '', value: vRef.current }) + }} ref={boxRef} > {rendered}