winit working

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

@ -1,4 +1,4 @@
use log::{error, trace}; use log::error;
use crate::settings::*; use crate::settings::*;

@ -1,5 +1,5 @@
mod settings;
pub mod keyboard; pub mod keyboard;
mod settings;
#[cfg_attr(feature = "sdl2", path = "sdl2/mod.rs")] #[cfg_attr(feature = "sdl2", path = "sdl2/mod.rs")]
#[cfg_attr(feature = "winit", path = "winit/mod.rs")] #[cfg_attr(feature = "winit", path = "winit/mod.rs")]
@ -19,6 +19,8 @@ use crate::INITIAL_DIMENSIONS;
#[cfg(feature = "sdl2")] #[cfg(feature = "sdl2")]
pub use window_wrapper::start_loop; pub use window_wrapper::start_loop;
#[cfg(feature = "winit")]
pub use window_wrapper::start_loop;
pub use settings::*; pub use settings::*;

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

@ -22,8 +22,8 @@ use skulpin::{
}; };
use super::handle_new_grid_size; use super::handle_new_grid_size;
use super::settings::*;
pub use super::keyboard; pub use super::keyboard;
use super::settings::*;
use crate::bridge::UiCommand; use crate::bridge::UiCommand;
use crate::editor::WindowCommand; use crate::editor::WindowCommand;
use crate::error_handling::ResultPanicExplanation; use crate::error_handling::ResultPanicExplanation;

@ -1,30 +1,30 @@
use crate::settings::*; use super::keyboard::initialize_settings as keyboard_initialize_settings;
use super::keyboard::initialize_settings as keyboard_initialize_settings; use crate::settings::*;
#[derive(Clone)] #[derive(Clone)]
pub struct WindowSettings { pub struct WindowSettings {
pub refresh_rate: u64, pub refresh_rate: u64,
pub transparency: f32, pub transparency: f32,
pub no_idle: bool, pub no_idle: bool,
pub fullscreen: bool, pub fullscreen: bool,
} }
pub fn initialize_settings() { pub fn initialize_settings() {
let no_idle = SETTINGS let no_idle = SETTINGS
.neovim_arguments .neovim_arguments
.contains(&String::from("--noIdle")); .contains(&String::from("--noIdle"));
SETTINGS.set(&WindowSettings { SETTINGS.set(&WindowSettings {
refresh_rate: 60, refresh_rate: 60,
transparency: 1.0, transparency: 1.0,
no_idle, no_idle,
fullscreen: false, fullscreen: false,
}); });
register_nvim_setting!("refresh_rate", WindowSettings::refresh_rate); register_nvim_setting!("refresh_rate", WindowSettings::refresh_rate);
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(); keyboard_initialize_settings();
} }

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

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