use winit::event::{
ElementState, Ime, KeyEvent, Modifiers, MouseButton as WinitMouseButton, MouseScrollDelta, TouchPhase,
WindowEvent,
};
use winit::keyboard::{KeyCode as WinitKeyCode, PhysicalKey};
use uzor::input::events::KeyCode;
use uzor::input::state::{ModifierKeys, MouseButton};
use uzor::platform::{ImeEvent, PlatformEvent};
pub struct EventMapper;
impl EventMapper {
pub fn map_window_event(event: &WindowEvent) -> Option<PlatformEvent> {
match event {
WindowEvent::Resized(size) => Some(PlatformEvent::WindowResized {
width: size.width,
height: size.height,
}),
WindowEvent::Moved(position) => Some(PlatformEvent::WindowMoved {
x: position.x,
y: position.y,
}),
WindowEvent::Focused(focused) => Some(PlatformEvent::WindowFocused(*focused)),
WindowEvent::CursorEntered { .. } => Some(PlatformEvent::PointerEntered),
WindowEvent::CursorLeft { .. } => Some(PlatformEvent::PointerLeft),
WindowEvent::CursorMoved { position, .. } => Some(PlatformEvent::PointerMoved {
x: position.x,
y: position.y,
}),
WindowEvent::MouseInput { state, button, .. } => {
let mapped_button = map_mouse_button(*button);
match state {
ElementState::Pressed => Some(PlatformEvent::PointerDown {
x: 0.0, y: 0.0,
button: mapped_button,
}),
ElementState::Released => Some(PlatformEvent::PointerUp {
x: 0.0,
y: 0.0,
button: mapped_button,
}),
}
}
WindowEvent::MouseWheel { delta, .. } => {
let (dx, dy) = match delta {
MouseScrollDelta::LineDelta(x, y) => (*x as f64 * 20.0, *y as f64 * 20.0),
MouseScrollDelta::PixelDelta(pos) => (pos.x, pos.y),
};
Some(PlatformEvent::Scroll { dx, dy })
}
WindowEvent::Touch(touch) => match touch.phase {
TouchPhase::Started => Some(PlatformEvent::TouchStart {
id: touch.id,
x: touch.location.x,
y: touch.location.y,
}),
TouchPhase::Moved => Some(PlatformEvent::TouchMove {
id: touch.id,
x: touch.location.x,
y: touch.location.y,
}),
TouchPhase::Ended => Some(PlatformEvent::TouchEnd {
id: touch.id,
x: touch.location.x,
y: touch.location.y,
}),
TouchPhase::Cancelled => Some(PlatformEvent::TouchCancel { id: touch.id }),
},
WindowEvent::KeyboardInput { event, .. } => {
map_keyboard_event(event)
}
WindowEvent::ModifiersChanged(modifiers) => {
Some(PlatformEvent::ModifiersChanged {
modifiers: map_modifiers(modifiers),
})
}
WindowEvent::Ime(ime) => Some(PlatformEvent::Ime(map_ime_event(ime))),
WindowEvent::DroppedFile(path) => Some(PlatformEvent::FileDropped {
path: path.clone(),
}),
WindowEvent::HoveredFile(path) => Some(PlatformEvent::FileHovered {
path: path.clone(),
}),
WindowEvent::HoveredFileCancelled => Some(PlatformEvent::FileCancelled),
WindowEvent::ScaleFactorChanged { scale_factor, .. } => {
Some(PlatformEvent::ScaleFactorChanged {
scale: *scale_factor,
})
}
WindowEvent::ThemeChanged(theme) => {
let dark_mode = matches!(theme, winit::window::Theme::Dark);
Some(PlatformEvent::ThemeChanged { dark_mode })
}
WindowEvent::RedrawRequested => Some(PlatformEvent::RedrawRequested),
WindowEvent::CloseRequested
| WindowEvent::Destroyed
| WindowEvent::ActivationTokenDone { .. }
| WindowEvent::AxisMotion { .. }
| WindowEvent::Occluded(_)
| WindowEvent::TouchpadPressure { .. }
| WindowEvent::PinchGesture { .. }
| WindowEvent::PanGesture { .. }
| WindowEvent::DoubleTapGesture { .. }
| WindowEvent::RotationGesture { .. } => None,
}
}
}
fn map_mouse_button(button: WinitMouseButton) -> MouseButton {
match button {
WinitMouseButton::Left => MouseButton::Left,
WinitMouseButton::Right => MouseButton::Right,
WinitMouseButton::Middle => MouseButton::Middle,
_ => MouseButton::Left, }
}
fn map_keyboard_event(event: &KeyEvent) -> Option<PlatformEvent> {
let key_code = match &event.physical_key {
PhysicalKey::Code(code) => map_key_code(*code),
PhysicalKey::Unidentified(_) => KeyCode::Unknown,
};
let modifiers = ModifierKeys::default();
match event.state {
ElementState::Pressed => Some(PlatformEvent::KeyDown {
key: key_code,
modifiers,
}),
ElementState::Released => Some(PlatformEvent::KeyUp {
key: key_code,
modifiers,
}),
}
}
fn map_key_code(key: WinitKeyCode) -> KeyCode {
match key {
WinitKeyCode::KeyA => KeyCode::A,
WinitKeyCode::KeyB => KeyCode::B,
WinitKeyCode::KeyC => KeyCode::C,
WinitKeyCode::KeyD => KeyCode::D,
WinitKeyCode::KeyE => KeyCode::E,
WinitKeyCode::KeyF => KeyCode::F,
WinitKeyCode::KeyG => KeyCode::G,
WinitKeyCode::KeyH => KeyCode::H,
WinitKeyCode::KeyI => KeyCode::I,
WinitKeyCode::KeyJ => KeyCode::J,
WinitKeyCode::KeyK => KeyCode::K,
WinitKeyCode::KeyL => KeyCode::L,
WinitKeyCode::KeyM => KeyCode::M,
WinitKeyCode::KeyN => KeyCode::N,
WinitKeyCode::KeyO => KeyCode::O,
WinitKeyCode::KeyP => KeyCode::P,
WinitKeyCode::KeyQ => KeyCode::Q,
WinitKeyCode::KeyR => KeyCode::R,
WinitKeyCode::KeyS => KeyCode::S,
WinitKeyCode::KeyT => KeyCode::T,
WinitKeyCode::KeyU => KeyCode::U,
WinitKeyCode::KeyV => KeyCode::V,
WinitKeyCode::KeyW => KeyCode::W,
WinitKeyCode::KeyX => KeyCode::X,
WinitKeyCode::KeyY => KeyCode::Y,
WinitKeyCode::KeyZ => KeyCode::Z,
WinitKeyCode::Digit0 => KeyCode::Num0,
WinitKeyCode::Digit1 => KeyCode::Num1,
WinitKeyCode::Digit2 => KeyCode::Num2,
WinitKeyCode::Digit3 => KeyCode::Num3,
WinitKeyCode::Digit4 => KeyCode::Num4,
WinitKeyCode::Digit5 => KeyCode::Num5,
WinitKeyCode::Digit6 => KeyCode::Num6,
WinitKeyCode::Digit7 => KeyCode::Num7,
WinitKeyCode::Digit8 => KeyCode::Num8,
WinitKeyCode::Digit9 => KeyCode::Num9,
WinitKeyCode::F1 => KeyCode::F1,
WinitKeyCode::F2 => KeyCode::F2,
WinitKeyCode::F3 => KeyCode::F3,
WinitKeyCode::F4 => KeyCode::F4,
WinitKeyCode::F5 => KeyCode::F5,
WinitKeyCode::F6 => KeyCode::F6,
WinitKeyCode::F7 => KeyCode::F7,
WinitKeyCode::F8 => KeyCode::F8,
WinitKeyCode::F9 => KeyCode::F9,
WinitKeyCode::F10 => KeyCode::F10,
WinitKeyCode::F11 => KeyCode::F11,
WinitKeyCode::F12 => KeyCode::F12,
WinitKeyCode::ArrowUp => KeyCode::ArrowUp,
WinitKeyCode::ArrowDown => KeyCode::ArrowDown,
WinitKeyCode::ArrowLeft => KeyCode::ArrowLeft,
WinitKeyCode::ArrowRight => KeyCode::ArrowRight,
WinitKeyCode::Home => KeyCode::Home,
WinitKeyCode::End => KeyCode::End,
WinitKeyCode::PageUp => KeyCode::PageUp,
WinitKeyCode::PageDown => KeyCode::PageDown,
WinitKeyCode::Backspace => KeyCode::Backspace,
WinitKeyCode::Delete => KeyCode::Delete,
WinitKeyCode::Insert => KeyCode::Insert,
WinitKeyCode::Enter => KeyCode::Enter,
WinitKeyCode::Tab => KeyCode::Tab,
WinitKeyCode::Space => KeyCode::Space,
WinitKeyCode::Escape => KeyCode::Escape,
WinitKeyCode::Equal => KeyCode::Plus,
WinitKeyCode::Minus => KeyCode::Minus,
WinitKeyCode::BracketLeft => KeyCode::BracketLeft,
WinitKeyCode::BracketRight => KeyCode::BracketRight,
_ => KeyCode::Unknown,
}
}
fn map_modifiers(modifiers: &Modifiers) -> ModifierKeys {
ModifierKeys {
shift: modifiers.state().shift_key(),
ctrl: modifiers.state().control_key(),
alt: modifiers.state().alt_key(),
meta: modifiers.state().super_key(),
}
}
fn map_ime_event(ime: &Ime) -> ImeEvent {
match ime {
Ime::Enabled => ImeEvent::Enabled,
Ime::Preedit(text, cursor) => {
ImeEvent::Preedit(text.clone(), *cursor)
}
Ime::Commit(text) => ImeEvent::Commit(text.clone()),
Ime::Disabled => ImeEvent::Disabled,
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_mouse_button_mapping() {
assert_eq!(
map_mouse_button(WinitMouseButton::Left),
MouseButton::Left
);
assert_eq!(
map_mouse_button(WinitMouseButton::Right),
MouseButton::Right
);
assert_eq!(
map_mouse_button(WinitMouseButton::Middle),
MouseButton::Middle
);
}
#[test]
fn test_key_code_mapping() {
assert_eq!(map_key_code(WinitKeyCode::KeyA), KeyCode::A);
assert_eq!(map_key_code(WinitKeyCode::Digit0), KeyCode::Num0);
assert_eq!(map_key_code(WinitKeyCode::F1), KeyCode::F1);
assert_eq!(map_key_code(WinitKeyCode::ArrowUp), KeyCode::ArrowUp);
assert_eq!(map_key_code(WinitKeyCode::Enter), KeyCode::Enter);
assert_eq!(map_key_code(WinitKeyCode::Space), KeyCode::Space);
}
#[test]
fn test_modifiers_mapping() {
let modifiers = Modifiers::default();
let mapped = map_modifiers(&modifiers);
assert!(!mapped.shift);
assert!(!mapped.ctrl);
assert!(!mapped.alt);
assert!(!mapped.meta);
}
}