makepad_platform/
window.rs1use {
2 crate::{
3 makepad_live_compiler::*,
4 makepad_live_id::*,
5 makepad_math::*,
6 makepad_error_log::*,
7 id_pool::*,
8 event::{
9 WindowGeom
10 },
11 pass::{Pass, PassId, CxPassParent},
12 cx::Cx,
13 cx_api::CxOsOp,
14 live_traits::*,
15 }
16};
17
18pub struct WindowHandle(PoolId);
19
20#[derive(Clone, Debug, PartialEq, Copy)]
21pub struct WindowId(usize, u64);
22
23impl WindowHandle {
24 pub fn window_id(&self) -> WindowId {WindowId(self.0.id, self.0.generation)}
25}
26
27#[derive(Default)]
28pub struct CxWindowPool(IdPool<CxWindow>);
29impl CxWindowPool {
30 fn alloc(&mut self) -> WindowHandle {
31 WindowHandle(self.0.alloc())
32 }
33
34 pub fn id_zero()->WindowId{
35 WindowId(0, 0)
36 }
37}
38
39impl std::ops::Index<WindowId> for CxWindowPool {
40 type Output = CxWindow;
41 fn index(&self, index: WindowId) -> &Self::Output {
42 let d = &self.0.pool[index.0];
43 if d.generation != index.1{
44 error!("Window id generation wrong {} {} {}", index.0, d.generation, index.1)
45 }
46 &d.item
47 }
48}
49
50impl std::ops::IndexMut<WindowId> for CxWindowPool {
51 fn index_mut(&mut self, index: WindowId) -> &mut Self::Output {
52 let d = &mut self.0.pool[index.0];
53 if d.generation != index.1{
54 error!("Window id generation wrong {} {} {}", index.0, d.generation, index.1)
55 }
56 &mut d.item
57 }
58}
59
60impl LiveHook for WindowHandle {}
61impl LiveNew for WindowHandle {
62 fn new(cx: &mut Cx) -> Self {
63 let window = cx.windows.alloc();
64 let cxwindow = &mut cx.windows[window.window_id()];
65 cxwindow.is_created = false;
66 cxwindow.create_title = "Makepad".to_string();
67 cxwindow.create_inner_size = None;
68 cxwindow.create_position = None;
69 cx.platform_ops.push(CxOsOp::CreateWindow(window.window_id()));
70 window
71 }
72
73 fn live_type_info(_cx: &mut Cx) -> LiveTypeInfo {
74 LiveTypeInfo {
75 module_id: LiveModuleId::from_str(&module_path!()).unwrap(),
76 live_type: LiveType::of::<Self>(),
77 fields: Vec::new(),
78 live_ignore: true,
79 type_name: id_lut!(Window)
80 }
81 }
82}
83impl LiveApply for WindowHandle {
84 fn apply(&mut self, cx: &mut Cx, from: ApplyFrom, start_index: usize, nodes: &[LiveNode]) -> usize {
86
87 if !nodes[start_index].value.is_structy_type() {
88 cx.apply_error_wrong_type_for_struct(live_error_origin!(), start_index, nodes, live_id!(View));
89 return nodes.skip_node(start_index);
90 }
91
92 let mut index = start_index + 1;
93 loop {
94 if nodes[index].value.is_close() {
95 index += 1;
96 break;
97 }
98 match nodes[index].id {
99 live_id!(inner_size) => {
100 let v:Vec2 = LiveNew::new_apply_mut_index(cx, from, &mut index, nodes);
101 cx.windows[self.window_id()].create_inner_size = Some(v.into());
102 },
103 live_id!(title) => {
104 let v = LiveNew::new_apply_mut_index(cx, from, &mut index, nodes);
105 cx.windows[self.window_id()].create_title = v;
106 }
107 live_id!(position) => {
108 let v:Vec2 = LiveNew::new_apply_mut_index(cx, from, &mut index, nodes);
109 cx.windows[self.window_id()].create_position = Some(v.into());
110 }
111 live_id!(dpi_override) => {
112 let v:f64 = LiveNew::new_apply_mut_index(cx, from, &mut index, nodes);
113 cx.windows[self.window_id()].dpi_override = Some(v);
115 }
116 _ => {
117 cx.apply_error_no_matching_field(live_error_origin!(), index, nodes);
118 index = nodes.skip_node(index);
119 }
120 }
121 }
122 return index;
123 }
124}
125
126
127impl WindowHandle {
128 pub fn set_pass(&self, cx: &mut Cx, pass: &Pass) {
129 cx.windows[self.window_id()].main_pass_id = Some(pass.pass_id());
130 cx.passes[pass.pass_id()].parent = CxPassParent::Window(self.window_id());
131 }
132
133 pub fn get_inner_size(&mut self, cx: &mut Cx) -> DVec2 {
134 cx.windows[self.window_id()].get_inner_size()
135 }
136
137 pub fn get_position(&mut self, cx: &mut Cx) -> DVec2 {
138 cx.windows[self.window_id()].get_position()
139 }
140
141 pub fn minimize(&mut self, cx: &mut Cx) {
142 cx.push_unique_platform_op(CxOsOp::MinimizeWindow(self.window_id()));
143 }
144
145 pub fn maximize(&mut self, cx: &mut Cx) {
146 cx.push_unique_platform_op(CxOsOp::MaximizeWindow(self.window_id()));
147 }
148
149 pub fn fullscreen(&mut self, cx: &mut Cx) {
150 cx.push_unique_platform_op(CxOsOp::FullscreenWindow(self.window_id()));
151 }
152
153 pub fn normal(&mut self, cx: &mut Cx) {
154 cx.push_unique_platform_op(CxOsOp::NormalizeWindow(self.window_id()));
155 }
156
157 pub fn can_fullscreen(&mut self, cx: &mut Cx) -> bool {
158 cx.windows[self.window_id()].window_geom.can_fullscreen
159 }
160
161 pub fn is_fullscreen(&mut self, cx: &mut Cx) -> bool {
162 cx.windows[self.window_id()].window_geom.is_fullscreen
163 }
164
165 pub fn xr_is_presenting(&mut self, cx: &mut Cx) -> bool {
166 cx.windows[self.window_id()].window_geom.xr_is_presenting
167 }
168
169 pub fn is_topmost(&mut self, cx: &mut Cx) -> bool {
170 cx.windows[self.window_id()].window_geom.is_topmost
171 }
172
173 pub fn set_topmost(&mut self, cx: &mut Cx, set_topmost: bool) {
174 cx.push_unique_platform_op(CxOsOp::SetTopmost(self.window_id(), set_topmost));
175 }
176
177 pub fn restore(&mut self, cx: &mut Cx) {
178 cx.push_unique_platform_op(CxOsOp::RestoreWindow(self.window_id()));
179 }
180
181 pub fn close(&mut self, cx: &mut Cx) {
182 cx.push_unique_platform_op(CxOsOp::CloseWindow(self.window_id()));
183 }
184}
185
186#[derive(Clone, Default)]
187pub struct CxWindow {
188 pub create_title: String,
189 pub create_position: Option<DVec2>,
190 pub create_inner_size: Option<DVec2>,
191 pub dpi_override: Option<f64>,
192 pub is_created: bool,
193 pub window_geom: WindowGeom,
194 pub main_pass_id: Option<PassId>,
195}
196
197impl CxWindow {
198
199 pub fn get_inner_size(&mut self) -> DVec2 {
200 if !self.is_created {
201 Default::default()
202 }
204 else {
205 self.window_geom.inner_size
206 }
207 }
208
209 pub fn get_position(&mut self) -> DVec2 {
210 if !self.is_created {
211 panic!();
212 }
213 else {
214 self.window_geom.position
215 }
216 }
217 }