Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions docs/next/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
- Experimental pane graphics now support bounded named layers, acknowledged full-RGBA primary-layer direct file frames on audited local terminals, owned BGRA fallback, exact pixel mouse input, and placement-only resize replay.

### Fixed
- Unix plugin pane commands now default `PWD` to their resolved working directory, so direct popup tools open at explicit `--cwd` paths while preserving caller-provided `PWD` values. (#2984)
- High-rate output from many hidden panes no longer floods the server loop with redundant wakeups, and terminal input-mode synchronization no longer formats pane scrollback to read one keyboard flag.
- Chinese IME commits now reach panes on macOS when the focused application requests printable key-release events. (#2924)
- Windows now recognizes `Ctrl+1` through `Ctrl+9` keybindings instead of decoding those key records as control characters. (#2910)
Expand Down
34 changes: 20 additions & 14 deletions src/app/api/plugins/panes.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,17 +16,17 @@ impl App {
pane: PluginManifestPane,
) -> String {
let context = self.current_plugin_context("plugin-pane");
let cwd = self.plugin_pane_cwd(plugin, params.cwd);
let extra_env =
match self.plugin_pane_launch_env(plugin, &pane.id, params.env.clone(), &context) {
match self.plugin_pane_launch_env(plugin, &pane.id, &cwd, params.env, &context) {
Ok(env) => env,
Err((code, message)) => return encode_error(id, &code, message),
};
let cwd = Some(self.plugin_pane_cwd(plugin, params.cwd));
let width = params.width.or(pane.width);
let height = params.height.or(pane.height);
if let Err(err) = self.spawn_popup_argv_command(
&pane.command,
cwd,
Some(cwd),
extra_env,
crate::app::popup::PopupGeometry { width, height },
) {
Expand All @@ -49,17 +49,21 @@ impl App {
pane: PluginManifestPane,
) -> String {
let context = self.current_plugin_context("plugin-pane");
let cwd = self.plugin_pane_cwd(plugin, params.cwd);
let extra_env =
match self.plugin_pane_launch_env(plugin, &pane.id, params.env.clone(), &context) {
match self.plugin_pane_launch_env(plugin, &pane.id, &cwd, params.env, &context) {
Ok(env) => env,
Err((code, message)) => return encode_error(id, &code, message),
};
let cwd = Some(self.plugin_pane_cwd(plugin, params.cwd));
let (ws_idx, new_pane) =
match self.spawn_overlay_argv_command(&pane.command, cwd, extra_env, Vec::new()) {
Ok(result) => result,
Err(err) => return encode_error(id, "plugin_pane_open_failed", err.to_string()),
};
let (ws_idx, new_pane) = match self.spawn_overlay_argv_command(
&pane.command,
Some(cwd),
extra_env,
Vec::new(),
) {
Ok(result) => result,
Err(err) => return encode_error(id, "plugin_pane_open_failed", err.to_string()),
};
let layout_tab_idx = self
.overlay_panes
.get(&new_pane.pane_id)
Expand Down Expand Up @@ -98,8 +102,9 @@ impl App {
);
};
let context = self.plugin_context_for_pane(ws_idx, target_pane, "plugin-pane");
let cwd = self.plugin_pane_cwd(plugin, params.cwd);
let extra_env =
match self.plugin_pane_launch_env(plugin, &pane.id, params.env.clone(), &context) {
match self.plugin_pane_launch_env(plugin, &pane.id, &cwd, params.env, &context) {
Ok(env) => env,
Err((code, message)) => return encode_error(id, &code, message),
};
Expand All @@ -110,7 +115,6 @@ impl App {
crate::api::schema::SplitDirection::Right => Direction::Horizontal,
crate::api::schema::SplitDirection::Down => Direction::Vertical,
};
let cwd = Some(self.plugin_pane_cwd(plugin, params.cwd));
let (rows, cols) = self.state.estimate_pane_size();
let previous_focus = self.state.current_pane_focus_target();
let Some(ws) = self.state.workspaces.get_mut(ws_idx) else {
Expand All @@ -121,7 +125,7 @@ impl App {
direction,
rows.max(4),
cols.max(10),
cwd,
Some(cwd),
&pane.command,
extra_env,
self.state.pane_scrollback_limit_bytes,
Expand Down Expand Up @@ -187,7 +191,7 @@ impl App {
let cwd = self.plugin_pane_cwd(plugin, params.cwd);
let context = self.plugin_context_for_workspace(ws_idx, "plugin-pane");
let extra_env =
match self.plugin_pane_launch_env(plugin, &pane.id, params.env.clone(), &context) {
match self.plugin_pane_launch_env(plugin, &pane.id, &cwd, params.env, &context) {
Ok(env) => env,
Err((code, message)) => return encode_error(id, &code, message),
};
Expand Down Expand Up @@ -233,10 +237,12 @@ impl App {
&self,
plugin: &InstalledPluginInfo,
entrypoint: &str,
cwd: &std::path::Path,
env: std::collections::HashMap<String, String>,
context: &PluginInvocationContext,
) -> Result<Vec<(String, String)>, (String, String)> {
let mut env = super::super::env::normalize_launch_env(env)?;
crate::platform::set_default_plugin_pane_pwd(&mut env, cwd);
let context_json = serde_json::to_string(&context)
.map_err(|err| ("invalid_plugin_context".to_string(), err.to_string()))?;
super::env::ensure_plugin_user_dirs(plugin)
Expand Down
10 changes: 10 additions & 0 deletions src/platform/fallback.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,16 @@ use std::process::Command;

use super::{ClipboardImage, ForegroundJob, Signal};

#[cfg(unix)]
pub(crate) use super::unix_common::set_default_plugin_pane_pwd;

#[cfg(not(unix))]
pub(crate) fn set_default_plugin_pane_pwd(
_env: &mut Vec<(String, String)>,
_cwd: &std::path::Path,
) {
}

pub(crate) fn remote_ssh_config_paths() -> super::RemoteSshConfigPaths {
super::RemoteSshConfigPaths {
user_config: std::env::var_os("HOME")
Expand Down
3 changes: 2 additions & 1 deletion src/platform/linux.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,8 @@ pub(crate) use super::unix_common::{
configure_status_command, create_remote_private_dir, create_remote_ssh_config_dir,
create_remote_ssh_config_file, hostname, local_datetime, remote_bridge_endpoint_path,
remote_private_temp_base, remote_reattach_argument, remote_reattach_program,
remote_ssh_config_paths, status_commands_supported, StatusCommandGuard,
remote_ssh_config_paths, set_default_plugin_pane_pwd, status_commands_supported,
StatusCommandGuard,
};

const WSL_MARKER_ENV_VARS: &[&str] = &["WSL_DISTRO_NAME", "WSL_INTEROP"];
Expand Down
3 changes: 2 additions & 1 deletion src/platform/macos.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,8 @@ pub(crate) use super::unix_common::{
configure_status_command, create_remote_private_dir, create_remote_ssh_config_dir,
create_remote_ssh_config_file, hostname, local_datetime, remote_bridge_endpoint_path,
remote_private_temp_base, remote_reattach_argument, remote_reattach_program,
remote_ssh_config_paths, status_commands_supported, StatusCommandGuard,
remote_ssh_config_paths, set_default_plugin_pane_pwd, status_commands_supported,
StatusCommandGuard,
};

const PROC_PGRP_ONLY: u32 = 2;
Expand Down
18 changes: 18 additions & 0 deletions src/platform/unix_common.rs
Original file line number Diff line number Diff line change
Expand Up @@ -209,10 +209,28 @@ fn datetime_from_tm(value: &libc::tm) -> Option<time::PrimitiveDateTime> {
Some(time::PrimitiveDateTime::new(date, time))
}

pub(crate) fn set_default_plugin_pane_pwd(env: &mut Vec<(String, String)>, cwd: &std::path::Path) {
if !env.iter().any(|(key, _)| key == "PWD") {
env.push(("PWD".to_string(), cwd.display().to_string()));
}
}

#[cfg(test)]
mod tests {
use super::*;

#[test]
fn plugin_pane_pwd_defaults_to_cwd_without_overriding_explicit_env() {
let cwd = Path::new("/plugin-cwd");
let mut derived = vec![("OTHER".to_string(), "value".to_string())];
set_default_plugin_pane_pwd(&mut derived, cwd);
assert!(derived.contains(&("PWD".to_string(), "/plugin-cwd".to_string())));

let mut explicit = vec![("PWD".to_string(), "/caller-pwd".to_string())];
set_default_plugin_pane_pwd(&mut explicit, cwd);
assert_eq!(explicit, [("PWD".to_string(), "/caller-pwd".to_string())]);
}

#[test]
fn remote_ssh_config_dir_rejects_overlong_control_socket_name() {
let err = create_remote_ssh_config_dir(&"x".repeat(200)).unwrap_err();
Expand Down
6 changes: 6 additions & 0 deletions src/platform/windows.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,12 @@ use std::{

mod clipboard_image;

pub(crate) fn set_default_plugin_pane_pwd(
_env: &mut Vec<(String, String)>,
_cwd: &std::path::Path,
) {
}

use windows_sys::{
Wdk::System::Threading::{NtQueryInformationProcess, ProcessBasicInformation},
Win32::{
Expand Down
Loading