makepad_platform/os/windows/
windows_stdin.rs

1use {
2    std::{
3        io,
4        io::prelude::*,
5        io::BufReader,
6    },
7    crate::{
8        makepad_live_id::*,
9        makepad_math::*,
10        makepad_micro_serde::*,
11        event::Event,
12        window::CxWindowPool,
13        event::WindowGeom,
14        CxOsApi,
15        texture::{Texture,  TextureFormat},
16        thread::SignalToUI,
17        os::{
18            win32_app::{Win32Time},
19            d3d11::D3d11Cx,
20            cx_stdin::{HostToStdin, PresentableDraw, StdinToHost, Swapchain},
21        },
22        pass::{CxPassParent},
23        cx_api::CxOsOp,
24        cx::Cx,
25        windows::Win32::Foundation::HANDLE,
26    }
27};
28
29#[derive(Default)]
30pub(crate) struct StdinWindow{
31    swapchain: Option<Swapchain<Texture>>,
32    present_index: usize,
33    new_frame_being_rendered: Option<PresentableDraw>
34}
35
36
37impl Cx {
38    
39    pub (crate) fn stdin_handle_repaint(
40        &mut self,
41        d3d11_cx: &mut D3d11Cx,
42        windows: &mut Vec<StdinWindow>,
43        time: &Win32Time,
44    ) {
45        let mut passes_todo = Vec::new();
46        self.compute_pass_repaint_order(&mut passes_todo);
47        self.repaint_id += 1;
48        let time_now = time.time_now();
49        for &pass_id in &passes_todo {
50            self.passes[pass_id].set_time(time_now as f32);
51            match self.passes[pass_id].parent.clone() {
52                CxPassParent::Xr => {}
53                CxPassParent::Window(window_id) => {
54                    // only render to swapchain if swapchain exists
55                    let window = &mut windows[window_id.id()];
56                    if let Some(swapchain) = &window.swapchain {
57                        
58                        // and if GPU is not already rendering something else
59                        if window.new_frame_being_rendered.is_none() {
60                            let current_image = &swapchain.presentable_images[window.present_index];
61                            
62                            window.present_index = (window.present_index + 1) % swapchain.presentable_images.len();
63                            
64                            // render to swapchain
65                            self.draw_pass_to_texture(pass_id, d3d11_cx, Some(current_image.image.texture_id()));
66
67                            let dpi_factor = self.passes[pass_id].dpi_factor.unwrap();
68                            let pass_rect = self.get_pass_rect(pass_id, dpi_factor).unwrap();
69                            let future_presentable_draw = PresentableDraw {
70                                window_id: window_id.id(),
71                                target_id: current_image.id,
72                                width: (pass_rect.size.x * dpi_factor) as u32,
73                                height: (pass_rect.size.y * dpi_factor) as u32,
74                            };
75                            
76                            // start GPU event query
77                            d3d11_cx.start_querying();
78                            
79                            // and inform event_loop to go poll GPU readiness
80                            window.new_frame_being_rendered = Some(future_presentable_draw);
81                        }
82                    }
83                }
84                CxPassParent::Pass(_) => {
85                    //let dpi_factor = self.get_delegated_dpi_factor(parent_pass_id);
86                    self.draw_pass_to_texture(pass_id, d3d11_cx, None);
87                },
88                CxPassParent::None => {
89                    self.draw_pass_to_texture(pass_id, d3d11_cx, None);
90                }
91            }
92        }
93    }
94    
95    pub fn stdin_event_loop(&mut self, d3d11_cx: &mut D3d11Cx) {
96
97        let (json_msg_tx, json_msg_rx) = std::sync::mpsc::channel();
98        {
99            std::thread::spawn(move || {
100                let mut reader = BufReader::new(std::io::stdin().lock());
101                let mut line = String::new();
102                loop {
103                    line.clear();
104                    if let Ok(0) | Err(_) = reader.read_line(&mut line) {
105                        break;
106                    }
107                    
108                    // alright lets put the line in a json parser
109                    match HostToStdin::deserialize_json(&line) {
110                        Ok(msg) => {
111                            if json_msg_tx.send(msg).is_err() {
112                                break;
113                            }
114                        }
115                        Err(err) => {
116                            // we should output a log string
117                            crate::error!("Cant parse stdin-JSON {} {:?}", line, err)
118                        }
119                    }
120                }
121            });
122        }
123        
124        let _ = io::stdout().write_all(StdinToHost::ReadyToStart.to_json().as_bytes());
125        
126        let mut stdin_windows:Vec<StdinWindow> = Vec::new();
127        let time = Win32Time::new();
128         
129        self.call_event_handler(&Event::Startup);
130
131        //let mut previous_tick_time_s: Option<f64> = None;
132        //let mut previous_elapsed_s = 0f64;
133        //let mut allow_rendering = true;
134        
135        while let Ok(msg) = json_msg_rx.recv() {
136
137            match msg {
138                HostToStdin::KeyDown(e) => {
139                    self.call_event_handler(&Event::KeyDown(e));
140                }
141                HostToStdin::KeyUp(e) => {
142                    self.call_event_handler(&Event::KeyUp(e));
143                }
144                HostToStdin::TextInput(e) => {
145                    self.call_event_handler(&Event::TextInput(e));
146                }
147                HostToStdin::MouseDown(e) => {
148                    self.fingers.process_tap_count(
149                        dvec2(e.x, e.y),
150                        e.time
151                    );
152                    let (window_id, pos) = self.windows.window_id_contains(dvec2(e.x, e.y));
153                    let mouse_down_event = e.into_event(window_id, pos);
154                    self.fingers.mouse_down(mouse_down_event.button, window_id);
155                    self.call_event_handler(&Event::MouseDown(mouse_down_event));
156                }
157                HostToStdin::MouseMove(e) => {
158                    let (window_id, pos) = if let Some((_, window_id)) = self.fingers.first_mouse_button{
159                        (window_id, self.windows[window_id].window_geom.position)
160                    }
161                    else{
162                        self.windows.window_id_contains(dvec2(e.x, e.y))
163                    };
164                    self.call_event_handler(&Event::MouseMove(e.into_event(window_id, pos)));
165                    self.fingers.cycle_hover_area(live_id!(mouse).into());
166                    self.fingers.switch_captures();
167                }
168                HostToStdin::MouseUp(e) => {
169                    let (window_id, pos) = if let Some((_, window_id)) = self.fingers.first_mouse_button{
170                        (window_id, self.windows[window_id].window_geom.position)
171                    }
172                    else{
173                        self.windows.window_id_contains(dvec2(e.x, e.y))
174                    };
175                    let mouse_up_event = e.into_event(window_id, pos);
176                    let button = mouse_up_event.button;
177                    self.call_event_handler(&Event::MouseUp(mouse_up_event));
178                    self.fingers.mouse_up(button);
179                    self.fingers.cycle_hover_area(live_id!(mouse).into());
180                }
181                HostToStdin::Scroll(e) => {
182                    let  (window_id,pos) = self.windows.window_id_contains(dvec2(e.x, e.y));
183                    self.call_event_handler(&Event::Scroll(e.into_event(window_id, pos)));
184                }
185                HostToStdin::WindowGeomChange { dpi_factor, left, top, width, height, window_id } => {
186                    self.windows[CxWindowPool::from_usize(window_id)].window_geom = WindowGeom {
187                        dpi_factor,
188                        position: dvec2(left, top),
189                        inner_size: dvec2(width, height),
190                        ..Default::default()
191                    };
192                    self.redraw_all();
193                }
194                HostToStdin::Swapchain(new_swapchain) => {
195                    let new_swapchain = new_swapchain.images_map(|pi| {
196                        let handle = HANDLE(pi.image as isize);
197                        
198                        let format = TextureFormat::SharedBGRAu8 {
199                            id: pi.id,
200                            width: new_swapchain.alloc_width as usize,
201                            height: new_swapchain.alloc_height as usize,
202                            initial: true,
203                        };
204                        let texture = Texture::new_with_format(self, format);
205                        self.textures[texture.texture_id()].update_from_shared_handle(d3d11_cx, handle);
206                        texture
207                    });
208                    let window_id = new_swapchain.window_id;
209                    let stdin_window = &mut stdin_windows[window_id];
210                    stdin_window.swapchain = Some(new_swapchain);
211                    stdin_window.present_index = 0;
212                    
213                    self.redraw_all();
214                    self.stdin_handle_platform_ops(&mut stdin_windows);
215                }
216                HostToStdin::Tick =>  {
217                    
218                    // probe current time
219                    //let start_time = ::std::time::SystemTime::now();
220
221                    // poll the service for updates
222                    // check signals
223                    if SignalToUI::check_and_clear_ui_signal() {
224                        self.handle_media_signals();
225                        self.call_event_handler(&Event::Signal);
226                    }
227                    if SignalToUI::check_and_clear_action_signal() {
228                        self.handle_action_receiver();
229                    }
230                                        
231                    if self.handle_live_edit() {
232                        self.call_event_handler(&Event::LiveEdit);
233                        self.redraw_all();
234                    }
235                    self.handle_networking_events();
236                    // we should poll our runloop
237                    self.stdin_handle_platform_ops(&mut stdin_windows);
238
239                    // alright a tick.
240                    // we should now run all the stuff.
241                    if self.new_next_frames.len() != 0 {
242                        self.call_next_frame_event(self.seconds_since_app_start());
243                    }
244
245                    if self.need_redrawing() {
246                        self.call_draw_event();
247                        self.hlsl_compile_shaders(d3d11_cx);
248                    }
249
250                    // repaint
251                    self.stdin_handle_repaint(d3d11_cx, &mut stdin_windows, &time);
252
253                    // only allow rendering if it didn't take too much time last time
254                    //if allow_rendering {
255
256                        // check if GPU is ready to flip frames
257                        for window in &mut stdin_windows{
258                            if let Some(presentable_draw) = window.new_frame_being_rendered {
259                                while !d3d11_cx.is_gpu_done() {
260                                    std::thread::sleep(std::time::Duration::from_millis(3));
261                                }
262                                let _ = io::stdout().write_all(StdinToHost::DrawCompleteAndFlip(presentable_draw).to_json().as_bytes());
263                                window.new_frame_being_rendered = None;
264                            }
265                        }
266                        //}
267
268                    // probe how long this took
269                    /*
270                    let elapsed_s = (start_time.elapsed().unwrap().as_nanos() as f64) / 1000000000.0;
271
272                    if let Some(previous_tick_time_s) = previous_tick_time_s {
273
274                        // calculate time difference as dictated by the ticks
275                        let previous_dtick_s = time - previous_tick_time_s;
276
277                        // if this time difference is smaller than the elapsed time, disallow rendering
278                        allow_rendering = previous_dtick_s > previous_elapsed_s;
279                    }
280
281                    // store current tick time and elapsed time
282                    previous_tick_time_s = Some(time);
283                    previous_elapsed_s = elapsed_s;*/
284                }
285            }
286        }
287    }
288    
289    fn stdin_handle_platform_ops(
290        &mut self,
291        stdin_windows:&mut Vec<StdinWindow>,
292    ) {
293        while let Some(op) = self.platform_ops.pop() {
294            match op {
295                CxOsOp::CreateWindow(window_id) => {
296                    while window_id.id() >= stdin_windows.len(){
297                        stdin_windows.push(StdinWindow::default());
298                    }
299                    //let stdin_window = &mut stdin_windows[window_id.id()];
300                    let window = &mut self.windows[window_id];
301                    window.is_created = true;
302                    let _ = io::stdout().write_all(StdinToHost::CreateWindow{window_id:window_id.id(),kind_id:window.kind_id}.to_json().as_bytes());
303                     
304                    // lets set up our render pass target
305                   /* let pass = &mut self.passes[window.main_pass_id.unwrap()];
306                    if let Some(swapchain) = swapchain {
307                        pass.color_textures = vec![CxPassColorTexture {
308                            clear_color: PassClearColor::ClearWith(vec4(1.0, 1.0, 0.0, 1.0)),
309                            //clear_color: PassClearColor::ClearWith(pass.clear_color),
310                            texture: swapchain.presentable_images[present_index].image.clone(),
311                        }];
312                    }*/
313                },
314                CxOsOp::SetCursor(cursor) => {
315                    let _ = io::stdout().write_all(StdinToHost::SetCursor(cursor).to_json().as_bytes());
316                },
317                _ => ()
318                /*
319                CxOsOp::CloseWindow(_window_id) => {},
320                CxOsOp::MinimizeWindow(_window_id) => {},
321                CxOsOp::MaximizeWindow(_window_id) => {},
322                CxOsOp::RestoreWindow(_window_id) => {},
323                CxOsOp::FullscreenWindow(_window_id) => {},
324                CxOsOp::NormalizeWindow(_window_id) => {}
325                CxOsOp::SetTopmost(_window_id, _is_topmost) => {}
326                CxOsOp::XrStartPresenting(_) => {},
327                CxOsOp::XrStopPresenting(_) => {},
328                CxOsOp::ShowTextIME(_area, _pos) => {},
329                CxOsOp::HideTextIME => {},
330                CxOsOp::SetCursor(_cursor) => {},
331                CxOsOp::StartTimer {timer_id, interval, repeats} => {},
332                CxOsOp::StopTimer(timer_id) => {},
333                CxOsOp::StartDragging(dragged_item) => {}
334                CxOsOp::UpdateMenu(menu) => {}*/
335            }
336        }
337    }
338    
339}