improve window closing and result handling

this makes sure the window is always gone before
something is written to the input
when using worf-warden

Signed-off-by: Alexander Mohr <git@mohr.io>
This commit is contained in:
Alexander Mohr 2025-05-06 19:06:02 +02:00
parent a3d4fc8551
commit 4f4bd116f9

View file

@ -8,7 +8,7 @@ use crossbeam::channel;
use crossbeam::channel::Sender; use crossbeam::channel::Sender;
use gdk4::Display; use gdk4::Display;
use gdk4::gio::File; use gdk4::gio::File;
use gdk4::glib::{Propagation, timeout_add_local}; use gdk4::glib::{Propagation, timeout_add_local, MainContext};
use gdk4::prelude::{Cast, DisplayExt, MonitorExt, SurfaceExt}; use gdk4::prelude::{Cast, DisplayExt, MonitorExt, SurfaceExt};
use gtk4::glib::ControlFlow; use gtk4::glib::ControlFlow;
use gtk4::prelude::{ use gtk4::prelude::{
@ -454,7 +454,15 @@ where
let gtk_args: [&str; 0] = []; let gtk_args: [&str; 0] = [];
app.run_with_args(&gtk_args); app.run_with_args(&gtk_args);
receiver.recv().map_err(|e| Error::Io(e.to_string()))? // Use glib's MainContext to handle the receiver asynchronously
let main_context = MainContext::default();
let receiver_result = main_context.block_on(async {
MainContext::default().spawn_local(async move {
receiver.recv().map_err(|e| Error::Io(e.to_string()))
}).await.unwrap_or_else(|e| Err(Error::Io(e.to_string())))
});
receiver_result?
} }
fn build_ui<T, P>( fn build_ui<T, P>(
@ -788,8 +796,8 @@ fn handle_key_press<T: Clone + 'static + Send>(
{ {
let search_lock = ui.search_text.lock().unwrap(); let search_lock = ui.search_text.lock().unwrap();
if let Err(e) = handle_selected_item( if let Err(e) = handle_selected_item(
ui, ui.clone(),
meta, meta.clone(),
Some(&search_lock), Some(&search_lock),
None, None,
meta.new_on_empty, meta.new_on_empty,
@ -811,7 +819,7 @@ fn handle_key_press<T: Clone + 'static + Send>(
gdk4::Key::Return => { gdk4::Key::Return => {
let search_lock = ui.search_text.lock().unwrap(); let search_lock = ui.search_text.lock().unwrap();
if let Err(e) = if let Err(e) =
handle_selected_item(ui, meta, Some(&search_lock), None, meta.new_on_empty, None) handle_selected_item(ui.clone(), meta.clone(), Some(&search_lock), None, meta.new_on_empty, None)
{ {
log::error!("{e}"); log::error!("{e}");
} }
@ -942,25 +950,25 @@ fn close_gui(app: &Application) {
} }
fn handle_selected_item<T>( fn handle_selected_item<T>(
ui: &UiElements<T>, ui: Rc<UiElements<T>>,
meta: &MetaData<T>, meta: Rc<MetaData<T>>,
query: Option<&str>, query: Option<&str>,
item: Option<MenuItem<T>>, item: Option<MenuItem<T>>,
new_on_empty: bool, new_on_empty: bool,
custom_key: Option<&KeyBinding>, custom_key: Option<&KeyBinding>,
) -> Result<(), String> ) -> Result<(), String>
where where
T: Clone + Send, T: Clone + Send +'static,
{ {
if let Some(selected_item) = item { if let Some(selected_item) = item {
send_selected_item(ui, meta, custom_key, &selected_item); send_selected_item(ui, meta, custom_key.map(|c| c.clone()), selected_item);
return Ok(()); return Ok(());
} else if let Some(s) = ui.main_box.selected_children().into_iter().next() { } else if let Some(s) = ui.main_box.selected_children().into_iter().next() {
let list_items = ui.menu_rows.lock().unwrap(); let list_items = ui.menu_rows.lock().unwrap();
let item = list_items.get(&s); let item = list_items.get(&s);
if let Some(selected_item) = item { if let Some(selected_item) = item {
if selected_item.visible { if selected_item.visible {
send_selected_item(ui, meta, custom_key, selected_item); send_selected_item(ui.clone(), meta, custom_key.map(|c| c.clone()), selected_item.clone());
return Ok(()); return Ok(());
} }
} }
@ -979,7 +987,7 @@ where
visible: true, visible: true,
}; };
send_selected_item(ui, meta, custom_key, &item); send_selected_item(ui, meta, custom_key.map(|c| c.clone()), item);
Ok(()) Ok(())
} else { } else {
Err("selected item cannot be resolved".to_owned()) Err("selected item cannot be resolved".to_owned())
@ -987,21 +995,24 @@ where
} }
fn send_selected_item<T>( fn send_selected_item<T>(
ui: &UiElements<T>, ui: Rc<UiElements<T>>,
meta: &MetaData<T>, meta: Rc<MetaData<T>>,
custom_key: Option<&KeyBinding>, custom_key: Option<KeyBinding>,
selected_item: &MenuItem<T>, selected_item: MenuItem<T>,
) where ) where
T: Clone + Send, T: Clone + Send + 'static,
{ {
ui.window.close(); let ui_clone = Rc::clone(&ui);
if let Err(e) = meta.selected_sender.send(Ok(Selection { ui.window.connect_hide(move |w| {
menu: selected_item.clone(), if let Err(e) = meta.selected_sender.send(Ok(Selection {
custom_key: custom_key.cloned(), menu: selected_item.clone(),
})) { custom_key: custom_key.clone(),
log::error!("failed to send message {e}"); })) {
} log::error!("failed to send message {e}");
close_gui(&ui.app); }
});
ui.window.hide();
close_gui(&ui_clone.app);
} }
fn add_menu_item<T: Clone + 'static + Send>( fn add_menu_item<T: Clone + 'static + Send>(
@ -1108,8 +1119,8 @@ fn create_menu_row<T: Clone + 'static + Send>(
click.connect_pressed(move |_gesture, n_press, _x, _y| { click.connect_pressed(move |_gesture, n_press, _x, _y| {
if n_press == 2 { if n_press == 2 {
if let Err(e) = handle_selected_item( if let Err(e) = handle_selected_item(
click_ui.as_ref(), click_ui.clone(),
click_meta.as_ref(), click_meta.clone(),
None, None,
Some(element_clone.clone()), Some(element_clone.clone()),
false, false,