Skip to content

Commit

Permalink
Enable event propagation (#3062)
Browse files Browse the repository at this point in the history
  • Loading branch information
daxpedda committed Aug 28, 2023
1 parent 7541220 commit 1dfca5a
Show file tree
Hide file tree
Showing 7 changed files with 76 additions and 177 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ And please only add new entries to the top of this list, right below the `# Unre
- On Web, never return a `MonitorHandle`.
- **Breaking:** Move `Event::RedrawRequested` to `WindowEvent::RedrawRequested`.
- On macOS, fix crash in `window.set_minimized(false)`.
- On Web, enable event propagation and let `DeviceEvent`s appear after `WindowEvent`s.

# 0.29.1-beta

Expand Down
16 changes: 8 additions & 8 deletions src/platform_impl/web/event_loop/runner.rs
Original file line number Diff line number Diff line change
Expand Up @@ -201,7 +201,7 @@ impl<T: 'static> Shared<T> {
self.init();

*self.0.page_transition_event_handle.borrow_mut() = Some(backend::on_page_transition(
self.window(),
self.window().clone(),
{
let runner = self.clone();
move |event: PageTransitionEvent| {
Expand All @@ -227,7 +227,7 @@ impl<T: 'static> Shared<T> {
let runner = self.clone();
let window = self.window().clone();
*self.0.on_mouse_move.borrow_mut() = Some(EventListenerHandle::new(
self.window(),
self.window().clone(),
"pointermove",
Closure::new(move |event: PointerEvent| {
if !runner.device_events() {
Expand Down Expand Up @@ -304,7 +304,7 @@ impl<T: 'static> Shared<T> {
let runner = self.clone();
let window = self.window().clone();
*self.0.on_wheel.borrow_mut() = Some(EventListenerHandle::new(
self.window(),
self.window().clone(),
"wheel",
Closure::new(move |event: WheelEvent| {
if !runner.device_events() {
Expand All @@ -321,7 +321,7 @@ impl<T: 'static> Shared<T> {
));
let runner = self.clone();
*self.0.on_mouse_press.borrow_mut() = Some(EventListenerHandle::new(
self.window(),
self.window().clone(),
"pointerdown",
Closure::new(move |event: PointerEvent| {
if !runner.device_events() {
Expand All @@ -344,7 +344,7 @@ impl<T: 'static> Shared<T> {
));
let runner = self.clone();
*self.0.on_mouse_release.borrow_mut() = Some(EventListenerHandle::new(
self.window(),
self.window().clone(),
"pointerup",
Closure::new(move |event: PointerEvent| {
if !runner.device_events() {
Expand All @@ -367,7 +367,7 @@ impl<T: 'static> Shared<T> {
));
let runner = self.clone();
*self.0.on_key_press.borrow_mut() = Some(EventListenerHandle::new(
self.window(),
self.window().clone(),
"keydown",
Closure::new(move |event: KeyboardEvent| {
if !runner.device_events() {
Expand All @@ -385,7 +385,7 @@ impl<T: 'static> Shared<T> {
));
let runner = self.clone();
*self.0.on_key_release.borrow_mut() = Some(EventListenerHandle::new(
self.window(),
self.window().clone(),
"keyup",
Closure::new(move |event: KeyboardEvent| {
if !runner.device_events() {
Expand All @@ -404,7 +404,7 @@ impl<T: 'static> Shared<T> {
let runner = self.clone();
*self.0.on_visibility_change.borrow_mut() = Some(EventListenerHandle::new(
// Safari <14 doesn't support the `visibilitychange` event on `Window`.
self.document(),
self.document().clone(),
"visibilitychange",
Closure::new(move |_| {
if !runner.0.suspended.get() {
Expand Down
181 changes: 51 additions & 130 deletions src/platform_impl/web/event_loop/window_target.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,7 @@ use super::{
window::WindowId,
};
use crate::event::{
DeviceEvent, DeviceId as RootDeviceId, ElementState, Event, KeyEvent, RawKeyEvent, Touch,
TouchPhase, WindowEvent,
DeviceId as RootDeviceId, ElementState, Event, KeyEvent, Touch, TouchPhase, WindowEvent,
};
use crate::event_loop::DeviceEvents;
use crate::keyboard::ModifiersState;
Expand Down Expand Up @@ -140,34 +139,24 @@ impl<T> EventLoopWindowTarget<T> {

let device_id = RootDeviceId(unsafe { DeviceId::dummy() });

let device_event = runner.device_events().then_some(Event::DeviceEvent {
device_id,
event: DeviceEvent::Key(RawKeyEvent {
physical_key,
state: ElementState::Pressed,
}),
});

runner.send_events(
device_event
.into_iter()
.chain(iter::once(Event::WindowEvent {
window_id: RootWindowId(id),
event: WindowEvent::KeyboardInput {
device_id,
event: KeyEvent {
physical_key,
logical_key,
text,
location,
state: ElementState::Pressed,
repeat,
platform_specific: KeyEventExtra,
},
is_synthetic: false,
iter::once(Event::WindowEvent {
window_id: RootWindowId(id),
event: WindowEvent::KeyboardInput {
device_id,
event: KeyEvent {
physical_key,
logical_key,
text,
location,
state: ElementState::Pressed,
repeat,
platform_specific: KeyEventExtra,
},
}))
.chain(modifiers_changed),
is_synthetic: false,
},
})
.chain(modifiers_changed),
);
},
prevent_default,
Expand All @@ -187,34 +176,24 @@ impl<T> EventLoopWindowTarget<T> {

let device_id = RootDeviceId(unsafe { DeviceId::dummy() });

let device_event = runner.device_events().then_some(Event::DeviceEvent {
device_id,
event: DeviceEvent::Key(RawKeyEvent {
physical_key,
state: ElementState::Pressed,
}),
});

runner.send_events(
device_event
.into_iter()
.chain(iter::once(Event::WindowEvent {
window_id: RootWindowId(id),
event: WindowEvent::KeyboardInput {
device_id,
event: KeyEvent {
physical_key,
logical_key,
text,
location,
state: ElementState::Released,
repeat,
platform_specific: KeyEventExtra,
},
is_synthetic: false,
iter::once(Event::WindowEvent {
window_id: RootWindowId(id),
event: WindowEvent::KeyboardInput {
device_id,
event: KeyEvent {
physical_key,
logical_key,
text,
location,
state: ElementState::Released,
repeat,
platform_specific: KeyEventExtra,
},
}))
.chain(modifiers_changed),
is_synthetic: false,
},
})
.chain(modifiers_changed),
)
},
prevent_default,
Expand Down Expand Up @@ -311,48 +290,17 @@ impl<T> EventLoopWindowTarget<T> {
}
});

runner.send_events(modifiers.into_iter().chain(events.flat_map(
|(position, delta)| {
let device_id = RootDeviceId(DeviceId(pointer_id));

let device_events = runner.device_events().then(|| {
let x_motion = (delta.x != 0.0).then_some(Event::DeviceEvent {
device_id,
event: DeviceEvent::Motion {
axis: 0,
value: delta.x,
},
});

let y_motion = (delta.y != 0.0).then_some(Event::DeviceEvent {
device_id,
event: DeviceEvent::Motion {
axis: 1,
value: delta.y,
},
});

x_motion.into_iter().chain(y_motion).chain(iter::once(
Event::DeviceEvent {
device_id,
event: DeviceEvent::MouseMotion {
delta: (delta.x, delta.y),
},
},
))
});

device_events.into_iter().flatten().chain(iter::once(
Event::WindowEvent {
window_id: RootWindowId(id),
event: WindowEvent::CursorMoved {
device_id,
position,
},
},
))
},
)));
runner.send_events(modifiers.into_iter().chain(events.flat_map(|position| {
let device_id = RootDeviceId(DeviceId(pointer_id));

iter::once(Event::WindowEvent {
window_id: RootWindowId(id),
event: WindowEvent::CursorMoved {
device_id,
position,
},
})
})));
}
},
{
Expand Down Expand Up @@ -413,18 +361,10 @@ impl<T> EventLoopWindowTarget<T> {
ElementState::Released
};

let device_event = runner.device_events().then(|| Event::DeviceEvent {
device_id,
event: DeviceEvent::Button {
button: button.to_id(),
state,
},
});

// A chorded button event may come in without any prior CursorMoved events,
// therefore we should send a CursorMoved event to make sure that the
// user code has the correct cursor position.
runner.send_events(modifiers.into_iter().chain(device_event).chain([
runner.send_events(modifiers.into_iter().chain([
Event::WindowEvent {
window_id: RootWindowId(id),
event: WindowEvent::CursorMoved {
Expand Down Expand Up @@ -475,18 +415,11 @@ impl<T> EventLoopWindowTarget<T> {
});

let device_id: RootDeviceId = RootDeviceId(DeviceId(pointer_id));
let device_event = runner.device_events().then(|| Event::DeviceEvent {
device_id,
event: DeviceEvent::Button {
button: button.to_id(),
state: ElementState::Pressed,
},
});

// A mouse down event may come in without any prior CursorMoved events,
// therefore we should send a CursorMoved event to make sure that the
// user code has the correct cursor position.
runner.send_events(modifiers.into_iter().chain(device_event).chain([
runner.send_events(modifiers.into_iter().chain([
Event::WindowEvent {
window_id: RootWindowId(id),
event: WindowEvent::CursorMoved {
Expand Down Expand Up @@ -568,18 +501,11 @@ impl<T> EventLoopWindowTarget<T> {
});

let device_id: RootDeviceId = RootDeviceId(DeviceId(pointer_id));
let device_event = runner.device_events().then(|| Event::DeviceEvent {
device_id,
event: DeviceEvent::Button {
button: button.to_id(),
state: ElementState::Pressed,
},
});

// A mouse up event may come in without any prior CursorMoved events,
// therefore we should send a CursorMoved event to make sure that the
// user code has the correct cursor position.
runner.send_events(modifiers.into_iter().chain(device_event).chain([
runner.send_events(modifiers.into_iter().chain([
Event::WindowEvent {
window_id: RootWindowId(id),
event: WindowEvent::CursorMoved {
Expand Down Expand Up @@ -644,21 +570,16 @@ impl<T> EventLoopWindowTarget<T> {
}
});

let device_event = runner.device_events().then_some(Event::DeviceEvent {
device_id: RootDeviceId(DeviceId(pointer_id)),
event: DeviceEvent::MouseWheel { delta },
});

runner.send_events(modifiers_changed.into_iter().chain(device_event).chain(
iter::once(Event::WindowEvent {
runner.send_events(modifiers_changed.into_iter().chain(iter::once(
Event::WindowEvent {
window_id: RootWindowId(id),
event: WindowEvent::MouseWheel {
device_id: RootDeviceId(DeviceId(pointer_id)),
delta,
phase: TouchPhase::Moved,
},
}),
));
},
)));
},
prevent_default,
);
Expand Down
15 changes: 3 additions & 12 deletions src/platform_impl/web/web_sys/canvas.rs
Original file line number Diff line number Diff line change
Expand Up @@ -367,12 +367,7 @@ impl Canvas {
prevent_default: bool,
) where
MOD: 'static + FnMut(ModifiersState),
M: 'static
+ FnMut(
ModifiersState,
i32,
&mut dyn Iterator<Item = (PhysicalPosition<f64>, PhysicalPosition<f64>)>,
),
M: 'static + FnMut(ModifiersState, i32, &mut dyn Iterator<Item = PhysicalPosition<f64>>),
T: 'static
+ FnMut(ModifiersState, i32, &mut dyn Iterator<Item = (PhysicalPosition<f64>, Force)>),
B: 'static + FnMut(ModifiersState, i32, PhysicalPosition<f64>, ButtonsState, MouseButton),
Expand Down Expand Up @@ -524,17 +519,13 @@ impl Common {
pub fn add_event<E, F>(
&self,
event_name: &'static str,
mut handler: F,
handler: F,
) -> EventListenerHandle<dyn FnMut(E)>
where
E: 'static + AsRef<web_sys::Event> + wasm_bindgen::convert::FromWasmAbi,
F: 'static + FnMut(E),
{
let closure = Closure::new(move |event: E| {
event.as_ref().stop_propagation();
handler(event);
});
EventListenerHandle::new(&self.raw, event_name, closure)
EventListenerHandle::new(self.raw.clone(), event_name, Closure::new(handler))
}

// The difference between add_event and add_user_event is that the latter has a special meaning
Expand Down
6 changes: 3 additions & 3 deletions src/platform_impl/web/web_sys/event_handle.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,11 @@ pub struct EventListenerHandle<T: ?Sized> {
}

impl<T: ?Sized> EventListenerHandle<T> {
pub fn new<U>(target: &U, event_type: &'static str, listener: Closure<T>) -> Self
pub fn new<U>(target: U, event_type: &'static str, listener: Closure<T>) -> Self
where
U: Clone + Into<EventTarget>,
U: Into<EventTarget>,
{
let target = target.clone().into();
let target = target.into();
target
.add_event_listener_with_callback(event_type, listener.as_ref().unchecked_ref())
.expect("Failed to add event listener");
Expand Down
Loading

0 comments on commit 1dfca5a

Please sign in to comment.