aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAyose <ayosec@gmail.com>2022-10-16 19:31:54 +0100
committerAyose <ayosec@gmail.com>2022-10-16 19:31:54 +0100
commit2eb9812849bc849cb634e2d9ada3dfa231603d43 (patch)
tree29872ba415a25e3f433dd809789773aa254b9d04
parent83aceede5b0de5152c5e448d79289d7237f1ee9e (diff)
parent269b6e3dba66f54ff6d83a1d26142683dd191905 (diff)
downloadr-alacritty-2eb9812849bc849cb634e2d9ada3dfa231603d43.tar.gz
r-alacritty-2eb9812849bc849cb634e2d9ada3dfa231603d43.tar.bz2
r-alacritty-2eb9812849bc849cb634e2d9ada3dfa231603d43.zip
Merge remote-tracking branch 'vendor/master' into graphics
-rw-r--r--.github/workflows/release.yml2
-rw-r--r--CHANGELOG.md21
-rw-r--r--Cargo.lock537
-rw-r--r--Cargo.toml1
-rw-r--r--INSTALL.md11
-rw-r--r--LICENSE-MIT23
-rw-r--r--alacritty.yml9
-rw-r--r--alacritty/Cargo.toml38
l---------alacritty/alacritty.png1
-rw-r--r--alacritty/build.rs6
l---------alacritty/extra1
-rw-r--r--alacritty/src/cli.rs77
-rw-r--r--alacritty/src/config/bindings.rs12
-rw-r--r--alacritty/src/config/font.rs4
-rw-r--r--alacritty/src/config/monitor.rs2
-rw-r--r--alacritty/src/config/ui_config.rs12
-rw-r--r--alacritty/src/config/window.rs32
-rw-r--r--alacritty/src/daemon.rs2
-rw-r--r--alacritty/src/display/content.rs5
-rw-r--r--alacritty/src/display/cursor.rs2
-rw-r--r--alacritty/src/display/mod.rs264
-rw-r--r--alacritty/src/display/window.rs61
-rw-r--r--alacritty/src/event.rs139
-rw-r--r--alacritty/src/input.rs19
-rw-r--r--alacritty/src/ipc.rs11
-rw-r--r--alacritty/src/logging.rs16
-rw-r--r--alacritty/src/main.rs43
-rw-r--r--alacritty/src/panic.rs15
-rw-r--r--alacritty/src/renderer/rects.rs2
-rw-r--r--alacritty/src/renderer/text/atlas.rs8
-rw-r--r--alacritty/src/renderer/text/builtin_font.rs22
-rw-r--r--alacritty/src/renderer/text/glsl3.rs1
-rw-r--r--alacritty/src/string.rs14
-rw-r--r--alacritty/src/window_context.rs128
-rw-r--r--alacritty/windows/alacritty.rc (renamed from alacritty/windows/windows.rc)0
-rw-r--r--alacritty/windows/wix/alacritty.wxs6
-rw-r--r--alacritty_config/Cargo.toml14
l---------alacritty_config/LICENSE-APACHE1
l---------alacritty_config/LICENSE-MIT1
-rw-r--r--alacritty_config/src/lib.rs64
-rw-r--r--alacritty_config_derive/Cargo.toml8
l---------[-rw-r--r--]alacritty_config_derive/LICENSE-MIT24
-rw-r--r--alacritty_config_derive/src/config_deserialize/de_enum.rs (renamed from alacritty_config_derive/src/de_enum.rs)11
-rw-r--r--alacritty_config_derive/src/config_deserialize/de_struct.rs (renamed from alacritty_config_derive/src/de_struct.rs)69
-rw-r--r--alacritty_config_derive/src/config_deserialize/mod.rs22
-rw-r--r--alacritty_config_derive/src/lib.rs80
-rw-r--r--alacritty_config_derive/src/serde_replace.rs113
-rw-r--r--alacritty_config_derive/tests/config.rs40
-rw-r--r--alacritty_terminal/Cargo.toml23
-rw-r--r--alacritty_terminal/src/config/mod.rs17
-rw-r--r--alacritty_terminal/src/config/scrolling.rs4
-rw-r--r--alacritty_terminal/src/index.rs16
-rw-r--r--alacritty_terminal/src/term/color.rs12
-rw-r--r--alacritty_terminal/src/term/mod.rs8
-rw-r--r--alacritty_terminal/src/tty/unix.rs9
-rw-r--r--alacritty_terminal/src/tty/windows/child.rs23
-rw-r--r--alacritty_terminal/src/tty/windows/conpty.rs48
-rw-r--r--alacritty_terminal/src/tty/windows/mod.rs2
-rw-r--r--extra/alacritty-msg.man29
-rw-r--r--extra/alacritty.man8
l---------extra/alacritty.yml1
-rw-r--r--extra/completions/_alacritty17
-rw-r--r--extra/completions/alacritty.bash27
-rw-r--r--extra/completions/alacritty.fish12
-rw-r--r--extra/osx/Alacritty.app/Contents/Info.plist2
l---------extra/windows1
66 files changed, 1596 insertions, 657 deletions
diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml
index 6bf947b7..1d16087b 100644
--- a/.github/workflows/release.yml
+++ b/.github/workflows/release.yml
@@ -50,7 +50,7 @@ jobs:
- name: Crate msi installer
run: |
./WiX.*/tools/candle.exe -nologo -arch "x64" -ext WixUIExtension -ext WixUtilExtension \
- -out "./alacritty.wixobj" "extra/windows/wix/alacritty.wxs"
+ -out "./alacritty.wixobj" "alacritty/windows/wix/alacritty.wxs"
./WiX.*/tools/light.exe -nologo -ext WixUIExtension -ext WixUtilExtension \
-out "./Alacritty-${GITHUB_REF##*/}-installer.msi" -sice:ICE61 -sice:ICE91 \
"./alacritty.wixobj"
diff --git a/CHANGELOG.md b/CHANGELOG.md
index f93e326d..129822ba 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -5,7 +5,9 @@ The sections should follow the order `Packaging`, `Added`, `Changed`, `Fixed` an
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
-## 0.11.0-dev
+## 0.12.0-dev
+
+## 0.11.0
### Packaging
@@ -27,9 +29,12 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
- Config option `cursor.blink_timeout` to timeout cursor blinking after inactivity
- Escape sequence to set hyperlinks (`OSC 8 ; params ; URI ST`)
- Config `hints.enabled.hyperlinks` for hyperlink escape sequence hint highlight
+- `window.decorations_theme_variant` to control both Wayland CSD and GTK theme variant on X11
+- Support for inline input method
### Changed
+- No longer renders to macos and x11 windows that are fully occluded / not directly visible
- The `--help` output was reworked with a new colorful syntax
- OSC 52 is now disabled on unfocused windows
- `SpawnNewInstance` no longer inherits initial `--command`
@@ -37,6 +42,13 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
- Deprecated `colors.search.bar`, use `colors.footer_bar` instead
- On macOS, Alacritty now reads `AppleFontSmoothing` from user defaults to control font smoothing
- Warn when either `columns` or `lines` is non-zero, but not both
+- Client side decorations should have proper text rendering now on Wayland
+- Config option `window.gtk_theme_variant`, you should use `window.decorations_theme_variant` instead
+- `--class` now sets both class part of WM_CLASS property and instance
+- `--class`'s `general` and `instance` options were swapped
+- Search bar is now respecting cursor thickness
+- On X11 the IME popup window is stuck at the bottom of the window due to Xlib limitations
+- IME no longer works in Vi mode when moving around
### Fixed
@@ -56,6 +68,13 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
- On macOS, `font.use_thin_strokes` did not work since Big Sur
- On macOS, trying to load a disabled font would crash
- On macOS, Alacritty sessions did not appear in the list of tty sessions for `w` and `who`
+- Cursor not hiding on GNOME Wayland
+- Font having different scale factor after monitor powering off/on on X11
+- Viewport not updating after opening a new tabbed window on macOS
+- Terminal not exiting sometimes after closing all windows on macOS
+- CPU usage spikes due to mouse movements for unfocused windows on X11/Windows
+- First window on macOS not tabbed with system prefer tabs setting
+- Window being treaten as focused by default on Wayland
### Removed
diff --git a/Cargo.lock b/Cargo.lock
index d37c730d..b81d0a9f 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -3,15 +3,16 @@
version = 3
[[package]]
-name = "adler32"
-version = "1.2.0"
+name = "adler"
+version = "1.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "aae1277d39aeec15cb388266ecc24b11c80469deae6067e17a1a7aa9e5c1f234"
+checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe"
[[package]]
name = "alacritty"
-version = "0.11.0-dev"
+version = "0.12.0-dev"
dependencies = [
+ "alacritty_config",
"alacritty_config_derive",
"alacritty_terminal",
"bitflags",
@@ -31,24 +32,34 @@ dependencies = [
"notify",
"objc",
"once_cell",
- "parking_lot",
+ "parking_lot 0.12.1",
"png",
- "raw-window-handle",
+ "raw-window-handle 0.5.0",
"serde",
"serde_json",
"serde_yaml",
"smallvec",
"unicode-width",
"wayland-client",
- "winapi 0.3.9",
+ "windows-sys",
"x11-dl",
"xdg",
]
[[package]]
+name = "alacritty_config"
+version = "0.1.1-dev"
+dependencies = [
+ "log",
+ "serde",
+ "serde_yaml",
+]
+
+[[package]]
name = "alacritty_config_derive"
-version = "0.1.0"
+version = "0.2.1-dev"
dependencies = [
+ "alacritty_config",
"log",
"proc-macro2",
"quote",
@@ -59,8 +70,9 @@ dependencies = [
[[package]]
name = "alacritty_terminal"
-version = "0.17.0-dev"
+version = "0.17.1-dev"
dependencies = [
+ "alacritty_config",
"alacritty_config_derive",
"base64",
"bitflags",
@@ -72,7 +84,7 @@ dependencies = [
"mio-extras",
"miow 0.3.7",
"nix",
- "parking_lot",
+ "parking_lot 0.12.1",
"regex-automata",
"serde",
"serde_json",
@@ -82,14 +94,20 @@ dependencies = [
"smallvec",
"unicode-width",
"vte",
- "winapi 0.3.9",
+ "windows-sys",
]
[[package]]
-name = "android_glue"
-version = "0.2.3"
+name = "arrayref"
+version = "0.3.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a4c527152e37cf757a3f78aae5a06fbeefdb07ccc535c980a3208ee3060dd544"
+
+[[package]]
+name = "arrayvec"
+version = "0.5.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "000444226fcff248f2bc4c7625be32c63caccfecc2723a2b9f78a7487a49c407"
+checksum = "23b62fc65de8e4e7f52534fb52b0f3ed04746ae267519eef2a83941e8085068b"
[[package]]
name = "atty"
@@ -128,18 +146,27 @@ checksum = "0d8c1fef690941d3e7788d328517591fecc684c084084702d6ff1641e993699a"
[[package]]
name = "bumpalo"
-version = "3.10.0"
+version = "3.11.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c1ad822118d20d2c234f427000d5acc36eabe1e29a348c89b63dd60b13f28e5d"
+
+[[package]]
+name = "bytemuck"
+version = "1.12.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "37ccbd214614c6783386c1af30caf03192f17891059cecc394b4fb119e363de3"
+checksum = "2f5715e491b5a1598fc2bef5a606847b5dc1d48ea625bd3c02c00de8285591da"
[[package]]
name = "calloop"
-version = "0.9.3"
+version = "0.10.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "bf2eec61efe56aa1e813f5126959296933cf0700030e4314786c48779a66ab82"
+checksum = "a22a6a8f622f797120d452c630b0ab12e1331a1a753e2039ce7868d4ac77b4ee"
dependencies = [
"log",
"nix",
+ "slotmap",
+ "thiserror",
+ "vec_map",
]
[[package]]
@@ -171,9 +198,9 @@ dependencies = [
[[package]]
name = "clap"
-version = "3.2.5"
+version = "3.2.21"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d53da17d37dba964b9b3ecb5c5a1f193a2762c700e6829201e645b9381c99dc7"
+checksum = "1ed5341b2301a26ab80be5cbdced622e80ed808483c52e45e3310a877d3b37d7"
dependencies = [
"atty",
"bitflags",
@@ -188,18 +215,18 @@ dependencies = [
[[package]]
name = "clap_complete"
-version = "3.2.1"
+version = "3.2.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0f6ebaab5f25e4f0312dfa07cb30a755204b96e6531457c2cfdecfdf5f2adf40"
+checksum = "3f7a2e0a962c45ce25afce14220bc24f9dade0a1787f185cecf96bfba7847cd8"
dependencies = [
"clap",
]
[[package]]
name = "clap_derive"
-version = "3.2.5"
+version = "3.2.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c11d40217d16aee8508cc8e5fde8b4ff24639758608e5374e731b53f85749fb9"
+checksum = "ea0c8bce528c4be4da13ea6fead8965e95b6073585a2f05204bd8f4119f82a65"
dependencies = [
"heck",
"proc-macro-error",
@@ -210,9 +237,9 @@ dependencies = [
[[package]]
name = "clap_lex"
-version = "0.2.2"
+version = "0.2.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5538cd660450ebeb4234cfecf8f2284b844ffc4c50531e66d584ad5b91293613"
+checksum = "2850f2f5a82cbf437dd5af4d49848fbdfc27c157c3d010345776f952765261c5"
dependencies = [
"os_str_bytes",
]
@@ -245,8 +272,8 @@ dependencies = [
"bitflags",
"block",
"cocoa-foundation",
- "core-foundation 0.9.3",
- "core-graphics 0.22.3",
+ "core-foundation",
+ "core-graphics",
"foreign-types 0.3.2",
"libc",
"objc",
@@ -260,7 +287,7 @@ checksum = "7ade49b65d560ca58c403a479bb396592b155c0185eada742ee323d1d68d6318"
dependencies = [
"bitflags",
"block",
- "core-foundation 0.9.3",
+ "core-foundation",
"core-graphics-types",
"foreign-types 0.3.2",
"libc",
@@ -283,56 +310,28 @@ dependencies = [
[[package]]
name = "core-foundation"
-version = "0.7.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "57d24c7a13c43e870e37c1556b74555437870a04514f7685f5b354e090567171"
-dependencies = [
- "core-foundation-sys 0.7.0",
- "libc",
-]
-
-[[package]]
-name = "core-foundation"
version = "0.9.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "194a7a9e6de53fa55116934067c844d9d749312f75c6f6d0980e8c252f8c2146"
dependencies = [
- "core-foundation-sys 0.8.3",
+ "core-foundation-sys",
"libc",
]
[[package]]
name = "core-foundation-sys"
-version = "0.7.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b3a71ab494c0b5b860bdc8407ae08978052417070c2ced38573a9157ad75b8ac"
-
-[[package]]
-name = "core-foundation-sys"
version = "0.8.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5827cebf4670468b8772dd191856768aedcb1b0278a04f989f7766351917b9dc"
[[package]]
name = "core-graphics"
-version = "0.19.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b3889374e6ea6ab25dba90bb5d96202f61108058361f6dc72e8b03e6f8bbe923"
-dependencies = [
- "bitflags",
- "core-foundation 0.7.0",
- "foreign-types 0.3.2",
- "libc",
-]
-
-[[package]]
-name = "core-graphics"
version = "0.22.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2581bbab3b8ffc6fcbd550bf46c355135d16e9ff2a6ea032ad6b9bf1d7efe4fb"
dependencies = [
"bitflags",
- "core-foundation 0.9.3",
+ "core-foundation",
"core-graphics-types",
"foreign-types 0.3.2",
"libc",
@@ -345,7 +344,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3a68b68b3446082644c91ac778bf50cd4104bfb002b5a6a7c44cca5a2c70788b"
dependencies = [
"bitflags",
- "core-foundation 0.9.3",
+ "core-foundation",
"foreign-types 0.3.2",
"libc",
]
@@ -356,26 +355,13 @@ version = "19.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "99d74ada66e07c1cefa18f8abfba765b486f250de2e4a999e5727fc0dd4b4a25"
dependencies = [
- "core-foundation 0.9.3",
- "core-graphics 0.22.3",
+ "core-foundation",
+ "core-graphics",
"foreign-types 0.3.2",
"libc",
]
[[package]]
-name = "core-video-sys"
-version = "0.1.4"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "34ecad23610ad9757664d644e369246edde1803fcb43ed72876565098a5d3828"
-dependencies = [
- "cfg-if 0.1.10",
- "core-foundation-sys 0.7.0",
- "core-graphics 0.19.2",
- "libc",
- "objc",
-]
-
-[[package]]
name = "crc32fast"
version = "1.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -391,9 +377,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f66b1c1979c4362323f03ab6bf7fb522902bfc418e0c37319ab347f9561d980f"
dependencies = [
"cocoa",
- "core-foundation 0.9.3",
- "core-foundation-sys 0.8.3",
- "core-graphics 0.22.3",
+ "core-foundation",
+ "core-foundation-sys",
+ "core-graphics",
"core-text",
"dwrote",
"foreign-types 0.5.0",
@@ -505,9 +491,9 @@ dependencies = [
[[package]]
name = "embed-resource"
-version = "1.7.2"
+version = "1.7.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ecc24ff8d764818e9ab17963b0593c535f077a513f565e75e4352d758bc4d8c0"
+checksum = "936c1354206a875581696369aef920e12396e93bbd251c43a7a3f3fa85023a7d"
dependencies = [
"cc",
"rustc_version",
@@ -528,14 +514,24 @@ dependencies = [
[[package]]
name = "filetime"
-version = "0.2.16"
+version = "0.2.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c0408e2626025178a6a7f7ffc05a25bc47103229f19c113755de7bf63816290c"
+checksum = "e94a7bbaa59354bc20dd75b67f23e2797b4490e9d6928203fb105c79e448c86c"
dependencies = [
"cfg-if 1.0.0",
"libc",
"redox_syscall",
- "winapi 0.3.9",
+ "windows-sys",
+]
+
+[[package]]
+name = "flate2"
+version = "1.0.24"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f82b0f4c27ad9f8bfd1f3208d882da2b09c301bc1c828fd3a00d0216d2fbbff6"
+dependencies = [
+ "crc32fast",
+ "miniz_oxide",
]
[[package]]
@@ -667,25 +663,24 @@ dependencies = [
[[package]]
name = "glutin"
-version = "0.28.0"
+version = "0.29.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "00ea9dbe544bc8a657c4c4a798c2d16cd01b549820e47657297549d28371f6d2"
+checksum = "444c9ad294fdcaf20ccf6726b78f380b5450275540c9b68ab62f49726ad1c713"
dependencies = [
- "android_glue",
"cgl",
"cocoa",
- "core-foundation 0.9.3",
+ "core-foundation",
"glutin_egl_sys",
- "glutin_emscripten_sys",
"glutin_gles2_sys",
"glutin_glx_sys",
"glutin_wgl_sys",
- "lazy_static",
"libloading",
"log",
"objc",
+ "once_cell",
"osmesa-sys",
- "parking_lot",
+ "parking_lot 0.12.1",
+ "raw-window-handle 0.5.0",
"wayland-client",
"wayland-egl",
"winapi 0.3.9",
@@ -694,21 +689,15 @@ dependencies = [
[[package]]
name = "glutin_egl_sys"
-version = "0.1.5"
+version = "0.1.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2abb6aa55523480c4adc5a56bbaa249992e2dddb2fc63dc96e04a3355364c211"
+checksum = "68900f84b471f31ea1d1355567eb865a2cf446294f06cef8d653ed7bcf5f013d"
dependencies = [
"gl_generator",
"winapi 0.3.9",
]
[[package]]
-name = "glutin_emscripten_sys"
-version = "0.1.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "80de4146df76e8a6c32b03007bc764ff3249dcaeb4f675d68a06caf1bac363f1"
-
-[[package]]
name = "glutin_gles2_sys"
version = "0.1.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -720,9 +709,9 @@ dependencies = [
[[package]]
name = "glutin_glx_sys"
-version = "0.1.7"
+version = "0.1.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7e393c8fc02b807459410429150e9c4faffdb312d59b8c038566173c81991351"
+checksum = "d93d0575865098580c5b3a423188cd959419912ea60b1e48e8b3b526f6d02468"
dependencies = [
"gl_generator",
"x11-dl",
@@ -739,9 +728,9 @@ dependencies = [
[[package]]
name = "hashbrown"
-version = "0.12.1"
+version = "0.12.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "db0d4cf898abf0081f964436dc980e96670a0f36863e4b83aaacdb65c9d7ccc3"
+checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888"
[[package]]
name = "heck"
@@ -766,9 +755,9 @@ checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39"
[[package]]
name = "indexmap"
-version = "1.9.0"
+version = "1.9.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6c6392766afd7964e2531940894cffe4bd8d7d17dbc3c1c4857040fd4b33bdb3"
+checksum = "10a35a97730320ffe8e2d410b5d3b69279b98d2c14bdb8b70ea89ecf7888d41e"
dependencies = [
"autocfg",
"hashbrown",
@@ -817,9 +806,9 @@ dependencies = [
[[package]]
name = "itoa"
-version = "1.0.2"
+version = "1.0.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "112c678d4050afce233f4f2852bb2eb519230b3cf12f33585275537d7e41578d"
+checksum = "6c8af84674fe1f223a982c933a0ee1086ac4d4052aa0fb8060c12c6ad838e754"
[[package]]
name = "jni-sys"
@@ -829,9 +818,9 @@ checksum = "8eaf4bc02d17cbdd7ff4c7438cafcdf7fb9a4613313ad11b4f8fefe7d3fa0130"
[[package]]
name = "js-sys"
-version = "0.3.58"
+version = "0.3.60"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c3fac17f7123a73ca62df411b1bf727ccc805daa070338fda671c86dac1bdc27"
+checksum = "49409df3e3bf0856b916e2ceaca09ee28e6871cf7d9ce97a692cacfdb2a25a47"
dependencies = [
"wasm-bindgen",
]
@@ -872,9 +861,9 @@ checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55"
[[package]]
name = "libc"
-version = "0.2.126"
+version = "0.2.132"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "349d5a591cd28b49e1d1037471617a32ddcda5731b99419008085f72d5a53836"
+checksum = "8371e4e5341c3a96db127eb2465ac681ced4c433e01dd0e938adbef26ba93ba5"
[[package]]
name = "libloading"
@@ -888,15 +877,15 @@ dependencies = [
[[package]]
name = "linked-hash-map"
-version = "0.5.4"
+version = "0.5.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7fb9b38af92608140b86b693604b9ffcc5824240a484d1ecd4795bacb2fe88f3"
+checksum = "0717cef1bc8b636c6e1c1bbdefc09e6322da8a9321966e8928ef80d20f7f770f"
[[package]]
name = "lock_api"
-version = "0.4.7"
+version = "0.4.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "327fa5b6a6940e4699ec49a9beae1ea4845c6bab9314e4f84ac68742139d8c53"
+checksum = "9f80bf5aacaf25cbfc8210d1cfb718f2bf3b11c4c54e5afe36c236853a8ec390"
dependencies = [
"autocfg",
"scopeguard",
@@ -929,9 +918,9 @@ checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d"
[[package]]
name = "memmap2"
-version = "0.3.1"
+version = "0.5.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "00b6c2ebff6180198788f5db08d7ce3bc1d0b617176678831a7510825973e357"
+checksum = "95af15f345b17af2efc8ead6080fb8bc376f8cec1b35277b935637595fe77498"
dependencies = [
"libc",
]
@@ -953,11 +942,11 @@ checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a"
[[package]]
name = "miniz_oxide"
-version = "0.3.7"
+version = "0.5.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "791daaae1ed6889560f8c4359194f56648355540573244a5448a83ba1ecc7435"
+checksum = "96590ba8f175222643a85693f33d26e9c8a015f599c216509b1a6894af675d34"
dependencies = [
- "adler32",
+ "adler",
]
[[package]]
@@ -981,9 +970,9 @@ dependencies = [
[[package]]
name = "mio"
-version = "0.8.3"
+version = "0.8.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "713d550d9b44d89174e066b7a6217ae06234c10cb47819a88290d2b353c31799"
+checksum = "57ee1c23c7c63b0c9250c339ffdc69255f110b298b901b9f6c82547b7b87caaf"
dependencies = [
"libc",
"log",
@@ -999,7 +988,7 @@ checksum = "6bc513025fe5005a3aa561b50fdb2cda5a150b84800ae02acd8aa9ed62ca1a6b"
dependencies = [
"mio 0.6.23",
"miow 0.3.7",
- "parking_lot",
+ "parking_lot 0.11.2",
"spsc-buffer",
"winapi 0.3.9",
]
@@ -1050,14 +1039,15 @@ dependencies = [
[[package]]
name = "ndk"
-version = "0.5.0"
+version = "0.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "96d868f654c72e75f8687572699cdabe755f03effbb62542768e995d5b8d699d"
+checksum = "451422b7e4718271c8b5b3aadf5adedba43dc76312454b387e98fae0fc951aa0"
dependencies = [
"bitflags",
"jni-sys",
"ndk-sys",
"num_enum",
+ "raw-window-handle 0.5.0",
"thiserror",
]
@@ -1069,17 +1059,18 @@ checksum = "27b02d87554356db9e9a873add8782d4ea6e3e58ea071a9adb9a2e8ddb884a8b"
[[package]]
name = "ndk-glue"
-version = "0.5.2"
+version = "0.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c71bee8ea72d685477e28bd004cfe1bf99c754d688cd78cad139eae4089484d4"
+checksum = "0434fabdd2c15e0aab768ca31d5b7b333717f03cf02037d5a0a3ff3c278ed67f"
dependencies = [
- "lazy_static",
"libc",
"log",
"ndk",
"ndk-context",
"ndk-macro",
"ndk-sys",
+ "once_cell",
+ "parking_lot 0.12.1",
]
[[package]]
@@ -1097,9 +1088,12 @@ dependencies = [
[[package]]
name = "ndk-sys"
-version = "0.2.2"
+version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e1bcdd74c20ad5d95aacd60ef9ba40fdf77f767051040541df557b7a9b2a2121"
+checksum = "21d83ec9c63ec5bf950200a8e508bdad6659972187b625469f58ef8c08e29046"
+dependencies = [
+ "jni-sys",
+]
[[package]]
name = "net2"
@@ -1114,12 +1108,11 @@ dependencies = [
[[package]]
name = "nix"
-version = "0.22.3"
+version = "0.24.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e4916f159ed8e5de0082076562152a76b7a1f64a01fd9d1e0fea002c37624faf"
+checksum = "195cdbc1741b8134346d515b3a56a1c94b0912758009cfd53f99ea0f57b065fc"
dependencies = [
"bitflags",
- "cc",
"cfg-if 1.0.0",
"libc",
"memoffset",
@@ -1205,15 +1198,15 @@ dependencies = [
[[package]]
name = "once_cell"
-version = "1.12.0"
+version = "1.14.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7709cef83f0c1f58f666e746a08b21e0085f7440fa6a29cc194d68aac97a4225"
+checksum = "2f7254b99e31cad77da24b08ebf628882739a608578bb1bcdfc1f9c21260d7c0"
[[package]]
name = "os_str_bytes"
-version = "6.1.0"
+version = "6.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "21326818e99cfe6ce1e524c2a805c189a99b5ae555a35d19f9a284b427d86afa"
+checksum = "9ff7415e9ae3fff1225851df9e0d9e4e5479f947619774677a63572e55e80eff"
[[package]]
name = "osmesa-sys"
@@ -1232,7 +1225,17 @@ checksum = "7d17b78036a60663b797adeaee46f5c9dfebb86948d1255007a1d6be0271ff99"
dependencies = [
"instant",
"lock_api",
- "parking_lot_core",
+ "parking_lot_core 0.8.5",
+]
+
+[[package]]
+name = "parking_lot"
+version = "0.12.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3742b2c103b9f06bc9fff0a37ff4912935851bee6d36f3c02bcc755bcfec228f"
+dependencies = [
+ "lock_api",
+ "parking_lot_core 0.9.3",
]
[[package]]
@@ -1250,10 +1253,23 @@ dependencies = [
]
[[package]]
+name = "parking_lot_core"
+version = "0.9.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "09a279cbf25cb0757810394fbc1e359949b59e348145c643a939a525692e6929"
+dependencies = [
+ "cfg-if 1.0.0",
+ "libc",
+ "redox_syscall",
+ "smallvec",
+ "windows-sys",
+]
+
+[[package]]
name = "percent-encoding"
-version = "2.1.0"
+version = "2.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d4fd5641d01c8f18a23da7b6fe29298ff4b55afcccdf78973b24cf3175fee32e"
+checksum = "478c572c3d73181ff3c2539045f6eb99e5491218eae919370993b890cdbdd98e"
[[package]]
name = "pkg-config"
@@ -1263,21 +1279,23 @@ checksum = "1df8c4ec4b0627e53bdf214615ad287367e482558cf84b109250b37464dc03ae"
[[package]]
name = "png"
-version = "0.16.8"
+version = "0.17.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3c3287920cb847dee3de33d301c463fba14dda99db24214ddf93f83d3021f4c6"
+checksum = "8f0e7f4c94ec26ff209cee506314212639d6c91b80afb82984819fafce9df01c"
dependencies = [
"bitflags",
"crc32fast",
+ "flate2",
"miniz_oxide",
]
[[package]]
name = "proc-macro-crate"
-version = "1.1.3"
+version = "1.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e17d47ce914bf4de440332250b0edd23ce48c005f59fab39d3335866b114f11a"
+checksum = "eda0fc3b0fb7c975631757e14d9049da17374063edb6ebbcbc54d880d4fe94e9"
dependencies = [
+ "once_cell",
"thiserror",
"toml",
]
@@ -1308,9 +1326,9 @@ dependencies = [
[[package]]
name = "proc-macro2"
-version = "1.0.39"
+version = "1.0.43"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c54b25569025b7fc9651de43004ae593a75ad88543b17178aa5e1b9c4f15f56f"
+checksum = "0a2ca2c61bc9f3d74d2886294ab7b9853abd9c1ad903a3ac7815c58989bb7bab"
dependencies = [
"unicode-ident",
]
@@ -1326,9 +1344,9 @@ dependencies = [
[[package]]
name = "quote"
-version = "1.0.18"
+version = "1.0.21"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a1feb54ed693b93a84e14094943b84b7c4eae204c512b7ccb95ab0c66d278ad1"
+checksum = "bbe448f377a7d6961e30f5955f9b8d106c3f5e449d493ee1b125c1d43c2b5179"
dependencies = [
"proc-macro2",
]
@@ -1343,10 +1361,19 @@ dependencies = [
]
[[package]]
+name = "raw-window-handle"
+version = "0.5.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ed7e3d950b66e19e0c372f3fa3fbbcf85b1746b571f74e0c2af6042a5c93420a"
+dependencies = [
+ "cty",
+]
+
+[[package]]
name = "redox_syscall"
-version = "0.2.13"
+version = "0.2.16"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "62f25bc4c7e55e0b0b7a1d43fb893f4fa1361d0abe38b9ce4f323c2adfe6ef42"
+checksum = "fb5a58c1855b4b6819d59012155603f0b22ad30cad752600aadfcb695265519a"
dependencies = [
"bitflags",
]
@@ -1373,9 +1400,9 @@ dependencies = [
[[package]]
name = "regex-syntax"
-version = "0.6.26"
+version = "0.6.27"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "49b3de9ec5dc0a3417da371aab17d729997c15010e7fd24ff707773a33bddb64"
+checksum = "a3f87b73ce11b1619a3c6332f45341e0047173771e8b8b73f87bfeefb7b56244"
[[package]]
name = "rustc_version"
@@ -1388,9 +1415,18 @@ dependencies = [
[[package]]
name = "ryu"
-version = "1.0.10"
+version = "1.0.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f3f6f92acf49d1b98f7a81226834412ada05458b7364277387724a237f062695"
+checksum = "4501abdff3ae82a1c1b477a17252eb69cee9e66eb915c1abaa4f44d873df9f09"
+
+[[package]]
+name = "safe_arch"
+version = "0.5.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c1ff3d6d9696af502cc3110dacce942840fb06ff4514cad92236ecc455f2ce05"
+dependencies = [
+ "bytemuck",
+]
[[package]]
name = "same-file"
@@ -1414,25 +1450,37 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd"
[[package]]
+name = "sctk-adwaita"
+version = "0.4.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "04b7c47a572f73de28bee5b5060d085b42b6ce1e4ee2b49c956ea7b25e94b6f0"
+dependencies = [
+ "crossfont",
+ "log",
+ "smithay-client-toolkit",
+ "tiny-skia",
+]
+
+[[package]]
name = "semver"
-version = "1.0.10"
+version = "1.0.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a41d061efea015927ac527063765e73601444cdc344ba855bc7bd44578b25e1c"
+checksum = "e25dfac463d778e353db5be2449d1cce89bd6fd23c9f1ea21310ce6e5a1b29c4"
[[package]]
name = "serde"
-version = "1.0.137"
+version = "1.0.144"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "61ea8d54c77f8315140a05f4c7237403bf38b72704d031543aa1d16abbf517d1"
+checksum = "0f747710de3dcd43b88c9168773254e809d8ddbdf9653b84e2554ab219f17860"
dependencies = [
"serde_derive",
]
[[package]]
name = "serde_derive"
-version = "1.0.137"
+version = "1.0.144"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1f26faba0c3959972377d3b2d306ee9f71faee9714294e41bb777f83f88578be"
+checksum = "94ed3a816fb1d101812f83e789f888322c34e291f894f19590dc310963e87a00"
dependencies = [
"proc-macro2",
"quote",
@@ -1441,9 +1489,9 @@ dependencies = [
[[package]]
name = "serde_json"
-version = "1.0.81"
+version = "1.0.85"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9b7ce2b32a1aed03c558dc61a5cd328f15aff2dbc17daad8fb8af04d2100e15c"
+checksum = "e55a28e3aaef9d5ce0506d0a14dbba8054ddc7e499ef522dd8b26859ec9d4a44"
dependencies = [
"itoa",
"ryu",
@@ -1452,9 +1500,9 @@ dependencies = [
[[package]]
name = "serde_yaml"
-version = "0.8.24"
+version = "0.8.26"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "707d15895415db6628332b737c838b88c598522e4dc70647e59b72312924aebc"
+checksum = "578a7433b776b56a35785ed5ce9a7e777ac0598aac5a6dd1b4b18a307c7fc71b"
dependencies = [
"indexmap",
"ryu",
@@ -1526,9 +1574,21 @@ dependencies = [
[[package]]
name = "slab"
-version = "0.4.6"
+version = "0.4.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "eb703cfe953bccee95685111adeedb76fabe4e97549a58d16f03ea7b9367bb32"
+checksum = "4614a76b2a8be0058caa9dbbaf66d988527d86d003c11a94fbd335d7661edcef"
+dependencies = [
+ "autocfg",
+]
+
+[[package]]
+name = "slotmap"
+version = "1.0.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e1e08e261d0e8f5c43123b7adf3e4ca1690d655377ac93a03b2c9d3e98de1342"
+dependencies = [
+ "version_check",
+]
[[package]]
name = "smallvec"
@@ -1541,9 +1601,9 @@ dependencies = [
[[package]]
name = "smithay-client-toolkit"
-version = "0.15.4"
+version = "0.16.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8a28f16a97fa0e8ce563b2774d1e732dd5d4025d2772c5dba0a41a0f90a29da3"
+checksum = "f307c47d32d2715eb2e0ece5589057820e0e5e70d07c247d1063e844e107f454"
dependencies = [
"bitflags",
"calloop",
@@ -1560,9 +1620,9 @@ dependencies = [
[[package]]
name = "smithay-clipboard"
-version = "0.6.5"
+version = "0.6.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "610b551bd25378bfd2b8e7a0fcbd83d427e8f2f6a40c47ae0f70688e9949dd55"
+checksum = "0a345c870a1fae0b1b779085e81b51e614767c239e93503588e54c5b17f4b0e8"
dependencies = [
"smithay-client-toolkit",
"wayland-client",
@@ -1582,9 +1642,9 @@ checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623"
[[package]]
name = "syn"
-version = "1.0.96"
+version = "1.0.99"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0748dd251e24453cb8717f0354206b91557e4ec8703673a4b30208f2abaf1ebf"
+checksum = "58dbef6ec655055e20b86b15a8cc6d439cca19b667537ac6a1369572d151ab13"
dependencies = [
"proc-macro2",
"quote",
@@ -1602,24 +1662,24 @@ dependencies = [
[[package]]
name = "textwrap"
-version = "0.15.0"
+version = "0.15.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b1141d4d61095b28419e22cb0bbf02755f5e54e0526f97f1e3d1d160e60885fb"
+checksum = "949517c0cf1bf4ee812e2e07e08ab448e3ae0d23472aee8a06c985f0c8815b16"
[[package]]
name = "thiserror"
-version = "1.0.31"
+version = "1.0.35"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "bd829fe32373d27f76265620b5309d0340cb8550f523c1dda251d6298069069a"
+checksum = "c53f98874615aea268107765aa1ed8f6116782501d18e53d08b471733bea6c85"
dependencies = [
"thiserror-impl",
]
[[package]]
name = "thiserror-impl"
-version = "1.0.31"
+version = "1.0.35"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0396bc89e626244658bef819e22d0cc459e795a5ebe878e6ec336d1674a8d79a"
+checksum = "f8b463991b4eab2d801e724172285ec4195c650e8ec79b149e6c2a8e6dd3f783"
dependencies = [
"proc-macro2",
"quote",
@@ -1627,25 +1687,50 @@ dependencies = [
]
[[package]]
+name = "tiny-skia"
+version = "0.7.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "642680569bb895b16e4b9d181c60be1ed136fa0c9c7f11d004daf053ba89bf82"
+dependencies = [
+ "arrayref",
+ "arrayvec",
+ "bytemuck",
+ "cfg-if 1.0.0",
+ "png",
+ "safe_arch",
+ "tiny-skia-path",
+]
+
+[[package]]
+name = "tiny-skia-path"
+version = "0.7.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c114d32f0c2ee43d585367cb013dfaba967ab9f62b90d9af0d696e955e70fa6c"
+dependencies = [
+ "arrayref",
+ "bytemuck",
+]
+
+[[package]]
name = "toml"
-version = "0.5.9"
+version = "0.5.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8d82e1a7758622a465f8cee077614c73484dac5b836c02ff6a40d5d1010324d7"
+checksum = "a31142970826733df8241ef35dc040ef98c679ab14d7c3e54d827099b3acecaa"
dependencies = [
"serde",
]
[[package]]
name = "unicode-ident"
-version = "1.0.1"
+version = "1.0.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5bd2fe26506023ed7b5e1e315add59d6f584c621d037f9368fea9cfb988f368c"
+checksum = "dcc811dc4066ac62f84f11307873c4850cb653bfa9b1719cee2bd2204a4bc5dd"
[[package]]
name = "unicode-width"
-version = "0.1.9"
+version = "0.1.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3ed742d4ea2bd1176e236172c8429aaf54486e7ac098db29ffe6529e0ce50973"
+checksum = "c0edd1e5b14653f783770bce4a4dabb4a5108a5370a5f5d8cfe8710c361f6c8b"
[[package]]
name = "utf8parse"
@@ -1654,6 +1739,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "936e4b492acfd135421d8dca4b1aa80a7bfc26e702ef3af710e0752684df5372"
[[package]]
+name = "vec_map"
+version = "0.8.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f1bddf1187be692e79c5ffeab891132dfb0f236ed36a43c7ed39f1165ee20191"
+
+[[package]]
name = "version_check"
version = "0.9.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -1718,9 +1809,9 @@ checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423"
[[package]]
name = "wasm-bindgen"
-version = "0.2.81"
+version = "0.2.83"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7c53b543413a17a202f4be280a7e5c62a1c69345f5de525ee64f8cfdbc954994"
+checksum = "eaf9f5aceeec8be17c128b2e93e031fb8a4d469bb9c4ae2d7dc1888b26887268"
dependencies = [
"cfg-if 1.0.0",
"wasm-bindgen-macro",
@@ -1728,13 +1819,13 @@ dependencies = [
[[package]]
name = "wasm-bindgen-backend"
-version = "0.2.81"
+version = "0.2.83"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5491a68ab4500fa6b4d726bd67408630c3dbe9c4fe7bda16d5c82a1fd8c7340a"
+checksum = "4c8ffb332579b0557b52d268b91feab8df3615f265d5270fec2a8c95b17c1142"
dependencies = [
"bumpalo",
- "lazy_static",
"log",
+ "once_cell",
"proc-macro2",
"quote",
"syn",
@@ -1743,9 +1834,9 @@ dependencies = [
[[package]]
name = "wasm-bindgen-macro"
-version = "0.2.81"
+version = "0.2.83"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c441e177922bc58f1e12c022624b6216378e5febc2f0533e41ba443d505b80aa"
+checksum = "052be0f94026e6cbc75cdefc9bae13fd6052cdcaf532fa6c45e7ae33a1e6c810"
dependencies = [
"quote",
"wasm-bindgen-macro-support",
@@ -1753,9 +1844,9 @@ dependencies = [
[[package]]
name = "wasm-bindgen-macro-support"
-version = "0.2.81"
+version = "0.2.83"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7d94ac45fcf608c1f45ef53e748d35660f168490c10b23704c7779ab8f5c3048"
+checksum = "07bc0c051dc5f23e307b13285f9d75df86bfdf816c5721e573dec1f9b8aa193c"
dependencies = [
"proc-macro2",
"quote",
@@ -1766,15 +1857,15 @@ dependencies = [
[[package]]
name = "wasm-bindgen-shared"
-version = "0.2.81"
+version = "0.2.83"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6a89911bd99e5f3659ec4acf9c4d93b0a90fe4a2a11f15328472058edc5261be"
+checksum = "1c38c045535d93ec4f0b4defec448e4291638ee608530863b1e2ba115d4fff7f"
[[package]]
name = "wayland-client"
-version = "0.29.4"
+version = "0.29.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "91223460e73257f697d9e23d401279123d36039a3f7a449e983f123292d4458f"
+checksum = "3f3b068c05a039c9f755f881dc50f01732214f5685e379829759088967c46715"
dependencies = [
"bitflags",
"downcast-rs",
@@ -1788,9 +1879,9 @@ dependencies = [
[[package]]
name = "wayland-commons"
-version = "0.29.4"
+version = "0.29.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "94f6e5e340d7c13490eca867898c4cec5af56c27a5ffe5c80c6fc4708e22d33e"
+checksum = "8691f134d584a33a6606d9d717b95c4fa20065605f798a3f350d78dced02a902"
dependencies = [
"nix",
"once_cell",
@@ -1800,9 +1891,9 @@ dependencies = [
[[package]]
name = "wayland-cursor"
-version = "0.29.4"
+version = "0.29.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c52758f13d5e7861fc83d942d3d99bf270c83269575e52ac29e5b73cb956a6bd"
+checksum = "6865c6b66f13d6257bef1cd40cbfe8ef2f150fb8ebbdb1e8e873455931377661"
dependencies = [
"nix",
"wayland-client",
@@ -1811,9 +1902,9 @@ dependencies = [
[[package]]
name = "wayland-egl"
-version = "0.29.4"
+version = "0.29.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "83281d69ee162b59031c666385e93bde4039ec553b90c4191cdb128ceea29a3a"
+checksum = "402de949f81a012926d821a2d659f930694257e76dd92b6e0042ceb27be4107d"
dependencies = [
"wayland-client",
"wayland-sys",
@@ -1821,9 +1912,9 @@ dependencies = [
[[package]]
name = "wayland-protocols"
-version = "0.29.4"
+version = "0.29.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "60147ae23303402e41fe034f74fb2c35ad0780ee88a1c40ac09a3be1e7465741"
+checksum = "b950621f9354b322ee817a23474e479b34be96c2e909c14f7bc0100e9a970bc6"
dependencies = [
"bitflags",
"wayland-client",
@@ -1833,9 +1924,9 @@ dependencies = [
[[package]]
name = "wayland-scanner"
-version = "0.29.4"
+version = "0.29.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "39a1ed3143f7a143187156a2ab52742e89dac33245ba505c17224df48939f9e0"
+checksum = "8f4303d8fa22ab852f789e75a967f0a2cdc430a607751c0499bada3e451cbd53"
dependencies = [
"proc-macro2",
"quote",
@@ -1844,9 +1935,9 @@ dependencies = [
[[package]]
name = "wayland-sys"
-version = "0.29.4"
+version = "0.29.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d9341df79a8975679188e37dab3889bfa57c44ac2cb6da166f519a81cbe452d4"
+checksum = "be12ce1a3c39ec7dba25594b97b42cb3195d54953ddb9d3d95a7c3902bc6e9d4"
dependencies = [
"dlib",
"lazy_static",
@@ -1855,9 +1946,9 @@ dependencies = [
[[package]]
name = "web-sys"
-version = "0.3.58"
+version = "0.3.60"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2fed94beee57daf8dd7d51f2b15dc2bcde92d7a72304cdf662a4371008b71b90"
+checksum = "bcda906d8be16e728fd5adc5b729afad4e444e106ab28cd1c7256e54fa61510f"
dependencies = [
"js-sys",
"wasm-bindgen",
@@ -1951,35 +2042,35 @@ checksum = "c811ca4a8c853ef420abd8592ba53ddbbac90410fab6903b3e79972a631f7680"
[[package]]
name = "winit"
-version = "0.26.1"
+version = "0.27.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9b43cc931d58b99461188607efd7acb2a093e65fc621f54cad78517a6063e73a"
+checksum = "37f64802920c4c35d12a53dad5e0c55bbc3004d8dc4f2e4dd64ad02c5665d7aa"
dependencies = [
"bitflags",
"cocoa",
- "core-foundation 0.9.3",
- "core-graphics 0.22.3",
- "core-video-sys",
+ "core-foundation",
+ "core-graphics",
"dispatch",
"instant",
- "lazy_static",
"libc",
"log",
- "mio 0.8.3",
+ "mio 0.8.4",
"ndk",
"ndk-glue",
- "ndk-sys",
"objc",
- "parking_lot",
+ "once_cell",
+ "parking_lot 0.12.1",
"percent-encoding",
- "raw-window-handle",
+ "raw-window-handle 0.4.3",
+ "raw-window-handle 0.5.0",
+ "sctk-adwaita",
"serde",
"smithay-client-toolkit",
"wasm-bindgen",
"wayland-client",
"wayland-protocols",
"web-sys",
- "winapi 0.3.9",
+ "windows-sys",
"x11-dl",
]
@@ -2022,9 +2113,9 @@ dependencies = [
[[package]]
name = "x11-dl"
-version = "2.19.1"
+version = "2.20.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ea26926b4ce81a6f5d9d0f3a0bc401e5a37c6ae14a1bfaa8ff6099ca80038c59"
+checksum = "0c83627bc137605acc00bb399c7b908ef460b621fc37c953db2b09f88c449ea6"
dependencies = [
"lazy_static",
"libc",
diff --git a/Cargo.toml b/Cargo.toml
index 7a6dec80..aad21557 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -2,6 +2,7 @@
members = [
"alacritty",
"alacritty_terminal",
+ "alacritty_config",
"alacritty_config_derive",
]
diff --git a/INSTALL.md b/INSTALL.md
index 61f4a978..0a3a3bfc 100644
--- a/INSTALL.md
+++ b/INSTALL.md
@@ -118,6 +118,17 @@ yum install cmake freetype-devel fontconfig-devel libxcb-devel libxkbcommon-deve
yum group install "Development Tools"
```
+#### RHEL 8
+
+On RHEL 8, like RHEL 7, you need a few extra libraries to build Alacritty. Here's a `dnf`
+command that should install all of them. If something is still found to be
+missing, please open an issue.
+
+```sh
+dnf install cmake freetype-devel fontconfig-devel libxcb-devel libxkbcommon-devel
+dnf group install "Development Tools"
+```
+
#### openSUSE
On openSUSE, you need a few extra libraries to build Alacritty. Here's
diff --git a/LICENSE-MIT b/LICENSE-MIT
new file mode 100644
index 00000000..31aa7938
--- /dev/null
+++ b/LICENSE-MIT
@@ -0,0 +1,23 @@
+Permission is hereby granted, free of charge, to any
+person obtaining a copy of this software and associated
+documentation files (the "Software"), to deal in the
+Software without restriction, including without
+limitation the rights to use, copy, modify, merge,
+publish, distribute, sublicense, and/or sell copies of
+the Software, and to permit persons to whom the Software
+is furnished to do so, subject to the following
+conditions:
+
+The above copyright notice and this permission notice
+shall be included in all copies or substantial portions
+of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
+ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
+TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
+PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
+SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
+IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+DEALINGS IN THE SOFTWARE.
diff --git a/alacritty.yml b/alacritty.yml
index 0f7bb884..4e9de637 100644
--- a/alacritty.yml
+++ b/alacritty.yml
@@ -94,11 +94,12 @@
# General application class
#general: Alacritty
- # GTK theme variant (Linux/BSD only)
+ # Decorations theme variant (Linux/BSD only)
#
- # Override the variant of the GTK theme. Commonly supported values are `dark`
- # and `light`. Set this to `None` to use the default theme variant.
- #gtk_theme_variant: None
+ # Override the variant of the GTK theme/Wayland client side decorations.
+ # Commonly supported values are `dark` and `light`. Set this to `None` to use
+ # the default theme variant.
+ #decorations_theme_variant: None
#scrolling:
# Maximum number of lines in the scrollback buffer.
diff --git a/alacritty/Cargo.toml b/alacritty/Cargo.toml
index d17b1a0e..f6aebfe1 100644
--- a/alacritty/Cargo.toml
+++ b/alacritty/Cargo.toml
@@ -1,6 +1,6 @@
[package]
name = "alacritty"
-version = "0.11.0-dev"
+version = "0.12.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"
@@ -11,25 +11,29 @@ rust-version = "1.57.0"
[dependencies.alacritty_terminal]
path = "../alacritty_terminal"
-version = "0.17.0-dev"
+version = "0.17.1-dev"
default-features = false
[dependencies.alacritty_config_derive]
path = "../alacritty_config_derive"
-version = "0.1.0"
+version = "0.2.1-dev"
+
+[dependencies.alacritty_config]
+path = "../alacritty_config"
+version = "0.1.1-dev"
[dependencies]
-clap = { version = "3.0.0", features = ["derive"] }
+clap = { version = "3.0.0", features = ["derive", "env"] }
log = { version = "0.4", features = ["std", "serde"] }
fnv = "1"
serde = { version = "1", features = ["derive"] }
serde_yaml = "0.8"
serde_json = "1"
-glutin = { version = "0.28.0", default-features = false, features = ["serde"] }
+glutin = { version = "0.29.1", default-features = false, features = ["serde"] }
notify = "4"
-parking_lot = "0.11.0"
+parking_lot = "0.12.0"
crossfont = { version = "0.5.0", features = ["force_system_fontconfig"] }
-copypasta = { version = "0.8.0", default-features = false }
+copypasta = { version = "0.8.1", default-features = false }
libc = "0.2"
unicode-width = "0.1"
bitflags = "1"
@@ -48,10 +52,10 @@ clap_complete = "3.0.0"
xdg = "2.4.0"
[target.'cfg(not(target_os = "macos"))'.dependencies]
-png = { version = "0.16.8", default-features = false, optional = true }
+png = { version = "0.17.5", default-features = false, optional = true }
[target.'cfg(target_os = "macos")'.dependencies]
-raw-window-handle = "0.4.0"
+raw-window-handle = "0.5.0"
cocoa = "0.24.0"
objc = "0.2.2"
@@ -60,13 +64,23 @@ x11-dl = { version = "2", optional = true }
wayland-client = { version = "0.29.0", features = ["dlopen"], optional = true }
[target.'cfg(windows)'.dependencies]
-winapi = { version = "0.3.7", features = ["impl-default", "wincon"]}
+windows-sys = { version = "0.36", features = [
+ "Win32_UI_WindowsAndMessaging",
+ "Win32_System_Threading",
+ "Win32_System_Console",
+ "Win32_Foundation",
+]}
[target.'cfg(windows)'.build-dependencies]
-embed-resource = "1.3"
+embed-resource = "1.7.2"
[features]
default = ["wayland", "x11"]
x11 = ["copypasta/x11", "glutin/x11", "x11-dl", "png"]
-wayland = ["copypasta/wayland", "glutin/wayland", "glutin/wayland-dlopen", "wayland-client"]
+wayland = [
+ "copypasta/wayland",
+ "glutin/wayland",
+ "glutin/wayland-dlopen",
+ "glutin/wayland-csd-adwaita",
+ "wayland-client"]
nightly = []
diff --git a/alacritty/alacritty.png b/alacritty/alacritty.png
deleted file mode 120000
index 3865403a..00000000
--- a/alacritty/alacritty.png
+++ /dev/null
@@ -1 +0,0 @@
-../extra/logo/compat/alacritty-term.png \ No newline at end of file
diff --git a/alacritty/build.rs b/alacritty/build.rs
index e8cf8e3b..99a7549b 100644
--- a/alacritty/build.rs
+++ b/alacritty/build.rs
@@ -13,7 +13,7 @@ fn main() {
println!("cargo:rustc-env=VERSION={}", version);
let dest = env::var("OUT_DIR").unwrap();
- let mut file = File::create(&Path::new(&dest).join("gl_bindings.rs")).unwrap();
+ let mut file = File::create(Path::new(&dest).join("gl_bindings.rs")).unwrap();
let extensions = ["GL_ARB_blend_func_extended", "GL_ARB_clear_texture"];
Registry::new(Api::Gl, (3, 3), Profile::Core, Fallbacks::All, extensions)
@@ -21,12 +21,12 @@ fn main() {
.unwrap();
#[cfg(windows)]
- embed_resource::compile("./windows/windows.rc");
+ embed_resource::compile("./windows/alacritty.rc");
}
fn commit_hash() -> Option<String> {
Command::new("git")
- .args(&["rev-parse", "--short", "HEAD"])
+ .args(["rev-parse", "--short", "HEAD"])
.output()
.ok()
.filter(|output| output.status.success())
diff --git a/alacritty/extra b/alacritty/extra
new file mode 120000
index 00000000..858d6fa4
--- /dev/null
+++ b/alacritty/extra
@@ -0,0 +1 @@
+../extra \ No newline at end of file
diff --git a/alacritty/src/cli.rs b/alacritty/src/cli.rs
index 8872ec99..e7aae207 100644
--- a/alacritty/src/cli.rs
+++ b/alacritty/src/cli.rs
@@ -11,7 +11,7 @@ use serde_yaml::Value;
use alacritty_terminal::config::{Program, PtyConfig};
-use crate::config::window::{Class, Identity, DEFAULT_NAME};
+use crate::config::window::{Class, Identity};
use crate::config::{serde_utils, UiConfig};
/// CLI options for the main Alacritty executable.
@@ -81,14 +81,7 @@ impl Options {
let mut options = Self::parse();
// Convert `--option` flags into serde `Value`.
- for option in &options.option {
- match option_as_value(option) {
- Ok(value) => {
- options.config_options = serde_utils::merge(options.config_options, value);
- },
- Err(_) => eprintln!("Invalid CLI config option: {:?}", option),
- }
- }
+ options.config_options = options_as_value(&options.option);
options
}
@@ -132,7 +125,18 @@ impl Options {
}
}
-/// Format an option in the format of `parent.field=value` to a serde Value.
+/// Combine multiple options into a [`serde_yaml::Value`].
+pub fn options_as_value(options: &[String]) -> Value {
+ options.iter().fold(Value::default(), |value, option| match option_as_value(option) {
+ Ok(new_value) => serde_utils::merge(value, new_value),
+ Err(_) => {
+ eprintln!("Ignoring invalid option: {:?}", option);
+ value
+ },
+ })
+}
+
+/// Parse an option in the format of `parent.field=value` as a serde Value.
fn option_as_value(option: &str) -> Result<Value, serde_yaml::Error> {
let mut yaml_text = String::with_capacity(option.len());
let mut closing_brackets = String::new();
@@ -159,19 +163,16 @@ fn option_as_value(option: &str) -> Result<Value, serde_yaml::Error> {
/// Parse the class CLI parameter.
fn parse_class(input: &str) -> Result<Class, String> {
- match input.find(',') {
- Some(position) => {
- let general = input[position + 1..].to_owned();
-
- // Warn the user if they've passed too many values.
- if general.contains(',') {
- return Err(String::from("Too many parameters"));
- }
-
- Ok(Class { instance: input[..position].into(), general })
+ let (general, instance) = match input.split_once(',') {
+ // Warn the user if they've passed too many values.
+ Some((_, instance)) if instance.contains(',') => {
+ return Err(String::from("Too many parameters"))
},
- None => Ok(Class { instance: input.into(), general: DEFAULT_NAME.into() }),
- }
+ Some((general, instance)) => (general, instance),
+ None => (input, input),
+ };
+
+ Ok(Class::new(general, instance))
}
/// Convert to hex if possible, else decimal
@@ -269,7 +270,7 @@ pub enum Subcommands {
#[derive(Args, Debug)]
pub struct MessageOptions {
/// IPC socket connection path override.
- #[clap(long, short, value_hint = ValueHint::FilePath)]
+ #[clap(short, long, value_hint = ValueHint::FilePath)]
pub socket: Option<PathBuf>,
/// Message which should be sent.
@@ -283,9 +284,12 @@ pub struct MessageOptions {
pub enum SocketMessage {
/// Create a new window in the same Alacritty process.
CreateWindow(WindowOptions),
+
+ /// Update the Alacritty configuration.
+ Config(IpcConfig),
}
-/// Subset of options that we pass to a 'create-window' subcommand.
+/// Subset of options that we pass to 'create-window' IPC subcommand.
#[derive(Serialize, Deserialize, Args, Default, Clone, Debug, PartialEq, Eq)]
pub struct WindowOptions {
/// Terminal options which can be passed via IPC.
@@ -297,6 +301,25 @@ pub struct WindowOptions {
pub window_identity: WindowIdentity,
}
+/// Parameters to the `config` IPC subcommand.
+#[cfg(unix)]
+#[derive(Args, Serialize, Deserialize, Default, Debug, Clone, PartialEq, Eq)]
+pub struct IpcConfig {
+ /// Configuration file options [example: cursor.style=Beam].
+ #[clap(required = true, value_name = "CONFIG_OPTIONS")]
+ pub options: Vec<String>,
+
+ /// Window ID for the new config.
+ ///
+ /// Use `-1` to apply this change to all windows.
+ #[clap(short, long, allow_hyphen_values = true, env = "ALACRITTY_WINDOW_ID")]
+ pub window_id: Option<i128>,
+
+ /// Clear all runtime configuration changes.
+ #[clap(short, long, conflicts_with = "options")]
+ pub reset: bool,
+}
+
#[cfg(test)]
mod tests {
use super::*;
@@ -385,15 +408,15 @@ mod tests {
#[test]
fn parse_instance_class() {
let class = parse_class("one").unwrap();
+ assert_eq!(class.general, "one");
assert_eq!(class.instance, "one");
- assert_eq!(class.general, DEFAULT_NAME);
}
#[test]
fn parse_general_class() {
let class = parse_class("one,two").unwrap();
- assert_eq!(class.instance, "one");
- assert_eq!(class.general, "two");
+ assert_eq!(class.general, "one");
+ assert_eq!(class.instance, "two");
}
#[test]
diff --git a/alacritty/src/config/bindings.rs b/alacritty/src/config/bindings.rs
index c48b2d75..3aae25ed 100644
--- a/alacritty/src/config/bindings.rs
+++ b/alacritty/src/config/bindings.rs
@@ -9,7 +9,7 @@ use serde::de::{self, Error as SerdeError, MapAccess, Unexpected, Visitor};
use serde::{Deserialize, Deserializer};
use serde_yaml::Value as SerdeValue;
-use alacritty_config_derive::ConfigDeserialize;
+use alacritty_config_derive::{ConfigDeserialize, SerdeReplace};
use alacritty_terminal::config::Program;
use alacritty_terminal::term::TermMode;
@@ -899,7 +899,7 @@ struct RawBinding {
}
impl RawBinding {
- fn into_mouse_binding(self) -> Result<MouseBinding, Self> {
+ fn into_mouse_binding(self) -> Result<MouseBinding, Box<Self>> {
if let Some(mouse) = self.mouse {
Ok(Binding {
trigger: mouse,
@@ -909,11 +909,11 @@ impl RawBinding {
notmode: self.notmode,
})
} else {
- Err(self)
+ Err(Box::new(self))
}
}
- fn into_key_binding(self) -> Result<KeyBinding, Self> {
+ fn into_key_binding(self) -> Result<KeyBinding, Box<Self>> {
if let Some(key) = self.key {
Ok(KeyBinding {
trigger: key,
@@ -923,7 +923,7 @@ impl RawBinding {
notmode: self.notmode,
})
} else {
- Err(self)
+ Err(Box::new(self))
}
}
}
@@ -1191,7 +1191,7 @@ impl<'a> Deserialize<'a> for KeyBinding {
///
/// Our deserialize impl wouldn't be covered by a derive(Deserialize); see the
/// impl below.
-#[derive(Debug, Copy, Clone, Hash, Default, Eq, PartialEq)]
+#[derive(SerdeReplace, Debug, Copy, Clone, Hash, Default, Eq, PartialEq)]
pub struct ModsWrapper(pub ModifiersState);
impl ModsWrapper {
diff --git a/alacritty/src/config/font.rs b/alacritty/src/config/font.rs
index d3431171..9c431b15 100644
--- a/alacritty/src/config/font.rs
+++ b/alacritty/src/config/font.rs
@@ -4,7 +4,7 @@ use crossfont::Size as FontSize;
use serde::de::{self, Visitor};
use serde::{Deserialize, Deserializer};
-use alacritty_config_derive::ConfigDeserialize;
+use alacritty_config_derive::{ConfigDeserialize, SerdeReplace};
use crate::config::ui_config::Delta;
@@ -129,7 +129,7 @@ impl SecondaryFontDescription {
}
}
-#[derive(Debug, Clone, PartialEq, Eq)]
+#[derive(SerdeReplace, Debug, Clone, PartialEq, Eq)]
struct Size(FontSize);
impl Default for Size {
diff --git a/alacritty/src/config/monitor.rs b/alacritty/src/config/monitor.rs
index 305f5dfb..8981570c 100644
--- a/alacritty/src/config/monitor.rs
+++ b/alacritty/src/config/monitor.rs
@@ -63,7 +63,7 @@ pub fn watch(mut paths: Vec<PathBuf>, event_proxy: EventLoopProxy<Event>) {
// Watch all configuration file directories.
for parent in &parents {
- if let Err(err) = watcher.watch(&parent, RecursiveMode::NonRecursive) {
+ if let Err(err) = watcher.watch(parent, RecursiveMode::NonRecursive) {
debug!("Unable to watch config directory {:?}: {}", parent, err);
}
}
diff --git a/alacritty/src/config/ui_config.rs b/alacritty/src/config/ui_config.rs
index 28139d27..a332b737 100644
--- a/alacritty/src/config/ui_config.rs
+++ b/alacritty/src/config/ui_config.rs
@@ -9,7 +9,7 @@ use serde::de::{Error as SerdeError, MapAccess, Visitor};
use serde::{self, Deserialize, Deserializer};
use unicode_width::UnicodeWidthChar;
-use alacritty_config_derive::ConfigDeserialize;
+use alacritty_config_derive::{ConfigDeserialize, SerdeReplace};
use alacritty_terminal::config::{
Config as TerminalConfig, Percentage, Program, LOG_TARGET_CONFIG,
};
@@ -30,7 +30,7 @@ use crate::config::window::WindowConfig;
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{-}\\^⟨⟩`]+";
-#[derive(ConfigDeserialize, Debug, PartialEq)]
+#[derive(ConfigDeserialize, Clone, Debug, PartialEq)]
pub struct UiConfig {
/// Font configuration.
pub font: Font,
@@ -145,7 +145,7 @@ impl UiConfig {
}
}
-#[derive(Debug, PartialEq, Eq)]
+#[derive(SerdeReplace, Clone, Debug, PartialEq, Eq)]
struct KeyBindings(Vec<KeyBinding>);
impl Default for KeyBindings {
@@ -163,7 +163,7 @@ impl<'de> Deserialize<'de> for KeyBindings {
}
}
-#[derive(Debug, PartialEq, Eq)]
+#[derive(SerdeReplace, Clone, Debug, PartialEq, Eq)]
struct MouseBindings(Vec<MouseBinding>);
impl Default for MouseBindings {
@@ -223,7 +223,7 @@ pub struct Delta<T: Default> {
}
/// Regex terminal hints.
-#[derive(ConfigDeserialize, Debug, PartialEq, Eq)]
+#[derive(ConfigDeserialize, Clone, Debug, PartialEq, Eq)]
pub struct Hints {
/// Characters for the hint labels.
alphabet: HintsAlphabet,
@@ -273,7 +273,7 @@ impl Hints {
}
}
-#[derive(Clone, Debug, PartialEq, Eq)]
+#[derive(SerdeReplace, Clone, Debug, PartialEq, Eq)]
struct HintsAlphabet(String);
impl Default for HintsAlphabet {
diff --git a/alacritty/src/config/window.rs b/alacritty/src/config/window.rs
index 08f38b57..5d63d60f 100644
--- a/alacritty/src/config/window.rs
+++ b/alacritty/src/config/window.rs
@@ -6,7 +6,7 @@ use log::{error, warn};
use serde::de::{self, MapAccess, Visitor};
use serde::{Deserialize, Deserializer, Serialize};
-use alacritty_config_derive::ConfigDeserialize;
+use alacritty_config_derive::{ConfigDeserialize, SerdeReplace};
use alacritty_terminal::config::{Percentage, LOG_TARGET_CONFIG};
use alacritty_terminal::index::Column;
@@ -31,7 +31,13 @@ pub struct WindowConfig {
pub embed: Option<c_ulong>,
/// GTK theme variant.
- pub gtk_theme_variant: Option<String>,
+ #[config(deprecated = "use window.decorations_theme_variant instead")]
+ gtk_theme_variant: Option<String>,
+
+ /// System decorations theme variant.
+ ///
+ /// Controls GTK theme variant on X11 and winit client side decorations on Wayland.
+ decorations_theme_variant: Option<String>,
/// Spread out additional padding evenly.
pub dynamic_padding: bool,
@@ -61,6 +67,7 @@ impl Default for WindowConfig {
decorations: Default::default(),
startup_mode: Default::default(),
embed: Default::default(),
+ decorations_theme_variant: Default::default(),
gtk_theme_variant: Default::default(),
dynamic_padding: Default::default(),
identity: Identity::default(),
@@ -104,6 +111,15 @@ impl WindowConfig {
}
}
+ #[cfg(not(any(target_os = "macos", windows)))]
+ #[inline]
+ pub fn decorations_theme_variant(&self) -> Option<&str> {
+ self.gtk_theme_variant
+ .as_ref()
+ .or_else(|| self.decorations_theme_variant.as_ref())
+ .map(|theme| theme.as_str())
+ }
+
#[inline]
pub fn padding(&self, scale_factor: f64) -> (f32, f32) {
let padding_x = (f32::from(self.padding.x) * scale_factor as f32).floor();
@@ -185,15 +201,21 @@ pub struct Dimensions {
}
/// Window class hint.
-#[derive(Serialize, Debug, Clone, PartialEq, Eq)]
+#[derive(SerdeReplace, Serialize, Debug, Clone, PartialEq, Eq)]
pub struct Class {
- pub instance: String,
pub general: String,
+ pub instance: String,
+}
+
+impl Class {
+ pub fn new(general: impl ToString, instance: impl ToString) -> Self {
+ Self { general: general.to_string(), instance: instance.to_string() }
+ }
}
impl Default for Class {
fn default() -> Self {
- Self { instance: DEFAULT_NAME.into(), general: DEFAULT_NAME.into() }
+ Self::new(DEFAULT_NAME, DEFAULT_NAME)
}
}
diff --git a/alacritty/src/daemon.rs b/alacritty/src/daemon.rs
index 730a2cc7..df66646a 100644
--- a/alacritty/src/daemon.rs
+++ b/alacritty/src/daemon.rs
@@ -18,7 +18,7 @@ use {
#[cfg(not(windows))]
use libc::pid_t;
#[cfg(windows)]
-use winapi::um::winbase::{CREATE_NEW_PROCESS_GROUP, CREATE_NO_WINDOW};
+use windows_sys::Win32::System::Threading::{CREATE_NEW_PROCESS_GROUP, CREATE_NO_WINDOW};
#[cfg(target_os = "macos")]
use crate::macos;
diff --git a/alacritty/src/display/content.rs b/alacritty/src/display/content.rs
index 82644018..fa59bc13 100644
--- a/alacritty/src/display/content.rs
+++ b/alacritty/src/display/content.rs
@@ -54,6 +54,7 @@ impl<'a> RenderableContent<'a> {
let cursor_shape = if terminal_content.cursor.shape == CursorShape::Hidden
|| display.cursor_hidden
|| search_state.regex().is_some()
+ || display.ime.preedit().is_some()
{
CursorShape::Hidden
} else if !term.is_focused && config.terminal_config.cursor.unfocused_hollow {
@@ -423,6 +424,10 @@ impl RenderableCursor {
}
impl RenderableCursor {
+ pub fn new(point: Point<usize>, shape: CursorShape, cursor_color: Rgb, is_wide: bool) -> Self {
+ Self { shape, cursor_color, text_color: cursor_color, is_wide, point }
+ }
+
pub fn color(&self) -> Rgb {
self.cursor_color
}
diff --git a/alacritty/src/display/cursor.rs b/alacritty/src/display/cursor.rs
index 89b0bcde..8a4cc729 100644
--- a/alacritty/src/display/cursor.rs
+++ b/alacritty/src/display/cursor.rs
@@ -22,7 +22,7 @@ impl IntoRects for RenderableCursor {
let mut width = size_info.cell_width();
let height = size_info.cell_height();
- let thickness = (thickness * width as f32).round().max(1.);
+ let thickness = (thickness * width).round().max(1.);
if self.is_wide() {
width *= 2.;
diff --git a/alacritty/src/display/mod.rs b/alacritty/src/display/mod.rs
index c731314e..f5c10de4 100644
--- a/alacritty/src/display/mod.rs
+++ b/alacritty/src/display/mod.rs
@@ -20,8 +20,9 @@ use serde::{Deserialize, Serialize};
use wayland_client::EventQueue;
use crossfont::{self, Rasterize, Rasterizer};
+use unicode_width::UnicodeWidthChar;
-use alacritty_terminal::ansi::NamedColor;
+use alacritty_terminal::ansi::{CursorShape, NamedColor};
use alacritty_terminal::config::MAX_SCROLLBACK_LINES;
use alacritty_terminal::event::{EventListener, OnResize, WindowSize};
use alacritty_terminal::grid::Dimensions as TermDimensions;
@@ -38,7 +39,7 @@ use crate::config::window::{Dimensions, Identity};
use crate::config::UiConfig;
use crate::display::bell::VisualBell;
use crate::display::color::List;
-use crate::display::content::RenderableContent;
+use crate::display::content::{RenderableContent, RenderableCursor};
use crate::display::cursor::IntoRects;
use crate::display::damage::RenderDamageIterator;
use crate::display::hint::{HintMatch, HintState};
@@ -46,7 +47,7 @@ use crate::display::meter::Meter;
use crate::display::window::Window;
use crate::event::{Mouse, SearchState};
use crate::message_bar::{MessageBuffer, MessageType};
-use crate::renderer::rects::{RenderLines, RenderRect};
+use crate::renderer::rects::{RenderLine, RenderLines, RenderRect};
use crate::renderer::{self, GlyphCache, Renderer};
use crate::string::{ShortenDirection, StrShortener};
@@ -372,6 +373,9 @@ pub struct Display {
/// The renderer update that takes place only once before the actual rendering.
pub pending_renderer_update: Option<RendererUpdate>,
+ /// The ime on the given display.
+ pub ime: Ime,
+
// Mouse point position when highlighting hints.
hint_mouse_point: Option<Point>,
@@ -384,6 +388,77 @@ pub struct Display {
meter: Meter,
}
+/// Input method state.
+#[derive(Debug, Default)]
+pub struct Ime {
+ /// Whether the IME is enabled.
+ enabled: bool,
+
+ /// Current IME preedit.
+ preedit: Option<Preedit>,
+}
+
+impl Ime {
+ pub fn new() -> Self {
+ Default::default()
+ }
+
+ #[inline]
+ pub fn set_enabled(&mut self, is_enabled: bool) {
+ if is_enabled {
+ self.enabled = is_enabled
+ } else {
+ // Clear state when disabling IME.
+ *self = Default::default();
+ }
+ }
+
+ #[inline]
+ pub fn is_enabled(&self) -> bool {
+ self.enabled
+ }
+
+ #[inline]
+ pub fn set_preedit(&mut self, preedit: Option<Preedit>) {
+ self.preedit = preedit;
+ }
+
+ #[inline]
+ pub fn preedit(&self) -> Option<&Preedit> {
+ self.preedit.as_ref()
+ }
+}
+
+#[derive(Debug, Default, PartialEq, Eq)]
+pub struct Preedit {
+ /// The preedit text.
+ text: String,
+
+ /// Byte offset for cursor start into the preedit text.
+ ///
+ /// `None` means that the cursor is invisible.
+ cursor_byte_offset: Option<usize>,
+
+ /// The cursor offset from the end of the preedit in char width.
+ cursor_end_offset: Option<usize>,
+}
+
+impl Preedit {
+ pub fn new(text: String, cursor_byte_offset: Option<usize>) -> Self {
+ let cursor_end_offset = if let Some(byte_offset) = cursor_byte_offset {
+ // Convert byte offset into char offset.
+ let cursor_end_offset =
+ text[byte_offset..].chars().fold(0, |acc, ch| acc + ch.width().unwrap_or(1));
+
+ Some(cursor_end_offset)
+ } else {
+ None
+ };
+
+ Self { text, cursor_byte_offset, cursor_end_offset }
+ }
+}
+
/// Pending renderer updates.
///
/// All renderer updates are cached to be applied just before rendering, to avoid platform-specific
@@ -539,6 +614,7 @@ impl Display {
hint_state,
meter: Meter::new(),
size_info,
+ ime: Ime::new(),
highlighted_hint: None,
vi_highlighted_hint: None,
#[cfg(not(any(target_os = "macos", windows)))]
@@ -639,7 +715,7 @@ impl Display {
// Update number of column/lines in the viewport.
let message_bar_lines =
message_buffer.message().map_or(0, |m| m.text(&self.size_info).len());
- let search_lines = if search_active { 1 } else { 0 };
+ let search_lines = usize::from(search_active);
self.size_info.reserve_lines(message_bar_lines + search_lines);
// Resize PTY.
@@ -760,6 +836,7 @@ impl Display {
grid_cells.push(cell);
}
let selection_range = content.selection_range();
+ let foreground_color = content.color(NamedColor::Foreground as usize);
let background_color = content.color(NamedColor::Background as usize);
let display_offset = content.display_offset();
let cursor = content.cursor();
@@ -860,9 +937,7 @@ impl Display {
};
// Draw cursor.
- for rect in cursor.rects(&size_info, config.terminal_config.cursor.thickness()) {
- rects.push(rect);
- }
+ rects.extend(cursor.rects(&size_info, config.terminal_config.cursor.thickness()));
// Push visual bell after url/underline/strikeout rects.
let visual_bell_intensity = self.visual_bell.intensity();
@@ -878,12 +953,61 @@ impl Display {
rects.push(visual_bell_rect);
}
+ // Handle IME positioning and search bar rendering.
+ let ime_position = match search_state.regex() {
+ Some(regex) => {
+ let search_label = match search_state.direction() {
+ Direction::Right => FORWARD_SEARCH_LABEL,
+ Direction::Left => BACKWARD_SEARCH_LABEL,
+ };
+
+ let search_text = Self::format_search(regex, search_label, size_info.columns());
+
+ // Render the search bar.
+ self.draw_search(config, &search_text);
+
+ // Draw search bar cursor.
+ let line = size_info.screen_lines();
+ let column = Column(search_text.chars().count() - 1);
+
+ // Add cursor to search bar if IME is not active.
+ if self.ime.preedit().is_none() {
+ let fg = config.colors.footer_bar_foreground();
+ let shape = CursorShape::Underline;
+ let cursor = RenderableCursor::new(Point::new(line, column), shape, fg, false);
+ rects.extend(
+ cursor.rects(&size_info, config.terminal_config.cursor.thickness()),
+ );
+ }
+
+ Some(Point::new(line, column))
+ },
+ None => {
+ let num_lines = self.size_info.screen_lines();
+ term::point_to_viewport(display_offset, cursor_point)
+ .filter(|point| point.line < num_lines)
+ },
+ };
+
+ // Handle IME.
+ if self.ime.is_enabled() {
+ if let Some(point) = ime_position {
+ let (fg, bg) = if search_state.regex().is_some() {
+ (config.colors.footer_bar_foreground(), config.colors.footer_bar_background())
+ } else {
+ (foreground_color, background_color)
+ };
+
+ self.draw_ime_preview(point, fg, bg, &mut rects, config);
+ }
+ }
+
if self.debug_damage {
self.highlight_damage(&mut rects);
}
if let Some(message) = message_buffer.message() {
- let search_offset = if search_state.regex().is_some() { 1 } else { 0 };
+ let search_offset = usize::from(search_state.regex().is_some());
let text = message.text(&size_info);
// Create a new rectangle for the background.
@@ -925,34 +1049,12 @@ impl Display {
self.draw_render_timer(config);
- // Handle search and IME positioning.
- let ime_position = match search_state.regex() {
- Some(regex) => {
- let search_label = match search_state.direction() {
- Direction::Right => FORWARD_SEARCH_LABEL,
- Direction::Left => BACKWARD_SEARCH_LABEL,
- };
-
- let search_text = Self::format_search(regex, search_label, size_info.columns());
-
- // Render the search bar.
- self.draw_search(config, &search_text);
-
- // Compute IME position.
- let line = Line(size_info.screen_lines() as i32 + 1);
- Point::new(line, Column(search_text.chars().count() - 1))
- },
- None => cursor_point,
- };
-
// Draw hyperlink uri preview.
if has_highlighted_hint {
- self.draw_hyperlink_preview(config, vi_cursor_point, display_offset);
+ let cursor_point = vi_cursor_point.or(Some(cursor_point));
+ self.draw_hyperlink_preview(config, cursor_point, display_offset);
}
- // Update IME position.
- self.window.update_ime_position(ime_position, &self.size_info);
-
// Frame event should be requested before swaping buffers, since it requires surface
// `commit`, which is done by swap buffers under the hood.
#[cfg(all(feature = "wayland", not(any(target_os = "macos", windows))))]
@@ -1040,6 +1142,95 @@ impl Display {
dirty
}
+ #[inline(never)]
+ fn draw_ime_preview(
+ &mut self,
+ point: Point<usize>,
+ fg: Rgb,
+ bg: Rgb,
+ rects: &mut Vec<RenderRect>,
+ config: &UiConfig,
+ ) {
+ let preedit = match self.ime.preedit() {
+ Some(preedit) => preedit,
+ None => {
+ // In case we don't have preedit, just set the popup point.
+ self.window.update_ime_position(point, &self.size_info);
+ return;
+ },
+ };
+
+ let num_cols = self.size_info.columns();
+
+ // Get the visible preedit.
+ let visible_text: String = match (preedit.cursor_byte_offset, preedit.cursor_end_offset) {
+ (Some(byte_offset), Some(end_offset)) if end_offset > num_cols => StrShortener::new(
+ &preedit.text[byte_offset..],
+ num_cols,
+ ShortenDirection::Right,
+ Some(SHORTENER),
+ ),
+ _ => {
+ StrShortener::new(&preedit.text, num_cols, ShortenDirection::Left, Some(SHORTENER))
+ },
+ }
+ .collect();
+
+ let visible_len = visible_text.chars().count();
+
+ let end = cmp::min(point.column.0 + visible_len, num_cols);
+ let start = end.saturating_sub(visible_len);
+
+ let start = Point::new(point.line, Column(start));
+ let end = Point::new(point.line, Column(end - 1));
+
+ let glyph_cache = &mut self.glyph_cache;
+ let metrics = glyph_cache.font_metrics();
+
+ self.renderer.draw_string(
+ start,
+ fg,
+ bg,
+ visible_text.chars(),
+ &self.size_info,
+ glyph_cache,
+ );
+
+ if self.collect_damage() {
+ let damage = self.damage_from_point(Point::new(start.line, Column(0)), num_cols as u32);
+ self.damage_rects.push(damage);
+ self.next_frame_damage_rects.push(damage);
+ }
+
+ // Add underline for preedit text.
+ let underline = RenderLine { start, end, color: fg };
+ rects.extend(underline.rects(Flags::UNDERLINE, &metrics, &self.size_info));
+
+ let ime_popup_point = match preedit.cursor_end_offset {
+ Some(cursor_end_offset) if cursor_end_offset != 0 => {
+ let is_wide = preedit.text[preedit.cursor_byte_offset.unwrap_or_default()..]
+ .chars()
+ .next()
+ .map(|ch| ch.width() == Some(2))
+ .unwrap_or_default();
+
+ let cursor_column = Column(
+ (end.column.0 as isize - cursor_end_offset as isize + 1).max(0) as usize,
+ );
+ let cursor_point = Point::new(point.line, cursor_column);
+ let cursor =
+ RenderableCursor::new(cursor_point, CursorShape::HollowBlock, fg, is_wide);
+ rects.extend(
+ cursor.rects(&self.size_info, config.terminal_config.cursor.thickness()),
+ );
+ cursor_point
+ },
+ _ => end,
+ };
+
+ self.window.update_ime_position(ime_popup_point, &self.size_info);
+ }
+
/// Format search regex to account for the cursor and fullwidth characters.
fn format_search(search_regex: &str, search_label: &str, max_width: usize) -> String {
let label_len = search_label.len();
@@ -1058,7 +1249,8 @@ impl Display {
Some(SHORTENER),
));
- bar_text.push('_');
+ // Add place for cursor.
+ bar_text.push(' ');
bar_text
}
@@ -1068,7 +1260,7 @@ impl Display {
fn draw_hyperlink_preview(
&mut self,
config: &UiConfig,
- vi_cursor_point: Option<Point>,
+ cursor_point: Option<Point>,
display_offset: usize,
) {
let num_cols = self.size_info.columns();
@@ -1094,7 +1286,7 @@ impl Display {
// Prefer to show preview even when it'll likely obscure the highlighted hint, when
// there's no place left for it.
protected_lines.push(self.hint_mouse_point.map(|point| point.line));
- protected_lines.push(vi_cursor_point.map(|point| point.line));
+ protected_lines.push(cursor_point.map(|point| point.line));
}
// Find the line in viewport we can draw preview on without obscuring protected lines.
@@ -1229,7 +1421,7 @@ impl Display {
let x = size_info.padding_x() + point.column.0 as u32 * size_info.cell_width();
let y_top = size_info.height() - size_info.padding_y();
let y = y_top - (point.line as u32 + 1) * size_info.cell_height();
- let width = len as u32 * size_info.cell_width();
+ let width = len * size_info.cell_width();
DamageRect { x, y, width, height: size_info.cell_height() }
}
diff --git a/alacritty/src/display/window.rs b/alacritty/src/display/window.rs
index 480654cf..f558a654 100644
--- a/alacritty/src/display/window.rs
+++ b/alacritty/src/display/window.rs
@@ -13,6 +13,7 @@ use {
wayland_client::protocol::wl_surface::WlSurface,
wayland_client::{Attached, EventQueue, Proxy},
glutin::platform::unix::EventLoopWindowTargetExtUnix,
+ glutin::window::Theme,
};
#[rustfmt::skip]
@@ -46,8 +47,6 @@ use glutin::{self, ContextBuilder, PossiblyCurrent, Rect, WindowedContext};
use objc::{msg_send, sel, sel_impl};
#[cfg(target_os = "macos")]
use raw_window_handle::{HasRawWindowHandle, RawWindowHandle};
-#[cfg(windows)]
-use winapi::shared::minwindef::WORD;
use alacritty_terminal::index::Point;
@@ -58,11 +57,11 @@ use crate::gl;
/// Window icon for `_NET_WM_ICON` property.
#[cfg(all(feature = "x11", not(any(target_os = "macos", windows))))]
-static WINDOW_ICON: &[u8] = include_bytes!("../../alacritty.png");
+static WINDOW_ICON: &[u8] = include_bytes!("../../extra/logo/compat/alacritty-term.png");
-/// This should match the definition of IDI_ICON from `windows.rc`.
+/// This should match the definition of IDI_ICON from `alacritty.rc`.
#[cfg(windows)]
-const IDI_ICON: WORD = 0x101;
+const IDI_ICON: u16 = 0x101;
/// Context creation flags from probing config.
static GL_CONTEXT_CREATION_FLAGS: AtomicU8 = AtomicU8::new(GlContextFlags::SRGB.bits);
@@ -233,6 +232,9 @@ impl Window {
let current_mouse_cursor = CursorIcon::Text;
windowed_context.window().set_cursor_icon(current_mouse_cursor);
+ // Enable IME.
+ windowed_context.window().set_ime_allowed(true);
+
// Set OpenGL symbol loader. This call MUST be after window.make_current on windows.
gl::load_with(|symbol| windowed_context.get_proc_address(symbol) as *const _);
@@ -322,15 +324,18 @@ impl Window {
pub fn get_platform_window(identity: &Identity, window_config: &WindowConfig) -> WindowBuilder {
#[cfg(feature = "x11")]
let icon = {
- let decoder = Decoder::new(Cursor::new(WINDOW_ICON));
- let (info, mut reader) = decoder.read_info().expect("invalid embedded icon");
- let mut buf = vec![0; info.buffer_size()];
+ let mut decoder = Decoder::new(Cursor::new(WINDOW_ICON));
+ decoder.set_transformations(png::Transformations::normalize_to_color8());
+ let mut reader = decoder.read_info().expect("invalid embedded icon");
+ let mut buf = vec![0; reader.output_buffer_size()];
let _ = reader.next_frame(&mut buf);
- Icon::from_rgba(buf, info.width, info.height)
+ Icon::from_rgba(buf, reader.info().width, reader.info().height)
+ .expect("invalid embedded icon format")
};
let builder = WindowBuilder::new()
.with_title(&identity.title)
+ .with_name(&identity.class.general, &identity.class.instance)
.with_visible(false)
.with_transparent(true)
.with_decorations(window_config.decorations != Decorations::None)
@@ -338,21 +343,21 @@ impl Window {
.with_fullscreen(window_config.fullscreen());
#[cfg(feature = "x11")]
- let builder = builder.with_window_icon(icon.ok());
-
- #[cfg(feature = "wayland")]
- let builder = builder.with_app_id(identity.class.instance.to_owned());
-
- #[cfg(feature = "x11")]
- let builder = builder
- .with_class(identity.class.instance.to_owned(), identity.class.general.to_owned());
+ let builder = builder.with_window_icon(Some(icon));
#[cfg(feature = "x11")]
- let builder = match &window_config.gtk_theme_variant {
- Some(val) => builder.with_gtk_theme_variant(val.clone()),
+ let builder = match window_config.decorations_theme_variant() {
+ Some(val) => builder.with_gtk_theme_variant(val.to_string()),
None => builder,
};
+ #[cfg(feature = "wayland")]
+ let builder = match window_config.decorations_theme_variant() {
+ Some("light") => builder.with_wayland_csd_theme(Theme::Light),
+ // Prefer dark theme by default, since default alacritty theme is dark.
+ _ => builder.with_wayland_csd_theme(Theme::Dark),
+ };
+
builder
}
@@ -400,16 +405,6 @@ impl Window {
self.window().request_user_attention(attention);
}
- #[cfg(all(feature = "x11", not(any(target_os = "macos", windows))))]
- pub fn x11_window_id(&self) -> Option<usize> {
- self.window().xlib_window().map(|xlib_window| xlib_window as usize)
- }
-
- #[cfg(any(not(feature = "x11"), target_os = "macos", windows))]
- pub fn x11_window_id(&self) -> Option<usize> {
- None
- }
-
pub fn id(&self) -> WindowId {
self.window().id()
}
@@ -455,10 +450,14 @@ impl Window {
self.wayland_surface.as_ref()
}
+ pub fn set_ime_allowed(&self, allowed: bool) {
+ self.windowed_context.window().set_ime_allowed(allowed);
+ }
+
/// Adjust the IME editor position according to the new location of the cursor.
- pub fn update_ime_position(&self, point: Point, size: &SizeInfo) {
+ pub fn update_ime_position(&self, point: Point<usize>, size: &SizeInfo) {
let nspot_x = f64::from(size.padding_x() + point.column.0 as f32 * size.cell_width());
- let nspot_y = f64::from(size.padding_y() + (point.line.0 + 1) as f32 * size.cell_height());
+ let nspot_y = f64::from(size.padding_y() + (point.line + 1) as f32 * size.cell_height());
self.window().set_ime_position(PhysicalPosition::new(nspot_x, nspot_y));
}
diff --git a/alacritty/src/event.rs b/alacritty/src/event.rs
index cfa1c25c..853e3f5e 100644
--- a/alacritty/src/event.rs
+++ b/alacritty/src/event.rs
@@ -9,12 +9,17 @@ use std::fmt::Debug;
#[cfg(not(windows))]
use std::os::unix::io::RawFd;
use std::path::PathBuf;
+use std::rc::Rc;
use std::time::{Duration, Instant};
use std::{env, f32, mem};
use glutin::dpi::PhysicalSize;
-use glutin::event::{ElementState, Event as GlutinEvent, ModifiersState, MouseButton, WindowEvent};
-use glutin::event_loop::{ControlFlow, EventLoop, EventLoopProxy, EventLoopWindowTarget};
+use glutin::event::{
+ ElementState, Event as GlutinEvent, Ime, ModifiersState, MouseButton, StartCause, WindowEvent,
+};
+use glutin::event_loop::{
+ ControlFlow, DeviceEventFilter, EventLoop, EventLoopProxy, EventLoopWindowTarget,
+};
use glutin::platform::run_return::EventLoopExtRunReturn;
#[cfg(all(feature = "wayland", not(any(target_os = "macos", windows))))]
use glutin::platform::unix::EventLoopWindowTargetExtUnix;
@@ -34,6 +39,8 @@ use alacritty_terminal::selection::{Selection, SelectionType};
use alacritty_terminal::term::search::{Match, RegexSearch};
use alacritty_terminal::term::{self, ClipboardType, Term, TermMode};
+#[cfg(unix)]
+use crate::cli::IpcConfig;
use crate::cli::{Options as CliOptions, WindowOptions};
use crate::clipboard::Clipboard;
use crate::config::ui_config::{HintAction, HintInternalAction};
@@ -43,7 +50,7 @@ use crate::daemon::foreground_process_path;
use crate::daemon::spawn_daemon;
use crate::display::hint::HintMatch;
use crate::display::window::Window;
-use crate::display::{Display, SizeInfo};
+use crate::display::{Display, Preedit, SizeInfo};
use crate::input::{self, ActionContext as _, FONT_SIZE_STEP};
use crate::message_bar::{Message, MessageBuffer};
use crate::scheduler::{Scheduler, TimerId, Topic};
@@ -89,6 +96,8 @@ pub enum EventType {
Message(Message),
Scroll(Scroll),
CreateWindow(WindowOptions),
+ #[cfg(unix)]
+ IpcConfig(IpcConfig),
BlinkCursor,
BlinkCursorTimeout,
SearchNext,
@@ -180,7 +189,7 @@ pub struct ActionContext<'a, N, T> {
pub modifiers: &'a mut ModifiersState,
pub display: &'a mut Display,
pub message_buffer: &'a mut MessageBuffer,
- pub config: &'a mut UiConfig,
+ pub config: &'a UiConfig,
pub cursor_blink_timed_out: &'a mut bool,
pub event_loop: &'a EventLoopWindowTarget<Event>,
pub event_proxy: &'a EventLoopProxy<Event>,
@@ -188,6 +197,7 @@ pub struct ActionContext<'a, N, T> {
pub search_state: &'a mut SearchState,
pub font_size: &'a mut Size,
pub dirty: &'a mut bool,
+ pub occluded: &'a mut bool,
pub preserve_title: bool,
#[cfg(not(windows))]
pub master_fd: RawFd,
@@ -471,6 +481,9 @@ impl<'a, N: Notify + 'a, T: EventListener> input::ActionContext<T> for ActionCon
};
}
+ // Enable IME so we can input into the search bar with it if we were in Vi mode.
+ self.window().set_ime_allowed(true);
+
self.display.pending_update.dirty = true;
}
@@ -781,7 +794,8 @@ impl<'a, N: Notify + 'a, T: EventListener> input::ActionContext<T> for ActionCon
/// Toggle the vi mode status.
#[inline]
fn toggle_vi_mode(&mut self) {
- if self.terminal.mode().contains(TermMode::VI) {
+ let was_in_vi_mode = self.terminal.mode().contains(TermMode::VI);
+ if was_in_vi_mode {
// If we had search running when leaving Vi mode we should mark terminal fully damaged
// to cleanup highlighted results.
if self.search_state.dfas.take().is_some() {
@@ -798,6 +812,9 @@ impl<'a, N: Notify + 'a, T: EventListener> input::ActionContext<T> for ActionCon
self.cancel_search();
}
+ // We don't want IME in Vi mode.
+ self.window().set_ime_allowed(was_in_vi_mode);
+
self.terminal.toggle_vi_mode();
*self.dirty = true;
@@ -931,6 +948,9 @@ impl<'a, N: Notify + 'a, T: EventListener> ActionContext<'a, N, T> {
/// Cleanup the search state.
fn exit_search(&mut self) {
+ let vi_mode = self.terminal.mode().contains(TermMode::VI);
+ self.window().set_ime_allowed(!vi_mode);
+
self.display.pending_update.dirty = true;
self.search_state.history_index = None;
@@ -950,7 +970,8 @@ impl<'a, N: Notify + 'a, T: EventListener> ActionContext<'a, N, T> {
// Check terminal cursor style.
let terminal_blinking = self.terminal.cursor_style().blinking;
let mut blinking = cursor_style.blinking_override().unwrap_or(terminal_blinking);
- blinking &= vi_mode || self.terminal().mode().contains(TermMode::SHOW_CURSOR);
+ blinking &= (vi_mode || self.terminal().mode().contains(TermMode::SHOW_CURSOR))
+ && self.display().ime.preedit().is_none();
// Update cursor blinking state.
let window_id = self.display.window.id();
@@ -1146,6 +1167,8 @@ impl input::Processor<EventProxy, ActionContext<'_, Notifier, EventProxy>> {
TerminalEvent::Exit => (),
TerminalEvent::CursorBlinkingChange => self.ctx.update_cursor_blinking(),
},
+ #[cfg(unix)]
+ EventType::IpcConfig(_) => (),
EventType::ConfigReload(_) | EventType::CreateWindow(_) => (),
},
GlutinEvent::RedrawRequested(_) => *self.ctx.dirty = true,
@@ -1197,6 +1220,9 @@ impl input::Processor<EventProxy, ActionContext<'_, Notifier, EventProxy>> {
self.ctx.update_cursor_blinking();
self.on_focus_change(is_focused);
},
+ WindowEvent::Occluded(occluded) => {
+ *self.ctx.occluded = occluded;
+ },
WindowEvent::DroppedFile(path) => {
let path: String = path.to_string_lossy().into();
self.ctx.write_to_pty((path + " ").into_bytes());
@@ -1208,6 +1234,38 @@ impl input::Processor<EventProxy, ActionContext<'_, Notifier, EventProxy>> {
*self.ctx.dirty = true;
}
},
+ WindowEvent::Ime(ime) => match ime {
+ Ime::Commit(text) => {
+ *self.ctx.dirty = true;
+
+ for ch in text.chars() {
+ self.received_char(ch);
+ }
+
+ self.ctx.update_cursor_blinking();
+ },
+ Ime::Preedit(text, cursor_offset) => {
+ let preedit = if text.is_empty() {
+ None
+ } else {
+ Some(Preedit::new(text, cursor_offset.map(|offset| offset.0)))
+ };
+
+ if self.ctx.display.ime.preedit() != preedit.as_ref() {
+ self.ctx.display.ime.set_preedit(preedit);
+ self.ctx.update_cursor_blinking();
+ *self.ctx.dirty = true;
+ }
+ },
+ Ime::Enabled => {
+ self.ctx.display.ime.set_enabled(true);
+ *self.ctx.dirty = true;
+ },
+ Ime::Disabled => {
+ self.ctx.display.ime.set_enabled(false);
+ *self.ctx.dirty = true;
+ },
+ },
WindowEvent::KeyboardInput { is_synthetic: true, .. }
| WindowEvent::TouchpadPressure { .. }
| WindowEvent::ScaleFactorChanged { .. }
@@ -1241,7 +1299,7 @@ pub struct Processor {
wayland_event_queue: Option<EventQueue>,
windows: HashMap<WindowId, WindowContext>,
cli_options: CliOptions,
- config: UiConfig,
+ config: Rc<UiConfig>,
}
impl Processor {
@@ -1262,8 +1320,8 @@ impl Processor {
Processor {
windows: HashMap::new(),
+ config: Rc::new(config),
cli_options,
- config,
#[cfg(all(feature = "wayland", not(any(target_os = "macos", windows))))]
wayland_event_queue,
}
@@ -1277,7 +1335,7 @@ impl Processor {
options: WindowOptions,
) -> Result<(), Box<dyn Error>> {
let window_context = WindowContext::new(
- &self.config,
+ self.config.clone(),
&options,
event_loop,
proxy,
@@ -1289,9 +1347,16 @@ impl Processor {
}
/// Run the event loop.
- pub fn run(&mut self, mut event_loop: EventLoop<Event>) {
+ ///
+ /// The result is exit code generate from the loop.
+ pub fn run(
+ &mut self,
+ mut event_loop: EventLoop<Event>,
+ initial_window_options: WindowOptions,
+ ) -> Result<(), Box<dyn Error>> {
let proxy = event_loop.create_proxy();
let mut scheduler = Scheduler::new(proxy.clone());
+ let mut initial_window_options = Some(initial_window_options);
// NOTE: Since this takes a pointer to the winit event loop, it MUST be dropped first.
#[cfg(all(feature = "wayland", not(any(target_os = "macos", windows))))]
@@ -1299,7 +1364,10 @@ impl Processor {
#[cfg(any(not(feature = "wayland"), target_os = "macos", windows))]
let mut clipboard = Clipboard::new();
- event_loop.run_return(|event, event_loop, control_flow| {
+ // Disable all device events, since we don't care about them.
+ event_loop.set_device_event_filter(DeviceEventFilter::Always);
+
+ let exit_code = event_loop.run_return(move |event, event_loop, control_flow| {
if self.config.debug.print_events {
info!("glutin event: {:?}", event);
}
@@ -1310,6 +1378,27 @@ impl Processor {
}
match event {
+ // The event loop just got initialized. Create a window.
+ GlutinEvent::Resumed => {
+ // Creating window inside event loop is required for platforms like macOS to
+ // properly initialize state, like tab management. Othwerwise the first window
+ // won't handle tabs.
+ let initial_window_options = match initial_window_options.take() {
+ Some(initial_window_options) => initial_window_options,
+ None => return,
+ };
+
+ if let Err(err) =
+ self.create_window(event_loop, proxy.clone(), initial_window_options)
+ {
+ // Log the error right away since we can't return it.
+ eprintln!("Error: {}", err);
+ *control_flow = ControlFlow::ExitWithCode(1);
+ return;
+ }
+
+ info!("Initialisation complete");
+ },
// Check for shutdown.
GlutinEvent::UserEvent(Event {
window_id: Some(window_id),
@@ -1354,7 +1443,6 @@ impl Processor {
window_context.handle_event(
event_loop,
&proxy,
- &mut self.config,
&mut clipboard,
&mut scheduler,
GlutinEvent::RedrawEventsCleared,
@@ -1375,13 +1463,27 @@ impl Processor {
// Load config and update each terminal.
if let Ok(config) = config::reload(&path, &self.cli_options) {
- let old_config = mem::replace(&mut self.config, config);
+ self.config = Rc::new(config);
for window_context in self.windows.values_mut() {
- window_context.update_config(&old_config, &self.config);
+ window_context.update_config(self.config.clone());
}
}
},
+ // Process IPC config update.
+ #[cfg(unix)]
+ GlutinEvent::UserEvent(Event {
+ payload: EventType::IpcConfig(ipc_config),
+ window_id,
+ }) => {
+ for (_, window_context) in self
+ .windows
+ .iter_mut()
+ .filter(|(id, _)| window_id.is_none() || window_id == Some(**id))
+ {
+ window_context.update_ipc_config(self.config.clone(), ipc_config.clone());
+ }
+ },
// Create a new terminal window.
GlutinEvent::UserEvent(Event {
payload: EventType::CreateWindow(options), ..
@@ -1403,7 +1505,6 @@ impl Processor {
window_context.handle_event(
event_loop,
&proxy,
- &mut self.config,
&mut clipboard,
&mut scheduler,
event.clone().into(),
@@ -1418,7 +1519,6 @@ impl Processor {
window_context.handle_event(
event_loop,
&proxy,
- &mut self.config,
&mut clipboard,
&mut scheduler,
event,
@@ -1428,11 +1528,18 @@ impl Processor {
_ => (),
}
});
+
+ if exit_code == 0 {
+ Ok(())
+ } else {
+ Err(format!("Event loop terminated with code: {}", exit_code).into())
+ }
}
/// Check if an event is irrelevant and can be skipped.
fn skip_event(event: &GlutinEvent<'_, Event>) -> bool {
match event {
+ GlutinEvent::NewEvents(StartCause::Init) => false,
GlutinEvent::WindowEvent { event, .. } => matches!(
event,
WindowEvent::KeyboardInput { is_synthetic: true, .. }
diff --git a/alacritty/src/input.rs b/alacritty/src/input.rs
index 35aaedda..6dbb72cf 100644
--- a/alacritty/src/input.rs
+++ b/alacritty/src/input.rs
@@ -369,8 +369,8 @@ impl<T: EventListener, A: ActionContext<T>> Processor<T, A> {
let display_offset = self.ctx.terminal().grid().display_offset();
let old_point = self.ctx.mouse().point(&size_info, display_offset);
- let x = min(max(x, 0), size_info.width() as i32 - 1) as usize;
- let y = min(max(y, 0), size_info.height() as i32 - 1) as usize;
+ let x = x.clamp(0, size_info.width() as i32 - 1) as usize;
+ let y = y.clamp(0, size_info.height() as i32 - 1) as usize;
self.ctx.mouse_mut().x = x;
self.ctx.mouse_mut().y = y;
@@ -754,6 +754,11 @@ impl<T: EventListener, A: ActionContext<T>> Processor<T, A> {
/// Process key input.
pub fn key_input(&mut self, input: KeyboardInput) {
+ // IME input will be applied on commit and shouldn't trigger key bindings.
+ if self.ctx.display().ime.preedit().is_some() {
+ return;
+ }
+
// All key bindings are disabled while a hint is being selected.
if self.ctx.display().hint_state.active() {
*self.ctx.suppress_chars() = false;
@@ -801,6 +806,11 @@ impl<T: EventListener, A: ActionContext<T>> Processor<T, A> {
pub fn received_char(&mut self, c: char) {
let suppress_chars = *self.ctx.suppress_chars();
+ // Don't insert chars when we have IME running.
+ if self.ctx.display().ime.preedit().is_some() {
+ return;
+ }
+
// Handle hint selection over anything else.
if self.ctx.display().hint_state.active() && !suppress_chars {
self.ctx.hint_input(c);
@@ -898,7 +908,7 @@ impl<T: EventListener, A: ActionContext<T>> Processor<T, A> {
/// Check mouse icon state in relation to the message bar.
fn message_bar_cursor_state(&self) -> Option<CursorIcon> {
// Since search is above the message bar, the button is offset by search's height.
- let search_height = if self.ctx.search_active() { 1 } else { 0 };
+ let search_height = usize::from(self.ctx.search_active());
// Calculate Y position of the end of the last terminal line.
let size = self.ctx.size_info();
@@ -967,8 +977,7 @@ impl<T: EventListener, A: ActionContext<T>> Processor<T, A> {
};
// Scale number of lines scrolled based on distance to boundary.
- let delta = delta as i32 / step as i32;
- let event = Event::new(EventType::Scroll(Scroll::Delta(delta)), Some(window_id));
+ let event = Event::new(EventType::Scroll(Scroll::Delta(delta / step)), Some(window_id));
// Schedule event.
let timer_id = TimerId::new(Topic::SelectionScrolling, window_id);
diff --git a/alacritty/src/ipc.rs b/alacritty/src/ipc.rs
index d4c807ba..368015a9 100644
--- a/alacritty/src/ipc.rs
+++ b/alacritty/src/ipc.rs
@@ -7,6 +7,7 @@ use std::path::PathBuf;
use std::{env, fs, process};
use glutin::event_loop::EventLoopProxy;
+use glutin::window::WindowId;
use log::warn;
use alacritty_terminal::thread;
@@ -62,6 +63,14 @@ pub fn spawn_ipc_socket(options: &Options, event_proxy: EventLoopProxy<Event>) -
let event = Event::new(EventType::CreateWindow(options), None);
let _ = event_proxy.send_event(event);
},
+ SocketMessage::Config(ipc_config) => {
+ let window_id = ipc_config
+ .window_id
+ .and_then(|id| u64::try_from(id).ok())
+ .map(WindowId::from);
+ let event = Event::new(EventType::IpcConfig(ipc_config), window_id);
+ let _ = event_proxy.send_event(event);
+ },
}
}
});
@@ -110,7 +119,7 @@ fn find_socket(socket_path: Option<PathBuf>) -> IoResult<UnixStream> {
// Handle environment variable.
if let Ok(path) = env::var(ALACRITTY_SOCKET_ENV) {
let socket_path = PathBuf::from(path);
- if let Ok(socket) = UnixStream::connect(&socket_path) {
+ if let Ok(socket) = UnixStream::connect(socket_path) {
return Ok(socket);
}
}
diff --git a/alacritty/src/logging.rs b/alacritty/src/logging.rs
index f3405e58..113e96ff 100644
--- a/alacritty/src/logging.rs
+++ b/alacritty/src/logging.rs
@@ -15,15 +15,27 @@ use std::{env, process};
use glutin::event_loop::EventLoopProxy;
use log::{self, Level, LevelFilter};
+use alacritty_terminal::config::LOG_TARGET_CONFIG;
+
use crate::cli::Options;
use crate::event::{Event, EventType};
use crate::message_bar::{Message, MessageType};
+/// Logging target for IPC config error messages.
+pub const LOG_TARGET_IPC_CONFIG: &str = "alacritty_log_ipc_config";
+
/// Name for the environment variable containing the log file's path.
const ALACRITTY_LOG_ENV: &str = "ALACRITTY_LOG";
+
/// List of targets which will be logged by Alacritty.
-const ALLOWED_TARGETS: [&str; 4] =
- ["alacritty_terminal", "alacritty_config_derive", "alacritty", "crossfont"];
+const ALLOWED_TARGETS: &[&str] = &[
+ LOG_TARGET_IPC_CONFIG,
+ LOG_TARGET_CONFIG,
+ "alacritty_config_derive",
+ "alacritty_terminal",
+ "alacritty",
+ "crossfont",
+];
pub fn initialize(
options: &Options,
diff --git a/alacritty/src/main.rs b/alacritty/src/main.rs
index a0a98efe..569ed30e 100644
--- a/alacritty/src/main.rs
+++ b/alacritty/src/main.rs
@@ -14,18 +14,18 @@ compile_error!(r#"at least one of the "x11"/"wayland" features must be enabled"#
#[cfg(target_os = "macos")]
use std::env;
+use std::error::Error;
use std::fmt::Write as _;
+use std::fs;
use std::io::{self, Write};
use std::path::PathBuf;
-use std::string::ToString;
-use std::{fs, process};
-use glutin::event_loop::EventLoop as GlutinEventLoop;
+use glutin::event_loop::EventLoopBuilder as GlutinEventLoopBuilder;
#[cfg(all(feature = "x11", not(any(target_os = "macos", windows))))]
use glutin::platform::unix::EventLoopWindowTargetExtUnix;
use log::info;
#[cfg(windows)]
-use winapi::um::wincon::{AttachConsole, FreeConsole, ATTACH_PARENT_PROCESS};
+use windows_sys::Win32::System::Console::{AttachConsole, FreeConsole, ATTACH_PARENT_PROCESS};
use alacritty_terminal::tty;
@@ -62,7 +62,7 @@ use crate::event::{Event, Processor};
#[cfg(target_os = "macos")]
use crate::macos::locale;
-fn main() {
+fn main() -> Result<(), Box<dyn Error>> {
#[cfg(windows)]
panic::attach_handler();
@@ -78,25 +78,19 @@ fn main() {
let options = Options::new();
#[cfg(unix)]
- let result = match options.subcommands {
+ match options.subcommands {
Some(Subcommands::Msg(options)) => msg(options),
None => alacritty(options),
- };
+ }
#[cfg(not(unix))]
- let result = alacritty(options);
-
- // Handle command failure.
- if let Err(err) = result {
- eprintln!("Error: {}", err);
- process::exit(1);
- }
+ alacritty(options)
}
/// `msg` subcommand entrypoint.
#[cfg(unix)]
-fn msg(options: MessageOptions) -> Result<(), String> {
- ipc::send_message(options.socket, options.message).map_err(|err| err.to_string())
+fn msg(options: MessageOptions) -> Result<(), Box<dyn Error>> {
+ ipc::send_message(options.socket, options.message).map_err(|err| err.into())
}
/// Temporary files stored for Alacritty.
@@ -129,9 +123,9 @@ impl Drop for TemporaryFiles {
///
/// Creates a window, the terminal state, PTY, I/O event loop, input processor,
/// config change monitor, and runs the main display loop.
-fn alacritty(options: Options) -> Result<(), String> {
+fn alacritty(options: Options) -> Result<(), Box<dyn Error>> {
// Setup glutin event loop.
- let window_event_loop = GlutinEventLoop::<Event>::with_user_event();
+ let window_event_loop = GlutinEventLoopBuilder::<Event>::with_user_event().build();
// Initialize the logger as soon as possible as to capture output from other subsystems.
let log_file = logging::initialize(&options, window_event_loop.create_proxy())
@@ -191,16 +185,8 @@ fn alacritty(options: Options) -> Result<(), String> {
let window_options = options.window_options.clone();
let mut processor = Processor::new(config, options, &window_event_loop);
- // Create the first Alacritty window.
- let proxy = window_event_loop.create_proxy();
- processor
- .create_window(&window_event_loop, proxy, window_options)
- .map_err(|err| err.to_string())?;
-
- info!("Initialisation complete");
-
// Start event loop and block until shutdown.
- processor.run(window_event_loop);
+ let result = processor.run(window_event_loop, window_options);
// This explicit drop is needed for Windows, ConPTY backend. Otherwise a deadlock can occur.
// The cause:
@@ -225,7 +211,8 @@ fn alacritty(options: Options) -> Result<(), String> {
}
info!("Goodbye");
- Ok(())
+
+ result
}
fn log_config_path(config: &UiConfig) {
diff --git a/alacritty/src/panic.rs b/alacritty/src/panic.rs
index 2311d7b9..2637f8d6 100644
--- a/alacritty/src/panic.rs
+++ b/alacritty/src/panic.rs
@@ -1,7 +1,9 @@
use std::io::Write;
-use std::{io, panic, ptr};
+use std::{io, panic};
-use winapi::um::winuser;
+use windows_sys::Win32::UI::WindowsAndMessaging::{
+ MessageBoxW, MB_ICONERROR, MB_OK, MB_SETFOREGROUND, MB_TASKMODAL,
+};
use alacritty_terminal::tty::windows::win32_string;
@@ -12,14 +14,11 @@ pub fn attach_handler() {
let _ = writeln!(io::stderr(), "{}", panic_info);
let msg = format!("{}\n\nPress Ctrl-C to Copy", panic_info);
unsafe {
- winuser::MessageBoxW(
- ptr::null_mut(),
+ MessageBoxW(
+ 0isize,
win32_string(&msg).as_ptr(),
win32_string("Alacritty: Runtime Error").as_ptr(),
- winuser::MB_ICONERROR
- | winuser::MB_OK
- | winuser::MB_SETFOREGROUND
- | winuser::MB_TASKMODAL,
+ MB_ICONERROR | MB_OK | MB_SETFOREGROUND | MB_TASKMODAL,
);
}
}));
diff --git a/alacritty/src/renderer/rects.rs b/alacritty/src/renderer/rects.rs
index 113eaab5..3acefa62 100644
--- a/alacritty/src/renderer/rects.rs
+++ b/alacritty/src/renderer/rects.rs
@@ -337,7 +337,7 @@ impl RectRenderer {
continue;
}
- self.program.set_rect_kind(rect_kind as u8);
+ self.program.set_rect_kind(rect_kind);
// Upload accumulated undercurl vertices.
gl::BufferData(
diff --git a/alacritty/src/renderer/text/atlas.rs b/alacritty/src/renderer/text/atlas.rs
index 0922c570..662d767b 100644
--- a/alacritty/src/renderer/text/atlas.rs
+++ b/alacritty/src/renderer/text/atlas.rs
@@ -133,8 +133,8 @@ impl Atlas {
fn insert_inner(&mut self, glyph: &RasterizedGlyph, active_tex: &mut u32) -> Glyph {
let offset_y = self.row_baseline;
let offset_x = self.row_extent;
- let height = glyph.height as i32;
- let width = glyph.width as i32;
+ let height = glyph.height;
+ let width = glyph.width;
let multicolor;
unsafe {
@@ -196,9 +196,9 @@ impl Atlas {
/// Check if there's room in the current row for given glyph.
pub fn room_in_row(&self, raw: &RasterizedGlyph) -> bool {
- let next_extent = self.row_extent + raw.width as i32;
+ let next_extent = self.row_extent + raw.width;
let enough_width = next_extent <= self.width;
- let enough_height = (raw.height as i32) < (self.height - self.row_baseline);
+ let enough_height = raw.height < (self.height - self.row_baseline);
enough_width && enough_height
}
diff --git a/alacritty/src/renderer/text/builtin_font.rs b/alacritty/src/renderer/text/builtin_font.rs
index a4bf65e3..aeee6d91 100644
--- a/alacritty/src/renderer/text/builtin_font.rs
+++ b/alacritty/src/renderer/text/builtin_font.rs
@@ -71,14 +71,14 @@ fn box_drawing(character: char, metrics: &Metrics, offset: &Delta<i8>) -> Raster
for stroke_size in 0..2 * stroke_size {
let stroke_size = stroke_size as f32 / 2.;
if character == '\u{2571}' || character == '\u{2573}' {
- let h = y_end - stroke_size as f32;
+ let h = y_end - stroke_size;
let from_y = f_x(from_x, h);
let to_y = f_x(to_x, h);
canvas.draw_line(from_x, from_y, to_x, to_y);
}
if character == '\u{2572}' || character == '\u{2573}' {
- let from_y = g_x(from_x, stroke_size as f32);
- let to_y = g_x(to_x, stroke_size as f32);
+ let from_y = g_x(from_x, stroke_size);
+ let to_y = g_x(to_x, stroke_size);
canvas.draw_line(from_x, from_y, to_x, to_y);
}
}
@@ -90,8 +90,8 @@ fn box_drawing(character: char, metrics: &Metrics, offset: &Delta<i8>) -> Raster
left: 0,
height: height as i32,
width: width as i32,
- advance: (0, 0),
buffer,
+ advance: (width as i32, height as i32),
};
},
_ => Canvas::new(width, height),
@@ -345,7 +345,7 @@ fn box_drawing(character: char, metrics: &Metrics, offset: &Delta<i8>) -> Raster
if character == '\u{256d}' || character == '\u{2570}' {
let center = canvas.x_center() as usize;
- let extra_offset = if stroke_size % 2 == width % 2 { 0 } else { 1 };
+ let extra_offset = usize::from(stroke_size % 2 != width % 2);
let buffer = canvas.buffer_mut();
for y in 1..height {
@@ -363,7 +363,7 @@ fn box_drawing(character: char, metrics: &Metrics, offset: &Delta<i8>) -> Raster
if character == '\u{256d}' || character == '\u{256e}' {
let center = canvas.y_center() as usize;
- let extra_offset = if stroke_size % 2 == height % 2 { 0 } else { 1 };
+ let extra_offset = usize::from(stroke_size % 2 != height % 2);
let buffer = canvas.buffer_mut();
if extra_offset != 0 {
@@ -422,7 +422,7 @@ fn box_drawing(character: char, metrics: &Metrics, offset: &Delta<i8>) -> Raster
let x = match character {
'\u{2590}' => canvas.x_center(),
- '\u{2595}' => width as f32 - rect_width,
+ '\u{2595}' => width - rect_width,
_ => 0.,
};
@@ -486,8 +486,8 @@ fn box_drawing(character: char, metrics: &Metrics, offset: &Delta<i8>) -> Raster
left: 0,
height: height as i32,
width: width as i32,
- advance: (0, 0),
buffer,
+ advance: (width as i32, height as i32),
}
}
@@ -592,13 +592,13 @@ impl Canvas {
/// Draws a horizontal straight line from (`x`, `y`) of `size` with the given `stroke_size`.
fn draw_h_line(&mut self, x: f32, y: f32, size: f32, stroke_size: usize) {
let (start_y, end_y) = self.h_line_bounds(y, stroke_size);
- self.draw_rect(x, start_y as f32, size, (end_y - start_y) as f32, COLOR_FILL);
+ self.draw_rect(x, start_y, size, end_y - start_y, COLOR_FILL);
}
/// Draws a vertical straight line from (`x`, `y`) of `size` with the given `stroke_size`.
fn draw_v_line(&mut self, x: f32, y: f32, size: f32, stroke_size: usize) {
let (start_x, end_x) = self.v_line_bounds(x, stroke_size);
- self.draw_rect(start_x as f32, y, (end_x - start_x) as f32, size, COLOR_FILL);
+ self.draw_rect(start_x, y, end_x - start_x, size, COLOR_FILL);
}
/// Draws a rect from the (`x`, `y`) of the given `width` and `height` using `color`.
@@ -750,7 +750,7 @@ impl Canvas {
let x_next = (x + 1.).clamp(0., v_line_bounds.1 as f32 - 1.);
let x = x.clamp(0., v_line_bounds.1 as f32 - 1.);
- let y = y.clamp(0., radius_y as f32);
+ let y = y.clamp(0., radius_y);
self.put_pixel(x, y, color_1);
self.put_pixel(x_next, y, color_2);
diff --git a/alacritty/src/renderer/text/glsl3.rs b/alacritty/src/renderer/text/glsl3.rs
index 23c64653..b35c5ef3 100644
--- a/alacritty/src/renderer/text/glsl3.rs
+++ b/alacritty/src/renderer/text/glsl3.rs
@@ -50,7 +50,6 @@ impl Glsl3Renderer {
unsafe {
gl::Enable(gl::BLEND);
gl::BlendFunc(gl::SRC1_COLOR, gl::ONE_MINUS_SRC1_COLOR);
- gl::Enable(gl::MULTISAMPLE);
// Disable depth mask, as the renderer never uses depth tests.
gl::DepthMask(gl::FALSE);
diff --git a/alacritty/src/string.rs b/alacritty/src/string.rs
index 4a758b34..a111166d 100644
--- a/alacritty/src/string.rs
+++ b/alacritty/src/string.rs
@@ -5,7 +5,7 @@ use std::str::Chars;
use unicode_width::UnicodeWidthChar;
/// The action performed by [`StrShortener`].
-#[derive(Clone, Copy, PartialEq, Eq)]
+#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum TextAction {
/// Yield a spacer.
Spacer,
@@ -93,7 +93,7 @@ impl<'a> StrShortener<'a> {
let num_chars = iter.last().map_or(offset, |(idx, _)| idx + 1);
let skip_chars = num_chars - offset;
- let text_action = if num_chars <= max_width || shortener.is_none() {
+ let text_action = if current_len < max_width || shortener.is_none() {
TextAction::Char
} else {
TextAction::Shortener
@@ -203,8 +203,8 @@ mod tests {
&StrShortener::new(s, len * 2, ShortenDirection::Left, Some('.')).collect::<String>()
);
- let s = "こJんにちはP";
- let len = 2 + 1 + 2 + 2 + 2 + 2 + 1;
+ let s = "ちはP";
+ let len = 2 + 2 + 1;
assert_eq!(
".",
&StrShortener::new(s, 1, ShortenDirection::Right, Some('.')).collect::<String>()
@@ -226,7 +226,7 @@ mod tests {
);
assert_eq!(
- "こ .",
+ "ち .",
&StrShortener::new(s, 3, ShortenDirection::Right, Some('.')).collect::<String>()
);
@@ -236,12 +236,12 @@ mod tests {
);
assert_eq!(
- "こ Jん に ち は P",
+ "ち は P",
&StrShortener::new(s, len * 2, ShortenDirection::Left, Some('.')).collect::<String>()
);
assert_eq!(
- "こ Jん に ち は P",
+ "ち は P",
&StrShortener::new(s, len * 2, ShortenDirection::Right, Some('.')).collect::<String>()
);
}
diff --git a/alacritty/src/window_context.rs b/alacritty/src/window_context.rs
index 1dd620a4..45adf8b8 100644
--- a/alacritty/src/window_context.rs
+++ b/alacritty/src/window_context.rs
@@ -6,6 +6,7 @@ use std::io::Write;
use std::mem;
#[cfg(not(windows))]
use std::os::unix::io::{AsRawFd, RawFd};
+use std::rc::Rc;
#[cfg(not(any(target_os = "macos", windows)))]
use std::sync::atomic::Ordering;
use std::sync::Arc;
@@ -14,11 +15,12 @@ use crossfont::Size;
use glutin::event::{Event as GlutinEvent, ModifiersState, WindowEvent};
use glutin::event_loop::{EventLoopProxy, EventLoopWindowTarget};
use glutin::window::WindowId;
-use log::info;
+use log::{error, info};
use serde_json as json;
#[cfg(all(feature = "wayland", not(any(target_os = "macos", windows))))]
use wayland_client::EventQueue;
+use alacritty_config::SerdeReplace;
use alacritty_terminal::event::Event as TerminalEvent;
use alacritty_terminal::event_loop::{EventLoop as PtyEventLoop, Msg, Notifier};
use alacritty_terminal::grid::{Dimensions, Scroll};
@@ -28,12 +30,15 @@ use alacritty_terminal::term::test::TermSize;
use alacritty_terminal::term::{Term, TermMode};
use alacritty_terminal::tty;
+#[cfg(unix)]
+use crate::cli::IpcConfig;
use crate::cli::WindowOptions;
use crate::clipboard::Clipboard;
use crate::config::UiConfig;
use crate::display::Display;
use crate::event::{ActionContext, Event, EventProxy, EventType, Mouse, SearchState};
use crate::input;
+use crate::logging::LOG_TARGET_IPC_CONFIG;
use crate::message_bar::MessageBuffer;
use crate::scheduler::Scheduler;
@@ -52,17 +57,20 @@ pub struct WindowContext {
font_size: Size,
mouse: Mouse,
dirty: bool,
+ occluded: bool,
preserve_title: bool,
#[cfg(not(windows))]
master_fd: RawFd,
#[cfg(not(windows))]
shell_pid: u32,
+ ipc_config: Vec<(String, serde_yaml::Value)>,
+ config: Rc<UiConfig>,
}
impl WindowContext {
/// Create a new terminal window context.
pub fn new(
- config: &UiConfig,
+ config: Rc<UiConfig>,
options: &WindowOptions,
window_event_loop: &EventLoopWindowTarget<Event>,
proxy: EventLoopProxy<Event>,
@@ -80,7 +88,7 @@ impl WindowContext {
//
// The display manages a window and can draw the terminal.
let display = Display::new(
- config,
+ &config,
window_event_loop,
&identity,
#[cfg(all(feature = "wayland", not(any(target_os = "macos", windows))))]
@@ -108,7 +116,7 @@ impl WindowContext {
// The PTY forks a process to run the shell on the slave side of the
// pseudoterminal. A file descriptor for the master side is retained for
// reading/writing to the shell.
- let pty = tty::new(&pty_config, display.size_info.into(), display.window.x11_window_id())?;
+ let pty = tty::new(&pty_config, display.size_info.into(), display.window.id().into())?;
#[cfg(not(windows))]
let master_fd = pty.file().as_raw_fd();
@@ -141,57 +149,88 @@ impl WindowContext {
event_proxy.send_event(TerminalEvent::CursorBlinkingChange.into());
}
+ let font_size = config.font.size();
+
// Create context for the Alacritty window.
Ok(WindowContext {
- font_size: config.font.size(),
- notifier: Notifier(loop_tx),
+ preserve_title,
+ font_size,
terminal,
display,
- preserve_title,
#[cfg(not(windows))]
master_fd,
#[cfg(not(windows))]
shell_pid,
+ config,
+ notifier: Notifier(loop_tx),
cursor_blink_timed_out: Default::default(),
suppress_chars: Default::default(),
message_buffer: Default::default(),
received_count: Default::default(),
search_state: Default::default(),
event_queue: Default::default(),
+ ipc_config: Default::default(),
modifiers: Default::default(),
mouse: Default::default(),
dirty: Default::default(),
+ occluded: Default::default(),
})
}
/// Update the terminal window to the latest config.
- pub fn update_config(&mut self, old_config: &UiConfig, config: &UiConfig) {
- self.display.update_config(config);
- self.terminal.lock().update_config(&config.terminal_config);
+ pub fn update_config(&mut self, new_config: Rc<UiConfig>) {
+ let old_config = mem::replace(&mut self.config, new_config);
+
+ // Apply ipc config if there are overrides.
+ if !self.ipc_config.is_empty() {
+ let mut config = (*self.config).clone();
+
+ // Apply each option, removing broken ones.
+ let mut i = 0;
+ while i < self.ipc_config.len() {
+ let (key, value) = &self.ipc_config[i];
+
+ match config.replace(key, value.clone()) {
+ Err(err) => {
+ error!(
+ target: LOG_TARGET_IPC_CONFIG,
+ "Unable to override option '{}': {}", key, err
+ );
+ self.ipc_config.swap_remove(i);
+ },
+ Ok(_) => i += 1,
+ }
+ }
+
+ self.config = Rc::new(config);
+ }
+
+ self.display.update_config(&self.config);
+ self.terminal.lock().update_config(&self.config.terminal_config);
// Reload cursor if its thickness has changed.
if (old_config.terminal_config.cursor.thickness()
- - config.terminal_config.cursor.thickness())
+ - self.config.terminal_config.cursor.thickness())
.abs()
> f32::EPSILON
{
self.display.pending_update.set_cursor_dirty();
}
- if old_config.font != config.font {
+ if old_config.font != self.config.font {
// Do not update font size if it has been changed at runtime.
if self.font_size == old_config.font.size() {
- self.font_size = config.font.size();
+ self.font_size = self.config.font.size();
}
- let font = config.font.clone().with_size(self.font_size);
+ let font = self.config.font.clone().with_size(self.font_size);
self.display.pending_update.set_font(font);
}
// Update display if padding options were changed.
let window_config = &old_config.window;
- if window_config.padding(1.) != config.window.padding(1.)
- || window_config.dynamic_padding != config.window.dynamic_padding
+ if window_config.padding(1.) != self.config.window.padding(1.)
+ || window_config.dynamic_padding != self.config.window.dynamic_padding
{
self.display.pending_update.dirty = true;
}
@@ -204,18 +243,18 @@ impl WindowContext {
// │ N │ Y │ N ││ N │
// │ N │ N │ _ ││ Y │
if !self.preserve_title
- && (!config.window.dynamic_title
+ && (!self.config.window.dynamic_title
|| self.display.window.title() == old_config.window.identity.title)
{
- self.display.window.set_title(config.window.identity.title.clone());
+ self.display.window.set_title(self.config.window.identity.title.clone());
}
// Disable shadows for transparent windows on macOS.
#[cfg(target_os = "macos")]
- self.display.window.set_has_shadow(config.window_opacity() >= 1.0);
+ self.display.window.set_has_shadow(self.config.window_opacity() >= 1.0);
// Update hint keys.
- self.display.hint_state.update_alphabet(config.hints.alphabet());
+ self.display.hint_state.update_alphabet(self.config.hints.alphabet());
// Update cursor blinking.
let event = Event::new(TerminalEvent::CursorBlinkingChange.into(), None);
@@ -224,12 +263,48 @@ impl WindowContext {
self.dirty = true;
}
+ /// Update the IPC config overrides.
+ #[cfg(unix)]
+ pub fn update_ipc_config(&mut self, config: Rc<UiConfig>, ipc_config: IpcConfig) {
+ // Clear previous IPC errors.
+ self.message_buffer.remove_target(LOG_TARGET_IPC_CONFIG);
+
+ if ipc_config.reset {
+ self.ipc_config.clear();
+ } else {
+ for option in &ipc_config.options {
+ // Separate config key/value.
+ let (key, value) = match option.split_once('=') {
+ Some(split) => split,
+ None => {
+ error!(
+ target: LOG_TARGET_IPC_CONFIG,
+ "'{}': IPC config option missing value", option
+ );
+ continue;
+ },
+ };
+
+ // Try and parse value as yaml.
+ match serde_yaml::from_str(value) {
+ Ok(value) => self.ipc_config.push((key.to_owned(), value)),
+ Err(err) => error!(
+ target: LOG_TARGET_IPC_CONFIG,
+ "'{}': Invalid IPC config value: {:?}", option, err
+ ),
+ }
+ }
+ }
+
+ // Reload current config to pull new IPC config.
+ self.update_config(config);
+ }
+
/// Process events for this terminal window.
pub fn handle_event(
&mut self,
event_loop: &EventLoopWindowTarget<Event>,
event_proxy: &EventLoopProxy<Event>,
- config: &mut UiConfig,
clipboard: &mut Clipboard,
scheduler: &mut Scheduler,
event: GlutinEvent<'_, Event>,
@@ -276,17 +351,18 @@ impl WindowContext {
display: &mut self.display,
mouse: &mut self.mouse,
dirty: &mut self.dirty,
+ occluded: &mut self.occluded,
terminal: &mut terminal,
#[cfg(not(windows))]
master_fd: self.master_fd,
#[cfg(not(windows))]
shell_pid: self.shell_pid,
preserve_title: self.preserve_title,
+ config: &self.config,
event_proxy,
event_loop,
clipboard,
scheduler,
- config,
};
let mut processor = input::Processor::new(context);
@@ -303,7 +379,7 @@ impl WindowContext {
&self.message_buffer,
&self.search_state,
old_is_searching,
- config,
+ &self.config,
);
self.dirty = true;
}
@@ -311,7 +387,7 @@ impl WindowContext {
if self.dirty || self.mouse.hint_highlight_dirty {
self.dirty |= self.display.update_highlighted_hints(
&terminal,
- config,
+ &self.config,
&self.mouse,
self.modifiers,
);
@@ -324,7 +400,7 @@ impl WindowContext {
return;
}
- if self.dirty {
+ if self.dirty && !self.occluded {
// Force the display to process any pending display update.
self.display.process_renderer_update();
@@ -336,7 +412,7 @@ impl WindowContext {
}
// Redraw screen.
- self.display.draw(terminal, &self.message_buffer, config, &self.search_state);
+ self.display.draw(terminal, &self.message_buffer, &self.config, &self.search_state);
}
}
diff --git a/alacritty/windows/windows.rc b/alacritty/windows/alacritty.rc
index b265d4bc..b265d4bc 100644
--- a/alacritty/windows/windows.rc
+++ b/alacritty/windows/alacritty.rc
diff --git a/alacritty/windows/wix/alacritty.wxs b/alacritty/windows/wix/alacritty.wxs
index 461e97cb..1a002d8f 100644
--- a/alacritty/windows/wix/alacritty.wxs
+++ b/alacritty/windows/wix/alacritty.wxs
@@ -1,10 +1,10 @@
<?xml version="1.0" encoding="windows-1252"?>
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi" xmlns:util="http://schemas.microsoft.com/wix/UtilExtension">
- <Product Name="Alacritty" Id="*" UpgradeCode="87c21c74-dbd5-4584-89d5-46d9cd0c40a7" Language="1033" Codepage="1252" Version="0.11.0-dev" Manufacturer="Alacritty">
+ <Product Name="Alacritty" Id="*" UpgradeCode="87c21c74-dbd5-4584-89d5-46d9cd0c40a7" Language="1033" Codepage="1252" Version="0.12.0-dev" Manufacturer="Alacritty">
<Package InstallerVersion="200" Compressed="yes" InstallScope="perMachine"/>
<MajorUpgrade AllowSameVersionUpgrades="yes" DowngradeErrorMessage="A newer version of [ProductName] is already installed."/>
- <Icon Id="AlacrittyIco" SourceFile=".\extra\windows\alacritty.ico"/>
- <WixVariable Id="WixUILicenseRtf" Value=".\extra\windows\wix\license.rtf"/>
+ <Icon Id="AlacrittyIco" SourceFile=".\alacritty\windows\alacritty.ico"/>
+ <WixVariable Id="WixUILicenseRtf" Value=".\alacritty\windows\wix\license.rtf"/>
<Property Id="ARPPRODUCTICON" Value="AlacrittyIco"/>
<MediaTemplate EmbedCab="yes"/>
<UIRef Id="WixUI_Minimal"/>
diff --git a/alacritty_config/Cargo.toml b/alacritty_config/Cargo.toml
new file mode 100644
index 00000000..dde2d9ac
--- /dev/null
+++ b/alacritty_config/Cargo.toml
@@ -0,0 +1,14 @@
+[package]
+name = "alacritty_config"
+version = "0.1.1-dev"
+authors = ["Christian Duerr <contact@christianduerr.com>"]
+license = "MIT/Apache-2.0"
+description = "Alacritty configuration abstractions"
+homepage = "https://github.com/alacritty/alacritty"
+edition = "2021"
+rust-version = "1.57.0"
+
+[dependencies]
+log = { version = "0.4.17", features = ["serde"] }
+serde_yaml = "0.8.24"
+serde = "1.0.137"
diff --git a/alacritty_config/LICENSE-APACHE b/alacritty_config/LICENSE-APACHE
new file mode 120000
index 00000000..965b606f
--- /dev/null
+++ b/alacritty_config/LICENSE-APACHE
@@ -0,0 +1 @@
+../LICENSE-APACHE \ No newline at end of file
diff --git a/alacritty_config/LICENSE-MIT b/alacritty_config/LICENSE-MIT
new file mode 120000
index 00000000..76219eb7
--- /dev/null
+++ b/alacritty_config/LICENSE-MIT
@@ -0,0 +1 @@
+../LICENSE-MIT \ No newline at end of file
diff --git a/alacritty_config/src/lib.rs b/alacritty_config/src/lib.rs
new file mode 100644
index 00000000..7a467650
--- /dev/null
+++ b/alacritty_config/src/lib.rs
@@ -0,0 +1,64 @@
+use std::collections::HashMap;
+use std::error::Error;
+
+use log::LevelFilter;
+use serde::Deserialize;
+use serde_yaml::Value;
+
+pub trait SerdeReplace {
+ fn replace(&mut self, key: &str, value: Value) -> Result<(), Box<dyn Error>>;
+}
+
+macro_rules! impl_replace {
+ ($($ty:ty),*$(,)*) => {
+ $(
+ impl SerdeReplace for $ty {
+ fn replace(&mut self, key: &str, value: Value) -> Result<(), Box<dyn Error>> {
+ replace_simple(self, key, value)
+ }
+ }
+ )*
+ };
+}
+
+#[rustfmt::skip]
+impl_replace!(
+ usize, u8, u16, u32, u64, u128,
+ isize, i8, i16, i32, i64, i128,
+ f32, f64,
+ bool,
+ char,
+ String,
+ LevelFilter,
+);
+
+fn replace_simple<'de, D>(data: &mut D, key: &str, value: Value) -> Result<(), Box<dyn Error>>
+where
+ D: Deserialize<'de>,
+{
+ if !key.is_empty() {
+ let error = format!("Fields \"{}\" do not exist", key);
+ return Err(error.into());
+ }
+ *data = D::deserialize(value)?;
+
+ Ok(())
+}
+
+impl<'de, T: Deserialize<'de>> SerdeReplace for Vec<T> {
+ fn replace(&mut self, key: &str, value: Value) -> Result<(), Box<dyn Error>> {
+ replace_simple(self, key, value)
+ }
+}
+
+impl<'de, T: Deserialize<'de>> SerdeReplace for Option<T> {
+ fn replace(&mut self, key: &str, value: Value) -> Result<(), Box<dyn Error>> {
+ replace_simple(self, key, value)
+ }
+}
+
+impl<'de, T: Deserialize<'de>> SerdeReplace for HashMap<String, T> {
+ fn replace(&mut self, key: &str, value: Value) -> Result<(), Box<dyn Error>> {
+ replace_simple(self, key, value)
+ }
+}
diff --git a/alacritty_config_derive/Cargo.toml b/alacritty_config_derive/Cargo.toml
index 8584d0d2..f01899b5 100644
--- a/alacritty_config_derive/Cargo.toml
+++ b/alacritty_config_derive/Cargo.toml
@@ -1,6 +1,6 @@
[package]
name = "alacritty_config_derive"
-version = "0.1.0"
+version = "0.2.1-dev"
authors = ["Christian Duerr <contact@christianduerr.com>"]
license = "MIT/Apache-2.0"
description = "Failure resistant deserialization derive"
@@ -16,7 +16,11 @@ syn = { version = "1.0.53", features = ["derive", "parsing", "proc-macro", "prin
proc-macro2 = "1.0.24"
quote = "1.0.7"
+[dev-dependencies.alacritty_config]
+path = "../alacritty_config"
+version = "0.1.1-dev"
+
[dev-dependencies]
+serde = { version = "1.0.117", features = ["derive"] }
serde_yaml = "0.8.14"
-serde = "1.0.117"
log = "0.4.11"
diff --git a/alacritty_config_derive/LICENSE-MIT b/alacritty_config_derive/LICENSE-MIT
index 31aa7938..76219eb7 100644..120000
--- a/alacritty_config_derive/LICENSE-MIT
+++ b/alacritty_config_derive/LICENSE-MIT
@@ -1,23 +1 @@
-Permission is hereby granted, free of charge, to any
-person obtaining a copy of this software and associated
-documentation files (the "Software"), to deal in the
-Software without restriction, including without
-limitation the rights to use, copy, modify, merge,
-publish, distribute, sublicense, and/or sell copies of
-the Software, and to permit persons to whom the Software
-is furnished to do so, subject to the following
-conditions:
-
-The above copyright notice and this permission notice
-shall be included in all copies or substantial portions
-of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
-ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
-TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
-PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
-SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
-CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
-OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
-IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
-DEALINGS IN THE SOFTWARE.
+../LICENSE-MIT \ No newline at end of file
diff --git a/alacritty_config_derive/src/de_enum.rs b/alacritty_config_derive/src/config_deserialize/de_enum.rs
index 98247c0c..73634e73 100644
--- a/alacritty_config_derive/src/de_enum.rs
+++ b/alacritty_config_derive/src/config_deserialize/de_enum.rs
@@ -1,9 +1,11 @@
use proc_macro::TokenStream;
use proc_macro2::TokenStream as TokenStream2;
use quote::{format_ident, quote};
-use syn::{DataEnum, Ident};
+use syn::{DataEnum, Generics, Ident};
-pub fn derive_deserialize(ident: Ident, data_enum: DataEnum) -> TokenStream {
+use crate::serde_replace;
+
+pub fn derive_deserialize(ident: Ident, generics: Generics, data_enum: DataEnum) -> TokenStream {
let visitor = format_ident!("{}Visitor", ident);
// Create match arm streams and get a list with all available values.
@@ -30,7 +32,7 @@ pub fn derive_deserialize(ident: Ident, data_enum: DataEnum) -> TokenStream {
available_values.truncate(available_values.len().saturating_sub(2));
// Generate deserialization impl.
- let tokens = quote! {
+ let mut tokens = quote! {
struct #visitor;
impl<'de> serde::de::Visitor<'de> for #visitor {
type Value = #ident;
@@ -62,5 +64,8 @@ pub fn derive_deserialize(ident: Ident, data_enum: DataEnum) -> TokenStream {
}
};
+ // Automatically implement [`alacritty_config::SerdeReplace`].
+ tokens.extend(serde_replace::derive_direct(ident, generics));
+
tokens.into()
}
diff --git a/alacritty_config_derive/src/de_struct.rs b/alacritty_config_derive/src/config_deserialize/de_struct.rs
index cf7ea141..4245764f 100644
--- a/alacritty_config_derive/src/de_struct.rs
+++ b/alacritty_config_derive/src/config_deserialize/de_struct.rs
@@ -1,13 +1,12 @@
use proc_macro::TokenStream;
use proc_macro2::TokenStream as TokenStream2;
use quote::{format_ident, quote};
-use syn::parse::{self, Parse, ParseStream};
use syn::punctuated::Punctuated;
use syn::spanned::Spanned;
-use syn::{Error, Field, GenericParam, Generics, Ident, LitStr, Token, Type, TypeParam};
+use syn::{Error, Field, Generics, Ident, Type};
+
+use crate::{serde_replace, Attr, GenericsStreams, MULTIPLE_FLATTEN_ERROR};
-/// Error message when attempting to flatten multiple fields.
-const MULTIPLE_FLATTEN_ERROR: &str = "At most one instance of #[config(flatten)] is supported";
/// Use this crate's name as log target.
const LOG_TARGET: &str = env!("CARGO_PKG_NAME");
@@ -18,20 +17,20 @@ pub fn derive_deserialize<T>(
) -> TokenStream {
// Create all necessary tokens for the implementation.
let GenericsStreams { unconstrained, constrained, phantoms } =
- generics_streams(generics.params);
+ crate::generics_streams(&generics.params);
let FieldStreams { flatten, match_assignments } = fields_deserializer(&fields);
let visitor = format_ident!("{}Visitor", ident);
// Generate deserialization impl.
- let tokens = quote! {
+ let mut tokens = quote! {
#[derive(Default)]
#[allow(non_snake_case)]
- struct #visitor < #unconstrained > {
+ struct #visitor <#unconstrained> {
#phantoms
}
- impl<'de, #constrained> serde::de::Visitor<'de> for #visitor < #unconstrained > {
- type Value = #ident < #unconstrained >;
+ impl <'de, #constrained> serde::de::Visitor<'de> for #visitor <#unconstrained> {
+ type Value = #ident <#unconstrained>;
fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
formatter.write_str("a mapping")
@@ -61,7 +60,7 @@ pub fn derive_deserialize<T>(
}
}
- impl<'de, #constrained> serde::Deserialize<'de> for #ident < #unconstrained > {
+ impl <'de, #constrained> serde::Deserialize<'de> for #ident <#unconstrained> {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: serde::Deserializer<'de>,
@@ -71,6 +70,9 @@ pub fn derive_deserialize<T>(
}
};
+ // Automatically implement [`alacritty_config::SerdeReplace`].
+ tokens.extend(serde_replace::derive_recursive(ident, generics, fields));
+
tokens.into()
}
@@ -177,50 +179,3 @@ fn field_deserializer(field_streams: &mut FieldStreams, field: &Field) -> Result
Ok(())
}
-
-/// Field attribute.
-struct Attr {
- ident: String,
- param: Option<LitStr>,
-}
-
-impl Parse for Attr {
- fn parse(input: ParseStream<'_>) -> parse::Result<Self> {
- let ident = input.parse::<Ident>()?.to_string();
- let param = input.parse::<Token![=]>().and_then(|_| input.parse()).ok();
- Ok(Self { ident, param })
- }
-}
-
-/// Storage for all necessary generics information.
-#[derive(Default)]
-struct GenericsStreams {
- unconstrained: TokenStream2,
- constrained: TokenStream2,
- phantoms: TokenStream2,
-}
-
-/// Create the necessary generics annotations.
-///
-/// This will create three different token streams, which might look like this:
-/// - unconstrained: `T`
-/// - constrained: `T: Default + Deserialize<'de>`
-/// - phantoms: `T: PhantomData<T>,`
-fn generics_streams<T>(params: Punctuated<GenericParam, T>) -> GenericsStreams {
- let mut generics = GenericsStreams::default();
-
- for generic in params {
- // NOTE: Lifetimes and const params are not supported.
- if let GenericParam::Type(TypeParam { ident, .. }) = generic {
- generics.unconstrained.extend(quote!( #ident , ));
- generics.constrained.extend(quote! {
- #ident : Default + serde::Deserialize<'de> ,
- });
- generics.phantoms.extend(quote! {
- #ident : std::marker::PhantomData < #ident >,
- });
- }
- }
-
- generics
-}
diff --git a/alacritty_config_derive/src/config_deserialize/mod.rs b/alacritty_config_derive/src/config_deserialize/mod.rs
new file mode 100644
index 00000000..b1923377
--- /dev/null
+++ b/alacritty_config_derive/src/config_deserialize/mod.rs
@@ -0,0 +1,22 @@
+use proc_macro::TokenStream;
+use syn::{parse_macro_input, Data, DataStruct, DeriveInput, Error, Fields};
+
+/// Error if the derive was used on an unsupported type.
+const UNSUPPORTED_ERROR: &str = "ConfigDeserialize must be used on an enum or struct with fields";
+
+mod de_enum;
+mod de_struct;
+
+pub fn derive(input: TokenStream) -> TokenStream {
+ let input = parse_macro_input!(input as DeriveInput);
+
+ match input.data {
+ Data::Struct(DataStruct { fields: Fields::Named(fields), .. }) => {
+ de_struct::derive_deserialize(input.ident, input.generics, fields.named)
+ },
+ Data::Enum(data_enum) => {
+ de_enum::derive_deserialize(input.ident, input.generics, data_enum)
+ },
+ _ => Error::new(input.ident.span(), UNSUPPORTED_ERROR).to_compile_error().into(),
+ }
+}
diff --git a/alacritty_config_derive/src/lib.rs b/alacritty_config_derive/src/lib.rs
index 8601d5cb..116d4828 100644
--- a/alacritty_config_derive/src/lib.rs
+++ b/alacritty_config_derive/src/lib.rs
@@ -1,23 +1,28 @@
+#![deny(clippy::all, clippy::if_not_else, clippy::enum_glob_use)]
+#![cfg_attr(feature = "cargo-clippy", deny(warnings))]
+
use proc_macro::TokenStream;
-use syn::{parse_macro_input, Data, DataStruct, DeriveInput, Error, Fields, Path};
+use proc_macro2::TokenStream as TokenStream2;
+use quote::quote;
+use syn::parse::{self, Parse, ParseStream};
+use syn::punctuated::Punctuated;
+use syn::{GenericParam, Ident, LitStr, Path, Token, TypeParam};
-mod de_enum;
-mod de_struct;
+mod config_deserialize;
+mod serde_replace;
-/// Error if the derive was used on an unsupported type.
-const UNSUPPORTED_ERROR: &str = "ConfigDeserialize must be used on a struct with fields";
+/// Error message when attempting to flatten multiple fields.
+pub(crate) const MULTIPLE_FLATTEN_ERROR: &str =
+ "At most one instance of #[config(flatten)] is supported";
#[proc_macro_derive(ConfigDeserialize, attributes(config))]
pub fn derive_config_deserialize(input: TokenStream) -> TokenStream {
- let input = parse_macro_input!(input as DeriveInput);
-
- match input.data {
- Data::Struct(DataStruct { fields: Fields::Named(fields), .. }) => {
- de_struct::derive_deserialize(input.ident, input.generics, fields.named)
- },
- Data::Enum(data_enum) => de_enum::derive_deserialize(input.ident, data_enum),
- _ => Error::new(input.ident.span(), UNSUPPORTED_ERROR).to_compile_error().into(),
- }
+ config_deserialize::derive(input)
+}
+
+#[proc_macro_derive(SerdeReplace)]
+pub fn derive_serde_replace(input: TokenStream) -> TokenStream {
+ serde_replace::derive(input)
}
/// Verify that a token path ends with a specific segment.
@@ -25,3 +30,50 @@ pub(crate) fn path_ends_with(path: &Path, segment: &str) -> bool {
let segments = path.segments.iter();
segments.last().map_or(false, |s| s.ident == segment)
}
+
+/// Storage for all necessary generics information.
+#[derive(Default)]
+struct GenericsStreams {
+ unconstrained: TokenStream2,
+ constrained: TokenStream2,
+ phantoms: TokenStream2,
+}
+
+/// Create the necessary generics annotations.
+///
+/// This will create three different token streams, which might look like this:
+/// - unconstrained: `T`
+/// - constrained: `T: Default + Deserialize<'de>`
+/// - phantoms: `T: PhantomData<T>,`
+pub(crate) fn generics_streams<T>(params: &Punctuated<GenericParam, T>) -> GenericsStreams {
+ let mut generics = GenericsStreams::default();
+
+ for generic in params {
+ // NOTE: Lifetimes and const params are not supported.
+ if let GenericParam::Type(TypeParam { ident, .. }) = generic {
+ generics.unconstrained.extend(quote!( #ident , ));
+ generics.constrained.extend(quote! {
+ #ident : Default + serde::Deserialize<'de> + alacritty_config::SerdeReplace,
+ });
+ generics.phantoms.extend(quote! {
+ #ident : std::marker::PhantomData < #ident >,
+ });
+ }
+ }
+
+ generics
+}
+
+/// Field attribute.
+pub(crate) struct Attr {
+ ident: String,
+ param: Option<LitStr>,
+}
+
+impl Parse for Attr {
+ fn parse(input: ParseStream<'_>) -> parse::Result<Self> {
+ let ident = input.parse::<Ident>()?.to_string();
+ let param = input.parse::<Token![=]>().and_then(|_| input.parse()).ok();
+ Ok(Self { ident, param })
+ }
+}
diff --git a/alacritty_config_derive/src/serde_replace.rs b/alacritty_config_derive/src/serde_replace.rs
new file mode 100644
index 00000000..4a0a6a99
--- /dev/null
+++ b/alacritty_config_derive/src/serde_replace.rs
@@ -0,0 +1,113 @@
+use proc_macro::TokenStream;
+use proc_macro2::TokenStream as TokenStream2;
+use quote::quote;
+use syn::punctuated::Punctuated;
+use syn::{
+ parse_macro_input, Data, DataStruct, DeriveInput, Error, Field, Fields, Generics, Ident,
+};
+
+use crate::{Attr, GenericsStreams, MULTIPLE_FLATTEN_ERROR};
+
+/// Error if the derive was used on an unsupported type.
+const UNSUPPORTED_ERROR: &str = "SerdeReplace must be used on a tuple struct";
+
+pub fn derive(input: TokenStream) -> TokenStream {
+ let input = parse_macro_input!(input as DeriveInput);
+
+ match input.data {
+ Data::Struct(DataStruct { fields: Fields::Unnamed(_), .. }) | Data::Enum(_) => {
+ derive_direct(input.ident, input.generics).into()
+ },
+ Data::Struct(DataStruct { fields: Fields::Named(fields), .. }) => {
+ derive_recursive(input.ident, input.generics, fields.named).into()
+ },
+ _ => Error::new(input.ident.span(), UNSUPPORTED_ERROR).to_compile_error().into(),
+ }
+}
+
+pub fn derive_direct(ident: Ident, generics: Generics) -> TokenStream2 {
+ quote! {
+ impl <#generics> alacritty_config::SerdeReplace for #ident <#generics> {
+ fn replace(&mut self, key: &str, value: serde_yaml::Value) -> Result<(), Box<dyn std::error::Error>> {
+ if !key.is_empty() {
+ let error = format!("Fields \"{}\" do not exist", key);
+ return Err(error.into());
+ }
+ *self = serde::Deserialize::deserialize(value)?;
+
+ Ok(())
+ }
+ }
+ }
+}
+
+pub fn derive_recursive<T>(
+ ident: Ident,
+ generics: Generics,
+ fields: Punctuated<Field, T>,
+) -> TokenStream2 {
+ let GenericsStreams { unconstrained, constrained, .. } =
+ crate::generics_streams(&generics.params);
+ let replace_arms = match_arms(&fields);
+
+ quote! {
+ #[allow(clippy::extra_unused_lifetimes)]
+ impl <'de, #constrained> alacritty_config::SerdeReplace for #ident <#unconstrained> {
+ fn replace(&mut self, key: &str, value: serde_yaml::Value) -> Result<(), Box<dyn std::error::Error>> {
+ if key.is_empty() {
+ *self = serde::Deserialize::deserialize(value)?;
+ return Ok(());
+ }
+
+ let (field, next_key) = key.split_once('.').unwrap_or((key, ""));
+ match field {
+ #replace_arms
+ _ => {
+ let error = format!("Field \"{}\" does not exist", field);
+ return Err(error.into());
+ },
+ }
+
+ Ok(())
+ }
+ }
+ }
+}
+
+/// Create SerdeReplace recursive match arms.
+fn match_arms<T>(fields: &Punctuated<Field, T>) -> TokenStream2 {
+ let mut stream = TokenStream2::default();
+ let mut flattened_arm = None;
+
+ // Create arm for each field.
+ for field in fields {
+ let ident = field.ident.as_ref().expect("unreachable tuple struct");
+ let literal = ident.to_string();
+
+ // Check if #[config(flattened)] attribute is present.
+ let flatten = field
+ .attrs
+ .iter()
+ .filter_map(|attr| attr.parse_args::<Attr>().ok())
+ .any(|parsed| parsed.ident.as_str() == "flatten");
+
+ if flatten && flattened_arm.is_some() {
+ return Error::new(ident.span(), MULTIPLE_FLATTEN_ERROR).to_compile_error();
+ } else if flatten {
+ flattened_arm = Some(quote! {
+ _ => alacritty_config::SerdeReplace::replace(&mut self.#ident, key, value)?,
+ });
+ } else {
+ stream.extend(quote! {
+ #literal => alacritty_config::SerdeReplace::replace(&mut self.#ident, next_key, value)?,
+ });
+ }
+ }
+
+ // Add the flattened catch-all as last match arm.
+ if let Some(flattened_arm) = flattened_arm.take() {
+ stream.extend(flattened_arm);
+ }
+
+ stream
+}
diff --git a/alacritty_config_derive/tests/config.rs b/alacritty_config_derive/tests/config.rs
index 2cdae613..bd449ff8 100644
--- a/alacritty_config_derive/tests/config.rs
+++ b/alacritty_config_derive/tests/config.rs
@@ -1,8 +1,10 @@
use std::sync::{Arc, Mutex};
use log::{Level, Log, Metadata, Record};
+use serde::Deserialize;
-use alacritty_config_derive::ConfigDeserialize;
+use alacritty_config::SerdeReplace as _;
+use alacritty_config_derive::{ConfigDeserialize, SerdeReplace};
#[derive(ConfigDeserialize, Debug, PartialEq, Eq)]
enum TestEnum {
@@ -63,6 +65,7 @@ struct Test2<T: Default> {
field3: usize,
#[config(alias = "aliased")]
field4: u8,
+ newtype: NewType,
}
#[derive(ConfigDeserialize, Default)]
@@ -70,6 +73,9 @@ struct Test3 {
flatty: usize,
}
+#[derive(SerdeReplace, Deserialize, Default, PartialEq, Eq, Debug)]
+struct NewType(usize);
+
#[test]
fn config_deserialize() {
let logger = unsafe {
@@ -105,7 +111,7 @@ fn config_deserialize() {
assert_eq!(test.enom_small, TestEnum::One);
assert_eq!(test.enom_big, TestEnum::Three);
assert_eq!(test.enom_error, Test::default().enom_error);
- assert_eq!(test.gone, false);
+ assert!(!test.gone);
assert_eq!(test.nesting.field1, Test::default().nesting.field1);
assert_eq!(test.nesting.field2, None);
assert_eq!(test.nesting.field3, Test::default().nesting.field3);
@@ -159,3 +165,33 @@ impl Log for Logger {
fn flush(&self) {}
}
+
+#[test]
+fn field_replacement() {
+ let mut test = Test::default();
+
+ let value = serde_yaml::to_value(13).unwrap();
+ test.replace("nesting.field2", value).unwrap();
+
+ assert_eq!(test.nesting.field2, Some(13));
+}
+
+#[test]
+fn replace_derive() {
+ let mut test = Test::default();
+
+ let value = serde_yaml::to_value(9).unwrap();
+ test.replace("nesting.newtype", value).unwrap();
+
+ assert_eq!(test.nesting.newtype, NewType(9));
+}
+
+#[test]
+fn replace_flatten() {
+ let mut test = Test::default();
+
+ let value = serde_yaml::to_value(7).unwrap();
+ test.replace("flatty", value).unwrap();
+
+ assert_eq!(test.flatten.flatty, 7);
+}
diff --git a/alacritty_terminal/Cargo.toml b/alacritty_terminal/Cargo.toml
index c798e065..bece9713 100644
--- a/alacritty_terminal/Cargo.toml
+++ b/alacritty_terminal/Cargo.toml
@@ -1,6 +1,6 @@
[package]
name = "alacritty_terminal"
-version = "0.17.0-dev"
+version = "0.17.1-dev"
authors = ["Christian Duerr <contact@christianduerr.com>", "Joe Wilm <joe@jwilm.com>"]
license = "Apache-2.0"
description = "Library for writing terminal emulators"
@@ -11,12 +11,16 @@ rust-version = "1.57.0"
[dependencies.alacritty_config_derive]
path = "../alacritty_config_derive"
-version = "0.1.0"
+version = "0.2.1-dev"
+
+[dependencies.alacritty_config]
+path = "../alacritty_config"
+version = "0.1.1-dev"
[dependencies]
libc = "0.2"
bitflags = "1"
-parking_lot = "0.11.0"
+parking_lot = "0.12.0"
serde = { version = "1", features = ["derive", "rc"] }
serde_yaml = "0.8"
vte = { version = "0.10.0", default-features = false }
@@ -30,17 +34,20 @@ dirs = "4.0.0"
smallvec = { version = "1.9.0", features = ["serde"] }
[target.'cfg(unix)'.dependencies]
-nix = "0.22.0"
+nix = "0.24.1"
signal-hook = "0.3.10"
signal-hook-mio = { version = "0.2.1", features = ["support-v0_6"] }
[target.'cfg(windows)'.dependencies]
miow = "0.3"
-winapi = { version = "0.3.7", features = [
- "impl-default", "basetsd", "libloaderapi", "minwindef", "ntdef", "processthreadsapi", "winbase",
- "wincon", "wincontypes", "winerror", "winnt", "winuser", "consoleapi",
-]}
mio-anonymous-pipes = "0.2"
+windows-sys = { version = "0.36", features = [
+ "Win32_System_Console",
+ "Win32_Foundation",
+ "Win32_Security",
+ "Win32_System_Threading",
+ "Win32_System_WindowsProgramming",
+]}
[dev-dependencies]
serde_json = "1.0.0"
diff --git a/alacritty_terminal/src/config/mod.rs b/alacritty_terminal/src/config/mod.rs
index 5822d591..f17c327f 100644
--- a/alacritty_terminal/src/config/mod.rs
+++ b/alacritty_terminal/src/config/mod.rs
@@ -4,7 +4,7 @@ use std::path::PathBuf;
use serde::Deserialize;
-use alacritty_config_derive::ConfigDeserialize;
+use alacritty_config_derive::{ConfigDeserialize, SerdeReplace};
mod scrolling;
@@ -12,12 +12,13 @@ use crate::ansi::{CursorShape, CursorStyle};
pub use crate::config::scrolling::{Scrolling, MAX_SCROLLBACK_LINES};
+/// Logging target for config error messages.
pub const LOG_TARGET_CONFIG: &str = "alacritty_config_derive";
const MIN_BLINK_INTERVAL: u64 = 10;
/// Top-level config type.
-#[derive(ConfigDeserialize, Debug, PartialEq, Default)]
+#[derive(ConfigDeserialize, Clone, Debug, PartialEq, Default)]
pub struct Config {
/// TERM env variable.
pub env: HashMap<String, String>,
@@ -125,7 +126,7 @@ impl Cursor {
}
}
-#[derive(Deserialize, Debug, Copy, Clone, PartialEq, Eq)]
+#[derive(SerdeReplace, Deserialize, Debug, Copy, Clone, PartialEq, Eq)]
#[serde(untagged)]
pub enum ConfigCursorStyle {
Shape(CursorShape),
@@ -222,7 +223,7 @@ impl Program {
}
/// Wrapper around f32 that represents a percentage value between 0.0 and 1.0.
-#[derive(Deserialize, Clone, Copy, Debug, PartialEq)]
+#[derive(SerdeReplace, Deserialize, Clone, Copy, Debug, PartialEq)]
pub struct Percentage(f32);
impl Default for Percentage {
@@ -233,13 +234,7 @@ impl Default for Percentage {
impl Percentage {
pub fn new(value: f32) -> Self {
- Percentage(if value < 0.0 {
- 0.0
- } else if value > 1.0 {
- 1.0
- } else {
- value
- })
+ Percentage(value.clamp(0., 1.))
}
pub fn as_f32(self) -> f32 {
diff --git a/alacritty_terminal/src/config/scrolling.rs b/alacritty_terminal/src/config/scrolling.rs
index 9a5a718c..f4e55787 100644
--- a/alacritty_terminal/src/config/scrolling.rs
+++ b/alacritty_terminal/src/config/scrolling.rs
@@ -1,7 +1,7 @@
use serde::de::Error as SerdeError;
use serde::{Deserialize, Deserializer};
-use alacritty_config_derive::ConfigDeserialize;
+use alacritty_config_derive::{ConfigDeserialize, SerdeReplace};
/// Maximum scrollback amount configurable.
pub const MAX_SCROLLBACK_LINES: u32 = 100_000;
@@ -31,7 +31,7 @@ impl Scrolling {
}
}
-#[derive(Copy, Clone, Debug, PartialEq, Eq)]
+#[derive(SerdeReplace, Copy, Clone, Debug, PartialEq, Eq)]
struct ScrollingHistory(u32);
impl Default for ScrollingHistory {
diff --git a/alacritty_terminal/src/index.rs b/alacritty_terminal/src/index.rs
index e672c752..9464b8d8 100644
--- a/alacritty_terminal/src/index.rs
+++ b/alacritty_terminal/src/index.rs
@@ -7,6 +7,8 @@ use std::ops::{Add, AddAssign, Deref, Sub, SubAssign};
use serde::{Deserialize, Serialize};
+use alacritty_config_derive::SerdeReplace;
+
use crate::grid::Dimensions;
/// The side of a cell.
@@ -222,7 +224,19 @@ impl PartialEq<usize> for Line {
/// A column.
///
/// Newtype to avoid passing values incorrectly.
-#[derive(Serialize, Deserialize, Debug, Copy, Clone, Eq, PartialEq, Default, Ord, PartialOrd)]
+#[derive(
+ SerdeReplace,
+ Serialize,
+ Deserialize,
+ Debug,
+ Copy,
+ Clone,
+ Eq,
+ PartialEq,
+ Default,
+ Ord,
+ PartialOrd,
+)]
pub struct Column(pub usize);
impl fmt::Display for Column {
diff --git a/alacritty_terminal/src/term/color.rs b/alacritty_terminal/src/term/color.rs
index 1cfdec6b..22b30828 100644
--- a/alacritty_terminal/src/term/color.rs
+++ b/alacritty_terminal/src/term/color.rs
@@ -7,12 +7,14 @@ use serde::de::{Error as _, Visitor};
use serde::{Deserialize, Deserializer, Serialize};
use serde_yaml::Value;
+use alacritty_config_derive::SerdeReplace;
+
use crate::ansi::NamedColor;
/// Number of terminal colors.
pub const COUNT: usize = 269;
-#[derive(Debug, Eq, PartialEq, Copy, Clone, Default, Serialize)]
+#[derive(SerdeReplace, Debug, Eq, PartialEq, Copy, Clone, Default, Serialize)]
pub struct Rgb {
pub r: u8,
pub g: u8,
@@ -62,9 +64,9 @@ impl Mul<f32> for Rgb {
fn mul(self, rhs: f32) -> Rgb {
let result = Rgb {
- r: (f32::from(self.r) * rhs).max(0.0).min(255.0) as u8,
- g: (f32::from(self.g) * rhs).max(0.0).min(255.0) as u8,
- b: (f32::from(self.b) * rhs).max(0.0).min(255.0) as u8,
+ r: (f32::from(self.r) * rhs).clamp(0.0, 255.0) as u8,
+ g: (f32::from(self.g) * rhs).clamp(0.0, 255.0) as u8,
+ b: (f32::from(self.b) * rhs).clamp(0.0, 255.0) as u8,
};
trace!("Scaling RGB by {} from {:?} to {:?}", rhs, self, result);
@@ -170,7 +172,7 @@ impl FromStr for Rgb {
}
/// RGB color optionally referencing the cell's foreground or background.
-#[derive(Copy, Clone, Debug, PartialEq, Eq)]
+#[derive(SerdeReplace, Copy, Clone, Debug, PartialEq, Eq)]
pub enum CellRgb {
CellForeground,
CellBackground,
diff --git a/alacritty_terminal/src/term/mod.rs b/alacritty_terminal/src/term/mod.rs
index b6848812..d54d9998 100644
--- a/alacritty_terminal/src/term/mod.rs
+++ b/alacritty_terminal/src/term/mod.rs
@@ -212,7 +212,7 @@ impl TermDamageState {
/// Damage point inside of the viewport.
#[inline]
fn damage_point(&mut self, point: Point<usize>) {
- self.damage_line(point.line, point.column.0 as usize, point.column.0 as usize);
+ self.damage_line(point.line, point.column.0, point.column.0);
}
/// Expand `line`'s damage to span at least `left` to `right` column.
@@ -238,7 +238,7 @@ impl TermDamageState {
};
let start = cmp::max(selection.start.line.0 + display_offset, 0);
- let end = cmp::min(cmp::max(selection.end.line.0 + display_offset, 0), last_visible_line);
+ let end = (selection.end.line.0 + display_offset).clamp(0, last_visible_line);
for line in start as usize..=end as usize {
self.damage_line(line, 0, num_cols - 1);
}
@@ -1267,7 +1267,7 @@ impl<T: EventListener> Handler for Term<T> {
if self.grid.cursor.point.column > Column(0) {
let line = self.grid.cursor.point.line.0 as usize;
- let column = self.grid.cursor.point.column.0 as usize;
+ let column = self.grid.cursor.point.column.0;
self.grid.cursor.point.column -= 1;
self.grid.cursor.input_needs_wrap = false;
self.damage.damage_line(line, column - 1, column);
@@ -1570,7 +1570,7 @@ impl<T: EventListener> Handler for Term<T> {
self.event_proxy.send_event(Event::ClipboardLoad(
clipboard_type,
Arc::new(move |text| {
- let base64 = base64::encode(&text);
+ let base64 = base64::encode(text);
format!("\x1b]52;{};{}{}", clipboard as char, base64, terminator)
}),
));
diff --git a/alacritty_terminal/src/tty/unix.rs b/alacritty_terminal/src/tty/unix.rs
index f52f0920..63da4f9c 100644
--- a/alacritty_terminal/src/tty/unix.rs
+++ b/alacritty_terminal/src/tty/unix.rs
@@ -148,7 +148,7 @@ fn default_shell_command(pw: &Passwd<'_>) -> Command {
}
/// Create a new TTY and return a handle to interact with it.
-pub fn new(config: &PtyConfig, window_size: WindowSize, window_id: Option<usize>) -> Result<Pty> {
+pub fn new(config: &PtyConfig, window_size: WindowSize, window_id: u64) -> Result<Pty> {
let (master, slave) = make_pty(window_size.to_winsize())?;
#[cfg(any(target_os = "linux", target_os = "macos"))]
@@ -178,13 +178,14 @@ pub fn new(config: &PtyConfig, window_size: WindowSize, window_id: Option<usize>
builder.stdout(unsafe { Stdio::from_raw_fd(slave) });
// Setup shell environment.
+ let window_id = window_id.to_string();
+ builder.env("ALACRITTY_WINDOW_ID", &window_id);
builder.env("LOGNAME", pw.name);
builder.env("USER", pw.name);
builder.env("HOME", pw.dir);
- if let Some(window_id) = window_id {
- builder.env("WINDOWID", format!("{}", window_id));
- }
+ // Set Window ID for clients relying on X11 hacks.
+ builder.env("WINDOWID", window_id);
unsafe {
builder.pre_exec(move || {
diff --git a/alacritty_terminal/src/tty/windows/child.rs b/alacritty_terminal/src/tty/windows/child.rs
index fc163600..91dd1725 100644
--- a/alacritty_terminal/src/tty/windows/child.rs
+++ b/alacritty_terminal/src/tty/windows/child.rs
@@ -4,14 +4,16 @@ use std::sync::atomic::{AtomicPtr, Ordering};
use mio_extras::channel::{channel, Receiver, Sender};
-use winapi::shared::ntdef::{BOOLEAN, HANDLE, PVOID};
-use winapi::um::winbase::{RegisterWaitForSingleObject, UnregisterWait, INFINITE};
-use winapi::um::winnt::{WT_EXECUTEINWAITTHREAD, WT_EXECUTEONLYONCE};
+use windows_sys::Win32::Foundation::{BOOLEAN, HANDLE};
+use windows_sys::Win32::System::Threading::{
+ RegisterWaitForSingleObject, UnregisterWait, WT_EXECUTEINWAITTHREAD, WT_EXECUTEONLYONCE,
+};
+use windows_sys::Win32::System::WindowsProgramming::INFINITE;
use crate::tty::ChildEvent;
/// WinAPI callback to run when child process exits.
-extern "system" fn child_exit_callback(ctx: PVOID, timed_out: BOOLEAN) {
+extern "system" fn child_exit_callback(ctx: *mut c_void, timed_out: BOOLEAN) {
if timed_out != 0 {
return;
}
@@ -29,7 +31,7 @@ impl ChildExitWatcher {
pub fn new(child_handle: HANDLE) -> Result<ChildExitWatcher, Error> {
let (event_tx, event_rx) = channel::<ChildEvent>();
- let mut wait_handle: HANDLE = 0 as HANDLE;
+ let mut wait_handle: HANDLE = 0;
let sender_ref = Box::new(event_tx);
let success = unsafe {
@@ -37,7 +39,7 @@ impl ChildExitWatcher {
&mut wait_handle,
child_handle,
Some(child_exit_callback),
- Box::into_raw(sender_ref) as PVOID,
+ Box::into_raw(sender_ref).cast(),
INFINITE,
WT_EXECUTEINWAITTHREAD | WT_EXECUTEONLYONCE,
)
@@ -46,7 +48,10 @@ impl ChildExitWatcher {
if success == 0 {
Err(Error::last_os_error())
} else {
- Ok(ChildExitWatcher { wait_handle: AtomicPtr::from(wait_handle), event_rx })
+ Ok(ChildExitWatcher {
+ wait_handle: AtomicPtr::from(wait_handle as *mut c_void),
+ event_rx,
+ })
}
}
@@ -58,7 +63,7 @@ impl ChildExitWatcher {
impl Drop for ChildExitWatcher {
fn drop(&mut self) {
unsafe {
- UnregisterWait(self.wait_handle.load(Ordering::Relaxed));
+ UnregisterWait(self.wait_handle.load(Ordering::Relaxed) as HANDLE);
}
}
}
@@ -78,7 +83,7 @@ mod tests {
const WAIT_TIMEOUT: Duration = Duration::from_millis(200);
let mut child = Command::new("cmd.exe").spawn().unwrap();
- let child_exit_watcher = ChildExitWatcher::new(child.as_raw_handle()).unwrap();
+ let child_exit_watcher = ChildExitWatcher::new(child.as_raw_handle() as HANDLE).unwrap();
let mut events = Events::with_capacity(1);
let poll = Poll::new().unwrap();
diff --git a/alacritty_terminal/src/tty/windows/conpty.rs b/alacritty_terminal/src/tty/windows/conpty.rs
index e856a1b1..3f6349de 100644
--- a/alacritty_terminal/src/tty/windows/conpty.rs
+++ b/alacritty_terminal/src/tty/windows/conpty.rs
@@ -3,17 +3,17 @@ use std::os::windows::io::IntoRawHandle;
use std::{mem, ptr};
use mio_anonymous_pipes::{EventedAnonRead, EventedAnonWrite};
-use winapi::shared::basetsd::{PSIZE_T, SIZE_T};
-use winapi::shared::minwindef::BYTE;
-use winapi::shared::ntdef::LPWSTR;
-use winapi::shared::winerror::S_OK;
-use winapi::um::consoleapi::{ClosePseudoConsole, CreatePseudoConsole, ResizePseudoConsole};
-use winapi::um::processthreadsapi::{
+
+use windows_sys::core::PWSTR;
+use windows_sys::Win32::Foundation::{HANDLE, S_OK};
+use windows_sys::Win32::System::Console::{
+ ClosePseudoConsole, CreatePseudoConsole, ResizePseudoConsole, COORD, HPCON,
+};
+use windows_sys::Win32::System::Threading::{
CreateProcessW, InitializeProcThreadAttributeList, UpdateProcThreadAttribute,
- PROCESS_INFORMATION, STARTUPINFOW,
+ EXTENDED_STARTUPINFO_PRESENT, PROCESS_INFORMATION, PROC_THREAD_ATTRIBUTE_PSEUDOCONSOLE,
+ STARTF_USESTDHANDLES, STARTUPINFOEXW, STARTUPINFOW,
};
-use winapi::um::winbase::{EXTENDED_STARTUPINFO_PRESENT, STARTF_USESTDHANDLES, STARTUPINFOEXW};
-use winapi::um::wincontypes::{COORD, HPCON};
use crate::config::PtyConfig;
use crate::event::{OnResize, WindowSize};
@@ -39,7 +39,7 @@ impl Drop for Conpty {
unsafe impl Send for Conpty {}
pub fn new(config: &PtyConfig, window_size: WindowSize) -> Option<Pty> {
- let mut pty_handle = 0 as HPCON;
+ let mut pty_handle: HPCON = 0;
// Passing 0 as the size parameter allows the "system default" buffer
// size to be used. There may be small performance and memory advantages
@@ -52,10 +52,10 @@ pub fn new(config: &PtyConfig, window_size: WindowSize) -> Option<Pty> {
let result = unsafe {
CreatePseudoConsole(
window_size.into(),
- conin_pty_handle.into_raw_handle(),
- conout_pty_handle.into_raw_handle(),
+ conin_pty_handle.into_raw_handle() as HANDLE,
+ conout_pty_handle.into_raw_handle() as HANDLE,
0,
- &mut pty_handle as *mut HPCON,
+ &mut pty_handle as *mut _,
)
};
@@ -65,11 +65,11 @@ pub fn new(config: &PtyConfig, window_size: WindowSize) -> Option<Pty> {
// Prepare child process startup info.
- let mut size: SIZE_T = 0;
+ let mut size: usize = 0;
- let mut startup_info_ex: STARTUPINFOEXW = Default::default();
+ let mut startup_info_ex: STARTUPINFOEXW = unsafe { mem::zeroed() };
- startup_info_ex.StartupInfo.lpTitle = std::ptr::null_mut() as LPWSTR;
+ startup_info_ex.StartupInfo.lpTitle = std::ptr::null_mut() as PWSTR;
startup_info_ex.StartupInfo.cb = mem::size_of::<STARTUPINFOEXW>() as u32;
@@ -80,7 +80,7 @@ pub fn new(config: &PtyConfig, window_size: WindowSize) -> Option<Pty> {
// Create the appropriately sized thread attribute list.
unsafe {
let failure =
- InitializeProcThreadAttributeList(ptr::null_mut(), 1, 0, &mut size as PSIZE_T) > 0;
+ InitializeProcThreadAttributeList(ptr::null_mut(), 1, 0, &mut size as *mut usize) > 0;
// This call was expected to return false.
if failure {
@@ -88,7 +88,7 @@ pub fn new(config: &PtyConfig, window_size: WindowSize) -> Option<Pty> {
}
}
- let mut attr_list: Box<[BYTE]> = vec![0; size].into_boxed_slice();
+ let mut attr_list: Box<[u8]> = vec![0; size].into_boxed_slice();
// Set startup info's attribute list & initialize it
//
@@ -106,7 +106,7 @@ pub fn new(config: &PtyConfig, window_size: WindowSize) -> Option<Pty> {
startup_info_ex.lpAttributeList,
1,
0,
- &mut size as PSIZE_T,
+ &mut size as *mut usize,
) > 0;
if !success {
@@ -119,8 +119,8 @@ pub fn new(config: &PtyConfig, window_size: WindowSize) -> Option<Pty> {
success = UpdateProcThreadAttribute(
startup_info_ex.lpAttributeList,
0,
- 22 | 0x0002_0000, // PROC_THREAD_ATTRIBUTE_PSEUDOCONSOLE.
- pty_handle,
+ PROC_THREAD_ATTRIBUTE_PSEUDOCONSOLE as usize,
+ pty_handle as *mut std::ffi::c_void,
mem::size_of::<HPCON>(),
ptr::null_mut(),
ptr::null_mut(),
@@ -134,11 +134,11 @@ pub fn new(config: &PtyConfig, window_size: WindowSize) -> Option<Pty> {
let cmdline = win32_string(&cmdline(config));
let cwd = config.working_directory.as_ref().map(win32_string);
- let mut proc_info: PROCESS_INFORMATION = Default::default();
+ let mut proc_info: PROCESS_INFORMATION = unsafe { mem::zeroed() };
unsafe {
success = CreateProcessW(
ptr::null(),
- cmdline.as_ptr() as LPWSTR,
+ cmdline.as_ptr() as PWSTR,
ptr::null_mut(),
ptr::null_mut(),
false as i32,
@@ -158,7 +158,7 @@ pub fn new(config: &PtyConfig, window_size: WindowSize) -> Option<Pty> {
let conout = EventedAnonRead::new(conout);
let child_watcher = ChildExitWatcher::new(proc_info.hProcess).unwrap();
- let conpty = Conpty { handle: pty_handle };
+ let conpty = Conpty { handle: pty_handle as HPCON };
Some(Pty::new(conpty, conout, conin, child_watcher))
}
diff --git a/alacritty_terminal/src/tty/windows/mod.rs b/alacritty_terminal/src/tty/windows/mod.rs
index aa21ce14..57925f4c 100644
--- a/alacritty_terminal/src/tty/windows/mod.rs
+++ b/alacritty_terminal/src/tty/windows/mod.rs
@@ -27,7 +27,7 @@ pub struct Pty {
child_watcher: ChildExitWatcher,
}
-pub fn new(config: &PtyConfig, window_size: WindowSize, _window_id: Option<usize>) -> Result<Pty> {
+pub fn new(config: &PtyConfig, window_size: WindowSize, _window_id: u64) -> Result<Pty> {
conpty::new(config, window_size)
.ok_or_else(|| Error::new(ErrorKind::Other, "failed to spawn conpty"))
}
diff --git a/extra/alacritty-msg.man b/extra/alacritty-msg.man
index ed600d40..96c3ee6b 100644
--- a/extra/alacritty-msg.man
+++ b/extra/alacritty-msg.man
@@ -1,4 +1,4 @@
-.TH ALACRITTY-MSG "1" "October 2021" "alacritty 0.11.0-dev" "User Commands"
+.TH ALACRITTY-MSG "1" "October 2021" "alacritty 0.12.0-dev" "User Commands"
.SH NAME
alacritty-msg \- Send messages to Alacritty
.SH "SYNOPSIS"
@@ -10,20 +10,43 @@ making it possible to control Alacritty without directly accessing it.
\fB\-s\fR, \fB\-\-socket\fR <socket>
Path for IPC socket creation
.SH "MESSAGES"
+.TP
\fBcreate-window\fR
Create a new window in the same Alacritty process
.TP
.SH "\tOPTIONS"
.RS 12
+.TP
\fB\-\-hold\fR
Remain open after child process exits
-
+.TP
\fB\-\-working\-directory\fR <working\-directory>
Start the shell in the specified working directory
-
+.TP
\fB\-e\fR, \fB\-\-command\fR <command>...
Command and args to execute (must be last argument)
.RE
+.TP
+\fBconfig\fR
+Update the Alacritty configuration
+.TP
+.SH "\tARGS"
+.RS 12
+.TP
+\fB<CONFIG_OPTIONS>...\fR
+Configuration file options [example: cursor.style=Beam]
+.RE
+.TP
+.SH "\tOPTIONS"
+.RS 12
+.TP
+\fB\-w\fR, \fB\-\-window\-id\fR <WINDOW_ID>
+Window ID for the new config.
+
+Use `-1` to apply this change to all windows.
+
+[default: \fB$ALACRITTY_WINDOW_ID\fR]
+.RE
.SH "SEE ALSO"
See the alacritty github repository at https://github.com/alacritty/alacritty for the full documentation.
.SH "BUGS"
diff --git a/extra/alacritty.man b/extra/alacritty.man
index eec20d60..09503a93 100644
--- a/extra/alacritty.man
+++ b/extra/alacritty.man
@@ -1,4 +1,4 @@
-.TH ALACRITTY "1" "August 2018" "alacritty 0.11.0-dev" "User Commands"
+.TH ALACRITTY "1" "August 2018" "alacritty 0.12.0-dev" "User Commands"
.SH NAME
Alacritty \- A fast, cross-platform, OpenGL terminal emulator
.SH "SYNOPSIS"
@@ -32,10 +32,12 @@ Increases the level of verbosity (the max level is \fB\-vvv\fR)
Prints version information
.SH "OPTIONS"
.TP
-\fB\-\-class\fR <instance> | <instance>,<general>
+\fB\-\-class\fR <general> | <general>,<instance>
Defines the window class hint on Linux [default: Alacritty,Alacritty]
-On Wayland the instance class sets the `app_id`, while the general class is ignored.
+When only the general class is passed, instance will be set to the same value.
+
+On Wayland the general class sets the `app_id`, while the instance class is ignored.
.TP
\fB\-e\fR, \fB\-\-command\fR <command>...
Command and args to execute (must be last argument)
diff --git a/extra/alacritty.yml b/extra/alacritty.yml
new file mode 120000
index 00000000..2db9ba40
--- /dev/null
+++ b/extra/alacritty.yml
@@ -0,0 +1 @@
+../alacritty.yml \ No newline at end of file
diff --git a/extra/completions/_alacritty b/extra/completions/_alacritty
index 50a5c00d..6b80a797 100644
--- a/extra/completions/_alacritty
+++ b/extra/completions/_alacritty
@@ -73,6 +73,17 @@ _arguments "${_arguments_options[@]}" \
'--help[Print help information]' \
&& ret=0
;;
+(config)
+_arguments "${_arguments_options[@]}" \
+'-w+[Window ID for the new config]:WINDOW_ID: ' \
+'--window-id=[Window ID for the new config]:WINDOW_ID: ' \
+'()-r[Clear all runtime configuration changes]' \
+'()--reset[Clear all runtime configuration changes]' \
+'-h[Print help information]' \
+'--help[Print help information]' \
+'*::options -- Configuration file options \[example\: cursor.style=Beam\]:' \
+&& ret=0
+;;
(help)
_arguments "${_arguments_options[@]}" \
'*::subcommand -- The subcommand whose help message to display:' \
@@ -100,6 +111,11 @@ _alacritty_commands() {
)
_describe -t commands 'alacritty commands' commands "$@"
}
+(( $+functions[_alacritty__msg__config_commands] )) ||
+_alacritty__msg__config_commands() {
+ local commands; commands=()
+ _describe -t commands 'alacritty msg config commands' commands "$@"
+}
(( $+functions[_alacritty__msg__create-window_commands] )) ||
_alacritty__msg__create-window_commands() {
local commands; commands=()
@@ -119,6 +135,7 @@ _alacritty__msg__help_commands() {
_alacritty__msg_commands() {
local commands; commands=(
'create-window:Create a new window in the same Alacritty process' \
+'config:Update the Alacritty configuration' \
'help:Print this message or the help of the given subcommand(s)' \
)
_describe -t commands 'alacritty msg commands' commands "$@"
diff --git a/extra/completions/alacritty.bash b/extra/completions/alacritty.bash
index 428e9583..5cca6466 100644
--- a/extra/completions/alacritty.bash
+++ b/extra/completions/alacritty.bash
@@ -12,6 +12,9 @@ _alacritty() {
"$1")
cmd="alacritty"
;;
+ config)
+ cmd+="__config"
+ ;;
create-window)
cmd+="__create__window"
;;
@@ -100,7 +103,7 @@ _alacritty() {
return 0
;;
alacritty__msg)
- opts="-s -h --socket --help create-window help"
+ opts="-s -h --socket --help create-window config help"
if [[ ${cur} == -* || ${COMP_CWORD} -eq 2 ]] ; then
COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") )
return 0
@@ -121,6 +124,28 @@ _alacritty() {
COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") )
return 0
;;
+ alacritty__msg__config)
+ opts="-w -r -h --window-id --reset --help <CONFIG_OPTIONS>..."
+ if [[ ${cur} == -* || ${COMP_CWORD} -eq 3 ]] ; then
+ COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") )
+ return 0
+ fi
+ case "${prev}" in
+ --window-id)
+ COMPREPLY=($(compgen -f "${cur}"))
+ return 0
+ ;;
+ -w)
+ COMPREPLY=($(compgen -f "${cur}"))
+ return 0
+ ;;
+ *)
+ COMPREPLY=()
+ ;;
+ esac
+ COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") )
+ return 0
+ ;;
alacritty__msg__create__window)
opts="-e -t -h --working-directory --hold --command --title --class --help"
if [[ ${cur} == -* || ${COMP_CWORD} -eq 3 ]] ; then
diff --git a/extra/completions/alacritty.fish b/extra/completions/alacritty.fish
index 69b3d777..fdc24ab2 100644
--- a/extra/completions/alacritty.fish
+++ b/extra/completions/alacritty.fish
@@ -15,13 +15,17 @@ complete -c alacritty -n "__fish_use_subcommand" -s v -d 'Increases the level of
complete -c alacritty -n "__fish_use_subcommand" -l hold -d 'Remain open after child process exit'
complete -c alacritty -n "__fish_use_subcommand" -f -a "msg" -d 'Send a message to the Alacritty socket'
complete -c alacritty -n "__fish_use_subcommand" -f -a "help" -d 'Print this message or the help of the given subcommand(s)'
-complete -c alacritty -n "__fish_seen_subcommand_from msg; and not __fish_seen_subcommand_from create-window; and not __fish_seen_subcommand_from help" -s s -l socket -d 'IPC socket connection path override' -r -F
-complete -c alacritty -n "__fish_seen_subcommand_from msg; and not __fish_seen_subcommand_from create-window; and not __fish_seen_subcommand_from help" -s h -l help -d 'Print help information'
-complete -c alacritty -n "__fish_seen_subcommand_from msg; and not __fish_seen_subcommand_from create-window; and not __fish_seen_subcommand_from help" -f -a "create-window" -d 'Create a new window in the same Alacritty process'
-complete -c alacritty -n "__fish_seen_subcommand_from msg; and not __fish_seen_subcommand_from create-window; and not __fish_seen_subcommand_from help" -f -a "help" -d 'Print this message or the help of the given subcommand(s)'
+complete -c alacritty -n "__fish_seen_subcommand_from msg; and not __fish_seen_subcommand_from create-window; and not __fish_seen_subcommand_from config; and not __fish_seen_subcommand_from help" -s s -l socket -d 'IPC socket connection path override' -r -F
+complete -c alacritty -n "__fish_seen_subcommand_from msg; and not __fish_seen_subcommand_from create-window; and not __fish_seen_subcommand_from config; and not __fish_seen_subcommand_from help" -s h -l help -d 'Print help information'
+complete -c alacritty -n "__fish_seen_subcommand_from msg; and not __fish_seen_subcommand_from create-window; and not __fish_seen_subcommand_from config; and not __fish_seen_subcommand_from help" -f -a "create-window" -d 'Create a new window in the same Alacritty process'
+complete -c alacritty -n "__fish_seen_subcommand_from msg; and not __fish_seen_subcommand_from create-window; and not __fish_seen_subcommand_from config; and not __fish_seen_subcommand_from help" -f -a "config" -d 'Update the Alacritty configuration'
+complete -c alacritty -n "__fish_seen_subcommand_from msg; and not __fish_seen_subcommand_from create-window; and not __fish_seen_subcommand_from config; and not __fish_seen_subcommand_from help" -f -a "help" -d 'Print this message or the help of the given subcommand(s)'
complete -c alacritty -n "__fish_seen_subcommand_from msg; and __fish_seen_subcommand_from create-window" -l working-directory -d 'Start the shell in the specified working directory' -r -F
complete -c alacritty -n "__fish_seen_subcommand_from msg; and __fish_seen_subcommand_from create-window" -s e -l command -d 'Command and args to execute (must be last argument)' -r
complete -c alacritty -n "__fish_seen_subcommand_from msg; and __fish_seen_subcommand_from create-window" -s t -l title -d 'Defines the window title [default: Alacritty]' -r
complete -c alacritty -n "__fish_seen_subcommand_from msg; and __fish_seen_subcommand_from create-window" -l class -d 'Defines window class/app_id on X11/Wayland [default: Alacritty]' -r
complete -c alacritty -n "__fish_seen_subcommand_from msg; and __fish_seen_subcommand_from create-window" -l hold -d 'Remain open after child process exit'
complete -c alacritty -n "__fish_seen_subcommand_from msg; and __fish_seen_subcommand_from create-window" -s h -l help -d 'Print help information'
+complete -c alacritty -n "__fish_seen_subcommand_from msg; and __fish_seen_subcommand_from config" -s w -l window-id -d 'Window ID for the new config' -r
+complete -c alacritty -n "__fish_seen_subcommand_from msg; and __fish_seen_subcommand_from config" -s r -l reset -d 'Clear all runtime configuration changes'
+complete -c alacritty -n "__fish_seen_subcommand_from msg; and __fish_seen_subcommand_from config" -s h -l help -d 'Print help information'
diff --git a/extra/osx/Alacritty.app/Contents/Info.plist b/extra/osx/Alacritty.app/Contents/Info.plist
index 593b9c6b..a3ccf2b7 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.11.0-dev</string>
+ <string>0.12.0-dev</string>
<key>CFBundleSupportedPlatforms</key>
<array>
<string>MacOSX</string>
diff --git a/extra/windows b/extra/windows
deleted file mode 120000
index 1c83ac5e..00000000
--- a/extra/windows
+++ /dev/null
@@ -1 +0,0 @@
-../alacritty/windows \ No newline at end of file