use std::env;
fn detect_screen_reader() -> bool {
let indicators = [
"SCREEN_READER",
"ACCESSIBILITY_ENABLED",
"ORCA_ENABLED", "NVDA_RUNNING", "JAWS_RUNNING", "VOICEOVER_RUNNING", "TERM_PROGRAM", ];
for var in indicators {
if let Ok(val) = env::var(var) {
if var == "TERM_PROGRAM" {
if val.to_lowercase().contains("accessibility") {
return true;
}
} else if !val.is_empty() && val != "0" && val.to_lowercase() != "false" {
return true;
}
}
}
if let Ok(term) = env::var("TERM")
&& (term.contains("screen") || term.contains("tmux"))
{
}
#[cfg(target_os = "macos")]
{
if let Ok(output) = std::process::Command::new("defaults")
.args(["read", "com.apple.universalaccess", "voiceOverOnOffKey"])
.output()
&& output.status.success()
{
let stdout = String::from_utf8_lossy(&output.stdout);
if stdout.trim() == "1" {
return true;
}
}
}
false
}
pub fn use_is_screen_reader_enabled() -> bool {
if let Some(ctx) = crate::runtime::current_runtime() {
if ctx.borrow().is_screen_reader_initialized() {
return ctx.borrow().is_screen_reader_enabled();
}
let detected = detect_screen_reader();
ctx.borrow_mut().set_screen_reader_enabled(detected);
detected
} else {
detect_screen_reader()
}
}
pub fn set_screen_reader_enabled(enabled: bool) {
if let Some(ctx) = crate::runtime::current_runtime() {
ctx.borrow_mut().set_screen_reader_enabled(enabled);
}
}
pub fn clear_screen_reader_cache() {
if let Some(ctx) = crate::runtime::current_runtime() {
ctx.borrow_mut()
.set_screen_reader_enabled(detect_screen_reader());
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::runtime::{RuntimeContext, set_current_runtime};
use std::cell::RefCell;
use std::rc::Rc;
#[test]
fn test_screen_reader_detection() {
let ctx = Rc::new(RefCell::new(RuntimeContext::new()));
set_current_runtime(Some(ctx.clone()));
let result = use_is_screen_reader_enabled();
let _ = result;
set_current_runtime(None);
}
#[test]
fn test_manual_override() {
let ctx = Rc::new(RefCell::new(RuntimeContext::new()));
set_current_runtime(Some(ctx.clone()));
set_screen_reader_enabled(true);
assert!(use_is_screen_reader_enabled());
set_screen_reader_enabled(false);
assert!(!use_is_screen_reader_enabled());
set_current_runtime(None);
}
#[test]
fn test_runtime_auto_initializes_on_first_read() {
let ctx = Rc::new(RefCell::new(RuntimeContext::new()));
set_current_runtime(Some(ctx.clone()));
assert!(!ctx.borrow().is_screen_reader_initialized());
let _ = use_is_screen_reader_enabled();
assert!(ctx.borrow().is_screen_reader_initialized());
set_current_runtime(None);
}
#[test]
fn test_caching() {
let ctx = Rc::new(RefCell::new(RuntimeContext::new()));
set_current_runtime(Some(ctx.clone()));
clear_screen_reader_cache();
let first = use_is_screen_reader_enabled();
let second = use_is_screen_reader_enabled();
assert_eq!(first, second);
set_current_runtime(None);
}
#[test]
fn test_without_runtime_falls_back() {
set_current_runtime(None);
let _ = use_is_screen_reader_enabled();
}
}