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,6 +1,7 @@
# Unreleased

- Added `Window::focus_window`to bring the window to the front and set input focus.
- On Web, added support for `Event::Touch`.
maroider marked this conversation as resolved.
Show resolved Hide resolved

# 0.25.0 (2021-05-15)

Expand Down
3 changes: 2 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,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 @@ -201,7 +201,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
15 changes: 15 additions & 0 deletions src/event.rs
Original file line number Diff line number Diff line change
Expand Up @@ -663,6 +663,21 @@ pub struct Touch {
pub force: Option<Force>,
/// Unique identifier of a finger.
pub id: u64,
/// Type of pointer used when touching.
///
/// ## Platform-specific
///
/// - Currently only available on Web targets.
pub pointer_type: Option<PointerType>,
maroider marked this conversation as resolved.
Show resolved Hide resolved
}

/// Describes the types of pointers available.
#[derive(Debug, Clone, Copy, PartialEq)]
pub enum PointerType {
Mouse,
Pen,
Touch,
Unknown,
}

/// Describes the force of a touch event
Expand Down
1 change: 1 addition & 0 deletions src/platform_impl/android/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -227,6 +227,7 @@ impl<T: 'static> EventLoop<T> {
location,
id: pointer.pointer_id() as u64,
force: None,
pointer_type: None,
},
),
};
Expand Down
1 change: 1 addition & 0 deletions src/platform_impl/ios/view.rs
Original file line number Diff line number Diff line change
Expand Up @@ -271,6 +271,7 @@ unsafe fn get_view_class(root_view_class: &'static Class) -> &'static Class {
device_id: RootDeviceId(DeviceId { uiscreen }),
id: touch_id,
location: physical_location,
pointer_type: None,
force,
phase,
}),
Expand Down
4 changes: 4 additions & 0 deletions src/platform_impl/linux/wayland/seat/touch/handlers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ pub(super) fn handle_touch(
location: position.to_physical(scale_factor),
force: None, // TODO
id: id as u64,
pointer_type: None,
}),
window_id,
);
Expand Down Expand Up @@ -67,6 +68,7 @@ pub(super) fn handle_touch(
location,
force: None, // TODO
id: id as u64,
pointer_type: None,
}),
window_id,
);
Expand All @@ -92,6 +94,7 @@ pub(super) fn handle_touch(
location,
force: None, // TODO
id: id as u64,
pointer_type: None,
}),
window_id,
);
Expand All @@ -112,6 +115,7 @@ pub(super) fn handle_touch(
location,
force: None, // TODO
id: touch_point.id as u64,
pointer_type: None,
}),
window_id,
);
Expand Down
1 change: 1 addition & 0 deletions src/platform_impl/linux/x11/event_processor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1006,6 +1006,7 @@ impl<T: 'static> EventProcessor<T> {
location,
force: None, // TODO
id,
pointer_type: None,
}),
})
}
Expand Down
62 changes: 61 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,66 @@ impl<T> WindowTarget<T> {
runner.request_redraw(WindowId(id));
});

let runner = self.runner.clone();
canvas.on_pointer_move(move |device_id, location, pointer_type| {
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
pointer_type: Some(pointer_type),
location,
}),
});
});

let runner = self.runner.clone();
canvas.on_pointer_down(move |device_id, location, pointer_type| {
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
pointer_type: Some(pointer_type),
location,
}),
});
});

let runner = self.runner.clone();
canvas.on_pointer_up(move |device_id, location, pointer_type| {
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
pointer_type: Some(pointer_type),
location,
}),
});
});

let runner = self.runner.clone();
canvas.on_pointer_cancel(move |device_id, location, pointer_type| {
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
pointer_type: Some(pointer_type),
location,
}),
});
});

