diff --git a/espanso/src/engine/event/mod.rs b/espanso/src/engine/event/mod.rs index e5fedaa..89b843f 100644 --- a/espanso/src/engine/event/mod.rs +++ b/espanso/src/engine/event/mod.rs @@ -72,6 +72,8 @@ pub enum EventType { Disabled, Enabled, + DisableRequest, + EnableRequest, SecureInputEnabled, SecureInputDisabled, diff --git a/espanso/src/engine/process/middleware/context_menu.rs b/espanso/src/engine/process/middleware/context_menu.rs index 1bca094..95efb32 100644 --- a/espanso/src/engine/process/middleware/context_menu.rs +++ b/espanso/src/engine/process/middleware/context_menu.rs @@ -17,6 +17,8 @@ * along with espanso. If not, see . */ +use std::cell::RefCell; + use super::super::Middleware; use crate::engine::event::{ ui::{MenuItem, ShowContextMenuEvent, SimpleMenuItem}, @@ -25,12 +27,18 @@ use crate::engine::event::{ const CONTEXT_ITEM_EXIT: u32 = 0; const CONTEXT_ITEM_RELOAD: u32 = 1; +const CONTEXT_ITEM_ENABLE: u32 = 2; +const CONTEXT_ITEM_DISABLE: u32 = 3; -pub struct ContextMenuMiddleware {} +pub struct ContextMenuMiddleware { + is_enabled: RefCell, +} impl ContextMenuMiddleware { pub fn new() -> Self { - Self {} + Self { + is_enabled: RefCell::new(true), + } } } @@ -39,7 +47,9 @@ impl Middleware for ContextMenuMiddleware { "context_menu" } - fn next(&self, event: Event, _: &mut dyn FnMut(Event)) -> Event { + fn next(&self, event: Event, dispatch: &mut dyn FnMut(Event)) -> Event { + let mut is_enabled = self.is_enabled.borrow_mut(); + match &event.etype { EventType::TrayIconClicked => { // TODO: fetch top matches for the active config to be added @@ -53,6 +63,18 @@ impl Middleware for ContextMenuMiddleware { EventType::ShowContextMenu(ShowContextMenuEvent { // TODO: add actual entries items: vec![ + MenuItem::Simple(if *is_enabled { + SimpleMenuItem { + id: CONTEXT_ITEM_DISABLE, + label: "Disable".to_string(), + } + } else { + SimpleMenuItem { + id: CONTEXT_ITEM_ENABLE, + label: "Enable".to_string(), + } + }), + MenuItem::Separator, MenuItem::Simple(SimpleMenuItem { id: CONTEXT_ITEM_RELOAD, label: "Reload config".to_string(), @@ -76,12 +98,28 @@ impl Middleware for ContextMenuMiddleware { event.source_id, EventType::ExitRequested(ExitMode::RestartWorker), ), + CONTEXT_ITEM_ENABLE => { + dispatch(Event::caused_by(event.source_id, EventType::EnableRequest)); + Event::caused_by(event.source_id, EventType::NOOP) + } + CONTEXT_ITEM_DISABLE => { + dispatch(Event::caused_by(event.source_id, EventType::DisableRequest)); + Event::caused_by(event.source_id, EventType::NOOP) + } custom => { // TODO: handle dynamic items todo!() } } } + EventType::Disabled => { + *is_enabled = false; + event + } + EventType::Enabled => { + *is_enabled = true; + event + } _ => event, } } diff --git a/espanso/src/engine/process/middleware/disable.rs b/espanso/src/engine/process/middleware/disable.rs index 83902e8..0a7c01f 100644 --- a/espanso/src/engine/process/middleware/disable.rs +++ b/espanso/src/engine/process/middleware/disable.rs @@ -22,16 +22,18 @@ use std::{ time::{Duration, Instant}, }; -use log::{info}; +use log::info; use super::super::Middleware; -use crate::engine::{event::{Event, EventType, input::{Key, KeyboardEvent, Status, Variant}}}; +use crate::engine::event::{ + input::{Key, KeyboardEvent, Status, Variant}, + Event, EventType, +}; pub struct DisableOptions { pub toggle_key: Option, pub toggle_key_variant: Option, pub toggle_key_maximum_window: Duration, - // TODO: toggle shortcut? } @@ -60,21 +62,32 @@ impl Middleware for DisableMiddleware { let mut has_status_changed = false; let mut enabled = self.enabled.borrow_mut(); - if let EventType::Keyboard(m_event) = &event.etype { - if is_toggle_key(m_event, &self.options) { - let mut last_toggle_press = self.last_toggle_press.borrow_mut(); - if let Some(previous_press) = *last_toggle_press { - if previous_press.elapsed() < self.options.toggle_key_maximum_window { - *enabled = !*enabled; - *last_toggle_press = None; - has_status_changed = true; + match &event.etype { + EventType::Keyboard(m_event) => { + if is_toggle_key(m_event, &self.options) { + let mut last_toggle_press = self.last_toggle_press.borrow_mut(); + if let Some(previous_press) = *last_toggle_press { + if previous_press.elapsed() < self.options.toggle_key_maximum_window { + *enabled = !*enabled; + *last_toggle_press = None; + has_status_changed = true; + } else { + *last_toggle_press = Some(Instant::now()); + } } else { *last_toggle_press = Some(Instant::now()); } - } else { - *last_toggle_press = Some(Instant::now()); } + }, + EventType::EnableRequest => { + *enabled = true; + has_status_changed = true; + }, + EventType::DisableRequest => { + *enabled = false; + has_status_changed = true; } + _ => {} } if has_status_changed {