mirror of
https://github.com/zed-industries/zed.git
synced 2025-02-05 02:20:10 +00:00
Prevent pane from being erroneously zoomed when toggling the outline pane (#2527)
Fixes https://linear.app/zed-industries/issue/Z-1818/toggling-the-outline-pane-causes-the-pane-to-zoom Add release note lines here: - Fixed a bug that could cause panes to be erroneously zoomed when toggling modals. (preview-only)
This commit is contained in:
commit
dba7ec4a35
2 changed files with 82 additions and 78 deletions
|
@ -100,8 +100,6 @@ pub fn init(cx: &mut AppContext) {
|
||||||
cx.capture_action({
|
cx.capture_action({
|
||||||
let assistant = assistant.clone();
|
let assistant = assistant.clone();
|
||||||
move |_: &mut Editor, _: &editor::Cancel, cx: &mut ViewContext<Editor>| {
|
move |_: &mut Editor, _: &editor::Cancel, cx: &mut ViewContext<Editor>| {
|
||||||
dbg!("CANCEL LAST ASSIST");
|
|
||||||
|
|
||||||
if !assistant.cancel_last_assist(cx.view_id()) {
|
if !assistant.cancel_last_assist(cx.view_id()) {
|
||||||
cx.propagate_action();
|
cx.propagate_action();
|
||||||
}
|
}
|
||||||
|
|
|
@ -40,9 +40,9 @@ use gpui::{
|
||||||
CursorStyle, MouseButton, PathPromptOptions, Platform, PromptLevel, WindowBounds,
|
CursorStyle, MouseButton, PathPromptOptions, Platform, PromptLevel, WindowBounds,
|
||||||
WindowOptions,
|
WindowOptions,
|
||||||
},
|
},
|
||||||
AnyModelHandle, AnyViewHandle, AppContext, AsyncAppContext, Entity, ModelContext, ModelHandle,
|
AnyModelHandle, AnyViewHandle, AnyWeakViewHandle, AppContext, AsyncAppContext, Entity,
|
||||||
SizeConstraint, Subscription, Task, View, ViewContext, ViewHandle, WeakViewHandle,
|
ModelContext, ModelHandle, SizeConstraint, Subscription, Task, View, ViewContext, ViewHandle,
|
||||||
WindowContext,
|
WeakViewHandle, WindowContext,
|
||||||
};
|
};
|
||||||
use item::{FollowableItem, FollowableItemHandle, Item, ItemHandle, ProjectItem};
|
use item::{FollowableItem, FollowableItemHandle, Item, ItemHandle, ProjectItem};
|
||||||
use itertools::Itertools;
|
use itertools::Itertools;
|
||||||
|
@ -484,6 +484,7 @@ pub struct Workspace {
|
||||||
weak_self: WeakViewHandle<Self>,
|
weak_self: WeakViewHandle<Self>,
|
||||||
remote_entity_subscription: Option<client::Subscription>,
|
remote_entity_subscription: Option<client::Subscription>,
|
||||||
modal: Option<AnyViewHandle>,
|
modal: Option<AnyViewHandle>,
|
||||||
|
zoomed: Option<AnyWeakViewHandle>,
|
||||||
center: PaneGroup,
|
center: PaneGroup,
|
||||||
left_dock: ViewHandle<Dock>,
|
left_dock: ViewHandle<Dock>,
|
||||||
bottom_dock: ViewHandle<Dock>,
|
bottom_dock: ViewHandle<Dock>,
|
||||||
|
@ -687,6 +688,7 @@ impl Workspace {
|
||||||
let mut this = Workspace {
|
let mut this = Workspace {
|
||||||
weak_self: weak_handle.clone(),
|
weak_self: weak_handle.clone(),
|
||||||
modal: None,
|
modal: None,
|
||||||
|
zoomed: None,
|
||||||
center: PaneGroup::new(center_pane.clone()),
|
center: PaneGroup::new(center_pane.clone()),
|
||||||
panes: vec![center_pane.clone()],
|
panes: vec![center_pane.clone()],
|
||||||
panes_by_item: Default::default(),
|
panes_by_item: Default::default(),
|
||||||
|
@ -905,9 +907,17 @@ impl Workspace {
|
||||||
} else if T::should_zoom_in_on_event(event) {
|
} else if T::should_zoom_in_on_event(event) {
|
||||||
this.zoom_out(cx);
|
this.zoom_out(cx);
|
||||||
dock.update(cx, |dock, cx| dock.set_panel_zoomed(&panel, true, cx));
|
dock.update(cx, |dock, cx| dock.set_panel_zoomed(&panel, true, cx));
|
||||||
|
if panel.has_focus(cx) {
|
||||||
|
this.zoomed = Some(panel.downgrade().into_any());
|
||||||
|
}
|
||||||
} else if T::should_zoom_out_on_event(event) {
|
} else if T::should_zoom_out_on_event(event) {
|
||||||
this.zoom_out(cx);
|
this.zoom_out(cx);
|
||||||
} else if T::is_focus_event(event) {
|
} else if T::is_focus_event(event) {
|
||||||
|
if panel.is_zoomed(cx) {
|
||||||
|
this.zoomed = Some(panel.downgrade().into_any());
|
||||||
|
} else {
|
||||||
|
this.zoomed = None;
|
||||||
|
}
|
||||||
cx.notify();
|
cx.notify();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1359,44 +1369,6 @@ impl Workspace {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn zoomed(&self, cx: &WindowContext) -> Option<AnyViewHandle> {
|
|
||||||
self.zoomed_panel_for_dock(DockPosition::Left, cx)
|
|
||||||
.or_else(|| self.zoomed_panel_for_dock(DockPosition::Bottom, cx))
|
|
||||||
.or_else(|| self.zoomed_panel_for_dock(DockPosition::Right, cx))
|
|
||||||
.or_else(|| self.zoomed_pane(cx))
|
|
||||||
}
|
|
||||||
|
|
||||||
fn zoomed_panel_for_dock(
|
|
||||||
&self,
|
|
||||||
position: DockPosition,
|
|
||||||
cx: &WindowContext,
|
|
||||||
) -> Option<AnyViewHandle> {
|
|
||||||
let (dock, other_docks) = match position {
|
|
||||||
DockPosition::Left => (&self.left_dock, [&self.bottom_dock, &self.right_dock]),
|
|
||||||
DockPosition::Bottom => (&self.bottom_dock, [&self.left_dock, &self.right_dock]),
|
|
||||||
DockPosition::Right => (&self.right_dock, [&self.left_dock, &self.bottom_dock]),
|
|
||||||
};
|
|
||||||
|
|
||||||
let zoomed_panel = dock.read(&cx).zoomed_panel(cx)?;
|
|
||||||
if other_docks.iter().all(|dock| !dock.read(cx).has_focus(cx))
|
|
||||||
&& !self.active_pane.read(cx).has_focus()
|
|
||||||
{
|
|
||||||
Some(zoomed_panel.as_any().clone())
|
|
||||||
} else {
|
|
||||||
None
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn zoomed_pane(&self, cx: &WindowContext) -> Option<AnyViewHandle> {
|
|
||||||
let active_pane = self.active_pane.read(cx);
|
|
||||||
let docks = [&self.left_dock, &self.bottom_dock, &self.right_dock];
|
|
||||||
if active_pane.is_zoomed() && docks.iter().all(|dock| !dock.read(cx).has_focus(cx)) {
|
|
||||||
Some(self.active_pane.clone().into_any())
|
|
||||||
} else {
|
|
||||||
None
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn items<'a>(
|
pub fn items<'a>(
|
||||||
&'a self,
|
&'a self,
|
||||||
cx: &'a AppContext,
|
cx: &'a AppContext,
|
||||||
|
@ -1567,6 +1539,7 @@ impl Workspace {
|
||||||
self.left_dock.update(cx, |dock, cx| dock.zoom_out(cx));
|
self.left_dock.update(cx, |dock, cx| dock.zoom_out(cx));
|
||||||
self.bottom_dock.update(cx, |dock, cx| dock.zoom_out(cx));
|
self.bottom_dock.update(cx, |dock, cx| dock.zoom_out(cx));
|
||||||
self.right_dock.update(cx, |dock, cx| dock.zoom_out(cx));
|
self.right_dock.update(cx, |dock, cx| dock.zoom_out(cx));
|
||||||
|
self.zoomed = None;
|
||||||
|
|
||||||
cx.notify();
|
cx.notify();
|
||||||
}
|
}
|
||||||
|
@ -1749,6 +1722,12 @@ impl Workspace {
|
||||||
self.last_active_center_pane = Some(pane.downgrade());
|
self.last_active_center_pane = Some(pane.downgrade());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if pane.read(cx).is_zoomed() {
|
||||||
|
self.zoomed = Some(pane.downgrade().into_any());
|
||||||
|
} else {
|
||||||
|
self.zoomed = None;
|
||||||
|
}
|
||||||
|
|
||||||
self.update_followers(
|
self.update_followers(
|
||||||
proto::update_followers::Variant::UpdateActiveView(proto::UpdateActiveView {
|
proto::update_followers::Variant::UpdateActiveView(proto::UpdateActiveView {
|
||||||
id: self.active_item(cx).and_then(|item| {
|
id: self.active_item(cx).and_then(|item| {
|
||||||
|
@ -1804,6 +1783,9 @@ impl Workspace {
|
||||||
if pane == self.active_pane {
|
if pane == self.active_pane {
|
||||||
self.zoom_out(cx);
|
self.zoom_out(cx);
|
||||||
pane.update(cx, |pane, cx| pane.set_zoomed(true, cx));
|
pane.update(cx, |pane, cx| pane.set_zoomed(true, cx));
|
||||||
|
if pane.read(cx).has_focus() {
|
||||||
|
self.zoomed = Some(pane.downgrade().into_any());
|
||||||
|
}
|
||||||
cx.notify();
|
cx.notify();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2840,7 +2822,7 @@ impl Workspace {
|
||||||
DockPosition::Bottom => &self.bottom_dock,
|
DockPosition::Bottom => &self.bottom_dock,
|
||||||
};
|
};
|
||||||
let active_panel = dock.read(cx).active_panel()?;
|
let active_panel = dock.read(cx).active_panel()?;
|
||||||
let element = if Some(active_panel.as_any()) == self.zoomed(cx).as_ref() {
|
let element = if Some(active_panel.id()) == self.zoomed.as_ref().map(|zoomed| zoomed.id()) {
|
||||||
dock.read(cx).render_placeholder(cx)
|
dock.read(cx).render_placeholder(cx)
|
||||||
} else {
|
} else {
|
||||||
ChildView::new(dock, cx).into_any()
|
ChildView::new(dock, cx).into_any()
|
||||||
|
@ -3008,16 +2990,21 @@ impl View for Workspace {
|
||||||
.with_child(
|
.with_child(
|
||||||
Flex::column()
|
Flex::column()
|
||||||
.with_child(
|
.with_child(
|
||||||
FlexItem::new(self.center.render(
|
FlexItem::new(
|
||||||
|
self.center.render(
|
||||||
&project,
|
&project,
|
||||||
&theme,
|
&theme,
|
||||||
&self.follower_states_by_leader,
|
&self.follower_states_by_leader,
|
||||||
self.active_call(),
|
self.active_call(),
|
||||||
self.active_pane(),
|
self.active_pane(),
|
||||||
self.zoomed(cx).as_ref(),
|
self.zoomed
|
||||||
|
.as_ref()
|
||||||
|
.and_then(|zoomed| zoomed.upgrade(cx))
|
||||||
|
.as_ref(),
|
||||||
&self.app_state,
|
&self.app_state,
|
||||||
cx,
|
cx,
|
||||||
))
|
),
|
||||||
|
)
|
||||||
.flex(1., true),
|
.flex(1., true),
|
||||||
)
|
)
|
||||||
.with_children(
|
.with_children(
|
||||||
|
@ -3029,9 +3016,10 @@ impl View for Workspace {
|
||||||
})
|
})
|
||||||
.with_child(Overlay::new(
|
.with_child(Overlay::new(
|
||||||
Stack::new()
|
Stack::new()
|
||||||
.with_children(self.zoomed(cx).map(|zoomed| {
|
.with_children(self.zoomed.as_ref().and_then(|zoomed| {
|
||||||
enum ZoomBackground {}
|
enum ZoomBackground {}
|
||||||
|
let zoomed = zoomed.upgrade(cx)?;
|
||||||
|
Some(
|
||||||
ChildView::new(&zoomed, cx)
|
ChildView::new(&zoomed, cx)
|
||||||
.contained()
|
.contained()
|
||||||
.with_style(theme.workspace.zoomed_foreground)
|
.with_style(theme.workspace.zoomed_foreground)
|
||||||
|
@ -3040,9 +3028,13 @@ impl View for Workspace {
|
||||||
.with_style(theme.workspace.zoomed_background)
|
.with_style(theme.workspace.zoomed_background)
|
||||||
.mouse::<ZoomBackground>(0)
|
.mouse::<ZoomBackground>(0)
|
||||||
.capture_all()
|
.capture_all()
|
||||||
.on_down(MouseButton::Left, |_, this: &mut Self, cx| {
|
.on_down(
|
||||||
|
MouseButton::Left,
|
||||||
|
|_, this: &mut Self, cx| {
|
||||||
this.zoom_out(cx);
|
this.zoom_out(cx);
|
||||||
})
|
},
|
||||||
|
),
|
||||||
|
)
|
||||||
}))
|
}))
|
||||||
.with_children(self.modal.as_ref().map(|modal| {
|
.with_children(self.modal.as_ref().map(|modal| {
|
||||||
ChildView::new(modal, cx)
|
ChildView::new(modal, cx)
|
||||||
|
@ -3068,7 +3060,6 @@ impl View for Workspace {
|
||||||
if cx.is_self_focused() {
|
if cx.is_self_focused() {
|
||||||
cx.focus(&self.active_pane);
|
cx.focus(&self.active_pane);
|
||||||
}
|
}
|
||||||
cx.notify();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3393,7 +3384,7 @@ mod tests {
|
||||||
item::test::{TestItem, TestItemEvent, TestProjectItem},
|
item::test::{TestItem, TestItemEvent, TestProjectItem},
|
||||||
};
|
};
|
||||||
use fs::FakeFs;
|
use fs::FakeFs;
|
||||||
use gpui::{executor::Deterministic, TestAppContext};
|
use gpui::{executor::Deterministic, test::EmptyView, TestAppContext};
|
||||||
use project::{Project, ProjectEntryId};
|
use project::{Project, ProjectEntryId};
|
||||||
use serde_json::json;
|
use serde_json::json;
|
||||||
use settings::SettingsStore;
|
use settings::SettingsStore;
|
||||||
|
@ -3971,7 +3962,7 @@ mod tests {
|
||||||
let fs = FakeFs::new(cx.background());
|
let fs = FakeFs::new(cx.background());
|
||||||
|
|
||||||
let project = Project::test(fs, [], cx).await;
|
let project = Project::test(fs, [], cx).await;
|
||||||
let (_window_id, workspace) = cx.add_window(|cx| Workspace::test_new(project, cx));
|
let (window_id, workspace) = cx.add_window(|cx| Workspace::test_new(project, cx));
|
||||||
|
|
||||||
let (panel_1, panel_2) = workspace.update(cx, |workspace, cx| {
|
let (panel_1, panel_2) = workspace.update(cx, |workspace, cx| {
|
||||||
// Add panel_1 on the left, panel_2 on the right.
|
// Add panel_1 on the left, panel_2 on the right.
|
||||||
|
@ -4102,26 +4093,41 @@ mod tests {
|
||||||
|
|
||||||
// Emitting a ZoomIn event shows the panel as zoomed.
|
// Emitting a ZoomIn event shows the panel as zoomed.
|
||||||
panel_1.update(cx, |_, cx| cx.emit(TestPanelEvent::ZoomIn));
|
panel_1.update(cx, |_, cx| cx.emit(TestPanelEvent::ZoomIn));
|
||||||
workspace.read_with(cx, |workspace, cx| {
|
workspace.read_with(cx, |workspace, _| {
|
||||||
assert_eq!(workspace.zoomed(cx), Some(panel_1.clone().into_any()));
|
assert_eq!(workspace.zoomed, Some(panel_1.downgrade().into_any()));
|
||||||
|
});
|
||||||
|
|
||||||
|
// If focus is transferred to another view that's not a panel or another pane, we still show
|
||||||
|
// the panel as zoomed.
|
||||||
|
let focus_receiver = cx.add_view(window_id, |_| EmptyView);
|
||||||
|
focus_receiver.update(cx, |_, cx| cx.focus_self());
|
||||||
|
workspace.read_with(cx, |workspace, _| {
|
||||||
|
assert_eq!(workspace.zoomed, Some(panel_1.downgrade().into_any()));
|
||||||
});
|
});
|
||||||
|
|
||||||
// If focus is transferred elsewhere in the workspace, the panel is no longer zoomed.
|
// If focus is transferred elsewhere in the workspace, the panel is no longer zoomed.
|
||||||
workspace.update(cx, |_, cx| cx.focus_self());
|
workspace.update(cx, |_, cx| cx.focus_self());
|
||||||
workspace.read_with(cx, |workspace, cx| {
|
workspace.read_with(cx, |workspace, _| {
|
||||||
assert_eq!(workspace.zoomed(cx), None);
|
assert_eq!(workspace.zoomed, None);
|
||||||
|
});
|
||||||
|
|
||||||
|
// If focus is transferred again to another view that's not a panel or a pane, we won't
|
||||||
|
// show the panel as zoomed because it wasn't zoomed before.
|
||||||
|
focus_receiver.update(cx, |_, cx| cx.focus_self());
|
||||||
|
workspace.read_with(cx, |workspace, _| {
|
||||||
|
assert_eq!(workspace.zoomed, None);
|
||||||
});
|
});
|
||||||
|
|
||||||
// When focus is transferred back to the panel, it is zoomed again.
|
// When focus is transferred back to the panel, it is zoomed again.
|
||||||
panel_1.update(cx, |_, cx| cx.focus_self());
|
panel_1.update(cx, |_, cx| cx.focus_self());
|
||||||
workspace.read_with(cx, |workspace, cx| {
|
workspace.read_with(cx, |workspace, _| {
|
||||||
assert_eq!(workspace.zoomed(cx), Some(panel_1.clone().into_any()));
|
assert_eq!(workspace.zoomed, Some(panel_1.downgrade().into_any()));
|
||||||
});
|
});
|
||||||
|
|
||||||
// Emitting a ZoomOut event unzooms the panel.
|
// Emitting a ZoomOut event unzooms the panel.
|
||||||
panel_1.update(cx, |_, cx| cx.emit(TestPanelEvent::ZoomOut));
|
panel_1.update(cx, |_, cx| cx.emit(TestPanelEvent::ZoomOut));
|
||||||
workspace.read_with(cx, |workspace, cx| {
|
workspace.read_with(cx, |workspace, _| {
|
||||||
assert_eq!(workspace.zoomed(cx), None);
|
assert_eq!(workspace.zoomed, None);
|
||||||
});
|
});
|
||||||
|
|
||||||
// Emit closed event on panel 1, which is active
|
// Emit closed event on panel 1, which is active
|
||||||
|
|
Loading…
Reference in a new issue