1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
//! Pointer-cursor model.
//!
//! Widgets opt into a non-default cursor by setting [`crate::tree::El::cursor`].
//! Per-frame the host runner reads [`crate::state::UiState::cursor`] and forwards
//! the resolved value to the windowing backend (winit's
//! `Window::set_cursor_icon`, the browser's `canvas.style.cursor`).
//!
//! The variants line up with the CSS `cursor` property — same names
//! winit's `CursorIcon` already uses — so backend bridges are dumb
//! `From` impls.
//!
//! # Resolution
//!
//! [`crate::state::UiState::cursor`] picks the active cursor each frame:
//!
//! 1. If a press is captured (button drag, slider thumb, scrollbar
//! drag, text selection, …), the cursor follows the *press target*'s
//! declared cursor and ignores whatever the pointer is currently
//! over. Drag off a button onto a text input and the cursor stays
//! [`Cursor::Pointer`] — matches native press-and-hold behaviour.
//! 2. Else the hovered node and its ancestors are walked root-ward,
//! returning the first explicit `.cursor(...)`. So a panel that
//! sets `.cursor(Move)` once propagates to children that don't
//! override.
//! 3. Else [`Cursor::Default`].
//!
//! Disabled state is *not* auto-mapped to [`Cursor::NotAllowed`] —
//! widgets that want that affordance branch in their build closure.
/// Pointer cursor. Variant names mirror CSS `cursor` so the
/// backend mapping is a 1:1 translation.