|
|
@ -1,24 +1,32 @@
|
|
|
|
use log::trace;
|
|
|
|
use std::sync::{
|
|
|
|
|
|
|
|
Arc,
|
|
|
|
|
|
|
|
atomic::{
|
|
|
|
|
|
|
|
AtomicBool,
|
|
|
|
|
|
|
|
Ordering,
|
|
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
use log::trace;
|
|
|
|
#[cfg(windows)]
|
|
|
|
#[cfg(windows)]
|
|
|
|
use log::error;
|
|
|
|
use log::error;
|
|
|
|
|
|
|
|
|
|
|
|
use nvim_rs::Neovim;
|
|
|
|
use nvim_rs::Neovim;
|
|
|
|
|
|
|
|
use tokio::sync::mpsc::{
|
|
|
|
|
|
|
|
unbounded_channel,
|
|
|
|
|
|
|
|
UnboundedReceiver,
|
|
|
|
|
|
|
|
UnboundedSender,
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
use crate::bridge::TxWrapper;
|
|
|
|
use crate::bridge::TxWrapper;
|
|
|
|
|
|
|
|
|
|
|
|
#[cfg(windows)]
|
|
|
|
#[cfg(windows)]
|
|
|
|
use crate::windows_utils::{
|
|
|
|
use crate::windows_utils::{
|
|
|
|
register_rightclick_directory, register_rightclick_file, unregister_rightclick,
|
|
|
|
register_rightclick_directory, register_rightclick_file, unregister_rightclick,
|
|
|
|
};
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Serial commands are any commands which must complete before the next value is sent. This
|
|
|
|
|
|
|
|
// includes keyboard and mouse input which would cuase problems if sent out of order.
|
|
|
|
#[derive(Debug, Clone)]
|
|
|
|
#[derive(Debug, Clone)]
|
|
|
|
pub enum UiCommand {
|
|
|
|
pub enum SerialCommand {
|
|
|
|
Quit,
|
|
|
|
|
|
|
|
Resize {
|
|
|
|
|
|
|
|
width: u64,
|
|
|
|
|
|
|
|
height: u64,
|
|
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
Keyboard(String),
|
|
|
|
Keyboard(String),
|
|
|
|
MouseButton {
|
|
|
|
MouseButton {
|
|
|
|
button: String,
|
|
|
|
button: String,
|
|
|
@ -39,30 +47,16 @@ pub enum UiCommand {
|
|
|
|
position: (u32, u32),
|
|
|
|
position: (u32, u32),
|
|
|
|
modifier_string: String,
|
|
|
|
modifier_string: String,
|
|
|
|
},
|
|
|
|
},
|
|
|
|
FileDrop(String),
|
|
|
|
|
|
|
|
FocusLost,
|
|
|
|
|
|
|
|
FocusGained,
|
|
|
|
|
|
|
|
#[cfg(windows)]
|
|
|
|
|
|
|
|
RegisterRightClick,
|
|
|
|
|
|
|
|
#[cfg(windows)]
|
|
|
|
|
|
|
|
UnregisterRightClick,
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
impl UiCommand {
|
|
|
|
impl SerialCommand {
|
|
|
|
pub async fn execute(self, nvim: &Neovim<TxWrapper>) {
|
|
|
|
async fn execute(self, nvim: &Neovim<TxWrapper>) {
|
|
|
|
match self {
|
|
|
|
match self {
|
|
|
|
UiCommand::Quit => {
|
|
|
|
SerialCommand::Keyboard(input_command) => {
|
|
|
|
nvim.command("qa!").await.ok();
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
UiCommand::Resize { width, height } => nvim
|
|
|
|
|
|
|
|
.ui_try_resize(width.max(10) as i64, height.max(3) as i64)
|
|
|
|
|
|
|
|
.await
|
|
|
|
|
|
|
|
.expect("Resize failed"),
|
|
|
|
|
|
|
|
UiCommand::Keyboard(input_command) => {
|
|
|
|
|
|
|
|
trace!("Keyboard Input Sent: {}", input_command);
|
|
|
|
trace!("Keyboard Input Sent: {}", input_command);
|
|
|
|
nvim.input(&input_command).await.expect("Input failed");
|
|
|
|
nvim.input(&input_command).await.expect("Input failed");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
UiCommand::MouseButton {
|
|
|
|
SerialCommand::MouseButton {
|
|
|
|
button,
|
|
|
|
button,
|
|
|
|
action,
|
|
|
|
action,
|
|
|
|
grid_id,
|
|
|
|
grid_id,
|
|
|
@ -80,7 +74,7 @@ impl UiCommand {
|
|
|
|
.await
|
|
|
|
.await
|
|
|
|
.expect("Mouse Input Failed");
|
|
|
|
.expect("Mouse Input Failed");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
UiCommand::Scroll {
|
|
|
|
SerialCommand::Scroll {
|
|
|
|
direction,
|
|
|
|
direction,
|
|
|
|
grid_id,
|
|
|
|
grid_id,
|
|
|
|
position: (grid_x, grid_y),
|
|
|
|
position: (grid_x, grid_y),
|
|
|
@ -97,8 +91,12 @@ impl UiCommand {
|
|
|
|
.await
|
|
|
|
.await
|
|
|
|
.expect("Mouse Scroll Failed");
|
|
|
|
.expect("Mouse Scroll Failed");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
<<<<<<< Updated upstream
|
|
|
|
UiCommand::Drag {
|
|
|
|
UiCommand::Drag {
|
|
|
|
button,
|
|
|
|
button,
|
|
|
|
|
|
|
|
=======
|
|
|
|
|
|
|
|
SerialCommand::Drag {
|
|
|
|
|
|
|
|
>>>>>>> Stashed changes
|
|
|
|
grid_id,
|
|
|
|
grid_id,
|
|
|
|
position: (grid_x, grid_y),
|
|
|
|
position: (grid_x, grid_y),
|
|
|
|
modifier_string,
|
|
|
|
modifier_string,
|
|
|
@ -114,19 +112,49 @@ impl UiCommand {
|
|
|
|
.await
|
|
|
|
.await
|
|
|
|
.expect("Mouse Drag Failed");
|
|
|
|
.expect("Mouse Drag Failed");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
UiCommand::FocusLost => nvim
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#[derive(Debug, Clone)]
|
|
|
|
|
|
|
|
pub enum ParallelCommand {
|
|
|
|
|
|
|
|
Quit,
|
|
|
|
|
|
|
|
Resize {
|
|
|
|
|
|
|
|
width: u64,
|
|
|
|
|
|
|
|
height: u64,
|
|
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
FileDrop(String),
|
|
|
|
|
|
|
|
FocusLost,
|
|
|
|
|
|
|
|
FocusGained,
|
|
|
|
|
|
|
|
#[cfg(windows)]
|
|
|
|
|
|
|
|
RegisterRightClick,
|
|
|
|
|
|
|
|
#[cfg(windows)]
|
|
|
|
|
|
|
|
UnregisterRightClick,
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
impl ParallelCommand {
|
|
|
|
|
|
|
|
async fn execute(self, nvim: &Neovim<TxWrapper>) {
|
|
|
|
|
|
|
|
match self {
|
|
|
|
|
|
|
|
ParallelCommand::Quit => {
|
|
|
|
|
|
|
|
nvim.command("qa!").await.ok();
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
ParallelCommand::Resize { width, height } => nvim
|
|
|
|
|
|
|
|
.ui_try_resize(width.max(10) as i64, height.max(3) as i64)
|
|
|
|
|
|
|
|
.await
|
|
|
|
|
|
|
|
.expect("Resize failed"),
|
|
|
|
|
|
|
|
ParallelCommand::FocusLost => nvim
|
|
|
|
.command("if exists('#FocusLost') | doautocmd <nomodeline> FocusLost | endif")
|
|
|
|
.command("if exists('#FocusLost') | doautocmd <nomodeline> FocusLost | endif")
|
|
|
|
.await
|
|
|
|
.await
|
|
|
|
.expect("Focus Lost Failed"),
|
|
|
|
.expect("Focus Lost Failed"),
|
|
|
|
UiCommand::FocusGained => nvim
|
|
|
|
ParallelCommand::FocusGained => nvim
|
|
|
|
.command("if exists('#FocusGained') | doautocmd <nomodeline> FocusGained | endif")
|
|
|
|
.command("if exists('#FocusGained') | doautocmd <nomodeline> FocusGained | endif")
|
|
|
|
.await
|
|
|
|
.await
|
|
|
|
.expect("Focus Gained Failed"),
|
|
|
|
.expect("Focus Gained Failed"),
|
|
|
|
UiCommand::FileDrop(path) => {
|
|
|
|
ParallelCommand::FileDrop(path) => {
|
|
|
|
nvim.command(format!("e {}", path).as_str()).await.ok();
|
|
|
|
nvim.command(format!("e {}", path).as_str()).await.ok();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#[cfg(windows)]
|
|
|
|
#[cfg(windows)]
|
|
|
|
UiCommand::RegisterRightClick => {
|
|
|
|
ParallelCommand::RegisterRightClick => {
|
|
|
|
if unregister_rightclick() {
|
|
|
|
if unregister_rightclick() {
|
|
|
|
let msg = "Could not unregister previous menu item. Possibly already registered or not running as Admin?";
|
|
|
|
let msg = "Could not unregister previous menu item. Possibly already registered or not running as Admin?";
|
|
|
|
nvim.err_writeln(msg).await.ok();
|
|
|
|
nvim.err_writeln(msg).await.ok();
|
|
|
@ -144,7 +172,7 @@ impl UiCommand {
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#[cfg(windows)]
|
|
|
|
#[cfg(windows)]
|
|
|
|
UiCommand::UnregisterRightClick => {
|
|
|
|
ParallelCommand::UnregisterRightClick => {
|
|
|
|
if !unregister_rightclick() {
|
|
|
|
if !unregister_rightclick() {
|
|
|
|
let msg = "Could not remove context menu items. Possibly already removed or not running as Admin?";
|
|
|
|
let msg = "Could not remove context menu items. Possibly already removed or not running as Admin?";
|
|
|
|
nvim.err_writeln(msg).await.ok();
|
|
|
|
nvim.err_writeln(msg).await.ok();
|
|
|
@ -154,3 +182,72 @@ impl UiCommand {
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#[derive(Debug, Clone)]
|
|
|
|
|
|
|
|
pub enum UiCommand {
|
|
|
|
|
|
|
|
Serial(SerialCommand),
|
|
|
|
|
|
|
|
Parallel(ParallelCommand),
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
impl From<SerialCommand> for UiCommand {
|
|
|
|
|
|
|
|
fn from(serial: SerialCommand) -> Self {
|
|
|
|
|
|
|
|
UiCommand::Serial(serial)
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
impl From<ParallelCommand> for UiCommand {
|
|
|
|
|
|
|
|
fn from(parallel: ParallelCommand) -> Self {
|
|
|
|
|
|
|
|
UiCommand::Parallel(parallel)
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
pub fn start_ui_command_handler(running: Arc<AtomicBool>, mut ui_command_receiver: UnboundedReceiver<UiCommand>, nvim: Arc<Neovim<TxWrapper>>) {
|
|
|
|
|
|
|
|
let serial_tx = start_serial_command_handler(running, nvim);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
tokio::spawn(async move {
|
|
|
|
|
|
|
|
loop {
|
|
|
|
|
|
|
|
if !running.load(Ordering::Relaxed) {
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
match ui_command_receiver.recv().await {
|
|
|
|
|
|
|
|
Some(UiCommand::Serial(serial_command)) =>
|
|
|
|
|
|
|
|
serial_tx.send(serial_command).expect("Could not send serial ui command"),
|
|
|
|
|
|
|
|
Some(UiCommand::Parallel(parallel_command)) => {
|
|
|
|
|
|
|
|
let nvim = nvim.clone();
|
|
|
|
|
|
|
|
tokio::spawn(async move {
|
|
|
|
|
|
|
|
parallel_command.execute(&nvim).await;
|
|
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
None => {
|
|
|
|
|
|
|
|
running.store(false, Ordering::Relaxed);
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
pub fn start_serial_command_handler(running: Arc<AtomicBool>, nvim: Arc<Neovim<TxWrapper>>) -> UnboundedSender<SerialCommand> {
|
|
|
|
|
|
|
|
let (serial_tx, serial_rx) = unbounded_channel::<SerialCommand>();
|
|
|
|
|
|
|
|
tokio::spawn(async move {
|
|
|
|
|
|
|
|
loop {
|
|
|
|
|
|
|
|
if !running.load(Ordering::Relaxed) {
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
match serial_rx.recv().await {
|
|
|
|
|
|
|
|
Some(serial_command) => {
|
|
|
|
|
|
|
|
serial_command.execute(&nvim).await;
|
|
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
None => {
|
|
|
|
|
|
|
|
running.store(false, Ordering::Relaxed);
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
serial_tx
|
|
|
|
|
|
|
|
}
|
|
|
|