finish up cursor options

macos-click-through
Keith Simmons 5 years ago
parent a1ad41247d
commit e4dd7e572b

1
Cargo.lock generated

@ -2425,6 +2425,7 @@ dependencies = [
"num_cpus", "num_cpus",
"pin-project-lite", "pin-project-lite",
"signal-hook-registry", "signal-hook-registry",
"slab",
"tokio-macros", "tokio-macros",
"winapi 0.3.8", "winapi 0.3.8",
] ]

@ -20,7 +20,7 @@ rust-embed = { version = "5.2.0", features = ["debug-embed"] }
image = "0.22.3" image = "0.22.3"
#nvim-rs = "0.1.0" #nvim-rs = "0.1.0"
nvim-rs = { git = "https://github.com/KillTheMule/nvim-rs", branch = "futures", features = [ "use_tokio" ] } nvim-rs = { git = "https://github.com/KillTheMule/nvim-rs", branch = "futures", features = [ "use_tokio" ] }
tokio = { version = "0.2.9", features = [ "blocking", "process" ] } tokio = { version = "0.2.9", features = [ "blocking", "process", "time" ] }
async-trait = "0.1.18" async-trait = "0.1.18"
[build-dependencies] [build-dependencies]

@ -5,6 +5,7 @@ mod editor;
mod window; mod window;
mod renderer; mod renderer;
mod error_handling; mod error_handling;
mod redraw_scheduler;
#[macro_use] extern crate derive_new; #[macro_use] extern crate derive_new;
#[macro_use] extern crate rust_embed; #[macro_use] extern crate rust_embed;

@ -0,0 +1,28 @@
use std::sync::Arc;
use std::time::Instant;
use skulpin::winit::window::Window;
use tokio::runtime::Runtime;
use tokio::time::{Instant as TokioInstant, delay_until};
pub struct RedrawScheduler {
runtime: Runtime,
window: Arc<Window>
}
impl RedrawScheduler {
pub fn new(window: &Arc<Window>) -> RedrawScheduler {
RedrawScheduler {
runtime: Runtime::new().unwrap(),
window: window.clone()
}
}
pub fn schedule(&self, time: Instant) {
let window = self.window.clone();
self.runtime.spawn(async move {
delay_until(TokioInstant::from_std(time)).await;
window.request_redraw();
});
}
}

