Get basic mouse_down and mouse_up working

This commit is contained in:
Nathan Sobo 2023-08-16 22:21:27 -06:00
parent 187d78011c
commit 812d3f6af6
10 changed files with 175 additions and 82 deletions

View file

@ -5216,6 +5216,7 @@ mod tests {
button: MouseButton::Left,
modifiers: Default::default(),
click_count: 1,
is_down: true,
}),
false,
);

View file

@ -8,8 +8,9 @@ use crate::{
MouseButton, MouseMovedEvent, PromptLevel, WindowBounds,
},
scene::{
CursorRegion, MouseClick, MouseClickOut, MouseDown, MouseDownOut, MouseDrag, MouseEvent,
MouseHover, MouseMove, MouseMoveOut, MouseScrollWheel, MouseUp, MouseUpOut, Scene,
CursorRegion, InteractiveRegion, MouseClick, MouseClickOut, MouseDown, MouseDownOut,
MouseDrag, MouseEvent, MouseHover, MouseMove, MouseMoveOut, MouseScrollWheel, MouseUp,
MouseUpOut, Scene,
},
text_layout::TextLayoutCache,
util::post_inc,
@ -56,6 +57,7 @@ pub struct Window {
appearance: Appearance,
cursor_regions: Vec<CursorRegion>,
mouse_regions: Vec<(MouseRegion, usize)>,
interactive_regions: Vec<InteractiveRegion>,
last_mouse_moved_event: Option<Event>,
pub(crate) hovered_region_ids: Vec<MouseRegionId>,
pub(crate) clicked_region_ids: Vec<MouseRegionId>,
@ -89,6 +91,7 @@ impl Window {
rendered_views: Default::default(),
cursor_regions: Default::default(),
mouse_regions: Default::default(),
interactive_regions: Vec::new(),
text_layout_cache: TextLayoutCache::new(cx.font_system.clone()),
last_mouse_moved_event: None,
hovered_region_ids: Default::default(),
@ -490,6 +493,8 @@ impl<'a> WindowContext<'a> {
}
pub(crate) fn dispatch_event(&mut self, event: Event, event_reused: bool) -> bool {
self.dispatch_to_interactive_regions(&event);
let mut mouse_events = SmallVec::<[_; 2]>::new();
let mut notified_views: HashSet<usize> = Default::default();
let handle = self.window_handle;
@ -867,6 +872,30 @@ impl<'a> WindowContext<'a> {
any_event_handled
}
fn dispatch_to_interactive_regions(&mut self, event: &Event) {
if let Some(mouse_event) = event.mouse_event() {
let mouse_position = event.position().expect("mouse events must have a position");
let interactive_regions = std::mem::take(&mut self.window.interactive_regions);
for region in interactive_regions.iter().rev() {
if region.event_type == mouse_event.type_id() {
if region.bounds.contains_point(mouse_position) {
self.update_any_view(region.view_id, |view, window_cx| {
(region.event_handler)(
view.as_any_mut(),
mouse_event,
window_cx,
region.view_id,
)
});
}
}
}
self.window.interactive_regions = interactive_regions;
}
}
pub(crate) fn dispatch_key_down(&mut self, event: &KeyDownEvent) -> bool {
let handle = self.window_handle;
if let Some(focused_view_id) = self.window.focused_view_id {
@ -1018,9 +1047,10 @@ impl<'a> WindowContext<'a> {
.insert(root_view_id, rendered_root);
self.window.text_layout_cache.finish_frame();
let scene = scene_builder.build();
let mut scene = scene_builder.build();
self.window.cursor_regions = scene.cursor_regions();
self.window.mouse_regions = scene.mouse_regions();
self.window.interactive_regions = scene.take_interactive_regions();
if self.window_is_active() {
if let Some(event) = self.window.last_mouse_moved_event.clone() {

View file

@ -1,4 +1,4 @@
use std::ops::Deref;
use std::{any::Any, ops::Deref};
use pathfinder_geometry::vector::vec2f;
@ -142,6 +142,7 @@ pub struct MouseButtonEvent {
pub position: Vector2F,
pub modifiers: Modifiers,
pub click_count: usize,
pub is_down: bool,
}
impl Deref for MouseButtonEvent {
@ -174,6 +175,7 @@ impl MouseMovedEvent {
button: self.pressed_button.unwrap_or(button),
modifiers: self.modifiers,
click_count: 0,
is_down: self.pressed_button.is_some(),
}
}
}
@ -211,10 +213,25 @@ impl Event {
Event::KeyDown { .. } => None,
Event::KeyUp { .. } => None,
Event::ModifiersChanged { .. } => None,
Event::MouseDown(event) | Event::MouseUp(event) => Some(event.position),
Event::MouseDown(event) => Some(event.position),
Event::MouseUp(event) => Some(event.position),
Event::MouseMoved(event) => Some(event.position),
Event::MouseExited(event) => Some(event.position),
Event::ScrollWheel(event) => Some(event.position),
}
}
pub fn mouse_event<'a>(&'a self) -> Option<&'a dyn Any> {
match self {
Event::KeyDown { .. } => None,
Event::KeyUp { .. } => None,
Event::ModifiersChanged { .. } => None,
Event::MouseDown(event) => Some(event),
Event::MouseUp(event) => Some(event),
_ => None,
// Event::MouseMoved(event) => Some(event),
// Event::MouseExited(event) => Some(event),
// Event::ScrollWheel(event) => Some(event),
}
}
}

View file

@ -132,6 +132,7 @@ impl Event {
),
modifiers: read_modifiers(native_event),
click_count: native_event.clickCount() as usize,
is_down: true,
})
})
}
@ -158,6 +159,7 @@ impl Event {
),
modifiers: read_modifiers(native_event),
click_count: native_event.clickCount() as usize,
is_down: false,
})
})
}

