Split modifier handling in all pointer events

This commit is contained in:
dAxpeDDa 2023-06-04 02:16:55 +02:00 committed by daxpedda
parent 964e342f69
commit b4b2389d0a
3 changed files with 198 additions and 131 deletions

View file

@ -198,51 +198,65 @@ impl<T> EventLoopWindowTarget<T> {
prevent_default, prevent_default,
); );
let runner = self.runner.clone(); canvas.on_cursor_leave(
let modifiers = self.modifiers.clone(); {
let has_focus_clone = has_focus.clone(); let runner = self.runner.clone();
canvas.on_cursor_leave(move |pointer_id, active_modifiers| { let has_focus = has_focus.clone();
let modifiers_changed = (has_focus_clone.get() && modifiers.get() != active_modifiers) let modifiers = self.modifiers.clone();
.then(|| {
modifiers.set(active_modifiers); move |active_modifiers| {
Event::WindowEvent { if has_focus.get() && modifiers.get() != active_modifiers {
window_id: RootWindowId(id), modifiers.set(active_modifiers);
event: WindowEvent::ModifiersChanged(active_modifiers.into()), runner.send_event(Event::WindowEvent {
window_id: RootWindowId(id),
event: WindowEvent::ModifiersChanged(active_modifiers.into()),
});
} }
}); }
},
{
let runner = self.runner.clone();
runner.send_events(modifiers_changed.into_iter().chain(iter::once( move |pointer_id| {
Event::WindowEvent { runner.send_event(Event::WindowEvent {
window_id: RootWindowId(id),
event: WindowEvent::CursorLeft {
device_id: RootDeviceId(DeviceId(pointer_id)),
},
},
)));
});
let runner = self.runner.clone();
let modifiers = self.modifiers.clone();
let has_focus_clone = has_focus.clone();
canvas.on_cursor_enter(move |pointer_id, active_modifiers| {
let modifiers_changed = (has_focus_clone.get() && modifiers.get() != active_modifiers)
.then(|| {
modifiers.set(active_modifiers);
Event::WindowEvent {
window_id: RootWindowId(id), window_id: RootWindowId(id),
event: WindowEvent::ModifiersChanged(active_modifiers.into()), event: WindowEvent::CursorLeft {
} device_id: RootDeviceId(DeviceId(pointer_id)),
}); },
});
}
},
);
runner.send_events(modifiers_changed.into_iter().chain(iter::once( canvas.on_cursor_enter(
Event::WindowEvent { {
window_id: RootWindowId(id), let runner = self.runner.clone();
event: WindowEvent::CursorEntered { let has_focus = has_focus.clone();
device_id: RootDeviceId(DeviceId(pointer_id)), let modifiers = self.modifiers.clone();
},
}, move |active_modifiers| {
))); if has_focus.get() && modifiers.get() != active_modifiers {
}); modifiers.set(active_modifiers);
runner.send_event(Event::WindowEvent {
window_id: RootWindowId(id),
event: WindowEvent::ModifiersChanged(active_modifiers.into()),
});
}
}
},
{
let runner = self.runner.clone();
move |pointer_id| {
runner.send_event(Event::WindowEvent {
window_id: RootWindowId(id),
event: WindowEvent::CursorEntered {
device_id: RootDeviceId(DeviceId(pointer_id)),
},
});
}
},
);
canvas.on_cursor_move( canvas.on_cursor_move(
{ {
@ -350,35 +364,43 @@ impl<T> EventLoopWindowTarget<T> {
let runner = self.runner.clone(); let runner = self.runner.clone();
let modifiers = self.modifiers.clone(); let modifiers = self.modifiers.clone();
move |pointer_id, position, button, active_modifiers| { move |active_modifiers| {
let modifiers_changed = (modifiers.get() != active_modifiers).then(|| { if modifiers.get() != active_modifiers {
modifiers.set(active_modifiers); modifiers.set(active_modifiers);
Event::WindowEvent { runner.send_event(Event::WindowEvent {
window_id: RootWindowId(id), window_id: RootWindowId(id),
event: WindowEvent::ModifiersChanged(active_modifiers.into()), event: WindowEvent::ModifiersChanged(active_modifiers.into()),
} })
}); }
}
},
{
let runner = self.runner.clone();
move |pointer_id, position, button| {
// A mouse down event may come in without any prior CursorMoved events, // A mouse down event may come in without any prior CursorMoved events,
// therefore we should send a CursorMoved event to make sure that the // therefore we should send a CursorMoved event to make sure that the
// user code has the correct cursor position. // user code has the correct cursor position.
runner.send_events(modifiers_changed.into_iter().chain([ runner.send_events(
Event::WindowEvent { [
window_id: RootWindowId(id), Event::WindowEvent {
event: WindowEvent::CursorMoved { window_id: RootWindowId(id),
device_id: RootDeviceId(DeviceId(pointer_id)), event: WindowEvent::CursorMoved {
position, device_id: RootDeviceId(DeviceId(pointer_id)),
position,
},
}, },
}, Event::WindowEvent {
Event::WindowEvent { window_id: RootWindowId(id),
window_id: RootWindowId(id), event: WindowEvent::MouseInput {
event: WindowEvent::MouseInput { device_id: RootDeviceId(DeviceId(pointer_id)),
device_id: RootDeviceId(DeviceId(pointer_id)), state: ElementState::Pressed,
state: ElementState::Pressed, button,
button, },
}, },
}, ]
])); .into_iter(),
);
} }
}, },
{ {
@ -403,39 +425,46 @@ impl<T> EventLoopWindowTarget<T> {
canvas.on_mouse_release( canvas.on_mouse_release(
{ {
let runner = self.runner.clone(); let runner = self.runner.clone();
let modifiers = self.modifiers.clone();
let has_focus = has_focus.clone(); let has_focus = has_focus.clone();
let modifiers = self.modifiers.clone();
move |pointer_id, position, button, active_modifiers| { move |active_modifiers| {
let modifiers_changed = if has_focus.get() && modifiers.get() != active_modifiers {
(has_focus.get() && modifiers.get() != active_modifiers).then(|| { modifiers.set(active_modifiers);
modifiers.set(active_modifiers); runner.send_event(Event::WindowEvent {
Event::WindowEvent { window_id: RootWindowId(id),
window_id: RootWindowId(id), event: WindowEvent::ModifiersChanged(active_modifiers.into()),
event: WindowEvent::ModifiersChanged(active_modifiers.into()),
}
}); });
}
}
},
{
let runner = self.runner.clone();
move |pointer_id, position, button| {
// A mouse up event may come in without any prior CursorMoved events, // A mouse up event may come in without any prior CursorMoved events,
// therefore we should send a CursorMoved event to make sure that the // therefore we should send a CursorMoved event to make sure that the
// user code has the correct cursor position. // user code has the correct cursor position.
runner.send_events(modifiers_changed.into_iter().chain([ runner.send_events(
Event::WindowEvent { [
window_id: RootWindowId(id), Event::WindowEvent {
event: WindowEvent::CursorMoved { window_id: RootWindowId(id),
device_id: RootDeviceId(DeviceId(pointer_id)), event: WindowEvent::CursorMoved {
position, device_id: RootDeviceId(DeviceId(pointer_id)),
position,
},
}, },
}, Event::WindowEvent {
Event::WindowEvent { window_id: RootWindowId(id),
window_id: RootWindowId(id), event: WindowEvent::MouseInput {
event: WindowEvent::MouseInput { device_id: RootDeviceId(DeviceId(pointer_id)),
device_id: RootDeviceId(DeviceId(pointer_id)), state: ElementState::Released,
state: ElementState::Released, button,
button, },
}, },
}, ]
])); .into_iter(),
);
} }
}, },
{ {

View file

@ -212,40 +212,56 @@ impl Canvas {
)); ));
} }
pub fn on_cursor_leave<F>(&mut self, handler: F) pub fn on_cursor_leave<MOD, M>(&mut self, modifier_handler: MOD, mouse_handler: M)
where where
F: 'static + FnMut(i32, ModifiersState), MOD: 'static + FnMut(ModifiersState),
{ M: 'static + FnMut(i32),
self.pointer_handler.on_cursor_leave(&self.common, handler)
}
pub fn on_cursor_enter<F>(&mut self, handler: F)
where
F: 'static + FnMut(i32, ModifiersState),
{
self.pointer_handler.on_cursor_enter(&self.common, handler)
}
pub fn on_mouse_release<M, T>(&mut self, mouse_handler: M, touch_handler: T)
where
M: 'static + FnMut(i32, PhysicalPosition<f64>, MouseButton, ModifiersState),
T: 'static + FnMut(i32, PhysicalPosition<f64>, Force),
{ {
self.pointer_handler self.pointer_handler
.on_mouse_release(&self.common, mouse_handler, touch_handler) .on_cursor_leave(&self.common, modifier_handler, mouse_handler)
} }
pub fn on_mouse_press<M, T>( pub fn on_cursor_enter<MOD, M>(&mut self, modifier_handler: MOD, mouse_handler: M)
where
MOD: 'static + FnMut(ModifiersState),
M: 'static + FnMut(i32),
{
self.pointer_handler
.on_cursor_enter(&self.common, modifier_handler, mouse_handler)
}
pub fn on_mouse_release<MOD, M, T>(
&mut self, &mut self,
modifier_handler: MOD,
mouse_handler: M,
touch_handler: T,
) where
MOD: 'static + FnMut(ModifiersState),
M: 'static + FnMut(i32, PhysicalPosition<f64>, MouseButton),
T: 'static + FnMut(i32, PhysicalPosition<f64>, Force),
{
self.pointer_handler.on_mouse_release(
&self.common,
modifier_handler,
mouse_handler,
touch_handler,
)
}
pub fn on_mouse_press<MOD, M, T>(
&mut self,
modifier_handler: MOD,
mouse_handler: M, mouse_handler: M,
touch_handler: T, touch_handler: T,
prevent_default: bool, prevent_default: bool,
) where ) where
M: 'static + FnMut(i32, PhysicalPosition<f64>, MouseButton, ModifiersState), MOD: 'static + FnMut(ModifiersState),
M: 'static + FnMut(i32, PhysicalPosition<f64>, MouseButton),
T: 'static + FnMut(i32, PhysicalPosition<f64>, Force), T: 'static + FnMut(i32, PhysicalPosition<f64>, Force),
{ {
self.pointer_handler.on_mouse_press( self.pointer_handler.on_mouse_press(
&self.common, &self.common,
modifier_handler,
mouse_handler, mouse_handler,
touch_handler, touch_handler,
prevent_default, prevent_default,

View file

@ -32,13 +32,20 @@ impl PointerHandler {
} }
} }
pub fn on_cursor_leave<F>(&mut self, canvas_common: &Common, mut handler: F) pub fn on_cursor_leave<MOD, M>(
where &mut self,
F: 'static + FnMut(i32, ModifiersState), canvas_common: &Common,
mut modifier_handler: MOD,
mut mouse_handler: M,
) where
MOD: 'static + FnMut(ModifiersState),
M: 'static + FnMut(i32),
{ {
self.on_cursor_leave = Some(canvas_common.add_event( self.on_cursor_leave = Some(canvas_common.add_event(
"pointerout", "pointerout",
move |event: PointerEvent| { move |event: PointerEvent| {
modifier_handler(event::mouse_modifiers(&event));
// touch events are handled separately // touch events are handled separately
// handling them here would produce duplicate mouse events, inconsistent with // handling them here would produce duplicate mouse events, inconsistent with
// other platforms. // other platforms.
@ -46,18 +53,25 @@ impl PointerHandler {
return; return;
} }
handler(event.pointer_id(), event::mouse_modifiers(&event)); mouse_handler(event.pointer_id());
}, },
)); ));
} }
pub fn on_cursor_enter<F>(&mut self, canvas_common: &Common, mut handler: F) pub fn on_cursor_enter<MOD, M>(
where &mut self,
F: 'static + FnMut(i32, ModifiersState), canvas_common: &Common,
mut modifier_handler: MOD,
mut mouse_handler: M,
) where
MOD: 'static + FnMut(ModifiersState),
M: 'static + FnMut(i32),
{ {
self.on_cursor_enter = Some(canvas_common.add_event( self.on_cursor_enter = Some(canvas_common.add_event(
"pointerover", "pointerover",
move |event: PointerEvent| { move |event: PointerEvent| {
modifier_handler(event::mouse_modifiers(&event));
// touch events are handled separately // touch events are handled separately
// handling them here would produce duplicate mouse events, inconsistent with // handling them here would produce duplicate mouse events, inconsistent with
// other platforms. // other platforms.
@ -65,48 +79,55 @@ impl PointerHandler {
return; return;
} }
handler(event.pointer_id(), event::mouse_modifiers(&event)); mouse_handler(event.pointer_id());
}, },
)); ));
} }
pub fn on_mouse_release<M, T>( pub fn on_mouse_release<MOD, M, T>(
&mut self, &mut self,
canvas_common: &Common, canvas_common: &Common,
mut modifier_handler: MOD,
mut mouse_handler: M, mut mouse_handler: M,
mut touch_handler: T, mut touch_handler: T,
) where ) where
M: 'static + FnMut(i32, PhysicalPosition<f64>, MouseButton, ModifiersState), MOD: 'static + FnMut(ModifiersState),
M: 'static + FnMut(i32, PhysicalPosition<f64>, MouseButton),
T: 'static + FnMut(i32, PhysicalPosition<f64>, Force), T: 'static + FnMut(i32, PhysicalPosition<f64>, Force),
{ {
let canvas = canvas_common.raw.clone(); let canvas = canvas_common.raw.clone();
self.on_pointer_release = Some(canvas_common.add_user_event( self.on_pointer_release = Some(canvas_common.add_user_event(
"pointerup", "pointerup",
move |event: PointerEvent| match event.pointer_type().as_str() { move |event: PointerEvent| {
"touch" => touch_handler( modifier_handler(event::mouse_modifiers(&event));
event.pointer_id(),
event::touch_position(&event, &canvas).to_physical(super::scale_factor()), match event.pointer_type().as_str() {
Force::Normalized(event.pressure() as f64), "touch" => touch_handler(
), event.pointer_id(),
"mouse" => mouse_handler( event::touch_position(&event, &canvas).to_physical(super::scale_factor()),
event.pointer_id(), Force::Normalized(event.pressure() as f64),
event::mouse_position(&event).to_physical(super::scale_factor()), ),
event::mouse_button(&event).expect("no mouse button released"), "mouse" => mouse_handler(
event::mouse_modifiers(&event), event.pointer_id(),
), event::mouse_position(&event).to_physical(super::scale_factor()),
_ => (), event::mouse_button(&event).expect("no mouse button released"),
),
_ => (),
}
}, },
)); ));
} }
pub fn on_mouse_press<M, T>( pub fn on_mouse_press<MOD, M, T>(
&mut self, &mut self,
canvas_common: &Common, canvas_common: &Common,
mut modifier_handler: MOD,
mut mouse_handler: M, mut mouse_handler: M,
mut touch_handler: T, mut touch_handler: T,
prevent_default: bool, prevent_default: bool,
) where ) where
M: 'static + FnMut(i32, PhysicalPosition<f64>, MouseButton, ModifiersState), MOD: 'static + FnMut(ModifiersState),
M: 'static + FnMut(i32, PhysicalPosition<f64>, MouseButton),
T: 'static + FnMut(i32, PhysicalPosition<f64>, Force), T: 'static + FnMut(i32, PhysicalPosition<f64>, Force),
{ {
let canvas = canvas_common.raw.clone(); let canvas = canvas_common.raw.clone();
@ -120,6 +141,8 @@ impl PointerHandler {
let _ = canvas.focus(); let _ = canvas.focus();
} }
modifier_handler(event::mouse_modifiers(&event));
match event.pointer_type().as_str() { match event.pointer_type().as_str() {
"touch" => { "touch" => {
touch_handler( touch_handler(
@ -134,7 +157,6 @@ impl PointerHandler {
event.pointer_id(), event.pointer_id(),
event::mouse_position(&event).to_physical(super::scale_factor()), event::mouse_position(&event).to_physical(super::scale_factor()),
event::mouse_button(&event).expect("no mouse button pressed"), event::mouse_button(&event).expect("no mouse button pressed"),
event::mouse_modifiers(&event),
); );
// Error is swallowed here since the error would occur every time the mouse is // Error is swallowed here since the error would occur every time the mouse is