diff --git a/src/display.rs b/src/display.rs index cfe684c0..b16bf95a 100644 --- a/src/display.rs +++ b/src/display.rs @@ -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 { +pub struct Display { window: Window, renderer: QuadRenderer, glyph_cache: GlyphCache, @@ -38,22 +38,24 @@ pub struct Display { rx: mpsc::Receiver<(u32, u32)>, tx: mpsc::Sender<(u32, u32)>, meter: Meter, - resize_callback: Option, 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 Display - where F: Fn(&SizeInfo) -{ +impl Display { pub fn notifier(&self) -> Notifier { Notifier(self.window.create_window_proxy()) } @@ -63,11 +65,6 @@ impl Display 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 Display pub fn new( config: &Config, options: &cli::Options, - ) -> Result, window::Error> { + ) -> Result { // Extract some properties from config let font = config.font(); let dpi = config.dpi(); @@ -156,7 +153,6 @@ impl Display tx: tx, rx: rx, meter: Meter::new(), - resize_callback: None, size_info: size_info, }; @@ -179,6 +175,33 @@ impl Display &self.window } + /// Process pending resize events + pub fn handle_resize(&mut self, terminal: &mut MutexGuard, 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 Display // 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 diff --git a/src/event.rs b/src/event.rs index 4f28649e..b9a8551d 100644 --- a/src/event.rs +++ b/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 { @@ -22,6 +22,15 @@ pub struct Processor { ref_test: bool, } +/// Notify that the terminal was resized +/// +/// Currently this just forwards the notice to the input processor. +impl OnResize for Processor { + fn on_resize(&mut self, size: &SizeInfo) { + self.input_processor.resize(size); + } +} + impl Processor { /// Create a new event processor /// @@ -48,13 +57,6 @@ impl Processor { } } - /// 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 => { diff --git a/src/main.rs b/src/main.rs index 7ae45787..c917fe43 100644 --- a/src/main.rs +++ b/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> { // 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> { // Event processor // // Need the Rc> 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> { // 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); } diff --git a/src/term/mod.rs b/src/term/mod.rs index 523fcb62..fb31af9b 100644 --- a/src/term/mod.rs +++ b/src/term/mod.rs @@ -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; diff --git a/src/tty.rs b/src/tty.rs index 7071bad3..667daf04 100644 --- a/src/tty.rs +++ b/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};