zng_wgt_input/
pointer_capture.rs
1use 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 pub fn got_pointer_capture {
15 event: POINTER_CAPTURE_EVENT,
16 args: PointerCaptureArgs,
17 filter: |args| args.is_got(WIDGET.id()),
18 }
19
20 pub fn lost_pointer_capture {
22 event: POINTER_CAPTURE_EVENT,
23 args: PointerCaptureArgs,
24 filter: |args| args.is_lost(WIDGET.id()),
25 }
26
27 pub fn pointer_capture_changed {
29 event: POINTER_CAPTURE_EVENT,
30 args: PointerCaptureArgs,
31 }
32}
33
34#[property(CONTEXT, default(false))]
45pub fn capture_pointer(child: impl UiNode, mode: impl IntoVar<CaptureMode>) -> impl UiNode {
46 let mode = mode.into_var();
47 match_node(child, move |_, op| match op {
48 UiNodeOp::Init => {
49 WIDGET.sub_event(&MOUSE_INPUT_EVENT).sub_event(&TOUCH_INPUT_EVENT).sub_var(&mode);
50 }
51 UiNodeOp::Event { update } => {
52 let mut capture = false;
53 if let Some(args) = MOUSE_INPUT_EVENT.on(update) {
54 capture = args.is_mouse_down();
55 } else if let Some(args) = TOUCH_INPUT_EVENT.on(update) {
56 capture = args.is_touch_start();
57 }
58
59 if capture {
60 let widget_id = WIDGET.id();
61
62 match mode.get() {
63 CaptureMode::Widget => {
64 POINTER_CAPTURE.capture_widget(widget_id);
65 }
66 CaptureMode::Subtree => {
67 POINTER_CAPTURE.capture_subtree(widget_id);
68 }
69 CaptureMode::Window => (),
70 }
71 }
72 }
73 UiNodeOp::Update { .. } => {
74 if let Some(new_mode) = mode.get_new() {
75 let tree = WINDOW.info();
76 let widget_id = WIDGET.id();
77 if tree.get(widget_id).map(|w| w.interactivity().is_enabled()).unwrap_or(false) {
78 if let Some(current) = POINTER_CAPTURE.current_capture().get() {
79 if current.target.widget_id() == widget_id {
80 match new_mode {
82 CaptureMode::Widget => POINTER_CAPTURE.capture_widget(widget_id),
83 CaptureMode::Subtree => POINTER_CAPTURE.capture_subtree(widget_id),
84 CaptureMode::Window => POINTER_CAPTURE.release_capture(),
85 }
86 }
87 }
88 }
89 }
90 }
91 _ => {}
92 })
93}
94
95#[property(CONTEXT, default(false))]
106pub fn capture_pointer_on_init(child: impl UiNode, mode: impl IntoVar<CaptureMode>) -> impl UiNode {
107 let mode = mode.into_var();
108 let mut capture = true;
109
110 match_node(child, move |_, op| match op {
111 UiNodeOp::Init => {
112 WIDGET.sub_var(&mode);
113 capture = true; }
115 UiNodeOp::Info { .. } => {
116 if std::mem::take(&mut capture) {
117 let widget_id = WIDGET.id();
118
119 match mode.get() {
120 CaptureMode::Widget => {
121 POINTER_CAPTURE.capture_widget(widget_id);
122 }
123 CaptureMode::Subtree => {
124 POINTER_CAPTURE.capture_subtree(widget_id);
125 }
126 CaptureMode::Window => (),
127 }
128 }
129 }
130 UiNodeOp::Update { .. } => {
131 if let Some(new_mode) = mode.get_new() {
132 let tree = WINDOW.info();
133 let widget_id = WIDGET.id();
134 if tree.get(widget_id).map(|w| w.interactivity().is_enabled()).unwrap_or(false) {
135 if let Some(current) = POINTER_CAPTURE.current_capture().get() {
136 if current.target.widget_id() == widget_id {
137 match new_mode {
139 CaptureMode::Widget => POINTER_CAPTURE.capture_widget(widget_id),
140 CaptureMode::Subtree => POINTER_CAPTURE.capture_subtree(widget_id),
141 CaptureMode::Window => POINTER_CAPTURE.release_capture(),
142 }
143 }
144 }
145 }
146 }
147 }
148 _ => {}
149 })
150}