zng_wgt_input/
pointer_capture.rs1use zng_ext_input::{
4 mouse::MOUSE_INPUT_EVENT,
5 pointer_capture::{POINTER_CAPTURE, POINTER_CAPTURE_EVENT, PointerCaptureArgs},
6 touch::TOUCH_INPUT_EVENT,
7};
8use zng_wgt::prelude::*;
9
10pub use zng_ext_input::pointer_capture::CaptureMode;
11
12event_property! {
13 #[property(EVENT)]
15 pub fn on_got_pointer_capture<on_pre_got_pointer_capture>(child: impl IntoUiNode, handler: Handler<PointerCaptureArgs>) -> UiNode {
16 const PRE: bool;
17 EventNodeBuilder::new(POINTER_CAPTURE_EVENT)
18 .filter(|| {
19 let id = WIDGET.id();
20 move |args| args.is_got(id)
21 })
22 .build::<PRE>(child, handler)
23 }
24
25 #[property(EVENT)]
27 pub fn on_lost_pointer_capture<on_pre_lost_pointer_capture>(
28 child: impl IntoUiNode,
29 handler: Handler<PointerCaptureArgs>,
30 ) -> UiNode {
31 const PRE: bool;
32 EventNodeBuilder::new(POINTER_CAPTURE_EVENT)
33 .filter(|| {
34 let id = WIDGET.id();
35 move |args| args.is_lost(id)
36 })
37 .build::<PRE>(child, handler)
38 }
39
40 #[property(EVENT)]
42 pub fn on_pointer_capture_changed<on_pre_pointer_capture_changed>(
43 child: impl IntoUiNode,
44 handler: Handler<PointerCaptureArgs>,
45 ) -> UiNode {
46 const PRE: bool;
47 EventNodeBuilder::new(POINTER_CAPTURE_EVENT).build::<PRE>(child, handler)
48 }
49}
50
51#[property(CONTEXT, default(false))]
62pub fn capture_pointer(child: impl IntoUiNode, mode: impl IntoVar<CaptureMode>) -> UiNode {
63 let mode = mode.into_var();
64 match_node(child, move |_, op| match op {
65 UiNodeOp::Init => {
66 WIDGET.sub_event(&MOUSE_INPUT_EVENT).sub_event(&TOUCH_INPUT_EVENT).sub_var(&mode);
67 }
68 UiNodeOp::Update { .. } => {
69 if let Some(new_mode) = mode.get_new() {
70 let tree = WINDOW.info();
71 let widget_id = WIDGET.id();
72 if tree.get(widget_id).map(|w| w.interactivity().is_enabled()).unwrap_or(false)
73 && let Some(current) = POINTER_CAPTURE.current_capture().get()
74 && current.target.widget_id() == widget_id
75 {
76 match new_mode {
78 CaptureMode::Widget => POINTER_CAPTURE.capture_widget(widget_id),
79 CaptureMode::Subtree => POINTER_CAPTURE.capture_subtree(widget_id),
80 CaptureMode::Window => POINTER_CAPTURE.release_capture(),
81 }
82 }
83 }
84 if MOUSE_INPUT_EVENT.latest_update(true, |a| a.is_mouse_down()).unwrap_or(false)
85 || TOUCH_INPUT_EVENT.latest_update(true, |a| a.is_touch_start()).unwrap_or(false)
86 {
87 let widget_id = WIDGET.id();
88
89 match mode.get() {
90 CaptureMode::Widget => {
91 POINTER_CAPTURE.capture_widget(widget_id);
92 }
93 CaptureMode::Subtree => {
94 POINTER_CAPTURE.capture_subtree(widget_id);
95 }
96 CaptureMode::Window => (),
97 }
98 }
99 }
100 _ => {}
101 })
102}
103
104#[property(CONTEXT, default(false))]
115pub fn capture_pointer_on_init(child: impl IntoUiNode, mode: impl IntoVar<CaptureMode>) -> UiNode {
116 let mode = mode.into_var();
117 let mut capture = true;
118
119 match_node(child, move |_, op| match op {
120 UiNodeOp::Init => {
121 WIDGET.sub_var(&mode);
122 capture = true; }
124 UiNodeOp::Info { .. } => {
125 if std::mem::take(&mut capture) {
126 let widget_id = WIDGET.id();
127
128 match mode.get() {
129 CaptureMode::Widget => {
130 POINTER_CAPTURE.capture_widget(widget_id);
131 }
132 CaptureMode::Subtree => {
133 POINTER_CAPTURE.capture_subtree(widget_id);
134 }
135 CaptureMode::Window => (),
136 }
137 }
138 }
139 UiNodeOp::Update { .. } => {
140 if let Some(new_mode) = mode.get_new() {
141 let tree = WINDOW.info();
142 let widget_id = WIDGET.id();
143 if tree.get(widget_id).map(|w| w.interactivity().is_enabled()).unwrap_or(false)
144 && let Some(current) = POINTER_CAPTURE.current_capture().get()
145 && current.target.widget_id() == widget_id
146 {
147 match new_mode {
149 CaptureMode::Widget => POINTER_CAPTURE.capture_widget(widget_id),
150 CaptureMode::Subtree => POINTER_CAPTURE.capture_subtree(widget_id),
151 CaptureMode::Window => POINTER_CAPTURE.release_capture(),
152 }
153 }
154 }
155 }
156 _ => {}
157 })
158}