makepad_render/
cx_linux.rs

1use crate::cx_xlib::*;
2use crate::cx::*;
3 
4impl Cx{
5    pub fn event_loop<F>(&mut self, mut event_handler: F)
6    where F: FnMut(&mut Cx, &mut Event),
7    {
8        self.platform_type = PlatformType::Linux;
9        
10        let mut xlib_app = XlibApp::new();
11        
12        xlib_app.init();
13        
14        let opengl_cx = OpenglCx::new(xlib_app.display);
15        
16        let mut opengl_windows: Vec<OpenglWindow> = Vec::new();
17        
18        self.opengl_compile_all_shaders(&opengl_cx);
19        
20        self.load_theme_fonts();
21        
22        self.call_event_handler(&mut event_handler, &mut Event::Construct);
23        
24        self.redraw_child_area(Area::All); 
25        
26        let mut passes_todo = Vec::new();
27        
28        xlib_app.event_loop( | xlib_app, events | {
29            let mut paint_dirty = false;
30            for mut event in events {
31                
32                self.process_desktop_pre_event(&mut event, &mut event_handler);
33                
34                match &event {
35                    Event::WindowSetHoverCursor(mc) => {
36                        self.set_hover_mouse_cursor(mc.clone());
37                    },
38                    Event::WindowGeomChange(re) => { // do this here because mac
39                        for opengl_window in &mut opengl_windows {if opengl_window.window_id == re.window_id {
40                            opengl_window.window_geom = re.new_geom.clone();
41                            self.windows[re.window_id].window_geom = re.new_geom.clone();
42                            // redraw just this windows root draw list
43                            if re.old_geom.inner_size != re.new_geom.inner_size{
44                                if let Some(main_pass_id) = self.windows[re.window_id].main_pass_id {
45                                    self.redraw_pass_and_sub_passes(main_pass_id);
46                                }
47                            }
48                            break;
49                        }}
50                        // ok lets not redraw all, just this window
51                        self.call_event_handler(&mut event_handler, &mut event);
52                    },
53                    Event::WindowClosed(wc) => {
54                        // lets remove the window from the set
55                        self.windows[wc.window_id].window_state = CxWindowState::Closed;
56                        self.windows_free.push(wc.window_id);
57                        // remove the d3d11/win32 window
58                        
59                        for index in 0..opengl_windows.len() {
60                            if opengl_windows[index].window_id == wc.window_id {
61                                opengl_windows.remove(index);
62                                if opengl_windows.len() == 0 {
63                                    xlib_app.terminate_event_loop();
64                                }
65                                for opengl_window in &mut opengl_windows {
66                                    opengl_window.xlib_window.update_ptrs();
67                                }
68                            }
69                        }
70                        self.call_event_handler(&mut event_handler, &mut event);
71                    },
72                    Event::Paint => {
73                        let _vsync = self.process_desktop_paint_callbacks(xlib_app.time_now(), &mut event_handler);
74                        
75                        // construct or destruct windows
76                        for (index, window) in self.windows.iter_mut().enumerate() {
77                            
78                            window.window_state = match &window.window_state {
79                                CxWindowState::Create {inner_size, position, title} => {
80                                    // lets create a platformwindow
81                                    let opengl_window = OpenglWindow::new(index, &opengl_cx, xlib_app, *inner_size, *position, &title);
82                                    window.window_geom = opengl_window.window_geom.clone();
83                                    opengl_windows.push(opengl_window);
84                                    for opengl_window in &mut opengl_windows {
85                                        opengl_window.xlib_window.update_ptrs();
86                                    }
87                                    
88                                    CxWindowState::Created
89                                },
90                                CxWindowState::Close => {
91                                    for opengl_window in &mut opengl_windows {if opengl_window.window_id == index {
92                                        opengl_window.xlib_window.close_window();
93                                        break;
94                                    }}
95                                    CxWindowState::Closed
96                                },
97                                CxWindowState::Created => CxWindowState::Created,
98                                CxWindowState::Closed => CxWindowState::Closed
99                            };
100                            
101                            window.window_command = match &window.window_command {
102                                CxWindowCmd::Restore => {
103                                    for opengl_window in &mut opengl_windows {if opengl_window.window_id == index {
104                                        opengl_window.xlib_window.restore();
105                                    }}
106                                    CxWindowCmd::None
107                                },
108                                CxWindowCmd::Maximize => {
109                                    for opengl_window in &mut opengl_windows {if opengl_window.window_id == index {
110                                        opengl_window.xlib_window.maximize();
111                                    }}
112                                    CxWindowCmd::None
113                                },
114                                CxWindowCmd::Minimize => {
115                                    for opengl_window in &mut opengl_windows {if opengl_window.window_id == index {
116                                        opengl_window.xlib_window.minimize();
117                                    }}
118                                    CxWindowCmd::None
119                                },
120                                _ => CxWindowCmd::None,
121                            };
122                            
123                            if let Some(topmost) = window.window_topmost {
124                                for opengl_window in &mut opengl_windows {if opengl_window.window_id == index {
125                                    opengl_window.xlib_window.set_topmost(topmost);
126                                }}
127                            }
128                        }
129                        // set a cursor
130                        if !self.down_mouse_cursor.is_none() {
131                            xlib_app.set_mouse_cursor(self.down_mouse_cursor.as_ref().unwrap().clone())
132                        }
133                        else if !self.hover_mouse_cursor.is_none() {
134                            xlib_app.set_mouse_cursor(self.hover_mouse_cursor.as_ref().unwrap().clone())
135                        }
136                        else {
137                            xlib_app.set_mouse_cursor(MouseCursor::Default)
138                        }
139                        
140                        if let Some(set_ime_position) = self.platform.set_ime_position {
141                            self.platform.set_ime_position = None;
142                            for opengl_window in &mut opengl_windows {
143                                opengl_window.xlib_window.set_ime_spot(set_ime_position);
144                            }
145                        }
146                        
147                        while self.platform.start_timer.len() > 0 {
148                            let (timer_id, interval, repeats) = self.platform.start_timer.pop().unwrap();
149                            xlib_app.start_timer(timer_id, interval, repeats);
150                        }
151                        
152                        while self.platform.stop_timer.len() > 0 {
153                            let timer_id = self.platform.stop_timer.pop().unwrap();
154                            xlib_app.stop_timer(timer_id);
155                        }
156                        
157                        // build a list of renderpasses to repaint
158                        let mut windows_need_repaint = 0;
159                        self.compute_passes_to_repaint(&mut passes_todo, &mut windows_need_repaint);
160                        
161                        if passes_todo.len() > 0 {
162                            for pass_id in &passes_todo {
163                                match self.passes[*pass_id].dep_of.clone() {
164                                    CxPassDepOf::Window(window_id) => {
165                                        // find the accompanying render window
166                                        // its a render window
167                                        windows_need_repaint -= 1;
168                                        for opengl_window in &mut opengl_windows {if opengl_window.window_id == window_id {
169                                            if opengl_window.xlib_window.window.is_none(){
170                                                break;
171                                            }
172                                            let dpi_factor = opengl_window.window_geom.dpi_factor;
173                                            
174                                            self.passes[*pass_id].set_dpi_factor(dpi_factor);
175                                            
176                                            opengl_window.resize_framebuffer(&opengl_cx);
177                                            
178                                            self.passes[*pass_id].paint_dirty = false;
179                                            
180                                            if self.draw_pass_to_window(
181                                                *pass_id,
182                                                dpi_factor,
183                                                opengl_window,
184                                                &opengl_cx,
185                                                false
186                                            ){
187                                                // paint it again a few times, apparently this is necessary
188                                                self.passes[*pass_id].paint_dirty = true;
189                                                paint_dirty = true;
190                                            }
191                                            if opengl_window.first_draw{
192                                                opengl_window.first_draw = false;
193                                                if dpi_factor != self.default_dpi_factor{
194                                                    self.redraw_pass_and_sub_passes(*pass_id);
195                                                }
196
197                                            }
198                                        }}
199                                    }
200                                    CxPassDepOf::Pass(parent_pass_id) => {
201                                        let dpi_factor = self.get_delegated_dpi_factor(parent_pass_id);
202                                        self.draw_pass_to_texture(
203                                            *pass_id,
204                                            dpi_factor,
205                                            &opengl_cx,
206                                        );
207                                    },
208                                    CxPassDepOf::None => {
209                                        self.draw_pass_to_texture(
210                                            *pass_id,
211                                            1.0,
212                                            &opengl_cx,
213                                        );
214                                    }
215                                }
216                            }
217                        }
218                    },
219                    Event::Signal{..}=>{
220                        self.call_event_handler(&mut event_handler, &mut event);
221                        self.call_signals(&mut event_handler);
222                    },
223                    Event::None => {
224                    },
225                    _ => {
226                        self.call_event_handler(&mut event_handler, &mut event);
227                    }
228                }
229                if self.process_desktop_post_event(event) {
230                    xlib_app.terminate_event_loop();
231                }
232            }
233            if !paint_dirty && self.playing_anim_areas.len() == 0 && self.redraw_parent_areas.len() == 0 && self.redraw_child_areas.len() == 0 && self.frame_callbacks.len() == 0 {
234                true
235            } else {
236                false
237            }
238        })
239    }
240    
241    
242    pub fn show_text_ime(&mut self, x: f32, y: f32) {
243        self.platform.set_ime_position = Some(Vec2 {x: x, y: y});
244    }
245    
246    pub fn hide_text_ime(&mut self) {
247    }
248    
249    pub fn set_window_outer_size(&mut self, size: Vec2) {
250        self.platform.set_window_outer_size = Some(size);
251    }
252    
253    pub fn set_window_position(&mut self, pos: Vec2) {
254        self.platform.set_window_position = Some(pos);
255    }
256    
257    pub fn start_timer(&mut self, interval: f64, repeats: bool) -> Timer {
258        self.timer_id += 1;
259        self.platform.start_timer.push((self.timer_id, interval, repeats));
260        Timer {timer_id: self.timer_id}
261    }
262    
263    pub fn stop_timer(&mut self, timer: &mut Timer) {
264        if timer.timer_id != 0 {
265            self.platform.stop_timer.push(timer.timer_id);
266            timer.timer_id = 0;
267        }
268    }
269    
270    pub fn post_signal(signal: Signal, status: StatusId) {
271        XlibApp::post_signal(signal, status);
272    }
273
274    pub fn update_menu(&mut self, _menu:&Menu){
275    }
276}
277
278#[derive(Clone, Default)]
279pub struct CxPlatform {
280    pub set_window_position: Option<Vec2>,
281    pub set_window_outer_size: Option<Vec2>,
282    pub set_ime_position: Option<Vec2>,
283    pub start_timer: Vec<(u64, f64, bool)>,
284    pub stop_timer: Vec<u64>,
285    pub text_clipboard_response: Option<String>,
286    pub desktop: CxDesktop,
287}