let runner = self.runner.clone();
canvas.on_dark_mode(move |is_dark_mode| {
let theme = if is_dark_mode {
Expand Down
44 changes: 43 additions & 1 deletion src/platform_impl/web/web_sys/canvas.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,9 @@ use super::event_handle::EventListenerHandle;
use super::media_query_handle::MediaQueryListHandle;
use crate::dpi::{LogicalPosition, PhysicalPosition, PhysicalSize};
use crate::error::OsError as RootOE;
use crate::event::{ModifiersState, MouseButton, MouseScrollDelta, ScanCode, VirtualKeyCode};
use crate::event::{
ModifiersState, MouseButton, MouseScrollDelta, PointerType, ScanCode, VirtualKeyCode,
};
use crate::platform_impl::{OsError, PlatformSpecificWindowBuilderAttributes};

use std::cell::RefCell;
Expand Down Expand Up @@ -247,6 +249,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>, PointerType),
{
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>, PointerType),
{
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>, PointerType),
{
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>, PointerType),
{
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
110 changes: 109 additions & 1 deletion src/platform_impl/web/web_sys/canvas/pointer_handler.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use super::event;
use super::EventListenerHandle;
use crate::dpi::PhysicalPosition;
use crate::event::{ModifiersState, MouseButton};
use crate::event::{ModifiersState, MouseButton, PointerType};

use web_sys::PointerEvent;

Expand All @@ -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_pointer_move: Option<EventListenerHandle<dyn FnMut(PointerEvent)>>,
on_pointer_down: Option<EventListenerHandle<dyn FnMut(PointerEvent)>>,
on_pointer_up: Option<EventListenerHandle<dyn FnMut(PointerEvent)>>,
on_pointer_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_pointer_move: None,
on_pointer_down: None,
on_pointer_up: None,
on_pointer_cancel: None,
}
dsluijk marked this conversation as resolved.
Show resolved Hide resolved
}

Expand Down Expand Up @@ -103,11 +111,111 @@ 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>, PointerType),
{
self.on_pointer_move = Some(canvas_common.add_event(
"pointermove",
move |event: PointerEvent| {
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,
},
match event.pointer_type().as_str() {
"mouse" => PointerType::Mouse,
"pen" => PointerType::Pen,
"touch" => PointerType::Touch,
_ => PointerType::Unknown,
},
);
},
));
}

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>, PointerType),
{
self.on_pointer_down = Some(canvas_common.add_event(
"pointerdown",
move |event: PointerEvent| {
handler(
event.pointer_id(),
PhysicalPosition {
x: event.offset_x() as f64,
y: event.offset_y() as f64,
},
match event.pointer_type().as_str() {
"mouse" => PointerType::Mouse,
"pen" => PointerType::Pen,
"touch" => PointerType::Touch,
_ => PointerType::Unknown,
},
);
},
));
}

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>, PointerType),
{
self.on_pointer_up = Some(canvas_common.add_event(
"pointerup",
move |event: PointerEvent| {
handler(
event.pointer_id(),
PhysicalPosition {
x: event.offset_x() as f64,
y: event.offset_y() as f64,
},
match event.pointer_type().as_str() {
"mouse" => PointerType::Mouse,
"pen" => PointerType::Pen,
"touch" => PointerType::Touch,
_ => PointerType::Unknown,
},
);
},
));
}

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>, PointerType),
{
self.on_pointer_cancel = Some(canvas_common.add_event(
"pointercancel",
move |event: PointerEvent| {
handler(
event.pointer_id(),
PhysicalPosition {
x: event.offset_x() as f64,
y: event.offset_y() as f64,
},
match event.pointer_type().as_str() {
"mouse" => PointerType::Mouse,
"pen" => PointerType::Pen,
"touch" => PointerType::Touch,
_ => PointerType::Unknown,
},
);
},
));
}

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_pointer_move = None;
self.on_pointer_down = None;
self.on_pointer_up = None;
self.on_pointer_cancel = None;
}
}
2 changes: 2 additions & 0 deletions src/platform_impl/windows/event_loop.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1445,6 +1445,7 @@ unsafe fn public_window_callback_inner<T: 'static>(
force: None, // WM_TOUCH doesn't support pressure information
id: input.dwID as u64,
device_id: DEVICE_ID,
pointer_type: None,
}),
});
}
Expand Down Expand Up @@ -1584,6 +1585,7 @@ unsafe fn public_window_callback_inner<T: 'static>(
force,
id: pointer_info.pointerId as u64,
device_id: DEVICE_ID,
pointer_type: None,
}),
});
}
Expand Down