StratoSDK is a framework with a declarative approach similar to Flutter/React, written and designed entirely for Rust.
| 1 | //! Desktop platform implementation |
| 2 | |
| 3 | use crate::event_loop::CustomEvent; |
| 4 | use crate::window::WindowInner; |
| 5 | use crate::{Platform, PlatformError, Window, WindowBuilder, WindowId}; |
| 6 | use std::collections::HashMap; |
| 7 | use std::sync::Arc; |
| 8 | use strato_core::event::Event; |
| 9 | |
| 10 | /// Desktop platform implementation |
| 11 | pub struct DesktopPlatform { |
| 12 | event_loop: Option<winit::event_loop::EventLoop<CustomEvent>>, |
| 13 | windows: HashMap<WindowId, Arc<winit::window::Window>>, |
| 14 | next_window_id: WindowId, |
| 15 | } |
| 16 | |
| 17 | impl DesktopPlatform { |
| 18 | /// Create a new desktop platform |
| 19 | pub fn new() -> Self { |
| 20 | Self { |
| 21 | event_loop: Some( |
| 22 | winit::event_loop::EventLoopBuilder::with_user_event() |
| 23 | .build() |
| 24 | .expect("Failed to create event loop"), |
| 25 | ), |
| 26 | windows: HashMap::new(), |
| 27 | next_window_id: 0, |
| 28 | } |
| 29 | } |
| 30 | } |
| 31 | |
| 32 | impl Platform for DesktopPlatform { |
| 33 | fn init() -> Result<Self, PlatformError> { |
| 34 | Ok(Self::new()) |
| 35 | } |
| 36 | |
| 37 | fn create_window(&mut self, builder: WindowBuilder) -> Result<Window, PlatformError> { |
| 38 | let event_loop = self |
| 39 | .event_loop |
| 40 | .as_ref() |
| 41 | .ok_or_else(|| PlatformError::EventLoop("Event loop not available".to_string()))?; |
| 42 | |
| 43 | let winit_window = builder |
| 44 | .build_winit(event_loop) |
| 45 | .map_err(|e| PlatformError::WindowCreation(e.to_string()))?; |
| 46 | |
| 47 | let window_arc = Arc::new(winit_window); |
| 48 | let window_id = self.next_window_id; |
| 49 | self.next_window_id += 1; |
| 50 | |
| 51 | self.windows.insert(window_id, window_arc.clone()); |
| 52 | |
| 53 | Ok(Window { |
| 54 | id: window_id, |
| 55 | inner: WindowInner::Desktop(window_arc), |
| 56 | }) |
| 57 | } |
| 58 | |
| 59 | fn run_event_loop( |
| 60 | &mut self, |
| 61 | mut callback: Box<dyn FnMut(Event) + 'static>, |
| 62 | ) -> Result<(), PlatformError> { |
| 63 | let event_loop = self |
| 64 | .event_loop |
| 65 | .take() |
| 66 | .ok_or_else(|| PlatformError::EventLoop("Event loop already taken".to_string()))?; |
| 67 | |
| 68 | use winit::event::{Event as WinitEvent, WindowEvent as WinitWindowEvent}; |
| 69 | |
| 70 | let mut cursor_position = winit::dpi::PhysicalPosition::new(0.0, 0.0); |
| 71 | let mut scale_factor = 1.0; |
| 72 | |
| 73 | let _ = event_loop.run(move |event, elwt| { |
| 74 | elwt.set_control_flow(winit::event_loop::ControlFlow::Wait); |
| 75 | |
| 76 | match event { |
| 77 | WinitEvent::WindowEvent { event, .. } => match event { |
| 78 | WinitWindowEvent::CursorMoved { |
| 79 | position, |
| 80 | device_id, |
| 81 | .. |
| 82 | } => { |
| 83 | cursor_position = position; |
| 84 | if let Some(strato_event) = crate::event_loop::convert_window_event( |
| 85 | WinitWindowEvent::CursorMoved { |
| 86 | position, |
| 87 | device_id, |
| 88 | }, |
| 89 | cursor_position, |
| 90 | scale_factor, |
| 91 | ) { |
| 92 | callback(strato_event); |
| 93 | } |
| 94 | } |
| 95 | WinitWindowEvent::ScaleFactorChanged { |
| 96 | scale_factor: sf, |
| 97 | inner_size_writer, |
| 98 | } => { |
| 99 | scale_factor = sf; |
| 100 | if let Some(strato_event) = crate::event_loop::convert_window_event( |
| 101 | WinitWindowEvent::ScaleFactorChanged { |
| 102 | scale_factor: sf, |
| 103 | inner_size_writer, |
| 104 | }, |
| 105 | cursor_position, |
| 106 | scale_factor, |
| 107 | ) { |
| 108 | callback(strato_event); |
| 109 | } |
| 110 | } |
| 111 | _ => { |
| 112 | if let Some(strato_event) = crate::event_loop::convert_window_event( |
| 113 | event, |
| 114 | cursor_position, |
| 115 | scale_factor, |
| 116 | ) { |
| 117 | callback(strato_event); |
| 118 | } |
| 119 | } |
| 120 | }, |
| 121 | WinitEvent::AboutToWait => { |
| 122 | // All events have been processed |
| 123 | } |
| 124 | _ => {} |
| 125 | } |
| 126 | }); |
| 127 | |
| 128 | Ok(()) |
| 129 | } |
| 130 | |
| 131 | fn request_redraw(&self, window_id: WindowId) { |
| 132 | if let Some(window) = self.windows.get(&window_id) { |
| 133 | window.request_redraw(); |
| 134 | } |
| 135 | } |
| 136 | |
| 137 | fn exit(&mut self) { |
| 138 | std::process::exit(0); |
| 139 | } |
| 140 | } |
| 141 |