Overhaul the Keyboard API
Overhaul the keyboard API in winit to mimic the W3C specification
to achieve better crossplatform parity. The `KeyboardInput` event
is now uses `KeyEvent` which consists of:
- `physical_key` - a cross platform way to refer to scancodes;
- `logical_key` - keysym value, which shows your key respecting the
layout;
- `text` - the text produced by this keypress;
- `location` - the location of the key on the keyboard;
- `repeat` - whether the key was produced by the repeat.
And also a `platform_specific` field which encapsulates extra
information on desktop platforms, like key without modifiers
and text with all modifiers.
The `Modifiers` were also slightly reworked as in, the information
whether the left or right modifier is pressed is now also exposed
on platforms where it could be queried reliably. The support was
also added for the web and orbital platforms finishing the API
change.
This change made the `OptionAsAlt` API on macOS redundant thus it
was removed all together.
Co-authored-by: Artúr Kovács <kovacs.artur.barnabas@gmail.com>
Co-authored-by: Kirill Chibisov <contact@kchibisov.com>
Co-authored-by: daxpedda <daxpedda@gmail.com>
Fixes: #2631.
Fixes: #2055.
Fixes: #2032.
Fixes: #1904.
Fixes: #1810.
Fixes: #1700.
Fixes: #1443.
Fixes: #1343.
Fixes: #1208.
Fixes: #1151.
Fixes: #812.
Fixes: #600.
Fixes: #361.
Fixes: #343.
This commit is contained in:
parent
f3f46cb3f6
commit
918430979f
81 changed files with 9577 additions and 3419 deletions
|
|
@ -1,29 +1,56 @@
|
|||
use std::cell::RefCell;
|
||||
use std::cell::{Cell, RefCell};
|
||||
use std::clone::Clone;
|
||||
use std::collections::{vec_deque::IntoIter as VecDequeIter, VecDeque};
|
||||
use std::iter;
|
||||
use std::rc::Rc;
|
||||
|
||||
use raw_window_handle::{RawDisplayHandle, WebDisplayHandle};
|
||||
|
||||
use super::{
|
||||
super::monitor::MonitorHandle, backend, device::DeviceId, proxy::EventLoopProxy, runner,
|
||||
super::{monitor::MonitorHandle, KeyEventExtra},
|
||||
backend,
|
||||
device::DeviceId,
|
||||
proxy::EventLoopProxy,
|
||||
runner,
|
||||
window::WindowId,
|
||||
};
|
||||
use crate::dpi::{PhysicalSize, Size};
|
||||
use crate::event::{
|
||||
DeviceEvent, DeviceId as RootDeviceId, ElementState, Event, KeyboardInput, Touch, TouchPhase,
|
||||
DeviceEvent, DeviceId as RootDeviceId, ElementState, Event, KeyEvent, Touch, TouchPhase,
|
||||
WindowEvent,
|
||||
};
|
||||
use crate::keyboard::ModifiersState;
|
||||
use crate::window::{Theme, WindowId as RootWindowId};
|
||||
|
||||
#[derive(Default)]
|
||||
struct ModifiersShared(Rc<Cell<ModifiersState>>);
|
||||
|
||||
impl ModifiersShared {
|
||||
fn set(&self, new: ModifiersState) {
|
||||
self.0.set(new)
|
||||
}
|
||||
|
||||
fn get(&self) -> ModifiersState {
|
||||
self.0.get()
|
||||
}
|
||||
}
|
||||
|
||||
impl Clone for ModifiersShared {
|
||||
fn clone(&self) -> Self {
|
||||
Self(Rc::clone(&self.0))
|
||||
}
|
||||
}
|
||||
|
||||
pub struct EventLoopWindowTarget<T: 'static> {
|
||||
pub(crate) runner: runner::Shared<T>,
|
||||
modifiers: ModifiersShared,
|
||||
}
|
||||
|
||||
impl<T> Clone for EventLoopWindowTarget<T> {
|
||||
fn clone(&self) -> Self {
|
||||
Self {
|
||||
runner: self.runner.clone(),
|
||||
modifiers: self.modifiers.clone(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -32,6 +59,7 @@ impl<T> EventLoopWindowTarget<T> {
|
|||
pub fn new() -> Self {
|
||||
Self {
|
||||
runner: runner::Shared::new(),
|
||||
modifiers: ModifiersShared::default(),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -56,7 +84,7 @@ impl<T> EventLoopWindowTarget<T> {
|
|||
canvas: &Rc<RefCell<backend::Canvas>>,
|
||||
id: WindowId,
|
||||
prevent_default: bool,
|
||||
has_focus: Rc<RefCell<bool>>,
|
||||
has_focus: Rc<Cell<bool>>,
|
||||
) {
|
||||
self.runner.add_canvas(RootWindowId(id), canvas);
|
||||
let mut canvas = canvas.borrow_mut();
|
||||
|
|
@ -67,115 +95,185 @@ impl<T> EventLoopWindowTarget<T> {
|
|||
|
||||
let runner = self.runner.clone();
|
||||
let has_focus_clone = has_focus.clone();
|
||||
let modifiers = self.modifiers.clone();
|
||||
canvas.on_blur(move || {
|
||||
*has_focus_clone.borrow_mut() = false;
|
||||
runner.send_event(Event::WindowEvent {
|
||||
window_id: RootWindowId(id),
|
||||
event: WindowEvent::Focused(false),
|
||||
has_focus_clone.set(false);
|
||||
|
||||
let clear_modifiers = (!modifiers.get().is_empty()).then(|| {
|
||||
modifiers.set(ModifiersState::empty());
|
||||
Event::WindowEvent {
|
||||
window_id: RootWindowId(id),
|
||||
event: WindowEvent::ModifiersChanged(ModifiersState::empty().into()),
|
||||
}
|
||||
});
|
||||
|
||||
runner.send_events(
|
||||
clear_modifiers
|
||||
.into_iter()
|
||||
.chain(iter::once(Event::WindowEvent {
|
||||
window_id: RootWindowId(id),
|
||||
event: WindowEvent::Focused(false),
|
||||
})),
|
||||
);
|
||||
});
|
||||
|
||||
let runner = self.runner.clone();
|
||||
let has_focus_clone = has_focus.clone();
|
||||
canvas.on_focus(move || {
|
||||
*has_focus_clone.borrow_mut() = true;
|
||||
runner.send_event(Event::WindowEvent {
|
||||
window_id: RootWindowId(id),
|
||||
event: WindowEvent::Focused(true),
|
||||
});
|
||||
if !has_focus_clone.replace(true) {
|
||||
runner.send_event(Event::WindowEvent {
|
||||
window_id: RootWindowId(id),
|
||||
event: WindowEvent::Focused(true),
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
let runner = self.runner.clone();
|
||||
let modifiers = self.modifiers.clone();
|
||||
canvas.on_keyboard_press(
|
||||
move |scancode, virtual_keycode, modifiers| {
|
||||
#[allow(deprecated)]
|
||||
runner.send_event(Event::WindowEvent {
|
||||
window_id: RootWindowId(id),
|
||||
event: WindowEvent::KeyboardInput {
|
||||
device_id: RootDeviceId(unsafe { DeviceId::dummy() }),
|
||||
input: KeyboardInput {
|
||||
scancode,
|
||||
state: ElementState::Pressed,
|
||||
virtual_keycode,
|
||||
modifiers,
|
||||
},
|
||||
is_synthetic: false,
|
||||
},
|
||||
move |physical_key, logical_key, text, location, repeat, active_modifiers| {
|
||||
let modifiers_changed = (modifiers.get() != active_modifiers).then(|| {
|
||||
modifiers.set(active_modifiers);
|
||||
Event::WindowEvent {
|
||||
window_id: RootWindowId(id),
|
||||
event: WindowEvent::ModifiersChanged(active_modifiers.into()),
|
||||
}
|
||||
});
|
||||
|
||||
runner.send_events(
|
||||
iter::once(Event::WindowEvent {
|
||||
window_id: RootWindowId(id),
|
||||
event: WindowEvent::KeyboardInput {
|
||||
device_id: RootDeviceId(unsafe { DeviceId::dummy() }),
|
||||
event: KeyEvent {
|
||||
physical_key,
|
||||
logical_key,
|
||||
text,
|
||||
location,
|
||||
state: ElementState::Pressed,
|
||||
repeat,
|
||||
platform_specific: KeyEventExtra,
|
||||
},
|
||||
is_synthetic: false,
|
||||
},
|
||||
})
|
||||
.chain(modifiers_changed),
|
||||
);
|
||||
},
|
||||
prevent_default,
|
||||
);
|
||||
|
||||
let runner = self.runner.clone();
|
||||
let modifiers = self.modifiers.clone();
|
||||
canvas.on_keyboard_release(
|
||||
move |scancode, virtual_keycode, modifiers| {
|
||||
#[allow(deprecated)]
|
||||
runner.send_event(Event::WindowEvent {
|
||||
window_id: RootWindowId(id),
|
||||
event: WindowEvent::KeyboardInput {
|
||||
device_id: RootDeviceId(unsafe { DeviceId::dummy() }),
|
||||
input: KeyboardInput {
|
||||
scancode,
|
||||
state: ElementState::Released,
|
||||
virtual_keycode,
|
||||
modifiers,
|
||||
move |physical_key, logical_key, text, location, repeat, active_modifiers| {
|
||||
let modifiers_changed = (modifiers.get() != active_modifiers).then(|| {
|
||||
modifiers.set(active_modifiers);
|
||||
Event::WindowEvent {
|
||||
window_id: RootWindowId(id),
|
||||
event: WindowEvent::ModifiersChanged(active_modifiers.into()),
|
||||
}
|
||||
});
|
||||
|
||||
runner.send_events(
|
||||
iter::once(Event::WindowEvent {
|
||||
window_id: RootWindowId(id),
|
||||
event: WindowEvent::KeyboardInput {
|
||||
device_id: RootDeviceId(unsafe { DeviceId::dummy() }),
|
||||
event: KeyEvent {
|
||||
physical_key,
|
||||
logical_key,
|
||||
text,
|
||||
location,
|
||||
state: ElementState::Released,
|
||||
repeat,
|
||||
platform_specific: KeyEventExtra,
|
||||
},
|
||||
is_synthetic: false,
|
||||
},
|
||||
is_synthetic: false,
|
||||
},
|
||||
});
|
||||
})
|
||||
.chain(modifiers_changed),
|
||||
)
|
||||
},
|
||||
prevent_default,
|
||||
);
|
||||
|
||||
let runner = self.runner.clone();
|
||||
canvas.on_received_character(
|
||||
move |char_code| {
|
||||
runner.send_event(Event::WindowEvent {
|
||||
let modifiers = self.modifiers.clone();
|
||||
let has_focus_clone = has_focus.clone();
|
||||
canvas.on_cursor_leave(move |pointer_id, active_modifiers| {
|
||||
let modifiers_changed = (has_focus_clone.get() && modifiers.get() != active_modifiers)
|
||||
.then(|| {
|
||||
modifiers.set(active_modifiers);
|
||||
Event::WindowEvent {
|
||||
window_id: RootWindowId(id),
|
||||
event: WindowEvent::ModifiersChanged(active_modifiers.into()),
|
||||
}
|
||||
});
|
||||
|
||||
runner.send_events(modifiers_changed.into_iter().chain(iter::once(
|
||||
Event::WindowEvent {
|
||||
window_id: RootWindowId(id),
|
||||
event: WindowEvent::ReceivedCharacter(char_code),
|
||||
});
|
||||
},
|
||||
prevent_default,
|
||||
);
|
||||
|
||||
let runner = self.runner.clone();
|
||||
canvas.on_cursor_leave(move |pointer_id| {
|
||||
runner.send_event(Event::WindowEvent {
|
||||
window_id: RootWindowId(id),
|
||||
event: WindowEvent::CursorLeft {
|
||||
device_id: RootDeviceId(DeviceId(pointer_id)),
|
||||
event: WindowEvent::CursorLeft {
|
||||
device_id: RootDeviceId(DeviceId(pointer_id)),
|
||||
},
|
||||
},
|
||||
});
|
||||
)));
|
||||
});
|
||||
|
||||
let runner = self.runner.clone();
|
||||
canvas.on_cursor_enter(move |pointer_id| {
|
||||
runner.send_event(Event::WindowEvent {
|
||||
window_id: RootWindowId(id),
|
||||
event: WindowEvent::CursorEntered {
|
||||
device_id: RootDeviceId(DeviceId(pointer_id)),
|
||||
let modifiers = self.modifiers.clone();
|
||||
let has_focus_clone = has_focus.clone();
|
||||
canvas.on_cursor_enter(move |pointer_id, active_modifiers| {
|
||||
let modifiers_changed = (has_focus_clone.get() && modifiers.get() != active_modifiers)
|
||||
.then(|| {
|
||||
modifiers.set(active_modifiers);
|
||||
Event::WindowEvent {
|
||||
window_id: RootWindowId(id),
|
||||
event: WindowEvent::ModifiersChanged(active_modifiers.into()),
|
||||
}
|
||||
});
|
||||
|
||||
runner.send_events(modifiers_changed.into_iter().chain(iter::once(
|
||||
Event::WindowEvent {
|
||||
window_id: RootWindowId(id),
|
||||
event: WindowEvent::CursorEntered {
|
||||
device_id: RootDeviceId(DeviceId(pointer_id)),
|
||||
},
|
||||
},
|
||||
});
|
||||
)));
|
||||
});
|
||||
|
||||
let runner = self.runner.clone();
|
||||
let runner_touch = self.runner.clone();
|
||||
let modifiers = self.modifiers.clone();
|
||||
let has_focus_clone = has_focus.clone();
|
||||
canvas.on_cursor_move(
|
||||
move |pointer_id, position, delta, modifiers| {
|
||||
runner.send_event(Event::WindowEvent {
|
||||
window_id: RootWindowId(id),
|
||||
event: WindowEvent::CursorMoved {
|
||||
move |pointer_id, position, delta, active_modifiers| {
|
||||
let modifiers_changed =
|
||||
(has_focus_clone.get() && modifiers.get() != active_modifiers).then(|| {
|
||||
modifiers.set(active_modifiers);
|
||||
Event::WindowEvent {
|
||||
window_id: RootWindowId(id),
|
||||
event: WindowEvent::ModifiersChanged(active_modifiers.into()),
|
||||
}
|
||||
});
|
||||
|
||||
runner.send_events(modifiers_changed.into_iter().chain([
|
||||
Event::WindowEvent {
|
||||
window_id: RootWindowId(id),
|
||||
event: WindowEvent::CursorMoved {
|
||||
device_id: RootDeviceId(DeviceId(pointer_id)),
|
||||
position,
|
||||
},
|
||||
},
|
||||
Event::DeviceEvent {
|
||||
device_id: RootDeviceId(DeviceId(pointer_id)),
|
||||
position,
|
||||
modifiers,
|
||||
event: DeviceEvent::MouseMotion {
|
||||
delta: (delta.x, delta.y),
|
||||
},
|
||||
},
|
||||
});
|
||||
runner.send_event(Event::DeviceEvent {
|
||||
device_id: RootDeviceId(DeviceId(pointer_id)),
|
||||
event: DeviceEvent::MouseMotion {
|
||||
delta: (delta.x, delta.y),
|
||||
},
|
||||
});
|
||||
]));
|
||||
},
|
||||
move |device_id, location, force| {
|
||||
runner_touch.send_event(Event::WindowEvent {
|
||||
|
|
@ -194,36 +292,44 @@ impl<T> EventLoopWindowTarget<T> {
|
|||
|
||||
let runner = self.runner.clone();
|
||||
let runner_touch = self.runner.clone();
|
||||
let modifiers = self.modifiers.clone();
|
||||
let has_focus_clone = has_focus.clone();
|
||||
canvas.on_mouse_press(
|
||||
move |pointer_id, position, button, modifiers| {
|
||||
*has_focus.borrow_mut() = true;
|
||||
move |pointer_id, position, button, active_modifiers| {
|
||||
let focus_changed =
|
||||
(!has_focus_clone.replace(true)).then_some(Event::WindowEvent {
|
||||
window_id: RootWindowId(id),
|
||||
event: WindowEvent::Focused(true),
|
||||
});
|
||||
|
||||
let modifiers_changed = (modifiers.get() != active_modifiers).then(|| {
|
||||
modifiers.set(active_modifiers);
|
||||
Event::WindowEvent {
|
||||
window_id: RootWindowId(id),
|
||||
event: WindowEvent::ModifiersChanged(active_modifiers.into()),
|
||||
}
|
||||
});
|
||||
|
||||
// A mouse down event may come in without any prior CursorMoved events,
|
||||
// therefore we should send a CursorMoved event to make sure that the
|
||||
// user code has the correct cursor position.
|
||||
runner.send_events(
|
||||
std::iter::once(Event::WindowEvent {
|
||||
window_id: RootWindowId(id),
|
||||
event: WindowEvent::Focused(true),
|
||||
})
|
||||
.chain(std::iter::once(Event::WindowEvent {
|
||||
runner.send_events(focus_changed.into_iter().chain(modifiers_changed).chain([
|
||||
Event::WindowEvent {
|
||||
window_id: RootWindowId(id),
|
||||
event: WindowEvent::CursorMoved {
|
||||
device_id: RootDeviceId(DeviceId(pointer_id)),
|
||||
position,
|
||||
modifiers,
|
||||
},
|
||||
}))
|
||||
.chain(std::iter::once(Event::WindowEvent {
|
||||
},
|
||||
Event::WindowEvent {
|
||||
window_id: RootWindowId(id),
|
||||
event: WindowEvent::MouseInput {
|
||||
device_id: RootDeviceId(DeviceId(pointer_id)),
|
||||
state: ElementState::Pressed,
|
||||
button,
|
||||
modifiers,
|
||||
},
|
||||
})),
|
||||
);
|
||||
},
|
||||
]));
|
||||
},
|
||||
move |device_id, location, force| {
|
||||
runner_touch.send_event(Event::WindowEvent {
|
||||
|
|
@ -241,17 +347,29 @@ impl<T> EventLoopWindowTarget<T> {
|
|||
|
||||
let runner = self.runner.clone();
|
||||
let runner_touch = self.runner.clone();
|
||||
let modifiers = self.modifiers.clone();
|
||||
let has_focus_clone = has_focus.clone();
|
||||
canvas.on_mouse_release(
|
||||
move |pointer_id, button, modifiers| {
|
||||
runner.send_event(Event::WindowEvent {
|
||||
window_id: RootWindowId(id),
|
||||
event: WindowEvent::MouseInput {
|
||||
device_id: RootDeviceId(DeviceId(pointer_id)),
|
||||
state: ElementState::Released,
|
||||
button,
|
||||
modifiers,
|
||||
move |pointer_id, button, active_modifiers| {
|
||||
let modifiers_changed =
|
||||
(has_focus_clone.get() && modifiers.get() != active_modifiers).then(|| {
|
||||
modifiers.set(active_modifiers);
|
||||
Event::WindowEvent {
|
||||
window_id: RootWindowId(id),
|
||||
event: WindowEvent::ModifiersChanged(active_modifiers.into()),
|
||||
}
|
||||
});
|
||||
|
||||
runner.send_events(modifiers_changed.into_iter().chain(iter::once(
|
||||
Event::WindowEvent {
|
||||
window_id: RootWindowId(id),
|
||||
event: WindowEvent::MouseInput {
|
||||
device_id: RootDeviceId(DeviceId(pointer_id)),
|
||||
state: ElementState::Released,
|
||||
button,
|
||||
},
|
||||
},
|
||||
});
|
||||
)));
|
||||
},
|
||||
move |device_id, location, force| {
|
||||
runner_touch.send_event(Event::WindowEvent {
|
||||
|
|
@ -268,17 +386,28 @@ impl<T> EventLoopWindowTarget<T> {
|
|||
);
|
||||
|
||||
let runner = self.runner.clone();
|
||||
let modifiers = self.modifiers.clone();
|
||||
canvas.on_mouse_wheel(
|
||||
move |pointer_id, delta, modifiers| {
|
||||
runner.send_event(Event::WindowEvent {
|
||||
window_id: RootWindowId(id),
|
||||
event: WindowEvent::MouseWheel {
|
||||
device_id: RootDeviceId(DeviceId(pointer_id)),
|
||||
delta,
|
||||
phase: TouchPhase::Moved,
|
||||
modifiers,
|
||||
move |pointer_id, delta, active_modifiers| {
|
||||
let modifiers_changed = (has_focus.get() && modifiers.get() != active_modifiers)
|
||||
.then(|| {
|
||||
modifiers.set(active_modifiers);
|
||||
Event::WindowEvent {
|
||||
window_id: RootWindowId(id),
|
||||
event: WindowEvent::ModifiersChanged(active_modifiers.into()),
|
||||
}
|
||||
});
|
||||
|
||||
runner.send_events(modifiers_changed.into_iter().chain(iter::once(
|
||||
Event::WindowEvent {
|
||||
window_id: RootWindowId(id),
|
||||
event: WindowEvent::MouseWheel {
|
||||
device_id: RootDeviceId(DeviceId(pointer_id)),
|
||||
delta,
|
||||
phase: TouchPhase::Moved,
|
||||
},
|
||||
},
|
||||
});
|
||||
)));
|
||||
},
|
||||
prevent_default,
|
||||
);
|
||||
|
|
|
|||
522
src/platform_impl/web/keyboard.rs
Normal file
522
src/platform_impl/web/keyboard.rs
Normal file
|
|
@ -0,0 +1,522 @@
|
|||
use smol_str::SmolStr;
|
||||
|
||||
use crate::keyboard::{Key, KeyCode, NativeKey, NativeKeyCode};
|
||||
|
||||
#[derive(Debug, Clone, Eq, PartialEq, Hash)]
|
||||
pub(crate) struct KeyEventExtra;
|
||||
|
||||
impl Key {
|
||||
pub(crate) fn from_key_attribute_value(kav: &str) -> Self {
|
||||
match kav {
|
||||
"Unidentified" => Key::Unidentified(NativeKey::Web(SmolStr::new(kav))),
|
||||
"Dead" => Key::Dead(None),
|
||||
"Alt" => Key::Alt,
|
||||
"AltGraph" => Key::AltGraph,
|
||||
"CapsLock" => Key::CapsLock,
|
||||
"Control" => Key::Control,
|
||||
"Fn" => Key::Fn,
|
||||
"FnLock" => Key::FnLock,
|
||||
"NumLock" => Key::NumLock,
|
||||
"ScrollLock" => Key::ScrollLock,
|
||||
"Shift" => Key::Shift,
|
||||
"Symbol" => Key::Symbol,
|
||||
"SymbolLock" => Key::SymbolLock,
|
||||
"Hyper" => Key::Hyper,
|
||||
"Meta" => Key::Super,
|
||||
"Enter" => Key::Enter,
|
||||
"Tab" => Key::Tab,
|
||||
" " => Key::Space,
|
||||
"ArrowDown" => Key::ArrowDown,
|
||||
"ArrowLeft" => Key::ArrowLeft,
|
||||
"ArrowRight" => Key::ArrowRight,
|
||||
"ArrowUp" => Key::ArrowUp,
|
||||
"End" => Key::End,
|
||||
"Home" => Key::Home,
|
||||
"PageDown" => Key::PageDown,
|
||||
"PageUp" => Key::PageUp,
|
||||
"Backspace" => Key::Backspace,
|
||||
"Clear" => Key::Clear,
|
||||
"Copy" => Key::Copy,
|
||||
"CrSel" => Key::CrSel,
|
||||
"Cut" => Key::Cut,
|
||||
"Delete" => Key::Delete,
|
||||
"EraseEof" => Key::EraseEof,
|
||||
"ExSel" => Key::ExSel,
|
||||
"Insert" => Key::Insert,
|
||||
"Paste" => Key::Paste,
|
||||
"Redo" => Key::Redo,
|
||||
"Undo" => Key::Undo,
|
||||
"Accept" => Key::Accept,
|
||||
"Again" => Key::Again,
|
||||
"Attn" => Key::Attn,
|
||||
"Cancel" => Key::Cancel,
|
||||
"ContextMenu" => Key::ContextMenu,
|
||||
"Escape" => Key::Escape,
|
||||
"Execute" => Key::Execute,
|
||||
"Find" => Key::Find,
|
||||
"Help" => Key::Help,
|
||||
"Pause" => Key::Pause,
|
||||
"Play" => Key::Play,
|
||||
"Props" => Key::Props,
|
||||
"Select" => Key::Select,
|
||||
"ZoomIn" => Key::ZoomIn,
|
||||
"ZoomOut" => Key::ZoomOut,
|
||||
"BrightnessDown" => Key::BrightnessDown,
|
||||
"BrightnessUp" => Key::BrightnessUp,
|
||||
"Eject" => Key::Eject,
|
||||
"LogOff" => Key::LogOff,
|
||||
"Power" => Key::Power,
|
||||
"PowerOff" => Key::PowerOff,
|
||||
"PrintScreen" => Key::PrintScreen,
|
||||
"Hibernate" => Key::Hibernate,
|
||||
"Standby" => Key::Standby,
|
||||
"WakeUp" => Key::WakeUp,
|
||||
"AllCandidates" => Key::AllCandidates,
|
||||
"Alphanumeric" => Key::Alphanumeric,
|
||||
"CodeInput" => Key::CodeInput,
|
||||
"Compose" => Key::Compose,
|
||||
"Convert" => Key::Convert,
|
||||
"FinalMode" => Key::FinalMode,
|
||||
"GroupFirst" => Key::GroupFirst,
|
||||
"GroupLast" => Key::GroupLast,
|
||||
"GroupNext" => Key::GroupNext,
|
||||
"GroupPrevious" => Key::GroupPrevious,
|
||||
"ModeChange" => Key::ModeChange,
|
||||
"NextCandidate" => Key::NextCandidate,
|
||||
"NonConvert" => Key::NonConvert,
|
||||
"PreviousCandidate" => Key::PreviousCandidate,
|
||||
"Process" => Key::Process,
|
||||
"SingleCandidate" => Key::SingleCandidate,
|
||||
"HangulMode" => Key::HangulMode,
|
||||
"HanjaMode" => Key::HanjaMode,
|
||||
"JunjaMode" => Key::JunjaMode,
|
||||
"Eisu" => Key::Eisu,
|
||||
"Hankaku" => Key::Hankaku,
|
||||
"Hiragana" => Key::Hiragana,
|
||||
"HiraganaKatakana" => Key::HiraganaKatakana,
|
||||
"KanaMode" => Key::KanaMode,
|
||||
"KanjiMode" => Key::KanjiMode,
|
||||
"Katakana" => Key::Katakana,
|
||||
"Romaji" => Key::Romaji,
|
||||
"Zenkaku" => Key::Zenkaku,
|
||||
"ZenkakuHankaku" => Key::ZenkakuHankaku,
|
||||
"Soft1" => Key::Soft1,
|
||||
"Soft2" => Key::Soft2,
|
||||
"Soft3" => Key::Soft3,
|
||||
"Soft4" => Key::Soft4,
|
||||
"ChannelDown" => Key::ChannelDown,
|
||||
"ChannelUp" => Key::ChannelUp,
|
||||
"Close" => Key::Close,
|
||||
"MailForward" => Key::MailForward,
|
||||
"MailReply" => Key::MailReply,
|
||||
"MailSend" => Key::MailSend,
|
||||
"MediaClose" => Key::MediaClose,
|
||||
"MediaFastForward" => Key::MediaFastForward,
|
||||
"MediaPause" => Key::MediaPause,
|
||||
"MediaPlay" => Key::MediaPlay,
|
||||
"MediaPlayPause" => Key::MediaPlayPause,
|
||||
"MediaRecord" => Key::MediaRecord,
|
||||
"MediaRewind" => Key::MediaRewind,
|
||||
"MediaStop" => Key::MediaStop,
|
||||
"MediaTrackNext" => Key::MediaTrackNext,
|
||||
"MediaTrackPrevious" => Key::MediaTrackPrevious,
|
||||
"New" => Key::New,
|
||||
"Open" => Key::Open,
|
||||
"Print" => Key::Print,
|
||||
"Save" => Key::Save,
|
||||
"SpellCheck" => Key::SpellCheck,
|
||||
"Key11" => Key::Key11,
|
||||
"Key12" => Key::Key12,
|
||||
"AudioBalanceLeft" => Key::AudioBalanceLeft,
|
||||
"AudioBalanceRight" => Key::AudioBalanceRight,
|
||||
"AudioBassBoostDown" => Key::AudioBassBoostDown,
|
||||
"AudioBassBoostToggle" => Key::AudioBassBoostToggle,
|
||||
"AudioBassBoostUp" => Key::AudioBassBoostUp,
|
||||
"AudioFaderFront" => Key::AudioFaderFront,
|
||||
"AudioFaderRear" => Key::AudioFaderRear,
|
||||
"AudioSurroundModeNext" => Key::AudioSurroundModeNext,
|
||||
"AudioTrebleDown" => Key::AudioTrebleDown,
|
||||
"AudioTrebleUp" => Key::AudioTrebleUp,
|
||||
"AudioVolumeDown" => Key::AudioVolumeDown,
|
||||
"AudioVolumeUp" => Key::AudioVolumeUp,
|
||||
"AudioVolumeMute" => Key::AudioVolumeMute,
|
||||
"MicrophoneToggle" => Key::MicrophoneToggle,
|
||||
"MicrophoneVolumeDown" => Key::MicrophoneVolumeDown,
|
||||
"MicrophoneVolumeUp" => Key::MicrophoneVolumeUp,
|
||||
"MicrophoneVolumeMute" => Key::MicrophoneVolumeMute,
|
||||
"SpeechCorrectionList" => Key::SpeechCorrectionList,
|
||||
"SpeechInputToggle" => Key::SpeechInputToggle,
|
||||
"LaunchApplication1" => Key::LaunchApplication1,
|
||||
"LaunchApplication2" => Key::LaunchApplication2,
|
||||
"LaunchCalendar" => Key::LaunchCalendar,
|
||||
"LaunchContacts" => Key::LaunchContacts,
|
||||
"LaunchMail" => Key::LaunchMail,
|
||||
"LaunchMediaPlayer" => Key::LaunchMediaPlayer,
|
||||
"LaunchMusicPlayer" => Key::LaunchMusicPlayer,
|
||||
"LaunchPhone" => Key::LaunchPhone,
|
||||
"LaunchScreenSaver" => Key::LaunchScreenSaver,
|
||||
"LaunchSpreadsheet" => Key::LaunchSpreadsheet,
|
||||
"LaunchWebBrowser" => Key::LaunchWebBrowser,
|
||||
"LaunchWebCam" => Key::LaunchWebCam,
|
||||
"LaunchWordProcessor" => Key::LaunchWordProcessor,
|
||||
"BrowserBack" => Key::BrowserBack,
|
||||
"BrowserFavorites" => Key::BrowserFavorites,
|
||||
"BrowserForward" => Key::BrowserForward,
|
||||
"BrowserHome" => Key::BrowserHome,
|
||||
"BrowserRefresh" => Key::BrowserRefresh,
|
||||
"BrowserSearch" => Key::BrowserSearch,
|
||||
"BrowserStop" => Key::BrowserStop,
|
||||
"AppSwitch" => Key::AppSwitch,
|
||||
"Call" => Key::Call,
|
||||
"Camera" => Key::Camera,
|
||||
"CameraFocus" => Key::CameraFocus,
|
||||
"EndCall" => Key::EndCall,
|
||||
"GoBack" => Key::GoBack,
|
||||
"GoHome" => Key::GoHome,
|
||||
"HeadsetHook" => Key::HeadsetHook,
|
||||
"LastNumberRedial" => Key::LastNumberRedial,
|
||||
"Notification" => Key::Notification,
|
||||
"MannerMode" => Key::MannerMode,
|
||||
"VoiceDial" => Key::VoiceDial,
|
||||
"TV" => Key::TV,
|
||||
"TV3DMode" => Key::TV3DMode,
|
||||
"TVAntennaCable" => Key::TVAntennaCable,
|
||||
"TVAudioDescription" => Key::TVAudioDescription,
|
||||
"TVAudioDescriptionMixDown" => Key::TVAudioDescriptionMixDown,
|
||||
"TVAudioDescriptionMixUp" => Key::TVAudioDescriptionMixUp,
|
||||
"TVContentsMenu" => Key::TVContentsMenu,
|
||||
"TVDataService" => Key::TVDataService,
|
||||
"TVInput" => Key::TVInput,
|
||||
"TVInputComponent1" => Key::TVInputComponent1,
|
||||
"TVInputComponent2" => Key::TVInputComponent2,
|
||||
"TVInputComposite1" => Key::TVInputComposite1,
|
||||
"TVInputComposite2" => Key::TVInputComposite2,
|
||||
"TVInputHDMI1" => Key::TVInputHDMI1,
|
||||
"TVInputHDMI2" => Key::TVInputHDMI2,
|
||||
"TVInputHDMI3" => Key::TVInputHDMI3,
|
||||
"TVInputHDMI4" => Key::TVInputHDMI4,
|
||||
"TVInputVGA1" => Key::TVInputVGA1,
|
||||
"TVMediaContext" => Key::TVMediaContext,
|
||||
"TVNetwork" => Key::TVNetwork,
|
||||
"TVNumberEntry" => Key::TVNumberEntry,
|
||||
"TVPower" => Key::TVPower,
|
||||
"TVRadioService" => Key::TVRadioService,
|
||||
"TVSatellite" => Key::TVSatellite,
|
||||
"TVSatelliteBS" => Key::TVSatelliteBS,
|
||||
"TVSatelliteCS" => Key::TVSatelliteCS,
|
||||
"TVSatelliteToggle" => Key::TVSatelliteToggle,
|
||||
"TVTerrestrialAnalog" => Key::TVTerrestrialAnalog,
|
||||
"TVTerrestrialDigital" => Key::TVTerrestrialDigital,
|
||||
"TVTimer" => Key::TVTimer,
|
||||
"AVRInput" => Key::AVRInput,
|
||||
"AVRPower" => Key::AVRPower,
|
||||
"ColorF0Red" => Key::ColorF0Red,
|
||||
"ColorF1Green" => Key::ColorF1Green,
|
||||
"ColorF2Yellow" => Key::ColorF2Yellow,
|
||||
"ColorF3Blue" => Key::ColorF3Blue,
|
||||
"ColorF4Grey" => Key::ColorF4Grey,
|
||||
"ColorF5Brown" => Key::ColorF5Brown,
|
||||
"ClosedCaptionToggle" => Key::ClosedCaptionToggle,
|
||||
"Dimmer" => Key::Dimmer,
|
||||
"DisplaySwap" => Key::DisplaySwap,
|
||||
"DVR" => Key::DVR,
|
||||
"Exit" => Key::Exit,
|
||||
"FavoriteClear0" => Key::FavoriteClear0,
|
||||
"FavoriteClear1" => Key::FavoriteClear1,
|
||||
"FavoriteClear2" => Key::FavoriteClear2,
|
||||
"FavoriteClear3" => Key::FavoriteClear3,
|
||||
"FavoriteRecall0" => Key::FavoriteRecall0,
|
||||
"FavoriteRecall1" => Key::FavoriteRecall1,
|
||||
"FavoriteRecall2" => Key::FavoriteRecall2,
|
||||
"FavoriteRecall3" => Key::FavoriteRecall3,
|
||||
"FavoriteStore0" => Key::FavoriteStore0,
|
||||
"FavoriteStore1" => Key::FavoriteStore1,
|
||||
"FavoriteStore2" => Key::FavoriteStore2,
|
||||
"FavoriteStore3" => Key::FavoriteStore3,
|
||||
"Guide" => Key::Guide,
|
||||
"GuideNextDay" => Key::GuideNextDay,
|
||||
"GuidePreviousDay" => Key::GuidePreviousDay,
|
||||
"Info" => Key::Info,
|
||||
"InstantReplay" => Key::InstantReplay,
|
||||
"Link" => Key::Link,
|
||||
"ListProgram" => Key::ListProgram,
|
||||
"LiveContent" => Key::LiveContent,
|
||||
"Lock" => Key::Lock,
|
||||
"MediaApps" => Key::MediaApps,
|
||||
"MediaAudioTrack" => Key::MediaAudioTrack,
|
||||
"MediaLast" => Key::MediaLast,
|
||||
"MediaSkipBackward" => Key::MediaSkipBackward,
|
||||
"MediaSkipForward" => Key::MediaSkipForward,
|
||||
"MediaStepBackward" => Key::MediaStepBackward,
|
||||
"MediaStepForward" => Key::MediaStepForward,
|
||||
"MediaTopMenu" => Key::MediaTopMenu,
|
||||
"NavigateIn" => Key::NavigateIn,
|
||||
"NavigateNext" => Key::NavigateNext,
|
||||
"NavigateOut" => Key::NavigateOut,
|
||||
"NavigatePrevious" => Key::NavigatePrevious,
|
||||
"NextFavoriteChannel" => Key::NextFavoriteChannel,
|
||||
"NextUserProfile" => Key::NextUserProfile,
|
||||
"OnDemand" => Key::OnDemand,
|
||||
"Pairing" => Key::Pairing,
|
||||
"PinPDown" => Key::PinPDown,
|
||||
"PinPMove" => Key::PinPMove,
|
||||
"PinPToggle" => Key::PinPToggle,
|
||||
"PinPUp" => Key::PinPUp,
|
||||
"PlaySpeedDown" => Key::PlaySpeedDown,
|
||||
"PlaySpeedReset" => Key::PlaySpeedReset,
|
||||
"PlaySpeedUp" => Key::PlaySpeedUp,
|
||||
"RandomToggle" => Key::RandomToggle,
|
||||
"RcLowBattery" => Key::RcLowBattery,
|
||||
"RecordSpeedNext" => Key::RecordSpeedNext,
|
||||
"RfBypass" => Key::RfBypass,
|
||||
"ScanChannelsToggle" => Key::ScanChannelsToggle,
|
||||
"ScreenModeNext" => Key::ScreenModeNext,
|
||||
"Settings" => Key::Settings,
|
||||
"SplitScreenToggle" => Key::SplitScreenToggle,
|
||||
"STBInput" => Key::STBInput,
|
||||
"STBPower" => Key::STBPower,
|
||||
"Subtitle" => Key::Subtitle,
|
||||
"Teletext" => Key::Teletext,
|
||||
"VideoModeNext" => Key::VideoModeNext,
|
||||
"Wink" => Key::Wink,
|
||||
"ZoomToggle" => Key::ZoomToggle,
|
||||
"F1" => Key::F1,
|
||||
"F2" => Key::F2,
|
||||
"F3" => Key::F3,
|
||||
"F4" => Key::F4,
|
||||
"F5" => Key::F5,
|
||||
"F6" => Key::F6,
|
||||
"F7" => Key::F7,
|
||||
"F8" => Key::F8,
|
||||
"F9" => Key::F9,
|
||||
"F10" => Key::F10,
|
||||
"F11" => Key::F11,
|
||||
"F12" => Key::F12,
|
||||
"F13" => Key::F13,
|
||||
"F14" => Key::F14,
|
||||
"F15" => Key::F15,
|
||||
"F16" => Key::F16,
|
||||
"F17" => Key::F17,
|
||||
"F18" => Key::F18,
|
||||
"F19" => Key::F19,
|
||||
"F20" => Key::F20,
|
||||
"F21" => Key::F21,
|
||||
"F22" => Key::F22,
|
||||
"F23" => Key::F23,
|
||||
"F24" => Key::F24,
|
||||
"F25" => Key::F25,
|
||||
"F26" => Key::F26,
|
||||
"F27" => Key::F27,
|
||||
"F28" => Key::F28,
|
||||
"F29" => Key::F29,
|
||||
"F30" => Key::F30,
|
||||
"F31" => Key::F31,
|
||||
"F32" => Key::F32,
|
||||
"F33" => Key::F33,
|
||||
"F34" => Key::F34,
|
||||
"F35" => Key::F35,
|
||||
string => Key::Character(SmolStr::new(string)),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl KeyCode {
|
||||
pub fn from_key_code_attribute_value(kcav: &str) -> Self {
|
||||
match kcav {
|
||||
"Backquote" => KeyCode::Backquote,
|
||||
"Backslash" => KeyCode::Backslash,
|
||||
"BracketLeft" => KeyCode::BracketLeft,
|
||||
"BracketRight" => KeyCode::BracketRight,
|
||||
"Comma" => KeyCode::Comma,
|
||||
"Digit0" => KeyCode::Digit0,
|
||||
"Digit1" => KeyCode::Digit1,
|
||||
"Digit2" => KeyCode::Digit2,
|
||||
"Digit3" => KeyCode::Digit3,
|
||||
"Digit4" => KeyCode::Digit4,
|
||||
"Digit5" => KeyCode::Digit5,
|
||||
"Digit6" => KeyCode::Digit6,
|
||||
"Digit7" => KeyCode::Digit7,
|
||||
"Digit8" => KeyCode::Digit8,
|
||||
"Digit9" => KeyCode::Digit9,
|
||||
"Equal" => KeyCode::Equal,
|
||||
"IntlBackslash" => KeyCode::IntlBackslash,
|
||||
"IntlRo" => KeyCode::IntlRo,
|
||||
"IntlYen" => KeyCode::IntlYen,
|
||||
"KeyA" => KeyCode::KeyA,
|
||||
"KeyB" => KeyCode::KeyB,
|
||||
"KeyC" => KeyCode::KeyC,
|
||||
"KeyD" => KeyCode::KeyD,
|
||||
"KeyE" => KeyCode::KeyE,
|
||||
"KeyF" => KeyCode::KeyF,
|
||||
"KeyG" => KeyCode::KeyG,
|
||||
"KeyH" => KeyCode::KeyH,
|
||||
"KeyI" => KeyCode::KeyI,
|
||||
"KeyJ" => KeyCode::KeyJ,
|
||||
"KeyK" => KeyCode::KeyK,
|
||||
"KeyL" => KeyCode::KeyL,
|
||||
"KeyM" => KeyCode::KeyM,
|
||||
"KeyN" => KeyCode::KeyN,
|
||||
"KeyO" => KeyCode::KeyO,
|
||||
"KeyP" => KeyCode::KeyP,
|
||||
"KeyQ" => KeyCode::KeyQ,
|
||||
"KeyR" => KeyCode::KeyR,
|
||||
"KeyS" => KeyCode::KeyS,
|
||||
"KeyT" => KeyCode::KeyT,
|
||||
"KeyU" => KeyCode::KeyU,
|
||||
"KeyV" => KeyCode::KeyV,
|
||||
"KeyW" => KeyCode::KeyW,
|
||||
"KeyX" => KeyCode::KeyX,
|
||||
"KeyY" => KeyCode::KeyY,
|
||||
"KeyZ" => KeyCode::KeyZ,
|
||||
"Minus" => KeyCode::Minus,
|
||||
"Period" => KeyCode::Period,
|
||||
"Quote" => KeyCode::Quote,
|
||||
"Semicolon" => KeyCode::Semicolon,
|
||||
"Slash" => KeyCode::Slash,
|
||||
"AltLeft" => KeyCode::AltLeft,
|
||||
"AltRight" => KeyCode::AltRight,
|
||||
"Backspace" => KeyCode::Backspace,
|
||||
"CapsLock" => KeyCode::CapsLock,
|
||||
"ContextMenu" => KeyCode::ContextMenu,
|
||||
"ControlLeft" => KeyCode::ControlLeft,
|
||||
"ControlRight" => KeyCode::ControlRight,
|
||||
"Enter" => KeyCode::Enter,
|
||||
"MetaLeft" => KeyCode::SuperLeft,
|
||||
"MetaRight" => KeyCode::SuperRight,
|
||||
"ShiftLeft" => KeyCode::ShiftLeft,
|
||||
"ShiftRight" => KeyCode::ShiftRight,
|
||||
"Space" => KeyCode::Space,
|
||||
"Tab" => KeyCode::Tab,
|
||||
"Convert" => KeyCode::Convert,
|
||||
"KanaMode" => KeyCode::KanaMode,
|
||||
"Lang1" => KeyCode::Lang1,
|
||||
"Lang2" => KeyCode::Lang2,
|
||||
"Lang3" => KeyCode::Lang3,
|
||||
"Lang4" => KeyCode::Lang4,
|
||||
"Lang5" => KeyCode::Lang5,
|
||||
"NonConvert" => KeyCode::NonConvert,
|
||||
"Delete" => KeyCode::Delete,
|
||||
"End" => KeyCode::End,
|
||||
"Help" => KeyCode::Help,
|
||||
"Home" => KeyCode::Home,
|
||||
"Insert" => KeyCode::Insert,
|
||||
"PageDown" => KeyCode::PageDown,
|
||||
"PageUp" => KeyCode::PageUp,
|
||||
"ArrowDown" => KeyCode::ArrowDown,
|
||||
"ArrowLeft" => KeyCode::ArrowLeft,
|
||||
"ArrowRight" => KeyCode::ArrowRight,
|
||||
"ArrowUp" => KeyCode::ArrowUp,
|
||||
"NumLock" => KeyCode::NumLock,
|
||||
"Numpad0" => KeyCode::Numpad0,
|
||||
"Numpad1" => KeyCode::Numpad1,
|
||||
"Numpad2" => KeyCode::Numpad2,
|
||||
"Numpad3" => KeyCode::Numpad3,
|
||||
"Numpad4" => KeyCode::Numpad4,
|
||||
"Numpad5" => KeyCode::Numpad5,
|
||||
"Numpad6" => KeyCode::Numpad6,
|
||||
"Numpad7" => KeyCode::Numpad7,
|
||||
"Numpad8" => KeyCode::Numpad8,
|
||||
"Numpad9" => KeyCode::Numpad9,
|
||||
"NumpadAdd" => KeyCode::NumpadAdd,
|
||||
"NumpadBackspace" => KeyCode::NumpadBackspace,
|
||||
"NumpadClear" => KeyCode::NumpadClear,
|
||||
"NumpadClearEntry" => KeyCode::NumpadClearEntry,
|
||||
"NumpadComma" => KeyCode::NumpadComma,
|
||||
"NumpadDecimal" => KeyCode::NumpadDecimal,
|
||||
"NumpadDivide" => KeyCode::NumpadDivide,
|
||||
"NumpadEnter" => KeyCode::NumpadEnter,
|
||||
"NumpadEqual" => KeyCode::NumpadEqual,
|
||||
"NumpadHash" => KeyCode::NumpadHash,
|
||||
"NumpadMemoryAdd" => KeyCode::NumpadMemoryAdd,
|
||||
"NumpadMemoryClear" => KeyCode::NumpadMemoryClear,
|
||||
"NumpadMemoryRecall" => KeyCode::NumpadMemoryRecall,
|
||||
"NumpadMemoryStore" => KeyCode::NumpadMemoryStore,
|
||||
"NumpadMemorySubtract" => KeyCode::NumpadMemorySubtract,
|
||||
"NumpadMultiply" => KeyCode::NumpadMultiply,
|
||||
"NumpadParenLeft" => KeyCode::NumpadParenLeft,
|
||||
"NumpadParenRight" => KeyCode::NumpadParenRight,
|
||||
"NumpadStar" => KeyCode::NumpadStar,
|
||||
"NumpadSubtract" => KeyCode::NumpadSubtract,
|
||||
"Escape" => KeyCode::Escape,
|
||||
"Fn" => KeyCode::Fn,
|
||||
"FnLock" => KeyCode::FnLock,
|
||||
"PrintScreen" => KeyCode::PrintScreen,
|
||||
"ScrollLock" => KeyCode::ScrollLock,
|
||||
"Pause" => KeyCode::Pause,
|
||||
"BrowserBack" => KeyCode::BrowserBack,
|
||||
"BrowserFavorites" => KeyCode::BrowserFavorites,
|
||||
"BrowserForward" => KeyCode::BrowserForward,
|
||||
"BrowserHome" => KeyCode::BrowserHome,
|
||||
"BrowserRefresh" => KeyCode::BrowserRefresh,
|
||||
"BrowserSearch" => KeyCode::BrowserSearch,
|
||||
"BrowserStop" => KeyCode::BrowserStop,
|
||||
"Eject" => KeyCode::Eject,
|
||||
"LaunchApp1" => KeyCode::LaunchApp1,
|
||||
"LaunchApp2" => KeyCode::LaunchApp2,
|
||||
"LaunchMail" => KeyCode::LaunchMail,
|
||||
"MediaPlayPause" => KeyCode::MediaPlayPause,
|
||||
"MediaSelect" => KeyCode::MediaSelect,
|
||||
"MediaStop" => KeyCode::MediaStop,
|
||||
"MediaTrackNext" => KeyCode::MediaTrackNext,
|
||||
"MediaTrackPrevious" => KeyCode::MediaTrackPrevious,
|
||||
"Power" => KeyCode::Power,
|
||||
"Sleep" => KeyCode::Sleep,
|
||||
"AudioVolumeDown" => KeyCode::AudioVolumeDown,
|
||||
"AudioVolumeMute" => KeyCode::AudioVolumeMute,
|
||||
"AudioVolumeUp" => KeyCode::AudioVolumeUp,
|
||||
"WakeUp" => KeyCode::WakeUp,
|
||||
"Hyper" => KeyCode::Hyper,
|
||||
"Turbo" => KeyCode::Turbo,
|
||||
"Abort" => KeyCode::Abort,
|
||||
"Resume" => KeyCode::Resume,
|
||||
"Suspend" => KeyCode::Suspend,
|
||||
"Again" => KeyCode::Again,
|
||||
"Copy" => KeyCode::Copy,
|
||||
"Cut" => KeyCode::Cut,
|
||||
"Find" => KeyCode::Find,
|
||||
"Open" => KeyCode::Open,
|
||||
"Paste" => KeyCode::Paste,
|
||||
"Props" => KeyCode::Props,
|
||||
"Select" => KeyCode::Select,
|
||||
"Undo" => KeyCode::Undo,
|
||||
"Hiragana" => KeyCode::Hiragana,
|
||||
"Katakana" => KeyCode::Katakana,
|
||||
"F1" => KeyCode::F1,
|
||||
"F2" => KeyCode::F2,
|
||||
"F3" => KeyCode::F3,
|
||||
"F4" => KeyCode::F4,
|
||||
"F5" => KeyCode::F5,
|
||||
"F6" => KeyCode::F6,
|
||||
"F7" => KeyCode::F7,
|
||||
"F8" => KeyCode::F8,
|
||||
"F9" => KeyCode::F9,
|
||||
"F10" => KeyCode::F10,
|
||||
"F11" => KeyCode::F11,
|
||||
"F12" => KeyCode::F12,
|
||||
"F13" => KeyCode::F13,
|
||||
"F14" => KeyCode::F14,
|
||||
"F15" => KeyCode::F15,
|
||||
"F16" => KeyCode::F16,
|
||||
"F17" => KeyCode::F17,
|
||||
"F18" => KeyCode::F18,
|
||||
"F19" => KeyCode::F19,
|
||||
"F20" => KeyCode::F20,
|
||||
"F21" => KeyCode::F21,
|
||||
"F22" => KeyCode::F22,
|
||||
"F23" => KeyCode::F23,
|
||||
"F24" => KeyCode::F24,
|
||||
"F25" => KeyCode::F25,
|
||||
"F26" => KeyCode::F26,
|
||||
"F27" => KeyCode::F27,
|
||||
"F28" => KeyCode::F28,
|
||||
"F29" => KeyCode::F29,
|
||||
"F30" => KeyCode::F30,
|
||||
"F31" => KeyCode::F31,
|
||||
"F32" => KeyCode::F32,
|
||||
"F33" => KeyCode::F33,
|
||||
"F34" => KeyCode::F34,
|
||||
"F35" => KeyCode::F35,
|
||||
_ => KeyCode::Unidentified(NativeKeyCode::Unidentified),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -20,6 +20,7 @@
|
|||
mod device;
|
||||
mod error;
|
||||
mod event_loop;
|
||||
mod keyboard;
|
||||
mod monitor;
|
||||
mod window;
|
||||
|
||||
|
|
@ -34,6 +35,7 @@ pub(crate) use self::event_loop::{
|
|||
pub use self::monitor::{MonitorHandle, VideoMode};
|
||||
pub use self::window::{PlatformSpecificWindowBuilderAttributes, Window, WindowId};
|
||||
|
||||
pub(crate) use self::keyboard::KeyEventExtra;
|
||||
pub(crate) use crate::icon::NoIcon as PlatformIcon;
|
||||
pub(self) use crate::platform_impl::Fullscreen;
|
||||
|
||||
|
|
|
|||
|
|
@ -3,14 +3,14 @@ use super::event_handle::EventListenerHandle;
|
|||
use super::media_query_handle::MediaQueryListHandle;
|
||||
use crate::dpi::{LogicalPosition, PhysicalPosition, PhysicalSize};
|
||||
use crate::error::OsError as RootOE;
|
||||
use crate::event::{
|
||||
Force, ModifiersState, MouseButton, MouseScrollDelta, ScanCode, VirtualKeyCode,
|
||||
};
|
||||
use crate::event::{Force, MouseButton, MouseScrollDelta};
|
||||
use crate::keyboard::{Key, KeyCode, KeyLocation, ModifiersState};
|
||||
use crate::platform_impl::{OsError, PlatformSpecificWindowBuilderAttributes};
|
||||
|
||||
use std::cell::RefCell;
|
||||
use std::rc::Rc;
|
||||
|
||||
use smol_str::SmolStr;
|
||||
use wasm_bindgen::{closure::Closure, JsCast};
|
||||
use web_sys::{
|
||||
AddEventListenerOptions, Event, FocusEvent, HtmlCanvasElement, KeyboardEvent,
|
||||
|
|
@ -29,7 +29,6 @@ pub struct Canvas {
|
|||
on_blur: Option<EventListenerHandle<dyn FnMut(FocusEvent)>>,
|
||||
on_keyboard_release: Option<EventListenerHandle<dyn FnMut(KeyboardEvent)>>,
|
||||
on_keyboard_press: Option<EventListenerHandle<dyn FnMut(KeyboardEvent)>>,
|
||||
on_received_character: Option<EventListenerHandle<dyn FnMut(KeyboardEvent)>>,
|
||||
on_mouse_wheel: Option<EventListenerHandle<dyn FnMut(WheelEvent)>>,
|
||||
on_fullscreen_change: Option<EventListenerHandle<dyn FnMut(Event)>>,
|
||||
on_dark_mode: Option<MediaQueryListHandle>,
|
||||
|
|
@ -89,7 +88,6 @@ impl Canvas {
|
|||
on_focus: None,
|
||||
on_keyboard_release: None,
|
||||
on_keyboard_press: None,
|
||||
on_received_character: None,
|
||||
on_mouse_wheel: None,
|
||||
on_fullscreen_change: None,
|
||||
on_dark_mode: None,
|
||||
|
|
@ -174,7 +172,7 @@ impl Canvas {
|
|||
|
||||
pub fn on_keyboard_release<F>(&mut self, mut handler: F, prevent_default: bool)
|
||||
where
|
||||
F: 'static + FnMut(ScanCode, Option<VirtualKeyCode>, ModifiersState),
|
||||
F: 'static + FnMut(KeyCode, Key, Option<SmolStr>, KeyLocation, bool, ModifiersState),
|
||||
{
|
||||
self.on_keyboard_release = Some(self.common.add_user_event(
|
||||
"keyup",
|
||||
|
|
@ -182,11 +180,15 @@ impl Canvas {
|
|||
if prevent_default {
|
||||
event.prevent_default();
|
||||
}
|
||||
|
||||
let key = event::key(&event);
|
||||
let modifiers = event::keyboard_modifiers(&event);
|
||||
handler(
|
||||
event::scan_code(&event),
|
||||
event::virtual_key_code(&event),
|
||||
event::keyboard_modifiers(&event),
|
||||
event::key_code(&event),
|
||||
key,
|
||||
event::key_text(&event),
|
||||
event::key_location(&event),
|
||||
event.repeat(),
|
||||
modifiers,
|
||||
);
|
||||
},
|
||||
));
|
||||
|
|
@ -194,59 +196,31 @@ impl Canvas {
|
|||
|
||||
pub fn on_keyboard_press<F>(&mut self, mut handler: F, prevent_default: bool)
|
||||
where
|
||||
F: 'static + FnMut(ScanCode, Option<VirtualKeyCode>, ModifiersState),
|
||||
F: 'static + FnMut(KeyCode, Key, Option<SmolStr>, KeyLocation, bool, ModifiersState),
|
||||
{
|
||||
self.on_keyboard_press = Some(self.common.add_user_event(
|
||||
"keydown",
|
||||
move |event: KeyboardEvent| {
|
||||
// event.prevent_default() would suppress subsequent on_received_character() calls. That
|
||||
// suppression is correct for key sequences like Tab/Shift-Tab, Ctrl+R, PgUp/Down to
|
||||
// scroll, etc. We should not do it for key sequences that result in meaningful character
|
||||
// input though.
|
||||
if prevent_default {
|
||||
let event_key = &event.key();
|
||||
let is_key_string = event_key.len() == 1 || !event_key.is_ascii();
|
||||
let is_shortcut_modifiers =
|
||||
(event.ctrl_key() || event.alt_key()) && !event.get_modifier_state("AltGr");
|
||||
if !is_key_string || is_shortcut_modifiers {
|
||||
event.prevent_default();
|
||||
}
|
||||
}
|
||||
|
||||
handler(
|
||||
event::scan_code(&event),
|
||||
event::virtual_key_code(&event),
|
||||
event::keyboard_modifiers(&event),
|
||||
);
|
||||
},
|
||||
));
|
||||
}
|
||||
|
||||
pub fn on_received_character<F>(&mut self, mut handler: F, prevent_default: bool)
|
||||
where
|
||||
F: 'static + FnMut(char),
|
||||
{
|
||||
// TODO: Use `beforeinput`.
|
||||
//
|
||||
// The `keypress` event is deprecated, but there does not seem to be a
|
||||
// viable/compatible alternative as of now. `beforeinput` is still widely
|
||||
// unsupported.
|
||||
self.on_received_character = Some(self.common.add_user_event(
|
||||
"keypress",
|
||||
move |event: KeyboardEvent| {
|
||||
// Suppress further handling to stop keys like the space key from scrolling the page.
|
||||
if prevent_default {
|
||||
event.prevent_default();
|
||||
}
|
||||
|
||||
handler(event::codepoint(&event));
|
||||
let key = event::key(&event);
|
||||
let modifiers = event::keyboard_modifiers(&event);
|
||||
handler(
|
||||
event::key_code(&event),
|
||||
key,
|
||||
event::key_text(&event),
|
||||
event::key_location(&event),
|
||||
event.repeat(),
|
||||
modifiers,
|
||||
);
|
||||
},
|
||||
));
|
||||
}
|
||||
|
||||
pub fn on_cursor_leave<F>(&mut self, handler: F)
|
||||
where
|
||||
F: 'static + FnMut(i32),
|
||||
F: 'static + FnMut(i32, ModifiersState),
|
||||
{
|
||||
match &mut self.mouse_state {
|
||||
MouseState::HasPointerEvent(h) => h.on_cursor_leave(&self.common, handler),
|
||||
|
|
@ -256,7 +230,7 @@ impl Canvas {
|
|||
|
||||
pub fn on_cursor_enter<F>(&mut self, handler: F)
|
||||
where
|
||||
F: 'static + FnMut(i32),
|
||||
F: 'static + FnMut(i32, ModifiersState),
|
||||
{
|
||||
match &mut self.mouse_state {
|
||||
MouseState::HasPointerEvent(h) => h.on_cursor_enter(&self.common, handler),
|
||||
|
|
@ -326,7 +300,8 @@ impl Canvas {
|
|||
}
|
||||
|
||||
if let Some(delta) = event::mouse_scroll_delta(&event) {
|
||||
handler(0, delta, event::mouse_modifiers(&event));
|
||||
let modifiers = event::mouse_modifiers(&event);
|
||||
handler(0, delta, modifiers);
|
||||
}
|
||||
}));
|
||||
}
|
||||
|
|
@ -366,7 +341,6 @@ impl Canvas {
|
|||
self.on_blur = None;
|
||||
self.on_keyboard_release = None;
|
||||
self.on_keyboard_press = None;
|
||||
self.on_received_character = None;
|
||||
self.on_mouse_wheel = None;
|
||||
self.on_fullscreen_change = None;
|
||||
self.on_dark_mode = None;
|
||||
|
|
|
|||
|
|
@ -1,14 +1,15 @@
|
|||
use super::event;
|
||||
use super::EventListenerHandle;
|
||||
use crate::dpi::PhysicalPosition;
|
||||
use crate::event::{ModifiersState, MouseButton};
|
||||
use crate::event::MouseButton;
|
||||
use crate::keyboard::ModifiersState;
|
||||
|
||||
use std::cell::RefCell;
|
||||
use std::rc::Rc;
|
||||
|
||||
use web_sys::{EventTarget, MouseEvent};
|
||||
|
||||
type MouseLeaveHandler = Rc<RefCell<Option<Box<dyn FnMut(i32)>>>>;
|
||||
type MouseLeaveHandler = Rc<RefCell<Option<Box<dyn FnMut(i32, ModifiersState)>>>>;
|
||||
|
||||
#[allow(dead_code)]
|
||||
pub(super) struct MouseHandler {
|
||||
|
|
@ -42,35 +43,43 @@ impl MouseHandler {
|
|||
}
|
||||
pub fn on_cursor_leave<F>(&mut self, canvas_common: &super::Common, handler: F)
|
||||
where
|
||||
F: 'static + FnMut(i32),
|
||||
F: 'static + FnMut(i32, ModifiersState),
|
||||
{
|
||||
*self.on_mouse_leave_handler.borrow_mut() = Some(Box::new(handler));
|
||||
let on_mouse_leave_handler = self.on_mouse_leave_handler.clone();
|
||||
let mouse_capture_state = self.mouse_capture_state.clone();
|
||||
self.on_mouse_leave = Some(canvas_common.add_event("mouseout", move |_: MouseEvent| {
|
||||
// If the mouse is being captured, it is always considered
|
||||
// to be "within" the the canvas, until the capture has been
|
||||
// released, therefore we don't send cursor leave events.
|
||||
if *mouse_capture_state.borrow() != MouseCaptureState::Captured {
|
||||
if let Some(handler) = on_mouse_leave_handler.borrow_mut().as_mut() {
|
||||
handler(0);
|
||||
self.on_mouse_leave = Some(canvas_common.add_event(
|
||||
"mouseout",
|
||||
move |event: MouseEvent| {
|
||||
// If the mouse is being captured, it is always considered
|
||||
// to be "within" the the canvas, until the capture has been
|
||||
// released, therefore we don't send cursor leave events.
|
||||
if *mouse_capture_state.borrow() != MouseCaptureState::Captured {
|
||||
if let Some(handler) = on_mouse_leave_handler.borrow_mut().as_mut() {
|
||||
let modifiers = event::mouse_modifiers(&event);
|
||||
handler(0, modifiers);
|
||||
}
|
||||
}
|
||||
}
|
||||
}));
|
||||
},
|
||||
));
|
||||
}
|
||||
|
||||
pub fn on_cursor_enter<F>(&mut self, canvas_common: &super::Common, mut handler: F)
|
||||
where
|
||||
F: 'static + FnMut(i32),
|
||||
F: 'static + FnMut(i32, ModifiersState),
|
||||
{
|
||||
let mouse_capture_state = self.mouse_capture_state.clone();
|
||||
self.on_mouse_enter = Some(canvas_common.add_event("mouseover", move |_: MouseEvent| {
|
||||
// We don't send cursor leave events when the mouse is being
|
||||
// captured, therefore we do the same with cursor enter events.
|
||||
if *mouse_capture_state.borrow() != MouseCaptureState::Captured {
|
||||
handler(0);
|
||||
}
|
||||
}));
|
||||
self.on_mouse_enter = Some(canvas_common.add_event(
|
||||
"mouseover",
|
||||
move |event: MouseEvent| {
|
||||
// We don't send cursor leave events when the mouse is being
|
||||
// captured, therefore we do the same with cursor enter events.
|
||||
if *mouse_capture_state.borrow() != MouseCaptureState::Captured {
|
||||
let modifiers = event::mouse_modifiers(&event);
|
||||
handler(0, modifiers);
|
||||
}
|
||||
},
|
||||
));
|
||||
}
|
||||
|
||||
pub fn on_mouse_release<F>(&mut self, canvas_common: &super::Common, mut handler: F)
|
||||
|
|
@ -99,11 +108,8 @@ impl MouseHandler {
|
|||
MouseCaptureState::Captured => {}
|
||||
}
|
||||
event.stop_propagation();
|
||||
handler(
|
||||
0,
|
||||
event::mouse_button(&event),
|
||||
event::mouse_modifiers(&event),
|
||||
);
|
||||
let modifiers = event::mouse_modifiers(&event);
|
||||
handler(0, event::mouse_button(&event), modifiers);
|
||||
if event
|
||||
.target()
|
||||
.map_or(false, |target| target != EventTarget::from(canvas))
|
||||
|
|
@ -112,7 +118,8 @@ impl MouseHandler {
|
|||
// cursor is being captured, we instead send it after
|
||||
// the capture has been released.
|
||||
if let Some(handler) = on_mouse_leave_handler.borrow_mut().as_mut() {
|
||||
handler(0);
|
||||
let modifiers = event::mouse_modifiers(&event);
|
||||
handler(0, modifiers);
|
||||
}
|
||||
}
|
||||
if event.buttons() == 0 {
|
||||
|
|
@ -151,11 +158,12 @@ impl MouseHandler {
|
|||
}
|
||||
*mouse_capture_state = MouseCaptureState::Captured;
|
||||
event.stop_propagation();
|
||||
let modifiers = event::mouse_modifiers(&event);
|
||||
handler(
|
||||
0,
|
||||
event::mouse_position(&event).to_physical(super::super::scale_factor()),
|
||||
event::mouse_button(&event),
|
||||
event::mouse_modifiers(&event),
|
||||
modifiers,
|
||||
);
|
||||
},
|
||||
));
|
||||
|
|
@ -194,11 +202,12 @@ impl MouseHandler {
|
|||
event::mouse_position_by_client(&event, &canvas)
|
||||
};
|
||||
let mouse_delta = event::mouse_delta(&event);
|
||||
let modifiers = event::mouse_modifiers(&event);
|
||||
handler(
|
||||
0,
|
||||
mouse_pos.to_physical(super::super::scale_factor()),
|
||||
mouse_delta.to_physical(super::super::scale_factor()),
|
||||
event::mouse_modifiers(&event),
|
||||
modifiers,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
use super::event;
|
||||
use super::EventListenerHandle;
|
||||
use crate::dpi::PhysicalPosition;
|
||||
use crate::event::Force;
|
||||
use crate::event::{ModifiersState, MouseButton};
|
||||
use crate::event::{Force, MouseButton};
|
||||
use crate::keyboard::ModifiersState;
|
||||
|
||||
use web_sys::PointerEvent;
|
||||
|
||||
|
|
@ -30,7 +30,7 @@ impl PointerHandler {
|
|||
|
||||
pub fn on_cursor_leave<F>(&mut self, canvas_common: &super::Common, mut handler: F)
|
||||
where
|
||||
F: 'static + FnMut(i32),
|
||||
F: 'static + FnMut(i32, ModifiersState),
|
||||
{
|
||||
self.on_cursor_leave = Some(canvas_common.add_event(
|
||||
"pointerout",
|
||||
|
|
@ -42,14 +42,15 @@ impl PointerHandler {
|
|||
return;
|
||||
}
|
||||
|
||||
handler(event.pointer_id());
|
||||
let modifiers = event::mouse_modifiers(&event);
|
||||
handler(event.pointer_id(), modifiers);
|
||||
},
|
||||
));
|
||||
}
|
||||
|
||||
pub fn on_cursor_enter<F>(&mut self, canvas_common: &super::Common, mut handler: F)
|
||||
where
|
||||
F: 'static + FnMut(i32),
|
||||
F: 'static + FnMut(i32, ModifiersState),
|
||||
{
|
||||
self.on_cursor_enter = Some(canvas_common.add_event(
|
||||
"pointerover",
|
||||
|
|
@ -61,7 +62,8 @@ impl PointerHandler {
|
|||
return;
|
||||
}
|
||||
|
||||
handler(event.pointer_id());
|
||||
let modifiers = event::mouse_modifiers(&event);
|
||||
handler(event.pointer_id(), modifiers);
|
||||
},
|
||||
));
|
||||
}
|
||||
|
|
@ -87,11 +89,8 @@ impl PointerHandler {
|
|||
Force::Normalized(event.pressure() as f64),
|
||||
);
|
||||
} else {
|
||||
mouse_handler(
|
||||
event.pointer_id(),
|
||||
event::mouse_button(&event),
|
||||
event::mouse_modifiers(&event),
|
||||
);
|
||||
let modifiers = event::mouse_modifiers(&event);
|
||||
mouse_handler(event.pointer_id(), event::mouse_button(&event), modifiers);
|
||||
}
|
||||
},
|
||||
));
|
||||
|
|
@ -118,11 +117,12 @@ impl PointerHandler {
|
|||
Force::Normalized(event.pressure() as f64),
|
||||
);
|
||||
} else {
|
||||
let modifiers = event::mouse_modifiers(&event);
|
||||
mouse_handler(
|
||||
event.pointer_id(),
|
||||
event::mouse_position(&event).to_physical(super::super::scale_factor()),
|
||||
event::mouse_button(&event),
|
||||
event::mouse_modifiers(&event),
|
||||
modifiers,
|
||||
);
|
||||
|
||||
// Error is swallowed here since the error would occur every time the mouse is
|
||||
|
|
@ -160,11 +160,12 @@ impl PointerHandler {
|
|||
Force::Normalized(event.pressure() as f64),
|
||||
);
|
||||
} else {
|
||||
let modifiers = event::mouse_modifiers(&event);
|
||||
mouse_handler(
|
||||
event.pointer_id(),
|
||||
event::mouse_position(&event).to_physical(super::super::scale_factor()),
|
||||
event::mouse_delta(&event).to_physical(super::super::scale_factor()),
|
||||
event::mouse_modifiers(&event),
|
||||
modifiers,
|
||||
);
|
||||
}
|
||||
},
|
||||
|
|
|
|||
|
|
@ -1,6 +1,8 @@
|
|||
use crate::dpi::LogicalPosition;
|
||||
use crate::event::{ModifiersState, MouseButton, MouseScrollDelta, ScanCode, VirtualKeyCode};
|
||||
use crate::event::{MouseButton, MouseScrollDelta};
|
||||
use crate::keyboard::{Key, KeyCode, KeyLocation, ModifiersState};
|
||||
|
||||
use smol_str::SmolStr;
|
||||
use std::convert::TryInto;
|
||||
use web_sys::{HtmlCanvasElement, KeyboardEvent, MouseEvent, PointerEvent, WheelEvent};
|
||||
|
||||
|
|
@ -13,15 +15,6 @@ pub fn mouse_button(event: &MouseEvent) -> MouseButton {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn mouse_modifiers(event: &MouseEvent) -> ModifiersState {
|
||||
let mut m = ModifiersState::empty();
|
||||
m.set(ModifiersState::SHIFT, event.shift_key());
|
||||
m.set(ModifiersState::CTRL, event.ctrl_key());
|
||||
m.set(ModifiersState::ALT, event.alt_key());
|
||||
m.set(ModifiersState::LOGO, event.meta_key());
|
||||
m
|
||||
}
|
||||
|
||||
pub fn mouse_position(event: &MouseEvent) -> LogicalPosition<f64> {
|
||||
LogicalPosition {
|
||||
x: event.offset_x() as f64,
|
||||
|
|
@ -61,190 +54,77 @@ pub fn mouse_scroll_delta(event: &WheelEvent) -> Option<MouseScrollDelta> {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn scan_code(event: &KeyboardEvent) -> ScanCode {
|
||||
match event.key_code() {
|
||||
0 => event.char_code(),
|
||||
i => i,
|
||||
pub fn key_code(event: &KeyboardEvent) -> KeyCode {
|
||||
let code = event.code();
|
||||
KeyCode::from_key_code_attribute_value(&code)
|
||||
}
|
||||
|
||||
pub fn key(event: &KeyboardEvent) -> Key {
|
||||
Key::from_key_attribute_value(&event.key())
|
||||
}
|
||||
|
||||
pub fn key_text(event: &KeyboardEvent) -> Option<SmolStr> {
|
||||
let key = event.key();
|
||||
let key = Key::from_key_attribute_value(&key);
|
||||
match &key {
|
||||
Key::Character(text) => Some(text.clone()),
|
||||
Key::Tab => Some(SmolStr::new("\t")),
|
||||
Key::Enter => Some(SmolStr::new("\r")),
|
||||
Key::Space => Some(SmolStr::new(" ")),
|
||||
_ => None,
|
||||
}
|
||||
.map(SmolStr::new)
|
||||
}
|
||||
|
||||
pub fn key_location(event: &KeyboardEvent) -> KeyLocation {
|
||||
match event.location() {
|
||||
KeyboardEvent::DOM_KEY_LOCATION_LEFT => KeyLocation::Left,
|
||||
KeyboardEvent::DOM_KEY_LOCATION_RIGHT => KeyLocation::Right,
|
||||
KeyboardEvent::DOM_KEY_LOCATION_NUMPAD => KeyLocation::Numpad,
|
||||
KeyboardEvent::DOM_KEY_LOCATION_STANDARD => KeyLocation::Standard,
|
||||
location => {
|
||||
warn!("Unexpected key location: {location}");
|
||||
KeyLocation::Standard
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn virtual_key_code(event: &KeyboardEvent) -> Option<VirtualKeyCode> {
|
||||
Some(match &event.code()[..] {
|
||||
"Digit1" => VirtualKeyCode::Key1,
|
||||
"Digit2" => VirtualKeyCode::Key2,
|
||||
"Digit3" => VirtualKeyCode::Key3,
|
||||
"Digit4" => VirtualKeyCode::Key4,
|
||||
"Digit5" => VirtualKeyCode::Key5,
|
||||
"Digit6" => VirtualKeyCode::Key6,
|
||||
"Digit7" => VirtualKeyCode::Key7,
|
||||
"Digit8" => VirtualKeyCode::Key8,
|
||||
"Digit9" => VirtualKeyCode::Key9,
|
||||
"Digit0" => VirtualKeyCode::Key0,
|
||||
"KeyA" => VirtualKeyCode::A,
|
||||
"KeyB" => VirtualKeyCode::B,
|
||||
"KeyC" => VirtualKeyCode::C,
|
||||
"KeyD" => VirtualKeyCode::D,
|
||||
"KeyE" => VirtualKeyCode::E,
|
||||
"KeyF" => VirtualKeyCode::F,
|
||||
"KeyG" => VirtualKeyCode::G,
|
||||
"KeyH" => VirtualKeyCode::H,
|
||||
"KeyI" => VirtualKeyCode::I,
|
||||
"KeyJ" => VirtualKeyCode::J,
|
||||
"KeyK" => VirtualKeyCode::K,
|
||||
"KeyL" => VirtualKeyCode::L,
|
||||
"KeyM" => VirtualKeyCode::M,
|
||||
"KeyN" => VirtualKeyCode::N,
|
||||
"KeyO" => VirtualKeyCode::O,
|
||||
"KeyP" => VirtualKeyCode::P,
|
||||
"KeyQ" => VirtualKeyCode::Q,
|
||||
"KeyR" => VirtualKeyCode::R,
|
||||
"KeyS" => VirtualKeyCode::S,
|
||||
"KeyT" => VirtualKeyCode::T,
|
||||
"KeyU" => VirtualKeyCode::U,
|
||||
"KeyV" => VirtualKeyCode::V,
|
||||
"KeyW" => VirtualKeyCode::W,
|
||||
"KeyX" => VirtualKeyCode::X,
|
||||
"KeyY" => VirtualKeyCode::Y,
|
||||
"KeyZ" => VirtualKeyCode::Z,
|
||||
"Escape" => VirtualKeyCode::Escape,
|
||||
"F1" => VirtualKeyCode::F1,
|
||||
"F2" => VirtualKeyCode::F2,
|
||||
"F3" => VirtualKeyCode::F3,
|
||||
"F4" => VirtualKeyCode::F4,
|
||||
"F5" => VirtualKeyCode::F5,
|
||||
"F6" => VirtualKeyCode::F6,
|
||||
"F7" => VirtualKeyCode::F7,
|
||||
"F8" => VirtualKeyCode::F8,
|
||||
"F9" => VirtualKeyCode::F9,
|
||||
"F10" => VirtualKeyCode::F10,
|
||||
"F11" => VirtualKeyCode::F11,
|
||||
"F12" => VirtualKeyCode::F12,
|
||||
"F13" => VirtualKeyCode::F13,
|
||||
"F14" => VirtualKeyCode::F14,
|
||||
"F15" => VirtualKeyCode::F15,
|
||||
"F16" => VirtualKeyCode::F16,
|
||||
"F17" => VirtualKeyCode::F17,
|
||||
"F18" => VirtualKeyCode::F18,
|
||||
"F19" => VirtualKeyCode::F19,
|
||||
"F20" => VirtualKeyCode::F20,
|
||||
"F21" => VirtualKeyCode::F21,
|
||||
"F22" => VirtualKeyCode::F22,
|
||||
"F23" => VirtualKeyCode::F23,
|
||||
"F24" => VirtualKeyCode::F24,
|
||||
"PrintScreen" => VirtualKeyCode::Snapshot,
|
||||
"ScrollLock" => VirtualKeyCode::Scroll,
|
||||
"Pause" => VirtualKeyCode::Pause,
|
||||
"Insert" => VirtualKeyCode::Insert,
|
||||
"Home" => VirtualKeyCode::Home,
|
||||
"Delete" => VirtualKeyCode::Delete,
|
||||
"End" => VirtualKeyCode::End,
|
||||
"PageDown" => VirtualKeyCode::PageDown,
|
||||
"PageUp" => VirtualKeyCode::PageUp,
|
||||
"ArrowLeft" => VirtualKeyCode::Left,
|
||||
"ArrowUp" => VirtualKeyCode::Up,
|
||||
"ArrowRight" => VirtualKeyCode::Right,
|
||||
"ArrowDown" => VirtualKeyCode::Down,
|
||||
"Backspace" => VirtualKeyCode::Back,
|
||||
"Enter" => VirtualKeyCode::Return,
|
||||
"Space" => VirtualKeyCode::Space,
|
||||
"Compose" => VirtualKeyCode::Compose,
|
||||
"Caret" => VirtualKeyCode::Caret,
|
||||
"NumLock" => VirtualKeyCode::Numlock,
|
||||
"Numpad0" => VirtualKeyCode::Numpad0,
|
||||
"Numpad1" => VirtualKeyCode::Numpad1,
|
||||
"Numpad2" => VirtualKeyCode::Numpad2,
|
||||
"Numpad3" => VirtualKeyCode::Numpad3,
|
||||
"Numpad4" => VirtualKeyCode::Numpad4,
|
||||
"Numpad5" => VirtualKeyCode::Numpad5,
|
||||
"Numpad6" => VirtualKeyCode::Numpad6,
|
||||
"Numpad7" => VirtualKeyCode::Numpad7,
|
||||
"Numpad8" => VirtualKeyCode::Numpad8,
|
||||
"Numpad9" => VirtualKeyCode::Numpad9,
|
||||
"AbntC1" => VirtualKeyCode::AbntC1,
|
||||
"AbntC2" => VirtualKeyCode::AbntC2,
|
||||
"NumpadAdd" => VirtualKeyCode::NumpadAdd,
|
||||
"Quote" => VirtualKeyCode::Apostrophe,
|
||||
"Apps" => VirtualKeyCode::Apps,
|
||||
"At" => VirtualKeyCode::At,
|
||||
"Ax" => VirtualKeyCode::Ax,
|
||||
"Backslash" => VirtualKeyCode::Backslash,
|
||||
"Calculator" => VirtualKeyCode::Calculator,
|
||||
"Capital" => VirtualKeyCode::Capital,
|
||||
"Semicolon" => VirtualKeyCode::Semicolon,
|
||||
"Comma" => VirtualKeyCode::Comma,
|
||||
"Convert" => VirtualKeyCode::Convert,
|
||||
"NumpadDecimal" => VirtualKeyCode::NumpadDecimal,
|
||||
"NumpadDivide" => VirtualKeyCode::NumpadDivide,
|
||||
"Equal" => VirtualKeyCode::Equals,
|
||||
"Backquote" => VirtualKeyCode::Grave,
|
||||
"Kana" => VirtualKeyCode::Kana,
|
||||
"Kanji" => VirtualKeyCode::Kanji,
|
||||
"AltLeft" => VirtualKeyCode::LAlt,
|
||||
"BracketLeft" => VirtualKeyCode::LBracket,
|
||||
"ControlLeft" => VirtualKeyCode::LControl,
|
||||
"ShiftLeft" => VirtualKeyCode::LShift,
|
||||
"MetaLeft" => VirtualKeyCode::LWin,
|
||||
"Mail" => VirtualKeyCode::Mail,
|
||||
"MediaSelect" => VirtualKeyCode::MediaSelect,
|
||||
"MediaStop" => VirtualKeyCode::MediaStop,
|
||||
"Minus" => VirtualKeyCode::Minus,
|
||||
"NumpadMultiply" => VirtualKeyCode::NumpadMultiply,
|
||||
"Mute" => VirtualKeyCode::Mute,
|
||||
"LaunchMyComputer" => VirtualKeyCode::MyComputer,
|
||||
"NavigateForward" => VirtualKeyCode::NavigateForward,
|
||||
"NavigateBackward" => VirtualKeyCode::NavigateBackward,
|
||||
"NextTrack" => VirtualKeyCode::NextTrack,
|
||||
"NoConvert" => VirtualKeyCode::NoConvert,
|
||||
"NumpadComma" => VirtualKeyCode::NumpadComma,
|
||||
"NumpadEnter" => VirtualKeyCode::NumpadEnter,
|
||||
"NumpadEquals" => VirtualKeyCode::NumpadEquals,
|
||||
"OEM102" => VirtualKeyCode::OEM102,
|
||||
"Period" => VirtualKeyCode::Period,
|
||||
"PlayPause" => VirtualKeyCode::PlayPause,
|
||||
"Power" => VirtualKeyCode::Power,
|
||||
"PrevTrack" => VirtualKeyCode::PrevTrack,
|
||||
"AltRight" => VirtualKeyCode::RAlt,
|
||||
"BracketRight" => VirtualKeyCode::RBracket,
|
||||
"ControlRight" => VirtualKeyCode::RControl,
|
||||
"ShiftRight" => VirtualKeyCode::RShift,
|
||||
"MetaRight" => VirtualKeyCode::RWin,
|
||||
"Slash" => VirtualKeyCode::Slash,
|
||||
"Sleep" => VirtualKeyCode::Sleep,
|
||||
"Stop" => VirtualKeyCode::Stop,
|
||||
"NumpadSubtract" => VirtualKeyCode::NumpadSubtract,
|
||||
"Sysrq" => VirtualKeyCode::Sysrq,
|
||||
"Tab" => VirtualKeyCode::Tab,
|
||||
"Underline" => VirtualKeyCode::Underline,
|
||||
"Unlabeled" => VirtualKeyCode::Unlabeled,
|
||||
"AudioVolumeDown" => VirtualKeyCode::VolumeDown,
|
||||
"AudioVolumeUp" => VirtualKeyCode::VolumeUp,
|
||||
"Wake" => VirtualKeyCode::Wake,
|
||||
"WebBack" => VirtualKeyCode::WebBack,
|
||||
"WebFavorites" => VirtualKeyCode::WebFavorites,
|
||||
"WebForward" => VirtualKeyCode::WebForward,
|
||||
"WebHome" => VirtualKeyCode::WebHome,
|
||||
"WebRefresh" => VirtualKeyCode::WebRefresh,
|
||||
"WebSearch" => VirtualKeyCode::WebSearch,
|
||||
"WebStop" => VirtualKeyCode::WebStop,
|
||||
"Yen" => VirtualKeyCode::Yen,
|
||||
_ => return None,
|
||||
})
|
||||
}
|
||||
|
||||
pub fn keyboard_modifiers(event: &KeyboardEvent) -> ModifiersState {
|
||||
let mut m = ModifiersState::empty();
|
||||
m.set(ModifiersState::SHIFT, event.shift_key());
|
||||
m.set(ModifiersState::CTRL, event.ctrl_key());
|
||||
m.set(ModifiersState::ALT, event.alt_key());
|
||||
m.set(ModifiersState::LOGO, event.meta_key());
|
||||
m
|
||||
let mut state = ModifiersState::empty();
|
||||
|
||||
if event.shift_key() {
|
||||
state |= ModifiersState::SHIFT;
|
||||
}
|
||||
if event.ctrl_key() {
|
||||
state |= ModifiersState::CONTROL;
|
||||
}
|
||||
if event.alt_key() {
|
||||
state |= ModifiersState::ALT;
|
||||
}
|
||||
if event.meta_key() {
|
||||
state |= ModifiersState::SUPER;
|
||||
}
|
||||
|
||||
state
|
||||
}
|
||||
|
||||
pub fn codepoint(event: &KeyboardEvent) -> char {
|
||||
// `event.key()` always returns a non-empty `String`. Therefore, this should
|
||||
// never panic.
|
||||
// https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/key
|
||||
event.key().chars().next().unwrap()
|
||||
pub fn mouse_modifiers(event: &MouseEvent) -> ModifiersState {
|
||||
let mut state = ModifiersState::empty();
|
||||
|
||||
if event.shift_key() {
|
||||
state |= ModifiersState::SHIFT;
|
||||
}
|
||||
if event.ctrl_key() {
|
||||
state |= ModifiersState::CONTROL;
|
||||
}
|
||||
if event.alt_key() {
|
||||
state |= ModifiersState::ALT;
|
||||
}
|
||||
if event.meta_key() {
|
||||
state |= ModifiersState::SUPER;
|
||||
}
|
||||
|
||||
state
|
||||
}
|
||||
|
||||
pub fn touch_position(event: &PointerEvent, _canvas: &HtmlCanvasElement) -> LogicalPosition<f64> {
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@ use raw_window_handle::{RawDisplayHandle, RawWindowHandle, WebDisplayHandle, Web
|
|||
|
||||
use super::{backend, monitor::MonitorHandle, EventLoopWindowTarget, Fullscreen};
|
||||
|
||||
use std::cell::{Ref, RefCell};
|
||||
use std::cell::{Cell, Ref, RefCell};
|
||||
use std::collections::vec_deque::IntoIter as VecDequeIter;
|
||||
use std::collections::VecDeque;
|
||||
use std::rc::Rc;
|
||||
|
|
@ -23,7 +23,7 @@ pub struct Window {
|
|||
register_redraw_request: Box<dyn Fn()>,
|
||||
resize_notify_fn: Box<dyn Fn(PhysicalSize<u32>)>,
|
||||
destroy_fn: Option<Box<dyn FnOnce()>>,
|
||||
has_focus: Rc<RefCell<bool>>,
|
||||
has_focus: Rc<Cell<bool>>,
|
||||
}
|
||||
|
||||
impl Window {
|
||||
|
|
@ -43,7 +43,7 @@ impl Window {
|
|||
|
||||
let register_redraw_request = Box::new(move || runner.request_redraw(RootWI(id)));
|
||||
|
||||
let has_focus = Rc::new(RefCell::new(false));
|
||||
let has_focus = Rc::new(Cell::new(false));
|
||||
target.register(&canvas, id, prevent_default, has_focus.clone());
|
||||
|
||||
let runner = target.runner.clone();
|
||||
|
|
@ -388,12 +388,16 @@ impl Window {
|
|||
|
||||
#[inline]
|
||||
pub fn has_focus(&self) -> bool {
|
||||
*self.has_focus.borrow()
|
||||
self.has_focus.get()
|
||||
}
|
||||
|
||||
pub fn title(&self) -> String {
|
||||
String::new()
|
||||
}
|
||||
|
||||
pub fn reset_dead_keys(&self) {
|
||||
// Not supported
|
||||
}
|
||||
}
|
||||
|
||||
impl Drop for Window {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue