makepad_platform/os/linux/x11/
linux_x11_stdin.rs1use {
2 std::{
3 io,
4 io::prelude::*,
5 io::BufReader,
6 },
7 crate::{
8 makepad_live_id::*,
9 makepad_math::*,
10 makepad_error_log::*,
11 makepad_micro_serde::*,
12 makepad_live_compiler::LiveFileChange,
13 event::Event,
14 window::CxWindowPool,
15 event::WindowGeom,
16 texture::{Texture, TextureDesc, TextureFormat},
17 live_traits::LiveNew,
18 thread::Signal,
19 os::cx_stdin::{aux_chan, HostToStdin, PresentableDraw, StdinToHost, Swapchain},
20 pass::{CxPassParent, PassClearColor, CxPassColorTexture},
21 cx_api::CxOsOp,
22 cx::Cx,
23 gl_sys,
24 }
25};
26
27impl Cx {
28
29 pub (crate) fn stdin_handle_repaint(
30 &mut self,
31 swapchain: Option<&Swapchain<Texture>>,
32 present_index: &mut usize,
33 ) {
34 self.os.opengl_cx.as_ref().unwrap().make_current();
35 let mut passes_todo = Vec::new();
36 self.compute_pass_repaint_order(&mut passes_todo);
37 self.repaint_id += 1;
38 for &pass_id in &passes_todo {
39 match self.passes[pass_id].parent.clone() {
40 CxPassParent::Window(_) => {
41 if let Some(swapchain) = swapchain {
43 let current_image = &swapchain.presentable_images[*present_index];
44 *present_index = (*present_index + 1) % swapchain.presentable_images.len();
45
46 self.draw_pass_to_texture(pass_id, current_image.image.texture_id());
48
49 unsafe { gl_sys::Finish(); }
51
52 let dpi_factor = self.passes[pass_id].dpi_factor.unwrap();
53 let pass_rect = self.get_pass_rect(pass_id, dpi_factor).unwrap();
54 let presentable_draw = PresentableDraw {
55 target_id: current_image.id,
56 width: (pass_rect.size.x * dpi_factor) as u32,
57 height: (pass_rect.size.y * dpi_factor) as u32,
58 };
59
60 let _ = io::stdout().write_all(StdinToHost::DrawCompleteAndFlip(presentable_draw).to_json().as_bytes());
62 }
63 }
64 CxPassParent::Pass(_) => {
65 self.draw_pass_to_magic_texture(pass_id);
67 },
68 CxPassParent::None => {
69 self.draw_pass_to_magic_texture(pass_id);
70 }
71 }
72 }
73 }
74
75 pub fn stdin_event_loop(&mut self) {
76 let aux_chan_client_endpoint =
77 aux_chan::InheritableClientEndpoint::from_process_args_in_client()
78 .and_then(|chan| chan.into_uninheritable())
79 .expect("failed to acquire auxiliary channel");
80
81
82 let (json_msg_tx, json_msg_rx) = std::sync::mpsc::channel();
83 {
84 std::thread::spawn(move || {
85 let mut reader = BufReader::new(std::io::stdin().lock());
86 let mut line = String::new();
87 loop {
88 line.clear();
89 if let Ok(0) | Err(_) = reader.read_line(&mut line) {
90 break;
91 }
92
93 match HostToStdin::deserialize_json(&line) {
95 Ok(msg) => {
96 if json_msg_tx.send(msg).is_err() {
97 break;
98 }
99 }
100 Err(err) => {
101 error!("Cant parse stdin-JSON {} {:?}", line, err)
103 }
104 }
105 }
106 });
107 }
108
109 let _ = io::stdout().write_all(StdinToHost::ReadyToStart.to_json().as_bytes());
110
111 let mut swapchain = None;
112 let mut present_index = 0;
113
114 self.call_event_handler(&Event::Construct);
115
116 while let Ok(msg) = json_msg_rx.recv(){
117 match msg {
118 HostToStdin::ReloadFile{file, contents}=>{
119 let _ = self.live_file_change_sender.send(vec![LiveFileChange{
121 file_name: file,
122 content: contents
123 }]);
124 }
125 HostToStdin::KeyDown(e) => {
126 self.call_event_handler(&Event::KeyDown(e));
127 }
128 HostToStdin::KeyUp(e) => {
129 self.call_event_handler(&Event::KeyUp(e));
130 }
131 HostToStdin::MouseDown(e) => {
132 self.fingers.process_tap_count(
133 dvec2(e.x,e.y),
134 e.time
135 );
136 self.fingers.mouse_down(e.button);
137
138 self.call_event_handler(&Event::MouseDown(e.into()));
139 }
140 HostToStdin::MouseMove(e) => {
141 self.call_event_handler(&Event::MouseMove(e.into()));
142 self.fingers.cycle_hover_area(live_id!(mouse).into());
143 self.fingers.switch_captures();
144 }
145 HostToStdin::MouseUp(e) => {
146 let button = e.button;
147 self.call_event_handler(&Event::MouseUp(e.into()));
148 self.fingers.mouse_up(button);
149 self.fingers.cycle_hover_area(live_id!(mouse).into());
150 }
151 HostToStdin::Scroll(e) => {
152 self.call_event_handler(&Event::Scroll(e.into()))
153 }
154 HostToStdin::WindowGeomChange { dpi_factor, inner_width, inner_height } => {
155 self.windows[CxWindowPool::id_zero()].window_geom = WindowGeom {
156 dpi_factor,
157 inner_size: dvec2(inner_width, inner_height),
158 ..Default::default()
159 };
160 self.redraw_all();
161 }
162 HostToStdin::Swapchain(new_swapchain) => {
163 let new_swapchain = new_swapchain.images_map(|pi| {
164 let new_texture = Texture::new(self);
165 match pi.recv_fds_from_aux_chan(&aux_chan_client_endpoint) {
166 Ok(pi) => {
167 let desc = TextureDesc {
169 format: TextureFormat::SharedBGRA(pi.id),
170 width: Some(new_swapchain.alloc_width as usize),
171 height: Some(new_swapchain.alloc_height as usize),
172 };
173 new_texture.set_desc(self, desc);
174 self.textures[new_texture.texture_id()]
175 .os.update_from_shared_dma_buf_image(
176 self.os.opengl_cx.as_ref().unwrap(),
177 &desc,
178 &pi.image,
179 );
180 }
181 Err(err) => {
182 error!("failed to receive new swapchain on auxiliary channel: {err:?}");
183 }
184 }
185 new_texture
186 });
187 let swapchain = swapchain.insert(new_swapchain);
188
189 present_index = 0;
191
192 self.redraw_all();
193 self.stdin_handle_platform_ops(Some(swapchain), present_index);
194 }
195
196 HostToStdin::Tick {frame: _, time, buffer_id: _} => if swapchain.is_some() {
197
198 if Signal::check_and_clear_ui_signal(){
201 self.handle_media_signals();
202 self.call_event_handler(&Event::Signal);
203 }
204 if self.handle_live_edit(){
205 self.call_event_handler(&Event::LiveEdit);
206 self.redraw_all();
207 }
208 self.handle_networking_events();
209
210 self.stdin_handle_platform_ops(swapchain.as_ref(), present_index);
212
213 if self.new_next_frames.len() != 0 {
216 self.call_next_frame_event(time);
217 }
218
219 if self.need_redrawing() {
220 self.call_draw_event();
221 self.opengl_compile_shaders();
222 }
223
224 self.stdin_handle_repaint(swapchain.as_ref(), &mut present_index);
225 }
226 }
227 }
228 }
229
230
231 fn stdin_handle_platform_ops(
232 &mut self,
233 swapchain: Option<&Swapchain<Texture>>,
234 present_index: usize,
235 ) {
236 while let Some(op) = self.platform_ops.pop() {
237 match op {
238 CxOsOp::CreateWindow(window_id) => {
239 if window_id != CxWindowPool::id_zero() {
240 panic!("ONLY ONE WINDOW SUPPORTED");
241 }
242 let window = &mut self.windows[CxWindowPool::id_zero()];
243 window.is_created = true;
244 let pass = &mut self.passes[window.main_pass_id.unwrap()];
246 if let Some(swapchain) = swapchain {
247 pass.color_textures = vec![CxPassColorTexture {
248 clear_color: PassClearColor::ClearWith(vec4(1.0,1.0,0.0,1.0)),
249 texture_id: swapchain.presentable_images[present_index].image.texture_id(),
251 }];
252 }
253 },
254 CxOsOp::SetCursor(cursor) => {
255 let _ = io::stdout().write_all(StdinToHost::SetCursor(cursor).to_json().as_bytes());
256 },
257 _ => ()
258 }
276 }
277 }
278
279}