Implement reading config from file and scss loading

This commit is contained in:
elkowar 2020-09-24 00:20:35 +02:00
parent c9c9f25afb
commit 2155ec0fd8
4 changed files with 466 additions and 122 deletions

308
Cargo.lock generated
View file

@ -15,6 +15,12 @@ version = "0.2.3"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ee2a4ec343196209d6594e19543ae87a39f96d5534d7174822a3ad825dd6ed7e" checksum = "ee2a4ec343196209d6594e19543ae87a39f96d5534d7174822a3ad825dd6ed7e"
[[package]]
name = "ahash"
version = "0.3.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e8fd72866655d1904d6b0997d0b07ba561047d070fbe29de039031c641b61217"
[[package]] [[package]]
name = "aho-corasick" name = "aho-corasick"
version = "0.7.13" version = "0.7.13"
@ -96,6 +102,12 @@ dependencies = [
"rustc-demangle", "rustc-demangle",
] ]
[[package]]
name = "beef"
version = "0.4.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "474a626a67200bd107d44179bb3d4fc61891172d11696609264589be6a0e6a43"
[[package]] [[package]]
name = "bincode" name = "bincode"
version = "1.3.1" version = "1.3.1"
@ -171,6 +183,12 @@ dependencies = [
"vec_map", "vec_map",
] ]
[[package]]
name = "codemap"
version = "0.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b9e769b5c8c8283982a987c6e948e540254f1058d5a74b8794914d4ef5fc2a24"
[[package]] [[package]]
name = "crossbeam-channel" name = "crossbeam-channel"
version = "0.4.4" version = "0.4.4"
@ -299,10 +317,12 @@ dependencies = [
"gdk", "gdk",
"gio", "gio",
"glib", "glib",
"grass",
"gtk", "gtk",
"hocon", "hocon",
"ipc-channel", "ipc-channel",
"maplit", "maplit",
"notify",
"pretty_assertions", "pretty_assertions",
"regex", "regex",
"serde", "serde",
@ -344,12 +364,43 @@ dependencies = [
"synstructure", "synstructure",
] ]
[[package]]
name = "filetime"
version = "0.2.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3ed85775dcc68644b5c950ac06a2b23768d3bc9390464151aaf27136998dcf9e"
dependencies = [
"cfg-if",
"libc",
"redox_syscall",
"winapi 0.3.9",
]
[[package]] [[package]]
name = "fnv" name = "fnv"
version = "1.0.7" version = "1.0.7"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1"
[[package]]
name = "fsevent"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5ab7d1bd1bd33cc98b0889831b72da23c0aa4df9cec7e0702f46ecea04b35db6"
dependencies = [
"bitflags",
"fsevent-sys",
]
[[package]]
name = "fsevent-sys"
version = "2.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f41b048a94555da0f42f1d632e2e19510084fb8e303b0daa2816e733fb3644a0"
dependencies = [
"libc",
]
[[package]] [[package]]
name = "fuchsia-zircon" name = "fuchsia-zircon"
version = "0.3.3" version = "0.3.3"
@ -633,6 +684,26 @@ dependencies = [
"system-deps", "system-deps",
] ]
[[package]]
name = "grass"
version = "0.10.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "de2cf11276bb4d38b76d9666f9d87423522d57a519aefb9df744c1f6cf574e4f"
dependencies = [
"beef",
"clap",
"codemap",
"indexmap",
"lasso",
"num-bigint",
"num-rational",
"num-traits",
"once_cell",
"peekmore",
"phf",
"rand",
]
[[package]] [[package]]
name = "gtk" name = "gtk"
version = "0.9.2" version = "0.9.2"
@ -679,6 +750,22 @@ dependencies = [
"system-deps", "system-deps",
] ]
[[package]]
name = "hashbrown"
version = "0.8.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e91b62f79061a0bc2e046024cb7ba44b08419ed238ecbd9adbd787434b9e8c25"
dependencies = [
"ahash",
"autocfg",
]
[[package]]
name = "hashbrown"
version = "0.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "00d63df3d41950fb462ed38308eea019113ad1508da725bbedcd0fa5a85ef5f7"
[[package]] [[package]]
name = "heck" name = "heck"
version = "0.3.1" version = "0.3.1"
@ -711,6 +798,36 @@ dependencies = [
"uuid", "uuid",
] ]
[[package]]
name = "indexmap"
version = "1.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "55e2e4c765aa53a0424761bf9f41aa7a6ac1efa87238f59560640e27fca028f2"
dependencies = [
"autocfg",
"hashbrown 0.9.0",
]
[[package]]
name = "inotify"
version = "0.7.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4816c66d2c8ae673df83366c18341538f234a26d65a9ecea5c348b453ac1d02f"
dependencies = [
"bitflags",
"inotify-sys",
"libc",
]
[[package]]
name = "inotify-sys"
version = "0.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e74a1aa87c59aeff6ef2cc2fa62d41bc43f54952f55652656b18a02fd5e356c0"
dependencies = [
"libc",
]
[[package]] [[package]]
name = "iovec" name = "iovec"
version = "0.1.4" version = "0.1.4"
@ -767,12 +884,27 @@ dependencies = [
"winapi-build", "winapi-build",
] ]
[[package]]
name = "lasso"
version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bf1a626ea51398f5acf36666c8046ff4bfd048aab88e92db676d2a6eac8805d0"
dependencies = [
"hashbrown 0.8.2",
]
[[package]] [[package]]
name = "lazy_static" name = "lazy_static"
version = "1.4.0" version = "1.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
[[package]]
name = "lazycell"
version = "1.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55"
[[package]] [[package]]
name = "libc" name = "libc"
version = "0.2.77" version = "0.2.77"
@ -835,6 +967,18 @@ dependencies = [
"winapi 0.2.8", "winapi 0.2.8",
] ]
[[package]]
name = "mio-extras"
version = "2.0.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "52403fe290012ce777c4626790c8951324a2b9e3316b3143779c72b029742f19"
dependencies = [
"lazycell",
"log",
"mio",
"slab",
]
[[package]] [[package]]
name = "miow" name = "miow"
version = "0.2.1" version = "0.2.1"
@ -868,6 +1012,66 @@ dependencies = [
"version_check 0.1.5", "version_check 0.1.5",
] ]
[[package]]
name = "notify"
version = "4.0.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "80ae4a7688d1fab81c5bf19c64fc8db920be8d519ce6336ed4e7efe024724dbd"
dependencies = [
"bitflags",
"filetime",
"fsevent",
"fsevent-sys",
"inotify",
"libc",
"mio",
"mio-extras",
"walkdir",
"winapi 0.3.9",
]
[[package]]
name = "num-bigint"
version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b7f3fc75e3697059fb1bc465e3d8cca6cf92f56854f201158b3f9c77d5a3cfa0"
dependencies = [
"autocfg",
"num-integer",
"num-traits",
]
[[package]]
name = "num-integer"
version = "0.1.43"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8d59457e662d541ba17869cf51cf177c0b5f0cbf476c66bdc90bf1edac4f875b"
dependencies = [
"autocfg",
"num-traits",
]
[[package]]
name = "num-rational"
version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a5b4d7360f362cfb50dde8143501e6940b22f644be75a4cc90b2d81968908138"
dependencies = [
"autocfg",
"num-bigint",
"num-integer",
"num-traits",
]
[[package]]
name = "num-traits"
version = "0.2.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ac267bcc07f48ee5f8935ab0d24f316fb722d7a1292e2913f0cc196b29ffd611"
dependencies = [
"autocfg",
]
[[package]] [[package]]
name = "object" name = "object"
version = "0.20.0" version = "0.20.0"
@ -916,6 +1120,59 @@ dependencies = [
"system-deps", "system-deps",
] ]
[[package]]
name = "peekmore"
version = "0.5.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e029e89e27328ecf6a2e0820b5767ce6deb10872f2f18fb9e98d2e8ab7aef29f"
dependencies = [
"smallvec",
]
[[package]]
name = "phf"
version = "0.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3dfb61232e34fcb633f43d12c58f83c1df82962dcdfa565a4e866ffc17dafe12"
dependencies = [
"phf_macros",
"phf_shared",
"proc-macro-hack",
]
[[package]]
name = "phf_generator"
version = "0.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "17367f0cc86f2d25802b2c26ee58a7b23faeccf78a396094c13dced0d0182526"
dependencies = [
"phf_shared",
"rand",
]
[[package]]
name = "phf_macros"
version = "0.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7f6fde18ff429ffc8fe78e2bf7f8b7a5a5a6e2a8b58bc5a9ac69198bbda9189c"
dependencies = [
"phf_generator",
"phf_shared",
"proc-macro-hack",
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "phf_shared"
version = "0.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c00cf8b9eafe68dde5e9eaa2cef8ee84a9336a47d566ec55ca16589633b65af7"
dependencies = [
"siphasher",
]
[[package]] [[package]]
name = "pin-project" name = "pin-project"
version = "0.4.23" version = "0.4.23"
@ -1040,6 +1297,7 @@ dependencies = [
"rand_chacha", "rand_chacha",
"rand_core", "rand_core",
"rand_hc", "rand_hc",
"rand_pcg",
] ]
[[package]] [[package]]
@ -1070,6 +1328,15 @@ dependencies = [
"rand_core", "rand_core",
] ]
[[package]]
name = "rand_pcg"
version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "16abd0c1b639e9eb4d7c50c0b8100b0d0f849be2349829c740fe8e6eb4816429"
dependencies = [
"rand_core",
]
[[package]] [[package]]
name = "redox_syscall" name = "redox_syscall"
version = "0.1.57" version = "0.1.57"
@ -1109,6 +1376,15 @@ version = "0.1.16"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4c691c0e608126e00913e33f0ccf3727d5fc84573623b8d65b2df340b5201783" checksum = "4c691c0e608126e00913e33f0ccf3727d5fc84573623b8d65b2df340b5201783"
[[package]]
name = "same-file"
version = "1.0.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502"
dependencies = [
"winapi-util",
]
[[package]] [[package]]
name = "serde" name = "serde"
version = "1.0.116" version = "1.0.116"
@ -1129,12 +1405,24 @@ dependencies = [
"syn", "syn",
] ]
[[package]]
name = "siphasher"
version = "0.3.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fa8f3741c7372e75519bd9346068370c9cdaabcc1f9599cbcf2a2719352286b7"
[[package]] [[package]]
name = "slab" name = "slab"
version = "0.4.2" version = "0.4.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c111b5bd5695e56cffe5129854aa230b39c93a305372fdbb2668ca2394eea9f8" checksum = "c111b5bd5695e56cffe5129854aa230b39c93a305372fdbb2668ca2394eea9f8"
[[package]]
name = "smallvec"
version = "1.4.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fbee7696b84bbf3d89a1c2eccff0850e3047ed46bfcd2e92c29a2d074d57e252"
[[package]] [[package]]
name = "strsim" name = "strsim"
version = "0.8.0" version = "0.8.0"
@ -1356,6 +1644,17 @@ version = "0.9.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b5a972e5669d67ba988ce3dc826706fb0a8b01471c088cb0b6110b805cc36aed" checksum = "b5a972e5669d67ba988ce3dc826706fb0a8b01471c088cb0b6110b805cc36aed"
[[package]]
name = "walkdir"
version = "2.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "777182bc735b6424e1a57516d35ed72cb8019d85c8c9bf536dccb3445c1a2f7d"
dependencies = [
"same-file",
"winapi 0.3.9",
"winapi-util",
]
[[package]] [[package]]
name = "wasi" name = "wasi"
version = "0.9.0+wasi-snapshot-preview1" version = "0.9.0+wasi-snapshot-preview1"
@ -1390,6 +1689,15 @@ version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
[[package]]
name = "winapi-util"
version = "0.1.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178"
dependencies = [
"winapi 0.3.9",
]
[[package]] [[package]]
name = "winapi-x86_64-pc-windows-gnu" name = "winapi-x86_64-pc-windows-gnu"
version = "0.4.0" version = "0.4.0"

