makepad_platform/event/
finger.rs

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// Mouse events
33
34
35#[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// Touch events
86
87#[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// Finger API
117
118
119#[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    /*
214    pub (crate) fn get_captured_area(&self, digit_id: DigitId) -> Area {
215        if let Some(cxdigit) = self.captures.iter().find( | v | v.digit_id == digit_id) {
216            cxdigit.area
217        }
218        else {
219            Area::Empty
220        }
221    }*/
222    /*
223    pub (crate) fn get_capture_time(&self, digit_id: DigitId) -> f64 {
224        if let Some(cxdigit) = self.captures.iter().find( | v | v.digit_id == digit_id) {
225            cxdigit.time
226        }
227        else {
228            0.0
229        }
230    }*/
231    
232    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        /*if let Some(capture) = self.captures.iter_mut().find( | v | v.digit_id == digit_id) {
290            capture.sweep_area = sweep_area;
291            capture.area = area;
292            capture.time = time;
293            capture.abs_start = abs_start;
294        }
295        else {*/
296        self.captures.push(CxDigitCapture {
297            sweep_area,
298            digit_id,
299            area,
300            time,
301            abs_start,
302            switch_capture: None
303        })
304        /*}*/
305    }
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    // pub fn xr_input(&self) -> Option<usize> {if let DigitDevice::XR(input) = self {Some(*input)}else {None}}
440}
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/*
552pub enum HitTouch {
553    Single,
554    Multi
555}*/
556
557
558// Status
559
560
561#[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                    //fe.handled = true;
653                    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 hover_last = cx.fingers.get_hover_area(digit_id);
731                            let rect = area.get_clipped_rect(&cx);
732                            
733                            //let handled_area = t.handled.get();
734                            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 { // take over the capture
755                                                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 { // we are not over the area
770                                        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) => { // ok so we dont get hovers
810                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                    //let handled_area = e.handled.get();
825                    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 { // take over the capture
846                                        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 { // we are not over the area
862                                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                            //let any_captured = cx.fingers.get_digit_for_captured_area(area);
930                            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}