On Web, handle coalesced events

This commit is contained in:
dAxpeDDa 2023-06-02 14:23:09 +02:00 committed by daxpedda
parent 31ebc5caf4
commit 4f3eacf01e
3 changed files with 71 additions and 18 deletions

View file

@ -59,6 +59,7 @@ And please only add new entries to the top of this list, right below the `# Unre
a transient activation. a transient activation.
- On Web, fix pointer button events not being processed when a buttons is already pressed. - On Web, fix pointer button events not being processed when a buttons is already pressed.
- **Breaking:** Updated `bitflags` crate version to `2`, which changes the API on exposed types. - **Breaking:** Updated `bitflags` crate version to `2`, which changes the API on exposed types.
- On Web, handle coalesced pointer events, which increases the resolution of pointer inputs.
# 0.28.6 # 0.28.6

View file

@ -5,6 +5,8 @@ use crate::event::{Force, MouseButton};
use crate::keyboard::ModifiersState; use crate::keyboard::ModifiersState;
use event::ButtonsState; use event::ButtonsState;
use wasm_bindgen::prelude::wasm_bindgen;
use wasm_bindgen::{JsCast, JsValue};
use web_sys::PointerEvent; use web_sys::PointerEvent;
#[allow(dead_code)] #[allow(dead_code)]
@ -157,26 +159,76 @@ impl PointerHandler {
self.on_cursor_move = Some(canvas_common.add_event( self.on_cursor_move = Some(canvas_common.add_event(
"pointermove", "pointermove",
move |event: PointerEvent| { move |event: PointerEvent| {
if event.pointer_type() == "touch" { // coalesced events are not available on Safari
if prevent_default { #[wasm_bindgen]
// prevent scroll on mobile web extern "C" {
event.prevent_default(); #[wasm_bindgen(extends = PointerEvent)]
} type PointerEventExt;
touch_handler(
event.pointer_id(), #[wasm_bindgen(method, getter, js_name = getCoalescedEvents)]
event::touch_position(&event, &canvas) fn has_get_coalesced_events(this: &PointerEventExt) -> JsValue;
.to_physical(super::super::scale_factor()), }
Force::Normalized(event.pressure() as f64),
); if event.pointer_type() == "touch" && prevent_default {
} else { // prevent scroll on mobile web
mouse_handler( event.prevent_default();
event.pointer_id(), }
event::mouse_position(&event).to_physical(super::super::scale_factor()),
event::mouse_delta(&event).to_physical(super::super::scale_factor()), let event: PointerEventExt = event.unchecked_into();
let id = event.pointer_id();
// cache buttons if the pointer is a mouse
let mouse = (event.pointer_type() != "touch").then(|| {
(
event::mouse_modifiers(&event), event::mouse_modifiers(&event),
event::mouse_buttons(&event), event::mouse_buttons(&event),
event::mouse_button(&event), event::mouse_button(&event),
); )
});
// store coalesced events to extend it's lifetime
let events = (!event.has_get_coalesced_events().is_undefined())
.then(|| event.get_coalesced_events())
// if coalesced events is empty, it's a chorded button event
.filter(|events| events.length() != 0);
// make a single iterator depending on the availability of coalesced events
let events = if let Some(events) = &events {
None.into_iter().chain(
Some(events.iter().map(PointerEventExt::unchecked_from_js))
.into_iter()
.flatten(),
)
} else {
Some(event).into_iter().chain(None.into_iter().flatten())
};
for event in events {
// coalesced events should always have the same source as the root event
debug_assert_eq!(id, event.pointer_id());
debug_assert_eq!(mouse.is_none(), event.pointer_type() == "touch");
if let Some((modifiers, buttons, button)) = mouse {
// coalesced events should have the same buttons
debug_assert_eq!(modifiers, event::mouse_modifiers(&event));
debug_assert_eq!(buttons, event::mouse_buttons(&event));
mouse_handler(
id,
event::mouse_position(&event).to_physical(super::super::scale_factor()),
event::mouse_delta(&event).to_physical(super::super::scale_factor()),
modifiers,
buttons,
button,
);
} else {
touch_handler(
id,
event::touch_position(&event, &canvas)
.to_physical(super::super::scale_factor()),
Force::Normalized(event.pressure() as f64),
);
}
} }
}, },
)); ));

View file

@ -7,7 +7,7 @@ use std::convert::TryInto;
use web_sys::{HtmlCanvasElement, KeyboardEvent, MouseEvent, PointerEvent, WheelEvent}; use web_sys::{HtmlCanvasElement, KeyboardEvent, MouseEvent, PointerEvent, WheelEvent};
bitflags! { bitflags! {
#[derive(Clone, Copy, PartialEq, Eq)] #[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct ButtonsState: u16 { pub struct ButtonsState: u16 {
const LEFT = 0b001; const LEFT = 0b001;
const RIGHT = 0b010; const RIGHT = 0b010;