Merge pull request #865 from neovide/refactor-grid-conv

Refactor grid conversions
macos-click-through
partizan 3 years ago committed by GitHub
commit 9149c98292
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -1,4 +1,5 @@
use crate::settings::*; use crate::settings::*;
use crate::utils::Dimensions;
use clap::{App, Arg}; use clap::{App, Arg};
@ -11,7 +12,7 @@ pub struct CmdLineSettings {
pub files_to_open: Vec<String>, pub files_to_open: Vec<String>,
pub nofork: bool, pub nofork: bool,
pub geometry: WindowGeometry, pub geometry: Dimensions,
pub wsl: bool, pub wsl: bool,
pub remote_tcp: Option<String>, pub remote_tcp: Option<String>,
pub multi_grid: bool, pub multi_grid: bool,

@ -20,6 +20,7 @@ mod error_handling;
mod redraw_scheduler; mod redraw_scheduler;
mod renderer; mod renderer;
mod settings; mod settings;
mod utils;
mod window; mod window;
pub mod windows_utils; pub mod windows_utils;

@ -228,8 +228,7 @@ impl CursorRenderer {
pub fn update_cursor_destination( pub fn update_cursor_destination(
&mut self, &mut self,
font_width: u64, (font_width, font_height): (u64, u64),
font_height: u64,
windows: &HashMap<u64, RenderedWindow>, windows: &HashMap<u64, RenderedWindow>,
) { ) {
let (cursor_grid_x, cursor_grid_y) = self.cursor.grid_position; let (cursor_grid_x, cursor_grid_y) = self.cursor.grid_position;
@ -244,7 +243,7 @@ impl CursorRenderer {
// grid position. // grid position.
grid_y = grid_y grid_y = grid_y
.max(window.grid_current_position.y) .max(window.grid_current_position.y)
.min(window.grid_current_position.y + window.grid_height as f32 - 1.0); .min(window.grid_current_position.y + window.grid_size.height as f32 - 1.0);
self.destination = (grid_x * font_width as f32, grid_y * font_height as f32).into(); self.destination = (grid_x * font_width as f32, grid_y * font_height as f32).into();
} else { } else {
@ -259,13 +258,12 @@ impl CursorRenderer {
pub fn draw( pub fn draw(
&mut self, &mut self,
default_colors: &Colors, default_colors: &Colors,
font_size: (u64, u64), (font_width, font_height): (u64, u64),
current_mode: &EditorMode, current_mode: &EditorMode,
shaper: &mut CachingShaper, shaper: &mut CachingShaper,
canvas: &mut Canvas, canvas: &mut Canvas,
dt: f32, dt: f32,
) { ) {
let (font_width, font_height) = font_size;
let render = self.blink_status.update_status(&self.cursor); let render = self.blink_status.update_status(&self.cursor);
let settings = SETTINGS.get::<CursorSettings>(); let settings = SETTINGS.get::<CursorSettings>();

@ -231,7 +231,7 @@ impl CachingShaper {
pub fn shape(&mut self, cells: &[String], bold: bool, italic: bool) -> Vec<TextBlob> { pub fn shape(&mut self, cells: &[String], bold: bool, italic: bool) -> Vec<TextBlob> {
let current_size = self.current_size(); let current_size = self.current_size();
let (glyph_width, _glyph_height) = self.font_base_dimensions(); let (glyph_width, ..) = self.font_base_dimensions();
let mut resulting_blobs = Vec::new(); let mut resulting_blobs = Vec::new();

@ -1,3 +1,8 @@
pub mod animation_utils;
pub mod cursor_renderer;
mod fonts;
mod rendered_window;
use std::collections::HashMap; use std::collections::HashMap;
use std::sync::mpsc::Receiver; use std::sync::mpsc::Receiver;
use std::sync::Arc; use std::sync::Arc;
@ -6,18 +11,13 @@ use glutin::dpi::PhysicalSize;
use log::{error, trace}; use log::{error, trace};
use skia_safe::{colors, dash_path_effect, BlendMode, Canvas, Color, Paint, Rect, HSV}; use skia_safe::{colors, dash_path_effect, BlendMode, Canvas, Color, Paint, Rect, HSV};
pub mod animation_utils;
pub mod cursor_renderer;
mod fonts;
mod rendered_window;
pub use fonts::caching_shaper::CachingShaper;
pub use rendered_window::{RenderedWindow, WindowDrawDetails};
use crate::bridge::EditorMode; use crate::bridge::EditorMode;
use crate::editor::{Colors, DrawCommand, Style, WindowDrawCommand}; use crate::editor::{Colors, DrawCommand, Style, WindowDrawCommand};
use crate::settings::*; use crate::settings::*;
use crate::utils::Dimensions;
use cursor_renderer::CursorRenderer; use cursor_renderer::CursorRenderer;
pub use fonts::caching_shaper::CachingShaper;
pub use rendered_window::{RenderedWindow, WindowDrawDetails};
#[derive(SettingGroup)] #[derive(SettingGroup)]
#[derive(Clone)] #[derive(Clone)]
@ -48,8 +48,7 @@ pub struct Renderer {
pub paint: Paint, pub paint: Paint,
pub shaper: CachingShaper, pub shaper: CachingShaper,
pub default_style: Arc<Style>, pub default_style: Arc<Style>,
pub font_width: u64, pub font_dimensions: Dimensions,
pub font_height: u64,
pub window_regions: Vec<WindowDrawDetails>, pub window_regions: Vec<WindowDrawDetails>,
pub batched_draw_command_receiver: Receiver<Vec<DrawCommand>>, pub batched_draw_command_receiver: Receiver<Vec<DrawCommand>>,
pub is_ready: bool, pub is_ready: bool,
@ -67,7 +66,7 @@ impl Renderer {
let mut paint = Paint::new(colors::WHITE, None); let mut paint = Paint::new(colors::WHITE, None);
paint.set_anti_alias(false); paint.set_anti_alias(false);
let mut shaper = CachingShaper::new(scale_factor as f32); let mut shaper = CachingShaper::new(scale_factor as f32);
let (font_width, font_height) = shaper.font_base_dimensions(); let font_dimensions: Dimensions = shaper.font_base_dimensions().into();
let default_style = Arc::new(Style::new(Colors::new( let default_style = Arc::new(Style::new(Colors::new(
Some(colors::WHITE), Some(colors::WHITE),
Some(colors::BLACK), Some(colors::BLACK),
@ -82,29 +81,21 @@ impl Renderer {
paint, paint,
shaper, shaper,
default_style, default_style,
font_width, font_dimensions,
font_height,
window_regions, window_regions,
batched_draw_command_receiver, batched_draw_command_receiver,
is_ready: false, is_ready: false,
} }
} }
// TODO: Refactor code to use these two functions instead of multiplication.
/// Convert PhysicalSize to grid size /// Convert PhysicalSize to grid size
pub fn to_grid_size(&self, new_size: PhysicalSize<u32>) -> (u64, u64) { pub fn convert_physical_to_grid(&self, physical: PhysicalSize<u32>) -> Dimensions {
let width = new_size.width as u64 / self.font_width; Dimensions::from(physical) / self.font_dimensions
let height = new_size.height as u64 / self.font_height;
(width, height)
} }
/// Convert grid size to PhysicalSize /// Convert grid size to PhysicalSize
pub fn to_physical_size(&self, new_size: (u64, u64)) -> PhysicalSize<u32> { pub fn convert_grid_to_physical(&self, grid: Dimensions) -> PhysicalSize<u32> {
let (width, height) = new_size; (grid * self.font_dimensions).into()
PhysicalSize {
width: (width * self.font_width) as u32,
height: (height * self.font_height) as u32,
}
} }
pub fn handle_scale_factor_update(&mut self, scale_factor: f64) { pub fn handle_scale_factor_update(&mut self, scale_factor: f64) {
@ -118,23 +109,15 @@ impl Renderer {
} }
fn update_font_dimensions(&mut self) { fn update_font_dimensions(&mut self) {
let (font_width, font_height) = self.shaper.font_base_dimensions(); self.font_dimensions = self.shaper.font_base_dimensions().into();
self.font_width = font_width;
self.font_height = font_height;
self.is_ready = true; self.is_ready = true;
trace!( trace!("Updated font dimensions: {:?}", self.font_dimensions,);
"Updating font dimensions: {}x{}",
self.font_width,
self.font_height,
);
} }
fn compute_text_region(&self, grid_pos: (u64, u64), cell_width: u64) -> Rect { fn compute_text_region(&self, grid_position: (u64, u64), cell_width: u64) -> Rect {
let (grid_x, grid_y) = grid_pos; let (x, y) = grid_position * self.font_dimensions;
let x = grid_x * self.font_width; let width = cell_width * self.font_dimensions.width;
let y = grid_y * self.font_height; let height = self.font_dimensions.height;
let width = cell_width * self.font_width;
let height = self.font_height;
Rect::new(x as f32, y as f32, (x + width) as f32, (y + height) as f32) Rect::new(x as f32, y as f32, (x + width) as f32, (y + height) as f32)
} }
@ -145,13 +128,13 @@ impl Renderer {
fn draw_background( fn draw_background(
&mut self, &mut self,
canvas: &mut Canvas, canvas: &mut Canvas,
grid_pos: (u64, u64), grid_position: (u64, u64),
cell_width: u64, cell_width: u64,
style: &Option<Arc<Style>>, style: &Option<Arc<Style>>,
) { ) {
self.paint.set_blend_mode(BlendMode::Src); self.paint.set_blend_mode(BlendMode::Src);
let region = self.compute_text_region(grid_pos, cell_width); let region = self.compute_text_region(grid_position, cell_width);
let style = style.as_ref().unwrap_or(&self.default_style); let style = style.as_ref().unwrap_or(&self.default_style);
if SETTINGS.get_global::<RendererSettings>().debug_renderer { if SETTINGS.get_global::<RendererSettings>().debug_renderer {
@ -169,20 +152,18 @@ impl Renderer {
&mut self, &mut self,
canvas: &mut Canvas, canvas: &mut Canvas,
cells: &[String], cells: &[String],
grid_pos: (u64, u64), grid_position: (u64, u64),
cell_width: u64, cell_width: u64,
style: &Option<Arc<Style>>, style: &Option<Arc<Style>>,
) { ) {
let (grid_x, grid_y) = grid_pos; let (x, y) = grid_position * self.font_dimensions;
let x = grid_x * self.font_width; let width = cell_width * self.font_dimensions.width;
let y = grid_y * self.font_height;
let width = cell_width * self.font_width;
let style = style.as_ref().unwrap_or(&self.default_style); let style = style.as_ref().unwrap_or(&self.default_style);
canvas.save(); canvas.save();
let region = self.compute_text_region(grid_pos, cell_width); let region = self.compute_text_region(grid_position, cell_width);
canvas.clip_rect(region, None, Some(false)); canvas.clip_rect(region, None, Some(false));
@ -204,10 +185,13 @@ impl Renderer {
} }
canvas.draw_line( canvas.draw_line(
(x as f32, (y - line_position + self.font_height) as f32), (
x as f32,
(y - line_position + self.font_dimensions.height) as f32,
),
( (
(x + width) as f32, (x + width) as f32,
(y - line_position + self.font_height) as f32, (y - line_position + self.font_dimensions.height) as f32,
), ),
&self.paint, &self.paint,
); );
@ -270,8 +254,7 @@ impl Renderer {
self, self,
grid_id, grid_id,
(grid_left as f32, grid_top as f32).into(), (grid_left as f32, grid_top as f32).into(),
width, (width, height).into(),
height,
); );
self.rendered_windows.insert(grid_id, new_window); self.rendered_windows.insert(grid_id, new_window);
} else { } else {
@ -317,13 +300,11 @@ impl Renderer {
root_canvas.reset_matrix(); root_canvas.reset_matrix();
if let Some(root_window) = self.rendered_windows.get(&1) { if let Some(root_window) = self.rendered_windows.get(&1) {
let clip_rect = root_window.pixel_region(self.font_width, self.font_height); let clip_rect = root_window.pixel_region(self.font_dimensions);
root_canvas.clip_rect(&clip_rect, None, Some(false)); root_canvas.clip_rect(&clip_rect, None, Some(false));
} }
let default_background = self.get_default_background(); let default_background = self.get_default_background();
let font_width = self.font_width;
let font_height = self.font_height;
let windows: Vec<&mut RenderedWindow> = { let windows: Vec<&mut RenderedWindow> = {
let (mut root_windows, mut floating_windows): ( let (mut root_windows, mut floating_windows): (
@ -352,6 +333,7 @@ impl Renderer {
}; };
let settings = SETTINGS.get::<RendererSettings>(); let settings = SETTINGS.get::<RendererSettings>();
let font_dimensions = self.font_dimensions;
self.window_regions = windows self.window_regions = windows
.into_iter() .into_iter()
.map(|window| { .map(|window| {
@ -359,8 +341,7 @@ impl Renderer {
root_canvas, root_canvas,
&settings, &settings,
default_background, default_background,
font_width, font_dimensions,
font_height,
dt, dt,
) )
}) })
@ -368,11 +349,11 @@ impl Renderer {
let windows = &self.rendered_windows; let windows = &self.rendered_windows;
self.cursor_renderer self.cursor_renderer
.update_cursor_destination(font_width, font_height, windows); .update_cursor_destination(font_dimensions.into(), windows);
self.cursor_renderer.draw( self.cursor_renderer.draw(
&self.default_style.colors, &self.default_style.colors,
(self.font_width, self.font_height), font_dimensions.into(),
&self.current_mode, &self.current_mode,
&mut self.shaper, &mut self.shaper,
root_canvas, root_canvas,

@ -11,18 +11,14 @@ use super::animation_utils::*;
use super::{Renderer, RendererSettings}; use super::{Renderer, RendererSettings};
use crate::editor::WindowDrawCommand; use crate::editor::WindowDrawCommand;
use crate::redraw_scheduler::REDRAW_SCHEDULER; use crate::redraw_scheduler::REDRAW_SCHEDULER;
use crate::utils::Dimensions;
fn build_window_surface( fn build_window_surface(parent_canvas: &mut Canvas, pixel_size: (i32, i32)) -> Surface {
parent_canvas: &mut Canvas,
pixel_width: u64,
pixel_height: u64,
) -> Surface {
let dimensions = (pixel_width as i32, pixel_height as i32);
let mut context = parent_canvas.recording_context().unwrap(); let mut context = parent_canvas.recording_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();
let image_info = ImageInfo::new( let image_info = ImageInfo::new(
dimensions, pixel_size,
parent_image_info.color_type(), parent_image_info.color_type(),
parent_image_info.alpha_type(), parent_image_info.alpha_type(),
parent_image_info.color_space(), parent_image_info.color_space(),
@ -45,12 +41,10 @@ fn build_window_surface(
fn build_window_surface_with_grid_size( fn build_window_surface_with_grid_size(
parent_canvas: &mut Canvas, parent_canvas: &mut Canvas,
renderer: &Renderer, renderer: &Renderer,
grid_width: u64, grid_size: Dimensions,
grid_height: u64,
) -> Surface { ) -> Surface {
let pixel_width = ((grid_width * renderer.font_width) as f32) as u64; let mut surface =
let pixel_height = ((grid_height * renderer.font_height) as f32) as u64; build_window_surface(parent_canvas, (grid_size * renderer.font_dimensions).into());
let mut surface = build_window_surface(parent_canvas, pixel_width, pixel_height);
let canvas = surface.canvas(); let canvas = surface.canvas();
canvas.clear(renderer.get_default_background()); canvas.clear(renderer.get_default_background());
@ -71,12 +65,10 @@ impl LocatedSurface {
fn new( fn new(
parent_canvas: &mut Canvas, parent_canvas: &mut Canvas,
renderer: &Renderer, renderer: &Renderer,
grid_width: u64, grid_size: Dimensions,
grid_height: u64,
top_line: u64, top_line: u64,
) -> LocatedSurface { ) -> LocatedSurface {
let surface = let surface = build_window_surface_with_grid_size(parent_canvas, renderer, grid_size);
build_window_surface_with_grid_size(parent_canvas, renderer, grid_width, grid_height);
LocatedSurface { surface, top_line } LocatedSurface { surface, top_line }
} }
@ -98,8 +90,7 @@ pub struct RenderedWindow {
pub hidden: bool, pub hidden: bool,
pub floating_order: Option<u64>, pub floating_order: Option<u64>,
pub grid_width: u64, pub grid_size: Dimensions,
pub grid_height: u64,
grid_start_position: Point, grid_start_position: Point,
pub grid_current_position: Point, pub grid_current_position: Point,
@ -125,11 +116,9 @@ impl RenderedWindow {
renderer: &Renderer, renderer: &Renderer,
id: u64, id: u64,
grid_position: Point, grid_position: Point,
grid_width: u64, grid_size: Dimensions,
grid_height: u64,
) -> RenderedWindow { ) -> RenderedWindow {
let current_surface = let current_surface = LocatedSurface::new(parent_canvas, renderer, grid_size, 0);
LocatedSurface::new(parent_canvas, renderer, grid_width, grid_height, 0);
RenderedWindow { RenderedWindow {
snapshots: VecDeque::new(), snapshots: VecDeque::new(),
@ -138,8 +127,7 @@ impl RenderedWindow {
hidden: false, hidden: false,
floating_order: None, floating_order: None,
grid_width, grid_size,
grid_height,
grid_start_position: grid_position, grid_start_position: grid_position,
grid_current_position: grid_position, grid_current_position: grid_position,
@ -153,16 +141,15 @@ impl RenderedWindow {
} }
} }
pub fn pixel_region(&self, font_width: u64, font_height: u64) -> Rect { pub fn pixel_region(&self, font_dimensions: Dimensions) -> Rect {
let current_pixel_position = Point::new( let current_pixel_position = Point::new(
self.grid_current_position.x * font_width as f32, self.grid_current_position.x * font_dimensions.width as f32,
self.grid_current_position.y * font_height as f32, self.grid_current_position.y * font_dimensions.height as f32,
); );
let image_width = (self.grid_width * font_width) as i32; let image_size: (i32, i32) = (self.grid_size * font_dimensions).into();
let image_height = (self.grid_height * font_height) as i32;
Rect::from_point_and_size(current_pixel_position, (image_width, image_height)) Rect::from_point_and_size(current_pixel_position, image_size)
} }
pub fn update(&mut self, settings: &RendererSettings, dt: f32) -> bool { pub fn update(&mut self, settings: &RendererSettings, dt: f32) -> bool {
@ -212,15 +199,14 @@ impl RenderedWindow {
root_canvas: &mut Canvas, root_canvas: &mut Canvas,
settings: &RendererSettings, settings: &RendererSettings,
default_background: Color, default_background: Color,
font_width: u64, font_dimensions: Dimensions,
font_height: u64,
dt: f32, dt: f32,
) -> WindowDrawDetails { ) -> WindowDrawDetails {
if self.update(settings, dt) { if self.update(settings, dt) {
REDRAW_SCHEDULER.queue_next_frame(); REDRAW_SCHEDULER.queue_next_frame();
} }
let pixel_region = self.pixel_region(font_width, font_height); let pixel_region = self.pixel_region(font_dimensions);
root_canvas.save(); root_canvas.save();
root_canvas.clip_rect(&pixel_region, None, Some(false)); root_canvas.clip_rect(&pixel_region, None, Some(false));
@ -252,6 +238,8 @@ impl RenderedWindow {
paint.set_color(Color::from_argb(a, 255, 255, 255)); paint.set_color(Color::from_argb(a, 255, 255, 255));
let font_height = font_dimensions.height;
// Draw scrolling snapshots // Draw scrolling snapshots
for snapshot in self.snapshots.iter_mut().rev() { for snapshot in self.snapshots.iter_mut().rev() {
let scroll_offset = (snapshot.top_line * font_height) as f32 let scroll_offset = (snapshot.top_line * font_height) as f32
@ -298,10 +286,11 @@ impl RenderedWindow {
match draw_command { match draw_command {
WindowDrawCommand::Position { WindowDrawCommand::Position {
grid_position: (grid_left, grid_top), grid_position: (grid_left, grid_top),
grid_size: (grid_width, grid_height), grid_size,
floating_order, floating_order,
} => { } => {
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();
let new_grid_size: Dimensions = grid_size.into();
if self.grid_destination != new_destination { if self.grid_destination != new_destination {
if self.grid_start_position.x.abs() > f32::EPSILON if self.grid_start_position.x.abs() > f32::EPSILON
@ -318,13 +307,12 @@ impl RenderedWindow {
self.grid_destination = new_destination; self.grid_destination = new_destination;
} }
if grid_width != self.grid_width || grid_height != self.grid_height { if self.grid_size != new_grid_size {
let mut old_surface = self.current_surface.surface; let mut old_surface = self.current_surface.surface;
self.current_surface.surface = build_window_surface_with_grid_size( self.current_surface.surface = build_window_surface_with_grid_size(
old_surface.canvas(), old_surface.canvas(),
renderer, renderer,
grid_width, new_grid_size,
grid_height,
); );
old_surface.draw( old_surface.draw(
self.current_surface.surface.canvas(), self.current_surface.surface.canvas(),
@ -333,8 +321,7 @@ impl RenderedWindow {
None, None,
); );
self.grid_width = grid_width; self.grid_size = new_grid_size;
self.grid_height = grid_height;
} }
self.floating_order = floating_order; self.floating_order = floating_order;
@ -354,8 +341,8 @@ impl RenderedWindow {
style, style,
} => { } => {
let grid_position = (window_left, window_top); let grid_position = (window_left, window_top);
let canvas = self.current_surface.surface.canvas(); let canvas = self.current_surface.surface.canvas();
canvas.save(); canvas.save();
renderer.draw_background(canvas, grid_position, width, &style); renderer.draw_background(canvas, grid_position, width, &style);
renderer.draw_foreground(canvas, &cells, grid_position, width, &style); renderer.draw_foreground(canvas, &cells, grid_position, width, &style);
@ -369,17 +356,22 @@ impl RenderedWindow {
rows, rows,
cols, cols,
} => { } => {
let font_width = renderer.font_width as f32; let Dimensions {
let font_height = renderer.font_height as f32; width: font_width,
height: font_height,
} = renderer.font_dimensions;
let scrolled_region = Rect::new( let scrolled_region = Rect::new(
left as f32 * font_width, (left * font_width) as f32,
top as f32 * font_height, (top * font_height) as f32,
right as f32 * font_width, (right * font_width) as f32,
bottom as f32 * font_height, (bottom * font_height) as f32,
); );
let mut translated_region = scrolled_region; let mut translated_region = scrolled_region;
translated_region.offset((-cols as f32 * font_width, -rows as f32 * font_height)); translated_region.offset((
-cols as f32 * font_width as f32,
-rows as f32 * font_height as f32,
));
let snapshot = self.current_surface.surface.image_snapshot(); let snapshot = self.current_surface.surface.image_snapshot();
let canvas = self.current_surface.surface.canvas(); let canvas = self.current_surface.surface.canvas();
@ -400,8 +392,7 @@ impl RenderedWindow {
self.current_surface.surface = build_window_surface_with_grid_size( self.current_surface.surface = build_window_surface_with_grid_size(
self.current_surface.surface.canvas(), self.current_surface.surface.canvas(),
renderer, renderer,
self.grid_width, self.grid_size,
self.grid_height,
); );
self.snapshots.clear(); self.snapshots.clear();

@ -9,9 +9,7 @@ use log::trace;
use nvim_rs::Neovim; use nvim_rs::Neovim;
use parking_lot::RwLock; use parking_lot::RwLock;
pub use rmpv::Value; pub use rmpv::Value;
pub use window_geometry::{ pub use window_geometry::{maybe_save_window_size, parse_window_geometry, DEFAULT_WINDOW_GEOMETRY};
maybe_save_window_size, parse_window_geometry, WindowGeometry, DEFAULT_WINDOW_GEOMETRY,
};
use crate::bridge::TxWrapper; use crate::bridge::TxWrapper;
use crate::error_handling::ResultPanicExplanation; use crate::error_handling::ResultPanicExplanation;

@ -1,6 +1,6 @@
use crate::settings::SETTINGS; use crate::settings::SETTINGS;
use crate::utils::Dimensions;
use crate::window::WindowSettings; use crate::window::WindowSettings;
use serde::{Deserialize, Serialize};
use std::path::PathBuf; use std::path::PathBuf;
#[cfg(unix)] #[cfg(unix)]
@ -8,56 +8,40 @@ const SETTINGS_PATH: &str = ".local/share/nvim/neovide-settings.json";
#[cfg(windows)] #[cfg(windows)]
const SETTINGS_PATH: &str = "AppData/Local/nvim-data/neovide-settings.json"; const SETTINGS_PATH: &str = "AppData/Local/nvim-data/neovide-settings.json";
#[derive(Debug, Clone, Copy, Eq, PartialEq, Serialize, Deserialize)]
pub struct WindowGeometry {
pub width: u64,
pub height: u64,
}
impl From<(u64, u64)> for WindowGeometry {
fn from((width, height): (u64, u64)) -> Self {
WindowGeometry { width, height }
}
}
fn neovim_std_datapath() -> PathBuf { fn neovim_std_datapath() -> PathBuf {
let mut settings_path = dirs::home_dir().unwrap(); let mut settings_path = dirs::home_dir().unwrap();
settings_path.push(SETTINGS_PATH); settings_path.push(SETTINGS_PATH);
settings_path settings_path
} }
pub fn try_to_load_last_window_size() -> Result<WindowGeometry, String> { pub fn try_to_load_last_window_size() -> Result<Dimensions, String> {
let settings_path = neovim_std_datapath(); let settings_path = neovim_std_datapath();
let serialized_size = std::fs::read_to_string(&settings_path).map_err(|e| e.to_string())?; let json = std::fs::read_to_string(&settings_path).map_err(|e| e.to_string())?;
let deserialize_size: WindowGeometry = let geometry: Dimensions = serde_json::from_str(&json).map_err(|e| e.to_string())?;
serde_json::from_str(&serialized_size).map_err(|e| e.to_string())?; log::debug!("Loaded Window Size: {:?}", geometry);
log::debug!("Loaded Window Size: {:?}", deserialize_size); Ok(geometry)
Ok(deserialize_size)
} }
pub const DEFAULT_WINDOW_GEOMETRY: WindowGeometry = WindowGeometry { pub const DEFAULT_WINDOW_GEOMETRY: Dimensions = Dimensions {
width: 100, width: 100,
height: 50, height: 50,
}; };
pub fn maybe_save_window_size(grid_size: Option<WindowGeometry>) { pub fn maybe_save_window_size(grid_size: Option<Dimensions>) {
let settings = SETTINGS.get::<WindowSettings>(); let settings = SETTINGS.get::<WindowSettings>();
let saved_window_size = if settings.remember_window_size && grid_size.is_some() { let saved_window_size = if settings.remember_window_size {
grid_size.unwrap() grid_size.unwrap_or(DEFAULT_WINDOW_GEOMETRY)
} else { } else {
WindowGeometry { DEFAULT_WINDOW_GEOMETRY
width: DEFAULT_WINDOW_GEOMETRY.width as u64,
height: DEFAULT_WINDOW_GEOMETRY.height as u64,
}
}; };
let settings_path = neovim_std_datapath(); let settings_path = neovim_std_datapath();
let serialized_size = serde_json::to_string(&saved_window_size).unwrap(); let json = serde_json::to_string(&saved_window_size).unwrap();
log::debug!("Saved Window Size: {}", serialized_size); log::debug!("Saved Window Size: {}", json);
std::fs::write(settings_path, serialized_size).unwrap(); std::fs::write(settings_path, json).unwrap();
} }
pub fn parse_window_geometry(geometry: Option<String>) -> Result<WindowGeometry, String> { pub fn parse_window_geometry(geometry: Option<String>) -> Result<Dimensions, String> {
let saved_window_size = let saved_window_size =
try_to_load_last_window_size().or::<String>(Ok(DEFAULT_WINDOW_GEOMETRY)); try_to_load_last_window_size().or::<String>(Ok(DEFAULT_WINDOW_GEOMETRY));
geometry.map_or(saved_window_size, |input| { geometry.map_or(saved_window_size, |input| {
@ -83,7 +67,7 @@ pub fn parse_window_geometry(geometry: Option<String>) -> Result<WindowGeometry,
.collect::<Result<Vec<_>, &str>>() .collect::<Result<Vec<_>, &str>>()
.and_then(|dimensions| { .and_then(|dimensions| {
if let [width, height] = dimensions[..] { if let [width, height] = dimensions[..] {
Ok(WindowGeometry { width, height }) Ok(Dimensions { width, height })
} else { } else {
Err(invalid_parse_err.as_str()) Err(invalid_parse_err.as_str())
} }

@ -0,0 +1,83 @@
use glutin::dpi::PhysicalSize;
use serde::{Deserialize, Serialize};
use std::ops::{Div, Mul};
// Maybe this should be independent from serialization?
#[derive(Debug, Clone, Copy, Eq, PartialEq, Serialize, Deserialize)]
pub struct Dimensions {
pub width: u64,
pub height: u64,
}
macro_rules! impl_from_tuple_to_dimensions {
($type:ty) => {
impl From<($type, $type)> for Dimensions {
fn from((width, height): ($type, $type)) -> Self {
Dimensions {
width: width as u64,
height: height as u64,
}
}
}
};
}
macro_rules! impl_from_dimensions_to_tuple {
($type:ty) => {
impl From<Dimensions> for ($type, $type) {
fn from(dimensions: Dimensions) -> Self {
(dimensions.width as $type, dimensions.height as $type)
}
}
};
}
impl_from_tuple_to_dimensions!(u64);
impl_from_tuple_to_dimensions!(f32);
impl_from_dimensions_to_tuple!(u64);
impl_from_dimensions_to_tuple!(u32);
impl_from_dimensions_to_tuple!(i32);
impl From<PhysicalSize<u32>> for Dimensions {
fn from(PhysicalSize { width, height }: PhysicalSize<u32>) -> Self {
Dimensions {
width: width as u64,
height: height as u64,
}
}
}
impl From<Dimensions> for PhysicalSize<u32> {
fn from(Dimensions { width, height }: Dimensions) -> Self {
PhysicalSize {
width: width as u32,
height: height as u32,
}
}
}
impl Mul for Dimensions {
type Output = Self;
fn mul(self, other: Self) -> Self {
Dimensions::from((self.width * other.width, self.height * other.height))
}
}
impl Div for Dimensions {
type Output = Self;
fn div(self, other: Self) -> Self {
Dimensions::from((self.width / other.width, self.height / other.height))
}
}
impl Mul<Dimensions> for (u64, u64) {
type Output = Self;
fn mul(self, other: Dimensions) -> Self {
let (x, y) = self;
(x * other.width, y * other.height)
}
}

@ -0,0 +1,3 @@
mod dimensions;
pub use dimensions::*;

@ -33,7 +33,8 @@ use crate::{
editor::WindowCommand, editor::WindowCommand,
redraw_scheduler::REDRAW_SCHEDULER, redraw_scheduler::REDRAW_SCHEDULER,
renderer::Renderer, renderer::Renderer,
settings::{maybe_save_window_size, WindowGeometry, SETTINGS}, settings::{maybe_save_window_size, SETTINGS},
utils::Dimensions,
}; };
use image::{load_from_memory, GenericImageView, Pixel}; use image::{load_from_memory, GenericImageView, Pixel};
use keyboard_manager::KeyboardManager; use keyboard_manager::KeyboardManager;
@ -53,7 +54,7 @@ pub struct GlutinWindowWrapper {
title: String, title: String,
fullscreen: bool, fullscreen: bool,
saved_inner_size: PhysicalSize<u32>, saved_inner_size: PhysicalSize<u32>,
saved_grid_size: Option<WindowGeometry>, saved_grid_size: Option<Dimensions>,
ui_command_sender: LoggingTx<UiCommand>, ui_command_sender: LoggingTx<UiCommand>,
window_command_receiver: Receiver<WindowCommand>, window_command_receiver: Receiver<WindowCommand>,
} }
@ -177,7 +178,7 @@ impl GlutinWindowWrapper {
if self.saved_grid_size.is_none() && !window.is_maximized() { if self.saved_grid_size.is_none() && !window.is_maximized() {
let size = SETTINGS.get::<CmdLineSettings>().geometry; let size = SETTINGS.get::<CmdLineSettings>().geometry;
window.set_inner_size(self.renderer.to_physical_size((size.width, size.height))); window.set_inner_size(self.renderer.convert_grid_to_physical(size));
self.saved_grid_size = Some(size); self.saved_grid_size = Some(size);
} }
@ -191,7 +192,7 @@ impl GlutinWindowWrapper {
} }
fn handle_new_grid_size(&mut self, new_size: PhysicalSize<u32>) { fn handle_new_grid_size(&mut self, new_size: PhysicalSize<u32>) {
let grid_size: WindowGeometry = self.renderer.to_grid_size(new_size).into(); let grid_size = self.renderer.convert_physical_to_grid(new_size);
if self.saved_grid_size == Some(grid_size) { if self.saved_grid_size == Some(grid_size) {
trace!("Grid matched saved size, skip update."); trace!("Grid matched saved size, skip update.");
return; return;
@ -263,10 +264,9 @@ pub fn create_window(
let skia_renderer = SkiaRenderer::new(&windowed_context); let skia_renderer = SkiaRenderer::new(&windowed_context);
log::info!( log::info!(
"window created (scale_factor: {}, font_size: {}x{})", "window created (scale_factor: {}, font_dimensions: {:?})",
scale_factor, scale_factor,
renderer.font_width, renderer.font_dimensions,
renderer.font_height,
); );
let mut window_wrapper = GlutinWindowWrapper { let mut window_wrapper = GlutinWindowWrapper {

@ -15,8 +15,7 @@ use crate::renderer::{Renderer, WindowDrawDetails};
fn clamp_position( fn clamp_position(
position: PhysicalPosition<f32>, position: PhysicalPosition<f32>,
region: Rect, region: Rect,
font_width: u64, (font_width, font_height): (u64, u64),
font_height: u64,
) -> PhysicalPosition<f32> { ) -> PhysicalPosition<f32> {
PhysicalPosition::new( PhysicalPosition::new(
position position
@ -32,8 +31,7 @@ fn clamp_position(
fn to_grid_coords( fn to_grid_coords(
position: PhysicalPosition<f32>, position: PhysicalPosition<f32>,
font_width: u64, (font_width, font_height): (u64, u64),
font_height: u64,
) -> PhysicalPosition<u32> { ) -> PhysicalPosition<u32> {
PhysicalPosition::new( PhysicalPosition::new(
(position.x as u64 / font_width) as u32, (position.x as u64 / font_width) as u32,
@ -115,14 +113,10 @@ impl MouseManager {
let global_bounds = relevant_window_details let global_bounds = relevant_window_details
.map(|details| details.region) .map(|details| details.region)
.unwrap_or_else(|| Rect::from_wh(size.width as f32, size.height as f32)); .unwrap_or_else(|| Rect::from_wh(size.width as f32, size.height as f32));
let clamped_position = clamp_position( let clamped_position =
position, clamp_position(position, global_bounds, renderer.font_dimensions.into());
global_bounds,
renderer.font_width,
renderer.font_height,
);
self.position = to_grid_coords(clamped_position, renderer.font_width, renderer.font_height); self.position = to_grid_coords(clamped_position, renderer.font_dimensions.into());
if let Some(relevant_window_details) = relevant_window_details { if let Some(relevant_window_details) = relevant_window_details {
let relative_position = PhysicalPosition::new( let relative_position = PhysicalPosition::new(
@ -130,7 +124,7 @@ impl MouseManager {
clamped_position.y - relevant_window_details.region.top, clamped_position.y - relevant_window_details.region.top,
); );
self.relative_position = self.relative_position =
to_grid_coords(relative_position, renderer.font_width, renderer.font_height); to_grid_coords(relative_position, renderer.font_dimensions.into());
let previous_position = self.drag_position; let previous_position = self.drag_position;
// Until https://github.com/neovim/neovim/pull/12667 is merged, we have to special // Until https://github.com/neovim/neovim/pull/12667 is merged, we have to special
@ -254,11 +248,12 @@ impl MouseManager {
} }
} }
fn handle_pixel_scroll(&mut self, renderer: &Renderer, pixel_x: f32, pixel_y: f32) { fn handle_pixel_scroll(
self.handle_line_scroll( &mut self,
pixel_x / renderer.font_width as f32, (font_width, font_height): (u64, u64),
pixel_y / renderer.font_height as f32, (pixel_x, pixel_y): (f32, f32),
); ) {
self.handle_line_scroll(pixel_x / font_width as f32, pixel_y / font_height as f32);
} }
pub fn handle_event( pub fn handle_event(
@ -292,7 +287,10 @@ impl MouseManager {
.. ..
}, },
.. ..
} => self.handle_pixel_scroll(renderer, delta.x as f32, delta.y as f32), } => self.handle_pixel_scroll(
renderer.font_dimensions.into(),
(delta.x as f32, delta.y as f32),
),
Event::WindowEvent { Event::WindowEvent {
event: event:
WindowEvent::MouseInput { WindowEvent::MouseInput {

Loading…
Cancel
Save