From e4dd7e572baa39ec25c5a711e2f95120e9c6dd57 Mon Sep 17 00:00:00 2001 From: Keith Simmons Date: Tue, 21 Jan 2020 17:48:44 -0800 Subject: [PATCH] finish up cursor options --- Cargo.lock | 1 + Cargo.toml | 2 +- src/main.rs | 1 + src/redraw_scheduler.rs | 28 ++++++++++++++++++++++++++++ src/renderer/cursor_renderer.rs | 29 ++++++++++++++++++----------- src/renderer/mod.rs | 9 ++++++--- src/window.rs | 9 +++++++-- 7 files changed, 62 insertions(+), 17 deletions(-) create mode 100644 src/redraw_scheduler.rs diff --git a/Cargo.lock b/Cargo.lock index 52d3350..d46dd6d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2425,6 +2425,7 @@ dependencies = [ "num_cpus", "pin-project-lite", "signal-hook-registry", + "slab", "tokio-macros", "winapi 0.3.8", ] diff --git a/Cargo.toml b/Cargo.toml index 21fb009..4917eeb 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -20,7 +20,7 @@ rust-embed = { version = "5.2.0", features = ["debug-embed"] } image = "0.22.3" #nvim-rs = "0.1.0" 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" [build-dependencies] diff --git a/src/main.rs b/src/main.rs index dfe385a..d2b8c16 100644 --- a/src/main.rs +++ b/src/main.rs @@ -5,6 +5,7 @@ mod editor; mod window; mod renderer; mod error_handling; +mod redraw_scheduler; #[macro_use] extern crate derive_new; #[macro_use] extern crate rust_embed; diff --git a/src/redraw_scheduler.rs b/src/redraw_scheduler.rs new file mode 100644 index 0000000..64075f8 --- /dev/null +++ b/src/redraw_scheduler.rs @@ -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 +} + +impl RedrawScheduler { + pub fn new(window: &Arc) -> 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(); + }); + } +} diff --git a/src/renderer/cursor_renderer.rs b/src/renderer/cursor_renderer.rs index 39d661f..a9b467b 100644 --- a/src/renderer/cursor_renderer.rs +++ b/src/renderer/cursor_renderer.rs @@ -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) { if self.previous_cursor.is_none() || new_cursor != self.previous_cursor.as_ref().unwrap() { self.previous_cursor = Some(new_cursor.clone()); self.last_transition = Instant::now(); @@ -48,16 +48,16 @@ impl BlinkStatus { if new_cursor.blinkwait == Some(0) || new_cursor.blinkoff == Some(0) || new_cursor.blinkon == Some(0) { - return true; + return (true, None); } let delay = match self.state { BlinkState::Waiting => new_cursor.blinkwait, BlinkState::Off => new_cursor.blinkoff, 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 { BlinkState::Waiting => BlinkState::On, BlinkState::On => BlinkState::Off, @@ -66,10 +66,17 @@ impl BlinkStatus { self.last_transition = Instant::now(); } - match self.state { - BlinkState::Waiting | BlinkState::Off => false, - BlinkState::On => true - } + ( + match self.state { + BlinkState::Waiting | BlinkState::Off => false, + 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, paint: &mut Paint, editor: Arc>, shaper: &mut CachingShaper, fonts_lookup: &mut FontLookup, - canvas: &mut Canvas) -> bool { - let render = self.blink_status.update_status(&cursor); + canvas: &mut Canvas) -> (bool, Option) { + let (render, scheduled_update) = self.blink_status.update_status(&cursor); self.previous_position = { let editor = editor.lock().unwrap(); @@ -233,6 +240,6 @@ impl CursorRenderer { canvas.restore(); } - animating + (animating, scheduled_update) } } diff --git a/src/renderer/mod.rs b/src/renderer/mod.rs index 15626fa..76cb240 100644 --- a/src/renderer/mod.rs +++ b/src/renderer/mod.rs @@ -1,4 +1,6 @@ use std::sync::{Arc, Mutex}; +use std::time::Instant; + use skulpin::CoordinateSystemHelper; use skulpin::skia_safe::{Canvas, Paint, Surface, Budgeted, Rect, colors}; use skulpin::skia_safe::gpu::SurfaceOrigin; @@ -19,7 +21,8 @@ const DEFAULT_FONT_SIZE: f32 = 14.0; #[derive(new)] pub struct DrawResult { pub is_animating: bool, - pub font_changed: bool + pub font_changed: bool, + pub scheduled_update: Option } pub struct Renderer { @@ -167,13 +170,13 @@ impl Renderer { self.surface = Some(surface); - let cursor_animating = self.cursor_renderer.draw( + let (cursor_animating, scheduled_cursor_update) = self.cursor_renderer.draw( cursor, &default_colors, self.font_width, self.font_height, &mut self.paint, self.editor.clone(), &mut self.shaper, &mut self.fonts_lookup, 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) } } diff --git a/src/window.rs b/src/window.rs index c2c8576..52d2497 100644 --- a/src/window.rs +++ b/src/window.rs @@ -10,9 +10,9 @@ use skulpin::winit::event_loop::{ControlFlow, EventLoop}; use skulpin::winit::window::{Icon, WindowBuilder}; 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::bridge::UiCommand; +use crate::redraw_scheduler::RedrawScheduler; #[derive(RustEmbed)] #[folder = "assets/"] @@ -75,6 +75,7 @@ pub fn ui_loop(editor: Arc>, mut bridge: Bridge, initial_size: (u6 editor.window = Some(window.clone()); } + let redraw_scheduler = RedrawScheduler::new(&window); let mut live_frames = 0; let mut frame_start = Instant::now(); event_loop.run(move |event, _window_target, control_flow| { @@ -197,6 +198,10 @@ pub fn ui_loop(editor: Arc>, mut bridge: Bridge, initial_size: (u6 } else { *control_flow = ControlFlow::Wait; } + + if let Some(scheduled_update) = draw_result.scheduled_update { + redraw_scheduler.schedule(scheduled_update); + } }) { println!("Error during draw: {:?}", e); *control_flow = ControlFlow::Exit