Skip to content

Commit

Permalink
Support --duration close timer for windows (#884)
Browse files Browse the repository at this point in the history
  • Loading branch information
elkowar authored Aug 18, 2023
1 parent 393f7fa commit a9a35c1
Show file tree
Hide file tree
Showing 6 changed files with 69 additions and 12 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ All notable changes to eww will be listed here, starting at changes since versio
- Add `EWW_TIME` magic variable (By: Erenoit)
- Add trigonometric functions (`sin`, `cos`, `tan`, `cot`) and degree/radian conversions (`degtorad`, `radtodeg`) (By: end-4)
- Add `substring` function to simplexpr
- Add `--duration` flag to `eww open`

## [0.4.0] (04.09.2022)

Expand Down
7 changes: 5 additions & 2 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 1 addition & 2 deletions crates/eww/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -50,8 +50,7 @@ simple-signal = "1.1"
unescape = "0.1"

tokio = { version = "1.31.0", features = ["full"] }
futures-core = "0.3.28"
futures-util = "0.3.28"
futures = "0.3.28"
tokio-util = "0.7.8"

sysinfo = "0.29.8"
Expand Down
58 changes: 51 additions & 7 deletions crates/eww/src/app.rs
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ pub enum DaemonCommand {
anchor: Option<AnchorPoint>,
screen: Option<MonitorIdentifier>,
should_toggle: bool,
duration: Option<std::time::Duration>,
sender: DaemonResponseSender,
},
CloseWindows {
Expand Down Expand Up @@ -114,6 +115,9 @@ pub struct App<B> {
pub app_evt_send: UnboundedSender<DaemonCommand>,
pub script_var_handler: ScriptVarHandlerHandle,

/// Senders that will cancel a windows auto-close timer when started with --duration.
pub window_close_timer_abort_senders: HashMap<String, futures::channel::oneshot::Sender<()>>,

pub paths: EwwPaths,
}

Expand Down Expand Up @@ -181,20 +185,27 @@ impl<B: DisplayBackend> App<B> {
if should_toggle && self.open_windows.contains_key(w) {
self.close_window(w)
} else {
self.open_window(w, None, None, None, None)
self.open_window(w, None, None, None, None, None)
}
})
.filter_map(Result::err);
sender.respond_with_error_list(errors)?;
}
DaemonCommand::OpenWindow { window_name, pos, size, anchor, screen: monitor, should_toggle, sender } => {
DaemonCommand::OpenWindow {
window_name,
pos,
size,
anchor,
screen: monitor,
should_toggle,
duration,
sender,
} => {
let is_open = self.open_windows.contains_key(&window_name);
let result = if !is_open {
self.open_window(&window_name, pos, size, monitor, anchor)
} else if should_toggle {
let result = if should_toggle && is_open {
self.close_window(&window_name)
} else {
Ok(())
self.open_window(&window_name, pos, size, monitor, anchor, duration)
};
sender.respond_with_result(result)?;
}
Expand Down Expand Up @@ -294,6 +305,9 @@ impl<B: DisplayBackend> App<B> {

/// Close a window and do all the required cleanups in the scope_graph and script_var_handler
fn close_window(&mut self, window_name: &str) -> Result<()> {
if let Some(old_abort_send) = self.window_close_timer_abort_senders.remove(window_name) {
_ = old_abort_send.send(());
}
let eww_window = self
.open_windows
.remove(window_name)
Expand All @@ -320,11 +334,13 @@ impl<B: DisplayBackend> App<B> {
size: Option<Coords>,
monitor: Option<MonitorIdentifier>,
anchor: Option<AnchorPoint>,
duration: Option<std::time::Duration>,
) -> Result<()> {
self.failed_windows.remove(window_name);
log::info!("Opening window {}", window_name);

// if an instance of this is already running, close it
// TODO make reopening optional via a --no-reopen flag?
if self.open_windows.contains_key(window_name) {
self.close_window(window_name)?;
}
Expand Down Expand Up @@ -380,6 +396,34 @@ impl<B: DisplayBackend> App<B> {
}
}));

if let Some(duration) = duration {
let app_evt_sender = self.app_evt_send.clone();
let window_name = window_name.to_string();

let (abort_send, abort_recv) = futures::channel::oneshot::channel();

glib::MainContext::default().spawn_local({
let window_name = window_name.clone();
async move {
tokio::select! {
_ = glib::timeout_future(duration) => {
let (response_sender, mut response_recv) = daemon_response::create_pair();
let command = DaemonCommand::CloseWindows { windows: vec![window_name], sender: response_sender };
if let Err(err) = app_evt_sender.send(command) {
log::error!("Error sending close window command to daemon after gtk window destroy event: {}", err);
}
_ = response_recv.recv().await;
}
_ = abort_recv => {}
}
}
});

if let Some(old_abort_send) = self.window_close_timer_abort_senders.insert(window_name, abort_send) {
_ = old_abort_send.send(());
}
}

self.open_windows.insert(window_name.to_string(), eww_window);
};

Expand Down Expand Up @@ -407,7 +451,7 @@ impl<B: DisplayBackend> App<B> {
let window_names: Vec<String> =
self.open_windows.keys().cloned().chain(self.failed_windows.iter().cloned()).dedup().collect();
for window_name in &window_names {
self.open_window(window_name, None, None, None, None)?;
self.open_window(window_name, None, None, None, None, None)?;
}
Ok(())
}
Expand Down
11 changes: 10 additions & 1 deletion crates/eww/src/opts.rs
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,10 @@ pub enum ActionWithServer {
/// If the window is already open, close it instead
#[arg(long = "toggle")]
should_toggle: bool,

/// Automatically close the window after a specified amount of time, i.e.: 1s
#[arg(long, value_parser=parse_duration)]
duration: Option<std::time::Duration>,
},

/// Open multiple windows at once.
Expand Down Expand Up @@ -218,14 +222,15 @@ impl ActionWithServer {
ActionWithServer::OpenMany { windows, should_toggle } => {
return with_response_channel(|sender| app::DaemonCommand::OpenMany { windows, should_toggle, sender });
}
ActionWithServer::OpenWindow { window_name, pos, size, screen, anchor, should_toggle } => {
ActionWithServer::OpenWindow { window_name, pos, size, screen, anchor, should_toggle, duration } => {
return with_response_channel(|sender| app::DaemonCommand::OpenWindow {
window_name,
pos,
size,
anchor,
screen,
should_toggle,
duration,
sender,
})
}
Expand Down Expand Up @@ -254,3 +259,7 @@ where
let (sender, recv) = daemon_response::create_pair();
(f(sender), Some(recv))
}

fn parse_duration(s: &str) -> Result<std::time::Duration, simplexpr::dynval::ConversionError> {
DynVal::from_string(s.to_owned()).as_duration()
}
1 change: 1 addition & 0 deletions crates/eww/src/server.rs
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,7 @@ pub fn initialize_server<B: DisplayBackend>(
css_provider: gtk::CssProvider::new(),
script_var_handler,
app_evt_send: ui_send.clone(),
window_close_timer_abort_senders: HashMap::new(),
paths,
};

Expand Down

0 comments on commit a9a35c1

Please sign in to comment.