diff options
29 files changed, 1421 insertions, 811 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md index f337f601..4f464608 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). ### Added - Option `colors.transparent_background_colors` to allow applying opacity to all background colors +- Support for running multiple windows from a single Alacritty instance (see docs/features.md) ### Changed @@ -1989,9 +1989,12 @@ dependencies = [ [[package]] name = "xdg" -version = "2.2.0" +version = "2.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d089681aa106a86fade1b0128fb5daf07d5867a509ab036d99988dec80429a57" +checksum = "3a23fe958c70412687039c86f578938b4a0bb50ec788e96bce4d6ab00ddd5803" +dependencies = [ + "dirs", +] [[package]] name = "xml-rs" diff --git a/alacritty.yml b/alacritty.yml index 04654e56..09abce3c 100644 --- a/alacritty.yml +++ b/alacritty.yml @@ -440,6 +440,9 @@ # Send ESC (\x1b) before characters when alt is pressed. #alt_send_esc: true +# Offer IPC using `alacritty msg` (unix only) +#ipc_socket: true + #mouse: # Click settings # @@ -595,6 +598,8 @@ # - ToggleFullscreen # - SpawnNewInstance # Spawn a new instance of Alacritty. +# - CreateNewWindow +# Create a new Alacritty window from the current process. # - ClearLogNotice # Clear Alacritty's UI warning and error notice. # - ClearSelection diff --git a/alacritty/Cargo.toml b/alacritty/Cargo.toml index b1fee0c2..5d02d19c 100644 --- a/alacritty/Cargo.toml +++ b/alacritty/Cargo.toml @@ -39,7 +39,7 @@ dirs = "3.0.1" gl_generator = "0.14.0" [target.'cfg(not(windows))'.dependencies] -xdg = "2" +xdg = "2.4.0" [target.'cfg(not(target_os = "macos"))'.dependencies] png = { version = "0.16.8", default-features = false, optional = true } diff --git a/alacritty/src/cli.rs b/alacritty/src/cli.rs index b1e12007..ce0563ff 100644 --- a/alacritty/src/cli.rs +++ b/alacritty/src/cli.rs @@ -10,7 +10,7 @@ use alacritty_terminal::config::Program; use crate::config::window::{Class, DEFAULT_NAME}; use crate::config::{serde_utils, Config}; -/// Options specified on the command line. +/// CLI options for the main Alacritty executable. #[derive(StructOpt, Debug)] #[structopt(author, about, version = env!("VERSION"))] pub struct Options { @@ -57,9 +57,10 @@ pub struct Options { #[structopt(long)] pub hold: bool, - /// CLI options for config overrides. - #[structopt(skip)] - pub config_options: Value, + /// Path for IPC socket creation. + #[cfg(unix)] + #[structopt(long)] + pub socket: Option<PathBuf>, /// Reduces the level of verbosity (the min level is -qq). #[structopt(short, conflicts_with("verbose"), parse(from_occurrences))] @@ -76,6 +77,15 @@ pub struct Options { /// Override configuration file options [example: cursor.style=Beam]. #[structopt(short = "o", long)] option: Vec<String>, + + /// CLI options for config overrides. + #[structopt(skip)] + pub config_options: Value, + + /// Subcommand passed to the CLI. + #[cfg(unix)] + #[structopt(subcommand)] + pub subcommands: Option<Subcommands>, } impl Options { @@ -118,6 +128,11 @@ impl Options { config.ui_config.window.class = class.clone(); } + #[cfg(unix)] + { + config.ui_config.ipc_socket |= self.socket.is_some(); + } + config.ui_config.window.dynamic_title &= self.title.is_none(); config.ui_config.window.embed = self.embed.as_ref().and_then(|embed| embed.parse().ok()); config.ui_config.debug.print_events |= self.print_events; @@ -199,6 +214,34 @@ fn parse_class(input: &str) -> Result<Class, String> { } } +/// Available CLI subcommands. +#[cfg(unix)] +#[derive(StructOpt, Debug)] +pub enum Subcommands { + Msg(MessageOptions), +} + +/// Send a message to the Alacritty socket. +#[cfg(unix)] +#[derive(StructOpt, Debug)] +pub struct MessageOptions { + /// IPC socket connection path override. + #[structopt(long, short)] + pub socket: Option<PathBuf>, + + /// Message which should be sent. + #[structopt(subcommand)] + pub message: SocketMessage, +} + +/// Available socket messages. +#[cfg(unix)] +#[derive(StructOpt, Debug)] +pub enum SocketMessage { + /// Create a new window in the same Alacritty process. + CreateWindow, +} + #[cfg(test)] mod tests { use super::*; diff --git a/alacritty/src/config/bindings.rs b/alacritty/src/config/bindings.rs index 8289fc20..533573c8 100644 --- a/alacritty/src/config/bindings.rs +++ b/alacritty/src/config/bindings.rs @@ -180,6 +180,9 @@ pub enum Action { /// Spawn a new instance of Alacritty. SpawnNewInstance, + /// Create a new Alacritty window. + CreateNewWindow, + /// Toggle fullscreen. ToggleFullscreen, @@ -1099,7 +1102,7 @@ impl<'a> Deserialize<'a> for RawBinding { let mode = mode.unwrap_or_else(BindingMode::empty); let not_mode = not_mode.unwrap_or_else(BindingMode::empty); - let mods = mods.unwrap_or_else(ModifiersState::default); + let mods = mods.unwrap_or_default(); let action = match (action, chars, command) { (Some(action @ Action::ViMotion(_)), None, None) diff --git a/alacritty/src/config/monitor.rs b/alacritty/src/config/monitor.rs index e3dd0556..9d37172e 100644 --- a/alacritty/src/config/monitor.rs +++ b/alacritty/src/config/monitor.rs @@ -2,19 +2,20 @@ use std::path::PathBuf; use std::sync::mpsc; use std::time::Duration; +use glutin::event_loop::EventLoopProxy; use log::{debug, error}; use notify::{watcher, DebouncedEvent, RecursiveMode, Watcher}; use alacritty_terminal::thread; -use crate::event::{Event, EventProxy}; +use crate::event::{Event, EventType}; #[cfg(any(target_os = "linux", target_os = "macos", target_os = "windows"))] const DEBOUNCE_DELAY: Duration = Duration::from_millis(10); #[cfg(not(any(target_os = "linux", target_os = "macos", target_os = "windows")))] const DEBOUNCE_DELAY: Duration = Duration::from_millis(1000); -pub fn watch(mut paths: Vec<PathBuf>, event_proxy: EventProxy) { +pub fn watch(mut paths: Vec<PathBuf>, event_proxy: EventLoopProxy<Event>) { // Don't monitor config if there is no path to watch. if paths.is_empty() { return; @@ -77,9 +78,10 @@ pub fn watch(mut paths: Vec<PathBuf>, event_proxy: EventProxy) { if paths.contains(&path) => { // Always reload the primary configuration file. - event_proxy.send_event(Event::ConfigReload(paths[0].clone())); + let event = Event::new(EventType::ConfigReload(paths[0].clone()), None); + let _ = event_proxy.send_event(event); } - _ => {}, + _ => (), } } }); diff --git a/alacritty/src/config/ui_config.rs b/alacritty/src/config/ui_config.rs index 3ce02161..3ba59ea8 100644 --- a/alacritty/src/config/ui_config.rs +++ b/alacritty/src/config/ui_config.rs @@ -62,6 +62,10 @@ pub struct UiConfig { /// Regex hints for interacting with terminal content. pub hints: Hints, + /// Offer IPC through a unix socket. + #[cfg(unix)] + pub ipc_socket: bool, + /// Keybindings. key_bindings: KeyBindings, @@ -76,8 +80,10 @@ pub struct UiConfig { impl Default for UiConfig { fn default() -> Self { Self { - alt_send_esc: true, live_config_reload: true, + alt_send_esc: true, + #[cfg(unix)] + ipc_socket: true, font: Default::default(), window: Default::default(), mouse: Default::default(), diff --git a/alacritty/src/display/mod.rs b/alacritty/src/display/mod.rs index 946c27f9..a942a88d 100644 --- a/alacritty/src/display/mod.rs +++ b/alacritty/src/display/mod.rs @@ -3,15 +3,15 @@ use std::cmp::min; use std::convert::TryFrom; -use std::f64; use std::fmt::{self, Formatter}; #[cfg(all(feature = "wayland", not(any(target_os = "macos", windows))))] use std::sync::atomic::Ordering; use std::time::Instant; +use std::{f64, mem}; use glutin::dpi::{PhysicalPosition, PhysicalSize}; use glutin::event::ModifiersState; -use glutin::event_loop::EventLoop; +use glutin::event_loop::EventLoopWindowTarget; #[cfg(not(any(target_os = "macos", windows)))] use glutin::platform::unix::EventLoopWindowTargetExtUnix; use glutin::window::CursorIcon; @@ -19,7 +19,7 @@ use log::{debug, info}; use parking_lot::MutexGuard; use unicode_width::UnicodeWidthChar; #[cfg(all(feature = "wayland", not(any(target_os = "macos", windows))))] -use wayland_client::{Display as WaylandDisplay, EventQueue}; +use wayland_client::EventQueue; use crossfont::{self, Rasterize, Rasterizer}; @@ -178,9 +178,6 @@ pub struct Display { /// Hint highlighted by the vi mode cursor. pub vi_highlighted_hint: Option<HintMatch>, - #[cfg(all(feature = "wayland", not(any(target_os = "macos", windows))))] - pub wayland_event_queue: Option<EventQueue>, - #[cfg(not(any(target_os = "macos", windows)))] pub is_x11: bool, @@ -195,13 +192,21 @@ pub struct Display { /// State of the keyboard hints. pub hint_state: HintState, + /// Unprocessed display updates. + pub pending_update: DisplayUpdate, + renderer: QuadRenderer, glyph_cache: GlyphCache, meter: Meter, } impl Display { - pub fn new<E>(config: &Config, event_loop: &EventLoop<E>) -> Result<Display, Error> { + pub fn new<E>( + config: &Config, + event_loop: &EventLoopWindowTarget<E>, + #[cfg(all(feature = "wayland", not(any(target_os = "macos", windows))))] + wayland_event_queue: Option<&EventQueue>, + ) -> Result<Display, Error> { #[cfg(any(not(feature = "x11"), target_os = "macos", windows))] let is_x11 = false; #[cfg(all(feature = "x11", not(any(target_os = "macos", windows))))] @@ -229,23 +234,13 @@ impl Display { debug!("Estimated window size: {:?}", estimated_size); debug!("Estimated cell size: {} x {}", cell_width, cell_height); - #[cfg(all(feature = "wayland", not(any(target_os = "macos", windows))))] - let mut wayland_event_queue = None; - - // Initialize Wayland event queue, to handle Wayland callbacks. - #[cfg(all(feature = "wayland", not(any(target_os = "macos", windows))))] - if let Some(display) = event_loop.wayland_display() { - let display = unsafe { WaylandDisplay::from_external_display(display as _) }; - wayland_event_queue = Some(display.create_event_queue()); - } - // Spawn the Alacritty window. let mut window = Window::new( event_loop, config, estimated_size, #[cfg(all(feature = "wayland", not(any(target_os = "macos", windows))))] - wayland_event_queue.as_ref(), + wayland_event_queue, )?; info!("Device pixel ratio: {}", window.dpr); @@ -344,11 +339,10 @@ impl Display { vi_highlighted_hint: None, #[cfg(not(any(target_os = "macos", windows)))] is_x11, - #[cfg(all(feature = "wayland", not(any(target_os = "macos", windows))))] - wayland_event_queue, cursor_hidden: false, visual_bell: VisualBell::from(&config.ui_config.bell), colors: List::from(&config.ui_config.colors), + pending_update: Default::default(), }) } @@ -414,26 +408,30 @@ impl Display { message_buffer: &MessageBuffer, search_active: bool, config: &Config, - update_pending: DisplayUpdate, ) where T: EventListener, { + let pending_update = mem::take(&mut self.pending_update); + let (mut cell_width, mut cell_height) = (self.size_info.cell_width(), self.size_info.cell_height()); + // Ensure we're modifying the correct OpenGL context. + self.window.make_current(); + // Update font size and cell dimensions. - if let Some(font) = update_pending.font() { + if let Some(font) = pending_update.font() { let cell_dimensions = self.update_glyph_cache(config, font); cell_width = cell_dimensions.0; cell_height = cell_dimensions.1; info!("Cell size: {} x {}", cell_width, cell_height); - } else if update_pending.cursor_dirty() { + } else if pending_update.cursor_dirty() { self.clear_glyph_cache(); } let (mut width, mut height) = (self.size_info.width(), self.size_info.height()); - if let Some(dimensions) = update_pending.dimensions() { + if let Some(dimensions) = pending_update.dimensions() { width = dimensions.width as f32; height = dimensions.height as f32; } @@ -463,8 +461,7 @@ impl Display { terminal.resize(self.size_info); // Resize renderer. - let physical = - PhysicalSize::new(self.size_info.width() as u32, self.size_info.height() as u32); + let physical = PhysicalSize::new(self.size_info.width() as _, self.size_info.height() as _); self.window.resize(physical); self.renderer.resize(&self.size_info); @@ -505,6 +502,9 @@ impl Display { // Drop terminal as early as possible to free lock. drop(terminal); + // Make sure this window's OpenGL context is active. + self.window.make_current(); + self.renderer.with_api(&config.ui_config, &size_info, |api| { api.clear(background_color); }); @@ -515,6 +515,10 @@ impl Display { { let _sampler = self.meter.sampler(); + // Ensure macOS hasn't reset our viewport. + #[cfg(target_os = "macos")] + self.renderer.set_viewport(&size_info); + let glyph_cache = &mut self.glyph_cache; let highlighted_hint = &self.highlighted_hint; let vi_highlighted_hint = &self.vi_highlighted_hint; @@ -819,6 +823,14 @@ impl Display { } } +impl Drop for Display { + fn drop(&mut self) { + // Switch OpenGL context before dropping, otherwise objects (like programs) from other + // contexts might be deleted. + self.window.make_current() + } +} + /// Convert a terminal point to a viewport relative point. pub fn point_to_viewport(display_offset: usize, point: Point) -> Option<Point<usize>> { let viewport_line = point.line.0 + display_offset as i32; diff --git a/alacritty/src/display/window.rs b/alacritty/src/display/window.rs index 12416700..16932dc4 100644 --- a/alacritty/src/display/window.rs +++ b/alacritty/src/display/window.rs @@ -29,11 +29,12 @@ use { }; use std::fmt::{self, Display, Formatter}; +use std::ops::{Deref, DerefMut}; #[cfg(target_os = "macos")] use cocoa::base::{id, NO, YES}; use glutin::dpi::{PhysicalPosition, PhysicalSize}; -use glutin::event_loop::EventLoop; +use glutin::event_loop::EventLoopWindowTarget; #[cfg(target_os = "macos")] use glutin::platform::macos::{WindowBuilderExtMacOS, WindowExtMacOS}; #[cfg(windows)] @@ -124,7 +125,7 @@ impl From<crossfont::Error> for Error { fn create_gl_window<E>( mut window: WindowBuilder, - event_loop: &EventLoop<E>, + event_loop: &EventLoopWindowTarget<E>, srgb: bool, vsync: bool, dimensions: Option<PhysicalSize<u32>>, @@ -160,7 +161,7 @@ pub struct Window { /// Cached DPR for quickly scaling pixel sizes. pub dpr: f64, - windowed_context: WindowedContext<PossiblyCurrent>, + windowed_context: Replaceable<WindowedContext<PossiblyCurrent>>, current_mouse_cursor: CursorIcon, mouse_visible: bool, } @@ -170,7 +171,7 @@ impl Window { /// /// This creates a window and fully initializes a window. pub fn new<E>( - event_loop: &EventLoop<E>, + event_loop: &EventLoopWindowTarget<E>, config: &Config, size: Option<PhysicalSize<u32>>, #[cfg(all(feature = "wayland", not(any(target_os = "macos", windows))))] @@ -232,7 +233,7 @@ impl Window { Ok(Self { current_mouse_cursor, mouse_visible: true, - windowed_context, + windowed_context: Replaceable::new(windowed_context), #[cfg(not(any(target_os = "macos", windows)))] should_draw: Arc::new(AtomicBool::new(true)), #[cfg(all(feature = "wayland", not(any(target_os = "macos", windows))))] @@ -241,10 +242,12 @@ impl Window { }) } + #[inline] pub fn set_inner_size(&mut self, size: PhysicalSize<u32>) { self.window().set_inner_size(size); } + #[inline] pub fn inner_size(&self) -> PhysicalSize<u32> { self.window().inner_size() } @@ -261,6 +264,11 @@ impl Window { } #[inline] + pub fn request_redraw(&self) { + self.window().request_redraw(); + } + + #[inline] pub fn set_mouse_cursor(&mut self, cursor: CursorIcon) { if cursor != self.current_mouse_cursor { self.current_mouse_cursor = cursor; @@ -374,7 +382,7 @@ impl Window { None } - pub fn window_id(&self) -> WindowId { + pub fn id(&self) -> WindowId { self.window().id() } @@ -436,6 +444,13 @@ impl Window { self.windowed_context.resize(size); } + pub fn make_current(&mut self) { + if !self.windowed_context.is_current() { + self.windowed_context + .replace_with(|context| unsafe { context.make_current().expect("context swap") }); + } + } + /// Disable macOS window shadows. /// /// This prevents rendering artifacts from showing up when the window is transparent. @@ -496,3 +511,44 @@ unsafe extern "C" fn xembed_error_handler(_: *mut XDisplay, _: *mut XErrorEvent) log::error!("Could not embed into specified window."); std::process::exit(1); } + +/// Struct for safe in-place replacement. +/// +/// This struct allows easily replacing struct fields that provide `self -> Self` methods in-place, +/// without having to deal with constantly unwrapping the underlying [`Option`]. +struct Replaceable<T>(Option<T>); + +impl<T> Replaceable<T> { + pub fn new(inner: T) -> Self { + Self(Some(inner)) + } + + /// Replace the contents of the container. + pub fn replace_with<F: FnMut(T) -> T>(&mut self, f: F) { + self.0 = self.0.take().map(f); + } + + /// Get immutable access to the wrapped value. + pub fn get(&self) -> &T { + self.0.as_ref().unwrap() + } + + /// Get mutable access to the wrapped value. + pub fn get_mut(&mut self) -> &mut T { + self.0.as_mut().unwrap() + } +} + +impl<T> Deref for Replaceable<T> { + type Target = T; + + fn deref(&self) -> &Self::Target { + self.get() + } +} + +impl<T> DerefMut for Replaceable<T> { + fn deref_mut(&mut self) -> &mut Self::Target { + self.get_mut() + } +} diff --git a/alacritty/src/event.rs b/alacritty/src/event.rs index 8e8fac08..09e74a9d 100644 --- a/alacritty/src/event.rs +++ b/alacritty/src/event.rs @@ -2,16 +2,12 @@ use std::borrow::Cow; use std::cmp::{max, min}; -use std::collections::VecDeque; +use std::collections::{HashMap, VecDeque}; +use std::error::Error; use std::fmt::Debug; #[cfg(not(any(target_os = "macos", windows)))] use std::fs; -use std::fs::File; -use std::io::Write; -use std::path::{Path, PathBuf}; -#[cfg(not(any(target_os = "macos", windows)))] -use std::sync::atomic::Ordering; -use std::sync::Arc; +use std::path::PathBuf; use std::time::{Duration, Instant}; use std::{env, f32, mem}; @@ -21,35 +17,38 @@ use glutin::event_loop::{ControlFlow, EventLoop, EventLoopProxy, EventLoopWindow use glutin::platform::run_return::EventLoopExtRunReturn; #[cfg(all(feature = "wayland", not(any(target_os = "macos", windows))))] use glutin::platform::unix::EventLoopWindowTargetExtUnix; -use log::info; -use serde_json as json; +use glutin::window::WindowId; +use log::{error, info}; +#[cfg(all(feature = "wayland", not(any(target_os = "macos", windows))))] +use wayland_client::{Display as WaylandDisplay, EventQueue}; use crossfont::{self, Size}; use alacritty_terminal::config::LOG_TARGET_CONFIG; -use alacritty_terminal::event::{Event as TerminalEvent, EventListener, Notify, OnResize}; +use alacritty_terminal::event::{Event as TerminalEvent, EventListener, Notify}; +use alacritty_terminal::event_loop::Notifier; use alacritty_terminal::grid::{Dimensions, Scroll}; use alacritty_terminal::index::{Boundary, Column, Direction, Line, Point, Side}; use alacritty_terminal::selection::{Selection, SelectionType}; -use alacritty_terminal::sync::FairMutex; use alacritty_terminal::term::search::{Match, RegexSearch}; use alacritty_terminal::term::{ClipboardType, SizeInfo, Term, TermMode}; #[cfg(not(windows))] use alacritty_terminal::tty; -use crate::cli::Options as CLIOptions; +use crate::cli::Options as CliOptions; use crate::clipboard::Clipboard; use crate::config::ui_config::{HintAction, HintInternalAction}; use crate::config::{self, Config}; use crate::daemon::start_daemon; use crate::display::hint::HintMatch; use crate::display::window::Window; -use crate::display::{self, Display, DisplayUpdate}; +use crate::display::{self, Display}; use crate::input::{self, ActionContext as _, FONT_SIZE_STEP}; #[cfg(target_os = "macos")] use crate::macos; use crate::message_bar::{Message, MessageBuffer}; -use crate::scheduler::{Scheduler, TimerId}; +use crate::scheduler::{Scheduler, TimerId, Topic}; +use crate::window_context::WindowContext; /// Duration after the last user input until an unlimited search is performed. pub const TYPING_SEARCH_DELAY: Duration = Duration::from_millis(500); @@ -60,16 +59,20 @@ const MAX_SEARCH_WHILE_TYPING: Option<usize> = Some(1000); /// Maximum number of search terms stored in the history. const MAX_SEARCH_HISTORY_SIZE: usize = 255; -/// Events dispatched through the UI event loop. +/// Alacritty events. #[derive(Debug, Clone)] -pub enum Event { - Terminal(TerminalEvent), - DprChanged(f64, (u32, u32)), - Scroll(Scroll), - ConfigReload(PathBuf), - Message(Message), - BlinkCursor, - SearchNext, +pub struct Event { + /// Limit event to a specific window. + window_id: Option<WindowId>, + + /// Event payload. + payload: EventType, +} + +impl Event { + pub fn new<I: Into<Option<WindowId>>>(payload: EventType, window_id: I) -> Self { + Self { window_id: window_id.into(), payload } + } } impl From<Event> for GlutinEvent<'_, Event> { @@ -78,16 +81,32 @@ impl From<Event> for GlutinEvent<'_, Event> { } } -impl From<TerminalEvent> for Event { +/// Alacritty events. +#[derive(Debug, Clone)] +pub enum EventType { + DprChanged(f64, (u32, u32)), + Terminal(TerminalEvent), + ConfigReload(PathBuf), + Message(Message), + Scroll(Scroll), + CreateWindow, + BlinkCursor, + SearchNext, +} + +impl From<TerminalEvent> for EventType { fn from(event: TerminalEvent) -> Self { - Event::Terminal(event) + Self::Terminal(event) } } /// Regex search state. pub struct SearchState { /// Search direction. - direction: Direction, + pub direction: Direction, + + /// Current position in the search history. + pub history_index: Option<usize>, /// Change in display offset since the beginning of the search. display_offset_delta: i32, @@ -106,9 +125,6 @@ pub struct SearchState { /// in history which is currently being previewed. history: VecDeque<String>, - /// Current position in the search history. - history_index: Option<usize>, - /// Compiled search automatons. dfas: Option<RegexSearch>, } @@ -164,14 +180,13 @@ pub struct ActionContext<'a, N, T> { pub modifiers: &'a mut ModifiersState, pub display: &'a mut Display, pub message_buffer: &'a mut MessageBuffer, - pub display_update_pending: &'a mut DisplayUpdate, pub config: &'a mut Config, pub event_loop: &'a EventLoopWindowTarget<Event>, + pub event_proxy: &'a EventLoopProxy<Event>, pub scheduler: &'a mut Scheduler, pub search_state: &'a mut SearchState, - cli_options: &'a CLIOptions, - font_size: &'a mut Size, - dirty: &'a mut bool, + pub font_size: &'a mut Size, + pub dirty: &'a mut bool, } impl<'a, N: Notify + 'a, T: EventListener> input::ActionContext<T> for ActionContext<'a, N, T> { @@ -380,23 +395,27 @@ impl<'a, N: Notify + 'a, T: EventListener> input::ActionContext<T> for ActionCon start_daemon(&alacritty, &args); } + fn create_new_window(&mut self) { + let _ = self.event_proxy.send_event(Event::new(EventType::CreateWindow, None)); + } + fn change_font_size(&mut self, delta: f32) { *self.font_size = max(*self.font_size + delta, Size::new(FONT_SIZE_STEP)); let font = self.config.ui_config.font.clone().with_size(*self.font_size); - self.display_update_pending.set_font(font); + self.display.pending_update.set_font(font); *self.dirty = true; } |