makepad_platform/event/
event.rs

1use {
2    std::{
3        rc::Rc,
4        cell::Cell,
5        collections::{HashSet, HashMap}
6    },
7    crate::{
8        //makepad_live_compiler::LiveEditEvent,
9        makepad_live_id::LiveId,
10        cx::Cx,
11        area::Area,
12        //midi::{Midi1InputData, MidiInputInfo},
13        event::{
14            finger::*,
15            keyboard::*,
16            window::*,
17            xr::*,
18            drag_drop::*,
19            designer::*,
20            network::*,
21            video_playback::*,
22        },
23        action::ActionsBuf,
24        animator::Ease,
25        audio::AudioDevicesEvent,
26        midi::MidiPortsEvent,
27        video::VideoInputsEvent,
28        draw_list::DrawListId,
29    },
30};
31
32/// Events that can be sent between the Makepad framework and the application.
33#[derive(Debug)]
34pub enum Event {
35    /// The application has just been created.
36    ///
37    /// * This event is always sent exactly once (before any other event)
38    ///   at the very beginning of the application lifecycle.
39    /// * This is a good point for one-time initialization of application state, resources, tasks, etc.
40    ///
41    /// | Platform | Lifecycle Function/Callback |
42    /// |----------|-----------------------------|
43    /// | Android  | [`onCreate`]                |
44    /// | others   | coming soon...              |
45    ///
46    /// [`onCreate`]: https://developer.android.com/reference/android/app/Activity#onCreate(android.os.Bundle)
47    Startup,
48    /// The application is being shut down is about to close and be destroyed.
49    ///
50    /// * This event may not be sent at all, so you should not rely on it.
51    ///   * For example, some mobile platforms do not always send this event when closing the app.
52    ///   * Desktop platforms do typically send this event when the user closes the application.
53    /// * If it is sent, it will be sent only once at the end of the application lifecycle.
54    ///
55    /// | Platform | Lifecycle Function/Callback |
56    /// |----------|-----------------------------|
57    /// | Android  | [`onDestroy`]               |
58    /// | others   | coming soon...              |
59    ///
60    /// [`onDestroy`]: https://developer.android.com/reference/android/app/Activity#onDestroy()
61    Shutdown,
62
63    /// The application has been started in the foreground and is now visible to the user,
64    /// but is not yet actively receiving user input.
65    ///
66    /// * This event can be sent multiple times over the course of the application's lifecycle.
67    ///   * For example, it will be sent right after `Startup` has been sent
68    ///     at the beginning of the application.
69    ///   * It can also be sent after `Stop` if the user starts the application again
70    ///     by navigating back to the application.
71    ///   * It will be sent when the application was re-opened and shown again
72    ///     after being previously hidden in the background.
73    ///
74    /// | Platform | Lifecycle Function/Callback |
75    /// |----------|-----------------------------|
76    /// | Android  | [`onStart`]                 |
77    /// | others   | coming soon...              |
78    ///
79    /// [`onStart`]: https://developer.android.com/reference/android/app/Activity#onStart(
80    #[doc(alias("start, restart, show"))]
81    Foreground,
82    /// The application has been hidden in the background and is no longer visible to the user.
83    ///
84    /// * This event may be sent multiple times over the course of the application's lifecycle.
85    ///   * For example, it can be sent after `Pause` has been sent, i.e., when the user
86    ///     navigates away from the application, causing it to be no longer visible.
87    /// * This is a good point to stop updating the UI/animations and other visual elements.
88    ///
89    /// | Platform | Lifecycle Function/Callback |
90    /// |----------|-----------------------------|
91    /// | Android  | [`onStop`]                  |
92    /// | others   | coming soon...              |
93    ///
94    /// [`onStop`]: https://developer.android.com/reference/android/app/Activity#onStop()
95    #[doc(alias("stop, hide")) ]
96    Background,
97
98    /// The application is now in the foreground and being actively used,
99    /// i.e., it is receiving input from the user.
100    ///
101    /// * This event may be sent multiple times over the course of the application's lifecycle.
102    ///   * For example, it will be sent after `Start` once the application is fully in the foreground.
103    ///     It can also be sent after `Pause`, once the user navigates back to the application.
104    ///
105    /// | Platform | Lifecycle Function/Callback |
106    /// |----------|-----------------------------|
107    /// | Android  | [`onResume`]                |
108    /// | others   | coming soon...              |
109    ///
110    /// [`onResume`]: https://developer.android.com/reference/android/app/Activity#onResume()
111    Resume,
112    /// The application has been temporarily paused and is still visible in the foregound,
113    /// but is not actively receiving input from the user.
114    ///
115    /// * This event may be sent multiple times over the course of the application's lifecycle.
116    /// * This is a good point to save temporary application states in case the application
117    ///   is about to be stopped or destroyed.
118    ///
119    /// | Platform | Lifecycle Function/Callback |
120    /// |----------|-----------------------------|
121    /// | Android  | [`onPause`]                 |
122    /// | others   | coming soon...              |
123    ///
124    /// [`onPause`]: https://developer.android.com/reference/android/app/Activity#onPause()
125    Pause,
126    
127    Draw(DrawEvent),
128    LiveEdit,
129    /// The application has gained focus and is now the active window receiving user input.
130    AppGotFocus,
131    /// The application has lost focus and is no longer the active window receiving user input.
132    AppLostFocus,
133    NextFrame(NextFrameEvent),
134    XrUpdate(XrUpdateEvent),
135    XrLocal(XrLocalEvent),
136    
137    WindowDragQuery(WindowDragQueryEvent),
138    WindowCloseRequested(WindowCloseRequestedEvent),
139    WindowClosed(WindowClosedEvent),
140    WindowGeomChange(WindowGeomChangeEvent),
141    VirtualKeyboard(VirtualKeyboardEvent),
142    ClearAtlasses,
143
144    /// The raw event that occurs when the user presses a mouse button down.
145    ///
146    /// Do not match upon or handle this event directly; instead, use the family of
147    /// `hit`` functions ([`Event::hits()`]) and handle the returned [`Hit::FingerDown`].
148    MouseDown(MouseDownEvent),
149    /// The raw event that occurs when the user moves the mouse.
150    ///
151    /// Do not match upon or handle this event directly; instead, use the family of
152    /// `hit` functions ([`Event::hits()`]) and handle the returned [`Hit`].
153    MouseMove(MouseMoveEvent),
154    /// The raw event that occurs when the user releases a previously-pressed mouse button.
155    ///
156    /// Do not match upon or handle this event directly; instead, use the family of
157    /// `hit` functions ([`Event::hits()`]) and handle the returned [`Hit::FingerUp`].
158    MouseUp(MouseUpEvent),
159    /// The raw event that occurs when the user moves the mouse outside of the window.
160    ///
161    /// Do not match upon or handle this event directly; instead, use the family of
162    /// `hit` functions ([`Event::hits()`]) and handle the returned [`Hit::FingerOverOut`].
163    MouseLeave(MouseLeaveEvent),
164    /// The raw event that occurs when the user touches the screen.
165    ///
166    /// Do not match upon or handle this event directly; instead, use the family of
167    /// `hit` functions ([`Event::hits()`]) and handle the returned [`Hit`].
168    TouchUpdate(TouchUpdateEvent),
169    /// The raw event that occurs when the user finishes a long press touch/click.
170    ///
171    /// Do not match upon or handle this event directly; instead, use the family of
172    /// `hit` functions ([`Event::hits()`]) and handle the returned [`Hit::FingerLongPress`].
173    LongPress(LongPressEvent),
174    /// The raw event that occurs when the user scrolls, e.g.,
175    /// by using the mouse wheel or a touch flick.
176    ///
177    /// Do not match upon or handle this event directly; instead use the family of
178    /// `hit` functions ([`Event::hits()`]) and handle the returned [`Hit::FingerScroll`].
179    Scroll(ScrollEvent), // this is the MouseWheel / touch scroll event sent by the OS
180
181    Timer(TimerEvent),
182
183    Signal,
184    Trigger(TriggerEvent),
185    MacosMenuCommand(LiveId),
186    KeyFocus(KeyFocusEvent),
187    KeyFocusLost(KeyFocusEvent),
188    KeyDown(KeyEvent),
189    KeyUp(KeyEvent),
190    TextInput(TextInputEvent),
191    TextCopy(TextClipboardEvent),
192    TextCut(TextClipboardEvent),
193
194    Drag(DragEvent),
195    Drop(DropEvent),
196    DragEnd,
197
198    Actions(ActionsBuf),
199    AudioDevices(AudioDevicesEvent),
200    MidiPorts(MidiPortsEvent),
201    VideoInputs(VideoInputsEvent),
202    NetworkResponses(NetworkResponsesEvent),
203
204    VideoPlaybackPrepared(VideoPlaybackPreparedEvent),
205    VideoTextureUpdated(VideoTextureUpdatedEvent),
206    VideoPlaybackCompleted(VideoPlaybackCompletedEvent),
207    VideoPlaybackResourcesReleased(VideoPlaybackResourcesReleasedEvent),
208    VideoDecodingError(VideoDecodingErrorEvent),
209    TextureHandleReady(TextureHandleReadyEvent),
210    
211    /// The "go back" navigational button or gesture was performed.
212    ///
213    /// Tip: use the [`Event::consume_back_pressed()`] method to handle this event
214    /// instead of matching on it directly.
215    ///
216    /// Once a widget has handled this event, it should set the `handled` flag to `true`
217    /// to ensure that a single "go back" action is not handled multiple times.
218    BackPressed {
219        handled: Cell<bool>,
220    },
221    #[cfg(target_arch = "wasm32")]
222    ToWasmMsg(ToWasmMsgEvent),
223    
224    DesignerPick(DesignerPickEvent),
225}
226
227impl Event{
228    pub fn name(&self)->&'static str{
229        Self::name_from_u32(self.to_u32())
230    }
231
232    pub fn name_from_u32(v:u32)->&'static str{
233        match v{
234            1=>"Startup",
235            2=>"Shutdown",
236
237            3=>"Foreground",
238            4=>"Background",
239
240            5=>"Resume",
241            6=>"Pause",
242
243            7=>"Draw",
244            8=>"LiveEdit",
245            9=>"AppGotFocus",
246            10=>"AppLostFocus",
247            11=>"NextFrame",
248            12=>"XRUpdate",
249
250            13=>"WindowDragQuery",
251            14=>"WindowCloseRequested",
252            15=>"WindowClosed",
253            16=>"WindowGeomChange",
254            17=>"VirtualKeyboard",
255            18=>"ClearAtlasses",
256
257            19=>"MouseDown",
258            20=>"MouseMove",
259            21=>"MouseUp",
260            22=>"TouchUpdate",
261            23=>"LongPress",
262            24=>"Scroll",
263
264            25=>"Timer",
265
266            26=>"Signal",
267            27=>"Trigger",
268            28=>"MacosMenuCommand",
269            29=>"KeyFocus",
270            30=>"KeyFocusLost",
271            31=>"KeyDown",
272            32=>"KeyUp",
273            33=>"TextInput",
274            34=>"TextCopy",
275            35=>"TextCut",
276
277            36=>"Drag",
278            37=>"Drop",
279            38=>"DragEnd",
280
281            39=>"AudioDevices",
282            40=>"MidiPorts",
283            41=>"VideoInputs",
284            42=>"NetworkResponses",
285
286            43=>"VideoPlaybackPrepared",
287            44=>"VideoTextureUpdated",
288            45=>"VideoPlaybackCompleted",
289            46=>"VideoDecodingError",
290            47=>"VideoPlaybackResourcesReleased",
291            48=>"TextureHandleReady",
292            49=>"MouseLeave",
293            50=>"Actions",
294            51=>"BackPressed",
295
296            #[cfg(target_arch = "wasm32")]
297            52=>"ToWasmMsg",
298            
299            53=>"DesignerPick",
300            54=>"XrLocal",
301            _=>panic!()
302        }
303    }
304
305    pub fn to_u32(&self)->u32{
306        match self{
307            Self::Startup=>1,
308            Self::Shutdown=>2,
309
310            Self::Foreground=>3,
311            Self::Background=>4,
312
313            Self::Resume=>5,
314            Self::Pause=>6,
315
316            Self::Draw(_)=>7,
317            Self::LiveEdit=>8,
318            Self::AppGotFocus=>9,
319            Self::AppLostFocus=>10,
320            Self::NextFrame(_)=>11,
321            Self::XrUpdate(_)=>12,
322
323            Self::WindowDragQuery(_)=>13,
324            Self::WindowCloseRequested(_)=>14,
325            Self::WindowClosed(_)=>15,
326            Self::WindowGeomChange(_)=>16,
327            Self::VirtualKeyboard(_)=>17,
328            Self::ClearAtlasses=>18,
329
330            Self::MouseDown(_)=>19,
331            Self::MouseMove(_)=>20,
332            Self::MouseUp(_)=>21,
333            Self::TouchUpdate(_)=>22,
334            Self::LongPress(_)=>23,
335            Self::Scroll(_)=>24,
336
337            Self::Timer(_)=>25,
338
339            Self::Signal=>26,
340            Self::Trigger(_)=>27,
341            Self::MacosMenuCommand(_)=>28,
342            Self::KeyFocus(_)=>29,
343            Self::KeyFocusLost(_)=>30,
344            Self::KeyDown(_)=>31,
345            Self::KeyUp(_)=>32,
346            Self::TextInput(_)=>33,
347            Self::TextCopy(_)=>34,
348            Self::TextCut(_)=>35,
349
350            Self::Drag(_)=>36,
351            Self::Drop(_)=>37,
352            Self::DragEnd=>38,
353
354            Self::AudioDevices(_)=>39,
355            Self::MidiPorts(_)=>40,
356            Self::VideoInputs(_)=>41,
357            Self::NetworkResponses(_)=>42,
358
359            Self::VideoPlaybackPrepared(_)=>43,
360            Self::VideoTextureUpdated(_)=>44,
361            Self::VideoPlaybackCompleted(_)=>45,
362            Self::VideoDecodingError(_)=>46,
363            Self::VideoPlaybackResourcesReleased(_)=>47,
364            Self::TextureHandleReady(_)=>48,
365            Self::MouseLeave(_)=>49,
366            Self::Actions(_)=>50,
367            Self::BackPressed{..}=>51,
368            
369            #[cfg(target_arch = "wasm32")]
370            Self::ToWasmMsg(_)=>52,
371            
372            Self::DesignerPick(_) =>53,
373            Self::XrLocal(_)=>54
374        }
375    }
376
377    /// A convenience function to check if the event is a [`BackPressed`] event
378    /// that has not yet been handled, and then mark it as handled.
379    ///
380    /// Returns `true` if the event was a [`BackPressed`] event that wasn't already handled.
381    pub fn back_pressed(&self) -> bool {
382        if let Self::BackPressed { handled } = self {
383            if !handled.get() {
384                handled.set(true);
385                return true;
386            }
387        }
388        false
389    }
390}
391
392
393#[derive(Debug)]
394pub enum Hit{
395    KeyFocus(KeyFocusEvent),
396    KeyFocusLost(KeyFocusEvent),
397    KeyDown(KeyEvent),
398    KeyUp(KeyEvent),
399    Trigger(TriggerHitEvent),
400    TextInput(TextInputEvent),
401    TextCopy(TextClipboardEvent),
402    TextCut(TextClipboardEvent),
403
404    FingerScroll(FingerScrollEvent),
405    FingerDown(FingerDownEvent),
406    FingerMove(FingerMoveEvent),
407    FingerHoverIn(FingerHoverEvent),
408    FingerHoverOver(FingerHoverEvent),
409    FingerHoverOut(FingerHoverEvent),
410    FingerUp(FingerUpEvent),
411    FingerLongPress(FingerLongPressEvent),
412    
413    DesignerPick(DesignerPickEvent),
414
415    Nothing
416}
417
418#[derive(Clone)]
419pub enum DragHit{
420    Drag(DragHitEvent),
421    Drop(DropHitEvent),
422    DragEnd,
423    NoHit
424}
425
426impl Event{
427    pub fn requires_visibility(&self) -> bool{
428        match self{
429            Self::MouseDown(_)|
430            Self::MouseMove(_)|
431            Self::TouchUpdate(_)|
432            Self::Scroll(_)=>true,
433            _=>false
434        }
435    }
436}
437
438#[derive(Clone, Debug)]
439pub struct TriggerEvent {
440    pub triggers: HashMap<Area, Vec<Trigger>>
441}
442
443/*
444#[derive(Clone, Debug)]
445pub struct MidiInputListEvent {
446    pub inputs: Vec<MidiInputInfo>,
447}*/
448
449#[derive(Clone, Debug, Default)]
450pub struct DrawEvent {
451    pub draw_lists: Vec<DrawListId>,
452    pub draw_lists_and_children: Vec<DrawListId>,
453    pub redraw_all: bool,
454    pub xr_state: Option<Rc<XrState>>
455}
456
457impl DrawEvent{
458    pub fn will_redraw(&self) -> bool {
459        self.redraw_all
460            || self.draw_lists.len() != 0
461            || self.draw_lists_and_children.len() != 0
462    }
463
464    pub fn draw_list_will_redraw(&self, cx:&Cx, draw_list_id:DrawListId)->bool{
465         if self.redraw_all {
466            return true;
467        }
468        // figure out if areas are in some way a child of view_id, then we need to redraw
469        for check_draw_list_id in &self.draw_lists {
470            let mut next = Some(*check_draw_list_id);
471            while let Some(vw) = next{
472                if vw == draw_list_id {
473                    return true
474                }
475                if let Some(n) = cx.draw_lists.checked_index(vw){
476                    next = n.codeflow_parent_id;
477                }
478                else{ // a drawlist in our redraw lists was reused
479                    break;
480                }
481            }
482        }
483        // figure out if areas are in some way a parent of view_id, then redraw
484        for check_draw_list_id in &self.draw_lists_and_children {
485            let mut next = Some(draw_list_id);
486            while let Some(vw) = next{
487                if vw == *check_draw_list_id {
488                    return true
489                }
490                if let Some(n) = cx.draw_lists.checked_index(vw){
491                    next = n.codeflow_parent_id;
492                }
493                else{ // a drawlist in our redraw lists was reused
494                    break;
495                }
496            }
497        }
498        false
499    }
500}
501
502
503#[derive(Clone, Debug)]
504pub enum VirtualKeyboardEvent{
505    WillShow{time:f64, height:f64, duration:f64, ease:Ease},
506    WillHide{time:f64, height:f64, duration:f64, ease:Ease},
507    DidShow{time:f64, height:f64},
508    DidHide{time:f64},
509}
510
511#[derive(Clone, Default, Debug)]
512pub struct NextFrameEvent {
513    pub frame: u64,
514    pub time: f64,
515    pub set: HashSet<NextFrame>
516}
517
518#[derive(Clone, Debug)]
519pub struct TimerEvent {
520    pub time: Option<f64>,
521    pub timer_id: u64
522}
523
524#[derive(Clone, Debug, Default, Eq, Hash, Copy, PartialEq)]
525pub struct Trigger{
526    pub id:LiveId,
527    pub from:Area
528}
529
530#[derive(Clone, Debug, PartialEq)]
531pub struct TriggerHitEvent(pub Vec<Trigger>);
532
533#[derive(Clone, Debug)]
534pub struct WebSocketErrorEvent {
535    pub socket_id: LiveId,
536    pub error: String
537}
538
539#[derive(Clone, Debug)]
540pub struct WebSocketMessageEvent {
541    pub socket_id: LiveId,
542    pub data: Vec<u8>
543}
544
545#[derive(Clone, Debug, Default, Eq, PartialEq, Copy, Hash)]
546pub struct NextFrame(pub u64);
547
548impl NextFrame{
549    pub fn is_event(&self, event:&Event)->Option<NextFrameEvent>{
550        if let Event::NextFrame(ne) = event{
551            if ne.set.contains(&self){
552                return Some(ne.clone())
553            }
554        }
555        None
556    }
557}
558
559#[derive(Copy, Clone, Debug, Default)]
560pub struct Timer(pub u64);
561
562impl Timer {
563    pub fn is_event(&self, event:&Event)->Option<TimerEvent>{
564        if let Event::Timer(te) = event{
565            if te.timer_id == self.0{
566                return Some(te.clone())
567            }
568        }
569        None
570    }
571
572    pub fn is_timer(&self, event:&TimerEvent)->Option<TimerEvent>{
573        if event.timer_id == self.0{
574            return Some(event.clone())
575        }
576        None
577    }
578
579    pub fn empty() -> Timer {
580        Timer(0)
581    }
582
583    pub fn is_empty(&self) -> bool {
584        self.0 == 0
585    }
586}
587
588#[cfg(target_arch = "wasm32")]
589use crate::makepad_wasm_bridge::ToWasmMsg;
590
591#[cfg(target_arch = "wasm32")]
592use crate::makepad_wasm_bridge::ToWasmMsgRef;
593
594#[cfg(target_arch = "wasm32")]
595#[derive(Clone, Debug)]
596pub struct ToWasmMsgEvent{
597    pub id: LiveId,
598    pub msg: ToWasmMsg,
599    pub offset: usize
600}
601
602#[cfg(target_arch = "wasm32")]
603impl ToWasmMsgEvent{
604    pub fn as_ref(&self)->ToWasmMsgRef{self.msg.as_ref_at(self.offset)}
605}