mostly working

macos-click-through
keith 4 years ago
parent 15d02a0417
commit 8b87f92f5f

@ -700,7 +700,7 @@ fn parse_win_external_pos(win_external_pos_arguments: Vec<Value>) -> Result<Redr
let [grid, _window] = extract_values(win_external_pos_arguments, [Value::Nil, Value::Nil])?; let [grid, _window] = extract_values(win_external_pos_arguments, [Value::Nil, Value::Nil])?;
Ok(RedrawEvent::WindowExternalPosition { Ok(RedrawEvent::WindowExternalPosition {
grid: parse_u64(grid)? grid: parse_u64(grid)?,
}) })
} }

@ -4,12 +4,12 @@ pub mod layouts;
mod events; mod events;
mod ui_commands; mod ui_commands;
use std::process::{Stdio, Command};
use std::sync::atomic::{AtomicBool, Ordering};
use std::sync::Arc;
use std::sync::mpsc::{Sender, Receiver};
use std::env; use std::env;
use std::path::Path; use std::path::Path;
use std::process::{Command, Stdio};
use std::sync::atomic::{AtomicBool, Ordering};
use std::sync::mpsc::{Receiver, Sender};
use std::sync::Arc;
use std::thread; use std::thread;
#[cfg(windows)] #[cfg(windows)]
@ -108,10 +108,16 @@ pub fn create_nvim_command() -> Command {
cmd cmd
} }
pub fn start_bridge(ui_command_sender: Sender<UiCommand>, ui_command_receiver: Receiver<UiCommand>, redraw_event_sender: Sender<RedrawEvent>, running: Arc<AtomicBool>) { pub fn start_bridge(
ui_command_sender: Sender<UiCommand>,
ui_command_receiver: Receiver<UiCommand>,
redraw_event_sender: Sender<RedrawEvent>,
running: Arc<AtomicBool>,
) {
thread::spawn(move || { thread::spawn(move || {
let (width, height) = window_geometry_or_default(); let (width, height) = window_geometry_or_default();
let mut session = Session::new_child_cmd(&mut create_nvim_command()).unwrap_or_explained_panic("Could not locate or start neovim process"); let mut session = Session::new_child_cmd(&mut create_nvim_command())
.unwrap_or_explained_panic("Could not locate or start neovim process");
let notification_receiver = session.start_event_loop_channel(); let notification_receiver = session.start_event_loop_channel();
let mut nvim = Neovim::new(session); let mut nvim = Neovim::new(session);
@ -126,7 +132,8 @@ pub fn start_bridge(ui_command_sender: Sender<UiCommand>, ui_command_receiver: R
std::process::exit(0); std::process::exit(0);
}; };
nvim.set_var("neovide", Value::Boolean(true)).unwrap_or_explained_panic("Could not communicate with neovim process"); nvim.set_var("neovide", Value::Boolean(true))
.unwrap_or_explained_panic("Could not communicate with neovim process");
if let Err(command_error) = nvim.command("runtime! ginit.vim") { if let Err(command_error) = nvim.command("runtime! ginit.vim") {
nvim.command(&format!( nvim.command(&format!(
"echomsg \"error encountered in ginit.vim {:?}\"", "echomsg \"error encountered in ginit.vim {:?}\"",
@ -200,61 +207,58 @@ pub fn start_bridge(ui_command_sender: Sender<UiCommand>, ui_command_receiver: R
SETTINGS.setup_changed_listeners(&mut nvim); SETTINGS.setup_changed_listeners(&mut nvim);
let notification_running = running.clone(); let notification_running = running.clone();
thread::spawn(move || { thread::spawn(move || loop {
loop { if !notification_running.load(Ordering::Relaxed) {
if !notification_running.load(Ordering::Relaxed) { break;
break; }
}
match notification_receiver.recv() { match notification_receiver.recv() {
Ok((event_name, arguments)) => Ok((event_name, arguments)) => match event_name.as_ref() {
match event_name.as_ref() { "redraw" => {
"redraw" => { for events in arguments {
for events in arguments { let parsed_events = parse_redraw_event(events)
let parsed_events = parse_redraw_event(events) .unwrap_or_explained_panic("Could not parse event from neovim");
.unwrap_or_explained_panic("Could not parse event from neovim");
for parsed_event in parsed_events {
for parsed_event in parsed_events { redraw_event_sender.send(parsed_event).ok();
redraw_event_sender.send(parsed_event).ok();
}
}
}
"setting_changed" => {
SETTINGS.handle_changed_notification(arguments);
}
#[cfg(windows)]
"neovide.register_right_click" => {
ui_command_sender.send(UiCommand::RegisterRightClick).ok();
}
#[cfg(windows)]
"neovide.unregister_right_click" => {
ui_command_sender.send(UiCommand::UnregisterRightClick).ok();
} }
_ => {} }
},
Err(error) => {
notification_running.store(false, Ordering::Relaxed);
break;
} }
"setting_changed" => {
SETTINGS.handle_changed_notification(arguments);
}
#[cfg(windows)]
"neovide.register_right_click" => {
ui_command_sender.send(UiCommand::RegisterRightClick).ok();
}
#[cfg(windows)]
"neovide.unregister_right_click" => {
ui_command_sender.send(UiCommand::UnregisterRightClick).ok();
}
_ => {}
},
Err(error) => {
error!("Notification channel closed: {}", error);
notification_running.store(false, Ordering::Relaxed);
break;
} }
} }
}); });
let ui_command_running = running.clone(); let ui_command_running = running.clone();
thread::spawn(move || { thread::spawn(move || loop {
loop { if !ui_command_running.load(Ordering::Relaxed) {
if !ui_command_running.load(Ordering::Relaxed) { break;
break; }
}
match ui_command_receiver.recv() { match ui_command_receiver.recv() {
Ok(ui_command) => { Ok(ui_command) => {
ui_command.execute(&mut nvim); ui_command.execute(&mut nvim);
}, }
Err(error) => { Err(error) => {
ui_command_running.store(false, Ordering::Relaxed); error!("Ui command channel closed: {}", error);
break; ui_command_running.store(false, Ordering::Relaxed);
} break;
} }
} }
}); });

@ -52,23 +52,44 @@ impl UiCommand {
grid_id, grid_id,
position: (grid_x, grid_y), position: (grid_x, grid_y),
} => { } => {
nvim.input_mouse("left", &action, "", grid_id as i64, grid_y as i64, grid_x as i64) nvim.input_mouse(
.expect("Mouse Input Failed"); "left",
&action,
"",
grid_id as i64,
grid_y as i64,
grid_x as i64,
)
.expect("Mouse Input Failed");
} }
UiCommand::Scroll { UiCommand::Scroll {
direction, direction,
grid_id, grid_id,
position: (grid_x, grid_y), position: (grid_x, grid_y),
} => { } => {
nvim.input_mouse("wheel", &direction, "", grid_id as i64, grid_y as i64, grid_x as i64) nvim.input_mouse(
.expect("Mouse Scroll Failed"); "wheel",
&direction,
"",
grid_id as i64,
grid_y as i64,
grid_x as i64,
)
.expect("Mouse Scroll Failed");
} }
UiCommand::Drag { UiCommand::Drag {
grid_id, grid_id,
position: (grid_x, grid_y) position: (grid_x, grid_y),
} => { } => {
nvim.input_mouse("left", "drag", "", grid_id as i64, grid_y as i64, grid_x as i64) nvim.input_mouse(
.expect("Mouse Drag Failed"); "left",
"drag",
"",
grid_id as i64,
grid_y as i64,
grid_x as i64,
)
.expect("Mouse Drag Failed");
} }
UiCommand::FocusLost => nvim UiCommand::FocusLost => nvim
.command("if exists('#FocusLost') | doautocmd <nomodeline> FocusLost | endif") .command("if exists('#FocusLost') | doautocmd <nomodeline> FocusLost | endif")

@ -0,0 +1,31 @@
use std::sync::mpsc::{channel, Receiver, SendError, Sender};
use super::DrawCommand;
pub struct DrawCommandBatcher {
window_draw_command_sender: Sender<DrawCommand>,
window_draw_command_receiver: Receiver<DrawCommand>,
batched_draw_command_sender: Sender<Vec<DrawCommand>>,
}
impl DrawCommandBatcher {
pub fn new(batched_draw_command_sender: Sender<Vec<DrawCommand>>) -> DrawCommandBatcher {
let (sender, receiver) = channel();
DrawCommandBatcher {
window_draw_command_sender: sender,
window_draw_command_receiver: receiver,
batched_draw_command_sender,
}
}
pub fn queue(&self, draw_command: DrawCommand) -> Result<(), SendError<DrawCommand>> {
self.window_draw_command_sender.send(draw_command)
}
pub fn send_batch(&self) -> Result<(), SendError<Vec<DrawCommand>>> {
let batch = self.window_draw_command_receiver.try_iter().collect();
self.batched_draw_command_sender.send(batch)
}
}

@ -71,7 +71,10 @@ impl CharacterGrid {
pub fn row(&self, row_index: u64) -> Option<&[GridCell]> { pub fn row(&self, row_index: u64) -> Option<&[GridCell]> {
if row_index < self.height { if row_index < self.height {
Some(&self.characters[(row_index * self.width) as usize..((row_index + 1) * self.width) as usize]) Some(
&self.characters
[(row_index * self.width) as usize..((row_index + 1) * self.width) as usize],
)
} else { } else {
None None
} }
@ -230,7 +233,6 @@ mod tests {
(thread_rng().gen::<u64>() % 500) + 1, (thread_rng().gen::<u64>() % 500) + 1,
(thread_rng().gen::<u64>() % 500) + 1, (thread_rng().gen::<u64>() % 500) + 1,
); );
let new_area = (width * height) as usize;
let grid_cell = Some(( let grid_cell = Some((
"foo".to_string(), "foo".to_string(),
@ -243,6 +245,18 @@ mod tests {
assert_eq!(character_grid.width, width); assert_eq!(character_grid.width, width);
assert_eq!(character_grid.height, height); assert_eq!(character_grid.height, height);
assert_eq!(character_grid.characters, vec![grid_cell.clone(); new_area]);
let (original_width, original_height) = context.size;
for x in 0..original_width.min(width) {
for y in 0..original_height.min(height) {
assert_eq!(character_grid.get_cell(x, y).unwrap(), &grid_cell);
}
}
for x in original_width..width {
for y in original_height..height {
assert_eq!(character_grid.get_cell(x, y).unwrap(), &None);
}
}
} }
} }

@ -1,19 +1,21 @@
mod cursor; mod cursor;
mod draw_command_batcher;
mod grid; mod grid;
mod style; mod style;
mod window; mod window;
use std::collections::HashMap; use std::collections::HashMap;
use std::fmt;
use std::sync::mpsc::{Receiver, Sender};
use std::sync::Arc; use std::sync::Arc;
use std::sync::mpsc::{Sender, Receiver};
use std::thread; use std::thread;
use std::fmt;
use log::{error, warn, trace}; use log::{error, trace, warn};
use crate::bridge::{EditorMode, GuiOption, RedrawEvent, WindowAnchor}; use crate::bridge::{EditorMode, GuiOption, RedrawEvent, WindowAnchor};
use crate::redraw_scheduler::REDRAW_SCHEDULER; use crate::redraw_scheduler::REDRAW_SCHEDULER;
pub use cursor::{Cursor, CursorMode, CursorShape}; pub use cursor::{Cursor, CursorMode, CursorShape};
pub use draw_command_batcher::DrawCommandBatcher;
pub use grid::CharacterGrid; pub use grid::CharacterGrid;
pub use style::{Colors, Style}; pub use style::{Colors, Style};
pub use window::*; pub use window::*;
@ -26,24 +28,18 @@ pub struct AnchorInfo {
} }
impl WindowAnchor { impl WindowAnchor {
fn modified_top_left(&self, grid_left: f64, grid_top: f64, width: u64, height: u64) -> (f64, f64) { fn modified_top_left(
&self,
grid_left: f64,
grid_top: f64,
width: u64,
height: u64,
) -> (f64, f64) {
match self { match self {
WindowAnchor::NorthWest => ( WindowAnchor::NorthWest => (grid_left, grid_top),
grid_left, WindowAnchor::NorthEast => (grid_left - width as f64, grid_top),
grid_top, WindowAnchor::SouthWest => (grid_left, grid_top - height as f64),
), WindowAnchor::SouthEast => (grid_left - width as f64, grid_top - height as f64),
WindowAnchor::NorthEast => (
grid_left - width as f64,
grid_top,
),
WindowAnchor::SouthWest => (
grid_left,
grid_top - height as f64,
),
WindowAnchor::SouthEast => (
grid_left - width as f64,
grid_top - height as f64,
),
} }
} }
} }
@ -52,7 +48,7 @@ pub enum DrawCommand {
CloseWindow(u64), CloseWindow(u64),
Window { Window {
grid_id: u64, grid_id: u64,
command: WindowDrawCommand command: WindowDrawCommand,
}, },
UpdateCursor(Cursor), UpdateCursor(Cursor),
FontChanged(String), FontChanged(String),
@ -68,7 +64,9 @@ impl fmt::Debug for DrawCommand {
fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result { fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
match self { match self {
DrawCommand::CloseWindow(_) => write!(formatter, "CloseWindow"), DrawCommand::CloseWindow(_) => write!(formatter, "CloseWindow"),
DrawCommand::Window { grid_id, command } => write!(formatter, "Window {} {:?}", grid_id, command), DrawCommand::Window { grid_id, command } => {
write!(formatter, "Window {} {:?}", grid_id, command)
}
DrawCommand::UpdateCursor(_) => write!(formatter, "UpdateCursor"), DrawCommand::UpdateCursor(_) => write!(formatter, "UpdateCursor"),
DrawCommand::FontChanged(_) => write!(formatter, "FontChanged"), DrawCommand::FontChanged(_) => write!(formatter, "FontChanged"),
DrawCommand::DefaultStyleChanged(_) => write!(formatter, "DefaultStyleChanged"), DrawCommand::DefaultStyleChanged(_) => write!(formatter, "DefaultStyleChanged"),
@ -82,28 +80,33 @@ pub struct Editor {
pub defined_styles: HashMap<u64, Arc<Style>>, pub defined_styles: HashMap<u64, Arc<Style>>,
pub mode_list: Vec<CursorMode>, pub mode_list: Vec<CursorMode>,
pub current_mode: EditorMode, pub current_mode: EditorMode,
pub draw_command_sender: Sender<DrawCommand>, pub draw_command_batcher: Arc<DrawCommandBatcher>,
pub window_command_sender: Sender<WindowCommand>, pub window_command_sender: Sender<WindowCommand>,
} }
impl Editor { impl Editor {
pub fn new(draw_command_sender: Sender<DrawCommand>, window_command_sender: Sender<WindowCommand>) -> Editor { pub fn new(
batched_draw_command_sender: Sender<Vec<DrawCommand>>,
window_command_sender: Sender<WindowCommand>,
) -> Editor {
Editor { Editor {
windows: HashMap::new(), windows: HashMap::new(),
cursor: Cursor::new(), cursor: Cursor::new(),
defined_styles: HashMap::new(), defined_styles: HashMap::new(),
mode_list: Vec::new(), mode_list: Vec::new(),
current_mode: EditorMode::Unknown(String::from("")), current_mode: EditorMode::Unknown(String::from("")),
draw_command_sender, draw_command_batcher: Arc::new(DrawCommandBatcher::new(batched_draw_command_sender)),
window_command_sender window_command_sender,
} }
} }
pub fn handle_redraw_event(&mut self, event: RedrawEvent) { pub fn handle_redraw_event(&mut self, event: RedrawEvent) {
match event { match event {
RedrawEvent::SetTitle { title } => { RedrawEvent::SetTitle { title } => {
self.window_command_sender.send(WindowCommand::TitleChanged(title)).ok(); self.window_command_sender
}, .send(WindowCommand::TitleChanged(title))
.ok();
}
RedrawEvent::ModeInfoSet { cursor_modes } => self.mode_list = cursor_modes, RedrawEvent::ModeInfoSet { cursor_modes } => self.mode_list = cursor_modes,
RedrawEvent::OptionSet { gui_option } => self.set_option(gui_option), RedrawEvent::OptionSet { gui_option } => self.set_option(gui_option),
RedrawEvent::ModeChange { mode, mode_index } => { RedrawEvent::ModeChange { mode, mode_index } => {
@ -113,10 +116,14 @@ impl Editor {
} }
} }
RedrawEvent::MouseOn => { RedrawEvent::MouseOn => {
self.window_command_sender.send(WindowCommand::SetMouseEnabled(true)).ok(); self.window_command_sender
.send(WindowCommand::SetMouseEnabled(true))
.ok();
} }
RedrawEvent::MouseOff => { RedrawEvent::MouseOff => {
self.window_command_sender.send(WindowCommand::SetMouseEnabled(false)).ok(); self.window_command_sender
.send(WindowCommand::SetMouseEnabled(false))
.ok();
} }
RedrawEvent::BusyStart => { RedrawEvent::BusyStart => {
trace!("Cursor off"); trace!("Cursor off");
@ -129,17 +136,22 @@ impl Editor {
RedrawEvent::Flush => { RedrawEvent::Flush => {
trace!("Image flushed"); trace!("Image flushed");
self.send_cursor_info(); self.send_cursor_info();
self.draw_command_batcher.send_batch().ok();
REDRAW_SCHEDULER.queue_next_frame(); REDRAW_SCHEDULER.queue_next_frame();
} }
RedrawEvent::DefaultColorsSet { colors } => { RedrawEvent::DefaultColorsSet { colors } => {
self.draw_command_sender.send(DrawCommand::DefaultStyleChanged(Style::new(colors))).ok(); self.draw_command_batcher
.queue(DrawCommand::DefaultStyleChanged(Style::new(colors)))
.ok();
} }
RedrawEvent::HighlightAttributesDefine { id, style } => { RedrawEvent::HighlightAttributesDefine { id, style } => {
self.defined_styles.insert(id, Arc::new(style)); self.defined_styles.insert(id, Arc::new(style));
} }
RedrawEvent::CursorGoto { grid, column: left, row: top } => { RedrawEvent::CursorGoto {
self.set_cursor_position(grid, left, top) grid,
} column: left,
row: top,
} => self.set_cursor_position(grid, left, top),
RedrawEvent::Resize { RedrawEvent::Resize {
grid, grid,
width, width,
@ -154,19 +166,12 @@ impl Editor {
cells, cells,
} => { } => {
let defined_styles = &self.defined_styles; let defined_styles = &self.defined_styles;
self.windows.get_mut(&grid).map(|window| {
window.draw_grid_line(
row,
column_start,
cells,
defined_styles
)
});
}
RedrawEvent::Clear { grid } => {
self.windows self.windows
.get_mut(&grid) .get_mut(&grid)
.map(|window| window.clear()); .map(|window| window.draw_grid_line(row, column_start, cells, defined_styles));
}
RedrawEvent::Clear { grid } => {
self.windows.get_mut(&grid).map(|window| window.clear());
} }
RedrawEvent::Destroy { grid } => self.close_window(grid), RedrawEvent::Destroy { grid } => self.close_window(grid),
RedrawEvent::Scroll { RedrawEvent::Scroll {
@ -196,13 +201,9 @@ impl Editor {
anchor_column: anchor_left, anchor_column: anchor_left,
anchor_row: anchor_top, anchor_row: anchor_top,
.. ..
} => { } => self.set_window_float_position(grid, anchor_grid, anchor, anchor_left, anchor_top),
self.set_window_float_position(grid, anchor_grid, anchor, anchor_left, anchor_top)
}
RedrawEvent::WindowHide { grid } => { RedrawEvent::WindowHide { grid } => {
self.windows self.windows.get(&grid).map(|window| window.hide());
.get(&grid)
.map(|window| window.hide());
} }
RedrawEvent::WindowClose { grid } => self.close_window(grid), RedrawEvent::WindowClose { grid } => self.close_window(grid),
RedrawEvent::MessageSetPosition { grid, row, .. } => { RedrawEvent::MessageSetPosition { grid, row, .. } => {
@ -215,7 +216,9 @@ impl Editor {
fn close_window(&mut self, grid: u64) { fn close_window(&mut self, grid: u64) {
if let Some(window) = self.windows.remove(&grid) { if let Some(window) = self.windows.remove(&grid) {
window.close(); window.close();
self.draw_command_sender.send(DrawCommand::CloseWindow(grid)).ok(); self.draw_command_batcher
.queue(DrawCommand::CloseWindow(grid))
.ok();
} }
} }
@ -225,13 +228,14 @@ impl Editor {
window.resize(width, height); window.resize(width, height);
} else { } else {
let window = Window::new( let window = Window::new(
grid, grid,
width, width,
height, height,
None, None,
0.0, 0.0,
0.0, 0.0,
self.draw_command_sender.clone()); self.draw_command_batcher.clone(),
);
self.windows.insert(grid, window); self.windows.insert(grid, window);
} }
} }
@ -246,12 +250,7 @@ impl Editor {
) { ) {
warn!("position {}", grid); warn!("position {}", grid);
if let Some(window) = self.windows.get_mut(&grid) { if let Some(window) = self.windows.get_mut(&grid) {
window.position( window.position(width, height, None, start_left as f64, start_top as f64);
width,
height,
None,
start_left as f64,
start_top as f64);
window.show(); window.show();
} else { } else {
let new_window = Window::new( let new_window = Window::new(
@ -261,7 +260,7 @@ impl Editor {
None, None,
start_left as f64, start_left as f64,
start_top as f64, start_top as f64,
self.draw_command_sender.clone() self.draw_command_batcher.clone(),
); );
self.windows.insert(grid, new_window); self.windows.insert(grid, new_window);
} }
@ -280,9 +279,8 @@ impl Editor {
if let Some(window) = self.windows.get_mut(&grid) { if let Some(window) = self.windows.get_mut(&grid) {
let width = window.get_width(); let width = window.get_width();
let height = window.get_height(); let height = window.get_height();
let (mut modified_left, mut modified_top) = anchor_type.modified_top_left( let (mut modified_left, mut modified_top) =
anchor_left, anchor_top, anchor_type.modified_top_left(anchor_left, anchor_top, width, height);
width, height);
if let Some((parent_left, parent_top)) = parent_position { if let Some((parent_left, parent_top)) = parent_position {
modified_left = parent_left + modified_left; modified_left = parent_left + modified_left;
@ -290,12 +288,17 @@ impl Editor {
} }
window.position( window.position(
width, height, width,
height,
Some(AnchorInfo { Some(AnchorInfo {
anchor_grid_id: anchor_grid, anchor_grid_id: anchor_grid,
anchor_type, anchor_left, anchor_top anchor_type,
anchor_left,
anchor_top,
}), }),
modified_left, modified_top); modified_left,
modified_top,
);
window.show(); window.show();
} else { } else {
error!("Attempted to float window that does not exist."); error!("Attempted to float window that does not exist.");
@ -304,14 +307,20 @@ impl Editor {
fn set_message_position(&mut self, grid: u64, grid_top: u64) { fn set_message_position(&mut self, grid: u64, grid_top: u64) {
warn!("message position {}", grid); warn!("message position {}", grid);
let parent_width = self.windows.get(&1).map(|parent| parent.get_width()).unwrap_or(1); let parent_width = self
.windows
.get(&1)
.map(|parent| parent.get_width())
.unwrap_or(1);
if let Some(window) = self.windows.get_mut(&grid) { if let Some(window) = self.windows.get_mut(&grid) {
window.position( window.position(
parent_width, window.get_height(), parent_width,
window.get_height(),
None, None,
0.0, 0.0,
grid_top as f64); grid_top as f64,
);
window.show(); window.show();
} else { } else {
let new_window = Window::new( let new_window = Window::new(
@ -321,7 +330,7 @@ impl Editor {
None, None,
0.0, 0.0,
grid_top as f64, grid_top as f64,
self.draw_command_sender.clone() self.draw_command_batcher.clone(),
); );
self.windows.insert(grid, new_window); self.windows.insert(grid, new_window);
} }
@ -336,11 +345,18 @@ impl Editor {
let (parent_anchor_left, parent_anchor_top) = let (parent_anchor_left, parent_anchor_top) =
self.get_window_top_left(anchor_info.anchor_grid_id)?; self.get_window_top_left(anchor_info.anchor_grid_id)?;
let (anchor_modified_left, anchor_modified_top) = anchor_info.anchor_type.modified_top_left( let (anchor_modified_left, anchor_modified_top) =
anchor_info.anchor_left, anchor_info.anchor_top, anchor_info.anchor_type.modified_top_left(
window.get_width(), window.get_height()); anchor_info.anchor_left,
anchor_info.anchor_top,
window.get_width(),
window.get_height(),
);
Some((parent_anchor_left + anchor_modified_left, parent_anchor_top + anchor_modified_top)) Some((
parent_anchor_left + anchor_modified_left,
parent_anchor_top + anchor_modified_top,
))
} }
None => Some(window.get_grid_position()), None => Some(window.get_grid_position()),
} }
@ -355,10 +371,12 @@ impl Editor {
let (grid_left, grid_top) = self.cursor.grid_position; let (grid_left, grid_top) = self.cursor.grid_position;
match self.get_window_top_left(self.cursor.parent_window_id) { match self.get_window_top_left(self.cursor.parent_window_id) {
Some((window_left, window_top)) => { Some((window_left, window_top)) => {
self.cursor.position = (window_left + grid_left as f64, window_top + grid_top as f64); self.cursor.position =
(window_left + grid_left as f64, window_top + grid_top as f64);
if let Some(window) = self.windows.get(&self.cursor.parent_window_id) { if let Some(window) = self.windows.get(&self.cursor.parent_window_id) {
let (character, double_width) = window.get_cursor_character(grid_left, grid_top); let (character, double_width) =
window.get_cursor_character(grid_left, grid_top);
self.cursor.character = character; self.cursor.character = character;
self.cursor.double_width = double_width; self.cursor.double_width = double_width;
} }
@ -369,20 +387,28 @@ impl Editor {
self.cursor.character = " ".to_string(); self.cursor.character = " ".to_string();
} }
} }
self.draw_command_sender.send(DrawCommand::UpdateCursor(self.cursor.clone())).ok(); self.draw_command_batcher
.queue(DrawCommand::UpdateCursor(self.cursor.clone()))
.ok();
} }
fn set_option(&mut self, gui_option: GuiOption) { fn set_option(&mut self, gui_option: GuiOption) {
trace!("Option set {:?}", &gui_option); trace!("Option set {:?}", &gui_option);
if let GuiOption::GuiFont(guifont) = gui_option { if let GuiOption::GuiFont(guifont) = gui_option {
self.draw_command_sender.send(DrawCommand::FontChanged(guifont)).ok(); self.draw_command_batcher
.queue(DrawCommand::FontChanged(guifont))
.ok();
} }
} }
} }
pub fn start_editor(redraw_event_receiver: Receiver<RedrawEvent>, draw_command_sender: Sender<DrawCommand>, window_command_sender: Sender<WindowCommand>) { pub fn start_editor(
redraw_event_receiver: Receiver<RedrawEvent>,
batched_draw_command_sender: Sender<Vec<DrawCommand>>,
window_command_sender: Sender<WindowCommand>,
) {
thread::spawn(move || { thread::spawn(move || {
let mut editor = Editor::new(draw_command_sender, window_command_sender); let mut editor = Editor::new(batched_draw_command_sender, window_command_sender);
loop { loop {
if let Ok(redraw_event) = redraw_event_receiver.recv() { if let Ok(redraw_event) = redraw_event_receiver.recv() {

@ -1,14 +1,13 @@
use std::collections::HashMap; use std::collections::HashMap;
use std::sync::Arc;
use std::sync::mpsc::Sender;
use std::fmt; use std::fmt;
use std::sync::Arc;
use log::warn; use log::warn;
use unicode_segmentation::UnicodeSegmentation; use unicode_segmentation::UnicodeSegmentation;
use super::{DrawCommand, AnchorInfo};
use super::grid::CharacterGrid; use super::grid::CharacterGrid;
use super::style::Style; use super::style::Style;
use super::{AnchorInfo, DrawCommand, DrawCommandBatcher};
use crate::bridge::GridLineCell; use crate::bridge::GridLineCell;
#[derive(new, Clone)] #[derive(new, Clone)]
@ -18,7 +17,7 @@ pub enum WindowDrawCommand {
grid_top: f64, grid_top: f64,
width: u64, width: u64,
height: u64, height: u64,
floating: bool floating: bool,
}, },
Cell { Cell {
text: String, text: String,
@ -38,7 +37,7 @@ pub enum WindowDrawCommand {
Clear, Clear,
Show, Show,
Hide, Hide,
Close Close,
} }
impl fmt::Debug for WindowDrawCommand { impl fmt::Debug for WindowDrawCommand {
@ -64,7 +63,7 @@ pub struct Window {
grid_left: f64, grid_left: f64,
grid_top: f64, grid_top: f64,
draw_command_sender: Sender<DrawCommand> draw_command_batcher: Arc<DrawCommandBatcher>,
} }
impl Window { impl Window {
@ -75,7 +74,7 @@ impl Window {
anchor_info: Option<AnchorInfo>, anchor_info: Option<AnchorInfo>,
grid_left: f64, grid_left: f64,
grid_top: f64, grid_top: f64,
draw_command_sender: Sender<DrawCommand> draw_command_batcher: Arc<DrawCommandBatcher>,
) -> Window { ) -> Window {
let window = Window { let window = Window {
grid_id, grid_id,
@ -83,17 +82,19 @@ impl Window {
anchor_info, anchor_info,
grid_left, grid_left,
grid_top, grid_top,
draw_command_sender draw_command_batcher,
}; };
window.send_updated_position(); window.send_updated_position();
window window
} }
fn send_command(&self, command: WindowDrawCommand) { fn send_command(&self, command: WindowDrawCommand) {
self.draw_command_sender.send(DrawCommand::Window { self.draw_command_batcher
grid_id: self.grid_id, .queue(DrawCommand::Window {
command grid_id: self.grid_id,
}).ok(); command,
})
.ok();
} }
fn send_updated_position(&self) { fn send_updated_position(&self) {
@ -132,7 +133,14 @@ impl Window {
(self.grid_left, self.grid_top) (self.grid_left, self.grid_top)
} }
pub fn position(&mut self, width: u64, height: u64, anchor_info: Option<AnchorInfo>, grid_left: f64, grid_top: f64) { pub fn position(
&mut self,
width: u64,
height: u64,
anchor_info: Option<AnchorInfo>,
grid_left: f64,
grid_top: f64,
) {
self.grid.resize(width, height); self.grid.resize(width, height);
self.anchor_info = anchor_info; self.anchor_info = anchor_info;
self.grid_left = grid_left; self.grid_left = grid_left;
@ -151,17 +159,13 @@ impl Window {
column_pos: &mut u64, column_pos: &mut u64,
cell: GridLineCell, cell: GridLineCell,
defined_styles: &HashMap<u64, Arc<Style>>, defined_styles: &HashMap<u64, Arc<Style>>,
previous_style: &mut Option<Arc<Style>>, previous_style: &mut Option<Arc<Style>>,
) { ) {
// Get the defined style from the style list // Get the defined style from the style list
let style = match cell.highlight_id { let style = match cell.highlight_id {
Some(0) => None, Some(0) => None,
Some(style_id) => { Some(style_id) => defined_styles.get(&style_id).cloned(),
defined_styles.get(&style_id).cloned() None => previous_style.clone(),
},
None => {
previous_style.clone()
},
}; };
// Compute text // Compute text
@ -185,16 +189,14 @@ impl Window {
*column_pos += text.graphemes(true).count() as u64; *column_pos += text.graphemes(true).count() as u64;
} }
if let Some(style) = style { *previous_style = style;
*previous_style = Some(style);
}
} }
fn send_draw_command( fn send_draw_command(
&mut self, &mut self,
row_index: u64, row_index: u64,
line_start: u64, line_start: u64,
current_start: u64 current_start: u64,
) -> Option<u64> { ) -> Option<u64> {
let row = self.grid.row(row_index).unwrap(); let row = self.grid.row(row_index).unwrap();
@ -217,7 +219,6 @@ impl Window {
} }
} }
let mut draw_command_end_index = current_start; let mut draw_command_end_index = current_start;
for possible_end_index in draw_command_start_index..self.grid.width { for possible_end_index in draw_command_start_index..self.grid.width {
if let Some((_, possible_end_style)) = &row[possible_end_index as usize] { if let Some((_, possible_end_style)) = &row[possible_end_index as usize] {
@ -242,7 +243,7 @@ impl Window {
cell_width: draw_command_end_index - draw_command_start_index + 1, cell_width: draw_command_end_index - draw_command_start_index + 1,
window_left: draw_command_start_index, window_left: draw_command_start_index,
window_top: row_index, window_top: row_index,
style: style.clone() style: style.clone(),
}); });
Some(draw_command_end_index + 1) Some(draw_command_end_index + 1)
@ -253,7 +254,7 @@ impl Window {
row: u64, row: u64,
column_start: u64, column_start: u64,
cells: Vec<GridLineCell>, cells: Vec<GridLineCell>,
defined_styles: &HashMap<u64, Arc<Style>> defined_styles: &HashMap<u64, Arc<Style>>,
) { ) {
let mut previous_style = None; let mut previous_style = None;
if row < self.grid.height { if row < self.grid.height {
@ -297,7 +298,12 @@ impl Window {
}; };
self.send_command(WindowDrawCommand::Scroll { self.send_command(WindowDrawCommand::Scroll {
top, bot, left, right, rows, cols top,
bot,
left,
right,
rows,
cols,
}); });
// Scrolls must not only translate the rendered texture, but also must move the grid data // Scrolls must not only translate the rendered texture, but also must move the grid data

@ -18,14 +18,14 @@ extern crate rust_embed;
#[macro_use] #[macro_use]
extern crate lazy_static; extern crate lazy_static;
use std::sync::Arc; use std::process;
use std::sync::atomic::AtomicBool; use std::sync::atomic::AtomicBool;
use std::sync::mpsc::channel; use std::sync::mpsc::channel;
use std::process; use std::sync::Arc;
use window::window_geometry; use window::window_geometry;
use bridge::start_bridge; use bridge::start_bridge;
use editor::start_editor; use editor::start_editor;
use window::start_window; use window::start_window;
@ -132,11 +132,25 @@ fn main() {
let running = Arc::new(AtomicBool::new(true)); let running = Arc::new(AtomicBool::new(true));
let (redraw_event_sender, redraw_event_receiver) = channel(); let (redraw_event_sender, redraw_event_receiver) = channel();
let (draw_command_sender, draw_command_receiver) = channel(); let (batched_draw_command_sender, batched_draw_command_receiver) = channel();
let (ui_command_sender, ui_command_receiver) = channel(); let (ui_command_sender, ui_command_receiver) = channel();
let (window_command_sender, window_command_receiver) = channel(); let (window_command_sender, window_command_receiver) = channel();
start_bridge(ui_command_sender.clone(), ui_command_receiver, redraw_event_sender, running.clone()); start_bridge(
start_editor(redraw_event_receiver, draw_command_sender, window_command_sender); ui_command_sender.clone(),
start_window(draw_command_receiver, window_command_receiver, ui_command_sender, running.clone()); ui_command_receiver,
redraw_event_sender,
running.clone(),
);
start_editor(
redraw_event_receiver,
batched_draw_command_sender,
window_command_sender,
);
start_window(
batched_draw_command_receiver,
window_command_receiver,
ui_command_sender,
running.clone(),
);
} }

@ -2,8 +2,8 @@ use log::error;
use skulpin::skia_safe::{paint::Style, BlendMode, Canvas, Color, Paint, Point, Rect}; use skulpin::skia_safe::{paint::Style, BlendMode, Canvas, Color, Paint, Point, Rect};
use super::CursorSettings; use super::CursorSettings;
use crate::renderer::animation_utils::*;
use crate::editor::{Colors, Cursor}; use crate::editor::{Colors, Cursor};
use crate::renderer::animation_utils::*;
use crate::settings::*; use crate::settings::*;
pub trait CursorVfx { pub trait CursorVfx {

@ -5,8 +5,8 @@ use skulpin::skia_safe::{Canvas, Paint, Path, Point};
use crate::editor::{Colors, Cursor, CursorShape}; use crate::editor::{Colors, Cursor, CursorShape};
use crate::redraw_scheduler::REDRAW_SCHEDULER; use crate::redraw_scheduler::REDRAW_SCHEDULER;
use crate::renderer::CachingShaper;
use crate::renderer::animation_utils::*; use crate::renderer::animation_utils::*;
use crate::renderer::CachingShaper;
use crate::settings::*; use crate::settings::*;
use blink::*; use blink::*;
@ -265,8 +265,8 @@ impl CursorRenderer {
let in_insert_mode = false; let in_insert_mode = false;
// { // {
// let editor = EDITOR.lock(); // let editor = EDITOR.lock();
// matches!(editor.current_mode, EditorMode::Insert) // matches!(editor.current_mode, EditorMode::Insert)
// }; // };
let destination: Point = (grid_x as f32 * font_width, grid_y as f32 * font_height).into(); let destination: Point = (grid_x as f32 * font_width, grid_y as f32 * font_height).into();
@ -277,7 +277,9 @@ impl CursorRenderer {
self.previous_cursor_shape = new_cursor.clone(); self.previous_cursor_shape = new_cursor.clone();
self.set_cursor_shape( self.set_cursor_shape(
&new_cursor.unwrap(), &new_cursor.unwrap(),
self.cursor.cell_percentage.unwrap_or(DEFAULT_CELL_PERCENTAGE), self.cursor
.cell_percentage
.unwrap_or(DEFAULT_CELL_PERCENTAGE),
); );
if let Some(vfx) = self.cursor_vfx.as_mut() { if let Some(vfx) = self.cursor_vfx.as_mut() {

@ -1,28 +1,25 @@
use std::collections::HashMap; use std::collections::HashMap;
use std::sync::Arc;
use std::sync::mpsc::Receiver; use std::sync::mpsc::Receiver;
use std::sync::Arc;
use log::{trace, warn, error}; use log::{error, trace, warn};
use skulpin::skia_safe::{ use skulpin::skia_safe::{colors, dash_path_effect, BlendMode, Canvas, Color, Paint, Rect};
colors, dash_path_effect, Canvas, Paint, Rect, BlendMode, Color
};
use skulpin::CoordinateSystemHelper; use skulpin::CoordinateSystemHelper;
pub mod animation_utils;
mod caching_shaper; mod caching_shaper;
mod rendered_window;
pub mod cursor_renderer; pub mod cursor_renderer;
pub mod font_options; pub mod font_options;
pub mod animation_utils; mod rendered_window;
pub use caching_shaper::CachingShaper; pub use caching_shaper::CachingShaper;
pub use font_options::*; pub use font_options::*;
use crate::editor::{Style, Colors, DrawCommand, WindowDrawCommand}; use crate::editor::{Colors, DrawCommand, Style, WindowDrawCommand};
use crate::settings::*; use crate::settings::*;
use cursor_renderer::CursorRenderer; use cursor_renderer::CursorRenderer;
use rendered_window::RenderedWindow; use rendered_window::RenderedWindow;
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
#[derive(Clone)] #[derive(Clone)]
@ -39,14 +36,19 @@ pub fn initialize_settings() {
floating_blur: true, floating_blur: true,
}); });
register_nvim_setting!("window_animation_length", RendererSettings::animation_length); register_nvim_setting!(
register_nvim_setting!("floating_window_opacity", RendererSettings::floating_opacity); "window_animation_length",
RendererSettings::animation_length
);
register_nvim_setting!(
"floating_window_opacity",
RendererSettings::floating_opacity
);
register_nvim_setting!("floating_window_blur", RendererSettings::floating_opacity); register_nvim_setting!("floating_window_blur", RendererSettings::floating_opacity);
} }
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
pub struct Renderer { pub struct Renderer {
rendered_windows: HashMap<u64, RenderedWindow>, rendered_windows: HashMap<u64, RenderedWindow>,
cursor_renderer: CursorRenderer, cursor_renderer: CursorRenderer,
@ -58,11 +60,11 @@ pub struct Renderer {
pub font_width: f32, pub font_width: f32,
pub font_height: f32, pub font_height: f32,
pub window_regions: Vec<(u64, Rect)>, pub window_regions: Vec<(u64, Rect)>,
pub draw_command_receiver: Receiver<DrawCommand>, pub batched_draw_command_receiver: Receiver<Vec<DrawCommand>>,
} }
impl Renderer { impl Renderer {
pub fn new(draw_command_receiver: Receiver<DrawCommand>) -> Renderer { pub fn new(batched_draw_command_receiver: Receiver<Vec<DrawCommand>>) -> Renderer {
let rendered_windows = HashMap::new(); let rendered_windows = HashMap::new();
let cursor_renderer = CursorRenderer::new(); let cursor_renderer = CursorRenderer::new();
let settings = SETTINGS.get::<RendererSettings>(); let settings = SETTINGS.get::<RendererSettings>();
@ -89,7 +91,7 @@ impl Renderer {
font_width, font_width,
font_height, font_height,
window_regions, window_regions,
draw_command_receiver, batched_draw_command_receiver,
} }
} }
@ -124,7 +126,8 @@ impl Renderer {
let region = self.compute_text_region(grid_pos, cell_width); let region = self.compute_text_region(grid_pos, cell_width);
let style = style.as_ref().unwrap_or(&self.default_style); let style = style.as_ref().unwrap_or(&self.default_style);
self.paint.set_color(style.background(&self.default_style.colors).to_color()); self.paint
.set_color(style.background(&self.default_style.colors).to_color());
canvas.draw_rect(region, &self.paint); canvas.draw_rect(region, &self.paint);
} }
@ -205,44 +208,49 @@ impl Renderer {
match draw_command { match draw_command {
DrawCommand::Window { DrawCommand::Window {
grid_id, grid_id,
command: WindowDrawCommand::Close command: WindowDrawCommand::Close,
} => { } => {
self.rendered_windows.remove(&grid_id); self.rendered_windows.remove(&grid_id);
}, }
DrawCommand::Window { DrawCommand::Window { grid_id, command } => {
grid_id,
command
} => {
if let Some(rendered_window) = self.rendered_windows.remove(&grid_id) { if let Some(rendered_window) = self.rendered_windows.remove(&grid_id) {
warn!("Window positioned {}", grid_id); warn!("Window positioned {}", grid_id);
let rendered_window = rendered_window.handle_window_draw_command(self, command); let rendered_window = rendered_window.handle_window_draw_command(self, command);
self.rendered_windows.insert(grid_id, rendered_window); self.rendered_windows.insert(grid_id, rendered_window);
} else if let WindowDrawCommand::Position { } else if let WindowDrawCommand::Position {
grid_left, grid_top, grid_left,
width, height, .. grid_top,
} = command { width,
height,
..
} = command
{
warn!("Created window {}", grid_id); warn!("Created window {}", grid_id);
let new_window = RenderedWindow::new( let new_window = RenderedWindow::new(
root_canvas, &self, grid_id, root_canvas,
(grid_left as f32, grid_top as f32).into(), &self,
width, height); grid_id,
(grid_left as f32, grid_top as f32).into(),
width,
height,
);
self.rendered_windows.insert(grid_id, new_window); self.rendered_windows.insert(grid_id, new_window);
} else { } else {
error!("WindowDrawCommand sent for uninitialized grid {}", grid_id); error!("WindowDrawCommand sent for uninitialized grid {}", grid_id);
} }
}, }
DrawCommand::UpdateCursor(new_cursor) => { DrawCommand::UpdateCursor(new_cursor) => {
self.cursor_renderer.update_cursor(new_cursor); self.cursor_renderer.update_cursor(new_cursor);
}, }
DrawCommand::FontChanged(new_font) => { DrawCommand::FontChanged(new_font) => {
if self.update_font(&new_font) { if self.update_font(&new_font) {
// Resize all the grids // Resize all the grids
} }
}, }
DrawCommand::DefaultStyleChanged(new_style) => { DrawCommand::DefaultStyleChanged(new_style) => {
self.default_style = Arc::new(new_style); self.default_style = Arc::new(new_style);
}, }
_ => { } _ => {}
} }
} }
@ -255,7 +263,12 @@ impl Renderer {
trace!("Rendering"); trace!("Rendering");
let mut font_changed = false; let mut font_changed = false;
let draw_commands: Vec<DrawCommand> = self.draw_command_receiver.try_iter().collect(); let draw_commands: Vec<DrawCommand> = self
.batched_draw_command_receiver
.try_iter() // Iterator of Vec of DrawCommand
.map(|batch| batch.into_iter()) // Iterator of Iterator of DrawCommand
.flatten() // Iterator of DrawCommand
.collect(); // Vec of DrawCommand
for draw_command in draw_commands.into_iter() { for draw_command in draw_commands.into_iter() {
if let DrawCommand::FontChanged(_) = draw_command { if let DrawCommand::FontChanged(_) = draw_command {
font_changed = true; font_changed = true;
@ -263,20 +276,36 @@ impl Renderer {
self.handle_draw_command(root_canvas, draw_command); self.handle_draw_command(root_canvas, draw_command);
} }
root_canvas.clear(self.default_style.colors.background.clone().unwrap().to_color()); root_canvas.clear(
self.default_style
.colors
.background
.clone()
.unwrap()
.to_color(),
);
coordinate_system_helper.use_logical_coordinates(root_canvas); coordinate_system_helper.use_logical_coordinates(root_canvas);
let windows: Vec<&mut RenderedWindow> = { let windows: Vec<&mut RenderedWindow> = {
let (mut root_windows, mut floating_windows): (Vec<&mut RenderedWindow>, Vec<&mut RenderedWindow>) = self.rendered_windows let (mut root_windows, mut floating_windows): (
Vec<&mut RenderedWindow>,
Vec<&mut RenderedWindow>,
) = self
.rendered_windows
.values_mut() .values_mut()
.filter(|window| !window.hidden) .filter(|window| !window.hidden)
.partition(|window| !window.floating); .partition(|window| !window.floating);
root_windows.sort_by(|window_a, window_b| window_a.id.partial_cmp(&window_b.id).unwrap()); root_windows
floating_windows.sort_by(|window_a, window_b| window_a.id.partial_cmp(&window_b.id).unwrap()); .sort_by(|window_a, window_b| window_a.id.partial_cmp(&window_b.id).unwrap());
floating_windows
.sort_by(|window_a, window_b| window_a.id.partial_cmp(&window_b.id).unwrap());
root_windows.into_iter().chain(floating_windows.into_iter()).collect() root_windows
.into_iter()
.chain(floating_windows.into_iter())
.collect()
}; };
let settings = &self.settings; let settings = &self.settings;

@ -1,14 +1,11 @@
use skulpin::skia_safe::canvas::{SaveLayerRec, SrcRectConstraint};
use skulpin::skia_safe::gpu::SurfaceOrigin; use skulpin::skia_safe::gpu::SurfaceOrigin;
use skulpin::skia_safe::{ use skulpin::skia_safe::{
Budgeted, Canvas, ImageInfo, Rect, Surface, Point, Paint, Color, BlendMode, image_filters::blur image_filters::blur, BlendMode, Budgeted, Canvas, Color, ImageInfo, Paint, Point, Rect, Surface,
};
use skulpin::skia_safe::canvas::{
SaveLayerRec,
SrcRectConstraint
}; };
use super::{Renderer, RendererSettings};
use super::animation_utils::*; use super::animation_utils::*;
use super::{Renderer, RendererSettings};
use crate::editor::WindowDrawCommand; use crate::editor::WindowDrawCommand;
use crate::redraw_scheduler::REDRAW_SCHEDULER; use crate::redraw_scheduler::REDRAW_SCHEDULER;
@ -18,7 +15,10 @@ fn build_window_surface(
grid_width: u64, grid_width: u64,
grid_height: u64, grid_height: u64,
) -> Surface { ) -> Surface {
let dimensions = ((grid_width as f32 * renderer.font_width) as i32, (grid_height as f32 * renderer.font_height) as i32); let dimensions = (
(grid_width as f32 * renderer.font_width) as i32,
(grid_height as f32 * renderer.font_height) as i32,
);
let mut context = parent_canvas.gpu_context().unwrap(); let mut context = parent_canvas.gpu_context().unwrap();
let budgeted = Budgeted::Yes; let budgeted = Budgeted::Yes;
let parent_image_info = parent_canvas.image_info(); let parent_image_info = parent_canvas.image_info();
@ -39,9 +39,26 @@ fn build_window_surface(
None, None,
) )
.expect("Could not create surface"); .expect("Could not create surface");
let canvas = surface.canvas(); surface
}
canvas.clear(renderer.default_style.colors.background.clone().unwrap().to_color()); fn build_background_window_surface(
parent_canvas: &mut Canvas,
renderer: &Renderer,
grid_width: u64,
grid_height: u64,
) -> Surface {
let mut surface = build_window_surface(parent_canvas, renderer, grid_width, grid_height);
let canvas = surface.canvas();
canvas.clear(
renderer
.default_style
.colors
.background
.clone()
.unwrap()
.to_color(),
);
surface surface
} }
@ -52,18 +69,28 @@ pub struct RenderedWindow {
pub hidden: bool, pub hidden: bool,
pub floating: bool, pub floating: bool,
grid_width: u64, grid_height: u64, grid_width: u64,
grid_height: u64,
grid_start_position: Point, grid_start_position: Point,
grid_current_position: Point, grid_current_position: Point,
grid_destination: Point, grid_destination: Point,
t: f32 t: f32,
} }
impl RenderedWindow { impl RenderedWindow {
pub fn new(parent_canvas: &mut Canvas, renderer: &Renderer, id: u64, grid_position: Point, grid_width: u64, grid_height: u64) -> RenderedWindow { pub fn new(
let background_surface = build_window_surface(parent_canvas, renderer, grid_width, grid_height); parent_canvas: &mut Canvas,
let foreground_surface = build_window_surface(parent_canvas, renderer, grid_width, grid_height); renderer: &Renderer,
id: u64,
grid_position: Point,
grid_width: u64,
grid_height: u64,
) -> RenderedWindow {
let background_surface =
build_background_window_surface(parent_canvas, renderer, grid_width, grid_height);
let foreground_surface =
build_window_surface(parent_canvas, renderer, grid_width, grid_height);
RenderedWindow { RenderedWindow {
background_surface, background_surface,
@ -78,15 +105,11 @@ impl RenderedWindow {
grid_start_position: grid_position, grid_start_position: grid_position,
grid_current_position: grid_position, grid_current_position: grid_position,
grid_destination: grid_position, grid_destination: grid_position,
t: 2.0 // 2.0 is out of the 0.0 to 1.0 range and stops animation t: 2.0, // 2.0 is out of the 0.0 to 1.0 range and stops animation
} }
} }
pub fn update( pub fn update(&mut self, settings: &RendererSettings, dt: f32) -> bool {
&mut self,
settings: &RendererSettings,
dt: f32
) -> bool {
if (self.t - 1.0).abs() < std::f32::EPSILON { if (self.t - 1.0).abs() < std::f32::EPSILON {
return false; return false;
} }
@ -114,9 +137,12 @@ impl RenderedWindow {
settings: &RendererSettings, settings: &RendererSettings,
font_width: f32, font_width: f32,
font_height: f32, font_height: f32,
dt: f32 dt: f32,
) -> (u64, Rect) { ) -> (u64, Rect) {
let current_pixel_position = Point::new(self.grid_current_position.x * font_width, self.grid_current_position.y * font_height); let current_pixel_position = Point::new(
self.grid_current_position.x * font_width,
self.grid_current_position.y * font_height,
);
let image_width = (self.grid_width as f32 * font_width) as i32; let image_width = (self.grid_width as f32 * font_width) as i32;
let image_height = (self.grid_height as f32 * font_height) as i32; let image_height = (self.grid_height as f32 * font_height) as i32;
@ -132,9 +158,7 @@ impl RenderedWindow {
if self.floating && settings.floating_blur { if self.floating && settings.floating_blur {
let blur = blur((2.0, 2.0), None, None, None).unwrap(); let blur = blur((2.0, 2.0), None, None, None).unwrap();
let save_layer_rec = SaveLayerRec::default() let save_layer_rec = SaveLayerRec::default().backdrop(&blur).bounds(&region);
.backdrop(&blur)
.bounds(&region);
root_canvas.save_layer(&save_layer_rec); root_canvas.save_layer(&save_layer_rec);
} }
@ -146,12 +170,20 @@ impl RenderedWindow {
paint.set_color(Color::from_argb(a, 255, 255, 255)); paint.set_color(Color::from_argb(a, 255, 255, 255));
} }
self.background_surface.draw(root_canvas.as_mut(), (current_pixel_position.x, current_pixel_position.y), Some(&paint)); self.background_surface.draw(
root_canvas.as_mut(),
(current_pixel_position.x, current_pixel_position.y),
Some(&paint),
);
let mut paint = Paint::default(); let mut paint = Paint::default();
paint.set_blend_mode(BlendMode::SrcOver); paint.set_blend_mode(BlendMode::SrcOver);
self.foreground_surface.draw(root_canvas.as_mut(), (current_pixel_position.x, current_pixel_position.y), Some(&paint)); self.foreground_surface.draw(
root_canvas.as_mut(),
(current_pixel_position.x, current_pixel_position.y),
Some(&paint),
);
if self.floating { if self.floating {
root_canvas.restore(); root_canvas.restore();
@ -161,28 +193,38 @@ impl RenderedWindow {
let window_position = current_pixel_position.clone(); let window_position = current_pixel_position.clone();
(self.id, Rect::from_point_and_size(window_position, (image_width as f32, image_height as f32))) (
self.id,
Rect::from_point_and_size(window_position, (image_width as f32, image_height as f32)),
)
} }
pub fn handle_window_draw_command(mut self, renderer: &mut Renderer, draw_command: WindowDrawCommand) -> Self { pub fn handle_window_draw_command(
mut self,
renderer: &mut Renderer,
draw_command: WindowDrawCommand,
) -> Self {
match draw_command { match draw_command {
WindowDrawCommand::Position { WindowDrawCommand::Position {
grid_left, grid_top, grid_left,
width: grid_width, grid_top,
width: grid_width,
height: grid_height, height: grid_height,
floating floating,
} => { } => {
let new_destination: Point = (grid_left as f32, grid_top as f32).into(); let new_destination: Point = (grid_left as f32, grid_top as f32).into();
if self.grid_destination != new_destination { if self.grid_destination != new_destination {
if self.grid_start_position.x.abs() > f32::EPSILON || self.grid_start_position.y.abs() > f32::EPSILON { if self.grid_start_position.x.abs() > f32::EPSILON
|| self.grid_start_position.y.abs() > f32::EPSILON
{
self.t = 0.0; // Reset animation as we have a new destination. self.t = 0.0; // Reset animation as we have a new destination.
self.grid_start_position = self.grid_current_position; self.grid_start_position = self.grid_current_position;
self.grid_destination = new_destination; self.grid_destination = new_destination;
} else { } else {
// We don't want to animate since the window is animating out of the start location, // We don't want to animate since the window is animating out of the start location,
// so we set t to 2.0 to stop animations. // so we set t to 2.0 to stop animations.
self.t = 2.0; self.t = 2.0;
self.grid_start_position = new_destination; self.grid_start_position = new_destination;
self.grid_destination = new_destination; self.grid_destination = new_destination;
} }
@ -191,13 +233,23 @@ impl RenderedWindow {
if grid_width != self.grid_width || grid_height != self.grid_height { if grid_width != self.grid_width || grid_height != self.grid_height {
{ {
let mut old_background = self.background_surface; let mut old_background = self.background_surface;
self.background_surface = build_window_surface(old_background.canvas(), &renderer, grid_width, grid_height); self.background_surface = build_background_window_surface(
old_background.canvas(),
&renderer,
grid_width,
grid_height,
);
old_background.draw(self.background_surface.canvas(), (0.0, 0.0), None); old_background.draw(self.background_surface.canvas(), (0.0, 0.0), None);
} }
{ {
let mut old_foreground = self.foreground_surface; let mut old_foreground = self.foreground_surface;
self.foreground_surface = build_window_surface(old_foreground.canvas(), &renderer, grid_width, grid_height); self.foreground_surface = build_window_surface(
old_foreground.canvas(),
&renderer,
grid_width,
grid_height,
);
old_foreground.draw(self.foreground_surface.canvas(), (0.0, 0.0), None); old_foreground.draw(self.foreground_surface.canvas(), (0.0, 0.0), None);
} }
@ -213,9 +265,13 @@ impl RenderedWindow {
self.grid_start_position = new_destination; self.grid_start_position = new_destination;
self.grid_destination = new_destination; self.grid_destination = new_destination;
} }
}, }
WindowDrawCommand::Cell { WindowDrawCommand::Cell {
text, cell_width, window_left, window_top, style text,
cell_width,
window_left,
window_top,
style,
} => { } => {
let grid_position = (window_left, window_top); let grid_position = (window_left, window_top);
@ -225,7 +281,7 @@ impl RenderedWindow {
&mut background_canvas, &mut background_canvas,
grid_position, grid_position,
cell_width, cell_width,
&style &style,
); );
} }
@ -239,15 +295,21 @@ impl RenderedWindow {
&style, &style,
); );
} }
}, }
WindowDrawCommand::Scroll { WindowDrawCommand::Scroll {
top, bot, left, right, rows, cols top,
bot,
left,
right,
rows,
cols,
} => { } => {
let scrolled_region = Rect::new( let scrolled_region = Rect::new(
left as f32 * renderer.font_width, left as f32 * renderer.font_width,
top as f32 * renderer.font_height, top as f32 * renderer.font_height,
right as f32 * renderer.font_width, right as f32 * renderer.font_width,
bot as f32 * renderer.font_height); bot as f32 * renderer.font_height,
);
{ {
let background_snapshot = self.background_surface.image_snapshot(); let background_snapshot = self.background_surface.image_snapshot();
@ -257,9 +319,17 @@ impl RenderedWindow {
background_canvas.clip_rect(scrolled_region, None, Some(false)); background_canvas.clip_rect(scrolled_region, None, Some(false));
let mut translated_region = scrolled_region.clone(); let mut translated_region = scrolled_region.clone();
translated_region.offset((-cols as f32 * renderer.font_width, -rows as f32 * renderer.font_height)); translated_region.offset((
-cols as f32 * renderer.font_width,
background_canvas.draw_image_rect(background_snapshot, Some((&scrolled_region, SrcRectConstraint::Fast)), translated_region, &renderer.paint); -rows as f32 * renderer.font_height,
));
background_canvas.draw_image_rect(
background_snapshot,
Some((&scrolled_region, SrcRectConstraint::Fast)),
translated_region,
&renderer.paint,
);
background_canvas.restore(); background_canvas.restore();
} }
@ -272,20 +342,38 @@ impl RenderedWindow {
foreground_canvas.clip_rect(scrolled_region, None, Some(false)); foreground_canvas.clip_rect(scrolled_region, None, Some(false));
let mut translated_region = scrolled_region.clone(); let mut translated_region = scrolled_region.clone();
translated_region.offset((-cols as f32 * renderer.font_width, -rows as f32 * renderer.font_height)); translated_region.offset((
-cols as f32 * renderer.font_width,
foreground_canvas.draw_image_rect(foreground_snapshot, Some((&scrolled_region, SrcRectConstraint::Fast)), translated_region, &renderer.paint); -rows as f32 * renderer.font_height,
));
foreground_canvas.draw_image_rect(
foreground_snapshot,
Some((&scrolled_region, SrcRectConstraint::Fast)),
translated_region,
&renderer.paint,
);
foreground_canvas.restore(); foreground_canvas.restore();
} }
}, }
WindowDrawCommand::Clear => { WindowDrawCommand::Clear => {
let background_canvas = self.background_surface.canvas(); let background_canvas = self.background_surface.canvas();
self.background_surface = build_window_surface(background_canvas, &renderer, self.grid_width, self.grid_height); self.background_surface = build_background_window_surface(
background_canvas,
&renderer,
self.grid_width,
self.grid_height,
);
let foreground_canvas = self.foreground_surface.canvas(); let foreground_canvas = self.foreground_surface.canvas();
self.foreground_surface = build_window_surface(foreground_canvas, &renderer, self.grid_width, self.grid_height); self.foreground_surface = build_window_surface(
}, foreground_canvas,
&renderer,
self.grid_width,
self.grid_height,
);
}
WindowDrawCommand::Show => { WindowDrawCommand::Show => {
if self.hidden { if self.hidden {
self.hidden = false; self.hidden = false;
@ -293,7 +381,7 @@ impl RenderedWindow {
self.grid_start_position = self.grid_destination; self.grid_start_position = self.grid_destination;
self.grid_destination = self.grid_destination; self.grid_destination = self.grid_destination;
} }
}, }
WindowDrawCommand::Hide => self.hidden = true, WindowDrawCommand::Hide => self.hidden = true,
_ => {} _ => {}
}; };

@ -170,11 +170,10 @@ impl Settings {
), ),
name name
); );
nvim.command(&vimscript) nvim.command(&vimscript).unwrap_or_explained_panic(&format!(
.unwrap_or_explained_panic(&format!( "Could not setup setting notifier for {}",
"Could not setup setting notifier for {}", name
name ));
));
} }
} }
@ -191,31 +190,11 @@ impl Settings {
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use neovim_lib::{Neovim, NeovimApi, Session, UiAttachOptions};
use super::*; use super::*;
use crate::bridge::create_nvim_command; use crate::bridge::create_nvim_command;
use async_trait::async_trait;
use nvim_rs::create::tokio as create;
use nvim_rs::{compat::tokio::Compat, Handler, Neovim};
#[derive(Clone)]
pub struct NeovimHandler();
#[async_trait]
impl Handler for NeovimHandler {
type Writer = Compat<ChildStdin>;
async fn handle_notify(
&self,
_event_name: String,
_arguments: Vec<Value>,
_neovim: Neovim<Compat<ChildStdin>>,
) {
}
}
use tokio;
#[test] #[test]
fn test_set_setting_handlers() { fn test_set_setting_handlers() {
@ -288,8 +267,8 @@ mod tests {
assert_eq!(v2, r2); assert_eq!(v2, r2);
} }
#[tokio::test] #[test]
async fn test_read_initial_values() { fn test_read_initial_values() {
let settings = Settings::new(); let settings = Settings::new();
let v1: String = "foo".to_string(); let v1: String = "foo".to_string();
@ -298,12 +277,12 @@ mod tests {
let v4: String = format!("neovide_{}", v1); let v4: String = format!("neovide_{}", v1);
let v5: String = format!("neovide_{}", v2); let v5: String = format!("neovide_{}", v2);
let (nvim, _, _) = create::new_child_cmd(&mut create_nvim_command(), NeovimHandler()) let mut session = Session::new_child_cmd(&mut create_nvim_command())
.await .unwrap_or_explained_panic("Could not locate or start neovim process");
.unwrap_or_explained_panic("Could not locate or start the neovim process"); session.start_event_loop_channel();
let mut nvim = Neovim::new(session);
nvim.set_var(&v4, Value::from(v2.clone())).await.ok(); nvim.set_var(&v4, Value::from(v2.clone())).unwrap();
println!("v4 set");
fn noop_update(_v: Value) {} fn noop_update(_v: Value) {}
@ -327,10 +306,10 @@ mod tests {
settings.readers.force_unlock_write(); settings.readers.force_unlock_write();
} }
settings.read_initial_values(&nvim).await; settings.read_initial_values(&mut nvim);
let rt1 = nvim.get_var(&v4).await.unwrap(); let rt1 = nvim.get_var(&v4).unwrap();
let rt2 = nvim.get_var(&v5).await.unwrap(); let rt2 = nvim.get_var(&v5).unwrap();
let r1 = rt1.as_str().unwrap(); let r1 = rt1.as_str().unwrap();
let r2 = rt2.as_str().unwrap(); let r2 = rt2.as_str().unwrap();

@ -1,28 +1,28 @@
use std::sync::atomic::{AtomicBool, Ordering};
use std::sync::mpsc::{Receiver, Sender};
use std::sync::Arc;
use std::thread::sleep; use std::thread::sleep;
use std::time::{Duration, Instant}; use std::time::{Duration, Instant};
use std::sync::Arc;
use std::sync::atomic::{Ordering, AtomicBool};
use std::sync::mpsc::{Sender, Receiver};
use log::{debug, error, warn, info, trace}; use log::{debug, error, info, trace, warn};
use skulpin::ash::prelude::VkResult;
use skulpin::sdl2; use skulpin::sdl2;
use skulpin::sdl2::event::{Event, WindowEvent}; use skulpin::sdl2::event::{Event, WindowEvent};
use skulpin::sdl2::keyboard::Keycode; use skulpin::sdl2::keyboard::Keycode;
use skulpin::sdl2::video::FullscreenType; use skulpin::sdl2::video::FullscreenType;
use skulpin::sdl2::Sdl; use skulpin::sdl2::Sdl;
use skulpin::ash::prelude::VkResult;
use skulpin::{ use skulpin::{
CoordinateSystem, LogicalSize, PhysicalSize, PresentMode, Renderer as SkulpinRenderer, CoordinateSystem, LogicalSize, PhysicalSize, PresentMode, Renderer as SkulpinRenderer,
RendererBuilder, Sdl2Window, Window, RendererBuilder, Sdl2Window, Window,
}; };
use crate::editor::{DrawCommand, WindowCommand};
use crate::bridge::{produce_neovim_keybinding_string, UiCommand}; use crate::bridge::{produce_neovim_keybinding_string, UiCommand};
use crate::editor::{DrawCommand, WindowCommand};
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 crate::INITIAL_DIMENSIONS; use crate::INITIAL_DIMENSIONS;
use crate::error_handling::ResultPanicExplanation;
#[derive(RustEmbed)] #[derive(RustEmbed)]
#[folder = "assets/"] #[folder = "assets/"]
@ -37,15 +37,21 @@ fn windows_fix_dpi() {
} }
} }
fn handle_new_grid_size(new_size: LogicalSize, renderer: &Renderer, ui_command_sender: &Sender<UiCommand>) { fn handle_new_grid_size(
new_size: LogicalSize,
renderer: &Renderer,
ui_command_sender: &Sender<UiCommand>,
) {
if new_size.width > 0 && new_size.height > 0 { if new_size.width > 0 && new_size.height > 0 {
let new_width = ((new_size.width + 1) as f32 / renderer.font_width) as u32; let new_width = ((new_size.width + 1) as f32 / renderer.font_width) as u32;
let new_height = ((new_size.height + 1) as f32 / renderer.font_height) as u32; let new_height = ((new_size.height + 1) as f32 / renderer.font_height) as u32;
// Add 1 here to make sure resizing doesn't change the grid size on startup // Add 1 here to make sure resizing doesn't change the grid size on startup
ui_command_sender.send(UiCommand::Resize { ui_command_sender
width: new_width, .send(UiCommand::Resize {
height: new_height, width: new_width,
}).ok(); height: new_height,
})
.ok();
} }
} }
@ -65,7 +71,7 @@ struct WindowWrapper {
cached_size: (u32, u32), cached_size: (u32, u32),
cached_position: (i32, i32), cached_position: (i32, i32),
ui_command_sender: Sender<UiCommand>, ui_command_sender: Sender<UiCommand>,
running: Arc<AtomicBool> running: Arc<AtomicBool>,
} }
pub fn window_geometry() -> Result<(u64, u64), String> { pub fn window_geometry() -> Result<(u64, u64), String> {
@ -111,7 +117,11 @@ pub fn window_geometry_or_default() -> (u64, u64) {
} }
impl WindowWrapper { impl WindowWrapper {
pub fn new(ui_command_sender: Sender<UiCommand>, draw_command_receiver: Receiver<DrawCommand>, running: Arc<AtomicBool>) -> WindowWrapper { pub fn new(
ui_command_sender: Sender<UiCommand>,
batched_draw_command_receiver: Receiver<Vec<DrawCommand>>,
running: Arc<AtomicBool>,
) -> WindowWrapper {
let context = sdl2::init().expect("Failed to initialize sdl2"); let context = sdl2::init().expect("Failed to initialize sdl2");
let video_subsystem = context let video_subsystem = context
.video() .video()
@ -120,7 +130,7 @@ impl WindowWrapper {
let (width, height) = window_geometry_or_default(); let (width, height) = window_geometry_or_default();
let renderer = Renderer::new(draw_command_receiver); let renderer = Renderer::new(batched_draw_command_receiver);
let logical_size = LogicalSize { let logical_size = LogicalSize {
width: (width as f32 * renderer.font_width) as u32, width: (width as f32 * renderer.font_width) as u32,
height: (height as f32 * renderer.font_height + 1.0) as u32, height: (height as f32 * renderer.font_height + 1.0) as u32,
@ -172,7 +182,7 @@ impl WindowWrapper {
cached_size: (0, 0), cached_size: (0, 0),
cached_position: (0, 0), cached_position: (0, 0),
ui_command_sender, ui_command_sender,
running running,
} }
} }
@ -270,28 +280,36 @@ impl WindowWrapper {
if let Some(keybinding_string) = produce_neovim_keybinding_string(keycode, text, modifiers) if let Some(keybinding_string) = produce_neovim_keybinding_string(keycode, text, modifiers)
{ {
self.ui_command_sender.send(UiCommand::Keyboard(keybinding_string)).unwrap_or_explained_panic( self.ui_command_sender
"Could not send UI command from the window system to the neovim process.", .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) { pub fn handle_pointer_motion(&mut self, x: i32, y: i32) {
let previous_position = self.mouse_position; let previous_position = self.mouse_position;
let sdl_window_wrapper = Sdl2Window::new(&self.window); let sdl_window_wrapper = Sdl2Window::new(&self.window);
let logical_position = PhysicalSize::new(x as u32, y as u32) let logical_position =
.to_logical(sdl_window_wrapper.scale_factor()); PhysicalSize::new(x as u32, y as u32).to_logical(sdl_window_wrapper.scale_factor());
let mut top_window_position = (0.0, 0.0); let mut top_window_position = (0.0, 0.0);
let mut top_grid_position = None; let mut top_grid_position = None;
for (grid_id, window_region) in self.renderer.window_regions.iter() { for (grid_id, window_region) in self.renderer.window_regions.iter() {
if logical_position.width >= window_region.left as u32 && logical_position.width < window_region.right as u32 && if logical_position.width >= window_region.left as u32
logical_position.height >= window_region.top as u32 && logical_position.height < window_region.bottom as u32 { && logical_position.width < window_region.right as u32
&& logical_position.height >= window_region.top as u32
&& logical_position.height < window_region.bottom as u32
{
top_window_position = (window_region.left, window_region.top); top_window_position = (window_region.left, window_region.top);
top_grid_position = Some(( top_grid_position = Some((
grid_id, grid_id,
LogicalSize::new(logical_position.width - window_region.left as u32, logical_position.height - window_region.top as u32) LogicalSize::new(
logical_position.width - window_region.left as u32,
logical_position.height - window_region.top as u32,
),
)); ));
} }
} }
@ -300,40 +318,48 @@ impl WindowWrapper {
self.grid_id_under_mouse = *grid_id; self.grid_id_under_mouse = *grid_id;
self.mouse_position = LogicalSize::new( self.mouse_position = LogicalSize::new(
(grid_position.width as f32 / self.renderer.font_width) as u32, (grid_position.width as f32 / self.renderer.font_width) as u32,
(grid_position.height as f32 / self.renderer.font_height) 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 { if self.mouse_enabled && self.mouse_down && previous_position != self.mouse_position {
let (window_left, window_top) = top_window_position; let (window_left, window_top) = top_window_position;
let adjusted_drag_left = self.mouse_position.width + (window_left / self.renderer.font_width) as u32; let adjusted_drag_left =
let adjusted_drag_top = self.mouse_position.height + (window_top / self.renderer.font_height) as u32; self.mouse_position.width + (window_left / self.renderer.font_width) as u32;
let adjusted_drag_top =
self.ui_command_sender.send(UiCommand::Drag { self.mouse_position.height + (window_top / self.renderer.font_height) as u32;
grid_id: self.grid_id_under_mouse,
position: (adjusted_drag_left, adjusted_drag_top), self.ui_command_sender
}).ok(); .send(UiCommand::Drag {
grid_id: self.grid_id_under_mouse,
position: (adjusted_drag_left, adjusted_drag_top),
})
.ok();
} }
} }
} }
pub fn handle_pointer_down(&mut self) { pub fn handle_pointer_down(&mut self) {
if self.mouse_enabled { if self.mouse_enabled {
self.ui_command_sender.send(UiCommand::MouseButton { self.ui_command_sender
action: String::from("press"), .send(UiCommand::MouseButton {
grid_id: self.grid_id_under_mouse, action: String::from("press"),
position: (self.mouse_position.width, self.mouse_position.height), grid_id: self.grid_id_under_mouse,
}).ok(); position: (self.mouse_position.width, self.mouse_position.height),
})
.ok();
} }
self.mouse_down = true; self.mouse_down = true;
} }
pub fn handle_pointer_up(&mut self) { pub fn handle_pointer_up(&mut self) {
if self.mouse_enabled { if self.mouse_enabled {
self.ui_command_sender.send(UiCommand::MouseButton { self.ui_command_sender
action: String::from("release"), .send(UiCommand::MouseButton {
grid_id: self.grid_id_under_mouse, action: String::from("release"),
position: (self.mouse_position.width, self.mouse_position.height), grid_id: self.grid_id_under_mouse,
}).ok(); position: (self.mouse_position.width, self.mouse_position.height),
})
.ok();
} }
self.mouse_down = false; self.mouse_down = false;
} }
@ -350,11 +376,13 @@ impl WindowWrapper {
}; };
if let Some(input_type) = vertical_input_type { if let Some(input_type) = vertical_input_type {
self.ui_command_sender.send(UiCommand::Scroll { self.ui_command_sender
direction: input_type.to_string(), .send(UiCommand::Scroll {
grid_id: self.grid_id_under_mouse, direction: input_type.to_string(),
position: (self.mouse_position.width, self.mouse_position.height), grid_id: self.grid_id_under_mouse,
}).ok(); position: (self.mouse_position.width, self.mouse_position.height),
})
.ok();
} }
let horizontal_input_type = match y { let horizontal_input_type = match y {
@ -364,11 +392,13 @@ impl WindowWrapper {
}; };
if let Some(input_type) = horizontal_input_type { if let Some(input_type) = horizontal_input_type {
self.ui_command_sender.send(UiCommand::Scroll { self.ui_command_sender
direction: input_type.to_string(), .send(UiCommand::Scroll {
grid_id: self.grid_id_under_mouse, direction: input_type.to_string(),
position: (self.mouse_position.width, self.mouse_position.height), grid_id: self.grid_id_under_mouse,
}).ok(); position: (self.mouse_position.width, self.mouse_position.height),
})
.ok();
} }
} }
@ -396,12 +426,14 @@ impl WindowWrapper {
if REDRAW_SCHEDULER.should_draw() || SETTINGS.get::<WindowSettings>().no_idle { if REDRAW_SCHEDULER.should_draw() || SETTINGS.get::<WindowSettings>().no_idle {
let renderer = &mut self.renderer; let renderer = &mut self.renderer;
self.skulpin_renderer self.skulpin_renderer.draw(
.draw(&sdl_window_wrapper, |canvas, coordinate_system_helper| { &sdl_window_wrapper,
|canvas, coordinate_system_helper| {
if renderer.draw_frame(canvas, &coordinate_system_helper, dt) { if renderer.draw_frame(canvas, &coordinate_system_helper, dt) {
handle_new_grid_size(current_size, &renderer, &ui_command_sender); handle_new_grid_size(current_size, &renderer, &ui_command_sender);
} }
})?; },
)?;
Ok(true) Ok(true)
} else { } else {
@ -436,8 +468,17 @@ pub fn initialize_settings() {
register_nvim_setting!("fullscreen", WindowSettings::fullscreen); register_nvim_setting!("fullscreen", WindowSettings::fullscreen);
} }
pub fn start_window(draw_command_receiver: Receiver<DrawCommand>, window_command_receiver: Receiver<WindowCommand>, ui_command_sender: Sender<UiCommand>, running: Arc<AtomicBool>) { pub fn start_window(
let mut window = WindowWrapper::new(ui_command_sender.clone(), draw_command_receiver, running.clone()); batched_draw_command_receiver: Receiver<Vec<DrawCommand>>,
window_command_receiver: Receiver<WindowCommand>,
ui_command_sender: Sender<UiCommand>,
running: Arc<AtomicBool>,
) {
let mut window = WindowWrapper::new(
ui_command_sender.clone(),
batched_draw_command_receiver,
running.clone(),
);
info!("Starting window event loop"); info!("Starting window event loop");
let mut event_pump = window let mut event_pump = window
@ -507,14 +548,16 @@ pub fn start_window(draw_command_receiver: Receiver<DrawCommand>, window_command
for window_command in window_command_receiver.try_iter() { for window_command in window_command_receiver.try_iter() {
match window_command { match window_command {
WindowCommand::TitleChanged(new_title) => window.handle_title_changed(new_title), WindowCommand::TitleChanged(new_title) => window.handle_title_changed(new_title),
WindowCommand::SetMouseEnabled(mouse_enabled) => window.mouse_enabled = mouse_enabled, WindowCommand::SetMouseEnabled(mouse_enabled) => {
window.mouse_enabled = mouse_enabled
}
} }
} }
match window.draw_frame(dt) { match window.draw_frame(dt) {
Ok(animating) => { Ok(animating) => {
was_animating = animating; was_animating = animating;
}, }
Err(error) => { Err(error) => {
error!("Render failed: {}", error); error!("Render failed: {}", error);
break; break;

Loading…
Cancel
Save