makepad_platform/
window.rs

1use {
2    crate::{
3        makepad_live_compiler::*,
4        makepad_live_id::*,
5        makepad_math::*,
6        id_pool::*,
7        event::{
8            WindowGeom
9        },
10        pass::{Pass, PassId, CxPassParent},
11        cx::Cx,
12        cx_api::CxOsOp,
13        live_traits::*,
14    }
15};
16
17pub struct WindowHandle(PoolId);
18
19#[derive(Clone, Debug, PartialEq, Copy)]
20pub struct WindowId(pub usize, pub u64);
21
22impl WindowId{
23    pub fn id(&self)->usize{self.0}
24}
25
26impl WindowHandle {
27    pub fn window_id(&self) -> WindowId {WindowId(self.0.id, self.0.generation)}
28}
29
30#[derive(Default)]
31pub struct CxWindowPool(IdPool<CxWindow>);
32impl CxWindowPool {
33    fn alloc(&mut self) -> WindowHandle {
34        WindowHandle(self.0.alloc())
35    }
36    
37    pub fn window_id_contains(&self, pos:DVec2)->(WindowId, DVec2){
38        for (index,item) in self.0.pool.iter().enumerate(){
39            let window = &item.item;
40            if pos.x>= window.window_geom.position.x &&
41                pos.y>= window.window_geom.position.y && 
42                pos.x<= window.window_geom.position.x+window.window_geom.inner_size.x  &&
43                pos.y<= window.window_geom.position.y+window.window_geom.inner_size.y{
44                return (WindowId(index, item.generation), window.window_geom.position)
45            }
46        }
47        return (WindowId(0, self.0.pool[0].generation), self.0.pool[0].item.window_geom.position)
48    }
49    
50    
51    pub fn relative_to_window_id(&self, pos:DVec2)->(WindowId, DVec2){
52        for (index,item) in self.0.pool.iter().enumerate(){
53            let window = &item.item;
54            if pos.x>= window.window_geom.position.x &&
55            pos.y>= window.window_geom.position.y && 
56            pos.x<= window.window_geom.position.x+window.window_geom.inner_size.x  &&
57            pos.y<= window.window_geom.position.x+window.window_geom.inner_size.y{
58                return (WindowId(index, item.generation), window.window_geom.position)
59            }
60        }
61        return (WindowId(0, self.0.pool[0].generation), self.0.pool[0].item.window_geom.position)
62    }
63    
64    pub fn is_valid(&self, v: WindowId)->bool{
65        if v.0 < self.0.pool.len(){
66            if self.0.pool[v.0].generation == v.1{
67                return true
68            }
69        }
70        false
71    }
72    
73    pub fn id_zero()->WindowId{
74        WindowId(0, 0)
75    }
76    
77    pub fn from_usize(v:usize)->WindowId{
78        WindowId(v, 0)
79    }
80}
81
82impl std::ops::Index<WindowId> for CxWindowPool {
83    type Output = CxWindow;
84    fn index(&self, index: WindowId) -> &Self::Output {
85        let d = &self.0.pool[index.0];
86        if d.generation != index.1{
87            error!("Window id generation wrong {} {} {}", index.0, d.generation, index.1)
88        }
89        &d.item
90    }
91}
92
93impl std::ops::IndexMut<WindowId> for CxWindowPool {
94    fn index_mut(&mut self, index: WindowId) -> &mut Self::Output {
95        let d = &mut self.0.pool[index.0];
96        if d.generation != index.1{
97            error!("Window id generation wrong {} {} {}", index.0, d.generation, index.1)
98        }
99        &mut d.item
100    }
101}
102
103impl LiveHook for WindowHandle {}
104impl LiveNew for WindowHandle {
105
106    fn new(cx: &mut Cx) -> Self {
107        let window = cx.windows.alloc();
108        let cxwindow = &mut cx.windows[window.window_id()];
109        cxwindow.is_created = false;
110        cxwindow.create_title = "Makepad".to_string();
111        cxwindow.create_inner_size = None;
112        cxwindow.create_position = None;
113        cx.platform_ops.push(CxOsOp::CreateWindow(window.window_id()));
114        window
115    }
116    
117    fn live_type_info(_cx: &mut Cx) -> LiveTypeInfo {
118        LiveTypeInfo {
119            module_id: LiveModuleId::from_str(&module_path!()).unwrap(),
120            live_type: LiveType::of::<Self>(),
121            fields: Vec::new(),
122            live_ignore: true,
123            type_name: id_lut!(Window)
124        }
125    }
126}
127
128impl LiveApply for WindowHandle {
129    //fn type_id(&self)->std::any::TypeId{ std::any::TypeId::of::<Self>()}
130    fn apply(&mut self, cx: &mut Cx, apply: &mut Apply, start_index: usize, nodes: &[LiveNode]) -> usize {
131        
132        if !nodes[start_index].value.is_structy_type() {
133            cx.apply_error_wrong_type_for_struct(live_error_origin!(), start_index, nodes, live_id!(View));
134            return nodes.skip_node(start_index);
135        }
136        
137        let mut index = start_index + 1;
138        loop {
139            if nodes[index].value.is_close() {
140                index += 1;
141                break;
142            }
143            match nodes[index].id {
144                live_id!(inner_size) => {
145                    let v:Vec2 = LiveNew::new_apply_mut_index(cx, apply, &mut index, nodes);
146                    cx.windows[self.window_id()].create_inner_size = Some(v.into());
147                },
148                live_id!(title) => {
149                    let v = LiveNew::new_apply_mut_index(cx, apply, &mut index, nodes);
150                    cx.windows[self.window_id()].create_title = v;
151                }
152                live_id!(kind_id) => {
153                    let v = LiveNew::new_apply_mut_index(cx, apply, &mut index, nodes);
154                    cx.windows[self.window_id()].kind_id = v;
155                }
156                live_id!(position) => {
157                    let v:Vec2 = LiveNew::new_apply_mut_index(cx, apply, &mut index, nodes);
158                    cx.windows[self.window_id()].create_position = Some(v.into());
159                }
160                live_id!(dpi_override) => {
161                    let v:f64 = LiveNew::new_apply_mut_index(cx, apply, &mut index, nodes);
162                    //log!("DPI OVERRIDE {}", v);
163                    cx.windows[self.window_id()].dpi_override = Some(v);
164                }
165                live_id!(topmost) => {
166                    let v:bool = LiveNew::new_apply_mut_index(cx, apply, &mut index, nodes);
167                    self.set_topmost(cx, v);
168                }
169                _ => {
170                    cx.apply_error_no_matching_field(live_error_origin!(), index, nodes);
171                    index = nodes.skip_node(index);
172                }
173            }
174        }
175        return index;
176    }
177}
178
179impl WindowHandle {
180    pub fn set_pass(&self, cx: &mut Cx, pass: &Pass) {
181        cx.windows[self.window_id()].main_pass_id = Some(pass.pass_id());
182        cx.passes[pass.pass_id()].parent = CxPassParent::Window(self.window_id());
183    }
184    
185    pub fn get_inner_size(&self, cx: &Cx) -> DVec2 {
186        cx.windows[self.window_id()].get_inner_size()
187    }
188    
189    pub fn get_position(&self, cx: &Cx) -> DVec2 {
190        cx.windows[self.window_id()].get_position()
191    }
192    
193    pub fn set_kind_id(&mut self, cx: &mut Cx,kind_id:usize) {
194        cx.windows[self.window_id()].kind_id = kind_id;
195    }
196    
197    pub fn minimize(&mut self, cx: &mut Cx) {
198        cx.push_unique_platform_op(CxOsOp::MinimizeWindow(self.window_id()));
199    }
200    
201    pub fn maximize(&mut self, cx: &mut Cx) {
202        cx.push_unique_platform_op(CxOsOp::MaximizeWindow(self.window_id()));
203    }
204    
205    pub fn fullscreen(&mut self, cx: &mut Cx) {
206        cx.push_unique_platform_op(CxOsOp::FullscreenWindow(self.window_id()));
207    }
208    
209    pub fn normal(&mut self, cx: &mut Cx) {
210        cx.push_unique_platform_op(CxOsOp::NormalizeWindow(self.window_id()));
211    }
212    
213    pub fn can_fullscreen(&mut self, cx: &mut Cx) -> bool {
214        cx.windows[self.window_id()].window_geom.can_fullscreen
215    }
216    
217    pub fn is_fullscreen(&self, cx: &Cx) -> bool {
218        cx.windows[self.window_id()].window_geom.is_fullscreen
219    }
220    
221    pub fn xr_is_presenting(&mut self, cx: &mut Cx) -> bool {
222        cx.windows[self.window_id()].window_geom.xr_is_presenting
223    }
224    
225    pub fn is_topmost(&mut self, cx: &mut Cx) -> bool {
226        cx.windows[self.window_id()].window_geom.is_topmost
227    }
228    
229    pub fn set_topmost(&mut self, cx: &mut Cx, set_topmost: bool) {
230        cx.push_unique_platform_op(CxOsOp::SetTopmost(self.window_id(), set_topmost));
231    }
232    
233    pub fn resize(&self, cx: &mut Cx, size: DVec2) {
234        cx.push_unique_platform_op(CxOsOp::ResizeWindow(self.window_id(), size));
235    }
236
237    pub fn reposition(&self, cx: &mut Cx, position: DVec2) {
238        cx.push_unique_platform_op(CxOsOp::RepositionWindow(self.window_id(), position));
239    }
240
241    pub fn restore(&mut self, cx: &mut Cx) {
242        cx.push_unique_platform_op(CxOsOp::RestoreWindow(self.window_id()));
243    }
244    
245    pub fn close(&mut self, cx: &mut Cx) {
246        cx.push_unique_platform_op(CxOsOp::CloseWindow(self.window_id()));
247    }
248}
249
250#[derive(Clone, Default)]
251pub struct CxWindow {
252    pub create_title: String,
253    pub create_position: Option<DVec2>,
254    pub create_inner_size: Option<DVec2>,
255    pub kind_id: usize,
256    pub dpi_override: Option<f64>,
257    pub os_dpi_factor: Option<f64>,
258    pub is_created: bool,
259    pub window_geom: WindowGeom,
260    pub main_pass_id: Option<PassId>,
261}
262
263impl CxWindow {
264    pub fn remap_dpi_override(&self, pos:DVec2)->DVec2{
265        if let Some(dpi_override) = self.dpi_override{
266            if let Some(os_dpi_factor) = self.os_dpi_factor{
267                return pos * ( os_dpi_factor / dpi_override)
268            }
269        }
270        return pos
271    }
272    
273    pub fn get_inner_size(&self) -> DVec2 {
274        if !self.is_created {
275            Default::default()
276            //panic!();
277        }
278        else {
279            self.window_geom.inner_size
280        }
281    }
282    
283    pub fn get_position(&self) -> DVec2 {
284        if !self.is_created {
285            Default::default()
286            //panic!();
287        }
288        else {
289            self.window_geom.position
290        }
291    }
292    /*
293    pub fn get_dpi_factor(&mut self) -> Option<f32> {
294        if self.is_created {
295            Some(self.window_geom.dpi_factor)
296        }
297        else{
298            None
299        }
300    }*/
301}