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

Add support for event::Touch on web targets #1945

Closed
wants to merge 12 commits into from
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
# Unreleased

- On Web, added support for `WindowEvent::Touch`.
- **Breaking:** On Web, remove the `stdweb` backend.
- Added `Window::focus_window`to bring the window to the front and set input focus.

Expand Down
3 changes: 2 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,8 @@ features = [
'Node',
'PointerEvent',
'Window',
'WheelEvent'
'WheelEvent',
'PointerEvent',
]

[target.'cfg(target_arch = "wasm32")'.dependencies.wasm-bindgen]
Expand Down
2 changes: 1 addition & 1 deletion FEATURES.md
Original file line number Diff line number Diff line change
Expand Up @@ -199,7 +199,7 @@ Legend:
|Mouse set location |✔️ |✔️ |✔️ |❓ |**N/A**|**N/A**|**N/A**|
|Cursor grab |✔️ |▢[#165] |▢[#242] |✔️ |**N/A**|**N/A**|❓ |
|Cursor icon |✔️ |✔️ |✔️ |✔️ |**N/A**|**N/A**|✔️ |
|Touch events |✔️ |❌ |✔️ |✔️ |✔️ |✔️ | |
|Touch events |✔️ |❌ |✔️ |✔️ |✔️ |✔️ |✔️ |
|Touch pressure |✔️ |❌ |❌ |❌ |❌ |✔️ |❌ |
|Multitouch |✔️ |❌ |✔️ |✔️ |✔️ |✔️ |❌ |
|Keyboard events |✔️ |✔️ |✔️ |✔️ |❓ |❌ |✔️ |
Expand Down
58 changes: 57 additions & 1 deletion src/platform_impl/web/event_loop/window_target.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use super::{super::monitor, backend, device, proxy::Proxy, runner, window};
use crate::dpi::{PhysicalSize, Size};
use crate::event::{
DeviceEvent, DeviceId, ElementState, Event, KeyboardInput, TouchPhase, WindowEvent,
DeviceEvent, DeviceId, ElementState, Event, KeyboardInput, Touch, TouchPhase, WindowEvent,
};
use crate::event_loop::ControlFlow;
use crate::monitor::MonitorHandle as RootMH;
Expand Down Expand Up @@ -231,6 +231,62 @@ impl<T> WindowTarget<T> {
runner.request_redraw(WindowId(id));
});