View file

@ -22,6 +22,8 @@ structopt = "0.3"
ipc-channel="0.14.1" ipc-channel="0.14.1"
serde = {version = "1.0", features = ["derive"]} serde = {version = "1.0", features = ["derive"]}
extend = "0.3.0" extend = "0.3.0"
grass = "0.10"
notify = "4.0"
#thiserror = "1.0" #thiserror = "1.0"

View file

@ -6,10 +6,13 @@ extern crate gtk;
use anyhow::*; use anyhow::*;
use gdk::*; use gdk::*;
use gio::prelude::*; use gio::prelude::*;
use grass;
use gtk::prelude::*; use gtk::prelude::*;
use ipc_channel::ipc; use ipc_channel::ipc;
use notify::{self, Watcher};
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use std::collections::HashMap; use std::collections::HashMap;
use std::path;
use structopt::StructOpt; use structopt::StructOpt;
pub mod config; pub mod config;
@ -29,61 +32,6 @@ macro_rules! build {
}}; }};
} }
const EXAMPLE_CONFIG: &str = r#"{
widgets: {
some_widget: {
structure: {
layout: {
class: "container",
children: [
{ layout: {
orientation: "v"
children: [
"fancy button"
{ button: { children: "reeee" } }
]
} }
{ layout: {
children: [
"date" // TODO FIX!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
{ label: { text: "$$date" } }
{ button: { children: "click me you" } }
{ slider: { value: "$$some_value", min: 0, max: 100, onchange: "notify-send 'changed' {}" } }
{ slider: { value: "$$some_value", orientation: "vertical" } }
"hu"
]
} }
]
}
}
},
test: {
structure: {
some_widget: {
some_value: "$$ooph"
}
}
}
},
default_vars: {
ree: 12
date: "never"
}
windows: {
main_window: {
pos.x: 200
pos.y: 1550
size.x: 500
size.y: 50
widget: {
test: {
ooph: "$$ree"
}
}
}
},
}"#;
fn main() { fn main() {
if let Err(e) = try_main() { if let Err(e) = try_main() {
eprintln!("{:?}", e); eprintln!("{:?}", e);
@ -92,27 +40,29 @@ fn main() {
#[derive(StructOpt, Debug, Serialize, Deserialize)] #[derive(StructOpt, Debug, Serialize, Deserialize)]
struct Opt { struct Opt {
#[structopt(short = "-c", parse(from_os_str))]
config_file: Option<path::PathBuf>,
#[structopt(subcommand)] #[structopt(subcommand)]
action: OptAction, action: OptAction,
} }
#[derive(StructOpt, Debug, Serialize, Deserialize)] #[derive(StructOpt, Debug, Serialize, Deserialize)]
enum OptAction { enum OptAction {
#[structopt(name = "update")] #[structopt(name = "update")]
Update(OptActionUpdate), Update { fieldname: String, value: PrimitiveValue },
#[structopt(name = "open")] #[structopt(name = "open")]
OpenWindow(OptActionOpen), OpenWindow { window_name: String },
#[structopt(name = "close")]
CloseWindow { window_name: String },
} }
#[derive(StructOpt, Debug, Serialize, Deserialize)] #[derive(Debug)]
struct OptActionUpdate { enum EwwEvent {
fieldname: String, UserCommand(Opt),
value: PrimitiveValue, ReloadConfig(config::EwwConfig),
} ReloadCss(String),
#[derive(StructOpt, Debug, Serialize, Deserialize)]
struct OptActionOpen {
window_name: String,
} }
fn try_main() -> Result<()> { fn try_main() -> Result<()> {
@ -130,21 +80,102 @@ fn find_server_process() -> Result<ipc::IpcSender<Opt>> {
Ok(ipc::IpcSender::connect(instance_path)?) Ok(ipc::IpcSender::connect(instance_path)?)
} }
fn get_config_file_path() -> path::PathBuf {
std::env::var("XDG_CONFIG_HOME")
.map(|v| path::PathBuf::from(v))
.unwrap_or_else(|_| path::PathBuf::from(std::env::var("HOME").unwrap()).join(".config"))
.join("eww")
.join("eww.conf")
}
fn initialize_server(opts: Opt) -> Result<()> { fn initialize_server(opts: Opt) -> Result<()> {
let eww_config = config::EwwConfig::from_hocon(&config::parse_hocon(EXAMPLE_CONFIG)?)?; let config_file_path = opts.config_file.clone().unwrap_or_else(get_config_file_path);
let config_dir = config_file_path
.clone()
.parent()
.context("config file did not have a parent?!")?
.to_owned()
.to_path_buf();
let scss_file_path = config_dir.join("eww.scss");
let (watcher_tx, watcher_rx) = std::sync::mpsc::channel();
let mut file_watcher = notify::watcher(watcher_tx, std::time::Duration::from_millis(100))?;
file_watcher.watch(config_file_path.clone(), notify::RecursiveMode::NonRecursive)?;
if let Err(e) = file_watcher.watch(scss_file_path.clone(), notify::RecursiveMode::NonRecursive) {
eprintln!("WARN: error while loading CSS file for hot-reloading: \n{}", e)
}
let config_content = std::fs::read_to_string(config_file_path.clone())?;
let scss_content = std::fs::read_to_string(scss_file_path.clone()).unwrap_or_default();
let eww_config = config::EwwConfig::from_hocon(&config::parse_hocon(&config_content)?)?;
let eww_css =
grass::from_string(scss_content, &grass::Options::default()).map_err(|err| anyhow!("SCSS parsing error: {:?}", err))?;
let mut app = App { let mut app = App {
eww_state: EwwState::from_default_vars(eww_config.get_default_vars().clone()), eww_state: EwwState::from_default_vars(eww_config.get_default_vars().clone()),
eww_config, eww_config,
eww_css: eww_css.clone(),
windows: HashMap::new(),
}; };
let (send, recv) = glib::MainContext::channel(glib::PRIORITY_DEFAULT);
gtk::init()?; gtk::init()?;
let css_provider = gtk::CssProvider::new();
css_provider.load_from_data(eww_css.as_bytes())?;
gdk::Screen::get_default().map(|screen| {
gtk::StyleContext::add_provider_for_screen(&screen, &css_provider, gtk::STYLE_PROVIDER_PRIORITY_APPLICATION);
});
app.handle_user_command(opts)?; app.handle_user_command(opts)?;
std::thread::spawn(move || run_ipc_server(send)); let (send, recv) = glib::MainContext::channel(glib::PRIORITY_DEFAULT);
std::thread::spawn({
let send = send.clone();
{
move || {
let result: Result<_> = try {
loop {
let (ipc_server, instance_path): (ipc::IpcOneShotServer<Opt>, _) = ipc::IpcOneShotServer::new()?;
std::fs::write("/tmp/eww-instance-path", instance_path)?;
let (_, initial) = ipc_server.accept()?;
send.send(EwwEvent::UserCommand(initial))?;
}
};
if let Err(err) = result {
eprintln!("error in server thread: {}", err);
std::process::exit(1);
}
}
}
});
std::thread::spawn(move || {
while let Ok(event) = watcher_rx.recv() {
let result: Result<_> = try {
dbg!(&event);
match event {
notify::DebouncedEvent::Write(updated_path) | notify::DebouncedEvent::NoticeWrite(updated_path)
if updated_path == config_file_path =>
{
let new_eww_config = config::EwwConfig::from_hocon(&config::parse_hocon(&config_content)?)?;
send.send(EwwEvent::ReloadConfig(new_eww_config))?;
}
notify::DebouncedEvent::Write(updated_path) if updated_path == scss_file_path => {
let scss_content = std::fs::read_to_string(scss_file_path.clone()).unwrap_or_default();
let eww_css = grass::from_string(scss_content, &grass::Options::default())
.map_err(|err| anyhow!("SCSS parsing error: {:?}", err))?;
send.send(EwwEvent::ReloadCss(eww_css))?;
}
_ => {}
}
};
if let Err(err) = result {
eprintln!("error in server thread: {}", err);
std::process::exit(1);
}
}
});
recv.attach(None, move |msg| { recv.attach(None, move |msg| {
app.handle_event(msg); app.handle_event(msg);
glib::Continue(true) glib::Continue(true)
@ -155,63 +186,62 @@ fn initialize_server(opts: Opt) -> Result<()> {
Ok(()) Ok(())
} }
fn run_ipc_server(send: glib::Sender<EwwEvent>) -> Result<()> {
loop {
let (ipc_server, instance_path): (ipc::IpcOneShotServer<Opt>, _) = ipc::IpcOneShotServer::new()?;
std::fs::write("/tmp/eww-instance-path", instance_path)?;
let (receiver, initial) = ipc_server.accept()?;
send.send(EwwEvent::UserCommand(initial))?;
}
}
#[derive(Debug)] #[derive(Debug)]
struct App { struct App {
eww_state: EwwState, eww_state: EwwState,
eww_config: config::EwwConfig, eww_config: config::EwwConfig,
eww_css: String,
windows: HashMap<String, gtk::Window>,
} }
impl App { impl App {
fn handle_user_command(&mut self, opts: Opt) -> Result<()> { fn handle_user_command(&mut self, opts: Opt) -> Result<()> {
match opts.action { match opts.action {
OptAction::Update(update) => self.update_state(update), OptAction::Update { fieldname, value } => self.update_state(fieldname, value),
OptAction::OpenWindow(update) => self.open_window(update)?, OptAction::OpenWindow { window_name } => self.open_window(&window_name)?,
OptAction::CloseWindow { window_name } => self.close_window(&window_name)?,
} }
Ok(()) Ok(())
} }
fn update_state(&mut self, update: OptActionUpdate) { fn update_state(&mut self, fieldname: String, value: PrimitiveValue) {
self.eww_state.update_value(update.fieldname, update.value); self.eww_state.update_value(fieldname, value);
} }
fn open_window(&mut self, open_window: OptActionOpen) -> Result<()> { fn close_window(&mut self, window_name: &str) -> Result<()> {
let window_def = self.eww_config.get_windows()[&open_window.window_name].clone(); let window = self
.windows
.get(window_name)
.context(format!("No window with name '{}' is running.", window_name))?;
window.close();
Ok(())
}
let window = gtk::Window::new(gtk::WindowType::Toplevel); fn open_window(&mut self, window_name: &str) -> Result<()> {
let window_def = self
.eww_config
.get_windows()
.get(window_name)
.context(format!("No window named '{}' defined", window_name))?
.clone();
let window = gtk::Window::new(gtk::WindowType::Popup);
window.set_title("Eww"); window.set_title("Eww");
window.set_wmclass("noswallow", "noswallow"); window.set_wmclass("noswallow", "noswallow");
window.set_type_hint(gdk::WindowTypeHint::Dock); window.set_type_hint(gdk::WindowTypeHint::Dock);
window.set_position(gtk::WindowPosition::Center); window.set_position(gtk::WindowPosition::Center);
window.set_keep_above(true);
window.set_default_size(window_def.size.0, window_def.size.1); window.set_default_size(window_def.size.0, window_def.size.1);
window.set_visual( window.set_decorated(false);
window
.get_display()
.get_default_screen()
.get_rgba_visual()
.or_else(|| window.get_display().get_default_screen().get_system_visual())
.as_ref(),
);
window.fullscreen();
let empty_local_state = HashMap::new(); let empty_local_state = HashMap::new();
let root_widget = &widgets::element_to_gtk_thing(
window.add(&widgets::element_to_gtk_thing(
&self.eww_config.get_widgets(), &self.eww_config.get_widgets(),
&mut self.eww_state, &mut self.eww_state,
&empty_local_state, &empty_local_state,
&window_def.widget, &window_def.widget,
)?); )?;
root_widget.get_style_context().add_class(window_name);
window.add(root_widget);
window.show_all(); window.show_all();
@ -220,7 +250,27 @@ impl App {
gdk_window.move_(window_def.position.0, window_def.position.1); gdk_window.move_(window_def.position.0, window_def.position.1);
gdk_window.show(); gdk_window.show();
gdk_window.raise(); gdk_window.raise();
window.set_keep_above(true);
self.windows.insert(window_name.to_string(), window);
Ok(())
}
fn reload_all_windows(&mut self, config: config::EwwConfig) -> Result<()> {
self.eww_config = config;
let windows = self.windows.clone();
for (window_name, window) in windows {
dbg!(&window_name);
window.close();
window.hide();
self.open_window(&window_name)?;
}
Ok(())
}
fn reload_css(&mut self, css: String) -> Result<()> {
for window in self.windows.values() {}
Ok(()) Ok(())
} }
@ -228,6 +278,8 @@ impl App {
let result: Result<_> = try { let result: Result<_> = try {
match event { match event {
EwwEvent::UserCommand(command) => self.handle_user_command(command)?, EwwEvent::UserCommand(command) => self.handle_user_command(command)?,
EwwEvent::ReloadConfig(config) => self.reload_all_windows(config)?,
EwwEvent::ReloadCss(css) => self.reload_css(css)?,
} }
}; };
if let Err(err) = result { if let Err(err) = result {
@ -235,23 +287,3 @@ impl App {
} }
} }
} }
#[derive(Debug)]
enum EwwEvent {
UserCommand(Opt),
}
fn event_loop(sender: glib::Sender<EwwEvent>) {
let mut x = 0;
loop {
x += 1;
std::thread::sleep(std::time::Duration::from_millis(1000));
let event_opt = Opt {
action: OptAction::Update(OptActionUpdate {
fieldname: "ree".to_string(),
value: PrimitiveValue::Number(x as f64 * 10.0),
}),
};
sender.send(EwwEvent::UserCommand(event_opt)).unwrap();
}
}

View file

@ -39,7 +39,9 @@ pub fn element_to_gtk_thing(
} else if let Some(def) = widget_definitions.get(widget.name.as_str()) { } else if let Some(def) = widget_definitions.get(widget.name.as_str()) {
let mut local_env = local_env.clone(); let mut local_env = local_env.clone();
local_env.extend(widget.attrs.clone()); local_env.extend(widget.attrs.clone());
element_to_gtk_thing(widget_definitions, eww_state, &local_env, &def.structure)? let custom_widget = element_to_gtk_thing(widget_definitions, eww_state, &local_env, &def.structure)?;
custom_widget.get_style_context().add_class(widget.name.as_str());
custom_widget
} else { } else {
return Err(anyhow!("unknown widget: '{}'", &widget.name)); return Err(anyhow!("unknown widget: '{}'", &widget.name));
}; };