1use std::{collections::HashMap, mem, num::NonZeroU32, ops, time::Duration};
6use zng_app::{
7 AppExtension, DInstant,
8 event::{AnyEventArgs, EventPropagationHandle, event, event_args},
9 shortcut::ModifiersState,
10 timer::{DeadlineVar, TIMERS},
11 update::EventUpdate,
12 view_process::{
13 VIEW_PROCESS_INITED_EVENT,
14 raw_device_events::DeviceId,
15 raw_events::{RAW_FRAME_RENDERED_EVENT, RAW_MOUSE_LEFT_EVENT, RAW_TOUCH_CONFIG_CHANGED_EVENT, RAW_TOUCH_EVENT, RawTouchArgs},
16 },
17 widget::{
18 WIDGET, WidgetId,
19 info::{HitTestInfo, InteractionPath, WIDGET_INFO_CHANGED_EVENT},
20 },
21 window::WindowId,
22};
23
24use zng_app_context::app_local;
25use zng_ext_window::{NestedWindowWidgetInfoExt as _, WINDOWS};
26use zng_layout::unit::{
27 AngleRadian, Dip, DipPoint, DipToPx, DipVector, Factor, Px, PxPoint, PxToDip, PxTransform, PxVector, TimeUnits, euclid,
28};
29use zng_var::{ArcVar, ReadOnlyArcVar, Var, impl_from_and_into_var, types::ArcCowVar, var};
30pub use zng_view_api::{
31 config::TouchConfig,
32 touch::{TouchForce, TouchId, TouchPhase, TouchUpdate},
33};
34
35use crate::{
36 keyboard::MODIFIERS_CHANGED_EVENT,
37 pointer_capture::{CaptureInfo, POINTER_CAPTURE, POINTER_CAPTURE_EVENT},
38};
39
40#[derive(Default)]
59pub struct TouchManager {
60 modifiers: ModifiersState,
61 pressed: HashMap<TouchId, PressedInfo>,
62 tap_gesture: TapGesture,
63 transform_gesture: TransformGesture,
64 long_press_gesture: LongPressGesture,
65 mouse_touch: Option<TouchId>,
66}
67struct PressedInfo {
68 touch_propagation: EventPropagationHandle,
69 target: InteractionPath,
70 device_id: DeviceId,
71 position: DipPoint,
72 force: Option<TouchForce>,
73 hits: HitTestInfo,
74 velocity_samples: Vec<(DInstant, DipPoint)>,
75}
76impl PressedInfo {
77 fn push_velocity_sample(&mut self, timestamp: DInstant, position: DipPoint) {
78 if let Some(last) = self.velocity_samples.last_mut() {
79 if timestamp.duration_since(last.0) < 1.ms() {
80 last.1 = position;
81 return;
82 }
83 }
84
85 if self.velocity_samples.len() == 4 {
86 self.velocity_samples.remove(0);
87 }
88 self.velocity_samples.push((timestamp, position));
89 }
90
91 fn velocity(&self) -> DipVector {
92 if self.velocity_samples.len() < 4 {
93 DipVector::zero()
94 } else {
95 let samples = [
96 self.velocity_samples[0].1.cast::<f64>(),
97 self.velocity_samples[1].1.cast(),
98 self.velocity_samples[2].1.cast(),
99 self.velocity_samples[3].1.cast(),
100 ];
101 let velocity_at = |end_i: usize| {
102 let start_i = end_i - 1;
103
104 let start_t = self.velocity_samples[start_i].0;
105 let end_t = self.velocity_samples[end_i].0;
106
107 let start_s = samples[start_i];
108 let end_s = samples[end_i];
109
110 let delta = (end_t - start_t).as_secs_f64();
111
112 if delta > 0.0 {
113 (end_s - start_s) / delta
114 } else {
115 euclid::vec2(0.0, 0.0)
116 }
117 };
118
119 let v23 = velocity_at(3) * 0.6;
120 let v12 = velocity_at(2) * 0.35;
121 let v01 = velocity_at(1) * 0.05;
122 let v = v23 + v12 + v01;
123
124 v.cast::<f32>().cast()
125 }
126 }
127}
128
129pub struct TOUCH;
141
142impl TOUCH {
143 pub fn touch_config(&self) -> ArcCowVar<TouchConfig, ArcVar<TouchConfig>> {
149 TOUCH_SV.read().touch_config.clone()
150 }
151
152 pub fn sys_touch_config(&self) -> ReadOnlyArcVar<TouchConfig> {
164 TOUCH_SV.read().sys_touch_config.read_only()
165 }
166
167 pub fn positions(&self) -> ReadOnlyArcVar<Vec<TouchPosition>> {
169 TOUCH_SV.read().positions.read_only()
170 }
171
172 pub fn touch_from_mouse_events(&self) -> ArcVar<bool> {
176 TOUCH_SV.read().touch_from_mouse_events.clone()
177 }
178}
179
180#[derive(Debug, Clone, PartialEq)]
186pub struct TouchPosition {
187 pub window_id: WindowId,
189 pub touch: TouchId,
191 pub position: DipPoint,
193
194 pub start_time: DInstant,
196 pub update_time: DInstant,
198}
199
200app_local! {
201 static TOUCH_SV: TouchService = {
202 let sys_touch_config = var(TouchConfig::default());
203 TouchService {
204 touch_config: sys_touch_config.cow(),
205 sys_touch_config,
206 positions: var(vec![]),
207 touch_from_mouse_events: var(false),
208 }
209 };
210}
211struct TouchService {
212 touch_config: ArcCowVar<TouchConfig, ArcVar<TouchConfig>>,
213 sys_touch_config: ArcVar<TouchConfig>,
214 positions: ArcVar<Vec<TouchPosition>>,
215 touch_from_mouse_events: ArcVar<bool>,
216}
217
218#[derive(Debug, Clone)]
220pub struct TouchMove {
221 pub touch: TouchId,
227
228 pub touch_propagation: EventPropagationHandle,
232
233 pub moves: Vec<(DipPoint, Option<TouchForce>)>,
237
238 pub velocity: DipVector,
242
243 pub hits: HitTestInfo,
245
246 pub target: InteractionPath,
248}
249impl TouchMove {
250 pub fn position(&self) -> DipPoint {
252 self.moves.last().map(|(p, _)| *p).unwrap_or_else(DipPoint::zero)
253 }
254}
255
256event_args! {
257 pub struct TouchMoveArgs {
259 pub window_id: WindowId,
261
262 pub device_id: DeviceId,
264
265 pub touches: Vec<TouchMove>,
270
271 pub capture: Option<CaptureInfo>,
273
274 pub modifiers: ModifiersState,
276
277 ..
278
279 fn delivery_list(&self, list: &mut UpdateDeliveryList) {
283 for t in &self.touches {
284 list.insert_wgt(&t.target);
285 }
286 if let Some(c) = &self.capture {
287 list.insert_wgt(&c.target);
288 }
289 }
290 }
291
292 pub struct TouchInputArgs {
294 pub window_id: WindowId,
296
297 pub device_id: DeviceId,
299
300 pub touch: TouchId,
306
307 pub touch_propagation: EventPropagationHandle,
324
325 pub position: DipPoint,
327
328 pub force: Option<TouchForce>,
330
331 pub velocity: DipVector,
338
339 pub phase: TouchPhase,
343
344 pub hits: HitTestInfo,
346
347 pub target: InteractionPath,
349
350 pub capture: Option<CaptureInfo>,
352
353 pub modifiers: ModifiersState,
355
356 ..
357
358 fn delivery_list(&self, list: &mut UpdateDeliveryList) {
363 list.insert_wgt(&self.target);
364 if let Some(c) = &self.capture {
365 list.insert_wgt(&c.target);
366 }
367 }
368 }
369
370 pub struct TouchedArgs {
372 pub window_id: WindowId,
374
375 pub device_id: Option<DeviceId>,
377
378 pub touch: TouchId,
384
385 pub touch_propagation: EventPropagationHandle,
389
390 pub position: DipPoint,
392
393 pub force: Option<TouchForce>,
395
396 pub phase: TouchPhase,
398
399 pub hits: HitTestInfo,
401
402 pub prev_target: Option<InteractionPath>,
404
405 pub target: Option<InteractionPath>,
407
408 pub prev_capture: Option<CaptureInfo>,
410
411 pub capture: Option<CaptureInfo>,
413
414 ..
415
416 fn delivery_list(&self, list: &mut UpdateDeliveryList) {
422 if let Some(p) = &self.prev_target {
423 list.insert_wgt(p);
424 }
425 if let Some(p) = &self.target {
426 list.insert_wgt(p);
427 }
428 if let Some(c) = &self.capture {
429 list.insert_wgt(&c.target);
430 }
431 }
432 }
433
434 pub struct TouchTapArgs {
436 pub window_id: WindowId,
438
439 pub device_id: DeviceId,
441
442 pub touch: TouchId,
448
449 pub position: DipPoint,
451
452 pub hits: HitTestInfo,
454
455 pub target: InteractionPath,
457
458 pub modifiers: ModifiersState,
460
461 pub tap_count: NonZeroU32,
463
464 ..
465
466 fn delivery_list(&self, list: &mut UpdateDeliveryList) {
470 list.insert_wgt(&self.target);
471 }
472 }
473
474 pub struct TouchLongPressArgs {
476 pub window_id: WindowId,
478
479 pub device_id: DeviceId,
481
482 pub touch: TouchId,
488
489 pub position: DipPoint,
491
492 pub hits: HitTestInfo,
494
495 pub target: InteractionPath,
497
498 pub modifiers: ModifiersState,
500
501 pub start_time: DInstant,
503
504 ..
505
506 fn delivery_list(&self, list: &mut UpdateDeliveryList) {
510 list.insert_wgt(&self.target);
511 }
512 }
513
514 pub struct TouchTransformArgs {
516 pub window_id: WindowId,
518
519 pub device_id: DeviceId,
521
522 pub first_info: TouchTransformInfo,
524
525 pub latest_info: TouchTransformInfo,
527
528 pub velocity: [PxVector; 2],
530
531 pub scale_factor: Factor,
535
536 pub phase: TouchPhase,
538
539 pub hits: HitTestInfo,
542
543 pub target: InteractionPath,
545
546 pub capture: Option<CaptureInfo>,
548
549 pub modifiers: ModifiersState,
551
552 ..
553
554 fn delivery_list(&self, list: &mut UpdateDeliveryList) {
559 list.insert_wgt(&self.target);
560 if let Some(c) = &self.capture {
561 list.insert_wgt(&c.target);
562 }
563 }
564 }
565}
566
567impl TouchMoveArgs {
568 pub fn capture_allows(&self) -> bool {
574 self.capture.as_ref().map(|c| c.allows()).unwrap_or(true)
575 }
576}
577
578impl TouchInputArgs {
579 pub fn capture_allows(&self) -> bool {
585 self.capture.as_ref().map(|c| c.allows()).unwrap_or(true)
586 }
587
588 pub fn is_enabled(&self, widget_id: WidgetId) -> bool {
592 self.target.interactivity_of(widget_id).map(|i| i.is_enabled()).unwrap_or(false)
593 }
594
595 pub fn is_disabled(&self, widget_id: WidgetId) -> bool {
599 self.target.interactivity_of(widget_id).map(|i| i.is_disabled()).unwrap_or(false)
600 }
601
602 pub fn is_touch_start(&self) -> bool {
606 matches!(self.phase, TouchPhase::Start)
607 }
608
609 pub fn is_touch_end(&self) -> bool {
613 matches!(self.phase, TouchPhase::End)
614 }
615
616 pub fn is_touch_cancel(&self) -> bool {
620 matches!(self.phase, TouchPhase::Cancel)
621 }
622
623 pub fn inertia_x(&self, friction: Dip) -> (Dip, Duration) {
636 Self::inertia(self.velocity.x, friction)
637 }
638
639 pub fn inertia_y(&self, friction: Dip) -> (Dip, Duration) {
647 Self::inertia(self.velocity.y, friction)
648 }
649
650 fn inertia(velocity: Dip, friction: Dip) -> (Dip, Duration) {
651 let cfg = TOUCH.touch_config().get();
652 let signal = if velocity >= 0 { 1.0 } else { -1.0 };
653 let velocity = velocity.abs();
654
655 if velocity < cfg.min_fling_velocity {
656 (Dip::new(0), Duration::ZERO)
657 } else {
658 let velocity = velocity.min(cfg.max_fling_velocity).to_f32();
659 let friction = friction.to_f32();
660
661 let time = velocity / friction;
662 let offset = (velocity * time) - (friction * time);
663
664 (Dip::from(offset) * signal, time.secs())
665 }
666 }
667}
668
669impl TouchTapArgs {
670 pub fn is_enabled(&self, widget_id: WidgetId) -> bool {
674 self.target.interactivity_of(widget_id).map(|i| i.is_enabled()).unwrap_or(false)
675 }
676
677 pub fn is_disabled(&self, widget_id: WidgetId) -> bool {
681 self.target.interactivity_of(widget_id).map(|i| i.is_disabled()).unwrap_or(false)
682 }
683}
684
685impl TouchLongPressArgs {
686 pub fn is_enabled(&self, widget_id: WidgetId) -> bool {
690 self.target.interactivity_of(widget_id).map(|i| i.is_enabled()).unwrap_or(false)
691 }
692
693 pub fn is_disabled(&self, widget_id: WidgetId) -> bool {
697 self.target.interactivity_of(widget_id).map(|i| i.is_disabled()).unwrap_or(false)
698 }
699}
700
701impl TouchedArgs {
702 pub fn capture_allows(&self) -> bool {
708 self.capture.as_ref().map(|c| c.allows()).unwrap_or(true)
709 }
710
711 pub fn is_touch_move(&self) -> bool {
713 self.device_id.is_some()
714 }
715
716 pub fn is_widget_move(&self) -> bool {
718 self.device_id.is_none()
719 }
720
721 pub fn is_capture_change(&self) -> bool {
723 self.prev_capture != self.capture
724 }
725
726 pub fn is_touch_enter(&self) -> bool {
730 !self.was_touched() && self.is_touched()
731 }
732
733 pub fn is_touch_leave(&self) -> bool {
737 self.was_touched() && !self.is_touched()
738 }
739
740 pub fn is_touch_enter_enabled(&self) -> bool {
744 (!self.was_touched() || self.was_disabled(WIDGET.id())) && self.is_touched() && self.is_enabled(WIDGET.id())
745 }
746
747 pub fn is_touch_leave_enabled(&self) -> bool {
751 self.was_touched() && self.was_enabled(WIDGET.id()) && (!self.is_touched() || self.is_disabled(WIDGET.id()))
752 }
753
754 pub fn is_touch_enter_disabled(&self) -> bool {
758 (!self.was_touched() || self.was_enabled(WIDGET.id())) && self.is_touched() && self.is_disabled(WIDGET.id())
759 }
760
761 pub fn is_touch_leave_disabled(&self) -> bool {
765 self.was_touched() && self.was_disabled(WIDGET.id()) && (!self.is_touched() || self.is_enabled(WIDGET.id()))
766 }
767
768 pub fn was_touched(&self) -> bool {
774 if let Some(cap) = &self.prev_capture {
775 if !cap.allows() {
776 return false;
777 }
778 }
779
780 if let Some(t) = &self.prev_target {
781 return t.contains(WIDGET.id());
782 }
783
784 false
785 }
786
787 pub fn is_touched(&self) -> bool {
793 if let Some(cap) = &self.capture {
794 if !cap.allows() {
795 return false;
796 }
797 }
798
799 if let Some(t) = &self.target {
800 return t.contains(WIDGET.id());
801 }
802
803 false
804 }
805
806 pub fn was_enabled(&self, widget_id: WidgetId) -> bool {
810 self.prev_target
811 .as_ref()
812 .and_then(|t| t.interactivity_of(widget_id))
813 .map(|itr| itr.is_enabled())
814 .unwrap_or(false)
815 }
816
817 pub fn was_disabled(&self, widget_id: WidgetId) -> bool {
821 self.prev_target
822 .as_ref()
823 .and_then(|t| t.interactivity_of(widget_id))
824 .map(|itr| itr.is_disabled())
825 .unwrap_or(false)
826 }
827
828 pub fn is_enabled(&self, widget_id: WidgetId) -> bool {
832 self.target
833 .as_ref()
834 .and_then(|t| t.interactivity_of(widget_id))
835 .map(|itr| itr.is_enabled())
836 .unwrap_or(false)
837 }
838
839 pub fn is_disabled(&self, widget_id: WidgetId) -> bool {
843 self.target
844 .as_ref()
845 .and_then(|t| t.interactivity_of(widget_id))
846 .map(|itr| itr.is_disabled())
847 .unwrap_or(false)
848 }
849}
850
851impl TouchTransformArgs {
852 pub fn capture_allows(&self) -> bool {
858 self.capture.as_ref().map(|c| c.allows()).unwrap_or(true)
859 }
860
861 pub fn is_enabled(&self, widget_id: WidgetId) -> bool {
865 self.target.interactivity_of(widget_id).map(|i| i.is_enabled()).unwrap_or(false)
866 }
867
868 pub fn is_disabled(&self, widget_id: WidgetId) -> bool {
872 self.target.interactivity_of(widget_id).map(|i| i.is_disabled()).unwrap_or(false)
873 }
874
875 pub fn local_info(&self) -> [TouchTransformInfo; 2] {
881 let mut first = self.first_info.clone();
882 let mut latest = self.latest_info.clone();
883
884 let offset = WIDGET.bounds().inner_offset();
885
886 first -= offset;
887 latest -= offset;
888
889 [first, latest]
890 }
891
892 pub fn translation(&self) -> euclid::Vector2D<f32, Px> {
897 self.first_info.translation(&self.latest_info)
898 }
899
900 pub fn translation_x(&self) -> f32 {
905 self.first_info.translation_x(&self.latest_info)
906 }
907
908 pub fn translation_y(&self) -> f32 {
913 self.first_info.translation_y(&self.latest_info)
914 }
915
916 pub fn rotation(&self) -> AngleRadian {
921 self.first_info.rotation(&self.latest_info)
922 }
923
924 pub fn scale(&self) -> Factor {
929 self.first_info.scale(&self.latest_info)
930 }
931
932 pub fn scale_x(&self) -> Factor {
937 self.first_info.scale_x(&self.latest_info)
938 }
939
940 pub fn scale_y(&self) -> Factor {
945 self.first_info.scale_y(&self.latest_info)
946 }
947
948 pub fn transform(&self, mode: TouchTransformMode) -> PxTransform {
953 self.first_info.transform(&self.latest_info, mode)
954 }
955
956 pub fn local_transform(&self, mode: TouchTransformMode) -> PxTransform {
960 let [first, latest] = self.local_info();
961
962 let mut r = first.transform(&latest, mode);
963
964 if mode.contains(TouchTransformMode::ROTATE)
965 || mode.contains(TouchTransformMode::SCALE_X)
966 || mode.contains(TouchTransformMode::SCALE_Y)
967 {
968 let c = latest.center.to_vector();
969 r = PxTransform::Offset(-c).then(&r).then_translate(c);
970 }
971
972 r
973 }
974
975 pub fn translation_velocity(&self) -> PxVector {
977 (self.velocity[0] + self.velocity[1]) / Px(2)
978 }
979
980 pub fn translation_inertia_x(&self, deceleration: Dip) -> (Px, Duration) {
989 self.inertia((self.velocity[0].x + self.velocity[1].x) / Px(2), deceleration)
990 }
991
992 pub fn translation_inertia_y(&self, deceleration: Dip) -> (Px, Duration) {
1001 self.inertia((self.velocity[0].y + self.velocity[1].y) / Px(2), deceleration)
1002 }
1003
1004 pub fn is_start(&self) -> bool {
1013 matches!(self.phase, TouchPhase::Start)
1014 }
1015
1016 pub fn is_end(&self) -> bool {
1022 matches!(self.phase, TouchPhase::End)
1023 }
1024
1025 pub fn is_cancel(&self) -> bool {
1031 matches!(self.phase, TouchPhase::Cancel)
1032 }
1033
1034 fn inertia(&self, velocity: Px, deceleration: Dip) -> (Px, Duration) {
1035 let friction = deceleration.to_px(self.scale_factor);
1036 let cfg = TOUCH.touch_config().get();
1037 let min_fling_velocity = cfg.min_fling_velocity.to_px(self.scale_factor);
1038
1039 let signal = if velocity >= 0 { 1.0 } else { -1.0 };
1040 let velocity = velocity.abs();
1041
1042 if velocity < min_fling_velocity {
1043 (Px(0), Duration::ZERO)
1044 } else {
1045 let max_fling_velocity = cfg.max_fling_velocity.to_px(self.scale_factor);
1046 let velocity = velocity.min(max_fling_velocity).0 as f32;
1047 let friction = friction.0 as f32;
1048
1049 let time = velocity / friction;
1050 let offset = 0.5 * friction * time * time;
1051 (Px(offset.round() as _) * signal, time.secs())
1052 }
1053 }
1054}
1055
1056event! {
1057 pub static TOUCH_MOVE_EVENT: TouchMoveArgs;
1059
1060 pub static TOUCH_INPUT_EVENT: TouchInputArgs;
1062
1063 pub static TOUCHED_EVENT: TouchedArgs;
1065
1066 pub static TOUCH_TAP_EVENT: TouchTapArgs;
1071
1072 pub static TOUCH_TRANSFORM_EVENT: TouchTransformArgs;
1077
1078 pub static TOUCH_LONG_PRESS_EVENT: TouchLongPressArgs;
1085}
1086
1087impl AppExtension for TouchManager {
1088 fn event_preview(&mut self, update: &mut EventUpdate) {
1089 if let Some(args) = RAW_FRAME_RENDERED_EVENT.on(update) {
1090 self.continue_pressed(args.window_id);
1091 } else if let Some(args) = RAW_TOUCH_EVENT.on(update) {
1092 let mut pending_move: Vec<TouchMove> = vec![];
1093
1094 for u in &args.touches {
1095 if let TouchPhase::Move = u.phase {
1096 if let Some(e) = pending_move.iter_mut().find(|e| e.touch == u.touch) {
1097 e.moves.push((u.position, u.force));
1098 } else {
1099 pending_move.push(TouchMove {
1100 touch: u.touch,
1101 touch_propagation: if let Some(i) = self.pressed.get(&u.touch) {
1102 i.touch_propagation.clone()
1103 } else {
1104 let weird = EventPropagationHandle::new();
1105 weird.stop();
1106 weird
1107 },
1108 moves: vec![(u.position, u.force)],
1109 velocity: DipVector::zero(),
1110 hits: HitTestInfo::no_hits(args.window_id), target: InteractionPath::new(args.window_id, []),
1112 });
1113 }
1114 } else {
1115 self.on_move(args, mem::take(&mut pending_move));
1116 self.on_input(args, u);
1117 }
1118 }
1119
1120 self.on_move(args, pending_move);
1121 } else if let Some(args) = WIDGET_INFO_CHANGED_EVENT.on(update) {
1122 self.continue_pressed(args.window_id);
1123 } else if let Some(args) = MODIFIERS_CHANGED_EVENT.on(update) {
1124 self.modifiers = args.modifiers;
1125 } else if let Some(args) = RAW_TOUCH_CONFIG_CHANGED_EVENT.on(update) {
1126 TOUCH_SV.read().touch_config.set(args.config);
1127 } else if let Some(args) = VIEW_PROCESS_INITED_EVENT.on(update) {
1128 TOUCH_SV.read().touch_config.set(args.touch_config);
1129
1130 if args.is_respawn {
1131 self.tap_gesture.clear();
1132 self.transform_gesture.clear();
1133 self.long_press_gesture.clear();
1134 TOUCH_SV.read().positions.set(vec![]);
1135
1136 for (touch, info) in self.pressed.drain() {
1137 let args = TouchInputArgs::now(
1138 info.target.window_id(),
1139 info.device_id,
1140 touch,
1141 info.touch_propagation.clone(),
1142 DipPoint::splat(Dip::new(-1)),
1143 None,
1144 DipVector::zero(),
1145 TouchPhase::Cancel,
1146 HitTestInfo::no_hits(info.target.window_id()),
1147 info.target.clone(),
1148 None,
1149 ModifiersState::empty(),
1150 );
1151 TOUCH_INPUT_EVENT.notify(args);
1152
1153 let args = TouchedArgs::now(
1154 info.target.window_id(),
1155 info.device_id,
1156 touch,
1157 info.touch_propagation,
1158 DipPoint::splat(Dip::new(-1)),
1159 None,
1160 TouchPhase::Cancel,
1161 HitTestInfo::no_hits(info.target.window_id()),
1162 info.target,
1163 None,
1164 None,
1165 None,
1166 );
1167 TOUCHED_EVENT.notify(args);
1168 }
1169 }
1170 } else if TOUCH_SV.read().touch_from_mouse_events.get() {
1171 use super::mouse::*;
1172
1173 if let Some(args) = MOUSE_MOVE_EVENT.on(update) {
1174 if let Some(id) = self.mouse_touch {
1175 args.propagation().stop();
1176
1177 RAW_TOUCH_EVENT.notify(RawTouchArgs::now(
1178 args.window_id,
1179 args.device_id,
1180 vec![TouchUpdate {
1181 touch: id,
1182 phase: TouchPhase::Move,
1183 position: args.position,
1184 force: None,
1185 }],
1186 ));
1187 }
1188 } else if let Some(args) = MOUSE_INPUT_EVENT.on(update) {
1189 if args.button == super::mouse::MouseButton::Left {
1190 args.propagation().stop();
1191
1192 let phase = match args.state {
1193 ButtonState::Pressed => {
1194 if self.mouse_touch.is_some() {
1195 return;
1196 }
1197 self.mouse_touch = Some(TouchId(u64::MAX));
1198 TouchPhase::Start
1199 }
1200 ButtonState::Released => {
1201 if self.mouse_touch.is_none() {
1202 return;
1203 }
1204 self.mouse_touch = None;
1205 TouchPhase::End
1206 }
1207 };
1208
1209 RAW_TOUCH_EVENT.notify(RawTouchArgs::now(
1210 args.window_id,
1211 args.device_id.unwrap_or(DeviceId::new_unique()),
1212 vec![TouchUpdate {
1213 touch: TouchId(u64::MAX),
1214 phase,
1215 position: args.position,
1216 force: None,
1217 }],
1218 ));
1219 }
1220 } else if let Some(args) = RAW_MOUSE_LEFT_EVENT.on(update) {
1221 if let Some(id) = self.mouse_touch.take() {
1222 RAW_TOUCH_EVENT.notify(RawTouchArgs::now(
1223 args.window_id,
1224 args.device_id,
1225 vec![TouchUpdate {
1226 touch: id,
1227 phase: TouchPhase::Cancel,
1228 position: DipPoint::zero(),
1229 force: None,
1230 }],
1231 ))
1232 }
1233 }
1234 }
1235 }
1236
1237 fn event(&mut self, update: &mut EventUpdate) {
1238 if let Some(args) = TOUCH_INPUT_EVENT.on(update) {
1239 self.tap_gesture.on_input(args);
1240 self.transform_gesture.on_input(args);
1241 self.long_press_gesture.on_input(args);
1242 } else if let Some(args) = TOUCH_MOVE_EVENT.on(update) {
1243 self.tap_gesture.on_move(args);
1244 self.transform_gesture.on_move(args);
1245 self.long_press_gesture.on_move(args);
1246 } else if let Some(args) = POINTER_CAPTURE_EVENT.on(update) {
1247 for (touch, info) in &self.pressed {
1248 let args = TouchedArgs::now(
1249 info.target.window_id(),
1250 info.device_id,
1251 *touch,
1252 info.touch_propagation.clone(),
1253 info.position,
1254 info.force,
1255 TouchPhase::Move,
1256 info.hits.clone(),
1257 info.target.clone(),
1258 info.target.clone(),
1259 args.prev_capture.clone(),
1260 args.new_capture.clone(),
1261 );
1262 TOUCHED_EVENT.notify(args);
1263 }
1264 }
1265 }
1266
1267 fn update_preview(&mut self) {
1268 self.long_press_gesture.on_update();
1269 }
1270}
1271impl TouchManager {
1272 fn on_input(&mut self, args: &RawTouchArgs, update: &TouchUpdate) {
1273 if let Ok(w) = WINDOWS.widget_tree(args.window_id) {
1274 let mut hits = w.root().hit_test(update.position.to_px(w.scale_factor()));
1275 let mut target = hits
1276 .target()
1277 .and_then(|t| w.get(t.widget_id))
1278 .map(|t| t.interaction_path())
1279 .unwrap_or_else(|| w.root().interaction_path());
1280 let mut position = update.position;
1281
1282 if let Some(wgt) = w.get(target.widget_id()) {
1284 if let Some(w) = wgt.nested_window_tree() {
1285 let f = w.scale_factor();
1286 let p = update.position.to_px(f);
1287 let p = wgt.inner_transform().inverse().and_then(|t| t.transform_point(p)).unwrap_or(p);
1288 position = p.to_dip(f);
1289 hits = w.root().hit_test(p);
1290 target = hits
1291 .target()
1292 .and_then(|t| w.get(t.widget_id))
1293 .map(|t| t.interaction_path())
1294 .unwrap_or_else(|| w.root().interaction_path());
1295 }
1296 }
1297
1298 let target = match target.unblocked() {
1299 Some(t) => t,
1300 None => return, };
1302
1303 let capture_info = POINTER_CAPTURE.current_capture_value();
1304
1305 let (gesture_handle, velocity) = match update.phase {
1306 TouchPhase::Start => {
1307 let handle = EventPropagationHandle::new();
1308 if let Some(weird) = self.pressed.insert(
1309 update.touch,
1310 PressedInfo {
1311 touch_propagation: handle.clone(),
1312 target: target.clone(),
1313 device_id: args.device_id,
1314 position,
1315 force: update.force,
1316 hits: hits.clone(),
1317 velocity_samples: vec![], },
1319 ) {
1320 weird.touch_propagation.stop();
1321 }
1322 (handle, DipVector::zero())
1323 }
1324 TouchPhase::End => {
1325 if let Some(handle) = self.pressed.remove(&update.touch) {
1326 let vel = handle.velocity();
1327 (handle.touch_propagation, vel)
1328 } else {
1329 let weird = EventPropagationHandle::new();
1330 weird.stop();
1331 (weird, DipVector::zero())
1332 }
1333 }
1334 TouchPhase::Cancel => {
1335 let handle = self.pressed.remove(&update.touch).map(|i| i.touch_propagation).unwrap_or_default();
1336 handle.stop();
1337 (handle, DipVector::zero())
1338 }
1339 TouchPhase::Move => unreachable!(),
1340 };
1341
1342 match update.phase {
1343 TouchPhase::Start => {
1344 let pos_info = TouchPosition {
1345 window_id: hits.window_id(),
1346 touch: update.touch,
1347 position,
1348 start_time: args.timestamp,
1349 update_time: args.timestamp,
1350 };
1351 TOUCH_SV.read().positions.modify(move |p| {
1352 let p = p.to_mut();
1353 if let Some(weird) = p.iter().position(|p| p.touch == pos_info.touch) {
1354 p.remove(weird);
1355 }
1356 p.push(pos_info);
1357 });
1358 }
1359 _ => {
1360 let touch = update.touch;
1361 TOUCH_SV.read().positions.modify(move |p| {
1362 if let Some(i) = p.iter().position(|p| p.touch == touch) {
1363 p.to_mut().remove(i);
1364 }
1365 });
1366 }
1367 }
1368
1369 let args = TouchInputArgs::now(
1370 hits.window_id(),
1371 args.device_id,
1372 update.touch,
1373 gesture_handle,
1374 position,
1375 update.force,
1376 velocity,
1377 update.phase,
1378 hits,
1379 target,
1380 capture_info,
1381 self.modifiers,
1382 );
1383
1384 let touched_args = {
1385 let (prev_target, target) = match args.phase {
1388 TouchPhase::Start => (None, Some(args.target.clone())),
1389 TouchPhase::End | TouchPhase::Cancel => (Some(args.target.clone()), None),
1390 TouchPhase::Move => unreachable!(),
1391 };
1392
1393 TouchedArgs::now(
1394 args.window_id,
1395 args.device_id,
1396 args.touch,
1397 args.touch_propagation.clone(),
1398 args.position,
1399 args.force,
1400 args.phase,
1401 args.hits.clone(),
1402 prev_target,
1403 target,
1404 args.capture.clone(),
1405 args.capture.clone(),
1406 )
1407 };
1408
1409 TOUCH_INPUT_EVENT.notify(args);
1410 TOUCHED_EVENT.notify(touched_args);
1411 } else {
1412 for u in &args.touches {
1414 if let Some(i) = self.pressed.remove(&u.touch) {
1415 let capture = POINTER_CAPTURE.current_capture_value();
1416 let args = TouchedArgs::now(
1417 args.window_id,
1418 args.device_id,
1419 u.touch,
1420 i.touch_propagation,
1421 u.position,
1422 u.force,
1423 u.phase,
1424 HitTestInfo::no_hits(args.window_id),
1425 Some(i.target),
1426 None,
1427 capture.clone(),
1428 capture,
1429 );
1430 TOUCHED_EVENT.notify(args);
1431 }
1432 }
1433 }
1434 }
1435
1436 fn on_move(&mut self, args: &RawTouchArgs, mut moves: Vec<TouchMove>) {
1437 if !moves.is_empty() {
1438 if let Ok(w) = WINDOWS.widget_tree(args.window_id) {
1439 let mut window_blocked_remove = vec![];
1440 for m in &mut moves {
1441 m.hits = w.root().hit_test(m.position().to_px(w.scale_factor()));
1442 let target = m
1443 .hits
1444 .target()
1445 .and_then(|t| w.get(t.widget_id))
1446 .map(|t| t.interaction_path())
1447 .unwrap_or_else(|| w.root().interaction_path());
1448
1449 match target.unblocked() {
1450 Some(t) => {
1451 m.target = t;
1452 if let Some(wgt) = w.get(m.target.widget_id()) {
1454 if let Some(w) = wgt.nested_window_tree() {
1455 let transform = wgt.inner_transform().inverse();
1456 let factor = w.scale_factor();
1457 let mut position = PxPoint::zero(); for (mv, _) in &mut m.moves {
1459 let p = mv.to_px(factor);
1460 let p = transform.and_then(|t| t.transform_point(p)).unwrap_or(p);
1461 *mv = p.to_dip(factor);
1462 position = p;
1463 }
1464 m.hits = w.root().hit_test(position);
1465 let target = m
1466 .hits
1467 .target()
1468 .and_then(|t| w.get(t.widget_id))
1469 .map(|t| t.interaction_path())
1470 .unwrap_or_else(|| w.root().interaction_path());
1471
1472 match target.unblocked() {
1473 Some(t) => m.target = t,
1474 None => window_blocked_remove.push(m.touch),
1475 }
1476 }
1477 }
1478 }
1479 None => {
1480 window_blocked_remove.push(m.touch);
1481 }
1482 }
1483 }
1484
1485 let position_updates: Vec<_> = moves
1486 .iter()
1487 .map(|m| TouchPosition {
1488 window_id: args.window_id,
1489 touch: m.touch,
1490 position: m.position(),
1491 start_time: args.timestamp, update_time: args.timestamp,
1493 })
1494 .collect();
1495 TOUCH_SV.read().positions.modify(move |p| {
1496 for mut update in position_updates {
1497 if let Some(i) = p.iter().position(|p| p.touch == update.touch) {
1498 update.start_time = p[i].start_time;
1499 p.to_mut()[i] = update;
1500 }
1501 }
1502 });
1503
1504 let capture_info = POINTER_CAPTURE.current_capture_value();
1505
1506 let mut touched_events = vec![];
1507
1508 for touch in window_blocked_remove {
1509 let touch_move = moves.iter().position(|t| t.touch == touch).unwrap();
1510 moves.swap_remove(touch_move);
1511
1512 if let Some(i) = self.pressed.remove(&touch) {
1513 i.touch_propagation.stop();
1514 let args = TouchedArgs::now(
1515 args.window_id,
1516 args.device_id,
1517 touch,
1518 i.touch_propagation,
1519 DipPoint::splat(Dip::new(-1)),
1520 None,
1521 TouchPhase::Cancel,
1522 HitTestInfo::no_hits(args.window_id),
1523 i.target,
1524 None,
1525 None,
1526 None,
1527 );
1528 touched_events.push(args);
1529 }
1530 }
1531 for m in &mut moves {
1532 if let Some(i) = self.pressed.get_mut(&m.touch) {
1533 let (position, force) = *m.moves.last().unwrap();
1534 i.push_velocity_sample(args.timestamp, position);
1535 m.velocity = i.velocity();
1536 i.position = position;
1537 i.force = force;
1538 i.hits = m.hits.clone();
1539 if i.target != m.target {
1540 let args = TouchedArgs::now(
1541 args.window_id,
1542 args.device_id,
1543 m.touch,
1544 m.touch_propagation.clone(),
1545 position,
1546 force,
1547 TouchPhase::Move,
1548 m.hits.clone(),
1549 i.target.clone(),
1550 m.target.clone(),
1551 capture_info.clone(),
1552 capture_info.clone(),
1553 );
1554 i.target = m.target.clone();
1555 touched_events.push(args);
1556 }
1557 }
1558 }
1559
1560 if !moves.is_empty() {
1561 let args = TouchMoveArgs::now(args.window_id, args.device_id, moves, capture_info, self.modifiers);
1562 TOUCH_MOVE_EVENT.notify(args);
1563 }
1564
1565 for args in touched_events {
1566 TOUCHED_EVENT.notify(args);
1567 }
1568 }
1569 }
1570 }
1571
1572 fn continue_pressed(&mut self, window_id: WindowId) {
1573 let mut tree = None;
1574
1575 let mut window_blocked_remove = vec![];
1576
1577 for (touch, info) in &mut self.pressed {
1578 if info.target.window_id() != window_id {
1579 continue;
1580 }
1581
1582 let tree = tree.get_or_insert_with(|| WINDOWS.widget_tree(window_id).unwrap());
1583 info.hits = tree.root().hit_test(info.position.to_px(tree.scale_factor()));
1584
1585 let target = if let Some(t) = info.hits.target() {
1586 tree.get(t.widget_id).map(|w| w.interaction_path()).unwrap_or_else(|| {
1587 tracing::error!("hits target `{}` not found", t.widget_id);
1588 tree.root().interaction_path()
1589 })
1590 } else {
1591 tree.root().interaction_path()
1592 }
1593 .unblocked();
1594
1595 if let Some(target) = target {
1596 if info.target != target {
1597 let capture = POINTER_CAPTURE.current_capture_value();
1598 let prev = mem::replace(&mut info.target, target.clone());
1599
1600 let args = TouchedArgs::now(
1601 info.target.window_id(),
1602 None,
1603 *touch,
1604 info.touch_propagation.clone(),
1605 info.position,
1606 info.force,
1607 TouchPhase::Move,
1608 info.hits.clone(),
1609 prev,
1610 target,
1611 capture.clone(),
1612 capture,
1613 );
1614 TOUCHED_EVENT.notify(args);
1615 }
1616 } else {
1617 window_blocked_remove.push(*touch);
1618 }
1619 }
1620
1621 for touch in window_blocked_remove {
1622 if let Some(i) = self.pressed.remove(&touch) {
1623 i.touch_propagation.stop();
1624 let args = TouchedArgs::now(
1625 i.target.window_id(),
1626 None,
1627 touch,
1628 i.touch_propagation,
1629 DipPoint::splat(Dip::new(-1)),
1630 None,
1631 TouchPhase::Cancel,
1632 HitTestInfo::no_hits(i.target.window_id()),
1633 i.target,
1634 None,
1635 None,
1636 None,
1637 );
1638 TOUCHED_EVENT.notify(args);
1639 }
1640 }
1641 }
1642}
1643
1644struct PendingDoubleTap {
1645 window_id: WindowId,
1646 device_id: DeviceId,
1647 target: WidgetId,
1648 count: NonZeroU32,
1649 timestamp: DInstant,
1650}
1651struct PendingTap {
1652 window_id: WindowId,
1653 device_id: DeviceId,
1654 touch: TouchId,
1655 target: WidgetId,
1656
1657 propagation: EventPropagationHandle,
1658}
1659impl PendingTap {
1660 fn retain(&self, window_id: WindowId, device_id: DeviceId, touch: TouchId) -> bool {
1664 if self.propagation.is_stopped() {
1665 return false;
1667 }
1668
1669 if window_id != self.window_id || device_id != self.device_id {
1670 return false;
1672 }
1673
1674 if touch != self.touch {
1675 return false;
1677 }
1678
1679 true
1681 }
1682}
1683
1684struct PendingLongPress {
1685 window_id: WindowId,
1686 device_id: DeviceId,
1687 touch: TouchId,
1688 target: WidgetId,
1689 position: DipPoint,
1690 start_time: DInstant,
1691 modifiers: ModifiersState,
1692
1693 propagation: EventPropagationHandle,
1694
1695 delay: DeadlineVar,
1696 canceled: bool,
1697}
1698
1699#[derive(Default)]
1700struct LongPressGesture {
1701 pending: Option<PendingLongPress>,
1702}
1703impl LongPressGesture {
1704 fn on_input(&mut self, args: &TouchInputArgs) {
1705 match args.phase {
1706 TouchPhase::Start => {
1707 if let Some(p) = &mut self.pending {
1708 p.canceled = true;
1710 } else if TOUCH_LONG_PRESS_EVENT.has_hooks()
1711 || args.target.widgets_path().iter().any(|w| TOUCH_LONG_PRESS_EVENT.is_subscriber(*w))
1712 {
1713 self.pending = Some(PendingLongPress {
1714 window_id: args.window_id,
1715 device_id: args.device_id,
1716 touch: args.touch,
1717 position: args.position,
1718 start_time: args.timestamp,
1719 modifiers: args.modifiers,
1720 target: args.target.widget_id(),
1721 propagation: args.touch_propagation.clone(),
1722 delay: TIMERS.deadline(TOUCH.touch_config().get().tap_max_time),
1723 canceled: false,
1724 });
1725 }
1726 }
1727 TouchPhase::End | TouchPhase::Cancel => {
1728 if let Some(p) = &self.pending {
1729 if args.touch_propagation == p.propagation {
1730 self.pending = None;
1731 }
1732 }
1733 }
1734 TouchPhase::Move => unreachable!(),
1735 }
1736 }
1737
1738 fn on_move(&mut self, args: &TouchMoveArgs) {
1739 if let Some(p) = &mut self.pending {
1740 if !p.canceled && !p.propagation.is_stopped() {
1741 for m in &args.touches {
1742 if p.propagation == m.touch_propagation {
1743 let dist = p.position - m.position().to_vector();
1744 let max = TOUCH.touch_config().get().tap_area;
1745 if dist.x.abs() > max.width || dist.y.abs() > max.height {
1746 p.canceled = true;
1747 break;
1748 }
1749 } else {
1750 p.canceled = true;
1751 break;
1752 }
1753 }
1754 }
1755 }
1756 }
1757
1758 fn on_update(&mut self) {
1759 if let Some(p) = &mut self.pending {
1760 if !p.canceled && !p.propagation.is_stopped() && p.delay.get().has_elapsed() {
1761 if let Ok(w) = WINDOWS.widget_tree(p.window_id) {
1762 if let Some(w) = w.get(p.target) {
1763 let hits = w.hit_test(p.position.to_px(w.tree().scale_factor()));
1764 if hits.contains(p.target) {
1765 p.propagation.stop();
1766
1767 let args = TouchLongPressArgs::now(
1768 p.window_id,
1769 p.device_id,
1770 p.touch,
1771 p.position,
1772 hits,
1773 w.interaction_path(),
1774 p.modifiers,
1775 p.start_time,
1776 );
1777 TOUCH_LONG_PRESS_EVENT.notify(args);
1778 return;
1779 }
1780 }
1781 }
1782 p.canceled = true;
1783 }
1784 }
1785 }
1786
1787 fn clear(&mut self) {
1788 self.pending = None;
1789 }
1790}
1791
1792#[derive(Default)]
1793struct TapGesture {
1794 pending_double: Option<PendingDoubleTap>,
1795 pending: Option<PendingTap>,
1796}
1797impl TapGesture {
1798 fn on_input(&mut self, args: &TouchInputArgs) {
1799 match args.phase {
1800 TouchPhase::Start => {
1801 if self.pending.is_some() {
1802 self.pending = None;
1803 self.pending_double = None;
1804 } else if TOUCH_TAP_EVENT.has_hooks() || args.target.widgets_path().iter().any(|w| TOUCH_TAP_EVENT.is_subscriber(*w)) {
1805 self.pending = Some(PendingTap {
1806 window_id: args.window_id,
1807 device_id: args.device_id,
1808 touch: args.touch,
1809 target: args.target.widget_id(),
1810 propagation: args.touch_propagation.clone(),
1811 });
1812 }
1813 }
1814 TouchPhase::End => {
1815 let pending_double = self.pending_double.take();
1816
1817 if let Some(p) = self.pending.take() {
1818 if !p.retain(args.window_id, args.device_id, args.touch) {
1819 return;
1820 }
1821
1822 p.propagation.stop(); let tree = if let Ok(w) = WINDOWS.widget_tree(args.window_id) {
1825 w
1826 } else {
1827 return;
1828 };
1829
1830 match tree.get(p.target) {
1831 Some(t) => {
1832 if !t.hit_test(args.position.to_px(tree.scale_factor())).contains(p.target) {
1833 return;
1835 }
1836 }
1837 None => return,
1838 }
1839
1840 if let Some(target) = args.target.sub_path(p.target) {
1841 let tap_count = if let Some(double) = pending_double {
1842 let cfg = TOUCH.touch_config().get();
1843 if double.window_id == p.window_id
1844 && double.device_id == p.device_id
1845 && double.target == p.target
1846 && double.timestamp.elapsed() <= cfg.double_tap_max_time
1847 {
1848 NonZeroU32::new(double.count.get() + 1).unwrap()
1849 } else {
1850 NonZeroU32::new(1).unwrap()
1851 }
1852 } else {
1853 NonZeroU32::new(1).unwrap()
1854 };
1855
1856 self.pending_double = Some(PendingDoubleTap {
1857 window_id: args.window_id,
1858 device_id: args.device_id,
1859 target: p.target,
1860 count: tap_count,
1861 timestamp: args.timestamp,
1862 });
1863
1864 TOUCH_TAP_EVENT.notify(TouchTapArgs::new(
1865 args.timestamp,
1866 args.propagation().clone(),
1867 p.window_id,
1868 p.device_id,
1869 p.touch,
1870 args.position,
1871 args.hits.clone(),
1872 target.into_owned(),
1873 args.modifiers,
1874 tap_count,
1875 ));
1876 }
1877 }
1878 }
1879 TouchPhase::Cancel => {
1880 if let Some(p) = self.pending.take() {
1881 p.propagation.stop();
1882 }
1883 self.pending = None;
1884 self.pending_double = None;
1885 }
1886 TouchPhase::Move => unreachable!(),
1887 }
1888 }
1889
1890 fn on_move(&mut self, args: &TouchMoveArgs) {
1891 if let Some(p) = &self.pending {
1892 for t in &args.touches {
1893 if !p.retain(args.window_id, args.device_id, t.touch) {
1894 self.pending = None;
1895 self.pending_double = None;
1896 break;
1897 }
1898 }
1899 }
1900 }
1901
1902 fn clear(&mut self) {
1903 self.pending = None;
1904 self.pending_double = None;
1905 }
1906}
1907
1908#[derive(Clone, Debug, PartialEq, serde::Serialize, serde::Deserialize)]
1910pub struct TouchTransformInfo {
1911 pub touches: [euclid::Point2D<f32, Px>; 2],
1913
1914 pub center: euclid::Point2D<f32, Px>,
1916
1917 pub deviation: f32,
1921
1922 pub deviation_x: f32,
1926
1927 pub deviation_y: f32,
1931
1932 pub angle: AngleRadian,
1934}
1935impl TouchTransformInfo {
1936 pub fn new_f32(touches: [euclid::Point2D<f32, Px>; 2]) -> Self {
1938 let a = touches[0].to_vector();
1939 let b = touches[1].to_vector();
1940
1941 let center = (a + b) / 2.0;
1942 let deviation = (a - center).length();
1943 let deviation_x = (a.x - center.x).abs();
1944 let deviation_y = (a.y - center.y).abs();
1945
1946 Self {
1947 touches,
1948 center: center.to_point(),
1949 deviation: deviation.max(1.0),
1950 deviation_x: deviation_x.max(1.0),
1951 deviation_y: deviation_y.max(1.0),
1952 angle: AngleRadian((a.y - b.y).atan2(a.x - b.x)),
1953 }
1954 }
1955
1956 pub fn new(touches: [PxPoint; 2]) -> Self {
1958 Self::new_f32([touches[0].to_f32(), touches[1].to_f32()])
1959 }
1960
1961 pub fn new_dip(touches: [DipPoint; 2], scale_factor: Factor) -> Self {
1963 Self::new_f32([touches[0].to_f32().to_px(scale_factor), touches[1].to_f32().to_px(scale_factor)])
1964 }
1965}
1966impl TouchTransformInfo {
1967 pub fn translation(&self, other: &Self) -> euclid::Vector2D<f32, Px> {
1969 other.center.to_vector() - self.center.to_vector()
1970 }
1971
1972 pub fn translation_x(&self, other: &Self) -> f32 {
1974 other.center.x - self.center.x
1975 }
1976
1977 pub fn translation_y(&self, other: &Self) -> f32 {
1979 other.center.y - self.center.y
1980 }
1981
1982 pub fn rotation(&self, other: &Self) -> AngleRadian {
1984 other.angle - self.angle
1985 }
1986
1987 pub fn scale(&self, other: &Self) -> Factor {
1989 Factor(other.deviation / self.deviation)
1990 }
1991
1992 pub fn scale_x(&self, other: &Self) -> Factor {
1994 Factor(other.deviation_x / self.deviation_x)
1995 }
1996
1997 pub fn scale_y(&self, other: &Self) -> Factor {
1999 Factor(other.deviation_y / self.deviation_y)
2000 }
2001
2002 pub fn transform(&self, other: &Self, mode: TouchTransformMode) -> PxTransform {
2004 let mut m = PxTransform::identity();
2005
2006 if mode.contains(TouchTransformMode::TRANSLATE) {
2007 m = m.then_translate(self.translation(other));
2008 } else if mode.contains(TouchTransformMode::TRANSLATE_X) {
2009 let t = euclid::vec2(self.translation_x(other), 0.0);
2010 m = m.then_translate(t);
2011 } else if mode.contains(TouchTransformMode::TRANSLATE_Y) {
2012 let t = euclid::vec2(0.0, self.translation_y(other));
2013 m = m.then_translate(t);
2014 }
2015
2016 if mode.contains(TouchTransformMode::SCALE) {
2017 let s = self.scale(other).0;
2018 m = m.then(&PxTransform::scale(s, s));
2019 } else if mode.contains(TouchTransformMode::SCALE_X) {
2020 let s = self.scale_x(other);
2021 m = m.then(&PxTransform::scale(s.0, 1.0))
2022 } else if mode.contains(TouchTransformMode::SCALE_Y) {
2023 let s = self.scale_y(other);
2024 m = m.then(&PxTransform::scale(1.0, s.0))
2025 }
2026
2027 if mode.contains(TouchTransformMode::ROTATE) {
2028 let a = self.rotation(other);
2029 m = m.then(&PxTransform::rotation(0.0, 0.0, a.into()));
2030 }
2031
2032 m
2033 }
2034
2035 pub fn is_single(&self) -> bool {
2037 self.touches[0] == self.touches[1]
2038 }
2039}
2040impl ops::AddAssign<euclid::Vector2D<f32, Px>> for TouchTransformInfo {
2041 fn add_assign(&mut self, rhs: euclid::Vector2D<f32, Px>) {
2042 self.touches[0] += rhs;
2043 self.touches[1] += rhs;
2044 self.center += rhs;
2045 }
2046}
2047impl ops::Add<euclid::Vector2D<f32, Px>> for TouchTransformInfo {
2048 type Output = Self;
2049
2050 fn add(mut self, rhs: euclid::Vector2D<f32, Px>) -> Self::Output {
2051 self += rhs;
2052 self
2053 }
2054}
2055impl ops::AddAssign<PxVector> for TouchTransformInfo {
2056 fn add_assign(&mut self, rhs: PxVector) {
2057 *self += rhs.cast::<f32>();
2058 }
2059}
2060impl ops::Add<PxVector> for TouchTransformInfo {
2061 type Output = Self;
2062
2063 fn add(mut self, rhs: PxVector) -> Self::Output {
2064 self += rhs;
2065 self
2066 }
2067}
2068impl ops::SubAssign<euclid::Vector2D<f32, Px>> for TouchTransformInfo {
2069 fn sub_assign(&mut self, rhs: euclid::Vector2D<f32, Px>) {
2070 self.touches[0] -= rhs;
2071 self.touches[1] -= rhs;
2072 self.center -= rhs;
2073 }
2074}
2075impl ops::Sub<euclid::Vector2D<f32, Px>> for TouchTransformInfo {
2076 type Output = Self;
2077
2078 fn sub(mut self, rhs: euclid::Vector2D<f32, Px>) -> Self::Output {
2079 self -= rhs;
2080 self
2081 }
2082}
2083impl ops::SubAssign<PxVector> for TouchTransformInfo {
2084 fn sub_assign(&mut self, rhs: PxVector) {
2085 *self -= rhs.cast::<f32>();
2086 }
2087}
2088impl ops::Sub<PxVector> for TouchTransformInfo {
2089 type Output = Self;
2090
2091 fn sub(mut self, rhs: PxVector) -> Self::Output {
2092 self -= rhs;
2093 self
2094 }
2095}
2096
2097bitflags! {
2098 #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, serde::Serialize, serde::Deserialize)]
2101 #[serde(transparent)]
2102 pub struct TouchTransformMode: u8 {
2103 const TRANSLATE_X = 0b0000_0001;
2105 const TRANSLATE_Y = 0b0000_0010;
2107 const TRANSLATE = Self::TRANSLATE_X.bits() | Self::TRANSLATE_Y.bits();
2109
2110 const SCALE_X = 0b0000_0100;
2112 const SCALE_Y = 0b0000_1000;
2114 const SCALE = 0b0001_1100;
2116
2117 const ROTATE = 0b0010_0000;
2119
2120 const ALL = Self::TRANSLATE.bits()| Self::SCALE.bits() | Self::ROTATE.bits();
2122 }
2123}
2124impl_from_and_into_var! {
2125 fn from(all_or_empty: bool) -> TouchTransformMode {
2126 if all_or_empty {
2127 TouchTransformMode::ALL
2128 } else {
2129 TouchTransformMode::empty()
2130 }
2131 }
2132}
2133
2134#[derive(Default)]
2135enum TransformGesture {
2136 #[default]
2137 NoStartedZero,
2138
2139 NotStartedOne {
2140 window_id: WindowId,
2141 device_id: DeviceId,
2142 start_position: DipPoint,
2143 position: DipPoint,
2144 handle: EventPropagationHandle,
2145 },
2146 NotStartedTwo {
2147 window_id: WindowId,
2148 device_id: DeviceId,
2149 start_position: [DipPoint; 2],
2150 position: [DipPoint; 2],
2151 handle: [EventPropagationHandle; 2],
2152 scale_factor: Factor,
2153 },
2154
2155 StartedOne {
2156 window_id: WindowId,
2157 device_id: DeviceId,
2158 position: DipPoint,
2159 velocity: DipVector,
2160 scale_factor: Factor,
2161 handle: EventPropagationHandle,
2162 first_info: TouchTransformInfo,
2163 hits: HitTestInfo,
2164 target: InteractionPath,
2165 },
2166 StartedTwo {
2167 window_id: WindowId,
2168 device_id: DeviceId,
2169 position: [DipPoint; 2],
2170 velocity: [DipVector; 2],
2171 scale_factor: Factor,
2172 handle: [EventPropagationHandle; 2],
2173 first_info: TouchTransformInfo,
2174 hits: HitTestInfo,
2175 target: InteractionPath,
2176 },
2177}
2178impl TransformGesture {
2179 fn on_input(&mut self, args: &TouchInputArgs) {
2180 match mem::take(self) {
2181 Self::NoStartedZero => {
2182 if TouchPhase::Start == args.phase
2183 && !args.touch_propagation.is_stopped()
2184 && (TOUCH_TRANSFORM_EVENT.has_hooks()
2185 || args.target.widgets_path().iter().any(|w| TOUCH_TRANSFORM_EVENT.is_subscriber(*w)))
2186 {
2187 *self = Self::NotStartedOne {
2188 window_id: args.window_id,
2189 device_id: args.device_id,
2190 start_position: args.position,
2191 position: args.position,
2192 handle: args.touch_propagation.clone(),
2193 }
2194 }
2195 }
2196 Self::NotStartedOne {
2197 window_id,
2198 device_id,
2199 position,
2200 handle,
2201 ..
2202 } => {
2203 if TouchPhase::Start == args.phase
2204 && window_id == args.window_id
2205 && device_id == args.device_id
2206 && !args.touch_propagation.is_stopped()
2207 && !handle.is_stopped()
2208 && handle != args.touch_propagation
2209 {
2210 if let Ok(w) = WINDOWS.widget_tree(args.window_id) {
2211 *self = Self::NotStartedTwo {
2212 window_id: args.window_id,
2213 device_id: args.device_id,
2214 start_position: [position, args.position],
2215 position: [position, args.position],
2216 handle: [handle, args.touch_propagation.clone()],
2217 scale_factor: w.scale_factor(),
2218 }
2219 }
2220 }
2221 }
2222 Self::NotStartedTwo { .. } => {
2223 }
2225 Self::StartedOne {
2226 window_id,
2227 device_id,
2228 position,
2229 velocity,
2230 scale_factor,
2231 handle,
2232 first_info,
2233 hits,
2234 target,
2235 } => match args.phase {
2236 TouchPhase::Start
2237 if window_id == args.window_id
2238 && device_id == args.device_id
2239 && !args.touch_propagation.is_stopped()
2240 && !handle.is_stopped()
2241 && handle != args.touch_propagation =>
2242 {
2243 *self = Self::StartedTwo {
2244 window_id,
2245 device_id,
2246 position: [position, args.position],
2247 velocity: [velocity, args.velocity],
2248 scale_factor,
2249 handle: [handle, args.touch_propagation.clone()],
2250 first_info,
2251 hits,
2252 target,
2253 };
2254 }
2255 TouchPhase::Move => unreachable!(),
2256 TouchPhase::End if handle == args.touch_propagation => {
2257 let position = args.position;
2258
2259 let latest_info = TouchTransformInfo::new_dip([position, position], scale_factor);
2260 let capture = POINTER_CAPTURE.current_capture_value();
2261
2262 let velocity = velocity.to_px(scale_factor);
2263
2264 let args = TouchTransformArgs::now(
2265 window_id,
2266 device_id,
2267 first_info,
2268 latest_info,
2269 [velocity, velocity],
2270 scale_factor,
2271 TouchPhase::End,
2272 hits,
2273 target,
2274 capture,
2275 args.modifiers,
2276 );
2277 TOUCH_TRANSFORM_EVENT.notify(args);
2278 }
2279 _ => {
2280 *self = Self::StartedOne {
2282 window_id,
2283 device_id,
2284 position,
2285 velocity,
2286 scale_factor,
2287 handle,
2288 first_info,
2289 hits,
2290 target,
2291 };
2292 self.clear();
2293 }
2294 },
2295 Self::StartedTwo {
2296 window_id,
2297 device_id,
2298 mut position,
2299 velocity,
2300 scale_factor,
2301 handle,
2302 first_info,
2303 hits,
2304 target,
2305 } => {
2306 if TouchPhase::End == args.phase && handle.iter().any(|h| h == &args.touch_propagation) {
2307 let i = handle.iter().position(|h| h == &args.touch_propagation).unwrap();
2308 position[i] = args.position;
2309
2310 let latest_info = TouchTransformInfo::new_dip(position, scale_factor);
2311 let capture = POINTER_CAPTURE.current_capture_value();
2312
2313 let velocity = [velocity[0].to_px(scale_factor), velocity[1].to_px(scale_factor)];
2314
2315 let args = TouchTransformArgs::now(
2316 window_id,
2317 device_id,
2318 first_info,
2319 latest_info,
2320 velocity,
2321 scale_factor,
2322 TouchPhase::End,
2323 hits,
2324 target,
2325 capture,
2326 args.modifiers,
2327 );
2328 TOUCH_TRANSFORM_EVENT.notify(args);
2329 } else {
2330 *self = Self::StartedTwo {
2331 window_id,
2332 device_id,
2333 position,
2334 velocity,
2335 scale_factor,
2336 handle,
2337 first_info,
2338 hits,
2339 target,
2340 };
2341 self.clear();
2342 }
2343 }
2344 }
2345 }
2346
2347 fn on_move(&mut self, args: &TouchMoveArgs) {
2348 match self {
2349 Self::NoStartedZero => {}
2350 Self::NotStartedOne {
2351 start_position,
2352 position,
2353 handle,
2354 window_id,
2355 device_id,
2356 } => {
2357 if handle.is_stopped() {
2358 *self = Self::NoStartedZero;
2359 } else {
2360 let mut moved = false;
2361 for t in &args.touches {
2362 if handle == &t.touch_propagation {
2363 *position = t.position();
2364 moved = true;
2365 } else {
2366 *self = Self::NoStartedZero;
2367 return;
2368 }
2369 }
2370 if moved {
2371 let cfg = TOUCH.touch_config().get();
2372 if (position.x - start_position.x).abs() > cfg.double_tap_area.width
2373 || (position.y - start_position.y).abs() > cfg.double_tap_area.height
2374 {
2375 if let Ok(w) = WINDOWS.widget_tree(*window_id) {
2376 let scale_factor = w.scale_factor();
2377 let first_info = TouchTransformInfo::new_dip([*start_position, *start_position], scale_factor);
2378 let latest_info = TouchTransformInfo::new_dip([*position, *position], scale_factor);
2379
2380 let hits = w.root().hit_test(first_info.center.cast());
2381 let target = hits
2382 .target()
2383 .and_then(|t| w.get(t.widget_id))
2384 .map(|t| t.interaction_path())
2385 .unwrap_or_else(|| w.root().interaction_path());
2386
2387 let target = match target.unblocked() {
2388 Some(t) => t,
2389 None => {
2390 *self = Self::NoStartedZero;
2391 return; }
2393 };
2394 let capture = POINTER_CAPTURE.current_capture_value();
2395
2396 handle.stop();
2398
2399 let args = TouchTransformArgs::now(
2400 *window_id,
2401 *device_id,
2402 first_info.clone(),
2403 latest_info,
2404 [PxVector::zero(); 2],
2405 scale_factor,
2406 TouchPhase::Start,
2407 hits.clone(),
2408 target.clone(),
2409 capture,
2410 args.modifiers,
2411 );
2412 TOUCH_TRANSFORM_EVENT.notify(args);
2413
2414 *self = Self::StartedOne {
2415 window_id: *window_id,
2416 device_id: *device_id,
2417 position: *position,
2418 velocity: DipVector::zero(),
2419 scale_factor,
2420 handle: handle.clone(),
2421 first_info,
2422 hits,
2423 target,
2424 };
2425 } else {
2426 *self = Self::NoStartedZero;
2427 }
2428 }
2429 }
2430 }
2431 }
2432 Self::NotStartedTwo {
2433 start_position,
2434 position,
2435 handle,
2436 scale_factor,
2437 window_id,
2438 device_id,
2439 } => {
2440 if handle[0].is_stopped() || handle[1].is_stopped() {
2441 *self = Self::NoStartedZero;
2442 } else {
2443 let mut any_moved = false;
2444 for t in &args.touches {
2445 if let Some(i) = handle.iter().position(|h| h == &t.touch_propagation) {
2446 position[i] = t.position();
2447 any_moved = true;
2448 } else {
2449 *self = Self::NoStartedZero;
2450 return;
2451 }
2452 }
2453
2454 if any_moved {
2455 let first_info = TouchTransformInfo::new_dip(*start_position, *scale_factor);
2456 let latest_info = TouchTransformInfo::new_dip(*position, *scale_factor);
2457
2458 let start = {
2459 let translation = first_info.translation(&latest_info);
2460 translation.x > 0.0 && translation.y > 0.0
2461 } || {
2462 let scale = first_info.scale(&latest_info);
2463 scale.0 != 1.0
2464 } || {
2465 let rotate = first_info.rotation(&latest_info);
2466 rotate.0 != 0.0
2467 };
2468
2469 if start {
2470 if let Ok(w) = WINDOWS.widget_tree(*window_id) {
2471 let hits = w.root().hit_test(first_info.center.cast());
2472 let target = hits
2473 .target()
2474 .and_then(|t| w.get(t.widget_id))
2475 .map(|t| t.interaction_path())
2476 .unwrap_or_else(|| w.root().interaction_path());
2477
2478 let target = match target.unblocked() {
2479 Some(t) => t,
2480 None => {
2481 *self = Self::NoStartedZero;
2482 return; }
2484 };
2485 let capture = POINTER_CAPTURE.current_capture_value();
2486
2487 for h in handle.iter() {
2488 h.stop();
2490 }
2491
2492 let args = TouchTransformArgs::now(
2493 *window_id,
2494 *device_id,
2495 first_info.clone(),
2496 latest_info,
2497 [PxVector::zero(); 2],
2498 *scale_factor,
2499 TouchPhase::Start,
2500 hits.clone(),
2501 target.clone(),
2502 capture,
2503 args.modifiers,
2504 );
2505 TOUCH_TRANSFORM_EVENT.notify(args);
2506
2507 *self = Self::StartedTwo {
2508 window_id: *window_id,
2509 device_id: *device_id,
2510 position: *position,
2511 velocity: [DipVector::zero(); 2],
2512 scale_factor: *scale_factor,
2513 handle: handle.clone(),
2514 first_info,
2515 hits,
2516 target,
2517 };
2518 } else {
2519 *self = Self::NoStartedZero;
2520 }
2521 }
2522 }
2523 }
2524 }
2525 Self::StartedOne {
2526 window_id,
2527 device_id,
2528 position,
2529 velocity,
2530 scale_factor,
2531 handle,
2532 first_info,
2533 hits,
2534 target,
2535 } => {
2536 let mut any_moved = false;
2537 for t in &args.touches {
2538 if handle == &t.touch_propagation {
2539 *position = t.position();
2540 *velocity = t.velocity;
2541 any_moved = true;
2542 } else {
2543 self.clear();
2544 return;
2545 }
2546 }
2547
2548 if any_moved {
2549 let latest_info = TouchTransformInfo::new_dip([*position, *position], *scale_factor);
2550 let capture = POINTER_CAPTURE.current_capture_value();
2551
2552 let velocity = velocity.to_px(*scale_factor);
2553
2554 let args = TouchTransformArgs::now(
2555 *window_id,
2556 *device_id,
2557 first_info.clone(),
2558 latest_info,
2559 [velocity, velocity],
2560 *scale_factor,
2561 TouchPhase::Move,
2562 hits.clone(),
2563 target.clone(),
2564 capture,
2565 args.modifiers,
2566 );
2567 TOUCH_TRANSFORM_EVENT.notify(args);
2568 }
2569 }
2570 Self::StartedTwo {
2571 window_id,
2572 device_id,
2573 position,
2574 scale_factor,
2575 velocity,
2576 handle,
2577 first_info,
2578 hits,
2579 target,
2580 } => {
2581 let mut any_moved = false;
2582 for t in &args.touches {
2583 if let Some(i) = handle.iter().position(|h| h == &t.touch_propagation) {
2584 position[i] = t.position();
2585 velocity[i] = t.velocity;
2586 any_moved = true;
2587 } else {
2588 self.clear();
2589 return;
2590 }
2591 }
2592
2593 if any_moved {
2594 let latest_info = TouchTransformInfo::new_dip(*position, *scale_factor);
2595 let capture = POINTER_CAPTURE.current_capture_value();
2596
2597 let velocity = [velocity[0].to_px(*scale_factor), velocity[1].to_px(*scale_factor)];
2598
2599 let args = TouchTransformArgs::now(
2600 *window_id,
2601 *device_id,
2602 first_info.clone(),
2603 latest_info,
2604 velocity,
2605 *scale_factor,
2606 TouchPhase::Move,
2607 hits.clone(),
2608 target.clone(),
2609 capture,
2610 args.modifiers,
2611 );
2612 TOUCH_TRANSFORM_EVENT.notify(args);
2613 }
2614 }
2615 }
2616 }
2617
2618 fn clear(&mut self) {
2619 match mem::take(self) {
2620 TransformGesture::StartedOne {
2621 window_id,
2622 device_id,
2623 scale_factor,
2624 first_info,
2625 hits,
2626 target,
2627 ..
2628 }
2629 | TransformGesture::StartedTwo {
2630 window_id,
2631 device_id,
2632 scale_factor,
2633 first_info,
2634 hits,
2635 target,
2636 ..
2637 } => {
2638 let args = TouchTransformArgs::now(
2639 window_id,
2640 device_id,
2641 first_info.clone(),
2642 first_info,
2643 [PxVector::zero(); 2],
2644 scale_factor,
2645 TouchPhase::Cancel,
2646 hits,
2647 target,
2648 None,
2649 ModifiersState::empty(),
2650 );
2651 TOUCH_TRANSFORM_EVENT.notify(args);
2652 }
2653 _ => {}
2654 }
2655 }
2656}