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:
parent
4e9a307bed
commit
1a1b740c38
|
@ -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
|
||||
|
|
24
src/event.rs
24
src/event.rs
|
@ -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 => {
|
||||
|
|
36
src/main.rs
36
src/main.rs
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
20
src/tty.rs
20
src/tty.rs
|
@ -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};
|
||||
|
||||
|
|
Loading…
Reference in New Issue