summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorVille Hakulinen <ville.hakulinen@gmail.com>2020-07-04 22:53:27 +0300
committerVille Hakulinen <ville.hakulinen@gmail.com>2020-07-12 01:57:30 +0300
commit83073de44c953a7152dc4bf0765ec40c0ecb388c (patch)
treed3190a6b3cb84cad7c8aa99aef1b56bcd3480b6b
parent5ff4483e8ecd10a9305ddc136c7500cfe6a65ac7 (diff)
Fix external window handling
-rw-r--r--src/ui/grid/context.rs74
-rw-r--r--src/ui/grid/grid.rs24
-rw-r--r--src/ui/grid/row.rs4
-rw-r--r--src/ui/state.rs26
-rw-r--r--src/ui/window.rs7
5 files changed, 74 insertions, 61 deletions
diff --git a/src/ui/grid/context.rs b/src/ui/grid/context.rs
index d5abef9..eb870f4 100644
--- a/src/ui/grid/context.rs
+++ b/src/ui/grid/context.rs
@@ -1,12 +1,8 @@
use cairo;
+use gtk::prelude::*;
use gtk::DrawingArea;
use pango;
-use gdk::prelude::*;
-use gtk::prelude::*;
-
-use log::warn;
-
use crate::ui::color::{Color, Highlight, HlDefs};
use crate::ui::font::Font;
use crate::ui::grid::render;
@@ -69,9 +65,15 @@ impl Context {
cell_metrics.line_space = line_space;
cell_metrics.update(&pango_context);
- let w = cell_metrics.width as usize * cols;
- let h = cell_metrics.height as usize * rows;
- let surface = create_surface_clamp(win, w as i32, h as i32);
+ let w = cell_metrics.width * cols as f64;
+ let h = cell_metrics.height * rows as f64;
+ let surface = win
+ .create_similar_surface(
+ cairo::Content::Color,
+ w.ceil() as i32,
+ h.ceil() as i32,
+ )
+ .unwrap();
let cairo_context = cairo::Context::new(&surface);
@@ -90,7 +92,7 @@ impl Context {
.create_similar_surface(
cairo::Content::ColorAlpha,
(cell_metrics.width * 2.0) as i32, // times two for double width chars.
- cell_metrics.height as i32 + cell_metrics.ascent as i32,
+ (cell_metrics.height + cell_metrics.ascent).ceil() as i32,
)
.unwrap();
cairo::Context::new(&surface)
@@ -133,9 +135,15 @@ impl Context {
self.cell_metrics.update(&pctx);
- let w = self.cell_metrics.width as usize * cols;
- let h = self.cell_metrics.height as usize * rows;
- let surface = create_surface_clamp(win, w as i32, h as i32);
+ let w = self.cell_metrics.width * cols as f64;
+ let h = self.cell_metrics.height * rows as f64;
+ let surface = win
+ .create_similar_surface(
+ cairo::Content::Color,
+ w.ceil() as i32,
+ h.ceil() as i32,
+ )
+ .unwrap();
let ctx = cairo::Context::new(&surface);
// Fill the context with default bg color.
@@ -187,9 +195,9 @@ impl Context {
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,
+ (self.cell_metrics.width * 2.0).ceil() as i32, // times two for double width chars.
+ (self.cell_metrics.height + self.cell_metrics.ascent).ceil()
+ as i32,
)
.unwrap();
cairo::Context::new(&surface)
@@ -202,7 +210,11 @@ impl Context {
.rows
.get(self.cursor.0 as usize)
.and_then(|row| {
- Some(row.cell_at(self.cursor.1 as usize).double_width)
+ Some(
+ row.cell_at(self.cursor.1 as usize)
+ .map(|c| c.double_width)
+ .unwrap_or(false),
+ )
})
.unwrap_or(false);
@@ -259,33 +271,3 @@ impl CellMetrics {
f64::from(fm.get_underline_thickness()) / scale * 2.0;
}
}
-
-/// Creates a new surface from `win`. Clamps width and height to the size of `win`.
-/// When clamping, warn level log messages are emitted.
-fn create_surface_clamp(win: &gdk::Window, w: i32, h: i32) -> cairo::Surface {
- let max_height = win.get_height();
- let max_width = win.get_width();
-
- let width = if w > max_width {
- warn!(
- "Want to allocate surface with width {}, clamping to {}",
- w, max_width
- );
- max_width
- } else {
- w
- };
-
- let height = if h > max_height {
- warn!(
- "Want to allocate surface with height {}, clamping to {}",
- h, max_height
- );
- max_height
- } else {
- h
- };
-
- win.create_similar_surface(cairo::Content::Color, width, height)
- .unwrap()
-}
diff --git a/src/ui/grid/grid.rs b/src/ui/grid/grid.rs
index 3cf563e..a698cbb 100644
--- a/src/ui/grid/grid.rs
+++ b/src/ui/grid/grid.rs
@@ -118,22 +118,24 @@ impl Grid {
// cairo context.
if ctx.cursor_blink_on == 0 {
if let Some(row) = ctx.rows.get(ctx.cursor.0 as usize) {
- let cell = row.cell_at(ctx.cursor.1 as usize);
- render::cursor_cell(
- &ctx.cursor_context,
- &self.da.get_pango_context().unwrap(),
- &cell,
- &ctx.cell_metrics,
- hl_defs,
- );
+ if let Some(cell) = row.cell_at(ctx.cursor.1 as usize) {
+ render::cursor_cell(
+ &ctx.cursor_context,
+ &self.da.get_pango_context().unwrap(),
+ &cell,
+ &ctx.cell_metrics,
+ hl_defs,
+ );
+ }
}
}
// Update cursor color.
if let Some(row) = ctx.rows.get(ctx.cursor.0 as usize) {
- let cell = row.cell_at(ctx.cursor.1 as usize);
- let hl = hl_defs.get(&cell.hl_id).unwrap();
- ctx.cursor_color = hl.foreground.unwrap_or(hl_defs.default_fg);
+ if let Some(cell) = row.cell_at(ctx.cursor.1 as usize) {
+ let hl = hl_defs.get(&cell.hl_id).unwrap();
+ ctx.cursor_color = hl.foreground.unwrap_or(hl_defs.default_fg);
+ }
}
while let Some(area) = ctx.queue_draw_area.pop() {
diff --git a/src/ui/grid/row.rs b/src/ui/grid/row.rs
index 721e753..fa29964 100644
--- a/src/ui/grid/row.rs
+++ b/src/ui/grid/row.rs
@@ -53,8 +53,8 @@ impl Row {
/// Returns a leaf at a position.
#[inline]
- pub fn cell_at(&self, at: usize) -> &Cell {
- self.cells.get(at).unwrap()
+ pub fn cell_at(&self, at: usize) -> Option<&Cell> {
+ self.cells.get(at)
}
#[allow(unused)] // Not used currently, but tested.
diff --git a/src/ui/state.rs b/src/ui/state.rs
index db053e5..bbf2c56 100644
--- a/src/ui/state.rs
+++ b/src/ui/state.rs
@@ -160,6 +160,17 @@ impl UIState {
let win = window.get_window().unwrap();
if let Some(grid) = self.grids.get(&e.grid) {
grid.resize(&win, e.width, e.height, &self.hl_defs);
+
+ // If the grid is in a window (which is likely), resize the window
+ // to match the grid's size.
+ if let Some(ref w) =
+ self.windows.values().find(|w| w.grid_id == grid.id)
+ {
+ let grid_metrics = grid.get_grid_metrics();
+ let width = grid_metrics.cols * grid_metrics.cell_width;
+ let height = grid_metrics.rows * grid_metrics.cell_height;
+ w.resize((width.ceil() as i32, height.ceil() as i32));
+ }
} else {
let grid = Grid::new(
e.grid,
@@ -625,7 +636,20 @@ impl UIState {
let width = grid_metrics.cols * grid_metrics.cell_width;
let height = grid_metrics.rows * grid_metrics.cell_height;
- window.set_external(&parent_win, (width as i32, height as i32));
+ window.set_external(
+ &parent_win,
+ (width.ceil() as i32, height.ceil() as i32),
+ );
+
+ // NOTE(ville): Without this, "new" grids (e.g. once added to a external
+ // window without appearing in the main grid first) won't get proper
+ // font/linespace values.
+ grid.resize(
+ &parent_win.get_window().unwrap(),
+ grid_metrics.cols as u64,
+ grid_metrics.rows as u64,
+ &self.hl_defs,
+ );
}
fn window_hide(&mut self, grid_id: i64) {
diff --git a/src/ui/window.rs b/src/ui/window.rs
index 637a364..0615df9 100644
--- a/src/ui/window.rs
+++ b/src/ui/window.rs
@@ -101,16 +101,21 @@ impl Window {
}
}
+ pub fn resize(&self, size: (i32, i32)) {
+ self.frame.set_size_request(size.0, size.1);
+ }
+
pub fn set_external(&mut self, parent: &gtk::Window, size: (i32, i32)) {
if self.external_win.is_some() {
return;
}
+ self.frame.set_size_request(size.0, size.1);
+
let win = gtk::Window::new(gtk::WindowType::Toplevel);
self.fixed.remove(&self.frame);
win.add(&self.frame);
- win.set_default_size(size.0, size.1);
win.set_accept_focus(false);
win.set_deletable(false);
win.set_resizable(false);