Skip to content

Commit 36e4474

Browse files
committed
separate Window::open() into three functions (parented, as_if_parented, and blocking)
1 parent 86bf222 commit 36e4474

7 files changed

Lines changed: 280 additions & 227 deletions

File tree

examples/open_window.rs

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -34,16 +34,10 @@ fn main() {
3434
title: "baseview".into(),
3535
size: baseview::Size::new(512.0, 512.0),
3636
scale: WindowScalePolicy::SystemScaleFactor,
37-
parent: baseview::Parent::None,
3837
};
3938

4039
let (mut tx, rx) = RingBuffer::new(128).split();
4140

42-
let opt_app_runner = Window::open(
43-
window_open_options,
44-
|_| OpenWindowExample { rx }
45-
);
46-
4741
::std::thread::spawn(move || {
4842
loop {
4943
::std::thread::sleep(Duration::from_secs(5));
@@ -54,5 +48,8 @@ fn main() {
5448
}
5549
});
5650

57-
opt_app_runner.unwrap().app_run_blocking();
51+
Window::open_blocking(
52+
window_open_options,
53+
|_| OpenWindowExample { rx }
54+
);
5855
}

src/lib.rs

Lines changed: 0 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,3 @@
1-
use raw_window_handle::RawWindowHandle;
2-
31
#[cfg(target_os = "windows")]
42
mod win;
53
#[cfg(target_os = "linux")]
@@ -19,17 +17,3 @@ pub use mouse_cursor::MouseCursor;
1917
pub use window::*;
2018
pub use window_info::*;
2119
pub use window_open_options::*;
22-
23-
#[derive(Debug)]
24-
pub enum Parent {
25-
None,
26-
AsIfParented,
27-
WithParent(RawWindowHandle),
28-
}
29-
30-
unsafe impl Send for Parent {}
31-
32-
pub trait WindowHandler {
33-
fn on_frame(&mut self);
34-
fn on_event(&mut self, window: &mut Window, event: Event);
35-
}

src/macos/window.rs

Lines changed: 126 additions & 97 deletions
Original file line numberDiff line numberDiff line change
@@ -17,27 +17,13 @@ use objc::{msg_send, runtime::Object, sel, sel_impl};
1717
use raw_window_handle::{macos::MacOSHandle, HasRawWindowHandle, RawWindowHandle};
1818

1919
use crate::{
20-
Event, Parent, WindowHandler, WindowOpenOptions,
21-
WindowScalePolicy, WindowInfo
20+
Event, WindowHandler, WindowOpenOptions, WindowScalePolicy, WindowInfo,
2221
};
2322

2423
use super::view::{create_view, BASEVIEW_STATE_IVAR};
2524
use 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-
4127
pub 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

4935
impl 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

Comments
 (0)