feat(core): add support for Disable/Enable
This commit is contained in:
parent
d193cb749b
commit
5abea19016
|
@ -61,6 +61,10 @@ impl<'a> ConfigManager<'a> {
|
||||||
let match_paths = config.match_paths();
|
let match_paths = config.match_paths();
|
||||||
(config, self.match_store.query(&match_paths))
|
(config, self.match_store.query(&match_paths))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn default(&self) -> &'a dyn Config {
|
||||||
|
self.config_store.default()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: test
|
// TODO: test
|
||||||
|
|
46
espanso/src/cli/worker/engine/executor/icon.rs
Normal file
46
espanso/src/cli/worker/engine/executor/icon.rs
Normal file
|
@ -0,0 +1,46 @@
|
||||||
|
/*
|
||||||
|
* This file is part of espanso.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2019-2021 Federico Terzi
|
||||||
|
*
|
||||||
|
* espanso is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* espanso is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with espanso. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
use espanso_ui::{UIRemote, icons::TrayIcon};
|
||||||
|
|
||||||
|
use crate::engine::{dispatch::IconHandler, event::ui::IconStatus};
|
||||||
|
|
||||||
|
pub struct IconHandlerAdapter<'a> {
|
||||||
|
remote: &'a dyn UIRemote,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> IconHandlerAdapter<'a> {
|
||||||
|
pub fn new(remote: &'a dyn UIRemote) -> Self {
|
||||||
|
Self { remote }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> IconHandler for IconHandlerAdapter<'a> {
|
||||||
|
fn update_icon(&self, status: &IconStatus) -> anyhow::Result<()> {
|
||||||
|
let icon = match status {
|
||||||
|
IconStatus::Enabled => TrayIcon::Normal,
|
||||||
|
IconStatus::Disabled => TrayIcon::Disabled,
|
||||||
|
IconStatus::SecureInputDisabled => TrayIcon::SystemDisabled,
|
||||||
|
};
|
||||||
|
|
||||||
|
self.remote.update_tray_icon(icon);
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
|
@ -20,4 +20,5 @@
|
||||||
pub mod clipboard_injector;
|
pub mod clipboard_injector;
|
||||||
pub mod context_menu;
|
pub mod context_menu;
|
||||||
pub mod event_injector;
|
pub mod event_injector;
|
||||||
|
pub mod icon;
|
||||||
pub mod key_injector;
|
pub mod key_injector;
|
|
@ -34,6 +34,7 @@ pub mod match_cache;
|
||||||
pub mod matcher;
|
pub mod matcher;
|
||||||
pub mod multiplex;
|
pub mod multiplex;
|
||||||
pub mod path;
|
pub mod path;
|
||||||
|
pub mod process;
|
||||||
pub mod render;
|
pub mod render;
|
||||||
pub mod source;
|
pub mod source;
|
||||||
pub mod ui;
|
pub mod ui;
|
||||||
|
@ -118,6 +119,8 @@ pub fn initialize_and_spawn(
|
||||||
super::engine::render::RendererAdapter::new(&match_cache, &config_manager, &renderer);
|
super::engine::render::RendererAdapter::new(&match_cache, &config_manager, &renderer);
|
||||||
let path_provider = PathProviderAdapter::new(&paths);
|
let path_provider = PathProviderAdapter::new(&paths);
|
||||||
|
|
||||||
|
let disable_options = process::middleware::disable::extract_disable_options(config_manager.default());
|
||||||
|
|
||||||
let mut processor = crate::engine::process::default(
|
let mut processor = crate::engine::process::default(
|
||||||
&matchers,
|
&matchers,
|
||||||
&config_manager,
|
&config_manager,
|
||||||
|
@ -128,6 +131,7 @@ pub fn initialize_and_spawn(
|
||||||
&modifier_state_store,
|
&modifier_state_store,
|
||||||
&sequencer,
|
&sequencer,
|
||||||
&path_provider,
|
&path_provider,
|
||||||
|
disable_options,
|
||||||
);
|
);
|
||||||
|
|
||||||
let event_injector =
|
let event_injector =
|
||||||
|
@ -140,6 +144,7 @@ pub fn initialize_and_spawn(
|
||||||
);
|
);
|
||||||
let key_injector = super::engine::executor::key_injector::KeyInjectorAdapter::new(&*injector);
|
let key_injector = super::engine::executor::key_injector::KeyInjectorAdapter::new(&*injector);
|
||||||
let context_menu_adapter = super::engine::executor::context_menu::ContextMenuHandlerAdapter::new(&*ui_remote);
|
let context_menu_adapter = super::engine::executor::context_menu::ContextMenuHandlerAdapter::new(&*ui_remote);
|
||||||
|
let icon_adapter = super::engine::executor::icon::IconHandlerAdapter::new(&*ui_remote);
|
||||||
let dispatcher = crate::engine::dispatch::default(
|
let dispatcher = crate::engine::dispatch::default(
|
||||||
&event_injector,
|
&event_injector,
|
||||||
&clipboard_injector,
|
&clipboard_injector,
|
||||||
|
@ -148,6 +153,7 @@ pub fn initialize_and_spawn(
|
||||||
&clipboard_injector,
|
&clipboard_injector,
|
||||||
&clipboard_injector,
|
&clipboard_injector,
|
||||||
&context_menu_adapter,
|
&context_menu_adapter,
|
||||||
|
&icon_adapter,
|
||||||
);
|
);
|
||||||
|
|
||||||
let mut engine = crate::engine::Engine::new(&funnel, &mut processor, &dispatcher);
|
let mut engine = crate::engine::Engine::new(&funnel, &mut processor, &dispatcher);
|
||||||
|
|
49
espanso/src/cli/worker/engine/process/middleware/disable.rs
Normal file
49
espanso/src/cli/worker/engine/process/middleware/disable.rs
Normal file
|
@ -0,0 +1,49 @@
|
||||||
|
/*
|
||||||
|
* This file is part of espanso.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2019-2021 Federico Terzi
|
||||||
|
*
|
||||||
|
* espanso is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* espanso is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with espanso. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
use std::time::Duration;
|
||||||
|
|
||||||
|
use crate::engine::{event::input::{Key, Variant}, process::DisableOptions};
|
||||||
|
use espanso_config::config::Config;
|
||||||
|
|
||||||
|
pub fn extract_disable_options(config: &dyn Config) -> DisableOptions {
|
||||||
|
let (toggle_key, variant) = match config.toggle_key() {
|
||||||
|
Some(key) => match key {
|
||||||
|
espanso_config::config::ToggleKey::Ctrl => (Some(Key::Control), None),
|
||||||
|
espanso_config::config::ToggleKey::Meta => (Some(Key::Meta), None),
|
||||||
|
espanso_config::config::ToggleKey::Alt => (Some(Key::Alt), None),
|
||||||
|
espanso_config::config::ToggleKey::Shift => (Some(Key::Shift), None),
|
||||||
|
espanso_config::config::ToggleKey::RightCtrl => (Some(Key::Control), Some(Variant::Right)),
|
||||||
|
espanso_config::config::ToggleKey::RightAlt => (Some(Key::Alt), Some(Variant::Right)),
|
||||||
|
espanso_config::config::ToggleKey::RightShift => (Some(Key::Shift), Some(Variant::Right)),
|
||||||
|
espanso_config::config::ToggleKey::RightMeta => (Some(Key::Meta), Some(Variant::Right)),
|
||||||
|
espanso_config::config::ToggleKey::LeftCtrl => (Some(Key::Control), Some(Variant::Left)),
|
||||||
|
espanso_config::config::ToggleKey::LeftAlt => (Some(Key::Alt), Some(Variant::Left)),
|
||||||
|
espanso_config::config::ToggleKey::LeftShift => (Some(Key::Shift), Some(Variant::Left)),
|
||||||
|
espanso_config::config::ToggleKey::LeftMeta => (Some(Key::Meta), Some(Variant::Left)),
|
||||||
|
},
|
||||||
|
None => (None, None),
|
||||||
|
};
|
||||||
|
|
||||||
|
DisableOptions {
|
||||||
|
toggle_key,
|
||||||
|
toggle_key_variant: variant,
|
||||||
|
toggle_key_maximum_window: Duration::from_millis(1000),
|
||||||
|
}
|
||||||
|
}
|
20
espanso/src/cli/worker/engine/process/middleware/mod.rs
Normal file
20
espanso/src/cli/worker/engine/process/middleware/mod.rs
Normal file
|
@ -0,0 +1,20 @@
|
||||||
|
/*
|
||||||
|
* This file is part of espanso.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2019-2021 Federico Terzi
|
||||||
|
*
|
||||||
|
* espanso is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* espanso is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with espanso. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
pub mod disable;
|
20
espanso/src/cli/worker/engine/process/mod.rs
Normal file
20
espanso/src/cli/worker/engine/process/mod.rs
Normal file
|
@ -0,0 +1,20 @@
|
||||||
|
/*
|
||||||
|
* This file is part of espanso.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2019-2021 Federico Terzi
|
||||||
|
*
|
||||||
|
* espanso is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* espanso is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with espanso. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
pub mod middleware;
|
|
@ -17,7 +17,7 @@
|
||||||
* along with espanso. If not, see <https://www.gnu.org/licenses/>.
|
* along with espanso. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
use super::{ContextMenuHandler, Event, ImageInjector};
|
use super::{ContextMenuHandler, Event, IconHandler, ImageInjector};
|
||||||
use super::{ModeProvider, Dispatcher, Executor, KeyInjector, TextInjector, HtmlInjector};
|
use super::{ModeProvider, Dispatcher, Executor, KeyInjector, TextInjector, HtmlInjector};
|
||||||
|
|
||||||
pub struct DefaultDispatcher<'a> {
|
pub struct DefaultDispatcher<'a> {
|
||||||
|
@ -33,6 +33,7 @@ impl<'a> DefaultDispatcher<'a> {
|
||||||
html_injector: &'a dyn HtmlInjector,
|
html_injector: &'a dyn HtmlInjector,
|
||||||
image_injector: &'a dyn ImageInjector,
|
image_injector: &'a dyn ImageInjector,
|
||||||
context_menu_handler: &'a dyn ContextMenuHandler,
|
context_menu_handler: &'a dyn ContextMenuHandler,
|
||||||
|
icon_handler: &'a dyn IconHandler,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
Self {
|
Self {
|
||||||
executors: vec![
|
executors: vec![
|
||||||
|
@ -52,6 +53,9 @@ impl<'a> DefaultDispatcher<'a> {
|
||||||
)),
|
)),
|
||||||
Box::new(super::executor::context_menu::ContextMenuExecutor::new(
|
Box::new(super::executor::context_menu::ContextMenuExecutor::new(
|
||||||
context_menu_handler,
|
context_menu_handler,
|
||||||
|
)),
|
||||||
|
Box::new(super::executor::icon_update::IconUpdateExecutor::new(
|
||||||
|
icon_handler,
|
||||||
))
|
))
|
||||||
],
|
],
|
||||||
}
|
}
|
||||||
|
|
53
espanso/src/engine/dispatch/executor/icon_update.rs
Normal file
53
espanso/src/engine/dispatch/executor/icon_update.rs
Normal file
|
@ -0,0 +1,53 @@
|
||||||
|
/*
|
||||||
|
* This file is part of espanso.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2019-2021 Federico Terzi
|
||||||
|
*
|
||||||
|
* espanso is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* espanso is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with espanso. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
use super::super::{Event, Executor};
|
||||||
|
use crate::engine::event::{EventType, ui::{IconStatus}};
|
||||||
|
use anyhow::Result;
|
||||||
|
use log::error;
|
||||||
|
|
||||||
|
pub trait IconHandler {
|
||||||
|
fn update_icon(&self, status: &IconStatus) -> Result<()>;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct IconUpdateExecutor<'a> {
|
||||||
|
handler: &'a dyn IconHandler,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> IconUpdateExecutor<'a> {
|
||||||
|
pub fn new(handler: &'a dyn IconHandler) -> Self {
|
||||||
|
Self { handler }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> Executor for IconUpdateExecutor<'a> {
|
||||||
|
fn execute(&self, event: &Event) -> bool {
|
||||||
|
if let EventType::IconStatusChange(m_event) = &event.etype {
|
||||||
|
if let Err(error) = self.handler.update_icon(&m_event.status) {
|
||||||
|
error!("icon handler reported an error: {:?}", error);
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: test
|
|
@ -18,6 +18,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
pub mod context_menu;
|
pub mod context_menu;
|
||||||
|
pub mod icon_update;
|
||||||
pub mod image_inject;
|
pub mod image_inject;
|
||||||
pub mod html_inject;
|
pub mod html_inject;
|
||||||
pub mod key_inject;
|
pub mod key_inject;
|
||||||
|
|
|
@ -37,6 +37,7 @@ pub use executor::html_inject::HtmlInjector;
|
||||||
pub use executor::text_inject::{Mode, ModeProvider, TextInjector};
|
pub use executor::text_inject::{Mode, ModeProvider, TextInjector};
|
||||||
pub use executor::image_inject::{ImageInjector};
|
pub use executor::image_inject::{ImageInjector};
|
||||||
pub use executor::context_menu::{ContextMenuHandler};
|
pub use executor::context_menu::{ContextMenuHandler};
|
||||||
|
pub use executor::icon_update::IconHandler;
|
||||||
|
|
||||||
// TODO: move into module
|
// TODO: move into module
|
||||||
pub trait KeyInjector {
|
pub trait KeyInjector {
|
||||||
|
@ -51,6 +52,7 @@ pub fn default<'a>(
|
||||||
html_injector: &'a dyn HtmlInjector,
|
html_injector: &'a dyn HtmlInjector,
|
||||||
image_injector: &'a dyn ImageInjector,
|
image_injector: &'a dyn ImageInjector,
|
||||||
context_menu_handler: &'a dyn ContextMenuHandler,
|
context_menu_handler: &'a dyn ContextMenuHandler,
|
||||||
|
icon_handler: &'a dyn IconHandler,
|
||||||
) -> impl Dispatcher + 'a {
|
) -> impl Dispatcher + 'a {
|
||||||
default::DefaultDispatcher::new(
|
default::DefaultDispatcher::new(
|
||||||
event_injector,
|
event_injector,
|
||||||
|
@ -60,5 +62,6 @@ pub fn default<'a>(
|
||||||
html_injector,
|
html_injector,
|
||||||
image_injector,
|
image_injector,
|
||||||
context_menu_handler,
|
context_menu_handler,
|
||||||
|
icon_handler,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
@ -70,6 +70,11 @@ pub enum EventType {
|
||||||
MatchInjected,
|
MatchInjected,
|
||||||
DiscardPrevious(internal::DiscardPreviousEvent),
|
DiscardPrevious(internal::DiscardPreviousEvent),
|
||||||
|
|
||||||
|
Disabled,
|
||||||
|
Enabled,
|
||||||
|
SecureInputEnabled,
|
||||||
|
SecureInputDisabled,
|
||||||
|
|
||||||
// Effects
|
// Effects
|
||||||
TriggerCompensation(effect::TriggerCompensationEvent),
|
TriggerCompensation(effect::TriggerCompensationEvent),
|
||||||
CursorHintCompensation(effect::CursorHintCompensationEvent),
|
CursorHintCompensation(effect::CursorHintCompensationEvent),
|
||||||
|
@ -82,6 +87,7 @@ pub enum EventType {
|
||||||
|
|
||||||
// UI
|
// UI
|
||||||
ShowContextMenu(ui::ShowContextMenuEvent),
|
ShowContextMenu(ui::ShowContextMenuEvent),
|
||||||
|
IconStatusChange(ui::IconStatusChangeEvent),
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
|
|
|
@ -40,3 +40,15 @@ pub struct SubMenuItem {
|
||||||
pub label: String,
|
pub label: String,
|
||||||
pub items: Vec<MenuItem>,
|
pub items: Vec<MenuItem>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, PartialEq)]
|
||||||
|
pub struct IconStatusChangeEvent {
|
||||||
|
pub status: IconStatus
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, PartialEq)]
|
||||||
|
pub enum IconStatus {
|
||||||
|
Enabled,
|
||||||
|
Disabled,
|
||||||
|
SecureInputDisabled,
|
||||||
|
}
|
|
@ -19,13 +19,13 @@
|
||||||
|
|
||||||
use log::trace;
|
use log::trace;
|
||||||
|
|
||||||
use super::{MatchFilter, MatchInfoProvider, MatchSelector, Matcher, Middleware, Multiplexer, PathProvider, Processor, Renderer, middleware::{
|
use super::{DisableOptions, MatchFilter, MatchInfoProvider, MatchSelector, Matcher, Middleware, Multiplexer, PathProvider, Processor, Renderer, middleware::{
|
||||||
match_select::MatchSelectMiddleware, matcher::MatcherMiddleware, multiplex::MultiplexMiddleware,
|
match_select::MatchSelectMiddleware, matcher::MatcherMiddleware, multiplex::MultiplexMiddleware,
|
||||||
render::RenderMiddleware, action::{ActionMiddleware, EventSequenceProvider}, cursor_hint::CursorHintMiddleware, cause::CauseCompensateMiddleware,
|
render::RenderMiddleware, action::{ActionMiddleware, EventSequenceProvider}, cursor_hint::CursorHintMiddleware, cause::CauseCompensateMiddleware,
|
||||||
delay_modifiers::{DelayForModifierReleaseMiddleware, ModifierStatusProvider}, markdown::MarkdownMiddleware,
|
delay_modifiers::{DelayForModifierReleaseMiddleware, ModifierStatusProvider}, markdown::MarkdownMiddleware,
|
||||||
past_discard::PastEventsDiscardMiddleware,
|
past_discard::PastEventsDiscardMiddleware,
|
||||||
}};
|
}};
|
||||||
use crate::engine::{event::{Event, EventType}, process::middleware::{context_menu::ContextMenuMiddleware, exit::ExitMiddleware, image_resolve::ImageResolverMiddleware}};
|
use crate::engine::{event::{Event, EventType}, process::middleware::{context_menu::ContextMenuMiddleware, disable::DisableMiddleware, exit::ExitMiddleware, icon_status::IconStatusMiddleware, image_resolve::ImageResolverMiddleware}};
|
||||||
use std::collections::VecDeque;
|
use std::collections::VecDeque;
|
||||||
|
|
||||||
pub struct DefaultProcessor<'a> {
|
pub struct DefaultProcessor<'a> {
|
||||||
|
@ -44,11 +44,14 @@ impl<'a> DefaultProcessor<'a> {
|
||||||
modifier_status_provider: &'a dyn ModifierStatusProvider,
|
modifier_status_provider: &'a dyn ModifierStatusProvider,
|
||||||
event_sequence_provider: &'a dyn EventSequenceProvider,
|
event_sequence_provider: &'a dyn EventSequenceProvider,
|
||||||
path_provider: &'a dyn PathProvider,
|
path_provider: &'a dyn PathProvider,
|
||||||
|
disable_options: DisableOptions,
|
||||||
) -> DefaultProcessor<'a> {
|
) -> DefaultProcessor<'a> {
|
||||||
Self {
|
Self {
|
||||||
event_queue: VecDeque::new(),
|
event_queue: VecDeque::new(),
|
||||||
middleware: vec![
|
middleware: vec![
|
||||||
Box::new(PastEventsDiscardMiddleware::new()),
|
Box::new(PastEventsDiscardMiddleware::new()),
|
||||||
|
Box::new(DisableMiddleware::new(disable_options)),
|
||||||
|
Box::new(IconStatusMiddleware::new()),
|
||||||
Box::new(MatcherMiddleware::new(matchers)),
|
Box::new(MatcherMiddleware::new(matchers)),
|
||||||
Box::new(ContextMenuMiddleware::new()),
|
Box::new(ContextMenuMiddleware::new()),
|
||||||
Box::new(MatchSelectMiddleware::new(match_filter, match_selector)),
|
Box::new(MatchSelectMiddleware::new(match_filter, match_selector)),
|
||||||
|
|
125
espanso/src/engine/process/middleware/disable.rs
Normal file
125
espanso/src/engine/process/middleware/disable.rs
Normal file
|
@ -0,0 +1,125 @@
|
||||||
|
/*
|
||||||
|
* This file is part of espanso.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2019-2021 Federico Terzi
|
||||||
|
*
|
||||||
|
* espanso is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* espanso is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with espanso. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
use std::{
|
||||||
|
cell::RefCell,
|
||||||
|
time::{Duration, Instant},
|
||||||
|
};
|
||||||
|
|
||||||
|
use log::{info};
|
||||||
|
|
||||||
|
use super::super::Middleware;
|
||||||
|
use crate::engine::{event::{Event, EventType, input::{Key, KeyboardEvent, Status, Variant}}};
|
||||||
|
|
||||||
|
pub struct DisableOptions {
|
||||||
|
pub toggle_key: Option<Key>,
|
||||||
|
pub toggle_key_variant: Option<Variant>,
|
||||||
|
pub toggle_key_maximum_window: Duration,
|
||||||
|
|
||||||
|
// TODO: toggle shortcut?
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct DisableMiddleware {
|
||||||
|
enabled: RefCell<bool>,
|
||||||
|
last_toggle_press: RefCell<Option<Instant>>,
|
||||||
|
options: DisableOptions,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl DisableMiddleware {
|
||||||
|
pub fn new(options: DisableOptions) -> Self {
|
||||||
|
Self {
|
||||||
|
enabled: RefCell::new(true),
|
||||||
|
last_toggle_press: RefCell::new(None),
|
||||||
|
options,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Middleware for DisableMiddleware {
|
||||||
|
fn name(&self) -> &'static str {
|
||||||
|
"disable"
|
||||||
|
}
|
||||||
|
|
||||||
|
fn next(&self, event: Event, dispatch: &mut dyn FnMut(Event)) -> Event {
|
||||||
|
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;
|
||||||
|
} else {
|
||||||
|
*last_toggle_press = Some(Instant::now());
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
*last_toggle_press = Some(Instant::now());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if has_status_changed {
|
||||||
|
info!("toggled enabled state, is_enabled = {}", *enabled);
|
||||||
|
dispatch(Event::caused_by(
|
||||||
|
event.source_id,
|
||||||
|
if *enabled {
|
||||||
|
EventType::Enabled
|
||||||
|
} else {
|
||||||
|
EventType::Disabled
|
||||||
|
},
|
||||||
|
))
|
||||||
|
}
|
||||||
|
|
||||||
|
// Block keyboard events when disabled
|
||||||
|
if let EventType::Keyboard(_) = &event.etype {
|
||||||
|
if !*enabled {
|
||||||
|
return Event::caused_by(event.source_id, EventType::NOOP);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// TODO: also ignore hotkey and mouse events
|
||||||
|
|
||||||
|
event
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn is_toggle_key(event: &KeyboardEvent, options: &DisableOptions) -> bool {
|
||||||
|
if event.status != Status::Released {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if options
|
||||||
|
.toggle_key
|
||||||
|
.as_ref()
|
||||||
|
.map(|key| key == &event.key)
|
||||||
|
.unwrap_or(false)
|
||||||
|
{
|
||||||
|
if let (Some(variant), Some(e_variant)) = (&options.toggle_key_variant, &event.variant) {
|
||||||
|
variant == e_variant
|
||||||
|
} else {
|
||||||
|
true
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: test
|
79
espanso/src/engine/process/middleware/icon_status.rs
Normal file
79
espanso/src/engine/process/middleware/icon_status.rs
Normal file
|
@ -0,0 +1,79 @@
|
||||||
|
/*
|
||||||
|
* This file is part of espanso.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2019-2021 Federico Terzi
|
||||||
|
*
|
||||||
|
* espanso is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* espanso is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with espanso. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
use std::{
|
||||||
|
cell::RefCell,
|
||||||
|
};
|
||||||
|
|
||||||
|
use super::super::Middleware;
|
||||||
|
use crate::engine::event::{Event, EventType, ui::{IconStatus, IconStatusChangeEvent}};
|
||||||
|
|
||||||
|
pub struct IconStatusMiddleware {
|
||||||
|
enabled: RefCell<bool>,
|
||||||
|
secure_input_enabled: RefCell<bool>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl IconStatusMiddleware {
|
||||||
|
pub fn new() -> Self {
|
||||||
|
Self {
|
||||||
|
enabled: RefCell::new(true),
|
||||||
|
secure_input_enabled: RefCell::new(false),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Middleware for IconStatusMiddleware {
|
||||||
|
fn name(&self) -> &'static str {
|
||||||
|
"icon_status"
|
||||||
|
}
|
||||||
|
|
||||||
|
fn next(&self, event: Event, dispatch: &mut dyn FnMut(Event)) -> Event {
|
||||||
|
let mut enabled = self.enabled.borrow_mut();
|
||||||
|
let mut secure_input_enabled = self.secure_input_enabled.borrow_mut();
|
||||||
|
|
||||||
|
let mut did_update = true;
|
||||||
|
match &event.etype {
|
||||||
|
EventType::Enabled => *enabled = true,
|
||||||
|
EventType::Disabled => *enabled = false,
|
||||||
|
EventType::SecureInputEnabled => *secure_input_enabled = true,
|
||||||
|
EventType::SecureInputDisabled => *secure_input_enabled = false,
|
||||||
|
_ => did_update = false,
|
||||||
|
}
|
||||||
|
|
||||||
|
if did_update {
|
||||||
|
let status = if *enabled {
|
||||||
|
if *secure_input_enabled {
|
||||||
|
IconStatus::SecureInputDisabled
|
||||||
|
} else {
|
||||||
|
IconStatus::Enabled
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
IconStatus::Disabled
|
||||||
|
};
|
||||||
|
|
||||||
|
dispatch(Event::caused_by(event.source_id, EventType::IconStatusChange(IconStatusChangeEvent {
|
||||||
|
status,
|
||||||
|
})));
|
||||||
|
}
|
||||||
|
|
||||||
|
event
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: test
|
|
@ -22,7 +22,9 @@ pub mod cause;
|
||||||
pub mod context_menu;
|
pub mod context_menu;
|
||||||
pub mod cursor_hint;
|
pub mod cursor_hint;
|
||||||
pub mod delay_modifiers;
|
pub mod delay_modifiers;
|
||||||
|
pub mod disable;
|
||||||
pub mod exit;
|
pub mod exit;
|
||||||
|
pub mod icon_status;
|
||||||
pub mod image_resolve;
|
pub mod image_resolve;
|
||||||
pub mod match_select;
|
pub mod match_select;
|
||||||
pub mod matcher;
|
pub mod matcher;
|
||||||
|
|
|
@ -95,6 +95,7 @@ pub enum RendererError {
|
||||||
pub use middleware::action::{MatchInfoProvider, EventSequenceProvider};
|
pub use middleware::action::{MatchInfoProvider, EventSequenceProvider};
|
||||||
pub use middleware::delay_modifiers::ModifierStatusProvider;
|
pub use middleware::delay_modifiers::ModifierStatusProvider;
|
||||||
pub use middleware::image_resolve::PathProvider;
|
pub use middleware::image_resolve::PathProvider;
|
||||||
|
pub use middleware::disable::DisableOptions;
|
||||||
|
|
||||||
pub fn default<'a, MatcherState>(
|
pub fn default<'a, MatcherState>(
|
||||||
matchers: &'a [&'a dyn Matcher<'a, MatcherState>],
|
matchers: &'a [&'a dyn Matcher<'a, MatcherState>],
|
||||||
|
@ -106,6 +107,7 @@ pub fn default<'a, MatcherState>(
|
||||||
modifier_status_provider: &'a dyn ModifierStatusProvider,
|
modifier_status_provider: &'a dyn ModifierStatusProvider,
|
||||||
event_sequence_provider: &'a dyn EventSequenceProvider,
|
event_sequence_provider: &'a dyn EventSequenceProvider,
|
||||||
path_provider: &'a dyn PathProvider,
|
path_provider: &'a dyn PathProvider,
|
||||||
|
disable_options: DisableOptions,
|
||||||
) -> impl Processor + 'a {
|
) -> impl Processor + 'a {
|
||||||
default::DefaultProcessor::new(
|
default::DefaultProcessor::new(
|
||||||
matchers,
|
matchers,
|
||||||
|
@ -117,5 +119,6 @@ pub fn default<'a, MatcherState>(
|
||||||
modifier_status_provider,
|
modifier_status_provider,
|
||||||
event_sequence_provider,
|
event_sequence_provider,
|
||||||
path_provider,
|
path_provider,
|
||||||
|
disable_options,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user