From 3737eed03475bbeb5f65d6deba14a66363d78ddb Mon Sep 17 00:00:00 2001 From: Federico Terzi Date: Sun, 14 Feb 2021 22:01:42 +0100 Subject: [PATCH] Introduce wayland feature --- espanso-detect/Cargo.toml | 5 ++ espanso-detect/build.rs | 22 +++++---- espanso-detect/src/evdev/keymap.rs | 34 +++++++++++--- espanso-detect/src/evdev/mod.rs | 15 +++--- espanso-detect/src/lib.rs | 74 ++++++++++++++++++++++++++++++ espanso-detect/src/mac/mod.rs | 9 ++-- espanso-detect/src/win32/mod.rs | 9 ++-- espanso-detect/src/x11/mod.rs | 13 ++++-- espanso-inject/Cargo.toml | 5 ++ espanso-inject/build.rs | 18 +++----- espanso-inject/src/lib.rs | 34 ++++++++++---- espanso-inject/src/x11/mod.rs | 2 +- espanso-ui/src/lib.rs | 52 +++++++++++++++++++++ espanso-ui/src/linux/mod.rs | 20 ++++++-- espanso-ui/src/win32/mod.rs | 2 - espanso/Cargo.toml | 5 ++ espanso/src/main.rs | 66 +++++++++++++------------- 17 files changed, 292 insertions(+), 93 deletions(-) diff --git a/espanso-detect/Cargo.toml b/espanso-detect/Cargo.toml index 317b4a1..fe5c145 100644 --- a/espanso-detect/Cargo.toml +++ b/espanso-detect/Cargo.toml @@ -5,6 +5,11 @@ authors = ["Federico Terzi "] edition = "2018" build="build.rs" +[features] +# If the wayland feature is enabled, all X11 dependencies will be dropped +# and only EVDEV-based methods will be supported. +wayland = [] + [dependencies] log = "0.4.14" lazycell = "1.3.0" diff --git a/espanso-detect/build.rs b/espanso-detect/build.rs index 6fade5d..d125928 100644 --- a/espanso-detect/build.rs +++ b/espanso-detect/build.rs @@ -39,21 +39,27 @@ fn cc_config() { println!("cargo:rerun-if-changed=src/x11/native.h"); println!("cargo:rerun-if-changed=src/evdev/native.cpp"); println!("cargo:rerun-if-changed=src/evdev/native.h"); - cc::Build::new() - .cpp(true) - .include("src/x11/native.h") - .file("src/x11/native.cpp") - .compile("espansodetect"); + + if cfg!(not(feature = "wayland")) { + cc::Build::new() + .cpp(true) + .include("src/x11/native.h") + .file("src/x11/native.cpp") + .compile("espansodetect"); + + println!("cargo:rustc-link-lib=static=espansodetect"); + println!("cargo:rustc-link-lib=dylib=X11"); + println!("cargo:rustc-link-lib=dylib=Xtst"); + } + cc::Build::new() .cpp(true) .include("src/evdev/native.h") .file("src/evdev/native.cpp") .compile("espansodetectevdev"); + println!("cargo:rustc-link-search=native=/usr/lib/x86_64-linux-gnu/"); - println!("cargo:rustc-link-lib=static=espansodetect"); println!("cargo:rustc-link-lib=static=espansodetectevdev"); - println!("cargo:rustc-link-lib=dylib=X11"); - println!("cargo:rustc-link-lib=dylib=Xtst"); println!("cargo:rustc-link-lib=dylib=xkbcommon"); } diff --git a/espanso-detect/src/evdev/keymap.rs b/espanso-detect/src/evdev/keymap.rs index ac68fcf..8fc5ddb 100644 --- a/espanso-detect/src/evdev/keymap.rs +++ b/espanso-detect/src/evdev/keymap.rs @@ -1,26 +1,32 @@ // This code is a port of the libxkbcommon "interactive-evdev.c" example // https://github.com/xkbcommon/libxkbcommon/blob/master/tools/interactive-evdev.c +use std::ffi::CString; + use scopeguard::ScopeGuard; use anyhow::Result; use thiserror::Error; -use super::{ - context::Context, - ffi::{xkb_keymap, xkb_keymap_new_from_names, xkb_keymap_unref, XKB_KEYMAP_COMPILE_NO_FLAGS}, -}; +use crate::KeyboardConfig; + +use super::{context::Context, ffi::{XKB_KEYMAP_COMPILE_NO_FLAGS, xkb_keymap, xkb_keymap_new_from_names, xkb_keymap_unref, xkb_rule_names}}; pub struct Keymap { keymap: *mut xkb_keymap, } impl Keymap { - pub fn new(context: &Context) -> Result { + pub fn new(context: &Context, rmlvo: Option) -> Result { + let names = rmlvo.map(|rmlvo| { + Self::generate_names(rmlvo) + }); + + let names_ptr = names.map_or(std::ptr::null(), |names| &names); let raw_keymap = unsafe { xkb_keymap_new_from_names( context.get_handle(), - std::ptr::null(), + names_ptr, XKB_KEYMAP_COMPILE_NO_FLAGS, ) }; @@ -40,6 +46,22 @@ impl Keymap { pub fn get_handle(&self) -> *mut xkb_keymap { self.keymap } + + fn generate_names(rmlvo: KeyboardConfig) -> xkb_rule_names { + let rules = rmlvo.rules.map(|s| { CString::new(s).expect("unable to create CString for keymap") }); + let model = rmlvo.model.map(|s| { CString::new(s).expect("unable to create CString for keymap") }); + let layout = rmlvo.layout.map(|s| { CString::new(s).expect("unable to create CString for keymap") }); + let variant = rmlvo.variant.map(|s| { CString::new(s).expect("unable to create CString for keymap") }); + let options = rmlvo.options.map(|s| { CString::new(s).expect("unable to create CString for keymap") }); + + xkb_rule_names { + rules: rules.map_or(std::ptr::null(), |s| s.as_ptr()), + model: model.map_or(std::ptr::null(), |s| s.as_ptr()), + layout: layout.map_or(std::ptr::null(), |s| s.as_ptr()), + variant: variant.map_or(std::ptr::null(), |s| s.as_ptr()), + options: options.map_or(std::ptr::null(), |s| s.as_ptr()), + } + } } impl Drop for Keymap { diff --git a/espanso-detect/src/evdev/mod.rs b/espanso-detect/src/evdev/mod.rs index 488a74b..9faf115 100644 --- a/espanso-detect/src/evdev/mod.rs +++ b/espanso-detect/src/evdev/mod.rs @@ -36,7 +36,7 @@ use libc::{ use log::{error, trace}; use thiserror::Error; -use crate::event::Status::*; +use crate::{KeyboardConfig, Source, SourceCallback, SourceCreationOptions, event::Status::*}; use crate::event::Variant::*; use crate::event::{InputEvent, Key, KeyboardEvent, Variant}; use crate::event::{Key::*, MouseButton, MouseEvent}; @@ -49,27 +49,30 @@ const BTN_MIDDLE: u16 = 0x112; const BTN_SIDE: u16 = 0x113; const BTN_EXTRA: u16 = 0x114; -pub type EVDEVSourceCallback = Box; pub struct EVDEVSource { devices: Vec, + _keyboard_rmlvo: Option, _context: LazyCell, _keymap: LazyCell, } #[allow(clippy::new_without_default)] impl EVDEVSource { - pub fn new() -> EVDEVSource { + pub fn new(options: SourceCreationOptions) -> EVDEVSource { Self { devices: Vec::new(), _context: LazyCell::new(), _keymap: LazyCell::new(), + _keyboard_rmlvo: options.evdev_keyboard_rmlvo, } } +} - pub fn initialize(&mut self) -> Result<()> { +impl Source for EVDEVSource { + fn initialize(&mut self) -> Result<()> { let context = Context::new().expect("unable to obtain xkb context"); - let keymap = Keymap::new(&context).expect("unable to create xkb keymap"); + let keymap = Keymap::new(&context, self._keyboard_rmlvo.clone()).expect("unable to create xkb keymap"); match get_devices(&keymap) { Ok(devices) => self.devices = devices, @@ -97,7 +100,7 @@ impl EVDEVSource { Ok(()) } - pub fn eventloop(&self, event_callback: EVDEVSourceCallback) { + fn eventloop(&self, event_callback: SourceCallback) { if self.devices.is_empty() { panic!("can't start eventloop without evdev devices"); } diff --git a/espanso-detect/src/lib.rs b/espanso-detect/src/lib.rs index 3f8d85a..3915ae9 100644 --- a/espanso-detect/src/lib.rs +++ b/espanso-detect/src/lib.rs @@ -17,12 +17,16 @@ * along with espanso. If not, see . */ +use anyhow::Result; +use log::info; + pub mod event; #[cfg(target_os = "windows")] pub mod win32; #[cfg(target_os = "linux")] +#[cfg(not(feature = "wayland"))] pub mod x11; #[cfg(target_os = "linux")] @@ -34,3 +38,73 @@ pub mod mac; #[cfg(target_os = "macos")] #[macro_use] extern crate lazy_static; + +pub type SourceCallback = Box; + +pub trait Source { + fn initialize(&mut self) -> Result<()>; + fn eventloop(&self, event_callback: SourceCallback); +} + +#[allow(dead_code)] +pub struct SourceCreationOptions { + // Only relevant in X11 Linux systems, use the EVDEV backend instead of X11. + use_evdev: bool, + + // Can be used to overwrite the keymap configuration + // used by espanso to inject key presses. + evdev_keyboard_rmlvo: Option, +} + +// This struct identifies the keyboard layout that +// should be used by EVDEV when loading the keymap. +// For more information: https://xkbcommon.org/doc/current/structxkb__rule__names.html +#[derive(Debug, Clone)] +pub struct KeyboardConfig { + pub rules: Option, + pub model: Option, + pub layout: Option, + pub variant: Option, + pub options: Option, +} + +impl Default for SourceCreationOptions { + fn default() -> Self { + Self { + use_evdev: false, + evdev_keyboard_rmlvo: None, + } + } +} + +#[cfg(target_os = "windows")] +pub fn get_source(_options: SourceCreationOptions) -> Result> { + info!("using Win32Source"); + Ok(Box::new(win32::Win32Source::new())) +} + +#[cfg(target_os = "macos")] +pub fn get_source(_options: SourceCreationOptions) -> Result> { + info!("using CocoaSource"); + Ok(Box::new(mac::CocoaSource::new())) +} + +#[cfg(target_os = "linux")] +#[cfg(not(feature = "wayland"))] +pub fn get_source(options: SourceCreationOptions) -> Result> { + if options.use_evdev { + info!("using EVDEVSource"); + Ok(Box::new(evdev::EVDEVSource::new(options))) + } else { + info!("using X11Source"); + Ok(Box::new(x11::X11Source::new())) + } +} + +#[cfg(target_os = "linux")] +#[cfg(feature = "wayland")] +pub fn get_source(options: SourceCreationOptions) -> Result> { + info!("using EVDEVSource"); + Ok(Box::new(evdev::EVDEVSource::new(options))) +} + diff --git a/espanso-detect/src/mac/mod.rs b/espanso-detect/src/mac/mod.rs index 8137489..cc42bc4 100644 --- a/espanso-detect/src/mac/mod.rs +++ b/espanso-detect/src/mac/mod.rs @@ -86,7 +86,6 @@ extern "C" fn native_callback(raw_event: RawInputEvent) { } } -pub type CocoaSourceCallback = Box; pub struct CocoaSource { receiver: LazyCell>, } @@ -99,7 +98,11 @@ impl CocoaSource { } } - pub fn initialize(&mut self) -> Result<()> { + +} + +impl Source for CocoaSource { + fn initialize(&mut self) -> Result<()> { let (sender, receiver) = channel(); // Set the global sender @@ -120,7 +123,7 @@ impl CocoaSource { Ok(()) } - pub fn eventloop(&self, event_callback: CocoaSourceCallback) { + fn eventloop(&self, event_callback: SourceCallback) { if let Some(receiver) = self.receiver.borrow() { loop { let event = receiver.recv(); diff --git a/espanso-detect/src/win32/mod.rs b/espanso-detect/src/win32/mod.rs index b10bab9..bb0c01a 100644 --- a/espanso-detect/src/win32/mod.rs +++ b/espanso-detect/src/win32/mod.rs @@ -75,10 +75,9 @@ extern "C" { pub fn detect_destroy(window: *const c_void) -> i32; } -pub type Win32SourceCallback = Box; pub struct Win32Source { handle: *mut c_void, - callback: LazyCell, + callback: LazyCell, } #[allow(clippy::new_without_default)] @@ -89,8 +88,10 @@ impl Win32Source { callback: LazyCell::new(), } } +} - pub fn initialize(&mut self) -> Result<()> { +impl Source for Win32Source { + fn initialize(&mut self) -> Result<()> { let mut error_code = 0; let handle = unsafe { detect_initialize(self as *const Win32Source, &mut error_code) }; @@ -108,7 +109,7 @@ impl Win32Source { Ok(()) } - pub fn eventloop(&self, event_callback: Win32SourceCallback) { + fn eventloop(&self, event_callback: SourceCallback) { if self.handle.is_null() { panic!("Attempt to start Win32Source eventloop without initialization"); } diff --git a/espanso-detect/src/x11/mod.rs b/espanso-detect/src/x11/mod.rs index 9c9498a..36326ee 100644 --- a/espanso-detect/src/x11/mod.rs +++ b/espanso-detect/src/x11/mod.rs @@ -25,7 +25,7 @@ use log::{error, trace, warn}; use anyhow::Result; use thiserror::Error; -use crate::event::Status::*; +use crate::{Source, SourceCallback, event::Status::*}; use crate::event::Variant::*; use crate::event::{InputEvent, Key, KeyboardEvent, Variant}; use crate::event::{Key::*, MouseButton, MouseEvent}; @@ -70,10 +70,9 @@ extern "C" { pub fn detect_destroy(window: *const c_void) -> i32; } -pub type X11SourceCallback = Box; pub struct X11Source { handle: *mut c_void, - callback: LazyCell, + callback: LazyCell, } #[allow(clippy::new_without_default)] @@ -89,7 +88,11 @@ impl X11Source { unsafe { detect_check_x11() != 0 } } - pub fn initialize(&mut self) -> Result<()> { + +} + +impl Source for X11Source { + fn initialize(&mut self) -> Result<()> { let mut error_code = 0; let handle = unsafe { detect_initialize(self as *const X11Source, &mut error_code) }; @@ -111,7 +114,7 @@ impl X11Source { Ok(()) } - pub fn eventloop(&self, event_callback: X11SourceCallback) { + fn eventloop(&self, event_callback: SourceCallback) { if self.handle.is_null() { panic!("Attempt to start X11Source eventloop without initialization"); } diff --git a/espanso-inject/Cargo.toml b/espanso-inject/Cargo.toml index 4669352..5a0c9a0 100644 --- a/espanso-inject/Cargo.toml +++ b/espanso-inject/Cargo.toml @@ -5,6 +5,11 @@ authors = ["Federico Terzi "] edition = "2018" build="build.rs" +[features] +# If the wayland feature is enabled, all X11 dependencies will be dropped +# and only EVDEV-based methods will be supported. +wayland = [] + [dependencies] log = "0.4.14" lazycell = "1.3.0" diff --git a/espanso-inject/build.rs b/espanso-inject/build.rs index ad40878..a177c4b 100644 --- a/espanso-inject/build.rs +++ b/espanso-inject/build.rs @@ -35,27 +35,21 @@ fn cc_config() { #[cfg(target_os = "linux")] fn cc_config() { - // println!("cargo:rerun-if-changed=src/x11/native.cpp"); - // println!("cargo:rerun-if-changed=src/x11/native.h"); - // println!("cargo:rerun-if-changed=src/evdev/native.cpp"); - // println!("cargo:rerun-if-changed=src/evdev/native.h"); println!("cargo:rerun-if-changed=src/evdev/native.h"); println!("cargo:rerun-if-changed=src/evdev/native.c"); - // cc::Build::new() - // .cpp(true) - // .include("src/x11/native.h") - // .file("src/x11/native.cpp") - // .compile("espansoinject"); cc::Build::new() .include("src/evdev/native.h") .file("src/evdev/native.c") .compile("espansoinjectev"); + println!("cargo:rustc-link-search=native=/usr/lib/x86_64-linux-gnu/"); - // println!("cargo:rustc-link-lib=static=espansoinject"); println!("cargo:rustc-link-lib=static=espansoinjectev"); - println!("cargo:rustc-link-lib=dylib=X11"); - println!("cargo:rustc-link-lib=dylib=Xtst"); println!("cargo:rustc-link-lib=dylib=xkbcommon"); + + if cfg!(not(feature = "wayland")) { + println!("cargo:rustc-link-lib=dylib=X11"); + println!("cargo:rustc-link-lib=dylib=Xtst"); + } } #[cfg(target_os = "macos")] diff --git a/espanso-inject/src/lib.rs b/espanso-inject/src/lib.rs index 243c3c3..3fb4866 100644 --- a/espanso-inject/src/lib.rs +++ b/espanso-inject/src/lib.rs @@ -18,6 +18,7 @@ */ use anyhow::Result; +use log::info; pub mod keys; @@ -25,6 +26,7 @@ pub mod keys; mod win32; #[cfg(target_os = "linux")] +#[cfg(not(feature = "wayland"))] mod x11; #[cfg(target_os = "linux")] @@ -77,7 +79,7 @@ impl Default for InjectionOptions { #[allow(dead_code)] pub struct InjectorCreationOptions { - // Only relevant in Linux systems + // Only relevant in X11 Linux systems, use the EVDEV backend instead of X11. use_evdev: bool, // Overwrite the list of modifiers to be scanned when @@ -116,19 +118,33 @@ impl Default for InjectorCreationOptions { } #[cfg(target_os = "windows")] -pub fn get_injector(_options: InjectorOptions) -> impl Injector { - win32::Win32Injector::new() +pub fn get_injector(_options: InjectorOptions) -> Result> { + info!("using Win32Injector"); + Ok(Box::new(win32::Win32Injector::new())) } #[cfg(target_os = "macos")] -pub fn get_injector(_options: InjectorOptions) -> impl Injector { - mac::MacInjector::new() +pub fn get_injector(_options: InjectorOptions) -> Result> { + info!("using MacInjector"); + Ok(Box::new(mac::MacInjector::new())) } #[cfg(target_os = "linux")] -pub fn get_injector(options: InjectorCreationOptions) -> Result { - // TODO: differenciate based on the options - //x11::X11Injector::new() - evdev::EVDEVInjector::new(options) +#[cfg(not(feature = "wayland"))] +pub fn get_injector(options: InjectorCreationOptions) -> Result> { + if options.use_evdev { + info!("using EVDEVInjector"); + Ok(Box::new(evdev::EVDEVInjector::new(options)?)) + } else { + info!("using X11Injector"); + Ok(Box::new(x11::X11Injector::new()?)) + } +} + +#[cfg(target_os = "linux")] +#[cfg(feature = "wayland")] +pub fn get_injector(options: InjectorCreationOptions) -> Result> { + info!("using EVDEVInjector"); + Ok(Box::new(evdev::EVDEVInjector::new(options)?)) } diff --git a/espanso-inject/src/x11/mod.rs b/espanso-inject/src/x11/mod.rs index 4e439bf..6f53f15 100644 --- a/espanso-inject/src/x11/mod.rs +++ b/espanso-inject/src/x11/mod.rs @@ -30,7 +30,7 @@ use ffi::{Display, KeyCode, KeyPress, KeyRelease, KeySym, Window, XCloseDisplay, use log::error; use anyhow::Result; -use crate::linux::raw_keys::{convert_key_to_sym, convert_to_sym_array}; +use crate::linux::raw_keys::{convert_to_sym_array}; use thiserror::Error; use crate::{keys, InjectionOptions, Injector}; diff --git a/espanso-ui/src/lib.rs b/espanso-ui/src/lib.rs index a960074..3b7901f 100644 --- a/espanso-ui/src/lib.rs +++ b/espanso-ui/src/lib.rs @@ -1,3 +1,6 @@ +use icons::TrayIcon; +use anyhow::Result; + pub mod event; pub mod icons; pub mod menu; @@ -10,3 +13,52 @@ pub mod linux; #[cfg(target_os = "macos")] pub mod mac; + +pub trait UIRemote { + fn update_tray_icon(&self, icon: TrayIcon); + fn show_notification(&self, message: &str); + fn show_context_menu(&self, menu: &menu::Menu); +} + +pub type UIEventCallback = Box; +pub trait UIEventLoop { + fn initialize(&mut self); + fn run(&self, event_callback: UIEventCallback); +} + +pub struct UIOptions { + pub show_icon: bool, + pub icon_paths: Vec<(TrayIcon, String)>, + pub notification_icon_path: Option, +} + +impl Default for UIOptions { + fn default() -> Self { + Self { + show_icon: true, + icon_paths: Vec::new(), + notification_icon_path: None, + } + } +} + +#[cfg(target_os = "windows")] +pub fn create_ui(_options: UIOptions) -> Result> { + // TODO: refactor + Ok(Box::new(win32::Win32Injector::new())) +} + +#[cfg(target_os = "macos")] +pub fn create_ui(_options: UIOptions) -> Result> { + // TODO: refactor + Ok(Box::new(mac::MacInjector::new())) +} + +#[cfg(target_os = "linux")] +pub fn create_ui(options: UIOptions) -> Result<(Box, Box)> { + // TODO: here we could avoid panicking and instead return a good result + let (remote, eventloop) = linux::create(linux::LinuxUIOptions { + notification_icon_path: options.notification_icon_path.expect("missing notification icon path") + }); + Ok((Box::new(remote), Box::new(eventloop))) +} \ No newline at end of file diff --git a/espanso-ui/src/linux/mod.rs b/espanso-ui/src/linux/mod.rs index 0781573..66a28e4 100644 --- a/espanso-ui/src/linux/mod.rs +++ b/espanso-ui/src/linux/mod.rs @@ -3,6 +3,8 @@ use notify_rust::Notification; use std::sync::mpsc; use std::sync::mpsc::{Receiver, Sender}; +use crate::{UIEventLoop, UIRemote}; + pub struct LinuxUIOptions { pub notification_icon_path: String, } @@ -30,8 +32,14 @@ impl LinuxRemote { pub fn stop(&self) -> anyhow::Result<()> { Ok(self.tx.send(())?) } +} - pub fn show_notification(&self, message: &str) { +impl UIRemote for LinuxRemote { + fn update_tray_icon(&self, _: crate::icons::TrayIcon) { + // NOOP on linux + } + + fn show_notification(&self, message: &str) { if let Err(error) = Notification::new() .summary("Espanso") .body(message) @@ -41,6 +49,10 @@ impl LinuxRemote { error!("Unable to show notification: {}", error); } } + + fn show_context_menu(&self, _: &crate::menu::Menu) { + // NOOP on linux + } } pub struct LinuxEventLoop { @@ -51,12 +63,14 @@ impl LinuxEventLoop { pub fn new(rx: Receiver<()>) -> Self { Self { rx } } +} - pub fn initialize(&self) { +impl UIEventLoop for LinuxEventLoop { + fn initialize(&mut self) { // NOOP on linux } - pub fn run(&self) { + fn run(&self, _: crate::UIEventCallback) { // We don't run an event loop on Linux as there is no tray icon or application window needed. // Thad said, we still need a way to block this method, and thus we use a channel self.rx.recv().expect("Unable to block the LinuxEventLoop"); diff --git a/espanso-ui/src/win32/mod.rs b/espanso-ui/src/win32/mod.rs index eab5710..8f9e0d9 100644 --- a/espanso-ui/src/win32/mod.rs +++ b/espanso-ui/src/win32/mod.rs @@ -110,8 +110,6 @@ pub fn create(options: Win32UIOptions) -> (Win32Remote, Win32EventLoop) { (remote, eventloop) } -pub type Win32UIEventCallback = Box; - pub struct Win32EventLoop { handle: Arc>, diff --git a/espanso/Cargo.toml b/espanso/Cargo.toml index 13fd83e..ffb32cd 100644 --- a/espanso/Cargo.toml +++ b/espanso/Cargo.toml @@ -8,6 +8,11 @@ readme = "README.md" homepage = "https://github.com/federico-terzi/espanso" edition = "2018" +[features] +# If the wayland feature is enabled, all X11 dependencies will be dropped +# and only EVDEV-based methods will be supported. +wayland = ["espanso-detect/wayland", "espanso-inject/wayland"] + [dependencies] espanso-detect = { path = "../espanso-detect" } espanso-ui = { path = "../espanso-ui" } diff --git a/espanso/src/main.rs b/espanso/src/main.rs index b66edcc..dd9efa7 100644 --- a/espanso/src/main.rs +++ b/espanso/src/main.rs @@ -1,6 +1,6 @@ use std::time::Duration; -use espanso_detect::event::{InputEvent, Status}; +use espanso_detect::{event::{InputEvent, Status}, get_source}; use espanso_inject::{get_injector, Injector, keys}; use espanso_ui::{event::UIEvent::*, icons::TrayIcon, menu::*}; use simplelog::{CombinedLogger, Config, LevelFilter, TermLogger, TerminalMode}; @@ -48,18 +48,17 @@ fn main() { // show_icon: true, // icon_paths: &icon_paths, // }); - let (remote, mut eventloop) = espanso_ui::linux::create(espanso_ui::linux::LinuxUIOptions { - notification_icon_path: r"C:\Users\Freddy\Insync\Development\Espanso\Images\icongreensmall.png".to_string(), - }); + let (remote, mut eventloop) = espanso_ui::create_ui(espanso_ui::UIOptions { + notification_icon_path: Some(r"C:\Users\Freddy\Insync\Development\Espanso\Images\icongreensmall.png".to_string()), + ..Default::default() + }).unwrap(); eventloop.initialize(); let handle = std::thread::spawn(move || { let injector = get_injector(Default::default()).unwrap(); - //let mut source = espanso_detect::win32::Win32Source::new(); - let mut source = espanso_detect::x11::X11Source::new(); - //let mut source = espanso_detect::mac::CocoaSource::new(); - source.initialize(); + let mut source = get_source(Default::default()).unwrap(); + source.initialize().unwrap(); source.eventloop(Box::new(move |event: InputEvent| { println!("ev {:?}", event); match event { @@ -77,30 +76,29 @@ fn main() { })); }); - eventloop.run(); - // eventloop.run(Box::new(move |event| { - // println!("ui {:?}", event); - // let menu = Menu::from(vec![ - // MenuItem::Simple(SimpleMenuItem::new("open", "Open")), - // MenuItem::Separator, - // MenuItem::Sub(SubMenuItem::new( - // "Sub", - // vec![ - // MenuItem::Simple(SimpleMenuItem::new("sub1", "Sub 1")), - // MenuItem::Simple(SimpleMenuItem::new("sub2", "Sub 2")), - // ], - // )), - // ]) - // .unwrap(); - // match event { - // TrayIconClick => { - // remote.show_context_menu(&menu); - // } - // ContextMenuClick(raw_id) => { - // //remote.update_tray_icon(TrayIcon::Disabled); - // remote.show_notification("Hello there!"); - // println!("item {:?}", menu.get_item_id(raw_id)); - // } - // } - // })); + eventloop.run(Box::new(move |event| { + println!("ui {:?}", event); + let menu = Menu::from(vec![ + MenuItem::Simple(SimpleMenuItem::new("open", "Open")), + MenuItem::Separator, + MenuItem::Sub(SubMenuItem::new( + "Sub", + vec![ + MenuItem::Simple(SimpleMenuItem::new("sub1", "Sub 1")), + MenuItem::Simple(SimpleMenuItem::new("sub2", "Sub 2")), + ], + )), + ]) + .unwrap(); + match event { + TrayIconClick => { + remote.show_context_menu(&menu); + } + ContextMenuClick(raw_id) => { + //remote.update_tray_icon(TrayIcon::Disabled); + remote.show_notification("Hello there!"); + println!("item {:?}", menu.get_item_id(raw_id)); + } + } + })); }