diff --git a/crates/auto_update/src/auto_update.rs b/crates/auto_update/src/auto_update.rs index 499b3ed99d..234319bdd6 100644 --- a/crates/auto_update/src/auto_update.rs +++ b/crates/auto_update/src/auto_update.rs @@ -270,7 +270,7 @@ impl View for AutoUpdateIndicator { ) .boxed() }) - .on_click(|_, cx| cx.dispatch_action(DismissErrorMessage)) + .on_click(|_, _, cx| cx.dispatch_action(DismissErrorMessage)) .boxed() } AutoUpdateStatus::Idle => Empty::new().boxed(), diff --git a/crates/chat_panel/src/chat_panel.rs b/crates/chat_panel/src/chat_panel.rs index 2240bbf9c6..d3c5ef5592 100644 --- a/crates/chat_panel/src/chat_panel.rs +++ b/crates/chat_panel/src/chat_panel.rs @@ -320,7 +320,7 @@ impl ChatPanel { .boxed() }) .with_cursor_style(CursorStyle::PointingHand) - .on_click(move |_, cx| { + .on_click(move |_, _, cx| { let rpc = rpc.clone(); let this = this.clone(); cx.spawn(|mut cx| async move { diff --git a/crates/command_palette/src/command_palette.rs b/crates/command_palette/src/command_palette.rs index 9f0f396d85..0708826ea7 100644 --- a/crates/command_palette/src/command_palette.rs +++ b/crates/command_palette/src/command_palette.rs @@ -1,9 +1,9 @@ use fuzzy::{StringMatch, StringMatchCandidate}; use gpui::{ actions, - elements::{ChildView, Flex, Label, MouseState, ParentElement}, + elements::{ChildView, Flex, Label, ParentElement}, keymap::Keystroke, - Action, Element, Entity, MutableAppContext, View, ViewContext, ViewHandle, + Action, Element, Entity, MouseState, MutableAppContext, View, ViewContext, ViewHandle, }; use picker::{Picker, PickerDelegate}; use settings::Settings; @@ -203,7 +203,7 @@ impl PickerDelegate for CommandPalette { fn render_match( &self, ix: usize, - mouse_state: &MouseState, + mouse_state: MouseState, selected: bool, cx: &gpui::AppContext, ) -> gpui::ElementBox { diff --git a/crates/contacts_panel/src/contact_finder.rs b/crates/contacts_panel/src/contact_finder.rs index 18e17a93d9..244cfcad4a 100644 --- a/crates/contacts_panel/src/contact_finder.rs +++ b/crates/contacts_panel/src/contact_finder.rs @@ -1,7 +1,7 @@ use client::{ContactRequestStatus, User, UserStore}; use gpui::{ - actions, elements::*, Entity, ModelHandle, MutableAppContext, RenderContext, Task, View, - ViewContext, ViewHandle, + actions, elements::*, Entity, ModelHandle, MouseState, MutableAppContext, RenderContext, Task, + View, ViewContext, ViewHandle, }; use picker::{Picker, PickerDelegate}; use settings::Settings; @@ -105,7 +105,7 @@ impl PickerDelegate for ContactFinder { fn render_match( &self, ix: usize, - mouse_state: &MouseState, + mouse_state: MouseState, selected: bool, cx: &gpui::AppContext, ) -> ElementBox { diff --git a/crates/contacts_panel/src/contacts_panel.rs b/crates/contacts_panel/src/contacts_panel.rs index 888a0a28fb..6d2885e867 100644 --- a/crates/contacts_panel/src/contacts_panel.rs +++ b/crates/contacts_panel/src/contacts_panel.rs @@ -259,7 +259,7 @@ impl ContactsPanel { ) -> ElementBox { enum Header {} - let header_style = theme.header_row.style_for(&Default::default(), is_selected); + let header_style = theme.header_row.style_for(Default::default(), is_selected); let text = match section { Section::Requests => "Requests", Section::Online => "Online", @@ -299,7 +299,7 @@ impl ContactsPanel { .boxed() }) .with_cursor_style(CursorStyle::PointingHand) - .on_click(move |_, cx| cx.dispatch_action(ToggleExpanded(section))) + .on_click(move |_, _, cx| cx.dispatch_action(ToggleExpanded(section))) .boxed() } @@ -331,11 +331,7 @@ impl ContactsPanel { .constrained() .with_height(theme.row_height) .contained() - .with_style( - *theme - .contact_row - .style_for(&Default::default(), is_selected), - ) + .with_style(*theme.contact_row.style_for(Default::default(), is_selected)) .boxed() } @@ -442,7 +438,7 @@ impl ContactsPanel { } else { CursorStyle::Arrow }) - .on_click(move |_, cx| { + .on_click(move |_, _, cx| { if !is_host { cx.dispatch_global_action(JoinProject { contact: contact.clone(), @@ -504,7 +500,7 @@ impl ContactsPanel { .boxed() }) .with_cursor_style(CursorStyle::PointingHand) - .on_click(move |_, cx| { + .on_click(move |_, _, cx| { cx.dispatch_action(RespondToContactRequest { user_id, accept: false, @@ -526,7 +522,7 @@ impl ContactsPanel { .boxed() }) .with_cursor_style(CursorStyle::PointingHand) - .on_click(move |_, cx| { + .on_click(move |_, _, cx| { cx.dispatch_action(RespondToContactRequest { user_id, accept: true, @@ -549,7 +545,7 @@ impl ContactsPanel { }) .with_padding(Padding::uniform(2.)) .with_cursor_style(CursorStyle::PointingHand) - .on_click(move |_, cx| cx.dispatch_action(RemoveContact(user_id))) + .on_click(move |_, _, cx| cx.dispatch_action(RemoveContact(user_id))) .flex_float() .boxed(), ); @@ -558,11 +554,7 @@ impl ContactsPanel { row.constrained() .with_height(theme.row_height) .contained() - .with_style( - *theme - .contact_row - .style_for(&Default::default(), is_selected), - ) + .with_style(*theme.contact_row.style_for(Default::default(), is_selected)) .boxed() } @@ -862,7 +854,7 @@ impl View for ContactsPanel { .boxed() }) .with_cursor_style(CursorStyle::PointingHand) - .on_click(|_, cx| cx.dispatch_action(contact_finder::Toggle)) + .on_click(|_, _, cx| cx.dispatch_action(contact_finder::Toggle)) .boxed(), ) .constrained() @@ -910,7 +902,7 @@ impl View for ContactsPanel { }, ) .with_cursor_style(CursorStyle::PointingHand) - .on_click(move |_, cx| { + .on_click(move |_, _, cx| { cx.write_to_clipboard(ClipboardItem::new( info.url.to_string(), )); diff --git a/crates/contacts_panel/src/notifications.rs b/crates/contacts_panel/src/notifications.rs index 555d8962d3..c02fd73b8f 100644 --- a/crates/contacts_panel/src/notifications.rs +++ b/crates/contacts_panel/src/notifications.rs @@ -61,7 +61,7 @@ pub fn render_user_notification( }) .with_cursor_style(CursorStyle::PointingHand) .with_padding(Padding::uniform(5.)) - .on_click(move |_, cx| cx.dispatch_any_action(dismiss_action.boxed_clone())) + .on_click(move |_, _, cx| cx.dispatch_any_action(dismiss_action.boxed_clone())) .aligned() .constrained() .with_height( @@ -76,13 +76,10 @@ pub fn render_user_notification( .named("contact notification header"), ) .with_children(body.map(|body| { - Label::new( - body.to_string(), - theme.body_message.text.clone(), - ) - .contained() - .with_style(theme.body_message.container) - .boxed() + Label::new(body.to_string(), theme.body_message.text.clone()) + .contained() + .with_style(theme.body_message.container) + .boxed() })) .with_children(if buttons.is_empty() { None @@ -99,7 +96,7 @@ pub fn render_user_notification( .boxed() }) .with_cursor_style(CursorStyle::PointingHand) - .on_click(move |_, cx| cx.dispatch_any_action(action.boxed_clone())) + .on_click(move |_, _, cx| cx.dispatch_any_action(action.boxed_clone())) .boxed() }, )) diff --git a/crates/diagnostics/src/items.rs b/crates/diagnostics/src/items.rs index 426f25629d..224e5e94a7 100644 --- a/crates/diagnostics/src/items.rs +++ b/crates/diagnostics/src/items.rs @@ -159,7 +159,7 @@ impl View for DiagnosticIndicator { .boxed() }) .with_cursor_style(CursorStyle::PointingHand) - .on_click(|_, cx| cx.dispatch_action(crate::Deploy)) + .on_click(|_, _, cx| cx.dispatch_action(crate::Deploy)) .aligned() .boxed(), ); @@ -192,7 +192,7 @@ impl View for DiagnosticIndicator { .boxed() }) .with_cursor_style(CursorStyle::PointingHand) - .on_click(|_, cx| cx.dispatch_action(GoToNextDiagnostic)) + .on_click(|_, _, cx| cx.dispatch_action(GoToNextDiagnostic)) .boxed(), ); } diff --git a/crates/editor/src/editor.rs b/crates/editor/src/editor.rs index ae8335f242..56e88add54 100644 --- a/crates/editor/src/editor.rs +++ b/crates/editor/src/editor.rs @@ -679,7 +679,7 @@ impl CompletionsMenu { }, ) .with_cursor_style(CursorStyle::PointingHand) - .on_mouse_down(move |cx| { + .on_mouse_down(move |_, cx| { cx.dispatch_action(ConfirmCompletion { item_ix: Some(item_ix), }); @@ -812,7 +812,7 @@ impl CodeActionsMenu { .boxed() }) .with_cursor_style(CursorStyle::PointingHand) - .on_mouse_down(move |cx| { + .on_mouse_down(move |_, cx| { cx.dispatch_action(ConfirmCodeAction { item_ix: Some(item_ix), }); @@ -2603,7 +2603,7 @@ impl Editor { }) .with_cursor_style(CursorStyle::PointingHand) .with_padding(Padding::uniform(3.)) - .on_mouse_down(|cx| { + .on_mouse_down(|_, cx| { cx.dispatch_action(ToggleCodeActions { deployed_from_indicator: true, }); diff --git a/crates/file_finder/src/file_finder.rs b/crates/file_finder/src/file_finder.rs index f58c733cc7..e19c1de3a8 100644 --- a/crates/file_finder/src/file_finder.rs +++ b/crates/file_finder/src/file_finder.rs @@ -1,7 +1,7 @@ use fuzzy::PathMatch; use gpui::{ - actions, elements::*, AppContext, Entity, ModelHandle, MutableAppContext, RenderContext, Task, - View, ViewContext, ViewHandle, + actions, elements::*, AppContext, Entity, ModelHandle, MouseState, MutableAppContext, + RenderContext, Task, View, ViewContext, ViewHandle, }; use picker::{Picker, PickerDelegate}; use project::{Project, ProjectPath, WorktreeId}; @@ -226,7 +226,7 @@ impl PickerDelegate for FileFinder { fn render_match( &self, ix: usize, - mouse_state: &MouseState, + mouse_state: MouseState, selected: bool, cx: &AppContext, ) -> ElementBox { diff --git a/crates/gpui/src/app.rs b/crates/gpui/src/app.rs index e75461953f..63f7a67327 100644 --- a/crates/gpui/src/app.rs +++ b/crates/gpui/src/app.rs @@ -460,7 +460,7 @@ impl TestAppContext { view_id: handle.id(), view_type: PhantomData, titlebar_height: 0., - hovered_region_id: None, + hovered_region_ids: Default::default(), clicked_region_id: None, refreshing: false, }; @@ -1080,7 +1080,7 @@ impl MutableAppContext { window_id, view_id, titlebar_height, - hovered_region_id: None, + hovered_region_ids: Default::default(), clicked_region_id: None, refreshing: false, }) @@ -3402,7 +3402,7 @@ pub struct RenderParams { pub window_id: usize, pub view_id: usize, pub titlebar_height: f32, - pub hovered_region_id: Option, + pub hovered_region_ids: HashSet, pub clicked_region_id: Option, pub refreshing: bool, } @@ -3411,14 +3411,14 @@ pub struct RenderContext<'a, T: View> { pub(crate) window_id: usize, pub(crate) view_id: usize, pub(crate) view_type: PhantomData, - pub(crate) hovered_region_id: Option, + pub(crate) hovered_region_ids: HashSet, pub(crate) clicked_region_id: Option, pub app: &'a mut MutableAppContext, pub titlebar_height: f32, pub refreshing: bool, } -#[derive(Clone, Copy)] +#[derive(Clone, Copy, Default)] pub struct MouseState { pub hovered: bool, pub clicked: bool, @@ -3432,7 +3432,7 @@ impl<'a, V: View> RenderContext<'a, V> { view_id: params.view_id, view_type: PhantomData, titlebar_height: params.titlebar_height, - hovered_region_id: params.hovered_region_id, + hovered_region_ids: params.hovered_region_ids.clone(), clicked_region_id: params.clicked_region_id, refreshing: params.refreshing, } @@ -3447,14 +3447,14 @@ impl<'a, V: View> RenderContext<'a, V> { } pub fn mouse_state(&self, region_id: usize) -> MouseState { - let region_id = Some(MouseRegionId { + let region_id = MouseRegionId { view_id: self.view_id, tag: TypeId::of::(), region_id, - }); + }; MouseState { - hovered: self.hovered_region_id == region_id, - clicked: self.clicked_region_id == region_id, + hovered: self.hovered_region_ids.contains(®ion_id), + clicked: self.clicked_region_id == Some(region_id), } } diff --git a/crates/gpui/src/elements/mouse_event_handler.rs b/crates/gpui/src/elements/mouse_event_handler.rs index 7440be8c56..ffe70caa12 100644 --- a/crates/gpui/src/elements/mouse_event_handler.rs +++ b/crates/gpui/src/elements/mouse_event_handler.rs @@ -1,3 +1,5 @@ +use std::{any::TypeId, rc::Rc}; + use super::Padding; use crate::{ geometry::{ @@ -6,40 +8,33 @@ use crate::{ }, platform::CursorStyle, scene::CursorRegion, - DebugContext, Element, ElementBox, ElementStateHandle, Event, EventContext, LayoutContext, + DebugContext, Element, ElementBox, Event, EventContext, LayoutContext, MouseRegion, MouseState, PaintContext, RenderContext, SizeConstraint, View, }; use serde_json::json; pub struct MouseEventHandler { - state: ElementStateHandle, child: ElementBox, + tag: TypeId, + id: usize, cursor_style: Option, - mouse_down_handler: Option>, - click_handler: Option>, - drag_handler: Option>, + mouse_down_handler: Option>, + click_handler: Option>, + drag_handler: Option>, padding: Padding, } -#[derive(Default)] -pub struct MouseState { - pub hovered: bool, - pub clicked: bool, - prev_drag_position: Option, -} - impl MouseEventHandler { pub fn new(id: usize, cx: &mut RenderContext, render_child: F) -> Self where Tag: 'static, V: View, - F: FnOnce(&MouseState, &mut RenderContext) -> ElementBox, + F: FnOnce(MouseState, &mut RenderContext) -> ElementBox, { - let state_handle = cx.element_state::(id); - let child = state_handle.update(cx, |state, cx| render_child(state, cx)); Self { - state: state_handle, - child, + id, + tag: TypeId::of::(), + child: render_child(cx.mouse_state::(id), cx), cursor_style: None, mouse_down_handler: None, click_handler: None, @@ -53,18 +48,24 @@ impl MouseEventHandler { self } - pub fn on_mouse_down(mut self, handler: impl FnMut(&mut EventContext) + 'static) -> Self { - self.mouse_down_handler = Some(Box::new(handler)); + pub fn on_mouse_down( + mut self, + handler: impl Fn(Vector2F, &mut EventContext) + 'static, + ) -> Self { + self.mouse_down_handler = Some(Rc::new(handler)); self } - pub fn on_click(mut self, handler: impl FnMut(usize, &mut EventContext) + 'static) -> Self { - self.click_handler = Some(Box::new(handler)); + pub fn on_click( + mut self, + handler: impl Fn(Vector2F, usize, &mut EventContext) + 'static, + ) -> Self { + self.click_handler = Some(Rc::new(handler)); self } - pub fn on_drag(mut self, handler: impl FnMut(Vector2F, &mut EventContext) + 'static) -> Self { - self.drag_handler = Some(Box::new(handler)); + pub fn on_drag(mut self, handler: impl Fn(Vector2F, &mut EventContext) + 'static) -> Self { + self.drag_handler = Some(Rc::new(handler)); self } @@ -107,6 +108,18 @@ impl Element for MouseEventHandler { style, }); } + + cx.scene.push_mouse_region(MouseRegion { + view_id: cx.current_view_id(), + tag: self.tag, + region_id: self.id, + bounds, + hover: None, + click: self.click_handler.clone(), + mouse_down: self.mouse_down_handler.clone(), + drag: self.drag_handler.clone(), + }); + self.child.paint(bounds.origin(), visible_bounds, cx); } @@ -114,81 +127,12 @@ impl Element for MouseEventHandler { &mut self, event: &Event, _: RectF, - visible_bounds: RectF, + _: RectF, _: &mut Self::LayoutState, _: &mut Self::PaintState, cx: &mut EventContext, ) -> bool { - let hit_bounds = self.hit_bounds(visible_bounds); - let mouse_down_handler = self.mouse_down_handler.as_mut(); - let click_handler = self.click_handler.as_mut(); - let drag_handler = self.drag_handler.as_mut(); - - let handled_in_child = self.child.dispatch_event(event, cx); - - self.state.update(cx, |state, cx| match event { - Event::MouseMoved { - position, - left_mouse_down, - } => { - if !left_mouse_down { - let mouse_in = hit_bounds.contains_point(*position); - if state.hovered != mouse_in { - state.hovered = mouse_in; - cx.notify(); - return true; - } - } - handled_in_child - } - Event::LeftMouseDown { position, .. } => { - if !handled_in_child && hit_bounds.contains_point(*position) { - state.clicked = true; - state.prev_drag_position = Some(*position); - cx.notify(); - if let Some(handler) = mouse_down_handler { - handler(cx); - } - true - } else { - handled_in_child - } - } - Event::LeftMouseUp { - position, - click_count, - .. - } => { - state.prev_drag_position = None; - if !handled_in_child && state.clicked { - state.clicked = false; - cx.notify(); - if let Some(handler) = click_handler { - if hit_bounds.contains_point(*position) { - handler(*click_count, cx); - } - } - true - } else { - handled_in_child - } - } - Event::LeftMouseDragged { position, .. } => { - if !handled_in_child && state.clicked { - let prev_drag_position = state.prev_drag_position.replace(*position); - if let Some((handler, prev_position)) = drag_handler.zip(prev_drag_position) { - let delta = *position - prev_position; - if !delta.is_zero() { - (handler)(delta, cx); - } - } - true - } else { - handled_in_child - } - } - _ => handled_in_child, - }) + self.child.dispatch_event(event, cx) } fn debug( diff --git a/crates/gpui/src/presenter.rs b/crates/gpui/src/presenter.rs index 349f8a1a6f..1c22ceb1b6 100644 --- a/crates/gpui/src/presenter.rs +++ b/crates/gpui/src/presenter.rs @@ -31,7 +31,7 @@ pub struct Presenter { text_layout_cache: TextLayoutCache, asset_cache: Arc, last_mouse_moved_event: Option, - hovered_region_id: Option, + hovered_region_ids: HashSet, clicked_region: Option, prev_drag_position: Option, titlebar_height: f32, @@ -56,7 +56,7 @@ impl Presenter { text_layout_cache, asset_cache, last_mouse_moved_event: None, - hovered_region_id: None, + hovered_region_ids: Default::default(), clicked_region: None, prev_drag_position: None, titlebar_height, @@ -100,7 +100,7 @@ impl Presenter { window_id: self.window_id, view_id: *view_id, titlebar_height: self.titlebar_height, - hovered_region_id: self.hovered_region_id, + hovered_region_ids: self.hovered_region_ids.clone(), clicked_region_id: self.clicked_region.as_ref().map(MouseRegion::id), refreshing: false, }) @@ -118,7 +118,7 @@ impl Presenter { window_id: self.window_id, view_id: *view_id, titlebar_height: self.titlebar_height, - hovered_region_id: self.hovered_region_id, + hovered_region_ids: self.hovered_region_ids.clone(), clicked_region_id: self.clicked_region.as_ref().map(MouseRegion::id), refreshing: true, }) @@ -181,7 +181,7 @@ impl Presenter { asset_cache: &self.asset_cache, view_stack: Vec::new(), refreshing, - hovered_region_id: self.hovered_region_id, + hovered_region_ids: self.hovered_region_ids.clone(), clicked_region_id: self.clicked_region.as_ref().map(MouseRegion::id), titlebar_height: self.titlebar_height, app: cx, @@ -198,14 +198,16 @@ impl Presenter { font_cache: &self.font_cache, text_layout_cache: &self.text_layout_cache, rendered_views: &mut self.rendered_views, + view_stack: Vec::new(), app: cx, } } pub fn dispatch_event(&mut self, event: Event, cx: &mut MutableAppContext) { if let Some(root_view_id) = cx.root_view_id(self.window_id) { - let mut unhovered_region = None; - let mut hovered_region = None; + let mut invalidated_views = Vec::new(); + let mut hovered_regions = Vec::new(); + let mut unhovered_regions = Vec::new(); let mut clicked_region = None; let mut dragged_region = None; @@ -213,6 +215,7 @@ impl Presenter { Event::LeftMouseDown { position, .. } => { for region in self.mouse_regions.iter().rev() { if region.bounds.contains_point(position) { + invalidated_views.push(region.view_id); self.clicked_region = Some(region.clone()); self.prev_drag_position = Some(position); break; @@ -226,6 +229,7 @@ impl Presenter { } => { self.prev_drag_position.take(); if let Some(region) = self.clicked_region.take() { + invalidated_views.push(region.view_id); if region.bounds.contains_point(position) { clicked_region = Some((region, position, click_count)); } @@ -248,13 +252,18 @@ impl Presenter { cx.platform().set_cursor_style(style_to_assign); for region in self.mouse_regions.iter().rev() { + let region_id = region.id(); if region.bounds.contains_point(position) { - if hovered_region.is_none() { - hovered_region = Some(region.clone()); + if !self.hovered_region_ids.contains(®ion_id) { + invalidated_views.push(region.view_id); + hovered_regions.push(region.clone()); + self.hovered_region_ids.insert(region_id); } } else { - if self.hovered_region_id == Some(region.id()) { - unhovered_region = Some(region.clone()) + if self.hovered_region_ids.contains(®ion_id) { + invalidated_views.push(region.view_id); + unhovered_regions.push(region.clone()); + self.hovered_region_ids.remove(®ion_id); } } } @@ -279,10 +288,8 @@ impl Presenter { _ => {} } - self.hovered_region_id = hovered_region.as_ref().map(MouseRegion::id); - let mut event_cx = self.build_event_context(cx); - if let Some(unhovered_region) = unhovered_region { + for unhovered_region in unhovered_regions { if let Some(hover_callback) = unhovered_region.hover { event_cx.with_current_view(unhovered_region.view_id, |event_cx| { hover_callback(false, event_cx); @@ -290,7 +297,7 @@ impl Presenter { } } - if let Some(hovered_region) = hovered_region { + for hovered_region in hovered_regions { if let Some(hover_callback) = hovered_region.hover { event_cx.with_current_view(hovered_region.view_id, |event_cx| { hover_callback(true, event_cx); @@ -316,7 +323,7 @@ impl Presenter { event_cx.dispatch_event(root_view_id, &event); - let invalidated_views = event_cx.invalidated_views; + invalidated_views.extend(event_cx.invalidated_views); let dispatch_directives = event_cx.dispatched_actions; for view_id in invalidated_views { @@ -376,7 +383,7 @@ pub struct LayoutContext<'a> { pub app: &'a mut MutableAppContext, pub refreshing: bool, titlebar_height: f32, - hovered_region_id: Option, + hovered_region_ids: HashSet, clicked_region_id: Option, } @@ -405,7 +412,7 @@ impl<'a> LayoutContext<'a> { view_id: handle.id(), view_type: PhantomData, titlebar_height: self.titlebar_height, - hovered_region_id: self.hovered_region_id, + hovered_region_ids: self.hovered_region_ids.clone(), clicked_region_id: self.clicked_region_id, refreshing: self.refreshing, }; @@ -469,6 +476,7 @@ impl<'a> UpgradeViewHandle for LayoutContext<'a> { pub struct PaintContext<'a> { rendered_views: &'a mut HashMap, + view_stack: Vec, pub scene: &'a mut Scene, pub font_cache: &'a FontCache, pub text_layout_cache: &'a TextLayoutCache, @@ -478,10 +486,16 @@ pub struct PaintContext<'a> { impl<'a> PaintContext<'a> { fn paint(&mut self, view_id: usize, origin: Vector2F, visible_bounds: RectF) { if let Some(mut tree) = self.rendered_views.remove(&view_id) { + self.view_stack.push(view_id); tree.paint(origin, visible_bounds, self); self.rendered_views.insert(view_id, tree); + self.view_stack.pop(); } } + + pub fn current_view_id(&self) -> usize { + *self.view_stack.last().unwrap() + } } impl<'a> Deref for PaintContext<'a> { diff --git a/crates/gpui/src/scene.rs b/crates/gpui/src/scene.rs index 6b9ef962cf..caeae3c89f 100644 --- a/crates/gpui/src/scene.rs +++ b/crates/gpui/src/scene.rs @@ -50,11 +50,12 @@ pub struct MouseRegion { pub region_id: usize, pub bounds: RectF, pub hover: Option>, + pub mouse_down: Option>, pub click: Option>, pub drag: Option>, } -#[derive(Copy, Clone, Eq, PartialEq)] +#[derive(Copy, Clone, Eq, PartialEq, Hash)] pub struct MouseRegionId { pub view_id: usize, pub tag: TypeId, @@ -242,6 +243,10 @@ impl Scene { self.active_layer().push_cursor_region(region); } + pub fn push_mouse_region(&mut self, region: MouseRegion) { + self.active_layer().push_mouse_region(region); + } + pub fn push_image(&mut self, image: Image) { self.active_layer().push_image(image) } diff --git a/crates/gpui/src/views/select.rs b/crates/gpui/src/views/select.rs index 44576a0d95..80c3ba2884 100644 --- a/crates/gpui/src/views/select.rs +++ b/crates/gpui/src/views/select.rs @@ -119,7 +119,7 @@ impl View for Select { .with_style(style.header) .boxed() }) - .on_click(move |_, cx| cx.dispatch_action(ToggleSelect)) + .on_click(move |_, _, cx| cx.dispatch_action(ToggleSelect)) .boxed(), ); if self.is_open { @@ -151,7 +151,9 @@ impl View for Select { ) }, ) - .on_click(move |_, cx| cx.dispatch_action(SelectItem(ix))) + .on_click(move |_, _, cx| { + cx.dispatch_action(SelectItem(ix)) + }) .boxed() })) }, diff --git a/crates/outline/src/outline.rs b/crates/outline/src/outline.rs index 57c7441bfe..19b309116a 100644 --- a/crates/outline/src/outline.rs +++ b/crates/outline/src/outline.rs @@ -4,8 +4,8 @@ use editor::{ }; use fuzzy::StringMatch; use gpui::{ - actions, elements::*, geometry::vector::Vector2F, AppContext, Entity, MutableAppContext, - RenderContext, Task, View, ViewContext, ViewHandle, + actions, elements::*, geometry::vector::Vector2F, AppContext, Entity, MouseState, + MutableAppContext, RenderContext, Task, View, ViewContext, ViewHandle, }; use language::Outline; use ordered_float::OrderedFloat; @@ -231,7 +231,7 @@ impl PickerDelegate for OutlineView { fn render_match( &self, ix: usize, - mouse_state: &MouseState, + mouse_state: MouseState, selected: bool, cx: &AppContext, ) -> ElementBox { diff --git a/crates/picker/src/picker.rs b/crates/picker/src/picker.rs index 0dfd7c0a49..383d45ff3f 100644 --- a/crates/picker/src/picker.rs +++ b/crates/picker/src/picker.rs @@ -1,14 +1,14 @@ use editor::Editor; use gpui::{ elements::{ - ChildView, Flex, Label, MouseEventHandler, MouseState, ParentElement, ScrollTarget, - UniformList, UniformListState, + ChildView, Flex, Label, MouseEventHandler, ParentElement, ScrollTarget, UniformList, + UniformListState, }, geometry::vector::{vec2f, Vector2F}, keymap, platform::CursorStyle, - AppContext, Axis, Element, ElementBox, Entity, MutableAppContext, RenderContext, Task, View, - ViewContext, ViewHandle, WeakViewHandle, + AppContext, Axis, Element, ElementBox, Entity, MouseState, MutableAppContext, RenderContext, + Task, View, ViewContext, ViewHandle, WeakViewHandle, }; use settings::Settings; use std::cmp; @@ -34,7 +34,7 @@ pub trait PickerDelegate: View { fn render_match( &self, ix: usize, - state: &MouseState, + state: MouseState, selected: bool, cx: &AppContext, ) -> ElementBox; @@ -92,7 +92,7 @@ impl View for Picker { .read(cx) .render_match(ix, state, ix == selected_ix, cx) }) - .on_mouse_down(move |cx| cx.dispatch_action(SelectIndex(ix))) + .on_mouse_down(move |_, cx| cx.dispatch_action(SelectIndex(ix))) .with_cursor_style(CursorStyle::PointingHand) .boxed() })); diff --git a/crates/project_panel/src/project_panel.rs b/crates/project_panel/src/project_panel.rs index e128efddbe..17eca4d99f 100644 --- a/crates/project_panel/src/project_panel.rs +++ b/crates/project_panel/src/project_panel.rs @@ -839,7 +839,7 @@ impl ProjectPanel { .with_padding_left(padding) .boxed() }) - .on_click(move |click_count, cx| { + .on_click(move |_, click_count, cx| { if kind == EntryKind::Dir { cx.dispatch_action(ToggleExpanded(entry_id)) } else { diff --git a/crates/project_symbols/src/project_symbols.rs b/crates/project_symbols/src/project_symbols.rs index 20da49b1df..ea99767e0a 100644 --- a/crates/project_symbols/src/project_symbols.rs +++ b/crates/project_symbols/src/project_symbols.rs @@ -3,8 +3,8 @@ use editor::{ }; use fuzzy::{StringMatch, StringMatchCandidate}; use gpui::{ - actions, elements::*, AppContext, Entity, ModelHandle, MutableAppContext, RenderContext, Task, - View, ViewContext, ViewHandle, + actions, elements::*, AppContext, Entity, ModelHandle, MouseState, MutableAppContext, + RenderContext, Task, View, ViewContext, ViewHandle, }; use ordered_float::OrderedFloat; use picker::{Picker, PickerDelegate}; @@ -221,7 +221,7 @@ impl PickerDelegate for ProjectSymbolsView { fn render_match( &self, ix: usize, - mouse_state: &MouseState, + mouse_state: MouseState, selected: bool, cx: &AppContext, ) -> ElementBox { diff --git a/crates/search/src/buffer_search.rs b/crates/search/src/buffer_search.rs index 5581cbd608..94b6261a0f 100644 --- a/crates/search/src/buffer_search.rs +++ b/crates/search/src/buffer_search.rs @@ -290,7 +290,7 @@ impl BufferSearchBar { .with_style(style.container) .boxed() }) - .on_click(move |_, cx| cx.dispatch_action(ToggleSearchOption(search_option))) + .on_click(move |_, _, cx| cx.dispatch_action(ToggleSearchOption(search_option))) .with_cursor_style(CursorStyle::PointingHand) .boxed() } @@ -314,7 +314,7 @@ impl BufferSearchBar { .with_style(style.container) .boxed() }) - .on_click(move |_, cx| match direction { + .on_click(move |_, _, cx| match direction { Direction::Prev => cx.dispatch_action(SelectPrevMatch), Direction::Next => cx.dispatch_action(SelectNextMatch), }) diff --git a/crates/search/src/project_search.rs b/crates/search/src/project_search.rs index 4549aa4f90..e3834f6f45 100644 --- a/crates/search/src/project_search.rs +++ b/crates/search/src/project_search.rs @@ -672,7 +672,7 @@ impl ProjectSearchBar { .with_style(style.container) .boxed() }) - .on_click(move |_, cx| match direction { + .on_click(move |_, _, cx| match direction { Direction::Prev => cx.dispatch_action(SelectPrevMatch), Direction::Next => cx.dispatch_action(SelectNextMatch), }) @@ -699,7 +699,7 @@ impl ProjectSearchBar { .with_style(style.container) .boxed() }) - .on_click(move |_, cx| cx.dispatch_action(ToggleSearchOption(option))) + .on_click(move |_, _, cx| cx.dispatch_action(ToggleSearchOption(option))) .with_cursor_style(CursorStyle::PointingHand) .boxed() } diff --git a/crates/theme/src/theme.rs b/crates/theme/src/theme.rs index bc9e93025d..d654363648 100644 --- a/crates/theme/src/theme.rs +++ b/crates/theme/src/theme.rs @@ -2,9 +2,9 @@ mod theme_registry; use gpui::{ color::Color, - elements::{ContainerStyle, ImageStyle, LabelStyle, MouseState}, + elements::{ContainerStyle, ImageStyle, LabelStyle}, fonts::{HighlightStyle, TextStyle}, - Border, + Border, MouseState, }; use serde::{de::DeserializeOwned, Deserialize}; use serde_json::Value; @@ -488,7 +488,7 @@ pub struct Interactive { } impl Interactive { - pub fn style_for(&self, state: &MouseState, active: bool) -> &T { + pub fn style_for(&self, state: MouseState, active: bool) -> &T { if active { if state.hovered { self.active_hover diff --git a/crates/theme_selector/src/theme_selector.rs b/crates/theme_selector/src/theme_selector.rs index 9f445c633a..106e6ad429 100644 --- a/crates/theme_selector/src/theme_selector.rs +++ b/crates/theme_selector/src/theme_selector.rs @@ -1,6 +1,6 @@ use fuzzy::{match_strings, StringMatch, StringMatchCandidate}; use gpui::{ - actions, elements::*, AppContext, Element, ElementBox, Entity, MutableAppContext, + actions, elements::*, AppContext, Element, ElementBox, Entity, MouseState, MutableAppContext, RenderContext, View, ViewContext, ViewHandle, }; use picker::{Picker, PickerDelegate}; @@ -213,7 +213,7 @@ impl PickerDelegate for ThemeSelector { fn render_match( &self, ix: usize, - mouse_state: &MouseState, + mouse_state: MouseState, selected: bool, cx: &AppContext, ) -> ElementBox { diff --git a/crates/workspace/src/lsp_status.rs b/crates/workspace/src/lsp_status.rs index f58e0b973e..ab1ae4931f 100644 --- a/crates/workspace/src/lsp_status.rs +++ b/crates/workspace/src/lsp_status.rs @@ -168,7 +168,8 @@ impl View for LspStatus { self.failed.join(", "), if self.failed.len() > 1 { "s" } else { "" } ); - handler = Some(|_, cx: &mut EventContext| cx.dispatch_action(DismissErrorMessage)); + handler = + Some(|_, _, cx: &mut EventContext| cx.dispatch_action(DismissErrorMessage)); } else { return Empty::new().boxed(); } diff --git a/crates/workspace/src/pane.rs b/crates/workspace/src/pane.rs index 8b97ef1a80..ba2a21bce4 100644 --- a/crates/workspace/src/pane.rs +++ b/crates/workspace/src/pane.rs @@ -788,7 +788,7 @@ impl Pane { .with_cursor_style(CursorStyle::PointingHand) .on_click({ let pane = pane.clone(); - move |_, cx| { + move |_, _, cx| { cx.dispatch_action(CloseItem { item_id, pane: pane.clone(), diff --git a/crates/workspace/src/sidebar.rs b/crates/workspace/src/sidebar.rs index afdacc2a31..5aec332913 100644 --- a/crates/workspace/src/sidebar.rs +++ b/crates/workspace/src/sidebar.rs @@ -293,7 +293,7 @@ impl View for SidebarButtons { .boxed() }) .with_cursor_style(CursorStyle::PointingHand) - .on_click(move |_, cx| { + .on_click(move |_, _, cx| { cx.dispatch_action(ToggleSidebarItem { side, item_index: ix, diff --git a/crates/workspace/src/workspace.rs b/crates/workspace/src/workspace.rs index e9f0efa311..f4197e7296 100644 --- a/crates/workspace/src/workspace.rs +++ b/crates/workspace/src/workspace.rs @@ -1730,7 +1730,7 @@ impl Workspace { .with_style(style.container) .boxed() }) - .on_click(|_, cx| cx.dispatch_action(Authenticate)) + .on_click(|_, _, cx| cx.dispatch_action(Authenticate)) .with_cursor_style(CursorStyle::PointingHand) .aligned() .boxed(), @@ -1781,7 +1781,7 @@ impl Workspace { if let Some(peer_id) = peer_id { MouseEventHandler::new::(replica_id.into(), cx, move |_, _| content) .with_cursor_style(CursorStyle::PointingHand) - .on_click(move |_, cx| cx.dispatch_action(ToggleFollow(peer_id))) + .on_click(move |_, _, cx| cx.dispatch_action(ToggleFollow(peer_id))) .boxed() } else { content