mirror of
https://github.com/zed-industries/zed.git
synced 2024-12-29 08:32:27 +03:00
Merge pull request #633 from zed-industries/refresh-windows-panic
Fix edge cases when calling `refresh_windows`
This commit is contained in:
commit
e8efaed1b2
@ -1413,11 +1413,10 @@ impl MutableAppContext {
|
|||||||
invalidation: None,
|
invalidation: None,
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
this.open_platform_window(window_id, window_options);
|
|
||||||
root_view.update(this, |view, cx| {
|
root_view.update(this, |view, cx| {
|
||||||
view.on_focus(cx);
|
view.on_focus(cx);
|
||||||
cx.notify();
|
|
||||||
});
|
});
|
||||||
|
this.open_platform_window(window_id, window_options);
|
||||||
|
|
||||||
(window_id, root_view)
|
(window_id, root_view)
|
||||||
})
|
})
|
||||||
@ -1475,6 +1474,11 @@ impl MutableAppContext {
|
|||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let scene =
|
||||||
|
presenter
|
||||||
|
.borrow_mut()
|
||||||
|
.build_scene(window.size(), window.scale_factor(), false, self);
|
||||||
|
window.present_scene(scene);
|
||||||
self.presenters_and_platform_windows
|
self.presenters_and_platform_windows
|
||||||
.insert(window_id, (presenter.clone(), window));
|
.insert(window_id, (presenter.clone(), window));
|
||||||
}
|
}
|
||||||
@ -1666,13 +1670,13 @@ impl MutableAppContext {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (window_id, invalidation) in invalidations {
|
for (window_id, mut invalidation) in invalidations {
|
||||||
if let Some((presenter, mut window)) =
|
if let Some((presenter, mut window)) =
|
||||||
self.presenters_and_platform_windows.remove(&window_id)
|
self.presenters_and_platform_windows.remove(&window_id)
|
||||||
{
|
{
|
||||||
{
|
{
|
||||||
let mut presenter = presenter.borrow_mut();
|
let mut presenter = presenter.borrow_mut();
|
||||||
presenter.invalidate(invalidation, self);
|
presenter.invalidate(&mut invalidation, self);
|
||||||
let scene =
|
let scene =
|
||||||
presenter.build_scene(window.size(), window.scale_factor(), false, self);
|
presenter.build_scene(window.size(), window.scale_factor(), false, self);
|
||||||
window.present_scene(scene);
|
window.present_scene(scene);
|
||||||
@ -1695,7 +1699,7 @@ impl MutableAppContext {
|
|||||||
fn perform_window_refresh(&mut self) {
|
fn perform_window_refresh(&mut self) {
|
||||||
let mut presenters = mem::take(&mut self.presenters_and_platform_windows);
|
let mut presenters = mem::take(&mut self.presenters_and_platform_windows);
|
||||||
for (window_id, (presenter, window)) in &mut presenters {
|
for (window_id, (presenter, window)) in &mut presenters {
|
||||||
let invalidation = self
|
let mut invalidation = self
|
||||||
.cx
|
.cx
|
||||||
.windows
|
.windows
|
||||||
.get_mut(&window_id)
|
.get_mut(&window_id)
|
||||||
@ -1703,7 +1707,10 @@ impl MutableAppContext {
|
|||||||
.invalidation
|
.invalidation
|
||||||
.take();
|
.take();
|
||||||
let mut presenter = presenter.borrow_mut();
|
let mut presenter = presenter.borrow_mut();
|
||||||
presenter.refresh(invalidation, self);
|
presenter.refresh(
|
||||||
|
invalidation.as_mut().unwrap_or(&mut Default::default()),
|
||||||
|
self,
|
||||||
|
);
|
||||||
let scene = presenter.build_scene(window.size(), window.scale_factor(), true, self);
|
let scene = presenter.build_scene(window.size(), window.scale_factor(), true, self);
|
||||||
window.present_scene(scene);
|
window.present_scene(scene);
|
||||||
}
|
}
|
||||||
@ -5363,4 +5370,65 @@ mod tests {
|
|||||||
cx.update(|_| drop(view));
|
cx.update(|_| drop(view));
|
||||||
condition.await;
|
condition.await;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[crate::test(self)]
|
||||||
|
fn test_refresh_windows(cx: &mut MutableAppContext) {
|
||||||
|
struct View(usize);
|
||||||
|
|
||||||
|
impl super::Entity for View {
|
||||||
|
type Event = ();
|
||||||
|
}
|
||||||
|
|
||||||
|
impl super::View for View {
|
||||||
|
fn ui_name() -> &'static str {
|
||||||
|
"test view"
|
||||||
|
}
|
||||||
|
|
||||||
|
fn render(&mut self, _: &mut RenderContext<Self>) -> ElementBox {
|
||||||
|
Empty::new().named(format!("render count: {}", post_inc(&mut self.0)))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let (window_id, root_view) = cx.add_window(Default::default(), |_| View(0));
|
||||||
|
let presenter = cx.presenters_and_platform_windows[&window_id].0.clone();
|
||||||
|
|
||||||
|
assert_eq!(
|
||||||
|
presenter.borrow().rendered_views[&root_view.id()].name(),
|
||||||
|
Some("render count: 0")
|
||||||
|
);
|
||||||
|
|
||||||
|
let view = cx.add_view(window_id, |cx| {
|
||||||
|
cx.refresh_windows();
|
||||||
|
View(0)
|
||||||
|
});
|
||||||
|
|
||||||
|
assert_eq!(
|
||||||
|
presenter.borrow().rendered_views[&root_view.id()].name(),
|
||||||
|
Some("render count: 1")
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
presenter.borrow().rendered_views[&view.id()].name(),
|
||||||
|
Some("render count: 0")
|
||||||
|
);
|
||||||
|
|
||||||
|
cx.update(|cx| cx.refresh_windows());
|
||||||
|
assert_eq!(
|
||||||
|
presenter.borrow().rendered_views[&root_view.id()].name(),
|
||||||
|
Some("render count: 2")
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
presenter.borrow().rendered_views[&view.id()].name(),
|
||||||
|
Some("render count: 1")
|
||||||
|
);
|
||||||
|
|
||||||
|
cx.update(|cx| {
|
||||||
|
cx.refresh_windows();
|
||||||
|
drop(view);
|
||||||
|
});
|
||||||
|
assert_eq!(
|
||||||
|
presenter.borrow().rendered_views[&root_view.id()].name(),
|
||||||
|
Some("render count: 3")
|
||||||
|
);
|
||||||
|
assert_eq!(presenter.borrow().rendered_views.len(), 1);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -20,7 +20,7 @@ use std::{
|
|||||||
|
|
||||||
pub struct Presenter {
|
pub struct Presenter {
|
||||||
window_id: usize,
|
window_id: usize,
|
||||||
rendered_views: HashMap<usize, ElementBox>,
|
pub(crate) rendered_views: HashMap<usize, ElementBox>,
|
||||||
parents: HashMap<usize, usize>,
|
parents: HashMap<usize, usize>,
|
||||||
font_cache: Arc<FontCache>,
|
font_cache: Arc<FontCache>,
|
||||||
text_layout_cache: TextLayoutCache,
|
text_layout_cache: TextLayoutCache,
|
||||||
@ -63,39 +63,34 @@ impl Presenter {
|
|||||||
path
|
path
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn invalidate(&mut self, mut invalidation: WindowInvalidation, cx: &mut MutableAppContext) {
|
pub fn invalidate(
|
||||||
|
&mut self,
|
||||||
|
invalidation: &mut WindowInvalidation,
|
||||||
|
cx: &mut MutableAppContext,
|
||||||
|
) {
|
||||||
cx.start_frame();
|
cx.start_frame();
|
||||||
for view_id in invalidation.removed {
|
for view_id in &invalidation.removed {
|
||||||
invalidation.updated.remove(&view_id);
|
invalidation.updated.remove(&view_id);
|
||||||
self.rendered_views.remove(&view_id);
|
self.rendered_views.remove(&view_id);
|
||||||
self.parents.remove(&view_id);
|
self.parents.remove(&view_id);
|
||||||
}
|
}
|
||||||
for view_id in invalidation.updated {
|
for view_id in &invalidation.updated {
|
||||||
self.rendered_views.insert(
|
self.rendered_views.insert(
|
||||||
view_id,
|
*view_id,
|
||||||
cx.render_view(self.window_id, view_id, self.titlebar_height, false)
|
cx.render_view(self.window_id, *view_id, self.titlebar_height, false)
|
||||||
.unwrap(),
|
.unwrap(),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn refresh(
|
pub fn refresh(&mut self, invalidation: &mut WindowInvalidation, cx: &mut MutableAppContext) {
|
||||||
&mut self,
|
self.invalidate(invalidation, cx);
|
||||||
invalidation: Option<WindowInvalidation>,
|
|
||||||
cx: &mut MutableAppContext,
|
|
||||||
) {
|
|
||||||
cx.start_frame();
|
|
||||||
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 {
|
for (view_id, view) in &mut self.rendered_views {
|
||||||
*view = cx
|
if !invalidation.updated.contains(view_id) {
|
||||||
.render_view(self.window_id, *view_id, self.titlebar_height, true)
|
*view = cx
|
||||||
.unwrap();
|
.render_view(self.window_id, *view_id, self.titlebar_height, true)
|
||||||
|
.unwrap();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user