aboutsummaryrefslogtreecommitdiff
path: root/alacritty/src/main.rs
diff options
context:
space:
mode:
authorChristian Duerr <contact@christianduerr.com>2019-10-05 02:29:26 +0200
committerGitHub <noreply@github.com>2019-10-05 02:29:26 +0200
commit729eef0c933831bccfeac6a355bdb410787fbe5f (patch)
tree35cdf2e6427ad18bc53efbab4cab34a0af2054d7 /alacritty/src/main.rs
parentb0c6fdff763f7271506d26d7e768e6377fdc691b (diff)
downloadr-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.rs182
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");
-}