Remove need for Rc<RefCell<_>> usage

This adds a trait OnResize and a separate method handle_resize to the
display. Instead of having a callback to receive resize events, a list
of &mut OnResize are passed to this new method. Doing this allowed the
only RefCell usage in the codebase to be removed :).
This commit is contained in:
Joe Wilm 2016-12-12 09:31:48 -08:00
parent 4e9a307bed
commit 1a1b740c38
5 changed files with 81 additions and 80 deletions

View File

@ -30,7 +30,7 @@ use term::{Term, SizeInfo};
use window::{self, Size, Pixels, Window, SetInnerSize};
/// The display wraps a window, font rasterizer, and GPU renderer
pub struct Display<F> {
pub struct Display {
window: Window,
renderer: QuadRenderer,
glyph_cache: GlyphCache,
@ -38,22 +38,24 @@ pub struct Display<F> {
rx: mpsc::Receiver<(u32, u32)>,
tx: mpsc::Sender<(u32, u32)>,
meter: Meter,
resize_callback: Option<F>,
size_info: SizeInfo,
}
/// Can wakeup the render loop from other threads
pub struct Notifier(window::Proxy);
/// Types that are interested in when the display is resized
pub trait OnResize {
fn on_resize(&mut self, size: &SizeInfo);
}
impl Notifier {
pub fn notify(&self) {
self.0.wakeup_event_loop();
}
}
impl<F> Display<F>
where F: Fn(&SizeInfo)
{
impl Display {
pub fn notifier(&self) -> Notifier {
Notifier(self.window.create_window_proxy())
}
@ -63,11 +65,6 @@ impl<F> Display<F>
self.render_timer = config.render_timer();
}
/// Provide a callback to be invoked then the display changes size.
pub fn set_resize_callback(&mut self, callback: F) {
self.resize_callback = Some(callback);
}
/// Get size info about the display
pub fn size(&self) -> &SizeInfo {
&self.size_info
@ -76,7 +73,7 @@ impl<F> Display<F>
pub fn new(
config: &Config,
options: &cli::Options,
) -> Result<Display<F>, window::Error> {
) -> Result<Display, window::Error> {
// Extract some properties from config
let font = config.font();
let dpi = config.dpi();
@ -156,7 +153,6 @@ impl<F> Display<F>
tx: tx,
rx: rx,
meter: Meter::new(),
resize_callback: None,
size_info: size_info,
};
@ -179,6 +175,33 @@ impl<F> Display<F>
&self.window
}
/// Process pending resize events
pub fn handle_resize(&mut self, terminal: &mut MutexGuard<Term>, items: &mut [&mut OnResize]) {
// Resize events new_size and are handled outside the poll_events
// iterator. This has the effect of coalescing multiple resize
// events into one.
let mut new_size = None;
// Take most recent resize event, if any
while let Ok(sz) = self.rx.try_recv() {
new_size = Some(sz);
}
// Receive any resize events; only call gl::Viewport on last
// available
if let Some((w, h)) = new_size.take() {
terminal.resize(w as f32, h as f32);
let size = terminal.size_info();
for mut item in items {
item.on_resize(size)
}
self.renderer.resize(w as i32, h as i32);
}
}
/// Draw the screen
///
/// A reference to Term whose state is being drawn must be provided.
@ -194,26 +217,6 @@ impl<F> Display<F>
// Clear dirty flag
terminal.dirty = false;
// Resize events new_size and are handled outside the poll_events
// iterator. This has the effect of coalescing multiple resize
// events into one.
let mut new_size = None;
// Check for any out-of-band resize events (mac only)
while let Ok(sz) = self.rx.try_recv() {
new_size = Some(sz);
}
// Receive any resize events; only call gl::Viewport on last
// available
if let Some((w, h)) = new_size.take() {
terminal.resize(w as f32, h as f32);
let size = terminal.size_info();
self.resize_callback.as_ref()
.map(|func| func(&size));
self.renderer.resize(w as i32, h as i32);
}
{
let glyph_cache = &mut self.glyph_cache;
// Draw grid

View File

@ -6,12 +6,12 @@ use serde_json as json;
use glutin;
use window::Window;
use config::Config;
use display::OnResize;
use input;
use sync::FairMutex;
use term::{self, Term};
use config::Config;
use term::{Term, SizeInfo};
use window::Window;
/// The event processor
pub struct Processor<N> {
@ -22,6 +22,15 @@ pub struct Processor<N> {
ref_test: bool,
}
/// Notify that the terminal was resized
///
/// Currently this just forwards the notice to the input processor.
impl<N> OnResize for Processor<N> {
fn on_resize(&mut self, size: &SizeInfo) {
self.input_processor.resize(size);
}
}
impl<N: input::Notify> Processor<N> {
/// Create a new event processor
///
@ -48,13 +57,6 @@ impl<N: input::Notify> Processor<N> {
}
}
/// Notify that the terminal was resized
///
/// Currently this just forwards the notice to the input processor.
pub fn resize(&mut self, size_info: &term::SizeInfo) {
self.input_processor.resize(size_info);
}
fn handle_event(&mut self, event: glutin::Event, wakeup_request: &mut bool) {
match event {
glutin::Event::Closed => {

View File

@ -18,9 +18,7 @@
#[macro_use]
extern crate alacritty;
use std::cell::RefCell;
use std::error::Error;
use std::rc::Rc;
use std::sync::Arc;
use alacritty::cli;
@ -86,7 +84,7 @@ fn run(config: Config, options: cli::Options) -> Result<(), Box<Error>> {
// The pty forks a process to run the shell on the slave side of the
// pseudoterminal. A file descriptor for the master side is retained for
// reading/writing to the shell.
let pty = tty::new(display.size());
let mut pty = tty::new(display.size());
// Create the pseudoterminal I/O loop
//
@ -108,28 +106,13 @@ fn run(config: Config, options: cli::Options) -> Result<(), Box<Error>> {
// Event processor
//
// Need the Rc<RefCell<_>> here since a ref is shared in the resize callback
let processor = Rc::new(RefCell::new(event::Processor::new(
let mut processor = event::Processor::new(
input::LoopNotifier(loop_tx),
terminal.clone(),
display.resize_channel(),
&config,
options.ref_test,
)));
// Configure the display resize callback
let processor_ref = processor.clone();
display.set_resize_callback(move |size| {
// Resizing the pty lets the child processes know the window changed
// size.
pty.resize(size);
// It's a bit funny that the event processor is in this callback since
// on some platforms it's the first to be aware of a resize event. It
// appears here since resizes are processed out-of-band from when the
// events arrive. This way, the processor state is updated at the same
// time as the rest of the system.
processor_ref.borrow_mut().resize(size)
});
);
// Create a config monitor when config was loaded from path
//
@ -144,20 +127,27 @@ fn run(config: Config, options: cli::Options) -> Result<(), Box<Error>> {
// Main display loop
loop {
// Process input and window events
let wakeup_request = processor.borrow_mut().process_events(display.window());
let wakeup_request = processor.process_events(display.window());
// Handle config reloads
let config_updated = config_monitor.as_ref()
.and_then(|monitor| monitor.pending_config())
.map(|config| {
display.update_config(&config);
processor.borrow_mut().update_config(&config);
processor.update_config(&config);
true
}).unwrap_or(false);
// Maybe draw the terminal
let terminal = terminal.lock();
let mut terminal = terminal.lock();
if wakeup_request || config_updated {
// Handle pending resize events
//
// The second argument is a list of types that want to be notified
// of display size changes.
display.handle_resize(&mut terminal, &mut [&mut pty, &mut processor]);
// Draw the current state of the terminal
display.draw(terminal, &config);
}

View File

@ -23,20 +23,6 @@ use grid::{Grid, ClearRegion};
use index::{Cursor, Column, Line};
use ansi::{Color, NamedColor};
use tty::ToWinsize;
use libc::{self, winsize};
impl<'a> ToWinsize for &'a SizeInfo {
fn to_winsize(&self) -> winsize {
winsize {
ws_row: self.lines().0 as libc::c_ushort,
ws_col: self.cols().0 as libc::c_ushort,
ws_xpixel: self.width as libc::c_ushort,
ws_ypixel: self.height as libc::c_ushort,
}
}
}
pub mod cell;
pub use self::cell::Cell;

View File

@ -23,6 +23,9 @@ use std::ptr;
use libc::{self, winsize, c_int, pid_t, WNOHANG, WIFEXITED, WEXITSTATUS, SIGCHLD};
use term::SizeInfo;
use display::OnResize;
/// Process ID of child process
///
/// Necessary to put this in static storage for `sigchld` to have access
@ -326,6 +329,23 @@ pub trait ToWinsize {
fn to_winsize(&self) -> winsize;
}
impl<'a> ToWinsize for &'a SizeInfo {
fn to_winsize(&self) -> winsize {
winsize {
ws_row: self.lines().0 as libc::c_ushort,
ws_col: self.cols().0 as libc::c_ushort,
ws_xpixel: self.width as libc::c_ushort,
ws_ypixel: self.height as libc::c_ushort,
}
}
}
impl OnResize for Pty {
fn on_resize(&mut self, size: &SizeInfo) {
self.resize(size);
}
}
unsafe fn set_nonblocking(fd: c_int) {
use libc::{fcntl, F_SETFL, F_GETFL, O_NONBLOCK};