Merge pull request #821 from federico-terzi/dev

v2.0.4-alpha release
This commit is contained in:
Federico Terzi 2021-10-26 22:11:44 +02:00 committed by GitHub
commit 4bd5f4c6c5
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
28 changed files with 229 additions and 115 deletions

View File

@ -31,7 +31,7 @@ RUN set -eux; \
cargo --version; \ cargo --version; \
rustc --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 COPY . espanso

View File

@ -35,7 +35,7 @@ jobs:
MACOSX_DEPLOYMENT_TARGET: "10.13" MACOSX_DEPLOYMENT_TARGET: "10.13"
- name: Install cargo-make - name: Install cargo-make
run: | run: |
cargo install --force cargo-make cargo install --force cargo-make --version 0.34.0
- name: Run test suite - name: Run test suite
run: cargo make test-binary run: cargo make test-binary
- name: Build - name: Build
@ -60,7 +60,7 @@ jobs:
cargo clippy -p espanso --features wayland -- -D warnings cargo clippy -p espanso --features wayland -- -D warnings
- name: Install cargo-make - name: Install cargo-make
run: | run: |
cargo install --force cargo-make cargo install --force cargo-make --version 0.34.0
- name: Run test suite - name: Run test suite
run: cargo make test-binary --env NO_X11=true run: cargo make test-binary --env NO_X11=true
- name: Build - name: Build
@ -74,7 +74,7 @@ jobs:
run: rustup update && rustup target add aarch64-apple-darwin run: rustup update && rustup target add aarch64-apple-darwin
- name: Install cargo-make - name: Install cargo-make
run: | run: |
cargo install --force cargo-make cargo install --force cargo-make --version 0.34.0
- name: Build - name: Build
run: | run: |
cargo make build-macos-arm-binary cargo make build-macos-arm-binary

View File

@ -61,7 +61,7 @@ jobs:
echo Using version ${{ needs.extract-version.outputs.espanso_version }} echo Using version ${{ needs.extract-version.outputs.espanso_version }}
- name: Install cargo-make - name: Install cargo-make
run: | run: |
cargo install --force cargo-make cargo install --force cargo-make --version 0.34.0
- name: Test - name: Test
run: cargo make test-binary --profile release run: cargo make test-binary --profile release
- name: Build - name: Build
@ -128,7 +128,7 @@ jobs:
echo Using version ${{ needs.extract-version.outputs.espanso_version }} echo Using version ${{ needs.extract-version.outputs.espanso_version }}
- name: Install cargo-make - name: Install cargo-make
run: | run: |
cargo install --force cargo-make cargo install --force cargo-make --version 0.34.0
- name: Test - name: Test
run: cargo make test-binary --profile release run: cargo make test-binary --profile release
env: env:
@ -168,7 +168,7 @@ jobs:
run: rustup update && rustup target add aarch64-apple-darwin run: rustup update && rustup target add aarch64-apple-darwin
- name: Install cargo-make - name: Install cargo-make
run: | run: |
cargo install --force cargo-make cargo install --force cargo-make --version 0.34.0
- name: Build - name: Build
run: cargo make create-bundle --profile release --env BUILD_ARCH=aarch64-apple-darwin run: cargo make create-bundle --profile release --env BUILD_ARCH=aarch64-apple-darwin
- name: Codesign executable - name: Codesign executable

2
Cargo.lock generated
View File

