diff --git a/config/src/config.rs b/config/src/config.rs index 33798ec53..19d5b9c81 100644 --- a/config/src/config.rs +++ b/config/src/config.rs @@ -661,6 +661,9 @@ pub struct Config { #[dynamic(default)] pub ime_preedit_rendering: ImePreeditRendering, + #[dynamic(default)] + pub notification_handling: NotificationHandling, + #[dynamic(default = "default_true")] pub use_dead_keys: bool, @@ -2008,6 +2011,16 @@ pub enum ImePreeditRendering { System, } +#[derive(Debug, FromDynamic, ToDynamic, Clone, Copy, PartialEq, Eq, Default)] +pub enum NotificationHandling { + #[default] + AlwaysShow, + NeverShow, + SuppressFromFocusedPane, + SuppressFromFocusedTab, + SuppressFromFocusedWindow, +} + fn validate_row_or_col(value: &u16) -> Result<(), String> { if *value < 1 { Err("initial_cols and initial_rows must be non-zero".to_string()) diff --git a/docs/changelog.md b/docs/changelog.md index ab0969502..f15afed75 100644 --- a/docs/changelog.md +++ b/docs/changelog.md @@ -98,6 +98,8 @@ As features stabilize some brief notes about them will accumulate here. enhanced to allow setting an alphabet for quickly launching items beyond the first 10 items, as well as customizing the description/label text. Thanks to @Danielkonge! #4226 #4227 +* [notification_handling](config/lua/config/notification_handling.md) to + control whether notifications are suppressed based on focus. #3727 #### Fixed * Command Palette was using now-invalid Nerd Font 2.0 symbols for macOS diff --git a/docs/config/lua/config/notification_handling.md b/docs/config/lua/config/notification_handling.md new file mode 100644 index 000000000..ee3074165 --- /dev/null +++ b/docs/config/lua/config/notification_handling.md @@ -0,0 +1,30 @@ +--- +tags: + - notifications +--- + +# `notification_handling = "AlwaysShow"` + +{{since('nightly')}} + +This option controls how wezterm behaves when a toast notification escape +sequence is received. + +The following escape sequences will generate a toast notification: + +```console +$ printf "\e]777;notify;%s;%s\e\\" "title" "body" +``` + +```console +$ printf "\e]9;%s\e\\" "hello there" +``` + +This configuration option can have one of the following values, +which have the following effects: + + * `AlwaysShow` - Show the notification regardless of the current focus + * `NeverShow` - Never show the notification + * `SuppressFromFocusedPane` - Show the notification unless it was generated from the currently focused pane + * `SuppressFromFocusedTab` - Show the notification unless it was generated from the currently focused tab + * `SuppressFromFocusedWindow` - Show the notification unless it was generated from the currently focused window diff --git a/mux/src/lib.rs b/mux/src/lib.rs index b0146e2d4..a2eb06fe5 100644 --- a/mux/src/lib.rs +++ b/mux/src/lib.rs @@ -485,6 +485,15 @@ impl Mux { } } + pub fn resolve_focused_pane( + &self, + client_id: &ClientId, + ) -> Option<(DomainId, WindowId, TabId, PaneId)> { + let pane_id = self.clients.read().get(client_id)?.focused_pane_id?; + let (domain, window, tab) = self.resolve_pane_id(pane_id)?; + Some((domain, window, tab, pane_id)) + } + pub fn record_focus_for_client(&self, client_id: &ClientId, pane_id: PaneId) { let mut prior = None; if let Some(info) = self.clients.write().get_mut(client_id) { diff --git a/wezterm-gui/src/frontend.rs b/wezterm-gui/src/frontend.rs index 22672f0fb..c63c15d15 100644 --- a/wezterm-gui/src/frontend.rs +++ b/wezterm-gui/src/frontend.rs @@ -5,8 +5,8 @@ use crate::TermWindow; use ::window::*; use anyhow::{Context, Error}; use config::keyassignment::{KeyAssignment, SpawnCommand}; -use config::ConfigSubscription; pub use config::FrontEndSelection; +use config::{ConfigSubscription, NotificationHandling}; use mux::client::ClientId; use mux::window::WindowId as MuxWindowId; use mux::{Mux, MuxNotification}; @@ -96,7 +96,7 @@ impl GuiFrontEnd { MuxNotification::PaneOutput(_) => {} MuxNotification::PaneAdded(_) => {} MuxNotification::Alert { - pane_id: _, + pane_id, alert: Alert::ToastNotification { title, @@ -104,12 +104,34 @@ impl GuiFrontEnd { focus: _, }, } => { - let message = if title.is_none() { "" } else { &body }; - let title = title.as_ref().unwrap_or(&body); - // FIXME: if notification.focus is true, we should do - // something here to arrange to focus pane_id when the - // notification is clicked - persistent_toast_notification(title, message); + let mux = Mux::get(); + + if let Some((_domain, window_id, tab_id)) = mux.resolve_pane_id(pane_id) { + let config = config::configuration(); + + if let Some((_fdomain, f_window, f_tab, f_pane)) = + mux.resolve_focused_pane(&client_id) + { + let show = match config.notification_handling { + NotificationHandling::NeverShow => false, + NotificationHandling::AlwaysShow => true, + NotificationHandling::SuppressFromFocusedPane => f_pane != pane_id, + NotificationHandling::SuppressFromFocusedTab => f_tab != tab_id, + NotificationHandling::SuppressFromFocusedWindow => { + f_window != window_id + } + }; + + if show { + let message = if title.is_none() { "" } else { &body }; + let title = title.as_ref().unwrap_or(&body); + // FIXME: if notification.focus is true, we should do + // something here to arrange to focus pane_id when the + // notification is clicked + persistent_toast_notification(title, message); + } + } + } } MuxNotification::Alert { pane_id: _,