makepad_platform/os/
cx_shared.rs

1use {
2    std::collections::{HashSet, HashMap},
3    crate::{
4        cx_api::CxOsApi,
5        cx::Cx,
6        pass::{
7            PassId,
8            CxPassParent
9        },
10        event::{
11            TimerEvent,
12            DrawEvent,
13            TriggerEvent,
14            Event,
15            KeyFocusEvent,
16            NextFrameEvent,
17        },
18        studio::{AppToStudio,EventSample},
19    }
20};
21
22impl Cx {
23    #[allow(dead_code)]
24    pub (crate) fn repaint_windows(&mut self) {
25        for pass_id in self.passes.id_iter() {
26            match self.passes[pass_id].parent {
27                CxPassParent::Window(_) => {
28                    self.passes[pass_id].paint_dirty = true;
29                },
30                _ => ()
31            }
32        }
33    }
34    
35    #[allow(unused)]
36    pub (crate) fn any_passes_dirty(&self) -> bool {
37        for pass_id in self.passes.id_iter() {
38            if self.passes[pass_id].paint_dirty {
39                return true
40            }
41        }
42        false
43    }
44    
45    pub (crate) fn compute_pass_repaint_order(&mut self, passes_todo: &mut Vec<PassId>) {
46        passes_todo.clear();
47        
48        // we need this because we don't mark the entire deptree of passes dirty every small paint
49        loop { // loop untill we don't propagate anymore
50            let mut altered = false;
51            for pass_id in self.passes.id_iter(){
52                if self.demo_time_repaint {
53                    if self.passes[pass_id].main_draw_list_id.is_some(){
54                        self.passes[pass_id].paint_dirty = true;
55                    }
56                }
57                if self.passes[pass_id].paint_dirty {
58                    let other = match self.passes[pass_id].parent {
59                        CxPassParent::Pass(parent_pass_id) => {
60                            Some(parent_pass_id)
61                        }
62                        _ => None
63                    };
64                    if let Some(other) = other {
65                        if !self.passes[other].paint_dirty {
66                            self.passes[other].paint_dirty = true;
67                            altered = true;
68                        }
69                    }
70                }
71            }
72            if !altered {
73                break
74            }
75        }
76        
77        for pass_id in self.passes.id_iter(){
78            if self.passes[pass_id].paint_dirty {
79                let mut inserted = false;
80                match self.passes[pass_id].parent {
81                    CxPassParent::Window(_) | CxPassParent::Xr=> {
82                    },
83                    CxPassParent::Pass(dep_of_pass_id) => {
84                        if pass_id == dep_of_pass_id {
85                            panic!()
86                        }
87                        for insert_before in 0..passes_todo.len() {
88                            if passes_todo[insert_before] == dep_of_pass_id {
89                                passes_todo.insert(insert_before, pass_id);
90                                inserted = true;
91                                break;
92                            }
93                        }
94                    },
95                    CxPassParent::None => { // we need to be first
96                        passes_todo.insert(0, pass_id);
97                        inserted = true;
98                    },
99                }
100                if !inserted {
101                    passes_todo.push(pass_id);
102                }
103            }
104        }
105        self.demo_time_repaint = false;
106    }
107    
108    pub (crate) fn need_redrawing(&self) -> bool {
109        self.new_draw_event.will_redraw() 
110    }
111    
112    
113    
114    
115    // event handler wrappers
116    
117    
118    pub (crate) fn inner_call_event_handler(&mut self, event: &Event) {
119        self.event_id += 1;
120        if Cx::has_studio_web_socket(){
121            let start = self.seconds_since_app_start();
122            let mut event_handler = self.event_handler.take().unwrap();
123            event_handler(self, event);
124            self.event_handler = Some(event_handler);
125            let end = self.seconds_since_app_start();
126            Cx::send_studio_message(AppToStudio::EventSample(EventSample{
127                event_u32: event.to_u32(),
128                start: start,
129                event_meta: if let Event::Timer(TimerEvent{timer_id,..}) = event{*timer_id}else{0},
130                end: end
131            }))
132        }
133        else{
134            let mut event_handler = self.event_handler.take().unwrap();
135            event_handler(self, event);
136            self.event_handler = Some(event_handler);
137        }
138
139        // Reset widget query invalidation after all views have processed it.
140        // We wait until event_id is at least 1 events past the invalidation event
141        // to ensure the cache clear has propagated through the widget hierarchy
142        // during the previous event cycle.
143        if let Some(event_id) = self.widget_query_invalidation_event {
144            if self.event_id > event_id + 1 {
145                self.widget_query_invalidation_event = None;
146            }
147        }
148    }
149    
150    fn inner_key_focus_change(&mut self) {
151        if let Some((prev, focus)) = self.keyboard.cycle_key_focus_changed(){
152            self.inner_call_event_handler(&Event::KeyFocus(KeyFocusEvent {
153                prev,
154                focus
155            }));
156        }
157    }
158    
159    pub fn handle_triggers(&mut self) {
160        // post op events like signals, triggers and key-focus
161        let mut counter = 0;
162        while self.triggers.len() != 0 {
163            counter += 1;
164            let mut triggers = HashMap::new();
165            std::mem::swap(&mut self.triggers, &mut triggers);
166            self.inner_call_event_handler(&Event::Trigger(TriggerEvent {
167                triggers: triggers,
168            }));
169            self.inner_key_focus_change();
170            if counter > 100 {
171                crate::error!("Trigger feedback loop detected");
172                break
173            }
174        }
175    }
176    
177    pub fn handle_actions(&mut self) {
178        // post op events like signals, triggers and key-focus
179        let mut counter = 0;
180        while self.new_actions.len() != 0 {
181            counter += 1;
182            let mut actions = Vec::new();
183            std::mem::swap(&mut self.new_actions, &mut actions);
184            self.inner_call_event_handler(&Event::Actions(actions));
185            self.inner_key_focus_change();
186            if counter > 100 {
187                crate::error!("Action feedback loop detected");
188                crate::error!("New actions {:#?}", self.new_actions);
189                break
190            }
191        }
192    }
193    
194    pub (crate) fn call_event_handler(&mut self, event: &Event) {
195        self.inner_call_event_handler(event);
196        self.inner_key_focus_change();
197        self.handle_triggers();
198        self.handle_actions();
199    }
200
201    // helpers
202    
203    /*
204    pub (crate) fn call_all_keys_up(&mut self) {
205        let keys_down = self.keyboard.all_keys_up();
206        for key_event in keys_down {
207            self.call_event_handler(&Event::KeyUp(key_event))
208        }
209    }*/ 
210    
211    pub (crate) fn call_draw_event(&mut self) {
212        let mut draw_event = DrawEvent::default();
213        std::mem::swap(&mut draw_event, &mut self.new_draw_event);
214        self.in_draw_event = true;
215
216        self.call_event_handler(&Event::Draw(draw_event));
217        self.in_draw_event = false;
218    }
219
220    pub (crate) fn call_next_frame_event(&mut self, time: f64) {
221        let mut set = HashSet::default();
222        std::mem::swap(&mut set, &mut self.new_next_frames);
223
224        self.performance_stats.process_frame_data(time);
225
226        self.call_event_handler(&Event::NextFrame(NextFrameEvent {set, time: time, frame: self.repaint_id}));
227    }
228}