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 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 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 }
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 }
288 else {
289 self.window_geom.position
290 }
291 }
292 }