Fix script-vars being ran without window using them, and add debug flag. fixes #94.

This commit is contained in:
elkowar 2021-01-16 16:14:03 +01:00
parent 23db60508e
commit 6c2e0dbbc1
5 changed files with 62 additions and 46 deletions

View file

@ -30,8 +30,8 @@ If none of these fixed your problem [open an issue on the GitHub repo.](https://
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 - Kill the eww daemon by running `eww kill` and restart it with `eww --debug daemon` to get additional log output.
- 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`. - 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 state`, to see the state of all variables
- use `eww debug`, to see the xml of your widget and other information - use `eww debug`, to see the xml of your widget and other information
- update to the latest eww version - 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 '{}'" 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).

View file

@ -11,7 +11,7 @@ use debug_stub_derive::*;
use gdk::WindowExt; use gdk::WindowExt;
use gtk::{ContainerExt, CssProviderExt, GtkWindowExt, StyleContextExt, WidgetExt}; use gtk::{ContainerExt, CssProviderExt, GtkWindowExt, StyleContextExt, WidgetExt};
use itertools::Itertools; use itertools::Itertools;
use std::collections::{HashMap, HashSet}; use std::collections::HashMap;
use tokio::sync::mpsc::UnboundedSender; use tokio::sync::mpsc::UnboundedSender;
#[derive(Debug)] #[derive(Debug)]
@ -135,25 +135,16 @@ impl App {
} }
fn close_window(&mut self, window_name: &WindowName) -> Result<()> { 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 let window = self
.windows .windows
.remove(window_name) .remove(window_name)
.context(format!("No window with name '{}' is running.", 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::<HashSet<VarName>>();
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(); window.close();
self.eww_state.clear_window_state(window_name); self.eww_state.clear_window_state(window_name);
@ -172,10 +163,6 @@ impl App {
log::info!("Opening window {}", window_name); 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::<HashSet<_>>();
let mut window_def = self.eww_config.get_window(window_name)?.clone(); let mut window_def = self.eww_config.get_window(window_name)?.clone();
window_def.geometry = window_def.geometry.override_if_given(anchor, pos, size); 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 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)?; 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. // initialize script var handlers for variables that where not used before opening this window.
// TODO somehow make this less shit // TODO somehow make this less shit
let newly_used_vars = self for newly_used_var in self
.eww_state .variables_only_used_in(&window_name)
.vars_referenced_in(window_name) .filter_map(|var| self.eww_config.get_script_var(&var))
.into_iter() {
.filter(|x| !currently_used_vars.contains(*x)) self.script_var_handler.add(newly_used_var.clone());
.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());
}
} }
self.windows.insert(window_name.clone(), eww_window);
Ok(()) Ok(())
} }
@ -235,8 +213,32 @@ impl App {
Ok(()) Ok(())
} }
/// Get all variable names that are currently referenced in any of the open windows.
pub fn get_currently_used_variables(&self) -> impl Iterator<Item = &VarName> { pub fn get_currently_used_variables(&self) -> impl Iterator<Item = &VarName> {
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<Item = &'a VarName> {
self.currently_used_variables()
.into_iter()
.filter(move |(_, wins)| wins.len() == 1 && wins.contains(&window))
.map(|(var, _)| var)
} }
} }

View file

@ -43,11 +43,19 @@ lazy_static::lazy_static! {
} }
fn main() { 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 result: Result<_> = try {
let opts: opts::Opt = opts::Opt::from_env();
match opts.action { match opts.action {
opts::Action::ClientOnly(action) => { opts::Action::ClientOnly(action) => {
client::handle_client_only_action(action)?; client::handle_client_only_action(action)?;

View file

@ -8,14 +8,19 @@ use crate::{
value::{Coords, PrimitiveValue, VarName}, value::{Coords, PrimitiveValue, VarName},
}; };
/// Struct that gets generated from `RawOpt`.
#[derive(Debug, Serialize, Deserialize, PartialEq)] #[derive(Debug, Serialize, Deserialize, PartialEq)]
pub struct Opt { pub struct Opt {
pub log_debug: bool,
pub action: Action, pub action: Action,
} }
/// Helper struct that will be normalized into instance of [Opt]
#[derive(StructOpt, Debug, Serialize, Deserialize, PartialEq)] #[derive(StructOpt, Debug, Serialize, Deserialize, PartialEq)]
struct RawOpt { struct RawOpt {
/// Write out debug logs. (To read the logs, run `eww logs`).
#[structopt(long = "debug")]
log_debug: bool,
#[structopt(subcommand)] #[structopt(subcommand)]
action: Action, action: Action,
} }
@ -111,8 +116,8 @@ impl Opt {
impl From<RawOpt> for Opt { impl From<RawOpt> for Opt {
fn from(other: RawOpt) -> Self { fn from(other: RawOpt) -> Self {
let RawOpt { action } = other; let RawOpt { action, log_debug } = other;
Opt { action } Opt { action, log_debug }
} }
} }

View file

@ -89,6 +89,7 @@ fn init_async_part(config_file_path: PathBuf, scss_file_path: PathBuf, ui_send:
tokio::spawn(async move { tokio::spawn(async move {
// Wait for application exit event // Wait for application exit event
let _ = crate::application_lifecycle::recv_exit().await; let _ = crate::application_lifecycle::recv_exit().await;
log::info!("Forward task received exit event");
// Then forward that to the application // Then forward that to the application
let _ = ui_send.send(app::EwwCommand::KillServer); let _ = ui_send.send(app::EwwCommand::KillServer);
}) })