Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Float Pane #5576

Draft
wants to merge 22 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from 15 commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions codec/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -502,6 +502,7 @@ pdu! {
GetPaneDirection: 60,
GetPaneDirectionResponse: 61,
AdjustPaneSize: 62,
FloatPane: 63,
}

impl Pdu {
Expand Down Expand Up @@ -649,6 +650,14 @@ pub struct ListPanesResponse {
pub window_titles: HashMap<WindowId, String>,
}

#[derive(Deserialize, Serialize, PartialEq, Debug)]
pub struct FloatPane {
pub pane_id: PaneId,
pub command: Option<CommandBuilder>,
pub command_dir: Option<String>,
pub domain: config::keyassignment::SpawnTabDomain,
}

#[derive(Deserialize, Serialize, PartialEq, Debug)]
pub struct SplitPane {
pub pane_id: PaneId,
Expand Down
32 changes: 32 additions & 0 deletions config/src/color.rs
Original file line number Diff line number Diff line change
Expand Up @@ -598,6 +598,23 @@ pub struct WindowFrameConfig {
pub border_bottom_color: Option<RgbaColor>,
}

#[derive(Debug, Clone, FromDynamic, ToDynamic)]
pub struct FloatBorderConfig {
#[dynamic(try_from = "crate::units::PixelUnit", default = "default_zero_pixel")]
pub left_width: Dimension,
#[dynamic(try_from = "crate::units::PixelUnit", default = "default_zero_pixel")]
pub right_width: Dimension,
#[dynamic(try_from = "crate::units::PixelUnit", default = "default_zero_pixel")]
pub top_height: Dimension,
#[dynamic(try_from = "crate::units::PixelUnit", default = "default_zero_pixel")]
pub bottom_height: Dimension,

pub left_color: Option<RgbaColor>,
pub right_color: Option<RgbaColor>,
pub top_color: Option<RgbaColor>,
pub bottom_color: Option<RgbaColor>,
}

const fn default_zero_pixel() -> Dimension {
Dimension::Pixels(0.)
}
Expand Down Expand Up @@ -629,6 +646,21 @@ impl Default for WindowFrameConfig {
}
}

impl Default for FloatBorderConfig {
fn default() -> Self {
Self {
left_width: default_zero_pixel(),
right_width: default_zero_pixel(),
top_height: default_zero_pixel(),
bottom_height: default_zero_pixel(),
left_color: None,
right_color: None,
top_color: None,
bottom_color: None,
}
}
}

fn default_inactive_titlebar_bg() -> RgbaColor {
RgbColor::new_8bpc(0x33, 0x33, 0x33).into()
}
Expand Down
17 changes: 16 additions & 1 deletion config/src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ use crate::{
default_true, default_win32_acrylic_accent_color, GpuInfo, IntegratedTitleButtonColor,
KeyMapPreference, LoadedConfig, MouseEventTriggerMods, RgbaColor, SerialDomain, SystemBackdrop,
WebGpuPowerPreference, CONFIG_DIRS, CONFIG_FILE_OVERRIDE, CONFIG_OVERRIDES, CONFIG_SKIP,
HOME_DIR,
HOME_DIR,FloatBorderConfig
};
use anyhow::Context;
use luahelper::impl_lua_conversion_dynamic;
Expand Down Expand Up @@ -142,6 +142,9 @@ pub struct Config {
#[dynamic(default)]
pub window_frame: WindowFrameConfig,

#[dynamic(default)]
pub float_pane_border: FloatBorderConfig,

#[dynamic(default = "default_char_select_font_size")]
pub char_select_font_size: f64,

Expand Down Expand Up @@ -515,6 +518,9 @@ pub struct Config {
#[dynamic(default)]
pub window_padding: WindowPadding,

#[dynamic(default = "default_float_pane_padding")]
pub float_pane_padding: WindowPadding,

/// Specifies the path to a background image attachment file.
/// The file can be any image format that the rust `image`
/// crate is able to identify and load.
Expand Down Expand Up @@ -1573,6 +1579,15 @@ fn default_integrated_title_buttons() -> Vec<IntegratedTitleButton> {
vec![Hide, Maximize, Close]
}

fn default_float_pane_padding() -> WindowPadding {
WindowPadding{
left: Dimension::Percent(0.20),
top: Dimension::Percent(0.20),
right: Dimension::Percent(0.20),
bottom: Dimension::Percent(0.20),
}
}

fn default_char_select_font_size() -> f64 {
18.0
}
Expand Down
1 change: 1 addition & 0 deletions config/src/keyassignment.rs
Original file line number Diff line number Diff line change
Expand Up @@ -549,6 +549,7 @@ pub enum KeyAssignment {
SpawnCommandInNewWindow(SpawnCommand),
SplitHorizontal(SpawnCommand),
SplitVertical(SpawnCommand),
FloatPane(SpawnCommand),
ShowLauncher,
ShowLauncherArgs(LauncherActionArgs),
ClearScrollback(ScrollbackEraseMode),
Expand Down
19 changes: 19 additions & 0 deletions mux/src/domain.rs
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,25 @@ pub trait Domain: Downcast + Send + Sync {
Ok(tab)
}

async fn add_float_pane(
&self,
tab: TabId,
_pane_id: PaneId,
command_builder: Option<CommandBuilder>,
command_dir: Option<String>
) -> anyhow::Result<Arc<dyn Pane>> {
let mux = Mux::get();
let tab = match mux.get_tab(tab) {
Some(t) => t,
None => anyhow::bail!("Invalid tab id {}", tab),
};

let float_size = tab.get_float_size();
let pane = self.spawn_pane(float_size, command_builder, command_dir) .await?;
tab.insert_float(float_size, Arc::clone(&pane))?;
Ok(pane)
}

async fn split_pane(
&self,
source: SplitSource,
Expand Down
71 changes: 71 additions & 0 deletions mux/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -812,6 +812,15 @@ impl Mux {
}
}

fn remove_float_pane_internal(&self, pane_id: PaneId) {
log::debug!("removing float pane {}", pane_id);
if let Some(pane) = self.panes.write().remove(&pane_id).clone() {
log::debug!("killing float pane {}", pane_id);
pane.kill();
self.notify(MuxNotification::PaneRemoved(pane_id));
}
}

fn remove_tab_internal(&self, tab_id: TabId) -> Option<Arc<Tab>> {
log::debug!("remove_tab_internal tab {}", tab_id);

Expand Down Expand Up @@ -876,6 +885,11 @@ impl Mux {
self.prune_dead_windows();
}

pub fn remove_float_pane(&self, pane_id: PaneId) {
self.remove_float_pane_internal(pane_id);
self.prune_dead_windows();
}

pub fn remove_tab(&self, tab_id: TabId) -> Option<Arc<Tab>> {
let tab = self.remove_tab_internal(tab_id);
self.prune_dead_windows();
Expand Down Expand Up @@ -1169,6 +1183,63 @@ impl Mux {
})
}

pub async fn float_pane(
&self,
// TODO: disambiguate with TabId
pane_id: PaneId,
command_builder: Option<CommandBuilder>,
command_dir: Option<String>,
domain: config::keyassignment::SpawnTabDomain,
) -> anyhow::Result<(Arc<dyn Pane>, TerminalSize)> {
let (_pane_domain_id, window_id, tab_id) = self
.resolve_pane_id(pane_id)
.ok_or_else(|| anyhow!("pane_id {} invalid", pane_id))?;

let domain = self
.resolve_spawn_tab_domain(Some(pane_id), &domain)
.context("resolve_spawn_tab_domain")?;

if domain.state() == DomainState::Detached {
domain.attach(Some(window_id)).await?;
}

let current_pane = self
.get_pane(pane_id)
.ok_or_else(|| anyhow!("pane_id {} is invalid", pane_id))?;
let term_config = current_pane.get_config();

let command_dir = if !command_dir.is_some() {
self.resolve_cwd(
command_dir,
Some(Arc::clone(&current_pane)),
domain.domain_id(),
CachePolicy::FetchImmediate,
)
} else {
command_dir
};

let pane = domain.add_float_pane(tab_id, pane_id, command_builder, command_dir).await?;

if let Some(config) = term_config {
pane.set_config(config);
}

// FIXME: clipboard

let dims = pane.get_dimensions();

let size = TerminalSize {
cols: dims.cols,
rows: dims.viewport_rows,
pixel_height: 0, // FIXME: split pane pixel dimensions
pixel_width: 0,
dpi: dims.dpi,
};

Ok((pane, size))
}

pub async fn split_pane(
&self,
// TODO: disambiguate with TabId
Expand Down
Loading