zng/
focus.rs

1//! Focus service, properties, events and other types.
2//!
3//! # Keyboard Focus
4//!
5//! In an app instance only a single widget can receive keyboard input at a time, this widget has the *keyboard focus*.
6//! The operating system defines what window has keyboard focus and the app-process defines what widget has focus, these
7//! two systems work in conjunction to define the keyboard focus.
8//!
9//! You can track the focused widget by listening to the [`FOCUS_CHANGED_EVENT`] event or the [`FOCUS.focused`](FOCUS::focused)
10//! variable. The focus state of a widget can be tracked using the [`is_focused`](fn@is_focused), [`is_focus_within`](fn@is_focus_within),
11//! [`on_focus_changed`](fn@on_focus_changed) and other properties on this module.
12//!
13//! ```
14//! use zng::{focus, prelude::*};
15//!
16//! # fn example() {
17//!
18//! focus::FOCUS_CHANGED_EVENT
19//!     .on_pre_event(
20//!         true,
21//!         hn!(|args| {
22//!             println!("new_focus: {:?}", args.new_focus);
23//!         }),
24//!     )
25//!     .perm();
26//!
27//! # let _ =
28//! Stack!(
29//!     top_to_bottom,
30//!     5,
31//!     ui_vec![
32//!         Wgt! {
33//!             id = "subject";
34//!             focus::focusable = true;
35//!
36//!             layout::size = (100, 30);
37//!             widget::background_color = colors::RED;
38//!             when *#focus::is_focused {
39//!                 widget::background_color = colors::GREEN;
40//!             }
41//!
42//!             focus::on_focus = hn!(|_| {
43//!                 println!("subject on_focus");
44//!             });
45//!             focus::on_blur = hn!(|_| {
46//!                 println!("subject on_blur");
47//!             });
48//!         },
49//!         Button! {
50//!             child = Text!("Focus subject");
51//!             on_click = hn!(|_| {
52//!                 FOCUS.focus_widget("subject", /*highlight: */ false);
53//!             });
54//!         },
55//!         Text! {
56//!             txt = FOCUS.focused().map(|f| formatx!("focused {f:?}"));
57//!         }
58//!     ]
59//! )
60//! # ; }
61//! ```
62//!
63//! # Navigation
64//!
65//! The keyboard focus can be moved from one widget to the next using the keyboard or the [`FOCUS`] service methods.
66//! There are two styles of movement: [tabbing](#tab-navigation) that follows the logical order and [directional](#directional-navigation)
67//! that follows the visual order.
68//!
69//! Keyboard navigation behaves different depending on what region of the screen the current focused widget is in, these regions
70//! are called [focus scopes](#focus-scopes). Every window is a focus scope that can be subdivided further.
71//!
72//! ## Tab Navigation
73//!
74//! Tab navigation follows a logical order, the position of the widget in the [widget tree](FocusInfoTree),
75//! optionally overridden using [`tab_index`](fn@tab_index).
76//!
77//! Focus is moved forward by pressing `TAB` or calling [`FOCUS.focus_next`](FOCUS::focus_next) and backward by pressing `SHIFT+TAB` or
78//! calling [`FOCUS.focus_prev`](FOCUS::focus_prev).
79//!
80//! ## Directional Navigation
81//!
82//! Directional navigation follows the visual position of the widget on the screen.
83//!
84//! Focus is moved by pressing the **arrow keys** or calling the focus direction methods in the [`FOCUS`](FOCUS::focus_up) service.
85//!
86//! ## Focus Scopes
87//!
88//! Focus scopes are widgets that configure how focus navigation happens inside then. They control what happens
89//! when the scope widget is focused, how the navigation flows inside their screen region and even if the navigation
90//! can naturally mode out of their region.
91//!
92//! You can use the [`focus_scope`](fn@focus_scope) property on a widget to turn it into a focus scope and use
93//! the [`tab_nav`](fn@tab_nav), [`directional_nav`](fn@directional_nav) and other properties on this module to
94//! configure the focus scope.
95//!
96//! ### Alt Scopes
97//!
98//! Alt scopes are specially marked focus scopes that receive focus when the `ALT`
99//! key is pressed or [`FOCUS.focus_alt`](FOCUS::focus_alt) is called. The alt scope of a widget
100//! is selected by [`WidgetFocusInfo::alt_scope`].
101//!
102//! Alt scopes remember the previously focused widget as a [return focus](#return-focus). The focus returns ALT is pressed again,
103//! or [`FOCUS.focus_exit`](FOCUS::focus_exit) is called and the parent is the focus scope.
104//!
105//! ### Return Focus
106//!
107//! Focus scopes can be configured to remember the last focused widget inside then, the focus than **returns** to
108//! this widget when the scope receives focus. Alt scopes also remember the widget from which the *alt* focus happened
109//! and can also return focus back to that widget.
110//!
111//! You can track the return focus by listening to the [`RETURN_FOCUS_CHANGED_EVENT`] event or
112//! [`FOCUS.return_focused`](FOCUS::return_focused) variable. Usually the window root scope remembers
113//! return focus and some widgets, like text fields visually indicate that they will be focused when the window
114//! is focused.
115//!
116//! You can use the [`focus_scope_behavior`](fn@focus_scope_behavior) property to configure a custom focus scope
117//! to remember the return focus.
118//!
119//! # Configuring Widgets
120//!
121//! Focusable configuration is set as info metadata using the [`FocusInfoBuilder`]. You can use this type to make a widget
122//! focusable or a focus scope and customize how the focus manager interacts with the widget.
123//!
124//! Note that the main crate already provides properties for configuring focus in widgets, you only need to
125//! set the [`FocusInfoBuilder`] directly if you are developing your own focus defining properties.
126//!
127//! # Querying
128//!
129//! Focus information exists as metadata associated with a window widget tree. This metadata can be manually queried by
130//! creating a [`FocusInfoTree`] or directly from a widget info by using the [`WidgetInfoFocusExt`] extension methods.
131//!
132//! # Full API
133//!
134//! See [`zng_ext_input::focus`] and [`zng_wgt_input::focus`] for the full focus API.
135
136pub use zng_ext_input::focus::{
137    DirectionalNav, FOCUS, FOCUS_CHANGED_EVENT, FocusChangedArgs, FocusChangedCause, FocusInfo, FocusInfoBuilder, FocusInfoTree,
138    FocusNavAction, FocusRequest, FocusScopeOnFocus, FocusTarget, RETURN_FOCUS_CHANGED_EVENT, ReturnFocusChangedArgs, TabIndex, TabNav,
139    WidgetFocusInfo, WidgetInfoFocusExt, cmd, iter,
140};
141pub use zng_wgt_input::focus::{
142    FocusClickBehavior, FocusableMix, alt_focus_scope, directional_nav, focus_click_behavior, focus_highlight, focus_on_init, focus_scope,
143    focus_scope_behavior, focus_shortcut, focusable, is_focus_within, is_focus_within_hgl, is_focused, is_focused_hgl, is_return_focus,
144    is_return_focus_within, on_blur, on_focus, on_focus_changed, on_focus_enter, on_focus_leave, on_pre_blur, on_pre_focus,
145    on_pre_focus_changed, on_pre_focus_enter, on_pre_focus_leave, return_focus_on_deinit, skip_directional, tab_index, tab_nav,
146};