fix winit build

macos-click-through
Gabby Grinslade 4 years ago
parent c63b054521
commit 38c5538186

@ -1,65 +1,69 @@
mod events;
mod handler;
mod ui_commands;
use std::env;
use std::path::Path;
use std::process::Stdio;
use std::sync::atomic::{AtomicBool, Ordering};
use std::sync::Arc;
use crossfire::mpsc::{RxUnbounded, TxUnbounded};
use log::{error, info, warn};
use nvim_rs::{create::tokio as create, UiAttachOptions};
use rmpv::Value;
use tokio::process::Command;
use tokio::runtime::Runtime;
use crate::error_handling::ResultPanicExplanation;
use crate::settings::*;
use crate::window::window_geometry_or_default;
pub use events::*;
use handler::NeovimHandler;
pub use ui_commands::UiCommand;
#[cfg(windows)]
fn set_windows_creation_flags(cmd: &mut Command) {
cmd.creation_flags(0x0800_0000); // CREATE_NO_WINDOW
}
#[cfg(windows)]
fn platform_build_nvim_cmd(bin: &str) -> Option<Command> {
if env::args().any(|arg| arg == "--wsl") {
let mut cmd = Command::new("wsl");
cmd.arg(bin);
Some(cmd)
mod events;
mod handler;
mod ui_commands;
use std::env;
use std::path::Path;
use std::process::Stdio;
use std::sync::atomic::{AtomicBool, Ordering};
use std::sync::Arc;
use crossfire::mpsc::{RxUnbounded, TxUnbounded};
use log::{error, info, warn};
use nvim_rs::{create::tokio as create, UiAttachOptions};
use rmpv::Value;
use tokio::process::Command;
use tokio::runtime::Runtime;
use crate::error_handling::ResultPanicExplanation;
use crate::settings::*;
use crate::window::window_geometry_or_default;
pub use events::*;
use handler::NeovimHandler;
pub use ui_commands::UiCommand;
#[cfg(windows)]
fn set_windows_creation_flags(cmd: &mut Command) {
cmd.creation_flags(0x0800_0000); // CREATE_NO_WINDOW
}
#[cfg(windows)]
fn platform_build_nvim_cmd(bin: &str) -> Option<Command> {
if env::args().any(|arg| arg == "--wsl") {
let mut cmd = Command::new("wsl");
cmd.arg(bin);
Some(cmd)
} else if Path::new(&bin).exists() {
Some(Command::new(bin))
Some(Command::new(bin))
} else {
None
}
}
#[cfg(unix)]
fn platform_build_nvim_cmd(bin: &str) -> Option<Command> {
if Path::new(&bin).exists() {
Some(Command::new(bin))
} else {
None
}
}
fn build_nvim_cmd() -> Command {
if let Ok(path) = env::var("NEOVIM_BIN") {
if let Some(cmd) = platform_build_nvim_cmd(&path) {
return cmd;
} else {
warn!("NEOVIM_BIN is invalid falling back to first bin in PATH");
}
}
}
}
#[cfg(unix)]
fn platform_build_nvim_cmd(bin: &str) -> Option<Command> {
if Path::new(&bin).exists() {
Some(Command::new(bin))
} else {
None
}
}
fn build_nvim_cmd() -> Command {
if let Ok(path) = env::var("NEOVIM_BIN") {
if let Some(cmd) = platform_build_nvim_cmd(&path) {
return cmd;
} else {
warn!("NEOVIM_BIN is invalid falling back to first bin in PATH");
}
}
#[cfg(windows)]
if env::args().any(|arg| arg == "--wsl") {
if let Ok(output) = std::process::Command::new("wsl").arg("which").arg("nvim").output() {
if let Ok(output) = std::process::Command::new("wsl")
.arg("which")
.arg("nvim")
.output()
{
if output.status.success() {
let path = String::from_utf8(output.stdout).unwrap();
let mut cmd = Command::new("wsl");
@ -74,42 +78,42 @@ fn build_nvim_cmd() -> Command {
std::process::exit(1);
}
}
if let Ok(path) = which::which("nvim") {
if let Some(cmd) = platform_build_nvim_cmd(path.to_str().unwrap()) {
cmd
} else {
error!("nvim does not have proper permissions!");
std::process::exit(1);
}
} else {
error!("nvim not found!");
std::process::exit(1);
}
}
pub fn build_neovide_command(channel: u64, num_args: u64, command: &str, event: &str) -> String {
let nargs: String = if num_args > 1 {
"+".to_string()
} else {
num_args.to_string()
};
if num_args == 0 {
return format!(
"command! -nargs={} -complete=expression {} call rpcnotify({}, 'neovide.{}')",
nargs, command, channel, event
);
} else {
return format!(
"command! -nargs={} -complete=expression {} call rpcnotify({}, 'neovide.{}', <args>)",
nargs, command, channel, event
);
};
}
pub fn create_nvim_command() -> Command {
let mut cmd = build_nvim_cmd();
cmd.arg("--embed")
if let Ok(path) = which::which("nvim") {
if let Some(cmd) = platform_build_nvim_cmd(path.to_str().unwrap()) {
cmd
} else {
error!("nvim does not have proper permissions!");
std::process::exit(1);
}
} else {
error!("nvim not found!");
std::process::exit(1);
}
}
pub fn build_neovide_command(channel: u64, num_args: u64, command: &str, event: &str) -> String {
let nargs: String = if num_args > 1 {
"+".to_string()
} else {
num_args.to_string()
};
if num_args == 0 {
return format!(
"command! -nargs={} -complete=expression {} call rpcnotify({}, 'neovide.{}')",
nargs, command, channel, event
);
} else {
return format!(
"command! -nargs={} -complete=expression {} call rpcnotify({}, 'neovide.{}', <args>)",
nargs, command, channel, event
);
};
}
pub fn create_nvim_command() -> Command {
let mut cmd = build_nvim_cmd();
cmd.arg("--embed")
.args(SETTINGS.neovim_arguments.iter().skip(1));
#[cfg(not(debug_assertions))]
@ -117,184 +121,184 @@ pub fn create_nvim_command() -> Command {
#[cfg(debug_assertions)]
cmd.stderr(Stdio::inherit());
#[cfg(windows)]
set_windows_creation_flags(&mut cmd);
cmd
}
async fn start_neovim_runtime(
ui_command_sender: TxUnbounded<UiCommand>,
ui_command_receiver: RxUnbounded<UiCommand>,
redraw_event_sender: TxUnbounded<RedrawEvent>,
running: Arc<AtomicBool>,
) {
let (width, height) = window_geometry_or_default();
let handler = NeovimHandler::new(ui_command_sender.clone(), redraw_event_sender.clone());
let (mut nvim, io_handler, _) = create::new_child_cmd(&mut create_nvim_command(), handler)
.await
.unwrap_or_explained_panic("Could not locate or start neovim process");
if nvim.get_api_info().await.is_err() {
error!("Cannot get neovim api info, either neovide is launched with an unknown command line option or neovim version not supported!");
std::process::exit(-1);
}
let close_watcher_running = running.clone();
tokio::spawn(async move {
info!("Close watcher started");
match io_handler.await {
Err(join_error) => error!("Error joining IO loop: '{}'", join_error),
Ok(Err(error)) => {
if !error.is_channel_closed() {
error!("Error: '{}'", error);
}
}
Ok(Ok(())) => {}
};
close_watcher_running.store(false, Ordering::Relaxed);
});
if let Ok(Value::Integer(correct_version)) = nvim.eval("has(\"nvim-0.4\")").await {
if correct_version.as_i64() != Some(1) {
error!("Neovide requires version 0.4 or higher");
std::process::exit(0);
}
} else {
error!("Neovide requires version 0.4 or higher");
std::process::exit(0);
};
nvim.set_var("neovide", Value::Boolean(true))
.await
.unwrap_or_explained_panic("Could not communicate with neovim process");
if let Err(command_error) = nvim.command("runtime! ginit.vim").await {
nvim.command(&format!(
"echomsg \"error encountered in ginit.vim {:?}\"",
command_error
))
.await
.ok();
}
nvim.set_client_info(
"neovide",
vec![
(Value::from("major"), Value::from(0u64)),
(Value::from("minor"), Value::from(6u64)),
],
"ui",
vec![],
vec![],
)
.await
.ok();
let neovide_channel: u64 = nvim
.list_chans()
.await
.ok()
.and_then(|channel_values| parse_channel_list(channel_values).ok())
.and_then(|channel_list| {
channel_list.iter().find_map(|channel| match channel {
ChannelInfo {
id,
client: Some(ClientInfo { name, .. }),
..
} if name == "neovide" => Some(*id),
_ => None,
})
})
.unwrap_or(0);
info!(
"Neovide registered to nvim with channel id {}",
neovide_channel
);
#[cfg(windows)]
nvim.command(&build_neovide_command(
neovide_channel,
0,
"NeovideRegisterRightClick",
"register_right_click",
))
.await
.ok();
#[cfg(windows)]
nvim.command(&build_neovide_command(
neovide_channel,
0,
"NeovideUnregisterRightClick",
"unregister_right_click",
))
.await
.ok();
nvim.set_option("lazyredraw", Value::Boolean(false))
.await
.ok();
let mut options = UiAttachOptions::new();
options.set_linegrid_external(true);
if env::args().any(|arg| arg == "--multiGrid") || env::var("NeovideMultiGrid").is_ok() {
options.set_multigrid_external(true);
}
options.set_rgb(true);
nvim.ui_attach(width as i64, height as i64, &options)
.await
.unwrap_or_explained_panic("Could not attach ui to neovim process");
info!("Neovim process attached");
let nvim = Arc::new(nvim);
let ui_command_running = running.clone();
let input_nvim = nvim.clone();
tokio::spawn(async move {
loop {
if !ui_command_running.load(Ordering::Relaxed) {
break;
}
match ui_command_receiver.recv().await {
Ok(ui_command) => {
let input_nvim = input_nvim.clone();
tokio::spawn(async move {
ui_command.execute(&input_nvim).await;
});
}
Err(_) => {
ui_command_running.store(false, Ordering::Relaxed);
break;
}
}
}
});
SETTINGS.read_initial_values(&nvim).await;
SETTINGS.setup_changed_listeners(&nvim).await;
}
pub struct Bridge {
_runtime: Runtime, // Necessary to keep runtime running
}
pub fn start_bridge(
ui_command_sender: TxUnbounded<UiCommand>,
ui_command_receiver: RxUnbounded<UiCommand>,
redraw_event_sender: TxUnbounded<RedrawEvent>,
running: Arc<AtomicBool>,
) -> Bridge {
let runtime = Runtime::new().unwrap();
runtime.spawn(start_neovim_runtime(
ui_command_sender,
ui_command_receiver,
redraw_event_sender,
running,
));
Bridge { _runtime: runtime }
}
#[cfg(windows)]
set_windows_creation_flags(&mut cmd);
cmd
}
async fn start_neovim_runtime(
ui_command_sender: TxUnbounded<UiCommand>,
ui_command_receiver: RxUnbounded<UiCommand>,
redraw_event_sender: TxUnbounded<RedrawEvent>,
running: Arc<AtomicBool>,
) {
let (width, height) = window_geometry_or_default();
let handler = NeovimHandler::new(ui_command_sender.clone(), redraw_event_sender.clone());
let (mut nvim, io_handler, _) = create::new_child_cmd(&mut create_nvim_command(), handler)
.await
.unwrap_or_explained_panic("Could not locate or start neovim process");
if nvim.get_api_info().await.is_err() {
error!("Cannot get neovim api info, either neovide is launched with an unknown command line option or neovim version not supported!");
std::process::exit(-1);
}
let close_watcher_running = running.clone();
tokio::spawn(async move {
info!("Close watcher started");
match io_handler.await {
Err(join_error) => error!("Error joining IO loop: '{}'", join_error),
Ok(Err(error)) => {
if !error.is_channel_closed() {
error!("Error: '{}'", error);
}
}
Ok(Ok(())) => {}
};
close_watcher_running.store(false, Ordering::Relaxed);
});
if let Ok(Value::Integer(correct_version)) = nvim.eval("has(\"nvim-0.4\")").await {
if correct_version.as_i64() != Some(1) {
error!("Neovide requires version 0.4 or higher");
std::process::exit(0);
}
} else {
error!("Neovide requires version 0.4 or higher");
std::process::exit(0);
};
nvim.set_var("neovide", Value::Boolean(true))
.await
.unwrap_or_explained_panic("Could not communicate with neovim process");
if let Err(command_error) = nvim.command("runtime! ginit.vim").await {
nvim.command(&format!(
"echomsg \"error encountered in ginit.vim {:?}\"",
command_error
))
.await
.ok();
}
nvim.set_client_info(
"neovide",
vec![
(Value::from("major"), Value::from(0u64)),
(Value::from("minor"), Value::from(6u64)),
],
"ui",
vec![],
vec![],
)
.await
.ok();
let neovide_channel: u64 = nvim
.list_chans()
.await
.ok()
.and_then(|channel_values| parse_channel_list(channel_values).ok())
.and_then(|channel_list| {
channel_list.iter().find_map(|channel| match channel {
ChannelInfo {
id,
client: Some(ClientInfo { name, .. }),
..
} if name == "neovide" => Some(*id),
_ => None,
})
})
.unwrap_or(0);
info!(
"Neovide registered to nvim with channel id {}",
neovide_channel
);
#[cfg(windows)]
nvim.command(&build_neovide_command(
neovide_channel,
0,
"NeovideRegisterRightClick",
"register_right_click",
))
.await
.ok();
#[cfg(windows)]
nvim.command(&build_neovide_command(
neovide_channel,
0,
"NeovideUnregisterRightClick",
"unregister_right_click",
))
.await
.ok();
nvim.set_option("lazyredraw", Value::Boolean(false))
.await
.ok();
let mut options = UiAttachOptions::new();
options.set_linegrid_external(true);
if env::args().any(|arg| arg == "--multiGrid") || env::var("NeovideMultiGrid").is_ok() {
options.set_multigrid_external(true);
}
options.set_rgb(true);
nvim.ui_attach(width as i64, height as i64, &options)
.await
.unwrap_or_explained_panic("Could not attach ui to neovim process");
info!("Neovim process attached");
let nvim = Arc::new(nvim);
let ui_command_running = running.clone();
let input_nvim = nvim.clone();
tokio::spawn(async move {
loop {
if !ui_command_running.load(Ordering::Relaxed) {
break;
}
match ui_command_receiver.recv().await {
Ok(ui_command) => {
let input_nvim = input_nvim.clone();
tokio::spawn(async move {
ui_command.execute(&input_nvim).await;
});
}
Err(_) => {
ui_command_running.store(false, Ordering::Relaxed);
break;
}
}
}
});
SETTINGS.read_initial_values(&nvim).await;
SETTINGS.setup_changed_listeners(&nvim).await;
}
pub struct Bridge {
_runtime: Runtime, // Necessary to keep runtime running
}
pub fn start_bridge(
ui_command_sender: TxUnbounded<UiCommand>,
ui_command_receiver: RxUnbounded<UiCommand>,
redraw_event_sender: TxUnbounded<RedrawEvent>,
running: Arc<AtomicBool>,
) -> Bridge {
let runtime = Runtime::new().unwrap();
runtime.spawn(start_neovim_runtime(
ui_command_sender,
ui_command_receiver,
redraw_event_sender,
running,
));
Bridge { _runtime: runtime }
}

@ -9,13 +9,18 @@ impl From<Option<ModifiersState>> for Modifiers {
fn from(state: Option<ModifiersState>) -> Modifiers {
if let Some(modifiers) = state {
Modifiers {
shift: state.shift(),
control: state.ctrl(),
meta: state.alt(),
logo: state.logo(),
shift: modifiers.shift(),
control: modifiers.ctrl(),
meta: modifiers.alt(),
logo: modifiers.logo(),
}
} else {
Modifiers::new(false, false, false, false)
Modifiers {
shift: false,
control: false,
meta: false,
logo: false,
}
}
}
}

Loading…
Cancel
Save