Restore focus to previously focused view when dismissing a modal

This commit is contained in:
Antonio Scandurra 2023-07-05 09:40:26 +02:00
parent a8602b2a0c
commit 03a00df8b1

View file

@ -482,7 +482,7 @@ pub enum Event {
pub struct Workspace { 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<ActiveModal>,
zoomed: Option<AnyWeakViewHandle>, zoomed: Option<AnyWeakViewHandle>,
zoomed_position: Option<DockPosition>, zoomed_position: Option<DockPosition>,
center: PaneGroup, center: PaneGroup,
@ -511,6 +511,11 @@ pub struct Workspace {
pane_history_timestamp: Arc<AtomicUsize>, pane_history_timestamp: Arc<AtomicUsize>,
} }
struct ActiveModal {
view: Box<dyn ModalHandle>,
previously_focused_view_id: Option<usize>,
}
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)] #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
pub struct ViewId { pub struct ViewId {
pub creator: PeerId, pub creator: PeerId,
@ -1498,8 +1503,10 @@ impl Workspace {
cx.notify(); cx.notify();
// Whatever modal was visible is getting clobbered. If its the same type as V, then return // Whatever modal was visible is getting clobbered. If its the same type as V, then return
// it. Otherwise, create a new modal and set it as active. // it. Otherwise, create a new modal and set it as active.
let already_open_modal = self.modal.take().and_then(|modal| modal.downcast::<V>()); if let Some(already_open_modal) = self
if let Some(already_open_modal) = already_open_modal { .dismiss_modal(cx)
.and_then(|modal| modal.downcast::<V>())
{
cx.focus_self(); cx.focus_self();
Some(already_open_modal) Some(already_open_modal)
} else { } else {
@ -1510,8 +1517,12 @@ impl Workspace {
} }
}) })
.detach(); .detach();
let previously_focused_view_id = cx.focused_view_id();
cx.focus(&modal); cx.focus(&modal);
self.modal = Some(modal.into_any()); self.modal = Some(ActiveModal {
view: Box::new(modal),
previously_focused_view_id,
});
None None
} }
} }
@ -1519,13 +1530,20 @@ impl Workspace {
pub fn modal<V: 'static + View>(&self) -> Option<ViewHandle<V>> { pub fn modal<V: 'static + View>(&self) -> Option<ViewHandle<V>> {
self.modal self.modal
.as_ref() .as_ref()
.and_then(|modal| modal.clone().downcast::<V>()) .and_then(|modal| modal.view.as_any().clone().downcast::<V>())
} }
pub fn dismiss_modal(&mut self, cx: &mut ViewContext<Self>) { pub fn dismiss_modal(&mut self, cx: &mut ViewContext<Self>) -> Option<AnyViewHandle> {
if self.modal.take().is_some() { if let Some(modal) = self.modal.take() {
cx.focus(&self.active_pane); if let Some(previously_focused_view_id) = modal.previously_focused_view_id {
if modal.view.has_focus(cx) {
cx.window_context().focus(Some(previously_focused_view_id));
}
}
cx.notify(); cx.notify();
Some(modal.view.as_any().clone())
} else {
None
} }
} }
@ -3512,7 +3530,7 @@ impl View for Workspace {
) )
})) }))
.with_children(self.modal.as_ref().map(|modal| { .with_children(self.modal.as_ref().map(|modal| {
ChildView::new(modal, cx) ChildView::new(modal.view.as_any(), cx)
.contained() .contained()
.with_style(theme.workspace.modal) .with_style(theme.workspace.modal)
.aligned() .aligned()