Implement Auto-reload on Windows. #239
This commit is contained in:
parent
d41366b7c3
commit
56b89432d3
|
@ -32,6 +32,7 @@ use regex::{Regex};
|
|||
use std::sync::Arc;
|
||||
use std::sync::atomic::AtomicBool;
|
||||
use std::sync::atomic::Ordering::Release;
|
||||
use crate::protocol::{Service, IPCCommand, send_command_or_warn};
|
||||
|
||||
pub struct Engine<'a, S: KeyboardManager, C: ClipboardManager, M: ConfigManager<'a>,
|
||||
U: UIManager, R: Renderer> {
|
||||
|
@ -77,6 +78,18 @@ impl <'a, S: KeyboardManager, C: ClipboardManager, M: ConfigManager<'a>, U: UIMa
|
|||
item_id: ActionType::Toggle as i32,
|
||||
});
|
||||
|
||||
menu.push(MenuItem{
|
||||
item_type: MenuItemType::Separator,
|
||||
item_name: "".to_owned(),
|
||||
item_id: 998,
|
||||
});
|
||||
|
||||
menu.push(MenuItem{
|
||||
item_type: MenuItemType::Button,
|
||||
item_name: "Reload configs".to_owned(),
|
||||
item_id: ActionType::RestartWorker as i32,
|
||||
});
|
||||
|
||||
menu.push(MenuItem{
|
||||
item_type: MenuItemType::Separator,
|
||||
item_name: "".to_owned(),
|
||||
|
@ -332,15 +345,22 @@ impl <'a, S: KeyboardManager, C: ClipboardManager,
|
|||
M: ConfigManager<'a>, U: UIManager, R: Renderer> ActionEventReceiver for Engine<'a, S, C, M, U, R>{
|
||||
|
||||
fn on_action_event(&self, e: ActionType) {
|
||||
let config = self.config_manager.default_config();
|
||||
match e {
|
||||
ActionType::IconClick => {
|
||||
self.ui_manager.show_menu(self.build_menu());
|
||||
},
|
||||
ActionType::Exit => {
|
||||
ActionType::ExitWorker => {
|
||||
info!("terminating worker process");
|
||||
self.ui_manager.cleanup();
|
||||
exit(0);
|
||||
},
|
||||
ActionType::Exit => {
|
||||
send_command_or_warn(Service::Daemon, config.clone(), IPCCommand::exit());
|
||||
},
|
||||
ActionType::RestartWorker => {
|
||||
send_command_or_warn(Service::Daemon, config.clone(), IPCCommand::restart_worker());
|
||||
},
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -38,6 +38,7 @@ pub enum ActionType {
|
|||
Enable = 4,
|
||||
Disable = 5,
|
||||
RestartWorker = 6,
|
||||
ExitWorker = 7,
|
||||
}
|
||||
|
||||
impl From<i32> for ActionType {
|
||||
|
@ -49,6 +50,7 @@ impl From<i32> for ActionType {
|
|||
4 => ActionType::Enable,
|
||||
5 => ActionType::Disable,
|
||||
6 => ActionType::RestartWorker,
|
||||
7 => ActionType::ExitWorker,
|
||||
_ => ActionType::Noop,
|
||||
}
|
||||
}
|
||||
|
|
54
src/main.rs
54
src/main.rs
|
@ -382,11 +382,7 @@ fn daemon_main(config_set: ConfigSet) {
|
|||
match event {
|
||||
Event::Action(ActionType::RestartWorker) => {
|
||||
// Terminate the worker process
|
||||
let ipc_client = protocol::get_ipc_client(Service::Worker, config_set.default.clone());
|
||||
ipc_client.send_command(IPCCommand {
|
||||
id: "exit".to_owned(),
|
||||
payload: "".to_owned(),
|
||||
});
|
||||
send_command_or_warn(Service::Worker, config_set.default.clone(), IPCCommand::exit_worker());
|
||||
|
||||
std::thread::sleep(Duration::from_millis(500));
|
||||
|
||||
|
@ -394,11 +390,7 @@ fn daemon_main(config_set: ConfigSet) {
|
|||
crate::process::spawn_process(&espanso_path.to_string_lossy().to_string(), &vec!("worker".to_owned(), "--reload".to_owned()));
|
||||
},
|
||||
Event::Action(ActionType::Exit) => {
|
||||
let ipc_client = protocol::get_ipc_client(Service::Worker, config_set.default.clone());
|
||||
ipc_client.send_command(IPCCommand {
|
||||
id: "exit".to_owned(),
|
||||
payload: "".to_owned(),
|
||||
});
|
||||
send_command_or_warn(Service::Worker, config_set.default.clone(), IPCCommand::exit_worker());
|
||||
|
||||
std::thread::sleep(Duration::from_millis(200));
|
||||
|
||||
|
@ -408,9 +400,8 @@ fn daemon_main(config_set: ConfigSet) {
|
|||
_ => {
|
||||
// Forward the command to the worker
|
||||
let command = IPCCommand::from(event);
|
||||
let ipc_client = protocol::get_ipc_client(Service::Worker, config_set.default.clone());
|
||||
if let Some(command) = command {
|
||||
ipc_client.send_command(command);
|
||||
send_command_or_warn(Service::Worker, config_set.default.clone(), command);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -431,7 +422,7 @@ fn watcher_background(sender: Sender<Event>) {
|
|||
let config_path = crate::context::get_config_dir();
|
||||
watcher.watch(&config_path, RecursiveMode::Recursive).expect("unable to start watcher");
|
||||
|
||||
info!("watching for changes in path: {:?}", config_path);
|
||||
info!("watching for changes in path: {}", config_path.to_string_lossy());
|
||||
|
||||
|
||||
loop {
|
||||
|
@ -558,7 +549,7 @@ fn worker_background(receive_channel: Receiver<Event>, config_set: ConfigSet, is
|
|||
vec!(&engine),
|
||||
);
|
||||
|
||||
info!("espanso is running!");
|
||||
info!("worker is running!");
|
||||
|
||||
event_manager.eventloop();
|
||||
}
|
||||
|
@ -742,17 +733,7 @@ fn stop_main(config_set: ConfigSet) {
|
|||
exit(3);
|
||||
}
|
||||
|
||||
let res = send_command(Service::Daemon, config_set.default, IPCCommand{
|
||||
id: "exit".to_owned(),
|
||||
payload: "".to_owned(),
|
||||
});
|
||||
|
||||
if let Err(e) = res {
|
||||
println!("{}", e);
|
||||
exit(1);
|
||||
}else{
|
||||
exit(0);
|
||||
}
|
||||
send_command_or_warn(Service::Daemon, config_set.default, IPCCommand::exit());
|
||||
}
|
||||
|
||||
/// Kill the daemon if running and start it again
|
||||
|
@ -761,10 +742,7 @@ fn restart_main(config_set: ConfigSet) {
|
|||
let lock_file = acquire_lock();
|
||||
if lock_file.is_none() {
|
||||
// Terminate the current espanso daemon
|
||||
send_command(Service::Daemon, config_set.default.clone(), IPCCommand {
|
||||
id: "exit".to_owned(),
|
||||
payload: "".to_owned(),
|
||||
});
|
||||
send_command_or_warn(Service::Daemon, config_set.default.clone(), IPCCommand::exit());
|
||||
}else{
|
||||
release_lock(lock_file.unwrap());
|
||||
}
|
||||
|
@ -859,10 +837,7 @@ fn detect_main() {
|
|||
/// Send the given command to the espanso daemon
|
||||
fn cmd_main(config_set: ConfigSet, matches: &ArgMatches) {
|
||||
let command = if matches.subcommand_matches("exit").is_some() {
|
||||
Some(IPCCommand {
|
||||
id: String::from("exit"),
|
||||
payload: String::from(""),
|
||||
})
|
||||
Some(IPCCommand::exit())
|
||||
}else if matches.subcommand_matches("toggle").is_some() {
|
||||
Some(IPCCommand {
|
||||
id: String::from("toggle"),
|
||||
|
@ -883,23 +858,12 @@ fn cmd_main(config_set: ConfigSet, matches: &ArgMatches) {
|
|||
};
|
||||
|
||||
if let Some(command) = command {
|
||||
let res = send_command(Service::Daemon, config_set.default, command);
|
||||
|
||||
if res.is_ok() {
|
||||
exit(0);
|
||||
}else{
|
||||
println!("{}", res.unwrap_err());
|
||||
}
|
||||
send_command_or_warn(Service::Daemon, config_set.default, command);
|
||||
}
|
||||
|
||||
exit(1);
|
||||
}
|
||||
|
||||
fn send_command(service: Service, config: Configs, command: IPCCommand) -> Result<(), String> {
|
||||
let ipc_client = protocol::get_ipc_client(service, config);
|
||||
ipc_client.send_command(command)
|
||||
}
|
||||
|
||||
fn log_main() {
|
||||
let espanso_dir = context::get_data_dir();
|
||||
let log_file_path = espanso_dir.join(LOG_FILE);
|
||||
|
|
|
@ -40,6 +40,14 @@ pub trait IPCClient {
|
|||
fn send_command(&self, command: IPCCommand) -> Result<(), String>;
|
||||
}
|
||||
|
||||
pub fn send_command_or_warn(service: Service, configs: Configs, command: IPCCommand) {
|
||||
let ipc_client = get_ipc_client(service, configs);
|
||||
if let Err(e) = ipc_client.send_command(command) {
|
||||
error!("unable to send command to IPC server");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug)]
|
||||
pub struct IPCCommand {
|
||||
pub id: String,
|
||||
|
@ -54,6 +62,9 @@ impl IPCCommand {
|
|||
"exit" => {
|
||||
Some(Event::Action(ActionType::Exit))
|
||||
},
|
||||
"wexit" => {
|
||||
Some(Event::Action(ActionType::ExitWorker))
|
||||
},
|
||||
"toggle" => {
|
||||
Some(Event::Action(ActionType::Toggle))
|
||||
},
|
||||
|
@ -63,6 +74,9 @@ impl IPCCommand {
|
|||
"disable" => {
|
||||
Some(Event::Action(ActionType::Disable))
|
||||
},
|
||||
"restartworker" => {
|
||||
Some(Event::Action(ActionType::RestartWorker))
|
||||
},
|
||||
"notify" => {
|
||||
Some(Event::System(SystemEvent::NotifyRequest(self.payload.clone())))
|
||||
},
|
||||
|
@ -73,13 +87,36 @@ impl IPCCommand {
|
|||
pub fn from(event: Event) -> Option<IPCCommand> {
|
||||
match event {
|
||||
Event::Action(ActionType::Exit) => Some(IPCCommand{id: "exit".to_owned(), payload: "".to_owned()}),
|
||||
Event::Action(ActionType::ExitWorker) => Some(IPCCommand{id: "wexit".to_owned(), payload: "".to_owned()}),
|
||||
Event::Action(ActionType::Toggle) => Some(IPCCommand{id: "toggle".to_owned(), payload: "".to_owned()}),
|
||||
Event::Action(ActionType::Enable) => Some(IPCCommand{id: "enable".to_owned(), payload: "".to_owned()}),
|
||||
Event::Action(ActionType::Disable) => Some(IPCCommand{id: "disable".to_owned(), payload: "".to_owned()}),
|
||||
Event::Action(ActionType::RestartWorker) => Some(IPCCommand{id: "restartworker".to_owned(), payload: "".to_owned()}),
|
||||
Event::System(SystemEvent::NotifyRequest(message)) => Some(IPCCommand{id: "notify".to_owned(), payload: message}),
|
||||
_ => None
|
||||
}
|
||||
}
|
||||
|
||||
pub fn exit() -> IPCCommand {
|
||||
Self {
|
||||
id: "exit".to_owned(),
|
||||
payload: "".to_owned(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn exit_worker() -> IPCCommand {
|
||||
Self {
|
||||
id: "wexit".to_owned(),
|
||||
payload: "".to_owned(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn restart_worker() -> IPCCommand {
|
||||
Self {
|
||||
id: "restartworker".to_owned(),
|
||||
payload: "".to_owned(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn process_event<R: Read, E: Error>(event_channel: &Sender<Event>, stream: Result<R, E>) {
|
||||
|
@ -147,11 +184,11 @@ pub fn get_ipc_client(service: Service, _: Configs) -> impl IPCClient {
|
|||
|
||||
// WINDOWS IMPLEMENTATION
|
||||
#[cfg(target_os = "windows")]
|
||||
pub fn get_ipc_server(config_set: Configs, event_channel: Sender<Event>) -> impl IPCServer {
|
||||
windows::WindowsIPCServer::new(config_set, event_channel)
|
||||
pub fn get_ipc_server(service: Service, config: Configs, event_channel: Sender<Event>) -> impl IPCServer {
|
||||
windows::WindowsIPCServer::new(service, config, event_channel)
|
||||
}
|
||||
|
||||
#[cfg(target_os = "windows")]
|
||||
pub fn get_ipc_client(config_set: Configs) -> impl IPCClient {
|
||||
windows::WindowsIPCClient::new(config_set)
|
||||
pub fn get_ipc_client(service: Service, config: Configs) -> impl IPCClient {
|
||||
windows::WindowsIPCClient::new(service, config)
|
||||
}
|
|
@ -23,24 +23,33 @@ use std::net::{TcpListener, TcpStream};
|
|||
use super::IPCCommand;
|
||||
|
||||
use crate::event::*;
|
||||
use crate::protocol::{process_event, send_command};
|
||||
use crate::config::ConfigSet;
|
||||
use crate::protocol::{process_event, send_command, Service};
|
||||
use crate::config::{Configs};
|
||||
|
||||
pub struct WindowsIPCServer {
|
||||
config_set: ConfigSet,
|
||||
service: Service,
|
||||
config: Configs,
|
||||
event_channel: Sender<Event>,
|
||||
}
|
||||
|
||||
fn to_port(config: &Configs, service: &Service) -> u16 {
|
||||
let port = match service {
|
||||
Service::Daemon => {config.ipc_server_port},
|
||||
Service::Worker => {config.worker_ipc_server_port},
|
||||
};
|
||||
port as u16
|
||||
}
|
||||
|
||||
impl WindowsIPCServer {
|
||||
pub fn new(config_set: ConfigSet, event_channel: Sender<Event>) -> WindowsIPCServer {
|
||||
WindowsIPCServer {config_set, event_channel}
|
||||
pub fn new(service: Service, config: Configs, event_channel: Sender<Event>) -> WindowsIPCServer {
|
||||
WindowsIPCServer {service, config, event_channel}
|
||||
}
|
||||
}
|
||||
|
||||
impl super::IPCServer for WindowsIPCServer {
|
||||
fn start(&self) {
|
||||
let event_channel = self.event_channel.clone();
|
||||
let server_port = self.config_set.default.ipc_server_port;
|
||||
let server_port = to_port(&self.config, &self.service);
|
||||
std::thread::Builder::new().name("ipc_server".to_string()).spawn(move || {
|
||||
let listener = TcpListener::bind(
|
||||
format!("127.0.0.1:{}", server_port)
|
||||
|
@ -56,19 +65,21 @@ impl super::IPCServer for WindowsIPCServer {
|
|||
}
|
||||
|
||||
pub struct WindowsIPCClient {
|
||||
config_set: ConfigSet,
|
||||
service: Service,
|
||||
config: Configs,
|
||||
}
|
||||
|
||||
impl WindowsIPCClient {
|
||||
pub fn new(config_set: ConfigSet) -> WindowsIPCClient {
|
||||
WindowsIPCClient{config_set}
|
||||
pub fn new(service: Service, config: Configs) -> WindowsIPCClient {
|
||||
WindowsIPCClient{service, config}
|
||||
}
|
||||
}
|
||||
|
||||
impl super::IPCClient for WindowsIPCClient {
|
||||
fn send_command(&self, command: IPCCommand) -> Result<(), String> {
|
||||
let port = to_port(&self.config, &self.service);
|
||||
let stream = TcpStream::connect(
|
||||
("127.0.0.1", self.config_set.default.ipc_server_port as u16)
|
||||
("127.0.0.1", port)
|
||||
);
|
||||
|
||||
send_command(command, stream)
|
||||
|
|
Loading…
Reference in New Issue
Block a user