Browse Source

Remove dependency on `tts` (#3651)

We were using [`tts`](https://github.com/ndarilek/tts-rs) for the
web-only screen reader. This was overkill, to say the least. It is now
replaced with ten lines of `web-sys` calls.
pull/3665/head
Emil Ernerfeldt 11 months ago
committed by GitHub
parent
commit
a1f3c71b7f
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 243
      Cargo.lock
  2. 7
      crates/eframe/Cargo.toml
  3. 6
      crates/eframe/src/web/app_runner.rs
  4. 1
      crates/eframe/src/web/mod.rs
  5. 57
      crates/eframe/src/web/screen_reader.rs
  6. 2
      crates/egui/src/memory.rs
  7. 7
      crates/egui_demo_app/Cargo.toml
  8. 7
      crates/egui_demo_app/src/backend_panel.rs
  9. 2
      scripts/wasm_bindgen_check.sh

243
Cargo.lock

@ -490,29 +490,6 @@ dependencies = [
"serde",
]
[[package]]
name = "bindgen"
version = "0.68.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "726e4313eb6ec35d2730258ad4e15b547ee75d6afaa1361a922e78e59b7d8078"
dependencies = [
"bitflags 2.4.0",
"cexpr",
"clang-sys",
"lazy_static",
"lazycell",
"log",
"peeking_take_while",
"prettyplease",
"proc-macro2",
"quote",
"regex",
"rustc-hash",
"shlex",
"syn 2.0.37",
"which",
]
[[package]]
name = "bit-set"
version = "0.5.3"
@ -677,15 +654,6 @@ version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6d43a04d8753f35258c91f8ec639f792891f748a1edbd759cf1dcea3382ad83c"
[[package]]
name = "cexpr"
version = "0.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6fac387a98bb7c37292057cffc56d62ecb629900026402633ae9160df93a8766"
dependencies = [
"nom",
]
[[package]]
name = "cfg-expr"
version = "0.15.5"
@ -764,17 +732,6 @@ version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7a0e87cdf78571d9fbeff16861c37a006cd718d2433dc6d5b80beaae367d899a"
[[package]]
name = "clang-sys"
version = "1.6.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c688fc74432808e3eb684cae8830a86be1d66a2bd58e1f248ed0960a590baf6f"
dependencies = [
"glob",
"libc",
"libloading 0.7.4",
]
[[package]]
name = "clap"
version = "3.2.25"
@ -1058,41 +1015,6 @@ dependencies = [
"winapi",
]
[[package]]
name = "darling"
version = "0.13.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a01d95850c592940db9b8194bc39f4bc0e89dee5c4265e4b1807c34a9aba453c"
dependencies = [
"darling_core",
"darling_macro",
]
[[package]]
name = "darling_core"
version = "0.13.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "859d65a907b6852c9361e3185c862aae7fafd2887876799fa55f5f99dc40d610"
dependencies = [
"fnv",
"ident_case",
"proc-macro2",
"quote",
"strsim",
"syn 1.0.109",
]
[[package]]
name = "darling_macro"
version = "0.13.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9c972679f83bdf9c42bd905396b6c3588a843a17f0f16dfcfa3e2c5d57441835"
dependencies = [
"darling_core",
"quote",
"syn 1.0.109",
]
[[package]]
name = "data-url"
version = "0.2.0"
@ -1177,33 +1099,6 @@ version = "1.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9ea835d29036a4087793836fa931b08837ad5e957da9e23886b29586fb9b6650"
[[package]]
name = "dyn-clonable"
version = "0.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4e9232f0e607a262ceb9bd5141a3dfb3e4db6994b31989bbfd845878cba59fd4"
dependencies = [
"dyn-clonable-impl",
"dyn-clone",
]
[[package]]
name = "dyn-clonable-impl"
version = "0.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "558e40ea573c374cf53507fd240b7ee2f5477df7cfebdb97323ec61c719399c5"
dependencies = [
"proc-macro2",
"quote",
"syn 1.0.109",
]
[[package]]
name = "dyn-clone"
version = "1.0.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "23d2f3407d9a573d666de4b5bdf10569d73ca9478087346697dcbae6244bfbcd"
[[package]]
name = "ecolor"
version = "0.24.0"
@ -1243,7 +1138,6 @@ dependencies = [
"serde",
"static_assertions",
"thiserror",
"tts",
"wasm-bindgen",
"wasm-bindgen-futures",
"web-sys",
@ -1843,12 +1737,6 @@ dependencies = [
"system-deps",
]
[[package]]
name = "glob"
version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d2fabcfbdc87f4758337ca535fb41a6d701b65693ce38287d856d1674551ec9b"
[[package]]
name = "glow"
version = "0.12.3"
@ -2161,12 +2049,6 @@ dependencies = [
"cc",
]
[[package]]
name = "ident_case"
version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39"
[[package]]
name = "idna"
version = "0.4.0"
@ -2363,12 +2245,6 @@ version = "1.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
[[package]]
name = "lazycell"
version = "1.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55"
[[package]]
name = "libc"
version = "0.2.148"
@ -2614,35 +2490,6 @@ version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "27b02d87554356db9e9a873add8782d4ea6e3e58ea071a9adb9a2e8ddb884a8b"
[[package]]
name = "ndk-glue"
version = "0.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0434fabdd2c15e0aab768ca31d5b7b333717f03cf02037d5a0a3ff3c278ed67f"
dependencies = [
"libc",
"log",
"ndk",
"ndk-context",
"ndk-macro",
"ndk-sys",
"once_cell",
"parking_lot",
]
[[package]]
name = "ndk-macro"
version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0df7ac00c4672f9d5aece54ee3347520b7e20f158656c7db2e6de01902eb7a6c"
dependencies = [
"darling",
"proc-macro-crate",
"proc-macro2",
"quote",
"syn 1.0.109",
]
[[package]]
name = "ndk-sys"
version = "0.4.1+23.1.7779620"
@ -2876,12 +2723,6 @@ dependencies = [
"ttf-parser",
]
[[package]]
name = "oxilangtag"
version = "0.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8d91edf4fbb970279443471345a4e8c491bf05bb283b3e6c88e4e606fd8c181b"
[[package]]
name = "pango-sys"
version = "0.16.3"
@ -2929,12 +2770,6 @@ version = "1.0.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "de3145af08024dea9fa9914f381a17b8fc6034dfb00f3a84013f7ff43f29ed4c"
[[package]]
name = "peeking_take_while"
version = "0.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "19b17cddbe7ec3f8bc800887bab5e717348c95ea2ca0b1bf0837fb964dc67099"
[[package]]
name = "percent-encoding"
version = "2.3.0"
@ -3047,16 +2882,6 @@ version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e8cf8e6a8aa66ce33f63993ffc4ea4271eb5b0530a9002db8455ea6050c77bfa"
[[package]]
name = "prettyplease"
version = "0.2.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ae005bd773ab59b4725093fd7df83fd7892f7d8eafb48dbd7de6e024e4215f9d"
dependencies = [
"proc-macro2",
"syn 2.0.37",
]
[[package]]
name = "proc-macro-crate"
version = "1.3.1"
@ -3541,12 +3366,6 @@ dependencies = [
"digest",
]
[[package]]
name = "shlex"
version = "1.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a7cee0529a6d40f580e7a5e6c495c8fbfe21b7b52795ed4bb5e62cdf92bc6380"
[[package]]
name = "signal-hook-registry"
version = "1.4.1"
@ -3640,26 +3459,6 @@ dependencies = [
"winapi",
]
[[package]]
name = "speech-dispatcher"
version = "0.16.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5727d53c474ba5ada07784ad7d203cf896a74854cfee0eb32376b00759eb2972"
dependencies = [
"lazy_static",
"libc",
"speech-dispatcher-sys",
]
[[package]]
name = "speech-dispatcher-sys"
version = "0.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6c3e8acdf2b1f4bb13f1813b40b52f3edf4cc94d8a55fe713a584f672a10388d"
dependencies = [
"bindgen",
]
[[package]]
name = "spin"
version = "0.5.2"
@ -3706,12 +3505,6 @@ dependencies = [
"float-cmp",
]
[[package]]
name = "strsim"
version = "0.10.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623"
[[package]]
name = "svgtypes"
version = "0.8.2"
@ -3989,30 +3782,6 @@ version = "0.19.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a464a4b34948a5f67fddd2b823c62d9d92e44be75058b99939eae6c5b6960b33"
[[package]]
name = "tts"
version = "0.25.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "aee57eae77c7059f02e9ae166cd3ef4973e62c859b1eeaf9a738032a5b1c38e4"
dependencies = [
"cocoa-foundation",
"core-foundation",
"dyn-clonable",
"jni",
"lazy_static",
"libc",
"log",
"ndk-context",
"ndk-glue",
"objc",
"oxilangtag",
"speech-dispatcher",
"thiserror",
"wasm-bindgen",
"web-sys",
"windows 0.51.1",
]
[[package]]
name = "type-map"
version = "0.5.0"
@ -4484,18 +4253,6 @@ dependencies = [
"web-sys",
]
[[package]]
name = "which"
version = "4.4.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "87ba24419a2078cd2b0f2ede2691b6c66d8e47836da3b6db8265ebad47afbfc7"
dependencies = [
"either",
"home",
"once_cell",
"rustix 0.38.14",
]
[[package]]
name = "widestring"
version = "1.0.2"

7
crates/eframe/Cargo.toml

@ -32,6 +32,7 @@ default = [
"default_fonts",
"glow",
"wayland",
"web_screen_reader",
"winit/default",
"x11",
]
@ -84,7 +85,10 @@ wayland = ["egui-winit/wayland"]
## Enable screen reader support (requires `ctx.options_mut(|o| o.screen_reader = true);`) on web.
##
## For other platforms, use the `accesskit` feature instead.
web_screen_reader = ["tts"]
web_screen_reader = [
"web-sys/SpeechSynthesis",
"web-sys/SpeechSynthesisUtterance",
]
## Use [`wgpu`](https://docs.rs/wgpu) for painting (via [`egui-wgpu`](https://github.com/emilk/egui/tree/master/crates/egui-wgpu)).
## This overrides the `glow` feature.
@ -207,5 +211,4 @@ web-sys = { version = "0.3.58", features = [
# optional web:
egui-wgpu = { version = "0.24.0", path = "../egui-wgpu", optional = true } # if wgpu is used, use it without (!) winit
raw-window-handle = { workspace = true, optional = true }
tts = { version = "0.25", optional = true, default-features = false }
wgpu = { workspace = true, optional = true }

6
crates/eframe/src/web/app_runner.rs

@ -13,7 +13,6 @@ pub struct AppRunner {
app: Box<dyn epi::App>,
pub(crate) needs_repaint: std::sync::Arc<NeedRepaint>,
last_save_time: f64,
screen_reader: super::screen_reader::ScreenReader,
pub(crate) text_cursor_pos: Option<egui::Pos2>,
pub(crate) mutable_text_under_cursor: bool,
@ -113,7 +112,6 @@ impl AppRunner {
app,
needs_repaint,
last_save_time: now_sec(),
screen_reader: Default::default(),
text_cursor_pos: None,
mutable_text_under_cursor: false,
textures_delta: Default::default(),
@ -235,9 +233,9 @@ impl AppRunner {
}
fn handle_platform_output(&mut self, platform_output: egui::PlatformOutput) {
#[cfg(feature = "web_screen_reader")]
if self.egui_ctx.options(|o| o.screen_reader) {
self.screen_reader
.speak(&platform_output.events_description());
super::screen_reader::speak(&platform_output.events_description());
}
let egui::PlatformOutput {

1
crates/eframe/src/web/mod.rs

@ -12,6 +12,7 @@ mod web_logger;
mod web_runner;
/// Access to the browser screen reader.
#[cfg(feature = "web_screen_reader")]
pub mod screen_reader;
/// Access to local browser storage.

57
crates/eframe/src/web/screen_reader.rs

@ -1,51 +1,20 @@
/// Screen reader support.
pub struct ScreenReader {
#[cfg(feature = "tts")]
tts: Option<tts::Tts>,
}
#[cfg(not(feature = "tts"))]
#[allow(clippy::derivable_impls)] // False positive
impl Default for ScreenReader {
fn default() -> Self {
Self {}
/// Speak the given text out loud.
pub fn speak(text: &str) {
if text.is_empty() {
return;
}
}
#[cfg(feature = "tts")]
impl Default for ScreenReader {
fn default() -> Self {
let tts = match tts::Tts::default() {
Ok(screen_reader) => {
log::debug!("Initialized screen reader.");
Some(screen_reader)
}
Err(err) => {
log::warn!("Failed to load screen reader: {}", err);
None
}
};
Self { tts }
}
}
if let Some(window) = web_sys::window() {
log::debug!("Speaking {text:?}");
impl ScreenReader {
/// Speak the given text out loud.
#[cfg(not(feature = "tts"))]
#[allow(clippy::unused_self)]
pub fn speak(&mut self, _text: &str) {}
if let Ok(speech_synthesis) = window.speech_synthesis() {
speech_synthesis.cancel(); // interrupt previous speech, if any
/// Speak the given text out loud.
#[cfg(feature = "tts")]
pub fn speak(&mut self, text: &str) {
if text.is_empty() {
return;
}
if let Some(tts) = &mut self.tts {
log::debug!("Speaking: {:?}", text);
let interrupt = true;
if let Err(err) = tts.speak(text, interrupt) {
log::warn!("Failed to read: {}", err);
if let Ok(utterance) = web_sys::SpeechSynthesisUtterance::new_with_text(text) {
utterance.set_rate(1.0);
utterance.set_pitch(1.0);
utterance.set_volume(1.0);
speech_synthesis.speak(&utterance);
}
}
}

2
crates/egui/src/memory.rs

@ -199,7 +199,7 @@ pub struct Options {
///
/// Screen readers is an experimental feature of egui, and not supported on all platforms.
///
/// `eframe` supports it only on web, using the `web_screen_reader` feature flag,
/// `eframe` supports it only on web,
/// but you should consider using [AccessKit](https://github.com/AccessKit/accesskit) instead,
/// which `eframe` supports.
pub screen_reader: bool,

7
crates/egui_demo_app/Cargo.toml

@ -19,7 +19,7 @@ crate-type = ["cdylib", "rlib"]
default = ["glow", "persistence"]
# image_viewer adds about 0.9 MB of WASM
web_app = ["http", "persistence", "web_screen_reader"]
web_app = ["http", "persistence"]
http = ["ehttp", "image", "poll-promise", "egui_extras/image"]
image_viewer = ["image", "egui_extras/all_loaders", "rfd"]
@ -27,7 +27,6 @@ persistence = ["eframe/persistence", "egui/persistence", "serde"]
puffin = ["eframe/puffin", "dep:puffin", "dep:puffin_http"]
serde = ["dep:serde", "egui_demo_lib/serde", "egui/serde"]
syntect = ["egui_demo_lib/syntect"]
web_screen_reader = ["eframe/web_screen_reader"] # experimental
glow = ["eframe/glow"]
wgpu = ["eframe/wgpu", "bytemuck"]
@ -37,7 +36,9 @@ chrono = { version = "0.4", default-features = false, features = [
"js-sys",
"wasmbind",
] }
eframe = { version = "0.24.0", path = "../eframe", default-features = false }
eframe = { version = "0.24.0", path = "../eframe", default-features = false, features = [
"web_screen_reader",
] }
egui = { version = "0.24.0", path = "../egui", features = [
"callstack",
"extra_debug_asserts",

7
crates/egui_demo_app/src/backend_panel.rs

@ -94,15 +94,12 @@ impl BackendPanel {
self.egui_windows.checkboxes(ui);
#[cfg(debug_assertions)]
{
if ui.ctx().style().debug.debug_on_hover_with_all_modifiers {
ui.separator();
if ui.ctx().style().debug.debug_on_hover_with_all_modifiers {
ui.label("Press down all modifiers and hover a widget to see a callstack for it");
}
ui.label("Press down all modifiers and hover a widget to see a callstack for it");
}
#[cfg(target_arch = "wasm32")]
#[cfg(feature = "web_screen-reader")]
{
ui.separator();
let mut screen_reader = ui.ctx().options(|o| o.screen_reader);

2
scripts/wasm_bindgen_check.sh

@ -12,7 +12,7 @@ else
fi
CRATE_NAME="egui_demo_app"
FEATURES="glow,http,persistence,web_screen_reader"
FEATURES="glow,http,persistence"
# This is required to enable the web_sys clipboard API which eframe web uses
# https://rustwasm.github.io/wasm-bindgen/api/web_sys/struct.Clipboard.html

Loading…
Cancel
Save