workspace: Fix panel resize handles leaking through zoomed panels (#9909)

Fixes #9501 

Release Notes:

- Fixed panel resize handle "leaking through" into a zoomed panel or
pane.
This commit is contained in:
Piotr Osiewicz 2024-03-28 12:18:51 +01:00 committed by GitHub
parent f5823f9942
commit cb7c53bc52
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 74 additions and 54 deletions

View file

@ -1,6 +1,6 @@
use crate::persistence::model::DockData; use crate::persistence::model::DockData;
use crate::DraggedDock;
use crate::{status_bar::StatusItemView, Workspace}; use crate::{status_bar::StatusItemView, Workspace};
use crate::{DraggedDock, Event};
use gpui::{ use gpui::{
deferred, div, px, Action, AnchorCorner, AnyView, AppContext, Axis, ClickEvent, Entity, deferred, div, px, Action, AnchorCorner, AnyView, AppContext, Axis, ClickEvent, Entity,
EntityId, EventEmitter, FocusHandle, FocusableView, IntoElement, KeyContext, MouseButton, EntityId, EventEmitter, FocusHandle, FocusableView, IntoElement, KeyContext, MouseButton,
@ -149,7 +149,8 @@ pub struct Dock {
active_panel_index: usize, active_panel_index: usize,
focus_handle: FocusHandle, focus_handle: FocusHandle,
pub(crate) serialized_dock: Option<DockData>, pub(crate) serialized_dock: Option<DockData>,
_focus_subscription: Subscription, resizeable: bool,
_subscriptions: [Subscription; 2],
} }
impl FocusableView for Dock { impl FocusableView for Dock {
@ -195,21 +196,28 @@ pub struct PanelButtons {
impl Dock { impl Dock {
pub fn new(position: DockPosition, cx: &mut ViewContext<Workspace>) -> View<Self> { pub fn new(position: DockPosition, cx: &mut ViewContext<Workspace>) -> View<Self> {
let focus_handle = cx.focus_handle(); let focus_handle = cx.focus_handle();
let workspace = cx.view().clone();
let dock = cx.new_view(|cx: &mut ViewContext<Self>| { let dock = cx.new_view(|cx: &mut ViewContext<Self>| {
let focus_subscription = cx.on_focus(&focus_handle, |dock, cx| { let focus_subscription = cx.on_focus(&focus_handle, |dock, cx| {
if let Some(active_entry) = dock.panel_entries.get(dock.active_panel_index) { if let Some(active_entry) = dock.panel_entries.get(dock.active_panel_index) {
active_entry.panel.focus_handle(cx).focus(cx) active_entry.panel.focus_handle(cx).focus(cx)
} }
}); });
let zoom_subscription = cx.subscribe(&workspace, |dock, workspace, e: &Event, cx| {
if matches!(e, Event::ZoomChanged) {
let is_zoomed = workspace.read(cx).zoomed.is_some();
dock.resizeable = !is_zoomed;
}
});
Self { Self {
position, position,
panel_entries: Default::default(), panel_entries: Default::default(),
active_panel_index: 0, active_panel_index: 0,
is_open: false, is_open: false,
focus_handle: focus_handle.clone(), focus_handle: focus_handle.clone(),
_focus_subscription: focus_subscription, _subscriptions: [focus_subscription, zoom_subscription],
serialized_dock: None, serialized_dock: None,
resizeable: true,
} }
}); });
@ -229,6 +237,7 @@ impl Dock {
workspace.zoomed = None; workspace.zoomed = None;
workspace.zoomed_position = None; workspace.zoomed_position = None;
} }
cx.emit(Event::ZoomChanged);
workspace.dismiss_zoomed_items_to_reveal(Some(position), cx); workspace.dismiss_zoomed_items_to_reveal(Some(position), cx);
workspace.update_active_view_for_followers(cx) workspace.update_active_view_for_followers(cx)
} }
@ -241,6 +250,7 @@ impl Dock {
if panel.is_zoomed(cx) { if panel.is_zoomed(cx) {
workspace.zoomed = Some(panel.to_any().downgrade()); workspace.zoomed = Some(panel.to_any().downgrade());
workspace.zoomed_position = Some(position); workspace.zoomed_position = Some(position);
cx.emit(Event::ZoomChanged);
return; return;
} }
} }
@ -248,6 +258,7 @@ impl Dock {
if workspace.zoomed_position == Some(position) { if workspace.zoomed_position == Some(position) {
workspace.zoomed = None; workspace.zoomed = None;
workspace.zoomed_position = None; workspace.zoomed_position = None;
cx.emit(Event::ZoomChanged);
} }
}) })
.detach(); .detach();
@ -380,6 +391,7 @@ impl Dock {
.update(cx, |workspace, cx| { .update(cx, |workspace, cx| {
workspace.zoomed = Some(panel.downgrade().into()); workspace.zoomed = Some(panel.downgrade().into());
workspace.zoomed_position = Some(panel.read(cx).position(cx)); workspace.zoomed_position = Some(panel.read(cx).position(cx));
cx.emit(Event::ZoomChanged);
}) })
.ok(); .ok();
} }
@ -390,6 +402,7 @@ impl Dock {
if workspace.zoomed_position == Some(this.position) { if workspace.zoomed_position == Some(this.position) {
workspace.zoomed = None; workspace.zoomed = None;
workspace.zoomed_position = None; workspace.zoomed_position = None;
cx.emit(Event::ZoomChanged);
} }
cx.notify(); cx.notify();
}) })
@ -553,6 +566,7 @@ impl Render for Dock {
let size = entry.panel.size(cx); let size = entry.panel.size(cx);
let position = self.position; let position = self.position;
let create_resize_handle = || {
let handle = div() let handle = div()
.id("resize-handle") .id("resize-handle")
.on_drag(DraggedDock(position), |dock, cx| { .on_drag(DraggedDock(position), |dock, cx| {
@ -566,7 +580,7 @@ impl Render for Dock {
} }
})) }))
.occlude(); .occlude();
let handle = match self.position() { match self.position() {
DockPosition::Left => deferred( DockPosition::Left => deferred(
handle handle
.absolute() .absolute()
@ -594,6 +608,7 @@ impl Render for Dock {
.w(RESIZE_HANDLE_SIZE) .w(RESIZE_HANDLE_SIZE)
.cursor_col_resize(), .cursor_col_resize(),
), ),
}
}; };
div() div()
@ -625,7 +640,7 @@ impl Render for Dock {
.cached(StyleRefinement::default().v_flex().size_full()), .cached(StyleRefinement::default().v_flex().size_full()),
), ),
) )
.child(handle) .when(self.resizeable, |this| this.child(create_resize_handle()))
} else { } else {
div() div()
.key_context(dispatch_context) .key_context(dispatch_context)

View file

@ -75,9 +75,9 @@ use theme::{ActiveTheme, SystemAppearance, ThemeSettings};
pub use toolbar::{Toolbar, ToolbarItemEvent, ToolbarItemLocation, ToolbarItemView}; pub use toolbar::{Toolbar, ToolbarItemEvent, ToolbarItemLocation, ToolbarItemView};
pub use ui; pub use ui;
use ui::{ use ui::{
div, Context as _, Div, Element, ElementContext, InteractiveElement as _, IntoElement, Label, div, Context as _, Div, Element, ElementContext, FluentBuilder as _, InteractiveElement as _,
ParentElement as _, Pixels, SharedString, Styled as _, ViewContext, VisualContext as _, IntoElement, Label, ParentElement as _, Pixels, SharedString, Styled as _, ViewContext,
WindowContext, VisualContext as _, WindowContext,
}; };
use util::ResultExt; use util::ResultExt;
use uuid::Uuid; use uuid::Uuid;
@ -520,6 +520,7 @@ pub enum Event {
ContactRequestedJoin(u64), ContactRequestedJoin(u64),
WorkspaceCreated(WeakView<Workspace>), WorkspaceCreated(WeakView<Workspace>),
SpawnTask(SpawnInTerminal), SpawnTask(SpawnInTerminal),
ZoomChanged,
} }
pub enum OpenVisible { pub enum OpenVisible {
@ -1913,6 +1914,7 @@ impl Workspace {
if self.zoomed_position != dock_to_reveal { if self.zoomed_position != dock_to_reveal {
self.zoomed = None; self.zoomed = None;
self.zoomed_position = None; self.zoomed_position = None;
cx.emit(Event::ZoomChanged);
} }
cx.notify(); cx.notify();
@ -2341,6 +2343,7 @@ impl Workspace {
self.zoomed = None; self.zoomed = None;
} }
self.zoomed_position = None; self.zoomed_position = None;
cx.emit(Event::ZoomChanged);
self.update_active_view_for_followers(cx); self.update_active_view_for_followers(cx);
cx.notify(); cx.notify();
@ -2390,6 +2393,7 @@ impl Workspace {
if pane.read(cx).has_focus(cx) { if pane.read(cx).has_focus(cx) {
self.zoomed = Some(pane.downgrade().into()); self.zoomed = Some(pane.downgrade().into());
self.zoomed_position = None; self.zoomed_position = None;
cx.emit(Event::ZoomChanged);
} }
cx.notify(); cx.notify();
} }
@ -2398,6 +2402,7 @@ impl Workspace {
pane.update(cx, |pane, cx| pane.set_zoomed(false, cx)); pane.update(cx, |pane, cx| pane.set_zoomed(false, cx));
if self.zoomed_position.is_none() { if self.zoomed_position.is_none() {
self.zoomed = None; self.zoomed = None;
cx.emit(Event::ZoomChanged);
} }
cx.notify(); cx.notify();
} }
@ -3918,9 +3923,9 @@ impl Render for Workspace {
.absolute() .absolute()
.size_full() .size_full()
}) })
.on_drag_move( .when(self.zoomed.is_none(), |this| {
cx.listener(|workspace, e: &DragMoveEvent<DraggedDock>, cx| { this.on_drag_move(cx.listener(
match e.drag(cx).0 { |workspace, e: &DragMoveEvent<DraggedDock>, cx| match e.drag(cx).0 {
DockPosition::Left => { DockPosition::Left => {
let size = workspace.bounds.left() + e.event.position.x; let size = workspace.bounds.left() + e.event.position.x;
workspace.left_dock.update(cx, |left_dock, cx| { workspace.left_dock.update(cx, |left_dock, cx| {
@ -3939,9 +3944,9 @@ impl Render for Workspace {
bottom_dock.resize_active_panel(Some(size), cx); bottom_dock.resize_active_panel(Some(size), cx);
}); });
} }
} },
}), ))
) })
.child( .child(
div() div()
.flex() .flex()