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            flag.set(true);
237            flag.set_gained(true);
238            flag.call_on_gained();
239            focus_debug!(self.core, "    -> done");
240        }
241    }
242
243    /// Change to focus to the widget at the given position.
244    ///
245    /// This changes the focus and the gained/lost flags.
246    /// If this ends up with the same widget as before
247    /// gained and lost flags are not set.
248    ///
249    /// If the current widget has a [Navigation::Lock], this will
250    /// do nothing.
251    #[inline(always)]
252    pub fn focus_at(&self, col: u16, row: u16) -> bool {
253        focus_debug!(self.core, "focus at {},{}", col, row);
254        match self.navigation() {
255            Some(Navigation::Lock) => {
256                focus_debug!(self.core, "    -> locked");
257                false
258            }
259            _ => self.core.focus_at(col, row),
260        }
261    }
262
263    /// Reset the mouse-focus flag to __true__.
264    #[inline(always)]
265    pub fn reset_mouse_focus(&self) -> bool {
266        self.core.reset_mouse_focus()
267    }
268
269    /// Set the mouse-focus to the given position.  
270    ///
271    /// The top-most widget with a matching area will have
272    /// its mouse_focus flag set. Any containers
273    /// with an associated area that matches, will get
274    /// their mouse_focus flag set too.
275    #[inline(always)]
276    pub fn mouse_focus(&self, col: u16, row: u16) -> bool {
277        focus_debug!(self.core, "mouse-focus {} {}", col, row);
278        self.core.mouse_focus(col, row)
279    }
280
281    /// Focus the next widget in the cycle.
282    ///
283    /// This function will use the [Navigation] of the current widget
284    /// and only focus the next widget if it is `Leave`, `ReachLeaveBack` or
285    /// `Regular`.
286    ///
287    /// If no field has the focus the first navigable one gets it.
288    /// Sets the focus, gained and lost flags. If this ends up with
289    /// the same widget as before focus, gained and lost flag are not set.
290    #[inline]
291    pub fn next(&self) -> bool {
292        match self.navigation() {
293            None => {
294                self.first();
295                true
296            }
297            Some(Navigation::Leave | Navigation::ReachLeaveBack | Navigation::Regular) => {
298                focus_debug!(
299                    self.core,
300                    "next after {:?}",
301                    self.core
302                        .focused()
303                        .map(|v| v.name())
304                        .unwrap_or("None".into())
305                );
306                self.core.next()
307            }
308            v => {
309                focus_debug!(
310                    self.core,
311                    "next after {:?}, but navigation says {:?}",
312                    self.core
313                        .focused()
314                        .map(|v| v.name().to_string())
315                        .unwrap_or("None".into()),
316                    v
317                );
318                false
319            }
320        }
321    }
322
323    /// Focus the previous widget in the cycle.
324    ///
325    /// This function will use the [Navigation] of the current widget
326    /// and only focus the next widget if it is `Leave`, `ReachLeaveFront` or
327    /// `Regular`.
328    ///
329    /// If no field has the focus the first navigable one gets it.
330    /// Sets the focus, gained and lost flags. If this ends up with
331    /// the same widget as before focus, gained and lost flag are not set.
332    #[inline]
333    pub fn prev(&self) -> bool {
334        match self.navigation() {
335            None => {
336                self.first();
337                true
338            }
339            Some(Navigation::Leave | Navigation::ReachLeaveFront | Navigation::Regular) => {
340                focus_debug!(
341                    self.core,
342                    "prev before {:?}",
343                    self.core
344                        .focused()
345                        .map(|v| v.name().to_string())
346                        .unwrap_or("None".into())
347                );
348                self.core.prev()
349            }
350            v => {
351                focus_debug!(
352                    self.core,
353                    "prev before {:?}, but navigation says {:?}",
354                    self.core
355                        .focused()
356                        .map(|v| v.name().to_string())
357                        .unwrap_or("None".into()),
358                    v
359                );
360                false
361            }
362        }
363    }
364
365    /// Focus the next widget in the cycle.
366    ///
367    /// Applies some extra force to this action and allows
368    /// leaving widgets that have [Navigation] `Reach` and `ReachLeaveFront`
369    /// in addition to the regular `Leave`, `ReachLeaveBack` or
370    /// `Regular`.
371    ///
372    /// If no field has the focus the first navigable one gets it.
373    ///
374    /// Sets the focus, gained and lost flags. If this ends up with
375    /// the same widget as before focus, gained and lost flag are not set.
376    #[inline]
377    pub fn next_force(&self) -> bool {
378        match self.navigation() {
379            None => {
380                self.first();
381                true
382            }
383            Some(
384                Navigation::Leave
385                | Navigation::Reach
386                | Navigation::ReachLeaveFront
387                | Navigation::ReachLeaveBack
388                | Navigation::Regular,
389            ) => {
390                focus_debug!(
391                    self.core,
392                    "force next after {:?}",
393                    self.core.focused().map(|v| v.name().to_string())
394                );
395                self.core.next()
396            }
397            v => {
398                focus_debug!(
399                    self.core,
400                    "force next after {:?}, but navigation says {:?}",
401                    self.core.focused().map(|v| v.name().to_string()),
402                    v
403                );
404                false
405            }
406        }
407    }
408
409    /// Focus the previous widget in the cycle.
410    ///
411    /// Applies some extra force to this action and allows
412    /// leaving widgets that have [Navigation] `Reach` and `ReachLeaveBack`
413    /// in addition to the regular `Leave`, `ReachLeaveFront` or
414    /// `Regular`.
415    ///
416    /// If no field has the focus the first navigable one gets it.
417    ///
418    /// Sets the focus, gained and lost flags. If this ends up with
419    /// the same widget as before focus, gained and lost flag are not set.
420    #[inline]
421    pub fn prev_force(&self) -> bool {
422        match self.navigation() {
423            None => {
424                self.first();
425                true
426            }
427            Some(
428                Navigation::Leave
429                | Navigation::Reach
430                | Navigation::ReachLeaveFront
431                | Navigation::ReachLeaveBack
432                | Navigation::Regular,
433            ) => {
434                focus_debug!(
435                    self.core,
436                    "force prev before {:?}",
437                    self.core.focused().map(|v| v.name().to_string())
438                );
439                self.core.prev()
440            }
441            v => {
442                focus_debug!(
443                    self.core,
444                    "force prev before {:?}, but navigation says {:?}",
445                    self.core.focused().map(|v| v.name().to_string()),
446                    v
447                );
448                false
449            }
450        }
451    }
452
453    /// Is this widget part of this focus-cycle?
454    #[inline(always)]
455    pub fn is_valid_widget(&self, widget_state: &'_ dyn HasFocus) -> bool {
456        self.core.is_widget(&widget_state.focus())
457    }
458
459    /// Is this a container that is part of this focus-cycle?
460    #[inline(always)]
461    pub fn is_valid_container(&self, widget_state: &'_ dyn HasFocus) -> bool {
462        self.core.is_container(&widget_state.focus())
463    }
464
465    /// Returns the focused widget as FocusFlag.
466    ///
467    /// For control-flow [crate::match_focus] or [crate::on_gained] or [crate::on_lost]
468    /// will be nicer.
469    #[inline(always)]
470    pub fn focused(&self) -> Option<FocusFlag> {
471        self.core.focused()
472    }
473
474    /// Returns the focused widget as widget-id.
475    ///
476    /// For control-flow [crate::match_focus] or [crate::on_gained] or [crate::on_lost]
477    /// will be nicer.
478    #[inline(always)]
479    pub fn focused_widget_id(&self) -> Option<usize> {
480        self.core.focused().map(|v| v.id())
481    }
482
483    /// Returns the debug name of the focused widget.
484    #[inline(always)]
485    pub fn focused_name(&self) -> Option<String> {
486        self.core.focused().map(|v| v.name().to_string())
487    }
488
489    /// Returns the [Navigation] flag for the focused widget.
490    #[inline(always)]
491    pub fn navigation(&self) -> Option<Navigation> {
492        self.core.navigation()
493    }
494
495    /// Returns the widget that lost the focus as FocusFlag.
496    ///
497    /// For control-flow [crate::match_focus] or [crate::on_gained] or [crate::on_lost]
498    /// will be nicer.
499    #[inline(always)]
500    pub fn lost_focus(&self) -> Option<FocusFlag> {
501        self.core.lost_focus()
502    }
503
504    /// Returns the widget that gained the focus as FocusFlag.
505    ///
506    /// For control-flow [crate::match_focus] or [crate::on_gained] or [crate::on_lost]
507    /// will be nicer.
508    #[inline(always)]
509    pub fn gained_focus(&self) -> Option<FocusFlag> {
510        self.core.gained_focus()
511    }
512
513    /// Sets the focus to the given widget, but doesn't set
514    /// lost and gained. This can be used to prevent any side
515    /// effects that use the gained/lost state.
516    ///
517    /// This changes the focus and the gained/lost flags.
518    /// If this ends up with the same widget as before
519    /// gained and lost flags are not set.
520    ///
521    /// This will ignore the [Navigation] flag of the
522    /// currently focused widget.
523    ///
524    /// You can also use a container-widget for this.
525    /// It will set the focus to the first widget of the
526    /// container.
527    #[inline]
528    pub fn focus_no_lost(&self, widget_state: &'_ dyn HasFocus) {
529        focus_debug!(self.core, "focus no_lost {:?}", widget_state.focus().name());
530        let flag = widget_state.focus();
531        if self.core.is_widget(&flag) {
532            if let Some(n) = self.core.index_of(&flag) {
533                self.core.focus_idx(n, false);
534            } else {
535                panic!("    => invalid widget");
536            }
537        } else if self.core.is_container(&flag) {
538            self.core.first_container(&flag);
539        } else {
540            focus_fail!(self.core, "    => not a valid widget");
541        }
542    }
543
544    /// This expels the focus from the given widget/container.
545    ///
546    /// This is sometimes useful to set the focus to **somewhere else**.
547    /// This is especially useful when used for a container-widget that will
548    /// be hidden. Ensures there is still some widget with focus afterward.
549    ///
550    /// It will try to set the focus to the next widget or the
551    /// next widget following the container. If this ends up within
552    /// the given container it will set the focus to none.
553    ///
554    /// This function doesn't use the Navigation of the current widget.
555    #[inline]
556    pub fn expel_focus(&self, widget_state: &'_ dyn HasFocus) {
557        focus_debug!(
558            self.core,
559            "expel from widget {:?}",
560            widget_state.focus().name()
561        );
562        let flag = widget_state.focus();
563        if self.core.is_widget(&flag) {
564            if self.core.index_of(&flag).is_some() {
565                if widget_state.is_focused() {
566                    self.core.next();
567                    if widget_state.is_focused() {
568                        focus_debug!(self.core, "    -> no other focus, cleared");
569                        flag.clear();
570                    } else {
571                        focus_debug!(self.core, "    -> expelled");
572                    }
573                } else {
574                    focus_debug!(self.core, "    => widget not focused");
575                }
576            } else {
577                panic!("    => invalid widget");
578            }
579        } else if self.core.is_container(&flag) {
580            if flag.is_focused() {
581                self.core.expel_container(flag);
582            } else {
583                focus_debug!(self.core, "    => container not focused");
584            }
585        } else {
586            focus_fail!(self.core, "    => not a valid widget");
587        }
588    }
589
590    /// Dynamic change of the widget structure for a container widget.
591    ///
592    /// This is only necessary if your widget structure changes
593    /// during event-handling, and you need a programmatic
594    /// focus-change for the new structure.
595    ///
596    /// This resets the focus-flags of the removed container.
597    pub fn remove_container(&mut self, container: &'_ dyn HasFocus) {
598        focus_debug!(
599            self.core,
600            "focus remove container {:?} ",
601            container.focus().name()
602        );
603        let flag = container.focus();
604        if self.core.is_container(&flag) {
605            if let Some((cidx, _)) = self.core.container_index_of(&flag) {
606                self.core.remove_container(cidx).reset();
607                focus_debug!(self.core, "    -> removed");
608            } else {
609                panic!("    => invalid container?");
610            }
611        } else {
612            focus_fail!(self.core, "    => no container flag");
613        }
614    }
615
616    /// Dynamic change of the widget structure for a container.
617    ///
618    /// This is only necessary if your widget structure changes
619    /// during event-handling, and you need a programmatic
620    /// focus-change for the new structure.
621    ///
622    /// If the widget that currently has the focus is still
623    /// part of the widget structure it keeps the focus.
624    /// The focus-flags for all widgets that are no longer part
625    /// of the widget structure are reset.
626    pub fn update_container(&mut self, container: &'_ dyn HasFocus) {
627        focus_debug!(
628            self.core,
629            "focus update container {:?} ",
630            container.focus().name()
631        );
632        let flag = container.focus();
633        if self.core.is_container(&flag) {
634            if let Some((cidx, range)) = self.core.container_index_of(&flag) {
635                let removed = self.core.remove_container(cidx);
636
637                let mut b = FocusBuilder::new(Some(Focus {
638                    last: Default::default(),
639                    core: removed,
640                }));
641                b.widget(container);
642                let insert = b.build();
643
644                self.core.insert_container(range.start, cidx, insert.core);
645
646                focus_debug!(self.core, "    -> updated");
647            } else {
648                panic!("    => invalid container?");
649            }
650        } else {
651            focus_fail!(self.core, "    => no container flag");
652        }
653    }
654
655    /// Dynamic change of the widget structure of a container.
656    ///
657    /// This is only necessary if your widget structure changes
658    /// during event-handling, and you need a programmatic
659    /// focus-change.
660    ///
661    /// This removes the widgets of one container and inserts
662    /// the widgets of the other one in place.
663    ///
664    /// If the widget that currently has the focus is still
665    /// part of the widget structure it keeps the focus.
666    /// The focus-flags for all widgets that are no longer part
667    /// of the widget structure are reset.
668    pub fn replace_container(&mut self, container: &'_ dyn HasFocus, new: &'_ dyn HasFocus) {
669        focus_debug!(
670            self.core,
671            "focus replace container {:?} with {:?} ",
672            container.focus().name(),
673            new.focus().name()
674        );
675        let flag = container.focus();
676        if self.core.is_container(&flag) {
677            if let Some((cidx, range)) = self.core.container_index_of(&flag) {
678                let removed = self.core.remove_container(cidx);
679
680                let mut b = FocusBuilder::new(Some(Focus {
681                    last: Default::default(),
682                    core: removed,
683                }));
684                b.widget(new);
685                let insert = b.build();
686
687                self.core.insert_container(range.start, cidx, insert.core);
688
689                focus_debug!(self.core, "    -> replaced");
690            } else {
691                panic!("    => invalid container");
692            }
693        } else {
694            focus_fail!(self.core, "    => no container flag");
695        }
696    }
697
698    /// Reset lost + gained flags.
699    ///
700    /// This is done automatically during event-handling.
701    /// Lost+Gained flags will only be set while handling
702    /// the original event that made the focus-change.
703    /// The next event, whatever it is, will reset these flags.
704    #[inline(always)]
705    pub fn reset_lost_gained(&self) {
706        self.core.reset_lost_gained();
707    }
708
709    /// Debug destructuring.
710    #[allow(clippy::type_complexity)]
711    pub fn clone_destruct(
712        &self,
713    ) -> (
714        Vec<FocusFlag>,
715        Vec<bool>,
716        Vec<(Rect, u16)>,
717        Vec<Navigation>,
718        Vec<(FocusFlag, (Rect, u16), Range<usize>)>,
719    ) {
720        self.core.clone_destruct()
721    }
722}
723
724impl HandleEvent<Event, Regular, Outcome> for Focus {
725    #[inline(always)]
726    fn handle(&mut self, event: &Event, _keymap: Regular) -> Outcome {
727        match event {
728            ct_event!(keycode press Tab) => {
729                focus_debug!(
730                    self.core,
731                    "Tab {:?}",
732                    self.focused().map(|v| v.name().to_string())
733                );
734                let r = if self.next() {
735                    Outcome::Changed
736                } else {
737                    Outcome::Continue
738                };
739                focus_debug!(
740                    self.core,
741                    "    -> {:?} {:?}",
742                    r,
743                    self.focused().map(|v| v.name().to_string())
744                );
745                r
746            }
747            ct_event!(keycode press SHIFT-Tab) | ct_event!(keycode press SHIFT-BackTab) => {
748                focus_debug!(
749                    self.core,
750                    "BackTab {:?}",
751                    self.focused().map(|v| v.name().to_string())
752                );
753                let r = if self.prev() {
754                    Outcome::Changed
755                } else {
756                    Outcome::Continue
757                };
758                focus_debug!(
759                    self.core,
760                    "    -> {:?} {:?}",
761                    r,
762                    self.focused().map(|v| v.name().to_string())
763                );
764                r
765            }
766            _ => self.handle(event, MouseOnly),
767        }
768    }
769}
770
771impl HandleEvent<Event, MouseOnly, Outcome> for Focus {
772    #[inline(always)]
773    fn handle(&mut self, event: &Event, _keymap: MouseOnly) -> Outcome {
774        match event {
775            Event::Mouse(crossterm::event::MouseEvent {
776                kind: crossterm::event::MouseEventKind::Drag(_),
777                ..
778            }) => {
779                self.reset_mouse_focus();
780            }
781            Event::Mouse(crossterm::event::MouseEvent {
782                kind:
783                    crossterm::event::MouseEventKind::Moved
784                    | crossterm::event::MouseEventKind::Down(_)
785                    | crossterm::event::MouseEventKind::Up(_)
786                    | crossterm::event::MouseEventKind::ScrollDown
787                    | crossterm::event::MouseEventKind::ScrollUp
788                    | crossterm::event::MouseEventKind::ScrollLeft
789                    | crossterm::event::MouseEventKind::ScrollRight,
790                column: c,
791                row: r,
792                ..
793            }) => {
794                self.mouse_focus(*c, *r);
795            }
796            _ => {}
797        };
798
799        match event {
800            ct_event!(mouse down Left for column, row) => {
801                if self.focus_at(*column, *row) {
802                    Outcome::Changed
803                } else {
804                    self.reset_lost_gained();
805                    Outcome::Continue
806                }
807            }
808            _ => {
809                self.reset_lost_gained();
810                Outcome::Continue
811            }
812        }
813    }
814}
815
816/// Handle all events.
817#[inline(always)]
818pub fn handle_focus(focus: &mut Focus, event: &Event) -> Outcome {
819    HandleEvent::handle(focus, event, Regular)
820}