From e1ba66c1be5fc84f22fcedecf4724c827d109620 Mon Sep 17 00:00:00 2001 From: Joakim Hulthe Date: Thu, 6 Feb 2025 17:55:19 +0100 Subject: [PATCH] Add notification when switching keyboard layout --- src/main.rs | 1 + src/niri.rs | 12 ++++++--- src/notify.rs | 70 +++++++++++++++++++++++++++++++++++++++++++++++++++ src/util.rs | 4 +-- 4 files changed, 82 insertions(+), 5 deletions(-) create mode 100644 src/notify.rs diff --git a/src/main.rs b/src/main.rs index b78443f..22769bc 100644 --- a/src/main.rs +++ b/src/main.rs @@ -7,6 +7,7 @@ mod battery; mod eww; mod hyprland; mod niri; +mod notify; mod output; mod pulse; mod util; diff --git a/src/niri.rs b/src/niri.rs index e49341d..093e415 100644 --- a/src/niri.rs +++ b/src/niri.rs @@ -1,6 +1,6 @@ -use std::collections::HashMap; +use std::{collections::HashMap, time::Duration}; -use crate::{eww, WmCommand, Workspace}; +use crate::{eww, notify::Notify, WmCommand, Workspace}; use eyre::{bail, eyre, Context}; use niri_ipc::{socket::Socket, WorkspaceReferenceArg}; @@ -30,7 +30,13 @@ pub fn handle(command: WmCommand) -> eyre::Result<()> { .map(|(reply, _)| reply)? .map_err(|e| eyre!("niri error: {e}"))?; - eww::update_var("keyboard_layout", &get_keyboard_layout(true)?)?; + let layout = &get_keyboard_layout(true)?; + Notify::new("Keyboard Layout") + .with_body(layout) + .with_expire(Duration::from_secs(1)) + //.with_unique("keyboard-layout") // TODO: fix PATH so niri can call notify-send + .send()?; + eww::update_var("keyboard_layout", &layout)?; } WmCommand::KeyboardLayout { short } => { println!("{}", get_keyboard_layout(short)?); diff --git a/src/notify.rs b/src/notify.rs new file mode 100644 index 0000000..bda598f --- /dev/null +++ b/src/notify.rs @@ -0,0 +1,70 @@ +use std::{process::Command, time::Duration}; + +use crate::util::CommandExt; + +pub struct Notify { + summary: String, + body: Option, + expire: Option, + + // If set, only one notification with this ID may be shown at once. + unique_id: Option, +} + +impl Notify { + pub fn new(summary: impl Into) -> Self { + Self { + summary: summary.into(), + body: None, + expire: None, + unique_id: None, + } + } + + pub fn with_body(self, body: impl Into) -> Self { + Self { + body: Some(body.into()), + ..self + } + } + + pub fn with_expire(self, expire: impl Into) -> Self { + Self { + expire: Some(expire.into()), + ..self + } + } + + pub fn with_unique(self, unique_id: impl Into) -> Self { + Self { + unique_id: Some(unique_id.into()), + ..self + } + } + + pub fn send(&self) -> eyre::Result<()> { + let Notify { + summary, + body, + expire, + unique_id, + } = self; + + let mut command = match unique_id { + Some(id) => { + let mut command = Command::new("notify-set"); + command.arg(id); + command + } + None => Command::new("notify-send"), + }; + + command + .arg(summary) + .args(body) + .args(expire.map(|d| format!("--expire-time={}", d.as_millis().to_string()))) + .just_exec()?; + + Ok(()) + } +} diff --git a/src/util.rs b/src/util.rs index e98c5c2..93476a9 100644 --- a/src/util.rs +++ b/src/util.rs @@ -1,6 +1,6 @@ use eyre::{eyre, Context}; use serde::de::DeserializeOwned; -use std::{fmt::Write, str}; +use std::{fmt::Write, process::Command, str}; pub trait CommandExt: Sized { fn just_exec(&mut self) -> eyre::Result; @@ -16,7 +16,7 @@ pub trait CommandExt: Sized { } } -impl CommandExt for std::process::Command { +impl CommandExt for Command { fn just_exec(&mut self) -> eyre::Result { let error = self.error(); let output = self