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 gpui::{
actions, div, AppContext, Div, EventEmitter, ParentElement, Render, SharedString,
StatefulInteractivity, StatelessInteractive, Styled, Subscription, View, ViewContext,
VisualContext, WindowContext,
StatelessInteractive, Styled, Subscription, View, ViewContext, VisualContext, WindowContext,
};
use text::{Bias, Point};
use theme::ActiveTheme;
@ -146,11 +145,11 @@ impl 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 {
modal(cx)
.id("go to line")
.context("GoToLine")
.on_action(Self::cancel)
.on_action(Self::confirm)
.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>> {
Div {
interactivity: self.interactivity,
key_dispatch: FocusableKeyDispatch::new(),
key_dispatch: FocusableKeyDispatch::new(self.key_dispatch),
children: self.children,
group: self.group,
base_style: self.base_style,
@ -141,7 +141,7 @@ impl<V: 'static> Div<V, StatefulInteractivity<V>, NonFocusableKeyDispatch> {
) -> Div<V, StatefulInteractivity<V>, FocusableKeyDispatch<V>> {
Div {
interactivity: self.interactivity,
key_dispatch: FocusableKeyDispatch::tracked(handle),
key_dispatch: FocusableKeyDispatch::tracked(self.key_dispatch, handle),
children: self.children,
group: self.group,
base_style: self.base_style,
@ -172,7 +172,7 @@ impl<V: 'static> Div<V, StatelessInteractivity<V>, NonFocusableKeyDispatch> {
) -> Div<V, StatefulInteractivity<V>, FocusableKeyDispatch<V>> {
Div {
interactivity: self.interactivity.into_stateful(handle),
key_dispatch: handle.clone().into(),
key_dispatch: FocusableKeyDispatch::tracked(self.key_dispatch, handle),
children: self.children,
group: self.group,
base_style: self.base_style,

View file

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

View file

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

View file

@ -1,5 +1,5 @@
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,
DevicePixels, DispatchNodeId, DispatchTree, DisplayId, Edges, Effect, Entity, EntityId,
EventEmitter, FileDropEvent, FocusEvent, FontId, GlobalElementId, GlyphId, Hsla, ImageData,
@ -1306,7 +1306,7 @@ impl<'a> WindowContext<'a> {
// Capture phase
for node_id in &dispatch_path {
let node = self.window.current_frame.dispatch_tree.node(*node_id);
for ActionListener {
for DispatchActionListener {
action_type,
listener,
} in node.action_listeners.clone()
@ -1324,7 +1324,7 @@ impl<'a> WindowContext<'a> {
// Bubble phase
for node_id in dispatch_path.iter().rev() {
let node = self.window.current_frame.dispatch_tree.node(*node_id);
for ActionListener {
for DispatchActionListener {
action_type,
listener,
} in node.action_listeners.clone()

View file

@ -1,8 +1,7 @@
use editor::Editor;
use gpui::{
div, uniform_list, Component, Div, FocusableKeyDispatch, ParentElement, Render,
StatefulInteractivity, StatelessInteractive, Styled, Task, UniformListScrollHandle, View,
ViewContext, VisualContext, WindowContext,
div, uniform_list, Component, Div, ParentElement, Render, StatelessInteractive, Styled, Task,
UniformListScrollHandle, View, ViewContext, VisualContext, WindowContext,
};
use std::cmp;
use theme::ActiveTheme;
@ -137,13 +136,11 @@ impl<D: PickerDelegate> 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 {
div()
.context("picker")
.id("picker-container")
.focusable()
.size_full()
.on_action(Self::select_next)
.on_action(Self::select_prev)