aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHoru <73709188+HigherOrderLogic@users.noreply.github.com>2025-08-17 16:28:24 +1000
committerGitHub <noreply@github.com>2025-08-17 09:28:24 +0300
commit271534e115e5915231c99df287bbfe396185924d (patch)
tree5642ba961a88d5f5d1f5afc0686d7b2f2476f28c
parentaf30cc8df68b29973c8b9eec290f9e6b93463929 (diff)
downloadniri-271534e115e5915231c99df287bbfe396185924d.tar.gz
niri-271534e115e5915231c99df287bbfe396185924d.tar.bz2
niri-271534e115e5915231c99df287bbfe396185924d.zip
Add ConfigLoaded event to IPC, option to disable built-in notification (#1829)
* feat: config reload ipc event * cleanups * Rename and move the new config option * rename to ConfigLoaded and emit at connection --------- Co-authored-by: Ivan Molodetskikh <yalterz@gmail.com>
-rw-r--r--niri-config/src/lib.rs11
-rw-r--r--niri-ipc/src/lib.rs10
-rw-r--r--niri-ipc/src/state.rs30
-rw-r--r--src/ipc/client.rs8
-rw-r--r--src/ipc/server.rs11
-rw-r--r--src/main.rs1
-rw-r--r--src/ui/config_error_notification.rs5
-rw-r--r--src/utils/watcher.rs17
-rw-r--r--wiki/Configuration:-Miscellaneous.md19
9 files changed, 107 insertions, 5 deletions
diff --git a/niri-config/src/lib.rs b/niri-config/src/lib.rs
index 613aad3a..16ec6dca 100644
--- a/niri-config/src/lib.rs
+++ b/niri-config/src/lib.rs
@@ -60,6 +60,8 @@ pub struct Config {
#[knuffel(child, default)]
pub hotkey_overlay: HotkeyOverlay,
#[knuffel(child, default)]
+ pub config_notification: ConfigNotification,
+ #[knuffel(child, default)]
pub animations: Animations,
#[knuffel(child, default)]
pub gestures: Gestures,
@@ -1048,6 +1050,12 @@ pub struct HotkeyOverlay {
}
#[derive(knuffel::Decode, Debug, Default, Clone, Copy, PartialEq, Eq)]
+pub struct ConfigNotification {
+ #[knuffel(child)]
+ pub disable_failed: bool,
+}
+
+#[derive(knuffel::Decode, Debug, Default, Clone, Copy, PartialEq, Eq)]
pub struct Clipboard {
#[knuffel(child)]
pub disable_primary: bool,
@@ -4769,6 +4777,9 @@ mod tests {
skip_at_startup: true,
hide_not_bound: false,
},
+ config_notification: ConfigNotification {
+ disable_failed: false,
+ },
animations: Animations {
off: false,
slowdown: FloatOrInt(
diff --git a/niri-ipc/src/lib.rs b/niri-ipc/src/lib.rs
index 737f1647..a1be86d2 100644
--- a/niri-ipc/src/lib.rs
+++ b/niri-ipc/src/lib.rs
@@ -1399,6 +1399,16 @@ pub enum Event {
/// The new state of the overview.
is_open: bool,
},
+ /// The configuration was reloaded.
+ ///
+ /// You will always receive this event when connecting to the event stream, indicating the last
+ /// config load attempt.
+ ConfigLoaded {
+ /// Whether the loading failed.
+ ///
+ /// For example, the config file couldn't be parsed.
+ failed: bool,
+ },
}
impl FromStr for WorkspaceReferenceArg {
diff --git a/niri-ipc/src/state.rs b/niri-ipc/src/state.rs
index ef883021..3ba63a52 100644
--- a/niri-ipc/src/state.rs
+++ b/niri-ipc/src/state.rs
@@ -43,6 +43,9 @@ pub struct EventStreamState {
/// State of the overview.
pub overview: OverviewState,
+
+ /// State of the config.
+ pub config: ConfigState,
}
/// The workspaces state communicated over the event stream.
@@ -73,6 +76,13 @@ pub struct OverviewState {
pub is_open: bool,
}
+/// The config state communicated over the event stream.
+#[derive(Debug, Default)]
+pub struct ConfigState {
+ /// Whether the last config load attempt had failed.
+ pub failed: bool,
+}
+
impl EventStreamStatePart for EventStreamState {
fn replicate(&self) -> Vec<Event> {
let mut events = Vec::new();
@@ -80,6 +90,7 @@ impl EventStreamStatePart for EventStreamState {
events.extend(self.windows.replicate());
events.extend(self.keyboard_layouts.replicate());
events.extend(self.overview.replicate());
+ events.extend(self.config.replicate());
events
}
@@ -88,6 +99,7 @@ impl EventStreamStatePart for EventStreamState {
let event = self.windows.apply(event)?;
let event = self.keyboard_layouts.apply(event)?;
let event = self.overview.apply(event)?;
+ let event = self.config.apply(event)?;
Some(event)
}
}
@@ -244,3 +256,21 @@ impl EventStreamStatePart for OverviewState {
None
}
}
+
+impl EventStreamStatePart for ConfigState {
+ fn replicate(&self) -> Vec<Event> {
+ vec![Event::ConfigLoaded {
+ failed: self.failed,
+ }]
+ }
+
+ fn apply(&mut self, event: Event) -> Option<Event> {
+ match event {
+ Event::ConfigLoaded { failed } => {
+ self.failed = failed;
+ }
+ event => return Some(event),
+ }
+ None
+ }
+}
diff --git a/src/ipc/client.rs b/src/ipc/client.rs
index 42fbbf75..094bb636 100644
--- a/src/ipc/client.rs
+++ b/src/ipc/client.rs
@@ -459,6 +459,14 @@ pub fn handle_msg(msg: Msg, json: bool) -> anyhow::Result<()> {
Event::OverviewOpenedOrClosed { is_open: opened } => {
println!("Overview toggled: {opened}");
}
+ Event::ConfigLoaded { failed } => {
+ let status = if failed {
+ "with an error"
+ } else {
+ "successfully"
+ };
+ println!("Config loaded {status}");
+ }
}
}
}
diff --git a/src/ipc/server.rs b/src/ipc/server.rs
index 464a2a13..051bccab 100644
--- a/src/ipc/server.rs
+++ b/src/ipc/server.rs
@@ -762,4 +762,15 @@ impl State {
state.apply(event.clone());
server.send_event(event);
}
+
+ pub fn ipc_config_loaded(&mut self, failed: bool) {
+ let Some(server) = &self.niri.ipc_server else {
+ return;
+ };
+ let mut state = server.event_stream_state.borrow_mut();
+
+ let event = Event::ConfigLoaded { failed };
+ state.apply(event.clone());
+ server.send_event(event);
+ }
}
diff --git a/src/main.rs b/src/main.rs
index 2b3e1c5a..9654f7e9 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -241,6 +241,7 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
// Show the config error notification right away if needed.
if config_errored {
state.niri.config_error_notification.show();
+ state.ipc_config_loaded(true);
} else if let Some(path) = config_created_at {
state.niri.config_error_notification.show_created(path);
}
diff --git a/src/ui/config_error_notification.rs b/src/ui/config_error_notification.rs
index 4e976633..20667172 100644
--- a/src/ui/config_error_notification.rs
+++ b/src/ui/config_error_notification.rs
@@ -78,6 +78,11 @@ impl ConfigErrorNotification {
}
pub fn show(&mut self) {
+ let c = self.config.borrow();
+ if c.config_notification.disable_failed {
+ return;
+ }
+
if self.created_path.is_some() {
self.created_path = None;
self.buffers.borrow_mut().clear();
diff --git a/src/utils/watcher.rs b/src/utils/watcher.rs
index 4ed4c8ae..034e963a 100644
--- a/src/utils/watcher.rs
+++ b/src/utils/watcher.rs
@@ -5,7 +5,7 @@ use std::sync::mpsc;
use std::time::{Duration, SystemTime};
use std::{io, thread};
-use niri_config::ConfigPath;
+use niri_config::{Config, ConfigPath};
use smithay::reexports::calloop::channel::SyncSender;
use crate::niri::State;
@@ -137,10 +137,17 @@ pub fn setup(state: &mut State, config_path: &ConfigPath) {
state
.niri
.event_loop
- .insert_source(rx, |event, _, state| match event {
- calloop::channel::Event::Msg(config) => state.reload_config(config),
- calloop::channel::Event::Closed => (),
- })
+ .insert_source(
+ rx,
+ |event: calloop::channel::Event<Result<Config, ()>>, _, state| match event {
+ calloop::channel::Event::Msg(config) => {
+ let failed = config.is_err();
+ state.reload_config(config);
+ state.ipc_config_loaded(failed);
+ }
+ calloop::channel::Event::Closed => (),
+ },
+ )
.unwrap();
state.niri.config_file_watcher = Some(Watcher::new(config_path.clone(), process, tx));
diff --git a/wiki/Configuration:-Miscellaneous.md b/wiki/Configuration:-Miscellaneous.md
index 3eba0a31..f2d1010a 100644
--- a/wiki/Configuration:-Miscellaneous.md
+++ b/wiki/Configuration:-Miscellaneous.md
@@ -49,6 +49,10 @@ hotkey-overlay {
skip-at-startup
hide-not-bound
}
+
+config-notification {
+ disable-failed
+}
```
### `spawn-at-startup`
@@ -277,3 +281,18 @@ hotkey-overlay {
```
You can customize which binds the hotkey overlay shows using the [`hotkey-overlay-title` property](./Configuration:-Key-Bindings.md#custom-hotkey-overlay-titles).
+
+### `config-notification`
+
+<sup>Since: next release</sup>
+
+Settings for the config created/failed notification.
+
+Set the `disable-failed` flag to disable the "Failed to parse the config file" notification.
+For example, if you have a custom one.
+
+```kdl
+config-notification {
+ disable-failed
+}
+```