First steps in ipcmanager

This commit is contained in:
Federico Terzi 2019-09-14 12:19:11 +02:00
parent 7a680bf0b1
commit 041f53842f
10 changed files with 155 additions and 35 deletions

24
Cargo.lock generated
View File

@ -233,6 +233,7 @@ dependencies = [
"log 0.4.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_json 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)",
"serde_yaml 0.8.9 (registry+https://github.com/rust-lang/crates.io-index)",
"simplelog 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)",
"tempfile 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
@ -294,6 +295,11 @@ dependencies = [
"wasi 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "itoa"
version = "0.4.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "lazy_static"
version = "1.4.0"
@ -520,6 +526,11 @@ name = "rustc-demangle"
version = "0.1.16"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "ryu"
version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "serde"
version = "1.0.99"
@ -538,6 +549,16 @@ dependencies = [
"syn 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "serde_json"
version = "1.0.40"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"itoa 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)",
"ryu 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
"serde 1.0.99 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "serde_yaml"
version = "0.8.9"
@ -747,6 +768,7 @@ dependencies = [
"checksum fs2 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "9564fc758e15025b46aa6643b1b77d047d1a56a1aea6e01002ac0c7026876213"
"checksum fuchsia-cprng 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "a06f77d526c1a601b7c4cdd98f54b5eaabffc14d5f2f0296febdc7f357c6d3ba"
"checksum getrandom 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)" = "473a1265acc8ff1e808cd0a1af8cee3c2ee5200916058a2ca113c29f2d903571"
"checksum itoa 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)" = "501266b7edd0174f8530248f87f99c88fbe60ca4ef3dd486835b8d8d53136f7f"
"checksum lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
"checksum libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)" = "34fcd2c08d2f832f376f4173a231990fa5aef4e99fb569867318a227ef4c06ba"
"checksum linked-hash-map 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "ae91b68aebc4ddb91978b11a1b02ddd8602a05ec19002801c5666000e05e0f83"
@ -777,8 +799,10 @@ dependencies = [
"checksum remove_dir_all 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "4a83fa3702a688b9359eccba92d153ac33fd2e8462f9e0e3fdf155239ea7792e"
"checksum rust-argon2 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "4ca4eaef519b494d1f2848fc602d18816fed808a981aedf4f1f00ceb7c9d32cf"
"checksum rustc-demangle 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)" = "4c691c0e608126e00913e33f0ccf3727d5fc84573623b8d65b2df340b5201783"
"checksum ryu 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c92464b447c0ee8c4fb3824ecc8383b81717b9f1e74ba2e72540aef7b9f82997"
"checksum serde 1.0.99 (registry+https://github.com/rust-lang/crates.io-index)" = "fec2851eb56d010dc9a21b89ca53ee75e6528bab60c11e89d38390904982da9f"
"checksum serde_derive 1.0.99 (registry+https://github.com/rust-lang/crates.io-index)" = "cb4dc18c61206b08dc98216c98faa0232f4337e1e1b8574551d5bad29ea1b425"
"checksum serde_json 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)" = "051c49229f282f7c6f3813f8286cc1e3323e8051823fce42c7ea80fe13521704"
"checksum serde_yaml 0.8.9 (registry+https://github.com/rust-lang/crates.io-index)" = "38b08a9a90e5260fe01c6480ec7c811606df6d3a660415808c3c3fa8ed95b582"
"checksum simplelog 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ebbe8c881061cce7ee205784634eda7a61922925e7cc2833188467d3a560e027"
"checksum strsim 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a"

View File

@ -16,6 +16,7 @@ log = "0.4.8"
simplelog = "0.7.1"
zip = "0.5.3"
fs2 = "0.4.3"
serde_json = "1.0.40"
[target.'cfg(unix)'.dependencies]
libc = "0.2.62"

View File

@ -108,7 +108,7 @@ extern fn icon_click_callback(_self: *mut c_void) {
unsafe {
let _self = _self as *mut MacContext;
let event = Event::Action(ActionEvent::IconClick);
let event = Event::Action(ActionType::IconClick);
(*_self).send_channel.send(event).unwrap();
}
}
@ -117,7 +117,7 @@ extern fn context_menu_click_callback(_self: *mut c_void, id: i32) {
unsafe {
let _self = _self as *mut MacContext;
let event = Event::Action(ActionEvent::ContextMenuClick(ActionType::from(id)));
let event = Event::Action(ActionType::from(id));
(*_self).send_channel.send(event).unwrap();
}
}

View File

@ -127,7 +127,7 @@ extern fn icon_click_callback(_self: *mut c_void) {
unsafe {
let _self = _self as *mut WindowsContext;
let event = Event::Action(ActionEvent::IconClick);
let event = Event::Action(ActionType::IconClick);
(*_self).send_channel.send(event).unwrap();
}
}
@ -137,7 +137,7 @@ extern fn context_menu_click_callback(_self: *mut c_void, id: i32) {
unsafe {
let _self = _self as *mut WindowsContext;
let event = Event::Action(ActionEvent::ContextMenuClick(ActionType::from(id)));
let event = Event::Action(ActionType::from(id));
(*_self).send_channel.send(event).unwrap();
}
}

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, ActionEvent, ActionType};
use crate::event::{ActionEventReceiver, ActionType};
use std::cell::RefCell;
use std::process::exit;
@ -114,20 +114,16 @@ impl <'a, S: KeyboardManager, C: ClipboardManager, M: ConfigManager<'a>, U: UIMa
impl <'a, S: KeyboardManager, C: ClipboardManager,
M: ConfigManager<'a>, U: UIManager> ActionEventReceiver for Engine<'a, S, C, M, U>{
fn on_action_event(&self, e: ActionEvent) {
fn on_action_event(&self, e: ActionType) {
match e {
ActionEvent::IconClick => {
ActionType::IconClick => {
self.ui_manager.show_menu(self.build_menu());
},
ActionEvent::ContextMenuClick(id) => {
match id {
ActionType::Exit => {
info!("Terminating expanso from the context menu");
exit(0);
},
_ => {}
}
}
ActionType::Exit => {
info!("Terminating espanso.");
exit(0);
},
_ => {}
}
}
}

View File

@ -4,21 +4,16 @@ use serde::{Serialize, Deserialize};
#[derive(Debug, Clone)]
pub enum Event {
Action(ActionEvent),
Action(ActionType),
Key(KeyEvent)
}
#[derive(Debug, Clone)]
pub enum ActionEvent {
IconClick,
ContextMenuClick(ActionType)
}
#[derive(Debug, Clone)]
pub enum ActionType {
Noop = 0,
Toggle = 1,
Exit = 2,
IconClick = 3,
}
impl From<i32> for ActionType {
@ -26,6 +21,7 @@ impl From<i32> for ActionType {
match id {
1 => ActionType::Toggle,
2 => ActionType::Exit,
3 => ActionType::IconClick,
_ => ActionType::Noop,
}
}
@ -59,5 +55,5 @@ pub trait KeyEventReceiver {
}
pub trait ActionEventReceiver {
fn on_action_event(&self, e: ActionEvent);
fn on_action_event(&self, e: ActionType);
}

View File

@ -19,6 +19,7 @@ use crate::event::manager::{DefaultEventManager, EventManager};
use crate::matcher::scrolling::ScrollingMatcher;
use crate::system::SystemManager;
use crate::ui::UIManager;
use crate::protocol::*;
mod ui;
mod event;
@ -29,6 +30,7 @@ mod system;
mod context;
mod matcher;
mod keyboard;
mod protocol;
mod clipboard;
const VERSION: &'static str = env!("CARGO_PKG_VERSION");
@ -145,12 +147,15 @@ fn daemon_main(config_set: ConfigSet) {
let (send_channel, receive_channel) = mpsc::channel();
let context = context::new(send_channel);
let context = context::new(send_channel.clone());
thread::spawn(move || {
daemon_background(receive_channel, config_set);
});
let ipc_manager = protocol::get_ipc_manager(send_channel.clone());
ipc_manager.start_server();
context.eventloop();
}
@ -257,7 +262,7 @@ fn detect_main() {
println!("==> Title: '{}'", curr_title);
println!("==> Class: '{}'", curr_class);
println!("==> Executable: '{}'", curr_exec);
println!("");
println!();
}
last_title = curr_title;

View File

@ -1,6 +1,6 @@
use crate::matcher::{Match, MatchReceiver};
use std::cell::RefCell;
use crate::event::{KeyModifier, ActionEventReceiver, ActionEvent, ActionType};
use crate::event::{KeyModifier, ActionEventReceiver, ActionType};
use crate::config::ConfigManager;
use crate::event::KeyModifier::BACKSPACE;
use std::time::SystemTime;
@ -123,15 +123,10 @@ impl <'a, R: MatchReceiver, M: ConfigManager<'a>> super::Matcher for ScrollingMa
}
impl <'a, R: MatchReceiver, M: ConfigManager<'a>> ActionEventReceiver for ScrollingMatcher<'a, R, M> {
fn on_action_event(&self, e: ActionEvent) {
fn on_action_event(&self, e: ActionType) {
match e {
ActionEvent::ContextMenuClick(action_type) => {
match action_type {
ActionType::Toggle => {
self.toggle();
},
_ => {}
}
ActionType::Toggle => {
self.toggle();
},
_ => {}
}

40
src/protocol/mod.rs Normal file
View File

@ -0,0 +1,40 @@
use serde::{Deserialize, Serialize};
use serde_json::Result;
use std::sync::mpsc::Sender;
use crate::event::Event;
use crate::event::Event::*;
use crate::event::ActionType;
use crate::event::ActionType::*;
#[cfg(target_os = "windows")]
mod windows;
#[cfg(not(target_os = "windows"))]
mod unix;
pub trait IPCManager {
fn start_server(&self);
}
#[derive(Serialize, Deserialize, Debug)]
pub struct IPCCommand {
id: String,
payload: String,
}
impl IPCCommand {
fn to_event(&self) -> Option<Event> {
match self.id.as_ref() {
"exit" => {
Some(Event::Action(ActionType::Exit))
},
_ => None
}
}
}
// UNIX IMPLEMENTATION
#[cfg(not(target_os = "windows"))]
pub fn get_ipc_manager(event_channel: Sender<Event>) -> impl IPCManager {
unix::UnixIPCManager::new(event_channel)
}

63
src/protocol/unix.rs Normal file
View File

@ -0,0 +1,63 @@
use std::io::{BufRead, BufReader, Read};
use std::os::unix::net::{UnixStream,UnixListener};
use std::thread;
use log::{info, error};
use std::sync::mpsc::Sender;
use super::IPCCommand;
use crate::context;
use crate::context::get_data_dir;
use crate::event::*;
const UNIX_SOCKET_NAME : &str = "espanso.sock";
pub struct UnixIPCManager {
event_channel: Sender<Event>,
}
impl UnixIPCManager {
pub fn new(event_channel: Sender<Event>) -> UnixIPCManager {
UnixIPCManager{event_channel}
}
}
impl super::IPCManager for UnixIPCManager {
fn start_server(&self) {
std::thread::spawn(|| {
let espanso_dir = context::get_data_dir();
let unix_socket = espanso_dir.join(UNIX_SOCKET_NAME);
std::fs::remove_file(unix_socket.clone());
let listener = UnixListener::bind(unix_socket.clone()).expect("Can't bind to Unix Socket");
info!("Binded to IPC unix socket: {}", unix_socket.as_path().display());
for stream in listener.incoming() {
match stream {
Ok(stream) => {
let mut json_str= String::new();
let mut buf_reader = BufReader::new(stream);
buf_reader.read_to_string(&mut json_str);
let command : Result<IPCCommand, serde_json::Error> = serde_json::from_str(&json_str);
match command {
Ok(command) => {
let event = command.to_event();
if let Some(event) = event {
// TODO: send event to event channel
}
},
Err(e) => {
error!("Error deserializing JSON command: {}", e);
},
}
}
Err(err) => {
println!("Error: {}", err);
break;
}
}
}
});
}
}