1use crate::{
2 build_action_from_type, Action, Bounds, DispatchPhase, Element, FocusEvent, FocusHandle,
3 FocusId, KeyContext, KeyDownEvent, KeyMatch, Keymap, KeystrokeMatcher, MouseDownEvent, Pixels,
4 Style, StyleRefinement, ViewContext, WindowContext,
5};
6use collections::HashMap;
7use parking_lot::Mutex;
8use refineable::Refineable;
9use smallvec::SmallVec;
10use std::{
11 any::{Any, TypeId},
12 sync::Arc,
13};
14use util::ResultExt;
15
16type KeyListener = Box<dyn Fn(&dyn Any, DispatchPhase, &mut WindowContext)>;
17pub type FocusListeners<V> = SmallVec<[FocusListener<V>; 2]>;
18pub type FocusListener<V> =
19 Box<dyn Fn(&mut V, &FocusHandle, &FocusEvent, &mut ViewContext<V>) + 'static>;
20
21#[derive(Clone, Copy, Debug, Eq, PartialEq, Hash)]
22pub struct DispatchNodeId(usize);
23
24pub struct KeyDispatcher {
25 node_stack: Vec<DispatchNodeId>,
26 context_stack: Vec<KeyContext>,
27 nodes: Vec<DispatchNode>,
28 focusable_node_ids: HashMap<FocusId, DispatchNodeId>,
29 keystroke_matchers: HashMap<SmallVec<[KeyContext; 4]>, KeystrokeMatcher>,
30 keymap: Arc<Mutex<Keymap>>,
31}
32
33#[derive(Default)]
34pub struct DispatchNode {
35 key_listeners: SmallVec<[KeyListener; 2]>,
36 action_listeners: SmallVec<[ActionListener; 16]>,
37 context: KeyContext,
38 parent: Option<DispatchNodeId>,
39}
40
41struct ActionListener {
42 action_type: TypeId,
43 listener: Box<dyn Fn(&dyn Any, DispatchPhase, &mut WindowContext)>,
44}
45
46impl KeyDispatcher {
47 pub fn new(keymap: Arc<Mutex<Keymap>>) -> Self {
48 Self {
49 node_stack: Vec::new(),
50 context_stack: Vec::new(),
51 nodes: Vec::new(),
52 focusable_node_ids: HashMap::default(),
53 keystroke_matchers: HashMap::default(),
54 keymap,
55 }
56 }
57
58 pub fn clear(&mut self) {
59 self.node_stack.clear();
60 self.nodes.clear();
61 }
62
63 pub fn push_node(&mut self, context: KeyContext, old_dispatcher: &mut Self) {
64 let parent = self.node_stack.last().copied();
65 let node_id = DispatchNodeId(self.nodes.len());
66 self.nodes.push(DispatchNode {
67 parent,
68 ..Default::default()
69 });
70 self.node_stack.push(node_id);
71 if !context.is_empty() {
72 self.context_stack.push(context);
73 if let Some((context_stack, matcher)) = old_dispatcher
74 .keystroke_matchers
75 .remove_entry(self.context_stack.as_slice())
76 {
77 self.keystroke_matchers.insert(context_stack, matcher);
78 }
79 }
80 }
81
82 pub fn pop_node(&mut self) {
83 let node_id = self.node_stack.pop().unwrap();
84 if !self.nodes[node_id.0].context.is_empty() {
85 self.context_stack.pop();
86 }
87 }
88
89 pub fn on_key_event(&mut self, listener: KeyListener) {
90 self.active_node().key_listeners.push(listener);
91 }
92
93 pub fn on_action(
94 &mut self,
95 action_type: TypeId,
96 listener: Box<dyn Fn(&dyn Any, DispatchPhase, &mut WindowContext)>,
97 ) {
98 self.active_node().action_listeners.push(ActionListener {
99 action_type,
100 listener,
101 });
102 }
103
104 pub fn make_focusable(&mut self, focus_id: FocusId) {
105 self.focusable_node_ids
106 .insert(focus_id, self.active_node_id());
107 }
108
109 pub fn focus_contains(&self, parent: FocusId, child: FocusId) -> bool {
110 if parent == child {
111 return true;
112 }
113
114 if let Some(parent_node_id) = self.focusable_node_ids.get(&parent) {
115 let mut current_node_id = self.focusable_node_ids.get(&child).copied();
116 while let Some(node_id) = current_node_id {
117 if node_id == *parent_node_id {
118 return true;
119 }
120 current_node_id = self.nodes[node_id.0].parent;
121 }
122 }
123 false
124 }
125
126 pub fn available_actions(&self, target: FocusId) -> Vec<Box<dyn Action>> {
127 let mut actions = Vec::new();
128 if let Some(node) = self.focusable_node_ids.get(&target) {
129 for node_id in self.dispatch_path(*node) {
130 let node = &self.nodes[node_id.0];
131 for ActionListener { action_type, .. } in &node.action_listeners {
132 actions.extend(build_action_from_type(action_type).log_err());
133 }
134 }
135 }
136 actions
137 }
138
139 pub fn dispatch_key(&mut self, target: FocusId, event: &dyn Any, cx: &mut WindowContext) {
140 if let Some(target_node_id) = self.focusable_node_ids.get(&target).copied() {
141 self.dispatch_key_on_node(target_node_id, event, cx);
142 }
143 }
144
145 fn dispatch_key_on_node(
146 &mut self,
147 node_id: DispatchNodeId,
148 event: &dyn Any,
149 cx: &mut WindowContext,
150 ) {
151 let dispatch_path = self.dispatch_path(node_id);
152
153 // Capture phase
154 self.context_stack.clear();
155 cx.propagate_event = true;
156 for node_id in &dispatch_path {
157 let node = &self.nodes[node_id.0];
158 if !node.context.is_empty() {
159 self.context_stack.push(node.context.clone());
160 }
161
162 for key_listener in &node.key_listeners {
163 key_listener(event, DispatchPhase::Capture, cx);
164 if !cx.propagate_event {
165 return;
166 }
167 }
168 }
169
170 // Bubble phase
171 for node_id in dispatch_path.iter().rev() {
172 let node = &self.nodes[node_id.0];
173
174 // Handle low level key events
175 for key_listener in &node.key_listeners {
176 key_listener(event, DispatchPhase::Bubble, cx);
177 if !cx.propagate_event {
178 return;
179 }
180 }
181
182 // Match keystrokes
183 if !node.context.is_empty() {
184 if let Some(key_down_event) = event.downcast_ref::<KeyDownEvent>() {
185 if !self
186 .keystroke_matchers
187 .contains_key(self.context_stack.as_slice())
188 {
189 let keystroke_contexts = self.context_stack.iter().cloned().collect();
190 self.keystroke_matchers.insert(
191 keystroke_contexts,
192 KeystrokeMatcher::new(self.keymap.clone()),
193 );
194 }
195
196 if let Some(keystroke_matcher) = self
197 .keystroke_matchers
198 .get_mut(self.context_stack.as_slice())
199 {
200 if let KeyMatch::Some(action) = keystroke_matcher.match_keystroke(
201 &key_down_event.keystroke,
202 self.context_stack.as_slice(),
203 ) {
204 self.dispatch_action_on_node(*node_id, action, cx);
205 if !cx.propagate_event {
206 return;
207 }
208 }
209 }
210 }
211
212 self.context_stack.pop();
213 }
214 }
215 }
216
217 pub fn dispatch_action(
218 &self,
219 target: FocusId,
220 action: Box<dyn Action>,
221 cx: &mut WindowContext,
222 ) {
223 if let Some(target_node_id) = self.focusable_node_ids.get(&target).copied() {
224 self.dispatch_action_on_node(target_node_id, action, cx);
225 }
226 }
227
228 fn dispatch_action_on_node(
229 &self,
230 node_id: DispatchNodeId,
231 action: Box<dyn Action>,
232 cx: &mut WindowContext,
233 ) {
234 let dispatch_path = self.dispatch_path(node_id);
235
236 // Capture phase
237 for node_id in &dispatch_path {
238 let node = &self.nodes[node_id.0];
239 for ActionListener { listener, .. } in &node.action_listeners {
240 listener(&action, DispatchPhase::Capture, cx);
241 if !cx.propagate_event {
242 return;
243 }
244 }
245 }
246
247 // Bubble phase
248 for node_id in dispatch_path.iter().rev() {
249 let node = &self.nodes[node_id.0];
250 for ActionListener { listener, .. } in &node.action_listeners {
251 cx.propagate_event = false; // Actions stop propagation by default during the bubble phase
252 listener(&action, DispatchPhase::Capture, cx);
253 if !cx.propagate_event {
254 return;
255 }
256 }
257 }
258 }
259
260 fn active_node(&mut self) -> &mut DispatchNode {
261 let active_node_id = self.active_node_id();
262 &mut self.nodes[active_node_id.0]
263 }
264
265 fn active_node_id(&self) -> DispatchNodeId {
266 *self.node_stack.last().unwrap()
267 }
268
269 /// Returns the DispatchNodeIds from the root of the tree to the given target node id.
270 fn dispatch_path(&self, target: DispatchNodeId) -> SmallVec<[DispatchNodeId; 32]> {
271 let mut dispatch_path: SmallVec<[DispatchNodeId; 32]> = SmallVec::new();
272 let mut current_node_id = Some(target);
273 while let Some(node_id) = current_node_id {
274 dispatch_path.push(node_id);
275 current_node_id = self.nodes[node_id.0].parent;
276 }
277 dispatch_path.reverse(); // Reverse the path so it goes from the root to the focused node.
278 dispatch_path
279 }
280}
281
282pub trait KeyDispatch<V: 'static>: 'static {
283 fn as_focusable(&self) -> Option<&FocusableKeyDispatch<V>>;
284 fn as_focusable_mut(&mut self) -> Option<&mut FocusableKeyDispatch<V>>;
285 fn key_context(&self) -> &KeyContext;
286 fn key_context_mut(&mut self) -> &mut KeyContext;
287
288 fn initialize<R>(
289 &mut self,
290 focus_handle: Option<FocusHandle>,
291 cx: &mut ViewContext<V>,
292 f: impl FnOnce(Option<FocusHandle>, &mut ViewContext<V>) -> R,
293 ) -> R {
294 if let Some(focusable) = self.as_focusable_mut() {
295 let focus_handle = focusable
296 .focus_handle
297 .get_or_insert_with(|| focus_handle.unwrap_or_else(|| cx.focus_handle()))
298 .clone();
299 for listener in focusable.focus_listeners.drain(..) {
300 let focus_handle = focus_handle.clone();
301 cx.on_focus_changed(move |view, event, cx| {
302 listener(view, &focus_handle, event, cx)
303 });
304 }
305
306 cx.with_key_dispatch(self.key_context().clone(), Some(focus_handle), f)
307 } else {
308 f(None, cx)
309 }
310 }
311
312 fn refine_style(&self, style: &mut Style, cx: &WindowContext) {
313 if let Some(focusable) = self.as_focusable() {
314 let focus_handle = focusable
315 .focus_handle
316 .as_ref()
317 .expect("must call initialize before refine_style");
318 if focus_handle.contains_focused(cx) {
319 style.refine(&focusable.focus_in_style);
320 }
321
322 if focus_handle.within_focused(cx) {
323 style.refine(&focusable.in_focus_style);
324 }
325
326 if focus_handle.is_focused(cx) {
327 style.refine(&focusable.focus_style);
328 }
329 }
330 }
331
332 fn paint(&self, bounds: Bounds<Pixels>, cx: &mut WindowContext) {
333 if let Some(focusable) = self.as_focusable() {
334 let focus_handle = focusable
335 .focus_handle
336 .clone()
337 .expect("must call initialize before paint");
338 cx.on_mouse_event(move |event: &MouseDownEvent, phase, cx| {
339 if phase == DispatchPhase::Bubble && bounds.contains_point(&event.position) {
340 if !cx.default_prevented() {
341 cx.focus(&focus_handle);
342 cx.prevent_default();
343 }
344 }
345 })
346 }
347 }
348}
349
350pub struct FocusableKeyDispatch<V> {
351 pub key_context: KeyContext,
352 pub focus_handle: Option<FocusHandle>,
353 pub focus_listeners: FocusListeners<V>,
354 pub focus_style: StyleRefinement,
355 pub focus_in_style: StyleRefinement,
356 pub in_focus_style: StyleRefinement,
357}
358
359impl<V> FocusableKeyDispatch<V> {
360 pub fn new() -> Self {
361 Self {
362 key_context: KeyContext::default(),
363 focus_handle: None,
364 focus_listeners: FocusListeners::default(),
365 focus_style: StyleRefinement::default(),
366 focus_in_style: StyleRefinement::default(),
367 in_focus_style: StyleRefinement::default(),
368 }
369 }
370
371 pub fn tracked(handle: &FocusHandle) -> Self {
372 Self {
373 key_context: KeyContext::default(),
374 focus_handle: Some(handle.clone()),
375 focus_listeners: FocusListeners::default(),
376 focus_style: StyleRefinement::default(),
377 focus_in_style: StyleRefinement::default(),
378 in_focus_style: StyleRefinement::default(),
379 }
380 }
381}
382
383impl<V: 'static> KeyDispatch<V> for FocusableKeyDispatch<V> {
384 fn as_focusable(&self) -> Option<&FocusableKeyDispatch<V>> {
385 Some(self)
386 }
387
388 fn as_focusable_mut(&mut self) -> Option<&mut FocusableKeyDispatch<V>> {
389 Some(self)
390 }
391
392 fn key_context(&self) -> &KeyContext {
393 &self.key_context
394 }
395
396 fn key_context_mut(&mut self) -> &mut KeyContext {
397 &mut self.key_context
398 }
399}
400
401impl<V> From<FocusHandle> for FocusableKeyDispatch<V> {
402 fn from(value: FocusHandle) -> Self {
403 Self {
404 key_context: KeyContext::default(),
405 focus_handle: Some(value),
406 focus_listeners: FocusListeners::default(),
407 focus_style: StyleRefinement::default(),
408 focus_in_style: StyleRefinement::default(),
409 in_focus_style: StyleRefinement::default(),
410 }
411 }
412}
413
414#[derive(Default)]
415pub struct NonFocusableKeyDispatch {
416 pub(crate) key_context: KeyContext,
417}
418
419impl<V: 'static> KeyDispatch<V> for NonFocusableKeyDispatch {
420 fn as_focusable(&self) -> Option<&FocusableKeyDispatch<V>> {
421 None
422 }
423
424 fn as_focusable_mut(&mut self) -> Option<&mut FocusableKeyDispatch<V>> {
425 None
426 }
427
428 fn key_context(&self) -> &KeyContext {
429 &self.key_context
430 }
431
432 fn key_context_mut(&mut self) -> &mut KeyContext {
433 &mut self.key_context
434 }
435}
436
437pub trait Focusable<V: 'static>: Element<V> {
438 fn focus_listeners(&mut self) -> &mut FocusListeners<V>;
439 fn set_focus_style(&mut self, style: StyleRefinement);
440 fn set_focus_in_style(&mut self, style: StyleRefinement);
441 fn set_in_focus_style(&mut self, style: StyleRefinement);
442
443 fn focus(mut self, f: impl FnOnce(StyleRefinement) -> StyleRefinement) -> Self
444 where
445 Self: Sized,
446 {
447 self.set_focus_style(f(StyleRefinement::default()));
448 self
449 }
450
451 fn focus_in(mut self, f: impl FnOnce(StyleRefinement) -> StyleRefinement) -> Self
452 where
453 Self: Sized,
454 {
455 self.set_focus_in_style(f(StyleRefinement::default()));
456 self
457 }
458
459 fn in_focus(mut self, f: impl FnOnce(StyleRefinement) -> StyleRefinement) -> Self
460 where
461 Self: Sized,
462 {
463 self.set_in_focus_style(f(StyleRefinement::default()));
464 self
465 }
466
467 fn on_focus(
468 mut self,
469 listener: impl Fn(&mut V, &FocusEvent, &mut ViewContext<V>) + 'static,
470 ) -> Self
471 where
472 Self: Sized,
473 {
474 self.focus_listeners()
475 .push(Box::new(move |view, focus_handle, event, cx| {
476 if event.focused.as_ref() == Some(focus_handle) {
477 listener(view, event, cx)
478 }
479 }));
480 self
481 }
482
483 fn on_blur(
484 mut self,
485 listener: impl Fn(&mut V, &FocusEvent, &mut ViewContext<V>) + 'static,
486 ) -> Self
487 where
488 Self: Sized,
489 {
490 self.focus_listeners()
491 .push(Box::new(move |view, focus_handle, event, cx| {
492 if event.blurred.as_ref() == Some(focus_handle) {
493 listener(view, event, cx)
494 }
495 }));
496 self
497 }
498
499 fn on_focus_in(
500 mut self,
501 listener: impl Fn(&mut V, &FocusEvent, &mut ViewContext<V>) + 'static,
502 ) -> Self
503 where
504 Self: Sized,
505 {
506 self.focus_listeners()
507 .push(Box::new(move |view, focus_handle, event, cx| {
508 let descendant_blurred = event
509 .blurred
510 .as_ref()
511 .map_or(false, |blurred| focus_handle.contains(blurred, cx));
512 let descendant_focused = event
513 .focused
514 .as_ref()
515 .map_or(false, |focused| focus_handle.contains(focused, cx));
516
517 if !descendant_blurred && descendant_focused {
518 listener(view, event, cx)
519 }
520 }));
521 self
522 }
523
524 fn on_focus_out(
525 mut self,
526 listener: impl Fn(&mut V, &FocusEvent, &mut ViewContext<V>) + 'static,
527 ) -> Self
528 where
529 Self: Sized,
530 {
531 self.focus_listeners()
532 .push(Box::new(move |view, focus_handle, event, cx| {
533 let descendant_blurred = event
534 .blurred
535 .as_ref()
536 .map_or(false, |blurred| focus_handle.contains(blurred, cx));
537 let descendant_focused = event
538 .focused
539 .as_ref()
540 .map_or(false, |focused| focus_handle.contains(focused, cx));
541 if descendant_blurred && !descendant_focused {
542 listener(view, event, cx)
543 }
544 }));
545 self
546 }
547}