From 5fe5685641d5e08911c6967ff0f60c6d5d3b94d5 Mon Sep 17 00:00:00 2001 From: Antonio Scandurra Date: Thu, 26 Aug 2021 15:00:00 +0200 Subject: [PATCH] Replace `notify_all` with an explicit `refresh_windows` effect Co-Authored-By: Nathan Sobo --- gpui/src/app.rs | 60 ++++++++++++++++++++++++++++----------- gpui/src/presenter.rs | 17 ++++++++++- zed/src/theme_selector.rs | 4 +-- 3 files changed, 61 insertions(+), 20 deletions(-) diff --git a/gpui/src/app.rs b/gpui/src/app.rs index 5d1fdc3a49..af5746043e 100644 --- a/gpui/src/app.rs +++ b/gpui/src/app.rs @@ -22,6 +22,7 @@ use std::{ fmt::{self, Debug}, hash::{Hash, Hasher}, marker::PhantomData, + mem, ops::{Deref, DerefMut}, path::{Path, PathBuf}, rc::{self, Rc}, @@ -973,16 +974,6 @@ impl MutableAppContext { .push_back(Effect::ViewNotification { window_id, view_id }); } - pub(crate) fn notify_all_views(&mut self) { - let notifications = self - .views - .keys() - .copied() - .map(|(window_id, view_id)| Effect::ViewNotification { window_id, view_id }) - .collect::>(); - self.pending_effects.extend(notifications); - } - pub fn dispatch_action( &mut self, window_id: usize, @@ -1314,6 +1305,7 @@ impl MutableAppContext { if !self.flushing_effects && self.pending_flushes == 0 { self.flushing_effects = true; + let mut full_refresh = false; loop { if let Some(effect) = self.pending_effects.pop_front() { match effect { @@ -1327,15 +1319,24 @@ impl MutableAppContext { Effect::Focus { window_id, view_id } => { self.focus(window_id, view_id); } + Effect::RefreshWindows => { + full_refresh = true; + } } self.remove_dropped_entities(); } else { self.remove_dropped_entities(); - self.update_windows(); + if full_refresh { + self.perform_window_refresh(); + } else { + self.update_windows(); + } if self.pending_effects.is_empty() { self.flushing_effects = false; break; + } else { + full_refresh = false; } } } @@ -1366,6 +1367,28 @@ impl MutableAppContext { } } + pub fn refresh_windows(&mut self) { + self.pending_effects.push_back(Effect::RefreshWindows); + } + + fn perform_window_refresh(&mut self) { + let mut presenters = mem::take(&mut self.presenters_and_platform_windows); + for (window_id, (presenter, window)) in &mut presenters { + let invalidation = self + .cx + .windows + .get_mut(&window_id) + .unwrap() + .invalidation + .take(); + let mut presenter = presenter.borrow_mut(); + presenter.refresh(invalidation, self.as_ref()); + let scene = presenter.build_scene(window.size(), window.scale_factor(), self); + window.present_scene(scene); + } + self.presenters_and_platform_windows = presenters; + } + fn emit_event(&mut self, entity_id: usize, payload: Box) { let callbacks = self.subscriptions.lock().remove(&entity_id); if let Some(callbacks) = callbacks { @@ -1615,10 +1638,11 @@ impl AppContext { window_id: usize, view_id: usize, titlebar_height: f32, + refresh: bool, ) -> Result { self.views .get(&(window_id, view_id)) - .map(|v| v.render(window_id, view_id, titlebar_height, self)) + .map(|v| v.render(window_id, view_id, titlebar_height, refresh, self)) .ok_or(anyhow!("view not found")) } @@ -1633,7 +1657,7 @@ impl AppContext { if *win_id == window_id { Some(( *view_id, - view.render(*win_id, *view_id, titlebar_height, self), + view.render(*win_id, *view_id, titlebar_height, false, self), )) } else { None @@ -1730,6 +1754,7 @@ pub enum Effect { window_id: usize, view_id: usize, }, + RefreshWindows, } impl Debug for Effect { @@ -1753,6 +1778,7 @@ impl Debug for Effect { .field("window_id", window_id) .field("view_id", view_id) .finish(), + Effect::RefreshWindows => f.debug_struct("Effect::FullViewRefresh").finish(), } } } @@ -1790,6 +1816,7 @@ pub trait AnyView { window_id: usize, view_id: usize, titlebar_height: f32, + refresh: bool, cx: &AppContext, ) -> ElementBox; fn on_focus(&mut self, cx: &mut MutableAppContext, window_id: usize, view_id: usize); @@ -1822,6 +1849,7 @@ where window_id: usize, view_id: usize, titlebar_height: f32, + refresh: bool, cx: &AppContext, ) -> ElementBox { View::render( @@ -1832,6 +1860,7 @@ where app: cx, view_type: PhantomData::, titlebar_height, + refresh, }, ) } @@ -2182,10 +2211,6 @@ impl<'a, T: View> ViewContext<'a, T> { self.app.notify_view(self.window_id, self.view_id); } - pub fn notify_all(&mut self) { - self.app.notify_all_views(); - } - pub fn propagate_action(&mut self) { self.halt_action_dispatch = false; } @@ -2204,6 +2229,7 @@ impl<'a, T: View> ViewContext<'a, T> { pub struct RenderContext<'a, T: View> { pub app: &'a AppContext, pub titlebar_height: f32, + pub refresh: bool, window_id: usize, view_id: usize, view_type: PhantomData, diff --git a/gpui/src/presenter.rs b/gpui/src/presenter.rs index 80739a8be6..6e3487d76d 100644 --- a/gpui/src/presenter.rs +++ b/gpui/src/presenter.rs @@ -66,12 +66,27 @@ impl Presenter { for view_id in invalidation.updated { self.rendered_views.insert( view_id, - cx.render_view(self.window_id, view_id, self.titlebar_height) + cx.render_view(self.window_id, view_id, self.titlebar_height, false) .unwrap(), ); } } + pub fn refresh(&mut self, invalidation: Option, cx: &AppContext) { + if let Some(invalidation) = invalidation { + for view_id in invalidation.removed { + self.rendered_views.remove(&view_id); + self.parents.remove(&view_id); + } + } + + for (view_id, view) in &mut self.rendered_views { + *view = cx + .render_view(self.window_id, *view_id, self.titlebar_height, true) + .unwrap(); + } + } + pub fn build_scene( &mut self, window_size: Vector2F, diff --git a/zed/src/theme_selector.rs b/zed/src/theme_selector.rs index 5dc3ae448a..867c5b7693 100644 --- a/zed/src/theme_selector.rs +++ b/zed/src/theme_selector.rs @@ -97,7 +97,7 @@ impl ThemeSelector { action.0.themes.clear(); match action.0.themes.get(¤t_theme_name) { Ok(theme) => { - cx.notify_all(); + cx.refresh_windows(); action.0.settings_tx.lock().borrow_mut().theme = theme; log::info!("reloaded theme {}", current_theme_name); } @@ -112,7 +112,7 @@ impl ThemeSelector { match self.registry.get(&mat.string) { Ok(theme) => { self.settings_tx.lock().borrow_mut().theme = theme; - cx.notify_all(); + cx.refresh_windows(); cx.emit(Event::Dismissed); } Err(error) => log::error!("error loading theme {}: {}", mat.string, error),