fix winit build

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

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

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

Loading…
Cancel
Save