View file

@ -9,7 +9,12 @@ use schemars::JsonSchema;
use serde::Deserialize;
use serde_derive::Serialize;
use serde_json::json;
use std::{borrow::Cow, sync::Arc};
use std::{
any::{Any, TypeId},
borrow::Cow,
rc::Rc,
sync::Arc,
};
use crate::{
color::Color,
@ -17,7 +22,7 @@ use crate::{
geometry::{rect::RectF, vector::Vector2F},
json::ToJson,
platform::{current::Surface, CursorStyle},
ImageData,
ImageData, WindowContext,
};
pub use mouse_event::*;
pub use mouse_region::*;
@ -26,6 +31,8 @@ pub struct SceneBuilder {
scale_factor: f32,
stacking_contexts: Vec<StackingContext>,
active_stacking_context_stack: Vec<usize>,
/// Used by the playground crate.
pub interactive_regions: Vec<InteractiveRegion>,
#[cfg(debug_assertions)]
mouse_region_ids: HashSet<MouseRegionId>,
}
@ -33,6 +40,7 @@ pub struct SceneBuilder {
pub struct Scene {
scale_factor: f32,
stacking_contexts: Vec<StackingContext>,
interactive_regions: Vec<InteractiveRegion>,
}
struct StackingContext {
@ -273,6 +281,12 @@ impl Scene {
})
.collect()
}
pub fn take_interactive_regions(&mut self) -> Vec<InteractiveRegion> {
self.interactive_regions
.sort_by(|a, b| a.order.cmp(&b.order));
std::mem::take(&mut self.interactive_regions)
}
}
impl SceneBuilder {
@ -284,6 +298,7 @@ impl SceneBuilder {
active_stacking_context_stack: vec![0],
#[cfg(debug_assertions)]
mouse_region_ids: Default::default(),
interactive_regions: Vec::new(),
}
}
@ -293,6 +308,7 @@ impl SceneBuilder {
Scene {
scale_factor: self.scale_factor,
stacking_contexts: self.stacking_contexts,
interactive_regions: self.interactive_regions,
}
}
@ -689,6 +705,17 @@ impl MouseRegion {
}
}
/// This is currently only used in the playground crate. It represents a region
/// with which the user can interact via a pointing device. It aims to replace
/// MouseRegion and CursorRegion.
pub struct InteractiveRegion {
pub order: u32,
pub bounds: RectF,
pub event_handler: Rc<dyn Fn(&mut dyn Any, &dyn Any, &mut WindowContext, usize)>,
pub event_type: TypeId,
pub view_id: usize,
}
fn can_draw(bounds: RectF) -> bool {
let size = bounds.size();
size.x() > 0. && size.y() > 0.

View file

@ -364,13 +364,13 @@ impl Line {
origin: glyph_origin,
});
} else {
scene.push_glyph(dbg!(scene::Glyph {
scene.push_glyph(scene::Glyph {
font_id: run.font_id,
font_size: self.layout.font_size,
id: glyph.id,
origin: glyph_origin,
color,
}));
});
}
}
}