Skip to content

Commit 530de00

Browse files
authored
Move renderable cell transformation to alacritty
This refactors a large chunk of the alacritty_terminal API to expose all data necessary for rendering uniformly through the `renderable_content` call. This also no longer transforms the cells for rendering by a GUI but instead just reports the content from a terminal emulation perspective. The transformation into renderable cells is now done inside the alacritty crate. Since the terminal itself only ever needs to know about modified color RGB values, the configuration for colors was moved to the alacritty UI code.
1 parent 7291702 commit 530de00

35 files changed

+1434
-1548
lines changed

Diff for: CHANGELOG.md

+6-2
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,10 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
77

88
## 0.8.0-dev
99

10+
### Packaging
11+
12+
- Updated shell completions
13+
1014
### Added
1115

1216
- IME composition preview not appearing on Windows
@@ -15,9 +19,9 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
1519

1620
- Crash due to assertion failure on 32-bit architectures
1721

18-
### Packaging
22+
### Removed
1923

20-
- Updated shell completions
24+
- Config field `visual_bell`, you should use `bell` instead
2125

2226
## 0.7.1
2327

Diff for: Cargo.lock

+1-1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Diff for: alacritty/Cargo.toml

+1-1
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ edition = "2018"
1010

1111
[dependencies.alacritty_terminal]
1212
path = "../alacritty_terminal"
13-
version = "0.12.1-dev"
13+
version = "0.13.0-dev"
1414
default-features = false
1515

1616
[dependencies.alacritty_config_derive]

Diff for: alacritty_terminal/src/config/bell.rs renamed to alacritty/src/config/bell.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,8 @@ use std::time::Duration;
22

33
use alacritty_config_derive::ConfigDeserialize;
44

5-
use crate::config::Program;
6-
use crate::term::color::Rgb;
5+
use alacritty_terminal::config::Program;
6+
use alacritty_terminal::term::color::Rgb;
77

