Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Web: Use touch events instead of pointer events for touch #4118

Draft
wants to merge 16 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 5 additions & 2 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -318,8 +318,7 @@ js-sys = "0.3.70"
pin-project = "1"
wasm-bindgen = "0.2.93"
wasm-bindgen-futures = "0.4.43"
web-time = "1"
web_sys = { package = "web-sys", version = "0.3.70", features = [
web-sys = { version = "0.3.70", features = [
"AbortController",
"AbortSignal",
"Blob",
Expand Down Expand Up @@ -365,12 +364,16 @@ web_sys = { package = "web-sys", version = "0.3.70", features = [
"ResizeObserverSize",
"Screen",
"ScreenOrientation",
"Touch",
"TouchEvent",
"TouchList",
"Url",
"VisibilityState",
"WheelEvent",
"Window",
"Worker",
] }
web-time = "1"

[target.'cfg(all(target_family = "wasm", target_feature = "atomics"))'.dependencies]
atomic-waker = "1"
Expand Down
64 changes: 62 additions & 2 deletions src/platform_impl/web/event_loop/window_target.rs
Original file line number Diff line number Diff line change
Expand Up @@ -74,8 +74,6 @@ impl ActiveEventLoop {
pub fn register(&self, canvas: &Rc<backend::Canvas>, window_id: WindowId) {
let canvas_clone = canvas.clone();

canvas.on_touch_start();

let runner = self.runner.clone();
let has_focus = canvas.has_focus.clone();
let modifiers = self.modifiers.clone();
Expand Down Expand Up @@ -240,6 +238,68 @@ impl ActiveEventLoop {
}
});

canvas.on_touch_move({
let runner = self.runner.clone();

move |finger| {
runner.send_event(Event::WindowEvent {
window_id,
event: WindowEvent::PointerMoved {
device_id: finger.device_id,
position: finger.position,
primary: finger.primary,
source: finger.pointer_source(),
},
});
}
});
canvas.on_touch_start({
let runner = self.runner.clone();

move |finger| {
runner.send_event(Event::WindowEvent {
window_id,
event: WindowEvent::PointerButton {
device_id: finger.device_id,
state: ElementState::Pressed,
position: finger.position,
primary: finger.primary,
button: finger.button_source(),
},
});
}
});
canvas.on_touch_end({
let runner = self.runner.clone();

move |finger| {
runner.send_event(Event::WindowEvent {
window_id,
event: WindowEvent::PointerLeft {
device_id: finger.device_id,
position: Some(finger.position),
primary: finger.primary,
kind: finger.pointer_kind(),
},
});
}
});
canvas.on_touch_cancel({
let runner = self.runner.clone();

move |finger| {
runner.send_event(Event::WindowEvent {
window_id,
event: WindowEvent::PointerLeft {
device_id: finger.device_id,
position: Some(finger.position),
primary: finger.primary,
kind: finger.pointer_kind(),
},
});
}
});

canvas.on_pointer_move(
{
let runner = self.runner.clone();
Expand Down
50 changes: 40 additions & 10 deletions src/platform_impl/web/web_sys/canvas.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ use super::event_handle::EventListenerHandle;
use super::intersection_handle::IntersectionObserverHandle;
use super::media_query_handle::MediaQueryListHandle;
use super::pointer::PointerHandler;
use super::touch::{Finger, TouchHandler};
use super::{event, fullscreen, ResizeScaleHandle};
use crate::dpi::{LogicalPosition, PhysicalPosition, PhysicalSize};
use crate::error::RequestError;
Expand Down Expand Up @@ -51,6 +52,7 @@ struct Handlers {
on_mouse_wheel: Option<EventListenerHandle<dyn FnMut(WheelEvent)>>,
on_dark_mode: Option<MediaQueryListHandle>,
pointer_handler: PointerHandler,
touch_handler: TouchHandler,
on_resize_scale: Option<ResizeScaleHandle>,
on_intersect: Option<IntersectionObserverHandle>,
on_touch_end: Option<EventListenerHandle<dyn FnMut(Event)>>,
Expand Down Expand Up @@ -179,6 +181,7 @@ impl Canvas {
on_mouse_wheel: None,
on_dark_mode: None,
pointer_handler: PointerHandler::new(),
touch_handler: TouchHandler::new(),
on_resize_scale: None,
on_intersect: None,
on_touch_end: None,
Expand Down Expand Up @@ -253,16 +256,6 @@ impl Canvas {
&self.common.style
}

pub fn on_touch_start(&self) {
let prevent_default = Rc::clone(&self.prevent_default);
self.handlers.borrow_mut().on_touch_start =
Some(self.common.add_event("touchstart", move |event: Event| {
if prevent_default.get() {
event.prevent_default();
}
}));
}

pub fn on_blur<F>(&self, mut handler: F)
where
F: 'static + FnMut(),
Expand Down Expand Up @@ -392,6 +385,42 @@ impl Canvas {
)
}

pub fn on_touch_start<T>(&self, cursor_handler: T)
where
T: 'static + FnMut(Finger),
{
self.handlers.borrow_mut().touch_handler.on_touch_start(
&self.common,
cursor_handler,
Rc::clone(&self.prevent_default),
)
}

pub fn on_touch_cancel<T>(&self, cursor_handler: T)
where
T: 'static + FnMut(Finger),
{
self.handlers.borrow_mut().touch_handler.on_touch_cancel(&self.common, cursor_handler)
}

pub fn on_touch_end<T>(&self, cursor_handler: T)
where
T: 'static + FnMut(Finger),
{
self.handlers.borrow_mut().touch_handler.on_touch_end(&self.common, cursor_handler)
}

pub fn on_touch_move<T>(&self, cursor_handler: T)
where
T: 'static + FnMut(Finger),
{
self.handlers.borrow_mut().touch_handler.on_touch_move(
&self.common,
cursor_handler,
Rc::clone(&self.prevent_default),
)
}

pub fn on_mouse_wheel<F>(&self, mut handler: F)
where
F: 'static + FnMut(MouseScrollDelta, ModifiersState),
Expand Down Expand Up @@ -540,6 +569,7 @@ impl Canvas {
handlers.on_mouse_wheel.take();
handlers.on_dark_mode.take();
handlers.pointer_handler.remove_listeners();
handlers.touch_handler.remove_listeners();
handlers.on_resize_scale = None;
handlers.on_intersect = None;
handlers.animation_frame_handler.cancel();
Expand Down
1 change: 1 addition & 0 deletions src/platform_impl/web/web_sys/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ mod pointer;
mod resize_scaling;
mod safe_area;
mod schedule;
mod touch;

use std::cell::OnceCell;

Expand Down
51 changes: 23 additions & 28 deletions src/platform_impl/web/web_sys/pointer.rs
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
use std::cell::Cell;
use std::rc::Rc;

use dpi::PhysicalPosition;
use web_sys::PointerEvent;

use super::canvas::Common;
use super::event;
use super::event_handle::EventListenerHandle;
use crate::dpi::PhysicalPosition;
use crate::event::{ButtonSource, DeviceId, ElementState, Force, PointerKind, PointerSource};
use crate::event::{ButtonSource, DeviceId, ElementState, PointerKind, PointerSource};
use crate::keyboard::ModifiersState;
use crate::platform_impl::web::event::mkdid;

Expand All @@ -18,7 +18,6 @@ pub(super) struct PointerHandler {
on_cursor_move: Option<EventListenerHandle<dyn FnMut(PointerEvent)>>,
on_pointer_press: Option<EventListenerHandle<dyn FnMut(PointerEvent)>>,
on_pointer_release: Option<EventListenerHandle<dyn FnMut(PointerEvent)>>,
on_touch_cancel: Option<EventListenerHandle<dyn FnMut(PointerEvent)>>,
}

impl PointerHandler {
Expand All @@ -29,7 +28,6 @@ impl PointerHandler {
on_cursor_move: None,
on_pointer_press: None,
on_pointer_release: None,
on_touch_cancel: None,
}
}

Expand Down Expand Up @@ -81,14 +79,16 @@ impl PointerHandler {
let pointer_id = event.pointer_id();
let kind = event::pointer_type(&event, pointer_id);

// Touch events are handled separately, so return here to avoid duplicate events:
if let PointerKind::Touch(_) = kind {
return;
}

let button = event::mouse_button(&event).expect("no mouse button pressed");

let source = match kind {
PointerKind::Mouse => ButtonSource::Mouse(button),
PointerKind::Touch(finger_id) => ButtonSource::Touch {
finger_id,
force: Some(Force::Normalized(event.pressure().into())),
},
PointerKind::Touch(_) => unreachable!("Touch events are handled elsewhere"),
PointerKind::Unknown => ButtonSource::Unknown(button.to_id()),
};

Expand Down Expand Up @@ -127,6 +127,11 @@ impl PointerHandler {
let kind = event::pointer_type(&event, pointer_id);
let button = event::mouse_button(&event).expect("no mouse button pressed");

// Touch events are handled separately, so return here to avoid duplicate events:
if let PointerKind::Touch(_) = kind {
return;
}

let source = match kind {
PointerKind::Mouse => {
// Error is swallowed here since the error would occur every time the
Expand All @@ -138,10 +143,7 @@ impl PointerHandler {

ButtonSource::Mouse(button)
},
PointerKind::Touch(finger_id) => ButtonSource::Touch {
finger_id,
force: Some(Force::Normalized(event.pressure().into())),
},
PointerKind::Touch(_) => unreachable!("Touch events are handled elsewhere"),
PointerKind::Unknown => ButtonSource::Unknown(button.to_id()),
};

Expand Down Expand Up @@ -186,6 +188,12 @@ impl PointerHandler {
let pointer_id = event.pointer_id();
let device_id = mkdid(pointer_id);
let kind = event::pointer_type(&event, pointer_id);

// Touch events are handled separately, so return here to avoid duplicate events:
if let PointerKind::Touch(_) = kind {
return;
}

let primary = event.is_primary();

// chorded button event
Expand All @@ -205,18 +213,7 @@ impl PointerHandler {

let button = match kind {
PointerKind::Mouse => ButtonSource::Mouse(button),
PointerKind::Touch(finger_id) => {
let button_id = button.to_id();

if button_id != 1 {
tracing::error!("unexpected touch button id: {button_id}");
}

ButtonSource::Touch {
finger_id,
force: Some(Force::Normalized(event.pressure().into())),
}
},
PointerKind::Touch(_) => unreachable!("Touch events are handled elsewhere"),
PointerKind::Unknown => todo!(),
};

Expand Down Expand Up @@ -244,9 +241,8 @@ impl PointerHandler {
event::mouse_position(&event).to_physical(scale),
match kind {
PointerKind::Mouse => PointerSource::Mouse,
PointerKind::Touch(finger_id) => PointerSource::Touch {
finger_id,
force: Some(Force::Normalized(event.pressure().into())),
PointerKind::Touch(_) => {
unreachable!("Touch events are handled elsewhere")
},
PointerKind::Unknown => PointerSource::Unknown,
},
Expand All @@ -262,6 +258,5 @@ impl PointerHandler {
self.on_cursor_move = None;
self.on_pointer_press = None;
self.on_pointer_release = None;
self.on_touch_cancel = None;
}
}
Loading
Loading