diff --git a/default-plugins/fixture-plugin-for-tests/src/main.rs b/default-plugins/fixture-plugin-for-tests/src/main.rs index 17f29943..fe740f74 100644 --- a/default-plugins/fixture-plugin-for-tests/src/main.rs +++ b/default-plugins/fixture-plugin-for-tests/src/main.rs @@ -167,10 +167,13 @@ impl ZellijPlugin for State { }); }, Key::Ctrl('h') => { - open_file_floating(FileToOpen { - path: std::path::PathBuf::from("/path/to/my/file.rs"), - ..Default::default() - }); + open_file_floating( + FileToOpen { + path: std::path::PathBuf::from("/path/to/my/file.rs"), + ..Default::default() + }, + None, + ); }, Key::Ctrl('i') => { open_file(FileToOpen { @@ -180,11 +183,14 @@ impl ZellijPlugin for State { }); }, Key::Ctrl('j') => { - open_file_floating(FileToOpen { - path: std::path::PathBuf::from("/path/to/my/file.rs"), - line_number: Some(42), - ..Default::default() - }); + open_file_floating( + FileToOpen { + path: std::path::PathBuf::from("/path/to/my/file.rs"), + line_number: Some(42), + ..Default::default() + }, + None, + ); }, Key::Ctrl('k') => { open_terminal(std::path::PathBuf::from("/path/to/my/file.rs").as_path()); @@ -192,6 +198,7 @@ impl ZellijPlugin for State { Key::Ctrl('l') => { open_terminal_floating( std::path::PathBuf::from("/path/to/my/file.rs").as_path(), + None, ); }, Key::Ctrl('m') => { @@ -202,11 +209,14 @@ impl ZellijPlugin for State { }); }, Key::Ctrl('n') => { - open_command_pane_floating(CommandToRun { - path: std::path::PathBuf::from("/path/to/my/file.rs"), - args: vec!["arg1".to_owned(), "arg2".to_owned()], - ..Default::default() - }); + open_command_pane_floating( + CommandToRun { + path: std::path::PathBuf::from("/path/to/my/file.rs"), + args: vec!["arg1".to_owned(), "arg2".to_owned()], + ..Default::default() + }, + None, + ); }, Key::Ctrl('o') => { switch_tab_to(1); diff --git a/default-plugins/strider/src/search/search_state.rs b/default-plugins/strider/src/search/search_state.rs index 834a74fe..60d03941 100644 --- a/default-plugins/strider/src/search/search_state.rs +++ b/default-plugins/strider/src/search/search_state.rs @@ -88,10 +88,13 @@ impl SearchState { match self.selected_search_result_entry() { Some(SearchResult::File { path, .. }) => { if self.should_open_floating { - open_file_floating(FileToOpen { - path: PathBuf::from(path), - ..Default::default() - }); + open_file_floating( + FileToOpen { + path: PathBuf::from(path), + ..Default::default() + }, + None, + ); } else { open_file(FileToOpen { path: PathBuf::from(path), @@ -103,11 +106,14 @@ impl SearchState { path, line_number, .. }) => { if self.should_open_floating { - open_file_floating(FileToOpen { - path: PathBuf::from(path), - line_number: Some(line_number), - ..Default::default() - }); + open_file_floating( + FileToOpen { + path: PathBuf::from(path), + line_number: Some(line_number), + ..Default::default() + }, + None, + ); } else { open_file(FileToOpen { path: PathBuf::from(path), @@ -132,7 +138,7 @@ impl SearchState { { let dir_path = dir_path_of_result(&path); if self.should_open_floating { - open_terminal_floating(&dir_path); + open_terminal_floating(&dir_path, None); } else { open_terminal(&dir_path); } diff --git a/src/main.rs b/src/main.rs index 30770405..871d468f 100644 --- a/src/main.rs +++ b/src/main.rs @@ -29,6 +29,10 @@ fn main() { name, close_on_exit, start_suspended, + x, + y, + width, + height, })) = opts.command { let cwd = cwd.or_else(|| std::env::current_dir().ok()); @@ -45,6 +49,10 @@ fn main() { start_suspended, configuration: None, skip_plugin_cache, + x, + y, + width, + height, }; commands::send_action_to_session(command_cli_action, opts.session, config); std::process::exit(0); @@ -55,6 +63,10 @@ fn main() { in_place, configuration, skip_plugin_cache, + x, + y, + width, + height, })) = opts.command { let cwd = std::env::current_dir().ok(); @@ -70,6 +82,10 @@ fn main() { start_suspended: false, configuration, skip_plugin_cache, + x, + y, + width, + height, }; commands::send_action_to_session(command_cli_action, opts.session, config); std::process::exit(0); @@ -81,6 +97,10 @@ fn main() { floating, in_place, cwd, + x, + y, + width, + height, })) = opts.command { let mut file = file; @@ -97,6 +117,10 @@ fn main() { floating, in_place, cwd, + x, + y, + width, + height, }; commands::send_action_to_session(command_cli_action, opts.session, config); std::process::exit(0); diff --git a/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__open_command_pane_floating_plugin_command.snap b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__open_command_pane_floating_plugin_command.snap index a222f4fa..a1ab0475 100644 --- a/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__open_command_pane_floating_plugin_command.snap +++ b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__open_command_pane_floating_plugin_command.snap @@ -1,6 +1,6 @@ --- source: zellij-server/src/plugins/./unit/plugin_tests.rs -assertion_line: 3198 +assertion_line: 4400 expression: "format!(\"{:#?}\", new_tab_event)" --- Some( @@ -23,6 +23,7 @@ Some( true, ), None, + None, ClientId( 1, ), diff --git a/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__open_command_pane_plugin_command.snap b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__open_command_pane_plugin_command.snap index 2807e495..935f72bb 100644 --- a/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__open_command_pane_plugin_command.snap +++ b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__open_command_pane_plugin_command.snap @@ -1,6 +1,6 @@ --- source: zellij-server/src/plugins/./unit/plugin_tests.rs -assertion_line: 3144 +assertion_line: 4323 expression: "format!(\"{:#?}\", new_tab_event)" --- Some( @@ -23,6 +23,7 @@ Some( false, ), None, + None, ClientId( 1, ), diff --git a/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__open_file_floating_plugin_command.snap b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__open_file_floating_plugin_command.snap index daff15fa..9a1ffe58 100644 --- a/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__open_file_floating_plugin_command.snap +++ b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__open_file_floating_plugin_command.snap @@ -20,6 +20,7 @@ Some( Some( "Editing: /path/to/my/file.rs", ), + None, ClientId( 1, ), diff --git a/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__open_file_plugin_command.snap b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__open_file_plugin_command.snap index f895c55c..b24094af 100644 --- a/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__open_file_plugin_command.snap +++ b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__open_file_plugin_command.snap @@ -1,6 +1,6 @@ --- source: zellij-server/src/plugins/./unit/plugin_tests.rs -assertion_line: 3925 +assertion_line: 3927 expression: "format!(\"{:#?}\",\n new_tab_event).replace(&format!(\"{:?}\", temp_folder.path()),\n \"\\\"CWD\\\"\")" --- Some( @@ -20,6 +20,7 @@ Some( Some( "Editing: /path/to/my/file.rs", ), + None, ClientId( 1, ), diff --git a/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__open_file_with_line_floating_plugin_command.snap b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__open_file_with_line_floating_plugin_command.snap index da0a726e..dca771df 100644 --- a/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__open_file_with_line_floating_plugin_command.snap +++ b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__open_file_with_line_floating_plugin_command.snap @@ -1,6 +1,6 @@ --- source: zellij-server/src/plugins/./unit/plugin_tests.rs -assertion_line: 4076 +assertion_line: 4090 expression: "format!(\"{:#?}\",\n new_tab_event).replace(&format!(\"{:?}\", temp_folder.path()),\n \"\\\"CWD\\\"\")" --- Some( @@ -22,6 +22,7 @@ Some( Some( "Editing: /path/to/my/file.rs", ), + None, ClientId( 1, ), diff --git a/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__open_file_with_line_plugin_command.snap b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__open_file_with_line_plugin_command.snap index ee8feb31..fd9d8e82 100644 --- a/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__open_file_with_line_plugin_command.snap +++ b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__open_file_with_line_plugin_command.snap @@ -1,6 +1,6 @@ --- source: zellij-server/src/plugins/./unit/plugin_tests.rs -assertion_line: 3999 +assertion_line: 4009 expression: "format!(\"{:#?}\",\n new_tab_event).replace(&format!(\"{:?}\", temp_folder.path()),\n \"\\\"CWD\\\"\")" --- Some( @@ -22,6 +22,7 @@ Some( Some( "Editing: /path/to/my/file.rs", ), + None, ClientId( 1, ), diff --git a/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__open_terminal_floating_plugin_command.snap b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__open_terminal_floating_plugin_command.snap index c43958a7..4c752eff 100644 --- a/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__open_terminal_floating_plugin_command.snap +++ b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__open_terminal_floating_plugin_command.snap @@ -1,6 +1,6 @@ --- source: zellij-server/src/plugins/./unit/plugin_tests.rs -assertion_line: 3090 +assertion_line: 4246 expression: "format!(\"{:#?}\", new_tab_event)" --- Some( @@ -22,6 +22,7 @@ Some( true, ), None, + None, ClientId( 1, ), diff --git a/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__open_terminal_plugin_command.snap b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__open_terminal_plugin_command.snap index 88fdd2ed..7c0fb608 100644 --- a/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__open_terminal_plugin_command.snap +++ b/zellij-server/src/plugins/unit/snapshots/zellij_server__plugins__plugin_tests__open_terminal_plugin_command.snap @@ -1,6 +1,6 @@ --- source: zellij-server/src/plugins/./unit/plugin_tests.rs -assertion_line: 3036 +assertion_line: 4169 expression: "format!(\"{:#?}\", new_tab_event)" --- Some( @@ -22,6 +22,7 @@ Some( false, ), None, + None, ClientId( 1, ), diff --git a/zellij-server/src/plugins/zellij_exports.rs b/zellij-server/src/plugins/zellij_exports.rs index 4d203afd..19bac282 100644 --- a/zellij-server/src/plugins/zellij_exports.rs +++ b/zellij-server/src/plugins/zellij_exports.rs @@ -18,8 +18,8 @@ use std::{ use wasmer::{imports, AsStoreMut, Function, FunctionEnv, FunctionEnvMut, Imports}; use wasmer_wasi::WasiEnv; use zellij_utils::data::{ - CommandType, ConnectToSession, HttpVerb, LayoutInfo, MessageToPlugin, PermissionStatus, - PermissionType, PluginPermission, + CommandType, ConnectToSession, FloatingPaneCoordinates, HttpVerb, LayoutInfo, MessageToPlugin, + PermissionStatus, PermissionType, PluginPermission, }; use zellij_utils::input::permission::PermissionCache; use zellij_utils::{ @@ -117,19 +117,20 @@ fn host_run_plugin_command(env: FunctionEnvMut) { PluginCommand::GetPluginIds => get_plugin_ids(env), PluginCommand::GetZellijVersion => get_zellij_version(env), PluginCommand::OpenFile(file_to_open) => open_file(env, file_to_open), - PluginCommand::OpenFileFloating(file_to_open) => { - open_file_floating(env, file_to_open) + PluginCommand::OpenFileFloating(file_to_open, floating_pane_coordinates) => { + open_file_floating(env, file_to_open, floating_pane_coordinates) }, PluginCommand::OpenTerminal(cwd) => open_terminal(env, cwd.path.try_into()?), - PluginCommand::OpenTerminalFloating(cwd) => { - open_terminal_floating(env, cwd.path.try_into()?) + PluginCommand::OpenTerminalFloating(cwd, floating_pane_coordinates) => { + open_terminal_floating(env, cwd.path.try_into()?, floating_pane_coordinates) }, PluginCommand::OpenCommandPane(command_to_run) => { open_command_pane(env, command_to_run) }, - PluginCommand::OpenCommandPaneFloating(command_to_run) => { - open_command_pane_floating(env, command_to_run) - }, + PluginCommand::OpenCommandPaneFloating( + command_to_run, + floating_pane_coordinates, + ) => open_command_pane_floating(env, command_to_run, floating_pane_coordinates), PluginCommand::SwitchTabTo(tab_index) => switch_tab_to(env, tab_index), PluginCommand::SetTimeout(seconds) => set_timeout(env, seconds), PluginCommand::ExecCmd(command_line) => exec_cmd(env, command_line), @@ -447,11 +448,16 @@ fn open_file(env: &ForeignFunctionEnv, file_to_open: FileToOpen) { None, floating, in_place, + None, ); apply_action!(action, error_msg, env); } -fn open_file_floating(env: &ForeignFunctionEnv, file_to_open: FileToOpen) { +fn open_file_floating( + env: &ForeignFunctionEnv, + file_to_open: FileToOpen, + floating_pane_coordinates: Option, +) { let error_msg = || format!("failed to open file in plugin {}", env.plugin_env.name()); let floating = true; let in_place = false; @@ -467,6 +473,7 @@ fn open_file_floating(env: &ForeignFunctionEnv, file_to_open: FileToOpen) { None, floating, in_place, + floating_pane_coordinates, ); apply_action!(action, error_msg, env); } @@ -488,6 +495,7 @@ fn open_file_in_place(env: &ForeignFunctionEnv, file_to_open: FileToOpen) { None, floating, in_place, + None, ); apply_action!(action, error_msg, env); } @@ -509,7 +517,11 @@ fn open_terminal(env: &ForeignFunctionEnv, cwd: PathBuf) { apply_action!(action, error_msg, env); } -fn open_terminal_floating(env: &ForeignFunctionEnv, cwd: PathBuf) { +fn open_terminal_floating( + env: &ForeignFunctionEnv, + cwd: PathBuf, + floating_pane_coordinates: Option, +) { let error_msg = || format!("failed to open file in plugin {}", env.plugin_env.name()); let cwd = env.plugin_env.plugin_cwd.join(cwd); let mut default_shell = env @@ -522,7 +534,7 @@ fn open_terminal_floating(env: &ForeignFunctionEnv, cwd: PathBuf) { TerminalAction::RunCommand(run_command) => Some(run_command.into()), _ => None, }; - let action = Action::NewFloatingPane(run_command_action, None); + let action = Action::NewFloatingPane(run_command_action, None, floating_pane_coordinates); apply_action!(action, error_msg, env); } @@ -566,7 +578,11 @@ fn open_command_pane(env: &ForeignFunctionEnv, command_to_run: CommandToRun) { apply_action!(action, error_msg, env); } -fn open_command_pane_floating(env: &ForeignFunctionEnv, command_to_run: CommandToRun) { +fn open_command_pane_floating( + env: &ForeignFunctionEnv, + command_to_run: CommandToRun, + floating_pane_coordinates: Option, +) { let error_msg = || format!("failed to open command in plugin {}", env.plugin_env.name()); let command = command_to_run.path; let cwd = command_to_run @@ -585,7 +601,7 @@ fn open_command_pane_floating(env: &ForeignFunctionEnv, command_to_run: CommandT hold_on_close, hold_on_start, }; - let action = Action::NewFloatingPane(Some(run_command_action), name); + let action = Action::NewFloatingPane(Some(run_command_action), name, floating_pane_coordinates); apply_action!(action, error_msg, env); } diff --git a/zellij-server/src/pty.rs b/zellij-server/src/pty.rs index 8562044c..0f9001a2 100644 --- a/zellij-server/src/pty.rs +++ b/zellij-server/src/pty.rs @@ -13,6 +13,7 @@ use std::{collections::HashMap, os::unix::io::RawFd, path::PathBuf}; use zellij_utils::nix::unistd::Pid; use zellij_utils::{ async_std, + data::FloatingPaneCoordinates, errors::prelude::*, errors::{ContextType, PtyContext}, input::{ @@ -43,6 +44,7 @@ pub enum PtyInstruction { Option, Option, Option, + Option, ClientTabIndexOrPaneId, ), // bool (if Some) is // should_float, String is an optional pane name @@ -90,6 +92,7 @@ pub enum PtyInstruction { Size, bool, // skip cache Option, // if Some, will not fill cwd but just forward the message + Option, ), Exit, } @@ -135,6 +138,7 @@ pub(crate) fn pty_thread_main(mut pty: Pty, layout: Box) -> Result<()> { terminal_action, should_float, name, + floating_pane_coordinates, client_or_tab_index, ) => { let err_context = @@ -176,6 +180,7 @@ pub(crate) fn pty_thread_main(mut pty: Pty, layout: Box) -> Result<()> { should_float, hold_for_command, invoked_with, + floating_pane_coordinates, client_or_tab_index, )) .with_context(err_context)?; @@ -192,6 +197,7 @@ pub(crate) fn pty_thread_main(mut pty: Pty, layout: Box) -> Result<()> { should_float, hold_for_command, invoked_with, + floating_pane_coordinates, client_or_tab_index, )) .with_context(err_context)?; @@ -657,6 +663,7 @@ pub(crate) fn pty_thread_main(mut pty: Pty, layout: Box) -> Result<()> { size, skip_cache, cwd, + floating_pane_coordinates, ) => { pty.fill_plugin_cwd( should_float, @@ -669,6 +676,7 @@ pub(crate) fn pty_thread_main(mut pty: Pty, layout: Box) -> Result<()> { size, skip_cache, cwd, + floating_pane_coordinates, )?; }, PtyInstruction::Exit => break, @@ -1336,6 +1344,7 @@ impl Pty { size: Size, skip_cache: bool, cwd: Option, + floating_pane_coordinates: Option, ) -> Result<()> { let cwd = cwd.or_else(|| { self.active_panes diff --git a/zellij-server/src/route.rs b/zellij-server/src/route.rs index 471d90aa..0dd2946c 100644 --- a/zellij-server/src/route.rs +++ b/zellij-server/src/route.rs @@ -268,6 +268,7 @@ pub(crate) fn route_action( shell, None, name, + None, ClientTabIndexOrPaneId::ClientId(client_id), ), }; @@ -280,6 +281,7 @@ pub(crate) fn route_action( split_direction, should_float, should_open_in_place, + floating_pane_coordinates, ) => { let title = format!("Editing: {}", path_to_file.display()); let open_file = TerminalAction::OpenFile(path_to_file, line_number, cwd); @@ -319,6 +321,7 @@ pub(crate) fn route_action( Some(open_file), Some(should_float), Some(title), + floating_pane_coordinates, ClientTabIndexOrPaneId::ClientId(client_id), ), }; @@ -341,7 +344,7 @@ pub(crate) fn route_action( ))) .with_context(err_context)?; }, - Action::NewFloatingPane(run_command, name) => { + Action::NewFloatingPane(run_command, name, floating_pane_coordinates) => { let should_float = true; let run_cmd = run_command .map(|cmd| TerminalAction::RunCommand(cmd.into())) @@ -351,6 +354,7 @@ pub(crate) fn route_action( run_cmd, Some(should_float), name, + floating_pane_coordinates, ClientTabIndexOrPaneId::ClientId(client_id), )) .with_context(err_context)?; @@ -403,6 +407,7 @@ pub(crate) fn route_action( run_cmd, Some(should_float), name, + None, ClientTabIndexOrPaneId::ClientId(client_id), ), }; @@ -451,6 +456,7 @@ pub(crate) fn route_action( run_cmd, None, None, + None, ClientTabIndexOrPaneId::ClientId(client_id), ), }; @@ -666,10 +672,21 @@ pub(crate) fn route_action( )) .with_context(err_context)?; }, - Action::NewFloatingPluginPane(run_plugin, name, skip_cache, cwd) => { + Action::NewFloatingPluginPane( + run_plugin, + name, + skip_cache, + cwd, + floating_pane_coordinates, + ) => { senders .send_to_screen(ScreenInstruction::NewFloatingPluginPane( - run_plugin, name, skip_cache, cwd, client_id, + run_plugin, + name, + skip_cache, + cwd, + floating_pane_coordinates, + client_id, )) .with_context(err_context)?; }, diff --git a/zellij-server/src/screen.rs b/zellij-server/src/screen.rs index 69e1b6bf..fa803007 100644 --- a/zellij-server/src/screen.rs +++ b/zellij-server/src/screen.rs @@ -46,7 +46,10 @@ use crate::{ ClientId, ServerInstruction, }; use zellij_utils::{ - data::{Event, InputMode, ModeInfo, Palette, PaletteColor, PluginCapabilities, Style, TabInfo}, + data::{ + Event, FloatingPaneCoordinates, InputMode, ModeInfo, Palette, PaletteColor, + PluginCapabilities, Style, TabInfo, + }, errors::{ContextType, ScreenContext}, input::{get_mode_info, options::Options}, ipc::{ClientAttributes, PixelDimensions, ServerToClientMsg}, @@ -146,6 +149,7 @@ pub enum ScreenInstruction { Option, HoldForCommand, Option, // invoked with + Option, ClientTabIndexOrPaneId, ), OpenInPlaceEditor(PaneId, ClientId), @@ -274,7 +278,14 @@ pub enum ScreenInstruction { QueryTabNames(ClientId), NewTiledPluginPane(RunPlugin, Option, bool, Option, ClientId), // Option is // optional pane title, bool is skip cache, Option is an optional cwd - NewFloatingPluginPane(RunPlugin, Option, bool, Option, ClientId), // Option is an + NewFloatingPluginPane( + RunPlugin, + Option, + bool, + Option, + Option, + ClientId, + ), // Option is an // optional pane title, bool // is skip cache, Option is an optional cwd NewInPlacePluginPane(RunPlugin, Option, PaneId, bool, ClientId), // Option is an @@ -1760,6 +1771,7 @@ impl Screen { new_active_tab.add_floating_pane( plugin_pane_to_move_to_active_tab, pane_id, + None, Some(client_id), )?; } else { @@ -1844,7 +1856,7 @@ impl Screen { let (mut tiled_panes_layout, mut floating_panes_layout) = default_layout.new_tab(); if pane_to_break_is_floating { tab.show_floating_panes(); - tab.add_floating_pane(active_pane, active_pane_id, Some(client_id))?; + tab.add_floating_pane(active_pane, active_pane_id, None, Some(client_id))?; if let Some(already_running_layout) = floating_panes_layout .iter_mut() .find(|i| i.run == active_pane_run_instruction) @@ -1909,7 +1921,12 @@ impl Screen { if pane_to_break_is_floating { new_active_tab.show_floating_panes(); - new_active_tab.add_floating_pane(active_pane, active_pane_id, Some(client_id))?; + new_active_tab.add_floating_pane( + active_pane, + active_pane_id, + None, + Some(client_id), + )?; } else { new_active_tab.hide_floating_panes(); new_active_tab.add_tiled_pane(active_pane, active_pane_id, Some(client_id))?; @@ -2217,6 +2234,7 @@ pub(crate) fn screen_thread_main( should_float, hold_for_command, invoked_with, + floating_pane_coordinates, client_or_tab_index, ) => { match client_or_tab_index { @@ -2226,6 +2244,7 @@ pub(crate) fn screen_thread_main( initial_pane_title, should_float, invoked_with, + floating_pane_coordinates, Some(client_id) ) }, ?); @@ -2250,6 +2269,7 @@ pub(crate) fn screen_thread_main( initial_pane_title, should_float, invoked_with, + floating_pane_coordinates, None, )?; if let Some(hold_for_command) = hold_for_command { @@ -3241,6 +3261,7 @@ pub(crate) fn screen_thread_main( size, skip_cache, cwd, + None, ))?; }, ScreenInstruction::NewFloatingPluginPane( @@ -3248,6 +3269,7 @@ pub(crate) fn screen_thread_main( pane_title, skip_cache, cwd, + floating_pane_coordinates, client_id, ) => match screen.active_tab_indices.values().next() { Some(tab_index) => { @@ -3268,6 +3290,7 @@ pub(crate) fn screen_thread_main( size, skip_cache, cwd, + floating_pane_coordinates, ))?; }, None => { @@ -3301,6 +3324,7 @@ pub(crate) fn screen_thread_main( size, skip_cache, None, + None, ))?; }, None => { @@ -3378,6 +3402,7 @@ pub(crate) fn screen_thread_main( should_float, Some(run_plugin), None, + None, ) }, ?); } else if let Some(active_tab) = @@ -3389,6 +3414,7 @@ pub(crate) fn screen_thread_main( should_float, Some(run_plugin), None, + None, )?; } else { log::error!("Tab index not found: {:?}", tab_index); @@ -3462,6 +3488,7 @@ pub(crate) fn screen_thread_main( size, skip_cache, None, + None, ))?; }, None => { @@ -3507,6 +3534,7 @@ pub(crate) fn screen_thread_main( Size::default(), skip_cache, None, + None, ))?; } }, @@ -3542,6 +3570,7 @@ pub(crate) fn screen_thread_main( size, skip_cache, cwd, + None, ))?; }, None => { @@ -3578,6 +3607,7 @@ pub(crate) fn screen_thread_main( Size::default(), skip_cache, cwd, + None, ))?; }, None => { diff --git a/zellij-server/src/tab/mod.rs b/zellij-server/src/tab/mod.rs index 2ed9eb35..de1beccc 100644 --- a/zellij-server/src/tab/mod.rs +++ b/zellij-server/src/tab/mod.rs @@ -46,7 +46,7 @@ use std::{ str, }; use zellij_utils::{ - data::{Event, InputMode, ModeInfo, Palette, PaletteColor, Style}, + data::{Event, FloatingPaneCoordinates, InputMode, ModeInfo, Palette, PaletteColor, Style}, input::{ command::TerminalAction, layout::{ @@ -991,7 +991,12 @@ impl Tab { self.close_pane(focused_pane_id, true, Some(client_id)) { self.show_floating_panes(); - self.add_floating_pane(embedded_pane_to_float, focused_pane_id, Some(client_id))?; + self.add_floating_pane( + embedded_pane_to_float, + focused_pane_id, + None, + Some(client_id), + )?; } } Ok(()) @@ -1030,6 +1035,7 @@ impl Tab { default_shell, Some(should_float), name, + None, client_id_or_tab_index, ); self.senders @@ -1048,6 +1054,7 @@ impl Tab { initial_pane_title: Option, should_float: Option, invoked_with: Option, + floating_pane_coordinates: Option, client_id: Option, ) -> Result<()> { let err_context = || format!("failed to create new pane with id {pid:?}"); @@ -1105,7 +1112,7 @@ impl Tab { }, }; if self.floating_panes.panes_are_visible() { - self.add_floating_pane(new_pane, pid, client_id) + self.add_floating_pane(new_pane, pid, floating_pane_coordinates, client_id) } else { self.add_tiled_pane(new_pane, pid, client_id) } @@ -3615,7 +3622,7 @@ impl Tab { Some(pane) => { if should_float { self.show_floating_panes(); - self.add_floating_pane(pane.1, pane_id, Some(client_id)) + self.add_floating_pane(pane.1, pane_id, None, Some(client_id)) } else { self.hide_floating_panes(); self.add_tiled_pane(pane.1, pane_id, Some(client_id)) @@ -3655,10 +3662,16 @@ impl Tab { &mut self, mut pane: Box, pane_id: PaneId, + floating_pane_coordinates: Option, client_id: Option, ) -> Result<()> { let err_context = || format!("failed to add floating pane"); - if let Some(new_pane_geom) = self.floating_panes.find_room_for_new_pane() { + if let Some(mut new_pane_geom) = self.floating_panes.find_room_for_new_pane() { + if let Some(floating_pane_coordinates) = floating_pane_coordinates { + let viewport = self.viewport.borrow(); + new_pane_geom.adjust_coordinates(floating_pane_coordinates, *viewport); + self.swap_layouts.set_is_floating_damaged(); + } pane.set_active_at(Instant::now()); pane.set_geom(new_pane_geom); pane.set_content_offset(Offset::frame(1)); // floating panes always have a frame diff --git a/zellij-server/src/tab/unit/tab_integration_tests.rs b/zellij-server/src/tab/unit/tab_integration_tests.rs index 1ee1a727..ef5cc1bf 100644 --- a/zellij-server/src/tab/unit/tab_integration_tests.rs +++ b/zellij-server/src/tab/unit/tab_integration_tests.rs @@ -760,7 +760,7 @@ fn dump_screen() { ..Default::default() }); let new_pane_id = PaneId::Terminal(2); - tab.new_pane(new_pane_id, None, None, None, Some(client_id)) + tab.new_pane(new_pane_id, None, None, None, None, Some(client_id)) .unwrap(); tab.handle_pty_bytes(2, Vec::from("scratch".as_bytes())) .unwrap(); @@ -788,7 +788,7 @@ fn clear_screen() { ..Default::default() }); let new_pane_id = PaneId::Terminal(2); - tab.new_pane(new_pane_id, None, None, None, Some(client_id)) + tab.new_pane(new_pane_id, None, None, None, None, Some(client_id)) .unwrap(); tab.handle_pty_bytes(2, Vec::from("scratch".as_bytes())) .unwrap(); @@ -814,7 +814,7 @@ fn new_floating_pane() { let new_pane_id = PaneId::Terminal(2); let mut output = Output::default(); tab.toggle_floating_panes(Some(client_id), None).unwrap(); - tab.new_pane(new_pane_id, None, None, None, Some(client_id)) + tab.new_pane(new_pane_id, None, None, None, None, Some(client_id)) .unwrap(); tab.handle_pty_bytes( 2, @@ -842,7 +842,7 @@ fn floating_panes_persist_across_toggles() { let new_pane_id = PaneId::Terminal(2); let mut output = Output::default(); tab.toggle_floating_panes(Some(client_id), None).unwrap(); - tab.new_pane(new_pane_id, None, None, None, Some(client_id)) + tab.new_pane(new_pane_id, None, None, None, None, Some(client_id)) .unwrap(); tab.toggle_floating_panes(Some(client_id), None).unwrap(); // here we send bytes to the pane when it's not visible to make sure they're still handled and @@ -874,7 +874,7 @@ fn toggle_floating_panes_off() { let new_pane_id = PaneId::Terminal(2); let mut output = Output::default(); tab.toggle_floating_panes(Some(client_id), None).unwrap(); - tab.new_pane(new_pane_id, None, None, None, Some(client_id)) + tab.new_pane(new_pane_id, None, None, None, None, Some(client_id)) .unwrap(); tab.handle_pty_bytes( 2, @@ -903,7 +903,7 @@ fn toggle_floating_panes_on() { let new_pane_id = PaneId::Terminal(2); let mut output = Output::default(); tab.toggle_floating_panes(Some(client_id), None).unwrap(); - tab.new_pane(new_pane_id, None, None, None, Some(client_id)) + tab.new_pane(new_pane_id, None, None, None, None, Some(client_id)) .unwrap(); tab.handle_pty_bytes( 2, @@ -937,15 +937,15 @@ fn five_new_floating_panes() { let new_pane_id_5 = PaneId::Terminal(6); let mut output = Output::default(); tab.toggle_floating_panes(Some(client_id), None).unwrap(); - tab.new_pane(new_pane_id_1, None, None, None, Some(client_id)) + tab.new_pane(new_pane_id_1, None, None, None, None, Some(client_id)) .unwrap(); - tab.new_pane(new_pane_id_2, None, None, None, Some(client_id)) + tab.new_pane(new_pane_id_2, None, None, None, None, Some(client_id)) .unwrap(); - tab.new_pane(new_pane_id_3, None, None, None, Some(client_id)) + tab.new_pane(new_pane_id_3, None, None, None, None, Some(client_id)) .unwrap(); - tab.new_pane(new_pane_id_4, None, None, None, Some(client_id)) + tab.new_pane(new_pane_id_4, None, None, None, None, Some(client_id)) .unwrap(); - tab.new_pane(new_pane_id_5, None, None, None, Some(client_id)) + tab.new_pane(new_pane_id_5, None, None, None, None, Some(client_id)) .unwrap(); tab.handle_pty_bytes( 2, @@ -981,7 +981,7 @@ fn increase_floating_pane_size() { let new_pane_id_1 = PaneId::Terminal(2); let mut output = Output::default(); tab.toggle_floating_panes(Some(client_id), None).unwrap(); - tab.new_pane(new_pane_id_1, None, None, None, Some(client_id)) + tab.new_pane(new_pane_id_1, None, None, None, None, Some(client_id)) .unwrap(); tab.handle_pty_bytes( 2, @@ -1011,7 +1011,7 @@ fn decrease_floating_pane_size() { let new_pane_id_1 = PaneId::Terminal(2); let mut output = Output::default(); tab.toggle_floating_panes(Some(client_id), None).unwrap(); - tab.new_pane(new_pane_id_1, None, None, None, Some(client_id)) + tab.new_pane(new_pane_id_1, None, None, None, None, Some(client_id)) .unwrap(); tab.handle_pty_bytes( 2, @@ -1041,7 +1041,7 @@ fn resize_floating_pane_left() { let new_pane_id_1 = PaneId::Terminal(2); let mut output = Output::default(); tab.toggle_floating_panes(Some(client_id), None).unwrap(); - tab.new_pane(new_pane_id_1, None, None, None, Some(client_id)) + tab.new_pane(new_pane_id_1, None, None, None, None, Some(client_id)) .unwrap(); tab.handle_pty_bytes( 2, @@ -1074,7 +1074,7 @@ fn resize_floating_pane_right() { let new_pane_id_1 = PaneId::Terminal(2); let mut output = Output::default(); tab.toggle_floating_panes(Some(client_id), None).unwrap(); - tab.new_pane(new_pane_id_1, None, None, None, Some(client_id)) + tab.new_pane(new_pane_id_1, None, None, None, None, Some(client_id)) .unwrap(); tab.handle_pty_bytes( 2, @@ -1107,7 +1107,7 @@ fn resize_floating_pane_up() { let new_pane_id_1 = PaneId::Terminal(2); let mut output = Output::default(); tab.toggle_floating_panes(Some(client_id), None).unwrap(); - tab.new_pane(new_pane_id_1, None, None, None, Some(client_id)) + tab.new_pane(new_pane_id_1, None, None, None, None, Some(client_id)) .unwrap(); tab.handle_pty_bytes( 2, @@ -1140,7 +1140,7 @@ fn resize_floating_pane_down() { let new_pane_id_1 = PaneId::Terminal(2); let mut output = Output::default(); tab.toggle_floating_panes(Some(client_id), None).unwrap(); - tab.new_pane(new_pane_id_1, None, None, None, Some(client_id)) + tab.new_pane(new_pane_id_1, None, None, None, None, Some(client_id)) .unwrap(); tab.handle_pty_bytes( 2, @@ -1177,15 +1177,15 @@ fn move_floating_pane_focus_left() { let new_pane_id_5 = PaneId::Terminal(6); let mut output = Output::default(); tab.toggle_floating_panes(Some(client_id), None).unwrap(); - tab.new_pane(new_pane_id_1, None, None, None, Some(client_id)) + tab.new_pane(new_pane_id_1, None, None, None, None, Some(client_id)) .unwrap(); - tab.new_pane(new_pane_id_2, None, None, None, Some(client_id)) + tab.new_pane(new_pane_id_2, None, None, None, None, Some(client_id)) .unwrap(); - tab.new_pane(new_pane_id_3, None, None, None, Some(client_id)) + tab.new_pane(new_pane_id_3, None, None, None, None, Some(client_id)) .unwrap(); - tab.new_pane(new_pane_id_4, None, None, None, Some(client_id)) + tab.new_pane(new_pane_id_4, None, None, None, None, Some(client_id)) .unwrap(); - tab.new_pane(new_pane_id_5, None, None, None, Some(client_id)) + tab.new_pane(new_pane_id_5, None, None, None, None, Some(client_id)) .unwrap(); tab.handle_pty_bytes( 2, @@ -1232,15 +1232,15 @@ fn move_floating_pane_focus_right() { let new_pane_id_5 = PaneId::Terminal(6); let mut output = Output::default(); tab.toggle_floating_panes(Some(client_id), None).unwrap(); - tab.new_pane(new_pane_id_1, None, None, None, Some(client_id)) + tab.new_pane(new_pane_id_1, None, None, None, None, Some(client_id)) .unwrap(); - tab.new_pane(new_pane_id_2, None, None, None, Some(client_id)) + tab.new_pane(new_pane_id_2, None, None, None, None, Some(client_id)) .unwrap(); - tab.new_pane(new_pane_id_3, None, None, None, Some(client_id)) + tab.new_pane(new_pane_id_3, None, None, None, None, Some(client_id)) .unwrap(); - tab.new_pane(new_pane_id_4, None, None, None, Some(client_id)) + tab.new_pane(new_pane_id_4, None, None, None, None, Some(client_id)) .unwrap(); - tab.new_pane(new_pane_id_5, None, None, None, Some(client_id)) + tab.new_pane(new_pane_id_5, None, None, None, None, Some(client_id)) .unwrap(); tab.handle_pty_bytes( 2, @@ -1288,15 +1288,15 @@ fn move_floating_pane_focus_up() { let new_pane_id_5 = PaneId::Terminal(6); let mut output = Output::default(); tab.toggle_floating_panes(Some(client_id), None).unwrap(); - tab.new_pane(new_pane_id_1, None, None, None, Some(client_id)) + tab.new_pane(new_pane_id_1, None, None, None, None, Some(client_id)) .unwrap(); - tab.new_pane(new_pane_id_2, None, None, None, Some(client_id)) + tab.new_pane(new_pane_id_2, None, None, None, None, Some(client_id)) .unwrap(); - tab.new_pane(new_pane_id_3, None, None, None, Some(client_id)) + tab.new_pane(new_pane_id_3, None, None, None, None, Some(client_id)) .unwrap(); - tab.new_pane(new_pane_id_4, None, None, None, Some(client_id)) + tab.new_pane(new_pane_id_4, None, None, None, None, Some(client_id)) .unwrap(); - tab.new_pane(new_pane_id_5, None, None, None, Some(client_id)) + tab.new_pane(new_pane_id_5, None, None, None, None, Some(client_id)) .unwrap(); tab.handle_pty_bytes( 2, @@ -1343,15 +1343,15 @@ fn move_floating_pane_focus_down() { let new_pane_id_5 = PaneId::Terminal(6); let mut output = Output::default(); tab.toggle_floating_panes(Some(client_id), None).unwrap(); - tab.new_pane(new_pane_id_1, None, None, None, Some(client_id)) + tab.new_pane(new_pane_id_1, None, None, None, None, Some(client_id)) .unwrap(); - tab.new_pane(new_pane_id_2, None, None, None, Some(client_id)) + tab.new_pane(new_pane_id_2, None, None, None, None, Some(client_id)) .unwrap(); - tab.new_pane(new_pane_id_3, None, None, None, Some(client_id)) + tab.new_pane(new_pane_id_3, None, None, None, None, Some(client_id)) .unwrap(); - tab.new_pane(new_pane_id_4, None, None, None, Some(client_id)) + tab.new_pane(new_pane_id_4, None, None, None, None, Some(client_id)) .unwrap(); - tab.new_pane(new_pane_id_5, None, None, None, Some(client_id)) + tab.new_pane(new_pane_id_5, None, None, None, None, Some(client_id)) .unwrap(); tab.handle_pty_bytes( 2, @@ -1399,15 +1399,15 @@ fn move_floating_pane_focus_with_mouse() { let new_pane_id_5 = PaneId::Terminal(6); let mut output = Output::default(); tab.toggle_floating_panes(Some(client_id), None).unwrap(); - tab.new_pane(new_pane_id_1, None, None, None, Some(client_id)) + tab.new_pane(new_pane_id_1, None, None, None, None, Some(client_id)) .unwrap(); - tab.new_pane(new_pane_id_2, None, None, None, Some(client_id)) + tab.new_pane(new_pane_id_2, None, None, None, None, Some(client_id)) .unwrap(); - tab.new_pane(new_pane_id_3, None, None, None, Some(client_id)) + tab.new_pane(new_pane_id_3, None, None, None, None, Some(client_id)) .unwrap(); - tab.new_pane(new_pane_id_4, None, None, None, Some(client_id)) + tab.new_pane(new_pane_id_4, None, None, None, None, Some(client_id)) .unwrap(); - tab.new_pane(new_pane_id_5, None, None, None, Some(client_id)) + tab.new_pane(new_pane_id_5, None, None, None, None, Some(client_id)) .unwrap(); tab.handle_pty_bytes( 2, @@ -1457,15 +1457,15 @@ fn move_pane_focus_with_mouse_to_non_floating_pane() { let new_pane_id_5 = PaneId::Terminal(6); let mut output = Output::default(); tab.toggle_floating_panes(Some(client_id), None).unwrap(); - tab.new_pane(new_pane_id_1, None, None, None, Some(client_id)) + tab.new_pane(new_pane_id_1, None, None, None, None, Some(client_id)) .unwrap(); - tab.new_pane(new_pane_id_2, None, None, None, Some(client_id)) + tab.new_pane(new_pane_id_2, None, None, None, None, Some(client_id)) .unwrap(); - tab.new_pane(new_pane_id_3, None, None, None, Some(client_id)) + tab.new_pane(new_pane_id_3, None, None, None, None, Some(client_id)) .unwrap(); - tab.new_pane(new_pane_id_4, None, None, None, Some(client_id)) + tab.new_pane(new_pane_id_4, None, None, None, None, Some(client_id)) .unwrap(); - tab.new_pane(new_pane_id_5, None, None, None, Some(client_id)) + tab.new_pane(new_pane_id_5, None, None, None, None, Some(client_id)) .unwrap(); tab.handle_pty_bytes( 2, @@ -1515,15 +1515,15 @@ fn drag_pane_with_mouse() { let new_pane_id_5 = PaneId::Terminal(6); let mut output = Output::default(); tab.toggle_floating_panes(Some(client_id), None).unwrap(); - tab.new_pane(new_pane_id_1, None, None, None, Some(client_id)) + tab.new_pane(new_pane_id_1, None, None, None, None, Some(client_id)) .unwrap(); - tab.new_pane(new_pane_id_2, None, None, None, Some(client_id)) + tab.new_pane(new_pane_id_2, None, None, None, None, Some(client_id)) .unwrap(); - tab.new_pane(new_pane_id_3, None, None, None, Some(client_id)) + tab.new_pane(new_pane_id_3, None, None, None, None, Some(client_id)) .unwrap(); - tab.new_pane(new_pane_id_4, None, None, None, Some(client_id)) + tab.new_pane(new_pane_id_4, None, None, None, None, Some(client_id)) .unwrap(); - tab.new_pane(new_pane_id_5, None, None, None, Some(client_id)) + tab.new_pane(new_pane_id_5, None, None, None, None, Some(client_id)) .unwrap(); tab.handle_pty_bytes( 2, @@ -1573,15 +1573,15 @@ fn mark_text_inside_floating_pane() { let new_pane_id_5 = PaneId::Terminal(6); let mut output = Output::default(); tab.toggle_floating_panes(Some(client_id), None).unwrap(); - tab.new_pane(new_pane_id_1, None, None, None, Some(client_id)) + tab.new_pane(new_pane_id_1, None, None, None, None, Some(client_id)) .unwrap(); - tab.new_pane(new_pane_id_2, None, None, None, Some(client_id)) + tab.new_pane(new_pane_id_2, None, None, None, None, Some(client_id)) .unwrap(); - tab.new_pane(new_pane_id_3, None, None, None, Some(client_id)) + tab.new_pane(new_pane_id_3, None, None, None, None, Some(client_id)) .unwrap(); - tab.new_pane(new_pane_id_4, None, None, None, Some(client_id)) + tab.new_pane(new_pane_id_4, None, None, None, None, Some(client_id)) .unwrap(); - tab.new_pane(new_pane_id_5, None, None, None, Some(client_id)) + tab.new_pane(new_pane_id_5, None, None, None, None, Some(client_id)) .unwrap(); tab.handle_pty_bytes( 2, @@ -1639,15 +1639,15 @@ fn resize_tab_with_floating_panes() { let new_pane_id_5 = PaneId::Terminal(6); let mut output = Output::default(); tab.toggle_floating_panes(Some(client_id), None).unwrap(); - tab.new_pane(new_pane_id_1, None, None, None, Some(client_id)) + tab.new_pane(new_pane_id_1, None, None, None, None, Some(client_id)) .unwrap(); - tab.new_pane(new_pane_id_2, None, None, None, Some(client_id)) + tab.new_pane(new_pane_id_2, None, None, None, None, Some(client_id)) .unwrap(); - tab.new_pane(new_pane_id_3, None, None, None, Some(client_id)) + tab.new_pane(new_pane_id_3, None, None, None, None, Some(client_id)) .unwrap(); - tab.new_pane(new_pane_id_4, None, None, None, Some(client_id)) + tab.new_pane(new_pane_id_4, None, None, None, None, Some(client_id)) .unwrap(); - tab.new_pane(new_pane_id_5, None, None, None, Some(client_id)) + tab.new_pane(new_pane_id_5, None, None, None, None, Some(client_id)) .unwrap(); tab.handle_pty_bytes( 2, @@ -1693,15 +1693,15 @@ fn shrink_whole_tab_with_floating_panes_horizontally_and_vertically() { let new_pane_id_5 = PaneId::Terminal(6); let mut output = Output::default(); tab.toggle_floating_panes(Some(client_id), None).unwrap(); - tab.new_pane(new_pane_id_1, None, None, None, Some(client_id)) + tab.new_pane(new_pane_id_1, None, None, None, None, Some(client_id)) .unwrap(); - tab.new_pane(new_pane_id_2, None, None, None, Some(client_id)) + tab.new_pane(new_pane_id_2, None, None, None, None, Some(client_id)) .unwrap(); - tab.new_pane(new_pane_id_3, None, None, None, Some(client_id)) + tab.new_pane(new_pane_id_3, None, None, None, None, Some(client_id)) .unwrap(); - tab.new_pane(new_pane_id_4, None, None, None, Some(client_id)) + tab.new_pane(new_pane_id_4, None, None, None, None, Some(client_id)) .unwrap(); - tab.new_pane(new_pane_id_5, None, None, None, Some(client_id)) + tab.new_pane(new_pane_id_5, None, None, None, None, Some(client_id)) .unwrap(); tab.handle_pty_bytes( 2, @@ -1743,15 +1743,15 @@ fn shrink_whole_tab_with_floating_panes_horizontally_and_vertically_and_expand_b let new_pane_id_5 = PaneId::Terminal(6); let mut output = Output::default(); tab.toggle_floating_panes(Some(client_id), None).unwrap(); - tab.new_pane(new_pane_id_1, None, None, None, Some(client_id)) + tab.new_pane(new_pane_id_1, None, None, None, None, Some(client_id)) .unwrap(); - tab.new_pane(new_pane_id_2, None, None, None, Some(client_id)) + tab.new_pane(new_pane_id_2, None, None, None, None, Some(client_id)) .unwrap(); - tab.new_pane(new_pane_id_3, None, None, None, Some(client_id)) + tab.new_pane(new_pane_id_3, None, None, None, None, Some(client_id)) .unwrap(); - tab.new_pane(new_pane_id_4, None, None, None, Some(client_id)) + tab.new_pane(new_pane_id_4, None, None, None, None, Some(client_id)) .unwrap(); - tab.new_pane(new_pane_id_5, None, None, None, Some(client_id)) + tab.new_pane(new_pane_id_5, None, None, None, None, Some(client_id)) .unwrap(); tab.handle_pty_bytes( 2, @@ -1794,7 +1794,7 @@ fn embed_floating_pane() { let new_pane_id = PaneId::Terminal(2); let mut output = Output::default(); tab.toggle_floating_panes(Some(client_id), None).unwrap(); - tab.new_pane(new_pane_id, None, None, None, Some(client_id)) + tab.new_pane(new_pane_id, None, None, None, None, Some(client_id)) .unwrap(); tab.handle_pty_bytes( 2, @@ -1822,7 +1822,7 @@ fn float_embedded_pane() { let mut tab = create_new_tab(size, ModeInfo::default()); let new_pane_id = PaneId::Terminal(2); let mut output = Output::default(); - tab.new_pane(new_pane_id, None, None, None, Some(client_id)) + tab.new_pane(new_pane_id, None, None, None, None, Some(client_id)) .unwrap(); tab.handle_pty_bytes( 2, @@ -1852,7 +1852,7 @@ fn embed_floating_pane_without_pane_frames() { let mut output = Output::default(); tab.set_pane_frames(false); tab.toggle_floating_panes(Some(client_id), None).unwrap(); - tab.new_pane(new_pane_id, None, None, None, Some(client_id)) + tab.new_pane(new_pane_id, None, None, None, None, Some(client_id)) .unwrap(); tab.handle_pty_bytes( 2, @@ -1881,7 +1881,7 @@ fn float_embedded_pane_without_pane_frames() { let new_pane_id = PaneId::Terminal(2); let mut output = Output::default(); tab.set_pane_frames(false); - tab.new_pane(new_pane_id, None, None, None, Some(client_id)) + tab.new_pane(new_pane_id, None, None, None, None, Some(client_id)) .unwrap(); tab.handle_pty_bytes( 2, @@ -1984,7 +1984,7 @@ fn rename_floating_pane() { let mut tab = create_new_tab(size, ModeInfo::default()); let new_pane_id = PaneId::Terminal(2); let mut output = Output::default(); - tab.new_pane(new_pane_id, None, None, None, Some(client_id)) + tab.new_pane(new_pane_id, None, None, None, None, Some(client_id)) .unwrap(); tab.handle_pty_bytes( 2, @@ -2080,7 +2080,7 @@ fn move_floating_pane_with_sixel_image() { let mut output = Output::new(sixel_image_store.clone(), character_cell_size, true); tab.toggle_floating_panes(Some(client_id), None).unwrap(); - tab.new_pane(new_pane_id, None, None, None, Some(client_id)) + tab.new_pane(new_pane_id, None, None, None, None, Some(client_id)) .unwrap(); let fixture = read_fixture("sixel-image-500px.six"); tab.handle_pty_bytes(2, fixture).unwrap(); @@ -2118,7 +2118,7 @@ fn floating_pane_above_sixel_image() { let mut output = Output::new(sixel_image_store.clone(), character_cell_size, true); tab.toggle_floating_panes(Some(client_id), None).unwrap(); - tab.new_pane(new_pane_id, None, None, None, Some(client_id)) + tab.new_pane(new_pane_id, None, None, None, None, Some(client_id)) .unwrap(); let fixture = read_fixture("sixel-image-500px.six"); tab.handle_pty_bytes(1, fixture).unwrap(); @@ -2176,7 +2176,7 @@ fn suppress_floating_pane() { let mut output = Output::default(); tab.toggle_floating_panes(Some(client_id), None).unwrap(); - tab.new_pane(new_pane_id, None, None, None, Some(client_id)) + tab.new_pane(new_pane_id, None, None, None, None, Some(client_id)) .unwrap(); tab.replace_active_pane_with_editor_pane(editor_pane_id, client_id) .unwrap(); @@ -2232,7 +2232,7 @@ fn close_suppressing_floating_pane() { let mut output = Output::default(); tab.toggle_floating_panes(Some(client_id), None).unwrap(); - tab.new_pane(new_pane_id, None, None, None, Some(client_id)) + tab.new_pane(new_pane_id, None, None, None, None, Some(client_id)) .unwrap(); tab.replace_active_pane_with_editor_pane(editor_pane_id, client_id) .unwrap(); @@ -2292,7 +2292,7 @@ fn suppress_floating_pane_embed_it_and_close_it() { let mut output = Output::default(); tab.toggle_floating_panes(Some(client_id), None).unwrap(); - tab.new_pane(new_pane_id, None, None, None, Some(client_id)) + tab.new_pane(new_pane_id, None, None, None, None, Some(client_id)) .unwrap(); tab.replace_active_pane_with_editor_pane(editor_pane_id, client_id) .unwrap(); @@ -2354,7 +2354,7 @@ fn resize_whole_tab_while_floting_pane_is_suppressed() { let mut output = Output::default(); tab.toggle_floating_panes(Some(client_id), None).unwrap(); - tab.new_pane(new_pane_id, None, None, None, Some(client_id)) + tab.new_pane(new_pane_id, None, None, None, None, Some(client_id)) .unwrap(); tab.replace_active_pane_with_editor_pane(editor_pane_id, client_id) .unwrap(); @@ -2456,7 +2456,7 @@ fn enter_search_floating_pane() { let new_pane_id = PaneId::Terminal(2); let mut output = Output::default(); tab.toggle_floating_panes(Some(client_id), None).unwrap(); - tab.new_pane(new_pane_id, None, None, None, Some(client_id)) + tab.new_pane(new_pane_id, None, None, None, None, Some(client_id)) .unwrap(); let pane_content = read_fixture("grid_copy"); @@ -2961,7 +2961,7 @@ fn move_pane_focus_sends_tty_csi_event() { }); let mut tab = create_new_tab_with_os_api(size, ModeInfo::default(), &os_api); let new_pane_id_1 = PaneId::Terminal(2); - tab.new_pane(new_pane_id_1, None, None, None, Some(client_id)) + tab.new_pane(new_pane_id_1, None, None, None, None, Some(client_id)) .unwrap(); tab.handle_pty_bytes( 1, @@ -2996,9 +2996,9 @@ fn move_floating_pane_focus_sends_tty_csi_event() { let new_pane_id_2 = PaneId::Terminal(3); tab.toggle_floating_panes(Some(client_id), None).unwrap(); - tab.new_pane(new_pane_id_1, None, None, None, Some(client_id)) + tab.new_pane(new_pane_id_1, None, None, None, None, Some(client_id)) .unwrap(); - tab.new_pane(new_pane_id_2, None, None, None, Some(client_id)) + tab.new_pane(new_pane_id_2, None, None, None, None, Some(client_id)) .unwrap(); tab.handle_pty_bytes( 1, @@ -3039,9 +3039,9 @@ fn toggle_floating_panes_on_sends_tty_csi_event() { let new_pane_id_2 = PaneId::Terminal(3); tab.toggle_floating_panes(Some(client_id), None).unwrap(); - tab.new_pane(new_pane_id_1, None, None, None, Some(client_id)) + tab.new_pane(new_pane_id_1, None, None, None, None, Some(client_id)) .unwrap(); - tab.new_pane(new_pane_id_2, None, None, None, Some(client_id)) + tab.new_pane(new_pane_id_2, None, None, None, None, Some(client_id)) .unwrap(); tab.toggle_floating_panes(Some(client_id), None).unwrap(); tab.handle_pty_bytes( @@ -3083,9 +3083,9 @@ fn toggle_floating_panes_off_sends_tty_csi_event() { let new_pane_id_2 = PaneId::Terminal(3); tab.toggle_floating_panes(Some(client_id), None).unwrap(); - tab.new_pane(new_pane_id_1, None, None, None, Some(client_id)) + tab.new_pane(new_pane_id_1, None, None, None, None, Some(client_id)) .unwrap(); - tab.new_pane(new_pane_id_2, None, None, None, Some(client_id)) + tab.new_pane(new_pane_id_2, None, None, None, None, Some(client_id)) .unwrap(); tab.handle_pty_bytes( 1, @@ -3145,7 +3145,7 @@ fn can_swap_tiled_layout_at_runtime() { ); let new_pane_id_1 = PaneId::Terminal(2); - tab.new_pane(new_pane_id_1, None, None, None, Some(client_id)) + tab.new_pane(new_pane_id_1, None, None, None, None, Some(client_id)) .unwrap(); tab.next_swap_layout(Some(client_id), false).unwrap(); tab.render(&mut output).unwrap(); @@ -3200,9 +3200,9 @@ fn can_swap_floating_layout_at_runtime() { let new_pane_id_2 = PaneId::Terminal(3); tab.toggle_floating_panes(Some(client_id), None).unwrap(); - tab.new_pane(new_pane_id_1, None, None, None, Some(client_id)) + tab.new_pane(new_pane_id_1, None, None, None, None, Some(client_id)) .unwrap(); - tab.new_pane(new_pane_id_2, None, None, None, Some(client_id)) + tab.new_pane(new_pane_id_2, None, None, None, None, Some(client_id)) .unwrap(); tab.next_swap_layout(Some(client_id), false).unwrap(); tab.render(&mut output).unwrap(); @@ -3253,7 +3253,7 @@ fn swapping_layouts_after_resize_snaps_to_current_layout() { ); let new_pane_id_1 = PaneId::Terminal(2); - tab.new_pane(new_pane_id_1, None, None, None, Some(client_id)) + tab.new_pane(new_pane_id_1, None, None, None, None, Some(client_id)) .unwrap(); tab.next_swap_layout(Some(client_id), false).unwrap(); tab.resize(client_id, ResizeStrategy::new(Resize::Increase, None)) @@ -3303,11 +3303,11 @@ fn swap_tiled_layout_with_stacked_children() { let new_pane_id_2 = PaneId::Terminal(3); let new_pane_id_3 = PaneId::Terminal(4); - tab.new_pane(new_pane_id_1, None, None, None, Some(client_id)) + tab.new_pane(new_pane_id_1, None, None, None, None, Some(client_id)) .unwrap(); - tab.new_pane(new_pane_id_2, None, None, None, Some(client_id)) + tab.new_pane(new_pane_id_2, None, None, None, None, Some(client_id)) .unwrap(); - tab.new_pane(new_pane_id_3, None, None, None, Some(client_id)) + tab.new_pane(new_pane_id_3, None, None, None, None, Some(client_id)) .unwrap(); tab.render(&mut output).unwrap(); let snapshot = take_snapshot( @@ -3350,11 +3350,11 @@ fn swap_tiled_layout_with_only_stacked_children() { let new_pane_id_2 = PaneId::Terminal(3); let new_pane_id_3 = PaneId::Terminal(4); - tab.new_pane(new_pane_id_1, None, None, None, Some(client_id)) + tab.new_pane(new_pane_id_1, None, None, None, None, Some(client_id)) .unwrap(); - tab.new_pane(new_pane_id_2, None, None, None, Some(client_id)) + tab.new_pane(new_pane_id_2, None, None, None, None, Some(client_id)) .unwrap(); - tab.new_pane(new_pane_id_3, None, None, None, Some(client_id)) + tab.new_pane(new_pane_id_3, None, None, None, None, Some(client_id)) .unwrap(); tab.render(&mut output).unwrap(); let snapshot = take_snapshot( @@ -3400,11 +3400,11 @@ fn swap_tiled_layout_with_stacked_children_and_no_pane_frames() { let new_pane_id_2 = PaneId::Terminal(3); let new_pane_id_3 = PaneId::Terminal(4); - tab.new_pane(new_pane_id_1, None, None, None, Some(client_id)) + tab.new_pane(new_pane_id_1, None, None, None, None, Some(client_id)) .unwrap(); - tab.new_pane(new_pane_id_2, None, None, None, Some(client_id)) + tab.new_pane(new_pane_id_2, None, None, None, None, Some(client_id)) .unwrap(); - tab.new_pane(new_pane_id_3, None, None, None, Some(client_id)) + tab.new_pane(new_pane_id_3, None, None, None, None, Some(client_id)) .unwrap(); tab.render(&mut output).unwrap(); let snapshot = take_snapshot( @@ -3450,11 +3450,11 @@ fn move_focus_up_with_stacked_panes() { let new_pane_id_2 = PaneId::Terminal(3); let new_pane_id_3 = PaneId::Terminal(4); - tab.new_pane(new_pane_id_1, None, None, None, Some(client_id)) + tab.new_pane(new_pane_id_1, None, None, None, None, Some(client_id)) .unwrap(); - tab.new_pane(new_pane_id_2, None, None, None, Some(client_id)) + tab.new_pane(new_pane_id_2, None, None, None, None, Some(client_id)) .unwrap(); - tab.new_pane(new_pane_id_3, None, None, None, Some(client_id)) + tab.new_pane(new_pane_id_3, None, None, None, None, Some(client_id)) .unwrap(); tab.move_focus_right(client_id); tab.move_focus_up(client_id); @@ -3502,11 +3502,11 @@ fn move_focus_down_with_stacked_panes() { let new_pane_id_2 = PaneId::Terminal(3); let new_pane_id_3 = PaneId::Terminal(4); - tab.new_pane(new_pane_id_1, None, None, None, Some(client_id)) + tab.new_pane(new_pane_id_1, None, None, None, None, Some(client_id)) .unwrap(); - tab.new_pane(new_pane_id_2, None, None, None, Some(client_id)) + tab.new_pane(new_pane_id_2, None, None, None, None, Some(client_id)) .unwrap(); - tab.new_pane(new_pane_id_3, None, None, None, Some(client_id)) + tab.new_pane(new_pane_id_3, None, None, None, None, Some(client_id)) .unwrap(); tab.move_focus_right(client_id); tab.move_focus_up(client_id); @@ -3561,6 +3561,7 @@ fn move_focus_right_into_stacked_panes() { None, None, None, + None, Some(client_id), ) .unwrap(); @@ -3628,6 +3629,7 @@ fn move_focus_left_into_stacked_panes() { None, None, None, + None, Some(client_id), ) .unwrap(); @@ -3697,6 +3699,7 @@ fn move_focus_up_into_stacked_panes() { None, None, None, + None, Some(client_id), ) .unwrap(); @@ -3767,6 +3770,7 @@ fn move_focus_down_into_stacked_panes() { None, None, None, + None, Some(client_id), ) .unwrap(); @@ -3828,11 +3832,11 @@ fn close_main_stacked_pane() { let new_pane_id_2 = PaneId::Terminal(3); let new_pane_id_3 = PaneId::Terminal(4); - tab.new_pane(new_pane_id_1, None, None, None, Some(client_id)) + tab.new_pane(new_pane_id_1, None, None, None, None, Some(client_id)) .unwrap(); - tab.new_pane(new_pane_id_2, None, None, None, Some(client_id)) + tab.new_pane(new_pane_id_2, None, None, None, None, Some(client_id)) .unwrap(); - tab.new_pane(new_pane_id_3, None, None, None, Some(client_id)) + tab.new_pane(new_pane_id_3, None, None, None, None, Some(client_id)) .unwrap(); tab.close_pane(new_pane_id_2, false, None); tab.render(&mut output).unwrap(); @@ -3881,15 +3885,15 @@ fn close_main_stacked_pane_in_mid_stack() { let new_pane_id_4 = PaneId::Terminal(5); let new_pane_id_5 = PaneId::Terminal(6); - tab.new_pane(new_pane_id_1, None, None, None, Some(client_id)) + tab.new_pane(new_pane_id_1, None, None, None, None, Some(client_id)) .unwrap(); - tab.new_pane(new_pane_id_2, None, None, None, Some(client_id)) + tab.new_pane(new_pane_id_2, None, None, None, None, Some(client_id)) .unwrap(); - tab.new_pane(new_pane_id_3, None, None, None, Some(client_id)) + tab.new_pane(new_pane_id_3, None, None, None, None, Some(client_id)) .unwrap(); - tab.new_pane(new_pane_id_4, None, None, None, Some(client_id)) + tab.new_pane(new_pane_id_4, None, None, None, None, Some(client_id)) .unwrap(); - tab.new_pane(new_pane_id_5, None, None, None, Some(client_id)) + tab.new_pane(new_pane_id_5, None, None, None, None, Some(client_id)) .unwrap(); tab.move_focus_right(client_id); tab.move_focus_up(client_id); @@ -3941,15 +3945,15 @@ fn close_one_liner_stacked_pane_below_main_pane() { let new_pane_id_4 = PaneId::Terminal(5); let new_pane_id_5 = PaneId::Terminal(6); - tab.new_pane(new_pane_id_1, None, None, None, Some(client_id)) + tab.new_pane(new_pane_id_1, None, None, None, None, Some(client_id)) .unwrap(); - tab.new_pane(new_pane_id_2, None, None, None, Some(client_id)) + tab.new_pane(new_pane_id_2, None, None, None, None, Some(client_id)) .unwrap(); - tab.new_pane(new_pane_id_3, None, None, None, Some(client_id)) + tab.new_pane(new_pane_id_3, None, None, None, None, Some(client_id)) .unwrap(); - tab.new_pane(new_pane_id_4, None, None, None, Some(client_id)) + tab.new_pane(new_pane_id_4, None, None, None, None, Some(client_id)) .unwrap(); - tab.new_pane(new_pane_id_5, None, None, None, Some(client_id)) + tab.new_pane(new_pane_id_5, None, None, None, None, Some(client_id)) .unwrap(); tab.move_focus_left(client_id); tab.move_focus_right(client_id); @@ -4002,15 +4006,15 @@ fn close_one_liner_stacked_pane_above_main_pane() { let new_pane_id_4 = PaneId::Terminal(5); let new_pane_id_5 = PaneId::Terminal(6); - tab.new_pane(new_pane_id_1, None, None, None, Some(client_id)) + tab.new_pane(new_pane_id_1, None, None, None, None, Some(client_id)) .unwrap(); - tab.new_pane(new_pane_id_2, None, None, None, Some(client_id)) + tab.new_pane(new_pane_id_2, None, None, None, None, Some(client_id)) .unwrap(); - tab.new_pane(new_pane_id_3, None, None, None, Some(client_id)) + tab.new_pane(new_pane_id_3, None, None, None, None, Some(client_id)) .unwrap(); - tab.new_pane(new_pane_id_4, None, None, None, Some(client_id)) + tab.new_pane(new_pane_id_4, None, None, None, None, Some(client_id)) .unwrap(); - tab.new_pane(new_pane_id_5, None, None, None, Some(client_id)) + tab.new_pane(new_pane_id_5, None, None, None, None, Some(client_id)) .unwrap(); tab.move_focus_right(client_id); tab.move_focus_up(client_id); @@ -4062,15 +4066,15 @@ fn can_increase_size_of_main_pane_in_stack_horizontally() { let new_pane_id_4 = PaneId::Terminal(5); let new_pane_id_5 = PaneId::Terminal(6); - tab.new_pane(new_pane_id_1, None, None, None, Some(client_id)) + tab.new_pane(new_pane_id_1, None, None, None, None, Some(client_id)) .unwrap(); - tab.new_pane(new_pane_id_2, None, None, None, Some(client_id)) + tab.new_pane(new_pane_id_2, None, None, None, None, Some(client_id)) .unwrap(); - tab.new_pane(new_pane_id_3, None, None, None, Some(client_id)) + tab.new_pane(new_pane_id_3, None, None, None, None, Some(client_id)) .unwrap(); - tab.new_pane(new_pane_id_4, None, None, None, Some(client_id)) + tab.new_pane(new_pane_id_4, None, None, None, None, Some(client_id)) .unwrap(); - tab.new_pane(new_pane_id_5, None, None, None, Some(client_id)) + tab.new_pane(new_pane_id_5, None, None, None, None, Some(client_id)) .unwrap(); tab.move_focus_right(client_id); tab.resize( @@ -4126,15 +4130,15 @@ fn can_increase_size_of_main_pane_in_stack_vertically() { let new_pane_id_4 = PaneId::Terminal(5); let new_pane_id_5 = PaneId::Terminal(6); - tab.new_pane(new_pane_id_1, None, None, None, Some(client_id)) + tab.new_pane(new_pane_id_1, None, None, None, None, Some(client_id)) .unwrap(); - tab.new_pane(new_pane_id_2, None, None, None, Some(client_id)) + tab.new_pane(new_pane_id_2, None, None, None, None, Some(client_id)) .unwrap(); - tab.new_pane(new_pane_id_3, None, None, None, Some(client_id)) + tab.new_pane(new_pane_id_3, None, None, None, None, Some(client_id)) .unwrap(); - tab.new_pane(new_pane_id_4, None, None, None, Some(client_id)) + tab.new_pane(new_pane_id_4, None, None, None, None, Some(client_id)) .unwrap(); - tab.new_pane(new_pane_id_5, None, None, None, Some(client_id)) + tab.new_pane(new_pane_id_5, None, None, None, None, Some(client_id)) .unwrap(); tab.move_focus_right(client_id); tab.resize( @@ -4190,15 +4194,15 @@ fn can_increase_size_of_main_pane_in_stack_non_directionally() { let new_pane_id_4 = PaneId::Terminal(5); let new_pane_id_5 = PaneId::Terminal(6); - tab.new_pane(new_pane_id_1, None, None, None, Some(client_id)) + tab.new_pane(new_pane_id_1, None, None, None, None, Some(client_id)) .unwrap(); - tab.new_pane(new_pane_id_2, None, None, None, Some(client_id)) + tab.new_pane(new_pane_id_2, None, None, None, None, Some(client_id)) .unwrap(); - tab.new_pane(new_pane_id_3, None, None, None, Some(client_id)) + tab.new_pane(new_pane_id_3, None, None, None, None, Some(client_id)) .unwrap(); - tab.new_pane(new_pane_id_4, None, None, None, Some(client_id)) + tab.new_pane(new_pane_id_4, None, None, None, None, Some(client_id)) .unwrap(); - tab.new_pane(new_pane_id_5, None, None, None, Some(client_id)) + tab.new_pane(new_pane_id_5, None, None, None, None, Some(client_id)) .unwrap(); let _ = tab.move_focus_up(client_id); let _ = tab.move_focus_right(client_id); @@ -4250,15 +4254,15 @@ fn can_increase_size_into_pane_stack_horizontally() { let new_pane_id_4 = PaneId::Terminal(5); let new_pane_id_5 = PaneId::Terminal(6); - tab.new_pane(new_pane_id_1, None, None, None, Some(client_id)) + tab.new_pane(new_pane_id_1, None, None, None, None, Some(client_id)) .unwrap(); - tab.new_pane(new_pane_id_2, None, None, None, Some(client_id)) + tab.new_pane(new_pane_id_2, None, None, None, None, Some(client_id)) .unwrap(); - tab.new_pane(new_pane_id_3, None, None, None, Some(client_id)) + tab.new_pane(new_pane_id_3, None, None, None, None, Some(client_id)) .unwrap(); - tab.new_pane(new_pane_id_4, None, None, None, Some(client_id)) + tab.new_pane(new_pane_id_4, None, None, None, None, Some(client_id)) .unwrap(); - tab.new_pane(new_pane_id_5, None, None, None, Some(client_id)) + tab.new_pane(new_pane_id_5, None, None, None, None, Some(client_id)) .unwrap(); tab.resize( client_id, @@ -4313,15 +4317,15 @@ fn can_increase_size_into_pane_stack_vertically() { let new_pane_id_4 = PaneId::Terminal(5); let new_pane_id_5 = PaneId::Terminal(6); - tab.new_pane(new_pane_id_1, None, None, None, Some(client_id)) + tab.new_pane(new_pane_id_1, None, None, None, None, Some(client_id)) .unwrap(); - tab.new_pane(new_pane_id_2, None, None, None, Some(client_id)) + tab.new_pane(new_pane_id_2, None, None, None, None, Some(client_id)) .unwrap(); - tab.new_pane(new_pane_id_3, None, None, None, Some(client_id)) + tab.new_pane(new_pane_id_3, None, None, None, None, Some(client_id)) .unwrap(); - tab.new_pane(new_pane_id_4, None, None, None, Some(client_id)) + tab.new_pane(new_pane_id_4, None, None, None, None, Some(client_id)) .unwrap(); - tab.new_pane(new_pane_id_5, None, None, None, Some(client_id)) + tab.new_pane(new_pane_id_5, None, None, None, None, Some(client_id)) .unwrap(); tab.move_focus_right(client_id); tab.move_focus_down(client_id); @@ -4378,15 +4382,15 @@ fn can_increase_size_into_pane_stack_non_directionally() { let new_pane_id_4 = PaneId::Terminal(5); let new_pane_id_5 = PaneId::Terminal(6); - tab.new_pane(new_pane_id_1, None, None, None, Some(client_id)) + tab.new_pane(new_pane_id_1, None, None, None, None, Some(client_id)) .unwrap(); - tab.new_pane(new_pane_id_2, None, None, None, Some(client_id)) + tab.new_pane(new_pane_id_2, None, None, None, None, Some(client_id)) .unwrap(); - tab.new_pane(new_pane_id_3, None, None, None, Some(client_id)) + tab.new_pane(new_pane_id_3, None, None, None, None, Some(client_id)) .unwrap(); - tab.new_pane(new_pane_id_4, None, None, None, Some(client_id)) + tab.new_pane(new_pane_id_4, None, None, None, None, Some(client_id)) .unwrap(); - tab.new_pane(new_pane_id_5, None, None, None, Some(client_id)) + tab.new_pane(new_pane_id_5, None, None, None, None, Some(client_id)) .unwrap(); let _ = tab.move_focus_up(client_id); tab.resize(client_id, ResizeStrategy::new(Resize::Increase, None)) @@ -4437,15 +4441,15 @@ fn decreasing_size_of_whole_tab_treats_stacked_panes_properly() { let new_pane_id_4 = PaneId::Terminal(5); let new_pane_id_5 = PaneId::Terminal(6); - tab.new_pane(new_pane_id_1, None, None, None, Some(client_id)) + tab.new_pane(new_pane_id_1, None, None, None, None, Some(client_id)) .unwrap(); - tab.new_pane(new_pane_id_2, None, None, None, Some(client_id)) + tab.new_pane(new_pane_id_2, None, None, None, None, Some(client_id)) .unwrap(); - tab.new_pane(new_pane_id_3, None, None, None, Some(client_id)) + tab.new_pane(new_pane_id_3, None, None, None, None, Some(client_id)) .unwrap(); - tab.new_pane(new_pane_id_4, None, None, None, Some(client_id)) + tab.new_pane(new_pane_id_4, None, None, None, None, Some(client_id)) .unwrap(); - tab.new_pane(new_pane_id_5, None, None, None, Some(client_id)) + tab.new_pane(new_pane_id_5, None, None, None, None, Some(client_id)) .unwrap(); tab.resize_whole_tab(Size { cols: 100, @@ -4497,15 +4501,15 @@ fn increasing_size_of_whole_tab_treats_stacked_panes_properly() { let new_pane_id_4 = PaneId::Terminal(5); let new_pane_id_5 = PaneId::Terminal(6); - tab.new_pane(new_pane_id_1, None, None, None, Some(client_id)) + tab.new_pane(new_pane_id_1, None, None, None, None, Some(client_id)) .unwrap(); - tab.new_pane(new_pane_id_2, None, None, None, Some(client_id)) + tab.new_pane(new_pane_id_2, None, None, None, None, Some(client_id)) .unwrap(); - tab.new_pane(new_pane_id_3, None, None, None, Some(client_id)) + tab.new_pane(new_pane_id_3, None, None, None, None, Some(client_id)) .unwrap(); - tab.new_pane(new_pane_id_4, None, None, None, Some(client_id)) + tab.new_pane(new_pane_id_4, None, None, None, None, Some(client_id)) .unwrap(); - tab.new_pane(new_pane_id_5, None, None, None, Some(client_id)) + tab.new_pane(new_pane_id_5, None, None, None, None, Some(client_id)) .unwrap(); tab.resize_whole_tab(Size { cols: 100, @@ -4562,15 +4566,15 @@ fn cannot_decrease_stack_size_beyond_minimum_height() { let new_pane_id_4 = PaneId::Terminal(5); let new_pane_id_5 = PaneId::Terminal(6); - tab.new_pane(new_pane_id_1, None, None, None, Some(client_id)) + tab.new_pane(new_pane_id_1, None, None, None, None, Some(client_id)) .unwrap(); - tab.new_pane(new_pane_id_2, None, None, None, Some(client_id)) + tab.new_pane(new_pane_id_2, None, None, None, None, Some(client_id)) .unwrap(); - tab.new_pane(new_pane_id_3, None, None, None, Some(client_id)) + tab.new_pane(new_pane_id_3, None, None, None, None, Some(client_id)) .unwrap(); - tab.new_pane(new_pane_id_4, None, None, None, Some(client_id)) + tab.new_pane(new_pane_id_4, None, None, None, None, Some(client_id)) .unwrap(); - tab.new_pane(new_pane_id_5, None, None, None, Some(client_id)) + tab.new_pane(new_pane_id_5, None, None, None, None, Some(client_id)) .unwrap(); tab.move_focus_down(client_id); for _ in 0..6 { @@ -4627,15 +4631,15 @@ fn focus_stacked_pane_over_flexible_pane_with_the_mouse() { let new_pane_id_4 = PaneId::Terminal(5); let new_pane_id_5 = PaneId::Terminal(6); - tab.new_pane(new_pane_id_1, None, None, None, Some(client_id)) + tab.new_pane(new_pane_id_1, None, None, None, None, Some(client_id)) .unwrap(); - tab.new_pane(new_pane_id_2, None, None, None, Some(client_id)) + tab.new_pane(new_pane_id_2, None, None, None, None, Some(client_id)) .unwrap(); - tab.new_pane(new_pane_id_3, None, None, None, Some(client_id)) + tab.new_pane(new_pane_id_3, None, None, None, None, Some(client_id)) .unwrap(); - tab.new_pane(new_pane_id_4, None, None, None, Some(client_id)) + tab.new_pane(new_pane_id_4, None, None, None, None, Some(client_id)) .unwrap(); - tab.new_pane(new_pane_id_5, None, None, None, Some(client_id)) + tab.new_pane(new_pane_id_5, None, None, None, None, Some(client_id)) .unwrap(); tab.handle_left_click(&Position::new(1, 71), client_id) .unwrap(); @@ -4686,15 +4690,15 @@ fn focus_stacked_pane_under_flexible_pane_with_the_mouse() { let new_pane_id_4 = PaneId::Terminal(5); let new_pane_id_5 = PaneId::Terminal(6); - tab.new_pane(new_pane_id_1, None, None, None, Some(client_id)) + tab.new_pane(new_pane_id_1, None, None, None, None, Some(client_id)) .unwrap(); - tab.new_pane(new_pane_id_2, None, None, None, Some(client_id)) + tab.new_pane(new_pane_id_2, None, None, None, None, Some(client_id)) .unwrap(); - tab.new_pane(new_pane_id_3, None, None, None, Some(client_id)) + tab.new_pane(new_pane_id_3, None, None, None, None, Some(client_id)) .unwrap(); - tab.new_pane(new_pane_id_4, None, None, None, Some(client_id)) + tab.new_pane(new_pane_id_4, None, None, None, None, Some(client_id)) .unwrap(); - tab.new_pane(new_pane_id_5, None, None, None, Some(client_id)) + tab.new_pane(new_pane_id_5, None, None, None, None, Some(client_id)) .unwrap(); tab.handle_left_click(&Position::new(1, 71), client_id) .unwrap(); @@ -4747,15 +4751,15 @@ fn close_stacked_pane_with_previously_focused_other_pane() { let new_pane_id_4 = PaneId::Terminal(5); let new_pane_id_5 = PaneId::Terminal(6); - tab.new_pane(new_pane_id_1, None, None, None, Some(client_id)) + tab.new_pane(new_pane_id_1, None, None, None, None, Some(client_id)) .unwrap(); - tab.new_pane(new_pane_id_2, None, None, None, Some(client_id)) + tab.new_pane(new_pane_id_2, None, None, None, None, Some(client_id)) .unwrap(); - tab.new_pane(new_pane_id_3, None, None, None, Some(client_id)) + tab.new_pane(new_pane_id_3, None, None, None, None, Some(client_id)) .unwrap(); - tab.new_pane(new_pane_id_4, None, None, None, Some(client_id)) + tab.new_pane(new_pane_id_4, None, None, None, None, Some(client_id)) .unwrap(); - tab.new_pane(new_pane_id_5, None, None, None, Some(client_id)) + tab.new_pane(new_pane_id_5, None, None, None, None, Some(client_id)) .unwrap(); tab.handle_left_click(&Position::new(2, 71), client_id) .unwrap(); @@ -4814,15 +4818,15 @@ fn close_pane_near_stacked_panes() { let new_pane_id_4 = PaneId::Terminal(5); let new_pane_id_5 = PaneId::Terminal(6); - tab.new_pane(new_pane_id_1, None, None, None, Some(client_id)) + tab.new_pane(new_pane_id_1, None, None, None, None, Some(client_id)) .unwrap(); - tab.new_pane(new_pane_id_2, None, None, None, Some(client_id)) + tab.new_pane(new_pane_id_2, None, None, None, None, Some(client_id)) .unwrap(); - tab.new_pane(new_pane_id_3, None, None, None, Some(client_id)) + tab.new_pane(new_pane_id_3, None, None, None, None, Some(client_id)) .unwrap(); - tab.new_pane(new_pane_id_4, None, None, None, Some(client_id)) + tab.new_pane(new_pane_id_4, None, None, None, None, Some(client_id)) .unwrap(); - tab.new_pane(new_pane_id_5, None, None, None, Some(client_id)) + tab.new_pane(new_pane_id_5, None, None, None, None, Some(client_id)) .unwrap(); tab.close_pane(PaneId::Terminal(6), false, None); tab.render(&mut output).unwrap(); @@ -4878,15 +4882,15 @@ fn focus_next_pane_expands_stacked_panes() { let new_pane_id_4 = PaneId::Terminal(5); let new_pane_id_5 = PaneId::Terminal(6); - tab.new_pane(new_pane_id_1, None, None, None, Some(client_id)) + tab.new_pane(new_pane_id_1, None, None, None, None, Some(client_id)) .unwrap(); - tab.new_pane(new_pane_id_2, None, None, None, Some(client_id)) + tab.new_pane(new_pane_id_2, None, None, None, None, Some(client_id)) .unwrap(); - tab.new_pane(new_pane_id_3, None, None, None, Some(client_id)) + tab.new_pane(new_pane_id_3, None, None, None, None, Some(client_id)) .unwrap(); - tab.new_pane(new_pane_id_4, None, None, None, Some(client_id)) + tab.new_pane(new_pane_id_4, None, None, None, None, Some(client_id)) .unwrap(); - tab.new_pane(new_pane_id_5, None, None, None, Some(client_id)) + tab.new_pane(new_pane_id_5, None, None, None, None, Some(client_id)) .unwrap(); tab.move_focus_left(client_id); tab.focus_next_pane(client_id); @@ -4938,15 +4942,15 @@ fn stacked_panes_can_become_fullscreen() { let new_pane_id_4 = PaneId::Terminal(5); let new_pane_id_5 = PaneId::Terminal(6); - tab.new_pane(new_pane_id_1, None, None, None, Some(client_id)) + tab.new_pane(new_pane_id_1, None, None, None, None, Some(client_id)) .unwrap(); - tab.new_pane(new_pane_id_2, None, None, None, Some(client_id)) + tab.new_pane(new_pane_id_2, None, None, None, None, Some(client_id)) .unwrap(); - tab.new_pane(new_pane_id_3, None, None, None, Some(client_id)) + tab.new_pane(new_pane_id_3, None, None, None, None, Some(client_id)) .unwrap(); - tab.new_pane(new_pane_id_4, None, None, None, Some(client_id)) + tab.new_pane(new_pane_id_4, None, None, None, None, Some(client_id)) .unwrap(); - tab.new_pane(new_pane_id_5, None, None, None, Some(client_id)) + tab.new_pane(new_pane_id_5, None, None, None, None, Some(client_id)) .unwrap(); tab.move_focus_up(client_id); tab.toggle_active_pane_fullscreen(client_id); @@ -5608,6 +5612,7 @@ fn new_pane_in_auto_layout() { None, None, None, + None, Some(client_id), ) .unwrap(); @@ -6552,6 +6557,7 @@ fn new_floating_pane_in_auto_layout() { None, Some(should_float), None, + None, Some(client_id), ) .unwrap(); diff --git a/zellij-server/src/tab/unit/tab_tests.rs b/zellij-server/src/tab/unit/tab_tests.rs index 7bbd4fa0..d1a3c020 100644 --- a/zellij-server/src/tab/unit/tab_tests.rs +++ b/zellij-server/src/tab/unit/tab_tests.rs @@ -559,7 +559,7 @@ fn split_largest_pane() { let mut tab = create_new_tab(size); for i in 2..5 { let new_pane_id = PaneId::Terminal(i); - tab.new_pane(new_pane_id, None, None, None, Some(1)) + tab.new_pane(new_pane_id, None, None, None, None, Some(1)) .unwrap(); } assert_eq!(tab.tiled_panes.panes.len(), 4, "The tab has four panes"); @@ -765,7 +765,7 @@ pub fn cannot_split_panes_horizontally_when_active_pane_is_too_small() { pub fn cannot_split_largest_pane_when_there_is_no_room() { let size = Size { cols: 8, rows: 4 }; let mut tab = create_new_tab(size); - tab.new_pane(PaneId::Terminal(2), None, None, None, Some(1)) + tab.new_pane(PaneId::Terminal(2), None, None, None, None, Some(1)) .unwrap(); assert_eq!( tab.tiled_panes.panes.len(), @@ -809,7 +809,7 @@ pub fn toggle_focused_pane_fullscreen() { let mut tab = create_new_tab(size); for i in 2..5 { let new_pane_id = PaneId::Terminal(i); - tab.new_pane(new_pane_id, None, None, None, Some(1)) + tab.new_pane(new_pane_id, None, None, None, None, Some(1)) .unwrap(); } tab.toggle_active_pane_fullscreen(1); @@ -884,16 +884,16 @@ fn switch_to_next_pane_fullscreen() { let mut active_tab = create_new_tab(size); active_tab - .new_pane(PaneId::Terminal(1), None, None, None, Some(1)) + .new_pane(PaneId::Terminal(1), None, None, None, None, Some(1)) .unwrap(); active_tab - .new_pane(PaneId::Terminal(2), None, None, None, Some(1)) + .new_pane(PaneId::Terminal(2), None, None, None, None, Some(1)) .unwrap(); active_tab - .new_pane(PaneId::Terminal(3), None, None, None, Some(1)) + .new_pane(PaneId::Terminal(3), None, None, None, None, Some(1)) .unwrap(); active_tab - .new_pane(PaneId::Terminal(4), None, None, None, Some(1)) + .new_pane(PaneId::Terminal(4), None, None, None, None, Some(1)) .unwrap(); active_tab.toggle_active_pane_fullscreen(1); @@ -924,16 +924,16 @@ fn switch_to_prev_pane_fullscreen() { //testing four consecutive switches in fullscreen mode active_tab - .new_pane(PaneId::Terminal(1), None, None, None, Some(1)) + .new_pane(PaneId::Terminal(1), None, None, None, None, Some(1)) .unwrap(); active_tab - .new_pane(PaneId::Terminal(2), None, None, None, Some(1)) + .new_pane(PaneId::Terminal(2), None, None, None, None, Some(1)) .unwrap(); active_tab - .new_pane(PaneId::Terminal(3), None, None, None, Some(1)) + .new_pane(PaneId::Terminal(3), None, None, None, None, Some(1)) .unwrap(); active_tab - .new_pane(PaneId::Terminal(4), None, None, None, Some(1)) + .new_pane(PaneId::Terminal(4), None, None, None, None, Some(1)) .unwrap(); active_tab.toggle_active_pane_fullscreen(1); // order is now 1 2 3 4 @@ -14415,7 +14415,7 @@ fn correctly_resize_frameless_panes_on_pane_close() { let content_size = (pane.get_content_columns(), pane.get_content_rows()); assert_eq!(content_size, (cols, rows)); - tab.new_pane(PaneId::Terminal(2), None, None, None, Some(1)) + tab.new_pane(PaneId::Terminal(2), None, None, None, None, Some(1)) .unwrap(); tab.close_pane(PaneId::Terminal(2), true, None); diff --git a/zellij-server/src/unit/screen_tests.rs b/zellij-server/src/unit/screen_tests.rs index 4ce4dbc1..de3faafc 100644 --- a/zellij-server/src/unit/screen_tests.rs +++ b/zellij-server/src/unit/screen_tests.rs @@ -15,7 +15,8 @@ use zellij_utils::errors::{prelude::*, ErrorContext}; use zellij_utils::input::actions::Action; use zellij_utils::input::command::{RunCommand, TerminalAction}; use zellij_utils::input::layout::{ - FloatingPaneLayout, Layout, Run, RunPlugin, RunPluginLocation, SplitDirection, TiledPaneLayout, + FloatingPaneLayout, Layout, Run, RunPlugin, RunPluginLocation, SplitDirection, SplitSize, + TiledPaneLayout, }; use zellij_utils::input::options::Options; use zellij_utils::ipc::IpcReceiverWithContext; @@ -32,7 +33,7 @@ use zellij_utils::ipc::PixelDimensions; use zellij_utils::{ channels::{self, ChannelWithContext, Receiver}, - data::{Direction, InputMode, ModeInfo, Palette, PluginCapabilities}, + data::{Direction, FloatingPaneCoordinates, InputMode, ModeInfo, Palette, PluginCapabilities}, interprocess::local_socket::LocalSocketStream, ipc::{ClientAttributes, ClientToServerMsg, ServerToClientMsg}, }; @@ -923,7 +924,7 @@ fn switch_to_tab_with_fullscreen() { { let active_tab = screen.get_active_tab_mut(1).unwrap(); active_tab - .new_pane(PaneId::Terminal(2), None, None, None, Some(1)) + .new_pane(PaneId::Terminal(2), None, None, None, None, Some(1)) .unwrap(); active_tab.toggle_active_pane_fullscreen(1); } @@ -1038,7 +1039,7 @@ fn attach_after_first_tab_closed() { { let active_tab = screen.get_active_tab_mut(1).unwrap(); active_tab - .new_pane(PaneId::Terminal(2), None, None, None, Some(1)) + .new_pane(PaneId::Terminal(2), None, None, None, None, Some(1)) .unwrap(); active_tab.toggle_active_pane_fullscreen(1); } @@ -1049,6 +1050,72 @@ fn attach_after_first_tab_closed() { screen.add_client(1).expect("TEST"); } +#[test] +fn open_new_floating_pane_with_custom_coordinates() { + let size = Size { + cols: 121, + rows: 20, + }; + let mut screen = create_new_screen(size); + + new_tab(&mut screen, 1, 0); + let active_tab = screen.get_active_tab_mut(1).unwrap(); + let should_float = Some(true); + active_tab + .new_pane( + PaneId::Terminal(2), + None, + should_float, + None, + Some(FloatingPaneCoordinates { + x: Some(SplitSize::Percent(10)), + y: Some(SplitSize::Fixed(5)), + width: Some(SplitSize::Percent(1)), + height: Some(SplitSize::Fixed(2)), + }), + Some(1), + ) + .unwrap(); + let active_pane = active_tab.get_active_pane(1).unwrap(); + assert_eq!(active_pane.x(), 12, "x coordinates set properly"); + assert_eq!(active_pane.y(), 5, "y coordinates set properly"); + assert_eq!(active_pane.rows(), 2, "rows set properly"); + assert_eq!(active_pane.cols(), 1, "columns set properly"); +} + +#[test] +fn open_new_floating_pane_with_custom_coordinates_exceeding_viewport() { + let size = Size { + cols: 121, + rows: 20, + }; + let mut screen = create_new_screen(size); + + new_tab(&mut screen, 1, 0); + let active_tab = screen.get_active_tab_mut(1).unwrap(); + let should_float = Some(true); + active_tab + .new_pane( + PaneId::Terminal(2), + None, + should_float, + None, + Some(FloatingPaneCoordinates { + x: Some(SplitSize::Fixed(122)), + y: Some(SplitSize::Fixed(21)), + width: Some(SplitSize::Fixed(10)), + height: Some(SplitSize::Fixed(10)), + }), + Some(1), + ) + .unwrap(); + let active_pane = active_tab.get_active_pane(1).unwrap(); + assert_eq!(active_pane.x(), 111, "x coordinates set properly"); + assert_eq!(active_pane.y(), 10, "y coordinates set properly"); + assert_eq!(active_pane.rows(), 10, "rows set properly"); + assert_eq!(active_pane.cols(), 10, "columns set properly"); +} + // Following are tests for sending CLI actions // these tests are only partially relevant to Screen // and are included here for two reasons: @@ -1900,6 +1967,10 @@ pub fn send_cli_new_pane_action_with_default_parameters() { start_suspended: false, configuration: None, skip_plugin_cache: false, + x: None, + y: None, + width: None, + height: None, }; send_cli_action_to_server(&session_metadata, cli_new_pane_action, client_id); std::thread::sleep(std::time::Duration::from_millis(100)); // give time for actions to be @@ -1939,6 +2010,10 @@ pub fn send_cli_new_pane_action_with_split_direction() { start_suspended: false, configuration: None, skip_plugin_cache: false, + x: None, + y: None, + width: None, + height: None, }; send_cli_action_to_server(&session_metadata, cli_new_pane_action, client_id); std::thread::sleep(std::time::Duration::from_millis(100)); // give time for actions to be @@ -1978,6 +2053,53 @@ pub fn send_cli_new_pane_action_with_command_and_cwd() { start_suspended: false, configuration: None, skip_plugin_cache: false, + x: None, + y: None, + width: None, + height: None, + }; + send_cli_action_to_server(&session_metadata, cli_new_pane_action, client_id); + std::thread::sleep(std::time::Duration::from_millis(100)); // give time for actions to be + mock_screen.teardown(vec![pty_thread, screen_thread]); + assert_snapshot!(format!("{:?}", *received_pty_instructions.lock().unwrap())); +} + +#[test] +pub fn send_cli_new_pane_action_with_floating_pane_and_coordinates() { + let size = Size { + cols: 121, + rows: 20, + }; + let client_id = 10; // fake client id should not appear in the screen's state + let mut mock_screen = MockScreen::new(size); + let pty_receiver = mock_screen.pty_receiver.take().unwrap(); + let session_metadata = mock_screen.clone_session_metadata(); + let mut initial_layout = TiledPaneLayout::default(); + initial_layout.children_split_direction = SplitDirection::Vertical; + initial_layout.children = vec![TiledPaneLayout::default(), TiledPaneLayout::default()]; + let screen_thread = mock_screen.run(Some(initial_layout), vec![]); + let received_pty_instructions = Arc::new(Mutex::new(vec![])); + let pty_thread = log_actions_in_thread!( + received_pty_instructions, + PtyInstruction::Exit, + pty_receiver + ); + let cli_new_pane_action = CliAction::NewPane { + direction: Some(Direction::Right), + command: vec!["htop".into()], + plugin: None, + cwd: Some("/some/folder".into()), + floating: true, + in_place: false, + name: None, + close_on_exit: false, + start_suspended: false, + configuration: None, + skip_plugin_cache: false, + x: Some("10".to_owned()), + y: None, + width: Some("20%".to_owned()), + height: None, }; send_cli_action_to_server(&session_metadata, cli_new_pane_action, client_id); std::thread::sleep(std::time::Duration::from_millis(100)); // give time for actions to be @@ -2012,6 +2134,10 @@ pub fn send_cli_edit_action_with_default_parameters() { floating: false, in_place: false, cwd: None, + x: None, + y: None, + width: None, + height: None, }; send_cli_action_to_server(&session_metadata, cli_edit_action, client_id); std::thread::sleep(std::time::Duration::from_millis(100)); // give time for actions to be @@ -2046,6 +2172,10 @@ pub fn send_cli_edit_action_with_line_number() { floating: false, in_place: false, cwd: None, + x: None, + y: None, + width: None, + height: None, }; send_cli_action_to_server(&session_metadata, cli_edit_action, client_id); std::thread::sleep(std::time::Duration::from_millis(100)); // give time for actions to be @@ -2080,6 +2210,10 @@ pub fn send_cli_edit_action_with_split_direction() { floating: false, in_place: false, cwd: None, + x: None, + y: None, + width: None, + height: None, }; send_cli_action_to_server(&session_metadata, cli_edit_action, client_id); std::thread::sleep(std::time::Duration::from_millis(100)); // give time for actions to be diff --git a/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_edit_action_with_default_parameters.snap b/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_edit_action_with_default_parameters.snap index ccd71c6a..f4e2645a 100644 --- a/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_edit_action_with_default_parameters.snap +++ b/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_edit_action_with_default_parameters.snap @@ -1,6 +1,6 @@ --- source: zellij-server/src/./unit/screen_tests.rs -assertion_line: 2102 +assertion_line: 2031 expression: "format!(\"{:?}\", * received_pty_instructions.lock().unwrap())" --- -[SpawnTerminal(Some(OpenFile("/file/to/edit", None, Some("."))), Some(false), Some("Editing: /file/to/edit"), ClientId(10)), UpdateActivePane(Some(Terminal(0)), 1), UpdateActivePane(Some(Terminal(0)), 1), Exit] +[SpawnTerminal(Some(OpenFile("/file/to/edit", None, Some("."))), Some(false), Some("Editing: /file/to/edit"), None, ClientId(10)), UpdateActivePane(Some(Terminal(0)), 1), UpdateActivePane(Some(Terminal(0)), 1), Exit] diff --git a/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_edit_action_with_line_number.snap b/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_edit_action_with_line_number.snap index 485a2312..e5b22c9f 100644 --- a/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_edit_action_with_line_number.snap +++ b/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_edit_action_with_line_number.snap @@ -1,6 +1,6 @@ --- source: zellij-server/src/./unit/screen_tests.rs -assertion_line: 2140 +assertion_line: 2065 expression: "format!(\"{:?}\", * received_pty_instructions.lock().unwrap())" --- -[SpawnTerminal(Some(OpenFile("/file/to/edit", Some(100), Some("."))), Some(false), Some("Editing: /file/to/edit"), ClientId(10)), UpdateActivePane(Some(Terminal(0)), 1), UpdateActivePane(Some(Terminal(0)), 1), Exit] +[SpawnTerminal(Some(OpenFile("/file/to/edit", Some(100), Some("."))), Some(false), Some("Editing: /file/to/edit"), None, ClientId(10)), UpdateActivePane(Some(Terminal(0)), 1), UpdateActivePane(Some(Terminal(0)), 1), Exit] diff --git a/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_launch_or_focus_plugin_action.snap b/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_launch_or_focus_plugin_action.snap index 2276d050..28a3f4bb 100644 --- a/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_launch_or_focus_plugin_action.snap +++ b/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_launch_or_focus_plugin_action.snap @@ -1,6 +1,6 @@ --- source: zellij-server/src/./unit/screen_tests.rs -assertion_line: 2627 +assertion_line: 2639 expression: "format!(\"{:#?}\", pty_fill_plugin_cwd_instruction)" --- Some( @@ -28,5 +28,6 @@ Some( }, false, None, + None, ), ) diff --git a/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_new_pane_action_with_default_parameters.snap b/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_new_pane_action_with_default_parameters.snap index 305dd0df..39b5ea9d 100644 --- a/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_new_pane_action_with_default_parameters.snap +++ b/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_new_pane_action_with_default_parameters.snap @@ -1,6 +1,6 @@ --- source: zellij-server/src/./unit/screen_tests.rs -assertion_line: 1831 +assertion_line: 1911 expression: "format!(\"{:?}\", * received_pty_instructions.lock().unwrap())" --- -[SpawnTerminal(None, Some(false), None, ClientId(10)), UpdateActivePane(Some(Terminal(0)), 1), UpdateActivePane(Some(Terminal(0)), 1), Exit] +[SpawnTerminal(None, Some(false), None, None, ClientId(10)), UpdateActivePane(Some(Terminal(0)), 1), UpdateActivePane(Some(Terminal(0)), 1), Exit] diff --git a/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_new_pane_action_with_floating_pane_and_coordinates.snap b/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_new_pane_action_with_floating_pane_and_coordinates.snap new file mode 100644 index 00000000..bb30c0d2 --- /dev/null +++ b/zellij-server/src/unit/snapshots/zellij_server__screen__screen_tests__send_cli_new_pane_action_with_floating_pane_and_coordinates.snap @@ -0,0 +1,6 @@ +--- +source: zellij-server/src/./unit/screen_tests.rs +assertion_line: 2040 +expression: "format!(\"{:?}\", * received_pty_instructions.lock().unwrap())" +--- +[SpawnTerminal(Some(RunCommand(RunCommand { command: "htop", args: [], cwd: Some("/some/folder"), hold_on_close: true, hold_on_start: false })), Some(true), None, Some(FloatingPaneCoordinates { x: Some(Fixed(10)), y: None, width: Some(Percent(20)), height: None }), ClientId(10)), UpdateActivePane(Some(Terminal(0)), 1), UpdateActivePane(Some(Terminal(0)), 1), Exit] diff --git a/zellij-tile/src/shim.rs b/zellij-tile/src/shim.rs index dd5d1807..db3e84e3 100644 --- a/zellij-tile/src/shim.rs +++ b/zellij-tile/src/shim.rs @@ -84,8 +84,8 @@ pub fn open_file(file_to_open: FileToOpen) { } /// Open a file in the user's default `$EDITOR` in a new floating pane -pub fn open_file_floating(file_to_open: FileToOpen) { - let plugin_command = PluginCommand::OpenFileFloating(file_to_open); +pub fn open_file_floating(file_to_open: FileToOpen, coordinates: Option) { + let plugin_command = PluginCommand::OpenFileFloating(file_to_open, coordinates); let protobuf_plugin_command: ProtobufPluginCommand = plugin_command.try_into().unwrap(); object_to_stdout(&protobuf_plugin_command.encode_to_vec()); unsafe { host_run_plugin_command() }; @@ -109,9 +109,12 @@ pub fn open_terminal>(path: P) { } /// Open a new floating terminal pane to the specified location on the host filesystem -pub fn open_terminal_floating>(path: P) { +pub fn open_terminal_floating>( + path: P, + coordinates: Option, +) { let file_to_open = FileToOpen::new(path.as_ref().to_path_buf()); - let plugin_command = PluginCommand::OpenTerminalFloating(file_to_open); + let plugin_command = PluginCommand::OpenTerminalFloating(file_to_open, coordinates); let protobuf_plugin_command: ProtobufPluginCommand = plugin_command.try_into().unwrap(); object_to_stdout(&protobuf_plugin_command.encode_to_vec()); unsafe { host_run_plugin_command() }; @@ -136,14 +139,17 @@ pub fn open_command_pane(command_to_run: CommandToRun) { } /// Open a new floating command pane with the specified command and args (this sort of pane allows the user to control the command, re-run it and see its exit status through the Zellij UI). -pub fn open_command_pane_floating(command_to_run: CommandToRun) { - let plugin_command = PluginCommand::OpenCommandPaneFloating(command_to_run); +pub fn open_command_pane_floating( + command_to_run: CommandToRun, + coordinates: Option, +) { + let plugin_command = PluginCommand::OpenCommandPaneFloating(command_to_run, coordinates); let protobuf_plugin_command: ProtobufPluginCommand = plugin_command.try_into().unwrap(); object_to_stdout(&protobuf_plugin_command.encode_to_vec()); unsafe { host_run_plugin_command() }; } -/// Open a new floating command pane with the specified command and args (this sort of pane allows the user to control the command, re-run it and see its exit status through the Zellij UI). +/// Open a new in place command pane with the specified command and args (this sort of pane allows the user to control the command, re-run it and see its exit status through the Zellij UI). pub fn open_command_pane_in_place(command_to_run: CommandToRun) { let plugin_command = PluginCommand::OpenCommandPaneInPlace(command_to_run); let protobuf_plugin_command: ProtobufPluginCommand = plugin_command.try_into().unwrap(); diff --git a/zellij-utils/assets/plugins/compact-bar.wasm b/zellij-utils/assets/plugins/compact-bar.wasm index 2f7b7bcf..a0911ddb 100755 Binary files a/zellij-utils/assets/plugins/compact-bar.wasm and b/zellij-utils/assets/plugins/compact-bar.wasm differ diff --git a/zellij-utils/assets/plugins/fixture-plugin-for-tests.wasm b/zellij-utils/assets/plugins/fixture-plugin-for-tests.wasm index b9489c19..6dba31da 100755 Binary files a/zellij-utils/assets/plugins/fixture-plugin-for-tests.wasm and b/zellij-utils/assets/plugins/fixture-plugin-for-tests.wasm differ diff --git a/zellij-utils/assets/plugins/session-manager.wasm b/zellij-utils/assets/plugins/session-manager.wasm index 4be500b7..109987c0 100755 Binary files a/zellij-utils/assets/plugins/session-manager.wasm and b/zellij-utils/assets/plugins/session-manager.wasm differ diff --git a/zellij-utils/assets/plugins/status-bar.wasm b/zellij-utils/assets/plugins/status-bar.wasm index 3a7dbb82..59859dee 100755 Binary files a/zellij-utils/assets/plugins/status-bar.wasm and b/zellij-utils/assets/plugins/status-bar.wasm differ diff --git a/zellij-utils/assets/plugins/strider.wasm b/zellij-utils/assets/plugins/strider.wasm index c6e8b11b..9ba73f7a 100755 Binary files a/zellij-utils/assets/plugins/strider.wasm and b/zellij-utils/assets/plugins/strider.wasm differ diff --git a/zellij-utils/assets/plugins/tab-bar.wasm b/zellij-utils/assets/plugins/tab-bar.wasm index 562294a7..1b4ff173 100755 Binary files a/zellij-utils/assets/plugins/tab-bar.wasm and b/zellij-utils/assets/plugins/tab-bar.wasm differ diff --git a/zellij-utils/assets/prost/api.plugin_command.rs b/zellij-utils/assets/prost/api.plugin_command.rs index 5127bb81..a352ac98 100644 --- a/zellij-utils/assets/prost/api.plugin_command.rs +++ b/zellij-utils/assets/prost/api.plugin_command.rs @@ -209,12 +209,16 @@ pub struct UnsubscribePayload { pub struct OpenFilePayload { #[prost(message, optional, tag = "1")] pub file_to_open: ::core::option::Option, + #[prost(message, optional, tag = "2")] + pub floating_pane_coordinates: ::core::option::Option, } #[allow(clippy::derive_partial_eq_without_eq)] #[derive(Clone, PartialEq, ::prost::Message)] pub struct OpenCommandPanePayload { #[prost(message, optional, tag = "1")] pub command_to_run: ::core::option::Option, + #[prost(message, optional, tag = "2")] + pub floating_pane_coordinates: ::core::option::Option, } #[allow(clippy::derive_partial_eq_without_eq)] #[derive(Clone, PartialEq, ::prost::Message)] @@ -303,6 +307,26 @@ pub struct IdAndNewName { #[prost(string, tag = "2")] pub new_name: ::prost::alloc::string::String, } +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct FloatingPaneCoordinates { + #[prost(message, optional, tag = "1")] + pub x: ::core::option::Option, + #[prost(message, optional, tag = "2")] + pub y: ::core::option::Option, + #[prost(message, optional, tag = "3")] + pub width: ::core::option::Option, + #[prost(message, optional, tag = "4")] + pub height: ::core::option::Option, +} +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct FixedOrPercentValue { + #[prost(enumeration = "FixedOrPercent", tag = "1")] + pub r#type: i32, + #[prost(uint32, tag = "2")] + pub value: u32, +} #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord, ::prost::Enumeration)] #[repr(i32)] pub enum CommandName { @@ -627,3 +651,29 @@ impl HttpVerb { } } } +#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord, ::prost::Enumeration)] +#[repr(i32)] +pub enum FixedOrPercent { + Fixed = 0, + Percent = 1, +} +impl FixedOrPercent { + /// String value of the enum field names used in the ProtoBuf definition. + /// + /// The values are not transformed in any way and thus are considered stable + /// (if the ProtoBuf definition does not change) and safe for programmatic use. + pub fn as_str_name(&self) -> &'static str { + match self { + FixedOrPercent::Fixed => "Fixed", + FixedOrPercent::Percent => "Percent", + } + } + /// Creates an enum from field names used in the ProtoBuf definition. + pub fn from_str_name(value: &str) -> ::core::option::Option { + match value { + "Fixed" => Some(Self::Fixed), + "Percent" => Some(Self::Percent), + _ => None, + } + } +} diff --git a/zellij-utils/src/cli.rs b/zellij-utils/src/cli.rs index bf8f8880..595293f4 100644 --- a/zellij-utils/src/cli.rs +++ b/zellij-utils/src/cli.rs @@ -216,6 +216,19 @@ pub enum Sessions { /// Start the command suspended, only running after you first presses ENTER #[clap(short, long, value_parser, default_value("false"), takes_value(false))] start_suspended: bool, + + /// The x coordinates if the pane is floating as a bare integer (eg. 1) or percent (eg. 10%) + #[clap(short, long, requires("floating"))] + x: Option, + /// The y coordinates if the pane is floating as a bare integer (eg. 1) or percent (eg. 10%) + #[clap(short, long, requires("floating"))] + y: Option, + /// The width if the pane is floating as a bare integer (eg. 1) or percent (eg. 10%) + #[clap(long, requires("floating"))] + width: Option, + /// The height if the pane is floating as a bare integer (eg. 1) or percent (eg. 10%) + #[clap(long, requires("floating"))] + height: Option, }, /// Load a plugin #[clap(visible_alias = "r")] @@ -246,6 +259,18 @@ pub enum Sessions { /// Skip the memory and HD cache and force recompile of the plugin (good for development) #[clap(short, long, value_parser, default_value("false"), takes_value(false))] skip_plugin_cache: bool, + /// The x coordinates if the pane is floating as a bare integer (eg. 1) or percent (eg. 10%) + #[clap(short, long, requires("floating"))] + x: Option, + /// The y coordinates if the pane is floating as a bare integer (eg. 1) or percent (eg. 10%) + #[clap(short, long, requires("floating"))] + y: Option, + /// The width if the pane is floating as a bare integer (eg. 1) or percent (eg. 10%) + #[clap(long, requires("floating"))] + width: Option, + /// The height if the pane is floating as a bare integer (eg. 1) or percent (eg. 10%) + #[clap(long, requires("floating"))] + height: Option, }, /// Edit file with default $EDITOR / $VISUAL #[clap(visible_alias = "e")] @@ -279,6 +304,18 @@ pub enum Sessions { /// Change the working directory of the editor #[clap(long, value_parser)] cwd: Option, + /// The x coordinates if the pane is floating as a bare integer (eg. 1) or percent (eg. 10%) + #[clap(short, long, requires("floating"))] + x: Option, + /// The y coordinates if the pane is floating as a bare integer (eg. 1) or percent (eg. 10%) + #[clap(short, long, requires("floating"))] + y: Option, + /// The width if the pane is floating as a bare integer (eg. 1) or percent (eg. 10%) + #[clap(long, requires("floating"))] + width: Option, + /// The height if the pane is floating as a bare integer (eg. 1) or percent (eg. 10%) + #[clap(long, requires("floating"))] + height: Option, }, ConvertConfig { old_config_file: PathBuf, @@ -458,8 +495,20 @@ pub enum CliAction { start_suspended: bool, #[clap(long, value_parser)] configuration: Option, - #[clap(short, long, value_parser)] + #[clap(long, value_parser)] skip_plugin_cache: bool, + /// The x coordinates if the pane is floating as a bare integer (eg. 1) or percent (eg. 10%) + #[clap(short, long, requires("floating"))] + x: Option, + /// The y coordinates if the pane is floating as a bare integer (eg. 1) or percent (eg. 10%) + #[clap(short, long, requires("floating"))] + y: Option, + /// The width if the pane is floating as a bare integer (eg. 1) or percent (eg. 10%) + #[clap(long, requires("floating"))] + width: Option, + /// The height if the pane is floating as a bare integer (eg. 1) or percent (eg. 10%) + #[clap(long, requires("floating"))] + height: Option, }, /// Open the specified file in a new zellij pane with your default EDITOR Edit { @@ -492,6 +541,18 @@ pub enum CliAction { /// Change the working directory of the editor #[clap(long, value_parser)] cwd: Option, + /// The x coordinates if the pane is floating as a bare integer (eg. 1) or percent (eg. 10%) + #[clap(short, long, requires("floating"))] + x: Option, + /// The y coordinates if the pane is floating as a bare integer (eg. 1) or percent (eg. 10%) + #[clap(short, long, requires("floating"))] + y: Option, + /// The width if the pane is floating as a bare integer (eg. 1) or percent (eg. 10%) + #[clap(long, requires("floating"))] + width: Option, + /// The height if the pane is floating as a bare integer (eg. 1) or percent (eg. 10%) + #[clap(long, requires("floating"))] + height: Option, }, /// Switch input mode of all connected clients [locked|pane|tab|resize|move|search|session] SwitchMode { diff --git a/zellij-utils/src/data.rs b/zellij-utils/src/data.rs index d001b75f..7a1f4c52 100644 --- a/zellij-utils/src/data.rs +++ b/zellij-utils/src/data.rs @@ -1,5 +1,6 @@ use crate::input::actions::Action; use crate::input::config::ConversionError; +use crate::input::layout::SplitSize; use clap::ArgEnum; use serde::{Deserialize, Serialize}; use std::collections::{BTreeMap, HashMap, HashSet}; @@ -1166,6 +1167,86 @@ impl PipeMessage { } } +#[derive(Clone, Debug, PartialEq, Eq, Deserialize, Serialize, Default)] +pub struct FloatingPaneCoordinates { + pub x: Option, + pub y: Option, + pub width: Option, + pub height: Option, +} + +impl FloatingPaneCoordinates { + pub fn new( + x: Option, + y: Option, + width: Option, + height: Option, + ) -> Option { + let x = x.and_then(|x| SplitSize::from_str(&x).ok()); + let y = y.and_then(|y| SplitSize::from_str(&y).ok()); + let width = width.and_then(|width| SplitSize::from_str(&width).ok()); + let height = height.and_then(|height| SplitSize::from_str(&height).ok()); + if x.is_none() && y.is_none() && width.is_none() && height.is_none() { + None + } else { + Some(FloatingPaneCoordinates { + x, + y, + width, + height, + }) + } + } + pub fn with_x_fixed(mut self, x: usize) -> Self { + self.x = Some(SplitSize::Fixed(x)); + self + } + pub fn with_x_percent(mut self, x: usize) -> Self { + if x > 100 { + eprintln!("x must be between 0 and 100"); + return self; + } + self.x = Some(SplitSize::Percent(x)); + self + } + pub fn with_y_fixed(mut self, y: usize) -> Self { + self.y = Some(SplitSize::Fixed(y)); + self + } + pub fn with_y_percent(mut self, y: usize) -> Self { + if y > 100 { + eprintln!("y must be between 0 and 100"); + return self; + } + self.y = Some(SplitSize::Percent(y)); + self + } + pub fn with_width_fixed(mut self, width: usize) -> Self { + self.width = Some(SplitSize::Fixed(width)); + self + } + pub fn with_width_percent(mut self, width: usize) -> Self { + if width > 100 { + eprintln!("width must be between 0 and 100"); + return self; + } + self.width = Some(SplitSize::Percent(width)); + self + } + pub fn with_height_fixed(mut self, height: usize) -> Self { + self.height = Some(SplitSize::Fixed(height)); + self + } + pub fn with_height_percent(mut self, height: usize) -> Self { + if height > 100 { + eprintln!("height must be between 0 and 100"); + return self; + } + self.height = Some(SplitSize::Percent(height)); + self + } +} + #[derive(Debug, Clone, EnumDiscriminants, ToString)] #[strum_discriminants(derive(EnumString, Hash, Serialize, Deserialize))] #[strum_discriminants(name(CommandType))] @@ -1176,11 +1257,11 @@ pub enum PluginCommand { GetPluginIds, GetZellijVersion, OpenFile(FileToOpen), - OpenFileFloating(FileToOpen), - OpenTerminal(FileToOpen), // only used for the path as cwd - OpenTerminalFloating(FileToOpen), // only used for the path as cwd + OpenFileFloating(FileToOpen, Option), + OpenTerminal(FileToOpen), // only used for the path as cwd + OpenTerminalFloating(FileToOpen, Option), // only used for the path as cwd OpenCommandPane(CommandToRun), - OpenCommandPaneFloating(CommandToRun), + OpenCommandPaneFloating(CommandToRun, Option), SwitchTabTo(u32), // tab index SetTimeout(f64), // seconds ExecCmd(Vec), diff --git a/zellij-utils/src/input/actions.rs b/zellij-utils/src/input/actions.rs index 7ec50879..bb97a6eb 100644 --- a/zellij-utils/src/input/actions.rs +++ b/zellij-utils/src/input/actions.rs @@ -6,8 +6,8 @@ use super::layout::{ TiledPaneLayout, }; use crate::cli::CliAction; -use crate::data::InputMode; use crate::data::{Direction, Resize}; +use crate::data::{FloatingPaneCoordinates, InputMode}; use crate::home::{find_default_config_dir, get_layout_dir}; use crate::input::config::{Config, ConfigError, KdlError}; use crate::input::options::OnForceClose; @@ -166,9 +166,14 @@ pub enum Action { Option, bool, bool, + Option, ), // usize is an optional line number, Option is an optional cwd, bool is floating true/false, second bool is in_place /// Open a new floating pane - NewFloatingPane(Option, Option), // String is an optional pane name + NewFloatingPane( + Option, + Option, + Option, + ), // String is an optional pane name /// Open a new tiled (embedded, non-floating) pane NewTiledPane(Option, Option, Option), // String is an /// Open a new pane in place of the focused one, suppressing it instead @@ -242,7 +247,13 @@ pub enum Action { /// Open a new tiled (embedded, non-floating) plugin pane NewTiledPluginPane(RunPlugin, Option, bool, Option), // String is an optional name, bool is // skip_cache, Option is cwd - NewFloatingPluginPane(RunPlugin, Option, bool, Option), // String is an optional name, bool is + NewFloatingPluginPane( + RunPlugin, + Option, + bool, + Option, + Option, + ), // String is an optional name, bool is // skip_cache, Option is cwd NewInPlacePluginPane(RunPlugin, Option, bool), // String is an optional name, bool is // skip_cache @@ -330,6 +341,10 @@ impl Action { start_suspended, configuration, skip_plugin_cache, + x, + y, + width, + height, } => { let current_dir = get_current_dir(); let cwd = cwd @@ -350,6 +365,7 @@ impl Action { name, skip_plugin_cache, cwd, + FloatingPaneCoordinates::new(x, y, width, height), )]) } else if in_place { Ok(vec![Action::NewInPlacePluginPane( @@ -390,6 +406,7 @@ impl Action { Ok(vec![Action::NewFloatingPane( Some(run_command_action), name, + FloatingPaneCoordinates::new(x, y, width, height), )]) } else if in_place { Ok(vec![Action::NewInPlacePane(Some(run_command_action), name)]) @@ -402,7 +419,11 @@ impl Action { } } else { if floating { - Ok(vec![Action::NewFloatingPane(None, name)]) + Ok(vec![Action::NewFloatingPane( + None, + name, + FloatingPaneCoordinates::new(x, y, width, height), + )]) } else if in_place { Ok(vec![Action::NewInPlacePane(None, name)]) } else { @@ -417,6 +438,10 @@ impl Action { floating, in_place, cwd, + x, + y, + width, + height, } => { let mut file = file; let current_dir = get_current_dir(); @@ -435,6 +460,7 @@ impl Action { direction, floating, in_place, + FloatingPaneCoordinates::new(x, y, width, height), )]) }, CliAction::SwitchMode { input_mode } => { diff --git a/zellij-utils/src/input/layout.rs b/zellij-utils/src/input/layout.rs index 7f65d605..3dfadb40 100644 --- a/zellij-utils/src/input/layout.rs +++ b/zellij-utils/src/input/layout.rs @@ -69,6 +69,17 @@ pub enum SplitSize { Fixed(usize), // An absolute number of columns or rows } +impl SplitSize { + pub fn to_fixed(&self, full_size: usize) -> usize { + match self { + SplitSize::Percent(percent) => { + ((*percent as f64 / 100.0) * full_size as f64).floor() as usize + }, + SplitSize::Fixed(fixed) => *fixed, + } + } +} + #[derive(Debug, Serialize, Deserialize, Clone, PartialEq, Eq)] pub enum Run { #[serde(rename = "plugin")] diff --git a/zellij-utils/src/kdl/mod.rs b/zellij-utils/src/kdl/mod.rs index 95d52007..36d05aff 100644 --- a/zellij-utils/src/kdl/mod.rs +++ b/zellij-utils/src/kdl/mod.rs @@ -1,7 +1,7 @@ mod kdl_layout_parser; use crate::data::{ - Direction, InputMode, Key, LayoutInfo, Palette, PaletteColor, PaneInfo, PaneManifest, - PermissionType, Resize, SessionInfo, TabInfo, + Direction, FloatingPaneCoordinates, InputMode, Key, LayoutInfo, Palette, PaletteColor, + PaneInfo, PaneManifest, PermissionType, Resize, SessionInfo, TabInfo, }; use crate::envs::EnvironmentVariables; use crate::home::{find_default_config_dir, get_layout_dir}; @@ -904,8 +904,24 @@ impl TryFrom<(&KdlNode, &Options)> for Action { hold_on_close, hold_on_start, }; + let x = command_metadata + .and_then(|c_m| kdl_child_string_value_for_entry(c_m, "x")) + .map(|s| s.to_owned()); + let y = command_metadata + .and_then(|c_m| kdl_child_string_value_for_entry(c_m, "y")) + .map(|s| s.to_owned()); + let width = command_metadata + .and_then(|c_m| kdl_child_string_value_for_entry(c_m, "width")) + .map(|s| s.to_owned()); + let height = command_metadata + .and_then(|c_m| kdl_child_string_value_for_entry(c_m, "height")) + .map(|s| s.to_owned()); if floating { - Ok(Action::NewFloatingPane(Some(run_command_action), name)) + Ok(Action::NewFloatingPane( + Some(run_command_action), + name, + FloatingPaneCoordinates::new(x, y, width, height), + )) } else if in_place { Ok(Action::NewInPlacePane(Some(run_command_action), name)) } else { diff --git a/zellij-utils/src/pane_size.rs b/zellij-utils/src/pane_size.rs index c3c74748..16c111b2 100644 --- a/zellij-utils/src/pane_size.rs +++ b/zellij-utils/src/pane_size.rs @@ -4,7 +4,8 @@ use std::{ hash::{Hash, Hasher}, }; -use crate::input::layout::SplitDirection; +use crate::data::FloatingPaneCoordinates; +use crate::input::layout::{SplitDirection, SplitSize}; use crate::position::Position; /// Contains the position and size of a [`Pane`], or more generally of any terminal, measured @@ -130,6 +131,18 @@ impl Dimension { pub fn is_percent(&self) -> bool { matches!(self.constraint, Constraint::Percent(_)) } + pub fn from_split_size(split_size: SplitSize, full_size: usize) -> Self { + match split_size { + SplitSize::Fixed(fixed) => Dimension { + constraint: Constraint::Fixed(fixed), + inner: fixed, + }, + SplitSize::Percent(percent) => Dimension { + constraint: Constraint::Percent(percent as f64), + inner: ((percent as f64 / 100.0) * full_size as f64).floor() as usize, + }, + } + } } #[derive(Clone, Copy, PartialEq, Debug, Serialize, Deserialize)] @@ -181,6 +194,42 @@ impl PaneGeom { SplitDirection::Horizontal => self.rows.is_percent(), } } + pub fn adjust_coordinates( + &mut self, + floating_pane_coordinates: FloatingPaneCoordinates, + viewport: Viewport, + ) { + if let Some(x) = floating_pane_coordinates.x { + self.x = x.to_fixed(viewport.cols); + } + if let Some(y) = floating_pane_coordinates.y { + self.y = y.to_fixed(viewport.rows); + } + if let Some(height) = floating_pane_coordinates.height { + self.rows = Dimension::from_split_size(height, viewport.rows); + } + if let Some(width) = floating_pane_coordinates.width { + self.cols = Dimension::from_split_size(width, viewport.cols); + } + if self.x < viewport.x { + self.x = viewport.x; + } else if self.x > viewport.x + viewport.cols { + self.x = (viewport.x + viewport.cols).saturating_sub(self.cols.as_usize()); + } + if self.y < viewport.y { + self.y = viewport.y; + } else if self.y > viewport.y + viewport.rows { + self.y = (viewport.y + viewport.rows).saturating_sub(self.rows.as_usize()); + } + if self.x + self.cols.as_usize() > viewport.x + viewport.cols { + let new_cols = (viewport.x + viewport.cols).saturating_sub(self.x); + self.cols.set_inner(new_cols); + } + if self.y + self.rows.as_usize() > viewport.y + viewport.rows { + let new_rows = (viewport.y + viewport.rows).saturating_sub(self.y); + self.rows.set_inner(new_rows); + } + } } impl Display for PaneGeom { diff --git a/zellij-utils/src/plugin_api/action.rs b/zellij-utils/src/plugin_api/action.rs index e97c2433..be54e617 100644 --- a/zellij-utils/src/plugin_api/action.rs +++ b/zellij-utils/src/plugin_api/action.rs @@ -240,6 +240,7 @@ impl TryFrom for Action { direction, should_float, should_be_in_place, + None, )) }, _ => Err("Wrong payload for Action::NewPane"), @@ -249,9 +250,13 @@ impl TryFrom for Action { if let Some(payload) = payload.command { let pane_name = payload.pane_name.clone(); let run_command_action: RunCommandAction = payload.try_into()?; - Ok(Action::NewFloatingPane(Some(run_command_action), pane_name)) + Ok(Action::NewFloatingPane( + Some(run_command_action), + pane_name, + None, + )) } else { - Ok(Action::NewFloatingPane(None, None)) + Ok(Action::NewFloatingPane(None, None, None)) } }, _ => Err("Wrong payload for Action::NewFloatingPane"), @@ -573,6 +578,7 @@ impl TryFrom for Action { pane_name, skip_plugin_cache, None, + None, )) }, _ => Err("Wrong payload for Action::MiddleClick"), @@ -874,6 +880,7 @@ impl TryFrom for ProtobufAction { direction, should_float, _should_be_in_place, + _floating_pane_coordinates, ) => { let file_to_edit = path_to_file.display().to_string(); let cwd = cwd.map(|cwd| cwd.display().to_string()); @@ -892,7 +899,7 @@ impl TryFrom for ProtobufAction { })), }) }, - Action::NewFloatingPane(run_command_action, pane_name) => { + Action::NewFloatingPane(run_command_action, pane_name, _coordinates) => { let command = run_command_action.and_then(|r| { let mut protobuf_run_command_action: ProtobufRunCommandAction = r.try_into().ok()?; @@ -1046,7 +1053,7 @@ impl TryFrom for ProtobufAction { should_float, should_open_in_place, skip_plugin_cache, - cwd, + _cwd, ) => { let url: Url = Url::from(&run_plugin.location); Ok(ProtobufAction { @@ -1154,7 +1161,13 @@ impl TryFrom for ProtobufAction { )), }) }, - Action::NewFloatingPluginPane(run_plugin, pane_name, skip_plugin_cache, _cwd) => { + Action::NewFloatingPluginPane( + run_plugin, + pane_name, + skip_plugin_cache, + _cwd, + _coordinates, + ) => { let plugin_url: Url = Url::from(&run_plugin.location); Ok(ProtobufAction { name: ProtobufActionName::NewFloatingPluginPane as i32, diff --git a/zellij-utils/src/plugin_api/plugin_command.proto b/zellij-utils/src/plugin_api/plugin_command.proto index b02dd73f..725714f0 100644 --- a/zellij-utils/src/plugin_api/plugin_command.proto +++ b/zellij-utils/src/plugin_api/plugin_command.proto @@ -209,10 +209,12 @@ message UnsubscribePayload { message OpenFilePayload { file.File file_to_open = 1; + optional FloatingPaneCoordinates floating_pane_coordinates = 2; } message OpenCommandPanePayload { command.Command command_to_run = 1; + optional FloatingPaneCoordinates floating_pane_coordinates = 2; } message SwitchTabToPayload { @@ -275,3 +277,20 @@ message IdAndNewName { uint32 id = 1; // pane id or tab index string new_name = 2; } + +message FloatingPaneCoordinates { + optional FixedOrPercentValue x = 1; + optional FixedOrPercentValue y = 2; + optional FixedOrPercentValue width = 3; + optional FixedOrPercentValue height = 4; +} + +message FixedOrPercentValue { + FixedOrPercent type = 1; + uint32 value = 2; +} + +enum FixedOrPercent { + Fixed = 0; + Percent = 1; +} diff --git a/zellij-utils/src/plugin_api/plugin_command.rs b/zellij-utils/src/plugin_api/plugin_command.rs index a5272d42..e2fce1d0 100644 --- a/zellij-utils/src/plugin_api/plugin_command.rs +++ b/zellij-utils/src/plugin_api/plugin_command.rs @@ -4,10 +4,13 @@ pub use super::generated_api::api::{ input_mode::InputMode as ProtobufInputMode, plugin_command::{ plugin_command::Payload, CliPipeOutputPayload, CommandName, ContextItem, EnvVariable, - ExecCmdPayload, HttpVerb as ProtobufHttpVerb, IdAndNewName, KillSessionsPayload, - MessageToPluginPayload, MovePayload, NewPluginArgs as ProtobufNewPluginArgs, - OpenCommandPanePayload, OpenFilePayload, PaneId as ProtobufPaneId, - PaneType as ProtobufPaneType, PluginCommand as ProtobufPluginCommand, PluginMessagePayload, + ExecCmdPayload, FixedOrPercent as ProtobufFixedOrPercent, + FixedOrPercentValue as ProtobufFixedOrPercentValue, + FloatingPaneCoordinates as ProtobufFloatingPaneCoordinates, HttpVerb as ProtobufHttpVerb, + IdAndNewName, KillSessionsPayload, MessageToPluginPayload, MovePayload, + NewPluginArgs as ProtobufNewPluginArgs, OpenCommandPanePayload, OpenFilePayload, + PaneId as ProtobufPaneId, PaneType as ProtobufPaneType, + PluginCommand as ProtobufPluginCommand, PluginMessagePayload, RequestPluginPermissionPayload, ResizePayload, RunCommandPayload, SetTimeoutPayload, SubscribePayload, SwitchSessionPayload, SwitchTabToPayload, UnsubscribePayload, WebRequestPayload, @@ -17,14 +20,113 @@ pub use super::generated_api::api::{ }; use crate::data::{ - ConnectToSession, HttpVerb, MessageToPlugin, NewPluginArgs, PaneId, PermissionType, - PluginCommand, + ConnectToSession, FloatingPaneCoordinates, HttpVerb, MessageToPlugin, NewPluginArgs, PaneId, + PermissionType, PluginCommand, }; +use crate::input::layout::SplitSize; use std::collections::BTreeMap; use std::convert::TryFrom; use std::path::PathBuf; +impl Into for ProtobufFloatingPaneCoordinates { + fn into(self) -> FloatingPaneCoordinates { + FloatingPaneCoordinates { + x: self + .x + .and_then(|x| match ProtobufFixedOrPercent::from_i32(x.r#type) { + Some(ProtobufFixedOrPercent::Percent) => { + Some(SplitSize::Percent(x.value as usize)) + }, + Some(ProtobufFixedOrPercent::Fixed) => Some(SplitSize::Fixed(x.value as usize)), + None => None, + }), + y: self + .y + .and_then(|y| match ProtobufFixedOrPercent::from_i32(y.r#type) { + Some(ProtobufFixedOrPercent::Percent) => { + Some(SplitSize::Percent(y.value as usize)) + }, + Some(ProtobufFixedOrPercent::Fixed) => Some(SplitSize::Fixed(y.value as usize)), + None => None, + }), + width: self.width.and_then(|width| { + match ProtobufFixedOrPercent::from_i32(width.r#type) { + Some(ProtobufFixedOrPercent::Percent) => { + Some(SplitSize::Percent(width.value as usize)) + }, + Some(ProtobufFixedOrPercent::Fixed) => { + Some(SplitSize::Fixed(width.value as usize)) + }, + None => None, + } + }), + height: self.height.and_then(|height| { + match ProtobufFixedOrPercent::from_i32(height.r#type) { + Some(ProtobufFixedOrPercent::Percent) => { + Some(SplitSize::Percent(height.value as usize)) + }, + Some(ProtobufFixedOrPercent::Fixed) => { + Some(SplitSize::Fixed(height.value as usize)) + }, + None => None, + } + }), + } + } +} + +impl Into for FloatingPaneCoordinates { + fn into(self) -> ProtobufFloatingPaneCoordinates { + ProtobufFloatingPaneCoordinates { + x: match self.x { + Some(SplitSize::Percent(percent)) => Some(ProtobufFixedOrPercentValue { + r#type: ProtobufFixedOrPercent::Percent as i32, + value: percent as u32, + }), + Some(SplitSize::Fixed(fixed)) => Some(ProtobufFixedOrPercentValue { + r#type: ProtobufFixedOrPercent::Fixed as i32, + value: fixed as u32, + }), + None => None, + }, + y: match self.y { + Some(SplitSize::Percent(percent)) => Some(ProtobufFixedOrPercentValue { + r#type: ProtobufFixedOrPercent::Percent as i32, + value: percent as u32, + }), + Some(SplitSize::Fixed(fixed)) => Some(ProtobufFixedOrPercentValue { + r#type: ProtobufFixedOrPercent::Fixed as i32, + value: fixed as u32, + }), + None => None, + }, + width: match self.width { + Some(SplitSize::Percent(percent)) => Some(ProtobufFixedOrPercentValue { + r#type: ProtobufFixedOrPercent::Percent as i32, + value: percent as u32, + }), + Some(SplitSize::Fixed(fixed)) => Some(ProtobufFixedOrPercentValue { + r#type: ProtobufFixedOrPercent::Fixed as i32, + value: fixed as u32, + }), + None => None, + }, + height: match self.height { + Some(SplitSize::Percent(percent)) => Some(ProtobufFixedOrPercentValue { + r#type: ProtobufFixedOrPercent::Percent as i32, + value: percent as u32, + }), + Some(SplitSize::Fixed(fixed)) => Some(ProtobufFixedOrPercentValue { + r#type: ProtobufFixedOrPercent::Fixed as i32, + value: fixed as u32, + }), + None => None, + }, + } + } +} + impl Into for ProtobufHttpVerb { fn into(self) -> HttpVerb { match self { @@ -133,10 +235,14 @@ impl TryFrom for PluginCommand { }, Some(CommandName::OpenFileFloating) => match protobuf_plugin_command.payload { Some(Payload::OpenFileFloatingPayload(file_to_open_payload)) => { + let floating_pane_coordinates = file_to_open_payload + .floating_pane_coordinates + .map(|f| f.into()); match file_to_open_payload.file_to_open { - Some(file_to_open) => { - Ok(PluginCommand::OpenFileFloating(file_to_open.try_into()?)) - }, + Some(file_to_open) => Ok(PluginCommand::OpenFileFloating( + file_to_open.try_into()?, + floating_pane_coordinates, + )), None => Err("Malformed open file payload"), } }, @@ -155,9 +261,13 @@ impl TryFrom for PluginCommand { }, Some(CommandName::OpenTerminalFloating) => match protobuf_plugin_command.payload { Some(Payload::OpenTerminalFloatingPayload(file_to_open_payload)) => { + let floating_pane_coordinates = file_to_open_payload + .floating_pane_coordinates + .map(|f| f.into()); match file_to_open_payload.file_to_open { Some(file_to_open) => Ok(PluginCommand::OpenTerminalFloating( file_to_open.try_into()?, + floating_pane_coordinates, )), None => Err("Malformed open terminal floating payload"), } @@ -177,9 +287,13 @@ impl TryFrom for PluginCommand { }, Some(CommandName::OpenCommandPaneFloating) => match protobuf_plugin_command.payload { Some(Payload::OpenCommandPaneFloatingPayload(command_to_run_payload)) => { + let floating_pane_coordinates = command_to_run_payload + .floating_pane_coordinates + .map(|f| f.into()); match command_to_run_payload.command_to_run { Some(command_to_run) => Ok(PluginCommand::OpenCommandPaneFloating( command_to_run.try_into()?, + floating_pane_coordinates, )), None => Err("Malformed open command pane floating payload"), } @@ -783,40 +897,52 @@ impl TryFrom for ProtobufPluginCommand { name: CommandName::OpenFile as i32, payload: Some(Payload::OpenFilePayload(OpenFilePayload { file_to_open: Some(file_to_open.try_into()?), + floating_pane_coordinates: None, })), }), - PluginCommand::OpenFileFloating(file_to_open) => Ok(ProtobufPluginCommand { - name: CommandName::OpenFileFloating as i32, - payload: Some(Payload::OpenFileFloatingPayload(OpenFilePayload { - file_to_open: Some(file_to_open.try_into()?), - })), - }), + PluginCommand::OpenFileFloating(file_to_open, floating_pane_coordinates) => { + Ok(ProtobufPluginCommand { + name: CommandName::OpenFileFloating as i32, + payload: Some(Payload::OpenFileFloatingPayload(OpenFilePayload { + file_to_open: Some(file_to_open.try_into()?), + floating_pane_coordinates: floating_pane_coordinates.map(|f| f.into()), + })), + }) + }, PluginCommand::OpenTerminal(cwd) => Ok(ProtobufPluginCommand { name: CommandName::OpenTerminal as i32, payload: Some(Payload::OpenTerminalPayload(OpenFilePayload { file_to_open: Some(cwd.try_into()?), + floating_pane_coordinates: None, })), }), - PluginCommand::OpenTerminalFloating(cwd) => Ok(ProtobufPluginCommand { - name: CommandName::OpenTerminalFloating as i32, - payload: Some(Payload::OpenTerminalFloatingPayload(OpenFilePayload { - file_to_open: Some(cwd.try_into()?), - })), - }), + PluginCommand::OpenTerminalFloating(cwd, floating_pane_coordinates) => { + Ok(ProtobufPluginCommand { + name: CommandName::OpenTerminalFloating as i32, + payload: Some(Payload::OpenTerminalFloatingPayload(OpenFilePayload { + file_to_open: Some(cwd.try_into()?), + floating_pane_coordinates: floating_pane_coordinates.map(|f| f.into()), + })), + }) + }, PluginCommand::OpenCommandPane(command_to_run) => Ok(ProtobufPluginCommand { name: CommandName::OpenCommandPane as i32, payload: Some(Payload::OpenCommandPanePayload(OpenCommandPanePayload { command_to_run: Some(command_to_run.try_into()?), + floating_pane_coordinates: None, })), }), - PluginCommand::OpenCommandPaneFloating(command_to_run) => Ok(ProtobufPluginCommand { - name: CommandName::OpenCommandPaneFloating as i32, - payload: Some(Payload::OpenCommandPaneFloatingPayload( - OpenCommandPanePayload { - command_to_run: Some(command_to_run.try_into()?), - }, - )), - }), + PluginCommand::OpenCommandPaneFloating(command_to_run, floating_pane_coordinates) => { + Ok(ProtobufPluginCommand { + name: CommandName::OpenCommandPaneFloating as i32, + payload: Some(Payload::OpenCommandPaneFloatingPayload( + OpenCommandPanePayload { + command_to_run: Some(command_to_run.try_into()?), + floating_pane_coordinates: floating_pane_coordinates.map(|f| f.into()), + }, + )), + }) + }, PluginCommand::SwitchTabTo(tab_index) => Ok(ProtobufPluginCommand { name: CommandName::SwitchTabTo as i32, payload: Some(Payload::SwitchTabToPayload(SwitchTabToPayload { @@ -1100,12 +1226,14 @@ impl TryFrom for ProtobufPluginCommand { name: CommandName::OpenTerminalInPlace as i32, payload: Some(Payload::OpenTerminalInPlacePayload(OpenFilePayload { file_to_open: Some(cwd.try_into()?), + floating_pane_coordinates: None, })), }), PluginCommand::OpenFileInPlace(file_to_open) => Ok(ProtobufPluginCommand { name: CommandName::OpenFileInPlace as i32, payload: Some(Payload::OpenFileInPlacePayload(OpenFilePayload { file_to_open: Some(file_to_open.try_into()?), + floating_pane_coordinates: None, })), }), PluginCommand::OpenCommandPaneInPlace(command_to_run) => Ok(ProtobufPluginCommand { @@ -1113,6 +1241,7 @@ impl TryFrom for ProtobufPluginCommand { payload: Some(Payload::OpenCommandPaneInPlacePayload( OpenCommandPanePayload { command_to_run: Some(command_to_run.try_into()?), + floating_pane_coordinates: None, }, )), }),