diff options
| author | Ayose <ayosec@gmail.com> | 2025-02-24 00:00:00 +0000 |
|---|---|---|
| committer | Ayose <ayosec@gmail.com> | 2025-02-24 00:00:00 +0000 |
| commit | 814e8fefc60b4457ea155d11df9f27795de830ec (patch) | |
| tree | ecc31d4e95680fd7f2a4dfb61cf30cefae387d3b | |
| parent | ff44690b072de6cccffbc8e56b869b8842797692 (diff) | |
| parent | 03c2907b44b4189aac5fdeaea331f5aab5c7072e (diff) | |
| download | r-alacritty-814e8fefc60b4457ea155d11df9f27795de830ec.tar.gz r-alacritty-814e8fefc60b4457ea155d11df9f27795de830ec.tar.bz2 r-alacritty-814e8fefc60b4457ea155d11df9f27795de830ec.zip | |
Merge remote-tracking branch 'vendor/master' into graphics
26 files changed, 333 insertions, 199 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md index f23f442f..cf13eb7a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,17 +8,42 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). Notable changes to the `alacritty_terminal` crate are documented in its [CHANGELOG](./alacritty_terminal/CHANGELOG.md). -## 0.15.0-dev +## 0.16.0-dev + +### Changed + +- Hide login message if `~/.hushlogin` is present + +### Fixed + +- Crash when OpenGL context resets + +## 0.15.1 + +### Changed + +- Error out when socket fails to create with `--daemon` +- Default URL hints now stop before backslashes + +### Fixed + +- Modifiers being out of sync for fast/synthetic input on X11 +- Child process creation failing while inside a deleted directory +- Shifted key reported without a shift when using kitty keyboard protocol + +## 0.15.0 ### Added - Config option `window.level = "AlwaysOnTop"` to force Alacritty to always be the toplevel window - Escape sequence to move cursor forward tabs ( CSI Ps I ) +- Pass activation token in `alacritty msg create-window` on Wayland/X11 ### Changed - Always focus new windows on macOS - Don't switch to semantic/line selection when control is pressed +- Always emit `1` for the first parameter when having modifiers in kitty keyboard protocol ### Fixed @@ -29,6 +54,8 @@ Notable changes to the `alacritty_terminal` crate are documented in its - Migrating nonexistent toml import breaking the entire migration - First daemon mode window ignoring window options passed through CLI - Report of Enter/Tab/Backspace in kitty keyboard's report event types mode +- Crash when pressing certain modifier keys on macOS 15+ +- Cut off wide characters in preedit string ## 0.14.0 @@ -52,7 +79,6 @@ Notable changes to the `alacritty_terminal` crate are documented in its - Moved config option `shell` to `terminal.shell` - `ctrl+shift+u` binding to open links to `ctrl+shift+o` to avoid collisions with IMEs - Use `Beam` cursor for single char cursor inside the IME preview -- Always emit `1` for the first parameter when having modifiers in kitty keyboard protocol ### Fixed @@ -74,7 +100,6 @@ Notable changes to the `alacritty_terminal` crate are documented in its - Invalid URL highlights after terminal scrolling - Hollow block cursor not spanning multiple chars being edited inside the IME preview - Vi inline search only working for direct key input without modifiers -- Crash when pressing certain modifier keys on macOS 15+ ## 0.13.2 @@ -32,7 +32,7 @@ dependencies = [ [[package]] name = "alacritty" -version = "0.15.0-dev" +version = "0.16.0-dev" dependencies = [ "ahash", "alacritty_config", @@ -95,7 +95,7 @@ dependencies = [ [[package]] name = "alacritty_terminal" -version = "0.24.2-dev" +version = "0.25.1-dev" dependencies = [ "base64", "bitflags 2.6.0", @@ -817,9 +817,9 @@ dependencies = [ [[package]] name = "glutin" -version = "0.32.1" +version = "0.32.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec69412a0bf07ea7607e638b415447857a808846c2b685a43c8aa18bc6d5e499" +checksum = "03642b8b0cce622392deb0ee3e88511f75df2daac806102597905c3ea1974848" dependencies = [ "bitflags 2.6.0", "cfg_aliases", @@ -842,9 +842,9 @@ dependencies = [ [[package]] name = "glutin_egl_sys" -version = "0.7.0" +version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cae99fff4d2850dbe6fb8c1fa8e4fead5525bab715beaacfccf3fb994e01c827" +checksum = "4c4680ba6195f424febdc3ba46e7a42a0e58743f2edb115297b86d7f8ecc02d2" dependencies = [ "gl_generator", "windows-sys 0.52.0", @@ -852,9 +852,9 @@ dependencies = [ [[package]] name = "glutin_glx_sys" -version = "0.6.0" +version = "0.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c2b2d3918e76e18e08796b55eb64e8fe6ec67d5a6b2e2a7e2edce224ad24c63" +checksum = "8a7bb2938045a88b612499fbcba375a77198e01306f52272e692f8c1f3751185" dependencies = [ "gl_generator", "x11-dl", @@ -862,9 +862,9 @@ dependencies = [ [[package]] name = "glutin_wgl_sys" -version = "0.6.0" +version = "0.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0a4e1951bbd9434a81aa496fe59ccc2235af3820d27b85f9314e279609211e2c" +checksum = "2c4ee00b289aba7a9e5306d57c2d05499b2e5dc427f84ac708bd2c090212cf3e" dependencies = [ "gl_generator", ] @@ -2060,26 +2060,16 @@ dependencies = [ [[package]] name = "vte-graphics" -version = "0.13.1" +version = "0.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a567531be6ebf19138eed358a880b7959f206cb79dec94a83d145797aedc4bd" +checksum = "6a7d926313d94a0ef0d992fe9ab507451cdb4a7977e653155c8e4fa9b69c178f" dependencies = [ + "arrayvec", "bitflags 2.6.0", "cursor-icon", "log", + "memchr", "serde", - "utf8parse", - "vte_generate_state_changes", -] - -[[package]] -name = "vte_generate_state_changes" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2e369bee1b05d510a7b4ed645f5faa90619e05437111783ea5848f28d97d3c2e" -dependencies = [ - "proc-macro2", - "quote", ] [[package]] @@ -2541,9 +2531,9 @@ checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" [[package]] name = "winit" -version = "0.30.8" +version = "0.30.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f5d74280aabb958072864bff6cfbcf9025cf8bfacdde5e32b5e12920ef703b0f" +checksum = "a809eacf18c8eca8b6635091543f02a5a06ddf3dad846398795460e6e0ae3cc0" dependencies = [ "ahash", "android-activity", diff --git a/alacritty/Cargo.toml b/alacritty/Cargo.toml index 919394fb..19467e9d 100644 --- a/alacritty/Cargo.toml +++ b/alacritty/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "alacritty" -version = "0.15.0-dev" +version = "0.16.0-dev" authors = ["Christian Duerr <contact@christianduerr.com>", "Joe Wilm <joe@jwilm.com>"] license = "Apache-2.0" description = "A fast, cross-platform, OpenGL terminal emulator" @@ -12,7 +12,7 @@ rust-version = "1.74.0" [dependencies.alacritty_terminal] path = "../alacritty_terminal" -version = "0.24.2-dev" +version = "0.25.1-dev" [dependencies.alacritty_config_derive] path = "../alacritty_config_derive" @@ -28,7 +28,7 @@ bitflags = "2.2.1" clap = { version = "4.2.7", features = ["derive", "env"] } copypasta = { version = "0.10.1", default-features = false } crossfont = "0.8.0" -glutin = { version = "0.32.0", default-features = false, features = ["egl", "wgl"] } +glutin = { version = "0.32.2", default-features = false, features = ["egl", "wgl"] } home = "0.5.5" libc = "0.2" log = { version = "0.4", features = ["std", "serde"] } @@ -43,7 +43,7 @@ tempfile = "3.12.0" toml = "0.8.2" toml_edit = "0.22.21" unicode-width = "0.1" -winit = { version = "0.30.8", default-features = false, features = ["rwh_06", "serde"] } +winit = { version = "0.30.9", default-features = false, features = ["rwh_06", "serde"] } [build-dependencies] gl_generator = "0.14.0" diff --git a/alacritty/build.rs b/alacritty/build.rs index 2ecbdf8f..02f0fdaf 100644 --- a/alacritty/build.rs +++ b/alacritty/build.rs @@ -18,6 +18,7 @@ fn main() { Registry::new(Api::Gl, (3, 3), Profile::Core, Fallbacks::All, [ "GL_ARB_blend_func_extended", "GL_ARB_clear_texture", + "GL_KHR_robustness", "GL_KHR_debug", ]) .write_bindings(GlobalGenerator, &mut file) diff --git a/alacritty/src/cli.rs b/alacritty/src/cli.rs index bb0a24f4..feac41bd 100644 --- a/alacritty/src/cli.rs +++ b/alacritty/src/cli.rs @@ -189,7 +189,7 @@ impl TerminalOptions { pty_config.shell = Some(command.into()); } - pty_config.hold |= self.hold; + pty_config.drain_on_exit |= self.hold; } } @@ -198,7 +198,7 @@ impl From<TerminalOptions> for PtyOptions { PtyOptions { working_directory: options.working_directory.take(), shell: options.command().map(Into::into), - hold: options.hold, + drain_on_exit: options.hold, env: HashMap::new(), } } @@ -300,6 +300,11 @@ pub struct WindowOptions { /// The window tabbing identifier to use when building a window. pub window_tabbing_id: Option<String>, + #[clap(skip)] + #[cfg(not(any(target_os = "macos", windows)))] + /// `ActivationToken` that we pass to winit. + pub activation_token: Option<String>, + /// Override configuration file options [example: 'cursor.style="Beam"']. #[clap(short = 'o', long, num_args = 1..)] option: Vec<String>, diff --git a/alacritty/src/config/ui_config.rs b/alacritty/src/config/ui_config.rs index b44bda0d..960bdbbc 100644 --- a/alacritty/src/config/ui_config.rs +++ b/alacritty/src/config/ui_config.rs @@ -37,7 +37,7 @@ use crate::config::LOG_TARGET_CONFIG; /// Regex used for the default URL hint. #[rustfmt::skip] const URL_REGEX: &str = "(ipfs:|ipns:|magnet:|mailto:|gemini://|gopher://|https://|http://|news:|file:|git://|ssh:|ftp://)\ - [^\u{0000}-\u{001F}\u{007F}-\u{009F}<>\"\\s{-}\\^⟨⟩`]+"; + [^\u{0000}-\u{001F}\u{007F}-\u{009F}<>\"\\s{-}\\^⟨⟩`\\\\]+"; #[derive(ConfigDeserialize, Default, Clone, Debug, PartialEq)] pub struct UiConfig { @@ -130,7 +130,7 @@ impl UiConfig { let shell = self.terminal.shell.clone().or_else(|| self.shell.clone()).map(Into::into); let working_directory = self.working_directory.clone().or_else(|| self.general.working_directory.clone()); - PtyOptions { working_directory, shell, hold: false, env: HashMap::new() } + PtyOptions { working_directory, shell, drain_on_exit: false, env: HashMap::new() } } /// Generate key bindings for all keyboard hints. diff --git a/alacritty/src/daemon.rs b/alacritty/src/daemon.rs index c8fb88d1..fa530fa0 100644 --- a/alacritty/src/daemon.rs +++ b/alacritty/src/daemon.rs @@ -9,6 +9,7 @@ use std::process::{Command, Stdio}; #[rustfmt::skip] #[cfg(not(windows))] use { + std::env, std::error::Error, std::os::unix::process::CommandExt, std::os::unix::io::RawFd, @@ -58,18 +59,22 @@ where { let mut command = Command::new(program); command.args(args).stdin(Stdio::null()).stdout(Stdio::null()).stderr(Stdio::null()); - if let Ok(cwd) = foreground_process_path(master_fd, shell_pid) { - command.current_dir(cwd); - } + + let working_directory = foreground_process_path(master_fd, shell_pid).ok(); unsafe { command - .pre_exec(|| { + .pre_exec(move || { match libc::fork() { -1 => return Err(io::Error::last_os_error()), 0 => (), _ => libc::_exit(0), } + // Copy foreground process' working directory, ignoring invalid paths. + if let Some(working_directory) = working_directory.as_ref() { + let _ = env::set_current_dir(working_directory); + } + if libc::setsid() == -1 { return Err(io::Error::last_os_error()); } diff --git a/alacritty/src/display/mod.rs b/alacritty/src/display/mod.rs index a679fe21..6ff8b1e3 100644 --- a/alacritty/src/display/mod.rs +++ b/alacritty/src/display/mod.rs @@ -5,10 +5,13 @@ use std::cmp; use std::fmt::{self, Formatter}; use std::mem::{self, ManuallyDrop}; use std::num::NonZeroU32; -use std::ops::{Deref, DerefMut}; +use std::ops::Deref; use std::time::{Duration, Instant}; +use glutin::config::GetGlConfig; use glutin::context::{NotCurrentContext, PossiblyCurrentContext}; +use glutin::display::GetGlDisplay; +use glutin::error::ErrorKind; use glutin::prelude::*; use glutin::surface::{Surface, SwapInterval, WindowSurface}; @@ -33,6 +36,7 @@ use alacritty_terminal::term::{ }; use alacritty_terminal::vte::ansi::{CursorShape, NamedColor}; +use crate::config::debug::RendererPreference; use crate::config::font::Font; use crate::config::window::Dimensions; #[cfg(not(windows))] @@ -49,7 +53,7 @@ use crate::display::window::Window; use crate::event::{Event, EventType, Mouse, SearchState}; use crate::message_bar::{MessageBuffer, MessageType}; use crate::renderer::rects::{RenderLine, RenderLines, RenderRect}; -use crate::renderer::{self, GlyphCache, Renderer}; +use crate::renderer::{self, platform, GlyphCache, Renderer}; use crate::scheduler::{Scheduler, TimerId, Topic}; use crate::string::{ShortenDirection, StrShortener}; @@ -395,10 +399,11 @@ pub struct Display { hint_mouse_point: Option<Point>, renderer: ManuallyDrop<Renderer>, + renderer_preference: Option<RendererPreference>, surface: ManuallyDrop<Surface<WindowSurface>>, - context: ManuallyDrop<Replaceable<PossiblyCurrentContext>>, + context: ManuallyDrop<PossiblyCurrentContext>, glyph_cache: GlyphCache, meter: Meter, @@ -431,7 +436,7 @@ impl Display { } // Create the GL surface to draw into. - let surface = renderer::platform::create_gl_surface( + let surface = platform::create_gl_surface( &gl_context, window.inner_size(), window.raw_window_handle(), @@ -520,9 +525,10 @@ impl Display { } Ok(Self { - context: ManuallyDrop::new(Replaceable::new(context)), + context: ManuallyDrop::new(context), visual_bell: VisualBell::from(&config.bell), renderer: ManuallyDrop::new(renderer), + renderer_preference: config.debug.renderer, surface: ManuallyDrop::new(surface), colors: List::from(&config.colors), frame_timer: FrameTimer::new(), @@ -548,29 +554,69 @@ impl Display { #[inline] pub fn gl_context(&self) -> &PossiblyCurrentContext { - self.context.get() + &self.context } pub fn make_not_current(&mut self) { - if self.context.get().is_current() { - self.context.replace_with(|context| { - context - .make_not_current() - .expect("failed to disable context") - .treat_as_possibly_current() - }); + if self.context.is_current() { + self.context.make_not_current_in_place().expect("failed to disable context"); } } - pub fn make_current(&self) { - if !self.context.get().is_current() { - self.context.make_current(&self.surface).expect("failed to make context current") + pub fn make_current(&mut self) { + let is_current = self.context.is_current(); + + // Attempt to make the context current if it's not. + let context_loss = if is_current { + self.renderer.was_context_reset() + } else { + match self.context.make_current(&self.surface) { + Err(err) if err.error_kind() == ErrorKind::ContextLost => { + info!("Context lost for window {:?}", self.window.id()); + true + }, + _ => false, + } + }; + + if !context_loss { + return; + } + + let gl_display = self.context.display(); + let gl_config = self.context.config(); + let raw_window_handle = Some(self.window.raw_window_handle()); + let context = platform::create_gl_context(&gl_display, &gl_config, raw_window_handle) + .expect("failed to recreate context."); + + // Drop the old context and renderer. + unsafe { + ManuallyDrop::drop(&mut self.renderer); + ManuallyDrop::drop(&mut self.context); } + + // Activate new context. + let context = context.treat_as_possibly_current(); + self.context = ManuallyDrop::new(context); + self.context.make_current(&self.surface).expect("failed to reativate context after reset."); + + // Recreate renderer. + let renderer = Renderer::new(&self.context, self.renderer_preference) + .expect("failed to recreate renderer after reset"); + self.renderer = ManuallyDrop::new(renderer); + + // Resize the renderer. + self.renderer.resize(&self.size_info); + + self.reset_glyph_cache(); + self.damage_tracker.frame().mark_fully_damaged(); + + debug!("Recovered window {:?} from gpu reset", self.window.id()); } fn swap_buffers(&self) { #[allow(clippy::single_match)] - let res = match (self.surface.deref(), &self.context.get()) { + let res = match (self.surface.deref(), &self.context.deref()) { #[cfg(not(any(target_os = "macos", windows)))] (Surface::Egl(surface), PossiblyCurrentContext::Egl(context)) if matches!(self.raw_window_handle, RawWindowHandle::Wayland(_)) @@ -1374,6 +1420,8 @@ impl Display { (&mut self.highlighted_hint, &mut self.highlighted_hint_age, true), (&mut self.vi_highlighted_hint, &mut self.vi_highlighted_hint_age, false), ]; + + let num_lines = self.size_info.screen_lines(); for (hint, hint_age, reset_mouse) in hints { let (start, end) = match hint { Some(hint) => (*hint.bounds().start(), *hint.bounds().end()), @@ -1387,10 +1435,12 @@ impl Display { } // Convert hint bounds to viewport coordinates. - let start = term::point_to_viewport(display_offset, start).unwrap_or_default(); - let end = term::point_to_viewport(display_offset, end).unwrap_or_else(|| { - Point::new(self.size_info.screen_lines() - 1, self.size_info.last_column()) - }); + let start = term::point_to_viewport(display_offset, start) + .filter(|point| point.line < num_lines) + .unwrap_or_default(); + let end = term::point_to_viewport(display_offset, end) + .filter(|point| point.line < num_lines) + .unwrap_or_else(|| Point::new(num_lines - 1, self.size_info.last_column())); // Clear invalidated hints. if frame.intersects(start, end) { @@ -1525,47 +1575,6 @@ pub struct RendererUpdate { clear_font_cache: bool, } -/// 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() - } -} - /// The frame timer state. pub struct FrameTimer { /// Base timestamp used to compute sync points. diff --git a/alacritty/src/display/window.rs b/alacritty/src/display/window.rs index 1c8089bc..f9fb9272 100644 --- a/alacritty/src/display/window.rs +++ b/alacritty/src/display/window.rs @@ -2,6 +2,8 @@ use winit::platform::startup_notify::{ self, EventLoopExtStartupNotify, WindowAttributesExtStartupNotify, }; +#[cfg(not(any(target_os = "macos", windows)))] +use winit::window::ActivationToken; #[cfg(all(not(feature = "x11"), not(any(target_os = "macos", windows))))] use winit::platform::wayland::WindowAttributesExtWayland; @@ -38,6 +40,7 @@ use winit::window::{ use alacritty_terminal::index::Point; +use crate::cli::WindowOptions; use crate::config::window::{Decorations, Identity, WindowConfig}; use crate::config::UiConfig; use crate::display::SizeInfo; @@ -106,6 +109,9 @@ pub struct Window { /// Flag indicating whether redraw was requested. pub requested_redraw: bool, + /// Hold the window when terminal exits. + pub hold: bool, + window: WinitWindow, /// Current window title. @@ -124,9 +130,7 @@ impl Window { event_loop: &ActiveEventLoop, config: &UiConfig, identity: &Identity, - #[rustfmt::skip] - #[cfg(target_os = "macos")] - tabbing_id: &Option<String>, + options: &mut WindowOptions, #[rustfmt::skip] #[cfg(all(feature = "x11", not(any(target_os = "macos", windows))))] x11_visual: Option<X11VisualInfo>, @@ -138,7 +142,7 @@ impl Window { #[cfg(all(feature = "x11", not(any(target_os = "macos", windows))))] x11_visual, #[cfg(target_os = "macos")] - tabbing_id, + &options.window_tabbing_id.take(), ); if let Some(position) = config.window.position { @@ -147,7 +151,12 @@ impl Window { } #[cfg(not(any(target_os = "macos", windows)))] - if let Some(token) = event_loop.read_token_from_env() { + if let Some(token) = options + .activation_token + .take() + .map(ActivationToken::from_raw) + .or_else(|| event_loop.read_token_from_env()) + { log::debug!("Activating window with token: {token:?}"); window_attributes = window_attributes.with_activation_token(token); @@ -193,6 +202,7 @@ impl Window { let is_x11 = matches!(window.window_handle().unwrap().as_raw(), RawWindowHandle::Xlib(_)); Ok(Self { + hold: options.terminal_options.hold, requested_redraw: false, title: identity.title, current_mouse_cursor, diff --git a/alacritty/src/event.rs b/alacritty/src/event.rs index 2ac6279d..c761f5ae 100644 --- a/alacritty/src/event.rs +++ b/alacritty/src/event.rs @@ -4,6 +4,7 @@ use crate::ConfigMonitor; use glutin::config::GetGlConfig; use std::borrow::Cow; use std::cmp::min; +use std::collections::hash_map::Entry; use std::collections::{HashMap, HashSet, VecDeque}; use std::error::Error; use std::ffi::OsStr; @@ -380,9 +381,14 @@ impl ApplicationHandler<Event> for Processor { }, (EventType::Terminal(TerminalEvent::Exit), Some(window_id)) => { // Remove the closed terminal. - let window_context = match self.windows.remove(window_id) { - Some(window_context) => window_context, - None => return, + let window_context = match self.windows.entry(*window_id) { + // Don't exit when terminal exits if user asked to hold the window. + Entry::Occupied(window_context) + if !window_context.get().display.window.hold => + { + window_context.remove() + }, + _ => return, }; // Unschedule pending events. @@ -838,9 +844,8 @@ impl<'a, N: Notify + 'a, T: EventListener> input::ActionContext<T> for ActionCon #[cfg(not(windows))] fn create_new_window(&mut self, #[cfg(target_os = "macos")] tabbing_id: Option<String>) { let mut options = WindowOptions::default(); - if let Ok(working_directory) = foreground_process_path(self.master_fd, self.shell_pid) { - options.terminal_options.working_directory = Some(working_directory); - } + options.terminal_options.working_directory = + foreground_process_path(self.master_fd, self.shell_pid).ok(); #[cfg(target_os = "macos")] { @@ -869,7 +874,7 @@ impl<'a, N: Notify + 'a, T: EventListener> input::ActionContext<T> for ActionCon match result { Ok(_) => debug!("Launched {} with args {:?}", program, args), - Err(_) => warn!("Unable to launch {} with args {:?}", program, args), + Err(err) => warn!("Unable to launch {program} with args {args:?}: {err}"), } } @@ -1793,7 +1798,11 @@ impl input::Processor<EventProxy, ActionContext<'_, Notifier, EventProxy>> { }, WinitEvent::WindowEvent { event, .. } => { match event { - WindowEvent::CloseRequested => self.ctx.terminal.exit(), + WindowEvent::CloseRequested => { + // User asked to close the window, so no need to hold it. + self.ctx.window().hold = false; + self.ctx.terminal.exit(); + }, WindowEvent::ScaleFactorChanged { scale_factor, .. } => { let old_scale_factor = mem::replace(&mut self.ctx.window().scale_factor, scale_factor); diff --git a/alacritty/src/input/keyboard.rs b/alacritty/src/input/keyboard.rs index af9bfbb2..417f599b 100644 --- a/alacritty/src/input/keyboard.rs +++ b/alacritty/src/input/keyboard.rs @@ -342,18 +342,21 @@ impl SequenceBuilder { }; if character.chars().count() == 1 { - let character = character.chars().next().unwrap(); - let base_character = character.to_lowercase().next().unwrap(); + let shift = self.modifiers.contains(SequenceModifiers::SHIFT); - let alternate_key_code = u32::from(character); - let mut unicode_key_code = u32::from(base_character); + let ch = character.chars().next().unwrap(); + let unshifted_ch = if shift { ch.to_lowercase().next().unwrap() } else { ch }; + + let alternate_key_code = u32::from(ch); + let mut unicode_key_code = u32::from(unshifted_ch); // Try to get the base for keys which change based on modifier, like `1` for `!`. - match key.key_without_modifiers().as_ref() { - Key::Character(unmodded) if alternate_key_code == unicode_key_code => { - unicode_key_code = u32::from(unmodded.chars().next().unwrap_or(base_character)); - }, - _ => (), + // + // However it should only be performed when `SHIFT` is pressed. + if shift && alternate_key_code == unicode_key_code { + if let Key::Character(unmodded) = key.key_without_modifiers().as_ref() { + unicode_key_code = u32::from(unmodded.chars().next().unwrap_or(unshifted_ch)); + } } // NOTE: Base layouts are ignored, since winit doesn't expose this information diff --git a/alacritty/src/input/mod.rs b/alacritty/src/input/mod.rs index 60a50529..3f85512f 100644 --- a/alacritty/src/input/mod.rs +++ b/alacritty/src/input/mod.rs @@ -324,7 +324,10 @@ impl<T: EventListener> Execute<T> for Action { #[cfg(not(target_os = "macos"))] Action::Hide => ctx.window().set_visible(false), Action::Minimize => ctx.window().set_minimized(true), - Action::Quit => ctx.terminal_mut().exit(), + Action::Quit => { + ctx.window().hold = false; + ctx.terminal_mut().exit(); + }, Action::IncreaseFontSize => ctx.change_font_size(FONT_SIZE_STEP), Action::DecreaseFontSize => ctx.change_font_size(-FONT_SIZE_STEP), Action::ResetFontSize => ctx.reset_font_size(), diff --git a/alacritty/src/ipc.rs b/alacritty/src/ipc.rs index 3d14c4ce..919035a6 100644 --- a/alacritty/src/ipc.rs +++ b/alacritty/src/ipc.rs @@ -19,7 +19,10 @@ use crate::event::{Event, EventType}; const ALACRITTY_SOCKET_ENV: &str = "ALACRITTY_SOCKET"; /// Create an IPC socket. -pub fn spawn_ipc_socket(options: &Options, event_proxy: EventLoopProxy<Event>) -> Option<PathBuf> { +pub fn spawn_ipc_socket( + options: &Options, + event_proxy: EventLoopProxy<Event>, +) -> IoResult<PathBuf> { // Create the IPC socket and export its path as env. let socket_path = options.socket.clone().unwrap_or_else(|| { @@ -28,13 +31,7 @@ pub fn spawn_ipc_socket(options: &Options, event_proxy: EventLoopProxy<Event>) - path }); - let listener = match UnixListener::bind(&socket_path) { - Ok(listener) => listener, - Err(err) => { - warn!("Unable to create socket: {:?}", err); - return None; - }, - }; + let listener = UnixListener::bind(&socket_path)?; env::set_var(ALACRITTY_SOCKET_ENV, socket_path.as_os_str()); if options.daemon { @@ -80,7 +77,7 @@ pub fn spawn_ipc_socket(options: &Options, event_proxy: EventLoopProxy<Event>) - } }); - Some(socket_path) + Ok(socket_path) } /// Send a message to the active Alacritty socket. diff --git a/alacritty/src/main.rs b/alacritty/src/main.rs index 6bbf8dfd..9260bfa4 100644 --- a/alacritty/src/main.rs +++ b/alacritty/src/main.rs @@ -55,6 +55,8 @@ mod gl { #[cfg(unix)] use crate::cli::MessageOptions; +#[cfg(not(any(target_os = "macos", windows)))] +use crate::cli::SocketMessage; use crate::cli::{Options, Subcommands}; use crate::config::monitor::ConfigMonitor; use crate::config::UiConfig; @@ -89,7 +91,13 @@ fn main() -> Result<(), Box<dyn Error>> { /// `msg` subcommand entrypoint. #[cfg(unix)] -fn msg(options: MessageOptions) -> Result<(), Box<dyn Error>> { +#[allow(unused_mut)] +fn msg(mut options: MessageOptions) -> Result<(), Box<dyn Error>> { + #[cfg(not(any(target_os = "macos", windows)))] + if let SocketMessage::CreateWindow(window_options) = &mut options.message { + window_options.activation_token = + env::var("XDG_ACTIVATION_TOKEN").or_else(|_| env::var("DESKTOP_STARTUP_ID")).ok(); + } ipc::send_message(options.socket, options.message).map_err(|err| err.into()) } @@ -175,7 +183,14 @@ fn alacritty(mut options: Options) -> Result<(), Box<dyn Error>> { // Create the IPC socket listener. #[cfg(unix)] let socket_path = if config.ipc_socket() { - ipc::spawn_ipc_socket(&options, window_event_loop.create_proxy()) + match ipc::spawn_ipc_socket(&options, window_event_loop.create_proxy()) { + Ok(path) => Some(path), + Err(err) if options.daemon => return Err(err.into()), + Err(err) => { + log::warn!("Unable to create socket: {:?}", err); + None + }, + } } else { None }; diff --git a/alacritty/src/renderer/mod.rs b/alacritty/src/renderer/mod.rs index a1ffb311..ce6b0914 100644 --- a/alacritty/src/renderer/mod.rs +++ b/alacritty/src/renderer/mod.rs @@ -9,7 +9,7 @@ use ahash::RandomState; use crossfont::Metrics; use glutin::context::{ContextApi, GlContext, PossiblyCurrentContext}; use glutin::display::{GetGlDisplay, GlDisplay}; -use log::{debug, error, info, warn, LevelFilter}; +use log::{debug, info, LevelFilter}; use unicode_width::UnicodeWidthChar; use alacritty_terminal::graphics::UpdateQueues; @@ -101,6 +101,7 @@ pub struct Renderer { text_renderer: TextRendererProvider, rect_renderer: RectRenderer, graphics_renderer: GraphicsRenderer, + robustness: bool, } /// Wrapper around gl::GetString with error checking and reporting. @@ -148,6 +149,9 @@ impl Renderer { info!("Running on {renderer}"); info!("OpenGL version {gl_version}, shader_version {shader_version}"); + // Check if robustness is supported. + let robustness = Self::supports_robustness(); + let is_gles_context = matches!(context.context_api(), ContextApi::Gles(_)); // Use the config option to enforce a particular renderer configuration. @@ -181,7 +185,7 @@ impl Renderer { } } - Ok(Self { text_renderer, rect_renderer, graphics_renderer }) + Ok(Self { text_renderer, rect_renderer, graphics_renderer, robustness }) } pub fn draw_cells<I: Iterator<Item = RenderableCell>>( @@ -212,10 +216,10 @@ impl Renderer { glyph_cache: &mut GlyphCache, ) { let mut wide_char_spacer = false; - let cells = string_chars.enumerate().map(|(i, character)| { + let cells = string_chars.enumerate().filter_map(|(i, character)| { let flags = if wide_char_spacer { wide_char_spacer = false; - Flags::WIDE_CHAR_SPACER + return None; } else if character.width() == Some(2) { // The spacer is always following the wide char. wide_char_spacer = true; @@ -224,7 +228,7 @@ impl Renderer { Flags::empty() }; - RenderableCell { + Some(RenderableCell { point: Point::new(point.line, point.column + i), character, extra: None, @@ -233,7 +237,7 @@ impl Renderer { fg, bg, underline: fg, - } + }) }); self.draw_cells(size_info, glyph_cache, cells); @@ -287,6 +291,49 @@ impl Renderer { } } + /// Get the context reset status. + pub fn was_context_reset(&self) -> bool { + // If robustness is not supported, don't use its functions. + if !self.robustness { + return false; + } + + let status = unsafe { gl::GetGraphicsResetStatus() }; + if status == gl::NO_ERROR { + false + } else { + let reason = match status { + gl::GUILTY_CONTEXT_RESET_KHR => "guilty", + gl::INNOCENT_CONTEXT_RESET_KHR => "innocent", + gl::UNKNOWN_CONTEXT_RESET_KHR => "unknown", + _ => "invalid", + }; + + info!("GPU reset ({})", reason); + + true + } + } + + fn supports_robustness() -> bool { + let mut notification_strategy = 0; + if GlExtensions::contains("GL_KHR_robustness") { + unsafe { + gl::GetIntegerv(gl::RESET_NOTIFICATION_STRATEGY_KHR, &mut notification_strategy); + } + } else { + notification_strategy = gl::NO_RESET_NOTIFICATION_KHR as gl::types::GLint; + } + + if notification_strategy == gl::LOSE_CONTEXT_ON_RESET_KHR as gl::types::GLint { + info!("GPU reset notifications are enabled"); + true + } else { + info!("GPU reset notifications are disabled"); + false + } + } + pub fn finish(&self) { unsafe { gl::Finish(); @@ -387,7 +434,7 @@ impl GlExtensions { extern "system" fn gl_debug_log( _: gl::types::GLenum, - kind: gl::types::GLenum, + _: gl::types::GLenum, _: gl::types::GLuint, _: gl::types::GLenum, _: gl::types::GLsizei, @@ -395,11 +442,5 @@ extern "system" fn gl_debug_log( _: *mut std::os::raw::c_void, ) { let msg = unsafe { CStr::from_ptr(msg).to_string_lossy() }; - match kind { - gl::DEBUG_TYPE_ERROR | gl::DEBUG_TYPE_UNDEFINED_BEHAVIOR => { - error!("[gl_render] {}", msg) - }, - gl::DEBUG_TYPE_DEPRECATED_BEHAVIOR => warn!("[gl_render] {}", msg), - _ => debug!("[gl_render] {}", msg), - } + debug!("[gl_render] {}", msg); } diff --git a/alacritty/src/renderer/platform.rs b/alacritty/src/renderer/platform.rs index 87ed29c2..3b2e2fce 100644 --- a/alacritty/src/renderer/platform.rs +++ b/alacritty/src/renderer/platform.rs @@ -4,9 +4,9 @@ use std::num::NonZeroU32; use glutin::config::{ColorBufferType, Config, ConfigTemplateBuilder, GetGlConfig}; use glutin::context::{ - ContextApi, ContextAttributesBuilder, GlProfile, NotCurrentContext, Version, + ContextApi, ContextAttributesBuilder, GlProfile, NotCurrentContext, Robustness, Version, }; -use glutin::display::{Display, DisplayApiPreference, GetGlDisplay}; +use glutin::display::{Display, DisplayApiPreference, DisplayFeatures, GetGlDisplay}; use glutin::error::Result as GlutinResult; use glutin::prelude::*; use glutin::surface::{Surface, SurfaceAttributesBuilder, WindowSurface}; @@ -110,18 +110,24 @@ pub fn create_gl_context( raw_window_handle: Option<RawWindowHandle>, ) -> GlutinResult<NotCurrentContext> { let debug = log::max_level() >= LevelFilter::Debug; + let mut builder = ContextAttributesBuilder::new().with_debug(debug); + + // Try to enable robustness. + if gl_display.supported_features().contains(DisplayFeatures::CONTEXT_ROBUSTNESS) { + builder = builder.with_robustness(Robustness::RobustLoseContextOnReset); + } + let mut profiles = [ - ContextAttributesBuilder::new() - .with_debug(debug) + builder + .clone() .with_context_api(ContextApi::OpenGl(Some(Version::new(3, 3)))) .build(raw_window_handle), // Try gles before OpenGL 2.1 as it tends to be more stable. - ContextAttributesBuilder::new() - .with_debug(debug) + builder + .clone() .with_context_api(ContextApi::Gles(Some(Version::new(2, 0)))) .build(raw_window_handle), - ContextAttributesBuilder::new() - .with_debug(debug) + builder .with_profile(GlProfile::Compatibility) .with_context_api(ContextApi::OpenGl(Some(Version::new(2, 1)))) .build(raw_window_handle), diff --git a/alacritty/src/window_context.rs b/alacritty/src/window_context.rs index cfc3cd96..a0e66cc0 100644 --- a/alacritty/src/window_context.rs +++ b/alacritty/src/window_context.rs @@ -73,7 +73,7 @@ impl WindowContext { event_loop: &ActiveEventLoop, proxy: EventLoopProxy<Event>, config: Rc<UiConfig>, - options: WindowOptions, + mut options: WindowOptions, ) -> Result<Self, Box<dyn Error>> { let raw_display_handle = event_loop.display_handle().unwrap().as_raw(); @@ -83,7 +83,7 @@ impl WindowContext { // Windows has different order of GL platform initialization compared to any other platform; // it requires the window first. #[cfg(windows)] - let window = Window::new(event_loop, &config, &identity)?; + let window = Window::new(event_loop, &config, &identity, &mut options)?; #[cfg(windows)] let raw_window_handle = Some(window.raw_window_handle()); @@ -102,10 +102,9 @@ impl WindowContext { event_loop, &config, &identity, + &mut options, #[cfg(all(feature = "x11", not(any(target_os = "macos", windows))))] gl_config.x11_visual(), - #[cfg(target_os = "macos")] - &options.window_tabbing_id, )?; // Create context. @@ -123,7 +122,7 @@ impl WindowContext { event_loop: &ActiveEventLoop, proxy: EventLoopProxy<Event>, config: Rc<UiConfig>, - options: WindowOptions, + mut options: WindowOptions, config_overrides: ParsedOptions, ) -> Result<Self, Box<dyn Error>> { let gl_display = gl_config.display(); @@ -135,10 +134,9 @@ impl WindowContext { event_loop, &config, &identity, + &mut options, #[cfg(all(feature = "x11", not(any(target_os = "macos", windows))))] gl_config.x11_visual(), - #[cfg(target_os = "macos")] - &options.window_tabbing_id, )?; // Create context. @@ -214,7 +212,7 @@ impl WindowContext { Arc::clone(&terminal), event_proxy.clone(), pty, - pty_config.hold, + pty_config.drain_on_exit, config.debug.ref_test, )?; diff --git a/alacritty/windows/wix/alacritty.wxs b/alacritty/windows/wix/alacritty.wxs index 5c05d821..bcf59cf5 100644 --- a/alacritty/windows/wix/alacritty.wxs +++ b/alacritty/windows/wix/alacritty.wxs @@ -1,5 +1,5 @@ <Wix xmlns="http://wixtoolset.org/schemas/v4/wxs" xmlns:ui="http://wixtoolset.org/schemas/v4/wxs/ui"> - <Package Name="Alacritty" UpgradeCode="87c21c74-dbd5-4584-89d5-46d9cd0c40a7" Language="1033" Codepage="1252" Version="0.15.0-dev" Manufacturer="Alacritty" InstallerVersion="200"> + <Package Name="Alacritty" UpgradeCode="87c21c74-dbd5-4584-89d5-46d9cd0c40a7" Language="1033" Codepage="1252" Version="0.16.0-dev" Manufacturer="Alacritty" InstallerVersion="200"> <MajorUpgrade AllowSameVersionUpgrades="yes" DowngradeErrorMessage="A newer version of [ProductName] is already installed." /> <Icon Id="AlacrittyIco" SourceFile=".\alacritty\windows\alacritty.ico" /> <WixVariable Id="WixUILicenseRtf" Value=".\alacritty\windows\wix\license.rtf" /> diff --git a/alacritty_terminal/CHANGELOG.md b/alacritty_terminal/CHANGELOG.md index a6ee32b2..9b2f9ebf 100644 --- a/alacritty_terminal/CHANGELOG.md +++ b/alacritty_terminal/CHANGELOG.md @@ -8,7 +8,19 @@ sections should follow the order `Added`, `Changed`, `Deprecated`, `Fixed` and The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). -## 0.24.2-dev +## 0.25.1-dev + +### Changed + +- Pass `-q` to `login` on macOS if `~/.hushlogin` is present + +## 0.25.0 + +### Changed + +- Replaced `Options::hold` with `Options::drain_on_exit` + +## 0.24.2 ### Added diff --git a/alacritty_terminal/Cargo.toml b/alacritty_terminal/Cargo.toml index f8abf51d..04547103 100644 --- a/alacritty_terminal/Cargo.toml +++ b/alacritty_terminal/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "alacritty_terminal" -version = "0.24.2-dev" +version = "0.25.1-dev" authors = ["Christian Duerr <contact@christianduerr.com>", "Joe Wilm <joe@jwilm.com>"] license = "Apache-2.0" description = "Library for writing terminal emulators" @@ -24,7 +24,7 @@ parking_lot = "0.12.0" polling = "3.0.0" regex-automata = "0.4.3" unicode-width = "0.1" -vte = { version = "0.13.0", package = "vte-graphics", default-features = false, features = ["ansi", "serde"] } +vte = { version = "0.15.0", package = "vte-graphics", default-features = false, features = ["std", "ansi"] } serde = { version = "1", features = ["derive", "rc"], optional = true } smallvec = { version = "1.13.1", features = ["serde"] } diff --git a/alacritty_terminal/src/event_loop.rs b/alacritty_terminal/src/event_loop.rs index 62dd7440..1bef1d4f 100644 --- a/alacritty_terminal/src/event_loop.rs +++ b/alacritty_terminal/src/event_loop.rs @@ -17,8 +17,8 @@ use polling::{Event as PollingEvent, Events, PollMode}; use crate::event::{self, Event, EventListener, WindowSize}; use crate::sync::FairMutex; use crate::term::Term; -use crate::vte::ansi; use crate::{thread, tty}; +use vte::ansi; /// Max bytes to read from the PTY before forced terminal synchronization. pub(crate) const READ_BUFFER_SIZE: usize = 0x10_0000; @@ -50,7 +50,7 @@ pub struct EventLoop<T: tty::EventedPty, U: EventListener> { tx: Sender<Msg>, terminal: Arc<FairMutex<Term<U>>>, event_proxy: U, - hold: bool, + drain_on_exit: bool, ref_test: bool, } @@ -64,7 +64,7 @@ where terminal: Arc<FairMutex<Term<U>>>, event_proxy: U, pty: T, - hold: bool, + drain_on_exit: bool, ref_test: bool, ) -> io::Result<EventLoop<T, U>> { let (tx, rx) = mpsc::channel(); @@ -76,7 +76,7 @@ where rx: PeekableReceiver::new(rx), terminal, event_proxy, - hold, + drain_on_exit, ref_test, }) } @@ -151,9 +151,7 @@ where } // Parse the incoming bytes. - for byte in &buf[..unprocessed] { - state.parser.advance(&mut **terminal, *byte); - } + state.parser.advance(&mut **terminal, &buf[..unprocessed]); processed += unprocessed; unprocessed = 0; @@ -263,13 +261,10 @@ where if let Some(code) = code { self.event_proxy.send_event(Event::ChildExit(code)); } - if self.hold { - // With hold enabled, make sure the PTY is drained. + if self.drain_on_exit { let _ = self.pty_read(&mut state, &mut buf, pipe.as_mut()); - } else { - // Without hold, shutdown the terminal. - self.terminal.lock().exit(); } + self.terminal.lock().exit(); self.event_proxy.send_event(Event::Wakeup); break 'event_loop; } diff --git a/alacritty_terminal/src/tty/mod.rs b/alacritty_terminal/src/tty/mod.rs index eed2a76d..208547ba 100644 --- a/alacritty_terminal/src/tty/mod.rs +++ b/alacritty_terminal/src/tty/mod.rs @@ -28,8 +28,8 @@ pub struct Options { /// Shell startup directory. pub working_directory: Option<PathBuf>, - /// Remain open after child process exits. - pub hold: bool, + /// Drain the child process output before exiting the terminal. + pub drain_on_exit: bool, /// Extra environment variables. pub env: HashMap<String, String>, diff --git a/alacritty_terminal/src/tty/unix.rs b/alacritty_terminal/src/tty/unix.rs index 6565f20b..884cb5c1 100644 --- a/alacritty_terminal/src/tty/unix.rs +++ b/alacritty_terminal/src/tty/unix.rs @@ -8,6 +8,8 @@ use std::os::fd::OwnedFd; use std::os::unix::io::AsRawFd; use std::os::unix::net::UnixStream; use std::os::unix::process::CommandExt; +#[cfg(target_os = "macos")] +use std::path::Path; use std::process::{Child, Command}; use std::sync::Arc; use std::{env, ptr}; @@ -158,12 +160,12 @@ impl ShellUser { } #[cfg(not(target_os = "macos"))] -fn default_shell_command(shell: &str, _user: &str) -> Command { +fn default_shell_command(shell: &str, _user: &str, _home: &str) -> Command { Command::new(shell) } #[cfg(target_os = "macos")] -fn default_shell_command(shell: &str, user: &str) -> Command { +fn default_shell_command(shell: &str, user: &str, home: &str) -> Command { let shell_name = shell.rsplit('/').next().unwrap(); // On macOS, use the `login` command so the shell will appear as a tty session. @@ -173,12 +175,20 @@ fn default_shell_command(shell: &str, user: &str) -> Command { // `login` normally does this itself, but `-l` disables this. let exec = format!("exec -a -{} {}", shell_name, shell); + // Since we use -l, `login` will not change directory to the user's home. However, + // `login` only checks the current working directory for a .hushlogin file, causing + // it to miss any in the user's home directory. We can fix this by doing the check + // ourselves and passing `-q` + let has_home_hushlogin = Path::new(home).join(".hushlogin").exists(); + // -f: Bypasses authentication for the already-logged-in user. // -l: Skips changing directory to $HOME and prepending '-' to argv[0]. // -p: Preserves the environment. + // -q: Act as if `.hushlogin` exists. // // XXX: we use zsh here over sh due to `exec -a`. - login_command.args(["-flp", user, "/bin/zsh", "-fc", &exec]); + let flags = if has_home_hushlogin { "-qflp" } else { "-flp" }; + login_command.args([flags, user, "/bin/zsh", "-fc", &exec]); login_command } @@ -208,7 +218,7 @@ pub fn from_fd(config: &Options, window_id: u64, master: OwnedFd, slave: OwnedFd cmd.args(shell.args.as_slice()); cmd } else { - default_shell_command(&user.shell, &user.user) + default_shell_command(&user.shell, &user.user, &user.home) }; // Setup child stdin/stdout/stderr as slave fd of PTY. @@ -231,6 +241,7 @@ pub fn from_fd(config: &Options, window_id: u64, master: OwnedFd, slave: OwnedFd builder.env_remove("XDG_ACTIVATION_TOKEN"); builder.env_remove("DESKTOP_STARTUP_ID"); + let working_directory = config.working_directory.clone(); unsafe { builder.pre_exec(move || { // Create a new process group. @@ -239,6 +250,11 @@ pub fn from_fd(config: &Options, window_id: u64, master: OwnedFd, slave: OwnedFd return Err(Error::new(ErrorKind::Other, "Failed to set session id")); } + // Set working directory, ignoring invalid paths. + if let Some(working_directory) = working_directory.as_ref() { + let _ = env::set_current_dir(working_directory); + } + set_controlling_terminal(slave_fd); // No longer need slave/master fds. @@ -256,11 +272,6 @@ pub fn from_fd(config: &Options, window_id: u64, master: OwnedFd, slave: OwnedFd }); } - // Handle set working directory option. - if let Some(dir) = &config.working_directory { - builder.current_dir(dir); - } - // Prepare signal handling before spawning child. let (signals, sig_id) = { let (sender, recv) = UnixStream::pair()?; diff --git a/alacritty_terminal/tests/ref.rs b/alacritty_terminal/tests/ref.rs index 1f992941..454f2e5d 100644 --- a/alacritty_terminal/tests/ref.rs +++ b/alacritty_terminal/tests/ref.rs @@ -112,9 +112,7 @@ fn ref_test(dir: &Path) { let mut terminal = Term::new(options, &size, Mock); let mut parser: ansi::Processor = ansi::Processor::new(); - for byte in recording { - parser.advance(&mut terminal, byte); - } + parser.advance(&mut terminal, &recording); // Truncate invisible lines from the grid. let mut term_grid = terminal.grid().clone(); diff --git a/extra/man/alacritty.5.scd b/extra/man/alacritty.5.scd index 18172487..e2f5b252 100644 --- a/extra/man/alacritty.5.scd +++ b/extra/man/alacritty.5.scd @@ -740,7 +740,8 @@ post_processing = _true_++ persist = _false_++ mouse.enabled = _true_++ binding = { key = _"O"_, mods = _"Control|Shift"_ }++ -regex = _"(ipfs:|ipns:|magnet:|mailto:|gemini://|gopher://|https://|http://|news:|file:|git://|ssh:|ftp://)[^\\u0000-\\u001F\\u007F-\\u009F<>\\"\\\\s{-}\\\\^⟨⟩`]+"_ +regex = +_"(ipfs:|ipns:|magnet:|mailto:|gemini://|gopher://|https://|http://|news:|file:|git://|ssh:|ftp://)[^\\u0000-\\u001F\\u007F-\\u009F<>\\"\\\\s{-}\\\\^⟨⟩`\\\\\\\\]+"_ # KEYBOARD diff --git a/extra/osx/Alacritty.app/Contents/Info.plist b/extra/osx/Alacritty.app/Contents/Info.plist index 59c70ff2..ca8d2d7b 100644 --- a/extra/osx/Alacritty.app/Contents/Info.plist +++ b/extra/osx/Alacritty.app/Contents/Info.plist @@ -15,7 +15,7 @@ <key>CFBundlePackageType</key> <string>APPL</string> <key>CFBundleShortVersionString</key> - <string>0.15.0-dev</string> + <string>0.16.0-dev</string> <key>CFBundleSupportedPlatforms</key> <array> <string>MacOSX</string> |