makepad_render/
cx_macos.rs1use crate::cx_cocoa::*;
3use crate::cx::*;
4
5impl Cx {
6
7 pub fn event_loop<F>(&mut self, mut event_handler: F)
8 where F: FnMut(&mut Cx, &mut Event),
9 {
10 self.platform_type = PlatformType::OSX;
11
12 let mut cocoa_app = CocoaApp::new();
13
14 cocoa_app.init();
15
16 let mut metal_cx = MetalCx::new();
17
18 let mut metal_windows: Vec<MetalWindow> = Vec::new();
19
20 self.mtl_compile_all_shaders(&metal_cx);
21
22 self.load_theme_fonts();
23
24 self.call_event_handler(&mut event_handler, &mut Event::Construct);
25
26 self.redraw_child_area(Area::All);
27
28 let mut passes_todo = Vec::new();
29
30 cocoa_app.event_loop( | cocoa_app, events | {
31 for mut event in events {
33
34 self.process_desktop_pre_event(&mut event, &mut event_handler);
35
36 match &event {
37 Event::WindowGeomChange(re) => { for metal_window in &mut metal_windows {
39 if metal_window.window_id == re.window_id {
40 metal_window.window_geom = re.new_geom.clone();
41 self.windows[re.window_id].window_geom = re.new_geom.clone();
42 if re.old_geom.inner_size != re.new_geom.inner_size{
44 if let Some(main_pass_id) = self.windows[re.window_id].main_pass_id {
45 self.redraw_pass_and_sub_passes(main_pass_id);
46 }
47 }
48 break;
49 }
50 }
51 self.call_event_handler(&mut event_handler, &mut event);
53 },
54 Event::WindowClosed(wc) => {
55 self.windows[wc.window_id].window_state = CxWindowState::Closed;
57 self.windows_free.push(wc.window_id);
58 for index in 0..metal_windows.len() {
61 if metal_windows[index].window_id == wc.window_id {
62 metal_windows.remove(index);
63 if metal_windows.len() == 0 {
64 cocoa_app.terminate_event_loop();
65 }
66 for metal_window in &mut metal_windows {
67 metal_window.cocoa_window.update_ptrs();
68 }
69 }
70 }
71 self.call_event_handler(&mut event_handler, &mut event);
72 },
73 Event::Paint => {
74
75 let vsync = self.process_desktop_paint_callbacks(cocoa_app.time_now(), &mut event_handler);
76
77 for (index, window) in self.windows.iter_mut().enumerate() {
79
80 window.window_state = match &window.window_state {
81 CxWindowState::Create {inner_size, position, title} => {
82 let metal_window = MetalWindow::new(index, &metal_cx, cocoa_app, *inner_size, *position, &title);
84 window.window_geom = metal_window.window_geom.clone();
85 metal_windows.push(metal_window);
86 for metal_window in &mut metal_windows {
87 metal_window.cocoa_window.update_ptrs();
88 }
89 CxWindowState::Created
90 },
91 CxWindowState::Close => {
92 for metal_window in &mut metal_windows {if metal_window.window_id == index {
93 metal_window.cocoa_window.close_window();
94 break;
95 }}
96 CxWindowState::Closed
97 },
98 CxWindowState::Created => CxWindowState::Created,
99 CxWindowState::Closed => CxWindowState::Closed
100 };
101
102 window.window_command = match &window.window_command {
103 CxWindowCmd::Restore => {
104 for metal_window in &mut metal_windows {if metal_window.window_id == index {
105 metal_window.cocoa_window.restore();
106 }}
107 CxWindowCmd::None
108 },
109 CxWindowCmd::Maximize => {
110 for metal_window in &mut metal_windows {if metal_window.window_id == index {
111 metal_window.cocoa_window.maximize();
112 }}
113 CxWindowCmd::None
114 },
115 CxWindowCmd::Minimize => {
116 for metal_window in &mut metal_windows {if metal_window.window_id == index {
117 metal_window.cocoa_window.minimize();
118 }}
119 CxWindowCmd::None
120 },
121 _ => CxWindowCmd::None,
122 };
123
124 if let Some(topmost) = window.window_topmost {
125 for metal_window in &mut metal_windows {if metal_window.window_id == index {
126 metal_window.cocoa_window.set_topmost(topmost);
127 }}
128 }
129 }
130
131 if !self.down_mouse_cursor.is_none() {
133 cocoa_app.set_mouse_cursor(self.down_mouse_cursor.as_ref().unwrap().clone())
134 }
135 else if !self.hover_mouse_cursor.is_none() {
136 cocoa_app.set_mouse_cursor(self.hover_mouse_cursor.as_ref().unwrap().clone())
137 }
138 else {
139 cocoa_app.set_mouse_cursor(MouseCursor::Default)
140 }
141
142 if let Some(set_ime_position) = self.platform.set_ime_position {
143 self.platform.set_ime_position = None;
144 for metal_window in &mut metal_windows {
145 metal_window.cocoa_window.set_ime_spot(set_ime_position);
146 }
147 }
148
149 while self.platform.start_timer.len() > 0 {
150 let (timer_id, interval, repeats) = self.platform.start_timer.pop().unwrap();
151 cocoa_app.start_timer(timer_id, interval, repeats);
152 }
153
154 while self.platform.stop_timer.len() > 0 {
155 let timer_id = self.platform.stop_timer.pop().unwrap();
156 cocoa_app.stop_timer(timer_id);
157 }
158
159 if self.platform.set_menu{
160 self.platform.set_menu = false;
161 if let Some(menu) = &self.platform.last_menu{
162 cocoa_app.update_app_menu(menu, &self.command_settings)
163 }
164 }
165
166 let mut windows_need_repaint = 0;
168 self.compute_passes_to_repaint(&mut passes_todo, &mut windows_need_repaint);
169
170 if passes_todo.len() > 0 {
171 for pass_id in &passes_todo {
172 match self.passes[*pass_id].dep_of.clone() {
173 CxPassDepOf::Window(window_id) => {
174 windows_need_repaint -= 1;
177 for metal_window in &mut metal_windows {if metal_window.window_id == window_id {
178 metal_window.set_vsync_enable(windows_need_repaint == 0 && vsync);
179 metal_window.set_buffer_count(
180 if metal_window.window_geom.is_fullscreen {3}else {2}
181 );
182
183 let dpi_factor = metal_window.window_geom.dpi_factor;
184
185 metal_window.resize_core_animation_layer(&metal_cx);
186
187 self.draw_pass_to_layer(
188 *pass_id,
189 dpi_factor,
190 metal_window.ca_layer,
191 &mut metal_cx,
192 );
193 if metal_window.first_draw{
195 metal_window.first_draw = false;
196 if dpi_factor != self.default_dpi_factor{
197 self.redraw_pass_and_sub_passes(*pass_id);
198 }
199
200 }
201 }}
202 }
203 CxPassDepOf::Pass(parent_pass_id) => {
204 let dpi_factor = self.get_delegated_dpi_factor(parent_pass_id);
205 self.draw_pass_to_texture(
206 *pass_id,
207 dpi_factor,
208 &mut metal_cx,
209 );
210 },
211 CxPassDepOf::None => {
212 self.draw_pass_to_texture(
213 *pass_id,
214 1.0,
215 &mut metal_cx,
216 );
217 }
218 }
219 }
220 }
221 },
222 Event::None => {
223 },
224 Event::Signal{..}=>{
225 self.call_event_handler(&mut event_handler, &mut event);
226 self.call_signals(&mut event_handler);
227 },
228 _ => {
229 self.call_event_handler(&mut event_handler, &mut event);
230 }
231 }
232 if self.process_desktop_post_event(event) {
233 cocoa_app.terminate_event_loop();
234 }
235 }
236 if self.playing_anim_areas.len() == 0 && self.redraw_parent_areas.len() == 0 && self.redraw_child_areas.len() == 0 && self.frame_callbacks.len() == 0 {
237 true
238 } else {
239 false
240 }
241 })
242 }
243
244 pub fn show_text_ime(&mut self, x: f32, y: f32) {
245 self.platform.set_ime_position = Some(Vec2 {x: x, y: y});
246 }
247
248 pub fn hide_text_ime(&mut self) {
249 }
250
251 pub fn set_window_outer_size(&mut self, size: Vec2) {
252 self.platform.set_window_outer_size = Some(size);
253 }
254
255 pub fn set_window_position(&mut self, pos: Vec2) {
256 self.platform.set_window_position = Some(pos);
257 }
258
259 pub fn start_timer(&mut self, interval: f64, repeats: bool) -> Timer {
260 self.timer_id += 1;
261 self.platform.start_timer.push((self.timer_id, interval, repeats));
262 Timer {timer_id: self.timer_id}
263 }
264
265 pub fn stop_timer(&mut self, timer: &mut Timer) {
266 if timer.timer_id != 0 {
267 self.platform.stop_timer.push(timer.timer_id);
268 timer.timer_id = 0;
269 }
270 }
271
272 pub fn post_signal(signal: Signal, status: StatusId) {
273 if signal.signal_id != 0{
274 CocoaApp::post_signal(signal.signal_id, status);
275 }
276 }
277
278 pub fn update_menu(&mut self, menu:&Menu){
279 let platform = &mut self.platform;
281 if platform.last_menu.is_none() || platform.last_menu.as_ref().unwrap() != menu{
282 platform.last_menu = Some(menu.clone());
283 platform.set_menu = true;
284 }
285 }
286}
287
288#[derive(Clone, Default)]
289pub struct CxPlatform {
290 pub bytes_written: usize,
291 pub draw_calls_done: usize,
292 pub last_menu: Option<Menu>,
293 pub set_menu: bool,
294 pub set_window_position: Option<Vec2>,
295 pub set_window_outer_size: Option<Vec2>,
296 pub set_ime_position: Option<Vec2>,
297 pub start_timer: Vec<(u64, f64, bool)>,
298 pub stop_timer: Vec<(u64)>,
299 pub text_clipboard_response: Option<String>,
300 pub desktop: CxDesktop,
301}