makepad_platform/os/linux/x11/
linux_x11.rs1use {
2 std::cell::RefCell,
3 std::rc::Rc,
4 self::super::opengl_x11::{
5 OpenglWindow,
6 OpenglCx
7 },
8 self::super::super::{
9 egl_sys,
10 x11::xlib_event::*,
11 x11::xlib_app::*,
12 linux_media::CxLinuxMedia
13 },
14 crate::{
15 cx_api::{CxOsOp, CxOsApi},
16 makepad_math::dvec2,
17 makepad_live_id::*,
18 thread::Signal,
19 event::Event,
20 pass::CxPassParent,
21 cx::{Cx, OsType,LinuxWindowParams},
22 gpu_info::GpuPerformance,
23 os::cx_native::EventFlow,
24 }
25};
26
27impl Cx {
28 pub fn event_loop(cx:Rc<RefCell<Cx>>) {
29 cx.borrow_mut().self_ref = Some(cx.clone());
30 cx.borrow_mut().os_type = OsType::LinuxWindow(LinuxWindowParams{
31 custom_window_chrome: false
32 });
33 cx.borrow_mut().gpu_info.performance = GpuPerformance::Tier1;
34
35 let opengl_windows = Rc::new(RefCell::new(Vec::new()));
36 let is_stdin_loop = std::env::args().find(|v| v=="--stdin-loop").is_some();
37 init_xlib_app_global(Box::new({
38 let cx = cx.clone();
39 move | xlib_app,
40 events | {
41 if is_stdin_loop{
42 return EventFlow::Wait
43 }
44 let mut cx = cx.borrow_mut();
45 let mut opengl_windows = opengl_windows.borrow_mut();
46 cx.xlib_event_callback(xlib_app, events, &mut *opengl_windows)
47 }
48 }));
49
50 cx.borrow_mut().os.opengl_cx = Some(unsafe {
51 OpenglCx::from_egl_platform_display(
52 egl_sys::EGL_PLATFORM_X11_EXT,
53 get_xlib_app_global().display,
54 )
55 });
56
57 if is_stdin_loop {
58 return cx.borrow_mut().stdin_event_loop();
59 }
60
61 cx.borrow_mut().call_event_handler(&Event::Construct);
62 cx.borrow_mut().redraw_all();
63 get_xlib_app_global().start_timer(0,0.008,true);
64 get_xlib_app_global().event_loop();
65 }
66
67 fn xlib_event_callback(
68 &mut self,
69 xlib_app: &mut XlibApp,
70 event: XlibEvent,
71 opengl_windows: &mut Vec<OpenglWindow>
72 ) -> EventFlow {
73 if let EventFlow::Exit = self.handle_platform_ops(opengl_windows, xlib_app) {
74 return EventFlow::Exit
75 }
76
77 let mut paint_dirty = false;
78
79 match event {
81 XlibEvent::AppGotFocus => { for window in opengl_windows.iter_mut() {
83 if let Some(main_pass_id) = self.windows[window.window_id].main_pass_id {
84 self.repaint_pass(main_pass_id);
85 }
86 }
87 paint_dirty = true;
88 self.call_event_handler(&Event::AppGotFocus);
89 }
90 XlibEvent::AppLostFocus => {
91 self.call_event_handler(&Event::AppLostFocus);
92 }
93 XlibEvent::WindowGeomChange(re) => { if let Some(window) = opengl_windows.iter_mut().find( | w | w.window_id == re.window_id) {
95 window.window_geom = re.new_geom.clone();
96 self.windows[re.window_id].window_geom = re.new_geom.clone();
97 if re.old_geom.inner_size != re.new_geom.inner_size {
99 if let Some(main_pass_id) = self.windows[re.window_id].main_pass_id {
100 self.redraw_pass_and_child_passes(main_pass_id);
101 }
102 }
103 }
104 self.call_event_handler(&Event::WindowGeomChange(re));
106 }
107 XlibEvent::WindowClosed(wc) => {
108 let window_id = wc.window_id;
109 self.call_event_handler(&Event::WindowClosed(wc));
110 self.windows[window_id].is_created = false;
112 if let Some(index) = opengl_windows.iter().position( | w | w.window_id == window_id) {
113 opengl_windows.remove(index);
114 if opengl_windows.len() == 0 {
115 xlib_app.terminate_event_loop();
116 self.call_event_handler(&Event::Destruct);
117 return EventFlow::Exit
118 }
119 }
120 }
121 XlibEvent::Paint => {
122 if self.new_next_frames.len() != 0 {
123 self.call_next_frame_event(xlib_app.time_now());
124 }
125 if self.need_redrawing() {
126 self.call_draw_event();
127 self.os.opengl_cx.as_ref().unwrap().make_current();
128 self.opengl_compile_shaders();
129 }
130 self.handle_repaint(opengl_windows);
133 }
134 XlibEvent::MouseDown(e) => {
135 self.fingers.process_tap_count(
136 e.abs,
137 e.time
138 );
139 self.fingers.mouse_down(e.button);
140 self.call_event_handler(&Event::MouseDown(e.into()))
141 }
142 XlibEvent::MouseMove(e) => {
143 self.call_event_handler(&Event::MouseMove(e.into()));
144 self.fingers.cycle_hover_area(live_id!(mouse).into());
145 self.fingers.switch_captures();
146 }
147 XlibEvent::MouseUp(e) => {
148 let button = e.button;
149 self.call_event_handler(&Event::MouseUp(e.into()));
150 self.fingers.mouse_up(button);
151 self.fingers.cycle_hover_area(live_id!(mouse).into());
152 }
153 XlibEvent::Scroll(e) => {
154 self.call_event_handler(&Event::Scroll(e.into()))
155 }
156 XlibEvent::WindowDragQuery(e) => {
157 self.call_event_handler(&Event::WindowDragQuery(e))
158 }
159 XlibEvent::WindowCloseRequested(e) => {
160 self.call_event_handler(&Event::WindowCloseRequested(e))
161 }
162 XlibEvent::TextInput(e) => {
163 self.call_event_handler(&Event::TextInput(e))
164 }
165 XlibEvent::Drag(e) => {
166 self.call_event_handler(&Event::Drag(e))
167 }
168 XlibEvent::Drop(e) => {
169 self.call_event_handler(&Event::Drop(e))
170 }
171 XlibEvent::DragEnd => {
172 self.call_event_handler(&Event::DragEnd)
173 }
174 XlibEvent::KeyDown(e) => {
175 self.keyboard.process_key_down(e.clone());
176 self.call_event_handler(&Event::KeyDown(e))
177 }
178 XlibEvent::KeyUp(e) => {
179 self.keyboard.process_key_up(e.clone());
180 self.call_event_handler(&Event::KeyUp(e))
181 }
182 XlibEvent::TextCopy(e) => {
183 self.call_event_handler(&Event::TextCopy(e))
184 }
185 XlibEvent::TextCut(e) => {
186 self.call_event_handler(&Event::TextCut(e))
187 }
188 XlibEvent::Timer(e) => {
189 if e.timer_id == 0{
191 if Signal::check_and_clear_ui_signal(){
192 self.handle_media_signals();
193 self.call_event_handler(&Event::Signal);
194 }
195 }
196 else{
197 self.call_event_handler(&Event::Timer(e))
198 }
199 }
200 }
201
202 if self.any_passes_dirty() || self.need_redrawing() || self.new_next_frames.len() != 0 || paint_dirty {
203 EventFlow::Poll
204 } else {
205 EventFlow::Wait
206 }
207
208 }
209
210 pub(crate) fn handle_networking_events(&mut self) {
211 }
212
213 pub (crate) fn handle_repaint(&mut self, opengl_windows: &mut Vec<OpenglWindow>) {
214 self.os.opengl_cx.as_ref().unwrap().make_current();
215 let mut passes_todo = Vec::new();
216 self.compute_pass_repaint_order(&mut passes_todo);
217 self.repaint_id += 1;
218 for pass_id in &passes_todo {
219 self.passes[*pass_id].set_time(get_xlib_app_global().time_now() as f32);
220 match self.passes[*pass_id].parent.clone() {
221 CxPassParent::Window(window_id) => {
222 if let Some(window) = opengl_windows.iter_mut().find( | w | w.window_id == window_id) {
223 window.resize_buffers();
225 self.draw_pass_to_window(*pass_id, window);
226 }
227 }
228 CxPassParent::Pass(_) => {
229 self.draw_pass_to_magic_texture(*pass_id);
231 },
232 CxPassParent::None => {
233 self.draw_pass_to_magic_texture(*pass_id);
234 }
235 }
236 }
237 }
238
239 fn handle_platform_ops(&mut self, opengl_windows: &mut Vec<OpenglWindow>, xlib_app: &mut XlibApp) -> EventFlow {
240 let mut ret = EventFlow::Poll;
241 while let Some(op) = self.platform_ops.pop() {
242 match op {
243 CxOsOp::CreateWindow(window_id) => {
244 let window = &mut self.windows[window_id];
245 let opengl_window = OpenglWindow::new(
246 window_id,
247 self.os.opengl_cx.as_ref().unwrap(),
248 window.create_inner_size.unwrap_or(dvec2(800., 600.)),
249 window.create_position,
250 &window.create_title,
251 );
252 window.window_geom = opengl_window.window_geom.clone();
253 opengl_windows.push(opengl_window);
254 window.is_created = true;
255 },
256 CxOsOp::CloseWindow(window_id) => {
257 if let Some(index) = opengl_windows.iter().position( | w | w.window_id == window_id) {
258 self.windows[window_id].is_created = false;
259 opengl_windows[index].xlib_window.close_window();
260 opengl_windows.remove(index);
261 if opengl_windows.len() == 0 {
262 ret = EventFlow::Exit
263 }
264 }
265 },
266 CxOsOp::Quit=>{
267 ret = EventFlow::Exit
268 }
269 CxOsOp::MinimizeWindow(window_id) => {
270 if let Some(window) = opengl_windows.iter_mut().find( | w | w.window_id == window_id) {
271 window.xlib_window.minimize();
272 }
273 },
274 CxOsOp::MaximizeWindow(window_id) => {
275 if let Some(window) = opengl_windows.iter_mut().find( | w | w.window_id == window_id) {
276 window.xlib_window.maximize();
277 }
278 },
279 CxOsOp::RestoreWindow(window_id) => {
280 if let Some(window) = opengl_windows.iter_mut().find( | w | w.window_id == window_id) {
281 window.xlib_window.restore();
282 }
283 },
284 CxOsOp::ShowClipboardActions(_) =>{
285 }
286 CxOsOp::FullscreenWindow(_window_id) => {
287 todo!()
288 },
289 CxOsOp::NormalizeWindow(_window_id) => {
290 todo!()
291 }
292 CxOsOp::SetTopmost(_window_id, _is_topmost) => {
293 todo!()
294 }
295 CxOsOp::XrStartPresenting => {
296 },
298 CxOsOp::XrStopPresenting => {
299 },
301 CxOsOp::ShowTextIME(_area, _pos) => {
302 }
304 CxOsOp::HideTextIME => {
305 },
307 CxOsOp::SetCursor(cursor) => {
308 xlib_app.set_mouse_cursor(cursor);
309 },
310 CxOsOp::StartTimer {timer_id, interval, repeats} => {
311 xlib_app.start_timer(timer_id, interval, repeats);
312 },
313 CxOsOp::StopTimer(timer_id) => {
314 xlib_app.stop_timer(timer_id);
315 },
316 CxOsOp::StartDragging(_dragged_item) => {
317 },
318 CxOsOp::UpdateMacosMenu(_menu) => {
319 },
320 CxOsOp::HttpRequest{request_id:_, request:_} => {
321 todo!()
322 },
323 CxOsOp::WebSocketOpen{request_id:_, request:_}=>{
324 todo!()
325 }
326 CxOsOp::WebSocketSendBinary{request_id:_, data:_}=>{
327 todo!()
328 }
329 CxOsOp::WebSocketSendString{request_id:_, data:_}=>{
330 todo!()
331 },
332 CxOsOp::InitializeVideoDecoding(_, _, _) => todo!(),
333 CxOsOp::DecodeNextVideoChunk(_, _) => todo!(),
334 CxOsOp::FetchNextVideoFrames(_, _) => todo!(),
335 CxOsOp::CleanupVideoDecoding(_) => todo!(),
336 }
337 }
338 ret
339 }
340}
341
342impl CxOsApi for Cx {
343 fn init_cx_os(&mut self) {
344 self.live_expand();
345 self.live_scan_dependencies();
346 self.native_load_dependencies();
347 }
348
349 fn spawn_thread<F>(&mut self, f: F) where F: FnOnce() + Send + 'static {
350 std::thread::spawn(f);
351 }
352}
353
354#[derive(Default)]
355pub struct CxOs {
356 pub(crate) media: CxLinuxMedia,
357
358 pub(super) opengl_cx: Option<OpenglCx>,
360}
361