makepad_render/
cx_linux.rs1use 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) => { 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 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 self.call_event_handler(&mut event_handler, &mut event);
52 },
53 Event::WindowClosed(wc) => {
54 self.windows[wc.window_id].window_state = CxWindowState::Closed;
56 self.windows_free.push(wc.window_id);
57 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 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 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 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 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 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 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}