From c86b0daf7f0883411f0968fe404306e14a0caedd Mon Sep 17 00:00:00 2001 From: Mads Marquart Date: Sun, 14 Jan 2024 04:44:10 +0100 Subject: [PATCH] macOS: Remove unnecessary Mutex in window state (#3390) --- src/platform_impl/macos/window.rs | 278 ++++++++------------- src/platform_impl/macos/window_delegate.rs | 84 +++---- 2 files changed, 130 insertions(+), 232 deletions(-) diff --git a/src/platform_impl/macos/window.rs b/src/platform_impl/macos/window.rs index c1b888fe..c95dffa8 100644 --- a/src/platform_impl/macos/window.rs +++ b/src/platform_impl/macos/window.rs @@ -1,9 +1,8 @@ #![allow(clippy::unnecessary_cast)] +use std::cell::{Cell, RefCell}; use std::collections::VecDeque; use std::f64; -use std::ops; -use std::sync::{Mutex, MutexGuard}; use core_graphics::display::{CGDisplay, CGPoint}; use icrate::AppKit::{ @@ -23,7 +22,6 @@ use icrate::Foundation::{ CGFloat, MainThreadBound, MainThreadMarker, NSArray, NSCopying, NSObject, NSPoint, NSRect, NSSize, NSString, }; -use log::trace; use objc2::rc::{autoreleasepool, Id}; use objc2::{declare_class, msg_send, msg_send_id, mutability, sel, ClassType, DeclaredClass}; @@ -185,7 +183,7 @@ declare_class!( } impl DeclaredClass for WinitWindow { - type Ivars = Mutex; + type Ivars = State; } unsafe impl WinitWindow { @@ -204,81 +202,36 @@ declare_class!( ); #[derive(Debug, Default)] -pub struct SharedState { - pub resizable: bool, +pub struct State { + resizable: Cell, /// This field tracks the current fullscreen state of the window /// (as seen by `WindowDelegate`). - pub(crate) fullscreen: Option, + pub(super) fullscreen: RefCell>, // This is true between windowWillEnterFullScreen and windowDidEnterFullScreen // or windowWillExitFullScreen and windowDidExitFullScreen. // We must not toggle fullscreen when this is true. - pub in_fullscreen_transition: bool, + pub(super) in_fullscreen_transition: Cell, // If it is attempted to toggle fullscreen when in_fullscreen_transition is true, // Set target_fullscreen and do after fullscreen transition is end. - pub(crate) target_fullscreen: Option>, - pub maximized: bool, - pub standard_frame: Option, - pub(crate) is_simple_fullscreen: bool, - pub saved_style: Option, + pub(crate) target_fullscreen: RefCell>>, + pub(super) maximized: Cell, + standard_frame: Cell>, + pub(crate) is_simple_fullscreen: Cell, + pub(super) saved_style: Cell>, /// Presentation options saved before entering `set_simple_fullscreen`, and /// restored upon exiting it. Also used when transitioning from Borderless to /// Exclusive fullscreen in `set_fullscreen` because we need to disable the menu /// bar in exclusive fullscreen but want to restore the original options when /// transitioning back to borderless fullscreen. - save_presentation_opts: Option, - pub current_theme: Option, + save_presentation_opts: Cell>, + pub(super) current_theme: Cell>, - /// The current resize incerments for the window content. - pub(crate) resize_increments: NSSize, + /// The current resize increments for the window content. + pub(crate) resize_increments: Cell, /// The state of the `Option` as `Alt`. - pub(crate) option_as_alt: OptionAsAlt, - - decorations: bool, -} - -impl SharedState { - pub fn saved_standard_frame(&self) -> NSRect { - self.standard_frame - .unwrap_or_else(|| NSRect::new(NSPoint::new(50.0, 50.0), NSSize::new(800.0, 600.0))) - } -} - -pub(crate) struct SharedStateMutexGuard<'a> { - guard: MutexGuard<'a, SharedState>, - called_from_fn: &'static str, -} - -impl<'a> SharedStateMutexGuard<'a> { - #[inline] - fn new(guard: MutexGuard<'a, SharedState>, called_from_fn: &'static str) -> Self { - trace!("Locked shared state in `{}`", called_from_fn); - Self { - guard, - called_from_fn, - } - } -} - -impl ops::Deref for SharedStateMutexGuard<'_> { - type Target = SharedState; - #[inline] - fn deref(&self) -> &Self::Target { - self.guard.deref() - } -} - -impl ops::DerefMut for SharedStateMutexGuard<'_> { - #[inline] - fn deref_mut(&mut self) -> &mut Self::Target { - self.guard.deref_mut() - } -} - -impl Drop for SharedStateMutexGuard<'_> { - #[inline] - fn drop(&mut self) { - trace!("Unlocked shared state in `{}`", self.called_from_fn); - } + option_as_alt: Cell, + /// Whether the window is showing decorations. + decorations: Cell, } impl WinitWindow { @@ -360,14 +313,12 @@ impl WinitWindow { masks |= NSWindowStyleMaskFullSizeContentView; } - let state = SharedState { - resizable: attrs.resizable, - maximized: attrs.maximized, - decorations: attrs.decorations, + let this = mtm.alloc().set_ivars(State { + resizable: Cell::new(attrs.resizable), + maximized: Cell::new(attrs.maximized), + decorations: Cell::new(attrs.decorations), ..Default::default() - }; - - let this = mtm.alloc().set_ivars(Mutex::new(state)); + }); let this: Option> = unsafe { msg_send_id![ super(this), @@ -394,7 +345,7 @@ impl WinitWindow { _ => NSSize::new(1., 1.), }; - this.lock_shared_state("init").resize_increments = resize_increments; + this.ivars().resize_increments.set(resize_increments); this.setTitle(&NSString::from_str(&attrs.title)); this.setAcceptsMouseMovedEvents(true); @@ -517,13 +468,10 @@ impl WinitWindow { match attrs.preferred_theme { Some(theme) => { - set_ns_theme(Some(theme), mtm); - let mut state = this.lock_shared_state("WinitWindow::new"); - state.current_theme = Some(theme); + this.ivars().current_theme.set(Some(theme)); } None => { - let mut state = this.lock_shared_state("WinitWindow::new"); - state.current_theme = Some(get_ns_theme(mtm)); + this.ivars().current_theme.set(Some(get_ns_theme(mtm))); } } @@ -563,14 +511,6 @@ impl WinitWindow { unsafe { Id::cast(self.contentView().unwrap()) } } - #[track_caller] - pub(crate) fn lock_shared_state( - &self, - called_from_fn: &'static str, - ) -> SharedStateMutexGuard<'_> { - SharedStateMutexGuard::new(self.ivars().lock().unwrap(), called_from_fn) - } - fn set_style_mask(&self, mask: NSWindowStyleMask) { self.setStyleMask(mask); // If we don't do this, key handling will break @@ -708,9 +648,7 @@ impl WinitWindow { } pub fn resize_increments(&self) -> Option> { - let increments = self - .lock_shared_state("set_resize_increments") - .resize_increments; + let increments = self.ivars().resize_increments.get(); let (w, h) = (increments.width, increments.height); if w > 1.0 || h > 1.0 { Some(LogicalSize::new(w, h).to_physical(self.scale_factor())) @@ -721,13 +659,14 @@ impl WinitWindow { pub fn set_resize_increments(&self, increments: Option) { // XXX the resize increments are only used during live resizes. - let mut shared_state_lock = self.lock_shared_state("set_resize_increments"); - shared_state_lock.resize_increments = increments - .map(|increments| { - let logical = increments.to_logical::(self.scale_factor()); - NSSize::new(logical.width.max(1.0), logical.height.max(1.0)) - }) - .unwrap_or_else(|| NSSize::new(1.0, 1.0)); + self.ivars().resize_increments.set( + increments + .map(|increments| { + let logical = increments.to_logical::(self.scale_factor()); + NSSize::new(logical.width.max(1.0), logical.height.max(1.0)) + }) + .unwrap_or_else(|| NSSize::new(1.0, 1.0)), + ); } pub(crate) fn set_resize_increments_inner(&self, size: NSSize) { @@ -740,11 +679,8 @@ impl WinitWindow { #[inline] pub fn set_resizable(&self, resizable: bool) { - let fullscreen = { - let mut shared_state_lock = self.lock_shared_state("set_resizable"); - shared_state_lock.resizable = resizable; - shared_state_lock.fullscreen.is_some() - }; + self.ivars().resizable.set(resizable); + let fullscreen = self.ivars().fullscreen.borrow().is_some(); if !fullscreen { let mut mask = self.styleMask(); if resizable { @@ -917,12 +853,13 @@ impl WinitWindow { is_zoomed } - fn saved_style(&self, shared_state: &mut SharedState) -> NSWindowStyleMask { - let base_mask = shared_state + fn saved_style(&self) -> NSWindowStyleMask { + let base_mask = self + .ivars() .saved_style .take() .unwrap_or_else(|| self.styleMask()); - if shared_state.resizable { + if self.ivars().resizable.get() { base_mask | NSWindowStyleMaskResizable } else { base_mask & !NSWindowStyleMaskResizable @@ -933,14 +870,10 @@ impl WinitWindow { /// user clicking on the green fullscreen button or programmatically by /// `toggleFullScreen:` pub(crate) fn restore_state_from_fullscreen(&self) { - let mut shared_state_lock = self.lock_shared_state("restore_state_from_fullscreen"); + self.ivars().fullscreen.replace(None); - shared_state_lock.fullscreen = None; - - let maximized = shared_state_lock.maximized; - let mask = self.saved_style(&mut shared_state_lock); - - drop(shared_state_lock); + let maximized = self.ivars().maximized.get(); + let mask = self.saved_style(); self.set_style_mask(mask); self.set_maximized(maximized); @@ -973,21 +906,19 @@ impl WinitWindow { return; }; - let mut shared_state = self.lock_shared_state("set_maximized"); // Save the standard frame sized if it is not zoomed if !is_zoomed { - shared_state.standard_frame = Some(self.frame()); + self.ivars().standard_frame.set(Some(self.frame())); } - shared_state.maximized = maximized; + self.ivars().maximized.set(maximized); - if shared_state.fullscreen.is_some() { + if self.ivars().fullscreen.borrow().is_some() { // Handle it in window_did_exit_fullscreen return; } if mask_contains(self.styleMask(), NSWindowStyleMaskResizable) { - drop(shared_state); // Just use the native zoom if resizable self.zoom(None); } else { @@ -996,17 +927,18 @@ impl WinitWindow { let screen = NSScreen::mainScreen(mtm).expect("no screen found"); screen.visibleFrame() } else { - shared_state.saved_standard_frame() + self.ivars() + .standard_frame + .get() + .unwrap_or(DEFAULT_STANDARD_FRAME) }; - drop(shared_state); self.setFrame_display(new_rect, false); } } #[inline] pub(crate) fn fullscreen(&self) -> Option { - let shared_state_lock = self.lock_shared_state("fullscreen"); - shared_state_lock.fullscreen.clone() + self.ivars().fullscreen.borrow().clone() } #[inline] @@ -1019,21 +951,19 @@ impl WinitWindow { let mtm = MainThreadMarker::from(self); let app = NSApplication::sharedApplication(mtm); - let mut shared_state_lock = self.lock_shared_state("set_fullscreen"); - if shared_state_lock.is_simple_fullscreen { + if self.ivars().is_simple_fullscreen.get() { return; } - if shared_state_lock.in_fullscreen_transition { + if self.ivars().in_fullscreen_transition.get() { // We can't set fullscreen here. // Set fullscreen after transition. - shared_state_lock.target_fullscreen = Some(fullscreen); + self.ivars().target_fullscreen.replace(Some(fullscreen)); return; } - let old_fullscreen = shared_state_lock.fullscreen.clone(); + let old_fullscreen = self.ivars().fullscreen.borrow().clone(); if fullscreen == old_fullscreen { return; } - drop(shared_state_lock); // If the fullscreen is on a different monitor, we must move the window // to that monitor before we toggle fullscreen (as `toggleFullScreen` @@ -1077,8 +1007,9 @@ impl WinitWindow { let mut fade_token = ffi::kCGDisplayFadeReservationInvalidToken; if matches!(old_fullscreen, Some(Fullscreen::Borderless(_))) { - let mut shared_state_lock = self.lock_shared_state("set_fullscreen"); - shared_state_lock.save_presentation_opts = Some(app.presentationOptions()); + self.ivars() + .save_presentation_opts + .replace(Some(app.presentationOptions())); } unsafe { @@ -1128,7 +1059,7 @@ impl WinitWindow { } } - self.lock_shared_state("set_fullscreen").fullscreen = fullscreen.clone(); + self.ivars().fullscreen.replace(fullscreen.clone()); fn toggle_fullscreen(window: &WinitWindow) { // Window level must be restored from `CGShieldingWindowLevel() @@ -1147,7 +1078,7 @@ impl WinitWindow { let required = NSWindowStyleMaskTitled | NSWindowStyleMaskResizable; if !mask_contains(curr_mask, required) { self.set_style_mask(required); - self.lock_shared_state("set_fullscreen").saved_style = Some(curr_mask); + self.ivars().saved_style.set(Some(curr_mask)); } toggle_fullscreen(self); } @@ -1174,8 +1105,9 @@ impl WinitWindow { // of the menu bar, and this looks broken, so we must make sure // that the menu bar is disabled. This is done in the window // delegate in `window:willUseFullScreenPresentationOptions:`. - self.lock_shared_state("set_fullscreen") - .save_presentation_opts = Some(app.presentationOptions()); + self.ivars() + .save_presentation_opts + .set(Some(app.presentationOptions())); let presentation_options = NSApplicationPresentationFullScreen | NSApplicationPresentationHideDock @@ -1186,14 +1118,11 @@ impl WinitWindow { self.setLevel(window_level); } (Some(Fullscreen::Exclusive(ref video_mode)), Some(Fullscreen::Borderless(_))) => { - let presentation_options = self - .lock_shared_state("set_fullscreen") - .save_presentation_opts - .unwrap_or( - NSApplicationPresentationFullScreen - | NSApplicationPresentationAutoHideDock - | NSApplicationPresentationAutoHideMenuBar, - ); + let presentation_options = self.ivars().save_presentation_opts.get().unwrap_or( + NSApplicationPresentationFullScreen + | NSApplicationPresentationAutoHideDock + | NSApplicationPresentationAutoHideMenuBar, + ); app.setPresentationOptions(presentation_options); unsafe { @@ -1214,17 +1143,14 @@ impl WinitWindow { #[inline] pub fn set_decorations(&self, decorations: bool) { - let mut shared_state_lock = self.lock_shared_state("set_decorations"); - if decorations == shared_state_lock.decorations { + if decorations == self.ivars().decorations.get() { return; } - shared_state_lock.decorations = decorations; + self.ivars().decorations.set(decorations); - let fullscreen = shared_state_lock.fullscreen.is_some(); - let resizable = shared_state_lock.resizable; - - drop(shared_state_lock); + let fullscreen = self.ivars().fullscreen.borrow().is_some(); + let resizable = self.ivars().resizable.get(); // If we're in fullscreen mode, we wait to apply decoration changes // until we're in `window_did_exit_fullscreen`. @@ -1251,7 +1177,7 @@ impl WinitWindow { #[inline] pub fn is_decorated(&self) -> bool { - self.lock_shared_state("is_decorated").decorations + self.ivars().decorations.get() } #[inline] @@ -1389,7 +1315,7 @@ impl WinitWindow { #[inline] pub fn theme(&self) -> Option { - self.lock_shared_state("theme").current_theme + self.ivars().current_theme.get() } #[inline] @@ -1400,8 +1326,9 @@ impl WinitWindow { pub fn set_theme(&self, theme: Option) { let mtm = MainThreadMarker::from(self); set_ns_theme(theme, mtm); - self.lock_shared_state("set_theme").current_theme = - theme.or_else(|| Some(get_ns_theme(mtm))); + self.ivars() + .current_theme + .set(theme.or_else(|| Some(get_ns_theme(mtm)))); } #[inline] @@ -1426,18 +1353,16 @@ impl WinitWindow { impl WindowExtMacOS for WinitWindow { #[inline] fn simple_fullscreen(&self) -> bool { - self.lock_shared_state("simple_fullscreen") - .is_simple_fullscreen + self.ivars().is_simple_fullscreen.get() } #[inline] fn set_simple_fullscreen(&self, fullscreen: bool) -> bool { let mtm = MainThreadMarker::from(self); - let mut shared_state_lock = self.lock_shared_state("set_simple_fullscreen"); let app = NSApplication::sharedApplication(mtm); - let is_native_fullscreen = shared_state_lock.fullscreen.is_some(); - let is_simple_fullscreen = shared_state_lock.is_simple_fullscreen; + let is_native_fullscreen = self.ivars().fullscreen.borrow().is_some(); + let is_simple_fullscreen = self.ivars().is_simple_fullscreen.get(); // Do nothing if native fullscreen is active. if is_native_fullscreen @@ -1450,16 +1375,16 @@ impl WindowExtMacOS for WinitWindow { if fullscreen { // Remember the original window's settings // Exclude title bar - shared_state_lock.standard_frame = Some(self.contentRectForFrameRect(self.frame())); - shared_state_lock.saved_style = Some(self.styleMask()); - shared_state_lock.save_presentation_opts = Some(app.presentationOptions()); + self.ivars() + .standard_frame + .set(Some(self.contentRectForFrameRect(self.frame()))); + self.ivars().saved_style.set(Some(self.styleMask())); + self.ivars() + .save_presentation_opts + .set(Some(app.presentationOptions())); // Tell our window's state that we're in fullscreen - shared_state_lock.is_simple_fullscreen = true; - - // Drop shared state lock before calling app.setPresentationOptions, because - // it will call our windowDidChangeScreen listener which reacquires the lock - drop(shared_state_lock); + self.ivars().is_simple_fullscreen.set(true); // Simulate pre-Lion fullscreen by hiding the dock and menu bar let presentation_options = @@ -1480,16 +1405,16 @@ impl WindowExtMacOS for WinitWindow { true } else { - let new_mask = self.saved_style(&mut shared_state_lock); + let new_mask = self.saved_style(); self.set_style_mask(new_mask); - shared_state_lock.is_simple_fullscreen = false; + self.ivars().is_simple_fullscreen.set(false); - let save_presentation_opts = shared_state_lock.save_presentation_opts; - let frame = shared_state_lock.saved_standard_frame(); - - // Drop shared state lock before calling app.setPresentationOptions, because - // it will call our windowDidChangeScreen listener which reacquires the lock - drop(shared_state_lock); + let save_presentation_opts = self.ivars().save_presentation_opts.get(); + let frame = self + .ivars() + .standard_frame + .get() + .unwrap_or(DEFAULT_STANDARD_FRAME); if let Some(presentation_opts) = save_presentation_opts { app.setPresentationOptions(presentation_opts); @@ -1559,13 +1484,11 @@ impl WindowExtMacOS for WinitWindow { } fn set_option_as_alt(&self, option_as_alt: OptionAsAlt) { - let mut shared_state_lock = self.lock_shared_state("set_option_as_alt"); - shared_state_lock.option_as_alt = option_as_alt; + self.ivars().option_as_alt.set(option_as_alt); } fn option_as_alt(&self) -> OptionAsAlt { - let shared_state_lock = self.lock_shared_state("option_as_alt"); - shared_state_lock.option_as_alt + self.ivars().option_as_alt.get() } } @@ -1606,3 +1529,6 @@ fn set_ns_theme(theme: Option, mtm: MainThreadMarker) { app.setAppearance(appearance.as_ref().map(|a| a.as_ref())); } } + +const DEFAULT_STANDARD_FRAME: NSRect = + NSRect::new(NSPoint::new(50.0, 50.0), NSSize::new(800.0, 600.0)); diff --git a/src/platform_impl/macos/window_delegate.rs b/src/platform_impl/macos/window_delegate.rs index 01bcb1a4..fd89a8bd 100644 --- a/src/platform_impl/macos/window_delegate.rs +++ b/src/platform_impl/macos/window_delegate.rs @@ -90,11 +90,7 @@ declare_class!( fn window_will_start_live_resize(&self, _: Option<&AnyObject>) { trace_scope!("windowWillStartLiveResize:"); - let increments = self - .ivars() - .window - .lock_shared_state("window_will_enter_fullscreen") - .resize_increments; + let increments = self.ivars().window.ivars().resize_increments.get(); self.ivars().window.set_resize_increments_inner(increments); } @@ -147,13 +143,10 @@ declare_class!( fn window_will_enter_fullscreen(&self, _: Option<&AnyObject>) { trace_scope!("windowWillEnterFullScreen:"); - let mut shared_state = self - .ivars() - .window - .lock_shared_state("window_will_enter_fullscreen"); - shared_state.maximized = self.ivars().window.is_zoomed(); - let fullscreen = shared_state.fullscreen.as_ref(); - match fullscreen { + let window_ivars = self.ivars().window.ivars(); + window_ivars.maximized.set(self.ivars().window.is_zoomed()); + let mut fullscreen = window_ivars.fullscreen.borrow_mut(); + match &*fullscreen { // Exclusive mode sets the state in `set_fullscreen` as the user // can't enter exclusive mode by other means (like the // fullscreen button on the window decorations) @@ -166,10 +159,10 @@ declare_class!( // on the green fullscreen button. Update state! None => { let current_monitor = self.ivars().window.current_monitor_inner(); - shared_state.fullscreen = Some(Fullscreen::Borderless(current_monitor)) + *fullscreen = Some(Fullscreen::Borderless(current_monitor)); } } - shared_state.in_fullscreen_transition = true; + window_ivars.in_fullscreen_transition.set(true); } /// Invoked when before exit fullscreen @@ -177,11 +170,11 @@ declare_class!( fn window_will_exit_fullscreen(&self, _: Option<&AnyObject>) { trace_scope!("windowWillExitFullScreen:"); - let mut shared_state = self - .ivars() + self.ivars() .window - .lock_shared_state("window_will_exit_fullscreen"); - shared_state.in_fullscreen_transition = true; + .ivars() + .in_fullscreen_transition + .set(true); } #[method(window:willUseFullScreenPresentationOptions:)] @@ -200,11 +193,8 @@ declare_class!( // we don't, for consistency. If we do, it should be documented that the // user-provided options are ignored in exclusive fullscreen. let mut options = proposed_options; - let shared_state = self - .ivars() - .window - .lock_shared_state("window_will_use_fullscreen_presentation_options"); - if let Some(Fullscreen::Exclusive(_)) = shared_state.fullscreen { + let fullscreen = self.ivars().window.ivars().fullscreen.borrow(); + if let Some(Fullscreen::Exclusive(_)) = &*fullscreen { options = NSApplicationPresentationFullScreen | NSApplicationPresentationHideDock | NSApplicationPresentationHideMenuBar; @@ -218,14 +208,9 @@ declare_class!( fn window_did_enter_fullscreen(&self, _: Option<&AnyObject>) { trace_scope!("windowDidEnterFullScreen:"); self.ivars().initial_fullscreen.set(false); - let mut shared_state = self - .ivars() - .window - .lock_shared_state("window_did_enter_fullscreen"); - shared_state.in_fullscreen_transition = false; - let target_fullscreen = shared_state.target_fullscreen.take(); - drop(shared_state); - if let Some(target_fullscreen) = target_fullscreen { + let window_ivars = self.ivars().window.ivars(); + window_ivars.in_fullscreen_transition.set(false); + if let Some(target_fullscreen) = window_ivars.target_fullscreen.take() { self.ivars().window.set_fullscreen(target_fullscreen); } } @@ -236,14 +221,9 @@ declare_class!( trace_scope!("windowDidExitFullScreen:"); self.ivars().window.restore_state_from_fullscreen(); - let mut shared_state = self - .ivars() - .window - .lock_shared_state("window_did_exit_fullscreen"); - shared_state.in_fullscreen_transition = false; - let target_fullscreen = shared_state.target_fullscreen.take(); - drop(shared_state); - if let Some(target_fullscreen) = target_fullscreen { + let window_ivars = self.ivars().window.ivars(); + window_ivars.in_fullscreen_transition.set(false); + if let Some(target_fullscreen) = window_ivars.target_fullscreen.take() { self.ivars().window.set_fullscreen(target_fullscreen); } } @@ -267,12 +247,9 @@ declare_class!( #[method(windowDidFailToEnterFullScreen:)] fn window_did_fail_to_enter_fullscreen(&self, _: Option<&AnyObject>) { trace_scope!("windowDidFailToEnterFullScreen:"); - let mut shared_state = self - .ivars() - .window - .lock_shared_state("window_did_fail_to_enter_fullscreen"); - shared_state.in_fullscreen_transition = false; - shared_state.target_fullscreen = None; + let window_ivars = self.ivars().window.ivars(); + window_ivars.in_fullscreen_transition.set(false); + window_ivars.target_fullscreen.replace(None); if self.ivars().initial_fullscreen.get() { #[allow(clippy::let_unit_value)] unsafe { @@ -300,11 +277,7 @@ declare_class!( #[method(windowDidChangeScreen:)] fn window_did_change_screen(&self, _: Option<&AnyObject>) { trace_scope!("windowDidChangeScreen:"); - let is_simple_fullscreen = self - .ivars() - .window - .lock_shared_state("window_did_change_screen") - .is_simple_fullscreen; + let is_simple_fullscreen = self.ivars().window.ivars().is_simple_fullscreen.get(); if is_simple_fullscreen { if let Some(screen) = self.ivars().window.screen() { self.ivars().window.setFrame_display(screen.frame(), true); @@ -396,14 +369,13 @@ declare_class!( fn effective_appearance_did_changed_on_main_thread(&self, _: Option<&AnyObject>) { let mtm = MainThreadMarker::from(self); let theme = get_ns_theme(mtm); - let mut shared_state = self + let old_theme = self .ivars() .window - .lock_shared_state("effective_appearance_did_change"); - let current_theme = shared_state.current_theme; - shared_state.current_theme = Some(theme); - drop(shared_state); - if current_theme != Some(theme) { + .ivars() + .current_theme + .replace(Some(theme)); + if old_theme != Some(theme) { self.queue_event(WindowEvent::ThemeChanged(theme)); } }