|  |  |  | @ -20,6 +20,7 @@ use crate::module; | 
			
		
	
		
			
				
					|  |  |  |  | use crate::module::{BarModuleFn, NameAndInstance}; | 
			
		
	
		
			
				
					|  |  |  |  | use env_logger::Env; | 
			
		
	
		
			
				
					|  |  |  |  | use serde_json; | 
			
		
	
		
			
				
					|  |  |  |  | use std::collections::VecDeque; | 
			
		
	
		
			
				
					|  |  |  |  | use std::io; | 
			
		
	
		
			
				
					|  |  |  |  | use std::process as p; | 
			
		
	
		
			
				
					|  |  |  |  | use std::sync::Condvar; | 
			
		
	
	
		
			
				
					|  |  |  | @ -30,6 +31,7 @@ use swaybar_types as sbt; | 
			
		
	
		
			
				
					|  |  |  |  | use swayipc as si; | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | type NameInstanceAndReason = (String, String, String); | 
			
		
	
		
			
				
					|  |  |  |  | type Trigger = Arc<(Mutex<VecDeque<NameInstanceAndReason>>, Condvar)>; | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | pub fn start() { | 
			
		
	
		
			
				
					|  |  |  |  |     env_logger::Builder::from_env(Env::default().default_filter_or("warn")) | 
			
		
	
	
		
			
				
					|  |  |  | @ -39,10 +41,8 @@ pub fn start() { | 
			
		
	
		
			
				
					|  |  |  |  |     let refresh_interval = config.refresh_interval; | 
			
		
	
		
			
				
					|  |  |  |  |     let mods: Arc<Vec<Box<dyn BarModuleFn>>> = Arc::new(create_modules(config)); | 
			
		
	
		
			
				
					|  |  |  |  |     let mods_for_input = mods.clone(); | 
			
		
	
		
			
				
					|  |  |  |  |     let trigger: Arc<(Mutex<NameInstanceAndReason>, Condvar)> = Arc::new(( | 
			
		
	
		
			
				
					|  |  |  |  |         Mutex::new((String::new(), String::new(), String::new())), | 
			
		
	
		
			
				
					|  |  |  |  |         Condvar::new(), | 
			
		
	
		
			
				
					|  |  |  |  |     )); | 
			
		
	
		
			
				
					|  |  |  |  |     let trigger: Trigger = | 
			
		
	
		
			
				
					|  |  |  |  |         Arc::new((Mutex::new(VecDeque::new()), Condvar::new())); | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |     let trigger_for_input = trigger.clone(); | 
			
		
	
		
			
				
					|  |  |  |  |     thread::spawn(move || handle_input(mods_for_input, trigger_for_input)); | 
			
		
	
	
		
			
				
					|  |  |  | @ -83,10 +83,7 @@ fn create_modules(config: config::Config) -> Vec<Box<dyn BarModuleFn>> { | 
			
		
	
		
			
				
					|  |  |  |  |     mods | 
			
		
	
		
			
				
					|  |  |  |  | } | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | fn handle_input( | 
			
		
	
		
			
				
					|  |  |  |  |     mods: Arc<Vec<Box<dyn BarModuleFn>>>, | 
			
		
	
		
			
				
					|  |  |  |  |     trigger: Arc<(Mutex<NameInstanceAndReason>, Condvar)>, | 
			
		
	
		
			
				
					|  |  |  |  | ) { | 
			
		
	
		
			
				
					|  |  |  |  | fn handle_input(mods: Arc<Vec<Box<dyn BarModuleFn>>>, trigger: Trigger) { | 
			
		
	
		
			
				
					|  |  |  |  |     let mut sb = String::new(); | 
			
		
	
		
			
				
					|  |  |  |  |     io::stdin() | 
			
		
	
		
			
				
					|  |  |  |  |         .read_line(&mut sb) | 
			
		
	
	
		
			
				
					|  |  |  | @ -120,10 +117,8 @@ fn handle_input( | 
			
		
	
		
			
				
					|  |  |  |  |         log::debug!("Received click: {:?}", click); | 
			
		
	
		
			
				
					|  |  |  |  |         if let Some((name, instance)) = handle_click(click, mods.clone()) { | 
			
		
	
		
			
				
					|  |  |  |  |             let (mtx, cvar) = &*trigger; | 
			
		
	
		
			
				
					|  |  |  |  |             let mut name_inst_reason = mtx.lock().unwrap(); | 
			
		
	
		
			
				
					|  |  |  |  |             name_inst_reason.0 = name; | 
			
		
	
		
			
				
					|  |  |  |  |             name_inst_reason.1 = instance; | 
			
		
	
		
			
				
					|  |  |  |  |             name_inst_reason.2 = String::from("click event"); | 
			
		
	
		
			
				
					|  |  |  |  |             let mut queue = mtx.lock().unwrap(); | 
			
		
	
		
			
				
					|  |  |  |  |             queue.push_back((name, instance, String::from("click event"))); | 
			
		
	
		
			
				
					|  |  |  |  |             cvar.notify_one(); | 
			
		
	
		
			
				
					|  |  |  |  |         } | 
			
		
	
		
			
				
					|  |  |  |  |     } | 
			
		
	
	
		
			
				
					|  |  |  | @ -146,6 +141,9 @@ fn handle_click( | 
			
		
	
		
			
				
					|  |  |  |  |                 let cfg = m.get_config(); | 
			
		
	
		
			
				
					|  |  |  |  |                 // No refresh for click events for window modules because the
 | 
			
		
	
		
			
				
					|  |  |  |  |                 // refresh will be triggered by a sway event anyhow.
 | 
			
		
	
		
			
				
					|  |  |  |  |                 //
 | 
			
		
	
		
			
				
					|  |  |  |  |                 // TODO: That's too much coupling.  The bar module shouldn't do
 | 
			
		
	
		
			
				
					|  |  |  |  |                 // specific stuff for certain modules.
 | 
			
		
	
		
			
				
					|  |  |  |  |                 if cfg.name == module::window::NAME { | 
			
		
	
		
			
				
					|  |  |  |  |                     return None; | 
			
		
	
		
			
				
					|  |  |  |  |                 } | 
			
		
	
	
		
			
				
					|  |  |  | @ -184,10 +182,7 @@ fn sway_subscribe() -> si::Fallible<si::EventStream> { | 
			
		
	
		
			
				
					|  |  |  |  |     ]) | 
			
		
	
		
			
				
					|  |  |  |  | } | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | fn handle_sway_events( | 
			
		
	
		
			
				
					|  |  |  |  |     window_mods: Vec<NameAndInstance>, | 
			
		
	
		
			
				
					|  |  |  |  |     trigger: Arc<(Mutex<NameInstanceAndReason>, Condvar)>, | 
			
		
	
		
			
				
					|  |  |  |  | ) { | 
			
		
	
		
			
				
					|  |  |  |  | fn handle_sway_events(window_mods: Vec<NameAndInstance>, trigger: Trigger) { | 
			
		
	
		
			
				
					|  |  |  |  |     let mut resets = 0; | 
			
		
	
		
			
				
					|  |  |  |  |     let max_resets = 10; | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
	
		
			
				
					|  |  |  | @ -216,12 +211,12 @@ fn handle_sway_events( | 
			
		
	
		
			
				
					|  |  |  |  |                                 ); | 
			
		
	
		
			
				
					|  |  |  |  |                                 for m in &window_mods { | 
			
		
	
		
			
				
					|  |  |  |  |                                     let (mtx, cvar) = &*trigger; | 
			
		
	
		
			
				
					|  |  |  |  |                                     let mut name_inst_reason = | 
			
		
	
		
			
				
					|  |  |  |  |                                         mtx.lock().unwrap(); | 
			
		
	
		
			
				
					|  |  |  |  |                                     name_inst_reason.0 = m.0.to_owned(); | 
			
		
	
		
			
				
					|  |  |  |  |                                     name_inst_reason.1 = m.1.to_owned(); | 
			
		
	
		
			
				
					|  |  |  |  |                                     name_inst_reason.2 = | 
			
		
	
		
			
				
					|  |  |  |  |                                         String::from("sway event"); | 
			
		
	
		
			
				
					|  |  |  |  |                                     let mut queue = mtx.lock().unwrap(); | 
			
		
	
		
			
				
					|  |  |  |  |                                     queue.push_back(( | 
			
		
	
		
			
				
					|  |  |  |  |                                         m.0.to_owned(), | 
			
		
	
		
			
				
					|  |  |  |  |                                         m.1.to_owned(), | 
			
		
	
		
			
				
					|  |  |  |  |                                         String::from("sway event"), | 
			
		
	
		
			
				
					|  |  |  |  |                                     )); | 
			
		
	
		
			
				
					|  |  |  |  |                                     cvar.notify_one(); | 
			
		
	
		
			
				
					|  |  |  |  |                                 } | 
			
		
	
		
			
				
					|  |  |  |  |                             } | 
			
		
	
	
		
			
				
					|  |  |  | @ -248,31 +243,31 @@ fn handle_sway_events( | 
			
		
	
		
			
				
					|  |  |  |  |     } | 
			
		
	
		
			
				
					|  |  |  |  | } | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | fn generate_status( | 
			
		
	
		
			
				
					|  |  |  |  | fn generate_status_1( | 
			
		
	
		
			
				
					|  |  |  |  |     mods: &[Box<dyn BarModuleFn>], | 
			
		
	
		
			
				
					|  |  |  |  |     trigger: Arc<(Mutex<NameInstanceAndReason>, Condvar)>, | 
			
		
	
		
			
				
					|  |  |  |  |     refresh_interval: u64, | 
			
		
	
		
			
				
					|  |  |  |  |     name_and_instance: &Option<NameAndInstance>, | 
			
		
	
		
			
				
					|  |  |  |  | ) { | 
			
		
	
		
			
				
					|  |  |  |  |     println!("{{\"version\": 1, \"click_events\": true}}"); | 
			
		
	
		
			
				
					|  |  |  |  |     // status_command should output an infinite array meaning we emit an
 | 
			
		
	
		
			
				
					|  |  |  |  |     // opening [ and never the closing bracket.
 | 
			
		
	
		
			
				
					|  |  |  |  |     println!("["); | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |     let mut name_inst_reason: Option<NameInstanceAndReason> = None; | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |     loop { | 
			
		
	
		
			
				
					|  |  |  |  |     let mut blocks = vec![]; | 
			
		
	
		
			
				
					|  |  |  |  |         let name_and_instance = &name_inst_reason.map(|x| (x.0, x.1)); | 
			
		
	
		
			
				
					|  |  |  |  |     for m in mods { | 
			
		
	
		
			
				
					|  |  |  |  |         blocks.push(m.build(name_and_instance)); | 
			
		
	
		
			
				
					|  |  |  |  |     } | 
			
		
	
		
			
				
					|  |  |  |  |     let json = serde_json::to_string_pretty(&blocks) | 
			
		
	
		
			
				
					|  |  |  |  |         .unwrap_or_else(|_| "".to_string()); | 
			
		
	
		
			
				
					|  |  |  |  |     println!("{},", json); | 
			
		
	
		
			
				
					|  |  |  |  | } | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |         // FIXME: We sometimes miss click or sway events, most probably because
 | 
			
		
	
		
			
				
					|  |  |  |  |         // the corresponding notify_one() is executed when we are not waiting
 | 
			
		
	
		
			
				
					|  |  |  |  |         // here.
 | 
			
		
	
		
			
				
					|  |  |  |  | fn generate_status( | 
			
		
	
		
			
				
					|  |  |  |  |     mods: &[Box<dyn BarModuleFn>], | 
			
		
	
		
			
				
					|  |  |  |  |     trigger: Trigger, | 
			
		
	
		
			
				
					|  |  |  |  |     refresh_interval: u64, | 
			
		
	
		
			
				
					|  |  |  |  | ) { | 
			
		
	
		
			
				
					|  |  |  |  |     println!("{{\"version\": 1, \"click_events\": true}}"); | 
			
		
	
		
			
				
					|  |  |  |  |     // status_command should output an infinite array meaning we emit an
 | 
			
		
	
		
			
				
					|  |  |  |  |     // opening [ and never the closing bracket.
 | 
			
		
	
		
			
				
					|  |  |  |  |     println!("["); | 
			
		
	
		
			
				
					|  |  |  |  |     generate_status_1(mods, &None); | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |     loop { | 
			
		
	
		
			
				
					|  |  |  |  |         let (lock, cvar) = &*trigger; | 
			
		
	
		
			
				
					|  |  |  |  |         let result = cvar | 
			
		
	
		
			
				
					|  |  |  |  |             .wait_timeout( | 
			
		
	
	
		
			
				
					|  |  |  | @ -280,16 +275,19 @@ fn generate_status( | 
			
		
	
		
			
				
					|  |  |  |  |                 Duration::from_millis(refresh_interval), | 
			
		
	
		
			
				
					|  |  |  |  |             ) | 
			
		
	
		
			
				
					|  |  |  |  |             .unwrap(); | 
			
		
	
		
			
				
					|  |  |  |  |         if result.1.timed_out() { | 
			
		
	
		
			
				
					|  |  |  |  |             name_inst_reason = None; | 
			
		
	
		
			
				
					|  |  |  |  |         let mut queue = result.0; | 
			
		
	
		
			
				
					|  |  |  |  |         if queue.is_empty() { | 
			
		
	
		
			
				
					|  |  |  |  |             generate_status_1(mods, &None); | 
			
		
	
		
			
				
					|  |  |  |  |         } else { | 
			
		
	
		
			
				
					|  |  |  |  |             name_inst_reason = Some((*result.0).clone()); | 
			
		
	
		
			
				
					|  |  |  |  |             log::debug!( | 
			
		
	
		
			
				
					|  |  |  |  |                 "Status writing thread woke up early by {} for {}/{}.", | 
			
		
	
		
			
				
					|  |  |  |  |                 &result.0 .2, | 
			
		
	
		
			
				
					|  |  |  |  |                 &result.0 .0, | 
			
		
	
		
			
				
					|  |  |  |  |                 &result.0 .1 | 
			
		
	
		
			
				
					|  |  |  |  |                 "Status writing thread woke up early events:\n{:?}", | 
			
		
	
		
			
				
					|  |  |  |  |                 queue | 
			
		
	
		
			
				
					|  |  |  |  |             ); | 
			
		
	
		
			
				
					|  |  |  |  |             while let Some(name_inst_reason) = queue.pop_front() { | 
			
		
	
		
			
				
					|  |  |  |  |                 let name_and_instance = | 
			
		
	
		
			
				
					|  |  |  |  |                     Some(name_inst_reason).map(|x| (x.0, x.1)); | 
			
		
	
		
			
				
					|  |  |  |  |                 generate_status_1(mods, &name_and_instance); | 
			
		
	
		
			
				
					|  |  |  |  |             } | 
			
		
	
		
			
				
					|  |  |  |  |         } | 
			
		
	
		
			
				
					|  |  |  |  |     } | 
			
		
	
		
			
				
					|  |  |  |  | } | 
			
		
	
	
		
			
				
					|  |  |  | 
 |