makepad_platform/os/linux/x11/
linux_x11_stdin.rs1use {
2 crate::{
3 cx::Cx, cx_api::CxOsOp, event::{Event, WindowGeom}, makepad_live_id::*, makepad_math::*, makepad_micro_serde::*, os::cx_stdin::{aux_chan, HostToStdin, PollTimer, PresentableDraw, StdinToHost, Swapchain}, pass::{CxPassColorTexture, CxPassParent, PassClearColor}, texture::{Texture, TextureFormat}, thread::SignalToUI, window::CxWindowPool, CxOsApi,
4 }, std::io::{self, prelude::*, BufReader}
5};
6
7#[derive(Default)]
8pub(crate) struct StdinWindow{
9 swapchain: Option<Swapchain<Texture>>,
10 present_index: usize
11}
12
13impl Cx {
14
15 pub (crate) fn stdin_handle_repaint(
16 &mut self,
17 windows: &mut Vec<StdinWindow>,
18 ) {
19 self.os.opengl_cx.as_ref().unwrap().make_current();
20 let mut passes_todo = Vec::new();
21 self.compute_pass_repaint_order(&mut passes_todo);
22 self.repaint_id += 1;
23
24 let time_now = self.os.stdin_timers.time_now();
25 for &pass_id in &passes_todo {
26 self.passes[pass_id].set_time(time_now as f32);
27 match self.passes[pass_id].parent.clone() {
28 CxPassParent::Xr => {}
29 CxPassParent::Window(window_id) => {
30 let window = &mut windows[window_id.id()];
32 if let Some(swapchain) = &window.swapchain {
33 let current_image = &swapchain.presentable_images[window.present_index];
34 window.present_index = (window.present_index + 1) % swapchain.presentable_images.len();
35
36 self.draw_pass_to_texture(pass_id, Some(¤t_image.image));
38
39 unsafe { (self.os.gl().glFinish)(); }
41
42 let dpi_factor = self.passes[pass_id].dpi_factor.unwrap();
43 let pass_rect = self.get_pass_rect(pass_id, dpi_factor).unwrap();
44 let presentable_draw = PresentableDraw {
45 window_id: window_id.id(),
46 target_id: current_image.id,
47 width: (pass_rect.size.x * dpi_factor) as u32,
48 height: (pass_rect.size.y * dpi_factor) as u32,
49 };
50
51 let _ = io::stdout().write_all(StdinToHost::DrawCompleteAndFlip(presentable_draw).to_json().as_bytes());
53 }
54 }
55 CxPassParent::Pass(_) => {
56 self.draw_pass_to_texture(pass_id, None);
58 },
59 CxPassParent::None => {
60 self.draw_pass_to_texture(pass_id, None);
61 }
62 }
63 }
64 }
65
66 pub fn stdin_event_loop(&mut self) {
67 let aux_chan_client_endpoint =
68 aux_chan::InheritableClientEndpoint::from_process_args_in_client()
69 .and_then(|chan| chan.into_uninheritable())
70 .expect("failed to acquire auxiliary channel");
71
72
73 let (json_msg_tx, json_msg_rx) = std::sync::mpsc::channel();
74 {
75 std::thread::spawn(move || {
76 let mut reader = BufReader::new(std::io::stdin().lock());
77 let mut line = String::new();
78 loop {
79 line.clear();
80 if let Ok(0) | Err(_) = reader.read_line(&mut line) {
81 break;
82 }
83 match HostToStdin::deserialize_json(&line) {
85 Ok(msg) => {
86 if json_msg_tx.send(msg).is_err() {
87 break;
88 }
89 }
90 Err(err) => {
91 crate::error!("Cant parse stdin-JSON {} {:?}", line, err)
93 }
94 }
95 }
96 println!("Terminating STDIN reader loop")
97 });
98 }
99
100 let _ = io::stdout().write_all(StdinToHost::ReadyToStart.to_json().as_bytes());
101
102 let mut stdin_windows:Vec<StdinWindow> = Vec::new();
103
104 self.call_event_handler(&Event::Startup);
105
106 while let Ok(msg) = json_msg_rx.recv(){
107 match msg {
108 HostToStdin::KeyDown(e) => {
109 self.call_event_handler(&Event::KeyDown(e));
110 }
111 HostToStdin::KeyUp(e) => {
112 self.call_event_handler(&Event::KeyUp(e));
113 }
114 HostToStdin::TextInput(e) => {
115 self.call_event_handler(&Event::TextInput(e));
116 }
117 HostToStdin::MouseDown(e) => {
118 self.fingers.process_tap_count(
119 dvec2(e.x,e.y),
120 e.time
121 );
122 let (window_id,pos) = self.windows.window_id_contains(dvec2(e.x, e.y));
123 let mouse_down_event = e.into_event(window_id, pos);
124 self.fingers.mouse_down(mouse_down_event.button, window_id);
125 self.call_event_handler(&Event::MouseDown(mouse_down_event));
126 }
127 HostToStdin::MouseMove(e) => {
128 let (window_id, pos) = if let Some((_, window_id)) = self.fingers.first_mouse_button{
129 (window_id, self.windows[window_id].window_geom.position)
130 }
131 else{
132 self.windows.window_id_contains(dvec2(e.x, e.y))
133 };
134 self.call_event_handler(&Event::MouseMove(e.into_event(window_id,pos)));
135 self.fingers.cycle_hover_area(live_id!(mouse).into());
136 self.fingers.switch_captures();
137 }
138 HostToStdin::MouseUp(e) => {
139 let (window_id, pos) = if let Some((_, window_id)) = self.fingers.first_mouse_button{
140 (window_id, self.windows[window_id].window_geom.position)
141 }
142 else{
143 self.windows.window_id_contains(dvec2(e.x, e.y))
144 };
145 let mouse_up_event = e.into_event(window_id, pos);
146 let button = mouse_up_event.button;
147 self.call_event_handler(&Event::MouseUp(mouse_up_event));
148 self.fingers.mouse_up(button);
149 self.fingers.cycle_hover_area(live_id!(mouse).into());
150 }
151 HostToStdin::Scroll(e) => {
152 let (window_id,pos) = self.windows.window_id_contains(dvec2(e.x, e.y));
153 self.call_event_handler(&Event::Scroll(e.into_event(window_id,pos)))
154 }
155 HostToStdin::WindowGeomChange { dpi_factor, left, top, width, height, window_id } => {
156 self.windows[CxWindowPool::from_usize(window_id)].window_geom = WindowGeom {
157 dpi_factor,
158 position: dvec2(left, top),
159 inner_size: dvec2(width, height),
160 ..Default::default()
161 };
162 self.redraw_all();
163 }
164 HostToStdin::Swapchain(new_swapchain) => {
165 let new_swapchain = new_swapchain.images_map(|pi| {
166 let mut new_texture = Texture::new(self);
167 match pi.recv_fds_from_aux_chan(&aux_chan_client_endpoint) {
168 Ok(pi) => {
169 let desc = TextureFormat::SharedBGRAu8{
171 id: pi.id,
172 width: new_swapchain.alloc_width as usize,
173 height: new_swapchain.alloc_height as usize,
174 initial: true,
175 };
176 new_texture = Texture::new_with_format(self, desc);
177 self.textures[new_texture.texture_id()]
178 .update_from_shared_dma_buf_image(
179 self.os.gl(),
180 self.os.opengl_cx.as_ref().unwrap(),
181 &pi.image,
182 );
183 }
184 Err(err) => {
185 crate::error!("failed to receive new swapchain on auxiliary channel: {err:?}");
186 }
187 }
188 new_texture
189 });
190 let window_id = new_swapchain.window_id;
191 let stdin_window = &mut stdin_windows[window_id];
192 stdin_window.swapchain = Some(new_swapchain);
193
194 stdin_window.present_index = 0;
196
197 let window = &mut self.windows[CxWindowPool::from_usize(window_id)];
199 let pass = &mut self.passes[window.main_pass_id.unwrap()];
200 if let Some(swapchain) = &stdin_window.swapchain {
201 pass.color_textures = vec![CxPassColorTexture {
202 clear_color: PassClearColor::ClearWith(vec4(1.0,1.0,0.0,1.0)),
203 texture: swapchain.presentable_images[stdin_window.present_index].image.clone(),
205 }];
206 }
207
208
209 self.redraw_all();
210 self.stdin_handle_platform_ops(&mut stdin_windows);
211 }
212
213 HostToStdin::Tick => {
214
215 if SignalToUI::check_and_clear_ui_signal(){
218 self.handle_media_signals();
219 self.call_event_handler(&Event::Signal);
220 }
221 if SignalToUI::check_and_clear_action_signal() {
222 self.handle_action_receiver();
223 }
224
225 for event in self.os.stdin_timers.get_dispatch() {
226 self.call_event_handler(&event);
227 }
228 if self.handle_live_edit(){
229 self.call_event_handler(&Event::LiveEdit);
230 self.redraw_all();
231 }
232 self.handle_networking_events();
233
234 self.stdin_handle_platform_ops(&mut stdin_windows);
236
237 if self.new_next_frames.len() != 0 {
240 self.call_next_frame_event(self.seconds_since_app_start());
241 }
242
243 if self.need_redrawing() {
244 self.call_draw_event();
245 self.opengl_compile_shaders();
246 }
247
248 self.stdin_handle_repaint(&mut stdin_windows);
249 }
250 }
251 }
252 }
253
254
255 fn stdin_handle_platform_ops(
256 &mut self,
257 stdin_windows: &mut Vec<StdinWindow>,
258 ) {
259 while let Some(op) = self.platform_ops.pop() {
260 match op {
261 CxOsOp::CreateWindow(window_id) => {
262 while window_id.id() >= stdin_windows.len(){
263 stdin_windows.push(StdinWindow::default());
264 }
265 let window = &mut self.windows[window_id];
267 window.is_created = true;
268 let _ = io::stdout().write_all(StdinToHost::CreateWindow{window_id:window_id.id(),kind_id:window.kind_id}.to_json().as_bytes());
269 },
270 CxOsOp::SetCursor(cursor) => {
271 let _ = io::stdout().write_all(StdinToHost::SetCursor(cursor).to_json().as_bytes());
272 },
273 CxOsOp::StartTimer {timer_id, interval, repeats} => {
274 self.os.stdin_timers.timers.insert(timer_id, PollTimer::new(interval, repeats));
275 },
276 CxOsOp::StopTimer(timer_id) => {
277 self.os.stdin_timers.timers.remove(&timer_id);
278 },
279 _ => ()
280 }
298 }
299 }
300
301}