@@ -17,27 +17,13 @@ use objc::{msg_send, runtime::Object, sel, sel_impl};
1717use raw_window_handle:: { macos:: MacOSHandle , HasRawWindowHandle , RawWindowHandle } ;
1818
1919use crate :: {
20- Event , Parent , WindowHandler , WindowOpenOptions ,
21- WindowScalePolicy , WindowInfo
20+ Event , WindowHandler , WindowOpenOptions , WindowScalePolicy , WindowInfo ,
2221} ;
2322
2423use super :: view:: { create_view, BASEVIEW_STATE_IVAR } ;
2524use super :: keyboard:: KeyboardState ;
2625
2726
28- pub struct AppRunner ;
29-
30- impl AppRunner {
31- pub fn app_run_blocking ( self ) {
32- unsafe {
33- // Get reference to already created shared NSApplication object
34- // and run the main loop
35- NSApp ( ) . run ( ) ;
36- }
37- }
38- }
39-
40-
4127pub struct Window {
4228 /// Only set if we created the parent window, i.e. we are running in
4329 /// parentless mode
@@ -47,102 +33,147 @@ pub struct Window {
4733}
4834
4935impl Window {
50- pub fn open < H , B > (
51- options : WindowOpenOptions ,
52- build : B
53- ) -> Option < crate :: AppRunner >
54- where H : WindowHandler + ' static ,
55- B : FnOnce ( & mut crate :: Window ) -> H ,
56- B : Send + ' static
36+ pub fn open_parented < P , H , B > ( parent : & P , options : WindowOpenOptions , build : B )
37+ where
38+ P : HasRawWindowHandle ,
39+ H : WindowHandler + ' static ,
40+ B : FnOnce ( & mut crate :: Window ) -> H ,
41+ B : Send + ' static ,
5742 {
5843 let _pool = unsafe { NSAutoreleasePool :: new ( nil) } ;
5944
60- let mut window = unsafe {
61- Window {
62- ns_window : None ,
63- ns_view : create_view ( & options) ,
64- }
45+ let handle = if let RawWindowHandle :: MacOS ( handle) = parent. raw_window_handle ( ) {
46+ handle
47+ } else {
48+ panic ! ( "Not a macOS window" ) ;
6549 } ;
6650
67- let window_handler = Box :: new ( build ( & mut crate :: Window :: new ( & mut window ) ) ) ;
51+ let ns_view = unsafe { create_view ( & options ) } ;
6852
69- let retain_count_after_build: usize = unsafe {
70- msg_send ! [ window. ns_view, retainCount]
53+ let window = Window {
54+ ns_window : None ,
55+ ns_view,
56+ } ;
57+
58+ Self :: init ( window, build) ;
59+
60+ unsafe {
61+ let _: id = msg_send ! [ handle. ns_view as * mut Object , addSubview: ns_view] ;
62+ }
63+ }
64+
65+ pub fn open_as_if_parented < H , B > ( options : WindowOpenOptions , build : B ) -> RawWindowHandle
66+ where
67+ H : WindowHandler + ' static ,
68+ B : FnOnce ( & mut crate :: Window ) -> H ,
69+ B : Send + ' static ,
70+ {
71+ let _pool = unsafe { NSAutoreleasePool :: new ( nil) } ;
72+
73+ let ns_view = unsafe { create_view ( & options) } ;
74+
75+ let window = Window {
76+ ns_window : None ,
77+ ns_view,
7178 } ;
7279
73- let opt_app_runner = match options. parent {
74- Parent :: WithParent ( RawWindowHandle :: MacOS ( handle) ) => {
75- unsafe {
76- let ( ) = msg_send ! [
77- handle. ns_view as * mut Object ,
78- addSubview: window. ns_view
79- ] ;
80- }
81-
82- None
83- } ,
84- Parent :: WithParent ( _) => {
85- panic ! ( "Not a macOS window" ) ;
86- } ,
87- Parent :: AsIfParented => {
88- None
89- } ,
90- Parent :: None => {
91- // It seems prudent to run NSApp() here before doing other
92- // work. It runs [NSApplication sharedApplication], which is
93- // what is run at the very start of the Xcode-generated main
94- // function of a cocoa app according to:
95- // https://developer.apple.com/documentation/appkit/nsapplication
96- unsafe {
97- let app = NSApp ( ) ;
98- app. setActivationPolicy_ (
99- NSApplicationActivationPolicyRegular
100- ) ;
101- }
102-
103- let scaling = match options. scale {
104- WindowScalePolicy :: ScaleFactor ( scale) => scale,
105- WindowScalePolicy :: SystemScaleFactor => 1.0 ,
106- } ;
80+ let raw_window_handle = window. raw_window_handle ( ) ;
81+
82+ Self :: init ( window, build) ;
83+
84+ raw_window_handle
85+ }
86+
87+ pub fn open_blocking < H , B > ( options : WindowOpenOptions , build : B )
88+ where
89+ H : WindowHandler + ' static ,
90+ B : FnOnce ( & mut crate :: Window ) -> H ,
91+ B : Send + ' static ,
92+ {
93+ let _pool = unsafe { NSAutoreleasePool :: new ( nil) } ;
94+
95+ // It seems prudent to run NSApp() here before doing other
96+ // work. It runs [NSApplication sharedApplication], which is
97+ // what is run at the very start of the Xcode-generated main
98+ // function of a cocoa app according to:
99+ // https://developer.apple.com/documentation/appkit/nsapplication
100+ let app = unsafe { NSApp ( ) } ;
101+
102+ unsafe {
103+ app. setActivationPolicy_ (
104+ NSApplicationActivationPolicyRegular
105+ ) ;
106+ }
107+
108+ let scaling = match options. scale {
109+ WindowScalePolicy :: ScaleFactor ( scale) => scale,
110+ WindowScalePolicy :: SystemScaleFactor => 1.0 ,
111+ } ;
107112
108- let window_info = WindowInfo :: from_logical_size (
109- options. size ,
110- scaling
111- ) ;
113+ let window_info = WindowInfo :: from_logical_size (
114+ options. size ,
115+ scaling
116+ ) ;
112117
113- let rect = NSRect :: new (
114- NSPoint :: new ( 0.0 , 0.0 ) ,
115- NSSize :: new (
116- window_info. logical_size ( ) . width as f64 ,
117- window_info. logical_size ( ) . height as f64
118- ) ,
119- ) ;
118+ let rect = NSRect :: new (
119+ NSPoint :: new ( 0.0 , 0.0 ) ,
120+ NSSize :: new (
121+ window_info. logical_size ( ) . width as f64 ,
122+ window_info. logical_size ( ) . height as f64
123+ ) ,
124+ ) ;
120125
121- unsafe {
122- let ns_window = NSWindow :: alloc ( nil)
123- . initWithContentRect_styleMask_backing_defer_ (
124- rect,
125- NSWindowStyleMask :: NSTitledWindowMask ,
126- NSBackingStoreBuffered ,
127- NO ,
128- )
129- . autorelease ( ) ;
130- ns_window. center ( ) ;
126+ let ns_window = unsafe {
127+ let ns_window = NSWindow :: alloc ( nil)
128+ . initWithContentRect_styleMask_backing_defer_ (
129+ rect,
130+ NSWindowStyleMask :: NSTitledWindowMask ,
131+ NSBackingStoreBuffered ,
132+ NO ,
133+ )
134+ . autorelease ( ) ;
135+ ns_window. center ( ) ;
136+
137+ let title = NSString :: alloc ( nil)
138+ . init_str ( & options. title )
139+ . autorelease ( ) ;
140+ ns_window. setTitle_ ( title) ;
141+
142+ ns_window. makeKeyAndOrderFront_ ( nil) ;
143+
144+ ns_window
145+ } ;
131146
132- let title = NSString :: alloc ( nil)
133- . init_str ( & options. title )
134- . autorelease ( ) ;
135- ns_window. setTitle_ ( title) ;
147+ let ns_view = unsafe { create_view ( & options) } ;
136148
137- ns_window. makeKeyAndOrderFront_ ( nil) ;
149+ let window = Window {
150+ ns_window : Some ( ns_window) ,
151+ ns_view,
152+ } ;
138153
139- ns_window . setContentView_ ( window. ns_view ) ;
154+ Self :: init ( window, build ) ;
140155
141- window. ns_window = Some ( ns_window) ;
156+ unsafe {
157+ ns_window. setContentView_ ( ns_view) ;
158+ }
142159
143- Some ( crate :: AppRunner ( AppRunner ) )
144- }
145- } ,
160+ unsafe {
161+ app. run ( ) ;
162+ }
163+ }
164+
165+ fn init < H , B > (
166+ mut window : Window ,
167+ build : B
168+ )
169+ where H : WindowHandler + ' static ,
170+ B : FnOnce ( & mut crate :: Window ) -> H ,
171+ B : Send + ' static ,
172+ {
173+ let window_handler = Box :: new ( build ( & mut crate :: Window :: new ( & mut window) ) ) ;
174+
175+ let retain_count_after_build: usize = unsafe {
176+ msg_send ! [ window. ns_view, retainCount]
146177 } ;
147178
148179 let window_state_ptr = Box :: into_raw ( Box :: new ( WindowState {
@@ -161,8 +192,6 @@ impl Window {
161192
162193 WindowState :: setup_timer ( window_state_ptr) ;
163194 }
164-
165- opt_app_runner
166195 }
167196}
168197
0 commit comments