diff options
| author | Ayose <ayosec@gmail.com> | 2024-05-15 00:00:00 +0000 |
|---|---|---|
| committer | Ayose <ayosec@gmail.com> | 2024-05-15 00:00:00 +0000 |
| commit | 484e357eec38ae9a19aa1c859acb1f598185657e (patch) | |
| tree | 34c58ba0251db2d1ec39e7258b13502613236c41 | |
| parent | ff0f64fe699d69c7683d8e77bd5459709c49419f (diff) | |
| parent | 3a7f21b00c50748016bc4aa2916b13b5a2e27b76 (diff) | |
| download | r-alacritty-484e357eec38ae9a19aa1c859acb1f598185657e.tar.gz r-alacritty-484e357eec38ae9a19aa1c859acb1f598185657e.tar.bz2 r-alacritty-484e357eec38ae9a19aa1c859acb1f598185657e.zip | |
Merge remote-tracking branch 'vendor/master' into graphics
34 files changed, 1213 insertions, 883 deletions
diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 17b2d1af..3918a540 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -48,10 +48,10 @@ jobs: ./.github/workflows/upload_asset.sh \ ./Alacritty-${GITHUB_REF##*/}-portable.exe $GITHUB_TOKEN - name: Install WiX - run: dotnet tool install --global wix --version 4.0.1 - - name: Crate msi installer + run: dotnet tool install --global wix --version 4.0.5 + - name: Create msi installer run: | - wix extension add WixToolset.UI.wixext WixToolset.Util.wixext + wix extension add WixToolset.UI.wixext/4.0.5 WixToolset.Util.wixext/4.0.5 wix build -arch "x64" -ext WixToolset.UI.wixext -ext WixToolset.Util.wixext \ -out "./Alacritty-${GITHUB_REF##*/}-installer.msi" "alacritty/windows/wix/alacritty.wxs" - name: Upload msi installer diff --git a/CHANGELOG.md b/CHANGELOG.md index f5361861..5ae7ffb8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,11 +5,24 @@ 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/). +Notable changes to the `alacritty_terminal` crate are documented in its +[CHANGELOG](./alacritty_terminal/CHANGELOG.md). + ## 0.14.0-dev -### Packaging +### Changed + +- Pressing `Alt` with unicode input will now add `ESC` like for ASCII input +- Decorations use opaque style and system window background on macOS + +### Fixed + +- Crash when trying to create a new tab without decorations enabled +- New window being treated as focused when it's not on Wayland +- IME preview blending into text below it +- Dynamic title disabled for new windows when initial one has title as CLI option -- Minimum Rust version has been bumped to 1.72.0 +## 0.13.2 ### Added @@ -30,6 +43,8 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). - Mouse cursor not changing on Wayland when cursor theme uses legacy cursor icon names - Config keys are available under proper names - Build failure when compiling with x11 feature on NetBSD +- Hint `Select` action selecting the entire line for URL escapes +- Kitty encoding used for regular keys when they don't carry text ### Changed diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index b07c02ef..fe7b2a71 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -91,10 +91,11 @@ If any change has been made to the `config.rs` file, it should also be documente Changes compared to the latest Alacritty release which have a direct effect on the user (opposed to things like code refactorings or documentation/tests) additionally need to be documented in the -`CHANGELOG.md`. The existing entries should be used as a style guideline. The change log should be -used to document changes from a user-perspective, instead of explaining the technical background -(like commit messages). More information about Alacritty's change log format can be found -[here](https://keepachangelog.com). +`CHANGELOG.md`. When a notable change is made to `alacritty_terminal`, it should be documented in +`alacritty_terminal/CHANGELOG.md` as well. The existing entries should be used as a style guideline. +The change log should be used to document changes from a user-perspective, instead of explaining the +technical background (like commit messages) More information about Alacritty's change log format can +be found [here](https://keepachangelog.com). ### Style @@ -10,9 +10,9 @@ checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" [[package]] name = "ahash" -version = "0.8.8" +version = "0.8.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "42cd52102d3df161c77a887b608d7a4897d7cc112886a9537b738a887a03aaff" +checksum = "e89da841a80418a9b391ebaea17f5c112ffaaa96f621d2c285b5174da76b9011" dependencies = [ "cfg-if", "getrandom", @@ -38,7 +38,7 @@ dependencies = [ "alacritty_config", "alacritty_config_derive", "alacritty_terminal", - "bitflags 2.4.1", + "bitflags 2.4.2", "clap", "clap_complete", "cocoa", @@ -63,7 +63,7 @@ dependencies = [ "smallvec", "toml", "unicode-width", - "windows-sys 0.48.0", + "windows-sys 0.52.0", "winit", "xdg", ] @@ -93,10 +93,10 @@ dependencies = [ [[package]] name = "alacritty_terminal" -version = "0.22.1-dev" +version = "0.24.1-dev" dependencies = [ "base64", - "bitflags 2.4.1", + "bitflags 2.4.2", "home", "libc", "log", @@ -112,17 +112,17 @@ dependencies = [ "smallvec", "unicode-width", "vte", - "windows-sys 0.48.0", + "windows-sys 0.52.0", ] [[package]] name = "android-activity" -version = "0.5.1" +version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "39b801912a977c3fd52d80511fe1c0c8480c6f957f21ae2ce1b92ffe970cf4b9" +checksum = "ef6978589202a00cd7e118380c448a08b6ed394c3a8df3a430d0898e3a42d046" dependencies = [ "android-properties", - "bitflags 2.4.1", + "bitflags 2.4.2", "cc", "cesu8", "jni", @@ -144,9 +144,9 @@ checksum = "fc7eb209b1518d6bb87b283c20095f5228ecda460da70b44f0802523dea6da04" [[package]] name = "anstream" -version = "0.6.5" +version = "0.6.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d664a92ecae85fd0a7392615844904654d1d5f5514837f471ddef4a057aba1b6" +checksum = "d96bd03f33fe50a863e394ee9718a706f988b9079b20c3784fb726e7678b62fb" dependencies = [ "anstyle", "anstyle-parse", @@ -158,9 +158,9 @@ dependencies = [ [[package]] name = "anstyle" -version = "1.0.4" +version = "1.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7079075b41f533b8c61d2a4d073c4676e1f8b249ff94a393b0595db304e0dd87" +checksum = "8901269c6307e8d93993578286ac0edf7f195079ffff5ebdeea6a59ffb7e36bc" [[package]] name = "anstyle-parse" @@ -222,9 +222,9 @@ checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" [[package]] name = "base64" -version = "0.21.5" +version = "0.22.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "35636a1494ede3b646cc98f74f8e62c773a38a659ebc777a2cf26b9b74171df9" +checksum = "9475866fec1451be56a3c2400fd081ff546538961565ccb5b7142cbd22bc7a51" [[package]] name = "bitflags" @@ -234,9 +234,9 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" [[package]] name = "bitflags" -version = "2.4.1" +version = "2.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "327762f6e5a765692301e5bb513e0d9fef63be86bbc14528052b1cd3e6f03e07" +checksum = "ed570934406eb16438a4e976b1b4500774099c13b8cb96eec99f620f05090ddf" dependencies = [ "serde", ] @@ -249,9 +249,9 @@ checksum = "0d8c1fef690941d3e7788d328517591fecc684c084084702d6ff1641e993699a" [[package]] name = "block-sys" -version = "0.2.0" +version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2dd7cf50912cddc06dc5ea7c08c5e81c1b2c842a70d19def1848d54c586fed92" +checksum = "ae85a0696e7ea3b835a453750bf002770776609115e6d25c6d2ff28a8200f7e7" dependencies = [ "objc-sys", ] @@ -263,20 +263,29 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "15b55663a85f33501257357e6421bb33e769d5c9ffb5ba0921c975a123e35e68" dependencies = [ "block-sys", - "objc2", + "objc2 0.4.1", +] + +[[package]] +name = "block2" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "43ff7d91d3c1d568065b06c899777d1e48dcf76103a672a0adbc238a7f247f1e" +dependencies = [ + "objc2 0.5.1", ] [[package]] name = "bumpalo" -version = "3.14.0" +version = "3.15.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f30e7476521f6f8af1a1c4c0b8cc94f0bee37d91763d0ca2665f299b6cd8aec" +checksum = "7ff69b9dd49fd426c69a0db9fc04dd934cdb6645ff000864d98f7e2af8830eaa" [[package]] name = "bytemuck" -version = "1.14.0" +version = "1.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "374d28ec25809ee0e23827c2ab573d729e293f281dfe393500e7ad618baa61c6" +checksum = "5d6d68c57235a3a081186990eca2867354726650f42f7516ca50c28d6281fd15" [[package]] name = "bytes" @@ -286,11 +295,11 @@ checksum = "a2bd12c1caf447e69cd4528f47f94d203fd2582878ecb9e9465484c4148a8223" [[package]] name = "calloop" -version = "0.12.3" +version = "0.12.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7b50b5a44d59a98c55a9eeb518f39bf7499ba19fd98ee7d22618687f3f10adbf" +checksum = "fba7adb4dd5aa98e5553510223000e7148f621165ec5f9acd7113f6ca4995298" dependencies = [ - "bitflags 2.4.1", + "bitflags 2.4.2", "log", "polling", "rustix", @@ -312,9 +321,9 @@ dependencies = [ [[package]] name = "cc" -version = "1.0.83" +version = "1.0.90" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1174fb0b6ec23863f8b971027804a42614e347eafb0a95bf0b12cdae21fc4d0" +checksum = "8cd6604a82acf3039f1144f54b8eb34e91ffba622051189e71b781822d5ee1f5" dependencies = [ "jobserver", "libc", @@ -339,6 +348,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fd16c4719339c4530435d38e511904438d07cce7950afa3718a84ac36c10e89e" [[package]] +name = "cfg_aliases" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77e53693616d3075149f4ead59bdeecd204ac6b8192d8969757601b74bddf00f" + +[[package]] name = "cgl" version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -407,15 +422,6 @@ dependencies = [ ] [[package]] -name = "cmake" -version = "0.1.50" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a31c789563b815f77f4250caee12365734369f942439b7defd71e18a48197130" -dependencies = [ - "cc", -] - -[[package]] name = "cocoa" version = "0.25.0" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -538,37 +544,33 @@ dependencies = [ [[package]] name = "crc32fast" -version = "1.3.2" +version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b540bd8bc810d3885c6ea91e2018302f68baba2129ab3e88f32389ee9370880d" +checksum = "b3855a8a784b474f333699ef2bbca9db2c4a1f6d9088a90a2d25b1eb53111eaa" dependencies = [ "cfg-if", ] [[package]] name = "crossbeam-channel" -version = "0.5.10" +version = "0.5.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "82a9b73a36529d9c47029b9fb3a6f0ea3cc916a261195352ba19e770fc1748b2" +checksum = "ab3db02a9c5b5121e1e42fbdb1aeb65f5e02624cc58c43f2884c6ccac0b82f95" dependencies = [ - "cfg-if", "crossbeam-utils", ] [[package]] name = "crossbeam-utils" -version = "0.8.18" +version = "0.8.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c3a430a770ebd84726f584a90ee7f020d28db52c6d02138900f22341f866d39c" -dependencies = [ - "cfg-if", -] +checksum = "248e3bacc7dc6baa3b21e405ee045c3047101a49145e7e9eca583ab4c2ca5345" [[package]] name = "crossfont" -version = "0.7.0" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e89c65306ecd118368d875f48d69394b5c3ff6bb7c57ae6deb638782735a093c" +checksum = "c44e28d120f3c9254800ea53349b09cbb45ac1f15f09215011a16241ae0289bc" dependencies = [ "cocoa", "core-foundation", @@ -583,8 +585,18 @@ dependencies = [ "objc", "once_cell", "pkg-config", - "servo-fontconfig", "winapi", + "yeslogic-fontconfig-sys", +] + +[[package]] +name = "cstr" +version = "0.2.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "68523903c8ae5aacfa32a0d9ae60cadeb764e1da14ee0d26b1f3089f13a54636" +dependencies = [ + "proc-macro2", + "quote", ] [[package]] @@ -639,6 +651,15 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9ea835d29036a4087793836fa931b08837ad5e957da9e23886b29586fb9b6650" [[package]] +name = "dpi" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f25c0e292a7ca6d6498557ff1df68f32c99850012b6ea401cf8daf771f22ff53" +dependencies = [ + "serde", +] + +[[package]] name = "dwrote" version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -654,11 +675,12 @@ dependencies = [ [[package]] name = "embed-resource" -version = "2.4.0" +version = "2.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f54cc3e827ee1c3812239a9a41dede7b4d7d5d5464faa32d71bd7cba28ce2cb2" +checksum = "c6985554d0688b687c5cb73898a34fbe3ad6c24c58c238a4d91d5e840670ee9d" dependencies = [ "cc", + "memchr", "rustc_version", "toml", "vswhom", @@ -682,16 +704,6 @@ dependencies = [ ] [[package]] -name = "expat-sys" -version = "2.1.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "658f19728920138342f68408b7cf7644d90d4784353d8ebc32e7e8663dbe45fa" -dependencies = [ - "cmake", - "pkg-config", -] - -[[package]] name = "fastrand" version = "2.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -699,9 +711,9 @@ checksum = "25cbce373ec4653f1a01a31e8a5e5ec0c622dc27ff9c4e6606eefef5cbbed4a5" [[package]] name = "fdeflate" -version = "0.3.3" +version = "0.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "209098dd6dfc4445aa6111f0e98653ac323eaa4dfd212c9ca3931bf9955c31bd" +checksum = "4f9bfee30e4dedf0ab8b422f03af778d9612b63f502710fc500a334ebe2de645" dependencies = [ "simd-adler32", ] @@ -757,22 +769,22 @@ checksum = "aa9a19cbb55df58761df49b23516a86d432839add4af60fc256da840f66ed35b" [[package]] name = "freetype-rs" -version = "0.26.0" +version = "0.36.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74eadec9d0a5c28c54bb9882e54787275152a4e36ce206b45d7451384e5bf5fb" +checksum = "5442dee36ca09604133580dc0553780e867936bb3cbef3275859e889026d2b17" dependencies = [ - "bitflags 1.3.2", + "bitflags 2.4.2", "freetype-sys", "libc", ] [[package]] name = "freetype-sys" -version = "0.13.1" +version = "0.20.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a37d4011c0cc628dfa766fcc195454f4b068d7afdc2adfd28861191d866e731a" +checksum = "0e7edc5b9669349acfda99533e9e0bcf26a51862ab43b08ee7745c55d28eb134" dependencies = [ - "cmake", + "cc", "libc", "pkg-config", ] @@ -804,9 +816,9 @@ dependencies = [ [[package]] name = "getrandom" -version = "0.2.11" +version = "0.2.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fe9006bed769170c11f845cf00c7c1e9092aeb3f268e007c3e760ac68008070f" +checksum = "190092ea657667030ac6a35e305e62fc4dd69fd98ac98631e5d3a2b1575a12b5" dependencies = [ "cfg-if", "libc", @@ -826,12 +838,12 @@ dependencies = [ [[package]] name = "glutin" -version = "0.31.2" +version = "0.31.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "005459a22af86adc706522d78d360101118e2638ec21df3852fcc626e0dbb212" +checksum = "18fcd4ae4e86d991ad1300b8f57166e5be0c95ef1f63f3f5b827f8a164548746" dependencies = [ - "bitflags 2.4.1", - "cfg_aliases", + "bitflags 2.4.2", + "cfg_aliases 0.1.1", "cgl", "core-foundation", "dispatch", @@ -840,7 +852,7 @@ dependencies = [ "glutin_wgl_sys", "icrate", "libloading", - "objc2", + "objc2 0.4.1", "once_cell", "raw-window-handle", "wayland-sys", @@ -904,16 +916,16 @@ version = "0.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "99d3aaff8a54577104bafdf686ff18565c3b6903ca5782a2026ef06e2c7aa319" dependencies = [ - "block2", + "block2 0.3.0", "dispatch", - "objc2", + "objc2 0.4.1", ] [[package]] name = "indexmap" -version = "2.1.0" +version = "2.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d530e1a18b1cb4c484e6e34556a0d948706958449fca0cab753d649f2bce3d1f" +checksum = "7b0b929d511467233429c45a44ac1dcaa21ba0f5ba11e4879e6ed28ddb4f9df4" dependencies = [ "equivalent", "hashbrown", @@ -969,18 +981,18 @@ checksum = "8eaf4bc02d17cbdd7ff4c7438cafcdf7fb9a4613313ad11b4f8fefe7d3fa0130" [[package]] name = "jobserver" -version = "0.1.27" +version = "0.1.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8c37f63953c4c63420ed5fd3d6d398c719489b9f872b9fa683262f8edd363c7d" +checksum = "ab46a6e9526ddef3ae7f787c06f0f2600639ba80ea3eade3d8e670a2230f51d6" dependencies = [ "libc", ] [[package]] name = "js-sys" -version = "0.3.66" +version = "0.3.69" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cee9c64da59eae3b50095c18d3e74f8b73c0b86d2792824ff01bbce68ba229ca" +checksum = "29c15563dc2726973df627357ce0c9ddddbea194836909d655df6a75d2cf296d" dependencies = [ "wasm-bindgen", ] @@ -1031,12 +1043,12 @@ checksum = "9c198f91728a82281a64e1f4f9eeb25d82cb32a5de251c6bd1b5154d63a8e7bd" [[package]] name = "libloading" -version = "0.8.1" +version = "0.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c571b676ddfc9a8c12f1f3d3085a7b163966a8fd8098a90640953ce5f6170161" +checksum = "0c2a198fb6b0eada2a8df47933734e6d35d350665a33a3593d7164fa52c75c19" dependencies = [ "cfg-if", - "windows-sys 0.48.0", + "windows-targets 0.48.5", ] [[package]] @@ -1045,7 +1057,7 @@ version = "0.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "85c833ca1e66078851dba29046874e38f08b2c883700aa29a03ddd3b23814ee8" dependencies = [ - "bitflags 2.4.1", + "bitflags 2.4.2", "libc", "redox_syscall 0.4.1", ] @@ -1056,16 +1068,16 @@ version = "0.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3af92c55d7d839293953fcd0fda5ecfe93297cfde6ffbdec13b41d99c0ba6607" dependencies = [ - "bitflags 2.4.1", + "bitflags 2.4.2", "libc", "redox_syscall 0.4.1", ] [[package]] name = "linux-raw-sys" -version = "0.4.12" +version = "0.4.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c4cd1a83af159aa67994778be9070f0ae1bd732942279cabb14f86f986a21456" +checksum = "01cda141df6706de531b6c46c3a33ecca755538219bd484262fa09410c13539c" [[package]] name = "lock_api" @@ -1079,9 +1091,9 @@ dependencies = [ [[package]] name = "log" -version = "0.4.20" +version = "0.4.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b5e6163cb8c49088c2c36f57875e58ccd8c87c7427f7fbd50ea6710b2f3f2e8f" +checksum = "90ed8c1e510134f979dbc4f070f87d4313098b704861a105fe34231c70a3901c" dependencies = [ "serde", ] @@ -1097,15 +1109,15 @@ dependencies = [ [[package]] name = "memchr" -version = "2.6.4" +version = "2.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f665ee40bc4a3c5590afb1e9677db74a508659dfd71e126420da8274909a0167" +checksum = "523dc4f511e55ab87b694dc30d0f820d60906ef06413f93d4d7a1385599cc149" [[package]] name = "memmap2" -version = "0.9.3" +version = "0.9.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "45fd3a57831bf88bc63f8cebc0cf956116276e97fef3966103e96416209f7c92" +checksum = "fe751422e4a8caa417e13c3ea66452215d7d63e19e604f4980461212f3ae1322" dependencies = [ "libc", ] @@ -1121,9 +1133,9 @@ dependencies = [ [[package]] name = "miniz_oxide" -version = "0.7.1" +version = "0.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e7810e0be55b428ada41041c41f32c9f1a42817901b4ccf45fa3d4b6561e74c7" +checksum = "9d811f3e15f28568be3407c8e7fdb6514c1cda3cb30683f15b6a1a1dc4ea14a7" dependencies = [ "adler", "simd-adler32", @@ -1152,11 +1164,11 @@ dependencies = [ [[package]] name = "ndk" -version = "0.8.0" +version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2076a31b7010b17a38c01907c45b945e8f11495ee4dd588309718901b1f7a5b7" +checksum = "c3f42e7bbe13d351b6bead8286a43aac9534b82bd3cc43e47037f012ebfd62d4" dependencies = [ - "bitflags 2.4.1", + "bitflags 2.4.2", "jni-sys", "log", "ndk-sys", @@ -1173,9 +1185,9 @@ checksum = "27b02d87554356db9e9a873add8782d4ea6e3e58ea071a9adb9a2e8ddb884a8b" [[package]] name = "ndk-sys" -version = "0.5.0+25.2.9519653" +version = "0.6.0+11769913" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8c196769dd60fd4f363e11d948139556a344e79d451aeb2fa2fd040738ef7691" +checksum = "ee6cda3051665f1fb8d9e08fc35c96d5a244fb1be711a03b71118828afc9a873" dependencies = [ "jni-sys", ] @@ -1186,7 +1198,7 @@ version = "6.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6205bd8bb1e454ad2e27422015fb5e4f2bcc7e08fa8f27058670d208324a4d2d" dependencies = [ - "bitflags 2.4.1", + "bitflags 2.4.2", "crossbeam-channel", "filetime", "fsevent-sys", @@ -1201,18 +1213,18 @@ dependencies = [ [[package]] name = "num_enum" -version = "0.7.1" +version = "0.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "683751d591e6d81200c39fb0d1032608b77724f34114db54f571ff1317b337c0" +checksum = "02339744ee7253741199f897151b38e72257d13802d4ee837285cc2990a90845" dependencies = [ "num_enum_derive", ] [[package]] name = "num_enum_derive" -version = "0.7.1" +version = "0.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6c11e44798ad209ccdd91fc192f0526a369a01234f7373e1b141c96d7cee4f0e" +checksum = "681030a937600a36906c185595136d26abfebb4aa9c65701cefcaf8578bb982b" dependencies = [ "proc-macro-crate", "proc-macro2", @@ -1242,9 +1254,9 @@ dependencies = [ [[package]] name = "objc-sys" -version = "0.3.2" +version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c7c71324e4180d0899963fc83d9d241ac39e699609fc1025a850aadac8257459" +checksum = "da284c198fb9b7b0603f8635185e85fbd5b64ee154b1ed406d489077de2d6d60" [[package]] name = "objc2" @@ -1253,7 +1265,40 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "559c5a40fdd30eb5e344fbceacf7595a81e242529fb4e21cf5f43fb4f11ff98d" dependencies = [ "objc-sys", - "objc2-encode", + "objc2-encode 3.0.0", +] + +[[package]] +name = "objc2" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b4b25e1034d0e636cd84707ccdaa9f81243d399196b8a773946dcffec0401659" +dependencies = [ + "objc-sys", + "objc2-encode 4.0.1", +] + +[[package]] +name = "objc2-app-kit" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fb79768a710a9a1798848179edb186d1af7e8a8679f369e4b8d201dd2a034047" +dependencies = [ + "block2 0.5.0", + "objc2 0.5.1", + "objc2-core-data", + "objc2-foundation", +] + +[[package]] +name = "objc2-core-data" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6e092bc42eaf30a08844e6a076938c60751225ec81431ab89f5d1ccd9f958d6c" +dependencies = [ + "block2 0.5.0", + "objc2 0.5.1", + "objc2-foundation", ] [[package]] @@ -1263,6 +1308,23 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d079845b37af429bfe5dfa76e6d087d788031045b25cfc6fd898486fd9847666" [[package]] +name = "objc2-encode" +version = "4.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "88658da63e4cc2c8adb1262902cd6af51094df0488b760d6fd27194269c0950a" + +[[package]] +name = "objc2-foundation" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cfaefe14254871ea16c7d88968c0ff14ba554712a20d76421eec52f0a7fb8904" +dependencies = [ + "block2 0.5.0", + "dispatch", + "objc2 0.5.1", +] + +[[package]] name = "objc_id" version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -1322,6 +1384,26 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" [[package]] +name = "pin-project" +version = "1.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6bf43b791c5b9e34c3d182969b4abb522f9343702850a2e57f460d00d09b4b3" +dependencies = [ + "pin-project-internal", +] + +[[package]] +name = "pin-project-internal" +version = "1.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2f38a4412a78282e09a2cf38d195ea5420d15ba0602cb375210efbc877243965" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] name = "pin-project-lite" version = "0.2.13" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -1340,15 +1422,15 @@ dependencies = [ [[package]] name = "pkg-config" -version = "0.3.28" +version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "69d3587f8a9e599cc7ec2c00e331f71c4e69a5f9a4b8a6efd5b07466b9736f9a" +checksum = "d231b230927b5e4ad203db57bbcbee2802f6bce620b1e4a9024a07d94e2907ec" [[package]] name = "png" -version = "0.17.10" +version = "0.17.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd75bf2d8dd3702b9707cdbc56a5b9ef42cec752eb8b3bafc01234558442aa64" +checksum = "06e4b0d3d1312775e782c86c91a111aa1f910cbb65e1337f9975b5f9a554b5e1" dependencies = [ "bitflags 1.3.2", "crc32fast", @@ -1373,18 +1455,18 @@ dependencies = [ [[package]] name = "proc-macro-crate" -version = "2.0.0" +version = "3.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7e8366a6159044a37876a2b9817124296703c586a5c92e2c53751fa06d8d43e8" +checksum = "6d37c51ca738a55da99dc0c4a34860fd675453b8b36209178c2249bb13651284" dependencies = [ - "toml_edit 0.20.7", + "toml_edit 0.21.1", ] [[package]] name = "proc-macro2" -version = "1.0.71" +version = "1.0.79" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "75cb1540fadbd5b8fbccc4dddad2734eba435053f725621c070711a14bb5f4b8" +checksum = "e835ff2298f5721608eb1a980ecaee1aef2c132bf95ecc026a11b7bf3c01c02e" dependencies = [ "unicode-ident", ] @@ -1400,9 +1482,9 @@ dependencies = [ [[package]] name = "quote" -version = "1.0.33" +version = "1.0.35" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5267fca4496028628a95160fc423a33e8b2e6af8a5302579e322e4b520293cae" +checksum = "291ec9ab5efd934aaf503a6466c5d5251535d108ee747472c3977cc5acc868ef" dependencies = [ "proc-macro2", ] @@ -1444,9 +1526,9 @@ dependencies = [ [[package]] name = "regex-automata" -version = "0.4.3" +version = "0.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f804c7828047e88b2d32e2d7fe5a105da8ee3264f01902f796c8e067dc2483f" +checksum = "86b83b8b9847f9bf95ef68afb0b8e6cdb80f498442f5179a29fad448fcc1eaea" dependencies = [ "aho-corasick", "memchr", @@ -1474,7 +1556,7 @@ version = "0.38.25" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dc99bc2d4f1fed22595588a013687477aedf3cdcfb26558c559edb67b4d9b22e" dependencies = [ - "bitflags 2.4.1", + "bitflags 2.4.2", "errno", "itoa", "libc", @@ -1495,9 +1577,9 @@ dependencies = [ [[package]] name = "ryu" -version = "1.0.16" +version = "1.0.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f98d2aa92eebf49b69786be48e4477826b256916e84a57ff2a4f21923b48eb4c" +checksum = "e86697c916019a8588c99b5fac3cead74ec0b4b819707a682fd4d23fa0ce1ba1" [[package]] name = "same-file" @@ -1522,9 +1604,9 @@ checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" [[package]] name = "sctk-adwaita" -version = "0.8.1" +version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "82b2eaf3a5b264a521b988b2e73042e742df700c4f962cde845d1541adb46550" +checksum = "7de61fa7334ee8ee1f5c3c58dcc414fb9361e7e8f5bff9d45f4d69eeb89a7169" dependencies = [ "crossfont", "log", @@ -1534,24 +1616,24 @@ dependencies = [ [[package]] name = "semver" -version = "1.0.20" +version = "1.0.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "836fa6a3e1e547f9a2c4040802ec865b5d85f4014efe00555d7090a3dcaa1090" +checksum = "92d43fe69e652f3df9bdc2b85b2854a0825b86e4fb76bc44d945137d053639ca" [[package]] name = "serde" -version = "1.0.193" +version = "1.0.197" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "25dd9975e68d0cb5aa1120c288333fc98731bd1dd12f561e468ea4728c042b89" +checksum = "3fb1c873e1b9b056a4dc4c0c198b24c3ffa059243875552b2bd0933b1aee4ce2" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.193" +version = "1.0.197" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "43576ca501357b9b071ac53cdc7da8ef0cbd9493d8df094cd821777ea6e894d3" +checksum = "7eb0b34b42edc17f6b7cac84a52a1c5f0e1bb2227e997ca9011ea3dd34e8610b" dependencies = [ "proc-macro2", "quote", @@ -1560,9 +1642,9 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.108" +version = "1.0.114" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d1c7e3eac408d115102c4c24ad393e0821bb3a5df4d506a80f85f7a742a526b" +checksum = "c5f09b1bd632ef549eaa9f60a1f8de742bdbc698e6cee2095fc84dde5f549ae0" dependencies = [ "itoa", "ryu", @@ -1580,9 +1662,9 @@ dependencies = [ [[package]] name = "serde_yaml" -version = "0.9.29" +version = "0.9.33" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a15e0ef66bf939a7c890a0bf6d5a733c70202225f9888a89ed5c62298b019129" +checksum = "a0623d197252096520c6f2a5e1171ee436e5af99a5d7caa2891e55e61950e6d9" dependencies = [ "indexmap", "itoa", @@ -1592,27 +1674,6 @@ dependencies = [ ] [[package]] -name = "servo-fontconfig" -version = "0.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c7e3e22fe5fd73d04ebf0daa049d3efe3eae55369ce38ab16d07ddd9ac5c217c" -dependencies = [ - "libc", - "servo-fontconfig-sys", -] - -[[package]] -name = "servo-fontconfig-sys" -version = "5.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e36b879db9892dfa40f95da1c38a835d41634b825fbd8c4c418093d53c24b388" -dependencies = [ - "expat-sys", - "freetype-sys", - "pkg-config", -] - -[[package]] name = "signal-hook" version = "0.3.17" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -1661,7 +1722,7 @@ version = "0.18.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "922fd3eeab3bd820d76537ce8f582b1cf951eceb5475c28500c7457d9d17f53a" dependencies = [ - "bitflags 2.4.1", + "bitflags 2.4.2", "calloop", "calloop-wayland-source", "cursor-icon", @@ -1693,9 +1754,9 @@ dependencies = [ [[package]] name = "smol_str" -version = "0.2.0" +version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74212e6bbe9a4352329b2f68ba3130c15a3f26fe88ff22dbdc6cdd58fa85e99c" +checksum = "e6845563ada680337a52d43bb0b29f396f2d911616f6573012645b9e3d048a49" dependencies = [ "serde", ] @@ -1714,9 +1775,9 @@ checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" [[package]] name = "syn" -version = "2.0.43" +version = "2.0.53" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ee659fb5f3d355364e1f3e5bc10fb82068efbf824a1e9d1c9504244a6469ad53" +checksum = "7383cd0e49fff4b6b90ca5670bfd3e9d6a733b3f90c686605aa7eec8c4996032" dependencies = [ "proc-macro2", "quote", @@ -1725,18 +1786,18 @@ dependencies = [ [[package]] name = "thiserror" -version = "1.0.52" +version = "1.0.58" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "83a48fd946b02c0a526b2e9481c8e2a17755e47039164a86c4070446e3a4614d" +checksum = "03468839009160513471e86a034bb2c5c0e4baae3b43f79ffc55c4a5427b3297" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.52" +version = "1.0.58" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e7fbe9b594d6568a6a1443250a7e67d80b74e1e96f6d1715e1e21cc1888291d3" +checksum = "c61f3ba182994efc43764a46c018c347bc492c79f024e705f46567b418f6d4f7" dependencies = [ "proc-macro2", "quote", @@ -1745,9 +1806,9 @@ dependencies = [ [[package]] name = "tiny-skia" -version = "0.11.3" +version = "0.11.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6a067b809476893fce6a254cf285850ff69c847e6cfbade6a20b655b6c7e80d" +checksum = "83d13394d44dae3207b52a326c0c85a8bf87f1541f23b0d143811088497b09ab" dependencies = [ "arrayref", "arrayvec", @@ -1759,9 +1820,9 @@ dependencies = [ [[package]] name = "tiny-skia-path" -version = "0.11.3" +version = "0.11.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5de35e8a90052baaaf61f171680ac2f8e925a1e43ea9d2e3a00514772250e541" +checksum = "9c9e7fc0c2e86a30b117d0462aa261b72b7a99b7ebd7deb3a14ceda95c5bdc93" dependencies = [ "arrayref", "bytemuck", @@ -1770,14 +1831,14 @@ dependencies = [ [[package]] name = "toml" -version = "0.8.8" +version = "0.8.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a1a195ec8c9da26928f773888e0742ca3ca1040c6cd859c919c9f59c1954ab35" +checksum = "af06656561d28735e9c1cd63dfd57132c8155426aa6af24f36a00a351f88c48e" dependencies = [ "serde", "serde_spanned", "toml_datetime", - "toml_edit 0.21.0", + "toml_edit 0.22.7", ] [[package]] @@ -1791,26 +1852,26 @@ dependencies = [ [[package]] name = "toml_edit" -version = "0.20.7" +version = "0.21.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "70f427fce4d84c72b5b732388bf4a9f4531b53f74e2887e3ecb2481f68f66d81" +checksum = "6a8534fd7f78b5405e860340ad6575217ce99f38d4d5c8f2442cb5ecb50090e1" dependencies = [ "indexmap", "toml_datetime", - "winnow", + "winnow 0.5.40", ] [[package]] name = "toml_edit" -version = "0.21.0" +version = "0.22.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d34d383cd00a163b4a5b85053df514d45bc330f6de7737edfe0a93311d1eaa03" +checksum = "18769cd1cec395d70860ceb4d932812a0b4d06b1a4bb336745a4d21b9496e992" dependencies = [ "indexmap", "serde", "serde_spanned", "toml_datetime", - "winnow", + "winnow 0.6.5", ] [[package]] @@ -1837,9 +1898,9 @@ checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" [[package]] name = "unicode-segmentation" -version = "1.10.1" +version = "1.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1dd624098567895118886609431a7c3b8f516e41d30e0643f03d94592a147e36" +checksum = "d4c87d22b6e3f4a18d4d40ef354e97c90fcb14dd91d7dc0aa9d8a1172ebf7202" [[package]] name = "unicode-width" @@ -1849,9 +1910,9 @@ checksum = "e51733f11c9c4f72aa0c160008246859e340b00807569a0da0e7a1079b27ba85" [[package]] name = "unsafe-libyaml" -version = "0.2.10" +version = "0.2.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ab4c90930b95a82d00dc9e9ac071b4991924390d46cbd0dfe566148667605e4b" +checksum = "673aac59facbab8a9007c7f6108d11f63b603f7cabff99fabf650fea5c32b861" [[package]] name = "utf8parse" @@ -1895,7 +1956,7 @@ name = "vte" version = "0.13.0" source = "git+https://github.com/ayosec/vte-graphics.git?branch=graphics#e876405dadee1c1104761eee89e31b9f34de8941" dependencies = [ - "bitflags 2.4.1", + "bitflags 2.4.2", "cursor-icon", "log", "serde", @@ -1914,9 +1975,9 @@ dependencies = [ [[package]] name = "walkdir" -version = "2.4.0" +version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d71d857dc86794ca4c280d616f7da00d2dbfd8cd788846559a6813e6aa4b54ee" +checksum = "29790946404f91d9c5d06f9874efddea1dc06c5efe94541a7d6863108e3a5e4b" dependencies = [ "same-file", "winapi-util", @@ -1930,9 +1991,9 @@ checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" [[package]] name = "wasm-bindgen" -version = "0.2.89" +version = "0.2.92" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ed0d4f68a3015cc185aff4db9506a015f4b96f95303897bfa23f846db54064e" +checksum = "4be2531df63900aeb2bca0daaaddec08491ee64ceecbee5076636a3b026795a8" dependencies = [ "cfg-if", "wasm-bindgen-macro", @@ -1940,9 +2001,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-backend" -version = "0.2.89" +version = "0.2.92" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b56f625e64f3a1084ded111c4d5f477df9f8c92df113852fa5a374dbda78826" +checksum = "614d787b966d3989fa7bb98a654e369c762374fd3213d212cfc0251257e747da" dependencies = [ "bumpalo", "log", @@ -1955,9 +2016,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-futures" -version = "0.4.39" +version = "0.4.42" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac36a15a220124ac510204aec1c3e5db8a22ab06fd6706d881dc6149f8ed9a12" +checksum = "76bc14366121efc8dbb487ab05bcc9d346b3b5ec0eaa76e46594cabbe51762c0" dependencies = [ "cfg-if", "js-sys", @@ -1967,9 +2028,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro" -version = "0.2.89" +version = "0.2.92" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0162dbf37223cd2afce98f3d0785506dcb8d266223983e4b5b525859e6e182b2" +checksum = "a1f8823de937b71b9460c0c34e25f3da88250760bec0ebac694b49997550d726" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -1977,9 +2038,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.89" +version = "0.2.92" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f0eb82fcb7930ae6219a7ecfd55b217f5f0893484b7a13022ebb2b2bf20b5283" +checksum = "e94f17b526d0a461a191c78ea52bbce64071ed5c04c9ffe424dcb38f74171bb7" dependencies = [ "proc-macro2", "quote", @@ -1990,9 +2051,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-shared" -version = "0.2.89" +version = "0.2.92" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ab9b36309365056cd639da3134bf87fa8f3d86008abf99e612384a6eecd459f" +checksum = "af190c94f2773fdb3729c55b007a722abb5384da03bc0986df4c289bf5567e96" [[package]] name = "wayland-backend" @@ -2014,7 +2075,7 @@ version = "0.31.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "82fb96ee935c2cea6668ccb470fb7771f6215d1691746c2d896b447a00ad3f1f" dependencies = [ - "bitflags 2.4.1", + "bitflags 2.4.2", "rustix", "wayland-backend", "wayland-scanner", @@ -2026,7 +2087,7 @@ version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "625c5029dbd43d25e6aa9615e88b829a5cad13b2819c4ae129fdbb7c31ab4c7e" dependencies = [ - "bitflags 2.4.1", + "bitflags 2.4.2", "cursor-icon", "wayland-backend", ] @@ -2048,7 +2109,7 @@ version = "0.31.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8f81f365b8b4a97f422ac0e8737c438024b5951734506b0e1d775c73030561f4" dependencies = [ - "bitflags 2.4.1", + "bitflags 2.4.2", "wayland-backend", "wayland-client", "wayland-scanner", @@ -2060,7 +2121,7 @@ version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "23803551115ff9ea9bce586860c5c5a971e360825a0309264102a9495a5ff479" dependencies = [ - "bitflags 2.4.1", + "bitflags 2.4.2", "wayland-backend", "wayland-client", "wayland-protocols", @@ -2073,7 +2134,7 @@ version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ad1f61b76b6c2d8742e10f9ba5c3737f6530b4c243132c2a2ccc8aa96fe25cd6" dependencies = [ - "bitflags 2.4.1", + "bitflags 2.4.2", "wayland-backend", "wayland-client", "wayland-protocols", @@ -2105,9 +2166,9 @@ dependencies = [ [[package]] name = "web-sys" -version = "0.3.66" +version = "0.3.69" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "50c24a44ec86bb68fbecd1b3efed7e85ea5621b39b35ef2766b66cd984f8010f" +checksum = "77afa9a11836342370f4817622a2f0f418b134426d91a82dfb48f532d2ec13ef" dependencies = [ "js-sys", "wasm-bindgen", @@ -2115,9 +2176,9 @@ dependencies = [ [[package]] name = "web-time" -version = "0.2.4" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aa30049b1c872b72c89866d458eae9f20380ab280ffd1b1e18df2d3e2d98cfe0" +checksum = "5a6580f308b1fad9207618087a65c04e7a10bc77e02c8e84e9b00dd4b12fa0bb" dependencies = [ "js-sys", "wasm-bindgen", @@ -2173,6 +2234,15 @@ dependencies = [ ] [[package]] +name = "windows-sys" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" +dependencies = [ + "windows-targets 0.52.5", +] + +[[package]] name = "windows-targets" version = "0.42.2" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -2203,6 +2273,22 @@ dependencies = [ ] [[package]] +name = "windows-targets" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6f0713a46559409d202e70e28227288446bf7841d3211583a4b53e3f6d96e7eb" +dependencies = [ + "windows_aarch64_gnullvm 0.52.5", + "windows_aarch64_msvc 0.52.5", + "windows_i686_gnu 0.52.5", + "windows_i686_gnullvm", + "windows_i686_msvc 0.52.5", + "windows_x86_64_gnu 0.52.5", + "windows_x86_64_gnullvm 0.52.5", + "windows_x86_64_msvc 0.52.5", +] + +[[package]] name = "windows_aarch64_gnullvm" version = "0.42.2" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -2215,6 +2301,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" [[package]] +name = "windows_aarch64_gnullvm" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7088eed71e8b8dda258ecc8bac5fb1153c5cffaf2578fc8ff5d61e23578d3263" + +[[package]] name = "windows_aarch64_msvc" version = "0.42.2" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -2227,6 +2319,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" [[package]] +name = "windows_aarch64_msvc" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9985fd1504e250c615ca5f281c3f7a6da76213ebd5ccc9561496568a2752afb6" + +[[package]] name = "windows_i686_gnu" version = "0.42.2" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -2239,6 +2337,18 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" [[package]] +name = "windows_i686_gnu" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "88ba073cf16d5372720ec942a8ccbf61626074c6d4dd2e745299726ce8b89670" + +[[package]] +name = "windows_i686_gnullvm" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "87f4261229030a858f36b459e748ae97545d6f1ec60e5e0d6a3d32e0dc232ee9" + +[[package]] name = "windows_i686_msvc" version = "0.42.2" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -2251,6 +2361,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" [[package]] +name = "windows_i686_msvc" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "db3c2bf3d13d5b658be73463284eaf12830ac9a26a90c717b7f771dfe97487bf" + +[[package]] name = "windows_x86_64_gnu" version = "0.42.2" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -2263,6 +2379,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" [[package]] +name = "windows_x86_64_gnu" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4e4246f76bdeff09eb48875a0fd3e2af6aada79d409d33011886d3e1581517d9" + +[[package]] name = "windows_x86_64_gnullvm" version = "0.42.2" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -2275,6 +2397,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" [[package]] +name = "windows_x86_64_gnullvm" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "852298e482cd67c356ddd9570386e2862b5673c85bd5f88df9ab6802b334c596" + +[[package]] name = "windows_x86_64_msvc" version = "0.42.2" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -2287,39 +2415,47 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" [[package]] +name = "windows_x86_64_msvc" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bec47e5bfd1bff0eeaf6d8b485cc1074891a197ab4225d504cb7a1ab88b02bf0" + +[[package]] name = "winit" -version = "0.29.14" +version = "0.30.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a7a3db69ffbe53a9babec7804da7a90f21020fcce1f2f5e5291e2311245b993d" +checksum = "ea9e6d5d66cbf702e0dd820302144f51b69a95acdc495dd98ca280ff206562b1" dependencies = [ "ahash", "android-activity", "atomic-waker", - "bitflags 2.4.1", + "bitflags 2.4.2", "bytemuck", "calloop", - "cfg_aliases", + "cfg_aliases 0.2.0", + "concurrent-queue", "core-foundation", "core-graphics", "cursor-icon", - "icrate", + "dpi", "js-sys", "libc", - "log", "memmap2", "ndk", - "ndk-sys", - "objc2", - "once_cell", + "objc2 0.5.1", + "objc2-app-kit", + "objc2-foundation", "orbclient", "percent-encoding", + "pin-project", "raw-window-handle", - "redox_syscall 0.3.5", + "redox_syscall 0.4.1", "rustix", "sctk-adwaita", "serde", "smithay-client-toolkit", "smol_str", + "tracing", "unicode-segmentation", "wasm-bindgen", "wasm-bindgen-futures", @@ -2329,7 +2465,7 @@ dependencies = [ "wayland-protocols-plasma", "web-sys", "web-time", - "windows-sys 0.48.0", + "windows-sys 0.52.0", "x11-dl", "x11rb", "xkbcommon-dl", @@ -2337,18 +2473,27 @@ dependencies = [ [[package]] name = "winnow" -version = "0.5.30" +version = "0.5.40" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f593a95398737aeed53e489c785df13f3618e41dbcd6718c6addbf1395aa6876" +dependencies = [ + "memchr", +] + +[[package]] +name = "winnow" +version = "0.6.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9b5c3db89721d50d0e2a673f5043fc4722f76dcc352d7b1ab8b8288bed4ed2c5" +checksum = "dffa400e67ed5a4dd237983829e66475f0a4a26938c4b04c21baede6262215b8" dependencies = [ "memchr", ] [[package]] name = "winreg" -version = "0.51.0" +version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "937f3df7948156640f46aacef17a70db0de5917bda9c92b0f751f3a955b588fc" +checksum = "a277a57398d4bfa075df44f501a17cfdf8542d224f0d36095a2adc7aee4ef0a5" dependencies = [ "cfg-if", "windows-sys 0.48.0", @@ -2423,7 +2568,7 @@ version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d039de8032a9a8856a6be89cea3e5d12fdd82306ab7c94d74e6deab2460651c5" dependencies = [ - "bitflags 2.4.1", + "bitflags 2.4.2", "dlib", "log", "once_cell", @@ -2443,6 +2588,18 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0fcb9cbac069e033553e8bb871be2fbdffcab578eb25bd0f7c508cedc6dcd75a" [[package]] +name = "yeslogic-fontconfig-sys" +version = "5.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ffb6b23999a8b1a997bf47c7bb4d19ad4029c3327bb3386ebe0a5ff584b33c7a" +dependencies = [ + "cstr", + "dlib", + "once_cell", + "pkg-config", +] + +[[package]] name = "zerocopy" version = "0.7.32" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -69,11 +69,9 @@ following locations: 3. `$HOME/.config/alacritty/alacritty.toml` 4. `$HOME/.alacritty.toml` -### Windows +On Windows, the config file will be looked for in: -On Windows, the config file should be located at: - -`%APPDATA%\alacritty\alacritty.toml` +* `%APPDATA%\alacritty\alacritty.toml` ## Contributing diff --git a/alacritty/Cargo.toml b/alacritty/Cargo.toml index d9013484..8d46c29c 100644 --- a/alacritty/Cargo.toml +++ b/alacritty/Cargo.toml @@ -5,13 +5,14 @@ authors = ["Christian Duerr <contact@christianduerr.com>", "Joe Wilm <joe@jwilm. license = "Apache-2.0" description = "A fast, cross-platform, OpenGL terminal emulator" readme = "README.md" -homepage = "https://github.com/alacritty/alacritty" +homepage = "https://alacritty.org" +repository = "https://github.com/alacritty/alacritty" edition = "2021" -rust-version = "1.72.0" +rust-version = "1.70.0" [dependencies.alacritty_terminal] path = "../alacritty_terminal" -version = "0.22.1-dev" +version = "0.24.1-dev" [dependencies.alacritty_config_derive] path = "../alacritty_config_derive" @@ -26,7 +27,7 @@ ahash = { version = "0.8.6", features = ["no-rng"] } bitflags = "2.2.1" clap = { version = "4.2.7", features = ["derive", "env"] } copypasta = { version = "0.10.1", default-features = false } -crossfont = { version = "0.7.0", features = ["force_system_fontconfig"] } +crossfont = "0.8.0" glutin = { version = "0.31.1", default-features = false, features = ["egl", "wgl"] } home = "0.5.5" libc = "0.2" @@ -41,7 +42,7 @@ serde_yaml = "0.9.25" smallvec = { version = "1.13.1", features = ["serde"] } toml = "0.8.2" unicode-width = "0.1" -winit = { version = "0.29.14", default-features = false, features = ["rwh_05", "serde"] } +winit = { version = "0.30.0", default-features = false, features = ["rwh_05", "serde"] } [build-dependencies] gl_generator = "0.14.0" @@ -61,7 +62,7 @@ objc = "0.2.2" [target.'cfg(windows)'.dependencies] dirs = "5.0.1" -windows-sys = { version = "0.48", features = [ +windows-sys = { version = "0.52", features = [ "Win32_UI_WindowsAndMessaging", "Win32_System_Threading", "Win32_System_Console", diff --git a/alacritty/src/cli.rs b/alacritty/src/cli.rs index fee2680f..e7f2d3ef 100644 --- a/alacritty/src/cli.rs +++ b/alacritty/src/cli.rs @@ -1,11 +1,12 @@ use std::cmp::max; +use std::collections::HashMap; use std::ops::{Deref, DerefMut}; use std::path::PathBuf; use std::rc::Rc; use alacritty_config::SerdeReplace; use clap::{ArgAction, Args, Parser, Subcommand, ValueHint}; -use log::{self, error, LevelFilter}; +use log::{error, LevelFilter}; use serde::{Deserialize, Serialize}; use toml::Value; @@ -91,7 +92,6 @@ impl Options { config.ipc_socket |= self.socket.is_some(); } - config.window.dynamic_title &= self.window_options.window_identity.title.is_none(); config.window.embed = self.embed.as_ref().and_then(|embed| parse_hex_or_decimal(embed)); config.debug.print_events |= self.print_events; config.debug.log_level = max(config.debug.log_level, self.log_level()); @@ -195,6 +195,7 @@ impl From<TerminalOptions> for PtyOptions { working_directory: options.working_directory.take(), shell: options.command().map(Into::into), hold: options.hold, + env: HashMap::new(), } } } @@ -424,19 +425,6 @@ mod tests { } #[test] - fn dynamic_title_overridden_by_options() { - let mut config = UiConfig::default(); - - let title = Some(String::from("foo")); - let window_identity = WindowIdentity { title, ..WindowIdentity::default() }; - let new_window_options = WindowOptions { window_identity, ..WindowOptions::default() }; - let mut options = Options { window_options: new_window_options, ..Options::default() }; - options.override_config(&mut config); - - assert!(!config.window.dynamic_title); - } - - #[test] fn dynamic_title_not_overridden_by_config() { let mut config = UiConfig::default(); diff --git a/alacritty/src/clipboard.rs b/alacritty/src/clipboard.rs index b3818c75..bb90a13d 100644 --- a/alacritty/src/clipboard.rs +++ b/alacritty/src/clipboard.rs @@ -3,7 +3,6 @@ use raw_window_handle::RawDisplayHandle; use alacritty_terminal::term::ClipboardType; -#[cfg(any(test, not(any(feature = "x11", target_os = "macos", windows))))] use copypasta::nop_clipboard::NopClipboardContext; #[cfg(all(feature = "wayland", not(any(target_os = "macos", windows))))] use copypasta::wayland_clipboard; @@ -31,9 +30,8 @@ impl Clipboard { } } - /// Used for tests and to handle missing clipboard provider when built without the `x11` - /// feature. - #[cfg(any(test, not(any(feature = "x11", target_os = "macos", windows))))] + /// Used for tests, to handle missing clipboard provider when built without the `x11` + /// feature, and as default clipboard value. pub fn new_nop() -> Self { Self { clipboard: Box::new(NopClipboardContext::new().unwrap()), selection: None } } diff --git a/alacritty/src/config/mod.rs b/alacritty/src/config/mod.rs index a77ed770..4ae3b67d 100644 --- a/alacritty/src/config/mod.rs +++ b/alacritty/src/config/mod.rs @@ -263,13 +263,12 @@ fn load_imports(config: &Value, config_paths: &mut Vec<PathBuf>, recursion_limit }, }; - if !path.exists() { - info!(target: LOG_TARGET_CONFIG, "Config import not found:\n {:?}", path.display()); - continue; - } - match parse_config(&path, config_paths, recursion_limit - 1) { Ok(config) => merged = serde_utils::merge(merged, config), + Err(Error::Io(io)) if io.kind() == io::ErrorKind::NotFound => { + info!(target: LOG_TARGET_CONFIG, "Config import not found:\n {:?}", path.display()); + continue; + }, Err(err) => { error!(target: LOG_TARGET_CONFIG, "Unable to import config {:?}: {}", path, err) }, diff --git a/alacritty/src/config/monitor.rs b/alacritty/src/config/monitor.rs index f4b39a22..53cff1c9 100644 --- a/alacritty/src/config/monitor.rs +++ b/alacritty/src/config/monitor.rs @@ -1,9 +1,13 @@ use std::path::PathBuf; -use std::sync::mpsc::{self, RecvTimeoutError}; +use std::sync::mpsc::{self, RecvTimeoutError, Sender}; +use std::thread::JoinHandle; use std::time::{Duration, Instant}; -use log::{debug, error}; -use notify::{Config, EventKind, RecommendedWatcher, RecursiveMode, Watcher}; +use log::{debug, error, warn}; +use notify::{ + Config, Error as NotifyError, Event as NotifyEvent, EventKind, RecommendedWatcher, + RecursiveMode, Watcher, +}; use winit::event_loop::EventLoopProxy; use alacritty_terminal::thread; @@ -15,115 +19,139 @@ const DEBOUNCE_DELAY: Duration = Duration::from_millis(10); /// The fallback for `RecommendedWatcher` polling. const FALLBACK_POLLING_TIMEOUT: Duration = Duration::from_secs(1); -pub fn watch(mut paths: Vec<PathBuf>, event_proxy: EventLoopProxy<Event>) { - // Don't monitor config if there is no path to watch. - if paths.is_empty() { - return; - } +/// Config file update monitor. +pub struct ConfigMonitor { + thread: JoinHandle<()>, + shutdown_tx: Sender<Result<NotifyEvent, NotifyError>>, +} - // Exclude char devices like `/dev/null`, sockets, and so on, by checking that file type is a - // regular file. - paths.retain(|path| { - // Call `metadata` to resolve symbolic links. - path.metadata().map_or(false, |metadata| metadata.file_type().is_file()) - }); - - // Canonicalize paths, keeping the base paths for symlinks. - for i in 0..paths.len() { - if let Ok(canonical_path) = paths[i].canonicalize() { - match paths[i].symlink_metadata() { - Ok(metadata) if metadata.file_type().is_symlink() => paths.push(canonical_path), - _ => paths[i] = canonical_path, - } +impl ConfigMonitor { + pub fn new(mut paths: Vec<PathBuf>, event_proxy: EventLoopProxy<Event>) -> Option<Self> { + // Don't monitor config if there is no path to watch. + if paths.is_empty() { + return None; } - } - // The Duration argument is a debouncing period. - let (tx, rx) = mpsc::channel(); - let mut watcher = match RecommendedWatcher::new( - tx, - Config::default().with_poll_interval(FALLBACK_POLLING_TIMEOUT), - ) { - Ok(watcher) => watcher, - Err(err) => { - error!("Unable to watch config file: {}", err); - return; - }, - }; - - thread::spawn_named("config watcher", move || { - // Get all unique parent directories. - let mut parents = paths - .iter() - .map(|path| { - let mut path = path.clone(); - path.pop(); - path - }) - .collect::<Vec<PathBuf>>(); - parents.sort_unstable(); - parents.dedup(); - - // Watch all configuration file directories. - for parent in &parents { - if let Err(err) = watcher.watch(parent, RecursiveMode::NonRecursive) { - debug!("Unable to watch config directory {:?}: {}", parent, err); + // Exclude char devices like `/dev/null`, sockets, and so on, by checking that file type is + // a regular file. + paths.retain(|path| { + // Call `metadata` to resolve symbolic links. + path.metadata().map_or(false, |metadata| metadata.file_type().is_file()) + }); + + // Canonicalize paths, keeping the base paths for symlinks. + for i in 0..paths.len() { + if let Ok(canonical_path) = paths[i].canonicalize() { + match paths[i].symlink_metadata() { + Ok(metadata) if metadata.file_type().is_symlink() => paths.push(canonical_path), + _ => paths[i] = canonical_path, + } } } - // The current debouncing time. - let mut debouncing_deadline: Option<Instant> = None; - - // The events accumulated during the debounce period. - let mut received_events = Vec::new(); - - loop { - // We use `recv_timeout` to debounce the events coming from the watcher and reduce - // the amount of config reloads. - let event = match debouncing_deadline.as_ref() { - Some(debouncing_deadline) => { - rx.recv_timeout(debouncing_deadline.saturating_duration_since(Instant::now())) - }, - None => { - let event = rx.recv().map_err(Into::into); - // Set the debouncing deadline after receiving the event. - debouncing_deadline = Some(Instant::now() + DEBOUNCE_DELAY); - event - }, - }; - - match event { - Ok(Ok(event)) => match event.kind { - EventKind::Any - | EventKind::Create(_) - | EventKind::Modify(_) - | EventKind::Other => { - received_events.push(event); + // The Duration argument is a debouncing period. + let (tx, rx) = mpsc::channel(); + let mut watcher = match RecommendedWatcher::new( + tx.clone(), + Config::default().with_poll_interval(FALLBACK_POLLING_TIMEOUT), + ) { + Ok(watcher) => watcher, + Err(err) => { + error!("Unable to watch config file: {}", err); + return None; + }, + }; + + let join_handle = thread::spawn_named("config watcher", move || { + // Get all unique parent directories. + let mut parents = paths + .iter() + .map(|path| { + let mut path = path.clone(); + path.pop(); + path + }) + .collect::<Vec<PathBuf>>(); + parents.sort_unstable(); + parents.dedup(); + + // Watch all configuration file directories. + for parent in &parents { + if let Err(err) = watcher.watch(parent, RecursiveMode::NonRecursive) { + debug!("Unable to watch config directory {:?}: {}", parent, err); + } + } + + // The current debouncing time. + let mut debouncing_deadline: Option<Instant> = None; + + // The events accumulated during the debounce period. + let mut received_events = Vec::new(); + + loop { + // We use `recv_timeout` to debounce the events coming from the watcher and reduce + // the amount of config reloads. + let event = match debouncing_deadline.as_ref() { + Some(debouncing_deadline) => rx.recv_timeout( + debouncing_deadline.saturating_duration_since(Instant::now()), + ), + None => { + let event = rx.recv().map_err(Into::into); + // Set the debouncing deadline after receiving the event. + debouncing_deadline = Some(Instant::now() + DEBOUNCE_DELAY); + event + }, + }; + + match event { + Ok(Ok(event)) => match event.kind { + EventKind::Other if event.info() == Some("shutdown") => break, + EventKind::Any + | EventKind::Create(_) + | EventKind::Modify(_) + | EventKind::Other => { + received_events.push(event); + }, + _ => (), + }, + Err(RecvTimeoutError::Timeout) => { + // Go back to polling the events. + debouncing_deadline = None; + + if received_events + .drain(..) + .flat_map(|event| event.paths.into_iter()) + .any(|path| paths.contains(&path)) + { + // Always reload the primary configuration file. + let event = Event::new(EventType::ConfigReload(paths[0].clone()), None); + let _ = event_proxy.send_event(event); + } }, - _ => (), - }, - Err(RecvTimeoutError::Timeout) => { - // Go back to polling the events. - debouncing_deadline = None; - - if received_events - .drain(..) - .flat_map(|event| event.paths.into_iter()) - .any(|path| paths.contains(&path)) - { - // Always reload the primary configuration file. - let event = Event::new(EventType::ConfigReload(paths[0].clone()), None); - let _ = event_proxy.send_event(event); - } - }, - Ok(Err(err)) => { - debug!("Config watcher errors: {:?}", err); - }, - Err(err) => { - debug!("Config watcher channel dropped unexpectedly: {}", err); - break; - }, - }; + Ok(Err(err)) => { + debug!("Config watcher errors: {:?}", err); + }, + Err(err) => { + debug!("Config watcher channel dropped unexpectedly: {}", err); + break; + }, + }; + } + }); + + Some(Self { thread: join_handle, shutdown_tx: tx }) + } + + /// Synchronously shut down the monitor. + pub fn shutdown(self) { + // Request shutdown. + let mut event = NotifyEvent::new(EventKind::Other); + event = event.set_info("shutdown"); + let _ = self.shutdown_tx.send(Ok(event)); + + // Wait for thread to terminate. + if let Err(err) = self.thread.join() { + warn!("config monitor shutdown failed: {err:?}"); } - }); + } } diff --git a/alacritty/src/config/ui_config.rs b/alacritty/src/config/ui_config.rs index 21059734..580a3dad 100644 --- a/alacritty/src/config/ui_config.rs +++ b/alacritty/src/config/ui_config.rs @@ -10,7 +10,7 @@ use alacritty_terminal::term::Config as TermConfig; use alacritty_terminal::tty::{Options as PtyOptions, Shell}; use log::{error, warn}; use serde::de::{Error as SerdeError, MapAccess, Visitor}; -use serde::{self, Deserialize, Deserializer}; +use serde::{Deserialize, Deserializer}; use unicode_width::UnicodeWidthChar; use winit::keyboard::{Key, ModifiersState}; @@ -167,7 +167,12 @@ impl UiConfig { /// Derive [`PtyOptions`] from the config. pub fn pty_config(&self) -> PtyOptions { let shell = self.shell.clone().map(Into::into); - PtyOptions { shell, working_directory: self.working_directory.clone(), hold: false } + PtyOptions { + shell, + working_directory: self.working_directory.clone(), + hold: false, + env: HashMap::new(), + } } /// Generate key bindings for all keyboard hints. diff --git a/alacritty/src/display/hint.rs b/alacritty/src/display/hint.rs index bd09a881..f118dbe0 100644 --- a/alacritty/src/display/hint.rs +++ b/alacritty/src/display/hint.rs @@ -204,7 +204,8 @@ pub struct HintMatch { impl HintMatch { #[inline] pub fn should_highlight(&self, point: Point, pointed_hyperlink: Option<&Hyperlink>) -> bool { - self.bounds.contains(&point) && self.hyperlink.as_ref() == pointed_hyperlink + self.hyperlink.as_ref() == pointed_hyperlink + && (self.hyperlink.is_some() || self.bounds.contains(&point)) } #[inline] @@ -400,49 +401,30 @@ pub fn highlighted_at<T>( } /// Retrieve the hyperlink with its range, if there is one at the specified point. +/// +/// This will only return contiguous cells, even if another hyperlink with the same ID exists. fn hyperlink_at<T>(term: &Term<T>, point: Point) -> Option<(Hyperlink, Match)> { let hyperlink = term.grid()[point].hyperlink()?; - let viewport_start = Line(-(term.grid().display_offset() as i32)); - let viewport_end = viewport_start + term.bottommost_line(); - - let mut match_start = Point::new(point.line, Column(0)); - let mut match_end = Point::new(point.line, Column(term.columns() - 1)); let grid = term.grid(); - // Find adjacent lines that have the same `hyperlink`. The end purpose to highlight hyperlinks - // that span across multiple lines or not directly attached to each other. - - // Find the closest to the viewport start adjacent line. - while match_start.line > viewport_start { - let next_line = match_start.line - 1i32; - // Iterate over all the cells in the grid's line and check if any of those cells contains - // the hyperlink we've found at original `point`. - let line_contains_hyperlink = grid[next_line] - .into_iter() - .any(|cell| cell.hyperlink().map_or(false, |h| h == hyperlink)); - - // There's no hyperlink on the next line, break. - if !line_contains_hyperlink { + let mut match_end = point; + for cell in grid.iter_from(point) { + if cell.hyperlink().map_or(false, |link| link == hyperlink) { + match_end = cell.point; + } else { break; } - - match_start.line = next_line; } - // Ditto for the end. - while match_end.line < viewport_end { - let next_line = match_end.line + 1i32; - - let line_contains_hyperlink = grid[next_line] - .into_iter() - .any(|cell| cell.hyperlink().map_or(false, |h| h == hyperlink)); - - if !line_contains_hyperlink { + let mut match_start = point; + let mut iter = grid.iter_from(point); + while let Some(cell) = iter.prev() { + if cell.hyperlink().map_or(false, |link| link == hyperlink) { + match_start = cell.point; + } else { break; } - - match_end.line = next_line; } Some((hyperlink, match_start..=match_end)) diff --git a/alacritty/src/display/mod.rs b/alacritty/src/display/mod.rs index b2ff4106..1e7534d0 100644 --- a/alacritty/src/display/mod.rs +++ b/alacritty/src/display/mod.rs @@ -20,7 +20,7 @@ use winit::dpi::PhysicalSize; use winit::keyboard::ModifiersState; use winit::window::CursorIcon; -use crossfont::{self, Rasterize, Rasterizer, Size as FontSize}; +use crossfont::{Rasterize, Rasterizer, Size as FontSize}; use unicode_width::UnicodeWidthChar; use alacritty_terminal::event::{EventListener, OnResize, WindowSize}; diff --git a/alacritty/src/display/window.rs b/alacritty/src/display/window.rs index e4bfa2cb..09793fa0 100644 --- a/alacritty/src/display/window.rs +++ b/alacritty/src/display/window.rs @@ -1,16 +1,16 @@ #[cfg(not(any(target_os = "macos", windows)))] use winit::platform::startup_notify::{ - self, EventLoopExtStartupNotify, WindowBuilderExtStartupNotify, + self, EventLoopExtStartupNotify, WindowAttributesExtStartupNotify, }; #[cfg(all(not(feature = "x11"), not(any(target_os = "macos", windows))))] -use winit::platform::wayland::WindowBuilderExtWayland; +use winit::platform::wayland::WindowAttributesExtWayland; #[rustfmt::skip] #[cfg(all(feature = "x11", not(any(target_os = "macos", windows))))] use { std::io::Cursor, - winit::platform::x11::{WindowBuilderExtX11, EventLoopWindowTargetExtX11}, + winit::platform::x11::{WindowAttributesExtX11, ActiveEventLoopExtX11}, glutin::platform::x11::X11VisualInfo, winit::window::Icon, png::Decoder, @@ -23,18 +23,18 @@ use { cocoa::appkit::NSColorSpace, cocoa::base::{id, nil, NO, YES}, objc::{msg_send, sel, sel_impl}, - winit::platform::macos::{OptionAsAlt, WindowBuilderExtMacOS, WindowExtMacOS}, + winit::platform::macos::{OptionAsAlt, WindowAttributesExtMacOS, WindowExtMacOS}, }; use raw_window_handle::{HasRawWindowHandle, RawWindowHandle}; use winit::dpi::{PhysicalPosition, PhysicalSize}; -use winit::event_loop::EventLoopWindowTarget; +use winit::event_loop::ActiveEventLoop; use winit::monitor::MonitorHandle; #[cfg(windows)] use winit::platform::windows::IconExtWindows; use winit::window::{ CursorIcon, Fullscreen, ImePurpose, Theme, UserAttentionType, Window as WinitWindow, - WindowBuilder, WindowId, + WindowAttributes, WindowId, }; use alacritty_terminal::index::Point; @@ -121,8 +121,8 @@ impl Window { /// Create a new window. /// /// This creates a window and fully initializes a window. - pub fn new<E>( - event_loop: &EventLoopWindowTarget<E>, + pub fn new( + event_loop: &ActiveEventLoop, config: &UiConfig, identity: &Identity, #[rustfmt::skip] @@ -133,7 +133,7 @@ impl Window { x11_visual: Option<X11VisualInfo>, ) -> Result<Window> { let identity = identity.clone(); - let mut window_builder = Window::get_platform_window( + let mut window_attributes = Window::get_platform_window( &identity, &config.window, #[cfg(all(feature = "x11", not(any(target_os = "macos", windows))))] @@ -143,14 +143,14 @@ impl Window { ); if let Some(position) = config.window.position { - window_builder = window_builder + window_attributes = window_attributes .with_position(PhysicalPosition::<i32>::from((position.x, position.y))); } #[cfg(not(any(target_os = "macos", windows)))] if let Some(token) = event_loop.read_token_from_env() { log::debug!("Activating window with token: {token:?}"); - window_builder = window_builder.with_activation_token(token); + window_attributes = window_attributes.with_activation_token(token); // Remove the token from the env. startup_notify::reset_activation_token_env(); @@ -160,22 +160,23 @@ impl Window { #[cfg(all(feature = "x11", not(any(target_os = "macos", windows))))] if let Some(parent_window_id) = event_loop.is_x11().then_some(config.window.embed).flatten() { - window_builder = window_builder.with_embed_parent_window(parent_window_id); + window_attributes = window_attributes.with_embed_parent_window(parent_window_id); } - let window = window_builder + window_attributes = window_attributes .with_title(&identity.title) .with_theme(config.window.theme()) .with_visible(false) .with_transparent(true) .with_blur(config.window.blur) .with_maximized(config.window.maximized()) - .with_fullscreen(config.window.fullscreen()) - .build(event_loop)?; + .with_fullscreen(config.window.fullscreen()); + + let window = event_loop.create_window(window_attributes)?; // Text cursor. let current_mouse_cursor = CursorIcon::Text; - window.set_cursor_icon(current_mouse_cursor); + window.set_cursor(current_mouse_cursor); // Enable IME. window.set_ime_allowed(true); @@ -248,7 +249,7 @@ impl Window { pub fn set_mouse_cursor(&mut self, cursor: CursorIcon) { if cursor != self.current_mouse_cursor { self.current_mouse_cursor = cursor; - self.window.set_cursor_icon(cursor); + self.window.set_cursor(cursor); } } @@ -267,7 +268,7 @@ impl Window { #[cfg(all(feature = "x11", not(any(target_os = "macos", windows))))] x11_visual: Option< X11VisualInfo, >, - ) -> WindowBuilder { + ) -> WindowAttributes { #[cfg(feature = "x11")] let icon = { let mut decoder = Decoder::new(Cursor::new(WINDOW_ICON)); @@ -279,7 +280,7 @@ impl Window { .expect("invalid embedded icon format") }; - let builder = WindowBuilder::new() + let builder = WinitWindow::default_attributes() .with_name(&identity.class.general, &identity.class.instance) .with_decorations(window_config.decorations != Decorations::None); @@ -296,10 +297,10 @@ impl Window { } #[cfg(windows)] - pub fn get_platform_window(_: &Identity, window_config: &WindowConfig) -> WindowBuilder { + pub fn get_platform_window(_: &Identity, window_config: &WindowConfig) -> WindowAttributes { let icon = winit::window::Icon::from_resource(IDI_ICON, None); - WindowBuilder::new() + WinitWindow::default_attributes() .with_decorations(window_config.decorations != Decorations::None) .with_window_icon(icon.ok()) } @@ -309,8 +310,9 @@ impl Window { _: &Identity, window_config: &WindowConfig, tabbing_id: &Option<String>, - ) -> WindowBuilder { - let mut window = WindowBuilder::new().with_option_as_alt(window_config.option_as_alt()); + ) -> WindowAttributes { + let mut window = + WinitWindow::default_attributes().with_option_as_alt(window_config.option_as_alt()); if let Some(tabbing_id) = tabbing_id { window = window.with_tabbing_identifier(tabbing_id); diff --git a/alacritty/src/event.rs b/alacritty/src/event.rs index 4fa397ad..9505e1a3 100644 --- a/alacritty/src/event.rs +++ b/alacritty/src/event.rs @@ -18,13 +18,12 @@ use crossfont::Size as FontSize; use glutin::display::{Display as GlutinDisplay, GetGlDisplay}; use log::{debug, error, info, warn}; use raw_window_handle::HasRawDisplayHandle; +use winit::application::ApplicationHandler; use winit::event::{ ElementState, Event as WinitEvent, Ime, Modifiers, MouseButton, StartCause, Touch as TouchEvent, WindowEvent, }; -use winit::event_loop::{ - ControlFlow, DeviceEvents, EventLoop, EventLoopProxy, EventLoopWindowTarget, -}; +use winit::event_loop::{ActiveEventLoop, ControlFlow, DeviceEvents, EventLoop, EventLoopProxy}; use winit::window::WindowId; use alacritty_terminal::event::{Event as TerminalEvent, EventListener, Notify}; @@ -49,7 +48,7 @@ use crate::display::hint::HintMatch; use crate::display::window::Window; use crate::display::{Display, Preedit, SizeInfo}; use crate::input::{self, ActionContext as _, FONT_SIZE_STEP}; -use crate::logging::LOG_TARGET_CONFIG; +use crate::logging::{LOG_TARGET_CONFIG, LOG_TARGET_WINIT}; use crate::message_bar::{Message, MessageBuffer}; use crate::scheduler::{Scheduler, TimerId, Topic}; use crate::window_context::WindowContext; @@ -66,6 +65,376 @@ const MAX_SEARCH_HISTORY_SIZE: usize = 255; /// Touch zoom speed. const TOUCH_ZOOM_FACTOR: f32 = 0.01; +/// The event processor. +/// +/// Stores some state from received events and dispatches actions when they are +/// triggered. +pub struct Processor { + clipboard: Clipboard, + scheduler: Scheduler, + initial_window_options: Option<WindowOptions>, + initial_window_error: Option<Box<dyn Error>>, + windows: HashMap<WindowId, WindowContext, RandomState>, + proxy: EventLoopProxy<Event>, + gl_display: Option<GlutinDisplay>, + #[cfg(unix)] + global_ipc_options: ParsedOptions, + cli_options: CliOptions, + config: Rc<UiConfig>, +} + +impl Processor { + /// Create a new event processor. + pub fn new( + config: UiConfig, + cli_options: CliOptions, + event_loop: &EventLoop<Event>, + ) -> Processor { + let proxy = event_loop.create_proxy(); + let scheduler = Scheduler::new(proxy.clone()); + let initial_window_options = Some(cli_options.window_options.clone()); + + // Disable all device events, since we don't care about them. + event_loop.listen_device_events(DeviceEvents::Never); + + // SAFETY: Since this takes a pointer to the winit event loop, it MUST be dropped first, + // which is done in `loop_exiting`. + let clipboard = unsafe { Clipboard::new(event_loop.raw_display_handle()) }; + + Processor { + initial_window_options, + initial_window_error: None, + cli_options, + proxy, + scheduler, + gl_display: None, + config: Rc::new(config), + clipboard, + windows: Default::default(), + #[cfg(unix)] + global_ipc_options: Default::default(), + } + } + + /// Create initial window and load GL platform. + /// + /// This will initialize the OpenGL Api and pick a config that + /// will be used for the rest of the windows. + pub fn create_initial_window( + &mut self, + event_loop: &ActiveEventLoop, + options: WindowOptions, + ) -> Result<(), Box<dyn Error>> { + let window_context = + WindowContext::initial(event_loop, self.proxy.clone(), self.config.clone(), options)?; + + self.gl_display = Some(window_context.display.gl_context().display()); + self.windows.insert(window_context.id(), window_context); + + Ok(()) + } + + /// Create a new terminal window. + pub fn create_window( + &mut self, + event_loop: &ActiveEventLoop, + options: WindowOptions, + ) -> Result<(), Box<dyn Error>> { + let window = self.windows.iter().next().as_ref().unwrap().1; + + // Overide config with CLI/IPC options. + let mut config_overrides = options.config_overrides(); + #[cfg(unix)] + config_overrides.extend_from_slice(&self.global_ipc_options); + let mut config = self.config.clone(); + config = config_overrides.override_config_rc(config); + + #[allow(unused_mut)] + let mut window_context = + window.additional(event_loop, self.proxy.clone(), config, options, config_overrides)?; + + self.windows.insert(window_context.id(), window_context); + Ok(()) + } + + /// Run the event loop. + /// + /// The result is exit code generate from the loop. + pub fn run(mut self, event_loop: EventLoop<Event>) -> Result<(), Box<dyn Error>> { + let result = event_loop.run_app(&mut self); + if let Some(initial_window_error) = self.initial_window_error.take() { + Err(initial_window_error) + } else { + result.map_err(Into::into) + } + } + + /// Check if an event is irrelevant and can be skipped. + fn skip_window_event(event: &WindowEvent) -> bool { + matches!( + event, + WindowEvent::KeyboardInput { is_synthetic: true, .. } + | WindowEvent::ActivationTokenDone { .. } + | WindowEvent::DoubleTapGesture { .. } + | WindowEvent::TouchpadPressure { .. } + | WindowEvent::RotationGesture { .. } + | WindowEvent::CursorEntered { .. } + | WindowEvent::PinchGesture { .. } + | WindowEvent::AxisMotion { .. } + | WindowEvent::PanGesture { .. } + | WindowEvent::HoveredFileCancelled + | WindowEvent::Destroyed + | WindowEvent::ThemeChanged(_) + | WindowEvent::HoveredFile(_) + | WindowEvent::Moved(_) + ) + } +} + +impl ApplicationHandler<Event> for Processor { + fn resumed(&mut self, _event_loop: &ActiveEventLoop) {} + + fn new_events(&mut self, event_loop: &ActiveEventLoop, cause: StartCause) { + if cause != StartCause::Init { + return; + } + + let initial_window_options = match self.initial_window_options.take() { + Some(initial_window_options) => initial_window_options, + None => return, + }; + + if let Err(err) = self.create_initial_window(event_loop, initial_window_options) { + self.initial_window_error = Some(err); + event_loop.exit(); + return; + } + + info!("Initialisation complete"); + } + + fn window_event( + &mut self, + _event_loop: &ActiveEventLoop, + window_id: WindowId, + event: WindowEvent, + ) { + if self.config.debug.print_events { + info!(target: LOG_TARGET_WINIT, "{event:?}"); + } + + // Ignore all events we do not care about. + if Self::skip_window_event(&event) { + return; + } + + let window_context = match self.windows.get_mut(&window_id) { + Some(window_context) => window_context, + None => return, + }; + + let is_redraw = matches!(event, WindowEvent::RedrawRequested); + + window_context.handle_event( + #[cfg(target_os = "macos")] + _event_loop, + &self.proxy, + &mut self.clipboard, + &mut self.scheduler, + WinitEvent::WindowEvent { window_id, event }, + ); + + if is_redraw { + window_context.draw(&mut self.scheduler); + } + } + + fn user_event(&mut self, event_loop: &ActiveEventLoop, event: Event) { + if self.config.debug.print_events { + info!(target: LOG_TARGET_WINIT, "{event:?}"); + } + + // Handle events which don't mandate the WindowId. + match (&event.payload, event.window_id.as_ref()) { + // Process IPC config update. + #[cfg(unix)] + (EventType::IpcConfig(ipc_config), window_id) => { + // Try and parse options as toml. + let mut options = ParsedOptions::from_options(&ipc_config.options); + + // Override IPC config for each window with matching ID. + for (_, window_context) in self + .windows + .iter_mut() + .filter(|(id, _)| window_id.is_none() || window_id == Some(*id)) + { + if ipc_config.reset { + window_context.reset_window_config(self.config.clone()); + } else { + window_context.add_window_config(self.config.clone(), &options); + } + } + + // Persist global options for future windows. + if window_id.is_none() { + if ipc_config.reset { + self.global_ipc_options.clear(); + } else { + self.global_ipc_options.append(&mut options); + } + } + }, + (EventType::ConfigReload(path), _) => { + // Clear config logs from message bar for all terminals. + for window_context in self.windows.values_mut() { + if !window_context.message_buffer.is_empty() { + window_context.message_buffer.remove_target(LOG_TARGET_CONFIG); + window_context.display.pending_update.dirty = true; + } + } + + // Load config and update each terminal. + if let Ok(config) = config::reload(path, &mut self.cli_options) { + self.config = Rc::new(config); + + for window_context in self.windows.values_mut() { + window_context.update_config(self.config.clone()); + } + } + }, + // Create a new terminal window. + (EventType::CreateWindow(options), _) => { + // XXX Ensure that no context is current when creating a new window, + // otherwise it may lock the backing buffer of the + // surface of current context when asking + // e.g. EGL on Wayland to create a new context. + for window_context in self.windows.values_mut() { + window_context.display.make_not_current(); + } + + if let Err(err) = self.create_window(event_loop, options.clone()) { + error!("Could not open window: {:?}", err); + } + }, + // Process events affecting all windows. + (_, None) => { + let event = WinitEvent::UserEvent(event); + for window_context in self.windows.values_mut() { + window_context.handle_event( + #[cfg(target_os = "macos")] + event_loop, + &self.proxy, + &mut self.clipboard, + &mut self.scheduler, + event.clone(), + ); + } + }, + (EventType::Terminal(TerminalEvent::Wakeup), Some(window_id)) => { + if let Some(window_context) = self.windows.get_mut(window_id) { + window_context.dirty = true; + if window_context.display.window.has_frame { + window_context.display.window.request_redraw(); + } + } + }, + (EventType::Terminal(TerminalEvent::Exit), Some(window_id)) => { + // Remove the closed terminal. + let window_context = match self.windows.remove(window_id) { + Some(window_context) => window_context, + None => return, + }; + + // Unschedule pending events. + self.scheduler.unschedule_window(window_context.id()); + + // Shutdown if no more terminals are open. + if self.windows.is_empty() { + // Write ref tests of last window to disk. + if self.config.debug.ref_test { + window_context.write_ref_test_results(); + } + + event_loop.exit(); + } + }, + // NOTE: This event bypasses batching to minimize input latency. + (EventType::Frame, Some(window_id)) => { + if let Some(window_context) = self.windows.get_mut(window_id) { + window_context.display.window.has_frame = true; + if window_context.dirty { + window_context.display.window.request_redraw(); + } + } + }, + (_, Some(window_id)) => { + if let Some(window_context) = self.windows.get_mut(window_id) { + window_context.handle_event( + #[cfg(target_os = "macos")] + event_loop, + &self.proxy, + &mut self.clipboard, + &mut self.scheduler, + WinitEvent::UserEvent(event), + ); + } + }, + }; + } + + fn about_to_wait(&mut self, event_loop: &ActiveEventLoop) { + if self.config.debug.print_events { + info!(target: LOG_TARGET_WINIT, "About to wait"); + } + + // Dispatch event to all windows. + for window_context in self.windows.values_mut() { + window_context.handle_event( + #[cfg(target_os = "macos")] + event_loop, + &self.proxy, + &mut self.clipboard, + &mut self.scheduler, + WinitEvent::AboutToWait, + ); + } + + // Update the scheduler after event processing to ensure + // the event loop deadline is as accurate as possible. + let control_flow = match self.scheduler.update() { + Some(instant) => ControlFlow::WaitUntil(instant), + None => ControlFlow::Wait, + }; + event_loop.set_control_flow(control_flow); + } + + fn exiting(&mut self, _event_loop: &ActiveEventLoop) { + if self.config.debug.print_events { + info!("Exiting the event loop"); + } + + match self.gl_display.take() { + #[cfg(not(target_os = "macos"))] + Some(glutin::display::Display::Egl(display)) => { + // Ensure that all the windows are dropped, so the destructors for + // Renderer and contexts ran. + self.windows.clear(); + + // SAFETY: the display is being destroyed after destroying all the + // windows, thus no attempt to access the EGL state will be made. + unsafe { + display.terminate(); + } + }, + _ => (), + } + + // SAFETY: The clipboard must be dropped before the event loop, so use the nop clipboard + // as a safe placeholder. + mem::swap(&mut self.clipboard, &mut Clipboard::new_nop()); + } +} + /// Alacritty events. #[derive(Debug, Clone)] pub struct Event { @@ -217,7 +586,8 @@ pub struct ActionContext<'a, N, T> { pub message_buffer: &'a mut MessageBuffer, pub config: &'a UiConfig, pub cursor_blink_timed_out: &'a mut bool, - pub event_loop: &'a EventLoopWindowTarget<Event>, + #[cfg(target_os = "macos")] + pub event_loop: &'a ActiveEventLoop, pub event_proxy: &'a EventLoopProxy<Event>, pub scheduler: &'a mut Scheduler, pub search_state: &'a mut SearchState, @@ -918,7 +1288,7 @@ impl<'a, N: Notify + 'a, T: EventListener> input::ActionContext<T> for ActionCon } #[cfg(target_os = "macos")] - fn event_loop(&self) -> &EventLoopWindowTarget<Event> { + fn event_loop(&self) -> &ActiveEventLoop { self.event_loop } @@ -1213,7 +1583,6 @@ pub struct Mouse { pub click_state: ClickState, pub accumulated_scroll: AccumulatedScroll, pub cell_side: Side, - pub lines_scrolled: f32, pub block_hint_launcher: bool, pub hint_highlight_dirty: bool, pub inside_text_area: bool, @@ -1234,7 +1603,6 @@ impl Default for Mouse { hint_highlight_dirty: Default::default(), block_hint_launcher: Default::default(), inside_text_area: Default::default(), - lines_scrolled: Default::default(), accumulated_scroll: Default::default(), x: Default::default(), y: Default::default(), @@ -1313,7 +1681,7 @@ impl input::Processor<EventProxy, ActionContext<'_, Notifier, EventProxy>> { }, TerminalEvent::ResetTitle => { let window_config = &self.ctx.config.window; - if window_config.dynamic_title { + if !self.ctx.preserve_title && window_config.dynamic_title { self.ctx.display.window.set_title(window_config.identity.title.clone()); } }, @@ -1469,12 +1837,13 @@ impl input::Processor<EventProxy, ActionContext<'_, Notifier, EventProxy>> { }, WindowEvent::KeyboardInput { is_synthetic: true, .. } | WindowEvent::ActivationTokenDone { .. } + | WindowEvent::DoubleTapGesture { .. } | WindowEvent::TouchpadPressure { .. } - | WindowEvent::TouchpadMagnify { .. } - | WindowEvent::TouchpadRotate { .. } - | WindowEvent::SmartMagnify { .. } + | WindowEvent::RotationGesture { .. } | WindowEvent::CursorEntered { .. } + | WindowEvent::PinchGesture { .. } | WindowEvent::AxisMotion { .. } + | WindowEvent::PanGesture { .. } | WindowEvent::HoveredFileCancelled | WindowEvent::Destroyed | WindowEvent::ThemeChanged(_) @@ -1494,359 +1863,6 @@ impl input::Processor<EventProxy, ActionContext<'_, Notifier, EventProxy>> { } } -/// The event processor. -/// -/// Stores some state from received events and dispatches actions when they are -/// triggered. -pub struct Processor { - windows: HashMap<WindowId, WindowContext, RandomState>, - gl_display: Option<GlutinDisplay>, - #[cfg(unix)] - global_ipc_options: ParsedOptions, - cli_options: CliOptions, - config: Rc<UiConfig>, -} - -impl Processor { - /// Create a new event processor. - /// - /// Takes a writer which is expected to be hooked up to the write end of a PTY. - pub fn new( - config: UiConfig, - cli_options: CliOptions, - _event_loop: &EventLoop<Event>, - ) -> Processor { - Processor { - cli_options, - gl_display: None, - config: Rc::new(config), - windows: Default::default(), - #[cfg(unix)] - global_ipc_options: Default::default(), - } - } - - /// Create initial window and load GL platform. - /// - /// This will initialize the OpenGL Api and pick a config that - /// will be used for the rest of the windows. - pub fn create_initial_window( - &mut self, - event_loop: &EventLoopWindowTarget<Event>, - proxy: EventLoopProxy<Event>, - options: WindowOptions, - ) -> Result<(), Box<dyn Error>> { - let window_context = - WindowContext::initial(event_loop, proxy, self.config.clone(), options)?; - - self.gl_display = Some(window_context.display.gl_context().display()); - self.windows.insert(window_context.id(), window_context); - - Ok(()) - } - - /// Create a new terminal window. - pub fn create_window( - &mut self, - event_loop: &EventLoopWindowTarget<Event>, - proxy: EventLoopProxy<Event>, - options: WindowOptions, - ) -> Result<(), Box<dyn Error>> { - let window = self.windows.iter().next().as_ref().unwrap().1; - - // Overide config with CLI/IPC options. - let mut config_overrides = options.config_overrides(); - #[cfg(unix)] - config_overrides.extend_from_slice(&self.global_ipc_options); - let mut config = self.config.clone(); - config = config_overrides.override_config_rc(config); - - #[allow(unused_mut)] - let mut window_context = - window.additional(event_loop, proxy, config, options, config_overrides)?; - - self.windows.insert(window_context.id(), window_context); - Ok(()) - } - - /// Run the event loop. - /// - /// The result is exit code generate from the loop. - pub fn run( - &mut self, - 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); - - // Disable all device events, since we don't care about them. - event_loop.listen_device_events(DeviceEvents::Never); - - let mut initial_window_error = Ok(()); - let initial_window_error_loop = &mut initial_window_error; - // SAFETY: Since this takes a pointer to the winit event loop, it MUST be dropped first, - // which is done by `move` into event loop. - let mut clipboard = unsafe { Clipboard::new(event_loop.raw_display_handle()) }; - let result = event_loop.run(move |event, event_loop| { - if self.config.debug.print_events { - info!("winit event: {:?}", event); - } - - // Ignore all events we do not care about. - if Self::skip_event(&event) { - return; - } - - match event { - // The event loop just got initialized. Create a window. - WinitEvent::Resumed => { - // Creating window inside event loop is required for platforms like macOS to - // properly initialize state, like tab management. Otherwise 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_initial_window( - event_loop, - proxy.clone(), - initial_window_options, - ) { - *initial_window_error_loop = Err(err); - event_loop.exit(); - return; - } - - info!("Initialisation complete"); - }, - WinitEvent::LoopExiting => { - match self.gl_display.take() { - #[cfg(not(target_os = "macos"))] - Some(glutin::display::Display::Egl(display)) => { - // Ensure that all the windows are dropped, so the destructors for - // Renderer and contexts ran. - self.windows.clear(); - - // SAFETY: the display is being destroyed after destroying all the - // windows, thus no attempt to access the EGL state will be made. - unsafe { - display.terminate(); - } - }, - _ => (), - } - }, - // NOTE: This event bypasses batching to minimize input latency. - WinitEvent::UserEvent(Event { - window_id: Some(window_id), - payload: EventType::Terminal(TerminalEvent::Wakeup), - }) => { - if let Some(window_context) = self.windows.get_mut(&window_id) { - window_context.dirty = true; - if window_context.display.window.has_frame { - window_context.display.window.request_redraw(); - } - } - }, - // NOTE: This event bypasses batching to minimize input latency. - WinitEvent::UserEvent(Event { - window_id: Some(window_id), - payload: EventType::Frame, - }) => { - if let Some(window_context) = self.windows.get_mut(&window_id) { - window_context.display.window.has_frame = true; - if window_context.dirty { - window_context.display.window.request_redraw(); - } - } - }, - // Check for shutdown. - WinitEvent::UserEvent(Event { - window_id: Some(window_id), - payload: EventType::Terminal(TerminalEvent::Exit), - }) => { - // Remove the closed terminal. - let window_context = match self.windows.remove(&window_id) { - Some(window_context) => window_context, - None => return, - }; - - // Unschedule pending events. - scheduler.unschedule_window(window_context.id()); - - // Shutdown if no more terminals are open. - if self.windows.is_empty() { - // Write ref tests of last window to disk. - if self.config.debug.ref_test { - window_context.write_ref_test_results(); - } - - event_loop.exit(); - } - }, - WinitEvent::WindowEvent { window_id, event: WindowEvent::RedrawRequested } => { - let window_context = match self.windows.get_mut(&window_id) { - Some(window_context) => window_context, - None => return, - }; - - window_context.handle_event( - event_loop, - &proxy, - &mut clipboard, - &mut scheduler, - event, - ); - - window_context.draw(&mut scheduler); - }, - // Process all pending events. - WinitEvent::AboutToWait => { - // Dispatch event to all windows. - for window_context in self.windows.values_mut() { - window_context.handle_event( - event_loop, - &proxy, - &mut clipboard, - &mut scheduler, - WinitEvent::AboutToWait, - ); - } - - // Update the scheduler after event processing to ensure - // the event loop deadline is as accurate as possible. - let control_flow = match scheduler.update() { - Some(instant) => ControlFlow::WaitUntil(instant), - None => ControlFlow::Wait, - }; - event_loop.set_control_flow(control_flow); - }, - // Process config update. - WinitEvent::UserEvent(Event { payload: EventType::ConfigReload(path), .. }) => { - // Clear config logs from message bar for all terminals. - for window_context in self.windows.values_mut() { - if !window_context.message_buffer.is_empty() { - window_context.message_buffer.remove_target(LOG_TARGET_CONFIG); - window_context.display.pending_update.dirty = true; - } - } - - // Load config and update each terminal. - if let Ok(config) = config::reload(&path, &mut self.cli_options) { - self.config = Rc::new(config); - - for window_context in self.windows.values_mut() { - window_context.update_config(self.config.clone()); - } - } - }, - // Process IPC config update. - #[cfg(unix)] - WinitEvent::UserEvent(Event { - payload: EventType::IpcConfig(ipc_config), - window_id, - }) => { - // Try and parse options as toml. - let mut options = ParsedOptions::from_options(&ipc_config.options); - - // Override IPC config for each window with matching ID. - for (_, window_context) in self - .windows - .iter_mut() - .filter(|(id, _)| window_id.is_none() || window_id == Some(**id)) - { - if ipc_config.reset { - window_context.reset_window_config(self.config.clone()); - } else { - window_context.add_window_config(self.config.clone(), &options); - } - } - - // Persist global options for future windows. - if window_id.is_none() { - if ipc_config.reset { - self.global_ipc_options.clear(); - } else { - self.global_ipc_options.append(&mut options); - } - } - }, - // Create a new terminal window. - WinitEvent::UserEvent(Event { - payload: EventType::CreateWindow(options), .. - }) => { - // XXX Ensure that no context is current when creating a new window, - // otherwise it may lock the backing buffer of the - // surface of current context when asking - // e.g. EGL on Wayland to create a new context. - for window_context in self.windows.values_mut() { - window_context.display.make_not_current(); - } - - if let Err(err) = self.create_window(event_loop, proxy.clone(), options) { - error!("Could not open window: {:?}", err); - } - }, - // Process events affecting all windows. - WinitEvent::UserEvent(event @ Event { window_id: None, .. }) => { - for window_context in self.windows.values_mut() { - window_context.handle_event( - event_loop, - &proxy, - &mut clipboard, - &mut scheduler, - event.clone().into(), - ); - } - }, - // Process window-specific events. - WinitEvent::WindowEvent { window_id, .. } - | WinitEvent::UserEvent(Event { window_id: Some(window_id), .. }) => { - if let Some(window_context) = self.windows.get_mut(&window_id) { - window_context.handle_event( - event_loop, - &proxy, - &mut clipboard, - &mut scheduler, - event, - ); - } - }, - _ => (), - } - }); - - if initial_window_error.is_err() { - initial_window_error - } else { - result.map_err(Into::into) - } - } - - /// Check if an event is irrelevant and can be skipped. - fn skip_event(event: &WinitEvent<Event>) -> bool { - match event { - WinitEvent::NewEvents(StartCause::Init) => false, - WinitEvent::WindowEvent { event, .. } => matches!( - event, - WindowEvent::KeyboardInput { is_synthetic: true, .. } - | WindowEvent::TouchpadPressure { .. } - | WindowEvent::CursorEntered { .. } - | WindowEvent::AxisMotion { .. } - | WindowEvent::HoveredFileCancelled - | WindowEvent::Destroyed - | WindowEvent::HoveredFile(_) - | WindowEvent::Moved(_) - ), - WinitEvent::Suspended { .. } | WinitEvent::NewEvents { .. } => true, - _ => false, - } - } -} - #[derive(Debug, Clone)] pub struct EventProxy { proxy: EventLoopProxy<Event>, diff --git a/alacritty/src/input/keyboard.rs b/alacritty/src/input/keyboard.rs index b7635bd9..b4c35741 100644 --- a/alacritty/src/input/keyboard.rs +++ b/alacritty/src/input/keyboard.rs @@ -126,7 +126,7 @@ impl<T: EventListener, A: ActionContext<T>> Processor<T, A> { self.ctx.modifiers().state().alt_key() } }, - _ => text.len() == 1 && alt_send_esc, + _ => alt_send_esc && text.chars().count() == 1, } } @@ -347,7 +347,7 @@ impl SequenceBuilder { associated_text: Option<&str>, ) -> Option<SequenceBase> { let character = match key.logical_key.as_ref() { - Key::Character(character) => character, + Key::Character(character) if self.kitty_seq => character, _ => return None, }; diff --git a/alacritty/src/input/mod.rs b/alacritty/src/input/mod.rs index 9a96b45b..095e8737 100644 --- a/alacritty/src/input/mod.rs +++ b/alacritty/src/input/mod.rs @@ -20,10 +20,10 @@ use winit::event::{ ElementState, Modifiers, MouseButton, MouseScrollDelta, Touch as TouchEvent, TouchPhase, }; #[cfg(target_os = "macos")] -use winit::event_loop::EventLoopWindowTarget; +use winit::event_loop::ActiveEventLoop; use winit::keyboard::ModifiersState; #[cfg(target_os = "macos")] -use winit::platform::macos::EventLoopWindowTargetExtMacOS; +use winit::platform::macos::ActiveEventLoopExtMacOS; use winit::window::CursorIcon; use alacritty_terminal::event::EventListener; @@ -36,6 +36,8 @@ use alacritty_terminal::vi_mode::ViMotion; use alacritty_terminal::vte::ansi::{ClearMode, Handler}; use crate::clipboard::Clipboard; +#[cfg(target_os = "macos")] +use crate::config::window::Decorations; use crate::config::{Action, BindingMode, MouseAction, SearchAction, UiConfig, ViAction}; use crate::display::hint::HintMatch; use crate::display::window::Window; @@ -105,7 +107,7 @@ pub trait ActionContext<T: EventListener> { fn message(&self) -> Option<&Message>; fn config(&self) -> &UiConfig; #[cfg(target_os = "macos")] - fn event_loop(&self) -> &EventLoopWindowTarget<Event>; + fn event_loop(&self) -> &ActiveEventLoop; fn mouse_mode(&self) -> bool; fn clipboard_mut(&mut self) -> &mut Clipboard; fn scheduler_mut(&mut self) -> &mut Scheduler; @@ -385,8 +387,11 @@ impl<T: EventListener> Execute<T> for Action { Action::CreateNewWindow => ctx.create_new_window(None), #[cfg(target_os = "macos")] Action::CreateNewTab => { - let tabbing_id = Some(ctx.window().tabbing_id()); - ctx.create_new_window(tabbing_id); + // Tabs on macOS are not possible without decorations. + if ctx.config().window.decorations != Decorations::None { + let tabbing_id = Some(ctx.window().tabbing_id()); + ctx.create_new_window(tabbing_id); + } }, #[cfg(target_os = "macos")] Action::SelectNextTab => ctx.window().select_next_tab(), @@ -1219,7 +1224,7 @@ mod tests { } #[cfg(target_os = "macos")] - fn event_loop(&self) -> &EventLoopWindowTarget<Event> { + fn event_loop(&self) -> &ActiveEventLoop { unimplemented!(); } diff --git a/alacritty/src/logging.rs b/alacritty/src/logging.rs index 42f1536e..59303649 100644 --- a/alacritty/src/logging.rs +++ b/alacritty/src/logging.rs @@ -12,7 +12,7 @@ use std::sync::{Arc, Mutex, OnceLock}; use std::time::Instant; use std::{env, process}; -use log::{self, Level, LevelFilter}; +use log::{Level, LevelFilter}; use winit::event_loop::EventLoopProxy; use crate::cli::Options; @@ -28,6 +28,9 @@ const ALACRITTY_LOG_ENV: &str = "ALACRITTY_LOG"; /// Logging target for config error messages. pub const LOG_TARGET_CONFIG: &str = "alacritty_config_derive"; +/// Logging target for winit events. +pub const LOG_TARGET_WINIT: &str = "alacritty_winit_event"; + /// Name for the environment variable containing extra logging targets. /// /// The targets are semicolon separated. @@ -47,6 +50,7 @@ fn extra_log_targets() -> &'static [String] { const ALLOWED_TARGETS: &[&str] = &[ LOG_TARGET_IPC_CONFIG, LOG_TARGET_CONFIG, + LOG_TARGET_WINIT, "alacritty_config_derive", "alacritty_terminal", "alacritty", diff --git a/alacritty/src/main.rs b/alacritty/src/main.rs index 2a60961a..2951c224 100644 --- a/alacritty/src/main.rs +++ b/alacritty/src/main.rs @@ -19,11 +19,11 @@ use std::path::PathBuf; use std::{env, fs}; use log::info; +#[cfg(all(feature = "x11", not(any(target_os = "macos", windows))))] +use raw_window_handle::{HasRawDisplayHandle, RawDisplayHandle}; #[cfg(windows)] use windows_sys::Win32::System::Console::{AttachConsole, FreeConsole, ATTACH_PARENT_PROCESS}; -use winit::event_loop::EventLoopBuilder as WinitEventLoopBuilder; -#[cfg(all(feature = "x11", not(any(target_os = "macos", windows))))] -use winit::platform::x11::EventLoopWindowTargetExtX11; +use winit::event_loop::EventLoop; use alacritty_terminal::tty; @@ -56,7 +56,8 @@ mod gl { #[cfg(unix)] use crate::cli::MessageOptions; use crate::cli::{Options, Subcommands}; -use crate::config::{monitor, UiConfig}; +use crate::config::monitor::ConfigMonitor; +use crate::config::UiConfig; use crate::event::{Event, Processor}; #[cfg(target_os = "macos")] use crate::macos::locale; @@ -124,7 +125,7 @@ impl Drop for TemporaryFiles { /// config change monitor, and runs the main display loop. fn alacritty(mut options: Options) -> Result<(), Box<dyn Error>> { // Setup winit event loop. - let window_event_loop = WinitEventLoopBuilder::<Event>::with_user_event().build()?; + let window_event_loop = EventLoop::<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()) @@ -134,7 +135,14 @@ fn alacritty(mut options: Options) -> Result<(), Box<dyn Error>> { info!("Version {}", env!("VERSION")); #[cfg(all(feature = "x11", not(any(target_os = "macos", windows))))] - info!("Running on {}", if window_event_loop.is_x11() { "X11" } else { "Wayland" }); + info!( + "Running on {}", + if matches!(window_event_loop.raw_display_handle(), RawDisplayHandle::Wayland(_)) { + "Wayland" + } else { + "X11" + } + ); #[cfg(not(any(feature = "x11", target_os = "macos", windows)))] info!("Running on Wayland"); @@ -165,8 +173,10 @@ fn alacritty(mut options: Options) -> Result<(), Box<dyn Error>> { // // The monitor watches the config file for changes and reloads it. Pending // config changes are processed in the main loop. + let mut config_monitor = None; if config.live_config_reload { - monitor::watch(config.config_paths.clone(), window_event_loop.create_proxy()); + config_monitor = + ConfigMonitor::new(config.config_paths.clone(), window_event_loop.create_proxy()); } // Create the IPC socket listener. @@ -186,13 +196,14 @@ fn alacritty(mut options: Options) -> Result<(), Box<dyn Error>> { }; // Event processor. - let window_options = options.window_options.clone(); - let mut processor = Processor::new(config, options, &window_event_loop); + let processor = Processor::new(config, options, &window_event_loop); // Start event loop and block until shutdown. - let result = processor.run(window_event_loop, window_options); + let result = processor.run(window_event_loop); - // This explicit drop is needed for Windows, ConPTY backend. Otherwise a deadlock can occur. + // `Processor` must be dropped before calling `FreeConsole`. + // + // This is needed for ConPTY backend. Otherwise a deadlock can occur. // The cause: // - Drop for ConPTY will deadlock if the conout pipe has already been dropped // - ConPTY is dropped when the last of processor and window context are dropped, because both @@ -203,10 +214,11 @@ fn alacritty(mut options: Options) -> Result<(), Box<dyn Error>> { // order. // // FIXME: Change PTY API to enforce the correct drop order with the typesystem. - drop(processor); - // FIXME patch notify library to have a shutdown method. - // config_reloader.join().ok(); + // Terminate the config monitor. + if let Some(config_monitor) = config_monitor.take() { + config_monitor.shutdown(); + } // Without explicitly detaching the console cmd won't redraw it's prompt. #[cfg(windows)] @@ -229,5 +241,5 @@ fn log_config_path(config: &UiConfig) { let _ = write!(msg, "\n {:?}", path.display()); } - info!("{}", msg); + info!("{msg}"); } diff --git a/alacritty/src/renderer/mod.rs b/alacritty/src/renderer/mod.rs index d869b503..165e28ec 100644 --- a/alacritty/src/renderer/mod.rs +++ b/alacritty/src/renderer/mod.rs @@ -211,30 +211,29 @@ impl Renderer { size_info: &SizeInfo, glyph_cache: &mut GlyphCache, ) { - let mut skip_next = false; - let cells = string_chars.enumerate().filter_map(|(i, character)| { - if skip_next { - skip_next = false; - return None; - } - - let mut flags = Flags::empty(); - if character.width() == Some(2) { - flags.insert(Flags::WIDE_CHAR); - // Wide character is always followed by a spacer, so skip it. - skip_next = true; - } + let mut wide_char_spacer = false; + let cells = string_chars.enumerate().map(|(i, character)| { + let flags = if wide_char_spacer { + wide_char_spacer = false; + Flags::WIDE_CHAR_SPACER + } else if character.width() == Some(2) { + // The spacer is always following the wide char. + wide_char_spacer = true; + Flags::WIDE_CHAR + } else { + Flags::empty() + }; - Some(RenderableCell { + RenderableCell { point: Point::new(point.line, point.column + i), character, extra: None, - flags: Flags::empty(), + flags, bg_alpha: 1.0, fg, bg, underline: fg, - }) + } }); self.draw_cells(size_info, glyph_cache, cells); diff --git a/alacritty/src/window_context.rs b/alacritty/src/window_context.rs index 891551bb..f5fb5cc5 100644 --- a/alacritty/src/window_context.rs +++ b/alacritty/src/window_context.rs @@ -17,7 +17,7 @@ use log::info; use raw_window_handle::HasRawDisplayHandle; use serde_json as json; use winit::event::{Event as WinitEvent, Modifiers, WindowEvent}; -use winit::event_loop::{EventLoopProxy, EventLoopWindowTarget}; +use winit::event_loop::{ActiveEventLoop, EventLoopProxy}; use winit::window::WindowId; use alacritty_terminal::event::Event as TerminalEvent; @@ -70,7 +70,7 @@ pub struct WindowContext { impl WindowContext { /// Create initial window context that does bootstrapping the graphics API we're going to use. pub fn initial( - event_loop: &EventLoopWindowTarget<Event>, + event_loop: &ActiveEventLoop, proxy: EventLoopProxy<Event>, config: Rc<UiConfig>, options: WindowOptions, @@ -120,7 +120,7 @@ impl WindowContext { /// Create additional context with the graphics platform other windows are using. pub fn additional( &self, - event_loop: &EventLoopWindowTarget<Event>, + event_loop: &ActiveEventLoop, proxy: EventLoopProxy<Event>, config: Rc<UiConfig>, options: WindowOptions, @@ -399,7 +399,7 @@ impl WindowContext { /// Process events for this terminal window. pub fn handle_event( &mut self, - event_loop: &EventLoopWindowTarget<Event>, + #[cfg(target_os = "macos")] event_loop: &ActiveEventLoop, event_proxy: &EventLoopProxy<Event>, clipboard: &mut Clipboard, scheduler: &mut Scheduler, @@ -445,6 +445,7 @@ impl WindowContext { preserve_title: self.preserve_title, config: &self.config, event_proxy, + #[cfg(target_os = "macos")] event_loop, clipboard, scheduler, diff --git a/alacritty/windows/wix/alacritty.wxs b/alacritty/windows/wix/alacritty.wxs index 0ef66ec3..cd64ec7b 100644 --- a/alacritty/windows/wix/alacritty.wxs +++ b/alacritty/windows/wix/alacritty.wxs @@ -41,7 +41,7 @@ <!-- Add context menu --> <Component Id="ContextMenu" Guid="449f9121-f7b9-41fe-82da-52349ea8ff91" Directory="TARGETDIR"> <RegistryKey Root="HKCU" Key="Software\Classes\Directory\Background\shell\Open Alacritty here\command"> - <RegistryValue Type="string" Value="[AlacrittyProgramFiles]alacritty.exe" KeyPath="yes" /> + <RegistryValue Type="string" Value='[AlacrittyProgramFiles]alacritty.exe --working-directory "%v"' KeyPath="yes" /> </RegistryKey> <RegistryKey Root="HKCU" Key="Software\Classes\Directory\Background\shell\Open Alacritty here"> <RegistryValue Type="string" Name="Icon" Value="[AlacrittyProgramFiles]alacritty.exe" /> diff --git a/alacritty_config/Cargo.toml b/alacritty_config/Cargo.toml index e773d810..c09a05e2 100644 --- a/alacritty_config/Cargo.toml +++ b/alacritty_config/Cargo.toml @@ -4,7 +4,8 @@ version = "0.2.1-dev" authors = ["Christian Duerr <contact@christianduerr.com>"] license = "MIT OR Apache-2.0" description = "Alacritty configuration abstractions" -homepage = "https://github.com/alacritty/alacritty" +homepage = "https://alacritty.org" +repository = "https://github.com/alacritty/alacritty" edition = "2021" rust-version = "1.70.0" diff --git a/alacritty_config_derive/Cargo.toml b/alacritty_config_derive/Cargo.toml index 655cde3c..dce13237 100644 --- a/alacritty_config_derive/Cargo.toml +++ b/alacritty_config_derive/Cargo.toml @@ -4,7 +4,8 @@ version = "0.2.3-dev" authors = ["Christian Duerr <contact@christianduerr.com>"] license = "MIT OR Apache-2.0" description = "Failure resistant deserialization derive" -homepage = "https://github.com/alacritty/alacritty" +homepage = "https://alacritty.org" +repository = "https://github.com/alacritty/alacritty" edition = "2021" rust-version = "1.70.0" diff --git a/alacritty_terminal/CHANGELOG.md b/alacritty_terminal/CHANGELOG.md new file mode 100644 index 00000000..82636168 --- /dev/null +++ b/alacritty_terminal/CHANGELOG.md @@ -0,0 +1,21 @@ +# Changelog + +All notable changes to alacritty_terminal are documented in this file. The +sections should follow the order `Added`, `Changed`, `Deprecated`, `Fixed` and +`Removed`. + +**Breaking changes are written in bold style.** + +The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). + +## 0.24.1-dev + +## 0.24.0 + +### Added + +- `tty::unix::from_fd()` to create a TTY from a pre-opened PTY's file-descriptors + +### Changed + +- **`Term` is not focused by default anymore** diff --git a/alacritty_terminal/Cargo.toml b/alacritty_terminal/Cargo.toml index 4ee05da4..82cc1cf1 100644 --- a/alacritty_terminal/Cargo.toml +++ b/alacritty_terminal/Cargo.toml @@ -1,11 +1,12 @@ [package] name = "alacritty_terminal" -version = "0.22.1-dev" +version = "0.24.1-dev" authors = ["Christian Duerr <contact@christianduerr.com>", "Joe Wilm <joe@jwilm.com>"] license = "Apache-2.0" description = "Library for writing terminal emulators" readme = "../README.md" -homepage = "https://github.com/alacritty/alacritty" +homepage = "https://alacritty.org" +repository = "https://github.com/alacritty/alacritty" edition = "2021" rust-version = "1.70.0" @@ -14,7 +15,7 @@ default = ["serde"] serde = ["dep:serde", "bitflags/serde", "vte/serde"] [dependencies] -base64 = "0.21.3" +base64 = "0.22.0" bitflags = "2.4.1" home = "0.5.5" libc = "0.2" @@ -34,7 +35,7 @@ signal-hook = "0.3.10" [target.'cfg(windows)'.dependencies] piper = "0.2.1" miow = "0.6.0" -windows-sys = { version = "0.48.0", features = [ +windows-sys = { version = "0.52.0", features = [ "Win32_System_Console", "Win32_Foundation", "Win32_Security", diff --git a/alacritty_terminal/src/event_loop.rs b/alacritty_terminal/src/event_loop.rs index 929c642d..62dd7440 100644 --- a/alacritty_terminal/src/event_loop.rs +++ b/alacritty_terminal/src/event_loop.rs @@ -5,7 +5,6 @@ use std::collections::VecDeque; use std::fmt::{self, Display, Formatter}; use std::fs::File; use std::io::{self, ErrorKind, Read, Write}; -use std::marker::Send; use std::num::NonZeroUsize; use std::sync::mpsc::{self, Receiver, Sender, TryRecvError}; use std::sync::Arc; diff --git a/alacritty_terminal/src/grid/storage.rs b/alacritty_terminal/src/grid/storage.rs index d5709d14..0a2be43b 100644 --- a/alacritty_terminal/src/grid/storage.rs +++ b/alacritty_terminal/src/grid/storage.rs @@ -1,4 +1,4 @@ -use std::cmp::{max, PartialEq}; +use std::cmp::max; use std::mem; use std::mem::MaybeUninit; use std::ops::{Index, IndexMut}; diff --git a/alacritty_terminal/src/term/mod.rs b/alacritty_terminal/src/term/mod.rs index a7a0a65a..cfa4ea14 100644 --- a/alacritty_terminal/src/term/mod.rs +++ b/alacritty_terminal/src/term/mod.rs @@ -418,13 +418,13 @@ impl<T> Term<T> { } } - pub fn new<D: Dimensions>(options: Config, dimensions: &D, event_proxy: T) -> Term<T> { + pub fn new<D: Dimensions>(config: Config, dimensions: &D, event_proxy: T) -> Term<T> { let num_cols = dimensions.columns(); let num_lines = dimensions.screen_lines(); - let history_size = options.scrolling_history; + let history_size = config.scrolling_history; let grid = Grid::new(num_lines, num_cols, history_size); - let alt = Grid::new(num_lines, num_cols, 0); + let inactive_grid = Grid::new(num_lines, num_cols, 0); let tabs = TabStops::new(grid.columns()); @@ -434,25 +434,25 @@ impl<T> Term<T> { let damage = TermDamageState::new(num_cols, num_lines); Term { + inactive_grid, + scroll_region, + event_proxy, + damage, + config, grid, - inactive_grid: alt, + tabs, + inactive_keyboard_mode_stack: Default::default(), + graphics: Graphics::new(dimensions), + keyboard_mode_stack: Default::default(), active_charset: Default::default(), vi_mode_cursor: Default::default(), - tabs, - mode: Default::default(), - scroll_region, + cursor_style: Default::default(), colors: color::Colors::default(), - cursor_style: None, - event_proxy, - is_focused: true, - title: None, title_stack: Default::default(), - keyboard_mode_stack: Default::default(), - inactive_keyboard_mode_stack: Default::default(), - selection: None, - graphics: Graphics::new(dimensions), - damage, - config: options, + is_focused: Default::default(), + selection: Default::default(), + title: Default::default(), + mode: Default::default(), } } @@ -2493,10 +2493,8 @@ pub mod test { #[cfg(feature = "serde")] use serde::{Deserialize, Serialize}; - use unicode_width::UnicodeWidthChar; use crate::event::VoidListener; - use crate::index::Column; #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] pub struct TermSize { diff --git a/alacritty_terminal/src/tty/mod.rs b/alacritty_terminal/src/tty/mod.rs index 35d227b8..55d263ca 100644 --- a/alacritty_terminal/src/tty/mod.rs +++ b/alacritty_terminal/src/tty/mod.rs @@ -1,5 +1,6 @@ //! TTY related functionality. +use std::collections::HashMap; use std::path::PathBuf; use std::sync::Arc; use std::{env, io}; @@ -29,6 +30,9 @@ pub struct Options { /// Remain open after child process exits. pub hold: bool, + + /// Extra environment variables. + pub env: HashMap<String, String>, } /// Shell options. diff --git a/alacritty_terminal/src/tty/unix.rs b/alacritty_terminal/src/tty/unix.rs index 8ce04191..54118a58 100644 --- a/alacritty_terminal/src/tty/unix.rs +++ b/alacritty_terminal/src/tty/unix.rs @@ -4,6 +4,7 @@ use std::ffi::CStr; use std::fs::File; use std::io::{Error, ErrorKind, Read, Result}; use std::mem::MaybeUninit; +use std::os::fd::OwnedFd; use std::os::unix::io::{AsRawFd, FromRawFd}; use std::os::unix::net::UnixStream; use std::os::unix::process::CommandExt; @@ -11,7 +12,7 @@ use std::process::{Child, Command, Stdio}; use std::sync::Arc; use std::{env, ptr}; -use libc::{self, c_int, TIOCSCTTY}; +use libc::{c_int, TIOCSCTTY}; use log::error; use polling::{Event, PollMode, Poller}; use rustix_openpty::openpty; @@ -184,6 +185,11 @@ fn default_shell_command(shell: &str, user: &str) -> Command { pub fn new(config: &Options, window_size: WindowSize, window_id: u64) -> Result<Pty> { let pty = openpty(None, Some(&window_size.to_winsize()))?; let (master, slave) = (pty.controller, pty.user); + from_fd(config, window_id, master, slave) +} + +/// Create a new TTY from a PTY's file descriptors. +pub fn from_fd(config: &Options, window_id: u64, master: OwnedFd, slave: OwnedFd) -> Result<Pty> { let master_fd = master.as_raw_fd(); let slave_fd = slave.as_raw_fd(); @@ -217,9 +223,11 @@ pub fn new(config: &Options, window_size: WindowSize, window_id: u64) -> Result< builder.env("ALACRITTY_WINDOW_ID", &window_id); builder.env("USER", user.user); builder.env("HOME", user.home); - // Set Window ID for clients relying on X11 hacks. builder.env("WINDOWID", window_id); + for (key, value) in &config.env { + builder.env(key, value); + } unsafe { builder.pre_exec(move || { diff --git a/alacritty_terminal/src/tty/windows/conpty.rs b/alacritty_terminal/src/tty/windows/conpty.rs index 9731b4f0..244681e7 100644 --- a/alacritty_terminal/src/tty/windows/conpty.rs +++ b/alacritty_terminal/src/tty/windows/conpty.rs @@ -1,5 +1,8 @@ -use log::info; +use log::{info, warn}; +use std::collections::{HashMap, HashSet}; +use std::ffi::OsStr; use std::io::Error; +use std::os::windows::ffi::OsStrExt; use std::os::windows::io::IntoRawHandle; use std::{mem, ptr}; @@ -13,8 +16,8 @@ use windows_sys::{s, w}; use windows_sys::Win32::System::Threading::{ CreateProcessW, InitializeProcThreadAttributeList, UpdateProcThreadAttribute, - EXTENDED_STARTUPINFO_PRESENT, PROCESS_INFORMATION, PROC_THREAD_ATTRIBUTE_PSEUDOCONSOLE, - STARTF_USESTDHANDLES, STARTUPINFOEXW, STARTUPINFOW, + CREATE_UNICODE_ENVIRONMENT, EXTENDED_STARTUPINFO_PRESENT, PROCESS_INFORMATION, + PROC_THREAD_ATTRIBUTE_PSEUDOCONSOLE, STARTF_USESTDHANDLES, STARTUPINFOEXW, STARTUPINFOW, }; use crate::event::{OnResize, WindowSize}; @@ -198,8 +201,18 @@ pub fn new(config: &Options, window_size: WindowSize) -> Option<Pty> { } } + // Prepare child process creation arguments. let cmdline = win32_string(&cmdline(config)); let cwd = config.working_directory.as_ref().map(win32_string); + let mut creation_flags = EXTENDED_STARTUPINFO_PRESENT; + let custom_env_block = convert_custom_env(&config.env); + let custom_env_block_pointer = match &custom_env_block { + Some(custom_env_block) => { + creation_flags |= CREATE_UNICODE_ENVIRONMENT; + custom_env_block.as_ptr() as *mut std::ffi::c_void + }, + None => ptr::null_mut(), + }; let mut proc_info: PROCESS_INFORMATION = unsafe { mem::zeroed() }; unsafe { @@ -209,8 +222,8 @@ pub fn new(config: &Options, window_size: WindowSize) -> Option<Pty> { ptr::null_mut(), ptr::null_mut(), false as i32, - EXTENDED_STARTUPINFO_PRESENT, - ptr::null_mut(), + creation_flags, + custom_env_block_pointer, cwd.as_ref().map_or_else(ptr::null, |s| s.as_ptr()), &mut startup_info_ex.StartupInfo as *mut STARTUPINFOW, &mut proc_info as *mut PROCESS_INFORMATION, @@ -230,6 +243,63 @@ pub fn new(config: &Options, window_size: WindowSize) -> Option<Pty> { Some(Pty::new(conpty, conout, conin, child_watcher)) } +// Windows environment variables are case-insensitive, and the caller is responsible for +// deduplicating environment variables, so do that here while converting. +// +// https://learn.microsoft.com/en-us/previous-versions/troubleshoot/windows/win32/createprocess-cannot-eliminate-duplicate-variables#environment-variables +fn convert_custom_env(custom_env: &HashMap<String, String>) -> Option<Vec<u16>> { + // Windows inherits parent's env when no `lpEnvironment` parameter is specified. + if custom_env.is_empty() { + return None; + } + + let mut converted_block = Vec::new(); + let mut all_env_keys = HashSet::new(); + for (custom_key, custom_value) in custom_env { + let custom_key_os = OsStr::new(custom_key); + if all_env_keys.insert(custom_key_os.to_ascii_uppercase()) { + add_windows_env_key_value_to_block( + &mut converted_block, + custom_key_os, + OsStr::new(&custom_value), + ); + } else { + warn!( + "Omitting environment variable pair with duplicate key: \ + '{custom_key}={custom_value}'" + ); + } + } + + // Pull the current process environment after, to avoid overwriting the user provided one. + for (inherited_key, inherited_value) in std::env::vars_os() { + if all_env_keys.insert(inherited_key.to_ascii_uppercase()) { + add_windows_env_key_value_to_block( + &mut converted_block, + &inherited_key, + &inherited_value, + ); + } + } + + converted_block.push(0); + Some(converted_block) +} + +// According to the `lpEnvironment` parameter description: +// https://learn.microsoft.com/en-us/windows/win32/api/processthreadsapi/nf-processthreadsapi-createprocessa#parameters +// +// > An environment block consists of a null-terminated block of null-terminated strings. Each +// string is in the following form: +// > +// > name=value\0 +fn add_windows_env_key_value_to_block(block: &mut Vec<u16>, key: &OsStr, value: &OsStr) { + block.extend(key.encode_wide()); + block.push('=' as u16); + block.extend(value.encode_wide()); + block.push(0); +} + // Panic with the last os error as message. fn panic_shell_spawn() { panic!("Unable to spawn shell: {}", Error::last_os_error()); diff --git a/extra/man/alacritty.5.scd b/extra/man/alacritty.5.scd index 81637f3e..1b56210b 100644 --- a/extra/man/alacritty.5.scd +++ b/extra/man/alacritty.5.scd @@ -9,6 +9,20 @@ Alacritty - TOML configuration file format. Alacritty's configuration file uses the TOML format. The format's specification can be found at _https://toml.io/en/v1.0.0_. +# LOCATION + +Alacritty doesn't create the config file for you, but it looks for one in the +following locations on UNIX systems: + +. `$XDG_CONFIG_HOME/alacritty/alacritty.toml` +. `$XDG_CONFIG_HOME/alacritty.toml` +. `$HOME/.config/alacritty/alacritty.toml` +. `$HOME/.alacritty.toml` + +On Windows, the config file will be looked for in: + +. `%APPDATA%\alacritty\alacritty.toml` + # GENERAL This section documents the root level of the configuration file. @@ -647,7 +661,7 @@ terminal and pipe it to other applications. Default: _"jfkdls;ahgurieowpq"_ -*enabled* = [{ *<regex>*, *<hyperlinks>*, *<post_processing>*, *<persist>*, *<action>*, *<command>* *<binding>*, *<mouse>* },] +*enabled* = [{ *<regex>*, *<hyperlinks>*, *<post_processing>*, *<persist>*, *<action>*, *<command>*, *<binding>*, *<mouse>* },] Array with all available hints. diff --git a/extra/osx/Alacritty.app/Contents/Info.plist b/extra/osx/Alacritty.app/Contents/Info.plist index e7afebcb..e402e372 100644 --- a/extra/osx/Alacritty.app/Contents/Info.plist +++ b/extra/osx/Alacritty.app/Contents/Info.plist @@ -54,5 +54,7 @@ <string>An application in Alacritty would like to access your reminders.</string> <key>NSSystemAdministrationUsageDescription</key> <string>An application in Alacritty requires elevated permissions.</string> + <key>NSBluetoothAlwaysUsageDescription</key> + <string>An application in Alacritty wants to use Bluetooth.</string> </dict> </plist> |