From 89a5506f43dcd7d982e20f7c37883c06a04f6265 Mon Sep 17 00:00:00 2001 From: Kay Simmons Date: Fri, 27 Jan 2023 12:39:32 -0800 Subject: [PATCH 1/3] Add function which checks if a child of a view is focused and use that to only focus item updates from the leader when that the active item was focused --- crates/gpui/src/app.rs | 41 ++++++++++++++++++++----------- crates/workspace/src/workspace.rs | 18 +++++++++----- 2 files changed, 38 insertions(+), 21 deletions(-) diff --git a/crates/gpui/src/app.rs b/crates/gpui/src/app.rs index 3fc11a6b58..cad800a38c 100644 --- a/crates/gpui/src/app.rs +++ b/crates/gpui/src/app.rs @@ -1414,21 +1414,6 @@ impl MutableAppContext { true } - /// Returns an iterator over all of the view ids from the passed view up to the root of the window - /// Includes the passed view itself - fn ancestors(&self, window_id: usize, mut view_id: usize) -> impl Iterator + '_ { - std::iter::once(view_id) - .into_iter() - .chain(std::iter::from_fn(move || { - if let Some(ParentId::View(parent_id)) = self.parents.get(&(window_id, view_id)) { - view_id = *parent_id; - Some(view_id) - } else { - None - } - })) - } - fn actions_mut( &mut self, capture_phase: bool, @@ -2733,6 +2718,32 @@ impl AppContext { panic!("no global has been added for {}", type_name::()); } } + + /// Returns an iterator over all of the view ids from the passed view up to the root of the window + /// Includes the passed view itself + fn ancestors(&self, window_id: usize, mut view_id: usize) -> impl Iterator + '_ { + std::iter::once(view_id) + .into_iter() + .chain(std::iter::from_fn(move || { + if let Some(ParentId::View(parent_id)) = self.parents.get(&(window_id, view_id)) { + view_id = *parent_id; + Some(view_id) + } else { + None + } + })) + } + + pub fn is_child_focused(&self, view: impl Into) -> bool { + let view = view.into(); + if let Some(focused_view_id) = self.focused_view_id(view.window_id) { + self.ancestors(view.window_id, focused_view_id) + .skip(1) // Skip self id + .any(|parent| parent == view.view_id) + } else { + false + } + } } impl ReadModel for AppContext { diff --git a/crates/workspace/src/workspace.rs b/crates/workspace/src/workspace.rs index b90c62aca1..9c64eada5a 100644 --- a/crates/workspace/src/workspace.rs +++ b/crates/workspace/src/workspace.rs @@ -2140,7 +2140,7 @@ impl Workspace { let call = self.active_call()?; let room = call.read(cx).room()?.read(cx); let participant = room.remote_participant_for_peer_id(leader_id)?; - let mut items_to_add = Vec::new(); + let mut items_to_activate = Vec::new(); match participant.location { call::ParticipantLocation::SharedProject { project_id } => { if Some(project_id) == self.project.read(cx).remote_id() { @@ -2149,12 +2149,12 @@ impl Workspace { .active_view_id .and_then(|id| state.items_by_leader_view_id.get(&id)) { - items_to_add.push((pane.clone(), item.boxed_clone())); + items_to_activate.push((pane.clone(), item.boxed_clone())); } else { if let Some(shared_screen) = self.shared_screen_for_peer(leader_id, pane, cx) { - items_to_add.push((pane.clone(), Box::new(shared_screen))); + items_to_activate.push((pane.clone(), Box::new(shared_screen))); } } } @@ -2164,20 +2164,26 @@ impl Workspace { call::ParticipantLocation::External => { for (pane, _) in self.follower_states_by_leader.get(&leader_id)? { if let Some(shared_screen) = self.shared_screen_for_peer(leader_id, pane, cx) { - items_to_add.push((pane.clone(), Box::new(shared_screen))); + items_to_activate.push((pane.clone(), Box::new(shared_screen))); } } } } - for (pane, item) in items_to_add { + for (pane, item) in items_to_activate { + let active_item_was_focused = pane + .read(cx) + .active_item() + .map(|active_item| cx.is_child_focused(active_item.to_any())) + .unwrap_or_default(); + if let Some(index) = pane.update(cx, |pane, _| pane.index_for_item(item.as_ref())) { pane.update(cx, |pane, cx| pane.activate_item(index, false, false, cx)); } else { Pane::add_item(self, &pane, item.boxed_clone(), false, false, None, cx); } - if pane == self.active_pane { + if active_item_was_focused { pane.update(cx, |pane, cx| pane.focus_active_item(cx)); } } From d6acea525df660d2ec2bdfe85b0d1cc7029865c6 Mon Sep 17 00:00:00 2001 From: Kay Simmons Date: Fri, 27 Jan 2023 13:00:26 -0800 Subject: [PATCH 2/3] add test for is_child_focused --- crates/gpui/src/app.rs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/crates/gpui/src/app.rs b/crates/gpui/src/app.rs index cad800a38c..9b1e13910d 100644 --- a/crates/gpui/src/app.rs +++ b/crates/gpui/src/app.rs @@ -6394,6 +6394,8 @@ mod tests { cx.focus(&view_1); cx.focus(&view_2); }); + assert!(cx.is_child_focused(view_1.clone())); + assert!(!cx.is_child_focused(view_2.clone())); assert_eq!( mem::take(&mut *view_events.lock()), [ @@ -6418,6 +6420,8 @@ mod tests { ); view_1.update(cx, |_, cx| cx.focus(&view_1)); + assert!(!cx.is_child_focused(view_1.clone())); + assert!(!cx.is_child_focused(view_2.clone())); assert_eq!( mem::take(&mut *view_events.lock()), ["view 2 blurred", "view 1 focused"], From 77a4f907a00eb0ef461111808487c8b8d9141628 Mon Sep 17 00:00:00 2001 From: Kay Simmons Date: Fri, 27 Jan 2023 13:43:36 -0800 Subject: [PATCH 3/3] removed invalid focus assertion --- crates/collab/src/tests/integration_tests.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/crates/collab/src/tests/integration_tests.rs b/crates/collab/src/tests/integration_tests.rs index a645d6dc71..9db5996b39 100644 --- a/crates/collab/src/tests/integration_tests.rs +++ b/crates/collab/src/tests/integration_tests.rs @@ -5623,7 +5623,6 @@ async fn test_following( .downcast::() .unwrap() }); - assert!(cx_b.read(|cx| editor_b2.is_focused(cx))); assert_eq!( cx_b.read(|cx| editor_b2.project_path(cx)), Some((worktree_id, "2.txt").into())