Clean up file structure, and add Struts tag which isn't functional yet
This commit is contained in:
parent
11eafe5d5f
commit
4573f056b0
12 changed files with 374 additions and 282 deletions
75
Cargo.lock
generated
75
Cargo.lock
generated
|
@ -305,6 +305,7 @@ dependencies = [
|
||||||
"extend",
|
"extend",
|
||||||
"gdk",
|
"gdk",
|
||||||
"gdk-pixbuf",
|
"gdk-pixbuf",
|
||||||
|
"gdkx11",
|
||||||
"gio",
|
"gio",
|
||||||
"glib",
|
"glib",
|
||||||
"grass",
|
"grass",
|
||||||
|
@ -315,6 +316,7 @@ dependencies = [
|
||||||
"libc",
|
"libc",
|
||||||
"log 0.4.11",
|
"log 0.4.11",
|
||||||
"maplit",
|
"maplit",
|
||||||
|
"nix",
|
||||||
"notify",
|
"notify",
|
||||||
"num",
|
"num",
|
||||||
"popol",
|
"popol",
|
||||||
|
@ -325,6 +327,7 @@ dependencies = [
|
||||||
"roxmltree",
|
"roxmltree",
|
||||||
"scheduled-executor",
|
"scheduled-executor",
|
||||||
"serde",
|
"serde",
|
||||||
|
"smart-default",
|
||||||
"stoppable_thread",
|
"stoppable_thread",
|
||||||
"structopt",
|
"structopt",
|
||||||
"try_match",
|
"try_match",
|
||||||
|
@ -571,6 +574,45 @@ dependencies = [
|
||||||
"system-deps",
|
"system-deps",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "gdkx11"
|
||||||
|
version = "0.9.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "b89606baa221f9b8d8aa81924fd448c6b107d20de949f0fbf9a4ec203bb54b63"
|
||||||
|
dependencies = [
|
||||||
|
"bitflags",
|
||||||
|
"gdk",
|
||||||
|
"gdk-pixbuf",
|
||||||
|
"gdk-pixbuf-sys",
|
||||||
|
"gdk-sys",
|
||||||
|
"gdkx11-sys",
|
||||||
|
"gio",
|
||||||
|
"gio-sys",
|
||||||
|
"glib",
|
||||||
|
"glib-sys",
|
||||||
|
"gobject-sys",
|
||||||
|
"libc",
|
||||||
|
"pango",
|
||||||
|
"x11",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "gdkx11-sys"
|
||||||
|
version = "0.10.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "6710388d530f3178ccbeb65cbafdf497a5772c4409eaf574ee9fa461af0a3d09"
|
||||||
|
dependencies = [
|
||||||
|
"gdk-pixbuf-sys",
|
||||||
|
"gdk-sys",
|
||||||
|
"gio-sys",
|
||||||
|
"glib-sys",
|
||||||
|
"gobject-sys",
|
||||||
|
"libc",
|
||||||
|
"pango-sys",
|
||||||
|
"system-deps",
|
||||||
|
"x11",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "getrandom"
|
name = "getrandom"
|
||||||
version = "0.1.15"
|
version = "0.1.15"
|
||||||
|
@ -995,6 +1037,18 @@ dependencies = [
|
||||||
"winapi 0.3.9",
|
"winapi 0.3.9",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "nix"
|
||||||
|
version = "0.19.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "85db2feff6bf70ebc3a4793191517d5f0331100a2f10f9bf93b5e5214f32b7b7"
|
||||||
|
dependencies = [
|
||||||
|
"bitflags",
|
||||||
|
"cc",
|
||||||
|
"cfg-if",
|
||||||
|
"libc",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "notify"
|
name = "notify"
|
||||||
version = "4.0.15"
|
version = "4.0.15"
|
||||||
|
@ -1572,6 +1626,17 @@ version = "1.4.2"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "fbee7696b84bbf3d89a1c2eccff0850e3047ed46bfcd2e92c29a2d074d57e252"
|
checksum = "fbee7696b84bbf3d89a1c2eccff0850e3047ed46bfcd2e92c29a2d074d57e252"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "smart-default"
|
||||||
|
version = "0.6.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "133659a15339456eeeb07572eb02a91c91e9815e9cbc89566944d2c8d3efdbf6"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
"quote 1.0.7",
|
||||||
|
"syn 1.0.44",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "stoppable_thread"
|
name = "stoppable_thread"
|
||||||
version = "0.2.1"
|
version = "0.2.1"
|
||||||
|
@ -2064,6 +2129,16 @@ dependencies = [
|
||||||
"winapi-build",
|
"winapi-build",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "x11"
|
||||||
|
version = "2.18.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "77ecd092546cb16f25783a5451538e73afc8d32e242648d54f4ae5459ba1e773"
|
||||||
|
dependencies = [
|
||||||
|
"libc",
|
||||||
|
"pkg-config",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "xmlparser"
|
name = "xmlparser"
|
||||||
version = "0.13.3"
|
version = "0.13.3"
|
||||||
|
|
|
@ -14,6 +14,7 @@ gtk = { version = "0.9", features = [ "v3_16" ] }
|
||||||
gdk = { version = "", features = ["v3_16"] }
|
gdk = { version = "", features = ["v3_16"] }
|
||||||
gio = { version = "", features = ["v2_44"] }
|
gio = { version = "", features = ["v2_44"] }
|
||||||
glib = { version = "", features = ["v2_44"] }
|
glib = { version = "", features = ["v2_44"] }
|
||||||
|
gdkx11 = "0.9"
|
||||||
gdk-pixbuf = "0.9"
|
gdk-pixbuf = "0.9"
|
||||||
|
|
||||||
regex = "1"
|
regex = "1"
|
||||||
|
@ -42,6 +43,7 @@ libc = "0.2"
|
||||||
ref-cast = "1.0"
|
ref-cast = "1.0"
|
||||||
popol = "0.3"
|
popol = "0.3"
|
||||||
nix = "0.19"
|
nix = "0.19"
|
||||||
|
smart-default = "0.6"
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
pretty_assertions = "0.6.1"
|
pretty_assertions = "0.6.1"
|
||||||
|
|
13
src/app.rs
13
src/app.rs
|
@ -1,6 +1,6 @@
|
||||||
use crate::{
|
use crate::{
|
||||||
config,
|
config,
|
||||||
config::{WindowName, WindowStacking},
|
config::{window_definition::WindowName, WindowStacking},
|
||||||
eww_state,
|
eww_state,
|
||||||
script_var_handler::*,
|
script_var_handler::*,
|
||||||
util,
|
util,
|
||||||
|
@ -11,6 +11,7 @@ use anyhow::*;
|
||||||
use crossbeam_channel;
|
use crossbeam_channel;
|
||||||
use debug_stub_derive::*;
|
use debug_stub_derive::*;
|
||||||
use gdk::WindowExt;
|
use gdk::WindowExt;
|
||||||
|
use glib::Cast;
|
||||||
use gtk::{ContainerExt, CssProviderExt, GtkWindowExt, StyleContextExt, WidgetExt};
|
use gtk::{ContainerExt, CssProviderExt, GtkWindowExt, StyleContextExt, WidgetExt};
|
||||||
use itertools::Itertools;
|
use itertools::Itertools;
|
||||||
|
|
||||||
|
@ -36,7 +37,7 @@ pub enum EwwCommand {
|
||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq)]
|
#[derive(Debug, Clone, PartialEq)]
|
||||||
pub struct EwwWindow {
|
pub struct EwwWindow {
|
||||||
pub name: config::WindowName,
|
pub name: WindowName,
|
||||||
pub definition: config::EwwWindowDefinition,
|
pub definition: config::EwwWindowDefinition,
|
||||||
pub gtk_window: gtk::Window,
|
pub gtk_window: gtk::Window,
|
||||||
}
|
}
|
||||||
|
@ -45,7 +46,7 @@ pub struct EwwWindow {
|
||||||
pub struct App {
|
pub struct App {
|
||||||
pub eww_state: eww_state::EwwState,
|
pub eww_state: eww_state::EwwState,
|
||||||
pub eww_config: config::EwwConfig,
|
pub eww_config: config::EwwConfig,
|
||||||
pub windows: HashMap<config::WindowName, EwwWindow>,
|
pub windows: HashMap<WindowName, EwwWindow>,
|
||||||
pub css_provider: gtk::CssProvider,
|
pub css_provider: gtk::CssProvider,
|
||||||
pub app_evt_send: glib::Sender<EwwCommand>,
|
pub app_evt_send: glib::Sender<EwwCommand>,
|
||||||
#[debug_stub = "ScriptVarHandler(...)"]
|
#[debug_stub = "ScriptVarHandler(...)"]
|
||||||
|
@ -87,7 +88,7 @@ impl App {
|
||||||
self.eww_state.update_variable(fieldname, value)
|
self.eww_state.update_variable(fieldname, value)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn close_window(&mut self, window_name: &config::WindowName) -> Result<()> {
|
fn close_window(&mut self, window_name: &WindowName) -> Result<()> {
|
||||||
let window = self
|
let window = self
|
||||||
.windows
|
.windows
|
||||||
.remove(window_name)
|
.remove(window_name)
|
||||||
|
@ -98,7 +99,7 @@ impl App {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn open_window(&mut self, window_name: &config::WindowName, pos: Option<Coords>, size: Option<Coords>) -> Result<()> {
|
fn open_window(&mut self, window_name: &WindowName, pos: Option<Coords>, size: Option<Coords>) -> Result<()> {
|
||||||
// remove and close existing window with the same name
|
// remove and close existing window with the same name
|
||||||
let _ = self.close_window(window_name);
|
let _ = self.close_window(window_name);
|
||||||
|
|
||||||
|
@ -150,13 +151,11 @@ impl App {
|
||||||
root_widget.get_style_context().add_class(&window_name.to_string());
|
root_widget.get_style_context().add_class(&window_name.to_string());
|
||||||
window.add(root_widget);
|
window.add(root_widget);
|
||||||
|
|
||||||
// REAL SHIT 0_o :elkowar_with_a_looking_glass:
|
|
||||||
window.show_all();
|
window.show_all();
|
||||||
|
|
||||||
let gdk_window = window.get_window().context("couldn't get gdk window from gtk window")?;
|
let gdk_window = window.get_window().context("couldn't get gdk window from gtk window")?;
|
||||||
gdk_window.set_override_redirect(true);
|
gdk_window.set_override_redirect(true);
|
||||||
gdk_window.move_(actual_window_rect.x, actual_window_rect.y);
|
gdk_window.move_(actual_window_rect.x, actual_window_rect.y);
|
||||||
gdk_window.show();
|
|
||||||
|
|
||||||
if window_def.stacking == WindowStacking::Foreground {
|
if window_def.stacking == WindowStacking::Foreground {
|
||||||
gdk_window.raise();
|
gdk_window.raise();
|
||||||
|
|
114
src/config/eww_config.rs
Normal file
114
src/config/eww_config.rs
Normal file
|
@ -0,0 +1,114 @@
|
||||||
|
use anyhow::*;
|
||||||
|
use std::collections::HashMap;
|
||||||
|
|
||||||
|
use crate::{
|
||||||
|
util,
|
||||||
|
value::{PrimitiveValue, VarName},
|
||||||
|
};
|
||||||
|
|
||||||
|
use super::{
|
||||||
|
element::WidgetDefinition,
|
||||||
|
xml_ext::{XmlElement, XmlNode},
|
||||||
|
EwwWindowDefinition, ScriptVar, WindowName,
|
||||||
|
};
|
||||||
|
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
pub struct EwwConfig {
|
||||||
|
widgets: HashMap<String, WidgetDefinition>,
|
||||||
|
windows: HashMap<WindowName, EwwWindowDefinition>,
|
||||||
|
initial_variables: HashMap<VarName, PrimitiveValue>,
|
||||||
|
script_vars: Vec<ScriptVar>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl EwwConfig {
|
||||||
|
pub fn read_from_file<P: AsRef<std::path::Path>>(path: P) -> Result<Self> {
|
||||||
|
let content = util::replace_env_var_references(std::fs::read_to_string(path)?);
|
||||||
|
let document = roxmltree::Document::parse(&content)?;
|
||||||
|
|
||||||
|
let result = EwwConfig::from_xml_element(XmlNode::from(document.root_element()).as_element()?.clone());
|
||||||
|
result
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn from_xml_element(xml: XmlElement) -> Result<Self> {
|
||||||
|
let definitions = xml
|
||||||
|
.child("definitions")?
|
||||||
|
.child_elements()
|
||||||
|
.map(|child| {
|
||||||
|
let def = WidgetDefinition::from_xml_element(child)?;
|
||||||
|
Ok((def.name.clone(), def))
|
||||||
|
})
|
||||||
|
.collect::<Result<HashMap<_, _>>>()
|
||||||
|
.context("error parsing widget definitions")?;
|
||||||
|
|
||||||
|
let windows = xml
|
||||||
|
.child("windows")?
|
||||||
|
.child_elements()
|
||||||
|
.map(|child| {
|
||||||
|
Ok((
|
||||||
|
WindowName::from(child.attr("name")?.to_owned()),
|
||||||
|
EwwWindowDefinition::from_xml_element(child)?,
|
||||||
|
))
|
||||||
|
})
|
||||||
|
.collect::<Result<HashMap<_, _>>>()
|
||||||
|
.context("error parsing window definitions")?;
|
||||||
|
|
||||||
|
let variables_block = xml.child("variables").ok();
|
||||||
|
|
||||||
|
let mut initial_variables = HashMap::new();
|
||||||
|
let mut script_vars = Vec::new();
|
||||||
|
if let Some(variables_block) = variables_block {
|
||||||
|
for node in variables_block.child_elements() {
|
||||||
|
match node.tag_name() {
|
||||||
|
"var" => {
|
||||||
|
initial_variables.insert(
|
||||||
|
VarName(node.attr("name")?.to_owned()),
|
||||||
|
PrimitiveValue::from_string(
|
||||||
|
node.only_child()
|
||||||
|
.map(|c| c.as_text_or_sourcecode())
|
||||||
|
.unwrap_or_else(|_| String::new()),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
"script-var" => {
|
||||||
|
script_vars.push(ScriptVar::from_xml_element(node)?);
|
||||||
|
}
|
||||||
|
_ => bail!("Illegal element in variables block: {}", node.as_tag_string()),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(EwwConfig {
|
||||||
|
widgets: definitions,
|
||||||
|
windows,
|
||||||
|
initial_variables,
|
||||||
|
script_vars,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO this is kinda ugly
|
||||||
|
pub fn generate_initial_state(&self) -> Result<HashMap<VarName, PrimitiveValue>> {
|
||||||
|
let mut vars = self
|
||||||
|
.script_vars
|
||||||
|
.iter()
|
||||||
|
.map(|var| Ok((var.name().clone(), var.initial_value()?)))
|
||||||
|
.collect::<Result<HashMap<_, _>>>()?;
|
||||||
|
vars.extend(self.get_default_vars().clone());
|
||||||
|
Ok(vars)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_widgets(&self) -> &HashMap<String, WidgetDefinition> {
|
||||||
|
&self.widgets
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_windows(&self) -> &HashMap<WindowName, EwwWindowDefinition> {
|
||||||
|
&self.windows
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_default_vars(&self) -> &HashMap<VarName, PrimitiveValue> {
|
||||||
|
&self.initial_variables
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_script_vars(&self) -> &Vec<ScriptVar> {
|
||||||
|
&self.script_vars
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,16 +1,20 @@
|
||||||
use crate::{
|
use crate::{
|
||||||
util,
|
util,
|
||||||
value::{Coords, PrimitiveValue, VarName},
|
value::{PrimitiveValue, VarName},
|
||||||
};
|
};
|
||||||
use anyhow::*;
|
use anyhow::*;
|
||||||
use derive_more;
|
|
||||||
use element::*;
|
use element::*;
|
||||||
use serde::{Deserialize, Serialize};
|
|
||||||
use std::{collections::HashMap, fmt};
|
|
||||||
use xml_ext::*;
|
use xml_ext::*;
|
||||||
|
|
||||||
pub mod element;
|
pub mod element;
|
||||||
|
pub mod eww_config;
|
||||||
|
pub mod script_var;
|
||||||
|
pub mod window_definition;
|
||||||
pub mod xml_ext;
|
pub mod xml_ext;
|
||||||
|
pub use eww_config::*;
|
||||||
|
pub use script_var::*;
|
||||||
|
pub use window_definition::*;
|
||||||
|
|
||||||
#[macro_export]
|
#[macro_export]
|
||||||
macro_rules! ensure_xml_tag_is {
|
macro_rules! ensure_xml_tag_is {
|
||||||
|
@ -26,234 +30,3 @@ macro_rules! ensure_xml_tag_is {
|
||||||
)
|
)
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, PartialEq)]
|
|
||||||
pub struct PollScriptVar {
|
|
||||||
pub name: VarName,
|
|
||||||
pub command: String,
|
|
||||||
pub interval: std::time::Duration,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Clone, Debug, PartialEq)]
|
|
||||||
pub struct TailScriptVar {
|
|
||||||
pub name: VarName,
|
|
||||||
pub command: String,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Clone, Debug, PartialEq)]
|
|
||||||
pub enum ScriptVar {
|
|
||||||
Poll(PollScriptVar),
|
|
||||||
Tail(TailScriptVar),
|
|
||||||
}
|
|
||||||
|
|
||||||
impl ScriptVar {
|
|
||||||
pub fn name(&self) -> &VarName {
|
|
||||||
match self {
|
|
||||||
ScriptVar::Poll(x) => &x.name,
|
|
||||||
ScriptVar::Tail(x) => &x.name,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn initial_value(&self) -> Result<PrimitiveValue> {
|
|
||||||
match self {
|
|
||||||
ScriptVar::Poll(x) => Ok(crate::run_command(&x.command)?),
|
|
||||||
ScriptVar::Tail(_) => Ok(PrimitiveValue::from_string(String::new())),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn from_xml_element(xml: XmlElement) -> Result<Self> {
|
|
||||||
ensure_xml_tag_is!(xml, "script-var");
|
|
||||||
|
|
||||||
let name = VarName(xml.attr("name")?.to_owned());
|
|
||||||
let command = xml.only_child()?.as_text()?.text();
|
|
||||||
if let Ok(interval) = xml.attr("interval") {
|
|
||||||
let interval = util::parse_duration(interval)?;
|
|
||||||
Ok(ScriptVar::Poll(PollScriptVar { name, command, interval }))
|
|
||||||
} else {
|
|
||||||
Ok(ScriptVar::Tail(TailScriptVar { name, command }))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
|
||||||
pub struct EwwConfig {
|
|
||||||
widgets: HashMap<String, WidgetDefinition>,
|
|
||||||
windows: HashMap<WindowName, EwwWindowDefinition>,
|
|
||||||
initial_variables: HashMap<VarName, PrimitiveValue>,
|
|
||||||
script_vars: Vec<ScriptVar>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl EwwConfig {
|
|
||||||
pub fn read_from_file<P: AsRef<std::path::Path>>(path: P) -> Result<Self> {
|
|
||||||
let content = util::replace_env_var_references(std::fs::read_to_string(path)?);
|
|
||||||
let document = roxmltree::Document::parse(&content)?;
|
|
||||||
|
|
||||||
let result = EwwConfig::from_xml_element(XmlNode::from(document.root_element()).as_element()?.clone());
|
|
||||||
result
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn from_xml_element(xml: XmlElement) -> Result<Self> {
|
|
||||||
let definitions = xml
|
|
||||||
.child("definitions")?
|
|
||||||
.child_elements()
|
|
||||||
.map(|child| {
|
|
||||||
let def = WidgetDefinition::from_xml_element(child)?;
|
|
||||||
Ok((def.name.clone(), def))
|
|
||||||
})
|
|
||||||
.collect::<Result<HashMap<_, _>>>()
|
|
||||||
.context("error parsing widget definitions")?;
|
|
||||||
|
|
||||||
let windows = xml
|
|
||||||
.child("windows")?
|
|
||||||
.child_elements()
|
|
||||||
.map(|child| {
|
|
||||||
Ok((
|
|
||||||
WindowName(child.attr("name")?.to_owned()),
|
|
||||||
EwwWindowDefinition::from_xml_element(child)?,
|
|
||||||
))
|
|
||||||
})
|
|
||||||
.collect::<Result<HashMap<_, _>>>()
|
|
||||||
.context("error parsing window definitions")?;
|
|
||||||
|
|
||||||
let variables_block = xml.child("variables").ok();
|
|
||||||
|
|
||||||
let mut initial_variables = HashMap::new();
|
|
||||||
let mut script_vars = Vec::new();
|
|
||||||
if let Some(variables_block) = variables_block {
|
|
||||||
for node in variables_block.child_elements() {
|
|
||||||
match node.tag_name() {
|
|
||||||
"var" => {
|
|
||||||
initial_variables.insert(
|
|
||||||
VarName(node.attr("name")?.to_owned()),
|
|
||||||
PrimitiveValue::from_string(
|
|
||||||
node.only_child()
|
|
||||||
.map(|c| c.as_text_or_sourcecode())
|
|
||||||
.unwrap_or_else(|_| String::new()),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
"script-var" => {
|
|
||||||
script_vars.push(ScriptVar::from_xml_element(node)?);
|
|
||||||
}
|
|
||||||
_ => bail!("Illegal element in variables block: {}", node.as_tag_string()),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(EwwConfig {
|
|
||||||
widgets: definitions,
|
|
||||||
windows,
|
|
||||||
initial_variables,
|
|
||||||
script_vars,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO this is kinda ugly
|
|
||||||
pub fn generate_initial_state(&self) -> Result<HashMap<VarName, PrimitiveValue>> {
|
|
||||||
let mut vars = self
|
|
||||||
.script_vars
|
|
||||||
.iter()
|
|
||||||
.map(|var| Ok((var.name().clone(), var.initial_value()?)))
|
|
||||||
.collect::<Result<HashMap<_, _>>>()?;
|
|
||||||
vars.extend(self.get_default_vars().clone());
|
|
||||||
Ok(vars)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn get_widgets(&self) -> &HashMap<String, WidgetDefinition> {
|
|
||||||
&self.widgets
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn get_windows(&self) -> &HashMap<WindowName, EwwWindowDefinition> {
|
|
||||||
&self.windows
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn get_default_vars(&self) -> &HashMap<VarName, PrimitiveValue> {
|
|
||||||
&self.initial_variables
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn get_script_vars(&self) -> &Vec<ScriptVar> {
|
|
||||||
&self.script_vars
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[repr(transparent)]
|
|
||||||
#[derive(Clone, Hash, PartialEq, Eq, derive_more::AsRef, derive_more::From, derive_more::FromStr, Serialize, Deserialize)]
|
|
||||||
pub struct WindowName(String);
|
|
||||||
|
|
||||||
impl std::borrow::Borrow<str> for WindowName {
|
|
||||||
fn borrow(&self) -> &str {
|
|
||||||
&self.0
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl fmt::Display for WindowName {
|
|
||||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
|
||||||
write!(f, "{}", self.0)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl fmt::Debug for WindowName {
|
|
||||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
|
||||||
write!(f, "WindowName(\"{}\")", self.0)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq)]
|
|
||||||
pub struct EwwWindowDefinition {
|
|
||||||
pub position: Coords,
|
|
||||||
pub size: Coords,
|
|
||||||
pub stacking: WindowStacking,
|
|
||||||
pub screen_number: Option<i32>,
|
|
||||||
pub widget: WidgetUse,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl EwwWindowDefinition {
|
|
||||||
pub fn from_xml_element(xml: XmlElement) -> Result<Self> {
|
|
||||||
ensure_xml_tag_is!(xml, "window");
|
|
||||||
|
|
||||||
let size_node = xml.child("size")?;
|
|
||||||
let size = Coords::from_strs(size_node.attr("x")?, size_node.attr("y")?)?;
|
|
||||||
let pos_node = xml.child("pos")?;
|
|
||||||
let position = Coords::from_strs(pos_node.attr("x")?, pos_node.attr("y")?)?;
|
|
||||||
|
|
||||||
let stacking = xml.attr("stacking").ok().map(|x| x.parse()).transpose()?.unwrap_or_default();
|
|
||||||
let screen_number = xml.attr("screen").ok().map(|x| x.parse()).transpose()?;
|
|
||||||
|
|
||||||
let widget = WidgetUse::from_xml_node(xml.child("widget")?.only_child()?)?;
|
|
||||||
Ok(EwwWindowDefinition {
|
|
||||||
position,
|
|
||||||
size,
|
|
||||||
widget,
|
|
||||||
stacking,
|
|
||||||
screen_number,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, derive_more::Display)]
|
|
||||||
pub enum WindowStacking {
|
|
||||||
Foreground,
|
|
||||||
Background,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Default for WindowStacking {
|
|
||||||
fn default() -> Self {
|
|
||||||
WindowStacking::Foreground
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl std::str::FromStr for WindowStacking {
|
|
||||||
type Err = anyhow::Error;
|
|
||||||
|
|
||||||
fn from_str(s: &str) -> Result<Self> {
|
|
||||||
let s = s.to_lowercase();
|
|
||||||
match s.as_str() {
|
|
||||||
"foreground" | "fg" | "f" => Ok(WindowStacking::Foreground),
|
|
||||||
"background" | "bg" | "b" => Ok(WindowStacking::Background),
|
|
||||||
_ => Err(anyhow!(
|
|
||||||
"Couldn't parse '{}' as window stacking, must be either foreground, fg, background or bg",
|
|
||||||
s
|
|
||||||
)),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
53
src/config/script_var.rs
Normal file
53
src/config/script_var.rs
Normal file
|
@ -0,0 +1,53 @@
|
||||||
|
use anyhow::*;
|
||||||
|
|
||||||
|
use crate::ensure_xml_tag_is;
|
||||||
|
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
#[derive(Clone, Debug, PartialEq)]
|
||||||
|
pub struct PollScriptVar {
|
||||||
|
pub name: VarName,
|
||||||
|
pub command: String,
|
||||||
|
pub interval: std::time::Duration,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Debug, PartialEq)]
|
||||||
|
pub struct TailScriptVar {
|
||||||
|
pub name: VarName,
|
||||||
|
pub command: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Debug, PartialEq)]
|
||||||
|
pub enum ScriptVar {
|
||||||
|
Poll(PollScriptVar),
|
||||||
|
Tail(TailScriptVar),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ScriptVar {
|
||||||
|
pub fn name(&self) -> &VarName {
|
||||||
|
match self {
|
||||||
|
ScriptVar::Poll(x) => &x.name,
|
||||||
|
ScriptVar::Tail(x) => &x.name,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn initial_value(&self) -> Result<PrimitiveValue> {
|
||||||
|
match self {
|
||||||
|
ScriptVar::Poll(x) => Ok(crate::run_command(&x.command)?),
|
||||||
|
ScriptVar::Tail(_) => Ok(PrimitiveValue::from_string(String::new())),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn from_xml_element(xml: XmlElement) -> Result<Self> {
|
||||||
|
ensure_xml_tag_is!(xml, "script-var");
|
||||||
|
|
||||||
|
let name = VarName(xml.attr("name")?.to_owned());
|
||||||
|
let command = xml.only_child()?.as_text()?.text();
|
||||||
|
if let Ok(interval) = xml.attr("interval") {
|
||||||
|
let interval = util::parse_duration(interval)?;
|
||||||
|
Ok(ScriptVar::Poll(PollScriptVar { name, command, interval }))
|
||||||
|
} else {
|
||||||
|
Ok(ScriptVar::Tail(TailScriptVar { name, command }))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
102
src/config/window_definition.rs
Normal file
102
src/config/window_definition.rs
Normal file
|
@ -0,0 +1,102 @@
|
||||||
|
use crate::{ensure_xml_tag_is, value::Coords};
|
||||||
|
use anyhow::*;
|
||||||
|
use derive_more::*;
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
|
use smart_default::SmartDefault;
|
||||||
|
|
||||||
|
use super::*;
|
||||||
|
use std::fmt;
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, PartialEq)]
|
||||||
|
pub struct EwwWindowDefinition {
|
||||||
|
pub position: Coords,
|
||||||
|
pub size: Coords,
|
||||||
|
pub stacking: WindowStacking,
|
||||||
|
pub screen_number: Option<i32>,
|
||||||
|
pub widget: WidgetUse,
|
||||||
|
pub struts: Struts,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl EwwWindowDefinition {
|
||||||
|
pub fn from_xml_element(xml: XmlElement) -> Result<Self> {
|
||||||
|
ensure_xml_tag_is!(xml, "window");
|
||||||
|
|
||||||
|
let size_node = xml.child("size")?;
|
||||||
|
let size = Coords::from_strs(size_node.attr("x")?, size_node.attr("y")?)?;
|
||||||
|
let pos_node = xml.child("pos")?;
|
||||||
|
let position = Coords::from_strs(pos_node.attr("x")?, pos_node.attr("y")?)?;
|
||||||
|
|
||||||
|
let stacking = xml.attr("stacking").ok().map(|x| x.parse()).transpose()?.unwrap_or_default();
|
||||||
|
let screen_number = xml.attr("screen").ok().map(|x| x.parse()).transpose()?;
|
||||||
|
let struts = xml.child("struts").ok().map(Struts::from_xml_element).transpose()?;
|
||||||
|
|
||||||
|
let widget = WidgetUse::from_xml_node(xml.child("widget")?.only_child()?)?;
|
||||||
|
Ok(EwwWindowDefinition {
|
||||||
|
position,
|
||||||
|
size,
|
||||||
|
widget,
|
||||||
|
stacking,
|
||||||
|
screen_number,
|
||||||
|
struts: struts.unwrap_or_default(),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
|
||||||
|
pub struct Struts {
|
||||||
|
left: i32,
|
||||||
|
right: i32,
|
||||||
|
top: i32,
|
||||||
|
bottom: i32,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Struts {
|
||||||
|
pub fn from_xml_element(xml: XmlElement) -> Result<Self> {
|
||||||
|
ensure_xml_tag_is!(xml, "struts");
|
||||||
|
Ok(Struts {
|
||||||
|
left: xml.attr("left")?.parse()?,
|
||||||
|
right: xml.attr("right")?.parse()?,
|
||||||
|
top: xml.attr("top")?.parse()?,
|
||||||
|
bottom: xml.attr("bottom")?.parse()?,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Copy, PartialEq, Eq, derive_more::Display, SmartDefault)]
|
||||||
|
pub enum WindowStacking {
|
||||||
|
#[default]
|
||||||
|
Foreground,
|
||||||
|
Background,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl std::str::FromStr for WindowStacking {
|
||||||
|
type Err = anyhow::Error;
|
||||||
|
|
||||||
|
fn from_str(s: &str) -> Result<Self> {
|
||||||
|
let s = s.to_lowercase();
|
||||||
|
match s.as_str() {
|
||||||
|
"foreground" | "fg" | "f" => Ok(WindowStacking::Foreground),
|
||||||
|
"background" | "bg" | "b" => Ok(WindowStacking::Background),
|
||||||
|
_ => Err(anyhow!(
|
||||||
|
"Couldn't parse '{}' as window stacking, must be either foreground, fg, background or bg",
|
||||||
|
s
|
||||||
|
)),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[repr(transparent)]
|
||||||
|
#[derive(Clone, Hash, PartialEq, Eq, AsRef, FromStr, Display, Serialize, Deserialize, Default, From)]
|
||||||
|
pub struct WindowName(String);
|
||||||
|
|
||||||
|
impl std::borrow::Borrow<str> for WindowName {
|
||||||
|
fn borrow(&self) -> &str {
|
||||||
|
&self.0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl fmt::Debug for WindowName {
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
|
write!(f, "WindowName(\"{}\")", self.0)
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,5 +1,5 @@
|
||||||
use crate::{
|
use crate::{
|
||||||
config::WindowName,
|
config::window_definition::WindowName,
|
||||||
util,
|
util,
|
||||||
value::{AttrName, AttrValueElement, VarName},
|
value::{AttrName, AttrValueElement, VarName},
|
||||||
};
|
};
|
||||||
|
|
|
@ -10,6 +10,7 @@ extern crate gtk;
|
||||||
|
|
||||||
use crate::value::{PrimitiveValue, VarName};
|
use crate::value::{PrimitiveValue, VarName};
|
||||||
use anyhow::*;
|
use anyhow::*;
|
||||||
|
use config::window_definition::WindowName;
|
||||||
use eww_state::*;
|
use eww_state::*;
|
||||||
use log;
|
use log;
|
||||||
use pretty_env_logger;
|
use pretty_env_logger;
|
||||||
|
@ -88,7 +89,7 @@ pub enum OptAction {
|
||||||
|
|
||||||
#[structopt(name = "open", help = "open a window")]
|
#[structopt(name = "open", help = "open a window")]
|
||||||
OpenWindow {
|
OpenWindow {
|
||||||
window_name: config::WindowName,
|
window_name: WindowName,
|
||||||
|
|
||||||
#[structopt(short, long, help = "The position of the window, where it should open.")]
|
#[structopt(short, long, help = "The position of the window, where it should open.")]
|
||||||
pos: Option<Coords>,
|
pos: Option<Coords>,
|
||||||
|
@ -98,7 +99,7 @@ pub enum OptAction {
|
||||||
},
|
},
|
||||||
|
|
||||||
#[structopt(name = "close", help = "close the window with the given name")]
|
#[structopt(name = "close", help = "close the window with the given name")]
|
||||||
CloseWindow { window_name: config::WindowName },
|
CloseWindow { window_name: WindowName },
|
||||||
|
|
||||||
#[structopt(name = "kill", help = "kill the eww daemon")]
|
#[structopt(name = "kill", help = "kill the eww daemon")]
|
||||||
KillServer,
|
KillServer,
|
||||||
|
|
|
@ -1,10 +1,13 @@
|
||||||
use anyhow::*;
|
use anyhow::*;
|
||||||
|
use derive_more::*;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use std::{fmt, str::FromStr};
|
use std::{fmt, str::FromStr};
|
||||||
|
|
||||||
#[derive(Clone, Copy, PartialEq, Eq, Deserialize, Serialize)]
|
#[derive(Clone, Copy, PartialEq, Eq, Deserialize, Serialize, Display)]
|
||||||
pub enum NumWithUnit {
|
pub enum NumWithUnit {
|
||||||
|
#[display(fmt = "{}%", .0)]
|
||||||
Percent(i32),
|
Percent(i32),
|
||||||
|
#[display(fmt = "{}px", .0)]
|
||||||
Pixels(i32),
|
Pixels(i32),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -14,15 +17,6 @@ impl fmt::Debug for NumWithUnit {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl fmt::Display for NumWithUnit {
|
|
||||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
|
||||||
match self {
|
|
||||||
NumWithUnit::Percent(x) => write!(f, "{}%", x),
|
|
||||||
NumWithUnit::Pixels(x) => write!(f, "{}px", x),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl FromStr for NumWithUnit {
|
impl FromStr for NumWithUnit {
|
||||||
type Err = anyhow::Error;
|
type Err = anyhow::Error;
|
||||||
|
|
||||||
|
@ -42,7 +36,8 @@ impl FromStr for NumWithUnit {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Copy, PartialEq, Eq, Deserialize, Serialize)]
|
#[derive(Clone, Copy, PartialEq, Eq, Deserialize, Serialize, Display)]
|
||||||
|
#[display(fmt = "{}X{}", x, y)]
|
||||||
pub struct Coords {
|
pub struct Coords {
|
||||||
pub x: NumWithUnit,
|
pub x: NumWithUnit,
|
||||||
pub y: NumWithUnit,
|
pub y: NumWithUnit,
|
||||||
|
@ -59,12 +54,6 @@ impl FromStr for Coords {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl fmt::Display for Coords {
|
|
||||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
|
||||||
write!(f, "{}X{}", self.x, self.y)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl fmt::Debug for Coords {
|
impl fmt::Debug for Coords {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
write!(f, "CoordsWithUnits({}, {})", self.x, self.y)
|
write!(f, "CoordsWithUnits({}, {})", self.x, self.y)
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
use derive_more;
|
use derive_more::*;
|
||||||
use ref_cast::RefCast;
|
use ref_cast::RefCast;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
|
@ -12,9 +12,7 @@ pub use primitive::*;
|
||||||
|
|
||||||
/// The name of a variable
|
/// The name of a variable
|
||||||
#[repr(transparent)]
|
#[repr(transparent)]
|
||||||
#[derive(
|
#[derive(Clone, Hash, PartialEq, Eq, Serialize, Deserialize, RefCast, AsRef, From, FromStr, Display)]
|
||||||
Clone, Hash, PartialEq, Eq, derive_more::AsRef, derive_more::From, derive_more::FromStr, Serialize, Deserialize, RefCast,
|
|
||||||
)]
|
|
||||||
pub struct VarName(pub String);
|
pub struct VarName(pub String);
|
||||||
|
|
||||||
impl std::borrow::Borrow<str> for VarName {
|
impl std::borrow::Borrow<str> for VarName {
|
||||||
|
@ -23,12 +21,6 @@ impl std::borrow::Borrow<str> for VarName {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl fmt::Display for VarName {
|
|
||||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
|
||||||
write!(f, "{}", self.0)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl fmt::Debug for VarName {
|
impl fmt::Debug for VarName {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
write!(f, "VarName(\"{}\")", self.0)
|
write!(f, "VarName(\"{}\")", self.0)
|
||||||
|
@ -37,9 +29,7 @@ impl fmt::Debug for VarName {
|
||||||
|
|
||||||
/// The name of an attribute
|
/// The name of an attribute
|
||||||
#[repr(transparent)]
|
#[repr(transparent)]
|
||||||
#[derive(
|
#[derive(Clone, Hash, PartialEq, Eq, Serialize, Deserialize, RefCast, AsRef, From, FromStr, Display)]
|
||||||
Clone, Hash, PartialEq, Eq, derive_more::AsRef, derive_more::From, derive_more::FromStr, Serialize, Deserialize, RefCast,
|
|
||||||
)]
|
|
||||||
pub struct AttrName(pub String);
|
pub struct AttrName(pub String);
|
||||||
|
|
||||||
impl std::borrow::Borrow<str> for AttrName {
|
impl std::borrow::Borrow<str> for AttrName {
|
||||||
|
@ -48,12 +38,6 @@ impl std::borrow::Borrow<str> for AttrName {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl fmt::Display for AttrName {
|
|
||||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
|
||||||
write!(f, "{}", self.0)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl fmt::Debug for AttrName {
|
impl fmt::Debug for AttrName {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
write!(f, "AttrName(\"{}\")", self.0)
|
write!(f, "AttrName(\"{}\")", self.0)
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
use crate::{
|
use crate::{
|
||||||
config::{element, WindowName},
|
config::{element, window_definition::WindowName},
|
||||||
eww_state::*,
|
eww_state::*,
|
||||||
value::{AttrName, AttrValue, VarName},
|
value::{AttrName, AttrValue, VarName},
|
||||||
};
|
};
|
||||||
|
|
Loading…
Add table
Reference in a new issue