Remove focus filtering from gpui so all focus events result in focus-in and focus-out calls

Remove pane focused event in favor of focus_in at the workspace level
Added is_child to ViewContext to determine if a given view is a child of the current view
Fix issue where dock would get in a infinite loop when activated after dragging an item out of it
Fix issue where the last focused view in an item was not correctly refocused when a pane is focused after switching active tabs

Co-Authored-By: Mikayla Maki <mikayla@zed.dev>
This commit is contained in:
K Simmons 2022-10-12 15:10:00 -07:00
parent 81a3a22379
commit 1d8717f4de
6 changed files with 249 additions and 131 deletions

View file

@ -112,10 +112,10 @@ pub fn init(cx: &mut MutableAppContext) {
pane.activate_item(pane.items.len() - 1, true, true, cx);
});
cx.add_action(|pane: &mut Pane, _: &ActivatePrevItem, cx| {
pane.activate_prev_item(cx);
pane.activate_prev_item(true, cx);
});
cx.add_action(|pane: &mut Pane, _: &ActivateNextItem, cx| {
pane.activate_next_item(cx);
pane.activate_next_item(true, cx);
});
cx.add_async_action(Pane::close_active_item);
cx.add_async_action(Pane::close_inactive_items);
@ -189,7 +189,6 @@ pub fn init(cx: &mut MutableAppContext) {
#[derive(Debug)]
pub enum Event {
Focused,
ActivateItem { local: bool },
Remove,
RemoveItem { item_id: usize },
@ -201,7 +200,7 @@ pub struct Pane {
items: Vec<Box<dyn ItemHandle>>,
is_active: bool,
active_item_index: usize,
last_focused_view: Option<AnyWeakViewHandle>,
last_focused_view_by_item: HashMap<usize, AnyWeakViewHandle>,
autoscroll: bool,
nav_history: Rc<RefCell<NavHistory>>,
toolbar: ViewHandle<Toolbar>,
@ -263,7 +262,7 @@ impl Pane {
items: Vec::new(),
is_active: true,
active_item_index: 0,
last_focused_view: None,
last_focused_view_by_item: Default::default(),
autoscroll: false,
nav_history: Rc::new(RefCell::new(NavHistory {
mode: NavigationMode::Normal,
@ -632,32 +631,29 @@ impl Pane {
if focus_item {
self.focus_active_item(cx);
}
if activate_pane {
cx.emit(Event::Focused);
}
self.autoscroll = true;
cx.notify();
}
}
pub fn activate_prev_item(&mut self, cx: &mut ViewContext<Self>) {
pub fn activate_prev_item(&mut self, activate_pane: bool, cx: &mut ViewContext<Self>) {
let mut index = self.active_item_index;
if index > 0 {
index -= 1;
} else if !self.items.is_empty() {
index = self.items.len() - 1;
}
self.activate_item(index, true, true, cx);
self.activate_item(index, activate_pane, activate_pane, cx);
}
pub fn activate_next_item(&mut self, cx: &mut ViewContext<Self>) {
pub fn activate_next_item(&mut self, activate_pane: bool, cx: &mut ViewContext<Self>) {
let mut index = self.active_item_index;
if index + 1 < self.items.len() {
index += 1;
} else {
index = 0;
}
self.activate_item(index, true, true, cx);
self.activate_item(index, activate_pane, activate_pane, cx);
}
pub fn close_active_item(
@ -784,7 +780,7 @@ impl Pane {
// Remove the item from the pane.
pane.update(&mut cx, |pane, cx| {
if let Some(item_ix) = pane.items.iter().position(|i| i.id() == item.id()) {
pane.remove_item(item_ix, cx);
pane.remove_item(item_ix, false, cx);
}
});
}
@ -794,15 +790,15 @@ impl Pane {
})
}
fn remove_item(&mut self, item_ix: usize, cx: &mut ViewContext<Self>) {
fn remove_item(&mut self, item_ix: usize, activate_pane: bool, cx: &mut ViewContext<Self>) {
if item_ix == self.active_item_index {
// Activate the previous item if possible.
// This returns the user to the previously opened tab if they closed
// a new item they just navigated to.
if item_ix > 0 {
self.activate_prev_item(cx);
self.activate_prev_item(activate_pane, cx);
} else if item_ix + 1 < self.items.len() {
self.activate_next_item(cx);
self.activate_next_item(activate_pane, cx);
}
}
@ -965,26 +961,27 @@ impl Pane {
log::warn!("Tried to move item handle which was not in `from` pane. Maybe tab was closed during drop");
return;
}
let (item_ix, item_handle) = item_to_move.unwrap();
let item_handle = item_handle.clone();
if from != to {
// Close item from previous pane
from.update(cx, |from, cx| {
from.remove_item(item_ix, false, cx);
});
}
// This automatically removes duplicate items in the pane
Pane::add_item(
workspace,
&to,
item_handle.clone(),
item_handle,
true,
true,
Some(destination_index),
cx,
);
if from != to {
// Close item from previous pane
from.update(cx, |from, cx| {
from.remove_item(item_ix, cx);
});
}
cx.focus(to);
}
@ -1488,21 +1485,27 @@ impl View for Pane {
}
fn on_focus_in(&mut self, focused: AnyViewHandle, cx: &mut ViewContext<Self>) {
if cx.is_self_focused() {
if let Some(last_focused_view) = self
.last_focused_view
.as_ref()
.and_then(|handle| handle.upgrade(cx))
.filter(|handle| handle.id() != self.tab_bar_context_menu.id())
{
cx.focus(last_focused_view);
if let Some(active_item) = self.active_item() {
if cx.is_self_focused() {
// Pane was focused directly. We need to either focus a view inside the active item,
// or focus the active item itself
if let Some(weak_last_focused_view) =
self.last_focused_view_by_item.get(&active_item.id())
{
if let Some(last_focused_view) = weak_last_focused_view.upgrade(cx) {
cx.focus(last_focused_view);
return;
} else {
self.last_focused_view_by_item.remove(&active_item.id());
}
}
cx.focus(active_item);
} else {
self.focus_active_item(cx);
self.last_focused_view_by_item
.insert(active_item.id(), focused.downgrade());
}
} else {
self.last_focused_view = Some(focused.downgrade());
}
cx.emit(Event::Focused);
}
}