Fix on_action on focusable

We were accidentally dropping the key context
This commit is contained in:
Conrad Irwin 2023-11-13 12:48:36 -07:00
parent 2625051f75
commit 7e7b065535
6 changed files with 34 additions and 54 deletions

View file

@ -1,8 +1,7 @@
use editor::{display_map::ToDisplayPoint, scroll::autoscroll::Autoscroll, Editor}; use editor::{display_map::ToDisplayPoint, scroll::autoscroll::Autoscroll, Editor};
use gpui::{ use gpui::{
actions, div, AppContext, Div, EventEmitter, ParentElement, Render, SharedString, actions, div, AppContext, Div, EventEmitter, ParentElement, Render, SharedString,
StatefulInteractivity, StatelessInteractive, Styled, Subscription, View, ViewContext, StatelessInteractive, Styled, Subscription, View, ViewContext, VisualContext, WindowContext,
VisualContext, WindowContext,
}; };
use text::{Bias, Point}; use text::{Bias, Point};
use theme::ActiveTheme; use theme::ActiveTheme;
@ -146,11 +145,11 @@ impl GoToLine {
} }
impl Render for GoToLine { impl Render for GoToLine {
type Element = Div<Self, StatefulInteractivity<Self>>; type Element = Div<Self>;
fn render(&mut self, cx: &mut ViewContext<Self>) -> Self::Element { fn render(&mut self, cx: &mut ViewContext<Self>) -> Self::Element {
modal(cx) modal(cx)
.id("go to line") .context("GoToLine")
.on_action(Self::cancel) .on_action(Self::cancel)
.on_action(Self::confirm) .on_action(Self::confirm)
.w_96() .w_96()

View file

@ -128,7 +128,7 @@ impl<V: 'static> Div<V, StatefulInteractivity<V>, NonFocusableKeyDispatch> {
pub fn focusable(self) -> Div<V, StatefulInteractivity<V>, FocusableKeyDispatch<V>> { pub fn focusable(self) -> Div<V, StatefulInteractivity<V>, FocusableKeyDispatch<V>> {
Div { Div {
interactivity: self.interactivity, interactivity: self.interactivity,
key_dispatch: FocusableKeyDispatch::new(), key_dispatch: FocusableKeyDispatch::new(self.key_dispatch),
children: self.children, children: self.children,
group: self.group, group: self.group,
base_style: self.base_style, base_style: self.base_style,
@ -141,7 +141,7 @@ impl<V: 'static> Div<V, StatefulInteractivity<V>, NonFocusableKeyDispatch> {
) -> Div<V, StatefulInteractivity<V>, FocusableKeyDispatch<V>> { ) -> Div<V, StatefulInteractivity<V>, FocusableKeyDispatch<V>> {
Div { Div {
interactivity: self.interactivity, interactivity: self.interactivity,
key_dispatch: FocusableKeyDispatch::tracked(handle), key_dispatch: FocusableKeyDispatch::tracked(self.key_dispatch, handle),
children: self.children, children: self.children,
group: self.group, group: self.group,
base_style: self.base_style, base_style: self.base_style,
@ -172,7 +172,7 @@ impl<V: 'static> Div<V, StatelessInteractivity<V>, NonFocusableKeyDispatch> {
) -> Div<V, StatefulInteractivity<V>, FocusableKeyDispatch<V>> { ) -> Div<V, StatefulInteractivity<V>, FocusableKeyDispatch<V>> {
Div { Div {
interactivity: self.interactivity.into_stateful(handle), interactivity: self.interactivity.into_stateful(handle),
key_dispatch: handle.clone().into(), key_dispatch: FocusableKeyDispatch::tracked(self.key_dispatch, handle),
children: self.children, children: self.children,
group: self.group, group: self.group,
base_style: self.base_style, base_style: self.base_style,

View file

@ -1247,9 +1247,10 @@ mod test {
fn render(&mut self, _: &mut gpui::ViewContext<Self>) -> Self::Element { fn render(&mut self, _: &mut gpui::ViewContext<Self>) -> Self::Element {
div().id("testview").child( div().id("testview").child(
div() div()
.context("test")
.track_focus(&self.focus_handle)
.on_key_down(|this: &mut TestView, _, _, _| this.saw_key_down = true) .on_key_down(|this: &mut TestView, _, _, _| this.saw_key_down = true)
.on_action(|this: &mut TestView, _: &TestAction, _| this.saw_action = true) .on_action(|this: &mut TestView, _: &TestAction, _| this.saw_action = true),
.track_focus(&self.focus_handle),
) )
} }
} }

View file

@ -33,7 +33,7 @@ pub(crate) struct DispatchTree {
#[derive(Default)] #[derive(Default)]
pub(crate) struct DispatchNode { pub(crate) struct DispatchNode {
pub key_listeners: SmallVec<[KeyListener; 2]>, pub key_listeners: SmallVec<[KeyListener; 2]>,
pub action_listeners: SmallVec<[ActionListener; 16]>, pub action_listeners: SmallVec<[DispatchActionListener; 16]>,
pub context: KeyContext, pub context: KeyContext,
parent: Option<DispatchNodeId>, parent: Option<DispatchNodeId>,
} }
@ -41,7 +41,7 @@ pub(crate) struct DispatchNode {
type KeyListener = Rc<dyn Fn(&dyn Any, DispatchPhase, &mut WindowContext)>; type KeyListener = Rc<dyn Fn(&dyn Any, DispatchPhase, &mut WindowContext)>;
#[derive(Clone)] #[derive(Clone)]
pub(crate) struct ActionListener { pub(crate) struct DispatchActionListener {
pub(crate) action_type: TypeId, pub(crate) action_type: TypeId,
pub(crate) listener: Rc<dyn Fn(&dyn Any, DispatchPhase, &mut WindowContext)>, pub(crate) listener: Rc<dyn Fn(&dyn Any, DispatchPhase, &mut WindowContext)>,
} }
@ -102,10 +102,12 @@ impl DispatchTree {
action_type: TypeId, action_type: TypeId,
listener: Rc<dyn Fn(&dyn Any, DispatchPhase, &mut WindowContext)>, listener: Rc<dyn Fn(&dyn Any, DispatchPhase, &mut WindowContext)>,
) { ) {
self.active_node().action_listeners.push(ActionListener { self.active_node()
action_type, .action_listeners
listener, .push(DispatchActionListener {
}); action_type,
listener,
});
} }
pub fn make_focusable(&mut self, focus_id: FocusId) { pub fn make_focusable(&mut self, focus_id: FocusId) {
@ -135,7 +137,7 @@ impl DispatchTree {
if let Some(node) = self.focusable_node_ids.get(&target) { if let Some(node) = self.focusable_node_ids.get(&target) {
for node_id in self.dispatch_path(*node) { for node_id in self.dispatch_path(*node) {
let node = &self.nodes[node_id.0]; let node = &self.nodes[node_id.0];
for ActionListener { action_type, .. } in &node.action_listeners { for DispatchActionListener { action_type, .. } in &node.action_listeners {
actions.extend(build_action_from_type(action_type).log_err()); actions.extend(build_action_from_type(action_type).log_err());
} }
} }
@ -148,21 +150,15 @@ impl DispatchTree {
keystroke: &Keystroke, keystroke: &Keystroke,
context: &[KeyContext], context: &[KeyContext],
) -> Option<Box<dyn Action>> { ) -> Option<Box<dyn Action>> {
if !self if !self.keystroke_matchers.contains_key(context) {
.keystroke_matchers let keystroke_contexts = context.iter().cloned().collect();
.contains_key(self.context_stack.as_slice())
{
let keystroke_contexts = self.context_stack.iter().cloned().collect();
self.keystroke_matchers.insert( self.keystroke_matchers.insert(
keystroke_contexts, keystroke_contexts,
KeystrokeMatcher::new(self.keymap.clone()), KeystrokeMatcher::new(self.keymap.clone()),
); );
} }
let keystroke_matcher = self let keystroke_matcher = self.keystroke_matchers.get_mut(context).unwrap();
.keystroke_matchers
.get_mut(self.context_stack.as_slice())
.unwrap();
if let KeyMatch::Some(action) = keystroke_matcher.match_keystroke(keystroke, context) { if let KeyMatch::Some(action) = keystroke_matcher.match_keystroke(keystroke, context) {
// Clear all pending keystrokes when an action has been found. // Clear all pending keystrokes when an action has been found.
for keystroke_matcher in self.keystroke_matchers.values_mut() { for keystroke_matcher in self.keystroke_matchers.values_mut() {
@ -274,7 +270,7 @@ pub trait KeyDispatch<V: 'static>: 'static {
} }
pub struct FocusableKeyDispatch<V> { pub struct FocusableKeyDispatch<V> {
pub key_context: KeyContext, pub non_focusable: NonFocusableKeyDispatch,
pub focus_handle: Option<FocusHandle>, pub focus_handle: Option<FocusHandle>,
pub focus_listeners: FocusListeners<V>, pub focus_listeners: FocusListeners<V>,
pub focus_style: StyleRefinement, pub focus_style: StyleRefinement,
@ -283,9 +279,9 @@ pub struct FocusableKeyDispatch<V> {
} }
impl<V> FocusableKeyDispatch<V> { impl<V> FocusableKeyDispatch<V> {
pub fn new() -> Self { pub fn new(non_focusable: NonFocusableKeyDispatch) -> Self {
Self { Self {
key_context: KeyContext::default(), non_focusable,
focus_handle: None, focus_handle: None,
focus_listeners: FocusListeners::default(), focus_listeners: FocusListeners::default(),
focus_style: StyleRefinement::default(), focus_style: StyleRefinement::default(),
@ -294,9 +290,9 @@ impl<V> FocusableKeyDispatch<V> {
} }
} }
pub fn tracked(handle: &FocusHandle) -> Self { pub fn tracked(non_focusable: NonFocusableKeyDispatch, handle: &FocusHandle) -> Self {
Self { Self {
key_context: KeyContext::default(), non_focusable,
focus_handle: Some(handle.clone()), focus_handle: Some(handle.clone()),
focus_listeners: FocusListeners::default(), focus_listeners: FocusListeners::default(),
focus_style: StyleRefinement::default(), focus_style: StyleRefinement::default(),
@ -316,24 +312,11 @@ impl<V: 'static> KeyDispatch<V> for FocusableKeyDispatch<V> {
} }
fn key_context(&self) -> &KeyContext { fn key_context(&self) -> &KeyContext {
&self.key_context &self.non_focusable.key_context
} }
fn key_context_mut(&mut self) -> &mut KeyContext { fn key_context_mut(&mut self) -> &mut KeyContext {
&mut self.key_context &mut self.non_focusable.key_context
}
}
impl<V> From<FocusHandle> for FocusableKeyDispatch<V> {
fn from(value: FocusHandle) -> Self {
Self {
key_context: KeyContext::default(),
focus_handle: Some(value),
focus_listeners: FocusListeners::default(),
focus_style: StyleRefinement::default(),
focus_in_style: StyleRefinement::default(),
in_focus_style: StyleRefinement::default(),
}
} }
} }

View file

@ -1,5 +1,5 @@
use crate::{ use crate::{
key_dispatch::ActionListener, px, size, Action, AnyBox, AnyDrag, AnyView, AppContext, key_dispatch::DispatchActionListener, px, size, Action, AnyBox, AnyDrag, AnyView, AppContext,
AsyncWindowContext, AvailableSpace, Bounds, BoxShadow, Context, Corners, CursorStyle, AsyncWindowContext, AvailableSpace, Bounds, BoxShadow, Context, Corners, CursorStyle,
DevicePixels, DispatchNodeId, DispatchTree, DisplayId, Edges, Effect, Entity, EntityId, DevicePixels, DispatchNodeId, DispatchTree, DisplayId, Edges, Effect, Entity, EntityId,
EventEmitter, FileDropEvent, FocusEvent, FontId, GlobalElementId, GlyphId, Hsla, ImageData, EventEmitter, FileDropEvent, FocusEvent, FontId, GlobalElementId, GlyphId, Hsla, ImageData,
@ -1306,7 +1306,7 @@ impl<'a> WindowContext<'a> {
// Capture phase // Capture phase
for node_id in &dispatch_path { for node_id in &dispatch_path {
let node = self.window.current_frame.dispatch_tree.node(*node_id); let node = self.window.current_frame.dispatch_tree.node(*node_id);
for ActionListener { for DispatchActionListener {
action_type, action_type,
listener, listener,
} in node.action_listeners.clone() } in node.action_listeners.clone()
@ -1324,7 +1324,7 @@ impl<'a> WindowContext<'a> {
// Bubble phase // Bubble phase
for node_id in dispatch_path.iter().rev() { for node_id in dispatch_path.iter().rev() {
let node = self.window.current_frame.dispatch_tree.node(*node_id); let node = self.window.current_frame.dispatch_tree.node(*node_id);
for ActionListener { for DispatchActionListener {
action_type, action_type,
listener, listener,
} in node.action_listeners.clone() } in node.action_listeners.clone()

View file

@ -1,8 +1,7 @@
use editor::Editor; use editor::Editor;
use gpui::{ use gpui::{
div, uniform_list, Component, Div, FocusableKeyDispatch, ParentElement, Render, div, uniform_list, Component, Div, ParentElement, Render, StatelessInteractive, Styled, Task,
StatefulInteractivity, StatelessInteractive, Styled, Task, UniformListScrollHandle, View, UniformListScrollHandle, View, ViewContext, VisualContext, WindowContext,
ViewContext, VisualContext, WindowContext,
}; };
use std::cmp; use std::cmp;
use theme::ActiveTheme; use theme::ActiveTheme;
@ -137,13 +136,11 @@ impl<D: PickerDelegate> Picker<D> {
} }
impl<D: PickerDelegate> Render for Picker<D> { impl<D: PickerDelegate> Render for Picker<D> {
type Element = Div<Self, StatefulInteractivity<Self>, FocusableKeyDispatch<Self>>; type Element = Div<Self>;
fn render(&mut self, cx: &mut ViewContext<Self>) -> Self::Element { fn render(&mut self, cx: &mut ViewContext<Self>) -> Self::Element {
div() div()
.context("picker") .context("picker")
.id("picker-container")
.focusable()
.size_full() .size_full()
.on_action(Self::select_next) .on_action(Self::select_next)
.on_action(Self::select_prev) .on_action(Self::select_prev)