makepad_platform/os/windows/
windows.rs

1use {
2    std::{
3        rc::Rc,
4        cell::RefCell,
5    },
6    crate::{
7        makepad_live_id::*,
8        cx::*,
9        event::*,
10        thread::Signal,
11        os::{
12            windows::{
13                windows_media::CxWindowsMedia,
14                windows_decoding::CxWindowsDecoding,
15                win32_event::*,
16                d3d11::{D3d11Window, D3d11Cx},
17                win32_app::*,
18            },
19            cx_native::EventFlow,
20        },
21        pass::CxPassParent,
22        cx_api::{CxOsApi, CxOsOp},
23        window::CxWindowPool,
24        windows::Win32::Graphics::Direct3D11::ID3D11Device,
25    }
26};
27
28impl Cx {
29    
30    pub fn event_loop(cx: Rc<RefCell<Cx >>) {
31        
32        cx.borrow_mut().self_ref = Some(cx.clone());
33        cx.borrow_mut().os_type = OsType::Windows;
34        
35        let d3d11_cx = Rc::new(RefCell::new(D3d11Cx::new()));
36
37        // hack: store ID3D11Device in CxOs, so texture-related operations become possible on the makepad/studio side, yet don't completely destroy the code there
38        cx.borrow_mut().os.d3d11_device = Some(d3d11_cx.borrow().device.clone());
39
40        for arg in std::env::args() {
41            if arg == "--stdin-loop" {
42                let mut cx = cx.borrow_mut();
43                cx.in_makepad_studio = true;
44                let mut d3d11_cx = d3d11_cx.borrow_mut();
45                return cx.stdin_event_loop(&mut d3d11_cx);
46            }
47        }
48        
49        let d3d11_windows = Rc::new(RefCell::new(Vec::new()));
50        
51        init_win32_app_global(Box::new({
52            let cx = cx.clone();
53            move | event | {
54                get_win32_app_global();
55                let mut cx = cx.borrow_mut();
56                let mut d3d11_cx = d3d11_cx.borrow_mut();
57                let mut d3d11_windows = d3d11_windows.borrow_mut();
58                cx.win32_event_callback(event, &mut d3d11_cx, &mut d3d11_windows)
59            }
60        }));
61        
62        cx.borrow_mut().call_event_handler(&Event::Construct);
63        cx.borrow_mut().redraw_all();
64        get_win32_app_global().start_signal_poll();
65        Win32App::event_loop();
66    }
67    
68    fn win32_event_callback(
69        &mut self,
70        event: Win32Event,
71        d3d11_cx: &mut D3d11Cx,
72        d3d11_windows: &mut Vec<D3d11Window>
73    ) -> EventFlow {
74        if let EventFlow::Exit = self.handle_platform_ops(d3d11_windows, d3d11_cx) {
75            return EventFlow::Exit
76        }
77        
78        let mut paint_dirty = false;
79        
80        //self.process_desktop_pre_event(&mut event);
81        match event {
82            Win32Event::AppGotFocus => { // repaint all window passes. Metal sometimes doesnt flip buffers when hidden/no focus
83                for window in d3d11_windows.iter_mut() {
84                    if let Some(main_pass_id) = self.windows[window.window_id].main_pass_id {
85                        self.repaint_pass(main_pass_id);
86                    }
87                }
88                paint_dirty = true;
89                self.call_event_handler(&Event::AppGotFocus);
90            }
91            Win32Event::AppLostFocus => {
92                self.call_event_handler(&Event::AppLostFocus);
93            }
94            Win32Event::WindowResizeLoopStart(window_id) => {
95                if let Some(window) = d3d11_windows.iter_mut().find( | w | w.window_id == window_id) {
96                    window.start_resize();
97                }
98            }
99            Win32Event::WindowResizeLoopStop(window_id) => {
100                if let Some(window) = d3d11_windows.iter_mut().find( | w | w.window_id == window_id) {
101                    window.stop_resize();
102                }
103            }
104            Win32Event::WindowGeomChange(re) => { // do this here because mac
105               
106                if let Some(window) = d3d11_windows.iter_mut().find( | w | w.window_id == re.window_id) {
107                    window.window_geom = re.new_geom.clone();
108                    self.windows[re.window_id].window_geom = re.new_geom.clone();
109                    // redraw just this windows root draw list
110                    if re.old_geom.inner_size != re.new_geom.inner_size {
111                        
112                        if let Some(main_pass_id) = self.windows[re.window_id].main_pass_id {
113                            self.redraw_pass_and_child_passes(main_pass_id);
114                        }
115                    }
116                }
117                // ok lets not redraw all, just this window
118                self.redraw_all();
119                self.call_event_handler(&Event::WindowGeomChange(re));
120            }
121            Win32Event::WindowClosed(wc) => {
122                let window_id = wc.window_id;
123                self.call_event_handler(&Event::WindowClosed(wc));
124                // lets remove the window from the set
125                self.windows[window_id].is_created = false;
126                if let Some(index) = d3d11_windows.iter().position( | w | w.window_id == window_id) {
127                    d3d11_windows.remove(index);
128                    if d3d11_windows.len() == 0 {
129                        self.call_event_handler(&Event::Destruct);
130                        return EventFlow::Exit
131                    }
132                }
133            }
134            Win32Event::Paint => {
135                if self.new_next_frames.len() != 0 {
136                    self.call_next_frame_event(get_win32_app_global().time_now());
137                }
138                if self.need_redrawing() {
139                    self.call_draw_event();
140                    self.hlsl_compile_shaders(&d3d11_cx);
141                }
142                // ok here we send out to all our childprocesses
143                
144                self.handle_repaint(d3d11_windows, d3d11_cx);
145            }
146            Win32Event::MouseDown(e) => {
147                self.fingers.process_tap_count(
148                    e.abs,
149                    e.time
150                );
151                self.fingers.mouse_down(e.button);
152                self.call_event_handler(&Event::MouseDown(e.into()))
153            }
154            Win32Event::MouseMove(e) => {
155                self.call_event_handler(&Event::MouseMove(e.into()));
156                self.fingers.cycle_hover_area(live_id!(mouse).into());
157                self.fingers.switch_captures();
158            }
159            Win32Event::MouseUp(e) => {
160                
161                let button = e.button;
162                self.call_event_handler(&Event::MouseUp(e.into()));
163                self.fingers.mouse_up(button);
164                self.fingers.cycle_hover_area(live_id!(mouse).into());
165            }
166            Win32Event::Scroll(e) => {
167                self.call_event_handler(&Event::Scroll(e.into()))
168            }
169            Win32Event::WindowDragQuery(e) => {
170                self.call_event_handler(&Event::WindowDragQuery(e))
171            }
172            Win32Event::WindowCloseRequested(e) => {
173                self.call_event_handler(&Event::WindowCloseRequested(e))
174            }
175            Win32Event::TextInput(e) => {
176                self.call_event_handler(&Event::TextInput(e))
177            }
178            Win32Event::Drag(e) => {
179                self.call_event_handler(&Event::Drag(e));
180                self.drag_drop.cycle_drag();
181            },
182            Win32Event::Drop(e) => {
183                self.call_event_handler(&Event::Drop(e));
184                self.drag_drop.cycle_drag();
185            },
186            Win32Event::DragEnd => {
187                // send MouseUp
188                self.call_event_handler(&Event::MouseUp(MouseUpEvent {
189                    abs: dvec2(-100000.0, -100000.0),
190                    button: 0,
191                    window_id: CxWindowPool::id_zero(),
192                    modifiers: Default::default(),
193                    time: 0.0
194                }));
195                self.fingers.mouse_up(0);
196                self.fingers.cycle_hover_area(live_id!(mouse).into());
197            }
198            Win32Event::KeyDown(e) => {
199                self.keyboard.process_key_down(e.clone());
200                self.call_event_handler(&Event::KeyDown(e))
201            }
202            Win32Event::KeyUp(e) => {
203                self.keyboard.process_key_up(e.clone());
204                self.call_event_handler(&Event::KeyUp(e))
205            }
206            Win32Event::TextCopy(e) => {
207                self.call_event_handler(&Event::TextCopy(e))
208            }
209            Win32Event::TextCut(e) => {
210                self.call_event_handler(&Event::TextCut(e))
211            }
212            Win32Event::Timer(e) => {
213                self.call_event_handler(&Event::Timer(e))
214            }
215            Win32Event::Signal => {
216                if Signal::check_and_clear_ui_signal() {
217                    self.handle_media_signals();
218                    self.call_event_handler(&Event::Signal);
219                }
220            }
221        }
222        
223        if self.any_passes_dirty() || self.need_redrawing() || self.new_next_frames.len() != 0 || paint_dirty {
224            EventFlow::Poll
225        } else {
226            EventFlow::Wait
227        }
228        
229    }
230    
231    pub (crate) fn handle_repaint(&mut self, d3d11_windows: &mut Vec<D3d11Window>, d3d11_cx: &mut D3d11Cx) {
232        let mut passes_todo = Vec::new();
233        self.compute_pass_repaint_order(&mut passes_todo);
234        self.repaint_id += 1;
235        for pass_id in &passes_todo {
236            self.passes[*pass_id].set_time(get_win32_app_global().time_now() as f32);
237            match self.passes[*pass_id].parent.clone() {
238                CxPassParent::Window(window_id) => {
239                    if let Some(window) = d3d11_windows.iter_mut().find( | w | w.window_id == window_id) {
240                        //let dpi_factor = window.window_geom.dpi_factor;
241                        window.resize_buffers(&d3d11_cx);
242                        self.draw_pass_to_window(*pass_id, true, window, d3d11_cx);
243                    }
244                }
245                CxPassParent::Pass(_) => {
246                    //let dpi_factor = self.get_delegated_dpi_factor(parent_pass_id);
247                    self.draw_pass_to_magic_texture(*pass_id, d3d11_cx);
248                },
249                CxPassParent::None => {
250                    self.draw_pass_to_magic_texture(*pass_id, d3d11_cx);
251                }
252            }
253        }
254    }
255    
256    pub (crate) fn handle_networking_events(&mut self) {
257    }
258    
259    fn handle_platform_ops(&mut self, d3d11_windows: &mut Vec<D3d11Window>, d3d11_cx: &D3d11Cx) -> EventFlow {
260        let mut ret = EventFlow::Poll;
261        while let Some(op) = self.platform_ops.pop() {
262            match op {
263                CxOsOp::CreateWindow(window_id) => {
264                    let window = &mut self.windows[window_id];
265                    let d3d11_window = D3d11Window::new(
266                        window_id,
267                        &d3d11_cx,
268                        window.create_inner_size.unwrap_or(dvec2(800., 600.)),
269                        window.create_position,
270                        &window.create_title
271                    );
272                    
273                    window.window_geom = d3d11_window.window_geom.clone();
274                    d3d11_windows.push(d3d11_window);
275                    window.is_created = true;
276                },
277                CxOsOp::CloseWindow(window_id) => {
278                    if let Some(index) = d3d11_windows.iter().position( | w | w.window_id == window_id) {
279                        self.windows[window_id].is_created = false;
280                        d3d11_windows[index].win32_window.close_window();
281                        d3d11_windows.remove(index);
282                        if d3d11_windows.len() == 0 {
283                            ret = EventFlow::Exit
284                        }
285                    }
286                },
287                CxOsOp::MinimizeWindow(window_id) => {
288                    if let Some(window) = d3d11_windows.iter_mut().find( | w | w.window_id == window_id) {
289                        window.win32_window.minimize();
290                    }
291                },
292                CxOsOp::MaximizeWindow(window_id) => {
293                    if let Some(window) = d3d11_windows.iter_mut().find( | w | w.window_id == window_id) {
294                        window.win32_window.maximize();
295                    }
296                },
297                CxOsOp::RestoreWindow(window_id) => {
298                    if let Some(window) = d3d11_windows.iter_mut().find( | w | w.window_id == window_id) {
299                        window.win32_window.restore();
300                    }
301                },
302                CxOsOp::Quit=>{
303                    ret = EventFlow::Exit
304                }
305                CxOsOp::FullscreenWindow(_window_id) => {
306                    todo!()
307                },
308                CxOsOp::NormalizeWindow(_window_id) => {
309                    todo!()
310                }
311                CxOsOp::SetTopmost(_window_id, _is_topmost) => {
312                    todo!()
313                }
314                CxOsOp::ShowClipboardActions(_) => {
315                }
316                CxOsOp::XrStartPresenting => {
317                    //todo!()
318                },
319                CxOsOp::XrStopPresenting => {
320                    //todo!()
321                },
322                CxOsOp::ShowTextIME(_area, _pos) => {
323                    //todo!()
324                }
325                CxOsOp::HideTextIME => {
326                    //todo!()
327                },
328                CxOsOp::SetCursor(cursor) => {
329                    get_win32_app_global().set_mouse_cursor(cursor);
330                },
331                CxOsOp::StartTimer {timer_id, interval, repeats} => {
332                    get_win32_app_global().start_timer(timer_id, interval, repeats);
333                },
334                CxOsOp::StopTimer(timer_id) => {
335                    get_win32_app_global().stop_timer(timer_id);
336                },
337                CxOsOp::StartDragging(dragged_item) => {
338                    get_win32_app_global().start_dragging(dragged_item);
339                },
340                CxOsOp::UpdateMacosMenu(_menu) => {
341                },
342                CxOsOp::HttpRequest {request_id: _, request: _} => {
343                    //todo!()
344                },
345                CxOsOp::WebSocketOpen {request_id: _, request: _,} => {
346                    //todo!()
347                }
348                CxOsOp::WebSocketSendBinary {request_id: _, data: _} => {
349                    //todo!()
350                }
351                CxOsOp::WebSocketSendString {request_id: _, data: _} => {
352                    //todo!()
353                },
354                CxOsOp::InitializeVideoDecoding(_, _, _) => todo!(),
355                CxOsOp::DecodeNextVideoChunk(_, _) => todo!(),
356                CxOsOp::FetchNextVideoFrames(_, _) => todo!(),
357                CxOsOp::CleanupVideoDecoding(_) => todo!(),
358            }
359        }
360        ret
361    }
362}
363
364impl CxOsApi for Cx {
365    fn init_cx_os(&mut self) {
366        self.live_expand();
367        self.live_scan_dependencies();
368        self.native_load_dependencies();
369    }
370    
371    fn spawn_thread<F>(&mut self, f: F) where F: FnOnce() + Send + 'static {
372        std::thread::spawn(f);
373    }
374}
375
376#[derive(Default)]
377pub struct CxOs {
378    pub (crate) media: CxWindowsMedia,
379    pub (crate) d3d11_device: Option<ID3D11Device>,
380    pub (crate) decoding: CxWindowsDecoding,
381    pub (crate) new_frame_being_rendered: Option<crate::cx_stdin::PresentableDraw>,
382}