Skip to content

Commit

Permalink
Improve gird resizes
Browse files Browse the repository at this point in the history
There were some problems with synchronizing grid resize events sent to
nvim from various sources, e.g. set font, set linespace and window
resize events. To solve this, set font and set linespace handling is now
postponed till the next `flush` event which we'll eventually receive
from nvim.

The uiattach call to nvim could still be more efficient.

Fix #82
Close #86
  • Loading branch information
vhakulinen committed Aug 6, 2019
1 parent d4d9d93 commit 3375207
Show file tree
Hide file tree
Showing 4 changed files with 147 additions and 149 deletions.
2 changes: 1 addition & 1 deletion src/ui/font.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ impl Display for FontUnit {
}
}

#[derive(Clone)]
#[derive(Clone, Debug)]
pub struct Font {
name: String,
pub height: f32,
Expand Down
70 changes: 29 additions & 41 deletions src/ui/grid/context.rs
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
use cairo;
use gtk::DrawingArea;
use pango;
use pango::FontDescription;
use pangocairo;

use gtk::prelude::*;

use ui::color::{Color, Highlight};
use ui::font::Font;
use ui::grid::render;
use ui::grid::row::Row;

Expand Down Expand Up @@ -62,11 +62,12 @@ impl Context {
let pango_context =
pangocairo::functions::create_context(&cairo_context).unwrap();

let font_desc = FontDescription::from_string("Monospace 12");
let font = Font::from_guifont("Monospace:h12").unwrap();
let font_desc = font.as_pango_font();
pango_context.set_font_description(&font_desc);

let mut cell_metrics = CellMetrics::default();
cell_metrics.font_desc = font_desc;
cell_metrics.font = font;
cell_metrics.line_space = 0;
cell_metrics.update(&pango_context);

Expand Down Expand Up @@ -121,7 +122,7 @@ impl Context {
self.cairo_context.restore();

let pctx = pangocairo::functions::create_context(&ctx).unwrap();
pctx.set_font_description(&self.cell_metrics.font_desc);
pctx.set_font_description(&self.cell_metrics.font.as_pango_font());

self.cairo_context = ctx;
self.pango_context = pctx;
Expand All @@ -134,44 +135,29 @@ impl Context {
/// make the update take place.
pub fn update_metrics(
&mut self,
mut font: Option<FontDescription>,
mut line_space: Option<i64>,
font: Font,
line_space: i64,
da: &gtk::DrawingArea,
) {
if self.cell_metrics_update.is_none() {
self.cell_metrics_update = Some(self.cell_metrics.clone());
}

if let Some(ref mut cm) = self.cell_metrics_update {
if let Some(font) = font.take() {
cm.font_desc = font;
}
if let Some(line_space) = line_space.take() {
cm.line_space = line_space;
}
self.pango_context
.set_font_description(&font.as_pango_font());

cm.update(&self.pango_context);
}
}
self.cell_metrics.font = font;
self.cell_metrics.line_space = line_space;
self.cell_metrics.update(&self.pango_context);

/// Finishes cell metrics update if one is on going.
pub fn finish_metrics_update(&mut self, da: &DrawingArea) {
if let Some(cm) = self.cell_metrics_update.take() {
self.pango_context.set_font_description(&cm.font_desc);
self.cell_metrics = cm;

self.cursor_context = {
let win = da.get_window().unwrap();
let surface = win
.create_similar_surface(
cairo::Content::ColorAlpha,
(self.cell_metrics.width * 2.0) as i32, // times two for double width chars.
self.cell_metrics.height as i32
+ self.cell_metrics.ascent as i32,
)
.unwrap();
cairo::Context::new(&surface)
};
}
self.cursor_context = {
let win = da.get_window().unwrap();
let surface = win
.create_similar_surface(
cairo::Content::ColorAlpha,
(self.cell_metrics.width * 2.0) as i32, // times two for double width chars.
self.cell_metrics.height as i32
+ self.cell_metrics.ascent as i32,
)
.unwrap();
cairo::Context::new(&surface)
};
}

/// Returns x, y, width and height for current cursor location.
Expand Down Expand Up @@ -215,12 +201,14 @@ pub struct CellMetrics {
pub underline_position: f64,

pub line_space: i64,
pub font_desc: FontDescription,
pub font: Font,
}

impl CellMetrics {
pub fn update(&mut self, ctx: &pango::Context) {
let fm = ctx.get_metrics(Some(&self.font_desc), None).unwrap();
let fm = ctx
.get_metrics(Some(&self.font.as_pango_font()), None)
.unwrap();
let extra = self.line_space as f64 / 2.0;
self.ascent = fm.get_ascent() as f64 / pango::SCALE as f64 + extra;
self.decent = fm.get_descent() as f64 / pango::SCALE as f64 + extra;
Expand Down
60 changes: 30 additions & 30 deletions src/ui/grid/grid.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,12 @@ use gdk;
use gdk::{EventMask, ModifierType};
use gtk;
use gtk::{DrawingArea, EventBox};
use pango::FontDescription;

use gtk::prelude::*;

use nvim_bridge::{GridLineSegment, ModeInfo};
use thread_guard::ThreadGuard;
use ui::font::Font;
use ui::grid::context::Context;
use ui::grid::render;
use ui::grid::row::Row;
Expand Down Expand Up @@ -348,11 +348,22 @@ impl Grid {
}
}

pub fn resize(&self, width: u64, height: u64) {
/// Calcualtes the current size of the grid.
pub fn calc_size(&self) -> (i64, i64) {
let mut ctx = self.context.borrow_mut();
let ctx = ctx.as_mut().unwrap();

ctx.finish_metrics_update(&self.da);
let w = self.da.get_allocated_width();
let h = self.da.get_allocated_height();
let cols = (w / ctx.cell_metrics.width as i32) as i64;
let rows = (h / ctx.cell_metrics.height as i32) as i64;

(cols, rows)
}

pub fn resize(&self, width: u64, height: u64) {
let mut ctx = self.context.borrow_mut();
let ctx = ctx.as_mut().unwrap();

// Clear internal grid (rows).
ctx.rows = vec![];
Expand Down Expand Up @@ -437,20 +448,26 @@ impl Grid {
.queue_draw_area(x as i32, y as i32, w as i32, h as i32);
}

/// Sets line space. Actual change is postponed till the next call
/// to `resize`.
pub fn set_line_space(&self, space: i64) {
/// Set a new font and line space. This will likely change the cell metrics.
/// Use `calc_size` to receive the updated size (cols and rows) of the grid.
pub fn update_cell_metrics(&self, font: Font, line_space: i64) {
let mut ctx = self.context.borrow_mut();
let ctx = ctx.as_mut().unwrap();
ctx.update_metrics(None, Some(space));
ctx.update_metrics(font, line_space, &self.da);
}

/// Sets font. Actual change is postponed till the next call
/// to `resize`.
pub fn set_font(&self, font: FontDescription) {
let mut ctx = self.context.borrow_mut();
let ctx = ctx.as_mut().unwrap();
ctx.update_metrics(Some(font), None);
/// Get the current line space value.
pub fn get_line_space(&self) -> i64 {
let ctx = self.context.borrow();
let ctx = ctx.as_ref().unwrap();
ctx.cell_metrics.line_space
}

/// Get a copy of the current font.
pub fn get_font(&self) -> Font {
let ctx = self.context.borrow();
let ctx = ctx.as_ref().unwrap();
ctx.cell_metrics.font.clone()
}

pub fn set_mode(&self, mode: &ModeInfo) {
Expand All @@ -467,23 +484,6 @@ impl Grid {

ctx.busy = busy;
}

/// Calculates the current gird size. Returns (rows, cols).
pub fn calc_size_for_new_metrics(&self) -> Option<(usize, usize)> {
let ctx = self.context.borrow();
let ctx = ctx.as_ref().unwrap();

if let Some(ref cm) = ctx.cell_metrics_update {
let w = self.da.get_allocated_width();
let h = self.da.get_allocated_height();
let cols = (w / cm.width as i32) as usize;
let rows = (h / cm.height as i32) as usize;

Some((rows, cols))
} else {
None
}
}
}

/// Handler for grid's drawingarea's draw event. Draws the internal cairo
Expand Down
Loading

0 comments on commit 3375207

Please sign in to comment.