makepad_platform/os/windows/
windows.rs1use {
2 std::{
3 time::Instant,
4 rc::Rc,
5 cell::RefCell,
6 },
7 crate::{
8 makepad_live_id::*,
9 cx::*,
10 event::*,
11 thread::SignalToUI,
12 os::{
13 windows::{
14 windows_media::CxWindowsMedia,
15 win32_event::*,
16 d3d11::{D3d11Window, D3d11Cx},
17 win32_app::*,
18 win32_window::Win32Window,
19 },
20 cx_native::EventFlow,
21 },
22 makepad_math::*,
23 pass::CxPassParent,
24 cx_api::{CxOsApi, CxOsOp, OpenUrlInPlace},
25 window::CxWindowPool,
26 windows::Win32::Graphics::Direct3D11::ID3D11Device,
27 }
28};
29
30impl Cx {
31
32 pub fn event_loop(cx: Rc<RefCell<Cx >>) {
33
34 cx.borrow_mut().self_ref = Some(cx.clone());
35 cx.borrow_mut().os_type = OsType::Windows;
36
37 let d3d11_cx = Rc::new(RefCell::new(D3d11Cx::new()));
38
39 cx.borrow_mut().os.d3d11_device = Some(d3d11_cx.borrow().device.clone());
41
42 for arg in std::env::args() {
43 if arg == "--stdin-loop" {
44 let mut cx = cx.borrow_mut();
45 cx.in_makepad_studio = true;
46 let mut d3d11_cx = d3d11_cx.borrow_mut();
47 return cx.stdin_event_loop(&mut d3d11_cx);
48 }
49 }
50
51 let d3d11_windows = Rc::new(RefCell::new(Vec::new()));
52
53 init_win32_app_global(Box::new({
54 let cx = cx.clone();
55 move | event | {
56 let mut cx = cx.borrow_mut();
57 let mut d3d11_cx = d3d11_cx.borrow_mut();
58 let mut d3d11_windows = d3d11_windows.borrow_mut();
59 cx.win32_event_callback(event, &mut d3d11_cx, &mut d3d11_windows)
60 }
61 }));
62 with_win32_app(|app| app.start_timer(0, 0.008, true));
64 cx.borrow_mut().call_event_handler(&Event::Startup);
65 cx.borrow_mut().redraw_all();
66 with_win32_app(|app| app.start_signal_poll());
67 Win32App::event_loop();
68 }
69
70 fn win32_event_callback(
71 &mut self,
72 event: Win32Event,
73 d3d11_cx: &mut D3d11Cx,
74 d3d11_windows: &mut Vec<D3d11Window>
75 ) -> EventFlow {
76 if let EventFlow::Exit = self.handle_platform_ops(d3d11_windows, d3d11_cx) {
77 return EventFlow::Exit
78 }
79
80 match event {
90 Win32Event::AppGotFocus => { for window in d3d11_windows.iter_mut() {
92 if let Some(main_pass_id) = self.windows[window.window_id].main_pass_id {
93 self.repaint_pass(main_pass_id);
94 }
95 }
96 self.call_event_handler(&Event::AppGotFocus);
98 }
99 Win32Event::AppLostFocus => {
100 self.call_event_handler(&Event::AppLostFocus);
101 }
102 Win32Event::WindowResizeLoopStart(window_id) => {
103 if let Some(window) = d3d11_windows.iter_mut().find( | w | w.window_id == window_id) {
104 window.start_resize();
105 }
106 }
107 Win32Event::WindowResizeLoopStop(window_id) => {
108 if let Some(window) = d3d11_windows.iter_mut().find( | w | w.window_id == window_id) {
109 window.stop_resize();
110 }
111 }
112 Win32Event::WindowGeomChange(mut re) => { if let Some(window) = d3d11_windows.iter_mut().find( | w | w.window_id == re.window_id) {
115 if let Some(dpi_override) = self.windows[re.window_id].dpi_override {
116 re.new_geom.inner_size *= re.new_geom.dpi_factor / dpi_override;
117 re.new_geom.dpi_factor = dpi_override;
118 }
119
120 window.window_geom = re.new_geom.clone();
121 self.windows[re.window_id].window_geom = re.new_geom.clone();
122 if re.old_geom.inner_size != re.new_geom.inner_size {
124
125 if let Some(main_pass_id) = self.windows[re.window_id].main_pass_id {
126 self.redraw_pass_and_child_passes(main_pass_id);
127 }
128 }
129 }
130 self.redraw_all();
132 self.call_event_handler(&Event::WindowGeomChange(re));
133 }
134 Win32Event::WindowClosed(wc) => {
135 let window_id = wc.window_id;
136 self.call_event_handler(&Event::WindowClosed(wc));
137 self.windows[window_id].is_created = false;
139 if let Some(index) = d3d11_windows.iter().position( | w | w.window_id == window_id) {
140 d3d11_windows.remove(index);
141 if d3d11_windows.len() == 0 {
142 self.call_event_handler(&Event::Shutdown);
143 return EventFlow::Exit
144 }
145 }
146 }
147 Win32Event::Paint => {
148 if self.new_next_frames.len() != 0 {
149 self.call_next_frame_event(with_win32_app(|app| app.time_now()));
150 }
151 if self.need_redrawing() {
152 self.call_draw_event();
153 self.hlsl_compile_shaders(&d3d11_cx);
154 }
155 self.handle_repaint(d3d11_windows, d3d11_cx);
158 }
159 Win32Event::MouseDown(e) => {
160 self.fingers.process_tap_count(
161 e.abs,
162 e.time
163 );
164 self.fingers.mouse_down(e.button, e.window_id);
165 self.call_event_handler(&Event::MouseDown(e.into()))
166 }
167 Win32Event::MouseMove(e) => {
168 self.call_event_handler(&Event::MouseMove(e.into()));
169 self.fingers.cycle_hover_area(live_id!(mouse).into());
170 self.fingers.switch_captures();
171 }
172 Win32Event::MouseUp(e) => {
173
174 let button = e.button;
175 self.call_event_handler(&Event::MouseUp(e.into()));
176 self.fingers.mouse_up(button);
177 self.fingers.cycle_hover_area(live_id!(mouse).into());
178 }
179 Win32Event::MouseLeave(e) => {
180 self.call_event_handler(&Event::MouseLeave(e.into()));
181 self.fingers.cycle_hover_area(live_id!(mouse).into());
182 self.fingers.switch_captures();
183 }
184 Win32Event::Scroll(e) => {
185 self.call_event_handler(&Event::Scroll(e.into()))
186 }
187 Win32Event::WindowDragQuery(e) => {
188 self.call_event_handler(&Event::WindowDragQuery(e))
189 }
190 Win32Event::WindowCloseRequested(e) => {
191 self.call_event_handler(&Event::WindowCloseRequested(e))
192 }
193 Win32Event::TextInput(e) => {
194 self.call_event_handler(&Event::TextInput(e))
195 }
196 Win32Event::Drag(e) => {
197 self.call_event_handler(&Event::Drag(e));
198 self.drag_drop.cycle_drag();
199 },
200 Win32Event::Drop(e) => {
201 self.call_event_handler(&Event::Drop(e));
202 self.drag_drop.cycle_drag();
203 },
204 Win32Event::DragEnd => {
205 self.call_event_handler(&Event::MouseUp(MouseUpEvent {
207 abs: dvec2(-100000.0, -100000.0),
208 button: MouseButton::PRIMARY,
209 window_id: CxWindowPool::id_zero(),
210 modifiers: Default::default(),
211 time: 0.0
212 }));
213 self.fingers.mouse_up(MouseButton::PRIMARY);
214 self.fingers.cycle_hover_area(live_id!(mouse).into());
215 }
216 Win32Event::KeyDown(e) => {
217 self.keyboard.process_key_down(e.clone());
218 self.call_event_handler(&Event::KeyDown(e))
219 }
220 Win32Event::KeyUp(e) => {
221 self.keyboard.process_key_up(e.clone());
222 self.call_event_handler(&Event::KeyUp(e))
223 }
224 Win32Event::TextCopy(e) => {
225 self.call_event_handler(&Event::TextCopy(e))
226 }
227 Win32Event::TextCut(e) => {
228 self.call_event_handler(&Event::TextCut(e))
229 }
230 Win32Event::Timer(e) => {
231 self.call_event_handler(&Event::Timer(e))
232 }
233 Win32Event::Signal => {
234 if SignalToUI::check_and_clear_ui_signal() {
235 self.handle_media_signals();
236 self.call_event_handler(&Event::Signal);
237 }
238 if SignalToUI::check_and_clear_action_signal() {
239 self.handle_action_receiver();
240 }
241
242 if self.handle_live_edit() {
243 self.call_event_handler(&Event::LiveEdit);
244 self.redraw_all();
245 }
246 self.handle_networking_events();
247
248 self.win32_event_callback(Win32Event::Paint, d3d11_cx, d3d11_windows);
249
250 return EventFlow::Wait;
251 }
252 }
253
254 return EventFlow::Poll;
255 }
263
264 pub (crate) fn handle_repaint(&mut self, d3d11_windows: &mut Vec<D3d11Window>, d3d11_cx: &mut D3d11Cx) {
265
266 let mut passes_todo = Vec::new();
267 self.compute_pass_repaint_order(&mut passes_todo);
268 self.repaint_id += 1;
269 for pass_id in &passes_todo {
270 self.passes[*pass_id].set_time(with_win32_app(|app| app.time_now() as f32));
271 match self.passes[*pass_id].parent.clone() {
272 CxPassParent::Xr => {}
273 CxPassParent::Window(window_id) => {
274 if let Some(window) = d3d11_windows.iter_mut().find( | w | w.window_id == window_id) {
275 window.resize_buffers(&d3d11_cx);
277 self.draw_pass_to_window(*pass_id, false, window, d3d11_cx);
278 }
279 }
280 CxPassParent::Pass(_) => {
281 self.draw_pass_to_texture(*pass_id, d3d11_cx, None);
283 },
284 CxPassParent::None => {
285 self.draw_pass_to_texture(*pass_id, d3d11_cx, None);
286 }
287 }
288 }
289 }
290
291 pub(crate) fn handle_networking_events(&mut self) {
292 let mut out = Vec::new();
293 while let Ok(event) = self.os.network_response.receiver.try_recv(){
294 out.push(event);
295 }
296 if out.len()>0{
297 self.call_event_handler(& Event::NetworkResponses(out))
298 }
299 }
300
301 fn handle_platform_ops(&mut self, d3d11_windows: &mut Vec<D3d11Window>, d3d11_cx: &D3d11Cx) -> EventFlow {
302 let mut ret = EventFlow::Poll;
303 let mut geom_changes = Vec::new();
304 while let Some(op) = self.platform_ops.pop() {
305 match op {
306 CxOsOp::CreateWindow(window_id) => {
307 let window = &mut self.windows[window_id];
308 let d3d11_window = D3d11Window::new(
309 window_id,
310 &d3d11_cx,
311 window.create_inner_size.unwrap_or(dvec2(800., 600.)),
312 window.create_position,
313 &window.create_title
314 );
315
316 window.window_geom = d3d11_window.window_geom.clone();
317 d3d11_windows.push(d3d11_window);
318 window.is_created = true;
319 geom_changes.push(WindowGeomChangeEvent{
320 window_id,
321 old_geom: window.window_geom.clone(),
322 new_geom: window.window_geom.clone()
323 });
324 },
325 CxOsOp::CloseWindow(window_id) => {
326 self.call_event_handler(&Event::WindowClosed(WindowClosedEvent { window_id }));
327 if let Some(index) = d3d11_windows.iter().position( | w | w.window_id == window_id) {
328 self.windows[window_id].is_created = false;
329 d3d11_windows[index].win32_window.close_window();
330 d3d11_windows.remove(index);
331 if d3d11_windows.len() == 0 {
332 ret = EventFlow::Exit
333 }
334 }
335 },
336 CxOsOp::MinimizeWindow(window_id) => {
337 if let Some(window) = d3d11_windows.iter_mut().find( | w | w.window_id == window_id) {
338 window.win32_window.minimize();
339 }
340 },
341 CxOsOp::Deminiaturize(_window_id) => todo!(),
342 CxOsOp::HideWindow(_window_id) => todo!(),
343 CxOsOp::MaximizeWindow(window_id) => {
344 if let Some(window) = d3d11_windows.iter_mut().find( | w | w.window_id == window_id) {
345 window.win32_window.maximize();
346 }
347 },
348 CxOsOp::ResizeWindow(window_id, size) => {
349 if let Some(window) = d3d11_windows.iter_mut().find( | w | w.window_id == window_id) {
350 window.win32_window.set_inner_size(size);
351 }
352 }
353 CxOsOp::RepositionWindow(window_id, pos) => {
354 if let Some(window) = d3d11_windows.iter_mut().find( | w | w.window_id == window_id) {
355 window.win32_window.set_position(pos);
356 }
357 }
358 CxOsOp::RestoreWindow(window_id) => {
359 if let Some(window) = d3d11_windows.iter_mut().find( | w | w.window_id == window_id) {
360 window.win32_window.restore();
361 }
362 },
363 CxOsOp::Quit=>{
364 ret = EventFlow::Exit
365 }
366 CxOsOp::SetTopmost(window_id, is_topmost) => {
367 if d3d11_windows.len() == 0 {
368 self.platform_ops.insert(0, CxOsOp::SetTopmost(window_id, is_topmost));
369 continue;
370 }
371 if let Some(window) = d3d11_windows.iter_mut().find( | w | w.window_id == window_id) {
372 window.win32_window.set_topmost(is_topmost);
373 }
374 }
375 CxOsOp::CopyToClipboard(content) => {
376 unsafe {
377 Win32Window::copy_to_clipboard(&content);
378 }
379 },
380 CxOsOp::SetCursor(cursor) => {
381 with_win32_app(|app| app.set_mouse_cursor(cursor));
382 },
383 CxOsOp::StartTimer {timer_id, interval, repeats} => {
384 with_win32_app(|app| app.start_timer(timer_id, interval, repeats));
385 },
386 CxOsOp::StopTimer(timer_id) => {
387 with_win32_app(|app| app.stop_timer(timer_id));
388 },
389 CxOsOp::StartDragging(dragged_item) => {
390 with_win32_app(|app| app.start_dragging(dragged_item));
391 },
392 CxOsOp::HttpRequest {request_id, request} => {
393 use crate::os::windows::http::WindowsHttpSocket;
394 WindowsHttpSocket::open(request_id, request, self.os.network_response.sender.clone());
395
396 },
398 CxOsOp::ShowTextIME{..}=>{
399
400 }
401 CxOsOp::HideTextIME=>{
402
403 }
404 e=>{
405 crate::error!("Not implemented on this platform: CxOsOp::{:?}", e);
406 }
407 }
408 }
409 if geom_changes.len()>0{
410 self.redraw_all();
411 for geom_change in geom_changes{
412 self.call_event_handler(&Event::WindowGeomChange(geom_change));
413 }
414 }
415 ret
416 }
417}
418
419impl CxOsApi for Cx {
420 fn init_cx_os(&mut self) {
421 self.os.start_time = Some(Instant::now());
422 if let Some(item) = std::option_env!("MAKEPAD_PACKAGE_DIR"){
423 self.live_registry.borrow_mut().package_root = Some(item.to_string());
424 }
425
426 self.live_expand();
427 if std::env::args().find( | v | v == "--stdin-loop").is_none() {
428 self.start_disk_live_file_watcher(100);
429 }
430 self.live_scan_dependencies();
431 self.native_load_dependencies();
432 }
433
434 fn spawn_thread<F>(&mut self, f: F) where F: FnOnce() + Send + 'static {
435 std::thread::spawn(f);
436 }
437
438 fn seconds_since_app_start(&self)->f64{
439 Instant::now().duration_since(self.os.start_time.unwrap()).as_secs_f64()
440 }
441
442 fn open_url(&mut self, _url:&str, _in_place:OpenUrlInPlace){
443 crate::error!("open_url not implemented on this platform");
444 }
445}
446
447#[derive(Default)]
448pub struct CxOs {
449 pub (crate) start_time: Option<Instant>,
450 pub (crate) media: CxWindowsMedia,
451 pub (crate) d3d11_device: Option<ID3D11Device>,
452 pub (crate) network_response: NetworkResponseChannel,
453 }