1#![allow(unused)]
2#![allow(dead_code)]
3use {
4 std::cell::{Cell},
5 crate::{
6 makepad_micro_serde::*,
7 makepad_live_tokenizer::{LiveErrorOrigin, live_error_origin},
8 makepad_live_compiler::{
9 LivePropType,
10 LiveType,
11 LiveTypeField,
12 LiveFieldKind,
13 LiveNode,
14 LiveId,
15 LiveModuleId,
16 LiveTypeInfo,
17 LiveNodeSliceApi
18 },
19 live_traits::{LiveNew, LiveHook, LiveHookDeref, LiveApplyValue, LiveApply, ApplyFrom},
20 makepad_derive_live::*,
21 makepad_math::*,
22 makepad_live_id::{FromLiveId, live_id, live_id_num},
23 event::{
24 event::{Event, Hit}
25 },
26 window::WindowId,
27 cx::Cx,
28 area::Area,
29 },
30};
31
32#[derive(Clone, Copy, Debug, Default, SerBin, DeBin, SerJson, DeJson, PartialEq)]
36pub struct KeyModifiers {
37 pub shift: bool,
38 pub control: bool,
39 pub alt: bool,
40 pub logo: bool
41}
42
43#[derive(Clone, Debug, PartialEq)]
44pub struct MouseDownEvent {
45 pub abs: DVec2,
46 pub button: usize,
47 pub window_id: WindowId,
48 pub modifiers: KeyModifiers,
49 pub handled: Cell<Area>,
50 pub time: f64
51}
52
53
54#[derive(Clone, Debug)]
55pub struct MouseMoveEvent {
56 pub abs: DVec2,
57 pub window_id: WindowId,
58 pub modifiers: KeyModifiers,
59 pub time: f64,
60 pub handled: Cell<Area>,
61}
62
63#[derive(Clone, Debug)]
64pub struct MouseUpEvent {
65 pub abs: DVec2,
66 pub button: usize,
67 pub window_id: WindowId,
68 pub modifiers: KeyModifiers,
69 pub time: f64
70}
71
72#[derive(Clone, Debug)]
73pub struct ScrollEvent {
74 pub window_id: WindowId,
75 pub scroll: DVec2,
76 pub abs: DVec2,
77 pub modifiers: KeyModifiers,
78 pub handled_x: Cell<bool>,
79 pub handled_y: Cell<bool>,
80 pub is_mouse: bool,
81 pub time: f64
82}
83
84
85#[derive(Clone, Copy, Debug)]
88pub enum TouchState {
89 Start,
90 Stop,
91 Move,
92 Stable
93}
94
95#[derive(Clone, Debug)]
96pub struct TouchPoint {
97 pub state: TouchState,
98 pub abs: DVec2,
99 pub uid: u64,
100 pub rotation_angle: f64,
101 pub force: f64,
102 pub radius: DVec2,
103 pub handled: Cell<Area>,
104 pub sweep_lock: Cell<Area>,
105}
106
107#[derive(Clone, Debug)]
108pub struct TouchUpdateEvent {
109 pub time: f64,
110 pub window_id: WindowId,
111 pub modifiers: KeyModifiers,
112 pub touches: Vec<TouchPoint>,
113}
114
115
116#[derive(Clone, Copy, Default, Debug, Live)]
120#[live_ignore]
121pub struct Margin {
122 #[live] pub left: f64,
123 #[live] pub top: f64,
124 #[live] pub right: f64,
125 #[live] pub bottom: f64
126}
127
128
129impl LiveHook for Margin {
130 fn skip_apply(&mut self, _cx: &mut Cx, _apply_from: ApplyFrom, index: usize, nodes: &[LiveNode]) -> Option<usize> {
131 if let Some(v) = nodes[index].value.as_float() {
132 *self = Self {left: v, top: v, right: v, bottom: v};
133 Some(index + 1)
134 }
135 else {
136 None
137 }
138 }
139}
140
141impl Margin {
142 pub fn left_top(&self) -> DVec2 {
143 dvec2(self.left, self.top)
144 }
145 pub fn right_bottom(&self) -> DVec2 {
146 dvec2(self.right, self.bottom)
147 }
148 pub fn size(&self) -> DVec2 {
149 dvec2(self.left + self.right, self.top + self.bottom)
150 }
151 pub fn width(&self) -> f64 {
152 self.left + self.right
153 }
154 pub fn height(&self) -> f64 {
155 self.top + self.bottom
156 }
157
158 pub fn rect_contains_with_margin(rect: &Rect, pos: DVec2, margin: &Option<Margin>) -> bool {
159 if let Some(margin) = margin {
160 return
161 pos.x >= rect.pos.x - margin.left
162 && pos.x <= rect.pos.x + rect.size.x + margin.right
163 && pos.y >= rect.pos.y - margin.top
164 && pos.y <= rect.pos.y + rect.size.y + margin.bottom;
165 }
166 else {
167 return rect.contains(pos);
168 }
169 }
170}
171
172pub const TAP_COUNT_TIME: f64 = 0.5;
173pub const TAP_COUNT_DISTANCE: f64 = 10.0;
174
175#[derive(Clone, Debug, Default, Eq, Hash, Copy, PartialEq, FromLiveId)]
176pub struct DigitId(pub LiveId);
177
178#[derive(Default, Clone)]
179pub struct CxDigitCapture {
180 digit_id: DigitId,
181 pub area: Area,
182 pub sweep_area: Area,
183 pub switch_capture: Option<Area>,
184 pub time: f64,
185 pub abs_start: DVec2,
186}
187
188#[derive(Default, Clone)]
189pub struct CxDigitTap {
190 digit_id: DigitId,
191 last_pos: DVec2,
192 last_time: f64,
193 count: u32
194}
195
196#[derive(Default, Clone)]
197pub struct CxDigitHover {
198 digit_id: DigitId,
199 new_area: Area,
200 area: Area,
201}
202
203#[derive(Default, Clone)]
204pub struct CxFingers {
205 pub first_mouse_button: Option<usize>,
206 captures: Vec<CxDigitCapture>,
207 tap: CxDigitTap,
208 hovers: Vec<CxDigitHover>,
209 sweep_lock: Option<Area>,
210}
211
212impl CxFingers {
213 pub (crate) fn get_digit_for_captured_area(&self, area: Area) -> Option<DigitId> {
233 if let Some(digit) = self.captures.iter().find( | d | d.area == area) {
234 return Some(digit.digit_id)
235 }
236 None
237 }
238
239 pub (crate) fn update_area(&mut self, old_area: Area, new_area: Area) {
240 for hover in &mut self.hovers {
241 if hover.area == old_area {
242 hover.area = new_area;
243 }
244 }
245 for capture in &mut self.captures {
246 if capture.area == old_area {
247 capture.area = new_area;
248 }
249 if capture.sweep_area == old_area {
250 capture.sweep_area = new_area;
251 }
252 }
253 if self.sweep_lock == Some(old_area) {
254 self.sweep_lock = Some(new_area);
255 }
256 }
257
258 pub (crate) fn new_hover_area(&mut self, digit_id: DigitId, new_area: Area) {
259 for hover in &mut self.hovers {
260 if hover.digit_id == digit_id {
261 hover.new_area = new_area;
262 return
263 }
264 }
265 self.hovers.push(CxDigitHover {
266 digit_id,
267 area: Area::Empty,
268 new_area: new_area,
269 })
270 }
271
272 pub (crate) fn get_hover_area(&self, digit: DigitId) -> Area {
273 for hover in &self.hovers {
274 if hover.digit_id == digit {
275 return hover.area
276 }
277 }
278 Area::Empty
279 }
280
281 pub (crate) fn cycle_hover_area(&mut self, digit_id: DigitId) {
282 if let Some(hover) = self.hovers.iter_mut().find( | v | v.digit_id == digit_id) {
283 hover.area = hover.new_area;
284 hover.new_area = Area::Empty;
285 }
286 }
287
288 pub (crate) fn capture_digit(&mut self, digit_id: DigitId, area: Area, sweep_area: Area, time: f64, abs_start: DVec2) {
289 self.captures.push(CxDigitCapture {
297 sweep_area,
298 digit_id,
299 area,
300 time,
301 abs_start,
302 switch_capture: None
303 })
304 }
306
307 pub (crate) fn get_digit_capture(&mut self, digit_id: DigitId) -> Option<&mut CxDigitCapture> {
308 self.captures.iter_mut().find( | v | v.digit_id == digit_id)
309 }
310
311
312 pub (crate) fn get_area_capture(&mut self, area: Area) -> Option<&mut CxDigitCapture> {
313 self.captures.iter_mut().find( | v | v.area == area)
314 }
315
316 pub fn is_area_captured(&self, area: Area) -> bool {
317 self.captures.iter().find( | v | v.area == area).is_some()
318 }
319
320 pub (crate) fn release_digit(&mut self, digit_id: DigitId) {
321 while let Some(index) = self.captures.iter_mut().position( | v | v.digit_id == digit_id) {
322 self.captures.remove(index);
323 }
324 }
325
326 pub (crate) fn remove_hover(&mut self, digit_id: DigitId) {
327 while let Some(index) = self.hovers.iter_mut().position( | v | v.digit_id == digit_id) {
328 self.hovers.remove(index);
329 }
330 }
331
332 pub (crate) fn get_tap_count(&self) -> u32 {
333 self.tap.count
334 }
335
336 pub (crate) fn process_tap_count(&mut self, pos: DVec2, time: f64) -> u32 {
337 if (time - self.tap.last_time) < TAP_COUNT_TIME
338 && pos.distance(&self.tap.last_pos) < TAP_COUNT_DISTANCE {
339 self.tap.count += 1;
340 }
341 else {
342 self.tap.count = 1;
343 }
344 self.tap.last_pos = pos;
345 self.tap.last_time = time;
346 return self.tap.count
347 }
348
349 pub (crate) fn process_touch_update_start(&mut self, time: f64, touches: &[TouchPoint]) {
350 for touch in touches {
351 if let TouchState::Start = touch.state {
352 self.process_tap_count(touch.abs, time);
353 }
354 }
355 }
356
357 pub (crate) fn process_touch_update_end(&mut self, touches: &[TouchPoint]) {
358 for touch in touches {
359 let digit_id = live_id_num!(touch, touch.uid).into();
360 match touch.state {
361 TouchState::Stop => {
362 self.release_digit(digit_id);
363 self.remove_hover(digit_id);
364 }
365 TouchState::Start | TouchState::Move | TouchState::Stable => {
366 self.cycle_hover_area(digit_id);
367 }
368 }
369 }
370 self.switch_captures();
371 }
372
373 pub (crate) fn mouse_down(&mut self, button: usize) {
374 if self.first_mouse_button.is_none() {
375 self.first_mouse_button = Some(button);
376 }
377 }
378
379 pub (crate) fn switch_captures(&mut self) {
380 for capture in &mut self.captures {
381 if let Some(area) = capture.switch_capture {
382 capture.area = area;
383 capture.switch_capture = None;
384 }
385 }
386 }
387
388 pub (crate) fn mouse_up(&mut self, button: usize) {
389 if self.first_mouse_button == Some(button) {
390 self.first_mouse_button = None;
391 let digit_id = live_id!(mouse).into();
392 self.release_digit(digit_id);
393 }
394 }
395
396 pub (crate) fn test_sweep_lock(&mut self, sweep_area: Area) -> bool {
397 if let Some(lock) = self.sweep_lock {
398 if lock != sweep_area {
399 return true
400 }
401 }
402 false
403 }
404
405 pub fn sweep_lock(&mut self, area: Area) {
406 if self.sweep_lock.is_none() {
407 self.sweep_lock = Some(area);
408 }
409 }
410
411 pub fn sweep_unlock(&mut self, area: Area) {
412 if self.sweep_lock == Some(area) {
413 self.sweep_lock = None;
414 }
415 }
416
417}
418
419#[derive(Clone, Debug)]
420pub enum DigitDevice {
421 Mouse {
422 button: usize
423 },
424 Touch {
425 uid: u64
426 },
427 XR {}
428}
429
430impl DigitDevice {
431 pub fn is_touch(&self) -> bool {if let DigitDevice::Touch {..} = self {true}else {false}}
432 pub fn is_mouse(&self) -> bool {if let DigitDevice::Mouse {..} = self {true}else {false}}
433 pub fn is_xr(&self) -> bool {if let DigitDevice::XR {..} = self {true}else {false}}
434
435 pub fn has_hovers(&self) -> bool {self.is_mouse() || self.is_xr()}
436
437 pub fn mouse_button(&self) -> Option<usize> {if let DigitDevice::Mouse {button} = self {Some(*button)}else {None}}
438 pub fn touch_uid(&self) -> Option<u64> {if let DigitDevice::Touch {uid} = self {Some(*uid)}else {None}}
439 }
441
442#[derive(Clone, Debug)]
443pub struct FingerDownEvent {
444 pub window_id: WindowId,
445 pub abs: DVec2,
446
447 pub digit_id: DigitId,
448 pub device: DigitDevice,
449
450 pub tap_count: u32,
451 pub modifiers: KeyModifiers,
452 pub time: f64,
453 pub rect: Rect,
454}
455
456impl FingerDownEvent {
457 pub fn mod_control(&self) -> bool {self.modifiers.control}
458 pub fn mod_alt(&self) -> bool {self.modifiers.alt}
459 pub fn mod_shift(&self) -> bool {self.modifiers.shift}
460 pub fn mod_logo(&self) -> bool {self.modifiers.logo}
461}
462
463#[derive(Clone, Debug)]
464pub struct FingerMoveEvent {
465 pub window_id: WindowId,
466 pub abs: DVec2,
467 pub digit_id: DigitId,
468 pub device: DigitDevice,
469
470 pub tap_count: u32,
471 pub modifiers: KeyModifiers,
472 pub time: f64,
473
474 pub abs_start: DVec2,
475 pub rect: Rect,
476 pub is_over: bool,
477}
478
479impl FingerMoveEvent {
480 pub fn move_distance(&self) -> f64 {
481 ((self.abs_start.x - self.abs.x).powf(2.) + (self.abs_start.y - self.abs.y).powf(2.)).sqrt()
482 }
483}
484
485#[derive(Clone, Debug)]
486pub struct FingerUpEvent {
487 pub window_id: WindowId,
488 pub abs: DVec2,
489 pub capture_time: f64,
490
491 pub digit_id: DigitId,
492 pub device: DigitDevice,
493
494 pub tap_count: u32,
495 pub modifiers: KeyModifiers,
496 pub time: f64,
497 pub abs_start: DVec2,
498 pub rect: Rect,
499 pub is_over: bool,
500 pub is_sweep: bool
501}
502
503impl FingerUpEvent {
504 pub fn was_tap(&self) -> bool {
505 self.time - self.capture_time < TAP_COUNT_TIME &&
506 (self.abs_start - self.abs).length() < TAP_COUNT_DISTANCE
507 }
508
509 pub fn was_long_press(&self) -> bool {
510 self.time - self.capture_time >= TAP_COUNT_TIME &&
511 (self.abs_start - self.abs).length() < TAP_COUNT_DISTANCE
512 }
513}
514
515#[derive(Clone, Debug, PartialEq)]
516pub enum HoverState {
517 In,
518 Over,
519 Out
520}
521
522impl Default for HoverState {
523 fn default() -> HoverState {
524 HoverState::Over
525 }
526}
527
528#[derive(Clone, Debug)]
529pub struct FingerHoverEvent {
530 pub window_id: WindowId,
531 pub abs: DVec2,
532 pub digit_id: DigitId,
533 pub device: DigitDevice,
534 pub modifiers: KeyModifiers,
535 pub time: f64,
536 pub rect: Rect,
537}
538
539#[derive(Clone, Debug)]
540pub struct FingerScrollEvent {
541 pub window_id: WindowId,
542 pub digit_id: DigitId,
543 pub abs: DVec2,
544 pub scroll: DVec2,
545 pub device: DigitDevice,
546 pub modifiers: KeyModifiers,
547 pub time: f64,
548 pub rect: Rect,
549}
550
551#[derive(Clone, Debug, Default)]
562pub struct HitOptions {
563 pub margin: Option<Margin>,
564 pub sweep_area: Area,
565 pub capture_overload: bool,
566}
567
568impl HitOptions {
569 pub fn new() -> Self {
570 Self::default()
571 }
572
573 pub fn with_sweep_area(self, area: Area) -> Self {
574 Self {
575 sweep_area: area,
576 ..self
577 }
578 }
579 pub fn with_margin(self, margin: Margin) -> Self {
580 Self {
581 margin: Some(margin),
582 ..self
583 }
584 }
585 pub fn with_capture_overload(self, capture_overload:bool) -> Self {
586 Self {
587 capture_overload,
588 ..self
589 }
590 }
591}
592
593
594impl Event {
595
596 pub fn hits(&self, cx: &mut Cx, area: Area) -> Hit {
597 self.hits_with_options(cx, area, HitOptions::default())
598 }
599
600 pub fn hits_with_sweep_area(&self, cx: &mut Cx, area: Area, sweep_area: Area) -> Hit {
601 self.hits_with_options(cx, area, HitOptions::new().with_sweep_area(sweep_area))
602 }
603
604
605 pub fn hits_with_capture_overload(&self, cx: &mut Cx, area: Area, capture_overload: bool) -> Hit {
606 self.hits_with_options(cx, area, HitOptions::new().with_capture_overload(capture_overload))
607 }
608
609 pub fn hits_with_options(&self, cx: &mut Cx, area: Area, options: HitOptions) -> Hit {
610 if !area.is_valid(cx) {
611 return Hit::Nothing
612 }
613 match self {
614 Event::KeyFocus(kf) => {
615 if area == kf.prev {
616 return Hit::KeyFocusLost(kf.clone())
617 }
618 else if area == kf.focus {
619 return Hit::KeyFocus(kf.clone())
620 }
621 },
622 Event::KeyDown(kd) => {
623 if cx.keyboard.has_key_focus(area) {
624 return Hit::KeyDown(kd.clone())
625 }
626 },
627 Event::KeyUp(ku) => {
628 if cx.keyboard.has_key_focus(area) {
629 return Hit::KeyUp(ku.clone())
630 }
631 },
632 Event::TextInput(ti) => {
633 if cx.keyboard.has_key_focus(area) {
634 return Hit::TextInput(ti.clone())
635 }
636 },
637 Event::TextCopy(tc) => {
638 if cx.keyboard.has_key_focus(area) {
639 return Hit::TextCopy(tc.clone());
640 }
641 },
642 Event::TextCut(tc) => {
643 if cx.keyboard.has_key_focus(area) {
644 return Hit::TextCut(tc.clone());
645 }
646 },
647 Event::Scroll(e) => {
648 let digit_id = live_id!(mouse).into();
649
650 let rect = area.get_clipped_rect(&cx);
651 if Margin::rect_contains_with_margin(&rect, e.abs, &options.margin) {
652 let device = DigitDevice::Mouse {
654 button: 0,
655 };
656 return Hit::FingerScroll(FingerScrollEvent {
657 abs: e.abs,
658 rect,
659 window_id: e.window_id,
660 digit_id,
661 device,
662 modifiers: e.modifiers.clone(),
663 time: e.time,
664 scroll: e.scroll
665 })
666 }
667 },
668 Event::TouchUpdate(e) => {
669 if cx.fingers.test_sweep_lock(options.sweep_area) {
670 return Hit::Nothing
671 }
672 for t in &e.touches {
673 let digit_id = live_id_num!(touch, t.uid).into();
674 let device = DigitDevice::Touch {
675 uid: t.uid,
676 };
677
678 match t.state {
679 TouchState::Start => {
680
681 if !options.capture_overload && !t.handled.get().is_empty() {
682 continue;
683 }
684
685 if cx.fingers.get_area_capture(area).is_some(){
686 continue;
687 }
688
689 let rect = area.get_clipped_rect(&cx);
690 if !Margin::rect_contains_with_margin(&rect, t.abs, &options.margin) {
691 continue;
692 }
693
694 cx.fingers.capture_digit(digit_id, area, options.sweep_area, e.time, t.abs);
695
696 t.handled.set(area);
697 return Hit::FingerDown(FingerDownEvent {
698 window_id: e.window_id,
699 abs: t.abs,
700 digit_id,
701 device,
702 tap_count: cx.fingers.get_tap_count(),
703 modifiers: e.modifiers.clone(),
704 time: e.time,
705 rect,
706 })
707 }
708 TouchState::Stop => {
709 let tap_count = cx.fingers.get_tap_count();
710 let rect = area.get_clipped_rect(&cx);
711 if let Some(capture) = cx.fingers.get_area_capture(area) {
712 return Hit::FingerUp(FingerUpEvent {
713 abs_start: capture.abs_start,
714 rect: rect,
715 window_id: e.window_id,
716 abs: t.abs,
717 digit_id,
718 device,
719 tap_count,
720 capture_time: capture.time,
721 modifiers: e.modifiers.clone(),
722 time: e.time,
723 is_over: rect.contains(t.abs),
724 is_sweep: false,
725 })
726 }
727 }
728 TouchState::Move => {
729 let tap_count = cx.fingers.get_tap_count();
730 let rect = area.get_clipped_rect(&cx);
732
733 if !options.sweep_area.is_empty() {
735 if let Some(capture) = cx.fingers.get_digit_capture(digit_id) {
736 if capture.switch_capture.is_none()
737 && Margin::rect_contains_with_margin(&rect, t.abs, &options.margin) {
738 if t.handled.get().is_empty() {
739 t.handled.set(area);
740 if capture.area == area {
741 return Hit::FingerMove(FingerMoveEvent {
742 window_id: e.window_id,
743 abs: t.abs,
744 digit_id,
745 device,
746 tap_count,
747 modifiers: e.modifiers.clone(),
748 time: e.time,
749 abs_start: capture.abs_start,
750 rect,
751 is_over: true,
752 })
753 }
754 else if capture.sweep_area == options.sweep_area { capture.switch_capture = Some(area);
756 return Hit::FingerDown(FingerDownEvent {
757 window_id: e.window_id,
758 abs: t.abs,
759 digit_id,
760 device,
761 tap_count: cx.fingers.get_tap_count(),
762 modifiers: e.modifiers.clone(),
763 time: e.time,
764 rect: rect,
765 })
766 }
767 }
768 }
769 else if capture.area == area { if capture.switch_capture.is_none() {
771 capture.switch_capture = Some(Area::Empty);
772 }
773 return Hit::FingerUp(FingerUpEvent {
774 abs_start: capture.abs_start,
775 rect: rect,
776 window_id: e.window_id,
777 abs: t.abs,
778 digit_id,
779 device,
780 tap_count,
781 capture_time: capture.time,
782 modifiers: e.modifiers.clone(),
783 time: e.time,
784 is_sweep: true,
785 is_over: false,
786 });
787 }
788 }
789 }
790 else if let Some(capture) = cx.fingers.get_area_capture(area) {
791 return Hit::FingerMove(FingerMoveEvent {
792 window_id: e.window_id,
793 abs: t.abs,
794 digit_id,
795 device,
796 tap_count,
797 modifiers: e.modifiers.clone(),
798 time: e.time,
799 abs_start: capture.abs_start,
800 rect,
801 is_over: Margin::rect_contains_with_margin(&rect, t.abs, &options.margin),
802 })
803 }
804 }
805 TouchState::Stable => {}
806 }
807 }
808 }
809 Event::MouseMove(e) => { if cx.fingers.test_sweep_lock(options.sweep_area) {
811 return Hit::Nothing
812 }
813
814 let digit_id = live_id!(mouse).into();
815
816 let tap_count = cx.fingers.get_tap_count();
817 let hover_last = cx.fingers.get_hover_area(digit_id);
818 let rect = area.get_clipped_rect(&cx);
819
820 if let Some(button) = cx.fingers.first_mouse_button {
821 let device = DigitDevice::Mouse {
822 button,
823 };
824 if !options.sweep_area.is_empty() {
826 if let Some(capture) = cx.fingers.get_digit_capture(digit_id) {
827 if capture.switch_capture.is_none()
828 && Margin::rect_contains_with_margin(&rect, e.abs, &options.margin) {
829 if e.handled.get().is_empty() {
830 e.handled.set(area);
831 if capture.area == area {
832 return Hit::FingerMove(FingerMoveEvent {
833 window_id: e.window_id,
834 abs: e.abs,
835 digit_id,
836 device,
837 tap_count,
838 modifiers: e.modifiers.clone(),
839 time: e.time,
840 abs_start: capture.abs_start,
841 rect,
842 is_over: true,
843 })
844 }
845 else if capture.sweep_area == options.sweep_area { capture.switch_capture = Some(area);
847 cx.fingers.new_hover_area(digit_id, area);
848 return Hit::FingerDown(FingerDownEvent {
849 window_id: e.window_id,
850 abs: e.abs,
851 digit_id,
852 device,
853 tap_count: cx.fingers.get_tap_count(),
854 modifiers: e.modifiers.clone(),
855 time: e.time,
856 rect,
857 })
858 }
859 }
860 }
861 else if capture.area == area { if capture.switch_capture.is_none() {
863 capture.switch_capture = Some(Area::Empty);
864 }
865 return Hit::FingerUp(FingerUpEvent {
866 abs_start: capture.abs_start,
867 rect,
868 window_id: e.window_id,
869 abs: e.abs,
870 digit_id,
871 device,
872 tap_count,
873 capture_time: capture.time,
874 modifiers: e.modifiers.clone(),
875 time: e.time,
876 is_sweep: true,
877 is_over: false,
878 });
879
880 }
881 }
882 }
883 else if let Some(capture) = cx.fingers.get_area_capture(area) {
884 let event = Hit::FingerMove(FingerMoveEvent {
885 window_id: e.window_id,
886 abs: e.abs,
887 digit_id,
888 device,
889 tap_count,
890 modifiers: e.modifiers.clone(),
891 time: e.time,
892 abs_start: capture.abs_start,
893 rect,
894 is_over: Margin::rect_contains_with_margin(&rect, e.abs, &options.margin),
895 });
896 cx.fingers.new_hover_area(digit_id, area);
897 return event
898 }
899 }
900 else {
901 let device = DigitDevice::Mouse {
902 button: 0,
903 };
904
905 let handled_area = e.handled.get();
906
907 let fhe = FingerHoverEvent {
908 window_id: e.window_id,
909 abs: e.abs,
910 digit_id,
911 device,
912 modifiers: e.modifiers.clone(),
913 time: e.time,
914 rect,
915 };
916
917 if hover_last == area {
918 if handled_area.is_empty() && Margin::rect_contains_with_margin(&rect, e.abs, &options.margin) {
919 e.handled.set(area);
920 cx.fingers.new_hover_area(digit_id, area);
921 return Hit::FingerHoverOver(fhe)
922 }
923 else {
924 return Hit::FingerHoverOut(fhe)
925 }
926 }
927 else {
928 if handled_area.is_empty() && Margin::rect_contains_with_margin(&rect, e.abs, &options.margin) {
929 cx.fingers.new_hover_area(digit_id, area);
931 e.handled.set(area);
932 return Hit::FingerHoverIn(fhe)
933 }
934 }
935 }
936 },
937 Event::MouseDown(e) => {
938 if cx.fingers.test_sweep_lock(options.sweep_area) {
939 return Hit::Nothing
940 }
941
942 let digit_id = live_id!(mouse).into();
943
944 if !options.capture_overload && !e.handled.get().is_empty() {
945 return Hit::Nothing
946 }
947
948 if cx.fingers.first_mouse_button != Some(e.button) {
949 return Hit::Nothing
950 }
951
952 let rect = area.get_clipped_rect(&cx);
953 if !Margin::rect_contains_with_margin(&rect, e.abs, &options.margin) {
954 return Hit::Nothing
955 }
956
957 let device = DigitDevice::Mouse {
958 button: e.button,
959 };
960
961 if cx.fingers.get_digit_for_captured_area(area).is_some() {
962 return Hit::Nothing;
963 }
964
965 cx.fingers.capture_digit(digit_id, area, options.sweep_area, e.time, e.abs);
966 e.handled.set(area);
967 cx.fingers.new_hover_area(digit_id, area);
968 return Hit::FingerDown(FingerDownEvent {
969 window_id: e.window_id,
970 abs: e.abs,
971 digit_id,
972 device,
973 tap_count: cx.fingers.get_tap_count(),
974 modifiers: e.modifiers.clone(),
975 time: e.time,
976 rect: rect,
977 })
978 },
979 Event::MouseUp(e) => {
980 if cx.fingers.test_sweep_lock(options.sweep_area) {
981 return Hit::Nothing
982 }
983
984 if cx.fingers.first_mouse_button != Some(e.button) {
985 return Hit::Nothing
986 }
987
988 let digit_id = live_id!(mouse).into();
989
990 let device = DigitDevice::Mouse {
991 button: e.button,
992 };
993 let tap_count = cx.fingers.get_tap_count();
994 let rect = area.get_clipped_rect(&cx);
995
996 if let Some(capture) = cx.fingers.get_area_capture(area) {
997 let is_over = rect.contains(e.abs);
998 let event = Hit::FingerUp(FingerUpEvent {
999 abs_start: capture.abs_start,
1000 rect: rect,
1001 window_id: e.window_id,
1002 abs: e.abs,
1003 digit_id,
1004 device,
1005 tap_count,
1006 capture_time: capture.time,
1007 modifiers: e.modifiers.clone(),
1008 time: e.time,
1009 is_over,
1010 is_sweep: false,
1011 });
1012 if is_over {
1013 cx.fingers.new_hover_area(digit_id, area);
1014 }
1015 return event
1016 }
1017 },
1018 _ => ()
1019 };
1020 Hit::Nothing
1021 }
1022}