diff options
author | Christian Duerr <contact@christianduerr.com> | 2019-10-05 02:29:26 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2019-10-05 02:29:26 +0200 |
commit | 729eef0c933831bccfeac6a355bdb410787fbe5f (patch) | |
tree | 35cdf2e6427ad18bc53efbab4cab34a0af2054d7 /alacritty/src/main.rs | |
parent | b0c6fdff763f7271506d26d7e768e6377fdc691b (diff) | |
download | r-alacritty-729eef0c933831bccfeac6a355bdb410787fbe5f.tar.gz r-alacritty-729eef0c933831bccfeac6a355bdb410787fbe5f.tar.bz2 r-alacritty-729eef0c933831bccfeac6a355bdb410787fbe5f.zip |
Update to winit/glutin EventLoop 2.0
This takes the latest glutin master to port Alacritty to the EventLoop
2.0 rework.
This changes a big part of the event loop handling by pushing the event
loop in a separate thread from the renderer and running both in
parallel.
Fixes #2796.
Fixes #2694.
Fixes #2643.
Fixes #2625.
Fixes #2618.
Fixes #2601.
Fixes #2564.
Fixes #2456.
Fixes #2438.
Fixes #2334.
Fixes #2254.
Fixes #2217.
Fixes #1789.
Fixes #1750.
Fixes #1125.
Diffstat (limited to 'alacritty/src/main.rs')
-rw-r--r-- | alacritty/src/main.rs | 182 |
1 files changed, 62 insertions, 120 deletions
diff --git a/alacritty/src/main.rs b/alacritty/src/main.rs index 65313cbe..146709fd 100644 --- a/alacritty/src/main.rs +++ b/alacritty/src/main.rs @@ -25,7 +25,7 @@ #[cfg(target_os = "macos")] use std::env; use std::error::Error; -use std::fs::{self, File}; +use std::fs; use std::io::{self, Write}; #[cfg(not(windows))] use std::os::unix::io::AsRawFd; @@ -33,29 +33,35 @@ use std::sync::Arc; #[cfg(target_os = "macos")] use dirs; +use glutin::event_loop::EventLoop as GlutinEventLoop; use log::{error, info}; -use serde_json as json; #[cfg(windows)] use winapi::um::wincon::{AttachConsole, FreeConsole, ATTACH_PARENT_PROCESS}; use alacritty_terminal::clipboard::Clipboard; -use alacritty_terminal::config::{Config, Monitor}; -use alacritty_terminal::display::Display; +use alacritty_terminal::event::Event; use alacritty_terminal::event_loop::{self, EventLoop, Msg}; #[cfg(target_os = "macos")] use alacritty_terminal::locale; use alacritty_terminal::message_bar::MessageBuffer; use alacritty_terminal::panic; use alacritty_terminal::sync::FairMutex; -use alacritty_terminal::term::{cell::Cell, Term}; +use alacritty_terminal::term::Term; use alacritty_terminal::tty; -use alacritty_terminal::{die, event}; mod cli; mod config; +mod display; +mod event; +mod input; mod logging; +mod window; use crate::cli::Options; +use crate::config::monitor::Monitor; +use crate::config::Config; +use crate::display::Display; +use crate::event::{EventProxy, Processor}; fn main() { panic::attach_handler(); @@ -71,12 +77,12 @@ fn main() { // Load command line options let options = Options::new(); - // Setup storage for message UI - let message_buffer = MessageBuffer::new(); + // Setup glutin event loop + let window_event_loop = GlutinEventLoop::<Event>::with_user_event(); // Initialize the logger as soon as possible as to capture output from other subsystems - let log_file = - logging::initialize(&options, message_buffer.tx()).expect("Unable to initialize logger"); + let log_file = logging::initialize(&options, window_event_loop.create_proxy()) + .expect("Unable to initialize logger"); // Load configuration file // If the file is a command line argument, we won't write a generated default file @@ -107,8 +113,9 @@ fn main() { let persistent_logging = config.persistent_logging(); // Run alacritty - if let Err(err) = run(config, message_buffer) { - die!("Alacritty encountered an unrecoverable error:\n\n\t{}\n", err); + if let Err(err) = run(window_event_loop, config) { + println!("Alacritty encountered an unrecoverable error:\n\n\t{}\n", err); + std::process::exit(1); } // Clean up logfile @@ -123,7 +130,7 @@ fn main() { /// /// Creates a window, the terminal state, pty, I/O event loop, input processor, /// config change monitor, and runs the main display loop. -fn run(config: Config, message_buffer: MessageBuffer) -> Result<(), Box<dyn Error>> { +fn run(window_event_loop: GlutinEventLoop<Event>, config: Config) -> Result<(), Box<dyn Error>> { info!("Welcome to Alacritty"); if let Some(config_path) = &config.config_path { info!("Configuration loaded from {:?}", config_path.display()); @@ -132,17 +139,19 @@ fn run(config: Config, message_buffer: MessageBuffer) -> Result<(), Box<dyn Erro // Set environment variables tty::setup_env(&config); - // Create a display. + let event_proxy = EventProxy::new(window_event_loop.create_proxy()); + + // Create a display // - // The display manages a window and can draw the terminal - let mut display = Display::new(&config)?; + // The display manages a window and can draw the terminal. + let display = Display::new(&config, &window_event_loop)?; - info!("PTY Dimensions: {:?} x {:?}", display.size().lines(), display.size().cols()); + info!("PTY Dimensions: {:?} x {:?}", display.size_info.lines(), display.size_info.cols()); // Create new native clipboard - #[cfg(not(any(target_os = "macos", target_os = "windows")))] - let clipboard = Clipboard::new(display.get_wayland_display()); - #[cfg(any(target_os = "macos", target_os = "windows"))] + #[cfg(not(any(target_os = "macos", windows)))] + let clipboard = Clipboard::new(display.window.wayland_display()); + #[cfg(any(target_os = "macos", windows))] let clipboard = Clipboard::new(); // Create the terminal @@ -150,28 +159,28 @@ fn run(config: Config, message_buffer: MessageBuffer) -> Result<(), Box<dyn Erro // This object contains all of the state about what's being displayed. It's // wrapped in a clonable mutex since both the I/O loop and display need to // access it. - let terminal = Term::new(&config, display.size().to_owned(), message_buffer, clipboard); + let terminal = Term::new(&config, &display.size_info, clipboard, event_proxy.clone()); let terminal = Arc::new(FairMutex::new(terminal)); - // Find the window ID for setting $WINDOWID - let window_id = display.get_window_id(); - // Create the pty // // 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(&config, &display.size(), window_id); + #[cfg(not(any(target_os = "macos", windows)))] + let pty = tty::new(&config, &display.size_info, display.window.x11_window_id()); + #[cfg(any(target_os = "macos", windows))] + let pty = tty::new(&config, &display.size_info, None); - // Get a reference to something that we can resize + // Create PTY resize handle // // This exists because rust doesn't know the interface is thread-safe // and we need to be able to resize the PTY from the main thread while the IO // thread owns the EventedRW object. #[cfg(windows)] - let mut resize_handle = pty.resize_handle(); + let resize_handle = pty.resize_handle(); #[cfg(not(windows))] - let mut resize_handle = pty.fd.as_raw_fd(); + let resize_handle = pty.fd.as_raw_fd(); // Create the pseudoterminal I/O loop // @@ -180,86 +189,45 @@ fn run(config: Config, message_buffer: MessageBuffer) -> Result<(), Box<dyn Erro // synchronized since the I/O loop updates the state, and the display // consumes it periodically. let event_loop = - EventLoop::new(Arc::clone(&terminal), display.notifier(), pty, config.debug.ref_test); + EventLoop::new(Arc::clone(&terminal), event_proxy.clone(), pty, config.debug.ref_test); // The event loop channel allows write requests from the event processor - // to be sent to the loop and ultimately written to the pty. + // to be sent to the pty loop and ultimately written to the pty. let loop_tx = event_loop.channel(); - // Event processor - // - // Need the Rc<RefCell<_>> here since a ref is shared in the resize callback - let mut processor = event::Processor::new( - event_loop::Notifier(event_loop.channel()), - display.resize_channel(), - &config, - display.size().to_owned(), - ); - // Create a config monitor when config was loaded from path // // The monitor watches the config file for changes and reloads it. Pending // config changes are processed in the main loop. - let config_monitor = if config.live_config_reload() { - config.config_path.as_ref().map(|path| Monitor::new(path, display.notifier())) - } else { - None - }; - - // Kick off the I/O thread - let _io_thread = event_loop.spawn(None); - - info!("Initialisation complete"); - - // Main display loop - loop { - // Process input and window events - let mut terminal_lock = processor.process_events(&terminal, display.window()); - - // Handle config reloads - if let Some(ref path) = config_monitor.as_ref().and_then(Monitor::pending) { - // Clear old config messages from bar - terminal_lock.message_buffer_mut().remove_topic(config::SOURCE_FILE_PATH); - - if let Ok(config) = config::reload_from(path) { - display.update_config(&config); - processor.update_config(&config); - terminal_lock.update_config(&config); - } - - terminal_lock.dirty = true; - } - - // Begin shutdown if the flag was raised - if terminal_lock.should_exit() || tty::process_should_exit() { - break; - } + if config.live_config_reload() { + config.config_path.as_ref().map(|path| Monitor::new(path, event_proxy.clone())); + } - // Maybe draw the terminal - if terminal_lock.needs_draw() { - // Try to update the position of the input method editor - #[cfg(not(windows))] - display.update_ime_position(&terminal_lock); + // Setup storage for message UI + let message_buffer = MessageBuffer::new(); - // 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_lock, &config, &mut resize_handle, &mut processor); + // Event processor + // + // Need the Rc<RefCell<_>> here since a ref is shared in the resize callback + let mut processor = Processor::new( + event_loop::Notifier(loop_tx.clone()), + Box::new(resize_handle), + message_buffer, + config, + display, + ); - drop(terminal_lock); + // Kick off the I/O thread + let io_thread = event_loop.spawn(); - // Draw the current state of the terminal - display.draw(&terminal, &config); - } - } + info!("Initialisation complete"); - // Write ref tests to disk - if config.debug.ref_test { - write_ref_test_results(&terminal.lock()); - } + // Start event loop and block until shutdown + processor.run(terminal, window_event_loop); - loop_tx.send(Msg::Shutdown).expect("Error sending shutdown to event loop"); + // Shutdown PTY parser event loop + loop_tx.send(Msg::Shutdown).expect("Error sending shutdown to pty event loop"); + io_thread.join().expect("join io thread"); // FIXME patch notify library to have a shutdown method // config_reloader.join().ok(); @@ -274,29 +242,3 @@ fn run(config: Config, message_buffer: MessageBuffer) -> Result<(), Box<dyn Erro Ok(()) } - -// Write the ref test results to the disk -fn write_ref_test_results(terminal: &Term) { - // dump grid state - let mut grid = terminal.grid().clone(); - grid.initialize_all(&Cell::default()); - grid.truncate(); - - let serialized_grid = json::to_string(&grid).expect("serialize grid"); - - let serialized_size = json::to_string(terminal.size_info()).expect("serialize size"); - - let serialized_config = format!("{{\"history_size\":{}}}", grid.history_size()); - - File::create("./grid.json") - .and_then(|mut f| f.write_all(serialized_grid.as_bytes())) - .expect("write grid.json"); - - File::create("./size.json") - .and_then(|mut f| f.write_all(serialized_size.as_bytes())) - .expect("write size.json"); - - File::create("./config.json") - .and_then(|mut f| f.write_all(serialized_config.as_bytes())) - .expect("write config.json"); -} |