@ -572,7 +572,7 @@ dependencies = [
[[package]] [[package]]
name = "espanso" name = "espanso"
version = "2.0.3-alpha" version = "2.0.4-alpha"
dependencies = [ dependencies = [
"anyhow", "anyhow",
"caps", "caps",

View File

@ -16,7 +16,7 @@ These are the basic tools required to build espanso:
steps. You can install it by running: steps. You can install it by running:
``` ```
cargo install --force cargo-make cargo install --force cargo-make --version 0.34.0
``` ```
# Linux # Linux

View File

@ -156,6 +156,12 @@ pub trait Config: Send + Sync {
// Disabling this option might conflict with the undo feature. // Disabling this option might conflict with the undo feature.
fn win32_exclude_orphan_events(&self) -> bool; 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 is_match<'a>(&self, app: &AppProperties<'a>) -> bool;
fn pretty_dump(&self) -> String { fn pretty_dump(&self) -> String {
@ -187,6 +193,9 @@ pub trait Config: Send + Sync {
show_notifications: {:?} show_notifications: {:?}
secure_input_notification: {:?} secure_input_notification: {:?}
win32_exclude_orphan_events: {:?}
win32_keyboard_layout_cache_interval: {:?}
match_paths: {:#?} match_paths: {:#?}
", ",
self.label(), self.label(),
@ -215,6 +224,9 @@ pub trait Config: Send + Sync {
self.show_notifications(), self.show_notifications(),
self.secure_input_notification(), self.secure_input_notification(),
self.win32_exclude_orphan_events(),
self.win32_keyboard_layout_cache_interval(),
self.match_paths(), self.match_paths(),
} }
} }

View File

@ -45,6 +45,7 @@ pub(crate) struct ParsedConfig {
pub show_icon: Option<bool>, pub show_icon: Option<bool>,
pub secure_input_notification: Option<bool>, pub secure_input_notification: Option<bool>,
pub win32_exclude_orphan_events: Option<bool>, pub win32_exclude_orphan_events: Option<bool>,
pub win32_keyboard_layout_cache_interval: Option<i64>,
pub pre_paste_delay: Option<usize>, pub pre_paste_delay: Option<usize>,
pub restore_clipboard_delay: Option<usize>, pub restore_clipboard_delay: Option<usize>,

View File

@ -109,6 +109,9 @@ pub(crate) struct YAMLConfig {
#[serde(default)] #[serde(default)]
pub win32_exclude_orphan_events: Option<bool>, pub win32_exclude_orphan_events: Option<bool>,
#[serde(default)]
pub win32_keyboard_layout_cache_interval: Option<i64>,
// Include/Exclude // Include/Exclude
#[serde(default)] #[serde(default)]
pub includes: Option<Vec<String>>, pub includes: Option<Vec<String>>,
@ -197,6 +200,7 @@ impl TryFrom<YAMLConfig> for ParsedConfig {
paste_shortcut_event_delay: yaml_config.paste_shortcut_event_delay, paste_shortcut_event_delay: yaml_config.paste_shortcut_event_delay,
win32_exclude_orphan_events: yaml_config.win32_exclude_orphan_events, 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, use_standard_includes: yaml_config.use_standard_includes,
includes: yaml_config.includes, includes: yaml_config.includes,
@ -253,6 +257,7 @@ mod tests {
show_notifications: false show_notifications: false
secure_input_notification: false secure_input_notification: false
win32_exclude_orphan_events: false win32_exclude_orphan_events: false
win32_keyboard_layout_cache_interval: 300
use_standard_includes: true use_standard_includes: true
includes: ["test1"] includes: ["test1"]
@ -305,6 +310,7 @@ mod tests {
show_notifications: Some(false), show_notifications: Some(false),
secure_input_notification: Some(false), secure_input_notification: Some(false),
win32_exclude_orphan_events: Some(false), win32_exclude_orphan_events: Some(false),
win32_keyboard_layout_cache_interval: Some(300),
pre_paste_delay: Some(300), pre_paste_delay: Some(300),
evdev_modifier_delay: Some(40), evdev_modifier_delay: Some(40),

View File

@ -323,6 +323,13 @@ impl Config for ResolvedConfig {
fn evdev_modifier_delay(&self) -> Option<usize> { fn evdev_modifier_delay(&self) -> Option<usize> {
self.parsed.evdev_modifier_delay 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 { impl ResolvedConfig {
@ -405,6 +412,7 @@ impl ResolvedConfig {
show_notifications, show_notifications,
secure_input_notification, secure_input_notification,
win32_exclude_orphan_events, win32_exclude_orphan_events,
win32_keyboard_layout_cache_interval,
includes, includes,
excludes, excludes,
extra_includes, extra_includes,

View File

@ -394,6 +394,10 @@ impl Config for LegacyInteropConfig {
fn evdev_modifier_delay(&self) -> Option<usize> { fn evdev_modifier_delay(&self) -> Option<usize> {
Some(10) Some(10)
} }
fn win32_keyboard_layout_cache_interval(&self) -> i64 {
2000
}
} }
struct LegacyMatchGroup { struct LegacyMatchGroup {

View File

@ -6,6 +6,7 @@ use libc::{input_event, size_t, ssize_t, EWOULDBLOCK, O_CLOEXEC, O_NONBLOCK, O_R
use log::trace; use log::trace;
use scopeguard::ScopeGuard; use scopeguard::ScopeGuard;
use std::collections::HashMap; use std::collections::HashMap;
use std::os::raw::c_char;
use std::os::unix::io::AsRawFd; use std::os::unix::io::AsRawFd;
use std::{ use std::{
ffi::{c_void, CStr}, ffi::{c_void, CStr},
@ -160,16 +161,16 @@ impl Device {
} }
// Extract the utf8 char // Extract the utf8 char
let mut buffer: [u8; 16] = [0; 16]; let mut buffer: [c_char; 16] = [0; 16];
unsafe { unsafe {
xkb_state_key_get_utf8( xkb_state_key_get_utf8(
self.get_state(), self.get_state(),
keycode, keycode,
buffer.as_mut_ptr() as *mut i8, buffer.as_mut_ptr(),
std::mem::size_of_val(&buffer), 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 content = content_raw.to_string_lossy().to_string();
let event = RawKeyboardEvent { let event = RawKeyboardEvent {

View File

@ -66,6 +66,12 @@ pub struct SourceCreationOptions {
// those from espanso, but might need to be disabled when using some software-level keyboards. // those from espanso, but might need to be disabled when using some software-level keyboards.
// Disabling this option might conflict with the undo feature. // Disabling this option might conflict with the undo feature.
pub win32_exclude_orphan_events: bool, 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 // This struct identifies the keyboard layout that
@ -87,6 +93,7 @@ impl Default for SourceCreationOptions {
evdev_keyboard_rmlvo: None, evdev_keyboard_rmlvo: None,
hotkeys: Vec::new(), hotkeys: Vec::new(),
win32_exclude_orphan_events: true, win32_exclude_orphan_events: true,
win32_keyboard_layout_cache_interval: 2000,
} }
} }
} }
@ -97,6 +104,7 @@ pub fn get_source(options: SourceCreationOptions) -> Result<Box<dyn Source>> {
Ok(Box::new(win32::Win32Source::new( Ok(Box::new(win32::Win32Source::new(
&options.hotkeys, &options.hotkeys,
options.win32_exclude_orphan_events, options.win32_exclude_orphan_events,
options.win32_keyboard_layout_cache_interval,
))) )))
} }

View File

@ -17,6 +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 std::os::raw::c_long;
use std::{convert::TryInto, ffi::c_void}; use std::{convert::TryInto, ffi::c_void};
use lazycell::LazyCell; use lazycell::LazyCell;
@ -79,10 +80,19 @@ pub struct RawHotKey {
pub flags: u32, pub flags: u32,
} }
#[repr(C)]
pub struct InitOptions {
pub keyboard_layout_cache_interval: c_long,
}
#[allow(improper_ctypes)] #[allow(improper_ctypes)]
#[link(name = "espansodetect", kind = "static")] #[link(name = "espansodetect", kind = "static")]
extern "C" { 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_register_hotkey(window: *const c_void, hotkey: RawHotKey) -> i32;
pub fn detect_eventloop( pub fn detect_eventloop(
@ -99,24 +109,35 @@ pub struct Win32Source {
hotkeys: Vec<HotKey>, hotkeys: Vec<HotKey>,
exclude_orphan_events: bool, exclude_orphan_events: bool,
keyboard_layout_cache_interval: i64,
} }
#[allow(clippy::new_without_default)] #[allow(clippy::new_without_default)]
impl Win32Source { 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 { Self {
handle: std::ptr::null_mut(), handle: std::ptr::null_mut(),
callback: LazyCell::new(), callback: LazyCell::new(),
hotkeys: hotkeys.to_vec(), hotkeys: hotkeys.to_vec(),
exclude_orphan_events, exclude_orphan_events,
keyboard_layout_cache_interval,
} }
} }
} }
impl Source for Win32Source { impl Source for Win32Source {
fn initialize(&mut self) -> Result<()> { 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 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() { if handle.is_null() {
let error = match error_code { let error = match error_code {

View File

@ -39,8 +39,6 @@
#include <strsafe.h> #include <strsafe.h>
#include <Windows.h> #include <Windows.h>
// 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 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 | 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 | 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 { typedef struct {
HKL current_keyboard_layout; HKL current_keyboard_layout;
DWORD last_key_press_tick; DWORD last_key_press_tick;
// How many milliseconds must pass between events before refreshing the keyboard layout
long keyboard_layout_cache_interval;
// Rust interop // Rust interop
void * rust_instance; void * rust_instance;
@ -130,7 +130,7 @@ LRESULT CALLBACK detect_window_procedure(HWND window, unsigned int msg, WPARAM w
DWORD currentTick = GetTickCount(); DWORD currentTick = GetTickCount();
// If enough time has passed between the last keypress and now, refresh the keyboard layout // 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 // 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; HWND window = NULL;
@ -297,6 +297,7 @@ void * detect_initialize(void *_self, int32_t *error_code)
// Initialize the default keyboard layout // Initialize the default keyboard layout
variables->current_keyboard_layout = GetKeyboardLayout(0); 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 // Docs: https://docs.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-createwindowexw
window = CreateWindowEx( window = CreateWindowEx(

View File

@ -76,9 +76,12 @@ typedef struct {
typedef void (*EventCallback)(void * rust_istance, InputEvent data); typedef void (*EventCallback)(void * rust_istance, InputEvent data);
typedef struct {
long keyboard_layout_cache_interval;
} InitOptions;
// Initialize the Raw Input API and the Window. // 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 // Register the given hotkey, return a non-zero code if successful
extern "C" int32_t detect_register_hotkey(void * window, HotKey hotkey); extern "C" int32_t detect_register_hotkey(void * window, HotKey hotkey);

View File

@ -64,8 +64,9 @@ impl Middleware for DisableMiddleware {
match &event.etype { match &event.etype {
EventType::Keyboard(m_event) => { 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(); let mut last_toggle_press = self.last_toggle_press.borrow_mut();
if is_toggle_key(m_event, &self.options) {
if let Some(previous_press) = *last_toggle_press { if let Some(previous_press) = *last_toggle_press {
if previous_press.elapsed() < self.options.toggle_key_maximum_window { if previous_press.elapsed() < self.options.toggle_key_maximum_window {
*enabled = !*enabled; *enabled = !*enabled;
@ -77,6 +78,11 @@ impl Middleware for DisableMiddleware {
} else { } else {
*last_toggle_press = Some(Instant::now()); *last_toggle_press = Some(Instant::now());
} }
} else {
// 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;
}
} }
} }
EventType::EnableRequest => { EventType::EnableRequest => {
@ -115,10 +121,6 @@ impl Middleware for DisableMiddleware {
} }
fn is_toggle_key(event: &KeyboardEvent, options: &DisableOptions) -> bool { fn is_toggle_key(event: &KeyboardEvent, options: &DisableOptions) -> bool {
if event.status != Status::Released {
return false;
}
if options if options
.toggle_key .toggle_key
.as_ref() .as_ref()

View File

@ -17,6 +17,8 @@
* along with espanso. If not, see <https://www.gnu.org/licenses/>. * along with espanso. If not, see <https://www.gnu.org/licenses/>.
*/ */
use log::error;
use super::super::Middleware; use super::super::Middleware;
use crate::event::{effect::HtmlInjectRequest, Event, EventType}; use crate::event::{effect::HtmlInjectRequest, Event, EventType};
@ -37,7 +39,12 @@ impl Middleware for MarkdownMiddleware {
fn next(&self, event: Event, _: &mut dyn FnMut(Event)) -> Event { fn next(&self, event: Event, _: &mut dyn FnMut(Event)) -> Event {
if let EventType::MarkdownInject(m_event) = &event.etype { if let EventType::MarkdownInject(m_event) = &event.etype {
// Render the markdown into HTML // Render the markdown into HTML
let html = markdown::to_html(&m_event.markdown); // 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(); let mut html = html.trim();
// Remove the surrounding paragraph // Remove the surrounding paragraph
@ -54,6 +61,11 @@ impl Middleware for MarkdownMiddleware {
html: html.to_owned(), 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 event

View File

@ -191,7 +191,7 @@ fn is_event_of_interest(event_type: &EventType) -> bool {
// In hex, they have the byte 3 = 0xfe // In hex, they have the byte 3 = 0xfe
// See list in "keysymdef.h" file // See list in "keysymdef.h" file
if cfg!(target_os = "linux") { 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) { if (65025..=65276).contains(raw_code) {
return false; return false;
} }

View File

@ -457,22 +457,5 @@ fn build_native() {
} }
fn main() { 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(); build_native();
} }

View File

@ -1,6 +1,6 @@
[package] [package]
name = "espanso" name = "espanso"
version = "2.0.3-alpha" version = "2.0.4-alpha"
authors = ["Federico Terzi <federicoterzi96@gmail.com>"] authors = ["Federico Terzi <federicoterzi96@gmail.com>"]
license = "GPL-3.0" license = "GPL-3.0"
description = "Cross-platform Text Expander written in Rust" description = "Cross-platform Text Expander written in Rust"

View File

@ -126,6 +126,8 @@ pub fn initialize_and_spawn(
), ),
hotkeys: match_converter.get_hotkeys(), hotkeys: match_converter.get_hotkeys(),
win32_exclude_orphan_events: default_config.win32_exclude_orphan_events(), 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"); .expect("failed to initialize detector module");
let exit_source = super::engine::funnel::exit::ExitSource::new(exit_signal, &sequencer); let exit_source = super::engine::funnel::exit::ExitSource::new(exit_signal, &sequencer);

View File

@ -55,9 +55,43 @@ fn convert_fields(fields: &Params) -> HashMap<String, FormField> {
let mut form_field = None; let mut form_field = None;
if let Value::Object(params) = field { if let Value::Object(params) = field {
if let Some(Value::String(field_type)) = params.get("type") { form_field = match params.get("type") {
form_field = match field_type.as_str() { Some(Value::String(field_type)) if field_type == "choice" => Some(FormField::Choice {
"text" => Some(FormField::Text { 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 default: params
.get("default") .get("default")
.and_then(|val| val.as_string()) .and_then(|val| val.as_string())
@ -68,42 +102,6 @@ fn convert_fields(fields: &Params) -> HashMap<String, FormField> {
.cloned() .cloned()
.unwrap_or(false), .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,
}
} }
} }

View File

@ -55,6 +55,7 @@ fn get_builtin_patches() -> Vec<PatchDefinition> {
patches::linux::urxvt_terminal_x11::patch(), patches::linux::urxvt_terminal_x11::patch(),
patches::linux::xterm_terminal_x11::patch(), patches::linux::xterm_terminal_x11::patch(),
patches::linux::yakuake_terminal_x11::patch(), patches::linux::yakuake_terminal_x11::patch(),
patches::linux::virtualbox_x11::patch(),
]; ];
} }

View File

@ -19,6 +19,8 @@
use std::sync::Arc; use std::sync::Arc;
use espanso_config::config::Backend;
use crate::patch::patches::{PatchedConfig, Patches}; use crate::patch::patches::{PatchedConfig, Patches};
use crate::patch::PatchDefinition; use crate::patch::PatchDefinition;
@ -33,6 +35,7 @@ pub fn patch() -> PatchDefinition {
name, name,
Patches { Patches {
paste_shortcut: Some(Some("CTRL+SHIFT+V".to_string())), paste_shortcut: Some(Some("CTRL+SHIFT+V".to_string())),
backend: Some(Backend::Clipboard),
..Default::default() ..Default::default()
}, },
)) ))

View File

@ -30,6 +30,7 @@ pub mod termite_terminal_x11;
pub mod thunderbird_x11; pub mod thunderbird_x11;
pub mod tilix_terminal_x11; pub mod tilix_terminal_x11;
pub mod urxvt_terminal_x11; pub mod urxvt_terminal_x11;
pub mod virtualbox_x11;
pub mod xterm_terminal_x11; pub mod xterm_terminal_x11;
pub mod yakuake_terminal_x11; pub mod yakuake_terminal_x11;

View 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 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()
},
))
},
}
}

View File

@ -49,5 +49,6 @@ generate_patchable_config!(
apply_patch -> bool, apply_patch -> bool,
undo_backspace -> bool, undo_backspace -> bool,
win32_exclude_orphan_events -> bool, win32_exclude_orphan_events -> bool,
win32_keyboard_layout_cache_interval -> i64,
keyboard_layout -> Option<RMLVOConfig> keyboard_layout -> Option<RMLVOConfig>
); );

View File

@ -1,5 +1,5 @@
name: espanso name: espanso
version: 2.0.3-alpha version: 2.0.4-alpha
summary: A Cross-platform Text Expander written in Rust summary: A Cross-platform Text Expander written in Rust
description: | description: |
espanso is a Cross-platform, Text Expander written in Rust. espanso is a Cross-platform, Text Expander written in Rust.