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