diff options
| author | a-kenji <aks.kenji@protonmail.com> | 2021-05-10 20:54:39 +0200 |
|---|---|---|
| committer | a-kenji <aks.kenji@protonmail.com> | 2021-05-10 20:54:39 +0200 |
| commit | 85a4e476f2011dc0491a15bcce3b0052ebb15adb (patch) | |
| tree | eb5d120250c5c3b0d74314a42129a857bf6b1afe /src/common/screen.rs | |
| parent | fixup! Add Option for Simplified Layout (diff) | |
| parent | Merge pull request #480 from a-kenji/dump-config-exit (diff) | |
| download | sl0ppij-85a4e476f2011dc0491a15bcce3b0052ebb15adb.tar.gz sl0ppij-85a4e476f2011dc0491a15bcce3b0052ebb15adb.tar.xz sl0ppij-85a4e476f2011dc0491a15bcce3b0052ebb15adb.zip | |
fixup! Merge branch 'main' of https://github.com/zellij-org/zellij into simple-font-ui
Diffstat (limited to 'src/common/screen.rs')
| -rw-r--r-- | src/common/screen.rs | 344 |
1 files changed, 301 insertions, 43 deletions
diff --git a/src/common/screen.rs b/src/common/screen.rs index 62d87b51..82f63537 100644 --- a/src/common/screen.rs +++ b/src/common/screen.rs @@ -3,18 +3,20 @@ use std::collections::BTreeMap; use std::os::unix::io::RawFd; use std::str; -use std::sync::mpsc::Receiver; -use crate::common::SenderWithContext; -use crate::os_input_output::ServerOsApi; +use crate::common::pty::{PtyInstruction, VteBytes}; +use crate::common::thread_bus::Bus; +use crate::common::input::options::Options; +use crate::cli::ConfigCli; +use crate::errors::{ContextType, ScreenContext}; +use crate::layout::Layout; +use crate::panes::PaneId; use crate::panes::PositionAndSize; -use crate::pty_bus::{PtyInstruction, VteBytes}; use crate::server::ServerInstruction; use crate::tab::Tab; -use crate::{errors::ErrorContext, wasm_vm::PluginInstruction}; -use crate::{layout::Layout, panes::PaneId}; +use crate::wasm_vm::PluginInstruction; -use zellij_tile::data::{Event, InputMode, ModeInfo, Palette, TabInfo}; +use zellij_tile::data::{Event, InputMode, ModeInfo, Palette, TabInfo, PluginCapabilities}; /// Instructions that can be sent to the [`Screen`]. #[derive(Debug, Clone)] @@ -33,9 +35,11 @@ pub enum ScreenInstruction { FocusNextPane, FocusPreviousPane, MoveFocusLeft, + MoveFocusLeftOrPreviousTab, MoveFocusDown, MoveFocusUp, MoveFocusRight, + MoveFocusRightOrNextTab, Exit, ScrollUp, ScrollDown, @@ -63,55 +67,37 @@ pub enum ScreenInstruction { /// A [`Screen`] holds multiple [`Tab`]s, each one holding multiple [`panes`](crate::client::panes). /// It only directly controls which tab is active, delegating the rest to the individual `Tab`. pub struct Screen { - /// A [`ScreenInstruction`] and [`ErrorContext`] receiver. - pub receiver: Receiver<(ScreenInstruction, ErrorContext)>, + /// A Bus for sending and receiving messages with the other threads. + pub bus: Bus<ScreenInstruction>, /// An optional maximal amount of panes allowed per [`Tab`] in this [`Screen`] instance. max_panes: Option<usize>, /// A map between this [`Screen`]'s tabs and their ID/key. tabs: BTreeMap<usize, Tab>, - /// A [`PluginInstruction`] and [`ErrorContext`] sender. - pub send_plugin_instructions: SenderWithContext<PluginInstruction>, - /// An [`PtyInstruction`] and [`ErrorContext`] sender. - pub send_pty_instructions: SenderWithContext<PtyInstruction>, - /// An [`ServerInstruction`] and [`ErrorContext`] sender. - pub send_server_instructions: SenderWithContext<ServerInstruction>, /// The full size of this [`Screen`]. full_screen_ws: PositionAndSize, /// The index of this [`Screen`]'s active [`Tab`]. active_tab_index: Option<usize>, - /// The [`ServerOsApi`] this [`Screen`] uses. - os_api: Box<dyn ServerOsApi>, mode_info: ModeInfo, input_mode: InputMode, colors: Palette, } impl Screen { - // FIXME: This lint needs actual fixing! Maybe by bundling the Senders /// Creates and returns a new [`Screen`]. - #[allow(clippy::too_many_arguments)] pub fn new( - receive_screen_instructions: Receiver<(ScreenInstruction, ErrorContext)>, - send_plugin_instructions: SenderWithContext<PluginInstruction>, - send_pty_instructions: SenderWithContext<PtyInstruction>, - send_server_instructions: SenderWithContext<ServerInstruction>, + bus: Bus<ScreenInstruction>, full_screen_ws: &PositionAndSize, - os_api: Box<dyn ServerOsApi>, max_panes: Option<usize>, mode_info: ModeInfo, input_mode: InputMode, colors: Palette, ) -> Self { Screen { - receiver: receive_screen_instructions, + bus, max_panes, - send_plugin_instructions, - send_pty_instructions, - send_server_instructions, full_screen_ws: *full_screen_ws, active_tab_index: None, tabs: BTreeMap::new(), - os_api, mode_info, input_mode, colors, @@ -128,10 +114,8 @@ impl Screen { position, String::new(), &self.full_screen_ws, - self.os_api.clone(), - self.send_plugin_instructions.clone(), - self.send_pty_instructions.clone(), - self.send_server_instructions.clone(), + self.bus.os_input.as_ref().unwrap().clone(), + self.bus.senders.clone(), self.max_panes, Some(PaneId::Terminal(pane_id)), self.mode_info.clone(), @@ -215,13 +199,15 @@ impl Screen { // below we don't check the result of sending the CloseTab instruction to the pty thread // because this might be happening when the app is closing, at which point the pty thread // has already closed and this would result in an error - self.send_pty_instructions - .send(PtyInstruction::CloseTab(pane_ids)) + self.bus + .senders + .send_to_pty(PtyInstruction::CloseTab(pane_ids)) .unwrap(); if self.tabs.is_empty() { self.active_tab_index = None; - self.send_server_instructions - .send(ServerInstruction::Render(None)) + self.bus + .senders + .send_to_server(ServerInstruction::Render(None)) .unwrap(); } else { for t in self.tabs.values_mut() { @@ -284,10 +270,8 @@ impl Screen { position, String::new(), &self.full_screen_ws, - self.os_api.clone(), - self.send_plugin_instructions.clone(), - self.send_pty_instructions.clone(), - self.send_server_instructions.clone(), + self.bus.os_input.as_ref().unwrap().clone(), + self.bus.senders.clone(), self.max_panes, None, self.mode_info.clone(), @@ -311,8 +295,9 @@ impl Screen { is_sync_panes_active: tab.is_sync_panes_active(), }); } - self.send_plugin_instructions - .send(PluginInstruction::Update(None, Event::TabUpdate(tab_data))) + self.bus + .senders + .send_to_plugin(PluginInstruction::Update(None, Event::TabUpdate(tab_data))) .unwrap(); } @@ -340,3 +325,276 @@ impl Screen { } } } + +pub fn screen_thread_main( + bus: Bus<ScreenInstruction>, + max_panes: Option<usize>, + full_screen_ws: PositionAndSize, + options: Option<ConfigCli>, + config_options: Options, +) { + let colors = bus.os_input.as_ref().unwrap().load_palette(); + let capabilities = if let Some(ConfigCli::Options(options)) = options { + options.simplified_ui + } else { + config_options.simplified_ui + }; + let mut screen = Screen::new( + bus, + &full_screen_ws, + max_panes, + ModeInfo { + palette: colors, + capabilities: PluginCapabilities { + arrow_fonts: capabilities, + }, + ..ModeInfo::default() + }, + InputMode::Normal, + colors, + ); + loop { + let (event, mut err_ctx) = screen + .bus + .recv() + .expect("failed to receive event on channel"); + err_ctx.add_call(ContextType::Screen(ScreenContext::from(&event))); + match event { + ScreenInstruction::PtyBytes(pid, vte_bytes) => { + let active_tab = screen.get_active_tab_mut().unwrap(); + if active_tab.has_terminal_pid(pid) { + // it's most likely that this event is directed at the active tab + // look there first + active_tab.handle_pty_bytes(pid, vte_bytes); + } else { + // if this event wasn't directed at the active tab, start looking + // in other tabs + let all_tabs = screen.get_tabs_mut(); + for tab in all_tabs.values_mut() { + if tab.has_terminal_pid(pid) { + tab.handle_pty_bytes(pid, vte_bytes); + break; + } + } + } + } + ScreenInstruction::Render => { + screen.render(); + } + ScreenInstruction::NewPane(pid) => { + screen.get_active_tab_mut().unwrap().new_pane(pid); + screen + .bus + .senders + .send_to_server(ServerInstruction::UnblockInputThread) + .unwrap(); + } + ScreenInstruction::HorizontalSplit(pid) => { + screen.get_active_tab_mut().unwrap().horizontal_split(pid); + screen + .bus + .senders + .send_to_server(ServerInstruction::UnblockInputThread) + .unwrap(); + } + ScreenInstruction::VerticalSplit(pid) => { + screen.get_active_tab_mut().unwrap().vertical_split(pid); + screen + .bus + .senders + .send_to_server(ServerInstruction::UnblockInputThread) + .unwrap(); + } + ScreenInstruction::WriteCharacter(bytes) => { + let active_tab = screen.get_active_tab_mut().unwrap(); + match active_tab.is_sync_panes_active() { + true => active_tab.write_to_terminals_on_current_tab(bytes), + false => active_tab.write_to_active_terminal(bytes), + } + } + ScreenInstruction::ResizeLeft => { + screen.get_active_tab_mut().unwrap().resize_left(); + } + ScreenInstruction::ResizeRight => { + screen.get_active_tab_mut().unwrap().resize_right(); + } + ScreenInstruction::ResizeDown => { + screen.get_active_tab_mut().unwrap().resize_down(); + } + ScreenInstruction::ResizeUp => { + screen.get_active_tab_mut().unwrap().resize_up(); + } + ScreenInstruction::SwitchFocus => { + screen.get_active_tab_mut().unwrap().move_focus(); + } + ScreenInstruction::FocusNextPane => { + screen.get_active_tab_mut().unwrap().focus_next_pane(); + } + ScreenInstruction::FocusPreviousPane => { + screen.get_active_tab_mut().unwrap().focus_previous_pane(); + } + ScreenInstruction::MoveFocusLeft => { + screen.get_active_tab_mut().unwrap().move_focus_left(); + } + ScreenInstruction::MoveFocusLeftOrPreviousTab => { + if !screen.get_active_tab_mut().unwrap().move_focus_left() { + screen.switch_tab_prev(); + } + screen + .bus + .senders + .send_to_server(ServerInstruction::UnblockInputThread) + .unwrap(); + } + ScreenInstruction::MoveFocusDown => { + screen.get_active_tab_mut().unwrap().move_focus_down(); + } + ScreenInstruction::MoveFocusRight => { + screen.get_active_tab_mut().unwrap().move_focus_right(); + } + ScreenInstruction::MoveFocusRightOrNextTab => { + if !screen.get_active_tab_mut().unwrap().move_focus_right() { + screen.switch_tab_next(); + } + screen + .bus + .senders + .send_to_server(ServerInstruction::UnblockInputThread) + .unwrap(); + } + ScreenInstruction::MoveFocusUp => { + screen.get_active_tab_mut().unwrap().move_focus_up(); + } + ScreenInstruction::ScrollUp => { + screen + .get_active_tab_mut() + .unwrap() + .scroll_active_terminal_up(); + } + ScreenInstruction::ScrollDown => { + screen + .get_active_tab_mut() + .unwrap() + .scroll_active_terminal_down(); + } + ScreenInstruction::PageScrollUp => { + screen + .get_active_tab_mut() + .unwrap() + .scroll_active_terminal_up_page(); + } + ScreenInstruction::PageScrollDown => { + screen + .get_active_tab_mut() + .unwrap() + .scroll_active_terminal_down_page(); + } + ScreenInstruction::ClearScroll => { + screen + .get_active_tab_mut() + .unwrap() + .clear_active_terminal_scroll(); + } + ScreenInstruction::CloseFocusedPane => { + screen.get_active_tab_mut().unwrap().close_focused_pane(); + screen.render(); + } + ScreenInstruction::SetSelectable(id, selectable) => { + screen + .get_active_tab_mut() + .unwrap() + .set_pane_selectable(id, selectable); + } + ScreenInstruction::SetMaxHeight(id, max_height) => { + screen + .get_active_tab_mut() + .unwrap() + .set_pane_max_height(id, max_height); + } + ScreenInstruction::SetInvisibleBorders(id, invisible_borders) => { + screen + .get_active_tab_mut() + .unwrap() + .set_pane_invisible_borders(id, invisible_borders); + screen.render(); + } + ScreenInstruction::ClosePane(id) => { + screen.get_active_tab_mut().unwrap().close_pane(id); + screen.render(); + } + ScreenInstruction::ToggleActiveTerminalFullscreen => { + screen + .get_active_tab_mut() + .unwrap() + .toggle_active_pane_fullscreen(); + } + ScreenInstruction::NewTab(pane_id) => { + screen.new_tab(pane_id); + screen + .bus + .senders + .send_to_server(ServerInstruction::UnblockInputThread) + .unwrap(); + } + ScreenInstruction::SwitchTabNext => { + screen.switch_tab_next(); + screen + .bus + .senders + .send_to_server(ServerInstruction::UnblockInputThread) + .unwrap(); + } + ScreenInstruction::SwitchTabPrev => { + screen.switch_tab_prev(); + screen + .bus + .senders + .send_to_server(ServerInstruction::UnblockInputThread) + .unwrap(); + } + ScreenInstruction::CloseTab => { + screen.close_tab(); + screen + .bus + .senders + .send_to_server(ServerInstruction::UnblockInputThread) + .unwrap(); + } + ScreenInstruction::ApplyLayout(layout, new_pane_pids) => { + screen.apply_layout(layout, new_pane_pids); + screen + .bus + .senders + .send_to_server(ServerInstruction::UnblockInputThread) + .unwrap(); + } + ScreenInstruction::GoToTab(tab_index) => { + screen.go_to_tab(tab_index as usize); + screen + .bus + .senders + .send_to_server(ServerInstruction::UnblockInputThread) + .unwrap(); + } + ScreenInstruction::UpdateTabName(c) => { + screen.update_active_tab_name(c); + } + ScreenInstruction::TerminalResize(new_size) => { + screen.resize_to_screen(new_size); + } + ScreenInstruction::ChangeMode(mode_info) => { + screen.change_mode(mode_info); + } + ScreenInstruction::ToggleActiveSyncTab => { + screen + .get_active_tab_mut() + .unwrap() + .toggle_sync_panes_is_active(); + screen.update_tabs(); + } + ScreenInstruction::Exit => { + break; + } + } + } +} |
