diff --git a/src/core/config.rs b/src/core/config.rs index 32e2fe79..700f3b94 100644 --- a/src/core/config.rs +++ b/src/core/config.rs @@ -60,6 +60,11 @@ pub struct Config { pub window_opacity: Option, /// Global window-blur override. `None` follows the active theme's `blur`. pub window_blur: Option, + /// Fade unfocused panes in a split tab so the focused terminal reads as + /// foreground. On by default; when off every pane renders at full opacity + /// and only focus (cursor, etc.) distinguishes the active one. + #[serde(default = "default_true")] + pub dim_inactive_panes: bool, /// Optional keybinding overrides: action name (e.g. "NewTab") → keystroke /// (e.g. "secondary-t", which is ⌘ on macOS and Ctrl elsewhere). Unknown /// actions and unparseable keystrokes are ignored (with a warning) so a bad @@ -596,6 +601,7 @@ impl Default for Config { theme_preset_dark: "dark".to_string(), window_opacity: None, window_blur: None, + dim_inactive_panes: true, keybindings: HashMap::new(), keybinding_preset: default_preset(), prefix: default_prefix(), diff --git a/src/ui/app.rs b/src/ui/app.rs index d5b06207..b2181f7d 100644 --- a/src/ui/app.rs +++ b/src/ui/app.rs @@ -2506,6 +2506,12 @@ impl Tty7App { self.update_config(cx, |cfg| cfg.check_for_updates = on); } + /// Toggle inactive-pane dimming. Applies on the next render — the pane tree + /// reads the flag from the `Config` global each frame. + pub(crate) fn set_dim_inactive_panes(&mut self, on: bool, cx: &mut Context) { + self.update_config(cx, |cfg| cfg.dim_inactive_panes = on); + } + pub(crate) fn set_cursor_blink(&mut self, on: bool, cx: &mut Context) { self.update_config(cx, |cfg| cfg.cursor_blink = on); // Turning blink off mid-cycle could leave the cursor in its hidden phase; diff --git a/src/ui/pane.rs b/src/ui/pane.rs index 9151b5a5..5f658295 100644 --- a/src/ui/pane.rs +++ b/src/ui/pane.rs @@ -542,8 +542,15 @@ impl Pane> { // (terminal glyphs + cell fills), unlike a background-tinted // scrim which is near-invisible on a light theme (white on // white). Applied to the container, so a click still lands on - // the terminal and focuses it. - .when(show_focus && !focused, |d| d.opacity(0.55)) + // the terminal and focuses it. `dim_inactive_panes` opts out. + .when( + show_focus + && !focused + && cx + .global::() + .dim_inactive_panes, + |d| d.opacity(0.55), + ) .child(v.clone()) .into_any_element() } diff --git a/src/ui/settings.rs b/src/ui/settings.rs index 5aa52d0d..4eeb63ff 100644 --- a/src/ui/settings.rs +++ b/src/ui/settings.rs @@ -1531,6 +1531,7 @@ impl Tty7App { }; let config = cx.global::(); let overridden = config.window_opacity.is_some() || config.window_blur.is_some(); + let dim_inactive_panes = config.dim_inactive_panes; let theme = presets::by_id(cx, &crate::ui::theme::effective_preset_id(cx)); let opacity = Tty7App::effective_window_opacity(cx); let blur = cx.global::().window_blur.unwrap_or(theme.blur); @@ -1554,6 +1555,10 @@ impl Tty7App { cx.listener(|this, on: &bool, window, cx| this.set_window_blur(*on, window, cx)), ) .into_any_element(); + let dim_switch = crate::ui::theme::switch("dim-inactive-panes", cx) + .checked(dim_inactive_panes) + .on_click(cx.listener(|this, on: &bool, _w, cx| this.set_dim_inactive_panes(*on, cx))) + .into_any_element(); v_flex() // Not "Window": Settings → Window & Tabs owns that word for the @@ -1573,6 +1578,12 @@ impl Tty7App { blur_switch, cx, )) + .child(self.settings_row( + "Dim inactive panes", + "Fade unfocused panes in a split so the active one stands out.", + dim_switch, + cx, + )) // Only offered while an override is active; otherwise the values // already follow the theme and the button would be a no-op. .when(overridden, |this| {