Handle scroll events and use winit Modifiers and MouseButton (#178)

This commit is contained in:
Aaron Muir Hamilton 2024-02-29 13:45:26 -05:00 committed by GitHub
parent 277160b484
commit 6500c5058b
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 124 additions and 1538 deletions

1498
Cargo.lock generated

File diff suppressed because it is too large Load Diff

View File

@ -42,8 +42,8 @@ cargo-args = ["-Zunstable-options", "-Zrustdoc-scrape-examples"]
[features] [features]
default = ["x11", "taffy"] default = ["x11", "taffy"]
x11 = ["glazier/x11"] x11 = ["winit/x11"]
wayland = ["glazier/wayland"] wayland = ["winit/wayland"]
taffy = ["dep:taffy"] taffy = ["dep:taffy"]
[dependencies] [dependencies]
@ -60,11 +60,6 @@ fnv = "1.0.7"
instant = { version = "0.1.6", features = ["wasm-bindgen"] } instant = { version = "0.1.6", features = ["wasm-bindgen"] }
winit = { version = "0.29", features = ["rwh_05"] } winit = { version = "0.29", features = ["rwh_05"] }
[dependencies.glazier]
git = "https://github.com/linebender/glazier"
rev = "8d2a4b2cafd5e6be49bfb4ac8d0bd26fe02f036e"
default-features = false
[dev-dependencies] [dev-dependencies]
env_logger = "0.10.0" env_logger = "0.10.0"
test-log = "0.2.11" test-log = "0.2.11"

View File

@ -14,20 +14,24 @@
use std::{num::NonZeroUsize, sync::Arc}; use std::{num::NonZeroUsize, sync::Arc};
use glazier::{Modifiers, PointerButton};
use vello::{ use vello::{
kurbo::{Affine, Point, Size}, kurbo::{Affine, Point, Size, Vec2},
peniko::Color, peniko::Color,
util::{RenderContext, RenderSurface}, util::{RenderContext, RenderSurface},
AaSupport, RenderParams, Renderer, RendererOptions, Scene, AaSupport, RenderParams, Renderer, RendererOptions, Scene,
}; };
use winit::{ use winit::{
event::WindowEvent, dpi::PhysicalPosition,
event::{ElementState, Modifiers, MouseButton, MouseScrollDelta, WindowEvent},
event_loop::{ControlFlow, EventLoop}, event_loop::{ControlFlow, EventLoop},
window::{Window, WindowBuilder}, window::{Window, WindowBuilder},
}; };
use crate::{app::App, view::View, widget::Event, widget::PointerCrusher}; use crate::{
app::App,
view::View,
widget::{Event, PointerCrusher, ScrollDelta},
};
// This is a bit of a hack just to get a window launched. The real version // This is a bit of a hack just to get a window launched. The real version
// would deal with multiple windows and have other ways to configure things. // would deal with multiple windows and have other ways to configure things.
@ -75,72 +79,31 @@ impl<T: Send + 'static, V: View<T> + 'static> AppLauncher<T, V> {
let mut main_state = MainState::new(self.app, window); let mut main_state = MainState::new(self.app, window);
event_loop event_loop
.run(move |event, elwt| match event { .run(move |event, elwt| {
winit::event::Event::WindowEvent { if let winit::event::Event::WindowEvent { event: e, .. } = event {
event: WindowEvent::CloseRequested, match e {
.. WindowEvent::CloseRequested => elwt.exit(),
} => elwt.exit(), WindowEvent::RedrawRequested => main_state.paint(),
winit::event::Event::WindowEvent { WindowEvent::Resized(winit::dpi::PhysicalSize { width, height }) => {
event: WindowEvent::RedrawRequested, main_state.size(Size {
.. width: width.into(),
} => main_state.paint(), height: height.into(),
winit::event::Event::WindowEvent { });
event: WindowEvent::Resized(winit::dpi::PhysicalSize { width, height }), }
.. WindowEvent::ModifiersChanged(modifiers) => main_state.mods(modifiers),
} => main_state.size(Size {
width: width.into(),
height: height.into(),
}),
winit::event::Event::WindowEvent {
event: WindowEvent::ModifiersChanged(modifiers),
..
} => {
let mut m = Modifiers::empty();
let ms = modifiers.state();
if ms.contains(winit::keyboard::ModifiersState::SHIFT) {
m |= Modifiers::SHIFT;
}
if ms.contains(winit::keyboard::ModifiersState::CONTROL) {
m |= Modifiers::CONTROL;
}
if ms.contains(winit::keyboard::ModifiersState::SUPER) {
m |= Modifiers::SUPER;
}
if ms.contains(winit::keyboard::ModifiersState::ALT) {
m |= Modifiers::ALT;
}
main_state.mods(m);
}
winit::event::Event::WindowEvent {
event:
WindowEvent::CursorMoved { WindowEvent::CursorMoved {
position: winit::dpi::PhysicalPosition { x, y }, position: winit::dpi::PhysicalPosition { x, y },
.. ..
} => main_state.pointer_move(Point { x, y }),
WindowEvent::CursorLeft { .. } => main_state.pointer_leave(),
WindowEvent::MouseInput { state, button, .. } => match state {
ElementState::Pressed => main_state.pointer_down(button),
ElementState::Released => main_state.pointer_up(button),
}, },
.. WindowEvent::MouseWheel { delta, .. } => main_state.pointer_wheel(delta),
} => main_state.pointer_move(Point { x, y }), _ => (),
winit::event::Event::WindowEvent {
event: WindowEvent::CursorLeft { .. },
..
} => main_state.pointer_leave(),
winit::event::Event::WindowEvent {
event: WindowEvent::MouseInput { state, button, .. },
..
} => {
let b = match button {
winit::event::MouseButton::Left => PointerButton::Primary,
winit::event::MouseButton::Right => PointerButton::Secondary,
winit::event::MouseButton::Middle => PointerButton::Auxiliary,
winit::event::MouseButton::Back => PointerButton::X1,
winit::event::MouseButton::Forward => PointerButton::X2,
winit::event::MouseButton::Other(_) => PointerButton::None,
};
match state {
winit::event::ElementState::Pressed => main_state.pointer_down(b),
winit::event::ElementState::Released => main_state.pointer_up(b),
} }
} }
_ => (),
}) })
.unwrap(); .unwrap();
} }
@ -187,13 +150,13 @@ where
self.window.request_redraw(); self.window.request_redraw();
} }
fn pointer_down(&mut self, button: PointerButton) { fn pointer_down(&mut self, button: MouseButton) {
self.app self.app
.window_event(Event::MouseDown(self.main_pointer.pressed(button))); .window_event(Event::MouseDown(self.main_pointer.pressed(button)));
self.window.request_redraw(); self.window.request_redraw();
} }
fn pointer_up(&mut self, button: PointerButton) { fn pointer_up(&mut self, button: MouseButton) {
self.app self.app
.window_event(Event::MouseUp(self.main_pointer.released(button))); .window_event(Event::MouseUp(self.main_pointer.released(button)));
self.window.request_redraw(); self.window.request_redraw();
@ -204,6 +167,19 @@ where
self.window.request_redraw(); self.window.request_redraw();
} }
fn pointer_wheel(&mut self, delta: MouseScrollDelta) {
self.app
.window_event(Event::MouseWheel(self.main_pointer.wheel(match delta {
MouseScrollDelta::LineDelta(x, y) => {
ScrollDelta::Lines(x.trunc() as isize, y.trunc() as isize)
}
MouseScrollDelta::PixelDelta(PhysicalPosition { x, y }) => {
ScrollDelta::Precise(Vec2::new(x, y) * (1.0 / self.window.scale_factor()))
}
})));
self.window.request_redraw();
}
fn paint(&mut self) { fn paint(&mut self) {
self.app.paint(); self.app.paint();
self.render(); self.render();

View File

@ -34,7 +34,7 @@ pub use box_constraints::BoxConstraints;
pub use button::Button; pub use button::Button;
pub use contexts::{CxState, EventCx, LayoutCx, LifeCycleCx, PaintCx, UpdateCx}; pub use contexts::{CxState, EventCx, LayoutCx, LifeCycleCx, PaintCx, UpdateCx};
pub use linear_layout::LinearLayout; pub use linear_layout::LinearLayout;
pub use raw_event::{Event, LifeCycle, MouseEvent, PointerCrusher, ViewContext}; pub use raw_event::{Event, LifeCycle, MouseEvent, PointerCrusher, ScrollDelta, ViewContext};
pub use switch::Switch; pub use switch::Switch;
pub use text::TextWidget; pub use text::TextWidget;
pub use tree_structure::TreeStructure; pub use tree_structure::TreeStructure;

View File

@ -16,9 +16,10 @@
//! //!
//! Note: arguably this module should be renamed, perhaps we should use //! Note: arguably this module should be renamed, perhaps we should use
//! "event" for this level and maybe "message" at the View level. //! "event" for this level and maybe "message" at the View level.
use std::collections::HashSet;
use glazier::{Modifiers, PointerButton, PointerButtons};
use vello::kurbo::{Point, Rect, Vec2}; use vello::kurbo::{Point, Rect, Vec2};
use winit::event::{Modifiers, MouseButton};
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub enum Event { pub enum Event {
@ -35,12 +36,18 @@ pub struct MouseEvent {
pub pos: Point, pub pos: Point,
/// The position of the mouse in the window coordinate space. /// The position of the mouse in the window coordinate space.
pub window_pos: Point, pub window_pos: Point,
pub buttons: PointerButtons, pub buttons: HashSet<MouseButton>,
pub mods: Modifiers, pub mods: Modifiers,
pub count: u8, pub count: u8,
pub focus: bool, pub focus: bool,
pub button: PointerButton, pub button: Option<MouseButton>,
pub wheel_delta: Vec2, pub wheel_delta: Option<ScrollDelta>,
}
#[derive(Debug, Clone)]
pub enum ScrollDelta {
Precise(Vec2),
Lines(isize, isize),
} }
#[derive(Debug)] #[derive(Debug)]
@ -62,12 +69,12 @@ impl Default for MouseEvent {
MouseEvent { MouseEvent {
pos: Point::ZERO, pos: Point::ZERO,
window_pos: Point::ZERO, window_pos: Point::ZERO,
buttons: PointerButtons::new(), buttons: HashSet::<MouseButton>::new(),
mods: Modifiers::default(), mods: Modifiers::default(),
count: 0, count: 0,
focus: false, focus: false,
button: PointerButton::None, button: None,
wheel_delta: Vec2::ZERO, wheel_delta: None,
} }
} }
} }
@ -100,32 +107,32 @@ impl PointerCrusher {
self.e.mods = mods; self.e.mods = mods;
} }
pub fn pressed(&mut self, button: PointerButton) -> MouseEvent { pub fn pressed(&mut self, button: MouseButton) -> MouseEvent {
self.e.wheel_delta = Vec2::ZERO; self.e.wheel_delta = None;
self.e.buttons.insert(button); self.e.buttons.insert(button);
self.e.count = self.counter.count_for_click(self.e.pos); self.e.count = self.counter.count_for_click(self.e.pos);
self.e.button = button; self.e.button = Some(button);
self.e.clone() self.e.clone()
} }
pub fn released(&mut self, button: PointerButton) -> MouseEvent { pub fn released(&mut self, button: MouseButton) -> MouseEvent {
self.e.wheel_delta = Vec2::ZERO; self.e.wheel_delta = None;
self.e.buttons.remove(button); self.e.buttons.remove(&button);
self.e.button = button; self.e.button = Some(button);
self.e.clone() self.e.clone()
} }
pub fn moved(&mut self, pos: Point) -> MouseEvent { pub fn moved(&mut self, pos: Point) -> MouseEvent {
self.e.wheel_delta = Vec2::ZERO; self.e.wheel_delta = None;
self.e.button = PointerButton::None; self.e.button = None;
self.e.pos = pos; self.e.pos = pos;
self.e.window_pos = pos; self.e.window_pos = pos;
self.e.clone() self.e.clone()
} }
pub fn wheel(&mut self, wheel_delta: Vec2) -> MouseEvent { pub fn wheel(&mut self, wheel_delta: ScrollDelta) -> MouseEvent {
self.e.wheel_delta = wheel_delta; self.e.wheel_delta = Some(wheel_delta);
self.e.button = PointerButton::None; self.e.button = None;
self.e.clone() self.e.clone()
} }
} }