Detailed changes
@@ -526,18 +526,6 @@ impl Element for AvatarRibbon {
cx.scene.push_path(path.build(self.color, None));
}
- fn dispatch_event(
- &mut self,
- _: &gpui::Event,
- _: RectF,
- _: RectF,
- _: &mut Self::LayoutState,
- _: &mut Self::PaintState,
- _: &mut gpui::EventContext,
- ) -> bool {
- false
- }
-
fn rect_for_text_range(
&self,
_: Range<usize>,
@@ -29,9 +29,9 @@ use gpui::{
json::{self, ToJson},
platform::CursorStyle,
text_layout::{self, Line, RunStyle, TextLayoutCache},
- AppContext, Axis, Border, CursorRegion, Element, ElementBox, Event, EventContext,
- LayoutContext, MouseButton, MouseButtonEvent, MouseMovedEvent, MouseRegion, MutableAppContext,
- PaintContext, Quad, Scene, SizeConstraint, ViewContext, WeakViewHandle,
+ AppContext, Axis, Border, CursorRegion, Element, ElementBox, EventContext, LayoutContext,
+ MouseButton, MouseButtonEvent, MouseMovedEvent, MouseRegion, MutableAppContext, PaintContext,
+ Quad, Scene, SizeConstraint, ViewContext, WeakViewHandle,
};
use json::json;
use language::{Bias, DiagnosticSeverity, OffsetUtf16, Selection};
@@ -1878,18 +1878,6 @@ impl Element for EditorElement {
cx.scene.pop_layer();
}
- fn dispatch_event(
- &mut self,
- _: &Event,
- _: RectF,
- _: RectF,
- _: &mut LayoutState,
- _: &mut (),
- _: &mut EventContext,
- ) -> bool {
- false
- }
-
fn rect_for_text_range(
&self,
range_utf16: Range<usize>,
@@ -101,18 +101,6 @@ impl gpui::Element for TextElement {
line.paint(bounds.origin(), visible_bounds, bounds.height(), cx);
}
- fn dispatch_event(
- &mut self,
- _: &gpui::Event,
- _: RectF,
- _: RectF,
- _: &mut Self::LayoutState,
- _: &mut Self::PaintState,
- _: &mut gpui::EventContext,
- ) -> bool {
- false
- }
-
fn rect_for_text_range(
&self,
_: Range<usize>,
@@ -33,8 +33,8 @@ use crate::{
},
json,
presenter::MeasurementContext,
- Action, DebugContext, Event, EventContext, LayoutContext, PaintContext, RenderContext,
- SizeConstraint, View,
+ Action, DebugContext, EventContext, LayoutContext, PaintContext, RenderContext, SizeConstraint,
+ View,
};
use core::panic;
use json::ToJson;
@@ -50,7 +50,6 @@ use std::{
trait AnyElement {
fn layout(&mut self, constraint: SizeConstraint, cx: &mut LayoutContext) -> Vector2F;
fn paint(&mut self, origin: Vector2F, visible_bounds: RectF, cx: &mut PaintContext);
- fn dispatch_event(&mut self, event: &Event, cx: &mut EventContext) -> bool;
fn rect_for_text_range(
&self,
range_utf16: Range<usize>,
@@ -80,16 +79,6 @@ pub trait Element {
cx: &mut PaintContext,
) -> Self::PaintState;
- fn dispatch_event(
- &mut self,
- event: &Event,
- bounds: RectF,
- visible_bounds: RectF,
- layout: &mut Self::LayoutState,
- paint: &mut Self::PaintState,
- cx: &mut EventContext,
- ) -> bool;
-
fn rect_for_text_range(
&self,
range_utf16: Range<usize>,
@@ -303,22 +292,6 @@ impl<T: Element> AnyElement for Lifecycle<T> {
}
}
- fn dispatch_event(&mut self, event: &Event, cx: &mut EventContext) -> bool {
- if let Lifecycle::PostPaint {
- element,
- bounds,
- visible_bounds,
- layout,
- paint,
- ..
- } = self
- {
- element.dispatch_event(event, *bounds, *visible_bounds, layout, paint, cx)
- } else {
- panic!("invalid element lifecycle state");
- }
- }
-
fn rect_for_text_range(
&self,
range_utf16: Range<usize>,
@@ -433,10 +406,6 @@ impl ElementRc {
self.element.borrow_mut().paint(origin, visible_bounds, cx);
}
- pub fn dispatch_event(&mut self, event: &Event, cx: &mut EventContext) -> bool {
- self.element.borrow_mut().dispatch_event(event, cx)
- }
-
pub fn rect_for_text_range(
&self,
range_utf16: Range<usize>,
@@ -2,8 +2,7 @@ use crate::{
geometry::{rect::RectF, vector::Vector2F},
json,
presenter::MeasurementContext,
- DebugContext, Element, ElementBox, Event, EventContext, LayoutContext, PaintContext,
- SizeConstraint,
+ DebugContext, Element, ElementBox, LayoutContext, PaintContext, SizeConstraint,
};
use json::ToJson;
@@ -84,18 +83,6 @@ impl Element for Align {
);
}
- fn dispatch_event(
- &mut self,
- event: &Event,
- _: RectF,
- _: RectF,
- _: &mut Self::LayoutState,
- _: &mut Self::PaintState,
- cx: &mut EventContext,
- ) -> bool {
- self.child.dispatch_event(event, cx)
- }
-
fn rect_for_text_range(
&self,
range_utf16: std::ops::Range<usize>,
@@ -56,18 +56,6 @@ where
self.0(bounds, visible_bounds, cx)
}
- fn dispatch_event(
- &mut self,
- _: &crate::Event,
- _: RectF,
- _: RectF,
- _: &mut Self::LayoutState,
- _: &mut Self::PaintState,
- _: &mut crate::EventContext,
- ) -> bool {
- false
- }
-
fn rect_for_text_range(
&self,
_: std::ops::Range<usize>,
@@ -7,8 +7,7 @@ use crate::{
geometry::{rect::RectF, vector::Vector2F},
json,
presenter::MeasurementContext,
- DebugContext, Element, ElementBox, Event, EventContext, LayoutContext, PaintContext,
- SizeConstraint,
+ DebugContext, Element, ElementBox, LayoutContext, PaintContext, SizeConstraint,
};
pub struct ConstrainedBox {
@@ -157,18 +156,6 @@ impl Element for ConstrainedBox {
self.child.paint(bounds.origin(), visible_bounds, cx);
}
- fn dispatch_event(
- &mut self,
- event: &Event,
- _: RectF,
- _: RectF,
- _: &mut Self::LayoutState,
- _: &mut Self::PaintState,
- cx: &mut EventContext,
- ) -> bool {
- self.child.dispatch_event(event, cx)
- }
-
fn rect_for_text_range(
&self,
range_utf16: Range<usize>,
@@ -11,7 +11,7 @@ use crate::{
platform::CursorStyle,
presenter::MeasurementContext,
scene::{self, Border, CursorRegion, Quad},
- Element, ElementBox, Event, EventContext, LayoutContext, PaintContext, SizeConstraint,
+ Element, ElementBox, LayoutContext, PaintContext, SizeConstraint,
};
use serde::Deserialize;
use serde_json::json;
@@ -285,18 +285,6 @@ impl Element for Container {
}
}
- fn dispatch_event(
- &mut self,
- event: &Event,
- _: RectF,
- _: RectF,
- _: &mut Self::LayoutState,
- _: &mut Self::PaintState,
- cx: &mut EventContext,
- ) -> bool {
- self.child.dispatch_event(event, cx)
- }
-
fn rect_for_text_range(
&self,
range_utf16: Range<usize>,
@@ -9,7 +9,7 @@ use crate::{
presenter::MeasurementContext,
DebugContext,
};
-use crate::{Element, Event, EventContext, LayoutContext, PaintContext, SizeConstraint};
+use crate::{Element, LayoutContext, PaintContext, SizeConstraint};
#[derive(Default)]
pub struct Empty {
@@ -59,18 +59,6 @@ impl Element for Empty {
) -> Self::PaintState {
}
- fn dispatch_event(
- &mut self,
- _: &Event,
- _: RectF,
- _: RectF,
- _: &mut Self::LayoutState,
- _: &mut Self::PaintState,
- _: &mut EventContext,
- ) -> bool {
- false
- }
-
fn rect_for_text_range(
&self,
_: Range<usize>,
@@ -4,8 +4,7 @@ use crate::{
geometry::{rect::RectF, vector::Vector2F},
json,
presenter::MeasurementContext,
- DebugContext, Element, ElementBox, Event, EventContext, LayoutContext, PaintContext,
- SizeConstraint,
+ DebugContext, Element, ElementBox, LayoutContext, PaintContext, SizeConstraint,
};
use serde_json::json;
@@ -66,18 +65,6 @@ impl Element for Expanded {
self.child.paint(bounds.origin(), visible_bounds, cx);
}
- fn dispatch_event(
- &mut self,
- event: &Event,
- _: RectF,
- _: RectF,
- _: &mut Self::LayoutState,
- _: &mut Self::PaintState,
- cx: &mut EventContext,
- ) -> bool {
- self.child.dispatch_event(event, cx)
- }
-
fn rect_for_text_range(
&self,
range_utf16: Range<usize>,
@@ -3,8 +3,8 @@ use std::{any::Any, cell::Cell, f32::INFINITY, ops::Range, rc::Rc};
use crate::{
json::{self, ToJson, Value},
presenter::MeasurementContext,
- Axis, DebugContext, Element, ElementBox, ElementStateHandle, Event, EventContext,
- LayoutContext, PaintContext, RenderContext, SizeConstraint, Vector2FExt, View,
+ Axis, DebugContext, Element, ElementBox, ElementStateHandle, LayoutContext, PaintContext,
+ RenderContext, SizeConstraint, Vector2FExt, View,
};
use pathfinder_geometry::{
rect::RectF,
@@ -318,23 +318,6 @@ impl Element for Flex {
}
}
- fn dispatch_event(
- &mut self,
- event: &Event,
- _: RectF,
- _: RectF,
- _: &mut Self::LayoutState,
- _: &mut Self::PaintState,
- cx: &mut EventContext,
- ) -> bool {
- let mut handled = false;
- for child in &mut self.children {
- handled = child.dispatch_event(event, cx) || handled;
- }
-
- handled
- }
-
fn rect_for_text_range(
&self,
range_utf16: Range<usize>,
@@ -420,18 +403,6 @@ impl Element for FlexItem {
self.child.paint(bounds.origin(), visible_bounds, cx)
}
- fn dispatch_event(
- &mut self,
- event: &Event,
- _: RectF,
- _: RectF,
- _: &mut Self::LayoutState,
- _: &mut Self::PaintState,
- cx: &mut EventContext,
- ) -> bool {
- self.child.dispatch_event(event, cx)
- }
-
fn rect_for_text_range(
&self,
range_utf16: Range<usize>,
@@ -4,8 +4,7 @@ use crate::{
geometry::{rect::RectF, vector::Vector2F},
json::json,
presenter::MeasurementContext,
- DebugContext, Element, ElementBox, Event, EventContext, LayoutContext, PaintContext,
- SizeConstraint,
+ DebugContext, Element, ElementBox, LayoutContext, PaintContext, SizeConstraint,
};
pub struct Hook {
@@ -56,18 +55,6 @@ impl Element for Hook {
self.child.paint(bounds.origin(), visible_bounds, cx);
}
- fn dispatch_event(
- &mut self,
- event: &Event,
- _: RectF,
- _: RectF,
- _: &mut Self::LayoutState,
- _: &mut Self::PaintState,
- cx: &mut EventContext,
- ) -> bool {
- self.child.dispatch_event(event, cx)
- }
-
fn rect_for_text_range(
&self,
range_utf16: Range<usize>,
@@ -6,8 +6,7 @@ use crate::{
},
json::{json, ToJson},
presenter::MeasurementContext,
- scene, Border, DebugContext, Element, Event, EventContext, ImageData, LayoutContext,
- PaintContext, SizeConstraint,
+ scene, Border, DebugContext, Element, ImageData, LayoutContext, PaintContext, SizeConstraint,
};
use serde::Deserialize;
use std::{ops::Range, sync::Arc};
@@ -81,18 +80,6 @@ impl Element for Image {
});
}
- fn dispatch_event(
- &mut self,
- _: &Event,
- _: RectF,
- _: RectF,
- _: &mut Self::LayoutState,
- _: &mut Self::PaintState,
- _: &mut EventContext,
- ) -> bool {
- false
- }
-
fn rect_for_text_range(
&self,
_: Range<usize>,
@@ -2,7 +2,7 @@ use crate::{
elements::*,
fonts::TextStyle,
geometry::{rect::RectF, vector::Vector2F},
- Action, ElementBox, Event, EventContext, LayoutContext, PaintContext, SizeConstraint,
+ Action, ElementBox, LayoutContext, PaintContext, SizeConstraint,
};
use serde_json::json;
@@ -64,18 +64,6 @@ impl Element for KeystrokeLabel {
element.paint(bounds.origin(), visible_bounds, cx);
}
- fn dispatch_event(
- &mut self,
- event: &Event,
- _: RectF,
- _: RectF,
- element: &mut ElementBox,
- _: &mut (),
- cx: &mut EventContext,
- ) -> bool {
- element.dispatch_event(event, cx)
- }
-
fn rect_for_text_range(
&self,
_: Range<usize>,
@@ -9,7 +9,7 @@ use crate::{
json::{ToJson, Value},
presenter::MeasurementContext,
text_layout::{Line, RunStyle},
- DebugContext, Element, Event, EventContext, LayoutContext, PaintContext, SizeConstraint,
+ DebugContext, Element, LayoutContext, PaintContext, SizeConstraint,
};
use serde::Deserialize;
use serde_json::json;
@@ -165,18 +165,6 @@ impl Element for Label {
line.paint(bounds.origin(), visible_bounds, bounds.size().y(), cx)
}
- fn dispatch_event(
- &mut self,
- _: &Event,
- _: RectF,
- _: RectF,
- _: &mut Self::LayoutState,
- _: &mut Self::PaintState,
- _: &mut EventContext,
- ) -> bool {
- false
- }
-
fn rect_for_text_range(
&self,
_: Range<usize>,
@@ -5,7 +5,7 @@ use crate::{
},
json::json,
presenter::MeasurementContext,
- DebugContext, Element, ElementBox, ElementRc, Event, EventContext, LayoutContext, MouseRegion,
+ DebugContext, Element, ElementBox, ElementRc, EventContext, LayoutContext, MouseRegion,
PaintContext, RenderContext, SizeConstraint, View, ViewContext,
};
use std::{cell::RefCell, collections::VecDeque, ops::Range, rc::Rc};
@@ -13,7 +13,6 @@ use sum_tree::{Bias, SumTree};
pub struct List {
state: ListState,
- invalidated_elements: Vec<ElementRc>,
}
#[derive(Clone)]
@@ -82,10 +81,7 @@ struct Height(f32);
impl List {
pub fn new(state: ListState) -> Self {
- Self {
- state,
- invalidated_elements: Default::default(),
- }
+ Self { state }
}
}
@@ -289,50 +285,6 @@ impl Element for List {
cx.scene.pop_layer();
}
- fn dispatch_event(
- &mut self,
- event: &Event,
- bounds: RectF,
- _: RectF,
- scroll_top: &mut ListOffset,
- _: &mut (),
- cx: &mut EventContext,
- ) -> bool {
- let mut handled = false;
-
- let mut state = self.state.0.borrow_mut();
- let mut item_origin = bounds.origin() - vec2f(0., scroll_top.offset_in_item);
- let mut cursor = state.items.cursor::<Count>();
- let mut new_items = cursor.slice(&Count(scroll_top.item_ix), Bias::Right, &());
- while let Some(item) = cursor.item() {
- if item_origin.y() > bounds.max_y() {
- break;
- }
-
- if let ListItem::Rendered(element) = item {
- let prev_notify_count = cx.notify_count();
- let mut element = element.clone();
- handled = element.dispatch_event(event, cx) || handled;
- item_origin.set_y(item_origin.y() + element.size().y());
- if cx.notify_count() > prev_notify_count {
- new_items.push(ListItem::Unrendered, &());
- self.invalidated_elements.push(element);
- } else {
- new_items.push(item.clone(), &());
- }
- cursor.next(&());
- } else {
- unreachable!();
- }
- }
-
- new_items.push_tree(cursor.suffix(&()), &());
- drop(cursor);
- state.items = new_items;
-
- handled
- }
-
fn rect_for_text_range(
&self,
range_utf16: Range<usize>,
@@ -964,18 +916,6 @@ mod tests {
todo!()
}
- fn dispatch_event(
- &mut self,
- _: &Event,
- _: RectF,
- _: RectF,
- _: &mut (),
- _: &mut (),
- _: &mut EventContext,
- ) -> bool {
- todo!()
- }
-
fn rect_for_text_range(
&self,
_: Range<usize>,
@@ -9,7 +9,7 @@ use crate::{
CursorRegion, HandlerSet, MouseClick, MouseDown, MouseDownOut, MouseDrag, MouseHover,
MouseMove, MouseScrollWheel, MouseUp, MouseUpOut,
},
- DebugContext, Element, ElementBox, Event, EventContext, LayoutContext, MeasurementContext,
+ DebugContext, Element, ElementBox, EventContext, LayoutContext, MeasurementContext,
MouseButton, MouseRegion, MouseState, PaintContext, RenderContext, SizeConstraint, View,
};
use serde_json::json;
@@ -194,18 +194,6 @@ impl<Tag> Element for MouseEventHandler<Tag> {
self.child.paint(bounds.origin(), visible_bounds, cx);
}
- fn dispatch_event(
- &mut self,
- event: &Event,
- _: RectF,
- _: RectF,
- _: &mut Self::LayoutState,
- _: &mut Self::PaintState,
- cx: &mut EventContext,
- ) -> bool {
- self.child.dispatch_event(event, cx)
- }
-
fn rect_for_text_range(
&self,
range_utf16: Range<usize>,
@@ -4,8 +4,8 @@ use crate::{
geometry::{rect::RectF, vector::Vector2F},
json::ToJson,
presenter::MeasurementContext,
- Axis, DebugContext, Element, ElementBox, Event, EventContext, LayoutContext, MouseRegion,
- PaintContext, SizeConstraint,
+ Axis, DebugContext, Element, ElementBox, LayoutContext, MouseRegion, PaintContext,
+ SizeConstraint,
};
use serde_json::json;
@@ -225,18 +225,6 @@ impl Element for Overlay {
cx.scene.pop_stacking_context();
}
- fn dispatch_event(
- &mut self,
- event: &Event,
- _: RectF,
- _: RectF,
- _: &mut Self::LayoutState,
- _: &mut Self::PaintState,
- cx: &mut EventContext,
- ) -> bool {
- self.child.dispatch_event(event, cx)
- }
-
fn rect_for_text_range(
&self,
range_utf16: Range<usize>,
@@ -187,18 +187,6 @@ impl Element for Resizable {
self.child.paint(bounds.origin(), visible_bounds, cx);
}
- fn dispatch_event(
- &mut self,
- event: &crate::Event,
- _bounds: pathfinder_geometry::rect::RectF,
- _visible_bounds: pathfinder_geometry::rect::RectF,
- _layout: &mut Self::LayoutState,
- _paint: &mut Self::PaintState,
- cx: &mut crate::EventContext,
- ) -> bool {
- self.child.dispatch_event(event, cx)
- }
-
fn rect_for_text_range(
&self,
range_utf16: std::ops::Range<usize>,
@@ -4,8 +4,7 @@ use crate::{
geometry::{rect::RectF, vector::Vector2F},
json::{self, json, ToJson},
presenter::MeasurementContext,
- DebugContext, Element, ElementBox, Event, EventContext, LayoutContext, PaintContext,
- SizeConstraint,
+ DebugContext, Element, ElementBox, LayoutContext, PaintContext, SizeConstraint,
};
#[derive(Default)]
@@ -49,23 +48,6 @@ impl Element for Stack {
}
}
- fn dispatch_event(
- &mut self,
- event: &Event,
- _: RectF,
- _: RectF,
- _: &mut Self::LayoutState,
- _: &mut Self::PaintState,
- cx: &mut EventContext,
- ) -> bool {
- for child in self.children.iter_mut().rev() {
- if child.dispatch_event(event, cx) {
- return true;
- }
- }
- false
- }
-
fn rect_for_text_range(
&self,
range_utf16: Range<usize>,
@@ -9,7 +9,7 @@ use crate::{
vector::{vec2f, Vector2F},
},
presenter::MeasurementContext,
- scene, DebugContext, Element, Event, EventContext, LayoutContext, PaintContext, SizeConstraint,
+ scene, DebugContext, Element, LayoutContext, PaintContext, SizeConstraint,
};
pub struct Svg {
@@ -73,18 +73,6 @@ impl Element for Svg {
}
}
- fn dispatch_event(
- &mut self,
- _: &Event,
- _: RectF,
- _: RectF,
- _: &mut Self::LayoutState,
- _: &mut Self::PaintState,
- _: &mut EventContext,
- ) -> bool {
- false
- }
-
fn rect_for_text_range(
&self,
_: Range<usize>,
@@ -8,8 +8,7 @@ use crate::{
json::{ToJson, Value},
presenter::MeasurementContext,
text_layout::{Line, RunStyle, ShapedBoundary},
- DebugContext, Element, Event, EventContext, FontCache, LayoutContext, PaintContext,
- SizeConstraint, TextLayoutCache,
+ DebugContext, Element, FontCache, LayoutContext, PaintContext, SizeConstraint, TextLayoutCache,
};
use log::warn;
use serde_json::json;
@@ -178,18 +177,6 @@ impl Element for Text {
}
}
- fn dispatch_event(
- &mut self,
- _: &Event,
- _: RectF,
- _: RectF,
- _: &mut Self::LayoutState,
- _: &mut Self::PaintState,
- _: &mut EventContext,
- ) -> bool {
- false
- }
-
fn rect_for_text_range(
&self,
_: Range<usize>,
@@ -186,18 +186,6 @@ impl Element for Tooltip {
}
}
- fn dispatch_event(
- &mut self,
- event: &crate::Event,
- _: RectF,
- _: RectF,
- _: &mut Self::LayoutState,
- _: &mut Self::PaintState,
- cx: &mut crate::EventContext,
- ) -> bool {
- self.child.dispatch_event(event, cx)
- }
-
fn rect_for_text_range(
&self,
range: Range<usize>,
@@ -1,4 +1,4 @@
-use super::{Element, Event, EventContext, LayoutContext, PaintContext, SizeConstraint};
+use super::{Element, EventContext, LayoutContext, PaintContext, SizeConstraint};
use crate::{
geometry::{
rect::RectF,
@@ -324,23 +324,6 @@ impl Element for UniformList {
cx.scene.pop_layer();
}
- fn dispatch_event(
- &mut self,
- event: &Event,
- _: RectF,
- _: RectF,
- layout: &mut Self::LayoutState,
- _: &mut Self::PaintState,
- cx: &mut EventContext,
- ) -> bool {
- let mut handled = false;
- for item in &mut layout.items {
- handled = item.dispatch_event(event, cx) || handled;
- }
-
- handled
- }
-
fn rect_for_text_range(
&self,
range: Range<usize>,
@@ -228,296 +228,283 @@ impl Presenter {
event_reused: bool,
cx: &mut MutableAppContext,
) -> bool {
- if let Some(root_view_id) = cx.root_view_id(self.window_id) {
- let mut mouse_events = SmallVec::<[_; 2]>::new();
- let mut notified_views: HashSet<usize> = Default::default();
-
- // 1. Handle platform event. Keyboard events get dispatched immediately, while mouse events
- // get mapped into the mouse-specific MouseEvent type.
- // -> These are usually small: [Mouse Down] or [Mouse up, Click] or [Mouse Moved, Mouse Dragged?]
- // -> Also updates mouse-related state
- match &event {
- Event::KeyDown(e) => return cx.dispatch_key_down(self.window_id, e),
- Event::KeyUp(e) => return cx.dispatch_key_up(self.window_id, e),
- Event::ModifiersChanged(e) => {
- return cx.dispatch_modifiers_changed(self.window_id, e)
+ let mut mouse_events = SmallVec::<[_; 2]>::new();
+ let mut notified_views: HashSet<usize> = Default::default();
+
+ // 1. Handle platform event. Keyboard events get dispatched immediately, while mouse events
+ // get mapped into the mouse-specific MouseEvent type.
+ // -> These are usually small: [Mouse Down] or [Mouse up, Click] or [Mouse Moved, Mouse Dragged?]
+ // -> Also updates mouse-related state
+ match &event {
+ Event::KeyDown(e) => return cx.dispatch_key_down(self.window_id, e),
+ Event::KeyUp(e) => return cx.dispatch_key_up(self.window_id, e),
+ Event::ModifiersChanged(e) => return cx.dispatch_modifiers_changed(self.window_id, e),
+ Event::MouseDown(e) => {
+ // Click events are weird because they can be fired after a drag event.
+ // MDN says that browsers handle this by starting from 'the most
+ // specific ancestor element that contained both [positions]'
+ // So we need to store the overlapping regions on mouse down.
+
+ // If there is already clicked_button stored, don't replace it.
+ if self.clicked_button.is_none() {
+ self.clicked_region_ids = self
+ .mouse_regions
+ .iter()
+ .filter_map(|(region, _)| {
+ if region.bounds.contains_point(e.position) {
+ Some(region.id())
+ } else {
+ None
+ }
+ })
+ .collect();
+
+ self.clicked_button = Some(e.button);
}
- Event::MouseDown(e) => {
- // Click events are weird because they can be fired after a drag event.
- // MDN says that browsers handle this by starting from 'the most
- // specific ancestor element that contained both [positions]'
- // So we need to store the overlapping regions on mouse down.
-
- // If there is already clicked_button stored, don't replace it.
- if self.clicked_button.is_none() {
- self.clicked_region_ids = self
- .mouse_regions
- .iter()
- .filter_map(|(region, _)| {
- if region.bounds.contains_point(e.position) {
- Some(region.id())
- } else {
- None
- }
- })
- .collect();
- self.clicked_button = Some(e.button);
+ mouse_events.push(MouseEvent::Down(MouseDown {
+ region: Default::default(),
+ platform_event: e.clone(),
+ }));
+ mouse_events.push(MouseEvent::DownOut(MouseDownOut {
+ region: Default::default(),
+ platform_event: e.clone(),
+ }));
+ }
+ Event::MouseUp(e) => {
+ // NOTE: The order of event pushes is important! MouseUp events MUST be fired
+ // before click events, and so the MouseUp events need to be pushed before
+ // MouseClick events.
+ mouse_events.push(MouseEvent::Up(MouseUp {
+ region: Default::default(),
+ platform_event: e.clone(),
+ }));
+ mouse_events.push(MouseEvent::UpOut(MouseUpOut {
+ region: Default::default(),
+ platform_event: e.clone(),
+ }));
+ mouse_events.push(MouseEvent::Click(MouseClick {
+ region: Default::default(),
+ platform_event: e.clone(),
+ }));
+ }
+ Event::MouseMoved(
+ e @ MouseMovedEvent {
+ position,
+ pressed_button,
+ ..
+ },
+ ) => {
+ let mut style_to_assign = CursorStyle::Arrow;
+ for region in self.cursor_regions.iter().rev() {
+ if region.bounds.contains_point(*position) {
+ style_to_assign = region.style;
+ break;
}
-
- mouse_events.push(MouseEvent::Down(MouseDown {
- region: Default::default(),
- platform_event: e.clone(),
- }));
- mouse_events.push(MouseEvent::DownOut(MouseDownOut {
- region: Default::default(),
- platform_event: e.clone(),
- }));
}
- Event::MouseUp(e) => {
- // NOTE: The order of event pushes is important! MouseUp events MUST be fired
- // before click events, and so the MouseUp events need to be pushed before
- // MouseClick events.
- mouse_events.push(MouseEvent::Up(MouseUp {
- region: Default::default(),
- platform_event: e.clone(),
- }));
- mouse_events.push(MouseEvent::UpOut(MouseUpOut {
- region: Default::default(),
- platform_event: e.clone(),
- }));
- mouse_events.push(MouseEvent::Click(MouseClick {
- region: Default::default(),
- platform_event: e.clone(),
- }));
- }
- Event::MouseMoved(
- e @ MouseMovedEvent {
- position,
- pressed_button,
- ..
- },
- ) => {
- let mut style_to_assign = CursorStyle::Arrow;
- for region in self.cursor_regions.iter().rev() {
- if region.bounds.contains_point(*position) {
- style_to_assign = region.style;
- break;
- }
- }
- cx.platform().set_cursor_style(style_to_assign);
-
- if !event_reused {
- if pressed_button.is_some() {
- mouse_events.push(MouseEvent::Drag(MouseDrag {
- region: Default::default(),
- prev_mouse_position: self.mouse_position,
- platform_event: e.clone(),
- }));
- } else if let Some(clicked_button) = self.clicked_button {
- // Mouse up event happened outside the current window. Simulate mouse up button event
- let button_event = e.to_button_event(clicked_button);
- mouse_events.push(MouseEvent::Up(MouseUp {
- region: Default::default(),
- platform_event: button_event.clone(),
- }));
- mouse_events.push(MouseEvent::UpOut(MouseUpOut {
- region: Default::default(),
- platform_event: button_event.clone(),
- }));
- mouse_events.push(MouseEvent::Click(MouseClick {
- region: Default::default(),
- platform_event: button_event.clone(),
- }));
- }
+ cx.platform().set_cursor_style(style_to_assign);
- mouse_events.push(MouseEvent::Move(MouseMove {
+ if !event_reused {
+ if pressed_button.is_some() {
+ mouse_events.push(MouseEvent::Drag(MouseDrag {
region: Default::default(),
+ prev_mouse_position: self.mouse_position,
platform_event: e.clone(),
}));
+ } else if let Some(clicked_button) = self.clicked_button {
+ // Mouse up event happened outside the current window. Simulate mouse up button event
+ let button_event = e.to_button_event(clicked_button);
+ mouse_events.push(MouseEvent::Up(MouseUp {
+ region: Default::default(),
+ platform_event: button_event.clone(),
+ }));
+ mouse_events.push(MouseEvent::UpOut(MouseUpOut {
+ region: Default::default(),
+ platform_event: button_event.clone(),
+ }));
+ mouse_events.push(MouseEvent::Click(MouseClick {
+ region: Default::default(),
+ platform_event: button_event.clone(),
+ }));
}
- mouse_events.push(MouseEvent::Hover(MouseHover {
+ mouse_events.push(MouseEvent::Move(MouseMove {
region: Default::default(),
platform_event: e.clone(),
- started: false,
}));
-
- self.last_mouse_moved_event = Some(event.clone());
- }
- Event::ScrollWheel(e) => {
- mouse_events.push(MouseEvent::ScrollWheel(MouseScrollWheel {
- region: Default::default(),
- platform_event: e.clone(),
- }))
}
- }
- if let Some(position) = event.position() {
- self.mouse_position = position;
+ mouse_events.push(MouseEvent::Hover(MouseHover {
+ region: Default::default(),
+ platform_event: e.clone(),
+ started: false,
+ }));
+
+ self.last_mouse_moved_event = Some(event.clone());
}
+ Event::ScrollWheel(e) => mouse_events.push(MouseEvent::ScrollWheel(MouseScrollWheel {
+ region: Default::default(),
+ platform_event: e.clone(),
+ })),
+ }
- // 2. Dispatch mouse events on regions
- let mut any_event_handled = false;
- for mut mouse_event in mouse_events {
- let mut valid_regions = Vec::new();
-
- // GPUI elements are arranged by depth but sibling elements can register overlapping
- // mouse regions. As such, hover events are only fired on overlapping elements which
- // are at the same depth as the topmost element which overlaps with the mouse.
- match &mouse_event {
- MouseEvent::Hover(_) => {
- let mut top_most_depth = None;
- let mouse_position = self.mouse_position.clone();
- for (region, depth) in self.mouse_regions.iter().rev() {
- // Allow mouse regions to appear transparent to hovers
- if !region.hoverable {
- continue;
- }
+ if let Some(position) = event.position() {
+ self.mouse_position = position;
+ }
- let contains_mouse = region.bounds.contains_point(mouse_position);
+ // 2. Dispatch mouse events on regions
+ let mut any_event_handled = false;
+ for mut mouse_event in mouse_events {
+ let mut valid_regions = Vec::new();
+
+ // GPUI elements are arranged by depth but sibling elements can register overlapping
+ // mouse regions. As such, hover events are only fired on overlapping elements which
+ // are at the same depth as the topmost element which overlaps with the mouse.
+ match &mouse_event {
+ MouseEvent::Hover(_) => {
+ let mut top_most_depth = None;
+ let mouse_position = self.mouse_position.clone();
+ for (region, depth) in self.mouse_regions.iter().rev() {
+ // Allow mouse regions to appear transparent to hovers
+ if !region.hoverable {
+ continue;
+ }
- if contains_mouse && top_most_depth.is_none() {
- top_most_depth = Some(depth);
- }
+ let contains_mouse = region.bounds.contains_point(mouse_position);
- // This unwrap relies on short circuiting boolean expressions
- // The right side of the && is only executed when contains_mouse
- // is true, and we know above that when contains_mouse is true
- // top_most_depth is set
- if contains_mouse && depth == top_most_depth.unwrap() {
- //Ensure that hover entrance events aren't sent twice
- if self.hovered_region_ids.insert(region.id()) {
- valid_regions.push(region.clone());
- if region.notify_on_hover {
- notified_views.insert(region.id().view_id());
- }
- }
- } else {
- // Ensure that hover exit events aren't sent twice
- if self.hovered_region_ids.remove(®ion.id()) {
- valid_regions.push(region.clone());
- if region.notify_on_hover {
- notified_views.insert(region.id().view_id());
- }
- }
- }
+ if contains_mouse && top_most_depth.is_none() {
+ top_most_depth = Some(depth);
}
- }
- MouseEvent::Down(_) | MouseEvent::Up(_) => {
- for (region, _) in self.mouse_regions.iter().rev() {
- if region.bounds.contains_point(self.mouse_position) {
- if region.notify_on_click {
+
+ // This unwrap relies on short circuiting boolean expressions
+ // The right side of the && is only executed when contains_mouse
+ // is true, and we know above that when contains_mouse is true
+ // top_most_depth is set
+ if contains_mouse && depth == top_most_depth.unwrap() {
+ //Ensure that hover entrance events aren't sent twice
+ if self.hovered_region_ids.insert(region.id()) {
+ valid_regions.push(region.clone());
+ if region.notify_on_hover {
notified_views.insert(region.id().view_id());
}
- valid_regions.push(region.clone());
}
- }
- }
- MouseEvent::Click(e) => {
- // Only raise click events if the released button is the same as the one stored
- if self
- .clicked_button
- .map(|clicked_button| clicked_button == e.button)
- .unwrap_or(false)
- {
- // Clear clicked regions and clicked button
- let clicked_region_ids =
- std::mem::replace(&mut self.clicked_region_ids, Default::default());
- self.clicked_button = None;
-
- // Find regions which still overlap with the mouse since the last MouseDown happened
- for (mouse_region, _) in self.mouse_regions.iter().rev() {
- if clicked_region_ids.contains(&mouse_region.id()) {
- if mouse_region.bounds.contains_point(self.mouse_position) {
- valid_regions.push(mouse_region.clone());
- }
+ } else {
+ // Ensure that hover exit events aren't sent twice
+ if self.hovered_region_ids.remove(®ion.id()) {
+ valid_regions.push(region.clone());
+ if region.notify_on_hover {
+ notified_views.insert(region.id().view_id());
}
}
}
}
- MouseEvent::Drag(_) => {
- for (mouse_region, _) in self.mouse_regions.iter().rev() {
- if self.clicked_region_ids.contains(&mouse_region.id()) {
- valid_regions.push(mouse_region.clone());
+ }
+ MouseEvent::Down(_) | MouseEvent::Up(_) => {
+ for (region, _) in self.mouse_regions.iter().rev() {
+ if region.bounds.contains_point(self.mouse_position) {
+ if region.notify_on_click {
+ notified_views.insert(region.id().view_id());
}
+ valid_regions.push(region.clone());
}
}
-
- MouseEvent::UpOut(_) | MouseEvent::DownOut(_) => {
+ }
+ MouseEvent::Click(e) => {
+ // Only raise click events if the released button is the same as the one stored
+ if self
+ .clicked_button
+ .map(|clicked_button| clicked_button == e.button)
+ .unwrap_or(false)
+ {
+ // Clear clicked regions and clicked button
+ let clicked_region_ids =
+ std::mem::replace(&mut self.clicked_region_ids, Default::default());
+ self.clicked_button = None;
+
+ // Find regions which still overlap with the mouse since the last MouseDown happened
for (mouse_region, _) in self.mouse_regions.iter().rev() {
- // NOT contains
- if !mouse_region.bounds.contains_point(self.mouse_position) {
- valid_regions.push(mouse_region.clone());
+ if clicked_region_ids.contains(&mouse_region.id()) {
+ if mouse_region.bounds.contains_point(self.mouse_position) {
+ valid_regions.push(mouse_region.clone());
+ }
}
}
}
- _ => {
- for (mouse_region, _) in self.mouse_regions.iter().rev() {
- // Contains
- if mouse_region.bounds.contains_point(self.mouse_position) {
- valid_regions.push(mouse_region.clone());
- }
+ }
+ MouseEvent::Drag(_) => {
+ for (mouse_region, _) in self.mouse_regions.iter().rev() {
+ if self.clicked_region_ids.contains(&mouse_region.id()) {
+ valid_regions.push(mouse_region.clone());
}
}
}
- //3. Fire region events
- let hovered_region_ids = self.hovered_region_ids.clone();
- for valid_region in valid_regions.into_iter() {
- let mut event_cx = self.build_event_context(&mut notified_views, cx);
-
- mouse_event.set_region(valid_region.bounds);
- if let MouseEvent::Hover(e) = &mut mouse_event {
- e.started = hovered_region_ids.contains(&valid_region.id())
+ MouseEvent::UpOut(_) | MouseEvent::DownOut(_) => {
+ for (mouse_region, _) in self.mouse_regions.iter().rev() {
+ // NOT contains
+ if !mouse_region.bounds.contains_point(self.mouse_position) {
+ valid_regions.push(mouse_region.clone());
+ }
}
- // Handle Down events if the MouseRegion has a Click or Drag handler. This makes the api more intuitive as you would
- // not expect a MouseRegion to be transparent to Down events if it also has a Click handler.
- // This behavior can be overridden by adding a Down handler that calls cx.propogate_event
- if let MouseEvent::Down(e) = &mouse_event {
- if valid_region
- .handlers
- .contains_handler(MouseEvent::click_disc(), Some(e.button))
- || valid_region
- .handlers
- .contains_handler(MouseEvent::drag_disc(), Some(e.button))
- {
- event_cx.handled = true;
+ }
+ _ => {
+ for (mouse_region, _) in self.mouse_regions.iter().rev() {
+ // Contains
+ if mouse_region.bounds.contains_point(self.mouse_position) {
+ valid_regions.push(mouse_region.clone());
}
}
+ }
+ }
- if let Some(callback) = valid_region.handlers.get(&mouse_event.handler_key()) {
- event_cx.handled = true;
- event_cx.with_current_view(valid_region.id().view_id(), {
- let region_event = mouse_event.clone();
- |cx| {
- callback(region_event, cx);
- }
- });
- }
+ //3. Fire region events
+ let hovered_region_ids = self.hovered_region_ids.clone();
+ for valid_region in valid_regions.into_iter() {
+ let mut event_cx = self.build_event_context(&mut notified_views, cx);
- any_event_handled = any_event_handled || event_cx.handled;
- // For bubbling events, if the event was handled, don't continue dispatching
- // This only makes sense for local events.
- if event_cx.handled && mouse_event.is_capturable() {
- break;
+ mouse_event.set_region(valid_region.bounds);
+ if let MouseEvent::Hover(e) = &mut mouse_event {
+ e.started = hovered_region_ids.contains(&valid_region.id())
+ }
+ // Handle Down events if the MouseRegion has a Click or Drag handler. This makes the api more intuitive as you would
+ // not expect a MouseRegion to be transparent to Down events if it also has a Click handler.
+ // This behavior can be overridden by adding a Down handler that calls cx.propogate_event
+ if let MouseEvent::Down(e) = &mouse_event {
+ if valid_region
+ .handlers
+ .contains_handler(MouseEvent::click_disc(), Some(e.button))
+ || valid_region
+ .handlers
+ .contains_handler(MouseEvent::drag_disc(), Some(e.button))
+ {
+ event_cx.handled = true;
}
}
- }
- if !any_event_handled && !event_reused {
- let mut event_cx = self.build_event_context(&mut notified_views, cx);
- any_event_handled = event_cx.dispatch_event(root_view_id, &event);
- }
+ if let Some(callback) = valid_region.handlers.get(&mouse_event.handler_key()) {
+ event_cx.handled = true;
+ event_cx.with_current_view(valid_region.id().view_id(), {
+ let region_event = mouse_event.clone();
+ |cx| {
+ callback(region_event, cx);
+ }
+ });
+ }
- for view_id in notified_views {
- cx.notify_view(self.window_id, view_id);
+ any_event_handled = any_event_handled || event_cx.handled;
+ // For bubbling events, if the event was handled, don't continue dispatching
+ // This only makes sense for local events.
+ if event_cx.handled && mouse_event.is_capturable() {
+ break;
+ }
}
+ }
- any_event_handled
- } else {
- false
+ for view_id in notified_views {
+ cx.notify_view(self.window_id, view_id);
}
+
+ any_event_handled
}
pub fn build_event_context<'a>(
@@ -526,7 +513,6 @@ impl Presenter {
cx: &'a mut MutableAppContext,
) -> EventContext<'a> {
EventContext {
- rendered_views: &mut self.rendered_views,
font_cache: &self.font_cache,
text_layout_cache: &self.text_layout_cache,
view_stack: Default::default(),
@@ -745,7 +731,6 @@ impl<'a> Deref for PaintContext<'a> {
}
pub struct EventContext<'a> {
- rendered_views: &'a mut HashMap<usize, ElementBox>,
pub font_cache: &'a FontCache,
pub text_layout_cache: &'a TextLayoutCache,
pub app: &'a mut MutableAppContext,
@@ -757,17 +742,6 @@ pub struct EventContext<'a> {
}
impl<'a> EventContext<'a> {
- fn dispatch_event(&mut self, view_id: usize, event: &Event) -> bool {
- if let Some(mut element) = self.rendered_views.remove(&view_id) {
- let result =
- self.with_current_view(view_id, |this| element.dispatch_event(event, this));
- self.rendered_views.insert(view_id, element);
- result
- } else {
- false
- }
- }
-
fn with_current_view<F, T>(&mut self, view_id: usize, f: F) -> T
where
F: FnOnce(&mut Self) -> T,
@@ -1030,27 +1004,6 @@ impl Element for ChildView {
}
}
- fn dispatch_event(
- &mut self,
- event: &Event,
- _: RectF,
- _: RectF,
- view_is_valid: &mut Self::LayoutState,
- _: &mut Self::PaintState,
- cx: &mut EventContext,
- ) -> bool {
- if *view_is_valid {
- cx.dispatch_event(self.view.id(), event)
- } else {
- log::error!(
- "dispatch_event called on a ChildView element whose underlying view was dropped (view_id: {}, name: {:?})",
- self.view.id(),
- self.view_name
- );
- false
- }
- }
-
fn rect_for_text_range(
&self,
range_utf16: Range<usize>,
@@ -798,18 +798,6 @@ impl Element for TerminalElement {
});
}
- fn dispatch_event(
- &mut self,
- _: &gpui::Event,
- _bounds: gpui::geometry::rect::RectF,
- _visible_bounds: gpui::geometry::rect::RectF,
- _layout: &mut Self::LayoutState,
- _paint: &mut Self::PaintState,
- _: &mut gpui::EventContext,
- ) -> bool {
- false
- }
-
fn metadata(&self) -> Option<&dyn std::any::Any> {
None
}