#[cfg(any(web, test))]
pub(crate) fn browser_owns(key: &str, cmd: bool, alt: bool, shift: bool) -> bool {
if matches!(key, "F5" | "F11" | "F12") {
return true;
}
if alt && !cmd && matches!(key, "ArrowLeft" | "ArrowRight" | "Home") {
return true;
}
if !cmd {
return false;
}
let letter = key.to_ascii_lowercase();
match letter.as_str() {
"r" | "l" | "t" | "n" | "w" | "p" | "f" | "h" | "j" | "d" | "u" => true,
"+" | "-" | "=" | "0" => true,
"tab" | "pageup" | "pagedown" => true,
"i" | "c" => shift, _ => false,
}
}
#[cfg(web)]
pub(crate) fn let_the_browser_keep_its_shortcuts() {
use wasm_bindgen::closure::Closure;
use wasm_bindgen::JsCast;
let Some(window) = web_sys::window() else {
return;
};
for kind in ["keydown", "keyup"] {
let closure = Closure::wrap(Box::new(move |event: web_sys::Event| {
let Some(key) = event.dyn_ref::<web_sys::KeyboardEvent>() else {
return;
};
let cmd = key.ctrl_key() || key.meta_key();
if browser_owns(&key.key(), cmd, key.alt_key(), key.shift_key()) {
event.stop_immediate_propagation();
}
}) as Box<dyn FnMut(web_sys::Event)>);
let _ = (window.as_ref() as &web_sys::EventTarget)
.add_event_listener_with_callback_and_bool(
kind,
closure.as_ref().unchecked_ref(),
true,
);
closure.forget();
}
}
#[cfg(test)]
mod tests {
use super::browser_owns;
#[test]
fn reload_and_the_developer_tools_are_the_browsers() {
assert!(browser_owns("F5", false, false, false));
assert!(
browser_owns("F5", true, false, false),
"Ctrl+F5, a hard reload"
);
assert!(browser_owns("F12", false, false, false));
assert!(browser_owns("F11", false, false, false));
assert!(browser_owns("r", true, false, false), "Ctrl+R");
assert!(
browser_owns("R", true, false, true),
"Ctrl+Shift+R, as the browser reports it"
);
assert!(browser_owns("i", true, false, true), "Ctrl+Shift+I");
assert!(browser_owns("l", true, false, false), "the address bar");
}
#[test]
fn save_and_open_are_left_to_the_application() {
assert!(!browser_owns("s", true, false, false));
assert!(!browser_owns("o", true, false, false));
}
#[test]
fn the_applications_own_keys_are_not() {
for key in ["c", "x", "v", "a", "z", "y"] {
assert!(!browser_owns(key, true, false, false), "Ctrl+{key}");
}
assert!(!browser_owns("c", true, false, false));
assert!(browser_owns("c", true, false, true));
for key in [
"a",
"Enter",
"Tab",
"Escape",
"ArrowLeft",
"Backspace",
" ",
"F1",
"F2",
"F10",
] {
assert!(!browser_owns(key, false, false, false), "{key}");
}
assert!(
!browser_owns("F10", false, false, true),
"Shift+F10 is the bar's"
);
assert!(!browser_owns("Tab", false, false, true));
}
#[test]
fn zoom_tabs_and_history_are_the_browsers() {
for key in ["+", "-", "=", "0"] {
assert!(browser_owns(key, true, false, false), "zoom {key}");
}
assert!(browser_owns("Tab", true, false, false), "Ctrl+Tab");
assert!(browser_owns("PageDown", true, false, false));
assert!(
browser_owns("ArrowLeft", false, true, false),
"Alt+Left, Back"
);
assert!(
browser_owns("ArrowRight", false, true, false),
"Alt+Right, Forward"
);
assert!(!browser_owns("ArrowLeft", true, true, false));
}
}