Add macos context

This commit is contained in:
Federico Terzi 2019-09-13 11:55:42 +02:00
parent a19b070fde
commit 1261a76bcd
15 changed files with 109 additions and 169 deletions

72
Cargo.lock generated
View File

@ -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"

View File

@ -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"

View File

@ -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);

View File

@ -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

View File

@ -9,18 +9,21 @@ extern "C" {
#include <vector>
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];
}

View File

@ -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);

View File

@ -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;

70
src/context/macos.rs Normal file
View File

@ -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<Event>
}
impl MacContext {
pub fn new(send_channel: Sender<Event>) -> Box<MacContext> {
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<KeyModifier> = 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();
}
}
}
}

View File

@ -17,8 +17,8 @@ pub trait Context {
// MAC IMPLEMENTATION
#[cfg(target_os = "macos")]
pub fn new(send_channel: Sender<Event>) -> Box<dyn Context> { // TODO
macos::MacUIManager::new()
pub fn new(send_channel: Sender<Event>) -> Box<dyn Context> {
macos::MacContext::new(send_channel)
}
// LINUX IMPLEMENTATION

View File

@ -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
}
}

View File

@ -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>,

View File

@ -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<KeyEvent>
}
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 {
}
@ -53,36 +32,3 @@ impl super::KeyboardSender for MacKeyboardSender {
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<KeyModifier> = 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();
}
}
}
}

View File

@ -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<Event>, 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<Event>, config_set: ConfigSet) {
let event_manager = DefaultEventManager::new(
receive_channel,
vec!(&matcher),
vec!(&engine, &matcher),
vec!(&engine),
);
event_manager.eventloop();

View File

@ -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();

View File

@ -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<MenuItem>) {
unimplemented!()
}
}
impl MacUIManager {