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_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::{
20            d3d11::D3d11Cx,
21            cx_stdin::{HostToStdin, PresentableDraw, StdinToHost, Swapchain},
22        },
23        pass::{CxPassParent, PassClearColor, CxPassColorTexture},
24        cx_api::CxOsOp,
25        cx::Cx,
26        windows::Win32::Foundation::HANDLE,
27    }
28};
29
30impl Cx {
31    
32    pub (crate) fn stdin_handle_repaint(
33        &mut self,
34        d3d11_cx: &mut D3d11Cx,
35        swapchain: Option<&Swapchain<Texture >>,
36        present_index: &mut usize,
37    ) {
38        let mut passes_todo = Vec::new();
39        self.compute_pass_repaint_order(&mut passes_todo);
40        self.repaint_id += 1;
41        for &pass_id in &passes_todo {
42            match self.passes[pass_id].parent.clone() {
43                CxPassParent::Window(_) => {
44                    // only render to swapchain if swapchain exists
45                    if let Some(swapchain) = swapchain {
46                        
47                        // and if GPU is not already rendering something else
48                        if self.os.new_frame_being_rendered.is_none() {
49                            let current_image = &swapchain.presentable_images[*present_index];
50                            *present_index = (*present_index + 1) % swapchain.presentable_images.len();
51                            
52                            // render to swapchain
53                            self.draw_pass_to_texture(pass_id, d3d11_cx, current_image.image.texture_id());
54
55                            let dpi_factor = self.passes[pass_id].dpi_factor.unwrap();
56                            let pass_rect = self.get_pass_rect(pass_id, dpi_factor).unwrap();
57                            let future_presentable_draw = PresentableDraw {
58                                target_id: current_image.id,
59                                width: (pass_rect.size.x * dpi_factor) as u32,
60                                height: (pass_rect.size.y * dpi_factor) as u32,
61                            };
62                            
63                            // start GPU event query
64                            d3d11_cx.start_querying();
65                            
66                            // and inform event_loop to go poll GPU readiness
67                            self.os.new_frame_being_rendered = Some(future_presentable_draw);
68                        }
69                    }
70                }
71                CxPassParent::Pass(_) => {
72                    //let dpi_factor = self.get_delegated_dpi_factor(parent_pass_id);
73                    self.draw_pass_to_magic_texture(pass_id, d3d11_cx);
74                },
75                CxPassParent::None => {
76                    self.draw_pass_to_magic_texture(pass_id, d3d11_cx);
77                }
78            }
79        }
80    }
81    
82    pub fn stdin_event_loop(&mut self, d3d11_cx: &mut D3d11Cx) {
83
84        let (json_msg_tx, json_msg_rx) = std::sync::mpsc::channel();
85        {
86            std::thread::spawn(move || {
87                let mut reader = BufReader::new(std::io::stdin().lock());
88                let mut line = String::new();
89                loop {
90                    line.clear();
91                    if let Ok(0) | Err(_) = reader.read_line(&mut line) {
92                        break;
93                    }
94                    
95                    // alright lets put the line in a json parser
96                    match HostToStdin::deserialize_json(&line) {
97                        Ok(msg) => {
98                            if json_msg_tx.send(msg).is_err() {
99                                break;
100                            }
101                        }
102                        Err(err) => {
103                            // we should output a log string
104                            error!("Cant parse stdin-JSON {} {:?}", line, err)
105                        }
106                    }
107                }
108            });
109        }
110        
111        let _ = io::stdout().write_all(StdinToHost::ReadyToStart.to_json().as_bytes());
112        
113        let mut swapchain = None;
114        let mut present_index = 0;
115        
116        self.call_event_handler(&Event::Construct);
117        
118        while let Ok(msg) = json_msg_rx.recv() {
119            match msg {
120                HostToStdin::ReloadFile {file, contents} => {
121                    // alright lets reload this file in our DSL system
122                    let _ = self.live_file_change_sender.send(vec![LiveFileChange {
123                        file_name: file,
124                        content: contents
125                    }]);
126                }
127                HostToStdin::KeyDown(e) => {
128                    self.call_event_handler(&Event::KeyDown(e));
129                }
130                HostToStdin::KeyUp(e) => {
131                    self.call_event_handler(&Event::KeyUp(e));
132                }
133                HostToStdin::MouseDown(e) => {
134                    self.fingers.process_tap_count(
135                        dvec2(e.x, e.y),
136                        e.time
137                    );
138                    self.fingers.mouse_down(e.button);
139                    
140                    self.call_event_handler(&Event::MouseDown(e.into()));
141                }
142                HostToStdin::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                HostToStdin::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                HostToStdin::Scroll(e) => {
154                    self.call_event_handler(&Event::Scroll(e.into()))
155                }
156                HostToStdin::WindowGeomChange { dpi_factor, inner_width, inner_height } => {
157                    self.windows[CxWindowPool::id_zero()].window_geom = WindowGeom {
158                        dpi_factor,
159                        inner_size: dvec2(inner_width, inner_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 handle = HANDLE(pi.image as isize);
167                        
168                        let texture = Texture::new(self);
169                        let desc = TextureDesc {
170                            format: TextureFormat::SharedBGRA(pi.id),
171                            width: Some(new_swapchain.alloc_width as usize),
172                            height: Some(new_swapchain.alloc_height as usize),
173                        };
174                        texture.set_desc(self, desc);
175                        self.textures[texture.texture_id()]
176                            .os.update_from_shared_handle(d3d11_cx, handle);
177                        texture
178                    });
179                    let swapchain = swapchain.insert(new_swapchain);
180                    
181                    // reset present_index
182                    present_index = 0;
183                    
184                    self.redraw_all();
185                    self.stdin_handle_platform_ops(Some(swapchain), present_index);
186                }
187                HostToStdin::Tick {frame: _, time, ..} => if swapchain.is_some() {
188                    
189                    // poll the service for updates
190                    // check signals
191                    if Signal::check_and_clear_ui_signal() {
192                        self.handle_media_signals();
193                        self.call_event_handler(&Event::Signal);
194                    }
195                    if self.handle_live_edit() {
196                        self.call_event_handler(&Event::LiveEdit);
197                        self.redraw_all();
198                    }
199                    self.handle_networking_events();
200                    // we should poll our runloop
201                    self.stdin_handle_platform_ops(swapchain.as_ref(), present_index);
202                    
203                    // alright a tick.
204                    // we should now run all the stuff.
205                    if self.new_next_frames.len() != 0 {
206                        self.call_next_frame_event(time);
207                    }
208                    
209                    if self.need_redrawing() {
210                        self.call_draw_event();
211                        self.hlsl_compile_shaders(d3d11_cx);
212                    }
213                    
214                    // repaint
215                    self.stdin_handle_repaint(d3d11_cx, swapchain.as_ref(), &mut present_index);
216                    
217                    
218                    // check if GPU is ready to flip frames
219                    if let Some(presentable_draw) = self.os.new_frame_being_rendered {
220                        while !d3d11_cx.is_gpu_done() {
221                            std::thread::sleep(std::time::Duration::from_millis(3));
222                        }
223                        let _ = io::stdout().write_all(StdinToHost::DrawCompleteAndFlip(presentable_draw).to_json().as_bytes());
224                        self.os.new_frame_being_rendered = None;
225                    }
226                    
227                }
228            }
229        }
230    }
231    
232    fn stdin_handle_platform_ops(
233        &mut self,
234        swapchain: Option<&Swapchain<Texture >>,
235        present_index: usize,
236    ) {
237        while let Some(op) = self.platform_ops.pop() {
238            match op {
239                CxOsOp::CreateWindow(window_id) => {
240                    if window_id != CxWindowPool::id_zero() {
241                        panic!("ONLY ONE WINDOW SUPPORTED");
242                    }
243                    let window = &mut self.windows[CxWindowPool::id_zero()];
244                    window.is_created = true;
245                    // lets set up our render pass target
246                    let pass = &mut self.passes[window.main_pass_id.unwrap()];
247                    if let Some(swapchain) = swapchain {
248                        pass.color_textures = vec![CxPassColorTexture {
249                            clear_color: PassClearColor::ClearWith(vec4(1.0, 1.0, 0.0, 1.0)),
250                            //clear_color: PassClearColor::ClearWith(pass.clear_color),
251                            texture_id: swapchain.presentable_images[present_index].image.texture_id(),
252                        }];
253                    }
254                },
255                CxOsOp::SetCursor(cursor) => {
256                    let _ = io::stdout().write_all(StdinToHost::SetCursor(cursor).to_json().as_bytes());
257                },
258                _ => ()
259                /*
260                CxOsOp::CloseWindow(_window_id) => {},
261                CxOsOp::MinimizeWindow(_window_id) => {},
262                CxOsOp::MaximizeWindow(_window_id) => {},
263                CxOsOp::RestoreWindow(_window_id) => {},
264                CxOsOp::FullscreenWindow(_window_id) => {},
265                CxOsOp::NormalizeWindow(_window_id) => {}
266                CxOsOp::SetTopmost(_window_id, _is_topmost) => {}
267                CxOsOp::XrStartPresenting(_) => {},
268                CxOsOp::XrStopPresenting(_) => {},
269                CxOsOp::ShowTextIME(_area, _pos) => {},
270                CxOsOp::HideTextIME => {},
271                CxOsOp::SetCursor(_cursor) => {},
272                CxOsOp::StartTimer {timer_id, interval, repeats} => {},
273                CxOsOp::StopTimer(timer_id) => {},
274                CxOsOp::StartDragging(dragged_item) => {}
275                CxOsOp::UpdateMenu(menu) => {}*/
276            }
277        }
278    }
279    
280}