Skip to content

Commit 4ded063

Browse files
liegleliegle
andauthored
feat: Add unfocus-close property in defwindow (#1442)
* feat: Add unfocus-close attribute of window to close it when it loses kbd focus * update markdowns --------- Co-authored-by: liegle <whatliegle@gmail.com>
1 parent 865cf63 commit 4ded063

5 files changed

Lines changed: 51 additions & 1 deletion

File tree

‎CHANGELOG.md‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ All notable changes to eww will be listed here, starting at changes since versio
4242
- Add `value-pos` to scale widget (By: ipsvn)
4343
- Add `floor` and `ceil` function calls to simplexpr (By: wsbankenstein)
4444
- Add `formatbytes` function calls to simplexpr (By: topongo)
45+
- Add `unfocus-close` property in defwindow (By: liegle)
4546

4647
## [0.6.0] (21.04.2024)
4748

‎crates/eww/src/app.rs‎

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -473,6 +473,32 @@ impl<B: DisplayBackend> App<B> {
473473
}
474474
}
475475

476+
if initiator.unfocus_close {
477+
eww_window.gtk_window.connect_focus_out_event({
478+
let app_evt_sender = self.app_evt_send.clone();
479+
let instance_id = instance_id.to_string();
480+
move |_, _| {
481+
// we don't care about the actual error response from the daemon as this is mostly just a fallback.
482+
// Generally, this should get disconnected before the gtk window gets destroyed.
483+
// This callback is triggered in 2 cases:
484+
// - When the monitor of this window gets disconnected
485+
// - When the window is closed manually.
486+
// We don't distinguish here and assume the window should be reopened once a monitor
487+
// becomes available again
488+
let (response_sender, _) = daemon_response::create_pair();
489+
let command = DaemonCommand::CloseWindows {
490+
windows: vec![instance_id.clone()],
491+
auto_reopen: false,
492+
sender: response_sender,
493+
};
494+
if let Err(err) = app_evt_sender.send(command) {
495+
log::error!("Error sending close window command to daemon after gtk window destroy event: {}", err);
496+
}
497+
gtk::glib::Propagation::Proceed
498+
}
499+
});
500+
}
501+
476502
eww_window.destroy_event_handler_id = Some(eww_window.gtk_window.connect_destroy({
477503
let app_evt_sender = self.app_evt_send.clone();
478504
let instance_id = instance_id.to_string();

‎crates/eww/src/window_initiator.rs‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ pub struct WindowInitiator {
2121
pub monitor: Option<MonitorIdentifier>,
2222
pub name: String,
2323
pub resizable: bool,
24+
pub unfocus_close: bool,
2425
pub stacking: WindowStacking,
2526
}
2627

@@ -40,6 +41,7 @@ impl WindowInitiator {
4041
name: window_def.name.clone(),
4142
resizable: window_def.eval_resizable(&vars)?,
4243
stacking: window_def.eval_stacking(&vars)?,
44+
unfocus_close: window_def.eval_close_on_focus_lost(&vars)?,
4345
local_variables: vars,
4446
})
4547
}

‎crates/yuck/src/config/window_definition.rs‎

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ pub struct WindowDefinition {
3939
pub monitor: Option<SimplExpr>,
4040
pub widget: WidgetUse,
4141
pub resizable: Option<SimplExpr>,
42+
pub unfocus_close: Option<SimplExpr>,
4243
pub backend_options: BackendWindowOptionsDef,
4344
}
4445

@@ -72,6 +73,13 @@ impl WindowDefinition {
7273
None => Ok(WindowStacking::Foreground),
7374
}
7475
}
76+
77+
pub fn eval_close_on_focus_lost(&self, local_variables: &HashMap<VarName, DynVal>) -> Result<bool, EvalError> {
78+
Ok(match &self.unfocus_close {
79+
Some(expr) => expr.eval(local_variables)?.as_bool()?,
80+
None => false,
81+
})
82+
}
7583
}
7684

7785
impl FromAstElementContent for WindowDefinition {
@@ -86,10 +94,22 @@ impl FromAstElementContent for WindowDefinition {
8694
let resizable = attrs.ast_optional("resizable")?;
8795
let stacking = attrs.ast_optional("stacking")?;
8896
let geometry = attrs.ast_optional("geometry")?;
97+
let unfocus_close = attrs.ast_optional("unfocus-close")?;
8998
let backend_options = BackendWindowOptionsDef::from_attrs(&mut attrs)?;
9099
let widget = iter.expect_any().map_err(DiagError::from).and_then(WidgetUse::from_ast)?;
91100
iter.expect_done()?;
92-
Ok(Self { name, expected_args, args_span, monitor, resizable, widget, stacking, geometry, backend_options })
101+
Ok(Self {
102+
name,
103+
expected_args,
104+
args_span,
105+
monitor,
106+
resizable,
107+
widget,
108+
stacking,
109+
geometry,
110+
unfocus_close,
111+
backend_options,
112+
})
93113
}
94114
}
95115

‎docs/src/configuration.md‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@ You can now open your first window by running `eww open example`! Glorious!
5252
| ---------: | ------------------------------------------------------------ |
5353
| `monitor` | Which monitor this window should be displayed on. See below for details.|
5454
| `geometry` | Geometry of the window. |
55+
| `unfocus-close` | Automaticly close this window when losing keyboard focus. |
5556

5657

5758
**`monitor`-property**

0 commit comments

Comments
 (0)