key_dispatch.rs

   1//! KeyDispatch is where GPUI deals with binding actions to key events.
   2//!
   3//! The key pieces to making a key binding work are to define an action,
   4//! implement a method that takes that action as a type parameter,
   5//! and then to register the action during render on a focused node
   6//! with a keymap context:
   7//!
   8//! ```ignore
   9//! actions!(editor,[Undo, Redo]);
  10//!
  11//! impl Editor {
  12//!   fn undo(&mut self, _: &Undo, _window: &mut Window, _cx: &mut Context<Self>) { ... }
  13//!   fn redo(&mut self, _: &Redo, _window: &mut Window, _cx: &mut Context<Self>) { ... }
  14//! }
  15//!
  16//! impl Render for Editor {
  17//!   fn render(&mut self, window: &mut Window, cx: &mut Context<Self>) -> impl IntoElement {
  18//!     div()
  19//!       .track_focus(&self.focus_handle(cx))
  20//!       .key_context("Editor")
  21//!       .on_action(cx.listener(Editor::undo))
  22//!       .on_action(cx.listener(Editor::redo))
  23//!     ...
  24//!    }
  25//! }
  26//!```
  27//!
  28//! The keybindings themselves are managed independently by calling cx.bind_keys().
  29//! (Though mostly when developing Zed itself, you just need to add a new line to
  30//!  assets/keymaps/default-{platform}.json).
  31//!
  32//! ```ignore
  33//! cx.bind_keys([
  34//!   KeyBinding::new("cmd-z", Editor::undo, Some("Editor")),
  35//!   KeyBinding::new("cmd-shift-z", Editor::redo, Some("Editor")),
  36//! ])
  37//! ```
  38//!
  39//! With all of this in place, GPUI will ensure that if you have an Editor that contains
  40//! the focus, hitting cmd-z will Undo.
  41//!
  42//! In real apps, it is a little more complicated than this, because typically you have
  43//! several nested views that each register keyboard handlers. In this case action matching
  44//! bubbles up from the bottom. For example in Zed, the Workspace is the top-level view, which contains Pane's, which contain Editors. If there are conflicting keybindings defined
  45//! then the Editor's bindings take precedence over the Pane's bindings, which take precedence over the Workspace.
  46//!
  47//! In GPUI, keybindings are not limited to just single keystrokes, you can define
  48//! sequences by separating the keys with a space:
  49//!
  50//!  KeyBinding::new("cmd-k left", pane::SplitLeft, Some("Pane"))
  51
  52use crate::{
  53    Action, ActionRegistry, App, DispatchPhase, EntityId, FocusId, KeyBinding, KeyContext, Keymap,
  54    Keystroke, ModifiersChangedEvent, Window,
  55};
  56use collections::FxHashMap;
  57use smallvec::SmallVec;
  58use std::{
  59    any::{Any, TypeId},
  60    cell::RefCell,
  61    mem,
  62    ops::Range,
  63    rc::Rc,
  64};
  65
  66/// ID of a node within `DispatchTree`. Note that these are **not** stable between frames, and so a
  67/// `DispatchNodeId` should only be used with the `DispatchTree` that provided it.
  68#[derive(Clone, Copy, Debug, Eq, PartialEq, Hash)]
  69pub(crate) struct DispatchNodeId(usize);
  70
  71pub(crate) struct DispatchTree {
  72    node_stack: Vec<DispatchNodeId>,
  73    pub(crate) context_stack: Vec<KeyContext>,
  74    view_stack: Vec<EntityId>,
  75    nodes: Vec<DispatchNode>,
  76    focusable_node_ids: FxHashMap<FocusId, DispatchNodeId>,
  77    view_node_ids: FxHashMap<EntityId, DispatchNodeId>,
  78    keymap: Rc<RefCell<Keymap>>,
  79    action_registry: Rc<ActionRegistry>,
  80}
  81
  82#[derive(Default)]
  83pub(crate) struct DispatchNode {
  84    pub key_listeners: Vec<KeyListener>,
  85    pub action_listeners: Vec<DispatchActionListener>,
  86    pub modifiers_changed_listeners: Vec<ModifiersChangedListener>,
  87    pub context: Option<KeyContext>,
  88    pub focus_id: Option<FocusId>,
  89    view_id: Option<EntityId>,
  90    parent: Option<DispatchNodeId>,
  91}
  92
  93pub(crate) struct ReusedSubtree {
  94    old_range: Range<usize>,
  95    new_range: Range<usize>,
  96    contains_focus: bool,
  97}
  98
  99impl ReusedSubtree {
 100    pub fn refresh_node_id(&self, node_id: DispatchNodeId) -> DispatchNodeId {
 101        debug_assert!(
 102            self.old_range.contains(&node_id.0),
 103            "node {} was not part of the reused subtree {:?}",
 104            node_id.0,
 105            self.old_range
 106        );
 107        DispatchNodeId((node_id.0 - self.old_range.start) + self.new_range.start)
 108    }
 109
 110    pub fn contains_focus(&self) -> bool {
 111        self.contains_focus
 112    }
 113}
 114
 115#[derive(Default, Debug)]
 116pub(crate) struct Replay {
 117    pub(crate) keystroke: Keystroke,
 118    pub(crate) bindings: SmallVec<[KeyBinding; 1]>,
 119}
 120
 121#[derive(Default, Debug)]
 122pub(crate) struct DispatchResult {
 123    pub(crate) pending: SmallVec<[Keystroke; 1]>,
 124    pub(crate) pending_has_binding: bool,
 125    pub(crate) bindings: SmallVec<[KeyBinding; 1]>,
 126    pub(crate) to_replay: SmallVec<[Replay; 1]>,
 127    pub(crate) context_stack: Vec<KeyContext>,
 128}
 129
 130type KeyListener = Rc<dyn Fn(&dyn Any, DispatchPhase, &mut Window, &mut App)>;
 131type ModifiersChangedListener = Rc<dyn Fn(&ModifiersChangedEvent, &mut Window, &mut App)>;
 132
 133#[derive(Clone)]
 134pub(crate) struct DispatchActionListener {
 135    pub(crate) action_type: TypeId,
 136    pub(crate) listener: Rc<dyn Fn(&dyn Any, DispatchPhase, &mut Window, &mut App)>,
 137}
 138
 139impl DispatchTree {
 140    pub fn new(keymap: Rc<RefCell<Keymap>>, action_registry: Rc<ActionRegistry>) -> Self {
 141        Self {
 142            node_stack: Vec::new(),
 143            context_stack: Vec::new(),
 144            view_stack: Vec::new(),
 145            nodes: Vec::new(),
 146            focusable_node_ids: FxHashMap::default(),
 147            view_node_ids: FxHashMap::default(),
 148            keymap,
 149            action_registry,
 150        }
 151    }
 152
 153    pub fn clear(&mut self) {
 154        self.node_stack.clear();
 155        self.context_stack.clear();
 156        self.view_stack.clear();
 157        self.nodes.clear();
 158        self.focusable_node_ids.clear();
 159        self.view_node_ids.clear();
 160    }
 161
 162    pub fn len(&self) -> usize {
 163        self.nodes.len()
 164    }
 165
 166    pub fn push_node(&mut self) -> DispatchNodeId {
 167        let parent = self.node_stack.last().copied();
 168        let node_id = DispatchNodeId(self.nodes.len());
 169
 170        self.nodes.push(DispatchNode {
 171            parent,
 172            ..Default::default()
 173        });
 174        self.node_stack.push(node_id);
 175        node_id
 176    }
 177
 178    pub fn set_active_node(&mut self, node_id: DispatchNodeId) {
 179        let next_node_parent = self.nodes[node_id.0].parent;
 180        while self.node_stack.last().copied() != next_node_parent && !self.node_stack.is_empty() {
 181            self.pop_node();
 182        }
 183
 184        if self.node_stack.last().copied() == next_node_parent {
 185            self.node_stack.push(node_id);
 186            let active_node = &self.nodes[node_id.0];
 187            if let Some(view_id) = active_node.view_id {
 188                self.view_stack.push(view_id)
 189            }
 190            if let Some(context) = active_node.context.clone() {
 191                self.context_stack.push(context);
 192            }
 193        } else {
 194            debug_assert_eq!(self.node_stack.len(), 0);
 195
 196            let mut current_node_id = Some(node_id);
 197            while let Some(node_id) = current_node_id {
 198                let node = &self.nodes[node_id.0];
 199                if let Some(context) = node.context.clone() {
 200                    self.context_stack.push(context);
 201                }
 202                if node.view_id.is_some() {
 203                    self.view_stack.push(node.view_id.unwrap());
 204                }
 205                self.node_stack.push(node_id);
 206                current_node_id = node.parent;
 207            }
 208
 209            self.context_stack.reverse();
 210            self.view_stack.reverse();
 211            self.node_stack.reverse();
 212        }
 213    }
 214
 215    pub fn set_key_context(&mut self, context: KeyContext) {
 216        self.active_node().context = Some(context.clone());
 217        self.context_stack.push(context);
 218    }
 219
 220    pub fn set_focus_id(&mut self, focus_id: FocusId) {
 221        let node_id = *self.node_stack.last().unwrap();
 222        self.nodes[node_id.0].focus_id = Some(focus_id);
 223        self.focusable_node_ids.insert(focus_id, node_id);
 224    }
 225
 226    pub fn set_view_id(&mut self, view_id: EntityId) {
 227        if self.view_stack.last().copied() != Some(view_id) {
 228            let node_id = *self.node_stack.last().unwrap();
 229            self.nodes[node_id.0].view_id = Some(view_id);
 230            self.view_node_ids.insert(view_id, node_id);
 231            self.view_stack.push(view_id);
 232        }
 233    }
 234
 235    pub fn pop_node(&mut self) {
 236        let node = &self.nodes[self.active_node_id().unwrap().0];
 237        if node.context.is_some() {
 238            self.context_stack.pop();
 239        }
 240        if node.view_id.is_some() {
 241            self.view_stack.pop();
 242        }
 243        self.node_stack.pop();
 244    }
 245
 246    fn move_node(&mut self, source: &mut DispatchNode) {
 247        self.push_node();
 248        if let Some(context) = source.context.clone() {
 249            self.set_key_context(context);
 250        }
 251        if let Some(focus_id) = source.focus_id {
 252            self.set_focus_id(focus_id);
 253        }
 254        if let Some(view_id) = source.view_id {
 255            self.set_view_id(view_id);
 256        }
 257
 258        let target = self.active_node();
 259        target.key_listeners = mem::take(&mut source.key_listeners);
 260        target.action_listeners = mem::take(&mut source.action_listeners);
 261        target.modifiers_changed_listeners = mem::take(&mut source.modifiers_changed_listeners);
 262    }
 263
 264    pub fn reuse_subtree(
 265        &mut self,
 266        old_range: Range<usize>,
 267        source: &mut Self,
 268        focus: Option<FocusId>,
 269    ) -> ReusedSubtree {
 270        let new_range = self.nodes.len()..self.nodes.len() + old_range.len();
 271
 272        let mut contains_focus = false;
 273        let mut source_stack = vec![];
 274        for (source_node_id, source_node) in source
 275            .nodes
 276            .iter_mut()
 277            .enumerate()
 278            .skip(old_range.start)
 279            .take(old_range.len())
 280        {
 281            let source_node_id = DispatchNodeId(source_node_id);
 282            while let Some(source_ancestor) = source_stack.last() {
 283                if source_node.parent == Some(*source_ancestor) {
 284                    break;
 285                } else {
 286                    source_stack.pop();
 287                    self.pop_node();
 288                }
 289            }
 290
 291            source_stack.push(source_node_id);
 292            if source_node.focus_id.is_some() && source_node.focus_id == focus {
 293                contains_focus = true;
 294            }
 295            self.move_node(source_node);
 296        }
 297
 298        while !source_stack.is_empty() {
 299            source_stack.pop();
 300            self.pop_node();
 301        }
 302
 303        ReusedSubtree {
 304            old_range,
 305            new_range,
 306            contains_focus,
 307        }
 308    }
 309
 310    pub fn truncate(&mut self, index: usize) {
 311        for node in &self.nodes[index..] {
 312            if let Some(focus_id) = node.focus_id {
 313                self.focusable_node_ids.remove(&focus_id);
 314            }
 315
 316            if let Some(view_id) = node.view_id {
 317                self.view_node_ids.remove(&view_id);
 318            }
 319        }
 320        self.nodes.truncate(index);
 321    }
 322
 323    pub fn on_key_event(&mut self, listener: KeyListener) {
 324        self.active_node().key_listeners.push(listener);
 325    }
 326
 327    pub fn on_modifiers_changed(&mut self, listener: ModifiersChangedListener) {
 328        self.active_node()
 329            .modifiers_changed_listeners
 330            .push(listener);
 331    }
 332
 333    pub fn on_action(
 334        &mut self,
 335        action_type: TypeId,
 336        listener: Rc<dyn Fn(&dyn Any, DispatchPhase, &mut Window, &mut App)>,
 337    ) {
 338        self.active_node()
 339            .action_listeners
 340            .push(DispatchActionListener {
 341                action_type,
 342                listener,
 343            });
 344    }
 345
 346    pub fn focus_contains(&self, parent: FocusId, child: FocusId) -> bool {
 347        if parent == child {
 348            return true;
 349        }
 350
 351        if let Some(parent_node_id) = self.focusable_node_ids.get(&parent) {
 352            let mut current_node_id = self.focusable_node_ids.get(&child).copied();
 353            while let Some(node_id) = current_node_id {
 354                if node_id == *parent_node_id {
 355                    return true;
 356                }
 357                current_node_id = self.nodes[node_id.0].parent;
 358            }
 359        }
 360        false
 361    }
 362
 363    pub fn available_actions(&self, target: DispatchNodeId) -> Vec<Box<dyn Action>> {
 364        let mut actions = Vec::<Box<dyn Action>>::new();
 365        for node_id in self.dispatch_path(target) {
 366            let node = &self.nodes[node_id.0];
 367            for DispatchActionListener { action_type, .. } in &node.action_listeners {
 368                if let Err(ix) = actions.binary_search_by_key(action_type, |a| a.as_any().type_id())
 369                {
 370                    // Intentionally silence these errors without logging.
 371                    // If an action cannot be built by default, it's not available.
 372                    let action = self.action_registry.build_action_type(action_type).ok();
 373                    if let Some(action) = action {
 374                        actions.insert(ix, action);
 375                    }
 376                }
 377            }
 378        }
 379        actions
 380    }
 381
 382    pub fn is_action_available(&self, action: &dyn Action, target: DispatchNodeId) -> bool {
 383        for node_id in self.dispatch_path(target) {
 384            let node = &self.nodes[node_id.0];
 385            if node
 386                .action_listeners
 387                .iter()
 388                .any(|listener| listener.action_type == action.as_any().type_id())
 389            {
 390                return true;
 391            }
 392        }
 393        false
 394    }
 395
 396    /// Returns key bindings that invoke an action on the currently focused element. Bindings are
 397    /// returned in the order they were added. For display, the last binding should take precedence.
 398    ///
 399    /// Bindings are only included if they are the highest precedence match for their keystrokes, so
 400    /// shadowed bindings are not included.
 401    pub fn bindings_for_action(
 402        &self,
 403        action: &dyn Action,
 404        context_stack: &[KeyContext],
 405    ) -> Vec<KeyBinding> {
 406        // Ideally this would return a `DoubleEndedIterator` to avoid `highest_precedence_*`
 407        // methods, but this can't be done very cleanly since keymap must be borrowed.
 408        let keymap = self.keymap.borrow();
 409        keymap
 410            .bindings_for_action(action)
 411            .filter(|binding| {
 412                Self::binding_matches_predicate_and_not_shadowed(&keymap, binding, context_stack)
 413            })
 414            .cloned()
 415            .collect()
 416    }
 417
 418    /// Returns the highest precedence binding for the given action and context stack. This is the
 419    /// same as the last result of `bindings_for_action`, but more efficient than getting all bindings.
 420    pub fn highest_precedence_binding_for_action(
 421        &self,
 422        action: &dyn Action,
 423        context_stack: &[KeyContext],
 424    ) -> Option<KeyBinding> {
 425        let keymap = self.keymap.borrow();
 426        keymap
 427            .bindings_for_action(action)
 428            .rev()
 429            .find(|binding| {
 430                Self::binding_matches_predicate_and_not_shadowed(&keymap, binding, context_stack)
 431            })
 432            .cloned()
 433    }
 434
 435    fn binding_matches_predicate_and_not_shadowed(
 436        keymap: &Keymap,
 437        binding: &KeyBinding,
 438        context_stack: &[KeyContext],
 439    ) -> bool {
 440        let (bindings, _) = keymap.bindings_for_input(&binding.keystrokes, context_stack);
 441        if let Some(found) = bindings.iter().next() {
 442            found.action.partial_eq(binding.action.as_ref())
 443        } else {
 444            false
 445        }
 446    }
 447
 448    fn bindings_for_input(
 449        &self,
 450        input: &[Keystroke],
 451        dispatch_path: &SmallVec<[DispatchNodeId; 32]>,
 452    ) -> (SmallVec<[KeyBinding; 1]>, bool, Vec<KeyContext>) {
 453        let context_stack: Vec<KeyContext> = dispatch_path
 454            .iter()
 455            .filter_map(|node_id| self.node(*node_id).context.clone())
 456            .collect();
 457
 458        let (bindings, partial) = self
 459            .keymap
 460            .borrow()
 461            .bindings_for_input(input, &context_stack);
 462        (bindings, partial, context_stack)
 463    }
 464
 465    /// Find the bindings that can follow the current input sequence.
 466    pub fn possible_next_bindings_for_input(
 467        &self,
 468        input: &[Keystroke],
 469        context_stack: &[KeyContext],
 470    ) -> Vec<KeyBinding> {
 471        self.keymap
 472            .borrow()
 473            .possible_next_bindings_for_input(input, context_stack)
 474    }
 475
 476    /// dispatch_key processes the keystroke
 477    /// input should be set to the value of `pending` from the previous call to dispatch_key.
 478    /// This returns three instructions to the input handler:
 479    /// - bindings: any bindings to execute before processing this keystroke
 480    /// - pending: the new set of pending keystrokes to store
 481    /// - to_replay: any keystroke that had been pushed to pending, but are no-longer matched,
 482    ///   these should be replayed first.
 483    pub fn dispatch_key(
 484        &mut self,
 485        mut input: SmallVec<[Keystroke; 1]>,
 486        keystroke: Keystroke,
 487        dispatch_path: &SmallVec<[DispatchNodeId; 32]>,
 488    ) -> DispatchResult {
 489        input.push(keystroke.clone());
 490        let (bindings, pending, context_stack) = self.bindings_for_input(&input, dispatch_path);
 491
 492        if pending {
 493            return DispatchResult {
 494                pending: input,
 495                pending_has_binding: !bindings.is_empty(),
 496                context_stack,
 497                ..Default::default()
 498            };
 499        } else if !bindings.is_empty() {
 500            return DispatchResult {
 501                bindings,
 502                context_stack,
 503                ..Default::default()
 504            };
 505        } else if input.len() == 1 {
 506            return DispatchResult {
 507                context_stack,
 508                ..Default::default()
 509            };
 510        }
 511        input.pop();
 512
 513        let (suffix, mut to_replay) = self.replay_prefix(input, dispatch_path);
 514
 515        let mut result = self.dispatch_key(suffix, keystroke, dispatch_path);
 516        to_replay.extend(result.to_replay);
 517        result.to_replay = to_replay;
 518        result
 519    }
 520
 521    /// If the user types a matching prefix of a binding and then waits for a timeout
 522    /// flush_dispatch() converts any previously pending input to replay events.
 523    pub fn flush_dispatch(
 524        &mut self,
 525        input: SmallVec<[Keystroke; 1]>,
 526        dispatch_path: &SmallVec<[DispatchNodeId; 32]>,
 527    ) -> SmallVec<[Replay; 1]> {
 528        let (suffix, mut to_replay) = self.replay_prefix(input, dispatch_path);
 529
 530        if !suffix.is_empty() {
 531            to_replay.extend(self.flush_dispatch(suffix, dispatch_path))
 532        }
 533
 534        to_replay
 535    }
 536
 537    /// Converts the longest prefix of input to a replay event and returns the rest.
 538    fn replay_prefix(
 539        &self,
 540        mut input: SmallVec<[Keystroke; 1]>,
 541        dispatch_path: &SmallVec<[DispatchNodeId; 32]>,
 542    ) -> (SmallVec<[Keystroke; 1]>, SmallVec<[Replay; 1]>) {
 543        let mut to_replay: SmallVec<[Replay; 1]> = Default::default();
 544        for last in (0..input.len()).rev() {
 545            let (bindings, _, _) = self.bindings_for_input(&input[0..=last], dispatch_path);
 546            if !bindings.is_empty() {
 547                to_replay.push(Replay {
 548                    keystroke: input.drain(0..=last).next_back().unwrap(),
 549                    bindings,
 550                });
 551                break;
 552            }
 553        }
 554        if to_replay.is_empty() {
 555            to_replay.push(Replay {
 556                keystroke: input.remove(0),
 557                ..Default::default()
 558            });
 559        }
 560        (input, to_replay)
 561    }
 562
 563    pub fn dispatch_path(&self, target: DispatchNodeId) -> SmallVec<[DispatchNodeId; 32]> {
 564        let mut dispatch_path: SmallVec<[DispatchNodeId; 32]> = SmallVec::new();
 565        let mut current_node_id = Some(target);
 566        while let Some(node_id) = current_node_id {
 567            dispatch_path.push(node_id);
 568            current_node_id = self.nodes.get(node_id.0).and_then(|node| node.parent);
 569        }
 570        dispatch_path.reverse(); // Reverse the path so it goes from the root to the focused node.
 571        dispatch_path
 572    }
 573
 574    pub fn focus_path(&self, focus_id: FocusId) -> SmallVec<[FocusId; 8]> {
 575        let mut focus_path: SmallVec<[FocusId; 8]> = SmallVec::new();
 576        let mut current_node_id = self.focusable_node_ids.get(&focus_id).copied();
 577        while let Some(node_id) = current_node_id {
 578            let node = self.node(node_id);
 579            if let Some(focus_id) = node.focus_id {
 580                focus_path.push(focus_id);
 581            }
 582            current_node_id = node.parent;
 583        }
 584        focus_path.reverse(); // Reverse the path so it goes from the root to the focused node.
 585        focus_path
 586    }
 587
 588    pub fn view_path_reversed(&self, view_id: EntityId) -> impl Iterator<Item = EntityId> {
 589        let mut current_node_id = self.view_node_ids.get(&view_id).copied();
 590
 591        std::iter::successors(
 592            current_node_id.map(|node_id| self.node(node_id)),
 593            |node_id| Some(self.node(node_id.parent?)),
 594        )
 595        .filter_map(|node| node.view_id)
 596    }
 597
 598    pub fn node(&self, node_id: DispatchNodeId) -> &DispatchNode {
 599        &self.nodes[node_id.0]
 600    }
 601
 602    fn active_node(&mut self) -> &mut DispatchNode {
 603        let active_node_id = self.active_node_id().unwrap();
 604        &mut self.nodes[active_node_id.0]
 605    }
 606
 607    pub fn focusable_node_id(&self, target: FocusId) -> Option<DispatchNodeId> {
 608        self.focusable_node_ids.get(&target).copied()
 609    }
 610
 611    pub fn root_node_id(&self) -> DispatchNodeId {
 612        debug_assert!(!self.nodes.is_empty());
 613        DispatchNodeId(0)
 614    }
 615
 616    pub fn active_node_id(&self) -> Option<DispatchNodeId> {
 617        self.node_stack.last().copied()
 618    }
 619}
 620
 621#[cfg(test)]
 622mod tests {
 623    use crate::{
 624        self as gpui, AppContext, DispatchResult, Element, ElementId, GlobalElementId,
 625        InspectorElementId, Keystroke, LayoutId, Style,
 626    };
 627    use core::panic;
 628    use smallvec::SmallVec;
 629    use std::{cell::RefCell, ops::Range, rc::Rc};
 630
 631    use crate::{
 632        Action, ActionRegistry, App, Bounds, Context, DispatchTree, FocusHandle, InputHandler,
 633        IntoElement, KeyBinding, KeyContext, Keymap, Pixels, Point, Render, Subscription,
 634        TestAppContext, UTF16Selection, Window,
 635    };
 636
 637    #[derive(PartialEq, Eq)]
 638    struct TestAction;
 639
 640    impl Action for TestAction {
 641        fn name(&self) -> &'static str {
 642            "test::TestAction"
 643        }
 644
 645        fn name_for_type() -> &'static str
 646        where
 647            Self: ::std::marker::Sized,
 648        {
 649            "test::TestAction"
 650        }
 651
 652        fn partial_eq(&self, action: &dyn Action) -> bool {
 653            action.as_any().downcast_ref::<Self>() == Some(self)
 654        }
 655
 656        fn boxed_clone(&self) -> std::boxed::Box<dyn Action> {
 657            Box::new(TestAction)
 658        }
 659
 660        fn build(_value: serde_json::Value) -> anyhow::Result<Box<dyn Action>>
 661        where
 662            Self: Sized,
 663        {
 664            Ok(Box::new(TestAction))
 665        }
 666    }
 667
 668    #[test]
 669    fn test_keybinding_for_action_bounds() {
 670        let keymap = Keymap::new(vec![KeyBinding::new(
 671            "cmd-n",
 672            TestAction,
 673            Some("ProjectPanel"),
 674        )]);
 675
 676        let mut registry = ActionRegistry::default();
 677
 678        registry.load_action::<TestAction>();
 679
 680        let keymap = Rc::new(RefCell::new(keymap));
 681
 682        let tree = DispatchTree::new(keymap, Rc::new(registry));
 683
 684        let contexts = vec![
 685            KeyContext::parse("Workspace").unwrap(),
 686            KeyContext::parse("ProjectPanel").unwrap(),
 687        ];
 688
 689        let keybinding = tree.bindings_for_action(&TestAction, &contexts);
 690
 691        assert!(keybinding[0].action.partial_eq(&TestAction))
 692    }
 693
 694    #[test]
 695    fn test_pending_has_binding_state() {
 696        let bindings = vec![
 697            KeyBinding::new("ctrl-b h", TestAction, None),
 698            KeyBinding::new("space", TestAction, Some("ContextA")),
 699            KeyBinding::new("space f g", TestAction, Some("ContextB")),
 700        ];
 701        let keymap = Rc::new(RefCell::new(Keymap::new(bindings)));
 702        let mut registry = ActionRegistry::default();
 703        registry.load_action::<TestAction>();
 704        let mut tree = DispatchTree::new(keymap, Rc::new(registry));
 705
 706        type DispatchPath = SmallVec<[super::DispatchNodeId; 32]>;
 707        fn dispatch(
 708            tree: &mut DispatchTree,
 709            pending: SmallVec<[Keystroke; 1]>,
 710            key: &str,
 711            path: &DispatchPath,
 712        ) -> DispatchResult {
 713            tree.dispatch_key(pending, Keystroke::parse(key).unwrap(), path)
 714        }
 715
 716        let dispatch_path: DispatchPath = SmallVec::new();
 717        let result = dispatch(&mut tree, SmallVec::new(), "ctrl-b", &dispatch_path);
 718        assert_eq!(result.pending.len(), 1);
 719        assert!(!result.pending_has_binding);
 720
 721        let result = dispatch(&mut tree, result.pending, "h", &dispatch_path);
 722        assert_eq!(result.pending.len(), 0);
 723        assert_eq!(result.bindings.len(), 1);
 724        assert!(!result.pending_has_binding);
 725
 726        let node_id = tree.push_node();
 727        tree.set_key_context(KeyContext::parse("ContextB").unwrap());
 728        tree.pop_node();
 729
 730        let dispatch_path = tree.dispatch_path(node_id);
 731        let result = dispatch(&mut tree, SmallVec::new(), "space", &dispatch_path);
 732
 733        assert_eq!(result.pending.len(), 1);
 734        assert!(!result.pending_has_binding);
 735    }
 736
 737    #[crate::test]
 738    fn test_pending_input_observers_notified_on_focus_change(cx: &mut TestAppContext) {
 739        #[derive(Clone)]
 740        struct CustomElement {
 741            focus_handle: FocusHandle,
 742            text: Rc<RefCell<String>>,
 743        }
 744
 745        impl CustomElement {
 746            fn new(cx: &mut Context<Self>) -> Self {
 747                Self {
 748                    focus_handle: cx.focus_handle(),
 749                    text: Rc::default(),
 750                }
 751            }
 752        }
 753
 754        impl Element for CustomElement {
 755            type RequestLayoutState = ();
 756
 757            type PrepaintState = ();
 758
 759            fn id(&self) -> Option<ElementId> {
 760                Some("custom".into())
 761            }
 762
 763            fn source_location(&self) -> Option<&'static panic::Location<'static>> {
 764                None
 765            }
 766
 767            fn request_layout(
 768                &mut self,
 769                _: Option<&GlobalElementId>,
 770                _: Option<&InspectorElementId>,
 771                window: &mut Window,
 772                cx: &mut App,
 773            ) -> (LayoutId, Self::RequestLayoutState) {
 774                (window.request_layout(Style::default(), [], cx), ())
 775            }
 776
 777            fn prepaint(
 778                &mut self,
 779                _: Option<&GlobalElementId>,
 780                _: Option<&InspectorElementId>,
 781                _: Bounds<Pixels>,
 782                _: &mut Self::RequestLayoutState,
 783                window: &mut Window,
 784                cx: &mut App,
 785            ) -> Self::PrepaintState {
 786                window.set_focus_handle(&self.focus_handle, cx);
 787            }
 788
 789            fn paint(
 790                &mut self,
 791                _: Option<&GlobalElementId>,
 792                _: Option<&InspectorElementId>,
 793                _: Bounds<Pixels>,
 794                _: &mut Self::RequestLayoutState,
 795                _: &mut Self::PrepaintState,
 796                window: &mut Window,
 797                cx: &mut App,
 798            ) {
 799                let mut key_context = KeyContext::default();
 800                key_context.add("Terminal");
 801                window.set_key_context(key_context);
 802                window.handle_input(&self.focus_handle, self.clone(), cx);
 803                window.on_action(std::any::TypeId::of::<TestAction>(), |_, _, _, _| {});
 804            }
 805        }
 806
 807        impl IntoElement for CustomElement {
 808            type Element = Self;
 809
 810            fn into_element(self) -> Self::Element {
 811                self
 812            }
 813        }
 814
 815        impl InputHandler for CustomElement {
 816            fn selected_text_range(
 817                &mut self,
 818                _: bool,
 819                _: &mut Window,
 820                _: &mut App,
 821            ) -> Option<UTF16Selection> {
 822                None
 823            }
 824
 825            fn marked_text_range(&mut self, _: &mut Window, _: &mut App) -> Option<Range<usize>> {
 826                None
 827            }
 828
 829            fn text_for_range(
 830                &mut self,
 831                _: Range<usize>,
 832                _: &mut Option<Range<usize>>,
 833                _: &mut Window,
 834                _: &mut App,
 835            ) -> Option<String> {
 836                None
 837            }
 838
 839            fn replace_text_in_range(
 840                &mut self,
 841                replacement_range: Option<Range<usize>>,
 842                text: &str,
 843                _: &mut Window,
 844                _: &mut App,
 845            ) {
 846                if replacement_range.is_some() {
 847                    unimplemented!()
 848                }
 849                self.text.borrow_mut().push_str(text)
 850            }
 851
 852            fn replace_and_mark_text_in_range(
 853                &mut self,
 854                replacement_range: Option<Range<usize>>,
 855                new_text: &str,
 856                _: Option<Range<usize>>,
 857                _: &mut Window,
 858                _: &mut App,
 859            ) {
 860                if replacement_range.is_some() {
 861                    unimplemented!()
 862                }
 863                self.text.borrow_mut().push_str(new_text)
 864            }
 865
 866            fn unmark_text(&mut self, _: &mut Window, _: &mut App) {}
 867
 868            fn bounds_for_range(
 869                &mut self,
 870                _: Range<usize>,
 871                _: &mut Window,
 872                _: &mut App,
 873            ) -> Option<Bounds<Pixels>> {
 874                None
 875            }
 876
 877            fn character_index_for_point(
 878                &mut self,
 879                _: Point<Pixels>,
 880                _: &mut Window,
 881                _: &mut App,
 882            ) -> Option<usize> {
 883                None
 884            }
 885        }
 886
 887        impl Render for CustomElement {
 888            fn render(&mut self, _: &mut Window, _: &mut Context<Self>) -> impl IntoElement {
 889                self.clone()
 890            }
 891        }
 892
 893        cx.update(|cx| {
 894            cx.bind_keys([KeyBinding::new("ctrl-b", TestAction, Some("Terminal"))]);
 895            cx.bind_keys([KeyBinding::new("ctrl-b h", TestAction, Some("Terminal"))]);
 896        });
 897
 898        let (test, cx) = cx.add_window_view(|_, cx| CustomElement::new(cx));
 899        let focus_handle = test.update(cx, |test, _| test.focus_handle.clone());
 900
 901        let pending_input_changed_count = Rc::new(RefCell::new(0usize));
 902        let pending_input_changed_count_for_observer = pending_input_changed_count.clone();
 903
 904        struct PendingInputObserver {
 905            _subscription: Subscription,
 906        }
 907
 908        let _observer = cx.update(|window, cx| {
 909            cx.new(|cx| PendingInputObserver {
 910                _subscription: cx.observe_pending_input(window, move |_, _, _| {
 911                    *pending_input_changed_count_for_observer.borrow_mut() += 1;
 912                }),
 913            })
 914        });
 915
 916        cx.update(|window, cx| {
 917            window.focus(&focus_handle, cx);
 918            window.activate_window();
 919        });
 920
 921        cx.simulate_keystrokes("ctrl-b");
 922
 923        let count_after_pending = Rc::new(RefCell::new(0usize));
 924        let count_after_pending_for_assertion = count_after_pending.clone();
 925
 926        cx.update(|window, cx| {
 927            assert!(window.has_pending_keystrokes());
 928            *count_after_pending.borrow_mut() = *pending_input_changed_count.borrow();
 929            assert!(*count_after_pending.borrow() > 0);
 930
 931            window.focus(&cx.focus_handle(), cx);
 932
 933            assert!(!window.has_pending_keystrokes());
 934        });
 935
 936        // Focus-triggered pending-input notifications are deferred to the end of the current
 937        // effect cycle, so the observer callback should run after the focus update completes.
 938        cx.update(|_, _| {
 939            let count_after_focus_change = *pending_input_changed_count.borrow();
 940            assert!(count_after_focus_change > *count_after_pending_for_assertion.borrow());
 941        });
 942    }
 943
 944    #[crate::test]
 945    fn test_input_handler_pending(cx: &mut TestAppContext) {
 946        #[derive(Clone)]
 947        struct CustomElement {
 948            focus_handle: FocusHandle,
 949            text: Rc<RefCell<String>>,
 950        }
 951        impl CustomElement {
 952            fn new(cx: &mut Context<Self>) -> Self {
 953                Self {
 954                    focus_handle: cx.focus_handle(),
 955                    text: Rc::default(),
 956                }
 957            }
 958        }
 959        impl Element for CustomElement {
 960            type RequestLayoutState = ();
 961
 962            type PrepaintState = ();
 963
 964            fn id(&self) -> Option<ElementId> {
 965                Some("custom".into())
 966            }
 967            fn source_location(&self) -> Option<&'static panic::Location<'static>> {
 968                None
 969            }
 970            fn request_layout(
 971                &mut self,
 972                _: Option<&GlobalElementId>,
 973                _: Option<&InspectorElementId>,
 974                window: &mut Window,
 975                cx: &mut App,
 976            ) -> (LayoutId, Self::RequestLayoutState) {
 977                (window.request_layout(Style::default(), [], cx), ())
 978            }
 979            fn prepaint(
 980                &mut self,
 981                _: Option<&GlobalElementId>,
 982                _: Option<&InspectorElementId>,
 983                _: Bounds<Pixels>,
 984                _: &mut Self::RequestLayoutState,
 985                window: &mut Window,
 986                cx: &mut App,
 987            ) -> Self::PrepaintState {
 988                window.set_focus_handle(&self.focus_handle, cx);
 989            }
 990            fn paint(
 991                &mut self,
 992                _: Option<&GlobalElementId>,
 993                _: Option<&InspectorElementId>,
 994                _: Bounds<Pixels>,
 995                _: &mut Self::RequestLayoutState,
 996                _: &mut Self::PrepaintState,
 997                window: &mut Window,
 998                cx: &mut App,
 999            ) {
1000                let mut key_context = KeyContext::default();
1001                key_context.add("Terminal");
1002                window.set_key_context(key_context);
1003                window.handle_input(&self.focus_handle, self.clone(), cx);
1004                window.on_action(std::any::TypeId::of::<TestAction>(), |_, _, _, _| {});
1005            }
1006        }
1007        impl IntoElement for CustomElement {
1008            type Element = Self;
1009
1010            fn into_element(self) -> Self::Element {
1011                self
1012            }
1013        }
1014
1015        impl InputHandler for CustomElement {
1016            fn selected_text_range(
1017                &mut self,
1018                _: bool,
1019                _: &mut Window,
1020                _: &mut App,
1021            ) -> Option<UTF16Selection> {
1022                None
1023            }
1024
1025            fn marked_text_range(&mut self, _: &mut Window, _: &mut App) -> Option<Range<usize>> {
1026                None
1027            }
1028
1029            fn text_for_range(
1030                &mut self,
1031                _: Range<usize>,
1032                _: &mut Option<Range<usize>>,
1033                _: &mut Window,
1034                _: &mut App,
1035            ) -> Option<String> {
1036                None
1037            }
1038
1039            fn replace_text_in_range(
1040                &mut self,
1041                replacement_range: Option<Range<usize>>,
1042                text: &str,
1043                _: &mut Window,
1044                _: &mut App,
1045            ) {
1046                if replacement_range.is_some() {
1047                    unimplemented!()
1048                }
1049                self.text.borrow_mut().push_str(text)
1050            }
1051
1052            fn replace_and_mark_text_in_range(
1053                &mut self,
1054                replacement_range: Option<Range<usize>>,
1055                new_text: &str,
1056                _: Option<Range<usize>>,
1057                _: &mut Window,
1058                _: &mut App,
1059            ) {
1060                if replacement_range.is_some() {
1061                    unimplemented!()
1062                }
1063                self.text.borrow_mut().push_str(new_text)
1064            }
1065
1066            fn unmark_text(&mut self, _: &mut Window, _: &mut App) {}
1067
1068            fn bounds_for_range(
1069                &mut self,
1070                _: Range<usize>,
1071                _: &mut Window,
1072                _: &mut App,
1073            ) -> Option<Bounds<Pixels>> {
1074                None
1075            }
1076
1077            fn character_index_for_point(
1078                &mut self,
1079                _: Point<Pixels>,
1080                _: &mut Window,
1081                _: &mut App,
1082            ) -> Option<usize> {
1083                None
1084            }
1085        }
1086        impl Render for CustomElement {
1087            fn render(&mut self, _: &mut Window, _: &mut Context<Self>) -> impl IntoElement {
1088                self.clone()
1089            }
1090        }
1091
1092        cx.update(|cx| {
1093            cx.bind_keys([KeyBinding::new("ctrl-b", TestAction, Some("Terminal"))]);
1094            cx.bind_keys([KeyBinding::new("ctrl-b h", TestAction, Some("Terminal"))]);
1095        });
1096        let (test, cx) = cx.add_window_view(|_, cx| CustomElement::new(cx));
1097        let focus_handle = test.update(cx, |test, _| test.focus_handle.clone());
1098        cx.update(|window, cx| {
1099            window.focus(&focus_handle, cx);
1100            window.activate_window();
1101        });
1102        cx.simulate_keystrokes("ctrl-b [");
1103        test.update(cx, |test, _| assert_eq!(test.text.borrow().as_str(), "["))
1104    }
1105}