in progress adding back winit

macos-click-through
Keith Simmons 4 years ago
parent a490e5992a
commit 451ff87272

@ -10,6 +10,7 @@ description = "A simple GUI for Neovim."
default = ["sdl2"] default = ["sdl2"]
embed-fonts = [] embed-fonts = []
sdl2 = ["skulpin/skulpin_sdl2"] sdl2 = ["skulpin/skulpin_sdl2"]
winit = ["skulpin/skulpin_winit"]
[dependencies] [dependencies]
euclid = "0.20.7" euclid = "0.20.7"

@ -1,6 +1,3 @@
#[macro_use]
pub mod layouts;
mod events; mod events;
mod handler; mod handler;
mod ui_commands; mod ui_commands;
@ -23,7 +20,6 @@ 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 layouts::*;
pub use ui_commands::UiCommand; pub use ui_commands::UiCommand;
#[cfg(windows)] #[cfg(windows)]

@ -124,7 +124,6 @@ fn main() {
} }
} }
bridge::layouts::initialize_settings();
window::initialize_settings(); window::initialize_settings();
redraw_scheduler::initialize_settings(); redraw_scheduler::initialize_settings();
renderer::initialize_settings(); renderer::initialize_settings();

@ -1,16 +1,6 @@
mod qwerty;
use log::{error, trace}; use log::{error, trace};
use skulpin::sdl2::keyboard::{Keycode, Mod};
use crate::settings::{FromValue, Value, SETTINGS};
use qwerty::*; use crate::settings::*;
pub fn unsupported_key<R>(keycode: Keycode) -> Option<R> {
trace!("Unsupported key: {:?}", keycode);
None
}
#[derive(Clone)] #[derive(Clone)]
pub enum KeyboardLayout { pub enum KeyboardLayout {
@ -38,8 +28,8 @@ impl From<KeyboardLayout> for Value {
} }
#[derive(Clone)] #[derive(Clone)]
struct KeyboardSettings { pub struct KeyboardSettings {
layout: KeyboardLayout, pub layout: KeyboardLayout,
} }
pub fn initialize_settings() { pub fn initialize_settings() {
@ -50,7 +40,7 @@ pub fn initialize_settings() {
register_nvim_setting!("keyboard_layout", KeyboardSettings::layout); register_nvim_setting!("keyboard_layout", KeyboardSettings::layout);
} }
fn append_modifiers( pub fn append_modifiers(
keycode_text: &str, keycode_text: &str,
special: bool, special: bool,
shift: bool, shift: bool,
@ -89,26 +79,3 @@ fn append_modifiers(
result result
} }
pub fn produce_neovim_keybinding_string(
keycode: Option<Keycode>,
keytext: Option<String>,
modifiers: Mod,
) -> Option<String> {
let shift = modifiers.contains(Mod::LSHIFTMOD) || modifiers.contains(Mod::RSHIFTMOD);
let ctrl = modifiers.contains(Mod::LCTRLMOD) || modifiers.contains(Mod::RCTRLMOD);
let alt = modifiers.contains(Mod::LALTMOD) || modifiers.contains(Mod::RALTMOD);
let gui = modifiers.contains(Mod::LGUIMOD) || modifiers.contains(Mod::RGUIMOD);
if let Some(text) = keytext {
Some(append_modifiers(&text, false, false, ctrl, alt, gui))
} else if let Some(keycode) = keycode {
(match SETTINGS.get::<KeyboardSettings>().layout {
KeyboardLayout::Qwerty => handle_qwerty_layout(keycode, shift, ctrl, alt),
})
.map(|(transformed_text, special, shift, ctrl, alt)| {
append_modifiers(transformed_text, special, shift, ctrl, alt, gui)
})
} else {
None
}
}

@ -1,5 +1,8 @@
mod settings; mod settings;
pub mod keyboard;
#[cfg_attr(feature = "sdl2", path = "sdl2/mod.rs")] #[cfg_attr(feature = "sdl2", path = "sdl2/mod.rs")]
#[cfg_attr(feature = "winit", path = "winit/mod.rs")]
mod window_wrapper; mod window_wrapper;
use std::sync::atomic::AtomicBool; use std::sync::atomic::AtomicBool;

@ -0,0 +1,36 @@
mod qwerty;
use log::trace;
use skulpin::sdl2::keyboard::{Keycode, Mod};
use qwerty::*;
use super::keyboard::*;
use crate::settings::*;
pub fn unsupported_key<R>(keycode: Keycode) -> Option<R> {
trace!("Unsupported key: {:?}", keycode);
None
}
pub fn produce_neovim_keybinding_string(
keycode: Option<Keycode>,
keytext: Option<String>,
modifiers: Mod,
) -> Option<String> {
let shift = modifiers.contains(Mod::LSHIFTMOD) || modifiers.contains(Mod::RSHIFTMOD);
let ctrl = modifiers.contains(Mod::LCTRLMOD) || modifiers.contains(Mod::RCTRLMOD);
let alt = modifiers.contains(Mod::LALTMOD) || modifiers.contains(Mod::RALTMOD);
let gui = modifiers.contains(Mod::LGUIMOD) || modifiers.contains(Mod::RGUIMOD);
if let Some(text) = keytext {
Some(append_modifiers(&text, false, false, ctrl, alt, gui))
} else if let Some(keycode) = keycode {
(match SETTINGS.get::<KeyboardSettings>().layout {
KeyboardLayout::Qwerty => handle_qwerty_layout(keycode, shift, ctrl, alt),
})
.map(|(transformed_text, special, shift, ctrl, alt)| {
append_modifiers(transformed_text, special, shift, ctrl, alt, gui)
})
} else {
None
}
}

@ -1,3 +1,6 @@
#[macro_use]
mod layouts;
use std::sync::atomic::{AtomicBool, Ordering}; use std::sync::atomic::{AtomicBool, Ordering};
use std::sync::mpsc::Receiver; use std::sync::mpsc::Receiver;
use std::sync::Arc; use std::sync::Arc;
@ -20,12 +23,14 @@ use skulpin::{
use super::handle_new_grid_size; use super::handle_new_grid_size;
use super::settings::*; use super::settings::*;
use crate::bridge::{produce_neovim_keybinding_string, UiCommand}; pub use super::keyboard;
use crate::bridge::UiCommand;
use crate::editor::WindowCommand; use crate::editor::WindowCommand;
use crate::error_handling::ResultPanicExplanation; use crate::error_handling::ResultPanicExplanation;
use crate::redraw_scheduler::REDRAW_SCHEDULER; use crate::redraw_scheduler::REDRAW_SCHEDULER;
use crate::renderer::Renderer; use crate::renderer::Renderer;
use crate::settings::*; use crate::settings::*;
use layouts::produce_neovim_keybinding_string;
#[derive(RustEmbed)] #[derive(RustEmbed)]
#[folder = "assets/"] #[folder = "assets/"]

@ -1,4 +1,5 @@
use crate::settings::*; use crate::settings::*;
use super::keyboard::initialize_settings as keyboard_initialize_settings;
#[derive(Clone)] #[derive(Clone)]
pub struct WindowSettings { pub struct WindowSettings {
@ -24,4 +25,6 @@ pub fn initialize_settings() {
register_nvim_setting!("transparency", WindowSettings::transparency); register_nvim_setting!("transparency", WindowSettings::transparency);
register_nvim_setting!("no_idle", WindowSettings::no_idle); register_nvim_setting!("no_idle", WindowSettings::no_idle);
register_nvim_setting!("fullscreen", WindowSettings::fullscreen); register_nvim_setting!("fullscreen", WindowSettings::fullscreen);
keyboard_initialize_settings();
} }

@ -0,0 +1,44 @@
mod qwerty;
use log::trace;
use skulpin::winit::event::ModifiersState;
use skulpin::winit::event::VirtualKeyCode as Keycode;
use qwerty::*;
use super::keyboard::*;
use crate::settings::*;
pub fn unsupported_key<R>(keycode: Keycode) -> Option<R> {
trace!("Unsupported key: {:?}", keycode);
None
}
pub fn produce_neovim_keybinding_string(
keycode: Option<Keycode>,
keytext: Option<String>,
modifiers: Option<ModifiersState>,
) -> Option<String> {
let mut shift = false;
let mut ctrl = false;
let mut alt = false;
let mut gui = false;
if let Some(modifiers) = modifiers {
shift = modifiers.shift();
ctrl = modifiers.ctrl();
alt = modifiers.alt();
gui = modifiers.logo();
}
if let Some(text) = keytext {
Some(append_modifiers(&text, false, false, ctrl, alt, gui))
} else if let Some(keycode) = keycode {
(match SETTINGS.get::<KeyboardSettings>().layout {
KeyboardLayout::Qwerty => handle_qwerty_layout(keycode, shift, ctrl, alt),
})
.map(|(transformed_text, special, shift, ctrl, alt)| {
append_modifiers(transformed_text, special, shift, ctrl, alt, gui)
})
} else {
None
}
}

@ -0,0 +1,164 @@
use super::unsupported_key;
use skulpin::winit::event::VirtualKeyCode as Keycode;
pub fn handle_qwerty_layout(
keycode: Keycode,
shift: bool,
ctrl: bool,
alt: bool,
) -> Option<(&'static str, bool, bool, bool, bool)> {
match (keycode, shift, ctrl, alt) {
(Keycode::Back, shift, ctrl, alt) => Some(("BS", true, shift, ctrl, alt)),
(Keycode::Tab, shift, ctrl, alt) => Some(("Tab", true, shift, ctrl, alt)),
(Keycode::Return, shift, ctrl, alt) => Some(("Enter", true, shift, ctrl, alt)),
(Keycode::Escape, shift, ctrl, alt) => Some(("Esc", true, shift, ctrl, alt)),
(Keycode::Space, shift, ctrl, alt) => Some((" ", false, shift, ctrl, alt)),
(Keycode::Apostrophe, false, ctrl, alt) => Some(("'", false, false, ctrl, alt)),
(Keycode::Apostrophe, true, ctrl, alt) => Some(("\"", false, false, ctrl, alt)),
(Keycode::Comma, false, ctrl, alt) => Some((",", false, shift, ctrl, alt)),
(Keycode::Comma, true, ctrl, alt) => Some(("<", false, shift, ctrl, alt)),
(Keycode::Minus, false, ctrl, alt) => Some(("-", false, false, ctrl, alt)),
(Keycode::Minus, true, ctrl, alt) => Some(("_", false, false, ctrl, alt)),
(Keycode::Period, false, ctrl, alt) => Some((".", false, false, ctrl, alt)),
(Keycode::Period, true, ctrl, alt) => Some((">", false, false, ctrl, alt)),
(Keycode::Slash, false, ctrl, alt) => Some(("/", false, false, ctrl, alt)),
(Keycode::Slash, true, ctrl, alt) => Some(("?", false, false, ctrl, alt)),
(Keycode::Key0, false, ctrl, alt) => Some(("0", false, shift, ctrl, alt)),
(Keycode::Key0, true, ctrl, alt) => Some((")", true, shift, ctrl, alt)),
(Keycode::Key1, false, ctrl, alt) => Some(("1", false, shift, ctrl, alt)),
(Keycode::Key1, true, ctrl, alt) => Some(("!", true, shift, ctrl, alt)),
(Keycode::Key2, false, ctrl, alt) => Some(("2", false, false, ctrl, alt)),
(Keycode::Key2, true, ctrl, alt) => Some(("@", false, false, ctrl, alt)),
(Keycode::Key3, false, ctrl, alt) => Some(("3", false, false, ctrl, alt)),
(Keycode::Key3, true, ctrl, alt) => Some(("#", false, false, ctrl, alt)),
(Keycode::Key4, false, ctrl, alt) => Some(("4", false, false, ctrl, alt)),
(Keycode::Key4, true, ctrl, alt) => Some(("$", false, false, ctrl, alt)),
(Keycode::Key5, false, ctrl, alt) => Some(("5", false, false, ctrl, alt)),
(Keycode::Key5, true, ctrl, alt) => Some(("%", false, false, ctrl, alt)),
(Keycode::Key6, false, ctrl, alt) => Some(("6", false, false, ctrl, alt)),
(Keycode::Key6, true, ctrl, alt) => Some(("^", false, false, ctrl, alt)),
(Keycode::Key7, false, ctrl, alt) => Some(("7", false, false, ctrl, alt)),
(Keycode::Key7, true, ctrl, alt) => Some(("&", false, false, ctrl, alt)),
(Keycode::Key8, false, ctrl, alt) => Some(("8", false, false, ctrl, alt)),
(Keycode::Key8, true, ctrl, alt) => Some(("*", false, false, ctrl, alt)),
(Keycode::Key9, false, ctrl, alt) => Some(("9", false, false, ctrl, alt)),
(Keycode::Key9, true, ctrl, alt) => Some(("(", true, false, ctrl, alt)),
(Keycode::Colon, shift, ctrl, alt) => Some((":", false, shift, ctrl, alt)),
(Keycode::Semicolon, false, ctrl, alt) => Some((";", false, false, ctrl, alt)),
(Keycode::Semicolon, true, ctrl, alt) => Some((":", false, false, ctrl, alt)),
(Keycode::Equals, false, ctrl, alt) => Some(("=", false, false, ctrl, alt)),
(Keycode::Equals, true, ctrl, alt) => Some(("+", false, false, ctrl, alt)),
(Keycode::At, shift, ctrl, alt) => Some(("@", false, shift, ctrl, alt)),
(Keycode::LBracket, false, ctrl, alt) => Some(("[", false, false, ctrl, alt)),
(Keycode::LBracket, true, ctrl, alt) => Some(("{", false, false, ctrl, alt)),
(Keycode::Backslash, false, ctrl, alt) => Some(("\\", false, false, ctrl, alt)),
(Keycode::Backslash, true, ctrl, alt) => Some(("|", false, false, ctrl, alt)),
(Keycode::RBracket, false, ctrl, alt) => Some(("]", false, false, ctrl, alt)),
(Keycode::RBracket, true, ctrl, alt) => Some(("}", false, false, ctrl, alt)),
(Keycode::Caret, shift, ctrl, alt) => Some(("^", false, shift, ctrl, alt)),
(Keycode::Grave, false, ctrl, alt) => Some(("`", false, false, ctrl, alt)),
(Keycode::Grave, true, ctrl, alt) => Some(("~", false, false, ctrl, alt)),
(Keycode::A, shift, ctrl, alt) => Some(("a", false, shift, ctrl, alt)),
(Keycode::B, shift, ctrl, alt) => Some(("b", false, shift, ctrl, alt)),
(Keycode::C, shift, ctrl, alt) => Some(("c", false, shift, ctrl, alt)),
(Keycode::D, shift, ctrl, alt) => Some(("d", false, shift, ctrl, alt)),
(Keycode::E, shift, ctrl, alt) => Some(("e", false, shift, ctrl, alt)),
(Keycode::F, shift, ctrl, alt) => Some(("f", false, shift, ctrl, alt)),
(Keycode::G, shift, ctrl, alt) => Some(("g", false, shift, ctrl, alt)),
(Keycode::H, shift, ctrl, alt) => Some(("h", false, shift, ctrl, alt)),
(Keycode::I, shift, ctrl, alt) => Some(("i", false, shift, ctrl, alt)),
(Keycode::J, shift, ctrl, alt) => Some(("j", false, shift, ctrl, alt)),
(Keycode::K, shift, ctrl, alt) => Some(("k", false, shift, ctrl, alt)),
(Keycode::L, shift, ctrl, alt) => Some(("l", false, shift, ctrl, alt)),
(Keycode::M, shift, ctrl, alt) => Some(("m", false, shift, ctrl, alt)),
(Keycode::N, shift, ctrl, alt) => Some(("n", false, shift, ctrl, alt)),
(Keycode::O, shift, ctrl, alt) => Some(("o", false, shift, ctrl, alt)),
(Keycode::P, shift, ctrl, alt) => Some(("p", false, shift, ctrl, alt)),
(Keycode::Q, shift, ctrl, alt) => Some(("q", false, shift, ctrl, alt)),
(Keycode::R, shift, ctrl, alt) => Some(("r", false, shift, ctrl, alt)),
(Keycode::S, shift, ctrl, alt) => Some(("s", false, shift, ctrl, alt)),
(Keycode::T, shift, ctrl, alt) => Some(("t", false, shift, ctrl, alt)),
(Keycode::U, shift, ctrl, alt) => Some(("u", false, shift, ctrl, alt)),
(Keycode::V, shift, ctrl, alt) => Some(("v", false, shift, ctrl, alt)),
(Keycode::W, shift, ctrl, alt) => Some(("w", false, shift, ctrl, alt)),
(Keycode::X, shift, ctrl, alt) => Some(("x", false, shift, ctrl, alt)),
(Keycode::Y, shift, ctrl, alt) => Some(("y", false, shift, ctrl, alt)),
(Keycode::Z, shift, ctrl, alt) => Some(("z", false, shift, ctrl, alt)),
(Keycode::Delete, shift, ctrl, alt) => Some(("Delete", true, shift, ctrl, alt)),
(Keycode::F1, shift, ctrl, alt) => Some(("F1", true, shift, ctrl, alt)),
(Keycode::F2, shift, ctrl, alt) => Some(("F2", true, shift, ctrl, alt)),
(Keycode::F3, shift, ctrl, alt) => Some(("F3", true, shift, ctrl, alt)),
(Keycode::F4, shift, ctrl, alt) => Some(("F4", true, shift, ctrl, alt)),
(Keycode::F5, shift, ctrl, alt) => Some(("F5", true, shift, ctrl, alt)),
(Keycode::F6, shift, ctrl, alt) => Some(("F6", true, shift, ctrl, alt)),
(Keycode::F7, shift, ctrl, alt) => Some(("F7", true, shift, ctrl, alt)),
(Keycode::F8, shift, ctrl, alt) => Some(("F8", true, shift, ctrl, alt)),
(Keycode::F9, shift, ctrl, alt) => Some(("F9", true, shift, ctrl, alt)),
(Keycode::F10, shift, ctrl, alt) => Some(("F10", true, shift, ctrl, alt)),
(Keycode::F11, shift, ctrl, alt) => Some(("F11", true, shift, ctrl, alt)),
(Keycode::F12, shift, ctrl, alt) => Some(("F12", true, shift, ctrl, alt)),
(Keycode::Snapshot, _, _, _) => unsupported_key(Keycode::Snapshot),
(Keycode::Pause, _, _, _) => unsupported_key(Keycode::Pause),
(Keycode::Insert, shift, ctrl, alt) => Some(("Insert", true, shift, ctrl, alt)),
(Keycode::Home, shift, ctrl, alt) => Some(("Home", true, shift, ctrl, alt)),
(Keycode::PageUp, shift, ctrl, alt) => Some(("PageUp", true, shift, ctrl, alt)),
(Keycode::End, shift, ctrl, alt) => Some(("End", true, shift, ctrl, alt)),
(Keycode::PageDown, shift, ctrl, alt) => Some(("PageDown", true, shift, ctrl, alt)),
(Keycode::Right, shift, ctrl, alt) => Some(("Right", true, shift, ctrl, alt)),
(Keycode::Left, shift, ctrl, alt) => Some(("Left", true, shift, ctrl, alt)),
(Keycode::Down, shift, ctrl, alt) => Some(("Down", true, shift, ctrl, alt)),
(Keycode::Up, shift, ctrl, alt) => Some(("Up", true, shift, ctrl, alt)),
(Keycode::Numpad0, shift, ctrl, alt) => Some(("0", false, shift, ctrl, alt)),
(Keycode::Numpad1, shift, ctrl, alt) => Some(("1", false, shift, ctrl, alt)),
(Keycode::Numpad2, shift, ctrl, alt) => Some(("2", false, shift, ctrl, alt)),
(Keycode::Numpad3, shift, ctrl, alt) => Some(("3", false, shift, ctrl, alt)),
(Keycode::Numpad4, shift, ctrl, alt) => Some(("4", false, shift, ctrl, alt)),
(Keycode::Numpad5, shift, ctrl, alt) => Some(("5", false, shift, ctrl, alt)),
(Keycode::Numpad6, shift, ctrl, alt) => Some(("6", false, shift, ctrl, alt)),
(Keycode::Numpad7, shift, ctrl, alt) => Some(("7", false, shift, ctrl, alt)),
(Keycode::Numpad8, shift, ctrl, alt) => Some(("8", false, shift, ctrl, alt)),
(Keycode::Numpad9, shift, ctrl, alt) => Some(("9", false, shift, ctrl, alt)),
(Keycode::Apps, _, _, _) => unsupported_key(Keycode::Apps),
(Keycode::Power, _, _, _) => unsupported_key(Keycode::Power),
(Keycode::F13, shift, ctrl, alt) => Some(("F13", true, shift, ctrl, alt)),
(Keycode::F14, shift, ctrl, alt) => Some(("F14", true, shift, ctrl, alt)),
(Keycode::F15, shift, ctrl, alt) => Some(("F15", true, shift, ctrl, alt)),
(Keycode::F16, shift, ctrl, alt) => Some(("F16", true, shift, ctrl, alt)),
(Keycode::F17, shift, ctrl, alt) => Some(("F17", true, shift, ctrl, alt)),
(Keycode::F18, shift, ctrl, alt) => Some(("F18", true, shift, ctrl, alt)),
(Keycode::F19, shift, ctrl, alt) => Some(("F19", true, shift, ctrl, alt)),
(Keycode::F20, shift, ctrl, alt) => Some(("F20", true, shift, ctrl, alt)),
(Keycode::F21, shift, ctrl, alt) => Some(("F21", true, shift, ctrl, alt)),
(Keycode::F22, shift, ctrl, alt) => Some(("F22", true, shift, ctrl, alt)),
(Keycode::F23, shift, ctrl, alt) => Some(("F23", true, shift, ctrl, alt)),
(Keycode::F24, shift, ctrl, alt) => Some(("F24", true, shift, ctrl, alt)),
(Keycode::Cut, _, _, _) => unsupported_key(Keycode::Cut),
(Keycode::Copy, _, _, _) => unsupported_key(Keycode::Copy),
(Keycode::Paste, _, _, _) => unsupported_key(Keycode::Paste),
(Keycode::Mute, _, _, _) => unsupported_key(Keycode::Mute),
(Keycode::VolumeUp, _, _, _) => unsupported_key(Keycode::VolumeUp),
(Keycode::VolumeDown, _, _, _) => unsupported_key(Keycode::VolumeDown),
(Keycode::Sysrq, _, _, _) => unsupported_key(Keycode::Sysrq),
(Keycode::LControl, _, _, _) => None,
(Keycode::LShift, _, _, _) => None,
(Keycode::LAlt, _, _, _) => None,
(Keycode::RControl, _, _, _) => None,
(Keycode::RShift, _, _, _) => None,
(Keycode::RAlt, _, _, _) => None,
(Keycode::MediaStop, _, _, _) => unsupported_key(Keycode::MediaStop),
(Keycode::MediaSelect, _, _, _) => unsupported_key(Keycode::MediaSelect),
(Keycode::Calculator, _, _, _) => unsupported_key(Keycode::Calculator),
(Keycode::MyComputer, _, _, _) => unsupported_key(Keycode::MyComputer),
(Keycode::WebSearch, _, _, _) => unsupported_key(Keycode::WebSearch),
(Keycode::WebHome, _, _, _) => unsupported_key(Keycode::WebHome),
(Keycode::WebBack, _, _, _) => unsupported_key(Keycode::WebBack),
(Keycode::WebForward, _, _, _) => unsupported_key(Keycode::WebForward),
(Keycode::NavigateBackward, _, _, _) => unsupported_key(Keycode::NavigateBackward),
(Keycode::NavigateForward, _, _, _) => unsupported_key(Keycode::NavigateForward),
(Keycode::WebStop, _, _, _) => unsupported_key(Keycode::WebStop),
(Keycode::WebRefresh, _, _, _) => unsupported_key(Keycode::WebRefresh),
(Keycode::Sleep, _, _, _) => unsupported_key(Keycode::Sleep),
_ => None,
}
}

@ -0,0 +1,473 @@
#[macro_use]
mod layouts;
use std::sync::atomic::{AtomicBool, Ordering};
use std::sync::mpsc::Receiver;
use std::sync::Arc;
use std::thread::sleep;
use std::time::{Duration, Instant};
use crossfire::mpsc::TxUnbounded;
use image::{load_from_memory, GenericImageView, Pixel};
use log::{debug, error, info, trace};
use skulpin::winit;
use skulpin::winit::dpi::Size;
use skulpin::winit::event::VirtualKeyCode as Keycode;
use skulpin::winit::event::{
ElementState, Event, ModifiersState, MouseButton, MouseScrollDelta, WindowEvent,
};
use skulpin::winit::event_loop::{ControlFlow, EventLoop};
use skulpin::winit::window::{Fullscreen, Icon};
use skulpin::{
CoordinateSystem, LogicalSize, PhysicalSize, PresentMode, Renderer as SkulpinRenderer,
RendererBuilder, Window, WinitWindow,
};
use super::handle_new_grid_size;
use super::settings::*;
pub use super::keyboard;
use crate::bridge::UiCommand;
use crate::editor::WindowCommand;
use crate::error_handling::ResultPanicExplanation;
use crate::redraw_scheduler::REDRAW_SCHEDULER;
use crate::renderer::Renderer;
use crate::settings::*;
use layouts::produce_neovim_keybinding_string;
#[derive(RustEmbed)]
#[folder = "assets/"]
struct Asset;
pub struct WinitWindowWrapper {
window: winit::window::Window,
skulpin_renderer: SkulpinRenderer,
renderer: Renderer,
mouse_down: bool,
mouse_position: LogicalSize,
mouse_enabled: bool,
grid_id_under_mouse: u64,
title: String,
previous_size: LogicalSize,
transparency: f32,
fullscreen: bool,
cached_size: (u32, u32),
cached_position: (i32, i32),
ui_command_sender: TxUnbounded<UiCommand>,
window_command_receiver: Receiver<WindowCommand>,
running: Arc<AtomicBool>,
}
impl WinitWindowWrapper {
pub fn toggle_fullscreen(&mut self) {
if self.fullscreen {
self.window.set_fullscreen(None);
// Use cached size and position
self.window.set_inner_size(self.cached_size.into::<Size>());
self.window.set_outer_position(self.cached_position.into::<Size>());
} else {
self.cached_size = self.window.inner_size().into();
self.cached_position = self.window.outer_position().unwrap().into();
let handle = self.window.current_monitor();
self.window
.set_fullscreen(Some(Fullscreen::Borderless(handle)));
}
self.fullscreen = !self.fullscreen;
}
pub fn synchronize_settings(&mut self) {
let editor_title = { EDITOR.lock().title.clone() };
if self.title != editor_title {
self.title = editor_title;
self.window.set_title(&self.title);
}
let fullscreen = { SETTINGS.get::<WindowSettings>().fullscreen };
if self.fullscreen != fullscreen {
self.toggle_fullscreen();
}
}
pub fn handle_quit(&mut self) {
self.running.store(false, Ordering::Relaxed);
}
pub fn handle_keyboard_input(
&mut self,
keycode: Option<Keycode>,
modifiers: Option<ModifiersState>,
) {
if keycode.is_some() {
trace!(
"Keyboard Input Received: keycode-{:?} modifiers-{:?} ",
keycode,
modifiers
);
}
if let Some(keybinding_string) = produce_neovim_keybinding_string(keycode, None, modifiers)
{
self.ui_command_sender
.send(UiCommand::Keyboard(keybinding_string))
.unwrap_or_explained_panic(
"Could not send UI command from the window system to the neovim process.",
);
}
}
pub fn handle_pointer_motion(&mut self, x: i32, y: i32) {
let previous_position = self.mouse_position;
let winit_window_wrapper = WinitWindow::new(&self.window);
let logical_position =
PhysicalSize::new(x as u32, y as u32).to_logical(winit_window_wrapper.scale_factor());
let mut top_window_position = (0.0, 0.0);
let mut top_grid_position = None;
for details in self.renderer.window_regions.iter() {
if logical_position.width >= details.region.left as u32
&& logical_position.width < details.region.right as u32
&& logical_position.height >= details.region.top as u32
&& logical_position.height < details.region.bottom as u32
{
top_window_position = (details.region.left, details.region.top);
top_grid_position = Some((
details.id,
LogicalSize::new(
logical_position.width - details.region.left as u32,
logical_position.height - details.region.top as u32,
),
details.floating,
));
}
}
if let Some((grid_id, grid_position, grid_floating)) = top_grid_position {
self.grid_id_under_mouse = grid_id;
self.mouse_position = LogicalSize::new(
(grid_position.width as f32 / self.renderer.font_width) as u32,
(grid_position.height as f32 / self.renderer.font_height) as u32,
);
if self.mouse_enabled && self.mouse_down && previous_position != self.mouse_position {
let (window_left, window_top) = top_window_position;
// Until https://github.com/neovim/neovim/pull/12667 is merged, we have to special
// case non floating windows. Floating windows correctly transform mouse positions
// into grid coordinates, but non floating windows do not.
let position = if grid_floating {
(self.mouse_position.width, self.mouse_position.height)
} else {
let adjusted_drag_left =
self.mouse_position.width + (window_left / self.renderer.font_width) as u32;
let adjusted_drag_top = self.mouse_position.height
+ (window_top / self.renderer.font_height) as u32;
(adjusted_drag_left, adjusted_drag_top)
};
self.ui_command_sender
.send(UiCommand::Drag {
grid_id: self.grid_id_under_mouse,
position,
})
.ok();
}
}
}
pub fn handle_pointer_down(&mut self) {
if self.mouse_enabled {
self.ui_command_sender
.send(UiCommand::MouseButton {
action: String::from("press"),
grid_id: self.grid_id_under_mouse,
position: (self.mouse_position.width, self.mouse_position.height),
})
.ok();
}
self.mouse_down = true;
}
pub fn handle_pointer_up(&mut self) {
if self.mouse_enabled {
self.ui_command_sender
.send(UiCommand::MouseButton {
action: String::from("release"),
grid_id: self.grid_id_under_mouse,
position: (self.mouse_position.width, self.mouse_position.height),
})
.ok();
}
self.mouse_down = false;
}
pub fn handle_mouse_wheel(&mut self, x: i32, y: i32) {
if !self.mouse_enabled {
return;
}
let vertical_input_type = match y {
_ if y > 0 => Some("up"),
_ if y < 0 => Some("down"),
_ => None,
};
if let Some(input_type) = vertical_input_type {
self.ui_command_sender
.send(UiCommand::Scroll {
direction: input_type.to_string(),
grid_id: self.grid_id_under_mouse,
position: (self.mouse_position.width, self.mouse_position.height),
})
.ok();
}
let horizontal_input_type = match y {
_ if x > 0 => Some("right"),
_ if x < 0 => Some("left"),
_ => None,
};
if let Some(input_type) = horizontal_input_type {
self.ui_command_sender
.send(UiCommand::Scroll {
direction: input_type.to_string(),
grid_id: self.grid_id_under_mouse,
position: (self.mouse_position.width, self.mouse_position.height),
})
.ok();
}
}
pub fn handle_focus_lost(&mut self) {
self.ui_command_sender.send(UiCommand::FocusLost).ok();
}
pub fn handle_focus_gained(&mut self) {
self.ui_command_sender.send(UiCommand::FocusGained).ok();
REDRAW_SCHEDULER.queue_next_frame();
}
pub fn handle_event(&mut self, event: Event<()>) {
let mut keycode = None;
let mut modifiers = None;
let mut ignore_text_this_frame = false;
match event {
Event::LoopDestroyed => {
self.handle_quit();
}
Event::WindowEvent {
event: WindowEvent::CloseRequested,
..
} => {
self.handle_quit();
}
Event::WindowEvent {
event: WindowEvent::DroppedFile(path),
..
} => {
self.ui_command_sender.send(UiCommand::FileDrop(
path.into_os_string().into_string().unwrap(),
)).ok();
}
Event::WindowEvent {
event: WindowEvent::KeyboardInput { input, .. },
..
} => {
if input.state == ElementState::Pressed {
keycode = input.virtual_keycode;
}
}
Event::WindowEvent {
event: WindowEvent::ModifiersChanged(m),
..
} => {
modifiers = Some(m);
}
Event::WindowEvent {
event: WindowEvent::CursorMoved { position, .. },
..
} => self.handle_pointer_motion(position.x as i32, position.y as i32),
Event::WindowEvent {
event:
WindowEvent::MouseWheel {
delta: MouseScrollDelta::LineDelta(x, y),
..
},
..
} => self.handle_mouse_wheel(x as i32, y as i32),
Event::WindowEvent {
event:
WindowEvent::MouseInput {
button: MouseButton::Left,
state,
..
},
..
} => {
if state == ElementState::Pressed {
self.handle_pointer_down();
} else {
self.handle_pointer_up();
}
}
Event::WindowEvent {
event: WindowEvent::Focused(focus),
..
} => {
if focus {
ignore_text_this_frame = true; // Ignore any text events on the first frame when focus is regained. https://github.com/Kethku/neovide/issues/193
self.handle_focus_gained();
} else {
self.handle_focus_lost();
}
}
Event::WindowEvent { .. } => REDRAW_SCHEDULER.queue_next_frame(),
_ => {}
}
if !ignore_text_this_frame {
window.handle_keyboard_input(keycode, modifiers);
}
}
pub fn draw_frame(&mut self, dt: f32) -> VkResult<bool> {
let winit_window_wrapper = WinitWindow::new(&self.window);
let new_size = winit_window_wrapper.logical_size();
if self.previous_size != new_size {
handle_new_grid_size(new_size, &self.renderer, &self.ui_command_sender);
self.previous_size = new_size;
}
let current_size = self.previous_size;
let ui_command_sender = self.ui_command_sender.clone();
if REDRAW_SCHEDULER.should_draw() || SETTINGS.get::<WindowSettings>().no_idle {
debug!("Render Triggered");
let renderer = &mut self.renderer;
self.skulpin_renderer.draw(
&sdl_window_wrapper,
|canvas, coordinate_system_helper| {
if renderer.draw_frame(canvas, &coordinate_system_helper, dt) {
handle_new_grid_size(current_size, &renderer, &ui_command_sender);
}
},
)?;
Ok(true)
} else {
Ok(false)
}
}
}
pub fn start_loop(
window_command_receiver: Receiver<WindowCommand>,
ui_command_sender: TxUnbounded<UiCommand>,
running: Arc<AtomicBool>,
logical_size: LogicalSize,
renderer: Renderer,
) {
let icon = {
let icon_data = Asset::get("nvim.ico").expect("Failed to read icon data");
let icon = load_from_memory(&icon_data).expect("Failed to parse icon data");
let (width, height) = icon.dimensions();
let mut rgba = Vec::with_capacity((width * height) as usize * 4);
for (_, _, pixel) in icon.pixels() {
rgba.extend_from_slice(&pixel.to_rgba().0);
}
Icon::from_rgba(rgba, width, height).expect("Failed to create icon object")
};
info!("icon created");
let winit_window = winit::window::WindowBuilder::new()
.with_title("Neovide")
.with_inner_size((logical_size.width, logical_size.height).into())
.with_window_icon(Some(icon))
.build(event_loop)
.expect("Failed to create window");
info!("window created");
let scale_factor = winit_window.scale_factor();
let skulpin_renderer = {
let winit_window_wrapper = WinitWindow::new(&winit_window);
RendererBuilder::new()
.prefer_integrated_gpu()
.use_vulkan_debug_layer(false)
.present_mode_priority(vec![PresentMode::Immediate])
.coordinate_system(CoordinateSystem::Logical)
.build(&winit_window_wrapper)
.expect("Failed to create renderer")
};
let mut window_wrapper = WinitWindowWrapper {
window: winit_window,
skulpin_renderer,
renderer,
mouse_down: false,
mouse_position: LogicalSize {
width: 0,
height: 0,
},
mouse_enabled: true,
grid_id_under_mouse: 0,
title: String::from("Neovide"),
previous_size: logical_size,
transparency: 1.0,
fullscreen: false,
cached_size: (0, 0),
cached_position: (0, 0),
ui_command_sender,
window_command_receiver,
running: running.clone(),
};
let mut was_animating = false;
let mut previous_frame_start = Instant::now();
let event_loop = EventLoop::new();
event_loop.run(move |e, _window_target, control_flow| {
if !running.load(Ordering::Relaxed) {
*control_flow = ControlFlow::Exit;
return;
}
let frame_start = Instant::now();
let refresh_rate = { SETTINGS.get::<WindowSettings>().refresh_rate as f32 };
let dt = if was_animating {
previous_frame_start.elapsed().as_secs_f32()
} else {
1.0 / refresh_rate
};
window_wrapper.synchronize_settings();
window_wrapper.handle_event(e);
match window_wrapper.draw_frame(dt) {
Ok(animating) => {
was_animating = animating;
}
Err(error) => {
error!("Render failed: {}", error);
self.running.store(false, Ordering::Relaxed);
return;
}
}
let elapsed = frame_start.elapsed();
let frame_length = Duration::from_secs_f32(1.0 / refresh_rate);
if elapsed < frame_length {
*control_flow = ControlFlow::WaitUntil(Instant::now() + frame_length);
}
});
}
Loading…
Cancel
Save