makepad_render/
events.rs

1use crate::cx::*;
2use std::any::TypeId;
3use std::collections::HashMap;
4
5#[derive(Clone, Debug, PartialEq, Default)]
6pub struct KeyModifiers {
7    pub shift: bool,
8    pub control: bool,
9    pub alt: bool,
10    pub logo: bool
11}
12
13#[derive(Clone, Default, Debug, PartialEq)]
14pub struct FingerDownEvent {
15    pub window_id: usize,
16    pub abs: Vec2,
17    pub rel: Vec2,
18    pub rect: Rect,
19    pub digit: usize,
20    pub tap_count: u32,
21    pub handled: bool,
22    pub is_touch: bool,
23    pub modifiers: KeyModifiers,
24    pub time: f64
25}
26
27#[derive(Clone, Default, Debug, PartialEq)]
28pub struct FingerMoveEvent {
29    pub window_id: usize,
30    pub abs: Vec2,
31    pub abs_start: Vec2,
32    pub rel: Vec2,
33    pub rel_start: Vec2,
34    pub rect: Rect,
35    pub is_over: bool,
36    pub digit: usize,
37    pub is_touch: bool,
38    pub modifiers: KeyModifiers,
39    pub time: f64
40}
41
42impl FingerMoveEvent {
43    pub fn move_distance(&self) -> f32 {
44        ((self.abs_start.x - self.abs.x).powf(2.) + (self.abs_start.y - self.abs.y).powf(2.)).sqrt()
45    }
46}
47
48#[derive(Clone, Default, Debug, PartialEq)]
49pub struct FingerUpEvent {
50    pub window_id: usize,
51    pub abs: Vec2,
52    pub abs_start: Vec2,
53    pub rel: Vec2,
54    pub rel_start: Vec2,
55    pub rect: Rect,
56    pub digit: usize,
57    pub is_over: bool,
58    pub is_touch: bool,
59    pub modifiers: KeyModifiers,
60    pub time: f64
61}
62
63#[derive(Clone, Debug, PartialEq)]
64pub enum HoverState {
65    In,
66    Over,
67    Out
68}
69
70impl Default for HoverState {
71    fn default() -> HoverState {
72        HoverState::Over
73    }
74}
75
76#[derive(Clone, Default, Debug, PartialEq)]
77pub struct FingerHoverEvent {
78    pub window_id: usize,
79    pub abs: Vec2,
80    pub rel: Vec2,
81    pub rect: Rect,
82    pub any_down: bool,
83    pub handled: bool,
84    pub hover_state: HoverState,
85    pub modifiers: KeyModifiers,
86    pub time: f64
87}
88
89#[derive(Clone, Default, Debug, PartialEq)]
90pub struct FingerScrollEvent {
91    pub window_id: usize,
92    pub abs: Vec2,
93    pub rel: Vec2,
94    pub rect: Rect,
95    pub scroll: Vec2,
96    pub is_wheel: bool,
97    pub handled: bool,
98    pub modifiers: KeyModifiers,
99    pub time: f64
100}
101
102#[derive(Clone, Default, Debug, PartialEq)]
103pub struct WindowGeomChangeEvent {
104    pub window_id: usize,
105    pub old_geom: WindowGeom,
106    pub new_geom: WindowGeom,
107}
108
109#[derive(Clone, Default, Debug, PartialEq)]
110pub struct WindowMovedEvent {
111    pub window_id: usize,
112    pub old_pos: Vec2,
113    pub new_pos: Vec2,
114}
115
116#[derive(Clone, Default, Debug, PartialEq)]
117pub struct AnimateEvent {
118    pub frame: u64,
119    pub time: f64
120}
121
122#[derive(Clone, Default, Debug, PartialEq)]
123pub struct FrameEvent {
124    pub frame: u64,
125    pub time: f64
126}
127
128#[derive(Clone, Default, Debug)]
129pub struct RedrawEvent {
130    pub area: Area
131}
132
133#[derive(Clone, Debug, PartialEq)]
134pub struct FileReadEvent {
135    pub read_id: u64,
136    pub data: Result<Vec<u8>, String>
137}
138
139#[derive(Clone, Debug, PartialEq)]
140pub struct TimerEvent {
141    pub timer_id: u64
142}
143
144#[derive(Clone, Debug, PartialEq)]
145pub struct SignalEvent {
146    pub signals: HashMap<Signal, Vec<StatusId>>
147}
148
149#[derive(Clone, Debug, PartialEq)]
150pub struct FileWriteEvent {
151    id: u64,
152    error: Option<String>
153}
154
155#[derive(Clone, Debug, PartialEq)]
156pub struct KeyEvent {
157    pub key_code: KeyCode,
158    //pub key_char: char,
159    pub is_repeat: bool,
160    pub modifiers: KeyModifiers,
161    pub time: f64
162}
163
164#[derive(Clone, Debug, PartialEq)]
165pub struct KeyFocusEvent {
166    pub prev: Area,
167    pub focus: Area,
168}
169
170#[derive(Clone, Debug, PartialEq)]
171pub struct TextInputEvent {
172    pub input: String,
173    pub replace_last: bool,
174    pub was_paste: bool
175}
176
177#[derive(Clone, Debug, PartialEq)]
178pub struct TextCopyEvent {
179    pub response: Option<String>
180}
181
182#[derive(Clone, Debug, PartialEq)]
183pub struct WindowCloseRequestedEvent {
184    pub window_id: usize,
185    pub accept_close: bool
186}
187
188#[derive(Clone, Debug, PartialEq)]
189pub struct WindowClosedEvent {
190    pub window_id: usize
191}
192
193#[derive(Clone, Debug, PartialEq)]
194pub struct WindowResizeLoopEvent {
195    pub was_started: bool,
196    pub window_id: usize
197}
198
199#[derive(Clone, Debug, PartialEq)]
200pub enum WindowDragQueryResponse {
201    NoAnswer,
202    Client,
203    Caption,
204    SysMenu, // windows only
205}
206
207#[derive(Clone, Debug, PartialEq)]
208pub struct WindowDragQueryEvent {
209    pub window_id: usize,
210    pub abs: Vec2,
211    pub response: WindowDragQueryResponse,
212}
213
214#[derive(Clone, Debug, PartialEq)]
215pub enum Event {
216    None,
217    Construct,
218    Destruct,
219    Draw,
220    Paint,
221    AppFocus,
222    AppFocusLost,
223    AnimEnded(AnimateEvent),
224    Animate(AnimateEvent),
225    Frame(FrameEvent),
226    WindowSetHoverCursor(MouseCursor),
227    WindowDragQuery(WindowDragQueryEvent),
228    WindowCloseRequested(WindowCloseRequestedEvent),
229    WindowClosed(WindowClosedEvent),
230    WindowGeomChange(WindowGeomChangeEvent),
231    WindowResizeLoop(WindowResizeLoopEvent),
232    FingerDown(FingerDownEvent),
233    FingerMove(FingerMoveEvent),
234    FingerHover(FingerHoverEvent),
235    FingerUp(FingerUpEvent),
236    FingerScroll(FingerScrollEvent),
237    FileRead(FileReadEvent),
238    FileWrite(FileWriteEvent),
239    Timer(TimerEvent),
240    Signal(SignalEvent),
241    Command(CommandId),
242    KeyFocus(KeyFocusEvent),
243    KeyFocusLost(KeyFocusEvent),
244    KeyDown(KeyEvent),
245    KeyUp(KeyEvent),
246    TextInput(TextInputEvent),
247    TextCopy(TextCopyEvent)
248}
249
250impl Default for Event {
251    fn default() -> Event {
252        Event::None
253    }
254}
255
256pub enum HitTouch {
257    Single,
258    Multi
259}
260
261#[derive(Clone, Debug, Default)]
262pub struct HitOpt {
263    pub use_multi_touch: bool,
264    pub margin: Option<Margin>,
265}
266
267impl Event {
268    
269    pub fn hits(&mut self, cx: &mut Cx, area: Area, opt: HitOpt) -> Event {
270        match self {
271            Event::KeyFocus(kf) => {
272                if area == kf.prev {
273                    return Event::KeyFocusLost(kf.clone())
274                }
275                else if area == kf.focus {
276                    return Event::KeyFocus(kf.clone())
277                }
278            },
279            Event::KeyDown(_) => {
280                if area == cx.key_focus {
281                    return self.clone();
282                }
283            },
284            Event::KeyUp(_) => {
285                if area == cx.key_focus {
286                    return self.clone();
287                }
288            },
289            Event::TextInput(_) => {
290                if area == cx.key_focus {
291                    return self.clone();
292                }
293            },
294            Event::TextCopy(_) => {
295                if area == cx.key_focus {
296                    return Event::TextCopy(
297                        TextCopyEvent {response: None}
298                    );
299                }
300            },
301            Event::Animate(_) => {
302                for anim in &cx.playing_anim_areas {
303                    if anim.area == area {
304                        return self.clone()
305                    }
306                }
307            },
308            Event::Frame(_) => {
309                for frame_area in &cx._frame_callbacks {
310                    if *frame_area == area {
311                        return self.clone()
312                    }
313                }
314            },
315            Event::AnimEnded(_) => {
316                for anim in &cx.ended_anim_areas {
317                    if anim.area == area {
318                        return self.clone()
319                    }
320                }
321            },
322            Event::FingerScroll(fe) => {
323                let rect = area.get_rect(&cx);
324                if !fe.handled && rect.contains_with_margin(fe.abs.x, fe.abs.y, &opt.margin) {
325                    //fe.handled = true;
326                    return Event::FingerScroll(FingerScrollEvent {
327                        rel: Vec2 {x: fe.abs.x - rect.x, y: fe.abs.y - rect.y},
328                        rect: rect,
329                        ..fe.clone()
330                    })
331                }
332            },
333            Event::FingerHover(fe) => {
334                let rect = area.get_rect(&cx);
335                
336                if cx._finger_over_last_area == area {
337                    let mut any_down = false;
338                    for fin_area in &cx.captured_fingers {
339                        if *fin_area == area {
340                            any_down = true;
341                            break;
342                        }
343                    }
344                    if !fe.handled && rect.contains_with_margin(fe.abs.x, fe.abs.y, &opt.margin) {
345                        fe.handled = true;
346                        if let HoverState::Out = fe.hover_state {
347                            //    cx.finger_over_last_area = Area::Empty;
348                        }
349                        else {
350                            cx.finger_over_last_area = area;
351                        }
352                        return Event::FingerHover(FingerHoverEvent {
353                            rel: area.abs_to_rel(cx, fe.abs),
354                            rect: rect,
355                            any_down:any_down,
356                            ..fe.clone()
357                        })
358                    }
359                    else {
360                        //self.was_over_last_call = false;
361                        return Event::FingerHover(FingerHoverEvent {
362                            rel: area.abs_to_rel(cx, fe.abs),
363                            rect: rect,
364                            any_down:any_down,
365                            hover_state: HoverState::Out,
366                            ..fe.clone()
367                        })
368                    }
369                }
370                else {
371                    if !fe.handled && rect.contains_with_margin(fe.abs.x, fe.abs.y, &opt.margin) {
372                        let mut any_down = false;
373                        for fin_area in &cx.captured_fingers {
374                            if *fin_area == area {
375                                any_down = true;
376                                break;
377                            }
378                        }
379                        cx.finger_over_last_area = area;
380                        fe.handled = true;
381                        //self.was_over_last_call = true;
382                        return Event::FingerHover(FingerHoverEvent {
383                            rel: area.abs_to_rel(cx, fe.abs),
384                            rect: rect,
385                            any_down:any_down,
386                            hover_state: HoverState::In,
387                            ..fe.clone()
388                        })
389                    }
390                }
391            },
392            Event::FingerMove(fe) => {
393                // check wether our digit is captured, otherwise don't send
394                if cx.captured_fingers[fe.digit] == area {
395                    let abs_start = cx.finger_down_abs_start[fe.digit];
396                    let rel_start = cx.finger_down_rel_start[fe.digit];
397                    let rect = area.get_rect(&cx);
398                    return Event::FingerMove(FingerMoveEvent {
399                        abs_start: abs_start,
400                        rel: area.abs_to_rel(cx, fe.abs),
401                        rel_start: rel_start,
402                        rect: rect,
403                        is_over: rect.contains_with_margin(fe.abs.x, fe.abs.y, &opt.margin),
404                        ..fe.clone()
405                    })
406                }
407            },
408            Event::FingerDown(fe) => {
409                if !fe.handled {
410                    let rect = area.get_rect(&cx);
411                    if rect.contains_with_margin(fe.abs.x, fe.abs.y, &opt.margin) {
412                        // scan if any of the fingers already captured this area
413                        if !opt.use_multi_touch {
414                            for fin_area in &cx.captured_fingers {
415                                if *fin_area == area {
416                                    return Event::None;
417                                }
418                            }
419                        }
420                        cx.captured_fingers[fe.digit] = area;
421                        let rel = area.abs_to_rel(cx, fe.abs);
422                        cx.finger_down_abs_start[fe.digit] = fe.abs;
423                        cx.finger_down_rel_start[fe.digit] = rel;
424                        fe.handled = true;
425                        return Event::FingerDown(FingerDownEvent {
426                            rel: rel,
427                            rect: rect,
428                            ..fe.clone()
429                        })
430                    }
431                }
432            },
433            Event::FingerUp(fe) => {
434                if cx.captured_fingers[fe.digit] == area {
435                    cx.captured_fingers[fe.digit] = Area::Empty;
436                    let abs_start = cx.finger_down_abs_start[fe.digit];
437                    let rel_start = cx.finger_down_rel_start[fe.digit];
438                    let rect = area.get_rect(&cx);
439                    return Event::FingerUp(FingerUpEvent {
440                        is_over: rect.contains(fe.abs.x, fe.abs.y),
441                        abs_start: abs_start,
442                        rel_start: rel_start,
443                        rel: area.abs_to_rel(cx, fe.abs),
444                        rect: rect,
445                        ..fe.clone()
446                    })
447                }
448            },
449            _ => ()
450        };
451        return Event::None;
452    }
453}
454
455#[derive(Hash, Eq, PartialEq, Clone, Copy, Debug, Default)]
456pub struct Signal {
457    pub signal_id: usize
458}
459
460impl Signal {
461    pub fn empty() -> Signal {
462        Signal {
463            signal_id: 0
464        }
465    }
466    
467    pub fn is_empty(&self) -> bool {
468        self.signal_id == 0
469    }
470    
471    pub fn send(&self, cx:&mut Cx, status:StatusId){
472        cx.send_signal(*self, status);
473    }
474
475    pub fn post(&self, status:StatusId){
476        Cx::post_signal(*self, status);
477    }
478}
479
480
481// Status
482
483
484#[derive(PartialEq, Copy, Clone, Hash, Eq, Debug)]
485pub struct StatusId(pub TypeId);
486
487impl Into<StatusId> for UniqueId {
488    fn into(self) -> StatusId {StatusId(self.0)}
489}
490
491
492
493
494
495
496#[derive(Clone, Debug, Default)]
497pub struct FileRead {
498    pub path: String,
499    pub read_id: u64
500}
501
502impl FileRead {
503    pub fn is_pending(&self) -> bool {
504        self.read_id != 0
505    }
506    
507    pub fn resolve_utf8<'a>(&mut self, fr: &'a FileReadEvent) -> Option<Result<&'a str,String>> {
508        if fr.read_id == self.read_id {
509            self.read_id = 0;
510            if let Ok(str_data) = &fr.data {
511                if let Ok(utf8_string) = std::str::from_utf8(&str_data) {
512                    return Some(Ok(utf8_string))
513                }
514                else {
515                    return Some(Err(format!("can't parse file as utf8 {}", self.path)))
516                }
517            }
518            else if let Err(err) = &fr.data {
519                return Some(Err(format!("can't load file as utf8 {} {}", self.path, err)))
520            }
521        }
522        return None
523    }
524}
525
526#[derive(Clone, Debug, Default)]
527pub struct Timer {
528    pub timer_id: u64
529}
530
531impl Timer {
532    pub fn empty() -> Timer {
533        Timer {
534            timer_id: 0,
535        }
536    }
537    
538    pub fn is_empty(&self) -> bool {
539        self.timer_id == 0
540    }
541    
542    pub fn is_timer(&mut self, te: &TimerEvent) -> bool {
543        te.timer_id == self.timer_id
544    }
545}
546
547impl Event {
548    pub fn set_handled(&mut self, set: bool) {
549        match self {
550            Event::FingerHover(fe) => {
551                fe.handled = set;
552            },
553            Event::FingerScroll(fe) => {
554                fe.handled = set;
555            },
556            Event::FingerDown(fe) => {
557                fe.handled = set;
558            },
559            _ => ()
560        }
561    }
562    
563    pub fn handled(&self) -> bool {
564        match self {
565            Event::FingerHover(fe) => {
566                fe.handled
567            },
568            Event::FingerScroll(fe) => {
569                fe.handled
570            },
571            Event::FingerDown(fe) => {
572                fe.handled
573            },
574            
575            _ => false
576        }
577    }
578    
579    
580}
581
582// lowest common denominator keymap between desktop and web
583#[derive(Clone, Copy, PartialEq, Debug)]
584pub enum KeyCode {
585    Escape,
586    
587    Backtick,
588    Key0,
589    Key1,
590    Key2,
591    Key3,
592    Key4,
593    Key5,
594    Key6,
595    Key7,
596    Key8,
597    Key9,
598    Minus,
599    Equals,
600    
601    Backspace,
602    Tab,
603    
604    KeyQ,
605    KeyW,
606    KeyE,
607    KeyR,
608    KeyT,
609    KeyY,
610    KeyU,
611    KeyI,
612    KeyO,
613    KeyP,
614    LBracket,
615    RBracket,
616    Return,
617    
618    KeyA,
619    KeyS,
620    KeyD,
621    KeyF,
622    KeyG,
623    KeyH,
624    KeyJ,
625    KeyK,
626    KeyL,
627    Semicolon,
628    Quote,
629    Backslash,
630    
631    KeyZ,
632    KeyX,
633    KeyC,
634    KeyV,
635    KeyB,
636    KeyN,
637    KeyM,
638    Comma,
639    Period,
640    Slash,
641    
642    Control,
643    Alt,
644    Shift,
645    Logo,
646    
647    //RightControl,
648    //RightShift,
649    //RightAlt,
650    //RightLogo,
651    
652    Space,
653    Capslock,
654    F1,
655    F2,
656    F3,
657    F4,
658    F5,
659    F6,
660    F7,
661    F8,
662    F9,
663    F10,
664    F11,
665    F12,
666    
667    PrintScreen,
668    Scrolllock,
669    Pause,
670    
671    Insert,
672    Delete,
673    Home,
674    End,
675    PageUp,
676    PageDown,
677    
678    Numpad0,
679    Numpad1,
680    Numpad2,
681    Numpad3,
682    Numpad4,
683    Numpad5,
684    Numpad6,
685    Numpad7,
686    Numpad8,
687    Numpad9,
688    
689    NumpadEquals,
690    NumpadSubtract,
691    NumpadAdd,
692    NumpadDecimal,
693    NumpadMultiply,
694    NumpadDivide,
695    Numlock,
696    NumpadEnter,
697    
698    ArrowUp,
699    ArrowDown,
700    ArrowLeft,
701    ArrowRight,
702    
703    Unknown
704}
705
706impl Default for KeyCode{
707    fn default()->Self{KeyCode::Unknown}
708}