Add eww windows
command and restructure daemon response.
Daemon response is now a dedicated type that contains information about failure / success, and used in more commands, such as `open` and `close`. Thus, this fixes #90 and also fixes #89. For #90, the decision has been made to not make this independent of the daemon, as that makes it possible to provide more information, and because in most cases, users will have the daemon running when checking windows anyways.
This commit is contained in:
parent
ff756da2c5
commit
8530f90a7c
7 changed files with 156 additions and 69 deletions
112
src/app.rs
112
src/app.rs
|
@ -14,26 +14,56 @@ use itertools::Itertools;
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use tokio::sync::mpsc::UnboundedSender;
|
use tokio::sync::mpsc::UnboundedSender;
|
||||||
|
|
||||||
|
/// Response that the app may send as a response to a event.
|
||||||
|
/// This is used in `DaemonCommand`s that contain a response sender.
|
||||||
|
#[derive(Debug, PartialEq, Eq, serde::Serialize, serde::Deserialize, derive_more::Display)]
|
||||||
|
pub enum DaemonResponse {
|
||||||
|
Success(String),
|
||||||
|
Failure(String),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl DaemonResponse {
|
||||||
|
pub fn is_success(&self) -> bool {
|
||||||
|
match self {
|
||||||
|
DaemonResponse::Success(_) => true,
|
||||||
|
_ => false,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn is_failure(&self) -> bool {
|
||||||
|
!self.is_success()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub type DaemonResponseSender = tokio::sync::mpsc::UnboundedSender<DaemonResponse>;
|
||||||
|
pub type DaemonResponseReceiver = tokio::sync::mpsc::UnboundedReceiver<DaemonResponse>;
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub enum EwwCommand {
|
pub enum DaemonCommand {
|
||||||
NoOp,
|
NoOp,
|
||||||
UpdateVars(Vec<(VarName, PrimitiveValue)>),
|
UpdateVars(Vec<(VarName, PrimitiveValue)>),
|
||||||
ReloadConfig(config::EwwConfig),
|
ReloadConfig(config::EwwConfig),
|
||||||
ReloadCss(String),
|
ReloadCss(String),
|
||||||
OpenMany(Vec<WindowName>),
|
OpenMany {
|
||||||
|
windows: Vec<WindowName>,
|
||||||
|
sender: DaemonResponseSender,
|
||||||
|
},
|
||||||
OpenWindow {
|
OpenWindow {
|
||||||
window_name: WindowName,
|
window_name: WindowName,
|
||||||
pos: Option<Coords>,
|
pos: Option<Coords>,
|
||||||
size: Option<Coords>,
|
size: Option<Coords>,
|
||||||
anchor: Option<AnchorPoint>,
|
anchor: Option<AnchorPoint>,
|
||||||
|
sender: DaemonResponseSender,
|
||||||
},
|
},
|
||||||
CloseWindow {
|
CloseWindow {
|
||||||
window_name: WindowName,
|
window_name: WindowName,
|
||||||
|
sender: DaemonResponseSender,
|
||||||
},
|
},
|
||||||
KillServer,
|
KillServer,
|
||||||
CloseAll,
|
CloseAll,
|
||||||
PrintState(tokio::sync::mpsc::UnboundedSender<String>),
|
PrintState(DaemonResponseSender),
|
||||||
PrintDebug(tokio::sync::mpsc::UnboundedSender<String>),
|
PrintDebug(DaemonResponseSender),
|
||||||
|
PrintWindows(DaemonResponseSender),
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq)]
|
#[derive(Debug, Clone, PartialEq)]
|
||||||
|
@ -55,68 +85,91 @@ pub struct App {
|
||||||
pub eww_config: config::EwwConfig,
|
pub eww_config: config::EwwConfig,
|
||||||
pub windows: HashMap<WindowName, EwwWindow>,
|
pub windows: HashMap<WindowName, EwwWindow>,
|
||||||
pub css_provider: gtk::CssProvider,
|
pub css_provider: gtk::CssProvider,
|
||||||
pub app_evt_send: UnboundedSender<EwwCommand>,
|
pub app_evt_send: UnboundedSender<DaemonCommand>,
|
||||||
#[debug_stub = "ScriptVarHandler(...)"]
|
#[debug_stub = "ScriptVarHandler(...)"]
|
||||||
pub script_var_handler: ScriptVarHandlerHandle,
|
pub script_var_handler: ScriptVarHandlerHandle,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl App {
|
impl App {
|
||||||
/// Handle an EwwCommand event.
|
/// Handle a DaemonCommand event.
|
||||||
pub fn handle_command(&mut self, event: EwwCommand) {
|
pub fn handle_command(&mut self, event: DaemonCommand) {
|
||||||
log::debug!("Handling event: {:?}", &event);
|
log::debug!("Handling event: {:?}", &event);
|
||||||
let result: Result<_> = try {
|
let result: Result<_> = try {
|
||||||
match event {
|
match event {
|
||||||
EwwCommand::NoOp => {}
|
DaemonCommand::NoOp => {}
|
||||||
EwwCommand::UpdateVars(mappings) => {
|
DaemonCommand::UpdateVars(mappings) => {
|
||||||
for (var_name, new_value) in mappings {
|
for (var_name, new_value) in mappings {
|
||||||
self.update_state(var_name, new_value)?;
|
self.update_state(var_name, new_value)?;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
EwwCommand::ReloadConfig(config) => {
|
DaemonCommand::ReloadConfig(config) => {
|
||||||
self.reload_all_windows(config)?;
|
self.reload_all_windows(config)?;
|
||||||
}
|
}
|
||||||
EwwCommand::ReloadCss(css) => {
|
DaemonCommand::ReloadCss(css) => {
|
||||||
self.load_css(&css)?;
|
self.load_css(&css)?;
|
||||||
}
|
}
|
||||||
EwwCommand::KillServer => {
|
DaemonCommand::KillServer => {
|
||||||
log::info!("Received kill command, stopping server!");
|
log::info!("Received kill command, stopping server!");
|
||||||
self.stop_application();
|
self.stop_application();
|
||||||
let _ = crate::application_lifecycle::send_exit();
|
let _ = crate::application_lifecycle::send_exit();
|
||||||
}
|
}
|
||||||
EwwCommand::CloseAll => {
|
DaemonCommand::CloseAll => {
|
||||||
log::info!("Received close command, closing all windows");
|
log::info!("Received close command, closing all windows");
|
||||||
for (window_name, _window) in self.windows.clone() {
|
for (window_name, _window) in self.windows.clone() {
|
||||||
self.close_window(&window_name)?;
|
self.close_window(&window_name)?;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
EwwCommand::OpenMany(windows) => {
|
DaemonCommand::OpenMany { windows, sender } => {
|
||||||
for window in windows {
|
let result = windows
|
||||||
self.open_window(&window, None, None, None)?;
|
.iter()
|
||||||
}
|
.map(|w| self.open_window(w, None, None, None))
|
||||||
|
.collect::<Result<()>>();
|
||||||
|
respond_with_error(sender, result)?;
|
||||||
}
|
}
|
||||||
EwwCommand::OpenWindow {
|
DaemonCommand::OpenWindow {
|
||||||
window_name,
|
window_name,
|
||||||
pos,
|
pos,
|
||||||
size,
|
size,
|
||||||
anchor,
|
anchor,
|
||||||
|
sender,
|
||||||
} => {
|
} => {
|
||||||
self.open_window(&window_name, pos, size, anchor)?;
|
let result = self.open_window(&window_name, pos, size, anchor);
|
||||||
|
respond_with_error(sender, result)?;
|
||||||
}
|
}
|
||||||
EwwCommand::CloseWindow { window_name } => {
|
DaemonCommand::CloseWindow { window_name, sender } => {
|
||||||
self.close_window(&window_name)?;
|
let result = self.close_window(&window_name);
|
||||||
|
respond_with_error(sender, result)?;
|
||||||
}
|
}
|
||||||
EwwCommand::PrintState(sender) => {
|
DaemonCommand::PrintState(sender) => {
|
||||||
let output = self
|
let output = self
|
||||||
.eww_state
|
.eww_state
|
||||||
.get_variables()
|
.get_variables()
|
||||||
.iter()
|
.iter()
|
||||||
.map(|(key, value)| format!("{}: {}", key, value))
|
.map(|(key, value)| format!("{}: {}", key, value))
|
||||||
.join("\n");
|
.join("\n");
|
||||||
sender.send(output).context("sending response from main thread")?
|
sender
|
||||||
|
.send(DaemonResponse::Success(output))
|
||||||
|
.context("sending response from main thread")?
|
||||||
}
|
}
|
||||||
EwwCommand::PrintDebug(sender) => {
|
DaemonCommand::PrintWindows(sender) => {
|
||||||
|
let output = self
|
||||||
|
.eww_config
|
||||||
|
.get_windows()
|
||||||
|
.keys()
|
||||||
|
.map(|window_name| {
|
||||||
|
let is_open = self.windows.contains_key(window_name);
|
||||||
|
format!("{}{}", if is_open { "*" } else { "" }, window_name)
|
||||||
|
})
|
||||||
|
.join("\n");
|
||||||
|
sender
|
||||||
|
.send(DaemonResponse::Success(output))
|
||||||
|
.context("sending response from main thread")?
|
||||||
|
}
|
||||||
|
DaemonCommand::PrintDebug(sender) => {
|
||||||
let output = format!("state: {:#?}\n\nconfig: {:#?}", &self.eww_state, &self.eww_config);
|
let output = format!("state: {:#?}\n\nconfig: {:#?}", &self.eww_state, &self.eww_config);
|
||||||
sender.send(output).context("sending response from main thread")?
|
sender
|
||||||
|
.send(DaemonResponse::Success(output))
|
||||||
|
.context("sending response from main thread")?
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -329,3 +382,12 @@ fn get_monitor_geometry(n: i32) -> gdk::Rectangle {
|
||||||
.get_default_screen()
|
.get_default_screen()
|
||||||
.get_monitor_geometry(n)
|
.get_monitor_geometry(n)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// In case of an Err, send the error message to a sender.
|
||||||
|
fn respond_with_error<T>(sender: DaemonResponseSender, result: Result<T>) -> Result<()> {
|
||||||
|
match result {
|
||||||
|
Ok(_) => sender.send(DaemonResponse::Success(String::new())),
|
||||||
|
Err(e) => sender.send(DaemonResponse::Failure(format!("{:?}", e))),
|
||||||
|
}
|
||||||
|
.context("sending response from main thread")
|
||||||
|
}
|
||||||
|
|
|
@ -1,6 +1,9 @@
|
||||||
use std::process::Stdio;
|
use std::process::Stdio;
|
||||||
|
|
||||||
use crate::opts::{self, ActionClientOnly};
|
use crate::{
|
||||||
|
app,
|
||||||
|
opts::{self, ActionClientOnly},
|
||||||
|
};
|
||||||
use anyhow::*;
|
use anyhow::*;
|
||||||
use std::{
|
use std::{
|
||||||
io::{Read, Write},
|
io::{Read, Write},
|
||||||
|
@ -20,7 +23,7 @@ pub fn handle_client_only_action(action: ActionClientOnly) -> Result<()> {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn do_server_call(mut stream: UnixStream, action: opts::ActionWithServer) -> Result<Option<String>> {
|
pub fn do_server_call(mut stream: UnixStream, action: opts::ActionWithServer) -> Result<Option<app::DaemonResponse>> {
|
||||||
log::info!("Forwarding options to server");
|
log::info!("Forwarding options to server");
|
||||||
stream
|
stream
|
||||||
.set_nonblocking(false)
|
.set_nonblocking(false)
|
||||||
|
@ -36,13 +39,16 @@ pub fn do_server_call(mut stream: UnixStream, action: opts::ActionWithServer) ->
|
||||||
.write_all(&message_bytes)
|
.write_all(&message_bytes)
|
||||||
.context("Failed to write command to IPC stream")?;
|
.context("Failed to write command to IPC stream")?;
|
||||||
|
|
||||||
let mut buf = String::new();
|
let mut buf = Vec::new();
|
||||||
stream
|
stream
|
||||||
.set_read_timeout(Some(std::time::Duration::from_millis(100)))
|
.set_read_timeout(Some(std::time::Duration::from_millis(100)))
|
||||||
.context("Failed to set read timeout")?;
|
.context("Failed to set read timeout")?;
|
||||||
stream
|
stream.read_to_end(&mut buf).context("Error reading response from server")?;
|
||||||
.read_to_string(&mut buf)
|
|
||||||
.context("Error reading response from server")?;
|
|
||||||
|
|
||||||
Ok(if buf.is_empty() { None } else { Some(buf) })
|
Ok(if buf.is_empty() {
|
||||||
|
None
|
||||||
|
} else {
|
||||||
|
let buf = bincode::deserialize(&buf)?;
|
||||||
|
Some(buf)
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,7 +6,7 @@ use tokio::{
|
||||||
sync::mpsc::*,
|
sync::mpsc::*,
|
||||||
};
|
};
|
||||||
|
|
||||||
pub async fn run_server(evt_send: UnboundedSender<app::EwwCommand>) -> Result<()> {
|
pub async fn run_server(evt_send: UnboundedSender<app::DaemonCommand>) -> Result<()> {
|
||||||
let listener = tokio::net::UnixListener::bind(&*crate::IPC_SOCKET_PATH)?;
|
let listener = tokio::net::UnixListener::bind(&*crate::IPC_SOCKET_PATH)?;
|
||||||
log::info!("IPC server initialized");
|
log::info!("IPC server initialized");
|
||||||
crate::loop_select_exiting! {
|
crate::loop_select_exiting! {
|
||||||
|
@ -25,21 +25,22 @@ pub async fn run_server(evt_send: UnboundedSender<app::EwwCommand>) -> Result<()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Handle a single IPC connection from start to end.
|
/// Handle a single IPC connection from start to end.
|
||||||
async fn handle_connection(mut stream: tokio::net::UnixStream, evt_send: UnboundedSender<app::EwwCommand>) -> Result<()> {
|
async fn handle_connection(mut stream: tokio::net::UnixStream, evt_send: UnboundedSender<app::DaemonCommand>) -> Result<()> {
|
||||||
let (mut stream_read, mut stream_write) = stream.split();
|
let (mut stream_read, mut stream_write) = stream.split();
|
||||||
|
|
||||||
let action: opts::ActionWithServer = read_action_from_stream(&mut stream_read).await?;
|
let action: opts::ActionWithServer = read_action_from_stream(&mut stream_read).await?;
|
||||||
|
|
||||||
log::info!("received command from IPC: {:?}", &action);
|
log::info!("received command from IPC: {:?}", &action);
|
||||||
|
|
||||||
let (command, maybe_response_recv) = action.into_eww_command();
|
let (command, maybe_response_recv) = action.into_daemon_command();
|
||||||
|
|
||||||
evt_send.send(command)?;
|
evt_send.send(command)?;
|
||||||
|
|
||||||
if let Some(mut response_recv) = maybe_response_recv {
|
if let Some(mut response_recv) = maybe_response_recv {
|
||||||
log::info!("Waiting for response for IPC client");
|
log::info!("Waiting for response for IPC client");
|
||||||
if let Ok(Some(response)) = tokio::time::timeout(Duration::from_millis(100), response_recv.recv()).await {
|
if let Ok(Some(response)) = tokio::time::timeout(Duration::from_millis(100), response_recv.recv()).await {
|
||||||
let result = &stream_write.write_all(response.as_bytes()).await;
|
let response = bincode::serialize(&response)?;
|
||||||
|
let result = &stream_write.write_all(&response).await;
|
||||||
crate::print_result_err!("sending text response to ipc client", &result);
|
crate::print_result_err!("sending text response to ipc client", &result);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -69,6 +69,9 @@ fn main() {
|
||||||
client::do_server_call(stream, action).context("Error while forwarding command to server")?;
|
client::do_server_call(stream, action).context("Error while forwarding command to server")?;
|
||||||
if let Some(response) = response {
|
if let Some(response) = response {
|
||||||
println!("{}", response);
|
println!("{}", response);
|
||||||
|
if response.is_failure() {
|
||||||
|
std::process::exit(1);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Err(_) => {
|
Err(_) => {
|
||||||
|
|
55
src/opts.rs
55
src/opts.rs
|
@ -99,6 +99,10 @@ pub enum ActionWithServer {
|
||||||
#[structopt(name = "state")]
|
#[structopt(name = "state")]
|
||||||
ShowState,
|
ShowState,
|
||||||
|
|
||||||
|
/// Print the names of all configured windows. Windows with a * in front of them are currently opened.
|
||||||
|
#[structopt(name = "windows")]
|
||||||
|
ShowWindows,
|
||||||
|
|
||||||
/// Print out the widget structure as seen by eww.
|
/// Print out the widget structure as seen by eww.
|
||||||
///
|
///
|
||||||
/// This may be useful if you are facing issues with how eww is interpreting your configuration,
|
/// This may be useful if you are facing issues with how eww is interpreting your configuration,
|
||||||
|
@ -129,38 +133,49 @@ fn parse_var_update_arg(s: &str) -> Result<(VarName, PrimitiveValue)> {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ActionWithServer {
|
impl ActionWithServer {
|
||||||
pub fn into_eww_command(self) -> (app::EwwCommand, Option<tokio::sync::mpsc::UnboundedReceiver<String>>) {
|
pub fn into_daemon_command(self) -> (app::DaemonCommand, Option<app::DaemonResponseReceiver>) {
|
||||||
let command = match self {
|
let command = match self {
|
||||||
|
ActionWithServer::Update { mappings } => app::DaemonCommand::UpdateVars(mappings.into_iter().collect()),
|
||||||
|
|
||||||
|
ActionWithServer::KillServer => app::DaemonCommand::KillServer,
|
||||||
|
ActionWithServer::CloseAll => app::DaemonCommand::CloseAll,
|
||||||
ActionWithServer::Ping => {
|
ActionWithServer::Ping => {
|
||||||
let (send, recv) = tokio::sync::mpsc::unbounded_channel();
|
let (send, recv) = tokio::sync::mpsc::unbounded_channel();
|
||||||
let _ = send.send("pong".to_owned());
|
let _ = send.send(app::DaemonResponse::Success("pong".to_owned()));
|
||||||
return (app::EwwCommand::NoOp, Some(recv));
|
return (app::DaemonCommand::NoOp, Some(recv));
|
||||||
|
}
|
||||||
|
ActionWithServer::OpenMany { windows } => {
|
||||||
|
return with_response_channel(|sender| app::DaemonCommand::OpenMany { windows, sender });
|
||||||
}
|
}
|
||||||
ActionWithServer::Update { mappings } => app::EwwCommand::UpdateVars(mappings.into_iter().collect()),
|
|
||||||
ActionWithServer::OpenMany { windows } => app::EwwCommand::OpenMany(windows),
|
|
||||||
ActionWithServer::OpenWindow {
|
ActionWithServer::OpenWindow {
|
||||||
window_name,
|
window_name,
|
||||||
pos,
|
pos,
|
||||||
size,
|
size,
|
||||||
anchor,
|
anchor,
|
||||||
} => app::EwwCommand::OpenWindow {
|
} => {
|
||||||
window_name,
|
return with_response_channel(|sender| app::DaemonCommand::OpenWindow {
|
||||||
pos,
|
window_name,
|
||||||
size,
|
pos,
|
||||||
anchor,
|
size,
|
||||||
},
|
anchor,
|
||||||
ActionWithServer::CloseWindow { window_name } => app::EwwCommand::CloseWindow { window_name },
|
sender,
|
||||||
ActionWithServer::KillServer => app::EwwCommand::KillServer,
|
})
|
||||||
ActionWithServer::CloseAll => app::EwwCommand::CloseAll,
|
|
||||||
ActionWithServer::ShowState => {
|
|
||||||
let (send, recv) = tokio::sync::mpsc::unbounded_channel();
|
|
||||||
return (app::EwwCommand::PrintState(send), Some(recv));
|
|
||||||
}
|
}
|
||||||
ActionWithServer::ShowDebug => {
|
ActionWithServer::CloseWindow { window_name } => {
|
||||||
let (send, recv) = tokio::sync::mpsc::unbounded_channel();
|
return with_response_channel(|sender| app::DaemonCommand::CloseWindow { window_name, sender });
|
||||||
return (app::EwwCommand::PrintDebug(send), Some(recv));
|
|
||||||
}
|
}
|
||||||
|
ActionWithServer::ShowWindows => return with_response_channel(app::DaemonCommand::PrintWindows),
|
||||||
|
ActionWithServer::ShowState => return with_response_channel(app::DaemonCommand::PrintState),
|
||||||
|
ActionWithServer::ShowDebug => return with_response_channel(app::DaemonCommand::PrintDebug),
|
||||||
};
|
};
|
||||||
(command, None)
|
(command, None)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn with_response_channel<T, O, F>(f: F) -> (O, Option<tokio::sync::mpsc::UnboundedReceiver<T>>)
|
||||||
|
where
|
||||||
|
F: FnOnce(tokio::sync::mpsc::UnboundedSender<T>) -> O,
|
||||||
|
{
|
||||||
|
let (sender, recv) = tokio::sync::mpsc::unbounded_channel();
|
||||||
|
(f(sender), Some(recv))
|
||||||
|
}
|
||||||
|
|
|
@ -5,7 +5,7 @@ use crate::{
|
||||||
value::{PrimitiveValue, VarName},
|
value::{PrimitiveValue, VarName},
|
||||||
};
|
};
|
||||||
use anyhow::*;
|
use anyhow::*;
|
||||||
use app::EwwCommand;
|
use app::DaemonCommand;
|
||||||
|
|
||||||
use tokio::{
|
use tokio::{
|
||||||
io::{AsyncBufReadExt, BufReader},
|
io::{AsyncBufReadExt, BufReader},
|
||||||
|
@ -15,7 +15,7 @@ use tokio_util::sync::CancellationToken;
|
||||||
|
|
||||||
/// Initialize the script var handler, and return a handle to that handler, which can be used to control
|
/// Initialize the script var handler, and return a handle to that handler, which can be used to control
|
||||||
/// the script var execution.
|
/// the script var execution.
|
||||||
pub fn init(evt_send: UnboundedSender<EwwCommand>) -> ScriptVarHandlerHandle {
|
pub fn init(evt_send: UnboundedSender<DaemonCommand>) -> ScriptVarHandlerHandle {
|
||||||
let (msg_send, mut msg_recv) = tokio::sync::mpsc::unbounded_channel();
|
let (msg_send, mut msg_recv) = tokio::sync::mpsc::unbounded_channel();
|
||||||
let handle = ScriptVarHandlerHandle { msg_send };
|
let handle = ScriptVarHandlerHandle { msg_send };
|
||||||
std::thread::spawn(move || {
|
std::thread::spawn(move || {
|
||||||
|
@ -116,12 +116,12 @@ impl ScriptVarHandler {
|
||||||
}
|
}
|
||||||
|
|
||||||
struct PollVarHandler {
|
struct PollVarHandler {
|
||||||
evt_send: UnboundedSender<EwwCommand>,
|
evt_send: UnboundedSender<DaemonCommand>,
|
||||||
poll_handles: HashMap<VarName, CancellationToken>,
|
poll_handles: HashMap<VarName, CancellationToken>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl PollVarHandler {
|
impl PollVarHandler {
|
||||||
fn new(evt_send: UnboundedSender<EwwCommand>) -> Result<Self> {
|
fn new(evt_send: UnboundedSender<DaemonCommand>) -> Result<Self> {
|
||||||
let handler = PollVarHandler {
|
let handler = PollVarHandler {
|
||||||
evt_send,
|
evt_send,
|
||||||
poll_handles: HashMap::new(),
|
poll_handles: HashMap::new(),
|
||||||
|
@ -139,7 +139,7 @@ impl PollVarHandler {
|
||||||
_ = cancellation_token.cancelled() => break,
|
_ = cancellation_token.cancelled() => break,
|
||||||
_ = tokio::time::sleep(var.interval) => {
|
_ = tokio::time::sleep(var.interval) => {
|
||||||
let result: Result<_> = try {
|
let result: Result<_> = try {
|
||||||
evt_send.send(app::EwwCommand::UpdateVars(vec![(var.name.clone(), var.run_once()?)]))?;
|
evt_send.send(app::DaemonCommand::UpdateVars(vec![(var.name.clone(), var.run_once()?)]))?;
|
||||||
};
|
};
|
||||||
crate::print_result_err!("while running script-var command", &result);
|
crate::print_result_err!("while running script-var command", &result);
|
||||||
}
|
}
|
||||||
|
@ -166,12 +166,12 @@ impl Drop for PollVarHandler {
|
||||||
}
|
}
|
||||||
|
|
||||||
struct TailVarHandler {
|
struct TailVarHandler {
|
||||||
evt_send: UnboundedSender<EwwCommand>,
|
evt_send: UnboundedSender<DaemonCommand>,
|
||||||
tail_process_handles: HashMap<VarName, CancellationToken>,
|
tail_process_handles: HashMap<VarName, CancellationToken>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl TailVarHandler {
|
impl TailVarHandler {
|
||||||
fn new(evt_send: UnboundedSender<EwwCommand>) -> Result<Self> {
|
fn new(evt_send: UnboundedSender<DaemonCommand>) -> Result<Self> {
|
||||||
let handler = TailVarHandler {
|
let handler = TailVarHandler {
|
||||||
evt_send,
|
evt_send,
|
||||||
tail_process_handles: HashMap::new(),
|
tail_process_handles: HashMap::new(),
|
||||||
|
@ -199,7 +199,7 @@ impl TailVarHandler {
|
||||||
_ = cancellation_token.cancelled() => break,
|
_ = cancellation_token.cancelled() => break,
|
||||||
Ok(Some(line)) = stdout_lines.next_line() => {
|
Ok(Some(line)) = stdout_lines.next_line() => {
|
||||||
let new_value = PrimitiveValue::from_string(line.to_owned());
|
let new_value = PrimitiveValue::from_string(line.to_owned());
|
||||||
evt_send.send(EwwCommand::UpdateVars(vec![(var.name.to_owned(), new_value)]))?;
|
evt_send.send(DaemonCommand::UpdateVars(vec![(var.name.to_owned(), new_value)]))?;
|
||||||
}
|
}
|
||||||
else => break,
|
else => break,
|
||||||
}
|
}
|
||||||
|
|
|
@ -67,7 +67,7 @@ pub fn initialize_server() -> Result<()> {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn init_async_part(config_file_path: PathBuf, scss_file_path: PathBuf, ui_send: UnboundedSender<app::EwwCommand>) {
|
fn init_async_part(config_file_path: PathBuf, scss_file_path: PathBuf, ui_send: UnboundedSender<app::DaemonCommand>) {
|
||||||
std::thread::spawn(move || {
|
std::thread::spawn(move || {
|
||||||
let rt = tokio::runtime::Builder::new_multi_thread()
|
let rt = tokio::runtime::Builder::new_multi_thread()
|
||||||
.enable_all()
|
.enable_all()
|
||||||
|
@ -91,7 +91,7 @@ fn init_async_part(config_file_path: PathBuf, scss_file_path: PathBuf, ui_send:
|
||||||
let _ = crate::application_lifecycle::recv_exit().await;
|
let _ = crate::application_lifecycle::recv_exit().await;
|
||||||
log::info!("Forward task received exit event");
|
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::DaemonCommand::KillServer);
|
||||||
})
|
})
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -108,7 +108,7 @@ fn init_async_part(config_file_path: PathBuf, scss_file_path: PathBuf, ui_send:
|
||||||
async fn run_filewatch<P: AsRef<Path>>(
|
async fn run_filewatch<P: AsRef<Path>>(
|
||||||
config_file_path: P,
|
config_file_path: P,
|
||||||
scss_file_path: P,
|
scss_file_path: P,
|
||||||
evt_send: UnboundedSender<app::EwwCommand>,
|
evt_send: UnboundedSender<app::DaemonCommand>,
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
let mut inotify = inotify::Inotify::init().context("Failed to initialize inotify")?;
|
let mut inotify = inotify::Inotify::init().context("Failed to initialize inotify")?;
|
||||||
let config_file_descriptor = inotify
|
let config_file_descriptor = inotify
|
||||||
|
@ -127,11 +127,11 @@ async fn run_filewatch<P: AsRef<Path>>(
|
||||||
if event.wd == config_file_descriptor {
|
if event.wd == config_file_descriptor {
|
||||||
log::info!("Reloading eww configuration");
|
log::info!("Reloading eww configuration");
|
||||||
let new_eww_config = config::EwwConfig::read_from_file(config_file_path.as_ref())?;
|
let new_eww_config = config::EwwConfig::read_from_file(config_file_path.as_ref())?;
|
||||||
evt_send.send(app::EwwCommand::ReloadConfig(new_eww_config))?;
|
evt_send.send(app::DaemonCommand::ReloadConfig(new_eww_config))?;
|
||||||
} else if event.wd == scss_file_descriptor {
|
} else if event.wd == scss_file_descriptor {
|
||||||
log::info!("reloading eww css file");
|
log::info!("reloading eww css file");
|
||||||
let eww_css = crate::util::parse_scss_from_file(scss_file_path.as_ref())?;
|
let eww_css = crate::util::parse_scss_from_file(scss_file_path.as_ref())?;
|
||||||
evt_send.send(app::EwwCommand::ReloadCss(eww_css))?;
|
evt_send.send(app::DaemonCommand::ReloadCss(eww_css))?;
|
||||||
} else {
|
} else {
|
||||||
eprintln!("Got inotify event for unknown thing: {:?}", event);
|
eprintln!("Got inotify event for unknown thing: {:?}", event);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue