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