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        has_pending_keystrokes: bool,
 453    ) -> (SmallVec<[KeyBinding; 1]>, bool, Vec<KeyContext>) {
 454        let mut context_stack: Vec<KeyContext> = dispatch_path
 455            .iter()
 456            .filter_map(|node_id| self.node(*node_id).context.clone())
 457            .collect();
 458
 459        if has_pending_keystrokes {
 460            let mut pending_context = KeyContext::default();
 461            pending_context.add("pending");
 462            context_stack.push(pending_context);
 463        }
 464
 465        let (bindings, partial) = self
 466            .keymap
 467            .borrow()
 468            .bindings_for_input(input, &context_stack);
 469        (bindings, partial, context_stack)
 470    }
 471
 472    /// Find the bindings that can follow the current input sequence.
 473    pub fn possible_next_bindings_for_input(
 474        &self,
 475        input: &[Keystroke],
 476        context_stack: &[KeyContext],
 477    ) -> Vec<KeyBinding> {
 478        self.keymap
 479            .borrow()
 480            .possible_next_bindings_for_input(input, context_stack)
 481    }
 482
 483    /// dispatch_key processes the keystroke
 484    /// input should be set to the value of `pending` from the previous call to dispatch_key.
 485    /// This returns three instructions to the input handler:
 486    /// - bindings: any bindings to execute before processing this keystroke
 487    /// - pending: the new set of pending keystrokes to store
 488    /// - to_replay: any keystroke that had been pushed to pending, but are no-longer matched,
 489    ///   these should be replayed first.
 490    pub fn dispatch_key(
 491        &mut self,
 492        mut input: SmallVec<[Keystroke; 1]>,
 493        keystroke: Keystroke,
 494        dispatch_path: &SmallVec<[DispatchNodeId; 32]>,
 495    ) -> DispatchResult {
 496        let has_pending_keystrokes = !input.is_empty();
 497        input.push(keystroke.clone());
 498        let (bindings, pending, context_stack) =
 499            self.bindings_for_input(&input, dispatch_path, has_pending_keystrokes);
 500
 501        if pending {
 502            return DispatchResult {
 503                pending: input,
 504                pending_has_binding: !bindings.is_empty(),
 505                context_stack,
 506                ..Default::default()
 507            };
 508        } else if !bindings.is_empty() {
 509            return DispatchResult {
 510                bindings,
 511                context_stack,
 512                ..Default::default()
 513            };
 514        } else if input.len() == 1 {
 515            return DispatchResult {
 516                context_stack,
 517                ..Default::default()
 518            };
 519        }
 520        input.pop();
 521
 522        let (suffix, mut to_replay) = self.replay_prefix(input, dispatch_path);
 523
 524        let mut result = self.dispatch_key(suffix, keystroke, dispatch_path);
 525        to_replay.extend(result.to_replay);
 526        result.to_replay = to_replay;
 527        result
 528    }
 529
 530    /// If the user types a matching prefix of a binding and then waits for a timeout
 531    /// flush_dispatch() converts any previously pending input to replay events.
 532    pub fn flush_dispatch(
 533        &mut self,
 534        input: SmallVec<[Keystroke; 1]>,
 535        dispatch_path: &SmallVec<[DispatchNodeId; 32]>,
 536    ) -> SmallVec<[Replay; 1]> {
 537        let (suffix, mut to_replay) = self.replay_prefix(input, dispatch_path);
 538
 539        if !suffix.is_empty() {
 540            to_replay.extend(self.flush_dispatch(suffix, dispatch_path))
 541        }
 542
 543        to_replay
 544    }
 545
 546    /// Converts the longest prefix of input to a replay event and returns the rest.
 547    fn replay_prefix(
 548        &self,
 549        mut input: SmallVec<[Keystroke; 1]>,
 550        dispatch_path: &SmallVec<[DispatchNodeId; 32]>,
 551    ) -> (SmallVec<[Keystroke; 1]>, SmallVec<[Replay; 1]>) {
 552        let mut to_replay: SmallVec<[Replay; 1]> = Default::default();
 553        for last in (0..input.len()).rev() {
 554            let (bindings, _, _) = self.bindings_for_input(&input[0..=last], dispatch_path, false);
 555            if !bindings.is_empty() {
 556                to_replay.push(Replay {
 557                    keystroke: input.drain(0..=last).next_back().unwrap(),
 558                    bindings,
 559                });
 560                break;
 561            }
 562        }
 563        if to_replay.is_empty() {
 564            to_replay.push(Replay {
 565                keystroke: input.remove(0),
 566                ..Default::default()
 567            });
 568        }
 569        (input, to_replay)
 570    }
 571
 572    pub fn dispatch_path(&self, target: DispatchNodeId) -> SmallVec<[DispatchNodeId; 32]> {
 573        let mut dispatch_path: SmallVec<[DispatchNodeId; 32]> = SmallVec::new();
 574        let mut current_node_id = Some(target);
 575        while let Some(node_id) = current_node_id {
 576            dispatch_path.push(node_id);
 577            current_node_id = self.nodes.get(node_id.0).and_then(|node| node.parent);
 578        }
 579        dispatch_path.reverse(); // Reverse the path so it goes from the root to the focused node.
 580        dispatch_path
 581    }
 582
 583    pub fn focus_path(&self, focus_id: FocusId) -> SmallVec<[FocusId; 8]> {
 584        let mut focus_path: SmallVec<[FocusId; 8]> = SmallVec::new();
 585        let mut current_node_id = self.focusable_node_ids.get(&focus_id).copied();
 586        while let Some(node_id) = current_node_id {
 587            let node = self.node(node_id);
 588            if let Some(focus_id) = node.focus_id {
 589                focus_path.push(focus_id);
 590            }
 591            current_node_id = node.parent;
 592        }
 593        focus_path.reverse(); // Reverse the path so it goes from the root to the focused node.
 594        focus_path
 595    }
 596
 597    pub fn view_path_reversed(&self, view_id: EntityId) -> impl Iterator<Item = EntityId> {
 598        let mut current_node_id = self.view_node_ids.get(&view_id).copied();
 599
 600        std::iter::successors(
 601            current_node_id.map(|node_id| self.node(node_id)),
 602            |node_id| Some(self.node(node_id.parent?)),
 603        )
 604        .filter_map(|node| node.view_id)
 605    }
 606
 607    pub fn node(&self, node_id: DispatchNodeId) -> &DispatchNode {
 608        &self.nodes[node_id.0]
 609    }
 610
 611    fn active_node(&mut self) -> &mut DispatchNode {
 612        let active_node_id = self.active_node_id().unwrap();
 613        &mut self.nodes[active_node_id.0]
 614    }
 615
 616    pub fn focusable_node_id(&self, target: FocusId) -> Option<DispatchNodeId> {
 617        self.focusable_node_ids.get(&target).copied()
 618    }
 619
 620    pub fn root_node_id(&self) -> DispatchNodeId {
 621        debug_assert!(!self.nodes.is_empty());
 622        DispatchNodeId(0)
 623    }
 624
 625    pub fn active_node_id(&self) -> Option<DispatchNodeId> {
 626        self.node_stack.last().copied()
 627    }
 628}
 629
 630#[cfg(test)]
 631mod tests {
 632    use crate::{
 633        self as gpui, AppContext, DispatchResult, Element, ElementId, GlobalElementId,
 634        InspectorElementId, Keystroke, LayoutId, Style,
 635    };
 636    use core::panic;
 637    use smallvec::SmallVec;
 638    use std::{cell::RefCell, ops::Range, rc::Rc};
 639
 640    use crate::{
 641        Action, ActionRegistry, App, Bounds, Context, DispatchTree, FocusHandle, InputHandler,
 642        IntoElement, KeyBinding, KeyContext, Keymap, Pixels, Point, Render, Subscription,
 643        TestAppContext, UTF16Selection, Window,
 644    };
 645
 646    #[derive(PartialEq, Eq)]
 647    struct TestAction;
 648
 649    impl Action for TestAction {
 650        fn name(&self) -> &'static str {
 651            "test::TestAction"
 652        }
 653
 654        fn name_for_type() -> &'static str
 655        where
 656            Self: ::std::marker::Sized,
 657        {
 658            "test::TestAction"
 659        }
 660
 661        fn partial_eq(&self, action: &dyn Action) -> bool {
 662            action.as_any().downcast_ref::<Self>() == Some(self)
 663        }
 664
 665        fn boxed_clone(&self) -> std::boxed::Box<dyn Action> {
 666            Box::new(TestAction)
 667        }
 668
 669        fn build(_value: serde_json::Value) -> anyhow::Result<Box<dyn Action>>
 670        where
 671            Self: Sized,
 672        {
 673            Ok(Box::new(TestAction))
 674        }
 675    }
 676
 677    #[test]
 678    fn test_keybinding_for_action_bounds() {
 679        let keymap = Keymap::new(vec![KeyBinding::new(
 680            "cmd-n",
 681            TestAction,
 682            Some("ProjectPanel"),
 683        )]);
 684
 685        let mut registry = ActionRegistry::default();
 686
 687        registry.load_action::<TestAction>();
 688
 689        let keymap = Rc::new(RefCell::new(keymap));
 690
 691        let tree = DispatchTree::new(keymap, Rc::new(registry));
 692
 693        let contexts = vec![
 694            KeyContext::parse("Workspace").unwrap(),
 695            KeyContext::parse("ProjectPanel").unwrap(),
 696        ];
 697
 698        let keybinding = tree.bindings_for_action(&TestAction, &contexts);
 699
 700        assert!(keybinding[0].action.partial_eq(&TestAction))
 701    }
 702
 703    #[test]
 704    fn test_pending_has_binding_state() {
 705        let bindings = vec![
 706            KeyBinding::new("ctrl-b h", TestAction, None),
 707            KeyBinding::new("space", TestAction, Some("ContextA")),
 708            KeyBinding::new("space f g", TestAction, Some("ContextB")),
 709        ];
 710        let keymap = Rc::new(RefCell::new(Keymap::new(bindings)));
 711        let mut registry = ActionRegistry::default();
 712        registry.load_action::<TestAction>();
 713        let mut tree = DispatchTree::new(keymap, Rc::new(registry));
 714
 715        type DispatchPath = SmallVec<[super::DispatchNodeId; 32]>;
 716        fn dispatch(
 717            tree: &mut DispatchTree,
 718            pending: SmallVec<[Keystroke; 1]>,
 719            key: &str,
 720            path: &DispatchPath,
 721        ) -> DispatchResult {
 722            tree.dispatch_key(pending, Keystroke::parse(key).unwrap(), path)
 723        }
 724
 725        let dispatch_path: DispatchPath = SmallVec::new();
 726        let result = dispatch(&mut tree, SmallVec::new(), "ctrl-b", &dispatch_path);
 727        assert_eq!(result.pending.len(), 1);
 728        assert!(!result.pending_has_binding);
 729
 730        let result = dispatch(&mut tree, result.pending, "h", &dispatch_path);
 731        assert_eq!(result.pending.len(), 0);
 732        assert_eq!(result.bindings.len(), 1);
 733        assert!(!result.pending_has_binding);
 734
 735        let node_id = tree.push_node();
 736        tree.set_key_context(KeyContext::parse("ContextB").unwrap());
 737        tree.pop_node();
 738
 739        let dispatch_path = tree.dispatch_path(node_id);
 740        let result = dispatch(&mut tree, SmallVec::new(), "space", &dispatch_path);
 741
 742        assert_eq!(result.pending.len(), 1);
 743        assert!(!result.pending_has_binding);
 744    }
 745
 746    #[crate::test]
 747    fn test_pending_input_observers_notified_on_focus_change(cx: &mut TestAppContext) {
 748        #[derive(Clone)]
 749        struct CustomElement {
 750            focus_handle: FocusHandle,
 751            text: Rc<RefCell<String>>,
 752        }
 753
 754        impl CustomElement {
 755            fn new(cx: &mut Context<Self>) -> Self {
 756                Self {
 757                    focus_handle: cx.focus_handle(),
 758                    text: Rc::default(),
 759                }
 760            }
 761        }
 762
 763        impl Element for CustomElement {
 764            type RequestLayoutState = ();
 765
 766            type PrepaintState = ();
 767
 768            fn id(&self) -> Option<ElementId> {
 769                Some("custom".into())
 770            }
 771
 772            fn source_location(&self) -> Option<&'static panic::Location<'static>> {
 773                None
 774            }
 775
 776            fn request_layout(
 777                &mut self,
 778                _: Option<&GlobalElementId>,
 779                _: Option<&InspectorElementId>,
 780                window: &mut Window,
 781                cx: &mut App,
 782            ) -> (LayoutId, Self::RequestLayoutState) {
 783                (window.request_layout(Style::default(), [], cx), ())
 784            }
 785
 786            fn prepaint(
 787                &mut self,
 788                _: Option<&GlobalElementId>,
 789                _: Option<&InspectorElementId>,
 790                _: Bounds<Pixels>,
 791                _: &mut Self::RequestLayoutState,
 792                window: &mut Window,
 793                cx: &mut App,
 794            ) -> Self::PrepaintState {
 795                window.set_focus_handle(&self.focus_handle, cx);
 796            }
 797
 798            fn paint(
 799                &mut self,
 800                _: Option<&GlobalElementId>,
 801                _: Option<&InspectorElementId>,
 802                _: Bounds<Pixels>,
 803                _: &mut Self::RequestLayoutState,
 804                _: &mut Self::PrepaintState,
 805                window: &mut Window,
 806                cx: &mut App,
 807            ) {
 808                let mut key_context = KeyContext::default();
 809                key_context.add("Terminal");
 810                window.set_key_context(key_context);
 811                window.handle_input(&self.focus_handle, self.clone(), cx);
 812                window.on_action(std::any::TypeId::of::<TestAction>(), |_, _, _, _| {});
 813            }
 814        }
 815
 816        impl IntoElement for CustomElement {
 817            type Element = Self;
 818
 819            fn into_element(self) -> Self::Element {
 820                self
 821            }
 822        }
 823
 824        impl InputHandler for CustomElement {
 825            fn selected_text_range(
 826                &mut self,
 827                _: bool,
 828                _: &mut Window,
 829                _: &mut App,
 830            ) -> Option<UTF16Selection> {
 831                None
 832            }
 833
 834            fn marked_text_range(&mut self, _: &mut Window, _: &mut App) -> Option<Range<usize>> {
 835                None
 836            }
 837
 838            fn text_for_range(
 839                &mut self,
 840                _: Range<usize>,
 841                _: &mut Option<Range<usize>>,
 842                _: &mut Window,
 843                _: &mut App,
 844            ) -> Option<String> {
 845                None
 846            }
 847
 848            fn replace_text_in_range(
 849                &mut self,
 850                replacement_range: Option<Range<usize>>,
 851                text: &str,
 852                _: &mut Window,
 853                _: &mut App,
 854            ) {
 855                if replacement_range.is_some() {
 856                    unimplemented!()
 857                }
 858                self.text.borrow_mut().push_str(text)
 859            }
 860
 861            fn replace_and_mark_text_in_range(
 862                &mut self,
 863                replacement_range: Option<Range<usize>>,
 864                new_text: &str,
 865                _: Option<Range<usize>>,
 866                _: &mut Window,
 867                _: &mut App,
 868            ) {
 869                if replacement_range.is_some() {
 870                    unimplemented!()
 871                }
 872                self.text.borrow_mut().push_str(new_text)
 873            }
 874
 875            fn unmark_text(&mut self, _: &mut Window, _: &mut App) {}
 876
 877            fn bounds_for_range(
 878                &mut self,
 879                _: Range<usize>,
 880                _: &mut Window,
 881                _: &mut App,
 882            ) -> Option<Bounds<Pixels>> {
 883                None
 884            }
 885
 886            fn character_index_for_point(
 887                &mut self,
 888                _: Point<Pixels>,
 889                _: &mut Window,
 890                _: &mut App,
 891            ) -> Option<usize> {
 892                None
 893            }
 894        }
 895
 896        impl Render for CustomElement {
 897            fn render(&mut self, _: &mut Window, _: &mut Context<Self>) -> impl IntoElement {
 898                self.clone()
 899            }
 900        }
 901
 902        cx.update(|cx| {
 903            cx.bind_keys([KeyBinding::new("ctrl-b", TestAction, Some("Terminal"))]);
 904            cx.bind_keys([KeyBinding::new("ctrl-b h", TestAction, Some("Terminal"))]);
 905        });
 906
 907        let (test, cx) = cx.add_window_view(|_, cx| CustomElement::new(cx));
 908        let focus_handle = test.update(cx, |test, _| test.focus_handle.clone());
 909
 910        let pending_input_changed_count = Rc::new(RefCell::new(0usize));
 911        let pending_input_changed_count_for_observer = pending_input_changed_count.clone();
 912
 913        struct PendingInputObserver {
 914            _subscription: Subscription,
 915        }
 916
 917        let _observer = cx.update(|window, cx| {
 918            cx.new(|cx| PendingInputObserver {
 919                _subscription: cx.observe_pending_input(window, move |_, _, _| {
 920                    *pending_input_changed_count_for_observer.borrow_mut() += 1;
 921                }),
 922            })
 923        });
 924
 925        cx.update(|window, cx| {
 926            window.focus(&focus_handle, cx);
 927            window.activate_window();
 928        });
 929
 930        cx.simulate_keystrokes("ctrl-b");
 931
 932        let count_after_pending = Rc::new(RefCell::new(0usize));
 933        let count_after_pending_for_assertion = count_after_pending.clone();
 934
 935        cx.update(|window, cx| {
 936            assert!(window.has_pending_keystrokes());
 937            *count_after_pending.borrow_mut() = *pending_input_changed_count.borrow();
 938            assert!(*count_after_pending.borrow() > 0);
 939
 940            window.focus(&cx.focus_handle(), cx);
 941
 942            assert!(!window.has_pending_keystrokes());
 943        });
 944
 945        // Focus-triggered pending-input notifications are deferred to the end of the current
 946        // effect cycle, so the observer callback should run after the focus update completes.
 947        cx.update(|_, _| {
 948            let count_after_focus_change = *pending_input_changed_count.borrow();
 949            assert!(count_after_focus_change > *count_after_pending_for_assertion.borrow());
 950        });
 951    }
 952
 953    #[crate::test]
 954    fn test_input_handler_pending(cx: &mut TestAppContext) {
 955        #[derive(Clone)]
 956        struct CustomElement {
 957            focus_handle: FocusHandle,
 958            text: Rc<RefCell<String>>,
 959        }
 960        impl CustomElement {
 961            fn new(cx: &mut Context<Self>) -> Self {
 962                Self {
 963                    focus_handle: cx.focus_handle(),
 964                    text: Rc::default(),
 965                }
 966            }
 967        }
 968        impl Element for CustomElement {
 969            type RequestLayoutState = ();
 970
 971            type PrepaintState = ();
 972
 973            fn id(&self) -> Option<ElementId> {
 974                Some("custom".into())
 975            }
 976            fn source_location(&self) -> Option<&'static panic::Location<'static>> {
 977                None
 978            }
 979            fn request_layout(
 980                &mut self,
 981                _: Option<&GlobalElementId>,
 982                _: Option<&InspectorElementId>,
 983                window: &mut Window,
 984                cx: &mut App,
 985            ) -> (LayoutId, Self::RequestLayoutState) {
 986                (window.request_layout(Style::default(), [], cx), ())
 987            }
 988            fn prepaint(
 989                &mut self,
 990                _: Option<&GlobalElementId>,
 991                _: Option<&InspectorElementId>,
 992                _: Bounds<Pixels>,
 993                _: &mut Self::RequestLayoutState,
 994                window: &mut Window,
 995                cx: &mut App,
 996            ) -> Self::PrepaintState {
 997                window.set_focus_handle(&self.focus_handle, cx);
 998            }
 999            fn paint(
1000                &mut self,
1001                _: Option<&GlobalElementId>,
1002                _: Option<&InspectorElementId>,
1003                _: Bounds<Pixels>,
1004                _: &mut Self::RequestLayoutState,
1005                _: &mut Self::PrepaintState,
1006                window: &mut Window,
1007                cx: &mut App,
1008            ) {
1009                let mut key_context = KeyContext::default();
1010                key_context.add("Terminal");
1011                window.set_key_context(key_context);
1012                window.handle_input(&self.focus_handle, self.clone(), cx);
1013                window.on_action(std::any::TypeId::of::<TestAction>(), |_, _, _, _| {});
1014            }
1015        }
1016        impl IntoElement for CustomElement {
1017            type Element = Self;
1018
1019            fn into_element(self) -> Self::Element {
1020                self
1021            }
1022        }
1023
1024        impl InputHandler for CustomElement {
1025            fn selected_text_range(
1026                &mut self,
1027                _: bool,
1028                _: &mut Window,
1029                _: &mut App,
1030            ) -> Option<UTF16Selection> {
1031                None
1032            }
1033
1034            fn marked_text_range(&mut self, _: &mut Window, _: &mut App) -> Option<Range<usize>> {
1035                None
1036            }
1037
1038            fn text_for_range(
1039                &mut self,
1040                _: Range<usize>,
1041                _: &mut Option<Range<usize>>,
1042                _: &mut Window,
1043                _: &mut App,
1044            ) -> Option<String> {
1045                None
1046            }
1047
1048            fn replace_text_in_range(
1049                &mut self,
1050                replacement_range: Option<Range<usize>>,
1051                text: &str,
1052                _: &mut Window,
1053                _: &mut App,
1054            ) {
1055                if replacement_range.is_some() {
1056                    unimplemented!()
1057                }
1058                self.text.borrow_mut().push_str(text)
1059            }
1060
1061            fn replace_and_mark_text_in_range(
1062                &mut self,
1063                replacement_range: Option<Range<usize>>,
1064                new_text: &str,
1065                _: Option<Range<usize>>,
1066                _: &mut Window,
1067                _: &mut App,
1068            ) {
1069                if replacement_range.is_some() {
1070                    unimplemented!()
1071                }
1072                self.text.borrow_mut().push_str(new_text)
1073            }
1074
1075            fn unmark_text(&mut self, _: &mut Window, _: &mut App) {}
1076
1077            fn bounds_for_range(
1078                &mut self,
1079                _: Range<usize>,
1080                _: &mut Window,
1081                _: &mut App,
1082            ) -> Option<Bounds<Pixels>> {
1083                None
1084            }
1085
1086            fn character_index_for_point(
1087                &mut self,
1088                _: Point<Pixels>,
1089                _: &mut Window,
1090                _: &mut App,
1091            ) -> Option<usize> {
1092                None
1093            }
1094        }
1095        impl Render for CustomElement {
1096            fn render(&mut self, _: &mut Window, _: &mut Context<Self>) -> impl IntoElement {
1097                self.clone()
1098            }
1099        }
1100
1101        cx.update(|cx| {
1102            cx.bind_keys([KeyBinding::new("ctrl-b", TestAction, Some("Terminal"))]);
1103            cx.bind_keys([KeyBinding::new("ctrl-b h", TestAction, Some("Terminal"))]);
1104        });
1105        let (test, cx) = cx.add_window_view(|_, cx| CustomElement::new(cx));
1106        let focus_handle = test.update(cx, |test, _| test.focus_handle.clone());
1107        cx.update(|window, cx| {
1108            window.focus(&focus_handle, cx);
1109            window.activate_window();
1110        });
1111        cx.simulate_keystrokes("ctrl-b [");
1112        test.update(cx, |test, _| assert_eq!(test.text.borrow().as_str(), "["))
1113    }
1114}