2019-06-25 18:07:47 +02:00
|
|
|
use crate::dpi::LogicalPosition;
|
2023-05-28 20:02:59 +02:00
|
|
|
use crate::event::{MouseButton, MouseScrollDelta};
|
|
|
|
|
use crate::keyboard::{Key, KeyCode, KeyLocation, ModifiersState};
|
2019-06-25 18:07:47 +02:00
|
|
|
|
2023-05-28 20:02:59 +02:00
|
|
|
use smol_str::SmolStr;
|
2019-06-25 18:07:47 +02:00
|
|
|
use std::convert::TryInto;
|
2022-12-23 14:55:22 +09:00
|
|
|
use web_sys::{HtmlCanvasElement, KeyboardEvent, MouseEvent, PointerEvent, WheelEvent};
|
2019-06-25 18:07:47 +02:00
|
|
|
|
2023-06-02 11:37:23 +02:00
|
|
|
bitflags! {
|
2023-06-02 14:23:09 +02:00
|
|
|
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
2023-06-02 11:37:23 +02:00
|
|
|
pub struct ButtonsState: u16 {
|
|
|
|
|
const LEFT = 0b001;
|
|
|
|
|
const RIGHT = 0b010;
|
|
|
|
|
const MIDDLE = 0b100;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl From<ButtonsState> for MouseButton {
|
|
|
|
|
fn from(value: ButtonsState) -> Self {
|
|
|
|
|
match value {
|
|
|
|
|
ButtonsState::LEFT => MouseButton::Left,
|
|
|
|
|
ButtonsState::RIGHT => MouseButton::Right,
|
|
|
|
|
ButtonsState::MIDDLE => MouseButton::Middle,
|
|
|
|
|
_ => MouseButton::Other(value.bits()),
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl From<MouseButton> for ButtonsState {
|
|
|
|
|
fn from(value: MouseButton) -> Self {
|
|
|
|
|
match value {
|
|
|
|
|
MouseButton::Left => ButtonsState::LEFT,
|
|
|
|
|
MouseButton::Right => ButtonsState::RIGHT,
|
|
|
|
|
MouseButton::Middle => ButtonsState::MIDDLE,
|
2023-06-02 15:44:36 +01:00
|
|
|
MouseButton::Other(value) => ButtonsState::from_bits_retain(value),
|
2023-06-02 11:37:23 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub fn mouse_buttons(event: &MouseEvent) -> ButtonsState {
|
2023-06-02 15:44:36 +01:00
|
|
|
ButtonsState::from_bits_retain(event.buttons())
|
2023-06-02 11:37:23 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub fn mouse_button(event: &MouseEvent) -> Option<MouseButton> {
|
2019-06-25 18:07:47 +02:00
|
|
|
match event.button() {
|
2023-06-02 11:37:23 +02:00
|
|
|
-1 => None,
|
|
|
|
|
0 => Some(MouseButton::Left),
|
|
|
|
|
1 => Some(MouseButton::Middle),
|
|
|
|
|
2 => Some(MouseButton::Right),
|
|
|
|
|
i => Some(MouseButton::Other(
|
|
|
|
|
i.try_into()
|
|
|
|
|
.expect("unexpected negative mouse button value"),
|
|
|
|
|
)),
|
2019-06-25 18:07:47 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2020-01-04 01:33:07 -05:00
|
|
|
pub fn mouse_position(event: &MouseEvent) -> LogicalPosition<f64> {
|
2019-06-25 18:07:47 +02:00
|
|
|
LogicalPosition {
|
|
|
|
|
x: event.offset_x() as f64,
|
|
|
|
|
y: event.offset_y() as f64,
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2021-02-16 17:50:46 -05:00
|
|
|
pub fn mouse_delta(event: &MouseEvent) -> LogicalPosition<f64> {
|
|
|
|
|
LogicalPosition {
|
|
|
|
|
x: event.movement_x() as f64,
|
|
|
|
|
y: event.movement_y() as f64,
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2020-08-29 21:34:33 +08:00
|
|
|
pub fn mouse_position_by_client(
|
|
|
|
|
event: &MouseEvent,
|
|
|
|
|
canvas: &HtmlCanvasElement,
|
|
|
|
|
) -> LogicalPosition<f64> {
|
|
|
|
|
let bounding_client_rect = canvas.get_bounding_client_rect();
|
|
|
|
|
LogicalPosition {
|
|
|
|
|
x: event.client_x() as f64 - bounding_client_rect.x(),
|
|
|
|
|
y: event.client_y() as f64 - bounding_client_rect.y(),
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2019-06-25 18:07:47 +02:00
|
|
|
pub fn mouse_scroll_delta(event: &WheelEvent) -> Option<MouseScrollDelta> {
|
2022-03-13 14:22:02 +01:00
|
|
|
let x = -event.delta_x();
|
2020-08-21 09:09:04 +08:00
|
|
|
let y = -event.delta_y();
|
2019-06-25 18:07:47 +02:00
|
|
|
|
|
|
|
|
match event.delta_mode() {
|
|
|
|
|
WheelEvent::DOM_DELTA_LINE => Some(MouseScrollDelta::LineDelta(x as f32, y as f32)),
|
2020-07-26 22:16:21 +00:00
|
|
|
WheelEvent::DOM_DELTA_PIXEL => {
|
|
|
|
|
let delta = LogicalPosition::new(x, y).to_physical(super::scale_factor());
|
|
|
|
|
Some(MouseScrollDelta::PixelDelta(delta))
|
|
|
|
|
}
|
2019-06-25 18:07:47 +02:00
|
|
|
_ => None,
|
|
|
|
|
}
|
|
|
|
|
}
|
2019-06-25 21:01:13 +02:00
|
|
|
|
2023-05-28 20:02:59 +02:00
|
|
|
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,
|
2019-06-25 21:01:13 +02:00
|
|
|
}
|
2023-05-28 20:02:59 +02:00
|
|
|
.map(SmolStr::new)
|
2019-06-25 21:01:13 +02:00
|
|
|
}
|
|
|
|
|
|
2023-05-28 20:02:59 +02:00
|
|
|
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
|
|
|
|
|
}
|
|
|
|
|
}
|
2019-06-25 21:01:13 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub fn keyboard_modifiers(event: &KeyboardEvent) -> ModifiersState {
|
2023-05-28 20:02:59 +02:00
|
|
|
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
|
2019-06-25 21:01:13 +02:00
|
|
|
}
|
2019-06-25 21:18:11 +02:00
|
|
|
|
2023-05-28 20:02:59 +02:00
|
|
|
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
|
2019-06-25 21:18:11 +02:00
|
|
|
}
|
2022-12-23 14:55:22 +09:00
|
|
|
|
2023-02-28 10:25:51 +01:00
|
|
|
pub fn touch_position(event: &PointerEvent, canvas: &HtmlCanvasElement) -> LogicalPosition<f64> {
|
|
|
|
|
mouse_position_by_client(event, canvas)
|
2022-12-23 14:55:22 +09:00
|
|
|
}
|