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