diff --git a/docs/content/main/troubleshooting.md b/docs/content/main/troubleshooting.md index 1cf7440..e5f3ae9 100644 --- a/docs/content/main/troubleshooting.md +++ b/docs/content/main/troubleshooting.md @@ -28,10 +28,10 @@ If none of these fixed your problem [open an issue on the GitHub repo.](https:// ### General issues -You should try the following things, before opening a issue or doing more specialized troubleshooting: +You should try the following things, before opening a issue or doing more specialized troubleshooting: -- Try killing the eww daemon with `eww kill` and run again -- If you're running with `-d`, run without `-d` to see output, or run `eww logs` to see the logs written by eww. These logs are stored in `~/.cache/eww.log`. +- Kill the eww daemon by running `eww kill` and restart it with `eww --debug daemon` to get additional log output. +- Now you can take a look at the logs by running `eww logs`. - use `eww state`, to see the state of all variables - use `eww debug`, to see the xml of your widget and other information - update to the latest eww version @@ -42,4 +42,4 @@ If you're experiencing issues printing variables, try to print them in quotes, s onchange="notify-send '{}'" ``` -Remember if your issue isn't listed here, [open an issue on the GitHub repo](https://github.com/elkowar/eww/issues). +Remember, if your issue isn't listed here, [open an issue on the GitHub repo](https://github.com/elkowar/eww/issues). diff --git a/src/app.rs b/src/app.rs index ed6bb09..4d9fbd7 100644 --- a/src/app.rs +++ b/src/app.rs @@ -11,7 +11,7 @@ use debug_stub_derive::*; use gdk::WindowExt; use gtk::{ContainerExt, CssProviderExt, GtkWindowExt, StyleContextExt, WidgetExt}; use itertools::Itertools; -use std::collections::{HashMap, HashSet}; +use std::collections::HashMap; use tokio::sync::mpsc::UnboundedSender; #[derive(Debug)] @@ -135,25 +135,16 @@ impl App { } fn close_window(&mut self, window_name: &WindowName) -> Result<()> { + for unused_var in self.variables_only_used_in(&window_name) { + log::info!("stopping for {}", &unused_var); + self.script_var_handler.stop_for_variable(unused_var.clone()); + } + let window = self .windows .remove(window_name) .context(format!("No window with name '{}' is running.", window_name))?; - // Stop script-var handlers for variables that where only referenced by this window - // TODO somehow make this whole process less shit. - let currently_used_vars = self.get_currently_used_variables().cloned().collect::>(); - - for unused_var in self - .eww_state - .vars_referenced_in(window_name) - .into_iter() - .filter(|var| !currently_used_vars.contains(*var)) - { - println!("stopping for {}", &unused_var); - self.script_var_handler.stop_for_variable(unused_var.clone()); - } - window.close(); self.eww_state.clear_window_state(window_name); @@ -172,10 +163,6 @@ impl App { log::info!("Opening window {}", window_name); - // remember which variables are used before opening the window, to then - // set up the necessary handlers for the newly used variables. - let currently_used_vars = self.get_currently_used_variables().cloned().collect::>(); - let mut window_def = self.eww_config.get_window(window_name)?.clone(); window_def.geometry = window_def.geometry.override_if_given(anchor, pos, size); @@ -191,26 +178,17 @@ impl App { let monitor_geometry = get_monitor_geometry(window_def.screen_number.unwrap_or_else(get_default_monitor_index)); let eww_window = initialize_window(monitor_geometry, root_widget, window_def)?; + self.windows.insert(window_name.clone(), eww_window); + // initialize script var handlers for variables that where not used before opening this window. // TODO somehow make this less shit - let newly_used_vars = self - .eww_state - .vars_referenced_in(window_name) - .into_iter() - .filter(|x| !currently_used_vars.contains(*x)) - .collect_vec() - .clone(); - - // TODO all of the cloning above is highly ugly.... REEEEEEEEEEEEEEEEEEEEEEEEEEEEEE - for newly_used_var in newly_used_vars { - let value = self.eww_config.get_script_var(&newly_used_var); - if let Some(value) = value { - self.script_var_handler.add(value.clone()); - } + for newly_used_var in self + .variables_only_used_in(&window_name) + .filter_map(|var| self.eww_config.get_script_var(&var)) + { + self.script_var_handler.add(newly_used_var.clone()); } - self.windows.insert(window_name.clone(), eww_window); - Ok(()) } @@ -235,8 +213,32 @@ impl App { Ok(()) } + /// Get all variable names that are currently referenced in any of the open windows. pub fn get_currently_used_variables(&self) -> impl Iterator { - self.eww_state.referenced_vars() + self.windows + .keys() + .flat_map(move |window_name| self.eww_state.vars_referenced_in(window_name)) + } + + /// Get all variables mapped to a list of windows they are being used in. + pub fn currently_used_variables<'a>(&'a self) -> HashMap<&'a VarName, Vec<&'a WindowName>> { + let mut vars: HashMap<&'a VarName, Vec<_>> = HashMap::new(); + for window_name in self.windows.keys() { + for var in self.eww_state.vars_referenced_in(window_name) { + vars.entry(var) + .and_modify(|l| l.push(window_name)) + .or_insert_with(|| vec![window_name]); + } + } + vars + } + + /// Get all variables that are only used in the given window. + pub fn variables_only_used_in<'a>(&'a self, window: &'a WindowName) -> impl Iterator { + self.currently_used_variables() + .into_iter() + .filter(move |(_, wins)| wins.len() == 1 && wins.contains(&window)) + .map(|(var, _)| var) } } diff --git a/src/main.rs b/src/main.rs index 6659cb4..ae7e457 100644 --- a/src/main.rs +++ b/src/main.rs @@ -43,11 +43,19 @@ lazy_static::lazy_static! { } fn main() { - pretty_env_logger::init(); + let opts: opts::Opt = opts::Opt::from_env(); + + let log_level_filter = if opts.log_debug { + log::LevelFilter::Debug + } else { + log::LevelFilter::Off + }; + + pretty_env_logger::formatted_builder() + .filter(Some("eww"), log_level_filter) + .init(); let result: Result<_> = try { - let opts: opts::Opt = opts::Opt::from_env(); - match opts.action { opts::Action::ClientOnly(action) => { client::handle_client_only_action(action)?; diff --git a/src/opts.rs b/src/opts.rs index 3abafd9..3908bcb 100644 --- a/src/opts.rs +++ b/src/opts.rs @@ -8,14 +8,19 @@ use crate::{ value::{Coords, PrimitiveValue, VarName}, }; +/// Struct that gets generated from `RawOpt`. #[derive(Debug, Serialize, Deserialize, PartialEq)] pub struct Opt { + pub log_debug: bool, pub action: Action, } -/// Helper struct that will be normalized into instance of [Opt] #[derive(StructOpt, Debug, Serialize, Deserialize, PartialEq)] struct RawOpt { + /// Write out debug logs. (To read the logs, run `eww logs`). + #[structopt(long = "debug")] + log_debug: bool, + #[structopt(subcommand)] action: Action, } @@ -111,8 +116,8 @@ impl Opt { impl From for Opt { fn from(other: RawOpt) -> Self { - let RawOpt { action } = other; - Opt { action } + let RawOpt { action, log_debug } = other; + Opt { action, log_debug } } } diff --git a/src/server.rs b/src/server.rs index b8692fb..7c14fcc 100644 --- a/src/server.rs +++ b/src/server.rs @@ -89,6 +89,7 @@ fn init_async_part(config_file_path: PathBuf, scss_file_path: PathBuf, ui_send: tokio::spawn(async move { // Wait for application exit event let _ = crate::application_lifecycle::recv_exit().await; + log::info!("Forward task received exit event"); // Then forward that to the application let _ = ui_send.send(app::EwwCommand::KillServer); })