Add raw mouse wheel event (#2782)
* Add raw mouse wheel event The event is sent as it comes from the backend, so it will follow different conventions depending on the target, and it is up to the user code to deal with that. The goal is to allow advanced users to implement alternative UI controls, e.g., using Ctrl to scroll the plot horizontally instead of zooming, or use Shift to scroll faster instead of changing direction. * Change Pixel to Point for consistency Apply suggestions from code review by emilk Co-authored-by: Emil Ernerfeldt <emil.ernerfeldt@gmail.com> * Inline mouse wheel raw event closure It was meant only to be able to use the same variable names without shadowing the rest of the code, but a simple block accomplishes the same thing. * Use wildcard on wheel event match Co-authored-by: Emil Ernerfeldt <emil.ernerfeldt@gmail.com> * Flip mouse wheel delta sign on web to match native * Use wheel event data to generate scroll event To avoid doing the same match and sign conversion twice. --------- Co-authored-by: Emil Ernerfeldt <emil.ernerfeldt@gmail.com>
This commit is contained in:
parent
89e42884fc
commit
8326fffdb0
|
|
@ -448,20 +448,33 @@ pub fn install_canvas_events(runner_container: &mut AppRunnerContainer) -> Resul
|
|||
&canvas,
|
||||
"wheel",
|
||||
|event: web_sys::WheelEvent, mut runner_lock| {
|
||||
let scroll_multiplier = match event.delta_mode() {
|
||||
web_sys::WheelEvent::DOM_DELTA_PAGE => {
|
||||
canvas_size_in_points(runner_lock.canvas_id()).y
|
||||
}
|
||||
web_sys::WheelEvent::DOM_DELTA_LINE => {
|
||||
let unit = match event.delta_mode() {
|
||||
web_sys::WheelEvent::DOM_DELTA_PIXEL => egui::MouseWheelUnit::Point,
|
||||
web_sys::WheelEvent::DOM_DELTA_LINE => egui::MouseWheelUnit::Line,
|
||||
web_sys::WheelEvent::DOM_DELTA_PAGE => egui::MouseWheelUnit::Page,
|
||||
_ => return,
|
||||
};
|
||||
// delta sign is flipped to match native (winit) convention.
|
||||
let delta = -egui::vec2(event.delta_x() as f32, event.delta_y() as f32);
|
||||
let modifiers = runner_lock.input.raw.modifiers;
|
||||
|
||||
runner_lock.input.raw.events.push(egui::Event::MouseWheel {
|
||||
unit,
|
||||
delta,
|
||||
modifiers,
|
||||
});
|
||||
|
||||
let scroll_multiplier = match unit {
|
||||
egui::MouseWheelUnit::Page => canvas_size_in_points(runner_lock.canvas_id()).y,
|
||||
egui::MouseWheelUnit::Line => {
|
||||
#[allow(clippy::let_and_return)]
|
||||
let points_per_scroll_line = 8.0; // Note that this is intentionally different from what we use in winit.
|
||||
points_per_scroll_line
|
||||
}
|
||||
_ => 1.0, // DOM_DELTA_PIXEL
|
||||
egui::MouseWheelUnit::Point => 1.0,
|
||||
};
|
||||
|
||||
let mut delta =
|
||||
-scroll_multiplier * egui::vec2(event.delta_x() as f32, event.delta_y() as f32);
|
||||
let mut delta = scroll_multiplier * delta;
|
||||
|
||||
// Report a zoom event in case CTRL (on Windows or Linux) or CMD (on Mac) is pressed.
|
||||
// This if-statement is equivalent to how `Modifiers.command` is determined in
|
||||
|
|
|
|||
|
|
@ -548,6 +548,26 @@ impl State {
|
|||
}
|
||||
|
||||
fn on_mouse_wheel(&mut self, delta: winit::event::MouseScrollDelta) {
|
||||
{
|
||||
let (unit, delta) = match delta {
|
||||
winit::event::MouseScrollDelta::LineDelta(x, y) => {
|
||||
(egui::MouseWheelUnit::Line, egui::vec2(x, y))
|
||||
}
|
||||
winit::event::MouseScrollDelta::PixelDelta(winit::dpi::PhysicalPosition {
|
||||
x,
|
||||
y,
|
||||
}) => (
|
||||
egui::MouseWheelUnit::Point,
|
||||
egui::vec2(x as f32, y as f32) / self.pixels_per_point(),
|
||||
),
|
||||
};
|
||||
let modifiers = self.egui_input.modifiers;
|
||||
self.egui_input.events.push(egui::Event::MouseWheel {
|
||||
unit,
|
||||
delta,
|
||||
modifiers,
|
||||
});
|
||||
}
|
||||
let delta = match delta {
|
||||
winit::event::MouseScrollDelta::LineDelta(x, y) => {
|
||||
let points_per_scroll_line = 50.0; // Scroll speed decided by consensus: https://github.com/emilk/egui/issues/461
|
||||
|
|
|
|||
|
|
@ -278,6 +278,22 @@ pub enum Event {
|
|||
force: f32,
|
||||
},
|
||||
|
||||
/// A raw mouse wheel event as sent by the backend (minus the z coordinate),
|
||||
/// for implementing alternative custom controls.
|
||||
/// Note that the same event can also trigger [`Self::Zoom`] and [`Self::Scroll`],
|
||||
/// so you probably want to handle only one of them.
|
||||
MouseWheel {
|
||||
/// The unit of scrolling: points, lines, or pages.
|
||||
unit: MouseWheelUnit,
|
||||
|
||||
/// The amount scrolled horizontally and vertically. The amount and direction corresponding
|
||||
/// to one step of the wheel depends on the platform.
|
||||
delta: Vec2,
|
||||
|
||||
/// The state of the modifier keys at the time of the event.
|
||||
modifiers: Modifiers,
|
||||
},
|
||||
|
||||
/// An assistive technology (e.g. screen reader) requested an action.
|
||||
#[cfg(feature = "accesskit")]
|
||||
AccessKitActionRequest(accesskit::ActionRequest),
|
||||
|
|
@ -891,6 +907,20 @@ pub enum TouchPhase {
|
|||
Cancel,
|
||||
}
|
||||
|
||||
/// The unit associated with the numeric value of a mouse wheel event
|
||||
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
|
||||
#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
|
||||
pub enum MouseWheelUnit {
|
||||
/// Number of ui points (logical pixels)
|
||||
Point,
|
||||
|
||||
/// Number of lines
|
||||
Line,
|
||||
|
||||
/// Number of pages
|
||||
Page,
|
||||
}
|
||||
|
||||
impl From<u64> for TouchId {
|
||||
fn from(id: u64) -> Self {
|
||||
Self(id)
|
||||
|
|
|
|||
Loading…
Reference in New Issue