@ -34,7 +34,7 @@ impl BlinkStatus {
} }
} }
pub fn update_status(&mut self, new_cursor: &Cursor) -> bool { pub fn update_status(&mut self, new_cursor: &Cursor) -> (bool, Option<Instant>) {
if self.previous_cursor.is_none() || new_cursor != self.previous_cursor.as_ref().unwrap() { if self.previous_cursor.is_none() || new_cursor != self.previous_cursor.as_ref().unwrap() {
self.previous_cursor = Some(new_cursor.clone()); self.previous_cursor = Some(new_cursor.clone());
self.last_transition = Instant::now(); self.last_transition = Instant::now();
@ -48,16 +48,16 @@ impl BlinkStatus {
if new_cursor.blinkwait == Some(0) || if new_cursor.blinkwait == Some(0) ||
new_cursor.blinkoff == Some(0) || new_cursor.blinkoff == Some(0) ||
new_cursor.blinkon == Some(0) { new_cursor.blinkon == Some(0) {
return true; return (true, None);
} }
let delay = match self.state { let delay = match self.state {
BlinkState::Waiting => new_cursor.blinkwait, BlinkState::Waiting => new_cursor.blinkwait,
BlinkState::Off => new_cursor.blinkoff, BlinkState::Off => new_cursor.blinkoff,
BlinkState::On => new_cursor.blinkon BlinkState::On => new_cursor.blinkon
}.filter(|millis| millis > &0).map(Duration::from_millis); }.filter(|millis| millis > &0).map(|millis| Duration::from_millis(millis));
if delay.map(|delay| Instant::now() - self.last_transition > delay).unwrap_or(false) { if delay.map(|delay| self.last_transition + delay < Instant::now()).unwrap_or(false) {
self.state = match self.state { self.state = match self.state {
BlinkState::Waiting => BlinkState::On, BlinkState::Waiting => BlinkState::On,
BlinkState::On => BlinkState::Off, BlinkState::On => BlinkState::Off,
@ -66,10 +66,17 @@ impl BlinkStatus {
self.last_transition = Instant::now(); self.last_transition = Instant::now();
} }
(
match self.state { match self.state {
BlinkState::Waiting | BlinkState::Off => false, BlinkState::Waiting | BlinkState::Off => false,
BlinkState::On => true BlinkState::On => true
} },
(match self.state {
BlinkState::Waiting => new_cursor.blinkwait,
BlinkState::Off => new_cursor.blinkoff,
BlinkState::On => new_cursor.blinkon
}).map(|delay| self.last_transition + Duration::from_millis(delay))
)
} }
} }
@ -166,8 +173,8 @@ impl CursorRenderer {
font_width: f32, font_height: f32, font_width: f32, font_height: f32,
paint: &mut Paint, editor: Arc<Mutex<Editor>>, paint: &mut Paint, editor: Arc<Mutex<Editor>>,
shaper: &mut CachingShaper, fonts_lookup: &mut FontLookup, shaper: &mut CachingShaper, fonts_lookup: &mut FontLookup,
canvas: &mut Canvas) -> bool { canvas: &mut Canvas) -> (bool, Option<Instant>) {
let render = self.blink_status.update_status(&cursor); let (render, scheduled_update) = self.blink_status.update_status(&cursor);
self.previous_position = { self.previous_position = {
let editor = editor.lock().unwrap(); let editor = editor.lock().unwrap();
@ -233,6 +240,6 @@ impl CursorRenderer {
canvas.restore(); canvas.restore();
} }
animating (animating, scheduled_update)
} }
} }

@ -1,4 +1,6 @@
use std::sync::{Arc, Mutex}; use std::sync::{Arc, Mutex};
use std::time::Instant;
use skulpin::CoordinateSystemHelper; use skulpin::CoordinateSystemHelper;
use skulpin::skia_safe::{Canvas, Paint, Surface, Budgeted, Rect, colors}; use skulpin::skia_safe::{Canvas, Paint, Surface, Budgeted, Rect, colors};
use skulpin::skia_safe::gpu::SurfaceOrigin; use skulpin::skia_safe::gpu::SurfaceOrigin;
@ -19,7 +21,8 @@ const DEFAULT_FONT_SIZE: f32 = 14.0;
#[derive(new)] #[derive(new)]
pub struct DrawResult { pub struct DrawResult {
pub is_animating: bool, pub is_animating: bool,
pub font_changed: bool pub font_changed: bool,
pub scheduled_update: Option<Instant>
} }
pub struct Renderer { pub struct Renderer {
@ -167,13 +170,13 @@ impl Renderer {
self.surface = Some(surface); self.surface = Some(surface);
let cursor_animating = self.cursor_renderer.draw( let (cursor_animating, scheduled_cursor_update) = self.cursor_renderer.draw(
cursor, &default_colors, cursor, &default_colors,
self.font_width, self.font_height, self.font_width, self.font_height,
&mut self.paint, self.editor.clone(), &mut self.paint, self.editor.clone(),
&mut self.shaper, &mut self.fonts_lookup, &mut self.shaper, &mut self.fonts_lookup,
gpu_canvas); gpu_canvas);
DrawResult::new(draw_commands.len() > 0 || cursor_animating, font_changed) DrawResult::new(draw_commands.len() > 0 || cursor_animating, font_changed, scheduled_cursor_update)
} }
} }

@ -10,9 +10,9 @@ use skulpin::winit::event_loop::{ControlFlow, EventLoop};
use skulpin::winit::window::{Icon, WindowBuilder}; use skulpin::winit::window::{Icon, WindowBuilder};
use crate::editor::Editor; use crate::editor::Editor;
use crate::bridge::{construct_keybinding_string, Bridge}; use crate::bridge::{construct_keybinding_string, Bridge, UiCommand};
use crate::renderer::Renderer; use crate::renderer::Renderer;
use crate::bridge::UiCommand; use crate::redraw_scheduler::RedrawScheduler;
#[derive(RustEmbed)] #[derive(RustEmbed)]
#[folder = "assets/"] #[folder = "assets/"]
@ -75,6 +75,7 @@ pub fn ui_loop(editor: Arc<Mutex<Editor>>, mut bridge: Bridge, initial_size: (u6
editor.window = Some(window.clone()); editor.window = Some(window.clone());
} }
let redraw_scheduler = RedrawScheduler::new(&window);
let mut live_frames = 0; let mut live_frames = 0;
let mut frame_start = Instant::now(); let mut frame_start = Instant::now();
event_loop.run(move |event, _window_target, control_flow| { event_loop.run(move |event, _window_target, control_flow| {
@ -197,6 +198,10 @@ pub fn ui_loop(editor: Arc<Mutex<Editor>>, mut bridge: Bridge, initial_size: (u6
} else { } else {
*control_flow = ControlFlow::Wait; *control_flow = ControlFlow::Wait;
} }
if let Some(scheduled_update) = draw_result.scheduled_update {
redraw_scheduler.schedule(scheduled_update);
}
}) { }) {
println!("Error during draw: {:?}", e); println!("Error during draw: {:?}", e);
*control_flow = ControlFlow::Exit *control_flow = ControlFlow::Exit

Loading…
Cancel
Save