Skip to content

Commit fdb43ea

Browse files
authored
Unify Window struct across backends (#162)
The public Window struct holds a mutable reference to `platform::Window`, which is a pattern that doesn't make sense for all backends. On Windows, the `platform::Window` struct itself just holds another (immutable) reference, and on macOS the `platform::Window` struct has to be wrapped in a `RefCell` so that a mutable reference to it can be formed. Change the public `Window` struct to hold `platform::Window` directly, and change `platform::Window` in the macOS and X11 backends so that it simply holds a reference to another `WindowInner` struct similarly to the Windows backend. This allows us to remove the platform conditional in the declaration of the top-level `Window` struct. It also allows us to remove the `RefCell` wrapping `platform::Window` in the macOS backend and replace it with `Cell`s wrapping its individual fields.
1 parent 937ef96 commit fdb43ea

5 files changed

Lines changed: 110 additions & 103 deletions

File tree

src/macos/window.rs

Lines changed: 45 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -95,22 +95,26 @@ impl Drop for ParentHandle {
9595
}
9696
}
9797

98-
pub struct Window {
98+
struct WindowInner {
9999
/// Only set if we created the parent window, i.e. we are running in
100100
/// parentless mode
101-
ns_app: Option<id>,
101+
ns_app: Cell<Option<id>>,
102102
/// Only set if we created the parent window, i.e. we are running in
103103
/// parentless mode
104-
ns_window: Option<id>,
104+
ns_window: Cell<Option<id>>,
105105
/// Our subclassed NSView
106106
ns_view: id,
107-
close_requested: bool,
107+
close_requested: Cell<bool>,
108108

109109
#[cfg(feature = "opengl")]
110110
gl_context: Option<GlContext>,
111111
}
112112

113-
impl Window {
113+
pub struct Window<'a> {
114+
inner: &'a WindowInner,
115+
}
116+
117+
impl<'a> Window<'a> {
114118
pub fn open_parented<P, H, B>(parent: &P, options: WindowOpenOptions, build: B) -> WindowHandle
115119
where
116120
P: HasRawWindowHandle,
@@ -135,19 +139,19 @@ impl Window {
135139

136140
let ns_view = unsafe { create_view(&options) };
137141

138-
let window = Window {
139-
ns_app: None,
140-
ns_window: None,
142+
let window_inner = WindowInner {
143+
ns_app: Cell::new(None),
144+
ns_window: Cell::new(None),
141145
ns_view,
142-
close_requested: false,
146+
close_requested: Cell::new(false),
143147

144148
#[cfg(feature = "opengl")]
145149
gl_context: options
146150
.gl_config
147151
.map(|gl_config| Self::create_gl_context(None, ns_view, gl_config)),
148152
};
149153

150-
let window_handle = Self::init(true, window, window_info, build);
154+
let window_handle = Self::init(true, window_inner, window_info, build);
151155

152156
unsafe {
153157
let _: id = msg_send![handle.ns_view as *mut Object, addSubview: ns_view];
@@ -211,19 +215,19 @@ impl Window {
211215

212216
let ns_view = unsafe { create_view(&options) };
213217

214-
let window = Window {
215-
ns_app: Some(app),
216-
ns_window: Some(ns_window),
218+
let window_inner = WindowInner {
219+
ns_app: Cell::new(Some(app)),
220+
ns_window: Cell::new(Some(ns_window)),
217221
ns_view,
218-
close_requested: false,
222+
close_requested: Cell::new(false),
219223

220224
#[cfg(feature = "opengl")]
221225
gl_context: options
222226
.gl_config
223227
.map(|gl_config| Self::create_gl_context(Some(ns_window), ns_view, gl_config)),
224228
};
225229

226-
let _ = Self::init(false, window, window_info, build);
230+
let _ = Self::init(false, window_inner, window_info, build);
227231

228232
unsafe {
229233
ns_window.setContentView_(ns_view);
@@ -236,24 +240,26 @@ impl Window {
236240
}
237241

238242
fn init<H, B>(
239-
parented: bool, mut window: Window, window_info: WindowInfo, build: B,
243+
parented: bool, window_inner: WindowInner, window_info: WindowInfo, build: B,
240244
) -> WindowHandle
241245
where
242246
H: WindowHandler + 'static,
243247
B: FnOnce(&mut crate::Window) -> H,
244248
B: Send + 'static,
245249
{
246-
let window_handler = Box::new(build(&mut crate::Window::new(&mut window)));
250+
let mut window = crate::Window::new(Window { inner: &window_inner });
251+
let window_handler = Box::new(build(&mut window));
247252

248253
let (parent_handle, window_handle) = ParentHandle::new(window.raw_window_handle());
249254
let parent_handle = if parented { Some(parent_handle) } else { None };
250255

251-
let retain_count_after_build: usize = unsafe { msg_send![window.ns_view, retainCount] };
256+
let retain_count_after_build: usize =
257+
unsafe { msg_send![window_inner.ns_view, retainCount] };
252258

253-
let ns_view = window.ns_view;
259+
let ns_view = window_inner.ns_view;
254260

255261
let window_state_ptr = Box::into_raw(Box::new(WindowState {
256-
window: RefCell::new(window),
262+
window_inner,
257263
window_handler: RefCell::new(window_handler),
258264
keyboard_state: KeyboardState::new(),
259265
frame_timer: Cell::new(None),
@@ -272,27 +278,27 @@ impl Window {
272278
}
273279

274280
pub fn close(&mut self) {
275-
self.close_requested = true;
281+
self.inner.close_requested.set(true);
276282
}
277283

278284
pub fn resize(&mut self, size: Size) {
279285
// NOTE: macOS gives you a personal rave if you pass in fractional pixels here. Even though
280286
// the size is in fractional pixels.
281287
let size = NSSize::new(size.width.round(), size.height.round());
282288

283-
unsafe { NSView::setFrameSize(self.ns_view, size) };
289+
unsafe { NSView::setFrameSize(self.inner.ns_view, size) };
284290
unsafe {
285-
let _: () = msg_send![self.ns_view, setNeedsDisplay: YES];
291+
let _: () = msg_send![self.inner.ns_view, setNeedsDisplay: YES];
286292
}
287293

288294
// When using OpenGL the `NSOpenGLView` needs to be resized separately? Why? Because macOS.
289295
#[cfg(feature = "opengl")]
290-
if let Some(gl_context) = &self.gl_context {
296+
if let Some(gl_context) = &self.inner.gl_context {
291297
gl_context.resize(size);
292298
}
293299

294300
// If this is a standalone window then we'll also need to resize the window itself
295-
if let Some(ns_window) = self.ns_window {
301+
if let Some(ns_window) = self.inner.ns_window.get() {
296302
unsafe { NSWindow::setContentSize_(ns_window, size) };
297303
}
298304
}
@@ -303,7 +309,7 @@ impl Window {
303309

304310
#[cfg(feature = "opengl")]
305311
pub fn gl_context(&self) -> Option<&GlContext> {
306-
self.gl_context.as_ref()
312+
self.inner.gl_context.as_ref()
307313
}
308314

309315
#[cfg(feature = "opengl")]
@@ -318,7 +324,7 @@ impl Window {
318324
}
319325

320326
pub(super) struct WindowState {
321-
window: RefCell<Window>,
327+
window_inner: WindowInner,
322328
window_handler: RefCell<Box<dyn WindowHandler>>,
323329
keyboard_state: KeyboardState,
324330
frame_timer: Cell<Option<CFRunLoopTimer>>,
@@ -337,13 +343,13 @@ impl WindowState {
337343
}
338344

339345
pub(super) fn trigger_event(&self, event: Event) -> EventStatus {
340-
let mut window = self.window.borrow_mut();
341-
self.window_handler.borrow_mut().on_event(&mut crate::Window::new(&mut window), event)
346+
let mut window = crate::Window::new(Window { inner: &self.window_inner });
347+
self.window_handler.borrow_mut().on_event(&mut window, event)
342348
}
343349

344350
pub(super) fn trigger_frame(&self) {
345-
let mut window = self.window.borrow_mut();
346-
self.window_handler.borrow_mut().on_frame(&mut crate::Window::new(&mut window));
351+
let mut window = crate::Window::new(Window { inner: &self.window_inner });
352+
self.window_handler.borrow_mut().on_frame(&mut window);
347353

348354
let mut do_close = false;
349355

@@ -359,14 +365,14 @@ impl WindowState {
359365
*/
360366

361367
// Check if the user requested the window to close
362-
if window.close_requested {
368+
if self.window_inner.close_requested.get() {
363369
do_close = true;
364-
window.close_requested = false;
370+
self.window_inner.close_requested.set(false);
365371
}
366372

367373
if do_close {
368374
unsafe {
369-
let ns_window = self.window.borrow_mut().ns_window.take();
375+
let ns_window = self.window_inner.ns_window.take();
370376
if let Some(ns_window) = ns_window {
371377
ns_window.close();
372378
} else {
@@ -430,26 +436,26 @@ impl WindowState {
430436
window_state.trigger_event(Event::Window(WindowEvent::WillClose));
431437

432438
// If in non-parented mode, we want to also quit the app altogether
433-
let app = window_state.window.borrow_mut().ns_app.take();
439+
let app = window_state.window_inner.ns_app.take();
434440
if let Some(app) = app {
435441
app.stop_(app);
436442
}
437443
}
438444
}
439445

440-
unsafe impl HasRawWindowHandle for Window {
446+
unsafe impl<'a> HasRawWindowHandle for Window<'a> {
441447
fn raw_window_handle(&self) -> RawWindowHandle {
442-
let ns_window = self.ns_window.unwrap_or(ptr::null_mut()) as *mut c_void;
448+
let ns_window = self.inner.ns_window.get().unwrap_or(ptr::null_mut()) as *mut c_void;
443449

444450
let mut handle = AppKitWindowHandle::empty();
445451
handle.ns_window = ns_window;
446-
handle.ns_view = self.ns_view as *mut c_void;
452+
handle.ns_view = self.inner.ns_view as *mut c_void;
447453

448454
RawWindowHandle::AppKit(handle)
449455
}
450456
}
451457

452-
unsafe impl HasRawDisplayHandle for Window {
458+
unsafe impl<'a> HasRawDisplayHandle for Window<'a> {
453459
fn raw_display_handle(&self) -> RawDisplayHandle {
454460
RawDisplayHandle::AppKit(AppKitDisplayHandle::empty())
455461
}

src/win/drop_target.rs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -90,8 +90,7 @@ impl DropTarget {
9090
};
9191

9292
unsafe {
93-
let mut window = window_state.create_window();
94-
let mut window = crate::Window::new(&mut window);
93+
let mut window = crate::Window::new(window_state.create_window());
9594

9695
let event = Event::Mouse(event);
9796
let event_status =

src/win/window.rs

Lines changed: 8 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -168,8 +168,7 @@ unsafe fn wnd_proc_inner(
168168
) -> Option<LRESULT> {
169169
match msg {
170170
WM_MOUSEMOVE => {
171-
let mut window = window_state.create_window();
172-
let mut window = crate::Window::new(&mut window);
171+
let mut window = crate::Window::new(window_state.create_window());
173172

174173
let x = (lparam & 0xFFFF) as i16 as i32;
175174
let y = ((lparam >> 16) & 0xFFFF) as i16 as i32;
@@ -189,8 +188,7 @@ unsafe fn wnd_proc_inner(
189188
Some(0)
190189
}
191190
WM_MOUSEWHEEL | WM_MOUSEHWHEEL => {
192-
let mut window = window_state.create_window();
193-
let mut window = crate::Window::new(&mut window);
191+
let mut window = crate::Window::new(window_state.create_window());
194192

195193
let value = (wparam >> 16) as i16;
196194
let value = value as i32;
@@ -214,8 +212,7 @@ unsafe fn wnd_proc_inner(
214212
}
215213
WM_LBUTTONDOWN | WM_LBUTTONUP | WM_MBUTTONDOWN | WM_MBUTTONUP | WM_RBUTTONDOWN
216214
| WM_RBUTTONUP | WM_XBUTTONDOWN | WM_XBUTTONUP => {
217-
let mut window = window_state.create_window();
218-
let mut window = crate::Window::new(&mut window);
215+
let mut window = crate::Window::new(window_state.create_window());
219216

220217
let mut mouse_button_counter = window_state.mouse_button_counter.get();
221218

@@ -278,8 +275,7 @@ unsafe fn wnd_proc_inner(
278275
None
279276
}
280277
WM_TIMER => {
281-
let mut window = window_state.create_window();
282-
let mut window = crate::Window::new(&mut window);
278+
let mut window = crate::Window::new(window_state.create_window());
283279

284280
if wparam == WIN_FRAME_TIMER {
285281
window_state.handler.borrow_mut().as_mut().unwrap().on_frame(&mut window);
@@ -290,8 +286,7 @@ unsafe fn wnd_proc_inner(
290286
WM_CLOSE => {
291287
// Make sure to release the borrow before the DefWindowProc call
292288
{
293-
let mut window = window_state.create_window();
294-
let mut window = crate::Window::new(&mut window);
289+
let mut window = crate::Window::new(window_state.create_window());
295290

296291
window_state
297292
.handler
@@ -307,8 +302,7 @@ unsafe fn wnd_proc_inner(
307302
}
308303
WM_CHAR | WM_SYSCHAR | WM_KEYDOWN | WM_SYSKEYDOWN | WM_KEYUP | WM_SYSKEYUP
309304
| WM_INPUTLANGCHANGE => {
310-
let mut window = window_state.create_window();
311-
let mut window = crate::Window::new(&mut window);
305+
let mut window = crate::Window::new(window_state.create_window());
312306

313307
let opt_event =
314308
window_state.keyboard_state.borrow_mut().process_message(hwnd, msg, wparam, lparam);
@@ -329,8 +323,7 @@ unsafe fn wnd_proc_inner(
329323
}
330324
}
331325
WM_SIZE => {
332-
let mut window = window_state.create_window();
333-
let mut window = crate::Window::new(&mut window);
326+
let mut window = crate::Window::new(window_state.create_window());
334327

335328
let width = (lparam & 0xFFFF) as u16 as u32;
336329
let height = ((lparam >> 16) & 0xFFFF) as u16 as u32;
@@ -676,8 +669,7 @@ impl Window<'_> {
676669
});
677670

678671
let handler = {
679-
let mut window = window_state.create_window();
680-
let mut window = crate::Window::new(&mut window);
672+
let mut window = crate::Window::new(window_state.create_window());
681673

682674
build(&mut window)
683675
};

src/window.rs

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -50,23 +50,20 @@ pub trait WindowHandler {
5050
}
5151

5252
pub struct Window<'a> {
53-
#[cfg(target_os = "windows")]
54-
window: &'a mut platform::Window<'a>,
55-
#[cfg(not(target_os = "windows"))]
56-
window: &'a mut platform::Window,
53+
window: platform::Window<'a>,
5754

5855
// so that Window is !Send on all platforms
5956
phantom: PhantomData<*mut ()>,
6057
}
6158

6259
impl<'a> Window<'a> {
6360
#[cfg(target_os = "windows")]
64-
pub(crate) fn new(window: &'a mut platform::Window<'a>) -> Window<'a> {
61+
pub(crate) fn new(window: platform::Window<'a>) -> Window<'a> {
6562
Window { window, phantom: PhantomData }
6663
}
6764

6865
#[cfg(not(target_os = "windows"))]
69-
pub(crate) fn new(window: &mut platform::Window) -> Window {
66+
pub(crate) fn new(window: platform::Window) -> Window {
7067
Window { window, phantom: PhantomData }
7168
}
7269

0 commit comments

Comments
 (0)