diff --git a/src/argtypes.rs b/src/argtypes.rs index 950f619..87c7076 100644 --- a/src/argtypes.rs +++ b/src/argtypes.rs @@ -7,6 +7,7 @@ pub enum ArgTypes { DeviceName = isize::MIN, TopMargin = isize::MIN + 1, MaxVolume = isize::MIN + 2, + CustomIcon = isize::MIN + 4, // Other None = 0, CapsLock = 1, @@ -21,6 +22,7 @@ pub enum ArgTypes { BrightnessSet = 12, NumLock = 10, ScrollLock = 11, + CustomMessage = 13, } impl fmt::Display for ArgTypes { @@ -42,6 +44,8 @@ impl fmt::Display for ArgTypes { ArgTypes::ScrollLock => "SCROLL-LOCK", ArgTypes::DeviceName => "DEVICE-NAME", ArgTypes::TopMargin => "TOP-MARGIN", + ArgTypes::CustomMessage => "CUSTOM-MESSAGE", + ArgTypes::CustomIcon => "CUSTOM-ICON", }; return write!(f, "{}", string); } @@ -67,6 +71,8 @@ impl str::FromStr for ArgTypes { "SCROLL-LOCK" => ArgTypes::ScrollLock, "DEVICE-NAME" => ArgTypes::DeviceName, "TOP-MARGIN" => ArgTypes::TopMargin, + "CUSTOM-MESSAGE" => ArgTypes::CustomMessage, + "CUSTOM-ICON" => ArgTypes::CustomIcon, other_type => return Err(other_type.to_owned()), }; Ok(result) diff --git a/src/client/main.rs b/src/client/main.rs index 0ca837e..c066e84 100644 --- a/src/client/main.rs +++ b/src/client/main.rs @@ -173,6 +173,24 @@ fn main() -> Result<(), glib::Error> { Some("Pulseaudio device name (pactl list short sinks|sources)"), ); + app.add_main_option( + "custom-message", + glib::Char::from(0), + OptionFlags::NONE, + OptionArg::String, + "Message to display", + Some("text"), + ); + + app.add_main_option( + "custom-icon", + glib::Char::from(0), + OptionFlags::NONE, + OptionArg::String, + "Icon to display when using custom-message. Icon name is from Freedesktop specification (https://specifications.freedesktop.org/icon-naming-spec/latest/)", + Some("Icon name"), + ); + // Parse args app.connect_handle_local_options(move |_app, args| { let variant = args.to_variant(); diff --git a/src/global_utils.rs b/src/global_utils.rs index d786474..9c0b87d 100644 --- a/src/global_utils.rs +++ b/src/global_utils.rs @@ -105,6 +105,26 @@ pub(crate) fn handle_application_args( }; (ArgTypes::DeviceName, Some(value)) } + "custom-message" => { + let value = match child.value().str() { + Some(v) => v.to_string(), + None => { + eprintln!("--custom-message found but no message given"); + return (HandleLocalStatus::FAILURE, actions); + } + }; + (ArgTypes::CustomMessage, Some(value)) + } + "custom-icon" => { + let value = match child.value().str() { + Some(v) => v.to_string(), + None => { + eprintln!("--custom-icon found but no icon given"); + return (HandleLocalStatus::FAILURE, actions); + } + }; + (ArgTypes::CustomIcon, Some(value)) + } "top-margin" => { let value = child.value().str().unwrap_or("").trim(); match value.parse::() { diff --git a/src/server/application.rs b/src/server/application.rs index 8a85fe0..1688413 100644 --- a/src/server/application.rs +++ b/src/server/application.rs @@ -339,6 +339,17 @@ impl SwayOSDApplication { (ArgTypes::DeviceName, name) => { set_device_name(name.unwrap_or(DEVICE_NAME_DEFAULT.to_string())) } + (ArgTypes::CustomMessage, message) => { + if let Some(message) = message { + for window in osd_app.windows.borrow().to_owned() { + window.custom_message(message.as_str(), get_icon_name().as_deref()); + } + } + reset_icon_name(); + } + (ArgTypes::CustomIcon, icon) => { + set_icon_name(icon.unwrap_or(ICON_NAME_DEFAULT.to_string())) + } (arg_type, data) => { eprintln!( "Failed to parse command... Type: {:?}, Data: {:?}", diff --git a/src/server/osd_window.rs b/src/server/osd_window.rs index 0c1cd6e..49296fa 100644 --- a/src/server/osd_window.rs +++ b/src/server/osd_window.rs @@ -163,6 +163,20 @@ impl SwayosdWindow { self.run_timeout(); } + pub fn custom_message(&self, message: &str, icon_name: Option<&str>) { + self.clear_osd(); + + if let Some(icon_name) = icon_name { + let icon = self.build_icon_widget(icon_name); + self.container.add(&icon); + } + + let label = self.build_text_widget(Some(message)); + self.container.add(&label); + + self.run_timeout(); + } + /// Clear all container children fn clear_osd(&self) { for widget in self.container.children() { diff --git a/src/server/utils.rs b/src/server/utils.rs index 5e14eec..163b2f2 100644 --- a/src/server/utils.rs +++ b/src/server/utils.rs @@ -21,6 +21,8 @@ lazy_static! { static ref MAX_VOLUME: Mutex = Mutex::new(PRIV_MAX_VOLUME_DEFAULT); pub static ref DEVICE_NAME_DEFAULT: &'static str = "default"; static ref DEVICE_NAME: Mutex> = Mutex::new(None); + pub static ref ICON_NAME_DEFAULT: &'static str = "text-x-generic"; + static ref ICON_NAME: Mutex> = Mutex::new(None); pub static ref TOP_MARGIN_DEFAULT: f32 = 0.85_f32; static ref TOP_MARGIN: Mutex = Mutex::new(*TOP_MARGIN_DEFAULT); } @@ -77,6 +79,20 @@ pub fn reset_device_name() { *global_name = None; } +pub fn get_icon_name() -> Option { + (*ICON_NAME.lock().unwrap()).clone() +} + +pub fn set_icon_name(name: String) { + let mut icon_name = ICON_NAME.lock().unwrap(); + *icon_name = Some(name); +} + +pub fn reset_icon_name() { + let mut icon_name = ICON_NAME.lock().unwrap(); + *icon_name = None; +} + pub fn get_key_lock_state(key: KeysLocks, led: Option) -> bool { const BASE_PATH: &str = "/sys/class/leds"; match fs::read_dir(BASE_PATH) {