let runner = self.runner.clone();
canvas.on_pointer_move(move |device_id, location| {

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
canvas.on_pointer_move(move |device_id, location| {
canvas.on_touch_move(move |device_id, location| {

runner.send_event(Event::WindowEvent {
window_id: WindowId(id),
event: WindowEvent::Touch(Touch {
id: device_id as u64,
device_id: DeviceId(device::Id(device_id)),
phase: TouchPhase::Moved,
force: None, // Todo
dsluijk marked this conversation as resolved.
Show resolved Hide resolved
location,
}),
});
});

let runner = self.runner.clone();
canvas.on_pointer_down(move |device_id, location| {

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
canvas.on_pointer_down(move |device_id, location| {
canvas.on_touch_down(move |device_id, location| {

runner.send_event(Event::WindowEvent {
window_id: WindowId(id),
event: WindowEvent::Touch(Touch {
id: device_id as u64,
device_id: DeviceId(device::Id(device_id)),
phase: TouchPhase::Started,
force: None, // Todo
location,
}),
});
});

let runner = self.runner.clone();
canvas.on_pointer_up(move |device_id, location| {

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
canvas.on_pointer_up(move |device_id, location| {
canvas.on_touch_up(move |device_id, location| {

runner.send_event(Event::WindowEvent {
window_id: WindowId(id),
event: WindowEvent::Touch(Touch {
id: device_id as u64,
device_id: DeviceId(device::Id(device_id)),
phase: TouchPhase::Ended,
force: None, // Todo
location,
}),
});
});

let runner = self.runner.clone();
canvas.on_pointer_cancel(move |device_id, location| {

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
canvas.on_pointer_cancel(move |device_id, location| {
canvas.on_touch_cancel(move |device_id, location| {

runner.send_event(Event::WindowEvent {
window_id: WindowId(id),
event: WindowEvent::Touch(Touch {
id: device_id as u64,
device_id: DeviceId(device::Id(device_id)),
phase: TouchPhase::Cancelled,
force: None, // Todo
location,
}),
});
});

let runner = self.runner.clone();
canvas.on_dark_mode(move |is_dark_mode| {
let theme = if is_dark_mode {
Expand Down
40 changes: 40 additions & 0 deletions src/platform_impl/web/web_sys/canvas.rs
Original file line number Diff line number Diff line change
Expand Up @@ -247,6 +247,46 @@ impl Canvas {
}
}

pub fn on_pointer_move<F>(&mut self, handler: F)

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
pub fn on_pointer_move<F>(&mut self, handler: F)
pub fn on_touch_move<F>(&mut self, handler: F)

where
F: 'static + FnMut(i32, PhysicalPosition<f64>),
{
match &mut self.mouse_state {
MouseState::HasPointerEvent(h) => h.on_pointer_move(&self.common, handler),

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
MouseState::HasPointerEvent(h) => h.on_pointer_move(&self.common, handler),
MouseState::HasPointerEvent(h) => h.on_touch_move(&self.common, handler),

_ => {}
}
}

pub fn on_pointer_down<F>(&mut self, handler: F)

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
pub fn on_pointer_down<F>(&mut self, handler: F)
pub fn on_touch_down<F>(&mut self, handler: F)

where
F: 'static + FnMut(i32, PhysicalPosition<f64>),
{
match &mut self.mouse_state {
MouseState::HasPointerEvent(h) => h.on_pointer_down(&self.common, handler),

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
MouseState::HasPointerEvent(h) => h.on_pointer_down(&self.common, handler),
MouseState::HasPointerEvent(h) => h.on_touch_down(&self.common, handler),

_ => {}
}
}

pub fn on_pointer_up<F>(&mut self, handler: F)

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
pub fn on_pointer_up<F>(&mut self, handler: F)
pub fn on_touch_up<F>(&mut self, handler: F)

where
F: 'static + FnMut(i32, PhysicalPosition<f64>),
{
match &mut self.mouse_state {
MouseState::HasPointerEvent(h) => h.on_pointer_up(&self.common, handler),

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
MouseState::HasPointerEvent(h) => h.on_pointer_up(&self.common, handler),
MouseState::HasPointerEvent(h) => h.on_touch_up(&self.common, handler),

_ => {}
}
}

pub fn on_pointer_cancel<F>(&mut self, handler: F)

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
pub fn on_pointer_cancel<F>(&mut self, handler: F)
pub fn on_touch_cancel<F>(&mut self, handler: F)

where
F: 'static + FnMut(i32, PhysicalPosition<f64>),
{
match &mut self.mouse_state {
MouseState::HasPointerEvent(h) => h.on_pointer_cancel(&self.common, handler),

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
MouseState::HasPointerEvent(h) => h.on_pointer_cancel(&self.common, handler),
MouseState::HasPointerEvent(h) => h.on_touch_cancel(&self.common, handler),

_ => {}
}
}

pub fn on_mouse_wheel<F>(&mut self, mut handler: F)
where
F: 'static + FnMut(i32, MouseScrollDelta, ModifiersState),
Expand Down
100 changes: 100 additions & 0 deletions src/platform_impl/web/web_sys/canvas/pointer_handler.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,10 @@ 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_move: Option<EventListenerHandle<dyn FnMut(PointerEvent)>>,
on_touch_down: Option<EventListenerHandle<dyn FnMut(PointerEvent)>>,
on_touch_up: Option<EventListenerHandle<dyn FnMut(PointerEvent)>>,
on_touch_cancel: Option<EventListenerHandle<dyn FnMut(PointerEvent)>>,
}

impl PointerHandler {
Expand All @@ -22,6 +26,10 @@ impl PointerHandler {
on_cursor_move: None,
on_pointer_press: None,
on_pointer_release: None,
on_touch_move: None,
on_touch_down: None,
on_touch_up: None,
on_touch_cancel: None,
}
dsluijk marked this conversation as resolved.
Show resolved Hide resolved
}

Expand Down Expand Up @@ -103,11 +111,103 @@ impl PointerHandler {
));
}

pub fn on_pointer_move<F>(&mut self, canvas_common: &super::Common, mut handler: F)

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
pub fn on_pointer_move<F>(&mut self, canvas_common: &super::Common, mut handler: F)
pub fn on_touch_move<F>(&mut self, canvas_common: &super::Common, mut handler: F)

where
F: 'static + FnMut(i32, PhysicalPosition<f64>),
{
self.on_touch_move = Some(canvas_common.add_event(
"pointermove",
move |event: PointerEvent| {
if event.pointer_type() != "touch" {
return;
}

handler(
event.pointer_id(),
dsluijk marked this conversation as resolved.
Show resolved Hide resolved
PhysicalPosition {
x: event.offset_x() as f64,
y: event.offset_y() as f64,
},
);
},
));
}

pub fn on_pointer_down<F>(&mut self, canvas_common: &super::Common, mut handler: F)

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
pub fn on_pointer_down<F>(&mut self, canvas_common: &super::Common, mut handler: F)
pub fn on_touch_down<F>(&mut self, canvas_common: &super::Common, mut handler: F)

where
F: 'static + FnMut(i32, PhysicalPosition<f64>),
{
self.on_touch_down = Some(canvas_common.add_event(
"pointerdown",
move |event: PointerEvent| {
if event.pointer_type() != "touch" {
return;
}

handler(
event.pointer_id(),
PhysicalPosition {
x: event.offset_x() as f64,
y: event.offset_y() as f64,
},
);
},
));
}

pub fn on_pointer_up<F>(&mut self, canvas_common: &super::Common, mut handler: F)

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
pub fn on_pointer_up<F>(&mut self, canvas_common: &super::Common, mut handler: F)
pub fn on_touch_up<F>(&mut self, canvas_common: &super::Common, mut handler: F)

where
F: 'static + FnMut(i32, PhysicalPosition<f64>),
{
self.on_touch_up = Some(canvas_common.add_event(
"pointerup",
move |event: PointerEvent| {
if event.pointer_type() != "touch" {
return;
}

handler(
event.pointer_id(),
PhysicalPosition {
x: event.offset_x() as f64,
y: event.offset_y() as f64,
},
);
},
));
}

pub fn on_pointer_cancel<F>(&mut self, canvas_common: &super::Common, mut handler: F)

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
pub fn on_pointer_cancel<F>(&mut self, canvas_common: &super::Common, mut handler: F)
pub fn on_touch_cancel<F>(&mut self, canvas_common: &super::Common, mut handler: F)

where
F: 'static + FnMut(i32, PhysicalPosition<f64>),
{
self.on_touch_cancel = Some(canvas_common.add_event(
"pointercancel",
move |event: PointerEvent| {
if event.pointer_type() != "touch" {
return;
}

handler(
event.pointer_id(),
PhysicalPosition {
x: event.offset_x() as f64,
y: event.offset_y() as f64,
},
);
},
));
}

pub fn remove_listeners(&mut self) {
self.on_cursor_leave = None;
self.on_cursor_enter = None;
self.on_cursor_move = None;
self.on_pointer_press = None;
self.on_pointer_release = None;
self.on_touch_move = None;
self.on_touch_down = None;
self.on_touch_up = None;
self.on_touch_cancel = None;
}
}