From 1261a76bcd693a244830bb95afae0f0f34f09a22 Mon Sep 17 00:00:00 2001 From: Federico Terzi Date: Fri, 13 Sep 2019 11:55:42 +0200 Subject: [PATCH] Add macos context --- Cargo.lock | 72 ------------------------------ Cargo.toml | 3 -- native/libmacbridge/AppDelegate.mm | 7 +-- native/libmacbridge/bridge.h | 7 +-- native/libmacbridge/bridge.mm | 13 +++--- src/bridge/macos.rs | 9 ++-- src/config/mod.rs | 4 +- src/context/macos.rs | 70 +++++++++++++++++++++++++++++ src/context/mod.rs | 4 +- src/context/windows.rs | 8 ++-- src/engine.rs | 2 +- src/keyboard/macos.rs | 54 ---------------------- src/main.rs | 13 ++---- src/matcher/scrolling.rs | 2 +- src/ui/macos.rs | 10 +++-- 15 files changed, 109 insertions(+), 169 deletions(-) create mode 100644 src/context/macos.rs diff --git a/Cargo.lock b/Cargo.lock index 9033e91..800cedc 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -229,9 +229,6 @@ dependencies = [ "cmake 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)", "dirs 2.0.2 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", - "num 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "num-derive 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)", - "num-traits 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", "regex 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.99 (registry+https://github.com/rust-lang/crates.io-index)", "serde_yaml 0.8.9 (registry+https://github.com/rust-lang/crates.io-index)", @@ -327,48 +324,6 @@ name = "nodrop" version = "0.1.13" source = "registry+https://github.com/rust-lang/crates.io-index" -[[package]] -name = "num" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "num-bigint 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", - "num-complex 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", - "num-integer 0.1.41 (registry+https://github.com/rust-lang/crates.io-index)", - "num-iter 0.1.39 (registry+https://github.com/rust-lang/crates.io-index)", - "num-rational 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "num-traits 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "num-bigint" -version = "0.2.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "autocfg 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", - "num-integer 0.1.41 (registry+https://github.com/rust-lang/crates.io-index)", - "num-traits 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "num-complex" -version = "0.2.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "autocfg 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", - "num-traits 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "num-derive" -version = "0.2.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 0.15.44 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "num-integer" version = "0.1.41" @@ -378,27 +333,6 @@ dependencies = [ "num-traits 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "num-iter" -version = "0.1.39" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "autocfg 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", - "num-integer 0.1.41 (registry+https://github.com/rust-lang/crates.io-index)", - "num-traits 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "num-rational" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "autocfg 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", - "num-bigint 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", - "num-integer 0.1.41 (registry+https://github.com/rust-lang/crates.io-index)", - "num-traits 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "num-traits" version = "0.2.8" @@ -808,13 +742,7 @@ dependencies = [ "checksum memchr 2.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "88579771288728879b57485cc7d6b07d648c9f0141eb955f8ab7f9d45394468e" "checksum miniz_oxide 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7108aff85b876d06f22503dcce091e29f76733b2bfdd91eebce81f5e68203a10" "checksum nodrop 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)" = "2f9667ddcc6cc8a43afc9b7917599d7216aa09c463919ea32c59ed6cac8bc945" -"checksum num 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "cf4825417e1e1406b3782a8ce92f4d53f26ec055e3622e1881ca8e9f5f9e08db" -"checksum num-bigint 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "f9c3f34cdd24f334cb265d9bf8bfa8a241920d026916785747a92f0e55541a1a" -"checksum num-complex 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "fcb0cf31fb3ff77e6d2a6ebd6800df7fdcd106f2ad89113c9130bcd07f93dffc" -"checksum num-derive 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)" = "eafd0b45c5537c3ba526f79d3e75120036502bebacbb3f3220914067ce39dbf2" "checksum num-integer 0.1.41 (registry+https://github.com/rust-lang/crates.io-index)" = "b85e541ef8255f6cf42bbfe4ef361305c6c135d10919ecc26126c4e5ae94bc09" -"checksum num-iter 0.1.39 (registry+https://github.com/rust-lang/crates.io-index)" = "76bd5272412d173d6bf9afdf98db8612bbabc9a7a830b7bfc9c188911716132e" -"checksum num-rational 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "f2885278d5fe2adc2f75ced642d52d879bffaceb5a2e0b1d4309ffdfb239b454" "checksum num-traits 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "6ba9a427cfca2be13aa6f6403b0b7e7368fe982bfa16fccc450ce74c46cd9b32" "checksum podio 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "780fb4b6698bbf9cf2444ea5d22411cef2953f0824b98f33cf454ec5615645bd" "checksum ppv-lite86 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)" = "e3cbf9f658cdb5000fcf6f362b8ea2ba154b9f146a61c7a20d647034c6b6561b" diff --git a/Cargo.toml b/Cargo.toml index bf7b913..4c772b3 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -15,9 +15,6 @@ regex = "1.3.1" log = "0.4.8" simplelog = "0.7.1" zip = "0.5.3" -num = "0.2.0" -num-traits = "0.2.8" -num-derive = "0.2.5" [dev-dependencies] tempfile = "3.1.0" diff --git a/native/libmacbridge/AppDelegate.mm b/native/libmacbridge/AppDelegate.mm index 92b19a7..6d1cdd1 100644 --- a/native/libmacbridge/AppDelegate.mm +++ b/native/libmacbridge/AppDelegate.mm @@ -10,9 +10,6 @@ BOOL checkAccessibility() return AXIsProcessTrustedWithOptions((__bridge CFDictionaryRef)opts); } -KeypressCallback keypress_callback; -void * interceptor_instance; - - (void)applicationDidFinishLaunching:(NSNotification *)aNotification { if (checkAccessibility()) { @@ -30,7 +27,7 @@ void * interceptor_instance; const char * chars = [event.characters UTF8String]; int len = event.characters.length; - keypress_callback(interceptor_instance, chars, len, 0, event.keyCode); + keypress_callback(context_instance, chars, len, 0, event.keyCode); //NSLog(@"keydown: %@, %d", event.characters, event.keyCode); }else{ // Because this event is triggered for both the press and release of a modifier, trigger the callback @@ -38,7 +35,7 @@ void * interceptor_instance; if (([event modifierFlags] & (NSEventModifierFlagShift | NSEventModifierFlagCommand | NSEventModifierFlagControl | NSEventModifierFlagOption)) == 0) { - keypress_callback(interceptor_instance, NULL, 0, 1, event.keyCode); + keypress_callback(context_instance, NULL, 0, 1, event.keyCode); } //NSLog(@"keydown: %d", event.keyCode); diff --git a/native/libmacbridge/bridge.h b/native/libmacbridge/bridge.h index 83f6af7..be939a0 100644 --- a/native/libmacbridge/bridge.h +++ b/native/libmacbridge/bridge.h @@ -5,10 +5,12 @@ extern "C" { +extern void * context_instance; + /* * Initialize the AppDelegate and check for accessibility permissions */ -int32_t initialize(); +int32_t initialize(void * context); /* * Start the event loop indefinitely. Blocking call. @@ -22,12 +24,11 @@ int32_t eventloop(); typedef void (*KeypressCallback)(void * self, const char *buffer, int32_t len, int32_t is_modifier, int32_t key_code); extern KeypressCallback keypress_callback; -extern void * interceptor_instance; /* * Register the callback that will be called when a keypress was made */ -void register_keypress_callback(void *self, KeypressCallback callback); +void register_keypress_callback(KeypressCallback callback); /* * Type the given string by using the CGEventKeyboardSetUnicodeString call diff --git a/native/libmacbridge/bridge.mm b/native/libmacbridge/bridge.mm index 156971b..acc594a 100644 --- a/native/libmacbridge/bridge.mm +++ b/native/libmacbridge/bridge.mm @@ -9,18 +9,21 @@ extern "C" { #include +KeypressCallback keypress_callback; +void * context_instance; -void register_keypress_callback(void * self, KeypressCallback callback) { - keypress_callback = callback; - interceptor_instance = self; -} +int32_t initialize(void * context) { + context_instance = context; -int32_t initialize() { AppDelegate *delegate = [[AppDelegate alloc] init]; NSApplication * application = [NSApplication sharedApplication]; [application setDelegate:delegate]; } +void register_keypress_callback(KeypressCallback callback) { + keypress_callback = callback; +} + int32_t eventloop() { [NSApp run]; } diff --git a/src/bridge/macos.rs b/src/bridge/macos.rs index 9fc5374..6bd6bc2 100644 --- a/src/bridge/macos.rs +++ b/src/bridge/macos.rs @@ -3,6 +3,9 @@ use std::os::raw::{c_void, c_char}; #[allow(improper_ctypes)] #[link(name="macbridge", kind="static")] extern { + pub fn initialize(s: *const c_void); + pub fn eventloop(); + // System pub fn get_active_app_bundle(buffer: *mut c_char, size: i32) -> i32; pub fn get_active_app_identifier(buffer: *mut c_char, size: i32) -> i32; @@ -12,11 +15,9 @@ extern { pub fn set_clipboard(text: *const c_char) -> i32; // Keyboard - pub fn register_keypress_callback(s: *const c_void, - cb: extern fn(_self: *mut c_void, *const u8, + pub fn register_keypress_callback(cb: extern fn(_self: *mut c_void, *const u8, i32, i32, i32)); - pub fn initialize(); - pub fn eventloop(); + pub fn send_string(string: *const c_char); pub fn send_vkey(vk: i32); pub fn delete_string(count: i32); diff --git a/src/config/mod.rs b/src/config/mod.rs index ced9246..91228e6 100644 --- a/src/config/mod.rs +++ b/src/config/mod.rs @@ -1,15 +1,13 @@ extern crate dirs; use std::path::{Path, PathBuf}; -use std::{fs, io}; +use std::{fs}; use crate::matcher::Match; use std::fs::{File, create_dir_all}; use std::io::Read; use serde::{Serialize, Deserialize}; use crate::event::KeyModifier; -use crate::system::SystemManager; use std::collections::HashSet; -use std::process::exit; use log::{debug, info, warn, error}; use std::fmt; use std::error::Error; diff --git a/src/context/macos.rs b/src/context/macos.rs new file mode 100644 index 0000000..6cec64f --- /dev/null +++ b/src/context/macos.rs @@ -0,0 +1,70 @@ +use std::sync::mpsc::Sender; +use std::os::raw::c_void; +use crate::bridge::macos::*; +use crate::event::{Event, KeyEvent, KeyModifier}; +use crate::event::KeyModifier::*; + +pub struct MacContext { + pub send_channel: Sender +} + +impl MacContext { + pub fn new(send_channel: Sender) -> Box { + let context = Box::new(MacContext { + send_channel + }); + + unsafe { + let context_ptr = &*context as *const MacContext as *const c_void; + + register_keypress_callback(keypress_callback); + + initialize(context_ptr); + } + + context + } +} + +impl super::Context for MacContext { + fn eventloop(&self) { + unsafe { + eventloop(); + } + } +} + +// Native bridge code + +extern fn keypress_callback(_self: *mut c_void, raw_buffer: *const u8, len: i32, + is_modifier: i32, key_code: i32) { + unsafe { + let _self = _self as *mut MacContext; + + if is_modifier == 0 { // Char event + // Convert the received buffer to a character + let buffer = std::slice::from_raw_parts(raw_buffer, len as usize); + let r = String::from_utf8_lossy(buffer).chars().nth(0); + + // Send the char through the channel + if let Some(c) = r { + let event = Event::Key(KeyEvent::Char(c)); + (*_self).send_channel.send(event).unwrap(); + } + }else{ // Modifier event + let modifier: Option = match key_code { + 0x37 => Some(META), + 0x38 => Some(SHIFT), + 0x3A => Some(ALT), + 0x3B => Some(CTRL), + 0x33 => Some(BACKSPACE), + _ => None, + }; + + if let Some(modifier) = modifier { + let event = Event::Key(KeyEvent::Modifier(modifier)); + (*_self).send_channel.send(event).unwrap(); + } + } + } +} \ No newline at end of file diff --git a/src/context/mod.rs b/src/context/mod.rs index 5bce035..39db451 100644 --- a/src/context/mod.rs +++ b/src/context/mod.rs @@ -17,8 +17,8 @@ pub trait Context { // MAC IMPLEMENTATION #[cfg(target_os = "macos")] -pub fn new(send_channel: Sender) -> Box { // TODO - macos::MacUIManager::new() +pub fn new(send_channel: Sender) -> Box { + macos::MacContext::new(send_channel) } // LINUX IMPLEMENTATION diff --git a/src/context/windows.rs b/src/context/windows.rs index c62e821..c918d01 100644 --- a/src/context/windows.rs +++ b/src/context/windows.rs @@ -53,13 +53,13 @@ impl WindowsContext { let id = Arc::new(Mutex::new(0)); let send_channel = send_channel; - let manager = Box::new(WindowsContext{ + let context = Box::new(WindowsContext{ send_channel, id }); unsafe { - let manager_ptr = &*manager as *const WindowsContext as *const c_void; + let context_ptr = &*context as *const WindowsContext as *const c_void; // Register callbacks register_keypress_callback(keypress_callback); @@ -70,13 +70,13 @@ impl WindowsContext { let bmp_file_c = U16CString::from_str(bmp_icon).unwrap(); // Initialize the windows - let res = initialize(manager_ptr, ico_file_c.as_ptr(), bmp_file_c.as_ptr()); + let res = initialize(context_ptr, ico_file_c.as_ptr(), bmp_file_c.as_ptr()); if res != 1 { panic!("Can't initialize Windows context") } } - manager + context } } diff --git a/src/engine.rs b/src/engine.rs index 44dc3ab..e7a4538 100644 --- a/src/engine.rs +++ b/src/engine.rs @@ -5,7 +5,7 @@ use crate::config::BackendType; use crate::clipboard::ClipboardManager; use log::{info}; use crate::ui::{UIManager, MenuItem, MenuItemType}; -use crate::event::{ActionEventReceiver, Event, ActionEvent, ActionType}; +use crate::event::{ActionEventReceiver, ActionEvent, ActionType}; use std::cell::RefCell; pub struct Engine<'a, S: KeyboardSender, C: ClipboardManager, M: ConfigManager<'a>, diff --git a/src/keyboard/macos.rs b/src/keyboard/macos.rs index 86afb44..f842fea 100644 --- a/src/keyboard/macos.rs +++ b/src/keyboard/macos.rs @@ -1,29 +1,8 @@ use std::sync::mpsc; use std::os::raw::{c_char, c_void}; use std::ffi::CString; -use crate::keyboard::{KeyEvent, KeyModifier}; -use crate::keyboard::KeyModifier::*; use crate::bridge::macos::*; -#[repr(C)] -pub struct MacKeyboardInterceptor { - pub sender: mpsc::Sender -} - -impl super::KeyboardInterceptor for MacKeyboardInterceptor { - fn initialize(&self) { - unsafe { - let self_ptr = self as *const MacKeyboardInterceptor as *const c_void; - register_keypress_callback(self_ptr,keypress_callback); - initialize(); - } // TODO: check initialization return codes - } - - fn start(&self) { - unsafe { eventloop(); } - } -} - pub struct MacKeyboardSender { } @@ -52,37 +31,4 @@ impl super::KeyboardSender for MacKeyboardSender { fn delete_string(&self, count: i32) { unsafe {delete_string(count)} } -} - -// Native bridge code - -extern fn keypress_callback(_self: *mut c_void, raw_buffer: *const u8, len: i32, - is_modifier: i32, key_code: i32) { - unsafe { - let _self = _self as *mut MacKeyboardInterceptor; - - if is_modifier == 0 { // Char event - // Convert the received buffer to a character - let buffer = std::slice::from_raw_parts(raw_buffer, len as usize); - let r = String::from_utf8_lossy(buffer).chars().nth(0); - - // Send the char through the channel - if let Some(c) = r { - (*_self).sender.send(KeyEvent::Char(c)).unwrap(); - } - }else{ // Modifier event - let modifier: Option = match key_code { - 0x37 => Some(META), - 0x38 => Some(SHIFT), - 0x3A => Some(ALT), - 0x3B => Some(CTRL), - 0x33 => Some(BACKSPACE), - _ => None, - }; - - if let Some(modifier) = modifier { - (*_self).sender.send(KeyEvent::Modifier(modifier)).unwrap(); - } - } - } } \ No newline at end of file diff --git a/src/main.rs b/src/main.rs index c22093e..75ababc 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,18 +1,13 @@ -#[macro_use] -extern crate num_derive; - -use std::sync::{mpsc, Arc}; -use crate::matcher::Matcher; +use std::sync::{mpsc}; use crate::matcher::scrolling::ScrollingMatcher; use crate::engine::Engine; -use crate::clipboard::ClipboardManager; use crate::config::ConfigSet; use crate::config::runtime::RuntimeConfigManager; use crate::ui::UIManager; use crate::context::Context; use crate::event::*; use crate::event::manager::{EventManager, DefaultEventManager}; -use std::{thread, time}; +use std::{thread}; use clap::{App, Arg}; use std::path::Path; use std::sync::mpsc::Receiver; @@ -114,7 +109,7 @@ fn espanso_background(receive_channel: Receiver, config_set: ConfigSet) { let sender = keyboard::get_sender(); // TODO: rename manager - // TODO: change sender to move to reference + // TODO: change sender from move to reference let engine = Engine::new(sender, &clipboard_manager, &config_manager, @@ -126,7 +121,7 @@ fn espanso_background(receive_channel: Receiver, config_set: ConfigSet) { let event_manager = DefaultEventManager::new( receive_channel, vec!(&matcher), - vec!(&engine, &matcher), + vec!(&engine), ); event_manager.eventloop(); diff --git a/src/matcher/scrolling.rs b/src/matcher/scrolling.rs index 7fe8d04..fa74211 100644 --- a/src/matcher/scrolling.rs +++ b/src/matcher/scrolling.rs @@ -101,7 +101,7 @@ impl <'a, R: MatchReceiver, M: ConfigManager<'a>> super::Matcher for ScrollingMa let mut toggle_press_time = self.toggle_press_time.borrow_mut(); if let Ok(elapsed) = toggle_press_time.elapsed() { if elapsed.as_millis() < config.toggle_interval as u128 { - let mut is_enabled = self.is_enabled.borrow(); + let is_enabled = self.is_enabled.borrow(); if !*is_enabled { self.current_set_queue.borrow_mut().clear(); diff --git a/src/ui/macos.rs b/src/ui/macos.rs index bfe7c15..6605d1c 100644 --- a/src/ui/macos.rs +++ b/src/ui/macos.rs @@ -1,10 +1,10 @@ use std::fs::create_dir_all; use std::{fs, io}; -use std::io::{BufReader, Cursor}; -use zip::ZipArchive; -use log::{info, debug, error}; +use std::io::{Cursor}; +use log::{info, debug}; use std::path::PathBuf; use std::process::Command; +use crate::ui::MenuItem; const NOTIFY_HELPER_BINARY : &'static [u8] = include_bytes!("../res/mac/EspansoNotifyHelper.zip"); const DEFAULT_NOTIFICATION_DELAY : f64 = 1.5; @@ -23,6 +23,10 @@ impl super::UIManager for MacUIManager { .args(&["espanso", message, &DEFAULT_NOTIFICATION_DELAY.to_string()]) .spawn(); } + + fn show_menu(&self, menu: Vec) { + unimplemented!() + } } impl MacUIManager {