aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGNUqb114514 <GNUqb114514@outlook.com>2024-12-27 21:18:49 +0800
committerGNUqb114514 <GNUqb114514@outlook.com>2024-12-27 21:18:49 +0800
commitd8b533d96f54f274e5d3c1b542f940309a579cde (patch)
tree7c48ff8cb851b522a6c6224f2749d6f7c64d1867
parent984f4382e9f51ff4290e168bb49aaff4fb4d1b64 (diff)
parent9e9e43d209f19e368153e79c898c09ced9671971 (diff)
downloadr-alacritty-d8b533d96f54f274e5d3c1b542f940309a579cde.tar.gz
r-alacritty-d8b533d96f54f274e5d3c1b542f940309a579cde.tar.bz2
r-alacritty-d8b533d96f54f274e5d3c1b542f940309a579cde.zip
Merge remote-tracking branch 'upstream/graphics' into graphics
-rw-r--r--CHANGELOG.md21
-rw-r--r--Cargo.lock31
-rw-r--r--INSTALL.md2
-rw-r--r--alacritty/Cargo.toml25
-rw-r--r--alacritty/src/config/bindings.rs11
-rw-r--r--alacritty/src/config/font.rs2
-rw-r--r--alacritty/src/config/ui_config.rs8
-rw-r--r--alacritty/src/config/window.rs22
-rw-r--r--alacritty/src/display/color.rs6
-rw-r--r--alacritty/src/display/content.rs6
-rw-r--r--alacritty/src/display/damage.rs8
-rw-r--r--alacritty/src/display/hint.rs52
-rw-r--r--alacritty/src/display/meter.rs2
-rw-r--r--alacritty/src/display/mod.rs42
-rw-r--r--alacritty/src/display/window.rs39
-rw-r--r--alacritty/src/event.rs48
-rw-r--r--alacritty/src/input/keyboard.rs15
-rw-r--r--alacritty/src/input/mod.rs2
-rw-r--r--alacritty/src/macos/locale.rs56
-rw-r--r--alacritty/src/migrate/mod.rs12
-rw-r--r--alacritty/src/renderer/graphics/shader.rs4
-rw-r--r--alacritty/src/renderer/rects.rs4
-rw-r--r--alacritty/src/renderer/text/gles2.rs10
-rw-r--r--alacritty/src/renderer/text/glsl3.rs10
-rw-r--r--alacritty/src/renderer/text/mod.rs2
-rw-r--r--alacritty/src/string.rs2
-rw-r--r--alacritty/windows/wix/alacritty.wxs2
-rw-r--r--alacritty_config/Cargo.toml4
-rw-r--r--alacritty_config_derive/Cargo.toml4
-rw-r--r--alacritty_terminal/CHANGELOG.md2
-rw-r--r--alacritty_terminal/Cargo.toml4
-rw-r--r--alacritty_terminal/src/graphics/mod.rs2
-rw-r--r--alacritty_terminal/src/grid/mod.rs2
-rw-r--r--alacritty_terminal/src/term/mod.rs7
-rw-r--r--alacritty_terminal/src/term/search.rs2
-rw-r--r--alacritty_terminal/src/tty/windows/child.rs13
-rw-r--r--alacritty_terminal/src/tty/windows/conpty.rs2
-rw-r--r--alacritty_terminal/src/vi_mode.rs49
-rw-r--r--extra/completions/_alacritty36
-rw-r--r--extra/man/alacritty.5.scd15
-rw-r--r--extra/osx/Alacritty.app/Contents/Info.plist2
41 files changed, 375 insertions, 213 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 2b3d2b46..94672511 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -8,6 +8,25 @@ 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
+
+### Added
+
+- Config option `window.level = "AlwaysOnTop"` to force Alacritty to always be the toplevel window
+
+### Changed
+
+- Always focus new windows on macOS
+
+### Fixed
+
+- Mouse/Vi cursor hint highlighting broken on the terminal cursor line
+- Hint launcher opening arbitrary text, when terminal content changed while opening
+- `SemanticRight`/`SemanticLeft` vi motions breaking with wide semantic escape characters
+- `alacritty migrate` crashing with recursive toml imports
+- Migrating nonexistent toml import breaking the entire migration
+- First daemon mode window ignoring window options passed through CLI
+
## 0.14.0
### Packaging
@@ -30,6 +49,7 @@ 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
@@ -51,6 +71,7 @@ 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
diff --git a/Cargo.lock b/Cargo.lock
index 6f5be73c..dbefd974 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -32,7 +32,7 @@ dependencies = [
[[package]]
name = "alacritty"
-version = "0.14.0"
+version = "0.15.0-dev"
dependencies = [
"ahash",
"alacritty_config",
@@ -41,7 +41,6 @@ dependencies = [
"bitflags 2.6.0",
"clap",
"clap_complete",
- "cocoa",
"copypasta",
"crossfont",
"dirs",
@@ -53,7 +52,9 @@ dependencies = [
"log",
"memoffset",
"notify",
- "objc",
+ "objc2",
+ "objc2-app-kit",
+ "objc2-foundation",
"parking_lot",
"png",
"serde",
@@ -71,7 +72,7 @@ dependencies = [
[[package]]
name = "alacritty_config"
-version = "0.2.2"
+version = "0.2.3-dev"
dependencies = [
"alacritty_config_derive",
"log",
@@ -81,7 +82,7 @@ dependencies = [
[[package]]
name = "alacritty_config_derive"
-version = "0.2.4"
+version = "0.2.5-dev"
dependencies = [
"alacritty_config",
"log",
@@ -94,7 +95,7 @@ dependencies = [
[[package]]
name = "alacritty_terminal"
-version = "0.24.1"
+version = "0.24.2-dev"
dependencies = [
"base64",
"bitflags 2.6.0",
@@ -113,7 +114,7 @@ dependencies = [
"smallvec",
"unicode-width",
"vte-graphics",
- "windows-sys 0.52.0",
+ "windows-sys 0.59.0",
]
[[package]]
@@ -304,9 +305,9 @@ dependencies = [
[[package]]
name = "cc"
-version = "1.2.5"
+version = "1.2.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c31a0499c1dc64f458ad13872de75c0eb7e3fdb0e67964610c914b034fc5956e"
+checksum = "8d6dbb628b8f8555f86d0323c2eb39e3ec81901f4b83e091db8a6a76d316a333"
dependencies = [
"jobserver",
"libc",
@@ -1584,9 +1585,9 @@ dependencies = [
[[package]]
name = "quote"
-version = "1.0.37"
+version = "1.0.38"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b5b9d34b8991d19d98081b46eacdd8eb58c6f2b201139f7c5f643cc155a633af"
+checksum = "0e4dccaaaf89514f546c693ddc140f729f958c247918a13380cccc6078391acc"
dependencies = [
"proc-macro2",
]
@@ -1884,9 +1885,9 @@ checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f"
[[package]]
name = "syn"
-version = "2.0.91"
+version = "2.0.92"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d53cbcb5a243bd33b7858b1d7f4aca2153490815872d86d955d6ea29f743c035"
+checksum = "70ae51629bf965c5c098cc9e87908a3df5301051a9e087d6f9bef5c9771ed126"
dependencies = [
"proc-macro2",
"quote",
@@ -2540,9 +2541,9 @@ checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec"
[[package]]
name = "winit"
-version = "0.30.6"
+version = "0.30.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7c3d72dfa0f47e429290cd0d236884ca02f22dbd5dd33a43ad2b8bf4d79b6c18"
+checksum = "dba50bc8ef4b6f1a75c9274fb95aa9a8f63fbc66c56f391bd85cf68d51e7b1a3"
dependencies = [
"ahash",
"android-activity",
diff --git a/INSTALL.md b/INSTALL.md
index b5f6871c..6974e1ee 100644
--- a/INSTALL.md
+++ b/INSTALL.md
@@ -84,7 +84,7 @@ to build Alacritty. Here's an apt command that should install all of them. If
something is still found to be missing, please open an issue.
```sh
-apt install cmake pkg-config libfreetype6-dev libfontconfig1-dev libxcb-xfixes0-dev libxkbcommon-dev python3
+apt install cmake g++ pkg-config libfreetype6-dev libfontconfig1-dev libxcb-xfixes0-dev libxkbcommon-dev python3
```
#### Arch Linux
diff --git a/alacritty/Cargo.toml b/alacritty/Cargo.toml
index 453ac70c..f144e578 100644
--- a/alacritty/Cargo.toml
+++ b/alacritty/Cargo.toml
@@ -1,6 +1,6 @@
[package]
name = "alacritty"
-version = "0.14.0"
+version = "0.15.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,15 +12,15 @@ rust-version = "1.74.0"
[dependencies.alacritty_terminal]
path = "../alacritty_terminal"
-version = "0.24.1"
+version = "0.24.2-dev"
[dependencies.alacritty_config_derive]
path = "../alacritty_config_derive"
-version = "0.2.4"
+version = "0.2.5-dev"
[dependencies.alacritty_config]
path = "../alacritty_config"
-version = "0.2.2"
+version = "0.2.3-dev"
[dependencies]
ahash = { version = "0.8.6", features = ["no-rng"] }
@@ -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.4", default-features = false, features = ["rwh_06", "serde"] }
+winit = { version = "0.30.7", default-features = false, features = ["rwh_06", "serde"] }
[build-dependencies]
gl_generator = "0.14.0"
@@ -58,8 +58,19 @@ xdg = "2.5.0"
png = { version = "0.17.5", default-features = false, optional = true }
[target.'cfg(target_os = "macos")'.dependencies]
-cocoa = "0.25.0"
-objc = "0.2.2"
+objc2 = "0.5.2"
+objc2-foundation = { version = "0.2.2", default-features = false, features = [
+ "std",
+ "NSString",
+ "NSLocale",
+] }
+objc2-app-kit = { version = "0.2.2", default-features = false, features = [
+ "std",
+ "NSColorSpace",
+ "NSResponder",
+ "NSView",
+ "NSWindow",
+] }
[target.'cfg(windows)'.dependencies]
dirs = "5.0.1"
diff --git a/alacritty/src/config/bindings.rs b/alacritty/src/config/bindings.rs
index dfe31853..931b0583 100644
--- a/alacritty/src/config/bindings.rs
+++ b/alacritty/src/config/bindings.rs
@@ -5,6 +5,7 @@ use std::fmt::{self, Debug, Display};
use bitflags::bitflags;
use serde::de::{self, Error as SerdeError, MapAccess, Unexpected, Visitor};
use serde::{Deserialize, Deserializer};
+use std::rc::Rc;
use toml::Value as SerdeValue;
use winit::event::MouseButton;
use winit::keyboard::{
@@ -96,7 +97,7 @@ pub enum Action {
/// Regex keyboard hints.
#[config(skip)]
- Hint(Hint),
+ Hint(Rc<Hint>),
/// Move vi mode cursor.
#[config(skip)]
@@ -790,7 +791,7 @@ impl<'a> Deserialize<'a> for ModeWrapper {
{
struct ModeVisitor;
- impl<'a> Visitor<'a> for ModeVisitor {
+ impl Visitor<'_> for ModeVisitor {
type Value = ModeWrapper;
fn expecting(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
@@ -844,7 +845,7 @@ impl<'a> Deserialize<'a> for MouseButtonWrapper {
{
struct MouseButtonVisitor;
- impl<'a> Visitor<'a> for MouseButtonVisitor {
+ impl Visitor<'_> for MouseButtonVisitor {
type Value = MouseButtonWrapper;
fn expecting(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
@@ -956,7 +957,7 @@ impl<'a> Deserialize<'a> for RawBinding {
{
struct FieldVisitor;
- impl<'a> Visitor<'a> for FieldVisitor {
+ impl Visitor<'_> for FieldVisitor {
type Value = Field;
fn expecting(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
@@ -1204,7 +1205,7 @@ impl<'a> de::Deserialize<'a> for ModsWrapper {
{
struct ModsVisitor;
- impl<'a> Visitor<'a> for ModsVisitor {
+ impl Visitor<'_> for ModsVisitor {
type Value = ModsWrapper;
fn expecting(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
diff --git a/alacritty/src/config/font.rs b/alacritty/src/config/font.rs
index 061c0f42..760c26d5 100644
--- a/alacritty/src/config/font.rs
+++ b/alacritty/src/config/font.rs
@@ -144,7 +144,7 @@ impl<'de> Deserialize<'de> for Size {
D: Deserializer<'de>,
{
struct NumVisitor;
- impl<'v> Visitor<'v> for NumVisitor {
+ impl Visitor<'_> for NumVisitor {
type Value = Size;
fn expecting(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
diff --git a/alacritty/src/config/ui_config.rs b/alacritty/src/config/ui_config.rs
index 69716dee..b44bda0d 100644
--- a/alacritty/src/config/ui_config.rs
+++ b/alacritty/src/config/ui_config.rs
@@ -253,7 +253,7 @@ pub struct Hints {
alphabet: HintsAlphabet,
/// All configured terminal hints.
- pub enabled: Vec<Hint>,
+ pub enabled: Vec<Rc<Hint>>,
}
impl Default for Hints {
@@ -274,7 +274,7 @@ impl Default for Hints {
});
Self {
- enabled: vec![Hint {
+ enabled: vec![Rc::new(Hint {
content,
action,
persist: false,
@@ -288,7 +288,7 @@ impl Default for Hints {
mods: ModsWrapper(ModifiersState::SHIFT | ModifiersState::CONTROL),
mode: Default::default(),
}),
- }],
+ })],
alphabet: Default::default(),
}
}
@@ -619,7 +619,7 @@ impl SerdeReplace for Program {
}
pub(crate) struct StringVisitor;
-impl<'de> serde::de::Visitor<'de> for StringVisitor {
+impl serde::de::Visitor<'_> for StringVisitor {
type Value = String;
fn expecting(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
diff --git a/alacritty/src/config/window.rs b/alacritty/src/config/window.rs
index 380f7a6f..358bb76d 100644
--- a/alacritty/src/config/window.rs
+++ b/alacritty/src/config/window.rs
@@ -6,7 +6,7 @@ use serde::{Deserialize, Deserializer, Serialize};
#[cfg(target_os = "macos")]
use winit::platform::macos::OptionAsAlt as WinitOptionAsAlt;
-use winit::window::{Fullscreen, Theme as WinitTheme};
+use winit::window::{Fullscreen, Theme as WinitTheme, WindowLevel as WinitWindowLevel};
use alacritty_config_derive::{ConfigDeserialize, SerdeReplace};
@@ -61,6 +61,9 @@ pub struct WindowConfig {
/// System decorations theme variant.
decorations_theme_variant: Option<Theme>,
+
+ /// Window level.
+ pub level: WindowLevel,
}
impl Default for WindowConfig {
@@ -80,6 +83,7 @@ impl Default for WindowConfig {
resize_increments: Default::default(),
decorations_theme_variant: Default::default(),
option_as_alt: Default::default(),
+ level: Default::default(),
}
}
}
@@ -306,3 +310,19 @@ impl From<Theme> for WinitTheme {
}
}
}
+
+#[derive(ConfigDeserialize, Default, Debug, Clone, Copy, PartialEq, Eq)]
+pub enum WindowLevel {
+ #[default]
+ Normal,
+ AlwaysOnTop,
+}
+
+impl From<WindowLevel> for WinitWindowLevel {
+ fn from(level: WindowLevel) -> Self {
+ match level {
+ WindowLevel::Normal => WinitWindowLevel::Normal,
+ WindowLevel::AlwaysOnTop => WinitWindowLevel::AlwaysOnTop,
+ }
+ }
+}
diff --git a/alacritty/src/display/color.rs b/alacritty/src/display/color.rs
index 669bf502..2e854a3f 100644
--- a/alacritty/src/display/color.rs
+++ b/alacritty/src/display/color.rs
@@ -18,7 +18,7 @@ pub const DIM_FACTOR: f32 = 0.66;
#[derive(Copy, Clone)]
pub struct List([Rgb; COUNT]);
-impl<'a> From<&'a Colors> for List {
+impl From<&'_ Colors> for List {
fn from(colors: &Colors) -> List {
// Type inference fails without this annotation.
let mut list = List([Rgb::default(); COUNT]);
@@ -235,7 +235,7 @@ impl<'de> Deserialize<'de> for Rgb {
b: u8,
}
- impl<'a> Visitor<'a> for RgbVisitor {
+ impl Visitor<'_> for RgbVisitor {
type Value = Rgb;
fn expecting(&self, f: &mut Formatter<'_>) -> fmt::Result {
@@ -331,7 +331,7 @@ impl<'de> Deserialize<'de> for CellRgb {
const EXPECTING: &str = "CellForeground, CellBackground, or hex color like #ff00ff";
struct CellRgbVisitor;
- impl<'a> Visitor<'a> for CellRgbVisitor {
+ impl Visitor<'_> for CellRgbVisitor {
type Value = CellRgb;
fn expecting(&self, f: &mut Formatter<'_>) -> fmt::Result {
diff --git a/alacritty/src/display/content.rs b/alacritty/src/display/content.rs
index 02ac50e3..9a7de3fe 100644
--- a/alacritty/src/display/content.rs
+++ b/alacritty/src/display/content.rs
@@ -153,7 +153,7 @@ impl<'a> RenderableContent<'a> {
}
}
-impl<'a> Iterator for RenderableContent<'a> {
+impl Iterator for RenderableContent<'_> {
type Item = RenderableCell;
/// Gets the next renderable cell.
@@ -482,7 +482,7 @@ struct Hint<'a> {
labels: &'a Vec<Vec<char>>,
}
-impl<'a> Hint<'a> {
+impl Hint<'_> {
/// Advance the hint iterator.
///
/// If the point is within a hint, the keyboard shortcut character that should be displayed at
@@ -572,7 +572,7 @@ impl<'a> HintMatches<'a> {
}
}
-impl<'a> Deref for HintMatches<'a> {
+impl Deref for HintMatches<'_> {
type Target = [Match];
fn deref(&self) -> &Self::Target {
diff --git a/alacritty/src/display/damage.rs b/alacritty/src/display/damage.rs
index 8efe0133..b0736375 100644
--- a/alacritty/src/display/damage.rs
+++ b/alacritty/src/display/damage.rs
@@ -193,9 +193,11 @@ impl FrameDamage {
/// Check if a range is damaged.
#[inline]
pub fn intersects(&self, start: Point<usize>, end: Point<usize>) -> bool {
+ let start_line = &self.lines[start.line];
+ let end_line = &self.lines[end.line];
self.full
- || self.lines[start.line].left <= start.column
- || self.lines[end.line].right >= end.column
+ || (start_line.left..=start_line.right).contains(&start.column)
+ || (end_line.left..=end_line.right).contains(&end.column)
|| (start.line + 1..end.line).any(|line| self.lines[line].is_damaged())
}
}
@@ -249,7 +251,7 @@ impl<'a> RenderDamageIterator<'a> {
}
}
-impl<'a> Iterator for RenderDamageIterator<'a> {
+impl Iterator for RenderDamageIterator<'_> {
type Item = Rect;
fn next(&mut self) -> Option<Rect> {
diff --git a/alacritty/src/display/hint.rs b/alacritty/src/display/hint.rs
index a01a1d03..3f10b4e5 100644
--- a/alacritty/src/display/hint.rs
+++ b/alacritty/src/display/hint.rs
@@ -1,6 +1,8 @@
+use std::borrow::Cow;
use std::cmp::Reverse;
use std::collections::HashSet;
use std::iter;
+use std::rc::Rc;
use ahash::RandomState;
use winit::keyboard::ModifiersState;
@@ -23,7 +25,7 @@ const HINT_SPLIT_PERCENTAGE: f32 = 0.5;
/// Keyboard regex hint state.
pub struct HintState {
/// Hint currently in use.
- hint: Option<Hint>,
+ hint: Option<Rc<Hint>>,
/// Alphabet for hint labels.
alphabet: String,
@@ -56,7 +58,7 @@ impl HintState {
}
/// Start the hint selection process.
- pub fn start(&mut self, hint: Hint) {
+ pub fn start(&mut self, hint: Rc<Hint>) {
self.hint = Some(hint);
}
@@ -150,7 +152,7 @@ impl HintState {
// Check if the selected label is fully matched.
if label.len() == 1 {
let bounds = self.matches[index].clone();
- let action = hint.action.clone();
+ let hint = hint.clone();
// Exit hint mode unless it requires explicit dismissal.
if hint.persist {
@@ -161,7 +163,7 @@ impl HintState {
// Hyperlinks take precedence over regex matches.
let hyperlink = term.grid()[*bounds.start()].hyperlink();
- Some(HintMatch { action, bounds, hyperlink })
+ Some(HintMatch { bounds, hyperlink, hint })
} else {
// Store character to preserve the selection.
self.keys.push(c);
@@ -192,13 +194,14 @@ impl HintState {
/// Hint match which was selected by the user.
#[derive(PartialEq, Eq, Debug, Clone)]
pub struct HintMatch {
- /// Action for handling the text.
- action: HintAction,
-
/// Terminal range matching the hint.
bounds: Match,
+ /// OSC 8 hyperlink.
hyperlink: Option<Hyperlink>,
+
+ /// Hint which triggered this match.
+ hint: Rc<Hint>,
}
impl HintMatch {
@@ -210,7 +213,7 @@ impl HintMatch {
#[inline]
pub fn action(&self) -> &HintAction {
- &self.action
+ &self.hint.action
}
#[inline]
@@ -221,6 +224,29 @@ impl HintMatch {
pub fn hyperlink(&self) -> Option<&Hyperlink> {
self.hyperlink.as_ref()
}
+
+ /// Get the text content of the hint match.
+ ///
+ /// This will always revalidate the hint text, to account for terminal content
+ /// changes since the [`HintMatch`] was constructed. The text of the hint might
+ /// be different from its original value, but it will **always** be a valid
+ /// match for this hint.
+ pub fn text<T>(&self, term: &Term<T>) -> Option<Cow<'_, str>> {
+ // Revalidate hyperlink match.
+ if let Some(hyperlink) = &self.hyperlink {
+ let (validated, bounds) = hyperlink_at(term, *self.bounds.start())?;
+ return (&validated == hyperlink && bounds == self.bounds)
+ .then(|| hyperlink.uri().into());
+ }
+
+ // Revalidate regex match.
+ let regex = self.hint.content.regex.as_ref()?;
+ let bounds = regex.with_compiled(|regex| {
+ regex_match_at(term, *self.bounds.start(), regex, self.hint.post_processing)
+ })??;
+ (bounds == self.bounds)
+ .then(|| term.bounds_to_string(*bounds.start(), *bounds.end()).into())
+ }
}
/// Generator for creating new hint labels.
@@ -382,18 +408,14 @@ pub fn highlighted_at<T>(
if let Some((hyperlink, bounds)) =
hint.content.hyperlinks.then(|| hyperlink_at(term, point)).flatten()
{
- return Some(HintMatch {
- bounds,
- action: hint.action.clone(),
- hyperlink: Some(hyperlink),
- });
+ return Some(HintMatch { bounds, hyperlink: Some(hyperlink), hint: hint.clone() });
}
let bounds = hint.content.regex.as_ref().and_then(|regex| {
regex.with_compiled(|regex| regex_match_at(term, point, regex, hint.post_processing))
});
if let Some(bounds) = bounds.flatten() {
- return Some(HintMatch { bounds, action: hint.action.clone(), hyperlink: None });
+ return Some(HintMatch { bounds, hint: hint.clone(), hyperlink: None });
}
None
@@ -554,7 +576,7 @@ impl<'a, T> HintPostProcessor<'a, T> {
}
}
-impl<'a, T> Iterator for HintPostProcessor<'a, T> {
+impl<T> Iterator for HintPostProcessor<'_, T> {
type Item = Match;
fn next(&mut self) -> Option<Self::Item> {
diff --git a/alacritty/src/display/meter.rs b/alacritty/src/display/meter.rs
index e263100f..20cbbd1b 100644
--- a/alacritty/src/display/meter.rs
+++ b/alacritty/src/display/meter.rs
@@ -57,7 +57,7 @@ impl<'a> Sampler<'a> {
}
}
-impl<'a> Drop for Sampler<'a> {
+impl Drop for Sampler<'_> {
fn drop(&mut self) {
self.meter.add_sample(self.alive_duration());
}
diff --git a/alacritty/src/display/mod.rs b/alacritty/src/display/mod.rs
index 17ab461c..a679fe21 100644
--- a/alacritty/src/display/mod.rs
+++ b/alacritty/src/display/mod.rs
@@ -297,12 +297,12 @@ impl TermDimensions for SizeInfo {
#[inline]
fn cell_height(&self) -> f32 {
- self.cell_height()
+ self.cell_height
}
#[inline]
fn cell_width(&self) -> f32 {
- self.cell_width()
+ self.cell_width
}
}
@@ -352,9 +352,13 @@ pub struct Display {
/// Hint highlighted by the mouse.
pub highlighted_hint: Option<HintMatch>,
+ /// Frames since hint highlight was created.
+ highlighted_hint_age: usize,
/// Hint highlighted by the vi mode cursor.
pub vi_highlighted_hint: Option<HintMatch>,
+ /// Frames since hint highlight was created.
+ vi_highlighted_hint_age: usize,
pub raw_window_handle: RawWindowHandle,
@@ -490,6 +494,10 @@ impl Display {
window.set_visible(true);
+ // Always focus new windows, even if no Alacritty window is currently focused.
+ #[cfg(target_os = "macos")]
+ window.focus_window();
+
#[allow(clippy::single_match)]
#[cfg(not(windows))]
if !_tabbed {
@@ -526,6 +534,8 @@ impl Display {
font_size,
window,
pending_renderer_update: Default::default(),
+ vi_highlighted_hint_age: Default::default(),
+ highlighted_hint_age: Default::default(),
vi_highlighted_hint: Default::default(),
highlighted_hint: Default::default(),
hint_mouse_point: Default::default(),
@@ -771,7 +781,7 @@ impl Display {
drop(terminal);
// Invalidate highlighted hints if grid has changed.
- self.validate_hints(display_offset);
+ self.validate_hint_highlights(display_offset);
// Add damage from alacritty's UI elements overlapping terminal.
@@ -1042,9 +1052,10 @@ impl Display {
};
let mut dirty = vi_highlighted_hint != self.vi_highlighted_hint;
self.vi_highlighted_hint = vi_highlighted_hint;
+ self.vi_highlighted_hint_age = 0;
// Force full redraw if the vi mode highlight was cleared.
- if dirty && self.vi_highlighted_hint.is_none() {
+ if dirty {
self.damage_tracker.frame().mark_fully_damaged();
}
@@ -1080,9 +1091,10 @@ impl Display {
let mouse_highlight_dirty = self.highlighted_hint != highlighted_hint;
dirty |= mouse_highlight_dirty;
self.highlighted_hint = highlighted_hint;
+ self.highlighted_hint_age = 0;
- // Force full redraw if the mouse cursor highlight was cleared.
- if mouse_highlight_dirty && self.highlighted_hint.is_none() {
+ // Force full redraw if the mouse cursor highlight was changed.
+ if mouse_highlight_dirty {
self.damage_tracker.frame().mark_fully_damaged();
}
@@ -1356,16 +1368,24 @@ impl Display {
}
/// Check whether a hint highlight needs to be cleared.
- fn validate_hints(&mut self, display_offset: usize) {
+ fn validate_hint_highlights(&mut self, display_offset: usize) {
let frame = self.damage_tracker.frame();
- for (hint, reset_mouse) in
- [(&mut self.highlighted_hint, true), (&mut self.vi_highlighted_hint, false)]
- {
+ let hints = [
+ (&mut self.highlighted_hint, &mut self.highlighted_hint_age, true),
+ (&mut self.vi_highlighted_hint, &mut self.vi_highlighted_hint_age, false),
+ ];
+ for (hint, hint_age, reset_mouse) in hints {
let (start, end) = match hint {
Some(hint) => (*hint.bounds().start(), *hint.bounds().end()),
- None => return,
+ None => continue,
};
+ // Ignore hints that were created this frame.
+ *hint_age += 1;
+ if *hint_age == 1 {
+ continue;
+ }
+
// 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(|| {
diff --git a/alacritty/src/display/window.rs b/alacritty/src/display/window.rs
index 1427dc75..1c8089bc 100644
--- a/alacritty/src/display/window.rs
+++ b/alacritty/src/display/window.rs
@@ -20,9 +20,8 @@ use std::fmt::{self, Display, Formatter};
#[cfg(target_os = "macos")]
use {
- cocoa::appkit::NSColorSpace,
- cocoa::base::{id, nil, NO, YES},
- objc::{msg_send, sel, sel_impl},
+ objc2_app_kit::{NSColorSpace, NSView},
+ objc2_foundation::is_main_thread,
winit::platform::macos::{OptionAsAlt, WindowAttributesExtMacOS, WindowExtMacOS},
};
@@ -45,7 +44,7 @@ use crate::display::SizeInfo;
/// Window icon for `_NET_WM_ICON` property.
#[cfg(all(feature = "x11", not(any(target_os = "macos", windows))))]
-static WINDOW_ICON: &[u8] = include_bytes!("../../extra/logo/compat/alacritty-term.png");
+const WINDOW_ICON: &[u8] = include_bytes!("../../extra/logo/compat/alacritty-term.png");
/// This should match the definition of IDI_ICON from `alacritty.rc`.
#[cfg(windows)]
@@ -170,7 +169,8 @@ impl Window {
.with_transparent(true)
.with_blur(config.window.blur)
.with_maximized(config.window.maximized())
- .with_fullscreen(config.window.fullscreen());
+ .with_fullscreen(config.window.fullscreen())
+ .with_window_level(config.window.level.into());
let window = event_loop.create_window(window_attributes)?;
@@ -224,6 +224,12 @@ impl Window {
self.window.set_visible(visibility);
}
+ #[cfg(target_os = "macos")]
+ #[inline]
+ pub fn focus_window(&self) {
+ self.window.focus_window();
+ }
+
/// Set the window title.
#[inline]
pub fn set_title(&mut self, title: String) {
@@ -445,16 +451,15 @@ impl Window {
/// This prevents rendering artifacts from showing up when the window is transparent.
#[cfg(target_os = "macos")]
pub fn set_has_shadow(&self, has_shadows: bool) {
- let ns_view = match self.raw_window_handle() {
- RawWindowHandle::AppKit(handle) => handle.ns_view.as_ptr() as id,
+ let view = match self.raw_window_handle() {
+ RawWindowHandle::AppKit(handle) => {
+ assert!(is_main_thread());
+ unsafe { handle.ns_view.cast::<NSView>().as_ref() }
+ },
_ => return,
};
- let value = if has_shadows { YES } else { NO };
- unsafe {
- let ns_window: id = msg_send![ns_view, window];
- let _: id = msg_send![ns_window, setHasShadow: value];
- }
+ view.window().unwrap().setHasShadow(has_shadows);
}
/// Select tab at the given `index`.
@@ -489,13 +494,15 @@ impl Window {
#[cfg(target_os = "macos")]
fn use_srgb_color_space(window: &WinitWindow) {
- let ns_view = match window.window_handle().unwrap().as_raw() {
- RawWindowHandle::AppKit(handle) => handle.ns_view.as_ptr() as id,
+ let view = match window.window_handle().unwrap().as_raw() {
+ RawWindowHandle::AppKit(handle) => {
+ assert!(is_main_thread());
+ unsafe { handle.ns_view.cast::<NSView>().as_ref() }
+ },
_ => return,
};
unsafe {
- let ns_window: id = msg_send![ns_view, window];
- let _: () = msg_send![ns_window, setColorSpace: NSColorSpace::sRGBColorSpace(nil)];
+ view.window().unwrap().setColorSpace(Some(&NSColorSpace::sRGBColorSpace()));
}
}
diff --git a/alacritty/src/event.rs b/alacritty/src/event.rs
index f0159060..79f31eef 100644
--- a/alacritty/src/event.rs
+++ b/alacritty/src/event.rs
@@ -140,14 +140,14 @@ impl Processor {
pub fn create_initial_window(
&mut self,
event_loop: &ActiveEventLoop,
+ window_options: WindowOptions,
) -> Result<(), Box<dyn Error>> {
- let options = match self.initial_window_options.take() {
- Some(options) => options,
- None => return Ok(()),
- };
-
- let window_context =
- WindowContext::initial(event_loop, self.proxy.clone(), self.config.clone(), options)?;
+ let window_context = WindowContext::initial(
+ event_loop,
+ self.proxy.clone(),
+ self.config.clone(),
+ window_options,
+ )?;
self.gl_config = Some(window_context.display.gl_context().config());
self.windows.insert(window_context.id(), window_context);
@@ -225,10 +225,12 @@ impl ApplicationHandler<Event> for Processor {
return;
}
- if let Err(err) = self.create_initial_window(event_loop) {
- self.initial_window_error = Some(err);
- event_loop.exit();
- return;
+ if let Some(window_options) = self.initial_window_options.take() {
+ if let Err(err) = self.create_initial_window(event_loop, window_options) {
+ self.initial_window_error = Some(err);
+ event_loop.exit();
+ return;
+ }
}
info!("Initialisation complete");
@@ -276,7 +278,7 @@ impl ApplicationHandler<Event> for Processor {
}
// Handle events which don't mandate the WindowId.
- match (&event.payload, event.window_id.as_ref()) {
+ match (event.payload, event.window_id.as_ref()) {
// Process IPC config update.
#[cfg(unix)]
(EventType::IpcConfig(ipc_config), window_id) => {
@@ -315,7 +317,7 @@ impl ApplicationHandler<Event> for Processor {
}
// Load config and update each terminal.
- if let Ok(config) = config::reload(path, &mut self.cli_options) {
+ if let Ok(config) = config::reload(&path, &mut self.cli_options) {
self.config = Rc::new(config);
// Restart config monitor if imports changed.
@@ -346,17 +348,17 @@ impl ApplicationHandler<Event> for Processor {
if self.gl_config.is_none() {
// Handle initial window creation in daemon mode.
- if let Err(err) = self.create_initial_window(event_loop) {
+ if let Err(err) = self.create_initial_window(event_loop, options) {
self.initial_window_error = Some(err);
event_loop.exit();
}
- } else if let Err(err) = self.create_window(event_loop, options.clone()) {
+ } else if let Err(err) = self.create_window(event_loop, options) {
error!("Could not open window: {:?}", err);
}
},
// Process events affecting all windows.
- (_, None) => {
- let event = WinitEvent::UserEvent(event);
+ (payload, None) => {
+ let event = WinitEvent::UserEvent(Event::new(payload, None));
for window_context in self.windows.values_mut() {
window_context.handle_event(
#[cfg(target_os = "macos")]
@@ -405,7 +407,7 @@ impl ApplicationHandler<Event> for Processor {
}
}
},
- (_, Some(window_id)) => {
+ (payload, Some(window_id)) => {
if let Some(window_context) = self.windows.get_mut(window_id) {
window_context.handle_event(
#[cfg(target_os = "macos")]
@@ -413,7 +415,7 @@ impl ApplicationHandler<Event> for Processor {
&self.proxy,
&mut self.clipboard,
&mut self.scheduler,
- WinitEvent::UserEvent(event),
+ WinitEvent::UserEvent(Event::new(payload, *window_id)),
);
}
},
@@ -1141,16 +1143,16 @@ impl<'a, N: Notify + 'a, T: EventListener> input::ActionContext<T> for ActionCon
}
let hint_bounds = hint.bounds();
- let text = match hint.hyperlink() {
- Some(hyperlink) => hyperlink.uri().to_owned(),
- None => self.terminal.bounds_to_string(*hint_bounds.start(), *hint_bounds.end()),
+ let text = match hint.text(self.terminal) {
+ Some(text) => text,
+ None => return,
};
match &hint.action() {
// Launch an external program.
HintAction::Command(command) => {
let mut args = command.args().to_vec();
- args.push(text);
+ args.push(text.into());
self.spawn_daemon(command.program(), &args);
},
// Copy the text to the clipboard.
diff --git a/alacritty/src/input/keyboard.rs b/alacritty/src/input/keyboard.rs
index 14755594..85734109 100644
--- a/alacritty/src/input/keyboard.rs
+++ b/alacritty/src/input/keyboard.rs
@@ -280,7 +280,7 @@ fn build_sequence(key: KeyEvent, mods: ModifiersState, mode: TermMode) -> Vec<u8
let sequence_base = context
.try_build_numpad(&key)
.or_else(|| context.try_build_named_kitty(&key))
- .or_else(|| context.try_build_named_normal(&key))
+ .or_else(|| context.try_build_named_normal(&key, associated_text.is_some()))
.or_else(|| context.try_build_control_char_or_mod(&key, &mut modifiers))
.or_else(|| context.try_build_textual(&key, associated_text));
@@ -483,14 +483,23 @@ impl SequenceBuilder {
}
/// Try building from [`NamedKey`].
- fn try_build_named_normal(&self, key: &KeyEvent) -> Option<SequenceBase> {
+ fn try_build_named_normal(
+ &self,
+ key: &KeyEvent,
+ has_associated_text: bool,
+ ) -> Option<SequenceBase> {
let named = match key.logical_key {
Key::Named(named) => named,
_ => return None,
};
// The default parameter is 1, so we can omit it.
- let one_based = if self.modifiers.is_empty() && !self.kitty_event_type { "" } else { "1" };
+ let one_based =
+ if self.modifiers.is_empty() && !self.kitty_event_type && !has_associated_text {
+ ""
+ } else {
+ "1"
+ };
let (base, terminator) = match named {
NamedKey::PageUp => ("5", SequenceTerminator::Normal('~')),
NamedKey::PageDown => ("6", SequenceTerminator::Normal('~')),
diff --git a/alacritty/src/input/mod.rs b/alacritty/src/input/mod.rs
index bbd8673f..1c9d6008 100644
--- a/alacritty/src/input/mod.rs
+++ b/alacritty/src/input/mod.rs
@@ -1136,7 +1136,7 @@ mod tests {
inline_search_state: &'a mut InlineSearchState,
}
- impl<'a, T: EventListener> super::ActionContext<T> for ActionContext<'a, T> {
+ impl<T: EventListener> super::ActionContext<T> for ActionContext<'_, T> {
fn search_next(
&mut self,
_origin: Point,
diff --git a/alacritty/src/macos/locale.rs b/alacritty/src/macos/locale.rs
index 2a47ace8..46996515 100644
--- a/alacritty/src/macos/locale.rs
+++ b/alacritty/src/macos/locale.rs
@@ -1,13 +1,12 @@
#![allow(clippy::let_unit_value)]
use std::ffi::{CStr, CString};
-use std::os::raw::c_char;
-use std::{env, slice, str};
+use std::{env, str};
use libc::{setlocale, LC_ALL, LC_CTYPE};
use log::debug;
-use objc::runtime::{Class, Object};
-use objc::{msg_send, sel, sel_impl};
+use objc2::sel;
+use objc2_foundation::{NSLocale, NSObjectProtocol};
const FALLBACK_LOCALE: &str = "UTF-8";
@@ -50,9 +49,7 @@ pub fn set_locale_environment() {
/// Determine system locale based on language and country code.
fn system_locale() -> String {
unsafe {
- let locale_class = Class::get("NSLocale").unwrap();
- let locale: *const Object = msg_send![locale_class, currentLocale];
- let _: () = msg_send![locale_class, release];
+ let locale = NSLocale::currentLocale();
// `localeIdentifier` returns extra metadata with the locale (including currency and
// collator) on newer versions of macOS. This is not a valid locale, so we use
@@ -61,38 +58,19 @@ fn system_locale() -> String {
// https://developer.apple.com/documentation/foundation/nslocale/1416263-localeidentifier?language=objc
// https://developer.apple.com/documentation/foundation/nslocale/1643060-countrycode?language=objc
// https://developer.apple.com/documentation/foundation/nslocale/1643026-languagecode?language=objc
- let is_language_code_supported: bool =
- msg_send![locale, respondsToSelector: sel!(languageCode)];
- let is_country_code_supported: bool =
- msg_send![locale, respondsToSelector: sel!(countryCode)];
- let locale_id = if is_language_code_supported && is_country_code_supported {
- let language_code: *const Object = msg_send![locale, languageCode];
- let language_code_str = nsstring_as_str(language_code).to_owned();
- let _: () = msg_send![language_code, release];
-
- let country_code: *const Object = msg_send![locale, countryCode];
- let country_code_str = nsstring_as_str(country_code).to_owned();
- let _: () = msg_send![country_code, release];
-
- format!("{}_{}.UTF-8", &language_code_str, &country_code_str)
+ let is_language_code_supported: bool = locale.respondsToSelector(sel!(languageCode));
+ let is_country_code_supported: bool = locale.respondsToSelector(sel!(countryCode));
+ if is_language_code_supported && is_country_code_supported {
+ let language_code = locale.languageCode();
+ #[allow(deprecated)]
+ if let Some(country_code) = locale.countryCode() {
+ format!("{}_{}.UTF-8", language_code, country_code)
+ } else {
+ // Fall back to en_US in case the country code is not available.
+ "en_US.UTF-8".into()
+ }
} else {
- let identifier: *const Object = msg_send![locale, localeIdentifier];
- let identifier_str = nsstring_as_str(identifier).to_owned();
- let _: () = msg_send![identifier, release];
-
- identifier_str + ".UTF-8"
- };
-
- let _: () = msg_send![locale, release];
-
- locale_id
+ locale.localeIdentifier().to_string() + ".UTF-8"
+ }
}
}
-
-const UTF8_ENCODING: usize = 4;
-
-unsafe fn nsstring_as_str<'a>(nsstring: *const Object) -> &'a str {
- let cstr: *const c_char = msg_send![nsstring, UTF8String];
- let len: usize = msg_send![nsstring, lengthOfBytesUsingEncoding: UTF8_ENCODING];
- str::from_utf8(slice::from_raw_parts(cstr as *const u8, len)).unwrap()
-}
diff --git a/alacritty/src/migrate/mod.rs b/alacritty/src/migrate/mod.rs
index 2f806d36..bfa72294 100644
--- a/alacritty/src/migrate/mod.rs
+++ b/alacritty/src/migrate/mod.rs
@@ -151,7 +151,15 @@ fn migrate_imports(
// Migrate each import.
for import in imports.into_iter().filter_map(|item| item.as_str()) {
let normalized_path = config::normalize_import(path, import);
- let migration = migrate_config(options, &normalized_path, recursion_limit)?;
+
+ if !normalized_path.exists() {
+ if options.dry_run {
+ println!("Skipping migration for nonexistent path: {}", normalized_path.display());
+ }
+ continue;
+ }
+
+ let migration = migrate_config(options, &normalized_path, recursion_limit - 1)?;
if options.dry_run {
println!("{}", migration.success_message(true));
}
@@ -244,7 +252,7 @@ enum Migration<'a> {
Yaml((&'a Path, String)),
}
-impl<'a> Migration<'a> {
+impl Migration<'_> {
/// Get the success message for this migration.
fn success_message(&self, import: bool) -> String {
match self {
diff --git a/alacritty/src/renderer/graphics/shader.rs b/alacritty/src/renderer/graphics/shader.rs
index e046c9ae..650af0a5 100644
--- a/alacritty/src/renderer/graphics/shader.rs
+++ b/alacritty/src/renderer/graphics/shader.rs
@@ -54,8 +54,8 @@ pub struct Vertex {
}
/// Sources for the graphics rendering program.
-static GRAPHICS_SHADER_F: &str = include_str!("../../../res/graphics.f.glsl");
-static GRAPHICS_SHADER_V: &str = include_str!("../../../res/graphics.v.glsl");
+const GRAPHICS_SHADER_F: &str = include_str!("../../../res/graphics.f.glsl");
+const GRAPHICS_SHADER_V: &str = include_str!("../../../res/graphics.v.glsl");
/// Graphics rendering program.
#[derive(Debug)]
diff --git a/alacritty/src/renderer/rects.rs b/alacritty/src/renderer/rects.rs
index 0bbcb832..d394073b 100644
--- a/alacritty/src/renderer/rects.rs
+++ b/alacritty/src/renderer/rects.rs
@@ -232,8 +232,8 @@ impl RenderLines {
}
/// Shader sources for rect rendering program.
-static RECT_SHADER_F: &str = include_str!("../../res/rect.f.glsl");
-static RECT_SHADER_V: &str = include_str!("../../res/rect.v.glsl");
+const RECT_SHADER_F: &str = include_str!("../../res/rect.f.glsl");
+const RECT_SHADER_V: &str = include_str!("../../res/rect.v.glsl");
#[repr(C)]
#[derive(Debug, Clone, Copy)]
diff --git a/alacritty/src/renderer/text/gles2.rs b/alacritty/src/renderer/text/gles2.rs
index 36b817ac..5268341d 100644
--- a/alacritty/src/renderer/text/gles2.rs
+++ b/alacritty/src/renderer/text/gles2.rs
@@ -20,8 +20,8 @@ use super::{
};
// Shader source.
-static TEXT_SHADER_F: &str = include_str!("../../../res/gles2/text.f.glsl");
-static TEXT_SHADER_V: &str = include_str!("../../../res/gles2/text.v.glsl");
+const TEXT_SHADER_F: &str = include_str!("../../../res/gles2/text.f.glsl");
+const TEXT_SHADER_V: &str = include_str!("../../../res/gles2/text.v.glsl");
#[derive(Debug)]
pub struct Gles2Renderer {
@@ -350,7 +350,7 @@ pub struct RenderApi<'a> {
dual_source_blending: bool,
}
-impl<'a> Drop for RenderApi<'a> {
+impl Drop for RenderApi<'_> {
fn drop(&mut self) {
if !self.batch.is_empty() {
self.render_batch();
@@ -358,7 +358,7 @@ impl<'a> Drop for RenderApi<'a> {
}
}
-impl<'a> LoadGlyph for RenderApi<'a> {
+impl LoadGlyph for RenderApi<'_> {
fn load_glyph(&mut self, rasterized: &RasterizedGlyph) -> Glyph {
Atlas::load_glyph(self.active_tex, self.atlas, self.current_atlas, rasterized)
}
@@ -368,7 +368,7 @@ impl<'a> LoadGlyph for RenderApi<'a> {
}
}
-impl<'a> TextRenderApi<Batch> for RenderApi<'a> {
+impl TextRenderApi<Batch> for RenderApi<'_> {
fn batch(&mut self) -> &mut Batch {
self.batch
}
diff --git a/alacritty/src/renderer/text/glsl3.rs b/alacritty/src/renderer/text/glsl3.rs
index 536fe048..07fcdff0 100644
--- a/alacritty/src/renderer/text/glsl3.rs
+++ b/alacritty/src/renderer/text/glsl3.rs
@@ -20,8 +20,8 @@ use super::{
};
// Shader source.
-pub static TEXT_SHADER_F: &str = include_str!("../../../res/glsl3/text.f.glsl");
-static TEXT_SHADER_V: &str = include_str!("../../../res/glsl3/text.v.glsl");
+pub const TEXT_SHADER_F: &str = include_str!("../../../res/glsl3/text.f.glsl");
+const TEXT_SHADER_V: &str = include_str!("../../../res/glsl3/text.v.glsl");
/// Maximum items to be drawn in a batch.
const BATCH_MAX: usize = 0x1_0000;
@@ -219,7 +219,7 @@ pub struct RenderApi<'a> {
program: &'a mut TextShaderProgram,
}
-impl<'a> TextRenderApi<Batch> for RenderApi<'a> {
+impl TextRenderApi<Batch> for RenderApi<'_> {
fn batch(&mut self) -> &mut Batch {
self.batch
}
@@ -265,7 +265,7 @@ impl<'a> TextRenderApi<Batch> for RenderApi<'a> {
}
}
-impl<'a> LoadGlyph for RenderApi<'a> {
+impl LoadGlyph for RenderApi<'_> {
fn load_glyph(&mut self, rasterized: &RasterizedGlyph) -> Glyph {
Atlas::load_glyph(self.active_tex, self.atlas, self.current_atlas, rasterized)
}
@@ -275,7 +275,7 @@ impl<'a> LoadGlyph for RenderApi<'a> {
}
}
-impl<'a> Drop for RenderApi<'a> {
+impl Drop for RenderApi<'_> {
fn drop(&mut self) {
if !self.batch.is_empty() {
self.render_batch();
diff --git a/alacritty/src/renderer/text/mod.rs b/alacritty/src/renderer/text/mod.rs
index 5ee6bc4c..2742704d 100644
--- a/alacritty/src/renderer/text/mod.rs
+++ b/alacritty/src/renderer/text/mod.rs
@@ -188,7 +188,7 @@ pub struct LoaderApi<'a> {
current_atlas: &'a mut usize,
}
-impl<'a> LoadGlyph for LoaderApi<'a> {
+impl LoadGlyph for LoaderApi<'_> {
fn load_glyph(&mut self, rasterized: &RasterizedGlyph) -> Glyph {
Atlas::load_glyph(self.active_tex, self.atlas, self.current_atlas, rasterized)
}
diff --git a/alacritty/src/string.rs b/alacritty/src/string.rs
index a7af4394..b8c47d3b 100644
--- a/alacritty/src/string.rs
+++ b/alacritty/src/string.rs
@@ -106,7 +106,7 @@ impl<'a> StrShortener<'a> {
}
}
-impl<'a> Iterator for StrShortener<'a> {
+impl Iterator for StrShortener<'_> {
type Item = char;
fn next(&mut self) -> Option<Self::Item> {
diff --git a/alacritty/windows/wix/alacritty.wxs b/alacritty/windows/wix/alacritty.wxs
index cd00bda0..5c05d821 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.14.0" Manufacturer="Alacritty" InstallerVersion="200">
+ <Package Name="Alacritty" UpgradeCode="87c21c74-dbd5-4584-89d5-46d9cd0c40a7" Language="1033" Codepage="1252" Version="0.15.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_config/Cargo.toml b/alacritty_config/Cargo.toml
index 862c6eb8..a6d651bc 100644
--- a/alacritty_config/Cargo.toml
+++ b/alacritty_config/Cargo.toml
@@ -1,6 +1,6 @@
[package]
name = "alacritty_config"
-version = "0.2.2"
+version = "0.2.3-dev"
authors = ["Christian Duerr <contact@christianduerr.com>"]
license = "MIT OR Apache-2.0"
description = "Alacritty configuration abstractions"
@@ -15,5 +15,5 @@ serde = "1.0.163"
toml = "0.8.2"
[dev-dependencies]
-alacritty_config_derive = { version = "0.2.4", path = "../alacritty_config_derive" }
+alacritty_config_derive = { version = "0.2.5-dev", path = "../alacritty_config_derive" }
serde = { version = "1.0.163", features = ["derive"] }
diff --git a/alacritty_config_derive/Cargo.toml b/alacritty_config_derive/Cargo.toml
index bf439ce7..7d04eacc 100644
--- a/alacritty_config_derive/Cargo.toml
+++ b/alacritty_config_derive/Cargo.toml
@@ -1,6 +1,6 @@
[package]
name = "alacritty_config_derive"
-version = "0.2.4"
+version = "0.2.5-dev"
authors = ["Christian Duerr <contact@christianduerr.com>"]
license = "MIT OR Apache-2.0"
description = "Failure resistant deserialization derive"
@@ -19,7 +19,7 @@ syn = { version = "2.0.16", features = ["derive", "parsing", "proc-macro", "prin
[dev-dependencies.alacritty_config]
path = "../alacritty_config"
-version = "0.2.2"
+version = "0.2.3-dev"
[dev-dependencies]
log = "0.4.11"
diff --git a/alacritty_terminal/CHANGELOG.md b/alacritty_terminal/CHANGELOG.md
index e612e749..28ed7540 100644
--- a/alacritty_terminal/CHANGELOG.md
+++ b/alacritty_terminal/CHANGELOG.md
@@ -8,6 +8,8 @@ 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.24.1
### Changed
diff --git a/alacritty_terminal/Cargo.toml b/alacritty_terminal/Cargo.toml
index b8c0db4c..f8abf51d 100644
--- a/alacritty_terminal/Cargo.toml
+++ b/alacritty_terminal/Cargo.toml
@@ -1,6 +1,6 @@
[package]
name = "alacritty_terminal"
-version = "0.24.1"
+version = "0.24.2-dev"
authors = ["Christian Duerr <contact@christianduerr.com>", "Joe Wilm <joe@jwilm.com>"]
license = "Apache-2.0"
description = "Library for writing terminal emulators"
@@ -35,7 +35,7 @@ signal-hook = "0.3.10"
[target.'cfg(windows)'.dependencies]
piper = "0.2.1"
miow = "0.6.0"
-windows-sys = { version = "0.52.0", features = [
+windows-sys = { version = "0.59.0", features = [
"Win32_System_Console",
"Win32_Foundation",
"Win32_Security",
diff --git a/alacritty_terminal/src/graphics/mod.rs b/alacritty_terminal/src/graphics/mod.rs
index 7d2a5edb..5ecdf29c 100644
--- a/alacritty_terminal/src/graphics/mod.rs
+++ b/alacritty_terminal/src/graphics/mod.rs
@@ -621,7 +621,7 @@ pub fn insert_graphic<L: EventListener>(
}
if term.mode().contains(TermMode::SIXEL_CURSOR_TO_THE_RIGHT) {
- let graphic_columns = (graphic.width + cell_width - 1) / cell_width;
+ let graphic_columns = graphic.width.div_ceil(cell_width);
term.move_forward(graphic_columns);
} else if scrolling {
term.linefeed();
diff --git a/alacritty_terminal/src/grid/mod.rs b/alacritty_terminal/src/grid/mod.rs
index 8c913de8..a1b4d67b 100644
--- a/alacritty_terminal/src/grid/mod.rs
+++ b/alacritty_terminal/src/grid/mod.rs
@@ -627,7 +627,7 @@ pub trait BidirectionalIterator: Iterator {
fn prev(&mut self) -> Option<Self::Item>;
}
-impl<'a, T> BidirectionalIterator for GridIterator<'a, T> {
+impl<T> BidirectionalIterator for GridIterator<'_, T> {
fn prev(&mut self) -> Option<Self::Item> {
let topmost_line = self.grid.topmost_line();
let last_column = self.grid.last_column();
diff --git a/alacritty_terminal/src/term/mod.rs b/alacritty_terminal/src/term/mod.rs
index 6b0ccccd..46b65377 100644
--- a/alacritty_terminal/src/term/mod.rs
+++ b/alacritty_terminal/src/term/mod.rs
@@ -207,7 +207,7 @@ impl<'a> TermDamageIterator<'a> {
}
}
-impl<'a> Iterator for TermDamageIterator<'a> {
+impl Iterator for TermDamageIterator<'_> {
type Item = LineDamageBounds;
fn next(&mut self) -> Option<Self::Item> {
@@ -956,6 +956,11 @@ impl<T> Term<T> {
&self.config.semantic_escape_chars
}
+ #[cfg(test)]
+ pub(crate) fn set_semantic_escape_chars(&mut self, semantic_escape_chars: &str) {
+ self.config.semantic_escape_chars = semantic_escape_chars.into();
+ }
+
/// Active terminal cursor style.
///
/// While vi mode is active, this will automatically return the vi mode cursor style.
diff --git a/alacritty_terminal/src/term/search.rs b/alacritty_terminal/src/term/search.rs
index 33f6ee05..20a427b7 100644
--- a/alacritty_terminal/src/term/search.rs
+++ b/alacritty_terminal/src/term/search.rs
@@ -656,7 +656,7 @@ impl<'a, T> RegexIter<'a, T> {
}
}
-impl<'a, T> Iterator for RegexIter<'a, T> {
+impl<T> Iterator for RegexIter<'_, T> {
type Item = Match;
fn next(&mut self) -> Option<Self::Item> {
diff --git a/alacritty_terminal/src/tty/windows/child.rs b/alacritty_terminal/src/tty/windows/child.rs
index dc6b992c..573eb475 100644
--- a/alacritty_terminal/src/tty/windows/child.rs
+++ b/alacritty_terminal/src/tty/windows/child.rs
@@ -1,6 +1,7 @@
use std::ffi::c_void;
use std::io::Error;
use std::num::NonZeroU32;
+use std::ptr;
use std::sync::atomic::{AtomicPtr, Ordering};
use std::sync::{mpsc, Arc, Mutex};
@@ -50,7 +51,7 @@ pub struct ChildExitWatcher {
wait_handle: AtomicPtr<c_void>,
event_rx: mpsc::Receiver<ChildEvent>,
interest: Arc<Mutex<Option<Interest>>>,
- child_handle: HANDLE,
+ child_handle: AtomicPtr<c_void>,
pid: Option<NonZeroU32>,
}
@@ -58,12 +59,12 @@ impl ChildExitWatcher {
pub fn new(child_handle: HANDLE) -> Result<ChildExitWatcher, Error> {
let (event_tx, event_rx) = mpsc::channel();
- let mut wait_handle: HANDLE = 0;
+ let mut wait_handle: HANDLE = ptr::null_mut();
let interest = Arc::new(Mutex::new(None));
let sender_ref = Box::new(ChildExitSender {
sender: event_tx,
interest: interest.clone(),
- child_handle: AtomicPtr::from(child_handle as *mut c_void),
+ child_handle: AtomicPtr::from(child_handle),
});
let success = unsafe {
@@ -82,11 +83,11 @@ impl ChildExitWatcher {
} else {
let pid = unsafe { NonZeroU32::new(GetProcessId(child_handle)) };
Ok(ChildExitWatcher {
- wait_handle: AtomicPtr::from(wait_handle as *mut c_void),
event_rx,
interest,
- child_handle,
pid,
+ child_handle: AtomicPtr::from(child_handle),
+ wait_handle: AtomicPtr::from(wait_handle),
})
}
}
@@ -112,7 +113,7 @@ impl ChildExitWatcher {
/// If you terminate the process using this handle, the terminal will get a
/// timeout error, and the child watcher will emit an `Exited` event.
pub fn raw_handle(&self) -> HANDLE {
- self.child_handle
+ self.child_handle.load(Ordering::Relaxed) as HANDLE
}
/// Retrieve the Process ID associated to the underlying child process.
diff --git a/alacritty_terminal/src/tty/windows/conpty.rs b/alacritty_terminal/src/tty/windows/conpty.rs
index 28289f90..bcbc1f0e 100644
--- a/alacritty_terminal/src/tty/windows/conpty.rs
+++ b/alacritty_terminal/src/tty/windows/conpty.rs
@@ -72,7 +72,7 @@ impl ConptyApi {
type LoadedFn = unsafe extern "system" fn() -> isize;
unsafe {
let hmodule = LoadLibraryW(w!("conpty.dll"));
- if hmodule == 0 {
+ if hmodule.is_null() {
return None;
}
let create_fn = GetProcAddress(hmodule, s!("CreatePseudoConsole"))?;
diff --git a/alacritty_terminal/src/vi_mode.rs b/alacritty_terminal/src/vi_mode.rs
index 7065544e..e23e9b80 100644
--- a/alacritty_terminal/src/vi_mode.rs
+++ b/alacritty_terminal/src/vi_mode.rs
@@ -265,14 +265,14 @@ fn semantic<T: EventListener>(
}
};
- // Make sure we jump above wide chars.
- point = term.expand_wide(point, direction);
-
// Move to word boundary.
if direction != side && !is_boundary(term, point, direction) {
point = expand_semantic(point);
}
+ // Make sure we jump above wide chars.
+ point = term.expand_wide(point, direction);
+
// Skip whitespace.
let mut next_point = advance(term, point, direction);
while !is_boundary(term, point, direction) && is_space(term, next_point) {
@@ -283,6 +283,11 @@ fn semantic<T: EventListener>(
// Assure minimum movement of one cell.
if !is_boundary(term, point, direction) {
point = advance(term, point, direction);
+
+ // Skip over wide cell spacers.
+ if direction == Direction::Left {
+ point = term.expand_wide(point, direction);
+ }
}
// Move to word boundary.
@@ -820,4 +825,42 @@ mod tests {
cursor = cursor.scroll(&term, -20);
assert_eq!(cursor.point, Point::new(Line(19), Column(0)));
}
+
+ #[test]
+ fn wide_semantic_char() {
+ let mut term = term();
+ term.set_semantic_escape_chars("-");
+ term.grid_mut()[Line(0)][Column(0)].c = 'x';
+ term.grid_mut()[Line(0)][Column(1)].c = 'x';
+ term.grid_mut()[Line(0)][Column(2)].c = '-';
+ term.grid_mut()[Line(0)][Column(2)].flags.insert(Flags::WIDE_CHAR);
+ term.grid_mut()[Line(0)][Column(3)].c = ' ';
+ term.grid_mut()[Line(0)][Column(3)].flags.insert(Flags::WIDE_CHAR_SPACER);
+ term.grid_mut()[Line(0)][Column(4)].c = 'x';
+ term.grid_mut()[Line(0)][Column(5)].c = 'x';
+
+ // Test motion to the right.
+
+ let mut cursor = ViModeCursor::new(Point::new(Line(0), Column(0)));
+ cursor = cursor.motion(&mut term, ViMotion::SemanticRight);
+ assert_eq!(cursor.point, Point::new(Line(0), Column(2)));
+
+ let mut cursor = ViModeCursor::new(Point::new(Line(0), Column(2)));
+ cursor = cursor.motion(&mut term, ViMotion::SemanticRight);
+ assert_eq!(cursor.point, Point::new(Line(0), Column(4)));
+
+ // Test motion to the left.
+
+ let mut cursor = ViModeCursor::new(Point::new(Line(0), Column(5)));
+ cursor = cursor.motion(&mut term, ViMotion::SemanticLeft);
+ assert_eq!(cursor.point, Point::new(Line(0), Column(4)));
+
+ let mut cursor = ViModeCursor::new(Point::new(Line(0), Column(4)));
+ cursor = cursor.motion(&mut term, ViMotion::SemanticLeft);
+ assert_eq!(cursor.point, Point::new(Line(0), Column(2)));
+
+ let mut cursor = ViModeCursor::new(Point::new(Line(0), Column(2)));
+ cursor = cursor.motion(&mut term, ViMotion::SemanticLeft);
+ assert_eq!(cursor.point, Point::new(Line(0), Column(0)));
+ }
}
diff --git a/extra/completions/_alacritty b/extra/completions/_alacritty
index 0ccce66f..a0ac0e3b 100644
--- a/extra/completions/_alacritty
+++ b/extra/completions/_alacritty
@@ -15,17 +15,17 @@ _alacritty() {
local context curcontext="$curcontext" state line
_arguments "${_arguments_options[@]}" : \
-'--embed=[X11 window ID to embed Alacritty within (decimal or hexadecimal with "0x" prefix)]:EMBED: ' \
+'--embed=[X11 window ID to embed Alacritty within (decimal or hexadecimal with "0x" prefix)]:EMBED:_default' \
'--config-file=[Specify alternative configuration file \[default\: \$XDG_CONFIG_HOME/alacritty/alacritty.toml\]]:CONFIG_FILE:_files' \
'--socket=[Path for IPC socket creation]:SOCKET:_files' \
'--working-directory=[Start the shell in the specified working directory]:WORKING_DIRECTORY:_files' \
-'*-e+[Command and args to execute (must be last argument)]:COMMAND: ' \
-'*--command=[Command and args to execute (must be last argument)]:COMMAND: ' \
-'-T+[Defines the window title \[default\: Alacritty\]]:TITLE: ' \
-'--title=[Defines the window title \[default\: Alacritty\]]:TITLE: ' \
-'--class=[Defines window class/app_id on X11/Wayland \[default\: Alacritty\]]:general> | <general>,<instance: ' \
-'*-o+[Override configuration file options \[example\: '\''cursor.style="Beam"'\''\]]:OPTION: ' \
-'*--option=[Override configuration file options \[example\: '\''cursor.style="Beam"'\''\]]:OPTION: ' \
+'*-e+[Command and args to execute (must be last argument)]:COMMAND:_default' \
+'*--command=[Command and args to execute (must be last argument)]:COMMAND:_default' \
+'-T+[Defines the window title \[default\: Alacritty\]]:TITLE:_default' \
+'--title=[Defines the window title \[default\: Alacritty\]]:TITLE:_default' \
+'--class=[Defines window class/app_id on X11/Wayland \[default\: Alacritty\]]:general> | <general>,<instance:_default' \
+'*-o+[Override configuration file options \[example\: '\''cursor.style="Beam"'\''\]]:OPTION:_default' \
+'*--option=[Override configuration file options \[example\: '\''cursor.style="Beam"'\''\]]:OPTION:_default' \
'--print-events[Print all events to STDOUT]' \
'(--daemon)--ref-test[Generates ref test]' \
'(-v)*-q[Reduces the level of verbosity (the min level is -qq)]' \
@@ -64,13 +64,13 @@ _arguments "${_arguments_options[@]}" : \
(create-window)
_arguments "${_arguments_options[@]}" : \
'--working-directory=[Start the shell in the specified working directory]:WORKING_DIRECTORY:_files' \
-'*-e+[Command and args to execute (must be last argument)]:COMMAND: ' \
-'*--command=[Command and args to execute (must be last argument)]:COMMAND: ' \
-'-T+[Defines the window title \[default\: Alacritty\]]:TITLE: ' \
-'--title=[Defines the window title \[default\: Alacritty\]]:TITLE: ' \
-'--class=[Defines window class/app_id on X11/Wayland \[default\: Alacritty\]]:general> | <general>,<instance: ' \
-'*-o+[Override configuration file options \[example\: '\''cursor.style="Beam"'\''\]]:OPTION: ' \
-'*--option=[Override configuration file options \[example\: '\''cursor.style="Beam"'\''\]]:OPTION: ' \
+'*-e+[Command and args to execute (must be last argument)]:COMMAND:_default' \
+'*--command=[Command and args to execute (must be last argument)]:COMMAND:_default' \
+'-T+[Defines the window title \[default\: Alacritty\]]:TITLE:_default' \
+'--title=[Defines the window title \[default\: Alacritty\]]:TITLE:_default' \
+'--class=[Defines window class/app_id on X11/Wayland \[default\: Alacritty\]]:general> | <general>,<instance:_default' \
+'*-o+[Override configuration file options \[example\: '\''cursor.style="Beam"'\''\]]:OPTION:_default' \
+'*--option=[Override configuration file options \[example\: '\''cursor.style="Beam"'\''\]]:OPTION:_default' \
'--hold[Remain open after child process exit]' \
'-h[Print help]' \
'--help[Print help]' \
@@ -78,13 +78,13 @@ _arguments "${_arguments_options[@]}" : \
;;
(config)
_arguments "${_arguments_options[@]}" : \
-'-w+[Window ID for the new config]:WINDOW_ID: ' \
-'--window-id=[Window ID for the new config]:WINDOW_ID: ' \
+'-w+[Window ID for the new config]:WINDOW_ID:_default' \
+'--window-id=[Window ID for the new config]:WINDOW_ID:_default' \
'()-r[Clear all runtime configuration changes]' \
'()--reset[Clear all runtime configuration changes]' \
'-h[Print help (see more with '\''--help'\'')]' \
'--help[Print help (see more with '\''--help'\'')]' \
-'*::options -- Configuration file options \[example\: '\''cursor.style="Beam"'\''\]:' \
+'*::options -- Configuration file options \[example\: '\''cursor.style="Beam"'\''\]:_default' \
&& ret=0
;;
(help)
diff --git a/extra/man/alacritty.5.scd b/extra/man/alacritty.5.scd
index 8e92734a..18172487 100644
--- a/extra/man/alacritty.5.scd
+++ b/extra/man/alacritty.5.scd
@@ -195,6 +195,17 @@ This section documents the *[window]* table of the configuration file.
Default: _"None"_
+*level* = _"Normal"_ | _"AlwaysOnTop"_
+
+ Sets window level.
+
+ *Normal*
+ Window adheres to system's default z-order.
+ *AlwaysOnTop*
+ Window is a toplevel window.
+
+ Default: _"Normal"_
+
Example:
*[window]*++
padding = { x = _3_, y = _3_ }++
@@ -601,9 +612,7 @@ This section documents the *[terminal]* table of the configuration file.
Windows: _"powershell"_
Example:
- *[shell]*++
-program = _"/bin/zsh"_++
-args = [_"-l"_]
+ *shell* = { program = _"/bin/zsh"_, args = [_"-l"_] }
*osc52* = _"Disabled"_ | _"OnlyCopy"_ | _"OnlyPaste"_ | _"CopyPaste"_
diff --git a/extra/osx/Alacritty.app/Contents/Info.plist b/extra/osx/Alacritty.app/Contents/Info.plist
index 08bf4270..59c70ff2 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.14.0</string>
+ <string>0.15.0-dev</string>
<key>CFBundleSupportedPlatforms</key>
<array>
<string>MacOSX</string>