From 726d9a0a9ee212c92cb894fb70c17c615e88b077 Mon Sep 17 00:00:00 2001 From: Tassilo Horn Date: Thu, 7 Apr 2022 21:51:57 +0200 Subject: [PATCH] Clicks work! --- swayrbar/src/bar.rs | 33 +++++++++++++++++++++++++++++- swayrbar/src/bar/config.rs | 11 ++++++++-- swayrbar/src/bar/module.rs | 16 ++++++++++++++- swayrbar/src/bar/module/battery.rs | 9 ++++---- swayrbar/src/bar/module/date.rs | 21 ++++++++++++------- swayrbar/src/bar/module/sysinfo.rs | 23 ++++++++++++--------- swayrbar/src/bar/module/window.rs | 9 +++++--- 7 files changed, 94 insertions(+), 28 deletions(-) diff --git a/swayrbar/src/bar.rs b/swayrbar/src/bar.rs index a4f5fef..49ae522 100644 --- a/swayrbar/src/bar.rs +++ b/swayrbar/src/bar.rs @@ -19,6 +19,7 @@ use crate::bar::module::BarModuleFn; use env_logger::Env; use serde_json; use std::io; +use std::process as p; use std::{sync::Arc, thread}; use swaybar_types as sbt; @@ -71,7 +72,7 @@ pub fn handle_input(mods: Arc>>) { } let click = match serde_json::from_str::( - buf.strip_prefix(",").unwrap_or(&buf), + buf.strip_prefix(',').unwrap_or(&buf), ) { Ok(click) => click, Err(err) => { @@ -82,6 +83,36 @@ pub fn handle_input(mods: Arc>>) { } }; log::debug!("Received click: {:?}", click); + handle_click(click, mods.clone()); + } +} + +fn handle_click( + click: sbt::Click, + mods: Arc>>, +) -> Option<()> { + let name = click.name?; + let instance = click.instance?; + let button_str = format!("{:?}", click.button); + for m in mods.iter() { + if let Some(on_click) = m.get_on_click_map(&name, &instance) { + if let Some(cmd) = on_click.get(&button_str) { + execute_command(cmd); + return Some(()); + } + } + } + + None +} + +fn execute_command(cmd: &[String]) { + match p::Command::new(&cmd[0]).args(&cmd[1..]).spawn() { + Ok(_child) => (), + Err(err) => { + log::error!("Error running shell command '{}':", cmd.join(" ")); + log::error!("{}", err); + } } } diff --git a/swayrbar/src/bar/config.rs b/swayrbar/src/bar/config.rs index 38ae408..df5a2b2 100644 --- a/swayrbar/src/bar/config.rs +++ b/swayrbar/src/bar/config.rs @@ -15,7 +15,9 @@ //! TOML configuration for swayrbar. +use crate::bar::module::BarModuleFn; use serde::{Deserialize, Serialize}; +use std::collections::HashMap; #[derive(Debug, Serialize, Deserialize)] pub struct Config { @@ -29,10 +31,11 @@ pub struct Config { #[derive(Debug, Serialize, Deserialize)] pub struct ModuleConfig { - pub module_type: String, + pub name: String, pub instance: String, pub format: String, pub html_escape: bool, + pub on_click: HashMap>, } impl Default for Config { @@ -40,7 +43,11 @@ impl Default for Config { Config { refresh_interval: 1000, modules: vec!["date/0".to_owned()], - module_configs: vec![], + module_configs: vec![ + crate::bar::module::date::BarModuleDate::default_config( + "0".to_owned(), + ), + ], } } } diff --git a/swayrbar/src/bar/module.rs b/swayrbar/src/bar/module.rs index 0f47a0b..c60fd2d 100644 --- a/swayrbar/src/bar/module.rs +++ b/swayrbar/src/bar/module.rs @@ -13,6 +13,8 @@ // You should have received a copy of the GNU General Public License along with // this program. If not, see . +use std::collections::HashMap; + use crate::bar::config; use swaybar_types as s; @@ -31,6 +33,18 @@ pub trait BarModuleFn: Sync + Send { fn name() -> &'static str where Self: Sized; - fn matches(&self, name: &str, instance: &str) -> bool; + fn get_config(&self) -> &config::ModuleConfig; + fn get_on_click_map( + &self, + name: &str, + instance: &str, + ) -> Option<&HashMap>> { + let cfg = self.get_config(); + if name == cfg.name && instance == cfg.instance { + Some(&cfg.on_click) + } else { + None + } + } fn build(&self) -> s::Block; } diff --git a/swayrbar/src/bar/module/battery.rs b/swayrbar/src/bar/module/battery.rs index 6fc2128..4fa52ba 100644 --- a/swayrbar/src/bar/module/battery.rs +++ b/swayrbar/src/bar/module/battery.rs @@ -19,7 +19,7 @@ use crate::bar::config; use crate::bar::module::BarModuleFn; use crate::fmt_replace::fmt_replace; use battery as bat; -use std::collections::HashSet; +use std::collections::{HashMap, HashSet}; use swaybar_types as s; const NAME: &str = "battery"; @@ -96,10 +96,11 @@ impl BarModuleFn for BarModuleBattery { fn default_config(instance: String) -> config::ModuleConfig { config::ModuleConfig { - module_type: Self::name().to_owned(), + name: Self::name().to_owned(), instance, format: "🔋 Bat: {state_of_charge:{:5.1}}%, {state}, Health: {state_of_health:{:5.1}}%".to_owned(), html_escape: true, + on_click: HashMap::new() } } @@ -107,8 +108,8 @@ impl BarModuleFn for BarModuleBattery { NAME } - fn matches(&self, name: &str, instance: &str) -> bool { - NAME == name && self.config.instance == instance + fn get_config(&self) -> &config::ModuleConfig { + &self.config } fn build(&self) -> s::Block { diff --git a/swayrbar/src/bar/module/date.rs b/swayrbar/src/bar/module/date.rs index 3cbd95b..2af2592 100644 --- a/swayrbar/src/bar/module/date.rs +++ b/swayrbar/src/bar/module/date.rs @@ -15,6 +15,8 @@ //! The date `swayrbar` module. +use std::collections::HashMap; + use crate::bar::module::config; use crate::bar::module::BarModuleFn; use swaybar_types as s; @@ -26,25 +28,30 @@ pub struct BarModuleDate { } impl BarModuleFn for BarModuleDate { + fn create(cfg: config::ModuleConfig) -> Box { + Box::new(BarModuleDate { config: cfg }) + } + fn default_config(instance: String) -> config::ModuleConfig { config::ModuleConfig { - module_type: "date".to_owned(), + name: "date".to_owned(), instance, format: "⏰ %F %X".to_owned(), html_escape: false, + // TODO: Only for testing. + on_click: HashMap::from([( + "Left".to_owned(), + vec!["foot".to_owned(), "htop".to_owned()], + )]), } } - fn create(cfg: config::ModuleConfig) -> Box { - Box::new(BarModuleDate { config: cfg }) - } - fn name() -> &'static str { NAME } - fn matches(&self, name: &str, instance: &str) -> bool { - NAME == name && self.config.instance == instance + fn get_config(&self) -> &config::ModuleConfig { + &self.config } fn build(&self) -> s::Block { diff --git a/swayrbar/src/bar/module/sysinfo.rs b/swayrbar/src/bar/module/sysinfo.rs index aa00b6d..c68fd04 100644 --- a/swayrbar/src/bar/module/sysinfo.rs +++ b/swayrbar/src/bar/module/sysinfo.rs @@ -18,6 +18,7 @@ use crate::bar::config; use crate::bar::module::BarModuleFn; use crate::fmt_replace::fmt_replace; +use std::collections::HashMap; use std::sync::Mutex; use std::sync::Once; use swaybar_types as s; @@ -93,12 +94,22 @@ impl BarModuleFn for BarModuleSysInfo { }) } + fn default_config(instance: String) -> config::ModuleConfig { + config::ModuleConfig { + name: "sysinfo".to_owned(), + instance, + format: "💻 CPU: {cpu_usage:{:4.1}}% Mem: {mem_usage:{:4.1}}% Load: {load_avg_1:{:4.2}} / {load_avg_5:{:4.2}} / {load_avg_15:{:4.2}}".to_owned(), + html_escape: true, + on_click: HashMap::new(), + } + } + fn name() -> &'static str { NAME } - fn matches(&self, name: &str, instance: &str) -> bool { - NAME == name && self.config.instance == instance + fn get_config(&self) -> &config::ModuleConfig { + &self.config } fn build(&self) -> s::Block { @@ -135,12 +146,4 @@ impl BarModuleFn for BarModuleSysInfo { separator_block_width: None, } } - - fn default_config(instance: String) -> config::ModuleConfig { - config::ModuleConfig { - module_type: "sysinfo".to_owned(), - instance, - format: "💻 CPU: {cpu_usage:{:4.1}}% Mem: {mem_usage:{:4.1}}% Load: {load_avg_1:{:4.2}} / {load_avg_5:{:4.2}} / {load_avg_15:{:4.2}}".to_owned(), - html_escape: true } - } } diff --git a/swayrbar/src/bar/module/window.rs b/swayrbar/src/bar/module/window.rs index 8113fdf..ee61eb4 100644 --- a/swayrbar/src/bar/module/window.rs +++ b/swayrbar/src/bar/module/window.rs @@ -15,6 +15,8 @@ //! The window `swayrbar` module. +use std::collections::HashMap; + use crate::bar::config; use crate::bar::module::BarModuleFn; use crate::fmt_replace::fmt_replace; @@ -35,10 +37,11 @@ impl BarModuleFn for BarModuleWindow { fn default_config(instance: String) -> config::ModuleConfig { config::ModuleConfig { - module_type: Self::name().to_owned(), + name: Self::name().to_owned(), instance, format: "🪟 {title} — {app_name}".to_owned(), html_escape: true, + on_click: HashMap::new(), } } @@ -46,8 +49,8 @@ impl BarModuleFn for BarModuleWindow { NAME } - fn matches(&self, name: &str, instance: &str) -> bool { - NAME == name && self.config.instance == instance + fn get_config(&self) -> &config::ModuleConfig { + &self.config } fn build(&self) -> s::Block {