Compare commits

...

2 Commits

Author SHA1 Message Date
canvrno-oai
380c15f5e4 Merge branch 'main' into canvrno/17502-windows-image-paste-hint 2026-04-20 16:58:20 -07:00
canvrno-oai
98e51c7e73 fix(tui): clarify windows image paste shortcut 2026-04-17 11:56:08 -07:00
3 changed files with 19 additions and 5 deletions

View File

@@ -911,6 +911,7 @@ enum DisplayCondition {
WhenShiftEnterHint,
WhenNotShiftEnterHint,
WhenUnderWSL,
WhenNativeWindows,
WhenCollaborationModesEnabled,
}
@@ -921,6 +922,7 @@ impl DisplayCondition {
DisplayCondition::WhenShiftEnterHint => state.use_shift_enter_hint,
DisplayCondition::WhenNotShiftEnterHint => !state.use_shift_enter_hint,
DisplayCondition::WhenUnderWSL => state.is_wsl,
DisplayCondition::WhenNativeWindows => cfg!(target_os = "windows") && !state.is_wsl,
DisplayCondition::WhenCollaborationModesEnabled => state.collaboration_modes_enabled,
}
}
@@ -1013,13 +1015,18 @@ const SHORTCUTS: &[ShortcutDescriptor] = &[
},
ShortcutDescriptor {
id: ShortcutId::PasteImage,
// Show Ctrl+Alt+V when running under WSL (terminals often intercept plain
// Ctrl+V); otherwise fall back to Ctrl+V.
// Show Ctrl+Alt+V when running under WSL, Alt+V on native Windows, and
// Ctrl+V elsewhere. Windows terminals often intercept plain Ctrl+V
// before the TUI sees it.
bindings: &[
ShortcutBinding {
key: key_hint::ctrl_alt(KeyCode::Char('v')),
condition: DisplayCondition::WhenUnderWSL,
},
ShortcutBinding {
key: key_hint::alt(KeyCode::Char('v')),
condition: DisplayCondition::WhenNativeWindows,
},
ShortcutBinding {
key: key_hint::ctrl(KeyCode::Char('v')),
condition: DisplayCondition::Always,
@@ -1743,7 +1750,7 @@ mod tests {
}
#[test]
fn paste_image_shortcut_prefers_ctrl_alt_v_under_wsl() {
fn paste_image_shortcut_uses_platform_specific_binding() {
let descriptor = SHORTCUTS
.iter()
.find(|descriptor| descriptor.id == ShortcutId::PasteImage)
@@ -1762,6 +1769,8 @@ mod tests {
let expected_key = if is_wsl {
key_hint::ctrl_alt(KeyCode::Char('v'))
} else if cfg!(target_os = "windows") {
key_hint::alt(KeyCode::Char('v'))
} else {
key_hint::ctrl(KeyCode::Char('v'))
};

View File

@@ -5307,8 +5307,13 @@ impl ChatWidget {
}
Err(err) => {
tracing::warn!("failed to paste image: {err}");
#[cfg(target_os = "windows")]
let guidance = "If you're on Windows, try Alt+V first; some terminals intercept Ctrl+V. If that still fails, save the image to a file and paste the file path instead.";
#[cfg(not(target_os = "windows"))]
let guidance =
"Try saving the image to a file and paste the file path instead.";
self.add_to_history(history_cell::new_error_event(format!(
"Failed to paste image: {err}",
"Failed to paste image: {err}. {guidance}",
)));
}
}

View File

@@ -21,6 +21,6 @@ You can run any shell command from Codex using `!` (e.g. `!ls`)
Type / to open the command popup; Tab autocompletes slash commands.
When the composer is empty, press Esc to step back and edit your last message; Enter confirms.
Press Tab to queue a message when a task is running; otherwise it sends immediately (except `!`).
Paste an image with Ctrl+V to attach it to your next message.
Paste an image with Ctrl+V to attach it to your next message. On Windows, try Alt+V if Ctrl+V is intercepted.
You can resume a previous conversation by running `codex resume`
Use /copy or press Ctrl+O to copy the latest agent response as Markdown.