From ef5784da0d7d8bba6cd7db8e942c5943a9eff259 Mon Sep 17 00:00:00 2001 From: Josh Matthews Date: Tue, 24 Jun 2025 23:52:49 -0400 Subject: [PATCH] servoshell: Enable accesskit integration. (#37519) These changes ensure that our browser shell can integrate with screenreaders. We do not provide any accessibility information about webview content yet, which requires further API design work in both Servo, accesskit, and egui. Testing: No a11y-specific testing at this point; just verifying that existing tests continue to pass. Fixes: part of #4344 --------- Signed-off-by: Josh Matthews --- Cargo.lock | 636 +++++++++++++++++++++- deny.toml | 12 + ports/servoshell/Cargo.toml | 5 +- ports/servoshell/desktop/app.rs | 27 +- ports/servoshell/desktop/egui_glue.rs | 26 +- ports/servoshell/desktop/events_loop.rs | 46 +- ports/servoshell/desktop/headed_window.rs | 4 +- ports/servoshell/desktop/minibrowser.rs | 34 +- ports/servoshell/desktop/tracing.rs | 9 +- 9 files changed, 743 insertions(+), 56 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 473e0d2e7af..b35f268ed2b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -18,6 +18,98 @@ version = "0.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c71b1793ee61086797f5c80b6efa2b8ffa6d5dd703f118545808a7f2e27f7046" +[[package]] +name = "accesskit" +version = "0.17.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3d3b8f9bae46a948369bc4a03e815d4ed6d616bd00de4051133a5019dc31c5a" + +[[package]] +name = "accesskit_atspi_common" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7c5dd55e6e94949498698daf4d48fb5659e824d7abec0d394089656ceaf99d4f" +dependencies = [ + "accesskit", + "accesskit_consumer", + "atspi-common", + "serde", + "thiserror 1.0.69", + "zvariant", +] + +[[package]] +name = "accesskit_consumer" +version = "0.26.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f47983a1084940ba9a39c077a8c63e55c619388be5476ac04c804cfbd1e63459" +dependencies = [ + "accesskit", + "hashbrown", + "immutable-chunkmap", +] + +[[package]] +name = "accesskit_macos" +version = "0.18.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7329821f3bd1101e03a7d2e03bd339e3ac0dc64c70b4c9f9ae1949e3ba8dece1" +dependencies = [ + "accesskit", + "accesskit_consumer", + "hashbrown", + "objc2 0.5.2", + "objc2-app-kit 0.2.2", + "objc2-foundation 0.2.2", +] + +[[package]] +name = "accesskit_unix" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fcee751cc20d88678c33edaf9c07e8b693cd02819fe89053776f5313492273f5" +dependencies = [ + "accesskit", + "accesskit_atspi_common", + "async-channel", + "async-executor", + "async-task", + "atspi", + "futures-lite", + "futures-util", + "serde", + "zbus", +] + +[[package]] +name = "accesskit_windows" +version = "0.24.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "24fcd5d23d70670992b823e735e859374d694a3d12bfd8dd32bd3bd8bedb5d81" +dependencies = [ + "accesskit", + "accesskit_consumer", + "hashbrown", + "paste", + "static_assertions", + "windows 0.58.0", + "windows-core 0.58.0", +] + +[[package]] +name = "accesskit_winit" +version = "0.23.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6a6a48dad5530b6deb9fc7a52cc6c3bf72cdd9eb8157ac9d32d69f2427a5e879" +dependencies = [ + "accesskit", + "accesskit_macos", + "accesskit_unix", + "accesskit_windows", + "raw-window-handle", + "winit", +] + [[package]] name = "accountable-refcell" version = "0.2.2" @@ -328,6 +420,30 @@ dependencies = [ "libloading", ] +[[package]] +name = "async-broadcast" +version = "0.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "435a87a52755b8f27fcf321ac4f04b2802e337c8c4872923137471ec39c37532" +dependencies = [ + "event-listener", + "event-listener-strategy", + "futures-core", + "pin-project-lite", +] + +[[package]] +name = "async-channel" +version = "2.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "89b47800b0be77592da0afd425cc03468052844aff33b84e33cc696f64e77b6a" +dependencies = [ + "concurrent-queue", + "event-listener-strategy", + "futures-core", + "pin-project-lite", +] + [[package]] name = "async-compression" version = "0.4.25" @@ -342,6 +458,80 @@ dependencies = [ "tokio", ] +[[package]] +name = "async-executor" +version = "1.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bb812ffb58524bdd10860d7d974e2f01cc0950c2438a74ee5ec2e2280c6c4ffa" +dependencies = [ + "async-task", + "concurrent-queue", + "fastrand", + "futures-lite", + "pin-project-lite", + "slab", +] + +[[package]] +name = "async-fs" +version = "2.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ebcd09b382f40fcd159c2d695175b2ae620ffa5f3bd6f664131efff4e8b9e04a" +dependencies = [ + "async-lock", + "blocking", + "futures-lite", +] + +[[package]] +name = "async-io" +version = "2.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1237c0ae75a0f3765f58910ff9cdd0a12eeb39ab2f4c7de23262f337f0aacbb3" +dependencies = [ + "async-lock", + "cfg-if", + "concurrent-queue", + "futures-io", + "futures-lite", + "parking", + "polling", + "rustix 1.0.7", + "slab", + "tracing", + "windows-sys 0.59.0", +] + +[[package]] +name = "async-lock" +version = "3.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ff6e472cdea888a4bd64f342f09b3f50e1886d32afe8df3d663c01140b811b18" +dependencies = [ + "event-listener", + "event-listener-strategy", + "pin-project-lite", +] + +[[package]] +name = "async-process" +version = "2.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cde3f4e40e6021d7acffc90095cbd6dc54cb593903d1de5832f435eb274b85dc" +dependencies = [ + "async-channel", + "async-io", + "async-lock", + "async-signal", + "async-task", + "blocking", + "cfg-if", + "event-listener", + "futures-lite", + "rustix 1.0.7", + "tracing", +] + [[package]] name = "async-recursion" version = "1.1.1" @@ -353,6 +543,41 @@ dependencies = [ "syn", ] +[[package]] +name = "async-signal" +version = "0.2.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d7605a4e50d4b06df3898d5a70bf5fde51ed9059b0434b73105193bc27acce0d" +dependencies = [ + "async-io", + "async-lock", + "atomic-waker", + "cfg-if", + "futures-core", + "futures-io", + "rustix 1.0.7", + "signal-hook-registry", + "slab", + "windows-sys 0.59.0", +] + +[[package]] +name = "async-task" +version = "4.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b75356056920673b02621b35afd0f7dda9306d03c79a30f5c56c44cf256e3de" + +[[package]] +name = "async-trait" +version = "0.1.88" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e539d3fca749fcee5236ab05e93a52867dd549cc157c8cb7f99595f3cedffdb5" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "async-tungstenite" version = "0.29.1" @@ -385,6 +610,57 @@ version = "0.1.13" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "41e67cd8309bbd06cd603a9e693a784ac2e5d1e955f11286e355089fcab3047c" +[[package]] +name = "atspi" +version = "0.22.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "be534b16650e35237bb1ed189ba2aab86ce65e88cc84c66f4935ba38575cecbf" +dependencies = [ + "atspi-common", + "atspi-connection", + "atspi-proxies", +] + +[[package]] +name = "atspi-common" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1909ed2dc01d0a17505d89311d192518507e8a056a48148e3598fef5e7bb6ba7" +dependencies = [ + "enumflags2", + "serde", + "static_assertions", + "zbus", + "zbus-lockstep", + "zbus-lockstep-macros", + "zbus_names", + "zvariant", +] + +[[package]] +name = "atspi-connection" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "430c5960624a4baaa511c9c0fcc2218e3b58f5dbcc47e6190cafee344b873333" +dependencies = [ + "atspi-common", + "atspi-proxies", + "futures-lite", + "zbus", +] + +[[package]] +name = "atspi-proxies" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a5e6c5de3e524cf967569722446bcd458d5032348554d9a17d7d72b041ab7496" +dependencies = [ + "atspi-common", + "serde", + "zbus", + "zvariant", +] + [[package]] name = "autocfg" version = "1.5.0" @@ -604,6 +880,19 @@ dependencies = [ "objc2 0.5.2", ] +[[package]] +name = "blocking" +version = "1.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "703f41c54fc768e63e091340b424302bb1c29ef4aa0c7f10fe849dfb114d29ea" +dependencies = [ + "async-channel", + "async-task", + "futures-io", + "futures-lite", + "piper", +] + [[package]] name = "bluetooth" version = "0.0.1" @@ -654,7 +943,7 @@ version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9c150fd617830fd121919bbd500a784507e8af1bae744efcf587591c65c375d4" dependencies = [ - "hex", + "hex 0.3.2", ] [[package]] @@ -664,7 +953,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f6dae8337ff67fe8ead29a28a0115605753e6a5205d4b6017e9f42f198c3c50a" dependencies = [ "dbus", - "hex", + "hex 0.3.2", ] [[package]] @@ -768,7 +1057,7 @@ dependencies = [ "bitflags 2.9.1", "log", "polling", - "rustix", + "rustix 0.38.44", "slab", "thiserror 1.0.69", ] @@ -780,7 +1069,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "95a66a987056935f7efce4ab5668920b5d0dac4a7c99991a67395f13702ddd20" dependencies = [ "calloop", - "rustix", + "rustix 0.38.44", "wayland-backend", "wayland-client", ] @@ -1867,6 +2156,7 @@ version = "0.31.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "25dd34cec49ab55d85ebf70139cb1ccd29c977ef6b6ba4fe85489d6877ee9ef3" dependencies = [ + "accesskit", "ahash", "bitflags 2.9.1", "emath", @@ -1895,6 +2185,7 @@ version = "0.31.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7d9dfbb78fe4eb9c3a39ad528b90ee5915c252e77bbab9d4ebc576541ab67e13" dependencies = [ + "accesskit_winit", "ahash", "arboard", "bytemuck", @@ -1996,6 +2287,33 @@ dependencies = [ "cfg-if", ] +[[package]] +name = "endi" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a3d8a32ae18130a3c84dd492d4215c3d913c3b07c6b63c2eb3eb7ff1101ab7bf" + +[[package]] +name = "enumflags2" +version = "0.7.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1027f7680c853e056ebcec683615fb6fbbc07dbaa13b4d5d9442b146ded4ecef" +dependencies = [ + "enumflags2_derive", + "serde", +] + +[[package]] +name = "enumflags2_derive" +version = "0.7.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "67c78a4d8fdf9953a5c9d458f9efe940fd97a0cab0941c075a813ac594733827" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "env_filter" version = "0.1.3" @@ -2096,6 +2414,27 @@ dependencies = [ "serde", ] +[[package]] +name = "event-listener" +version = "5.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3492acde4c3fc54c845eaab3eed8bd00c7a7d881f78bfc801e43a93dec1331ae" +dependencies = [ + "concurrent-queue", + "parking", + "pin-project-lite", +] + +[[package]] +name = "event-listener-strategy" +version = "0.5.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8be9f3dfaaffdae2972880079a491a1a8bb7cbed0b8dd7a347f668b4150a3b93" +dependencies = [ + "event-listener", + "pin-project-lite", +] + [[package]] name = "exr" version = "1.73.0" @@ -2468,6 +2807,19 @@ version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9e5c1b78ca4aae1ac06c48a526a655760685149f0d465d21f37abfe57ce075c6" +[[package]] +name = "futures-lite" +version = "2.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f5edaec856126859abb19ed65f39e90fea3a9574b9707f13539acf4abf7eb532" +dependencies = [ + "fastrand", + "futures-core", + "futures-io", + "parking", + "pin-project-lite", +] + [[package]] name = "futures-macro" version = "0.3.31" @@ -3315,6 +3667,12 @@ version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "805026a5d0141ffc30abb3be3173848ad46a1b1664fe632428479619a3644d77" +[[package]] +name = "hex" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" + [[package]] name = "hexf-parse" version = "0.2.1" @@ -4046,6 +4404,15 @@ version = "0.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "edcd27d72f2f071c64249075f42e205ff93c9a4c5f6c6da53e79ed9f9832c285" +[[package]] +name = "immutable-chunkmap" +version = "2.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "12f97096f508d54f8f8ab8957862eee2ccd628847b6217af1a335e1c44dee578" +dependencies = [ + "arrayvec", +] + [[package]] name = "imsz" version = "0.2.2" @@ -4554,6 +4921,12 @@ version = "0.4.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d26c52dbd32dccf2d10cac7725f8eae5296885fb5703b261f7d0a0739ec807ab" +[[package]] +name = "linux-raw-sys" +version = "0.9.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cd945864f07fe9f5371a27ad7b52a172b4b499999f1d97574c9fa68373937e12" + [[package]] name = "litemap" version = "0.7.5" @@ -5087,6 +5460,7 @@ dependencies = [ "cfg-if", "cfg_aliases", "libc", + "memoffset", ] [[package]] @@ -5673,6 +6047,16 @@ dependencies = [ "num-traits", ] +[[package]] +name = "ordered-stream" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9aa2b01e1d916879f73a53d01d1d6cee68adbb31d6d9177a8cfce093cced1d50" +dependencies = [ + "futures-core", + "pin-project-lite", +] + [[package]] name = "ordermap" version = "0.3.5" @@ -5704,6 +6088,12 @@ dependencies = [ "winapi", ] +[[package]] +name = "parking" +version = "2.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f38d5652c16fde515bb1ecef450ab0f6a219d619a7274976324d5e377f7dceba" + [[package]] name = "parking_lot" version = "0.12.4" @@ -5878,6 +6268,17 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" +[[package]] +name = "piper" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "96c8c490f422ef9a4efd2cb5b42b76c8613d7e7dfc1caf667b8a3350a5acc066" +dependencies = [ + "atomic-waker", + "fastrand", + "futures-io", +] + [[package]] name = "pixels" version = "0.0.1" @@ -5961,7 +6362,7 @@ dependencies = [ "concurrent-queue", "hermit-abi 0.4.0", "pin-project-lite", - "rustix", + "rustix 0.38.44", "tracing", "windows-sys 0.59.0", ] @@ -6139,6 +6540,16 @@ version = "2.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a993555f31e5a609f617c12db6250dedcac1b0a85076912c436e6fc9b2c8e6a3" +[[package]] +name = "quick-xml" +version = "0.30.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eff6510e86862b57b210fd8cbe8ed3f0d7d600b9c2863cd4549a2e033c66e956" +dependencies = [ + "memchr", + "serde", +] + [[package]] name = "quick-xml" version = "0.37.5" @@ -6486,10 +6897,23 @@ dependencies = [ "bitflags 2.9.1", "errno", "libc", - "linux-raw-sys", + "linux-raw-sys 0.4.15", "windows-sys 0.52.0", ] +[[package]] +name = "rustix" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c71e83d6afe7ff64890ec6b71d6a69bb8a610ab78ce364b3352876bb4c801266" +dependencies = [ + "bitflags 2.9.1", + "errno", + "libc", + "linux-raw-sys 0.9.4", + "windows-sys 0.59.0", +] + [[package]] name = "rustls" version = "0.23.28" @@ -6862,6 +7286,17 @@ dependencies = [ "serde", ] +[[package]] +name = "serde_repr" +version = "0.1.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "175ee3e80ae9982737ca543e96133087cbd9a485eecc3bc4de9c1a37b47ea59c" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "serde_spanned" version = "0.6.9" @@ -7198,6 +7633,7 @@ dependencies = [ name = "servoshell" version = "0.0.1" dependencies = [ + "accesskit_winit", "android_logger", "backtrace", "cc", @@ -7303,6 +7739,15 @@ dependencies = [ "libc", ] +[[package]] +name = "signal-hook-registry" +version = "1.4.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9203b8055f63a2a00e2f593bb0510367fe707d7ff1e5c872de2f537b339e5410" +dependencies = [ + "libc", +] + [[package]] name = "signpost" version = "0.1.0" @@ -7384,7 +7829,7 @@ dependencies = [ "libc", "log", "memmap2", - "rustix", + "rustix 0.38.44", "thiserror 1.0.69", "wayland-backend", "wayland-client", @@ -7842,7 +8287,7 @@ dependencies = [ "fastrand", "getrandom 0.2.16", "once_cell", - "rustix", + "rustix 0.38.44", "windows-sys 0.52.0", ] @@ -8360,6 +8805,17 @@ version = "1.18.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1dccffe3ce07af9386bfd29e80c0ab1a8205a2fc34e4bcd40364df902cfa8f3f" +[[package]] +name = "uds_windows" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "89daebc3e6fd160ac4aa9fc8b3bf71e1f74fbf92367ae71fb83a037e8bf164b9" +dependencies = [ + "memoffset", + "tempfile", + "winapi", +] + [[package]] name = "uluru" version = "3.1.0" @@ -8754,7 +9210,7 @@ checksum = "fe770181423e5fc79d3e2a7f4410b7799d5aab1de4372853de3c6aa13ca24121" dependencies = [ "cc", "downcast-rs", - "rustix", + "rustix 0.38.44", "scoped-tls", "smallvec", "wayland-sys 0.31.6", @@ -8767,7 +9223,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "978fa7c67b0847dbd6a9f350ca2569174974cd4082737054dbb7fbb79d7d9a61" dependencies = [ "bitflags 2.9.1", - "rustix", + "rustix 0.38.44", "wayland-backend", "wayland-scanner", ] @@ -8789,7 +9245,7 @@ version = "0.31.10" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a65317158dec28d00416cb16705934070aef4f8393353d41126c54264ae0f182" dependencies = [ - "rustix", + "rustix 0.38.44", "wayland-client", "xcursor", ] @@ -8839,7 +9295,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "896fdafd5d28145fce7958917d69f2fd44469b1d4e861cb5961bcbeebc6d1484" dependencies = [ "proc-macro2", - "quick-xml", + "quick-xml 0.37.5", "quote", ] @@ -9250,7 +9706,7 @@ dependencies = [ "either", "home", "once_cell", - "rustix", + "rustix 0.38.44", ] [[package]] @@ -9653,7 +10109,7 @@ dependencies = [ "pin-project", "raw-window-handle", "redox_syscall 0.4.1", - "rustix", + "rustix 0.38.44", "sctk-adwaita", "smithay-client-toolkit", "smol_str", @@ -9790,7 +10246,7 @@ dependencies = [ "libc", "libloading", "once_cell", - "rustix", + "rustix 0.38.44", "x11rb-protocol", ] @@ -9807,8 +10263,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e105d177a3871454f754b33bb0ee637ecaaac997446375fd3e5d43a2ed00c909" dependencies = [ "libc", - "linux-raw-sys", - "rustix", + "linux-raw-sys 0.4.15", + "rustix 0.38.44", ] [[package]] @@ -9828,6 +10284,16 @@ version = "0.3.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "635887f4315a33cb714eb059bdbd7c1c92bfa71bc5b9d5115460502f788c2ab5" +[[package]] +name = "xdg-home" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec1cdab258fb55c0da61328dc52c8764709b249011b2cad0454c72f0bf10a1f6" +dependencies = [ + "libc", + "windows-sys 0.59.0", +] + [[package]] name = "xi-unicode" version = "0.3.0" @@ -9911,6 +10377,105 @@ dependencies = [ "synstructure", ] +[[package]] +name = "zbus" +version = "4.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bb97012beadd29e654708a0fdb4c84bc046f537aecfde2c3ee0a9e4b4d48c725" +dependencies = [ + "async-broadcast", + "async-executor", + "async-fs", + "async-io", + "async-lock", + "async-process", + "async-recursion", + "async-task", + "async-trait", + "blocking", + "enumflags2", + "event-listener", + "futures-core", + "futures-sink", + "futures-util", + "hex 0.4.3", + "nix", + "ordered-stream", + "rand 0.8.5", + "serde", + "serde_repr", + "sha1", + "static_assertions", + "tracing", + "uds_windows", + "windows-sys 0.52.0", + "xdg-home", + "zbus_macros", + "zbus_names", + "zvariant", +] + +[[package]] +name = "zbus-lockstep" +version = "0.4.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4ca2c5dceb099bddaade154055c926bb8ae507a18756ba1d8963fd7b51d8ed1d" +dependencies = [ + "zbus_xml", + "zvariant", +] + +[[package]] +name = "zbus-lockstep-macros" +version = "0.4.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "709ab20fc57cb22af85be7b360239563209258430bccf38d8b979c5a2ae3ecce" +dependencies = [ + "proc-macro2", + "quote", + "syn", + "zbus-lockstep", + "zbus_xml", + "zvariant", +] + +[[package]] +name = "zbus_macros" +version = "4.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "267db9407081e90bbfa46d841d3cbc60f59c0351838c4bc65199ecd79ab1983e" +dependencies = [ + "proc-macro-crate", + "proc-macro2", + "quote", + "syn", + "zvariant_utils", +] + +[[package]] +name = "zbus_names" +version = "3.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4b9b1fef7d021261cc16cba64c351d291b715febe0fa10dc3a443ac5a5022e6c" +dependencies = [ + "serde", + "static_assertions", + "zvariant", +] + +[[package]] +name = "zbus_xml" +version = "4.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ab3f374552b954f6abb4bd6ce979e6c9b38fb9d0cd7cc68a7d796e70c9f3a233" +dependencies = [ + "quick-xml 0.30.0", + "serde", + "static_assertions", + "zbus_names", + "zvariant", +] + [[package]] name = "zerocopy" version = "0.7.35" @@ -10015,3 +10580,40 @@ checksum = "7384255a918371b5af158218d131530f694de9ad3815ebdd0453a940485cb0fa" dependencies = [ "zune-core", ] + +[[package]] +name = "zvariant" +version = "4.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2084290ab9a1c471c38fc524945837734fbf124487e105daec2bb57fd48c81fe" +dependencies = [ + "endi", + "enumflags2", + "serde", + "static_assertions", + "zvariant_derive", +] + +[[package]] +name = "zvariant_derive" +version = "4.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "73e2ba546bda683a90652bac4a279bc146adad1386f25379cf73200d2002c449" +dependencies = [ + "proc-macro-crate", + "proc-macro2", + "quote", + "syn", + "zvariant_utils", +] + +[[package]] +name = "zvariant_utils" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c51bcff7cc3dbb5055396bcf774748c3dab426b4b8659046963523cee4808340" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] diff --git a/deny.toml b/deny.toml index 123a14d9a7d..496f35cbbed 100644 --- a/deny.toml +++ b/deny.toml @@ -174,6 +174,18 @@ skip = [ # Stylo uses 2.0, WebRender uses 0.99 "derive_more", + + # duplicated by blurz/blurmock + "hex", + + # duplciated by rustix + "linux-raw-sys", + + # duplicated by async-io + "rustix", + + # duplicated by zbus-xml + "quick-xml", ] # github.com organizations to allow git sources for diff --git a/ports/servoshell/Cargo.toml b/ports/servoshell/Cargo.toml index 0f6afd7722a..414f08aabd4 100644 --- a/ports/servoshell/Cargo.toml +++ b/ports/servoshell/Cargo.toml @@ -106,10 +106,11 @@ serde_json = { workspace = true } surfman = { workspace = true, features = ["sm-angle-default"] } [target.'cfg(not(any(target_os = "android", target_env = "ohos")))'.dependencies] +accesskit_winit = "0.23" dirs = "6.0" -egui = "0.31.1" +egui = { version = "0.31.1", features = ["accesskit"] } egui-file-dialog = "0.9.0" -egui-winit = { version = "0.31.1", default-features = false, features = ["clipboard", "wayland"] } +egui-winit = { version = "0.31.1", default-features = false, features = ["accesskit", "clipboard", "wayland"] } egui_glow = { version = "0.31.1", features = ["winit"] } gilrs = "0.11.0" glow = "0.16.0" diff --git a/ports/servoshell/desktop/app.rs b/ports/servoshell/desktop/app.rs index c24e5426d5f..a7d48c4cca9 100644 --- a/ports/servoshell/desktop/app.rs +++ b/ports/servoshell/desktop/app.rs @@ -27,7 +27,7 @@ use winit::event_loop::{ActiveEventLoop, ControlFlow}; use winit::window::WindowId; use super::app_state::AppState; -use super::events_loop::{EventsLoop, WakerEvent}; +use super::events_loop::{AppEvent, EventLoopProxy, EventsLoop}; use super::minibrowser::{Minibrowser, MinibrowserEvent}; use super::{headed_window, headless_window}; use crate::desktop::app_state::RunningAppState; @@ -45,6 +45,7 @@ pub struct App { suspended: Cell, minibrowser: Option, waker: Box, + proxy: Option, initial_url: ServoUrl, t_start: Instant, t: Instant, @@ -89,6 +90,7 @@ impl App { windows: HashMap::new(), minibrowser: None, waker: events_loop.create_event_loop_waker(), + proxy: events_loop.event_loop_proxy(), initial_url: initial_url.clone(), t_start: t, t, @@ -103,10 +105,12 @@ impl App { assert_eq!(headless, event_loop.is_none()); let window = match event_loop { Some(event_loop) => { + let proxy = self.proxy.take().expect("Must have a proxy available"); let window = headed_window::Window::new(&self.servoshell_preferences, event_loop); self.minibrowser = Some(Minibrowser::new( - window.offscreen_rendering_context(), + &window, event_loop, + proxy, self.initial_url.clone(), )); Rc::new(window) @@ -238,7 +242,7 @@ impl App { /// continue. pub fn handle_events_with_headless(&mut self) -> bool { let now = Instant::now(); - let event = winit::event::Event::UserEvent(WakerEvent); + let event = winit::event::Event::UserEvent(AppEvent::Waker); trace_winit_event!( event, "@{:?} (+{:?}) {event:?}", @@ -360,7 +364,7 @@ impl App { } } -impl ApplicationHandler for App { +impl ApplicationHandler for App { fn resumed(&mut self, event_loop: &ActiveEventLoop) { self.init(Some(event_loop)); } @@ -468,7 +472,20 @@ impl ApplicationHandler for App { self.handle_events_with_winit(event_loop, window); } - fn user_event(&mut self, event_loop: &ActiveEventLoop, event: WakerEvent) { + fn user_event(&mut self, event_loop: &ActiveEventLoop, event: AppEvent) { + if let AppEvent::Accessibility(ref event) = event { + let Some(ref mut minibrowser) = self.minibrowser else { + return; + }; + if !minibrowser.handle_accesskit_event(&event.window_event) { + return; + } + if let Some(window) = self.windows.get(&event.window_id) { + window.winit_window().unwrap().request_redraw(); + } + return; + } + let now = Instant::now(); let event = winit::event::Event::UserEvent(event); trace_winit_event!( diff --git a/ports/servoshell/desktop/egui_glue.rs b/ports/servoshell/desktop/egui_glue.rs index e27a659dd24..385000abebd 100644 --- a/ports/servoshell/desktop/egui_glue.rs +++ b/ports/servoshell/desktop/egui_glue.rs @@ -41,6 +41,10 @@ use egui_winit::winit; use winit::event_loop::ActiveEventLoop; use winit::window::Theme; +use super::events_loop::EventLoopProxy; +use super::headed_window::Window; +use super::window_trait::WindowPortsMethods; + /// Use [`egui`] from a [`glow`] app based on [`winit`]. pub struct EguiGlow { pub egui_ctx: egui::Context, @@ -54,7 +58,9 @@ pub struct EguiGlow { impl EguiGlow { /// For automatic shader version detection set `shader_version` to `None`. pub fn new( + window: &Window, event_loop: &ActiveEventLoop, + event_loop_proxy: EventLoopProxy, gl: std::sync::Arc, shader_version: Option, ) -> Self { @@ -66,15 +72,19 @@ impl EguiGlow { let theme = event_loop.system_theme().unwrap_or(Theme::Light); let egui_ctx = egui::Context::default(); + let mut egui_winit = egui_winit::State::new( + egui_ctx.clone(), + ViewportId::ROOT, + event_loop, + None, + Some(theme), + None, + ); + let window = window.winit_window().unwrap(); + egui_winit.init_accesskit(window, event_loop_proxy); + window.set_visible(true); Self { - egui_winit: egui_winit::State::new( - egui_ctx.clone(), - ViewportId::ROOT, - event_loop, - None, - Some(theme), - None, - ), + egui_winit, egui_ctx, painter, shapes: Default::default(), diff --git a/ports/servoshell/desktop/events_loop.rs b/ports/servoshell/desktop/events_loop.rs index 859e9d8ba8a..4e1a64a00e5 100644 --- a/ports/servoshell/desktop/events_loop.rs +++ b/ports/servoshell/desktop/events_loop.rs @@ -16,15 +16,26 @@ use winit::platform::macos::{ActivationPolicy, EventLoopBuilderExtMacOS}; use super::app::App; -/// Another process or thread has kicked the OS event loop with EventLoopWaker. +pub type EventLoopProxy = winit::event_loop::EventLoopProxy; + #[derive(Debug)] -pub struct WakerEvent; +pub enum AppEvent { + /// Another process or thread has kicked the OS event loop with EventLoopWaker. + Waker, + Accessibility(accesskit_winit::Event), +} + +impl From for AppEvent { + fn from(event: accesskit_winit::Event) -> AppEvent { + AppEvent::Accessibility(event) + } +} /// The real or fake OS event loop. #[allow(dead_code)] enum EventLoop { /// A real Winit windowing event loop. - Winit(Option>), + Winit(winit::event_loop::EventLoop), /// A fake event loop which contains a signalling flag used to ensure /// that pending events get processed in a timely fashion, and a condition /// variable to allow waiting on that flag changing state. @@ -38,16 +49,16 @@ impl EventsLoop { // but on Linux, the event loop requires a X11 server. #[cfg(not(any(target_os = "linux", target_os = "macos")))] pub fn new(_headless: bool, _has_output_file: bool) -> Result { - Ok(EventsLoop(EventLoop::Winit(Some( + Ok(EventsLoop(EventLoop::Winit( WinitEventLoop::with_user_event().build()?, - )))) + ))) } #[cfg(target_os = "linux")] pub fn new(headless: bool, _has_output_file: bool) -> Result { Ok(EventsLoop(if headless { EventLoop::Headless(Arc::new((Mutex::new(false), Condvar::new()))) } else { - EventLoop::Winit(Some(WinitEventLoop::with_user_event().build()?)) + EventLoop::Winit(WinitEventLoop::with_user_event().build()?) })) } #[cfg(target_os = "macos")] @@ -61,20 +72,22 @@ impl EventsLoop { // when generating an output file. event_loop_builder.with_activation_policy(ActivationPolicy::Prohibited); } - EventLoop::Winit(Some(event_loop_builder.build()?)) + EventLoop::Winit(event_loop_builder.build()?) })) } } impl EventsLoop { + pub(crate) fn event_loop_proxy(&self) -> Option { + match self.0 { + EventLoop::Winit(ref events_loop) => Some(events_loop.create_proxy()), + EventLoop::Headless(..) => None, + } + } + pub fn create_event_loop_waker(&self) -> Box { match self.0 { - EventLoop::Winit(ref events_loop) => { - let events_loop = events_loop - .as_ref() - .expect("Can't create waker for unavailable event loop."); - Box::new(HeadedEventLoopWaker::new(events_loop)) - }, + EventLoop::Winit(ref events_loop) => Box::new(HeadedEventLoopWaker::new(events_loop)), EventLoop::Headless(ref data) => Box::new(HeadlessEventLoopWaker(data.clone())), } } @@ -82,7 +95,6 @@ impl EventsLoop { pub fn run_app(self, app: &mut App) { match self.0 { EventLoop::Winit(events_loop) => { - let events_loop = events_loop.expect("Can't run an unavailable event loop."); events_loop .run_app(app) .expect("Failed while running events loop"); @@ -121,10 +133,10 @@ impl EventsLoop { } struct HeadedEventLoopWaker { - proxy: Arc>>, + proxy: Arc>>, } impl HeadedEventLoopWaker { - fn new(events_loop: &winit::event_loop::EventLoop) -> HeadedEventLoopWaker { + fn new(events_loop: &winit::event_loop::EventLoop) -> HeadedEventLoopWaker { let proxy = Arc::new(Mutex::new(events_loop.create_proxy())); HeadedEventLoopWaker { proxy } } @@ -132,7 +144,7 @@ impl HeadedEventLoopWaker { impl EventLoopWaker for HeadedEventLoopWaker { fn wake(&self) { // Kick the OS event loop awake. - if let Err(err) = self.proxy.lock().unwrap().send_event(WakerEvent) { + if let Err(err) = self.proxy.lock().unwrap().send_event(AppEvent::Waker) { warn!("Failed to wake up event loop ({}).", err); } } diff --git a/ports/servoshell/desktop/headed_window.rs b/ports/servoshell/desktop/headed_window.rs index 6305b701539..fb2275f57da 100644 --- a/ports/servoshell/desktop/headed_window.rs +++ b/ports/servoshell/desktop/headed_window.rs @@ -92,7 +92,9 @@ impl Window { .with_transparent(no_native_titlebar) .with_inner_size(LogicalSize::new(window_size.width, window_size.height)) .with_min_inner_size(LogicalSize::new(1, 1)) - .with_visible(true); + // Must be invisible at startup; accesskit_winit setup needs to + // happen before the window is shown for the first time. + .with_visible(false); #[allow(deprecated)] let winit_window = event_loop diff --git a/ports/servoshell/desktop/minibrowser.rs b/ports/servoshell/desktop/minibrowser.rs index 5eac3005048..dcdd4ad94b2 100644 --- a/ports/servoshell/desktop/minibrowser.rs +++ b/ports/servoshell/desktop/minibrowser.rs @@ -29,7 +29,9 @@ use winit::window::Window; use super::app_state::RunningAppState; use super::egui_glue::EguiGlow; +use super::events_loop::EventLoopProxy; use super::geometry::winit_position_to_euclid_point; +use super::headed_window::Window as ServoWindow; pub struct Minibrowser { rendering_context: Rc, @@ -76,13 +78,21 @@ impl Drop for Minibrowser { impl Minibrowser { pub fn new( - rendering_context: Rc, + window: &ServoWindow, event_loop: &ActiveEventLoop, + event_loop_proxy: EventLoopProxy, initial_url: ServoUrl, ) -> Self { + let rendering_context = window.offscreen_rendering_context(); // Adapted from https://github.com/emilk/egui/blob/9478e50d012c5138551c38cbee16b07bc1fcf283/crates/egui_glow/examples/pure_glow.rs #[allow(clippy::arc_with_non_send_sync)] - let context = EguiGlow::new(event_loop, rendering_context.glow_gl_api(), None); + let context = EguiGlow::new( + window, + event_loop, + event_loop_proxy, + rendering_context.glow_gl_api(), + None, + ); // Disable the builtin egui handlers for the Ctrl+Plus, Ctrl+Minus and Ctrl+0 // shortcuts as they don't work well with servoshell's `device-pixel-ratio` CLI argument. @@ -489,4 +499,24 @@ impl Minibrowser { self.update_load_status(state) | self.update_status_text(state) } + + /// Returns true if a redraw is required after handling the provided event. + pub(crate) fn handle_accesskit_event(&mut self, event: &accesskit_winit::WindowEvent) -> bool { + match event { + accesskit_winit::WindowEvent::InitialTreeRequested => { + self.context.egui_ctx.enable_accesskit(); + true + }, + accesskit_winit::WindowEvent::ActionRequested(req) => { + self.context + .egui_winit + .on_accesskit_action_request(req.clone()); + true + }, + accesskit_winit::WindowEvent::AccessibilityDeactivated => { + self.context.egui_ctx.disable_accesskit(); + false + }, + } + } } diff --git a/ports/servoshell/desktop/tracing.rs b/ports/servoshell/desktop/tracing.rs index dfdfdc1602a..b1f0b1d742e 100644 --- a/ports/servoshell/desktop/tracing.rs +++ b/ports/servoshell/desktop/tracing.rs @@ -11,7 +11,7 @@ /// - servoshell { @@ -39,7 +39,7 @@ mod from_winit { }; } - impl LogTarget for winit::event::Event { + impl LogTarget for winit::event::Event { fn log_target(&self) -> &'static str { use winit::event::StartCause; match self { @@ -51,7 +51,8 @@ mod from_winit { }, Self::WindowEvent { event, .. } => event.log_target(), Self::DeviceEvent { .. } => target!("DeviceEvent"), - Self::UserEvent(WakerEvent) => target!("UserEvent(WakerEvent)"), + Self::UserEvent(AppEvent::Waker) => target!("UserEvent(Waker)"), + Self::UserEvent(AppEvent::Accessibility(..)) => target!("UserEvent(Accessibility)"), Self::Suspended => target!("Suspended"), Self::Resumed => target!("Resumed"), Self::AboutToWait => target!("AboutToWait"),