diff options
| author | Ogulcan Celik <ogulcancelik@gmail.com> | 2026-07-03 22:19:47 +0300 |
|---|---|---|
| committer | Ogulcan Celik <ogulcancelik@gmail.com> | 2026-07-03 22:19:47 +0300 |
| commit | 6f148588dde3b330618981c344c12f400d74da7d (patch) | |
| tree | 49e296f55a781bb3e4f2759311c667f2115b3a61 | |
| parent | 6ea68f9af2569ea87b7d243c5bbe4f3bc4c8fa44 (diff) | |
fix: scope empty image paste bridge to remote
refs #986
| -rw-r--r-- | docs/next/CHANGELOG.md | 1 | ||||
| -rw-r--r-- | docs/next/website/src/content/docs/configuration.mdx | 2 | ||||
| -rw-r--r-- | src/client/mod.rs | 33 |
3 files changed, 30 insertions, 6 deletions
diff --git a/docs/next/CHANGELOG.md b/docs/next/CHANGELOG.md index db771584..310e1da1 100644 --- a/docs/next/CHANGELOG.md +++ b/docs/next/CHANGELOG.md @@ -15,6 +15,7 @@ - Bumped the client/server protocol version to 15 for socket API placement mutation event and response compatibility. ### Fixed +- Unix local Herdr clients no longer treat empty bracketed paste as a clipboard-image bridge; `herdr --remote` keeps using it for local-desktop image paste over SSH. (#986) - Plain PageUp/PageDown now reach primary-screen pager apps such as `less -X` and Git diff when they enter application cursor mode, while shell transcripts still use Herdr pane scrollback. (#953) - `prefix+e` scrollback editor panes now open on Windows without trying to run `/bin/sh`; Windows uses `VISUAL`, then `EDITOR`, then `notepad.exe` as the fallback editor. (#914) - `herdr pane split --current` now resolves to the calling Herdr pane instead of the UI-focused pane when run inside a pane. (#902) diff --git a/docs/next/website/src/content/docs/configuration.mdx b/docs/next/website/src/content/docs/configuration.mdx index f7bcb616..0305a670 100644 --- a/docs/next/website/src/content/docs/configuration.mdx +++ b/docs/next/website/src/content/docs/configuration.mdx @@ -198,7 +198,7 @@ next_tab = ["prefix+n", "ctrl+alt+]"] `last_pane` switches back to the last focused pane across workspaces and tabs. It is unset by default because the tmux-style pane binding `prefix+l` is already used for pane-right focus. -`remote_image_paste` is only active in `herdr --remote`. It is the local-client shortcut that sends a local clipboard image to the remote pane. Set it to an empty string to disable the raw-key shortcut; terminal paste-image signals still work when the outer terminal sends them. +`remote_image_paste` is only active in `herdr --remote`. It is the local-client shortcut that sends a local clipboard image to the remote pane. Set it to an empty string to disable the raw-key shortcut; remote terminal paste-image signals still work when the outer terminal sends them. Key strings accept plain keys, modifier combinations such as `ctrl+a`, `shift+n`, `alt+1`, `cmd+k`, and special keys such as `enter`, `tab`, `esc`, `left`, `right`, `up`, and `down`. Named punctuation such as `minus`, `comma`, `ampersand`, `plus`, and `backtick` is also accepted. Plain direct printable keys such as `n` are unsafe because they intercept typing; use `prefix+n` unless you intentionally want a direct binding. The `navigate_workspace_*` and `navigate_pane_*` fields are navigate-mode-only and may use plain keys such as `j` or `k`; they must not use `prefix+`, `esc`, `enter`, `tab`, `shift+tab`, `left`, `right`, or unmodified `1` through `9`. Left and right arrows are permanent aliases for pane-left and pane-right navigation. These navigate-mode shortcuts are independent from general action bindings such as `focus_pane_down = "prefix+j"`; when both use the same key, the navigate-mode shortcut wins while navigate mode is open. Alt, Cmd/Super, and punctuation with modifiers depend on your terminal and tmux settings. diff --git a/src/client/mod.rs b/src/client/mod.rs index ceed9826..6a70c79c 100644 --- a/src/client/mod.rs +++ b/src/client/mod.rs @@ -1278,6 +1278,8 @@ async fn run_client_loop( #[cfg(windows)] let _ = config.mouse_scroll_lines; let draw_host_cursor = attach_escape.is_none() && should_draw_host_cursor(config.host_cursor); + #[cfg(unix)] + let is_remote_client = is_remote_client_process(); let mut state = ClientState { blit_encoder: render_ansi::BlitEncoder::new(), @@ -1409,7 +1411,11 @@ async fn run_client_loop( } data }; - if should_bridge_clipboard_image_paste(&data, state.remote_image_paste_key) { + if should_bridge_clipboard_image_paste( + &data, + is_remote_client, + state.remote_image_paste_key, + ) { if let Some(image) = crate::platform::read_clipboard_image() { if image.bytes.len() > MAX_CLIPBOARD_IMAGE_PAYLOAD { warn!( @@ -1761,10 +1767,11 @@ fn sound_from_notify_message(message: &str) -> Option<crate::sound::Sound> { #[cfg(unix)] fn should_bridge_clipboard_image_paste( data: &[u8], + is_remote_client: bool, remote_image_paste_key: Option<(crossterm::event::KeyCode, crossterm::event::KeyModifiers)>, ) -> bool { if data == b"\x1b[200~\x1b[201~" { - return true; + return is_remote_client; } let Some(remote_image_paste_key) = remote_image_paste_key else { @@ -2080,21 +2087,37 @@ mod tests { #[test] fn clipboard_image_paste_bridge_triggers_on_configured_key_and_empty_paste() { let ctrl_v = crate::config::parse_key_combo("ctrl+v").unwrap(); - assert!(should_bridge_clipboard_image_paste(&[0x16], Some(ctrl_v))); + assert!(should_bridge_clipboard_image_paste( + &[0x16], + true, + Some(ctrl_v) + )); assert!(should_bridge_clipboard_image_paste( b"\x1b[118;5u", + true, Some(ctrl_v) )); assert!(should_bridge_clipboard_image_paste( b"\x1b[200~\x1b[201~", + true, None )); assert!(!should_bridge_clipboard_image_paste( + b"\x1b[200~\x1b[201~", + false, + Some(ctrl_v) + )); + assert!(!should_bridge_clipboard_image_paste( b"\x1b[200~text\x1b[201~", + true, + Some(ctrl_v) + )); + assert!(!should_bridge_clipboard_image_paste(&[0x16], true, None)); + assert!(!should_bridge_clipboard_image_paste( + b"v", + true, Some(ctrl_v) )); - assert!(!should_bridge_clipboard_image_paste(&[0x16], None)); - assert!(!should_bridge_clipboard_image_paste(b"v", Some(ctrl_v))); } #[test] |
