improve key handler construction

This commit is contained in:
Alexander Mohr 2025-07-13 01:09:36 +02:00
parent b63b02830a
commit 3d9d5689c7
5 changed files with 58 additions and 54 deletions

1
Cargo.lock generated
View file

@ -2923,6 +2923,7 @@ dependencies = [
name = "worf-warden"
version = "0.1.0"
dependencies = [
"clap",
"env_logger",
"log",
"serde",

View file

@ -8,4 +8,4 @@ worf = {path = "../../worf"}
env_logger = "0.11.8"
log = "0.4.27"
serde = { version = "1.0.219", features = ["derive"] }
clap = { version = "4.5.40", features = ["derive"] }

View file

@ -1,3 +1,4 @@
use clap::Parser;
use serde::{Deserialize, Serialize};
use std::{
collections::HashMap,
@ -395,19 +396,28 @@ struct WardenConfig {
custom_auto_types: HashMap<String, String>,
}
#[derive(Debug, Parser, Clone)]
struct WardenArgs {
/// Configuration file for worf warden
#[clap(long = "warden-config")]
warden_config: Option<String>,
#[command(flatten)]
worf: Config,
}
fn main() -> Result<(), String> {
env_logger::Builder::new()
.parse_filters(&env::var("RUST_LOG").unwrap_or_else(|_| "error".to_owned()))
.format_timestamp_micros()
.init();
let args = config::parse_args();
let worf_config = Arc::new(RwLock::new(
config::load_worf_config(Some(&args)).unwrap_or(args.clone()),
));
let mut cfg = WardenArgs::parse();
cfg.worf = config::load_worf_config(Some(&cfg.worf)).unwrap_or(cfg.worf);
let warden_config: WardenConfig = config::load_config(Some(&args), "worf", "warden")
.map_err(|e| format!("failed to parse warden config {e}"))?;
let warden_config: WardenConfig =
config::load_config(cfg.warden_config.as_deref(), "worf", "warden")
.map_err(|e| format!("failed to parse warden config {e}"))?;
if !groups().contains("input") {
log::error!(
@ -421,6 +431,8 @@ fn main() -> Result<(), String> {
log::error!("Failed to start ydotool daemon: {e}");
}
let worf_config = Arc::new(RwLock::new(cfg.worf.clone()));
// todo eventually use a propper rust client for this, for now rbw is good enough
let provider = Arc::new(Mutex::new(PasswordProvider::new(
&worf_config.read().unwrap(),

View file

@ -945,13 +945,16 @@ fn style_path(full_path: Option<&String>) -> Result<PathBuf, Error> {
vec![dirs::config_dir()],
&PathBuf::from("worf").join("style.css"),
);
resolve_path(full_path, alternative_paths.into_iter().collect())
resolve_path(
full_path.map(std::string::String::as_str),
alternative_paths.into_iter().collect(),
)
}
/// # Errors
///
/// Will return Err when it cannot resolve any path or no style is found
pub fn conf_path(full_path: Option<&String>, folder: &str, name: &str) -> Result<PathBuf, Error> {
pub fn conf_path(full_path: Option<&str>, folder: &str, name: &str) -> Result<PathBuf, Error> {
let alternative_paths =
path_alternatives(vec![dirs::config_dir()], &PathBuf::from(folder).join(name));
resolve_path(full_path, alternative_paths.into_iter().collect())
@ -971,10 +974,7 @@ pub fn path_alternatives(base_paths: Vec<Option<PathBuf>>, sub_path: &PathBuf) -
/// # Errors
///
/// Will return `Err` if it is not able to find any valid path
pub fn resolve_path(
full_path: Option<&String>,
alternatives: Vec<PathBuf>,
) -> Result<PathBuf, Error> {
pub fn resolve_path(full_path: Option<&str>, alternatives: Vec<PathBuf>) -> Result<PathBuf, Error> {
log::debug!("resolving path for {full_path:?}, with alternatives: {alternatives:?}");
full_path
.map(PathBuf::from)
@ -988,6 +988,7 @@ pub fn resolve_path(
.ok_or(Error::MissingFile)
}
/// Load the worf config from disk
/// # Errors
///
/// Will return Err when it
@ -996,7 +997,11 @@ pub fn resolve_path(
/// * no config file exists
/// * config file and args cannot be merged
pub fn load_worf_config(args_opt: Option<&Config>) -> Result<Config, Error> {
let mut config = load_config(args_opt, "worf", "config")?;
let mut config = load_config(
args_opt.as_ref().and_then(|c| c.cfg_path.as_deref()),
"worf",
"config",
)?;
if let Some(args) = args_opt {
let merge_result = merge_config_with_args(&mut config, args)
.map_err(|e| Error::ParsingError(format!("{e}")))?;
@ -1006,6 +1011,7 @@ pub fn load_worf_config(args_opt: Option<&Config>) -> Result<Config, Error> {
}
}
/// Load any config from disk
/// # Errors
///
/// Will return Err when it
@ -1014,15 +1020,11 @@ pub fn load_worf_config(args_opt: Option<&Config>) -> Result<Config, Error> {
/// * no config file exists
/// * config file and args cannot be merged
pub fn load_config<T: DeserializeOwned>(
args_opt: Option<&Config>,
path: Option<&str>,
folder: &str,
name: &str,
) -> Result<T, Error> {
let config_path = conf_path(
args_opt.as_ref().and_then(|c| c.cfg_path.as_ref()),
folder,
name,
);
let config_path = conf_path(path, folder, name);
match config_path {
Ok(path) => {
log::debug!("loading config from {}", path.display());

View file

@ -984,42 +984,31 @@ fn setup_key_event_handler<T: Clone + 'static + Send>(
meta: &Rc<MetaData<T>>,
custom_keys: Option<&CustomKeys>,
) {
// handle keys as soon as possible
// Remove old handler, use only one for both window and search
let key_controller_window = EventControllerKey::new();
key_controller_window.set_propagation_phase(gtk4::PropagationPhase::Capture);
let ui_clone = Rc::clone(ui_elements);
let meta_clone = Rc::clone(meta);
let keys_clone = custom_keys.cloned();
key_controller_window.connect_key_pressed(move |_, key_value, key_code, modifier| {
handle_key_press(
&ui_clone,
&meta_clone,
key_value,
key_code,
modifier,
keys_clone.as_ref(),
)
});
fn connect_key_handler<
T: gtk4::prelude::ObjectExt + Clone + 'static + WidgetExt,
Menu: Clone + 'static + Send,
>(
widget: &T,
ui: &Rc<UiElements<Menu>>,
meta: &Rc<MetaData<Menu>>,
keys: Option<CustomKeys>,
) {
let controller = EventControllerKey::new();
controller.set_propagation_phase(gtk4::PropagationPhase::Capture);
ui_elements.window.add_controller(key_controller_window);
let ui = Rc::clone(ui);
let meta = Rc::clone(meta);
controller.connect_key_pressed(move |_, key_value, key_code, modifier| {
handle_key_press(&ui, &meta, key_value, key_code, modifier, keys.as_ref())
});
widget.add_controller(controller.clone());
}
let key_controller_search = EventControllerKey::new();
key_controller_search.set_propagation_phase(gtk4::PropagationPhase::Capture);
let ui_clone2 = Rc::clone(ui_elements);
let meta_clone2 = Rc::clone(meta);
let keys_clone2 = custom_keys.cloned();
key_controller_search.connect_key_pressed(move |_, key_value, key_code, modifier| {
handle_key_press(
&ui_clone2,
&meta_clone2,
key_value,
key_code,
modifier,
keys_clone2.as_ref(),
)
});
ui_elements.search.add_controller(key_controller_search);
// Setup window controller
connect_key_handler(&ui_elements.window, ui_elements, meta, custom_keys.cloned());
// Setup search controller
connect_key_handler(&ui_elements.search, ui_elements, meta, custom_keys.cloned());
}
fn is_key_match(