diff --git a/.github/scripts/ubuntu/Dockerfile b/.github/scripts/ubuntu/Dockerfile
index 6fbba6e..b3c7eee 100644
--- a/.github/scripts/ubuntu/Dockerfile
+++ b/.github/scripts/ubuntu/Dockerfile
@@ -31,7 +31,7 @@ RUN set -eux; \
cargo --version; \
rustc --version;
-RUN mkdir espanso && cargo install --force cargo-make
+RUN mkdir espanso && cargo install --force cargo-make --version 0.34.0
COPY . espanso
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index 519e97f..b881035 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -35,7 +35,7 @@ jobs:
MACOSX_DEPLOYMENT_TARGET: "10.13"
- name: Install cargo-make
run: |
- cargo install --force cargo-make
+ cargo install --force cargo-make --version 0.34.0
- name: Run test suite
run: cargo make test-binary
- name: Build
@@ -60,7 +60,7 @@ jobs:
cargo clippy -p espanso --features wayland -- -D warnings
- name: Install cargo-make
run: |
- cargo install --force cargo-make
+ cargo install --force cargo-make --version 0.34.0
- name: Run test suite
run: cargo make test-binary --env NO_X11=true
- name: Build
@@ -74,7 +74,7 @@ jobs:
run: rustup update && rustup target add aarch64-apple-darwin
- name: Install cargo-make
run: |
- cargo install --force cargo-make
+ cargo install --force cargo-make --version 0.34.0
- name: Build
run: |
cargo make build-macos-arm-binary
diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml
index d41c8b9..9674a1f 100644
--- a/.github/workflows/release.yml
+++ b/.github/workflows/release.yml
@@ -61,7 +61,7 @@ jobs:
echo Using version ${{ needs.extract-version.outputs.espanso_version }}
- name: Install cargo-make
run: |
- cargo install --force cargo-make
+ cargo install --force cargo-make --version 0.34.0
- name: Test
run: cargo make test-binary --profile release
- name: Build
@@ -128,7 +128,7 @@ jobs:
echo Using version ${{ needs.extract-version.outputs.espanso_version }}
- name: Install cargo-make
run: |
- cargo install --force cargo-make
+ cargo install --force cargo-make --version 0.34.0
- name: Test
run: cargo make test-binary --profile release
env:
@@ -168,7 +168,7 @@ jobs:
run: rustup update && rustup target add aarch64-apple-darwin
- name: Install cargo-make
run: |
- cargo install --force cargo-make
+ cargo install --force cargo-make --version 0.34.0
- name: Build
run: cargo make create-bundle --profile release --env BUILD_ARCH=aarch64-apple-darwin
- name: Codesign executable
diff --git a/Cargo.lock b/Cargo.lock
index 0c06a1c..716e52c 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -572,7 +572,7 @@ dependencies = [
[[package]]
name = "espanso"
-version = "2.0.3-alpha"
+version = "2.0.4-alpha"
dependencies = [
"anyhow",
"caps",
diff --git a/Compilation.md b/Compilation.md
index 8b936ed..860ffac 100644
--- a/Compilation.md
+++ b/Compilation.md
@@ -16,7 +16,7 @@ These are the basic tools required to build espanso:
steps. You can install it by running:
```
-cargo install --force cargo-make
+cargo install --force cargo-make --version 0.34.0
```
# Linux
diff --git a/espanso-config/src/config/mod.rs b/espanso-config/src/config/mod.rs
index d3d12da..dd88929 100644
--- a/espanso-config/src/config/mod.rs
+++ b/espanso-config/src/config/mod.rs
@@ -156,6 +156,12 @@ pub trait Config: Send + Sync {
// Disabling this option might conflict with the undo feature.
fn win32_exclude_orphan_events(&self) -> bool;
+ // The maximum interval (in milliseconds) for which a keyboard layout
+ // can be cached. If switching often between different layouts, you
+ // could lower this amount to avoid the "lost detection" effect described
+ // in this issue: https://github.com/federico-terzi/espanso/issues/745
+ fn win32_keyboard_layout_cache_interval(&self) -> i64;
+
fn is_match<'a>(&self, app: &AppProperties<'a>) -> bool;
fn pretty_dump(&self) -> String {
@@ -187,6 +193,9 @@ pub trait Config: Send + Sync {
show_notifications: {:?}
secure_input_notification: {:?}
+ win32_exclude_orphan_events: {:?}
+ win32_keyboard_layout_cache_interval: {:?}
+
match_paths: {:#?}
",
self.label(),
@@ -215,6 +224,9 @@ pub trait Config: Send + Sync {
self.show_notifications(),
self.secure_input_notification(),
+ self.win32_exclude_orphan_events(),
+ self.win32_keyboard_layout_cache_interval(),
+
self.match_paths(),
}
}
diff --git a/espanso-config/src/config/parse/mod.rs b/espanso-config/src/config/parse/mod.rs
index 134afc0..bd39ad4 100644
--- a/espanso-config/src/config/parse/mod.rs
+++ b/espanso-config/src/config/parse/mod.rs
@@ -45,6 +45,7 @@ pub(crate) struct ParsedConfig {
pub show_icon: Option,
pub secure_input_notification: Option,
pub win32_exclude_orphan_events: Option,
+ pub win32_keyboard_layout_cache_interval: Option,
pub pre_paste_delay: Option,
pub restore_clipboard_delay: Option,
diff --git a/espanso-config/src/config/parse/yaml.rs b/espanso-config/src/config/parse/yaml.rs
index 81e884d..824429c 100644
--- a/espanso-config/src/config/parse/yaml.rs
+++ b/espanso-config/src/config/parse/yaml.rs
@@ -109,6 +109,9 @@ pub(crate) struct YAMLConfig {
#[serde(default)]
pub win32_exclude_orphan_events: Option,
+ #[serde(default)]
+ pub win32_keyboard_layout_cache_interval: Option,
+
// Include/Exclude
#[serde(default)]
pub includes: Option>,
@@ -197,6 +200,7 @@ impl TryFrom for ParsedConfig {
paste_shortcut_event_delay: yaml_config.paste_shortcut_event_delay,
win32_exclude_orphan_events: yaml_config.win32_exclude_orphan_events,
+ win32_keyboard_layout_cache_interval: yaml_config.win32_keyboard_layout_cache_interval,
use_standard_includes: yaml_config.use_standard_includes,
includes: yaml_config.includes,
@@ -253,6 +257,7 @@ mod tests {
show_notifications: false
secure_input_notification: false
win32_exclude_orphan_events: false
+ win32_keyboard_layout_cache_interval: 300
use_standard_includes: true
includes: ["test1"]
@@ -305,6 +310,7 @@ mod tests {
show_notifications: Some(false),
secure_input_notification: Some(false),
win32_exclude_orphan_events: Some(false),
+ win32_keyboard_layout_cache_interval: Some(300),
pre_paste_delay: Some(300),
evdev_modifier_delay: Some(40),
diff --git a/espanso-config/src/config/resolve.rs b/espanso-config/src/config/resolve.rs
index ea74240..afcad9b 100644
--- a/espanso-config/src/config/resolve.rs
+++ b/espanso-config/src/config/resolve.rs
@@ -323,6 +323,13 @@ impl Config for ResolvedConfig {
fn evdev_modifier_delay(&self) -> Option {
self.parsed.evdev_modifier_delay
}
+
+ fn win32_keyboard_layout_cache_interval(&self) -> i64 {
+ self
+ .parsed
+ .win32_keyboard_layout_cache_interval
+ .unwrap_or(2000)
+ }
}
impl ResolvedConfig {
@@ -405,6 +412,7 @@ impl ResolvedConfig {
show_notifications,
secure_input_notification,
win32_exclude_orphan_events,
+ win32_keyboard_layout_cache_interval,
includes,
excludes,
extra_includes,
diff --git a/espanso-config/src/legacy/mod.rs b/espanso-config/src/legacy/mod.rs
index 4efbb56..674b08a 100644
--- a/espanso-config/src/legacy/mod.rs
+++ b/espanso-config/src/legacy/mod.rs
@@ -394,6 +394,10 @@ impl Config for LegacyInteropConfig {
fn evdev_modifier_delay(&self) -> Option {
Some(10)
}
+
+ fn win32_keyboard_layout_cache_interval(&self) -> i64 {
+ 2000
+ }
}
struct LegacyMatchGroup {
diff --git a/espanso-detect/src/evdev/device.rs b/espanso-detect/src/evdev/device.rs
index 2dd0b25..818578d 100644
--- a/espanso-detect/src/evdev/device.rs
+++ b/espanso-detect/src/evdev/device.rs
@@ -6,6 +6,7 @@ use libc::{input_event, size_t, ssize_t, EWOULDBLOCK, O_CLOEXEC, O_NONBLOCK, O_R
use log::trace;
use scopeguard::ScopeGuard;
use std::collections::HashMap;
+use std::os::raw::c_char;
use std::os::unix::io::AsRawFd;
use std::{
ffi::{c_void, CStr},
@@ -160,16 +161,16 @@ impl Device {
}
// Extract the utf8 char
- let mut buffer: [u8; 16] = [0; 16];
+ let mut buffer: [c_char; 16] = [0; 16];
unsafe {
xkb_state_key_get_utf8(
self.get_state(),
keycode,
- buffer.as_mut_ptr() as *mut i8,
+ buffer.as_mut_ptr(),
std::mem::size_of_val(&buffer),
)
};
- let content_raw = unsafe { CStr::from_ptr(buffer.as_ptr() as *mut i8) };
+ let content_raw = unsafe { CStr::from_ptr(buffer.as_ptr()) };
let content = content_raw.to_string_lossy().to_string();
let event = RawKeyboardEvent {
diff --git a/espanso-detect/src/lib.rs b/espanso-detect/src/lib.rs
index 393b40e..6d210ed 100644
--- a/espanso-detect/src/lib.rs
+++ b/espanso-detect/src/lib.rs
@@ -66,6 +66,12 @@ pub struct SourceCreationOptions {
// those from espanso, but might need to be disabled when using some software-level keyboards.
// Disabling this option might conflict with the undo feature.
pub win32_exclude_orphan_events: bool,
+
+ // The maximum interval (in milliseconds) for which a keyboard layout
+ // can be cached. If switching often between different layouts, you
+ // could lower this amount to avoid the "lost detection" effect described
+ // in this issue: https://github.com/federico-terzi/espanso/issues/745
+ pub win32_keyboard_layout_cache_interval: i64,
}
// This struct identifies the keyboard layout that
@@ -87,6 +93,7 @@ impl Default for SourceCreationOptions {
evdev_keyboard_rmlvo: None,
hotkeys: Vec::new(),
win32_exclude_orphan_events: true,
+ win32_keyboard_layout_cache_interval: 2000,
}
}
}
@@ -97,6 +104,7 @@ pub fn get_source(options: SourceCreationOptions) -> Result> {
Ok(Box::new(win32::Win32Source::new(
&options.hotkeys,
options.win32_exclude_orphan_events,
+ options.win32_keyboard_layout_cache_interval,
)))
}
diff --git a/espanso-detect/src/win32/mod.rs b/espanso-detect/src/win32/mod.rs
index d25e528..dbde573 100644
--- a/espanso-detect/src/win32/mod.rs
+++ b/espanso-detect/src/win32/mod.rs
@@ -17,6 +17,7 @@
* along with espanso. If not, see .
*/
+use std::os::raw::c_long;
use std::{convert::TryInto, ffi::c_void};
use lazycell::LazyCell;
@@ -79,10 +80,19 @@ pub struct RawHotKey {
pub flags: u32,
}
+#[repr(C)]
+pub struct InitOptions {
+ pub keyboard_layout_cache_interval: c_long,
+}
+
#[allow(improper_ctypes)]
#[link(name = "espansodetect", kind = "static")]
extern "C" {
- pub fn detect_initialize(_self: *const Win32Source, error_code: *mut i32) -> *mut c_void;
+ pub fn detect_initialize(
+ _self: *const Win32Source,
+ options: *const InitOptions,
+ error_code: *mut i32,
+ ) -> *mut c_void;
pub fn detect_register_hotkey(window: *const c_void, hotkey: RawHotKey) -> i32;
pub fn detect_eventloop(
@@ -99,24 +109,35 @@ pub struct Win32Source {
hotkeys: Vec,
exclude_orphan_events: bool,
+ keyboard_layout_cache_interval: i64,
}
#[allow(clippy::new_without_default)]
impl Win32Source {
- pub fn new(hotkeys: &[HotKey], exclude_orphan_events: bool) -> Win32Source {
+ pub fn new(
+ hotkeys: &[HotKey],
+ exclude_orphan_events: bool,
+ keyboard_layout_cache_interval: i64,
+ ) -> Win32Source {
Self {
handle: std::ptr::null_mut(),
callback: LazyCell::new(),
hotkeys: hotkeys.to_vec(),
exclude_orphan_events,
+ keyboard_layout_cache_interval,
}
}
}
impl Source for Win32Source {
fn initialize(&mut self) -> Result<()> {
+ let options = InitOptions {
+ keyboard_layout_cache_interval: self.keyboard_layout_cache_interval.try_into().unwrap(),
+ };
+
let mut error_code = 0;
- let handle = unsafe { detect_initialize(self as *const Win32Source, &mut error_code) };
+ let handle =
+ unsafe { detect_initialize(self as *const Win32Source, &options, &mut error_code) };
if handle.is_null() {
let error = match error_code {
diff --git a/espanso-detect/src/win32/native.cpp b/espanso-detect/src/win32/native.cpp
index 1ac9d41..c54c396 100644
--- a/espanso-detect/src/win32/native.cpp
+++ b/espanso-detect/src/win32/native.cpp
@@ -39,8 +39,6 @@
#include
#include
-// How many milliseconds must pass between events before refreshing the keyboard layout
-const long DETECT_REFRESH_KEYBOARD_LAYOUT_INTERVAL = 2000;
const wchar_t *const DETECT_WINCLASS = L"EspansoDetect";
const USHORT MOUSE_DOWN_FLAGS = RI_MOUSE_LEFT_BUTTON_DOWN | RI_MOUSE_RIGHT_BUTTON_DOWN | RI_MOUSE_MIDDLE_BUTTON_DOWN |
RI_MOUSE_BUTTON_1_DOWN | RI_MOUSE_BUTTON_2_DOWN | RI_MOUSE_BUTTON_3_DOWN |
@@ -52,6 +50,8 @@ const USHORT MOUSE_UP_FLAGS = RI_MOUSE_LEFT_BUTTON_UP | RI_MOUSE_RIGHT_BUTTON_UP
typedef struct {
HKL current_keyboard_layout;
DWORD last_key_press_tick;
+ // How many milliseconds must pass between events before refreshing the keyboard layout
+ long keyboard_layout_cache_interval;
// Rust interop
void * rust_instance;
@@ -130,7 +130,7 @@ LRESULT CALLBACK detect_window_procedure(HWND window, unsigned int msg, WPARAM w
DWORD currentTick = GetTickCount();
// If enough time has passed between the last keypress and now, refresh the keyboard layout
- if ((currentTick - variables->last_key_press_tick) > DETECT_REFRESH_KEYBOARD_LAYOUT_INTERVAL)
+ if ((currentTick - variables->last_key_press_tick) > variables->keyboard_layout_cache_interval)
{
// Because keyboard layouts on windows are Window-specific, to get the current
@@ -269,7 +269,7 @@ LRESULT CALLBACK detect_window_procedure(HWND window, unsigned int msg, WPARAM w
}
}
-void * detect_initialize(void *_self, int32_t *error_code)
+void * detect_initialize(void *_self, InitOptions * options, int32_t *error_code)
{
HWND window = NULL;
@@ -297,6 +297,7 @@ void * detect_initialize(void *_self, int32_t *error_code)
// Initialize the default keyboard layout
variables->current_keyboard_layout = GetKeyboardLayout(0);
+ variables->keyboard_layout_cache_interval = options->keyboard_layout_cache_interval;
// Docs: https://docs.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-createwindowexw
window = CreateWindowEx(
diff --git a/espanso-detect/src/win32/native.h b/espanso-detect/src/win32/native.h
index a93b9f7..7e187d3 100644
--- a/espanso-detect/src/win32/native.h
+++ b/espanso-detect/src/win32/native.h
@@ -76,9 +76,12 @@ typedef struct {
typedef void (*EventCallback)(void * rust_istance, InputEvent data);
+typedef struct {
+ long keyboard_layout_cache_interval;
+} InitOptions;
// Initialize the Raw Input API and the Window.
-extern "C" void * detect_initialize(void * rust_istance, int32_t *error_code);
+extern "C" void * detect_initialize(void * rust_istance, InitOptions * options, int32_t *error_code);
// Register the given hotkey, return a non-zero code if successful
extern "C" int32_t detect_register_hotkey(void * window, HotKey hotkey);
diff --git a/espanso-engine/src/process/middleware/disable.rs b/espanso-engine/src/process/middleware/disable.rs
index 77bd0e8..5b7e633 100644
--- a/espanso-engine/src/process/middleware/disable.rs
+++ b/espanso-engine/src/process/middleware/disable.rs
@@ -64,18 +64,24 @@ impl Middleware for DisableMiddleware {
match &event.etype {
EventType::Keyboard(m_event) => {
- if is_toggle_key(m_event, &self.options) {
+ if m_event.status == Status::Released {
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;
+ if is_toggle_key(m_event, &self.options) {
+ 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());
+ // If another key is pressed (not the toggle key), we should reset the window
+ // For more information, see: https://github.com/federico-terzi/espanso/issues/815
+ *last_toggle_press = None;
}
}
}
@@ -115,10 +121,6 @@ impl Middleware for DisableMiddleware {
}
fn is_toggle_key(event: &KeyboardEvent, options: &DisableOptions) -> bool {
- if event.status != Status::Released {
- return false;
- }
-
if options
.toggle_key
.as_ref()
diff --git a/espanso-engine/src/process/middleware/markdown.rs b/espanso-engine/src/process/middleware/markdown.rs
index abebc54..7deec85 100644
--- a/espanso-engine/src/process/middleware/markdown.rs
+++ b/espanso-engine/src/process/middleware/markdown.rs
@@ -17,6 +17,8 @@
* along with espanso. If not, see .
*/
+use log::error;
+
use super::super::Middleware;
use crate::event::{effect::HtmlInjectRequest, Event, EventType};
@@ -37,23 +39,33 @@ impl Middleware for MarkdownMiddleware {
fn next(&self, event: Event, _: &mut dyn FnMut(Event)) -> Event {
if let EventType::MarkdownInject(m_event) = &event.etype {
// Render the markdown into HTML
- let html = markdown::to_html(&m_event.markdown);
- let mut html = html.trim();
+ // NOTE: we wrap the `to_html` call between catch_unwind because if the markdown is malformed,
+ // the library panics. Ideally, the library would return a Result::Err in that case, but
+ // for now it doesn't, so we employ that workaround.
+ // See also: https://github.com/federico-terzi/espanso/issues/759
+ let html = std::panic::catch_unwind(|| markdown::to_html(&m_event.markdown));
+ if let Ok(html) = html {
+ let mut html = html.trim();
- // Remove the surrounding paragraph
- if html.starts_with("") {
- html = html.trim_start_matches("
");
- }
- if html.ends_with("
") {
- html = html.trim_end_matches("
");
- }
+ // Remove the surrounding paragraph
+ if html.starts_with("") {
+ html = html.trim_start_matches("
");
+ }
+ if html.ends_with("
") {
+ html = html.trim_end_matches("");
+ }
- return Event::caused_by(
- event.source_id,
- EventType::HtmlInject(HtmlInjectRequest {
- html: html.to_owned(),
- }),
- );
+ return Event::caused_by(
+ event.source_id,
+ EventType::HtmlInject(HtmlInjectRequest {
+ html: html.to_owned(),
+ }),
+ );
+ } else {
+ error!("unable to convert markdown to HTML, is it malformed?");
+
+ return Event::caused_by(event.source_id, EventType::NOOP);
+ }
}
event
diff --git a/espanso-engine/src/process/middleware/matcher.rs b/espanso-engine/src/process/middleware/matcher.rs
index 92f49ea..d16276d 100644
--- a/espanso-engine/src/process/middleware/matcher.rs
+++ b/espanso-engine/src/process/middleware/matcher.rs
@@ -191,7 +191,7 @@ fn is_event_of_interest(event_type: &EventType) -> bool {
// In hex, they have the byte 3 = 0xfe
// See list in "keysymdef.h" file
if cfg!(target_os = "linux") {
- if let Key::Other(raw_code) = &keyboard_event.key {
+ if let (Key::Other(raw_code), None) = (&keyboard_event.key, &keyboard_event.value) {
if (65025..=65276).contains(raw_code) {
return false;
}
diff --git a/espanso-modulo/build.rs b/espanso-modulo/build.rs
index 31646ca..86bc21d 100644
--- a/espanso-modulo/build.rs
+++ b/espanso-modulo/build.rs
@@ -457,22 +457,5 @@ fn build_native() {
}
fn main() {
- println!("cargo:rerun-if-changed=src/x11/native/native.h");
- println!("cargo:rerun-if-changed=src/sys/interop/interop.h");
- println!("cargo:rerun-if-changed=src/sys/form/form.cpp");
- println!("cargo:rerun-if-changed=src/sys/common/mac.h");
- println!("cargo:rerun-if-changed=src/sys/common/mac.mm");
- println!("cargo:rerun-if-changed=src/sys/common/common.h");
- println!("cargo:rerun-if-changed=src/sys/common/common.cpp");
- println!("cargo:rerun-if-changed=src/sys/welcome/welcome_gui.h");
- println!("cargo:rerun-if-changed=src/sys/welcome/welcome_gui.cpp");
- println!("cargo:rerun-if-changed=src/sys/welcome/welcome.cpp");
- println!("cargo:rerun-if-changed=src/sys/troubleshooting/troubleshooting_gui.h");
- println!("cargo:rerun-if-changed=src/sys/troubleshooting/troubleshooting_gui.cpp");
- println!("cargo:rerun-if-changed=src/sys/troubleshooting/troubleshooting.cpp");
- println!("cargo:rerun-if-changed=src/sys/search/search.cpp");
- println!("cargo:rerun-if-changed=src/sys/wizard/wizard.cpp");
- println!("cargo:rerun-if-changed=src/sys/wizard/wizard_gui.cpp");
- println!("cargo:rerun-if-changed=src/sys/wizard/wizard_gui.h");
build_native();
}
diff --git a/espanso/Cargo.toml b/espanso/Cargo.toml
index 60cd2cf..a31cae3 100644
--- a/espanso/Cargo.toml
+++ b/espanso/Cargo.toml
@@ -1,6 +1,6 @@
[package]
name = "espanso"
-version = "2.0.3-alpha"
+version = "2.0.4-alpha"
authors = ["Federico Terzi "]
license = "GPL-3.0"
description = "Cross-platform Text Expander written in Rust"
diff --git a/espanso/src/cli/worker/engine/mod.rs b/espanso/src/cli/worker/engine/mod.rs
index 249db13..f68309a 100644
--- a/espanso/src/cli/worker/engine/mod.rs
+++ b/espanso/src/cli/worker/engine/mod.rs
@@ -126,6 +126,8 @@ pub fn initialize_and_spawn(
),
hotkeys: match_converter.get_hotkeys(),
win32_exclude_orphan_events: default_config.win32_exclude_orphan_events(),
+ win32_keyboard_layout_cache_interval: default_config
+ .win32_keyboard_layout_cache_interval(),
})
.expect("failed to initialize detector module");
let exit_source = super::engine::funnel::exit::ExitSource::new(exit_signal, &sequencer);
diff --git a/espanso/src/cli/worker/engine/process/middleware/render/extension/form.rs b/espanso/src/cli/worker/engine/process/middleware/render/extension/form.rs
index dd9fbe7..fb0510b 100644
--- a/espanso/src/cli/worker/engine/process/middleware/render/extension/form.rs
+++ b/espanso/src/cli/worker/engine/process/middleware/render/extension/form.rs
@@ -55,55 +55,53 @@ fn convert_fields(fields: &Params) -> HashMap {
let mut form_field = None;
if let Value::Object(params) = field {
- if let Some(Value::String(field_type)) = params.get("type") {
- form_field = match field_type.as_str() {
- "text" => Some(FormField::Text {
- default: params
- .get("default")
- .and_then(|val| val.as_string())
- .cloned(),
- multiline: params
- .get("multiline")
- .and_then(|val| val.as_bool())
- .cloned()
- .unwrap_or(false),
- }),
- "choice" => Some(FormField::Choice {
- default: params
- .get("default")
- .and_then(|val| val.as_string())
- .cloned(),
- values: params
- .get("values")
- .and_then(|val| val.as_array())
- .map(|arr| {
- arr
- .iter()
- .flat_map(|choice| choice.as_string())
- .cloned()
- .collect()
- })
- .unwrap_or_default(),
- }),
- "list" => Some(FormField::List {
- default: params
- .get("default")
- .and_then(|val| val.as_string())
- .cloned(),
- values: params
- .get("values")
- .and_then(|val| val.as_array())
- .map(|arr| {
- arr
- .iter()
- .flat_map(|choice| choice.as_string())
- .cloned()
- .collect()
- })
- .unwrap_or_default(),
- }),
- _ => None,
- }
+ form_field = match params.get("type") {
+ Some(Value::String(field_type)) if field_type == "choice" => Some(FormField::Choice {
+ default: params
+ .get("default")
+ .and_then(|val| val.as_string())
+ .cloned(),
+ values: params
+ .get("values")
+ .and_then(|val| val.as_array())
+ .map(|arr| {
+ arr
+ .iter()
+ .flat_map(|choice| choice.as_string())
+ .cloned()
+ .collect()
+ })
+ .unwrap_or_default(),
+ }),
+ Some(Value::String(field_type)) if field_type == "list" => Some(FormField::List {
+ default: params
+ .get("default")
+ .and_then(|val| val.as_string())
+ .cloned(),
+ values: params
+ .get("values")
+ .and_then(|val| val.as_array())
+ .map(|arr| {
+ arr
+ .iter()
+ .flat_map(|choice| choice.as_string())
+ .cloned()
+ .collect()
+ })
+ .unwrap_or_default(),
+ }),
+ // By default, it's considered type 'text'
+ _ => Some(FormField::Text {
+ default: params
+ .get("default")
+ .and_then(|val| val.as_string())
+ .cloned(),
+ multiline: params
+ .get("multiline")
+ .and_then(|val| val.as_bool())
+ .cloned()
+ .unwrap_or(false),
+ }),
}
}
diff --git a/espanso/src/patch/mod.rs b/espanso/src/patch/mod.rs
index e499181..f1ce634 100644
--- a/espanso/src/patch/mod.rs
+++ b/espanso/src/patch/mod.rs
@@ -55,6 +55,7 @@ fn get_builtin_patches() -> Vec {
patches::linux::urxvt_terminal_x11::patch(),
patches::linux::xterm_terminal_x11::patch(),
patches::linux::yakuake_terminal_x11::patch(),
+ patches::linux::virtualbox_x11::patch(),
];
}
diff --git a/espanso/src/patch/patches/linux/alacritty_terminal_x11.rs b/espanso/src/patch/patches/linux/alacritty_terminal_x11.rs
index f02ea34..039d15c 100644
--- a/espanso/src/patch/patches/linux/alacritty_terminal_x11.rs
+++ b/espanso/src/patch/patches/linux/alacritty_terminal_x11.rs
@@ -19,6 +19,8 @@
use std::sync::Arc;
+use espanso_config::config::Backend;
+
use crate::patch::patches::{PatchedConfig, Patches};
use crate::patch::PatchDefinition;
@@ -33,6 +35,7 @@ pub fn patch() -> PatchDefinition {
name,
Patches {
paste_shortcut: Some(Some("CTRL+SHIFT+V".to_string())),
+ backend: Some(Backend::Clipboard),
..Default::default()
},
))
diff --git a/espanso/src/patch/patches/linux/mod.rs b/espanso/src/patch/patches/linux/mod.rs
index d145f16..3d42011 100644
--- a/espanso/src/patch/patches/linux/mod.rs
+++ b/espanso/src/patch/patches/linux/mod.rs
@@ -30,6 +30,7 @@ pub mod termite_terminal_x11;
pub mod thunderbird_x11;
pub mod tilix_terminal_x11;
pub mod urxvt_terminal_x11;
+pub mod virtualbox_x11;
pub mod xterm_terminal_x11;
pub mod yakuake_terminal_x11;
diff --git a/espanso/src/patch/patches/linux/virtualbox_x11.rs b/espanso/src/patch/patches/linux/virtualbox_x11.rs
new file mode 100644
index 0000000..9db735f
--- /dev/null
+++ b/espanso/src/patch/patches/linux/virtualbox_x11.rs
@@ -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 .
+ */
+
+use std::sync::Arc;
+
+use espanso_config::config::Backend;
+
+use crate::patch::patches::{PatchedConfig, Patches};
+use crate::patch::PatchDefinition;
+
+pub fn patch() -> PatchDefinition {
+ PatchDefinition {
+ name: module_path!().split(':').last().unwrap_or("unknown"),
+ is_enabled: || cfg!(target_os = "linux") && !super::util::is_wayland(),
+ should_patch: |app| app.class.unwrap_or_default().contains("VirtualBox Machine"),
+ apply: |base, name| {
+ Arc::new(PatchedConfig::patch(
+ base,
+ name,
+ Patches {
+ backend: Some(Backend::Inject),
+ key_delay: Some(Some(10)),
+ inject_delay: Some(Some(15)),
+ disable_x11_fast_inject: Some(true),
+ ..Default::default()
+ },
+ ))
+ },
+ }
+}
diff --git a/espanso/src/patch/patches/mod.rs b/espanso/src/patch/patches/mod.rs
index 5fddc89..c6dd4f7 100644
--- a/espanso/src/patch/patches/mod.rs
+++ b/espanso/src/patch/patches/mod.rs
@@ -49,5 +49,6 @@ generate_patchable_config!(
apply_patch -> bool,
undo_backspace -> bool,
win32_exclude_orphan_events -> bool,
+ win32_keyboard_layout_cache_interval -> i64,
keyboard_layout -> Option
);
diff --git a/snapcraft.yaml b/snapcraft.yaml
index 51f22b0..92a5f11 100644
--- a/snapcraft.yaml
+++ b/snapcraft.yaml
@@ -1,5 +1,5 @@
name: espanso
-version: 2.0.3-alpha
+version: 2.0.4-alpha
summary: A Cross-platform Text Expander written in Rust
description: |
espanso is a Cross-platform, Text Expander written in Rust.