From a3f42b19a98c00b90fdd60a0486275a5f1829226 Mon Sep 17 00:00:00 2001 From: Aram Drevekenin Date: Mon, 17 May 2021 18:13:05 +0200 Subject: [PATCH] Osc implementation (#517) * fix(compatibility): implement most osc methods * style(fmt): rustfmt * style(fmt): remove cargo warnings * style(fmt): make clippy happy * style(fmt): fix formatting after my clippy fixes broke it again ;P * fix(grid): fix tests --- Cargo.lock | 110 +++++++++++++- default-plugins/status-bar/src/main.rs | 64 ++++---- default-plugins/tab-bar/src/line.rs | 12 +- default-plugins/tab-bar/src/main.rs | 2 +- default-plugins/tab-bar/src/tab.rs | 8 +- src/tests/fakes.rs | 3 + src/tests/utils.rs | 3 +- zellij-client/Cargo.toml | 1 + zellij-client/src/lib.rs | 9 +- zellij-client/src/os_input_output.rs | 14 ++ zellij-server/src/lib.rs | 13 +- zellij-server/src/panes/grid.rs | 161 ++++++++++++++++++++- zellij-server/src/panes/terminal_pane.rs | 7 +- zellij-server/src/panes/unit/grid_tests.rs | 65 +++++---- zellij-server/src/route.rs | 7 +- zellij-server/src/screen.rs | 24 ++- zellij-server/src/tab.rs | 18 +-- zellij-utils/src/ipc.rs | 11 +- 18 files changed, 419 insertions(+), 113 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index a3037b008a..31c5e7093c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -132,7 +132,7 @@ dependencies = [ "event-listener", "futures-lite", "once_cell", - "signal-hook", + "signal-hook 0.3.8", "winapi", ] @@ -451,6 +451,31 @@ dependencies = [ "lazy_static", ] +[[package]] +name = "crossterm" +version = "0.18.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4e86d73f2a0b407b5768d10a8c720cf5d2df49a9efc10ca09176d201ead4b7fb" +dependencies = [ + "bitflags", + "crossterm_winapi", + "lazy_static", + "libc", + "mio", + "parking_lot", + "signal-hook 0.1.17", + "winapi", +] + +[[package]] +name = "crossterm_winapi" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c2265c3f8e080075d9b6417aa72293fc71662f34b4af2612d8d1b074d29510db" +dependencies = [ + "winapi", +] + [[package]] name = "ctor" version = "0.1.20" @@ -1016,6 +1041,28 @@ dependencies = [ "autocfg", ] +[[package]] +name = "mio" +version = "0.7.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cf80d3e903b34e0bd7282b218398aec54e082c840d9baf8339e0080a0c542956" +dependencies = [ + "libc", + "log", + "miow", + "ntapi", + "winapi", +] + +[[package]] +name = "miow" +version = "0.3.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9f1c5b025cda876f66ef43a113f91ebc9f4ccef34843000e0adf6ebbab84e21" +dependencies = [ + "winapi", +] + [[package]] name = "more-asserts" version = "0.2.1" @@ -1043,6 +1090,15 @@ dependencies = [ "libc", ] +[[package]] +name = "ntapi" +version = "0.3.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f6bb902e437b6d86e03cce10a7e2af662292c5dfef23b65899ea3ac9354ad44" +dependencies = [ + "winapi", +] + [[package]] name = "num_cpus" version = "1.13.0" @@ -1087,6 +1143,31 @@ version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "427c3892f9e783d91cc128285287e70a59e206ca452770ece88a76f7a3eddd72" +[[package]] +name = "parking_lot" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6d7744ac029df22dca6284efe4e898991d28e3085c706c972bcd7da4a27a15eb" +dependencies = [ + "instant", + "lock_api", + "parking_lot_core", +] + +[[package]] +name = "parking_lot_core" +version = "0.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fa7a782938e745763fe6907fc6ba86946d72f49fe7e21de074e08128a99fb018" +dependencies = [ + "cfg-if 1.0.0", + "instant", + "libc", + "redox_syscall", + "smallvec", + "winapi", +] + [[package]] name = "pin-project-lite" version = "0.2.6" @@ -1430,6 +1511,17 @@ dependencies = [ "yaml-rust", ] +[[package]] +name = "signal-hook" +version = "0.1.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7e31d442c16f047a671b5a71e2161d6e68814012b7f5379d269ebd915fac2729" +dependencies = [ + "libc", + "mio", + "signal-hook-registry", +] + [[package]] name = "signal-hook" version = "0.3.8" @@ -1615,6 +1707,17 @@ dependencies = [ "winapi", ] +[[package]] +name = "termbg" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "133c09f40b7a6a10616bb46d2b7d78d50cb8c6c475c84f3c02fe261957d9e0e0" +dependencies = [ + "crossterm", + "thiserror", + "winapi", +] + [[package]] name = "terminal_size" version = "0.1.16" @@ -2204,7 +2307,8 @@ dependencies = [ "interprocess", "libc", "nix", - "signal-hook", + "signal-hook 0.3.8", + "termbg", "termion", "zellij-tile", "zellij-utils", @@ -2224,7 +2328,7 @@ dependencies = [ "serde", "serde_json", "serde_yaml", - "signal-hook", + "signal-hook 0.3.8", "termion", "unicode-width", "vte 0.10.1", diff --git a/default-plugins/status-bar/src/main.rs b/default-plugins/status-bar/src/main.rs index bb56c279a9..cf9445d6ae 100644 --- a/default-plugins/status-bar/src/main.rs +++ b/default-plugins/status-bar/src/main.rs @@ -72,55 +72,61 @@ pub struct ColoredElements { // that can be defined in the config perhaps fn color_elements(palette: Palette) -> ColoredElements { match palette.source { + // "cyan" here is used as a background as a dirty hack + // this is because the Palette struct doesn't have a "gray" section + // and we can't use its "bg" because that is now dynamically taken from the terminal + // and might often not actually fit the rest of the colorscheme + // + // to fix this, we need to restructure the Palette struct PaletteSource::Default => ColoredElements { - selected_prefix_separator: style!(palette.bg, palette.green), + selected_prefix_separator: style!(palette.cyan, palette.green), selected_char_left_separator: style!(palette.black, palette.green).bold(), selected_char_shortcut: style!(palette.red, palette.green).bold(), selected_char_right_separator: style!(palette.black, palette.green).bold(), selected_styled_text: style!(palette.black, palette.green).bold(), - selected_suffix_separator: style!(palette.green, palette.bg).bold(), - unselected_prefix_separator: style!(palette.bg, palette.fg), + selected_suffix_separator: style!(palette.green, palette.cyan).bold(), + unselected_prefix_separator: style!(palette.cyan, palette.fg), unselected_char_left_separator: style!(palette.black, palette.fg).bold(), unselected_char_shortcut: style!(palette.red, palette.fg).bold(), unselected_char_right_separator: style!(palette.black, palette.fg).bold(), unselected_styled_text: style!(palette.black, palette.fg).bold(), - unselected_suffix_separator: style!(palette.fg, palette.bg), - disabled_prefix_separator: style!(palette.bg, palette.fg), - disabled_styled_text: style!(palette.bg, palette.fg).dimmed(), - disabled_suffix_separator: style!(palette.fg, palette.bg), - selected_single_letter_prefix_separator: style!(palette.bg, palette.green), + unselected_suffix_separator: style!(palette.fg, palette.cyan), + disabled_prefix_separator: style!(palette.cyan, palette.fg), + disabled_styled_text: style!(palette.cyan, palette.fg).dimmed(), + disabled_suffix_separator: style!(palette.fg, palette.cyan), + selected_single_letter_prefix_separator: style!(palette.cyan, palette.green), selected_single_letter_char_shortcut: style!(palette.red, palette.green).bold(), - selected_single_letter_suffix_separator: style!(palette.green, palette.bg), - unselected_single_letter_prefix_separator: style!(palette.bg, palette.fg), + selected_single_letter_suffix_separator: style!(palette.green, palette.cyan), + unselected_single_letter_prefix_separator: style!(palette.cyan, palette.fg), unselected_single_letter_char_shortcut: style!(palette.red, palette.fg).bold(), - unselected_single_letter_suffix_separator: style!(palette.fg, palette.bg), - superkey_prefix: style!(palette.white, palette.bg).bold(), - superkey_suffix_separator: style!(palette.bg, palette.bg), + unselected_single_letter_suffix_separator: style!(palette.fg, palette.cyan), + superkey_prefix: style!(palette.white, palette.cyan).bold(), + superkey_suffix_separator: style!(palette.cyan, palette.cyan), }, PaletteSource::Xresources => ColoredElements { - selected_prefix_separator: style!(palette.bg, palette.green), + selected_prefix_separator: style!(palette.cyan, palette.green), selected_char_left_separator: style!(palette.fg, palette.green).bold(), selected_char_shortcut: style!(palette.red, palette.green).bold(), selected_char_right_separator: style!(palette.fg, palette.green).bold(), - selected_styled_text: style!(palette.bg, palette.green).bold(), - selected_suffix_separator: style!(palette.green, palette.bg).bold(), - unselected_prefix_separator: style!(palette.bg, palette.fg), - unselected_char_left_separator: style!(palette.bg, palette.fg).bold(), + selected_styled_text: style!(palette.cyan, palette.green).bold(), + selected_suffix_separator: style!(palette.green, palette.cyan).bold(), + unselected_prefix_separator: style!(palette.cyan, palette.fg), + unselected_char_left_separator: style!(palette.cyan, palette.fg).bold(), unselected_char_shortcut: style!(palette.red, palette.fg).bold(), - unselected_char_right_separator: style!(palette.bg, palette.fg).bold(), - unselected_styled_text: style!(palette.bg, palette.fg).bold(), - unselected_suffix_separator: style!(palette.fg, palette.bg), - disabled_prefix_separator: style!(palette.bg, palette.fg), - disabled_styled_text: style!(palette.bg, palette.fg).dimmed(), - disabled_suffix_separator: style!(palette.fg, palette.bg), + unselected_char_right_separator: style!(palette.cyan, palette.fg).bold(), + unselected_styled_text: style!(palette.cyan, palette.fg).bold(), + unselected_suffix_separator: style!(palette.fg, palette.cyan), + disabled_prefix_separator: style!(palette.cyan, palette.fg), + disabled_styled_text: style!(palette.cyan, palette.fg).dimmed(), + disabled_suffix_separator: style!(palette.fg, palette.cyan), selected_single_letter_prefix_separator: style!(palette.fg, palette.green), selected_single_letter_char_shortcut: style!(palette.red, palette.green).bold(), selected_single_letter_suffix_separator: style!(palette.green, palette.fg), - unselected_single_letter_prefix_separator: style!(palette.fg, palette.bg), + unselected_single_letter_prefix_separator: style!(palette.fg, palette.cyan), unselected_single_letter_char_shortcut: style!(palette.red, palette.fg).bold(), - unselected_single_letter_suffix_separator: style!(palette.fg, palette.bg), - superkey_prefix: style!(palette.bg, palette.fg).bold(), - superkey_suffix_separator: style!(palette.fg, palette.bg), + unselected_single_letter_suffix_separator: style!(palette.fg, palette.cyan), + superkey_prefix: style!(palette.cyan, palette.fg).bold(), + superkey_suffix_separator: style!(palette.fg, palette.cyan), }, } } @@ -155,7 +161,7 @@ impl ZellijPlugin for State { // [48;5;238m is gray background, [0K is so that it fills the rest of the line // [m is background reset, [0K is so that it clears the rest of the line - match self.mode_info.palette.bg { + match self.mode_info.palette.cyan { PaletteColor::Rgb((r, g, b)) => { println!("{}\u{1b}[48;2;{};{};{}m\u{1b}[0K", first_line, r, g, b); } diff --git a/default-plugins/tab-bar/src/line.rs b/default-plugins/tab-bar/src/line.rs index 574edb78d7..fce8982dad 100644 --- a/default-plugins/tab-bar/src/line.rs +++ b/default-plugins/tab-bar/src/line.rs @@ -62,11 +62,11 @@ fn left_more_message(tab_count_to_the_left: usize, palette: Palette, separator: }; // 238 let more_text_len = more_text.chars().count() + 2; // 2 for the arrows - let left_separator = style!(palette.bg, palette.orange).paint(separator); + let left_separator = style!(palette.cyan, palette.orange).paint(separator); let more_styled_text = style!(palette.black, palette.orange) .bold() .paint(more_text); - let right_separator = style!(palette.orange, palette.bg).paint(separator); + let right_separator = style!(palette.orange, palette.cyan).paint(separator); let more_styled_text = format!( "{}", ANSIStrings(&[left_separator, more_styled_text, right_separator,]) @@ -94,11 +94,11 @@ fn right_more_message( " +many → ".to_string() }; let more_text_len = more_text.chars().count() + 1; // 2 for the arrow - let left_separator = style!(palette.bg, palette.orange).paint(separator); + let left_separator = style!(palette.cyan, palette.orange).paint(separator); let more_styled_text = style!(palette.black, palette.orange) .bold() .paint(more_text); - let right_separator = style!(palette.orange, palette.bg).paint(separator); + let right_separator = style!(palette.orange, palette.cyan).paint(separator); let more_styled_text = format!( "{}", ANSIStrings(&[left_separator, more_styled_text, right_separator,]) @@ -147,7 +147,9 @@ fn add_next_tabs_msg( fn tab_line_prefix(palette: Palette) -> LinePart { let prefix_text = " Zellij ".to_string(); let prefix_text_len = prefix_text.chars().count(); - let prefix_styled_text = style!(palette.white, palette.bg).bold().paint(prefix_text); + let prefix_styled_text = style!(palette.white, palette.cyan) + .bold() + .paint(prefix_text); LinePart { part: format!("{}", prefix_styled_text), len: prefix_text_len, diff --git a/default-plugins/tab-bar/src/main.rs b/default-plugins/tab-bar/src/main.rs index 00ff4bd967..46336be3da 100644 --- a/default-plugins/tab-bar/src/main.rs +++ b/default-plugins/tab-bar/src/main.rs @@ -75,7 +75,7 @@ impl ZellijPlugin for State { for bar_part in tab_line { s = format!("{}{}", s, bar_part.part); } - match self.mode_info.palette.bg { + match self.mode_info.palette.cyan { PaletteColor::Rgb((r, g, b)) => { println!("{}\u{1b}[48;2;{};{};{}m\u{1b}[0K", s, r, g, b); } diff --git a/default-plugins/tab-bar/src/tab.rs b/default-plugins/tab-bar/src/tab.rs index 85e2c378d3..fb8e377d12 100644 --- a/default-plugins/tab-bar/src/tab.rs +++ b/default-plugins/tab-bar/src/tab.rs @@ -4,12 +4,12 @@ use zellij_tile::prelude::*; use zellij_tile_utils::style; pub fn active_tab(text: String, palette: Palette, separator: &str) -> LinePart { - let left_separator = style!(palette.bg, palette.green).paint(separator); + let left_separator = style!(palette.cyan, palette.green).paint(separator); let tab_text_len = text.chars().count() + 4; // 2 for left and right separators, 2 for the text padding let tab_styled_text = style!(palette.black, palette.green) .bold() .paint(format!(" {} ", text)); - let right_separator = style!(palette.green, palette.bg).paint(separator); + let right_separator = style!(palette.green, palette.cyan).paint(separator); let tab_styled_text = format!( "{}", ANSIStrings(&[left_separator, tab_styled_text, right_separator,]) @@ -21,12 +21,12 @@ pub fn active_tab(text: String, palette: Palette, separator: &str) -> LinePart { } pub fn non_active_tab(text: String, palette: Palette, separator: &str) -> LinePart { - let left_separator = style!(palette.bg, palette.fg).paint(separator); + let left_separator = style!(palette.cyan, palette.fg).paint(separator); let tab_text_len = text.chars().count() + 4; // 2 for left and right separators, 2 for the padding let tab_styled_text = style!(palette.black, palette.fg) .bold() .paint(format!(" {} ", text)); - let right_separator = style!(palette.fg, palette.bg).paint(separator); + let right_separator = style!(palette.fg, palette.cyan).paint(separator); let tab_styled_text = format!( "{}", ANSIStrings(&[left_separator, tab_styled_text, right_separator,]) diff --git a/src/tests/fakes.rs b/src/tests/fakes.rs index 3fefa663a7..09cc2ba3d5 100644 --- a/src/tests/fakes.rs +++ b/src/tests/fakes.rs @@ -219,6 +219,9 @@ impl ClientOsApi for FakeInputOutput { } } fn connect_to_server(&self, _path: &std::path::Path) {} + fn load_palette(&self) -> Palette { + default_palette() + } } impl ServerOsApi for FakeInputOutput { diff --git a/src/tests/utils.rs b/src/tests/utils.rs index ee2de3cd8d..441f9bcea6 100644 --- a/src/tests/utils.rs +++ b/src/tests/utils.rs @@ -1,4 +1,5 @@ use zellij_server::{panes::TerminalPane, tab::Pane}; +use zellij_tile::data::Palette; use zellij_utils::pane_size::PositionAndSize; pub fn get_output_frame_snapshots( @@ -7,7 +8,7 @@ pub fn get_output_frame_snapshots( ) -> Vec { let mut vte_parser = vte::Parser::new(); let main_pid = 0; - let mut terminal_output = TerminalPane::new(main_pid, *win_size); + let mut terminal_output = TerminalPane::new(main_pid, *win_size, Palette::default()); let mut snapshots = vec![]; for frame in output_frames.iter() { diff --git a/zellij-client/Cargo.toml b/zellij-client/Cargo.toml index f5e668c776..5d7efdddc2 100644 --- a/zellij-client/Cargo.toml +++ b/zellij-client/Cargo.toml @@ -16,6 +16,7 @@ signal-hook = "0.3" nix = "0.19.1" interprocess = "1.1.1" libc = "0.2" +termbg = "0.2.0" [features] test = ["zellij-utils/test"] diff --git a/zellij-client/src/lib.rs b/zellij-client/src/lib.rs index 8ffcf72be0..9a1a706a9e 100644 --- a/zellij-client/src/lib.rs +++ b/zellij-client/src/lib.rs @@ -21,7 +21,7 @@ use zellij_utils::{ errors::{ClientContext, ContextType, ErrorInstruction}, input::config::Config, input::options::Options, - ipc::{ClientToServerMsg, ServerToClientMsg}, + ipc::{ClientAttributes, ClientToServerMsg, ServerToClientMsg}, }; /// Instructions related to the client-side application @@ -85,6 +85,7 @@ pub fn start_client(mut os_input: Box, opts: CliArgs, config: C let take_snapshot = "\u{1b}[?1049h"; let bracketed_paste = "\u{1b}[?2004h"; os_input.unset_raw_mode(0); + let palette = os_input.load_palette(); let _ = os_input .get_stdout_writer() .write(take_snapshot.as_bytes()) @@ -103,9 +104,13 @@ pub fn start_client(mut os_input: Box, opts: CliArgs, config: C let config_options = Options::from_cli(&config.options, opts.option.clone()); let full_screen_ws = os_input.get_terminal_size_using_fd(0); + let client_attributes = ClientAttributes { + position_and_size: full_screen_ws, + palette, + }; os_input.connect_to_server(&*ZELLIJ_IPC_PIPE); os_input.send_to_server(ClientToServerMsg::NewClient( - full_screen_ws, + client_attributes, opts, config_options, )); diff --git a/zellij-client/src/os_input_output.rs b/zellij-client/src/os_input_output.rs index 680561a863..02a516e8a4 100644 --- a/zellij-client/src/os_input_output.rs +++ b/zellij-client/src/os_input_output.rs @@ -7,11 +7,13 @@ use std::io::prelude::*; use std::os::unix::io::RawFd; use std::path::Path; use std::sync::{Arc, Mutex}; +use zellij_tile::data::{Palette, PaletteColor}; use zellij_utils::errors::ErrorContext; use zellij_utils::ipc::{ ClientToServerMsg, IpcReceiverWithContext, IpcSenderWithContext, ServerToClientMsg, }; use zellij_utils::pane_size::PositionAndSize; +use zellij_utils::shared::default_palette; fn into_raw_mode(pid: RawFd) { let mut tio = termios::tcgetattr(pid).expect("could not get terminal attribute"); @@ -77,6 +79,7 @@ pub trait ClientOsApi: Send + Sync { fn handle_signals(&self, sigwinch_cb: Box, quit_cb: Box); /// Establish a connection with the server socket. fn connect_to_server(&self, path: &Path); + fn load_palette(&self) -> Palette; } impl ClientOsApi for ClientOsInputOutput { @@ -155,6 +158,17 @@ impl ClientOsApi for ClientOsInputOutput { *self.send_instructions_to_server.lock().unwrap() = Some(sender); *self.receive_instructions_from_server.lock().unwrap() = Some(receiver); } + fn load_palette(&self) -> Palette { + let timeout = std::time::Duration::from_millis(100); + let mut palette = default_palette(); + if let Ok(rgb) = termbg::rgb(timeout) { + palette.bg = PaletteColor::Rgb((rgb.r as u8, rgb.g as u8, rgb.b as u8)); + // TODO: also dynamically get all other colors from the user's terminal + // this should be done in the same method (OSC ]11), but there might be other + // considerations here, hence using the library + }; + palette + } } impl Clone for Box { diff --git a/zellij-server/src/lib.rs b/zellij-server/src/lib.rs index 7e883ddc76..6fa87e4813 100644 --- a/zellij-server/src/lib.rs +++ b/zellij-server/src/lib.rs @@ -29,15 +29,14 @@ use zellij_utils::{ cli::CliArgs, errors::{ContextType, ErrorInstruction, ServerContext}, input::options::Options, - ipc::{ClientToServerMsg, ServerToClientMsg}, - pane_size::PositionAndSize, + ipc::{ClientAttributes, ClientToServerMsg, ServerToClientMsg}, setup::{get_default_data_dir, install::populate_data_dir}, }; /// Instructions related to server-side application #[derive(Debug, Clone)] pub(crate) enum ServerInstruction { - NewClient(PositionAndSize, CliArgs, Options), + NewClient(ClientAttributes, CliArgs, Options), Render(Option), UnblockInputThread, ClientExit, @@ -173,13 +172,13 @@ pub fn start_server(os_input: Box, socket_path: PathBuf) { let (instruction, mut err_ctx) = server_receiver.recv().unwrap(); err_ctx.add_call(ContextType::IPCServer((&instruction).into())); match instruction { - ServerInstruction::NewClient(full_screen_ws, opts, config_options) => { + ServerInstruction::NewClient(client_attributes, opts, config_options) => { let session_data = init_session( os_input.clone(), opts, config_options, to_server.clone(), - full_screen_ws, + client_attributes, ); *sessions.write().unwrap() = Some(session_data); sessions @@ -217,7 +216,7 @@ fn init_session( opts: CliArgs, config_options: Options, to_server: SenderWithContext, - full_screen_ws: PositionAndSize, + client_attributes: ClientAttributes, ) -> SessionMetaData { let (to_screen, screen_receiver): ChannelWithContext = mpsc::channel(); let to_screen = SenderWithContext::new(SenderType::Sender(to_screen)); @@ -280,7 +279,7 @@ fn init_session( let max_panes = opts.max_panes; move || { - screen_thread_main(screen_bus, max_panes, full_screen_ws, config_options); + screen_thread_main(screen_bus, max_panes, client_attributes, config_options); } }) .unwrap(); diff --git a/zellij-server/src/panes/grid.rs b/zellij-server/src/panes/grid.rs index 83e8c70f6b..d9cef5def8 100644 --- a/zellij-server/src/panes/grid.rs +++ b/zellij-server/src/panes/grid.rs @@ -2,6 +2,7 @@ use std::{ cmp::Ordering, collections::{BTreeSet, VecDeque}, fmt::{self, Debug, Formatter}, + str, }; use vte::{Params, Perform}; @@ -9,6 +10,7 @@ use vte::{Params, Perform}; const TABSTOP_WIDTH: usize = 8; // TODO: is this always right? const SCROLL_BACK: usize = 10_000; +use zellij_tile::data::{Palette, PaletteColor}; use zellij_utils::{consts::VERSION, logging::debug_log_to_file, shared::version_number}; use crate::panes::terminal_character::{ @@ -16,6 +18,26 @@ use crate::panes::terminal_character::{ EMPTY_TERMINAL_CHARACTER, }; +// this was copied verbatim from alacritty +fn parse_number(input: &[u8]) -> Option { + if input.is_empty() { + return None; + } + let mut num: u8 = 0; + for c in input { + let c = *c as char; + if let Some(digit) = c.to_digit(10) { + num = match num.checked_mul(10).and_then(|v| v.checked_add(digit as u8)) { + Some(v) => v, + None => return None, + } + } else { + return None; + } + } + Some(num) +} + fn get_top_non_canonical_rows(rows: &mut Vec) -> Vec { let mut index_of_last_non_canonical_row = None; for (i, row) in rows.iter().enumerate() { @@ -178,6 +200,7 @@ pub struct Grid { scroll_region: Option<(usize, usize)>, active_charset: CharsetIndex, preceding_char: Option, + colors: Palette, pub should_render: bool, pub cursor_key_mode: bool, // DECCKM - when set, cursor keys should send ANSI direction codes (eg. "OD") instead of the arrow keys (eg. "") pub erasure_mode: bool, // ERM @@ -203,7 +226,7 @@ impl Debug for Grid { } impl Grid { - pub fn new(rows: usize, columns: usize) -> Self { + pub fn new(rows: usize, columns: usize, colors: Palette) -> Self { Grid { lines_above: VecDeque::with_capacity(SCROLL_BACK), viewport: vec![Row::new().canonical()], @@ -224,6 +247,7 @@ impl Grid { clear_viewport_before_rendering: false, active_charset: Default::default(), pending_messages_to_pty: vec![], + colors, } } pub fn contains_widechar(&self) -> bool { @@ -1011,8 +1035,139 @@ impl Perform for Grid { // TBD } - fn osc_dispatch(&mut self, _params: &[&[u8]], _bell_terminated: bool) { - // TBD + fn osc_dispatch(&mut self, params: &[&[u8]], bell_terminated: bool) { + let terminator = if bell_terminated { "\x07" } else { "\x1b\\" }; + + if params.is_empty() || params[0].is_empty() { + return; + } + + match params[0] { + // Set window title. + b"0" | b"2" => { + if params.len() >= 2 { + let _title = params[1..] + .iter() + .flat_map(|x| str::from_utf8(x)) + .collect::>() + .join(";") + .trim() + .to_owned(); + // TBD: do something with title? + } + } + + // Set color index. + b"4" => { + // TBD: set color index - currently unsupported + // + // this changes a terminal color index to something else + // meaning anything set to that index will be changed + // during rendering + } + + // Get/set Foreground, Background, Cursor colors. + b"10" | b"11" | b"12" => { + if params.len() >= 2 { + if let Some(mut dynamic_code) = parse_number(params[0]) { + for param in ¶ms[1..] { + // currently only getting the color sequence is supported, + // setting still isn't + if param == b"?" { + let color_response_message = match self.colors.bg { + PaletteColor::Rgb((r, g, b)) => { + format!( + "\u{1b}]{};rgb:{1:02x}{1:02x}/{2:02x}{2:02x}/{3:02x}{3:02x}{4}", + // dynamic_code, color.r, color.g, color.b, terminator + dynamic_code, r, g, b, terminator + ) + } + _ => { + format!( + "\u{1b}]{};rgb:{1:02x}{1:02x}/{2:02x}{2:02x}/{3:02x}{3:02x}{4}", + // dynamic_code, color.r, color.g, color.b, terminator + dynamic_code, 0, 0, 0, terminator + ) + } + }; + self.pending_messages_to_pty + .push(color_response_message.as_bytes().to_vec()); + } + dynamic_code += 1; + } + return; + } + } + } + + // Set cursor style. + b"50" => { + if params.len() >= 2 + && params[1].len() >= 13 + && params[1][0..12] == *b"CursorShape=" + { + let shape = match params[1][12] as char { + '0' => Some(CursorShape::Block), + '1' => Some(CursorShape::Beam), + '2' => Some(CursorShape::Underline), + _ => None, + }; + if let Some(cursor_shape) = shape { + self.cursor.change_shape(cursor_shape); + } + } + } + + // Set clipboard. + b"52" => { + if params.len() < 3 { + return; + } + + let _clipboard = params[1].get(0).unwrap_or(&b'c'); + match params[2] { + b"?" => { + // TBD: paste from own clipboard - currently unsupported + } + _base64 => { + // TBD: copy to own clipboard - currently unsupported + } + } + } + + // Reset color index. + b"104" => { + // Reset all color indexes when no parameters are given. + if params.len() == 1 { + // TBD - reset all color changes - currently unsupported + return; + } + + // Reset color indexes given as parameters. + for param in ¶ms[1..] { + if let Some(_index) = parse_number(param) { + // TBD - reset color index - currently unimplemented + } + } + } + + // Reset foreground color. + b"110" => { + // TBD - reset foreground color - currently unimplemented + } + + // Reset background color. + b"111" => { + // TBD - reset background color - currently unimplemented + } + + // Reset text cursor color. + b"112" => { + // TBD - reset text cursor color - currently unimplemented + } + + _ => {} + } } fn csi_dispatch(&mut self, params: &Params, intermediates: &[u8], _ignore: bool, c: char) { diff --git a/zellij-server/src/panes/terminal_pane.rs b/zellij-server/src/panes/terminal_pane.rs index 25834c35dd..eaeb00264b 100644 --- a/zellij-server/src/panes/terminal_pane.rs +++ b/zellij-server/src/panes/terminal_pane.rs @@ -1,6 +1,7 @@ use std::fmt::Debug; use std::os::unix::io::RawFd; use std::time::Instant; +use zellij_tile::data::Palette; use zellij_utils::pane_size::PositionAndSize; use crate::panes::{ @@ -27,6 +28,7 @@ pub struct TerminalPane { pub max_height: Option, pub max_width: Option, pub active_at: Instant, + pub colors: Palette, vte_parser: vte::Parser, } @@ -285,8 +287,8 @@ impl Pane for TerminalPane { } impl TerminalPane { - pub fn new(pid: RawFd, position_and_size: PositionAndSize) -> TerminalPane { - let grid = Grid::new(position_and_size.rows, position_and_size.columns); + pub fn new(pid: RawFd, position_and_size: PositionAndSize, palette: Palette) -> TerminalPane { + let grid = Grid::new(position_and_size.rows, position_and_size.columns, palette); TerminalPane { pid, grid, @@ -297,6 +299,7 @@ impl TerminalPane { max_width: None, vte_parser: vte::Parser::new(), active_at: Instant::now(), + colors: palette, } } pub fn get_x(&self) -> usize { diff --git a/zellij-server/src/panes/unit/grid_tests.rs b/zellij-server/src/panes/unit/grid_tests.rs index 1cd623b6e0..7612a05d18 100644 --- a/zellij-server/src/panes/unit/grid_tests.rs +++ b/zellij-server/src/panes/unit/grid_tests.rs @@ -1,5 +1,6 @@ use super::super::Grid; use ::insta::assert_snapshot; +use zellij_tile::data::Palette; fn read_fixture(fixture_name: &str) -> Vec { let mut path_to_file = std::path::PathBuf::new(); @@ -15,7 +16,7 @@ fn read_fixture(fixture_name: &str) -> Vec { #[test] fn vttest1_0() { let mut vte_parser = vte::Parser::new(); - let mut grid = Grid::new(41, 110); + let mut grid = Grid::new(41, 110, Palette::default()); let fixture_name = "vttest1-0"; let content = read_fixture(fixture_name); for byte in content { @@ -27,7 +28,7 @@ fn vttest1_0() { #[test] fn vttest1_1() { let mut vte_parser = vte::Parser::new(); - let mut grid = Grid::new(41, 110); + let mut grid = Grid::new(41, 110, Palette::default()); let fixture_name = "vttest1-1"; let content = read_fixture(fixture_name); for byte in content { @@ -39,7 +40,7 @@ fn vttest1_1() { #[test] fn vttest1_2() { let mut vte_parser = vte::Parser::new(); - let mut grid = Grid::new(41, 110); + let mut grid = Grid::new(41, 110, Palette::default()); let fixture_name = "vttest1-2"; let content = read_fixture(fixture_name); for byte in content { @@ -51,7 +52,7 @@ fn vttest1_2() { #[test] fn vttest1_3() { let mut vte_parser = vte::Parser::new(); - let mut grid = Grid::new(41, 110); + let mut grid = Grid::new(41, 110, Palette::default()); let fixture_name = "vttest1-3"; let content = read_fixture(fixture_name); for byte in content { @@ -63,7 +64,7 @@ fn vttest1_3() { #[test] fn vttest1_4() { let mut vte_parser = vte::Parser::new(); - let mut grid = Grid::new(41, 110); + let mut grid = Grid::new(41, 110, Palette::default()); let fixture_name = "vttest1-4"; let content = read_fixture(fixture_name); for byte in content { @@ -75,7 +76,7 @@ fn vttest1_4() { #[test] fn vttest1_5() { let mut vte_parser = vte::Parser::new(); - let mut grid = Grid::new(41, 110); + let mut grid = Grid::new(41, 110, Palette::default()); let fixture_name = "vttest1-5"; let content = read_fixture(fixture_name); for byte in content { @@ -87,7 +88,7 @@ fn vttest1_5() { #[test] fn vttest2_0() { let mut vte_parser = vte::Parser::new(); - let mut grid = Grid::new(41, 110); + let mut grid = Grid::new(41, 110, Palette::default()); let fixture_name = "vttest2-0"; let content = read_fixture(fixture_name); for byte in content { @@ -99,7 +100,7 @@ fn vttest2_0() { #[test] fn vttest2_1() { let mut vte_parser = vte::Parser::new(); - let mut grid = Grid::new(41, 110); + let mut grid = Grid::new(41, 110, Palette::default()); let fixture_name = "vttest2-1"; let content = read_fixture(fixture_name); for byte in content { @@ -111,7 +112,7 @@ fn vttest2_1() { #[test] fn vttest2_2() { let mut vte_parser = vte::Parser::new(); - let mut grid = Grid::new(41, 110); + let mut grid = Grid::new(41, 110, Palette::default()); let fixture_name = "vttest2-2"; let content = read_fixture(fixture_name); for byte in content { @@ -123,7 +124,7 @@ fn vttest2_2() { #[test] fn vttest2_3() { let mut vte_parser = vte::Parser::new(); - let mut grid = Grid::new(41, 110); + let mut grid = Grid::new(41, 110, Palette::default()); let fixture_name = "vttest2-3"; let content = read_fixture(fixture_name); for byte in content { @@ -135,7 +136,7 @@ fn vttest2_3() { #[test] fn vttest2_4() { let mut vte_parser = vte::Parser::new(); - let mut grid = Grid::new(41, 110); + let mut grid = Grid::new(41, 110, Palette::default()); let fixture_name = "vttest2-4"; let content = read_fixture(fixture_name); for byte in content { @@ -147,7 +148,7 @@ fn vttest2_4() { #[test] fn vttest2_5() { let mut vte_parser = vte::Parser::new(); - let mut grid = Grid::new(41, 110); + let mut grid = Grid::new(41, 110, Palette::default()); let fixture_name = "vttest2-5"; let content = read_fixture(fixture_name); for byte in content { @@ -159,7 +160,7 @@ fn vttest2_5() { #[test] fn vttest2_6() { let mut vte_parser = vte::Parser::new(); - let mut grid = Grid::new(41, 110); + let mut grid = Grid::new(41, 110, Palette::default()); let fixture_name = "vttest2-6"; let content = read_fixture(fixture_name); for byte in content { @@ -171,7 +172,7 @@ fn vttest2_6() { #[test] fn vttest2_7() { let mut vte_parser = vte::Parser::new(); - let mut grid = Grid::new(41, 110); + let mut grid = Grid::new(41, 110, Palette::default()); let fixture_name = "vttest2-7"; let content = read_fixture(fixture_name); for byte in content { @@ -183,7 +184,7 @@ fn vttest2_7() { #[test] fn vttest2_8() { let mut vte_parser = vte::Parser::new(); - let mut grid = Grid::new(41, 110); + let mut grid = Grid::new(41, 110, Palette::default()); let fixture_name = "vttest2-8"; let content = read_fixture(fixture_name); for byte in content { @@ -195,7 +196,7 @@ fn vttest2_8() { #[test] fn vttest2_9() { let mut vte_parser = vte::Parser::new(); - let mut grid = Grid::new(41, 110); + let mut grid = Grid::new(41, 110, Palette::default()); let fixture_name = "vttest2-9"; let content = read_fixture(fixture_name); for byte in content { @@ -207,7 +208,7 @@ fn vttest2_9() { #[test] fn vttest2_10() { let mut vte_parser = vte::Parser::new(); - let mut grid = Grid::new(41, 110); + let mut grid = Grid::new(41, 110, Palette::default()); let fixture_name = "vttest2-10"; let content = read_fixture(fixture_name); for byte in content { @@ -219,7 +220,7 @@ fn vttest2_10() { #[test] fn vttest2_11() { let mut vte_parser = vte::Parser::new(); - let mut grid = Grid::new(41, 110); + let mut grid = Grid::new(41, 110, Palette::default()); let fixture_name = "vttest2-11"; let content = read_fixture(fixture_name); for byte in content { @@ -231,7 +232,7 @@ fn vttest2_11() { #[test] fn vttest2_12() { let mut vte_parser = vte::Parser::new(); - let mut grid = Grid::new(41, 110); + let mut grid = Grid::new(41, 110, Palette::default()); let fixture_name = "vttest2-12"; let content = read_fixture(fixture_name); for byte in content { @@ -243,7 +244,7 @@ fn vttest2_12() { #[test] fn vttest2_13() { let mut vte_parser = vte::Parser::new(); - let mut grid = Grid::new(41, 110); + let mut grid = Grid::new(41, 110, Palette::default()); let fixture_name = "vttest2-13"; let content = read_fixture(fixture_name); for byte in content { @@ -255,7 +256,7 @@ fn vttest2_13() { #[test] fn vttest2_14() { let mut vte_parser = vte::Parser::new(); - let mut grid = Grid::new(41, 110); + let mut grid = Grid::new(41, 110, Palette::default()); let fixture_name = "vttest2-14"; let content = read_fixture(fixture_name); for byte in content { @@ -267,7 +268,7 @@ fn vttest2_14() { #[test] fn vttest3_0() { let mut vte_parser = vte::Parser::new(); - let mut grid = Grid::new(41, 110); + let mut grid = Grid::new(41, 110, Palette::default()); let fixture_name = "vttest3-0"; let content = read_fixture(fixture_name); for byte in content { @@ -279,7 +280,7 @@ fn vttest3_0() { #[test] fn vttest8_0() { let mut vte_parser = vte::Parser::new(); - let mut grid = Grid::new(51, 97); + let mut grid = Grid::new(51, 97, Palette::default()); let fixture_name = "vttest8-0"; let content = read_fixture(fixture_name); for byte in content { @@ -291,7 +292,7 @@ fn vttest8_0() { #[test] fn vttest8_1() { let mut vte_parser = vte::Parser::new(); - let mut grid = Grid::new(51, 97); + let mut grid = Grid::new(51, 97, Palette::default()); let fixture_name = "vttest8-1"; let content = read_fixture(fixture_name); for byte in content { @@ -303,7 +304,7 @@ fn vttest8_1() { #[test] fn vttest8_2() { let mut vte_parser = vte::Parser::new(); - let mut grid = Grid::new(51, 97); + let mut grid = Grid::new(51, 97, Palette::default()); let fixture_name = "vttest8-2"; let content = read_fixture(fixture_name); for byte in content { @@ -315,7 +316,7 @@ fn vttest8_2() { #[test] fn vttest8_3() { let mut vte_parser = vte::Parser::new(); - let mut grid = Grid::new(51, 97); + let mut grid = Grid::new(51, 97, Palette::default()); let fixture_name = "vttest8-3"; let content = read_fixture(fixture_name); for byte in content { @@ -327,7 +328,7 @@ fn vttest8_3() { #[test] fn vttest8_4() { let mut vte_parser = vte::Parser::new(); - let mut grid = Grid::new(51, 97); + let mut grid = Grid::new(51, 97, Palette::default()); let fixture_name = "vttest8-4"; let content = read_fixture(fixture_name); for byte in content { @@ -339,7 +340,7 @@ fn vttest8_4() { #[test] fn vttest8_5() { let mut vte_parser = vte::Parser::new(); - let mut grid = Grid::new(51, 97); + let mut grid = Grid::new(51, 97, Palette::default()); let fixture_name = "vttest8-5"; let content = read_fixture(fixture_name); for byte in content { @@ -351,7 +352,7 @@ fn vttest8_5() { #[test] fn csi_b() { let mut vte_parser = vte::Parser::new(); - let mut grid = Grid::new(51, 97); + let mut grid = Grid::new(51, 97, Palette::default()); let fixture_name = "csi-b"; let content = read_fixture(fixture_name); for byte in content { @@ -363,7 +364,7 @@ fn csi_b() { #[test] fn csi_capital_i() { let mut vte_parser = vte::Parser::new(); - let mut grid = Grid::new(51, 97); + let mut grid = Grid::new(51, 97, Palette::default()); let fixture_name = "csi-capital-i"; let content = read_fixture(fixture_name); for byte in content { @@ -375,7 +376,7 @@ fn csi_capital_i() { #[test] fn csi_capital_z() { let mut vte_parser = vte::Parser::new(); - let mut grid = Grid::new(51, 97); + let mut grid = Grid::new(51, 97, Palette::default()); let fixture_name = "csi-capital-z"; let content = read_fixture(fixture_name); for byte in content { @@ -387,7 +388,7 @@ fn csi_capital_z() { #[test] fn terminal_reports() { let mut vte_parser = vte::Parser::new(); - let mut grid = Grid::new(51, 97); + let mut grid = Grid::new(51, 97, Palette::default()); let fixture_name = "terminal_reports"; let content = read_fixture(fixture_name); for byte in content { diff --git a/zellij-server/src/route.rs b/zellij-server/src/route.rs index 1d25ae77c4..e8ff337626 100644 --- a/zellij-server/src/route.rs +++ b/zellij-server/src/route.rs @@ -29,6 +29,9 @@ fn route_action(action: Action, session: &SessionMetaData, os_input: &dyn Server } Action::SwitchToMode(mode) => { let palette = os_input.load_palette(); + // TODO: use the palette from the client and remove it from the server os api + // this is left here as a stop gap measure until we shift some code around + // to allow for this session .senders .send_to_plugin(PluginInstruction::Update( @@ -199,7 +202,9 @@ pub(crate) fn route_thread_main( break; } ClientToServerMsg::Action(action) => { - route_action(action, rlocked_sessions.as_ref().unwrap(), &*os_input); + if let Some(rlocked_sessions) = rlocked_sessions.as_ref() { + route_action(action, rlocked_sessions, &*os_input); + } } ClientToServerMsg::TerminalResize(new_size) => { rlocked_sessions diff --git a/zellij-server/src/screen.rs b/zellij-server/src/screen.rs index 91619c57ce..178fd58e98 100644 --- a/zellij-server/src/screen.rs +++ b/zellij-server/src/screen.rs @@ -17,6 +17,7 @@ use zellij_tile::data::{Event, InputMode, ModeInfo, Palette, PluginCapabilities, use zellij_utils::{ errors::{ContextType, ScreenContext}, input::options::Options, + ipc::ClientAttributes, pane_size::PositionAndSize, }; @@ -128,7 +129,7 @@ pub(crate) struct Screen { /// A map between this [`Screen`]'s tabs and their ID/key. tabs: BTreeMap, /// The full size of this [`Screen`]. - full_screen_ws: PositionAndSize, + position_and_size: PositionAndSize, /// The index of this [`Screen`]'s active [`Tab`]. active_tab_index: Option, mode_info: ModeInfo, @@ -140,21 +141,20 @@ impl Screen { /// Creates and returns a new [`Screen`]. pub fn new( bus: Bus, - full_screen_ws: &PositionAndSize, + client_attributes: &ClientAttributes, max_panes: Option, mode_info: ModeInfo, input_mode: InputMode, - colors: Palette, ) -> Self { Screen { bus, max_panes, - full_screen_ws: *full_screen_ws, + position_and_size: client_attributes.position_and_size, + colors: client_attributes.palette, active_tab_index: None, tabs: BTreeMap::new(), mode_info, input_mode, - colors, } } @@ -167,7 +167,7 @@ impl Screen { tab_index, position, String::new(), - &self.full_screen_ws, + &self.position_and_size, self.bus.os_input.as_ref().unwrap().clone(), self.bus.senders.clone(), self.max_panes, @@ -274,7 +274,7 @@ impl Screen { } pub fn resize_to_screen(&mut self, new_screen_size: PositionAndSize) { - self.full_screen_ws = new_screen_size; + self.position_and_size = new_screen_size; for (_, tab) in self.tabs.iter_mut() { tab.resize_whole_tab(new_screen_size); } @@ -323,7 +323,7 @@ impl Screen { tab_index, position, String::new(), - &self.full_screen_ws, + &self.position_and_size, self.bus.os_input.as_ref().unwrap().clone(), self.bus.senders.clone(), self.max_panes, @@ -383,25 +383,23 @@ impl Screen { pub(crate) fn screen_thread_main( bus: Bus, max_panes: Option, - full_screen_ws: PositionAndSize, + client_attributes: ClientAttributes, config_options: Options, ) { - let colors = bus.os_input.as_ref().unwrap().load_palette(); let capabilities = config_options.simplified_ui; let mut screen = Screen::new( bus, - &full_screen_ws, + &client_attributes, max_panes, ModeInfo { - palette: colors, + palette: client_attributes.palette, capabilities: PluginCapabilities { arrow_fonts: capabilities, }, ..ModeInfo::default() }, InputMode::Normal, - colors, ); loop { let (event, mut err_ctx) = screen diff --git a/zellij-server/src/tab.rs b/zellij-server/src/tab.rs index e41cb530dd..69de7e861e 100644 --- a/zellij-server/src/tab.rs +++ b/zellij-server/src/tab.rs @@ -241,7 +241,7 @@ impl Tab { colors: Palette, ) -> Self { let panes = if let Some(PaneId::Terminal(pid)) = pane_id { - let new_terminal = TerminalPane::new(pid, *full_screen_ws); + let new_terminal = TerminalPane::new(pid, *full_screen_ws, colors); os_api.set_terminal_size_using_fd( new_terminal.pid, new_terminal.columns() as u16, @@ -343,7 +343,7 @@ impl Tab { } else { // there are still panes left to fill, use the pids we received in this method let pid = new_pids.next().unwrap(); // if this crashes it means we got less pids than there are panes in this layout - let new_terminal = TerminalPane::new(*pid, *position_and_size); + let new_terminal = TerminalPane::new(*pid, *position_and_size, self.colors); self.os_api.set_terminal_size_using_fd( new_terminal.pid, new_terminal.columns() as u16, @@ -371,7 +371,7 @@ impl Tab { } if !self.has_panes() { if let PaneId::Terminal(term_pid) = pid { - let new_terminal = TerminalPane::new(term_pid, self.full_screen_ws); + let new_terminal = TerminalPane::new(term_pid, self.full_screen_ws, self.colors); self.os_api.set_terminal_size_using_fd( new_terminal.pid, new_terminal.columns() as u16, @@ -421,7 +421,7 @@ impl Tab { { if let PaneId::Terminal(term_pid) = pid { let (top_winsize, bottom_winsize) = split_horizontally_with_gap(&terminal_ws); - let new_terminal = TerminalPane::new(term_pid, bottom_winsize); + let new_terminal = TerminalPane::new(term_pid, bottom_winsize, self.colors); self.os_api.set_terminal_size_using_fd( new_terminal.pid, bottom_winsize.columns as u16, @@ -441,7 +441,7 @@ impl Tab { } else if terminal_to_split.columns() > terminal_to_split.min_width() * 2 { if let PaneId::Terminal(term_pid) = pid { let (left_winsize, right_winsize) = split_vertically_with_gap(&terminal_ws); - let new_terminal = TerminalPane::new(term_pid, right_winsize); + let new_terminal = TerminalPane::new(term_pid, right_winsize, self.colors); self.os_api.set_terminal_size_using_fd( new_terminal.pid, right_winsize.columns as u16, @@ -469,7 +469,7 @@ impl Tab { } if !self.has_panes() { if let PaneId::Terminal(term_pid) = pid { - let new_terminal = TerminalPane::new(term_pid, self.full_screen_ws); + let new_terminal = TerminalPane::new(term_pid, self.full_screen_ws, self.colors); self.os_api.set_terminal_size_using_fd( new_terminal.pid, new_terminal.columns() as u16, @@ -499,7 +499,7 @@ impl Tab { active_pane.change_pos_and_size(&top_winsize); - let new_terminal = TerminalPane::new(term_pid, bottom_winsize); + let new_terminal = TerminalPane::new(term_pid, bottom_winsize, self.colors); self.os_api.set_terminal_size_using_fd( new_terminal.pid, bottom_winsize.columns as u16, @@ -526,7 +526,7 @@ impl Tab { } if !self.has_panes() { if let PaneId::Terminal(term_pid) = pid { - let new_terminal = TerminalPane::new(term_pid, self.full_screen_ws); + let new_terminal = TerminalPane::new(term_pid, self.full_screen_ws, self.colors); self.os_api.set_terminal_size_using_fd( new_terminal.pid, new_terminal.columns() as u16, @@ -556,7 +556,7 @@ impl Tab { active_pane.change_pos_and_size(&left_winsize); - let new_terminal = TerminalPane::new(term_pid, right_winsize); + let new_terminal = TerminalPane::new(term_pid, right_winsize, self.colors); self.os_api.set_terminal_size_using_fd( new_terminal.pid, right_winsize.columns as u16, diff --git a/zellij-utils/src/ipc.rs b/zellij-utils/src/ipc.rs index 6d36481c62..b7215f69ef 100644 --- a/zellij-utils/src/ipc.rs +++ b/zellij-utils/src/ipc.rs @@ -13,6 +13,8 @@ use std::io::{self, Write}; use std::marker::PhantomData; use std::os::unix::io::{AsRawFd, FromRawFd}; +use zellij_tile::data::Palette; + type SessionId = u64; #[derive(PartialEq, Eq, Serialize, Deserialize, Hash)] @@ -32,7 +34,14 @@ pub enum ClientType { Writer, } +#[derive(Serialize, Deserialize, Debug, Clone)] +pub struct ClientAttributes { + pub position_and_size: PositionAndSize, + pub palette: Palette, +} + // Types of messages sent from the client to the server +#[allow(clippy::large_enum_variant)] #[derive(Serialize, Deserialize, Debug, Clone)] pub enum ClientToServerMsg { /*// List which sessions are available @@ -47,7 +56,7 @@ pub enum ClientToServerMsg { DisconnectFromSession,*/ ClientExit, TerminalResize(PositionAndSize), - NewClient(PositionAndSize, CliArgs, Options), + NewClient(ClientAttributes, CliArgs, Options), Action(Action), }