diff --git a/crates/diagnostics/src/diagnostics.rs b/crates/diagnostics/src/diagnostics.rs index 0ac282d199..72337c4696 100644 --- a/crates/diagnostics/src/diagnostics.rs +++ b/crates/diagnostics/src/diagnostics.rs @@ -1177,7 +1177,7 @@ mod tests { } fn editor_blocks(editor: &ViewHandle, cx: &mut AppContext) -> Vec<(u32, String)> { - let mut presenter = cx.build_presenter(editor.id(), 0., Default::default()); + let mut presenter = cx.build_window(editor.id(), 0., Default::default()); let mut cx = presenter.build_layout_context(Default::default(), false, cx); cx.render(editor, |editor, cx| { let snapshot = editor.snapshot(cx); diff --git a/crates/editor/src/element.rs b/crates/editor/src/element.rs index 779a173c34..96d84f59af 100644 --- a/crates/editor/src/element.rs +++ b/crates/editor/src/element.rs @@ -2531,7 +2531,7 @@ mod tests { let layouts = editor.update(cx, |editor, cx| { let snapshot = editor.snapshot(cx); - let mut presenter = cx.build_presenter(window_id, 30., Default::default()); + let mut presenter = cx.build_window(window_id, 30., Default::default()); let layout_cx = presenter.build_layout_context(Vector2F::zero(), false, cx); element .layout_line_numbers(0..6, &Default::default(), false, &snapshot, &layout_cx) @@ -2568,7 +2568,7 @@ mod tests { let mut element = EditorElement::new(editor.downgrade(), editor.read(cx).style(cx)); let mut scene = SceneBuilder::new(1.0); - let mut presenter = cx.build_presenter(window_id, 30., Default::default()); + let mut presenter = cx.build_window(window_id, 30., Default::default()); let mut layout_cx = presenter.build_layout_context(Vector2F::zero(), false, cx); let (size, mut state) = element.layout( SizeConstraint::new(vec2f(500., 500.), vec2f(500., 500.)), diff --git a/crates/gpui/src/app.rs b/crates/gpui/src/app.rs index 86b466ebc5..163ff86fcd 100644 --- a/crates/gpui/src/app.rs +++ b/crates/gpui/src/app.rs @@ -4,6 +4,7 @@ mod menu; pub(crate) mod ref_counts; #[cfg(any(test, feature = "test-support"))] pub mod test_app_context; +pub(crate) mod window; mod window_input_handler; use std::{ @@ -23,7 +24,6 @@ use std::{ use anyhow::{anyhow, Context, Result}; use parking_lot::Mutex; -use pathfinder_geometry::vector::Vector2F; use postage::oneshot; use smallvec::SmallVec; use smol::prelude::*; @@ -48,8 +48,8 @@ use crate::{ self, Appearance, KeyDownEvent, KeyUpEvent, ModifiersChangedEvent, MouseButton, PathPromptOptions, Platform, PromptLevel, WindowBounds, WindowOptions, }, - presenter::Presenter, util::post_inc, + window::{Window, WindowContext}, AssetCache, AssetSource, ClipboardItem, FontCache, MouseRegionId, TextLayoutCache, }; @@ -1622,25 +1622,10 @@ impl AppContext { let platform_window = this.platform .open_window(window_id, window_options, this.foreground.clone()); - let presenter = self.build_presenter( - window_id, - platform_window.titlebar_height(), - platform_window.appearance(), - ); - this.register_platform_window(window_id, &mut presenter, platform_window.as_mut()); + let window = + this.build_window(window_id, root_view.clone().into_any(), platform_window); - this.windows.insert( - window_id, - Window { - root_view: root_view.clone().into_any(), - focused_view_id: Some(root_view.id()), - is_active: false, - invalidation: None, - is_fullscreen: false, - platform_window, - presenter, - }, - ); + this.windows.insert(window_id, window); root_view.update(this, |view, cx| view.focus_in(cx.handle().into_any(), cx)); (window_id, root_view) @@ -1658,27 +1643,11 @@ impl AppContext { .build_and_insert_view(window_id, ParentId::Root, |cx| Some(build_root_view(cx))) .unwrap(); - let mut platform_window = this.platform.add_status_item(); - let mut presenter = self.build_presenter( - window_id, - platform_window.titlebar_height(), - platform_window.appearance(), - ); - this.register_platform_window(window_id, &mut presenter, platform_window.as_mut()); + let platform_window = this.platform.add_status_item(); + let window = + this.build_window(window_id, root_view.clone().into_any(), platform_window); - let focused_view_id = root_view.id(); - this.windows.insert( - window_id, - Window { - root_view: root_view.clone().into_any(), - focused_view_id: Some(focused_view_id), - is_active: false, - invalidation: None, - is_fullscreen: false, - platform_window, - presenter, - }, - ); + this.windows.insert(window_id, window); root_view.update(this, |view, cx| view.focus_in(cx.handle().into_any(), cx)); (window_id, root_view) @@ -1689,12 +1658,33 @@ impl AppContext { self.remove_window(id); } - fn register_platform_window( + pub fn replace_root_view(&mut self, window_id: usize, build_root_view: F) -> ViewHandle + where + T: View, + F: FnOnce(&mut ViewContext) -> T, + { + self.update(|this| { + let root_view = this + .build_and_insert_view(window_id, ParentId::Root, |cx| Some(build_root_view(cx))) + .unwrap(); + let window = this.windows.get_mut(&window_id).unwrap(); + window.root_view = root_view.clone().into_any(); + window.focused_view_id = Some(root_view.id()); + root_view + }) + } + + pub fn remove_window(&mut self, window_id: usize) { + self.windows.remove(&window_id); + self.flush_effects(); + } + + pub fn build_window( &mut self, window_id: usize, - presenter: &mut Presenter, - platform_window: &mut dyn platform::Window, - ) { + root_view: AnyViewHandle, + mut platform_window: Box, + ) -> Window { { let mut app = self.upgrade(); @@ -1758,51 +1748,19 @@ impl AppContext { window_id, })); - let scene = presenter.build_scene( - platform_window.content_size(), - platform_window.scale_factor(), - false, - self, - ); - platform_window.present_scene(scene); - } - - pub fn replace_root_view(&mut self, window_id: usize, build_root_view: F) -> ViewHandle - where - T: View, - F: FnOnce(&mut ViewContext) -> T, - { - self.update(|this| { - let root_view = this - .build_and_insert_view(window_id, ParentId::Root, |cx| Some(build_root_view(cx))) - .unwrap(); - let window = this.windows.get_mut(&window_id).unwrap(); - window.root_view = root_view.clone().into_any(); - window.focused_view_id = Some(root_view.id()); - root_view - }) - } - - pub fn remove_window(&mut self, window_id: usize) { - self.windows.remove(&window_id); - self.flush_effects(); - } - - pub fn build_presenter( - &mut self, - window_id: usize, - titlebar_height: f32, - appearance: Appearance, - ) -> Presenter { - Presenter::new( + let mut window = Window::new( window_id, - titlebar_height, - appearance, + root_view, + platform_window, self.font_cache.clone(), TextLayoutCache::new(self.platform.fonts()), self.assets.clone(), self, - ) + ); + + let scene = WindowContext::new(self, &mut window, window_id).build_scene(false); + window.platform_window.present_scene(scene); + window } pub fn add_view(&mut self, parent_handle: &AnyViewHandle, build_view: F) -> ViewHandle @@ -2144,21 +2102,16 @@ impl AppContext { } fn update_windows(&mut self) { - for (window_id, window) in &mut self.windows { - if let Some(mut invalidation) = window.invalidation.take() { - window.presenter.invalidate( - &mut invalidation, - window.platform_window.appearance(), - self, - ); - let scene = window.presenter.build_scene( - window.platform_window.content_size(), - window.platform_window.scale_factor(), - false, - self, - ); - window.platform_window.present_scene(scene); - } + let window_ids = self.windows.keys().cloned().collect::>(); + for window_id in window_ids { + self.update_window(window_id, |cx| { + if let Some(mut invalidation) = cx.window.invalidation.take() { + let appearance = cx.window.platform_window.appearance(); + cx.invalidate(&mut invalidation, appearance); + let scene = cx.build_scene(false); + cx.window.platform_window.present_scene(scene); + } + }); } } @@ -2223,20 +2176,14 @@ impl AppContext { } fn perform_window_refresh(&mut self) { - for window in self.windows.values_mut() { - let mut invalidation = window.invalidation.take().unwrap_or_default(); - window.presenter.invalidate( - &mut invalidation, - window.platform_window.appearance(), - self, - ); - let scene = window.presenter.build_scene( - window.platform_window.content_size(), - window.platform_window.scale_factor(), - true, - self, - ); - window.platform_window.present_scene(scene); + let window_ids = self.windows.keys().cloned().collect::>(); + for window_id in window_ids { + self.update_window(window_id, |cx| { + let mut invalidation = cx.window.invalidation.take().unwrap_or_default(); + cx.invalidate(&mut invalidation, cx.window.platform_window.appearance()); + let scene = cx.build_scene(true); + cx.window.platform_window.present_scene(scene); + }); } } @@ -2478,14 +2425,12 @@ impl AppContext { self.update_window(window_id, |cx| { if let Some(display) = cx.window_display_uuid() { let bounds = cx.window_bounds(); - cx.window_bounds_observations.clone().emit( - window_id, - self, - move |callback, this| { + cx.window_bounds_observations + .clone() + .emit(window_id, cx, move |callback, this| { callback(bounds, display, this); true - }, - ); + }); } }); } @@ -2708,16 +2653,6 @@ pub enum ParentId { Root, } -pub struct Window { - root_view: AnyViewHandle, - focused_view_id: Option, - is_active: bool, - is_fullscreen: bool, - invalidation: Option, - presenter: Presenter, - platform_window: Box, -} - #[derive(Default, Clone)] pub struct WindowInvalidation { pub updated: HashSet, @@ -3494,138 +3429,6 @@ impl DerefMut for ModelContext<'_, M> { } } -pub struct WindowContext<'a: 'b, 'b> { - app_context: &'a mut AppContext, - window: &'b mut Window, - window_id: usize, -} - -impl Deref for WindowContext<'_, '_> { - type Target = AppContext; - - fn deref(&self) -> &Self::Target { - self.app_context - } -} - -impl DerefMut for WindowContext<'_, '_> { - fn deref_mut(&mut self) -> &mut Self::Target { - &mut self.app_context - } -} - -impl WindowContext<'_, '_> { - pub fn dispatch_keystroke(&mut self, keystroke: &Keystroke) -> bool { - let window_id = self.window_id; - if let Some(focused_view_id) = self.focused_view_id(window_id) { - let dispatch_path = self - .ancestors(window_id, focused_view_id) - .filter_map(|view_id| { - self.views - .get(&(window_id, view_id)) - .map(|view| (view_id, view.keymap_context(self))) - }) - .collect(); - - let match_result = self - .keystroke_matcher - .push_keystroke(keystroke.clone(), dispatch_path); - let mut handled_by = None; - - let keystroke_handled = match &match_result { - MatchResult::None => false, - MatchResult::Pending => true, - MatchResult::Matches(matches) => { - for (view_id, action) in matches { - if self.handle_dispatch_action_from_effect( - window_id, - Some(*view_id), - action.as_ref(), - ) { - self.keystroke_matcher.clear_pending(); - handled_by = Some(action.boxed_clone()); - break; - } - } - handled_by.is_some() - } - }; - - self.keystroke( - window_id, - keystroke.clone(), - handled_by, - match_result.clone(), - ); - keystroke_handled - } else { - self.keystroke(window_id, keystroke.clone(), None, MatchResult::None); - false - } - } - - pub fn dispatch_event(&mut self, event: Event, event_reused: bool) -> bool { - self.window - .presenter - .dispatch_event(event, event_reused, self) - } - - pub fn set_window_title(&mut self, title: &str) { - self.window.platform_window.set_title(title); - } - - pub fn set_window_edited(&mut self, edited: bool) { - self.window.platform_window.set_edited(edited); - } - - pub fn is_topmost_window_for_position(&self, position: Vector2F) -> bool { - self.window - .platform_window - .is_topmost_for_position(position) - } - - pub fn activate_window(&self) { - self.window.platform_window.activate(); - } - - pub fn window_bounds(&self) -> WindowBounds { - self.window.platform_window.bounds() - } - - pub fn window_display_uuid(&self) -> Option { - self.window.platform_window.screen().display_uuid() - } - - pub fn debug_elements(&self) -> Option { - self.window.presenter.debug_elements(self) - } - - fn show_character_palette(&self) { - self.window.platform_window.show_character_palette(); - } - - pub fn minimize_window(&self) { - self.window.platform_window.minimize(); - } - - pub fn zoom_window(&self) { - self.window.platform_window.zoom(); - } - - pub fn toggle_window_full_screen(&self) { - self.window.platform_window.toggle_full_screen(); - } - - pub fn prompt( - &self, - level: PromptLevel, - msg: &str, - answers: &[&str], - ) -> oneshot::Receiver { - self.window.platform_window.prompt(level, msg, answers) - } -} - pub struct ViewContext<'a, T: ?Sized> { app: &'a mut AppContext, window_id: usize, @@ -5139,6 +4942,7 @@ mod tests { elements::*, impl_actions, platform::{MouseButton, MouseButtonEvent}, + window::ChildView, }; use itertools::Itertools; use postage::{sink::Sink, stream::Stream}; @@ -6847,7 +6651,7 @@ mod tests { let (window_id, root_view) = cx.add_window(Default::default(), |_| View(0)); cx.update_window(window_id, |cx| { assert_eq!( - cx.window.presenter.rendered_views[&root_view.id()].name(), + cx.window.rendered_views[&root_view.id()].name(), Some("render count: 0") ); }); @@ -6859,11 +6663,11 @@ mod tests { cx.update_window(window_id, |cx| { assert_eq!( - cx.window.presenter.rendered_views[&root_view.id()].name(), + cx.window.rendered_views[&root_view.id()].name(), Some("render count: 1") ); assert_eq!( - cx.window.presenter.rendered_views[&view.id()].name(), + cx.window.rendered_views[&view.id()].name(), Some("render count: 0") ); }); @@ -6872,11 +6676,11 @@ mod tests { cx.update_window(window_id, |cx| { assert_eq!( - cx.window.presenter.rendered_views[&root_view.id()].name(), + cx.window.rendered_views[&root_view.id()].name(), Some("render count: 2") ); assert_eq!( - cx.window.presenter.rendered_views[&view.id()].name(), + cx.window.rendered_views[&view.id()].name(), Some("render count: 1") ); }); @@ -6888,10 +6692,10 @@ mod tests { cx.update_window(window_id, |cx| { assert_eq!( - cx.window.presenter.rendered_views[&root_view.id()].name(), + cx.window.rendered_views[&root_view.id()].name(), Some("render count: 3") ); - assert_eq!(cx.window.presenter.rendered_views.len(), 1); + assert_eq!(cx.window.rendered_views.len(), 1); }); } diff --git a/crates/gpui/src/app/test_app_context.rs b/crates/gpui/src/app/test_app_context.rs index 84fe2bafda..b8244f044b 100644 --- a/crates/gpui/src/app/test_app_context.rs +++ b/crates/gpui/src/app/test_app_context.rs @@ -92,13 +92,12 @@ impl TestAppContext { return true; } - if cx.window.presenter.dispatch_event( + if cx.dispatch_event( Event::KeyDown(KeyDownEvent { keystroke: keystroke.clone(), is_held, }), false, - cx, ) { return true; } @@ -286,12 +285,15 @@ impl TestAppContext { pub fn simulate_window_activation(&self, to_activate: Option) { self.cx.borrow_mut().update(|cx| { - for window_id in cx + let other_window_ids = cx .windows .keys() .filter(|window_id| Some(**window_id) != to_activate) - { - cx.window_changed_active_status(*window_id, false) + .copied() + .collect::>(); + + for window_id in other_window_ids { + cx.window_changed_active_status(window_id, false) } if let Some(to_activate) = to_activate { diff --git a/crates/gpui/src/presenter.rs b/crates/gpui/src/app/window.rs similarity index 72% rename from crates/gpui/src/presenter.rs rename to crates/gpui/src/app/window.rs index e11ae63c0b..ccb5a49ccf 100644 --- a/crates/gpui/src/presenter.rs +++ b/crates/gpui/src/app/window.rs @@ -4,7 +4,11 @@ use crate::{ font_cache::FontCache, geometry::rect::RectF, json::{self, ToJson}, - platform::{Appearance, CursorStyle, Event, FontSystem, MouseButton, MouseMovedEvent}, + keymap_matcher::{Keystroke, MatchResult}, + platform::{ + self, Appearance, CursorStyle, Event, FontSystem, MouseButton, MouseMovedEvent, + PromptLevel, WindowBounds, + }, scene::{ CursorRegion, MouseClick, MouseDown, MouseDownOut, MouseDrag, MouseEvent, MouseHover, MouseMove, MouseMoveOut, MouseScrollWheel, MouseUp, MouseUpOut, Scene, @@ -18,6 +22,7 @@ use crate::{ use anyhow::bail; use collections::{HashMap, HashSet}; use pathfinder_geometry::vector::{vec2f, Vector2F}; +use postage::oneshot; use serde_json::json; use smallvec::SmallVec; use sqlez::{ @@ -29,9 +34,16 @@ use std::{ ops::{Deref, DerefMut, Range}, sync::Arc, }; +use uuid::Uuid; -pub struct Presenter { +pub struct Window { window_id: usize, + pub(crate) root_view: AnyViewHandle, + pub(crate) focused_view_id: Option, + pub(crate) is_active: bool, + pub(crate) is_fullscreen: bool, + pub(crate) invalidation: Option, + pub(crate) platform_window: Box, pub(crate) rendered_views: HashMap, cursor_regions: Vec, mouse_regions: Vec<(MouseRegion, usize)>, @@ -47,18 +59,27 @@ pub struct Presenter { appearance: Appearance, } -impl Presenter { +impl Window { pub fn new( window_id: usize, - titlebar_height: f32, - appearance: Appearance, + root_view: AnyViewHandle, + platform_window: Box, font_cache: Arc, text_layout_cache: TextLayoutCache, asset_cache: Arc, cx: &mut AppContext, ) -> Self { + let focused_view_id = Some(root_view.id()); + let titlebar_height = platform_window.titlebar_height(); + let appearance = platform_window.appearance(); Self { window_id, + root_view, + focused_view_id, + is_active: false, + invalidation: None, + is_fullscreen: false, + platform_window, rendered_views: cx.render_views(window_id, titlebar_height, appearance), cursor_regions: Default::default(), mouse_regions: Default::default(), @@ -74,180 +95,101 @@ impl Presenter { appearance, } } +} - pub fn invalidate( - &mut self, - invalidation: &mut WindowInvalidation, - appearance: Appearance, - cx: &mut AppContext, - ) { - cx.start_frame(); - self.appearance = appearance; - for view_id in &invalidation.removed { - invalidation.updated.remove(view_id); - self.rendered_views.remove(view_id); +pub struct WindowContext<'a: 'b, 'b> { + app_context: &'a mut AppContext, + pub(crate) window: &'b mut Window, // TODO: make this private? + window_id: usize, +} + +impl Deref for WindowContext<'_, '_> { + type Target = AppContext; + + fn deref(&self) -> &Self::Target { + self.app_context + } +} + +impl DerefMut for WindowContext<'_, '_> { + fn deref_mut(&mut self) -> &mut Self::Target { + &mut self.app_context + } +} + +impl<'a: 'b, 'b> WindowContext<'a, 'b> { + pub fn new(app_context: &'a mut AppContext, window: &'b mut Window, window_id: usize) -> Self { + Self { + app_context, + window, + window_id, } - for view_id in &invalidation.updated { - self.rendered_views.insert( - *view_id, - cx.render_view(RenderParams { - window_id: self.window_id, - view_id: *view_id, - titlebar_height: self.titlebar_height, - hovered_region_ids: self.hovered_region_ids.clone(), - clicked_region_ids: self - .clicked_button - .map(|button| (self.clicked_region_ids.clone(), button)), - refreshing: false, - appearance, + } + + pub fn dispatch_keystroke(&mut self, keystroke: &Keystroke) -> bool { + let window_id = self.window_id; + if let Some(focused_view_id) = self.focused_view_id(window_id) { + let dispatch_path = self + .ancestors(window_id, focused_view_id) + .filter_map(|view_id| { + self.views + .get(&(window_id, view_id)) + .map(|view| (view_id, view.keymap_context(self))) }) - .unwrap(), - ); - } - } + .collect(); - pub fn refresh( - &mut self, - invalidation: &mut WindowInvalidation, - appearance: Appearance, - cx: &mut AppContext, - ) { - self.invalidate(invalidation, appearance, cx); - for (view_id, view) in &mut self.rendered_views { - if !invalidation.updated.contains(view_id) { - *view = cx - .render_view(RenderParams { - window_id: self.window_id, - view_id: *view_id, - titlebar_height: self.titlebar_height, - hovered_region_ids: self.hovered_region_ids.clone(), - clicked_region_ids: self - .clicked_button - .map(|button| (self.clicked_region_ids.clone(), button)), - refreshing: true, - appearance, - }) - .unwrap(); - } - } - } + let match_result = self + .keystroke_matcher + .push_keystroke(keystroke.clone(), dispatch_path); + let mut handled_by = None; - pub fn build_scene( - &mut self, - window_size: Vector2F, - scale_factor: f32, - refreshing: bool, - cx: &mut AppContext, - ) -> Scene { - let mut scene_builder = SceneBuilder::new(scale_factor); - - if let Some(root_view_id) = cx.root_view_id(self.window_id) { - self.layout(window_size, refreshing, cx); - let mut paint_cx = self.build_paint_context(&mut scene_builder, window_size, cx); - paint_cx.paint( - root_view_id, - Vector2F::zero(), - RectF::new(Vector2F::zero(), window_size), - ); - self.text_layout_cache.finish_frame(); - let scene = scene_builder.build(); - self.cursor_regions = scene.cursor_regions(); - self.mouse_regions = scene.mouse_regions(); - - // window.is_topmost for the mouse moved event's postion? - if cx.window_is_active(self.window_id) { - if let Some(event) = self.last_mouse_moved_event.clone() { - self.dispatch_event(event, true, cx); + let keystroke_handled = match &match_result { + MatchResult::None => false, + MatchResult::Pending => true, + MatchResult::Matches(matches) => { + for (view_id, action) in matches { + if self.handle_dispatch_action_from_effect( + window_id, + Some(*view_id), + action.as_ref(), + ) { + self.keystroke_matcher.clear_pending(); + handled_by = Some(action.boxed_clone()); + break; + } + } + handled_by.is_some() } - } - - scene - } else { - log::error!("could not find root_view_id for window {}", self.window_id); - scene_builder.build() - } - } - - fn layout(&mut self, window_size: Vector2F, refreshing: bool, cx: &mut AppContext) { - if let Some(root_view_id) = cx.root_view_id(self.window_id) { - self.build_layout_context(window_size, refreshing, cx) - .layout(root_view_id, SizeConstraint::strict(window_size)); - } - } - - pub fn build_layout_context<'a>( - &'a mut self, - window_size: Vector2F, - refreshing: bool, - cx: &'a mut AppContext, - ) -> LayoutContext<'a> { - LayoutContext { - window_id: self.window_id, - rendered_views: &mut self.rendered_views, - font_cache: &self.font_cache, - font_system: cx.platform().fonts(), - text_layout_cache: &self.text_layout_cache, - asset_cache: &self.asset_cache, - view_stack: Vec::new(), - refreshing, - hovered_region_ids: self.hovered_region_ids.clone(), - clicked_region_ids: self - .clicked_button - .map(|button| (self.clicked_region_ids.clone(), button)), - titlebar_height: self.titlebar_height, - appearance: self.appearance, - window_size, - app: cx, - } - } - - pub fn build_paint_context<'a>( - &'a mut self, - scene: &'a mut SceneBuilder, - window_size: Vector2F, - cx: &'a mut AppContext, - ) -> PaintContext { - PaintContext { - scene, - window_size, - 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 rect_for_text_range(&self, range_utf16: Range, cx: &AppContext) -> Option { - cx.focused_view_id(self.window_id).and_then(|view_id| { - let cx = MeasurementContext { - app: cx, - rendered_views: &self.rendered_views, - window_id: self.window_id, }; - cx.rect_for_text_range(view_id, range_utf16) - }) + + self.keystroke( + window_id, + keystroke.clone(), + handled_by, + match_result.clone(), + ); + keystroke_handled + } else { + self.keystroke(window_id, keystroke.clone(), None, MatchResult::None); + false + } } - pub fn dispatch_event( - &mut self, - event: Event, - event_reused: bool, - cx: &mut AppContext, - ) -> bool { + pub fn dispatch_event(&mut self, event: Event, event_reused: bool) -> bool { let mut mouse_events = SmallVec::<[_; 2]>::new(); let mut notified_views: HashSet = Default::default(); + let window_id = self.window_id; // 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::KeyDown(e) => return self.dispatch_key_down(window_id, e), - Event::KeyUp(e) => return cx.dispatch_key_up(self.window_id, e), + Event::KeyUp(e) => return self.dispatch_key_up(window_id, e), - Event::ModifiersChanged(e) => return cx.dispatch_modifiers_changed(self.window_id, e), + Event::ModifiersChanged(e) => return self.dispatch_modifiers_changed(window_id, e), Event::MouseDown(e) => { // Click events are weird because they can be fired after a drag event. @@ -256,8 +198,9 @@ impl Presenter { // 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 + if self.window.clicked_button.is_none() { + self.window.clicked_region_ids = self + .window .mouse_regions .iter() .filter_map(|(region, _)| { @@ -269,7 +212,7 @@ impl Presenter { }) .collect(); - self.clicked_button = Some(e.button); + self.window.clicked_button = Some(e.button); } mouse_events.push(MouseEvent::Down(MouseDown { @@ -308,26 +251,29 @@ impl Presenter { }, ) => { let mut style_to_assign = CursorStyle::Arrow; - for region in self.cursor_regions.iter().rev() { + for region in self.window.cursor_regions.iter().rev() { if region.bounds.contains_point(*position) { style_to_assign = region.style; break; } } - // TODO!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! - // if cx.is_topmost_window_for_position(self.window_id, *position) { - // cx.platform().set_cursor_style(style_to_assign); - // } + if self + .window + .platform_window + .is_topmost_for_position(*position) + { + self.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, + prev_mouse_position: self.window.mouse_position, platform_event: e.clone(), })); - } else if let Some(clicked_button) = self.clicked_button { + } else if let Some(clicked_button) = self.window.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 { @@ -359,7 +305,7 @@ impl Presenter { region: Default::default(), })); - self.last_mouse_moved_event = Some(event.clone()); + self.window.last_mouse_moved_event = Some(event.clone()); } Event::MouseExited(event) => { @@ -373,7 +319,6 @@ impl Presenter { modifiers: event.modifiers, }), event_reused, - cx, ); } @@ -384,7 +329,7 @@ impl Presenter { } if let Some(position) = event.position() { - self.mouse_position = position; + self.window.mouse_position = position; } // 2. Dispatch mouse events on regions @@ -398,8 +343,8 @@ impl Presenter { match &mouse_event { MouseEvent::Hover(_) => { let mut highest_z_index = None; - let mouse_position = self.mouse_position.clone(); - for (region, z_index) in self.mouse_regions.iter().rev() { + let mouse_position = self.window.mouse_position.clone(); + for (region, z_index) in self.window.mouse_regions.iter().rev() { // Allow mouse regions to appear transparent to hovers if !region.hoverable { continue; @@ -417,7 +362,7 @@ impl Presenter { // highest_z_index is set. if contains_mouse && z_index == highest_z_index.unwrap() { //Ensure that hover entrance events aren't sent twice - if self.hovered_region_ids.insert(region.id()) { + if self.window.hovered_region_ids.insert(region.id()) { valid_regions.push(region.clone()); if region.notify_on_hover { notified_views.insert(region.id().view_id()); @@ -425,7 +370,7 @@ impl Presenter { } } else { // Ensure that hover exit events aren't sent twice - if self.hovered_region_ids.remove(®ion.id()) { + if self.window.hovered_region_ids.remove(®ion.id()) { valid_regions.push(region.clone()); if region.notify_on_hover { notified_views.insert(region.id().view_id()); @@ -436,8 +381,8 @@ impl Presenter { } MouseEvent::Down(_) | MouseEvent::Up(_) => { - for (region, _) in self.mouse_regions.iter().rev() { - if region.bounds.contains_point(self.mouse_position) { + for (region, _) in self.window.mouse_regions.iter().rev() { + if region.bounds.contains_point(self.window.mouse_position) { valid_regions.push(region.clone()); if region.notify_on_click { notified_views.insert(region.id().view_id()); @@ -449,19 +394,25 @@ impl Presenter { MouseEvent::Click(e) => { // Only raise click events if the released button is the same as the one stored if self + .window .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; + let clicked_region_ids = std::mem::replace( + &mut self.window.clicked_region_ids, + Default::default(), + ); + self.window.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() { + for (mouse_region, _) in self.window.mouse_regions.iter().rev() { if clicked_region_ids.contains(&mouse_region.id()) { - if mouse_region.bounds.contains_point(self.mouse_position) { + if mouse_region + .bounds + .contains_point(self.window.mouse_position) + { valid_regions.push(mouse_region.clone()); } } @@ -470,26 +421,32 @@ impl Presenter { } MouseEvent::Drag(_) => { - for (mouse_region, _) in self.mouse_regions.iter().rev() { - if self.clicked_region_ids.contains(&mouse_region.id()) { + for (mouse_region, _) in self.window.mouse_regions.iter().rev() { + if self.window.clicked_region_ids.contains(&mouse_region.id()) { valid_regions.push(mouse_region.clone()); } } } MouseEvent::MoveOut(_) | MouseEvent::UpOut(_) | MouseEvent::DownOut(_) => { - for (mouse_region, _) in self.mouse_regions.iter().rev() { + for (mouse_region, _) in self.window.mouse_regions.iter().rev() { // NOT contains - if !mouse_region.bounds.contains_point(self.mouse_position) { + if !mouse_region + .bounds + .contains_point(self.window.mouse_position) + { valid_regions.push(mouse_region.clone()); } } } _ => { - for (mouse_region, _) in self.mouse_regions.iter().rev() { + for (mouse_region, _) in self.window.mouse_regions.iter().rev() { // Contains - if mouse_region.bounds.contains_point(self.mouse_position) { + if mouse_region + .bounds + .contains_point(self.window.mouse_position) + { valid_regions.push(mouse_region.clone()); } } @@ -497,9 +454,9 @@ impl Presenter { } //3. Fire region events - let hovered_region_ids = self.hovered_region_ids.clone(); + let hovered_region_ids = self.window.hovered_region_ids.clone(); for valid_region in valid_regions.into_iter() { - let mut event_cx = self.build_event_context(&mut notified_views, cx); + let mut event_cx = self.build_event_context(&mut notified_views); mouse_event.set_region(valid_region.bounds); if let MouseEvent::Hover(e) = &mut mouse_event { @@ -548,43 +505,253 @@ impl Presenter { } for view_id in notified_views { - cx.notify_view(self.window_id, view_id); + self.notify_view(window_id, view_id); } any_event_handled } - pub fn build_event_context<'a>( - &'a mut self, - notified_views: &'a mut HashSet, - cx: &'a mut AppContext, - ) -> EventContext<'a> { + pub fn build_event_context<'c>( + &'c mut self, + notified_views: &'c mut HashSet, + ) -> EventContext<'c> { EventContext { - font_cache: &self.font_cache, - text_layout_cache: &self.text_layout_cache, + font_cache: &self.window.font_cache, + text_layout_cache: &self.window.text_layout_cache, view_stack: Default::default(), notified_views, notify_count: 0, handled: false, window_id: self.window_id, + app: self, + } + } + + pub fn invalidate(&mut self, invalidation: &mut WindowInvalidation, appearance: Appearance) { + self.start_frame(); + self.window.appearance = appearance; + for view_id in &invalidation.removed { + invalidation.updated.remove(view_id); + self.window.rendered_views.remove(view_id); + } + for view_id in &invalidation.updated { + let window_id = self.window_id; + let titlebar_height = self.window.titlebar_height; + let hovered_region_ids = self.window.hovered_region_ids.clone(); + let clicked_region_ids = self + .window + .clicked_button + .map(|button| (self.window.clicked_region_ids.clone(), button)); + + let element = self + .render_view(RenderParams { + window_id, + view_id: *view_id, + titlebar_height, + hovered_region_ids, + clicked_region_ids, + refreshing: false, + appearance, + }) + .unwrap(); + self.window.rendered_views.insert(*view_id, element); + } + } + + pub fn refresh(&mut self, invalidation: &mut WindowInvalidation, appearance: Appearance) { + self.invalidate(invalidation, appearance); + + let view_ids = self + .window + .rendered_views + .keys() + .copied() + .collect::>(); + + for view_id in view_ids { + if !invalidation.updated.contains(&view_id) { + let window_id = self.window_id; + let titlebar_height = self.window.titlebar_height; + let hovered_region_ids = self.window.hovered_region_ids.clone(); + let clicked_region_ids = self + .window + .clicked_button + .map(|button| (self.window.clicked_region_ids.clone(), button)); + let element = self + .render_view(RenderParams { + window_id, + view_id, + titlebar_height, + hovered_region_ids, + clicked_region_ids, + refreshing: true, + appearance, + }) + .unwrap(); + self.window.rendered_views.insert(view_id, element); + } + } + } + + pub fn build_scene(&mut self, refreshing: bool) -> Scene { + let window_size = self.window.platform_window.content_size(); + let scale_factor = self.window.platform_window.scale_factor(); + + let mut scene_builder = SceneBuilder::new(scale_factor); + + if let Some(root_view_id) = self.root_view_id(self.window_id) { + self.layout(window_size, refreshing, self); + let mut paint_cx = self.build_paint_context(&mut scene_builder, window_size); + paint_cx.paint( + root_view_id, + Vector2F::zero(), + RectF::new(Vector2F::zero(), window_size), + ); + self.window.text_layout_cache.finish_frame(); + let scene = scene_builder.build(); + self.window.cursor_regions = scene.cursor_regions(); + self.window.mouse_regions = scene.mouse_regions(); + + // window.is_topmost for the mouse moved event's postion? + if self.window_is_active(self.window_id) { + if let Some(event) = self.window.last_mouse_moved_event.clone() { + self.dispatch_event(event, true); + } + } + + scene + } else { + log::error!("could not find root_view_id for window {}", self.window_id); + scene_builder.build() + } + } + + fn layout(&mut self, window_size: Vector2F, refreshing: bool, cx: &mut AppContext) { + if let Some(root_view_id) = cx.root_view_id(self.window_id) { + self.build_layout_context(window_size, refreshing, cx) + .layout(root_view_id, SizeConstraint::strict(window_size)); + } + } + + pub fn build_layout_context<'c>( + &'c mut self, + window_size: Vector2F, + refreshing: bool, + cx: &'c mut AppContext, + ) -> LayoutContext<'c> { + LayoutContext { + window_id: self.window_id, + rendered_views: &mut self.window.rendered_views, + font_cache: &self.font_cache, + font_system: cx.platform().fonts(), + text_layout_cache: &self.window.text_layout_cache, + asset_cache: &self.window.asset_cache, + view_stack: Vec::new(), + refreshing, + hovered_region_ids: self.window.hovered_region_ids.clone(), + clicked_region_ids: self + .window + .clicked_button + .map(|button| (self.window.clicked_region_ids.clone(), button)), + titlebar_height: self.window.titlebar_height, + appearance: self.window.appearance, + window_size, app: cx, } } - pub fn debug_elements(&self, cx: &AppContext) -> Option { - let view = cx.root_view(self.window_id)?; + pub fn build_paint_context<'c>( + &'c mut self, + scene: &'c mut SceneBuilder, + window_size: Vector2F, + ) -> PaintContext { + PaintContext { + scene, + window_size, + font_cache: &self.font_cache, + text_layout_cache: &self.window.text_layout_cache, + rendered_views: &mut self.window.rendered_views, + view_stack: Vec::new(), + app: self, + } + } + + pub fn rect_for_text_range(&self, range_utf16: Range) -> Option { + self.focused_view_id(self.window_id).and_then(|view_id| { + let cx = MeasurementContext { + app: self, + rendered_views: &self.window.rendered_views, + window_id: self.window_id, + }; + cx.rect_for_text_range(view_id, range_utf16) + }) + } + + pub fn debug_elements(&self) -> Option { + let view = self.root_view(self.window_id)?; Some(json!({ - "root_view": view.debug_json(cx), - "root_element": self.rendered_views.get(&view.id()) + "root_view": view.debug_json(self), + "root_element": self.window.rendered_views.get(&view.id()) .map(|root_element| { root_element.debug(&DebugContext { - rendered_views: &self.rendered_views, - font_cache: &self.font_cache, - app: cx, + rendered_views: &self.window.rendered_views, + font_cache: &self.window.font_cache, + app: self, }) }) })) } + + pub fn set_window_title(&mut self, title: &str) { + self.window.platform_window.set_title(title); + } + + pub fn set_window_edited(&mut self, edited: bool) { + self.window.platform_window.set_edited(edited); + } + + pub fn is_topmost_window_for_position(&self, position: Vector2F) -> bool { + self.window + .platform_window + .is_topmost_for_position(position) + } + + pub fn activate_window(&self) { + self.window.platform_window.activate(); + } + + pub fn window_bounds(&self) -> WindowBounds { + self.window.platform_window.bounds() + } + + pub fn window_display_uuid(&self) -> Option { + self.window.platform_window.screen().display_uuid() + } + + fn show_character_palette(&self) { + self.window.platform_window.show_character_palette(); + } + + pub fn minimize_window(&self) { + self.window.platform_window.minimize(); + } + + pub fn zoom_window(&self) { + self.window.platform_window.zoom(); + } + + pub fn toggle_window_full_screen(&self) { + self.window.platform_window.toggle_full_screen(); + } + + pub fn prompt( + &self, + level: PromptLevel, + msg: &str, + answers: &[&str], + ) -> oneshot::Receiver { + self.window.platform_window.prompt(level, msg, answers) + } } pub struct LayoutContext<'a> { diff --git a/crates/gpui/src/app/window_input_handler.rs b/crates/gpui/src/app/window_input_handler.rs index 997ec1c7a5..db92dd0b47 100644 --- a/crates/gpui/src/app/window_input_handler.rs +++ b/crates/gpui/src/app/window_input_handler.rs @@ -90,8 +90,9 @@ impl InputHandler for WindowInputHandler { } fn rect_for_range(&self, range_utf16: Range) -> Option { - let app = self.app.borrow(); - let window = app.windows.get(&self.window_id)?; - window.presenter.rect_for_text_range(range_utf16, &app) + self.app + .borrow_mut() + .update_window(self.window_id, |cx| cx.rect_for_text_range(range_utf16)) + .flatten() } } diff --git a/crates/gpui/src/elements.rs b/crates/gpui/src/elements.rs index 3e3370a507..6322f99772 100644 --- a/crates/gpui/src/elements.rs +++ b/crates/gpui/src/elements.rs @@ -26,16 +26,14 @@ pub use self::{ stack::*, svg::*, text::*, tooltip::*, uniform_list::*, }; use self::{clipped::Clipped, expanded::Expanded}; -pub use crate::presenter::ChildView; use crate::{ + app::window::MeasurementContext, geometry::{ rect::RectF, vector::{vec2f, Vector2F}, }, - json, - presenter::MeasurementContext, - Action, DebugContext, EventContext, LayoutContext, PaintContext, RenderContext, SizeConstraint, - View, + json, Action, DebugContext, EventContext, LayoutContext, PaintContext, RenderContext, + SizeConstraint, View, }; use core::panic; use json::ToJson; diff --git a/crates/gpui/src/elements/align.rs b/crates/gpui/src/elements/align.rs index ec1a210f75..9887fc71d7 100644 --- a/crates/gpui/src/elements/align.rs +++ b/crates/gpui/src/elements/align.rs @@ -1,7 +1,7 @@ use crate::{ geometry::{rect::RectF, vector::Vector2F}, json, - presenter::MeasurementContext, + window::MeasurementContext, DebugContext, Element, ElementBox, LayoutContext, PaintContext, SizeConstraint, }; use json::ToJson; diff --git a/crates/gpui/src/elements/canvas.rs b/crates/gpui/src/elements/canvas.rs index 31c56bb987..8dcdcce5ea 100644 --- a/crates/gpui/src/elements/canvas.rs +++ b/crates/gpui/src/elements/canvas.rs @@ -1,7 +1,7 @@ use super::Element; use crate::{ json::{self, json}, - presenter::MeasurementContext, + window::MeasurementContext, DebugContext, PaintContext, }; use json::ToJson; diff --git a/crates/gpui/src/elements/constrained_box.rs b/crates/gpui/src/elements/constrained_box.rs index e4d51f5730..ca48fdcbed 100644 --- a/crates/gpui/src/elements/constrained_box.rs +++ b/crates/gpui/src/elements/constrained_box.rs @@ -6,7 +6,7 @@ use serde_json::json; use crate::{ geometry::{rect::RectF, vector::Vector2F}, json, - presenter::MeasurementContext, + window::MeasurementContext, DebugContext, Element, ElementBox, LayoutContext, PaintContext, SizeConstraint, }; diff --git a/crates/gpui/src/elements/container.rs b/crates/gpui/src/elements/container.rs index 8e17fdd60f..11ef42c413 100644 --- a/crates/gpui/src/elements/container.rs +++ b/crates/gpui/src/elements/container.rs @@ -9,8 +9,8 @@ use crate::{ }, json::ToJson, platform::CursorStyle, - presenter::MeasurementContext, scene::{self, Border, CursorRegion, Quad}, + window::MeasurementContext, Element, ElementBox, LayoutContext, PaintContext, SizeConstraint, }; use serde::Deserialize; diff --git a/crates/gpui/src/elements/empty.rs b/crates/gpui/src/elements/empty.rs index b0a0481c05..a1c805f456 100644 --- a/crates/gpui/src/elements/empty.rs +++ b/crates/gpui/src/elements/empty.rs @@ -6,7 +6,7 @@ use crate::{ vector::{vec2f, Vector2F}, }, json::{json, ToJson}, - presenter::MeasurementContext, + window::MeasurementContext, DebugContext, }; use crate::{Element, LayoutContext, PaintContext, SizeConstraint}; diff --git a/crates/gpui/src/elements/expanded.rs b/crates/gpui/src/elements/expanded.rs index 89e9c7c7d8..e7d1cea3af 100644 --- a/crates/gpui/src/elements/expanded.rs +++ b/crates/gpui/src/elements/expanded.rs @@ -3,7 +3,7 @@ use std::ops::Range; use crate::{ geometry::{rect::RectF, vector::Vector2F}, json, - presenter::MeasurementContext, + window::MeasurementContext, DebugContext, Element, ElementBox, LayoutContext, PaintContext, SizeConstraint, }; use serde_json::json; diff --git a/crates/gpui/src/elements/flex.rs b/crates/gpui/src/elements/flex.rs index 5df283bfee..ba49557a8b 100644 --- a/crates/gpui/src/elements/flex.rs +++ b/crates/gpui/src/elements/flex.rs @@ -2,7 +2,7 @@ use std::{any::Any, cell::Cell, f32::INFINITY, ops::Range, rc::Rc}; use crate::{ json::{self, ToJson, Value}, - presenter::MeasurementContext, + window::MeasurementContext, Axis, DebugContext, Element, ElementBox, ElementStateHandle, LayoutContext, PaintContext, RenderContext, SizeConstraint, Vector2FExt, View, }; diff --git a/crates/gpui/src/elements/hook.rs b/crates/gpui/src/elements/hook.rs index b77fef4fae..37b6bb03c7 100644 --- a/crates/gpui/src/elements/hook.rs +++ b/crates/gpui/src/elements/hook.rs @@ -3,7 +3,7 @@ use std::ops::Range; use crate::{ geometry::{rect::RectF, vector::Vector2F}, json::json, - presenter::MeasurementContext, + window::MeasurementContext, DebugContext, Element, ElementBox, LayoutContext, PaintContext, SizeConstraint, }; diff --git a/crates/gpui/src/elements/image.rs b/crates/gpui/src/elements/image.rs index cc49308e15..a94f45815c 100644 --- a/crates/gpui/src/elements/image.rs +++ b/crates/gpui/src/elements/image.rs @@ -5,8 +5,9 @@ use crate::{ vector::{vec2f, Vector2F}, }, json::{json, ToJson}, - presenter::MeasurementContext, - scene, Border, DebugContext, Element, ImageData, LayoutContext, PaintContext, SizeConstraint, + scene, + window::MeasurementContext, + Border, DebugContext, Element, ImageData, LayoutContext, PaintContext, SizeConstraint, }; use serde::Deserialize; use std::{ops::Range, sync::Arc}; diff --git a/crates/gpui/src/elements/label.rs b/crates/gpui/src/elements/label.rs index 41eea05957..6b998a9c18 100644 --- a/crates/gpui/src/elements/label.rs +++ b/crates/gpui/src/elements/label.rs @@ -7,8 +7,8 @@ use crate::{ vector::{vec2f, Vector2F}, }, json::{ToJson, Value}, - presenter::MeasurementContext, text_layout::{Line, RunStyle}, + window::MeasurementContext, DebugContext, Element, LayoutContext, PaintContext, SizeConstraint, }; use serde::Deserialize; diff --git a/crates/gpui/src/elements/list.rs b/crates/gpui/src/elements/list.rs index df06f05009..9326c447f0 100644 --- a/crates/gpui/src/elements/list.rs +++ b/crates/gpui/src/elements/list.rs @@ -4,7 +4,7 @@ use crate::{ vector::{vec2f, Vector2F}, }, json::json, - presenter::MeasurementContext, + window::MeasurementContext, DebugContext, Element, ElementBox, ElementRc, EventContext, LayoutContext, MouseRegion, PaintContext, RenderContext, SizeConstraint, View, ViewContext, }; @@ -631,7 +631,6 @@ mod tests { #[crate::test(self)] fn test_layout(cx: &mut crate::AppContext) { - let mut presenter = cx.build_presenter(0, 0., Default::default()); let (_, view) = cx.add_window(Default::default(), |_| TestView); let constraint = SizeConstraint::new(vec2f(0., 0.), vec2f(100., 40.)); @@ -730,8 +729,7 @@ mod tests { .map(|i| i.parse().expect("invalid `OPERATIONS` variable")) .unwrap_or(10); - let (_, view) = cx.add_window(Default::default(), |_| TestView); - let mut presenter = cx.build_presenter(0, 0., Default::default()); + let (window_id, view) = cx.add_window(Default::default(), |_| TestView); let mut next_id = 0; let elements = Rc::new(RefCell::new( (0..rng.gen_range(0..=20)) diff --git a/crates/gpui/src/elements/overlay.rs b/crates/gpui/src/elements/overlay.rs index 3dd816ca2a..2c340c5c7c 100644 --- a/crates/gpui/src/elements/overlay.rs +++ b/crates/gpui/src/elements/overlay.rs @@ -3,7 +3,7 @@ use std::ops::Range; use crate::{ geometry::{rect::RectF, vector::Vector2F}, json::ToJson, - presenter::MeasurementContext, + window::MeasurementContext, Axis, DebugContext, Element, ElementBox, LayoutContext, MouseRegion, PaintContext, SizeConstraint, }; diff --git a/crates/gpui/src/elements/stack.rs b/crates/gpui/src/elements/stack.rs index 3b5c19505d..60f84f53e8 100644 --- a/crates/gpui/src/elements/stack.rs +++ b/crates/gpui/src/elements/stack.rs @@ -3,7 +3,7 @@ use std::ops::Range; use crate::{ geometry::{rect::RectF, vector::Vector2F}, json::{self, json, ToJson}, - presenter::MeasurementContext, + window::MeasurementContext, DebugContext, Element, ElementBox, LayoutContext, PaintContext, SizeConstraint, }; diff --git a/crates/gpui/src/elements/svg.rs b/crates/gpui/src/elements/svg.rs index 5bd2759f7a..dc3e37723b 100644 --- a/crates/gpui/src/elements/svg.rs +++ b/crates/gpui/src/elements/svg.rs @@ -8,8 +8,9 @@ use crate::{ rect::RectF, vector::{vec2f, Vector2F}, }, - presenter::MeasurementContext, - scene, DebugContext, Element, LayoutContext, PaintContext, SizeConstraint, + scene, + window::MeasurementContext, + DebugContext, Element, LayoutContext, PaintContext, SizeConstraint, }; pub struct Svg { diff --git a/crates/gpui/src/elements/text.rs b/crates/gpui/src/elements/text.rs index f5ece8ba2c..03ed147cde 100644 --- a/crates/gpui/src/elements/text.rs +++ b/crates/gpui/src/elements/text.rs @@ -6,8 +6,8 @@ use crate::{ vector::{vec2f, Vector2F}, }, json::{ToJson, Value}, - presenter::MeasurementContext, text_layout::{Line, RunStyle, ShapedBoundary}, + window::MeasurementContext, DebugContext, Element, FontCache, LayoutContext, PaintContext, SizeConstraint, TextLayoutCache, }; use log::warn; @@ -271,12 +271,18 @@ pub fn layout_highlighted_chunks<'a>( #[cfg(test)] mod tests { use super::*; - use crate::{elements::Empty, fonts, AppContext, ElementBox, Entity, RenderContext, View}; + use crate::{ + elements::Empty, fonts, platform, AppContext, ElementBox, Entity, RenderContext, View, + }; #[crate::test(self)] fn test_soft_wrapping_with_carriage_returns(cx: &mut AppContext) { - let (window_id, _) = cx.add_window(Default::default(), |_| TestView); - let mut presenter = cx.build_presenter(window_id, Default::default(), Default::default()); + let (window_id, root_view) = cx.add_window(Default::default(), |_| TestView); + let mut presenter = cx.build_window( + window_id, + root_view.into_any(), + Box::new(platform::test::Window::new(Vector2F::new(800., 600.))), + ); fonts::with_font_cache(cx.font_cache().clone(), || { let mut text = Text::new("Hello\r\n", Default::default()).with_soft_wrap(true); let (_, state) = text.layout( diff --git a/crates/gpui/src/elements/tooltip.rs b/crates/gpui/src/elements/tooltip.rs index 562f12295c..971d4bc3e0 100644 --- a/crates/gpui/src/elements/tooltip.rs +++ b/crates/gpui/src/elements/tooltip.rs @@ -6,7 +6,7 @@ use crate::{ fonts::TextStyle, geometry::{rect::RectF, vector::Vector2F}, json::json, - presenter::MeasurementContext, + window::MeasurementContext, Action, Axis, ElementStateHandle, LayoutContext, PaintContext, RenderContext, SizeConstraint, Task, View, }; diff --git a/crates/gpui/src/elements/uniform_list.rs b/crates/gpui/src/elements/uniform_list.rs index 9d91613f63..ea712994da 100644 --- a/crates/gpui/src/elements/uniform_list.rs +++ b/crates/gpui/src/elements/uniform_list.rs @@ -6,8 +6,8 @@ use crate::{ }, json::{self, json}, platform::ScrollWheelEvent, - presenter::MeasurementContext, scene::MouseScrollWheel, + window::MeasurementContext, ElementBox, MouseRegion, RenderContext, View, }; use json::ToJson; diff --git a/crates/gpui/src/gpui.rs b/crates/gpui/src/gpui.rs index dc84dc9619..52ed1197bb 100644 --- a/crates/gpui/src/gpui.rs +++ b/crates/gpui/src/gpui.rs @@ -14,7 +14,6 @@ mod clipboard; pub use clipboard::ClipboardItem; pub mod fonts; pub mod geometry; -mod presenter; pub mod scene; pub use scene::{Border, CursorRegion, MouseRegion, MouseRegionId, Quad, Scene, SceneBuilder}; pub mod text_layout; @@ -28,7 +27,7 @@ pub mod json; pub mod keymap_matcher; pub mod platform; pub use gpui_macros::test; -pub use presenter::{ +pub use window::{ Axis, DebugContext, EventContext, LayoutContext, MeasurementContext, PaintContext, SizeConstraint, Vector2FExt, }; diff --git a/crates/gpui/src/platform/test.rs b/crates/gpui/src/platform/test.rs index e2bd428303..fa711c3eea 100644 --- a/crates/gpui/src/platform/test.rs +++ b/crates/gpui/src/platform/test.rs @@ -261,7 +261,7 @@ pub struct Window { } impl Window { - fn new(size: Vector2F) -> Self { + pub fn new(size: Vector2F) -> Self { Self { size, event_handlers: Default::default(),