Don't steal focus when splitting pane via context menu

This commit is contained in:
Antonio Scandurra 2022-07-13 15:06:39 +02:00
parent 9677db9f8f
commit 3e3bd7ccc8

View file

@ -1,18 +1,23 @@
use std::{any::TypeId, time::Duration};
use gpui::{ use gpui::{
elements::*, geometry::vector::Vector2F, keymap, platform::CursorStyle, Action, AppContext, elements::*, geometry::vector::Vector2F, impl_internal_actions, keymap, platform::CursorStyle,
Axis, Entity, MutableAppContext, RenderContext, SizeConstraint, Subscription, View, Action, AppContext, Axis, Entity, MutableAppContext, RenderContext, SizeConstraint,
ViewContext, Subscription, View, ViewContext,
}; };
use menu::*; use menu::*;
use settings::Settings; use settings::Settings;
use std::{any::TypeId, time::Duration};
#[derive(Copy, Clone, PartialEq)]
struct Clicked;
impl_internal_actions!(context_menu, [Clicked]);
pub fn init(cx: &mut MutableAppContext) { pub fn init(cx: &mut MutableAppContext) {
cx.add_action(ContextMenu::select_first); cx.add_action(ContextMenu::select_first);
cx.add_action(ContextMenu::select_last); cx.add_action(ContextMenu::select_last);
cx.add_action(ContextMenu::select_next); cx.add_action(ContextMenu::select_next);
cx.add_action(ContextMenu::select_prev); cx.add_action(ContextMenu::select_prev);
cx.add_action(ContextMenu::clicked);
cx.add_action(ContextMenu::confirm); cx.add_action(ContextMenu::confirm);
cx.add_action(ContextMenu::cancel); cx.add_action(ContextMenu::cancel);
} }
@ -56,6 +61,7 @@ pub struct ContextMenu {
selected_index: Option<usize>, selected_index: Option<usize>,
visible: bool, visible: bool,
previously_focused_view_id: Option<usize>, previously_focused_view_id: Option<usize>,
clicked: bool,
_actions_observation: Subscription, _actions_observation: Subscription,
} }
@ -113,6 +119,7 @@ impl ContextMenu {
selected_index: Default::default(), selected_index: Default::default(),
visible: Default::default(), visible: Default::default(),
previously_focused_view_id: Default::default(), previously_focused_view_id: Default::default(),
clicked: false,
_actions_observation: cx.observe_actions(Self::action_dispatched), _actions_observation: cx.observe_actions(Self::action_dispatched),
} }
} }
@ -123,22 +130,31 @@ impl ContextMenu {
.iter() .iter()
.position(|item| item.action_id() == Some(action_id)) .position(|item| item.action_id() == Some(action_id))
{ {
self.selected_index = Some(ix); if self.clicked {
cx.notify(); self.cancel(&Default::default(), cx);
cx.spawn(|this, mut cx| async move { } else {
cx.background().timer(Duration::from_millis(100)).await; self.selected_index = Some(ix);
this.update(&mut cx, |this, cx| this.cancel(&Default::default(), cx)); cx.notify();
}) cx.spawn(|this, mut cx| async move {
.detach(); cx.background().timer(Duration::from_millis(50)).await;
this.update(&mut cx, |this, cx| this.cancel(&Default::default(), cx));
})
.detach();
}
} }
} }
fn clicked(&mut self, _: &Clicked, _: &mut ViewContext<Self>) {
self.clicked = true;
}
fn confirm(&mut self, _: &Confirm, cx: &mut ViewContext<Self>) { fn confirm(&mut self, _: &Confirm, cx: &mut ViewContext<Self>) {
if let Some(ix) = self.selected_index { if let Some(ix) = self.selected_index {
if let Some(ContextMenuItem::Item { action, .. }) = self.items.get(ix) { if let Some(ContextMenuItem::Item { action, .. }) = self.items.get(ix) {
let window_id = cx.window_id(); let window_id = cx.window_id();
let view_id = cx.view_id(); let view_id = cx.view_id();
cx.dispatch_action_at(window_id, view_id, action.as_ref()); cx.dispatch_action_at(window_id, view_id, action.as_ref());
self.reset(cx);
} }
} }
} }
@ -158,6 +174,7 @@ impl ContextMenu {
self.items.clear(); self.items.clear();
self.visible = false; self.visible = false;
self.selected_index.take(); self.selected_index.take();
self.clicked = false;
cx.notify(); cx.notify();
} }
@ -317,8 +334,8 @@ impl ContextMenu {
}) })
.with_cursor_style(CursorStyle::PointingHand) .with_cursor_style(CursorStyle::PointingHand)
.on_click(move |_, _, cx| { .on_click(move |_, _, cx| {
cx.dispatch_action(Clicked);
cx.dispatch_any_action(action.boxed_clone()); cx.dispatch_any_action(action.boxed_clone());
cx.dispatch_action(Cancel);
}) })
.boxed() .boxed()
} }