Skip to main content

rat_focus/
focus.rs

1use crate::core::FocusCore;
2use crate::{FocusBuilder, FocusFlag, HasFocus, Navigation};
3use rat_event::{HandleEvent, MouseOnly, Outcome, Regular, crossterm, ct_event};
4use ratatui_core::layout::Rect;
5use ratatui_crossterm::crossterm::event::Event;
6use std::ops::Range;
7
8/// Focus deals with all focus-related issues.
9///
10/// Use [FocusBuilder] to construct the current Focus.
11///
12/// This is usually quick enough to do it for each event.
13/// It has to be rebuilt if any area has changed, so
14/// rebuilding it after a render() is fine.
15#[derive(Default, Debug, Clone)]
16pub struct Focus {
17    pub(crate) last: FocusCore,
18    pub(crate) core: FocusCore,
19}
20
21macro_rules! focus_debug {
22    ($core:expr, $($arg:tt)+) => {
23        if $core.log.get() {
24            log::log!(log::Level::Debug, $($arg)+);
25        }
26    }
27}
28
29macro_rules! focus_fail {
30    ($core:expr, $($arg:tt)+) => {
31        if $core.log.get() {
32            log::log!(log::Level::Debug, $($arg)+);
33        }
34        if $core.insta_panic.get() {
35            panic!($($arg)+)
36        }
37    }
38}
39
40impl Focus {
41    /// Writes a log for each operation.
42    pub fn enable_log(&self) {
43        self.core.log.set(true);
44        self.last.log.set(true);
45    }
46
47    /// Writes a log for each operation.
48    pub fn disable_log(&self) {
49        self.core.log.set(false);
50        self.last.log.set(false);
51    }
52
53    /// Enable insta-panic if any function is called
54    /// with a widget that is not part of the Focus.
55    pub fn enable_panic(&self) {
56        self.core.insta_panic.set(true);
57        self.last.insta_panic.set(true);
58    }
59
60    /// Disable insta-panic.
61    pub fn disable_panic(&self) {
62        self.core.insta_panic.set(false);
63        self.last.insta_panic.set(false);
64    }
65
66    /// Sets the focus to the given widget and remembers
67    /// the previous focused widget. If the focus is
68    /// currently set to the given widget it sets the
69    /// focus back to the previous widget.
70    pub fn flip_focus(
71        &self,
72        widget_state: &'_ dyn HasFocus,
73        flip_focus: &'_ mut Option<FocusFlag>,
74    ) {
75        focus_debug!(
76            self.core,
77            "flip-focus {:?} {:?}",
78            widget_state.focus().name(),
79            flip_focus
80        );
81        let flag = widget_state.focus();
82        if self.core.is_widget(&flag) {
83            if flag.is_focused() {
84                if let Some(flip_focus) = flip_focus {
85                    self.focus(flip_focus);
86                } else {
87                    focus_fail!(self.core, "    => no previous widget");
88                }
89            } else {
90                *flip_focus = self.focused();
91                self.focus(&flag);
92            }
93        } else if self.core.is_container(&flag) {
94            if flag.is_focused() {
95                if let Some(flip_focus) = flip_focus {
96                    self.focus(flip_focus);
97                } else {
98                    focus_fail!(self.core, "    => no previous widget");
99                }
100            } else {
101                self.core.first_container(&flag);
102            }
103        } else {
104            focus_fail!(self.core, "    => not a valid widget");
105        }
106    }
107
108    /// Sets the focus to the given widget.
109    ///
110    /// This changes the focus and the gained/lost flags.
111    /// If this ends up with the same widget as before
112    /// gained and lost flags are not set.
113    ///
114    /// This will ignore the [Navigation] flag of the
115    /// currently focused widget.
116    ///
117    /// You can also use a container-widget for this.
118    /// It will set the focus to the first navigable widget
119    /// of the container.
120    #[inline]
121    pub fn focus(&self, widget_state: &'_ dyn HasFocus) {
122        focus_debug!(self.core, "focus {:?}", widget_state.focus().name());
123        let flag = widget_state.focus();
124        if self.core.is_widget(&flag) {
125            if let Some(n) = self.core.index_of(&flag) {
126                self.core.focus_idx(n, true);
127            } else {
128                panic!("    => invalid widget?");
129            }
130        } else if self.core.is_container(&flag) {
131            self.core.first_container(&flag);
132        } else {
133            focus_fail!(self.core, "    => not a valid widget");
134        }
135    }
136
137    /// Sets the focus to the widget by its widget-id.
138    ///
139    /// This can be useful if you want to store references
140    /// to widgets in some extra subsystem and can't use
141    /// a clone of the FocusFlag for that.
142    ///
143    /// This changes the focus and the gained/lost flags.
144    /// If this ends up with the same widget as before
145    /// gained and lost flags are not set.
146    ///
147    /// This will ignore the [Navigation] flag of the
148    /// currently focused widget.
149    ///
150    /// You can also use a container-widget for this.
151    /// It will set the focus to the first widget of the
152    /// container.
153    #[inline]
154    pub fn by_widget_id(&self, widget_id: usize) {
155        let widget_state = self.core.find_widget_id(widget_id);
156        focus_debug!(self.core, "focus {:?} -> {:?}", widget_id, widget_state);
157        let Some(widget_state) = widget_state else {
158            return;
159        };
160
161        let flag = widget_state.focus();
162        if self.core.is_widget(&flag) {
163            if let Some(n) = self.core.index_of(&flag) {
164                self.core.focus_idx(n, true);
165            } else {
166                panic!("    => invalid widget");
167            }
168        } else if self.core.is_container(&flag) {
169            self.core.first_container(&flag);
170        } else {
171            focus_fail!(self.core, "    => not a valid widget");
172        }
173    }
174
175    /// Set the focus to the first navigable widget.
176    ///
177    /// This changes the focus and the gained/lost flags.
178    /// If this ends up with the same widget as before
179    /// gained and lost flags are not set.
180    ///
181    /// This will ignore the [Navigation] flag of the
182    /// currently focused widget.
183    #[inline(always)]
184    pub fn first(&self) {
185        focus_debug!(self.core, "focus first");
186        self.core.first();
187    }
188
189    #[deprecated(since = "1.1.2", note = "use focus() instead")]
190    pub fn first_in(&self, container: &'_ dyn HasFocus) {
191        self.focus(container);
192    }
193
194    /// Clear the focus for all widgets.
195    ///
196    /// This will reset the focus, gained and lost flags for
197    /// all widgets.
198    #[inline(always)]
199    pub fn none(&self) {
200        focus_debug!(self.core, "focus none");
201        self.core.none();
202        focus_debug!(self.core, "    -> done");
203    }
204
205    /// This widget will have the focus, but it is not
206    /// yet part of the focus cycle. And the focus cycle
207    /// can't be properly rebuilt at this point.
208    ///
209    /// If the widget *is* part of the focus this will do nothing.
210    ///
211    /// If the widget is a container, it will just set
212    /// the container-flag. If you want to set a future widget
213    /// and its container, call future() for the widget first,
214    /// then the container.
215    #[inline(always)]
216    pub fn future(&self, widget_state: &'_ dyn HasFocus) {
217        focus_debug!(self.core, "focus {:?}", widget_state.focus().name());
218        let flag = widget_state.focus();
219        if self.core.is_widget(&flag) {
220            focus_fail!(
221                self.core,
222                "    => widget is part of focus. use focus() instead"
223            );
224        } else if self.core.is_container(&flag) {
225            focus_debug!(self.core, "future container");
226            let had_focus = flag.get();
227            flag.set(true);
228            if !had_focus {
229                flag.set_gained(true);
230                flag.call_on_gained();
231            }
232            focus_debug!(self.core, "    -> done");
233        } else {
234            focus_debug!(self.core, "future focus");
235            self.core.none();
236            let had_focus = flag.get();
237            flag.set(true);
238            if !had_focus {
239                flag.set_gained(true);
240                flag.call_on_gained();
241            }
242            focus_debug!(self.core, "    -> done");
243        }
244    }
245
246    /// Change to focus to the widget at the given position.
247    ///
248    /// This changes the focus and the gained/lost flags.
249    /// If this ends up with the same widget as before
250    /// gained and lost flags are not set.
251    ///
252    /// If the current widget has a [Navigation::Lock], this will
253    /// do nothing.
254    #[inline(always)]
255    pub fn focus_at(&self, col: u16, row: u16) -> bool {
256        focus_debug!(self.core, "focus at {},{}", col, row);
257        match self.navigation() {
258            Some(Navigation::Lock) => {
259                focus_debug!(self.core, "    -> locked");
260                false
261            }
262            _ => self.core.focus_at(col, row),
263        }
264    }
265
266    /// Reset the obscured flag to __false__.
267    #[inline(always)]
268    pub fn clear_obscured(&self) -> bool {
269        self.core.clear_obscured()
270    }
271
272    /// Sets the obscured state for the given position.
273    ///
274    /// Hit-tests all widgets for the given position and
275    /// sets obscured to false if the widget-area is hit
276    /// and there are no containers/widgets with a *higher*
277    /// z-index.
278    #[inline(always)]
279    pub fn find_obscured(&self, col: u16, row: u16) -> bool {
280        focus_debug!(self.core, "find_obscured {} {}", col, row);
281        self.core.find_obscured(col, row)
282    }
283
284    /// Focus the next widget in the cycle.
285    ///
286    /// This function will use the [Navigation] of the current widget
287    /// and only focus the next widget if it is `Leave`, `ReachLeaveBack` or
288    /// `Regular`.
289    ///
290    /// If no field has the focus the first navigable one gets it.
291    /// Sets the focus, gained and lost flags. If this ends up with
292    /// the same widget as before focus, gained and lost flag are not set.
293    #[inline]
294    pub fn next(&self) -> bool {
295        match self.navigation() {
296            None => {
297                self.first();
298                true
299            }
300            Some(Navigation::Leave | Navigation::ReachLeaveBack | Navigation::Regular) => {
301                focus_debug!(
302                    self.core,
303                    "next after {:?}",
304                    self.core
305                        .focused()
306                        .map(|v| v.name())
307                        .unwrap_or("None".into())
308                );
309                self.core.next()
310            }
311            v => {
312                focus_debug!(
313                    self.core,
314                    "next after {:?}, but navigation says {:?}",
315                    self.core
316                        .focused()
317                        .map(|v| v.name().to_string())
318                        .unwrap_or("None".into()),
319                    v
320                );
321                false
322            }
323        }
324    }
325
326    /// Focus the previous widget in the cycle.
327    ///
328    /// This function will use the [Navigation] of the current widget
329    /// and only focus the next widget if it is `Leave`, `ReachLeaveFront` or
330    /// `Regular`.
331    ///
332    /// If no field has the focus the first navigable one gets it.
333    /// Sets the focus, gained and lost flags. If this ends up with
334    /// the same widget as before focus, gained and lost flag are not set.
335    #[inline]
336    pub fn prev(&self) -> bool {
337        match self.navigation() {
338            None => {
339                self.first();
340                true
341            }
342            Some(Navigation::Leave | Navigation::ReachLeaveFront | Navigation::Regular) => {
343                focus_debug!(
344                    self.core,
345                    "prev before {:?}",
346                    self.core
347                        .focused()
348                        .map(|v| v.name().to_string())
349                        .unwrap_or("None".into())
350                );
351                self.core.prev()
352            }
353            v => {
354                focus_debug!(
355                    self.core,
356                    "prev before {:?}, but navigation says {:?}",
357                    self.core
358                        .focused()
359                        .map(|v| v.name().to_string())
360                        .unwrap_or("None".into()),
361                    v
362                );
363                false
364            }
365        }
366    }
367
368    /// Focus the next widget in the cycle.
369    ///
370    /// Applies some extra force to this action and allows
371    /// leaving widgets that have [Navigation] `Reach` and `ReachLeaveFront`
372    /// in addition to the regular `Leave`, `ReachLeaveBack` or
373    /// `Regular`.
374    ///
375    /// If no field has the focus the first navigable one gets it.
376    ///
377    /// Sets the focus, gained and lost flags. If this ends up with
378    /// the same widget as before focus, gained and lost flag are not set.
379    #[inline]
380    pub fn next_force(&self) -> bool {
381        match self.navigation() {
382            None => {
383                self.first();
384                true
385            }
386            Some(
387                Navigation::Leave
388                | Navigation::Reach
389                | Navigation::ReachLeaveFront
390                | Navigation::ReachLeaveBack
391                | Navigation::Regular,
392            ) => {
393                focus_debug!(
394                    self.core,
395                    "force next after {:?}",
396                    self.core.focused().map(|v| v.name().to_string())
397                );
398                self.core.next()
399            }
400            v => {
401                focus_debug!(
402                    self.core,
403                    "force next after {:?}, but navigation says {:?}",
404                    self.core.focused().map(|v| v.name().to_string()),
405                    v
406                );
407                false
408            }
409        }
410    }
411
412    /// Focus the previous widget in the cycle.
413    ///
414    /// Applies some extra force to this action and allows
415    /// leaving widgets that have [Navigation] `Reach` and `ReachLeaveBack`
416    /// in addition to the regular `Leave`, `ReachLeaveFront` or
417    /// `Regular`.
418    ///
419    /// If no field has the focus the first navigable one gets it.
420    ///
421    /// Sets the focus, gained and lost flags. If this ends up with
422    /// the same widget as before focus, gained and lost flag are not set.
423    #[inline]
424    pub fn prev_force(&self) -> bool {
425        match self.navigation() {
426            None => {
427                self.first();
428                true
429            }
430            Some(
431                Navigation::Leave
432                | Navigation::Reach
433                | Navigation::ReachLeaveFront
434                | Navigation::ReachLeaveBack
435                | Navigation::Regular,
436            ) => {
437                focus_debug!(
438                    self.core,
439                    "force prev before {:?}",
440                    self.core.focused().map(|v| v.name().to_string())
441                );
442                self.core.prev()
443            }
444            v => {
445                focus_debug!(
446                    self.core,
447                    "force prev before {:?}, but navigation says {:?}",
448                    self.core.focused().map(|v| v.name().to_string()),
449                    v
450                );
451                false
452            }
453        }
454    }
455
456    /// Is this widget part of this focus-cycle?
457    #[inline(always)]
458    pub fn is_valid_widget(&self, widget_state: &'_ dyn HasFocus) -> bool {
459        self.core.is_widget(&widget_state.focus())
460    }
461
462    /// Is this a container that is part of this focus-cycle?
463    #[inline(always)]
464    pub fn is_valid_container(&self, widget_state: &'_ dyn HasFocus) -> bool {
465        self.core.is_container(&widget_state.focus())
466    }
467
468    /// Returns the focused widget as FocusFlag.
469    ///
470    /// For control-flow [crate::match_focus] or [crate::on_gained] or [crate::on_lost]
471    /// will be nicer.
472    #[inline(always)]
473    pub fn focused(&self) -> Option<FocusFlag> {
474        self.core.focused()
475    }
476
477    /// Returns the focused widget as widget-id.
478    ///
479    /// For control-flow [crate::match_focus] or [crate::on_gained] or [crate::on_lost]
480    /// will be nicer.
481    #[inline(always)]
482    pub fn focused_widget_id(&self) -> Option<usize> {
483        self.core.focused().map(|v| v.id())
484    }
485
486    /// Returns the debug name of the focused widget.
487    #[inline(always)]
488    pub fn focused_name(&self) -> Option<String> {
489        self.core.focused().map(|v| v.name().to_string())
490    }
491
492    /// Returns the [Navigation] flag for the focused widget.
493    #[inline(always)]
494    pub fn navigation(&self) -> Option<Navigation> {
495        self.core.navigation()
496    }
497
498    /// Returns the widget that lost the focus as FocusFlag.
499    ///
500    /// For control-flow [crate::match_focus] or [crate::on_gained] or [crate::on_lost]
501    /// will be nicer.
502    #[inline(always)]
503    pub fn lost_focus(&self) -> Option<FocusFlag> {
504        self.core.lost_focus()
505    }
506
507    /// Returns the widget that gained the focus as FocusFlag.
508    ///
509    /// For control-flow [crate::match_focus] or [crate::on_gained] or [crate::on_lost]
510    /// will be nicer.
511    #[inline(always)]
512    pub fn gained_focus(&self) -> Option<FocusFlag> {
513        self.core.gained_focus()
514    }
515
516    /// Sets the focus to the given widget, but doesn't set
517    /// lost and gained. This can be used to prevent any side
518    /// effects that use the gained/lost state.
519    ///
520    /// This changes the focus and the gained/lost flags.
521    /// If this ends up with the same widget as before
522    /// gained and lost flags are not set.
523    ///
524    /// This will ignore the [Navigation] flag of the
525    /// currently focused widget.
526    ///
527    /// You can also use a container-widget for this.
528    /// It will set the focus to the first widget of the
529    /// container.
530    #[inline]
531    pub fn focus_no_lost(&self, widget_state: &'_ dyn HasFocus) {
532        focus_debug!(self.core, "focus no_lost {:?}", widget_state.focus().name());
533        let flag = widget_state.focus();
534        if self.core.is_widget(&flag) {
535            if let Some(n) = self.core.index_of(&flag) {
536                self.core.focus_idx(n, false);
537            } else {
538                panic!("    => invalid widget");
539            }
540        } else if self.core.is_container(&flag) {
541            self.core.first_container(&flag);
542        } else {
543            focus_fail!(self.core, "    => not a valid widget");
544        }
545    }
546
547    /// This expels the focus from the given widget/container.
548    ///
549    /// This is sometimes useful to set the focus to **somewhere else**.
550    /// This is especially useful when used for a container-widget that will
551    /// be hidden. Ensures there is still some widget with focus afterward.
552    ///
553    /// It will try to set the focus to the next widget or the
554    /// next widget following the container. If this ends up within
555    /// the given container it will set the focus to none.
556    ///
557    /// This function doesn't use the Navigation of the current widget.
558    #[inline]
559    pub fn expel_focus(&self, widget_state: &'_ dyn HasFocus) {
560        focus_debug!(
561            self.core,
562            "expel from widget {:?}",
563            widget_state.focus().name()
564        );
565        let flag = widget_state.focus();
566        if self.core.is_widget(&flag) {
567            if self.core.index_of(&flag).is_some() {
568                if widget_state.is_focused() {
569                    self.core.next();
570                    if widget_state.is_focused() {
571                        focus_debug!(self.core, "    -> no other focus, cleared");
572                        flag.clear();
573                    } else {
574                        focus_debug!(self.core, "    -> expelled");
575                    }
576                } else {
577                    focus_debug!(self.core, "    => widget not focused");
578                }
579            } else {
580                panic!("    => invalid widget");
581            }
582        } else if self.core.is_container(&flag) {
583            if flag.is_focused() {
584                self.core.expel_container(flag);
585            } else {
586                focus_debug!(self.core, "    => container not focused");
587            }
588        } else {
589            focus_fail!(self.core, "    => not a valid widget");
590        }
591    }
592
593    /// Dynamic change of the widget structure for a container widget.
594    ///
595    /// This is only necessary if your widget structure changes
596    /// during event-handling, and you need a programmatic
597    /// focus-change for the new structure.
598    ///
599    /// This resets the focus-flags of the removed container.
600    pub fn remove_container(&mut self, container: &'_ dyn HasFocus) {
601        focus_debug!(
602            self.core,
603            "focus remove container {:?} ",
604            container.focus().name()
605        );
606        let flag = container.focus();
607        if self.core.is_container(&flag) {
608            if let Some((cidx, _)) = self.core.container_index_of(&flag) {
609                self.core.remove_container(cidx).reset();
610                focus_debug!(self.core, "    -> removed");
611            } else {
612                panic!("    => invalid container?");
613            }
614        } else {
615            focus_fail!(self.core, "    => no container flag");
616        }
617    }
618
619    /// Dynamic change of the widget structure for a container.
620    ///
621    /// This is only necessary if your widget structure changes
622    /// during event-handling, and you need a programmatic
623    /// focus-change for the new structure.
624    ///
625    /// If the widget that currently has the focus is still
626    /// part of the widget structure it keeps the focus.
627    /// The focus-flags for all widgets that are no longer part
628    /// of the widget structure are reset.
629    pub fn update_container(&mut self, container: &'_ dyn HasFocus) {
630        focus_debug!(
631            self.core,
632            "focus update container {:?} ",
633            container.focus().name()
634        );
635        let flag = container.focus();
636        if self.core.is_container(&flag) {
637            if let Some((cidx, range)) = self.core.container_index_of(&flag) {
638                let removed = self.core.remove_container(cidx);
639
640                let mut b = FocusBuilder::new(Some(Focus {
641                    last: Default::default(),
642                    core: removed,
643                }));
644                b.widget(container);
645                let insert = b.build();
646
647                self.core.insert_container(range.start, cidx, insert.core);
648
649                focus_debug!(self.core, "    -> updated");
650            } else {
651                panic!("    => invalid container?");
652            }
653        } else {
654            focus_fail!(self.core, "    => no container flag");
655        }
656    }
657
658    /// Dynamic change of the widget structure of a container.
659    ///
660    /// This is only necessary if your widget structure changes
661    /// during event-handling, and you need a programmatic
662    /// focus-change.
663    ///
664    /// This removes the widgets of one container and inserts
665    /// the widgets of the other one in place.
666    ///
667    /// If the widget that currently has the focus is still
668    /// part of the widget structure it keeps the focus.
669    /// The focus-flags for all widgets that are no longer part
670    /// of the widget structure are reset.
671    pub fn replace_container(&mut self, container: &'_ dyn HasFocus, new: &'_ dyn HasFocus) {
672        focus_debug!(
673            self.core,
674            "focus replace container {:?} with {:?} ",
675            container.focus().name(),
676            new.focus().name()
677        );
678        let flag = container.focus();
679        if self.core.is_container(&flag) {
680            if let Some((cidx, range)) = self.core.container_index_of(&flag) {
681                let removed = self.core.remove_container(cidx);
682
683                let mut b = FocusBuilder::new(Some(Focus {
684                    last: Default::default(),
685                    core: removed,
686                }));
687                b.widget(new);
688                let insert = b.build();
689
690                self.core.insert_container(range.start, cidx, insert.core);
691
692                focus_debug!(self.core, "    -> replaced");
693            } else {
694                panic!("    => invalid container");
695            }
696        } else {
697            focus_fail!(self.core, "    => no container flag");
698        }
699    }
700
701    /// Reset lost + gained flags.
702    ///
703    /// This is done automatically during event-handling.
704    /// Lost+Gained flags will only be set while handling
705    /// the original event that made the focus-change.
706    /// The next event, whatever it is, will reset these flags.
707    #[inline(always)]
708    pub fn reset_lost_gained(&self) {
709        self.core.reset_lost_gained();
710    }
711
712    /// Debug destructuring.
713    #[allow(clippy::type_complexity)]
714    pub fn clone_destruct(
715        &self,
716    ) -> (
717        Vec<FocusFlag>,
718        Vec<bool>,
719        Vec<(Rect, u16)>,
720        Vec<Navigation>,
721        Vec<(FocusFlag, (Rect, u16), Range<usize>)>,
722    ) {
723        self.core.clone_destruct()
724    }
725}
726
727impl HandleEvent<Event, Regular, Outcome> for Focus {
728    #[inline(always)]
729    fn handle(&mut self, event: &Event, _keymap: Regular) -> Outcome {
730        match event {
731            ct_event!(keycode press Tab) => {
732                focus_debug!(
733                    self.core,
734                    "Tab {:?}",
735                    self.focused().map(|v| v.name().to_string())
736                );
737                let r = if self.next() {
738                    Outcome::Changed
739                } else {
740                    Outcome::Continue
741                };
742                focus_debug!(
743                    self.core,
744                    "    -> {:?} {:?}",
745                    r,
746                    self.focused().map(|v| v.name().to_string())
747                );
748                r
749            }
750            ct_event!(keycode press SHIFT-Tab) | ct_event!(keycode press SHIFT-BackTab) => {
751                focus_debug!(
752                    self.core,
753                    "BackTab {:?}",
754                    self.focused().map(|v| v.name().to_string())
755                );
756                let r = if self.prev() {
757                    Outcome::Changed
758                } else {
759                    Outcome::Continue
760                };
761                focus_debug!(
762                    self.core,
763                    "    -> {:?} {:?}",
764                    r,
765                    self.focused().map(|v| v.name().to_string())
766                );
767                r
768            }
769            _ => self.handle(event, MouseOnly),
770        }
771    }
772}
773
774impl HandleEvent<Event, MouseOnly, Outcome> for Focus {
775    #[inline(always)]
776    fn handle(&mut self, event: &Event, _keymap: MouseOnly) -> Outcome {
777        match event {
778            Event::Mouse(crossterm::event::MouseEvent {
779                kind: crossterm::event::MouseEventKind::Drag(_),
780                ..
781            }) => {
782                self.clear_obscured();
783            }
784            Event::Mouse(crossterm::event::MouseEvent {
785                kind:
786                    crossterm::event::MouseEventKind::Moved
787                    | crossterm::event::MouseEventKind::Down(_)
788                    | crossterm::event::MouseEventKind::Up(_)
789                    | crossterm::event::MouseEventKind::ScrollDown
790                    | crossterm::event::MouseEventKind::ScrollUp
791                    | crossterm::event::MouseEventKind::ScrollLeft
792                    | crossterm::event::MouseEventKind::ScrollRight,
793                column: c,
794                row: r,
795                ..
796            }) => {
797                self.find_obscured(*c, *r);
798            }
799            _ => {}
800        };
801
802        match event {
803            ct_event!(mouse down Left for column, row) => {
804                if self.focus_at(*column, *row) {
805                    Outcome::Changed
806                } else {
807                    self.reset_lost_gained();
808                    Outcome::Continue
809                }
810            }
811            _ => {
812                self.reset_lost_gained();
813                Outcome::Continue
814            }
815        }
816    }
817}
818
819/// Handle all events.
820#[inline(always)]
821pub fn handle_focus(focus: &mut Focus, event: &Event) -> Outcome {
822    HandleEvent::handle(focus, event, Regular)
823}