88
#[derive(ConfigDeserialize, Clone, Debug, PartialEq, Eq)]
99
pub struct BellConfig {

Diff for: alacritty_terminal/src/config/colors.rs renamed to alacritty/src/config/color.rs

+1-2
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,7 @@ use serde::de::Error as SerdeError;
22
use serde::{Deserialize, Deserializer};
33

44
use alacritty_config_derive::ConfigDeserialize;
5-
6-
use crate::term::color::{CellRgb, Rgb};
5+
use alacritty_terminal::term::color::{CellRgb, Rgb};
76

87
#[derive(ConfigDeserialize, Clone, Debug, Default, PartialEq, Eq)]
98
pub struct Colors {

Diff for: alacritty/src/config/mod.rs

+8-6
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
use std::fmt::{self, Display, Formatter};
2-
use std::path::PathBuf;
2+
use std::path::{Path, PathBuf};
33
use std::{env, fs, io};
44

55
use log::{error, info};
@@ -9,6 +9,8 @@ use serde_yaml::Value;
99

1010
use alacritty_terminal::config::{Config as TermConfig, LOG_TARGET_CONFIG};
1111

12+
pub mod bell;
13+
pub mod color;
1214
pub mod debug;
1315
pub mod font;
1416
pub mod monitor;
@@ -123,10 +125,10 @@ pub fn load(options: &Options) -> Config {
123125
}
124126

125127
/// Attempt to reload the configuration file.
126-
pub fn reload(config_path: &PathBuf, options: &Options) -> Result<Config> {
128+
pub fn reload(config_path: &Path, options: &Options) -> Result<Config> {
127129
// Load config, propagating errors.
128130
let config_options = options.config_options().clone();
129-
let mut config = load_from(&config_path, config_options)?;
131+
let mut config = load_from(config_path, config_options)?;
130132

131133
// Override config with CLI options.
132134
options.override_config(&mut config);
@@ -135,7 +137,7 @@ pub fn reload(config_path: &PathBuf, options: &Options) -> Result<Config> {
135137
}
136138

137139
/// Load configuration file and log errors.
138-
fn load_from(path: &PathBuf, cli_config: Value) -> Result<Config> {
140+
fn load_from(path: &Path, cli_config: Value) -> Result<Config> {
139141
match read_config(path, cli_config) {
140142
Ok(config) => Ok(config),
141143
Err(err) => {
@@ -146,7 +148,7 @@ fn load_from(path: &PathBuf, cli_config: Value) -> Result<Config> {
146148
}
147149

148150
/// Deserialize configuration file from path.
149-
fn read_config(path: &PathBuf, cli_config: Value) -> Result<Config> {
151+
fn read_config(path: &Path, cli_config: Value) -> Result<Config> {
150152
let mut config_paths = Vec::new();
151153
let mut config_value = parse_config(&path, &mut config_paths, IMPORT_RECURSION_LIMIT)?;
152154

@@ -162,7 +164,7 @@ fn read_config(path: &PathBuf, cli_config: Value) -> Result<Config> {
162164

163165
/// Deserialize all configuration files as generic Value.
164166
fn parse_config(
165-
path: &PathBuf,
167+
path: &Path,
166168
config_paths: &mut Vec<PathBuf>,
167169
recursion_limit: usize,
168170
) -> Result<Value> {

Diff for: alacritty/src/config/ui_config.rs

+14
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,9 @@ use serde::{Deserialize, Deserializer};
66
use alacritty_config_derive::ConfigDeserialize;
77
use alacritty_terminal::config::{Percentage, LOG_TARGET_CONFIG};
88

9+
use crate::config::bell::BellConfig;
910
use crate::config::bindings::{self, Binding, KeyBinding, MouseBinding};
11+
use crate::config::color::Colors;
1012
use crate::config::debug::Debug;
1113
use crate::config::font::Font;
1214
use crate::config::mouse::Mouse;
@@ -31,6 +33,15 @@ pub struct UIConfig {
3133
/// Live config reload.
3234
pub live_config_reload: bool,
3335

36+
/// Bell configuration.
37+
pub bell: BellConfig,
38+
39+
/// RGB values for colors.
40+
pub colors: Colors,
41+
42+
/// Should draw bold text with brighter colors instead of bold font.
43+
pub draw_bold_text_with_bright_colors: bool,
44+
3445
/// Path where config was loaded from.
3546
#[config(skip)]
3647
pub config_paths: Vec<PathBuf>,
@@ -58,6 +69,9 @@ impl Default for UIConfig {
5869
key_bindings: Default::default(),
5970
mouse_bindings: Default::default(),
6071
background_opacity: Default::default(),
72+
bell: Default::default(),
73+
colors: Default::default(),
74+
draw_bold_text_with_bright_colors: Default::default(),
6175
}
6276
}
6377
}

Diff for: alacritty/src/display/bell.rs

+122
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,122 @@
1+
use std::time::{Duration, Instant};
2+
3+
use crate::config::bell::{BellAnimation, BellConfig};
4+
5+
pub struct VisualBell {
6+
/// Visual bell animation.
7+
animation: BellAnimation,
8+
9+
/// Visual bell duration.
10+
duration: Duration,
11+
12+
/// The last time the visual bell rang, if at all.
13+
start_time: Option<Instant>,
14+
}
15+
16+
impl VisualBell {
17+
/// Ring the visual bell, and return its intensity.
18+
pub fn ring(&mut self) -> f64 {
19+
let now = Instant::now();
20+
self.start_time = Some(now);
21+
self.intensity_at_instant(now)
22+
}
23+
24+
/// Get the currently intensity of the visual bell. The bell's intensity
25+
/// ramps down from 1.0 to 0.0 at a rate determined by the bell's duration.
26+
pub fn intensity(&self) -> f64 {
27+
self.intensity_at_instant(Instant::now())
28+
}
29+
30+
/// Check whether or not the visual bell has completed "ringing".
31+
pub fn completed(&mut self) -> bool {
32+
match self.start_time {
33+
Some(earlier) => {
34+
if Instant::now().duration_since(earlier) >= self.duration {
35+
self.start_time = None;
36+
}
37+
false
38+
},
39+
None => true,
40+
}
41+
}
42+
43+
/// Get the intensity of the visual bell at a particular instant. The bell's
44+
/// intensity ramps down from 1.0 to 0.0 at a rate determined by the bell's
45+
/// duration.
46+
pub fn intensity_at_instant(&self, instant: Instant) -> f64 {
47+
// If `duration` is zero, then the VisualBell is disabled; therefore,
48+
// its `intensity` is zero.
49+
if self.duration == Duration::from_secs(0) {
50+
return 0.0;
51+
}
52+
53+
match self.start_time {
54+
// Similarly, if `start_time` is `None`, then the VisualBell has not
55+
// been "rung"; therefore, its `intensity` is zero.
56+
None => 0.0,
57+
58+
Some(earlier) => {
59+
// Finally, if the `instant` at which we wish to compute the
60+
// VisualBell's `intensity` occurred before the VisualBell was
61+
// "rung", then its `intensity` is also zero.
62+
if instant < earlier {
63+
return 0.0;
64+
}
65+
66+
let elapsed = instant.duration_since(earlier);
67+
let elapsed_f =
68+
elapsed.as_secs() as f64 + f64::from(elapsed.subsec_nanos()) / 1e9f64;
69+
let duration_f = self.duration.as_secs() as f64
70+
+ f64::from(self.duration.subsec_nanos()) / 1e9f64;
71+
72+
// Otherwise, we compute a value `time` from 0.0 to 1.0
73+
// inclusive that represents the ratio of `elapsed` time to the
74+
// `duration` of the VisualBell.
75+
let time = (elapsed_f / duration_f).min(1.0);
76+
77+
// We use this to compute the inverse `intensity` of the
78+
// VisualBell. When `time` is 0.0, `inverse_intensity` is 0.0,
79+
// and when `time` is 1.0, `inverse_intensity` is 1.0.
80+
let inverse_intensity = match self.animation {
81+
BellAnimation::Ease | BellAnimation::EaseOut => {
82+
cubic_bezier(0.25, 0.1, 0.25, 1.0, time)
83+
},
84+
BellAnimation::EaseOutSine => cubic_bezier(0.39, 0.575, 0.565, 1.0, time),
85+
BellAnimation::EaseOutQuad => cubic_bezier(0.25, 0.46, 0.45, 0.94, time),
86+
BellAnimation::EaseOutCubic => cubic_bezier(0.215, 0.61, 0.355, 1.0, time),
87+
BellAnimation::EaseOutQuart => cubic_bezier(0.165, 0.84, 0.44, 1.0, time),
88+
BellAnimation::EaseOutQuint => cubic_bezier(0.23, 1.0, 0.32, 1.0, time),
89+
BellAnimation::EaseOutExpo => cubic_bezier(0.19, 1.0, 0.22, 1.0, time),
90+
BellAnimation::EaseOutCirc => cubic_bezier(0.075, 0.82, 0.165, 1.0, time),
91+
BellAnimation::Linear => time,
92+
};
93+
94+
// Since we want the `intensity` of the VisualBell to decay over
95+
// `time`, we subtract the `inverse_intensity` from 1.0.
96+
1.0 - inverse_intensity
97+
},
98+
}
99+
}
100+
101+
pub fn update_config(&mut self, bell_config: &BellConfig) {
102+
self.animation = bell_config.animation;
103+
self.duration = bell_config.duration();
104+
}
105+
}
106+
107+
impl From<&BellConfig> for VisualBell {
108+
fn from(bell_config: &BellConfig) -> VisualBell {
109+
VisualBell {
110+
animation: bell_config.animation,
111+
duration: bell_config.duration(),
112+
start_time: None,
113+
}
114+
}
115+
}
116+
117+
fn cubic_bezier(p0: f64, p1: f64, p2: f64, p3: f64, x: f64) -> f64 {
118+
(1.0 - x).powi(3) * p0
119+
+ 3.0 * (1.0 - x).powi(2) * x * p1
120+
+ 3.0 * (1.0 - x) * x.powi(2) * p2
121+
+ x.powi(3) * p3
122+
}

0 commit comments

Comments
 (0)