mirror of
https://github.com/italicsjenga/winit-sonoma-fix.git
synced 2025-02-02 14:56:34 +11:00
macOS RAII trace guards (#2150)
* Add TraceGuard to make tracing simpler * Add SharedStateMutexGuard to make tracing simpler * Add trace_scope macro * Add missing let binding in trace_scope!
This commit is contained in:
parent
51bb6b751e
commit
9229e2d88b
7 changed files with 176 additions and 135 deletions
|
@ -75,7 +75,6 @@ extern "C" fn dealloc(this: &Object, _: Sel) {
|
|||
}
|
||||
|
||||
extern "C" fn did_finish_launching(this: &Object, _: Sel, _: id) {
|
||||
trace!("Triggered `applicationDidFinishLaunching`");
|
||||
trace_scope!("applicationDidFinishLaunching:");
|
||||
AppState::launched(this);
|
||||
trace!("Completed `applicationDidFinishLaunching`");
|
||||
}
|
||||
|
|
|
@ -1,5 +1,8 @@
|
|||
#![cfg(target_os = "macos")]
|
||||
|
||||
#[macro_use]
|
||||
mod util;
|
||||
|
||||
mod app;
|
||||
mod app_delegate;
|
||||
mod app_state;
|
||||
|
@ -9,7 +12,6 @@ mod ffi;
|
|||
mod menu;
|
||||
mod monitor;
|
||||
mod observer;
|
||||
mod util;
|
||||
mod view;
|
||||
mod window;
|
||||
mod window_delegate;
|
||||
|
|
|
@ -14,7 +14,11 @@ use objc::runtime::{BOOL, NO};
|
|||
|
||||
use crate::{
|
||||
dpi::LogicalSize,
|
||||
platform_impl::platform::{ffi, util::IdRef, window::SharedState},
|
||||
platform_impl::platform::{
|
||||
ffi,
|
||||
util::IdRef,
|
||||
window::{SharedState, SharedStateMutexGuard},
|
||||
},
|
||||
};
|
||||
|
||||
// Unsafe wrapper type that allows us to dispatch things that aren't Send.
|
||||
|
@ -111,10 +115,11 @@ pub unsafe fn toggle_full_screen_async(
|
|||
if !curr_mask.contains(required) {
|
||||
set_style_mask(*ns_window, *ns_view, required);
|
||||
if let Some(shared_state) = shared_state.upgrade() {
|
||||
trace!("Locked shared state in `toggle_full_screen_callback`");
|
||||
let mut shared_state_lock = shared_state.lock().unwrap();
|
||||
let mut shared_state_lock = SharedStateMutexGuard::new(
|
||||
shared_state.lock().unwrap(),
|
||||
"toggle_full_screen_callback",
|
||||
);
|
||||
(*shared_state_lock).saved_style = Some(curr_mask);
|
||||
trace!("Unlocked shared state in `toggle_full_screen_callback`");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -144,8 +149,8 @@ pub unsafe fn set_maximized_async(
|
|||
let shared_state = MainThreadSafe(shared_state);
|
||||
Queue::main().exec_async(move || {
|
||||
if let Some(shared_state) = shared_state.upgrade() {
|
||||
trace!("Locked shared state in `set_maximized`");
|
||||
let mut shared_state_lock = shared_state.lock().unwrap();
|
||||
let mut shared_state_lock =
|
||||
SharedStateMutexGuard::new(shared_state.lock().unwrap(), "set_maximized");
|
||||
|
||||
// Save the standard frame sized if it is not zoomed
|
||||
if !is_zoomed {
|
||||
|
@ -171,8 +176,6 @@ pub unsafe fn set_maximized_async(
|
|||
};
|
||||
ns_window.setFrame_display_(new_rect, NO);
|
||||
}
|
||||
|
||||
trace!("Unlocked shared state in `set_maximized`");
|
||||
}
|
||||
});
|
||||
}
|
||||
|
|
|
@ -11,7 +11,7 @@ use cocoa::{
|
|||
foundation::{NSPoint, NSRect, NSString, NSUInteger},
|
||||
};
|
||||
use core_graphics::display::CGDisplay;
|
||||
use objc::runtime::{Class, Object, Sel, BOOL, YES};
|
||||
use objc::runtime::{Class, Object};
|
||||
|
||||
use crate::dpi::LogicalPosition;
|
||||
use crate::platform_impl::platform::ffi;
|
||||
|
@ -79,6 +79,35 @@ impl Clone for IdRef {
|
|||
}
|
||||
}
|
||||
|
||||
macro_rules! trace_scope {
|
||||
($s:literal) => {
|
||||
let _crate = $crate::platform_impl::platform::util::TraceGuard::new(module_path!(), $s);
|
||||
};
|
||||
}
|
||||
|
||||
pub(crate) struct TraceGuard {
|
||||
module_path: &'static str,
|
||||
called_from_fn: &'static str,
|
||||
}
|
||||
|
||||
impl TraceGuard {
|
||||
#[inline]
|
||||
pub(crate) fn new(module_path: &'static str, called_from_fn: &'static str) -> Self {
|
||||
trace!(target: module_path, "Triggered `{}`", called_from_fn);
|
||||
Self {
|
||||
module_path,
|
||||
called_from_fn,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Drop for TraceGuard {
|
||||
#[inline]
|
||||
fn drop(&mut self) {
|
||||
trace!(target: self.module_path, "Completed `{}`", self.called_from_fn);
|
||||
}
|
||||
}
|
||||
|
||||
// For consistency with other platforms, this will...
|
||||
// 1. translate the bottom-left window corner into the top-left window corner
|
||||
// 2. translate the coordinate from a bottom-left origin coordinate system to a top-left one
|
||||
|
@ -129,10 +158,6 @@ pub unsafe fn open_emoji_picker() {
|
|||
let () = msg_send![NSApp(), orderFrontCharacterPalette: nil];
|
||||
}
|
||||
|
||||
pub extern "C" fn yes(_: &Object, _: Sel) -> BOOL {
|
||||
YES
|
||||
}
|
||||
|
||||
pub unsafe fn toggle_style_mask(window: id, view: id, mask: NSWindowStyleMask, on: bool) {
|
||||
use cocoa::appkit::NSWindow;
|
||||
|
||||
|
|
|
@ -301,7 +301,7 @@ extern "C" fn init_with_winit(this: &Object, _sel: Sel, state: *mut c_void) -> i
|
|||
}
|
||||
|
||||
extern "C" fn view_did_move_to_window(this: &Object, _sel: Sel) {
|
||||
trace!("Triggered `viewDidMoveToWindow`");
|
||||
trace_scope!("viewDidMoveToWindow");
|
||||
unsafe {
|
||||
let state_ptr: *mut c_void = *this.get_ivar("winitState");
|
||||
let state = &mut *(state_ptr as *mut ViewState);
|
||||
|
@ -319,10 +319,10 @@ extern "C" fn view_did_move_to_window(this: &Object, _sel: Sel) {
|
|||
];
|
||||
state.tracking_rect = Some(tracking_rect);
|
||||
}
|
||||
trace!("Completed `viewDidMoveToWindow`");
|
||||
}
|
||||
|
||||
extern "C" fn frame_did_change(this: &Object, _sel: Sel, _event: id) {
|
||||
trace_scope!("frameDidChange:");
|
||||
unsafe {
|
||||
let state_ptr: *mut c_void = *this.get_ivar("winitState");
|
||||
let state = &mut *(state_ptr as *mut ViewState);
|
||||
|
@ -344,6 +344,7 @@ extern "C" fn frame_did_change(this: &Object, _sel: Sel, _event: id) {
|
|||
}
|
||||
|
||||
extern "C" fn draw_rect(this: &Object, _sel: Sel, rect: NSRect) {
|
||||
trace_scope!("drawRect:");
|
||||
unsafe {
|
||||
let state_ptr: *mut c_void = *this.get_ivar("winitState");
|
||||
let state = &mut *(state_ptr as *mut ViewState);
|
||||
|
@ -356,6 +357,7 @@ extern "C" fn draw_rect(this: &Object, _sel: Sel, rect: NSRect) {
|
|||
}
|
||||
|
||||
extern "C" fn accepts_first_responder(_this: &Object, _sel: Sel) -> BOOL {
|
||||
trace_scope!("acceptsFirstResponder");
|
||||
YES
|
||||
}
|
||||
|
||||
|
@ -363,10 +365,12 @@ extern "C" fn accepts_first_responder(_this: &Object, _sel: Sel) -> BOOL {
|
|||
// IMKInputSession [0x7fc573576ff0 presentFunctionRowItemTextInputViewWithEndpoint:completionHandler:] : [self textInputContext]=0x7fc573558e10 *NO* NSRemoteViewController to client, NSError=Error Domain=NSCocoaErrorDomain Code=4099 "The connection from pid 0 was invalidated from this process." UserInfo={NSDebugDescription=The connection from pid 0 was invalidated from this process.}, com.apple.inputmethod.EmojiFunctionRowItem
|
||||
// TODO: Add an API extension for using `NSTouchBar`
|
||||
extern "C" fn touch_bar(_this: &Object, _sel: Sel) -> BOOL {
|
||||
trace_scope!("touchBar");
|
||||
NO
|
||||
}
|
||||
|
||||
extern "C" fn reset_cursor_rects(this: &Object, _sel: Sel) {
|
||||
trace_scope!("resetCursorRects");
|
||||
unsafe {
|
||||
let state_ptr: *mut c_void = *this.get_ivar("winitState");
|
||||
let state = &mut *(state_ptr as *mut ViewState);
|
||||
|
@ -386,20 +390,18 @@ extern "C" fn reset_cursor_rects(this: &Object, _sel: Sel) {
|
|||
}
|
||||
|
||||
extern "C" fn has_marked_text(this: &Object, _sel: Sel) -> BOOL {
|
||||
trace_scope!("hasMarkedText");
|
||||
unsafe {
|
||||
trace!("Triggered `hasMarkedText`");
|
||||
let marked_text: id = *this.get_ivar("markedText");
|
||||
trace!("Completed `hasMarkedText`");
|
||||
(marked_text.length() > 0) as BOOL
|
||||
}
|
||||
}
|
||||
|
||||
extern "C" fn marked_range(this: &Object, _sel: Sel) -> NSRange {
|
||||
trace_scope!("markedRange");
|
||||
unsafe {
|
||||
trace!("Triggered `markedRange`");
|
||||
let marked_text: id = *this.get_ivar("markedText");
|
||||
let length = marked_text.length();
|
||||
trace!("Completed `markedRange`");
|
||||
if length > 0 {
|
||||
NSRange::new(0, length - 1)
|
||||
} else {
|
||||
|
@ -409,8 +411,7 @@ extern "C" fn marked_range(this: &Object, _sel: Sel) -> NSRange {
|
|||
}
|
||||
|
||||
extern "C" fn selected_range(_this: &Object, _sel: Sel) -> NSRange {
|
||||
trace!("Triggered `selectedRange`");
|
||||
trace!("Completed `selectedRange`");
|
||||
trace_scope!("selectedRange");
|
||||
util::EMPTY_RANGE
|
||||
}
|
||||
|
||||
|
@ -421,7 +422,7 @@ extern "C" fn set_marked_text(
|
|||
_selected_range: NSRange,
|
||||
_replacement_range: NSRange,
|
||||
) {
|
||||
trace!("Triggered `setMarkedText`");
|
||||
trace_scope!("setMarkedText:selectedRange:replacementRange:");
|
||||
unsafe {
|
||||
let marked_text_ref: &mut id = this.get_mut_ivar("markedText");
|
||||
let _: () = msg_send![(*marked_text_ref), release];
|
||||
|
@ -434,11 +435,10 @@ extern "C" fn set_marked_text(
|
|||
};
|
||||
*marked_text_ref = marked_text;
|
||||
}
|
||||
trace!("Completed `setMarkedText`");
|
||||
}
|
||||
|
||||
extern "C" fn unmark_text(this: &Object, _sel: Sel) {
|
||||
trace!("Triggered `unmarkText`");
|
||||
trace_scope!("unmarkText");
|
||||
unsafe {
|
||||
let marked_text: id = *this.get_ivar("markedText");
|
||||
let mutable_string = marked_text.mutableString();
|
||||
|
@ -448,12 +448,10 @@ extern "C" fn unmark_text(this: &Object, _sel: Sel) {
|
|||
let input_context: id = msg_send![this, inputContext];
|
||||
let _: () = msg_send![input_context, discardMarkedText];
|
||||
}
|
||||
trace!("Completed `unmarkText`");
|
||||
}
|
||||
|
||||
extern "C" fn valid_attributes_for_marked_text(_this: &Object, _sel: Sel) -> id {
|
||||
trace!("Triggered `validAttributesForMarkedText`");
|
||||
trace!("Completed `validAttributesForMarkedText`");
|
||||
trace_scope!("validAttributesForMarkedText");
|
||||
unsafe { msg_send![class!(NSArray), array] }
|
||||
}
|
||||
|
||||
|
@ -463,14 +461,12 @@ extern "C" fn attributed_substring_for_proposed_range(
|
|||
_range: NSRange,
|
||||
_actual_range: *mut c_void, // *mut NSRange
|
||||
) -> id {
|
||||
trace!("Triggered `attributedSubstringForProposedRange`");
|
||||
trace!("Completed `attributedSubstringForProposedRange`");
|
||||
trace_scope!("attributedSubstringForProposedRange:actualRange:");
|
||||
nil
|
||||
}
|
||||
|
||||
extern "C" fn character_index_for_point(_this: &Object, _sel: Sel, _point: NSPoint) -> NSUInteger {
|
||||
trace!("Triggered `characterIndexForPoint`");
|
||||
trace!("Completed `characterIndexForPoint`");
|
||||
trace_scope!("characterIndexForPoint:");
|
||||
0
|
||||
}
|
||||
|
||||
|
@ -480,8 +476,8 @@ extern "C" fn first_rect_for_character_range(
|
|||
_range: NSRange,
|
||||
_actual_range: *mut c_void, // *mut NSRange
|
||||
) -> NSRect {
|
||||
trace_scope!("firstRectForCharacterRange:actualRange:");
|
||||
unsafe {
|
||||
trace!("Triggered `firstRectForCharacterRange`");
|
||||
let state_ptr: *mut c_void = *this.get_ivar("winitState");
|
||||
let state = &mut *(state_ptr as *mut ViewState);
|
||||
let (x, y) = state.ime_spot.unwrap_or_else(|| {
|
||||
|
@ -493,13 +489,12 @@ extern "C" fn first_rect_for_character_range(
|
|||
let y = util::bottom_left_to_top_left(content_rect);
|
||||
(x, y)
|
||||
});
|
||||
trace!("Completed `firstRectForCharacterRange`");
|
||||
NSRect::new(NSPoint::new(x as _, y as _), NSSize::new(0.0, 0.0))
|
||||
}
|
||||
}
|
||||
|
||||
extern "C" fn insert_text(this: &Object, _sel: Sel, string: id, _replacement_range: NSRange) {
|
||||
trace!("Triggered `insertText`");
|
||||
trace_scope!("insertText:replacementRange:");
|
||||
unsafe {
|
||||
let state_ptr: *mut c_void = *this.get_ivar("winitState");
|
||||
let state = &mut *(state_ptr as *mut ViewState);
|
||||
|
@ -530,11 +525,10 @@ extern "C" fn insert_text(this: &Object, _sel: Sel, string: id, _replacement_ran
|
|||
|
||||
AppState::queue_events(events);
|
||||
}
|
||||
trace!("Completed `insertText`");
|
||||
}
|
||||
|
||||
extern "C" fn do_command_by_selector(this: &Object, _sel: Sel, command: Sel) {
|
||||
trace!("Triggered `doCommandBySelector`");
|
||||
trace_scope!("doCommandBySelector:");
|
||||
// Basically, we're sent this message whenever a keyboard event that doesn't generate a "human readable" character
|
||||
// happens, i.e. newlines, tabs, and Ctrl+C.
|
||||
unsafe {
|
||||
|
@ -567,7 +561,6 @@ extern "C" fn do_command_by_selector(this: &Object, _sel: Sel, command: Sel) {
|
|||
|
||||
AppState::queue_events(events);
|
||||
}
|
||||
trace!("Completed `doCommandBySelector`");
|
||||
}
|
||||
|
||||
fn get_characters(event: id, ignore_modifiers: bool) -> String {
|
||||
|
@ -639,7 +632,7 @@ fn update_potentially_stale_modifiers(state: &mut ViewState, event: id) {
|
|||
}
|
||||
|
||||
extern "C" fn key_down(this: &Object, _sel: Sel, event: id) {
|
||||
trace!("Triggered `keyDown`");
|
||||
trace_scope!("keyDown:");
|
||||
unsafe {
|
||||
let state_ptr: *mut c_void = *this.get_ivar("winitState");
|
||||
let state = &mut *(state_ptr as *mut ViewState);
|
||||
|
@ -694,11 +687,10 @@ extern "C" fn key_down(this: &Object, _sel: Sel, event: id) {
|
|||
let _: () = msg_send![this, interpretKeyEvents: array];
|
||||
}
|
||||
}
|
||||
trace!("Completed `keyDown`");
|
||||
}
|
||||
|
||||
extern "C" fn key_up(this: &Object, _sel: Sel, event: id) {
|
||||
trace!("Triggered `keyUp`");
|
||||
trace_scope!("keyUp:");
|
||||
unsafe {
|
||||
let state_ptr: *mut c_void = *this.get_ivar("winitState");
|
||||
let state = &mut *(state_ptr as *mut ViewState);
|
||||
|
@ -725,11 +717,10 @@ extern "C" fn key_up(this: &Object, _sel: Sel, event: id) {
|
|||
|
||||
AppState::queue_event(EventWrapper::StaticEvent(window_event));
|
||||
}
|
||||
trace!("Completed `keyUp`");
|
||||
}
|
||||
|
||||
extern "C" fn flags_changed(this: &Object, _sel: Sel, event: id) {
|
||||
trace!("Triggered `flagsChanged`");
|
||||
trace_scope!("flagsChanged:");
|
||||
unsafe {
|
||||
let state_ptr: *mut c_void = *this.get_ivar("winitState");
|
||||
let state = &mut *(state_ptr as *mut ViewState);
|
||||
|
@ -786,10 +777,10 @@ extern "C" fn flags_changed(this: &Object, _sel: Sel, event: id) {
|
|||
event: WindowEvent::ModifiersChanged(state.modifiers),
|
||||
}));
|
||||
}
|
||||
trace!("Completed `flagsChanged`");
|
||||
}
|
||||
|
||||
extern "C" fn insert_tab(this: &Object, _sel: Sel, _sender: id) {
|
||||
trace_scope!("insertTab:");
|
||||
unsafe {
|
||||
let window: id = msg_send![this, window];
|
||||
let first_responder: id = msg_send![window, firstResponder];
|
||||
|
@ -801,6 +792,7 @@ extern "C" fn insert_tab(this: &Object, _sel: Sel, _sender: id) {
|
|||
}
|
||||
|
||||
extern "C" fn insert_back_tab(this: &Object, _sel: Sel, _sender: id) {
|
||||
trace_scope!("insertBackTab:");
|
||||
unsafe {
|
||||
let window: id = msg_send![this, window];
|
||||
let first_responder: id = msg_send![window, firstResponder];
|
||||
|
@ -814,7 +806,7 @@ extern "C" fn insert_back_tab(this: &Object, _sel: Sel, _sender: id) {
|
|||
// Allows us to receive Cmd-. (the shortcut for closing a dialog)
|
||||
// https://bugs.eclipse.org/bugs/show_bug.cgi?id=300620#c6
|
||||
extern "C" fn cancel_operation(this: &Object, _sel: Sel, _sender: id) {
|
||||
trace!("Triggered `cancelOperation`");
|
||||
trace_scope!("cancelOperation:");
|
||||
unsafe {
|
||||
let state_ptr: *mut c_void = *this.get_ivar("winitState");
|
||||
let state = &mut *(state_ptr as *mut ViewState);
|
||||
|
@ -844,7 +836,6 @@ extern "C" fn cancel_operation(this: &Object, _sel: Sel, _sender: id) {
|
|||
|
||||
AppState::queue_event(EventWrapper::StaticEvent(window_event));
|
||||
}
|
||||
trace!("Completed `cancelOperation`");
|
||||
}
|
||||
|
||||
fn mouse_click(this: &Object, event: id, button: MouseButton, button_state: ElementState) {
|
||||
|
@ -869,31 +860,37 @@ fn mouse_click(this: &Object, event: id, button: MouseButton, button_state: Elem
|
|||
}
|
||||
|
||||
extern "C" fn mouse_down(this: &Object, _sel: Sel, event: id) {
|
||||
trace_scope!("mouseDown:");
|
||||
mouse_motion(this, event);
|
||||
mouse_click(this, event, MouseButton::Left, ElementState::Pressed);
|
||||
}
|
||||
|
||||
extern "C" fn mouse_up(this: &Object, _sel: Sel, event: id) {
|
||||
trace_scope!("mouseUp:");
|
||||
mouse_motion(this, event);
|
||||
mouse_click(this, event, MouseButton::Left, ElementState::Released);
|
||||
}
|
||||
|
||||
extern "C" fn right_mouse_down(this: &Object, _sel: Sel, event: id) {
|
||||
trace_scope!("rightMouseDown:");
|
||||
mouse_motion(this, event);
|
||||
mouse_click(this, event, MouseButton::Right, ElementState::Pressed);
|
||||
}
|
||||
|
||||
extern "C" fn right_mouse_up(this: &Object, _sel: Sel, event: id) {
|
||||
trace_scope!("rightMouseUp:");
|
||||
mouse_motion(this, event);
|
||||
mouse_click(this, event, MouseButton::Right, ElementState::Released);
|
||||
}
|
||||
|
||||
extern "C" fn other_mouse_down(this: &Object, _sel: Sel, event: id) {
|
||||
trace_scope!("otherMouseDown:");
|
||||
mouse_motion(this, event);
|
||||
mouse_click(this, event, MouseButton::Middle, ElementState::Pressed);
|
||||
}
|
||||
|
||||
extern "C" fn other_mouse_up(this: &Object, _sel: Sel, event: id) {
|
||||
trace_scope!("otherMouseUp:");
|
||||
mouse_motion(this, event);
|
||||
mouse_click(this, event, MouseButton::Middle, ElementState::Released);
|
||||
}
|
||||
|
@ -941,6 +938,8 @@ fn mouse_motion(this: &Object, event: id) {
|
|||
}
|
||||
}
|
||||
|
||||
// No tracing on these because that would be overly verbose
|
||||
|
||||
extern "C" fn mouse_moved(this: &Object, _sel: Sel, event: id) {
|
||||
mouse_motion(this, event);
|
||||
}
|
||||
|
@ -958,7 +957,7 @@ extern "C" fn other_mouse_dragged(this: &Object, _sel: Sel, event: id) {
|
|||
}
|
||||
|
||||
extern "C" fn mouse_entered(this: &Object, _sel: Sel, _event: id) {
|
||||
trace!("Triggered `mouseEntered`");
|
||||
trace_scope!("mouseEntered:");
|
||||
unsafe {
|
||||
let state_ptr: *mut c_void = *this.get_ivar("winitState");
|
||||
let state = &mut *(state_ptr as *mut ViewState);
|
||||
|
@ -972,11 +971,10 @@ extern "C" fn mouse_entered(this: &Object, _sel: Sel, _event: id) {
|
|||
|
||||
AppState::queue_event(EventWrapper::StaticEvent(enter_event));
|
||||
}
|
||||
trace!("Completed `mouseEntered`");
|
||||
}
|
||||
|
||||
extern "C" fn mouse_exited(this: &Object, _sel: Sel, _event: id) {
|
||||
trace!("Triggered `mouseExited`");
|
||||
trace_scope!("mouseExited:");
|
||||
unsafe {
|
||||
let state_ptr: *mut c_void = *this.get_ivar("winitState");
|
||||
let state = &mut *(state_ptr as *mut ViewState);
|
||||
|
@ -990,11 +988,10 @@ extern "C" fn mouse_exited(this: &Object, _sel: Sel, _event: id) {
|
|||
|
||||
AppState::queue_event(EventWrapper::StaticEvent(window_event));
|
||||
}
|
||||
trace!("Completed `mouseExited`");
|
||||
}
|
||||
|
||||
extern "C" fn scroll_wheel(this: &Object, _sel: Sel, event: id) {
|
||||
trace!("Triggered `scrollWheel`");
|
||||
trace_scope!("scrollWheel:");
|
||||
|
||||
mouse_motion(this, event);
|
||||
|
||||
|
@ -1043,11 +1040,10 @@ extern "C" fn scroll_wheel(this: &Object, _sel: Sel, event: id) {
|
|||
AppState::queue_event(EventWrapper::StaticEvent(device_event));
|
||||
AppState::queue_event(EventWrapper::StaticEvent(window_event));
|
||||
}
|
||||
trace!("Completed `scrollWheel`");
|
||||
}
|
||||
|
||||
extern "C" fn pressure_change_with_event(this: &Object, _sel: Sel, event: id) {
|
||||
trace!("Triggered `pressureChangeWithEvent`");
|
||||
trace_scope!("pressureChangeWithEvent:");
|
||||
|
||||
mouse_motion(this, event);
|
||||
|
||||
|
@ -1069,16 +1065,17 @@ extern "C" fn pressure_change_with_event(this: &Object, _sel: Sel, event: id) {
|
|||
|
||||
AppState::queue_event(EventWrapper::StaticEvent(window_event));
|
||||
}
|
||||
trace!("Completed `pressureChangeWithEvent`");
|
||||
}
|
||||
|
||||
// Allows us to receive Ctrl-Tab and Ctrl-Esc.
|
||||
// Note that this *doesn't* help with any missing Cmd inputs.
|
||||
// https://github.com/chromium/chromium/blob/a86a8a6bcfa438fa3ac2eba6f02b3ad1f8e0756f/ui/views/cocoa/bridged_content_view.mm#L816
|
||||
extern "C" fn wants_key_down_for_event(_this: &Object, _sel: Sel, _event: id) -> BOOL {
|
||||
trace_scope!("_wantsKeyDownForEvent:");
|
||||
YES
|
||||
}
|
||||
|
||||
extern "C" fn accepts_first_mouse(_this: &Object, _sel: Sel, _event: id) -> BOOL {
|
||||
trace_scope!("acceptsFirstMouse:");
|
||||
YES
|
||||
}
|
||||
|
|
|
@ -2,11 +2,11 @@ use raw_window_handle::{AppKitHandle, RawWindowHandle};
|
|||
use std::{
|
||||
collections::VecDeque,
|
||||
convert::TryInto,
|
||||
f64,
|
||||
f64, ops,
|
||||
os::raw::c_void,
|
||||
sync::{
|
||||
atomic::{AtomicBool, Ordering},
|
||||
Arc, Mutex, Weak,
|
||||
Arc, Mutex, MutexGuard, Weak,
|
||||
},
|
||||
};
|
||||
|
||||
|
@ -251,13 +251,24 @@ lazy_static! {
|
|||
static ref WINDOW_CLASS: WindowClass = unsafe {
|
||||
let window_superclass = class!(NSWindow);
|
||||
let mut decl = ClassDecl::new("WinitWindow", window_superclass).unwrap();
|
||||
|
||||
pub extern "C" fn can_become_main_window(_: &Object, _: Sel) -> BOOL {
|
||||
trace_scope!("canBecomeMainWindow");
|
||||
YES
|
||||
}
|
||||
|
||||
pub extern "C" fn can_become_key_window(_: &Object, _: Sel) -> BOOL {
|
||||
trace_scope!("canBecomeKeyWindow");
|
||||
YES
|
||||
}
|
||||
|
||||
decl.add_method(
|
||||
sel!(canBecomeMainWindow),
|
||||
util::yes as extern "C" fn(&Object, Sel) -> BOOL,
|
||||
can_become_main_window as extern "C" fn(&Object, Sel) -> BOOL,
|
||||
);
|
||||
decl.add_method(
|
||||
sel!(canBecomeKeyWindow),
|
||||
util::yes as extern "C" fn(&Object, Sel) -> BOOL,
|
||||
can_become_key_window as extern "C" fn(&Object, Sel) -> BOOL,
|
||||
);
|
||||
WindowClass(decl.register())
|
||||
};
|
||||
|
@ -311,11 +322,49 @@ impl From<WindowAttributes> for SharedState {
|
|||
}
|
||||
}
|
||||
|
||||
pub(crate) struct SharedStateMutexGuard<'a> {
|
||||
guard: MutexGuard<'a, SharedState>,
|
||||
called_from_fn: &'static str,
|
||||
}
|
||||
|
||||
impl<'a> SharedStateMutexGuard<'a> {
|
||||
#[inline]
|
||||
pub(crate) 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);
|
||||
}
|
||||
}
|
||||
|
||||
pub struct UnownedWindow {
|
||||
pub ns_window: IdRef, // never changes
|
||||
pub ns_view: IdRef, // never changes
|
||||
input_context: IdRef, // never changes
|
||||
pub shared_state: Arc<Mutex<SharedState>>,
|
||||
shared_state: Arc<Mutex<SharedState>>,
|
||||
decorations: AtomicBool,
|
||||
cursor_state: Weak<Mutex<CursorState>>,
|
||||
pub inner_rect: Option<PhysicalSize<u32>>,
|
||||
|
@ -420,6 +469,14 @@ impl UnownedWindow {
|
|||
Ok((window, delegate))
|
||||
}
|
||||
|
||||
#[track_caller]
|
||||
pub(crate) fn lock_shared_state(
|
||||
&self,
|
||||
called_from_fn: &'static str,
|
||||
) -> SharedStateMutexGuard<'_> {
|
||||
SharedStateMutexGuard::new(self.shared_state.lock().unwrap(), called_from_fn)
|
||||
}
|
||||
|
||||
fn set_style_mask_async(&self, mask: NSWindowStyleMask) {
|
||||
unsafe { util::set_style_mask_async(*self.ns_window, *self.ns_view, mask) };
|
||||
}
|
||||
|
@ -530,10 +587,8 @@ impl UnownedWindow {
|
|||
#[inline]
|
||||
pub fn set_resizable(&self, resizable: bool) {
|
||||
let fullscreen = {
|
||||
trace!("Locked shared state in `set_resizable`");
|
||||
let mut shared_state_lock = self.shared_state.lock().unwrap();
|
||||
let mut shared_state_lock = self.lock_shared_state("set_resizable");
|
||||
shared_state_lock.resizable = resizable;
|
||||
trace!("Unlocked shared state in `set_resizable`");
|
||||
shared_state_lock.fullscreen.is_some()
|
||||
};
|
||||
if !fullscreen {
|
||||
|
@ -653,8 +708,7 @@ impl UnownedWindow {
|
|||
/// user clicking on the green fullscreen button or programmatically by
|
||||
/// `toggleFullScreen:`
|
||||
pub(crate) fn restore_state_from_fullscreen(&self) {
|
||||
trace!("Locked shared state in `restore_state_from_fullscreen`");
|
||||
let mut shared_state_lock = self.shared_state.lock().unwrap();
|
||||
let mut shared_state_lock = self.lock_shared_state("restore_state_from_fullscreen");
|
||||
|
||||
shared_state_lock.fullscreen = None;
|
||||
|
||||
|
@ -662,7 +716,6 @@ impl UnownedWindow {
|
|||
let mask = self.saved_style(&mut *shared_state_lock);
|
||||
|
||||
drop(shared_state_lock);
|
||||
trace!("Unocked shared state in `restore_state_from_fullscreen`");
|
||||
|
||||
self.set_style_mask_async(mask);
|
||||
self.set_maximized(maximized);
|
||||
|
@ -705,7 +758,7 @@ impl UnownedWindow {
|
|||
|
||||
#[inline]
|
||||
pub fn fullscreen(&self) -> Option<Fullscreen> {
|
||||
let shared_state_lock = self.shared_state.lock().unwrap();
|
||||
let shared_state_lock = self.lock_shared_state("fullscreen");
|
||||
shared_state_lock.fullscreen.clone()
|
||||
}
|
||||
|
||||
|
@ -716,25 +769,20 @@ impl UnownedWindow {
|
|||
|
||||
#[inline]
|
||||
pub fn set_fullscreen(&self, fullscreen: Option<Fullscreen>) {
|
||||
trace!("Locked shared state in `set_fullscreen`");
|
||||
let mut shared_state_lock = self.shared_state.lock().unwrap();
|
||||
let mut shared_state_lock = self.lock_shared_state("set_fullscreen");
|
||||
if shared_state_lock.is_simple_fullscreen {
|
||||
trace!("Unlocked shared state in `set_fullscreen`");
|
||||
return;
|
||||
}
|
||||
if shared_state_lock.in_fullscreen_transition {
|
||||
// We can't set fullscreen here.
|
||||
// Set fullscreen after transition.
|
||||
shared_state_lock.target_fullscreen = Some(fullscreen);
|
||||
trace!("Unlocked shared state in `set_fullscreen`");
|
||||
return;
|
||||
}
|
||||
let old_fullscreen = shared_state_lock.fullscreen.clone();
|
||||
if fullscreen == old_fullscreen {
|
||||
trace!("Unlocked shared state in `set_fullscreen`");
|
||||
return;
|
||||
}
|
||||
trace!("Unlocked shared state in `set_fullscreen`");
|
||||
drop(shared_state_lock);
|
||||
|
||||
// If the fullscreen is on a different monitor, we must move the window
|
||||
|
@ -787,8 +835,7 @@ impl UnownedWindow {
|
|||
if matches!(old_fullscreen, Some(Fullscreen::Borderless(_))) {
|
||||
unsafe {
|
||||
let app = NSApp();
|
||||
trace!("Locked shared state in `set_fullscreen`");
|
||||
let mut shared_state_lock = self.shared_state.lock().unwrap();
|
||||
let mut shared_state_lock = self.lock_shared_state("set_fullscreen");
|
||||
shared_state_lock.save_presentation_opts = Some(app.presentationOptions_());
|
||||
}
|
||||
}
|
||||
|
@ -840,8 +887,7 @@ impl UnownedWindow {
|
|||
}
|
||||
}
|
||||
|
||||
trace!("Locked shared state in `set_fullscreen`");
|
||||
let mut shared_state_lock = self.shared_state.lock().unwrap();
|
||||
let mut shared_state_lock = self.lock_shared_state("set_fullscreen");
|
||||
shared_state_lock.fullscreen = fullscreen.clone();
|
||||
|
||||
INTERRUPT_EVENT_LOOP_EXIT.store(true, Ordering::SeqCst);
|
||||
|
@ -884,7 +930,6 @@ impl UnownedWindow {
|
|||
// that the menu bar is disabled. This is done in the window
|
||||
// delegate in `window:willUseFullScreenPresentationOptions:`.
|
||||
let app = NSApp();
|
||||
trace!("Locked shared state in `set_fullscreen`");
|
||||
shared_state_lock.save_presentation_opts = Some(app.presentationOptions_());
|
||||
|
||||
let presentation_options =
|
||||
|
@ -918,7 +963,6 @@ impl UnownedWindow {
|
|||
},
|
||||
_ => INTERRUPT_EVENT_LOOP_EXIT.store(false, Ordering::SeqCst),
|
||||
};
|
||||
trace!("Unlocked shared state in `set_fullscreen`");
|
||||
}
|
||||
|
||||
#[inline]
|
||||
|
@ -927,9 +971,7 @@ impl UnownedWindow {
|
|||
self.decorations.store(decorations, Ordering::Release);
|
||||
|
||||
let (fullscreen, resizable) = {
|
||||
trace!("Locked shared state in `set_decorations`");
|
||||
let shared_state_lock = self.shared_state.lock().unwrap();
|
||||
trace!("Unlocked shared state in `set_decorations`");
|
||||
let shared_state_lock = self.lock_shared_state("set_decorations");
|
||||
(
|
||||
shared_state_lock.fullscreen.is_some(),
|
||||
shared_state_lock.resizable,
|
||||
|
|
|
@ -265,14 +265,13 @@ extern "C" fn init_with_winit(this: &Object, _sel: Sel, state: *mut c_void) -> i
|
|||
}
|
||||
|
||||
extern "C" fn window_should_close(this: &Object, _: Sel, _: id) -> BOOL {
|
||||
trace!("Triggered `windowShouldClose:`");
|
||||
trace_scope!("windowShouldClose:");
|
||||
with_state(this, |state| state.emit_event(WindowEvent::CloseRequested));
|
||||
trace!("Completed `windowShouldClose:`");
|
||||
NO
|
||||
}
|
||||
|
||||
extern "C" fn window_will_close(this: &Object, _: Sel, _: id) {
|
||||
trace!("Triggered `windowWillClose:`");
|
||||
trace_scope!("windowWillClose:");
|
||||
with_state(this, |state| unsafe {
|
||||
// `setDelegate:` retains the previous value and then autoreleases it
|
||||
autoreleasepool(|| {
|
||||
|
@ -282,47 +281,42 @@ extern "C" fn window_will_close(this: &Object, _: Sel, _: id) {
|
|||
});
|
||||
state.emit_event(WindowEvent::Destroyed);
|
||||
});
|
||||
trace!("Completed `windowWillClose:`");
|
||||
}
|
||||
|
||||
extern "C" fn window_did_resize(this: &Object, _: Sel, _: id) {
|
||||
trace!("Triggered `windowDidResize:`");
|
||||
trace_scope!("windowDidResize:");
|
||||
with_state(this, |state| {
|
||||
state.emit_resize_event();
|
||||
state.emit_move_event();
|
||||
});
|
||||
trace!("Completed `windowDidResize:`");
|
||||
}
|
||||
|
||||
// This won't be triggered if the move was part of a resize.
|
||||
extern "C" fn window_did_move(this: &Object, _: Sel, _: id) {
|
||||
trace!("Triggered `windowDidMove:`");
|
||||
trace_scope!("windowDidMove:");
|
||||
with_state(this, |state| {
|
||||
state.emit_move_event();
|
||||
});
|
||||
trace!("Completed `windowDidMove:`");
|
||||
}
|
||||
|
||||
extern "C" fn window_did_change_backing_properties(this: &Object, _: Sel, _: id) {
|
||||
trace!("Triggered `windowDidChangeBackingProperties:`");
|
||||
trace_scope!("windowDidChangeBackingProperties:");
|
||||
with_state(this, |state| {
|
||||
state.emit_static_scale_factor_changed_event();
|
||||
});
|
||||
trace!("Completed `windowDidChangeBackingProperties:`");
|
||||
}
|
||||
|
||||
extern "C" fn window_did_become_key(this: &Object, _: Sel, _: id) {
|
||||
trace!("Triggered `windowDidBecomeKey:`");
|
||||
trace_scope!("windowDidBecomeKey:");
|
||||
with_state(this, |state| {
|
||||
// TODO: center the cursor if the window had mouse grab when it
|
||||
// lost focus
|
||||
state.emit_event(WindowEvent::Focused(true));
|
||||
});
|
||||
trace!("Completed `windowDidBecomeKey:`");
|
||||
}
|
||||
|
||||
extern "C" fn window_did_resign_key(this: &Object, _: Sel, _: id) {
|
||||
trace!("Triggered `windowDidResignKey:`");
|
||||
trace_scope!("windowDidResignKey:");
|
||||
with_state(this, |state| {
|
||||
// It happens rather often, e.g. when the user is Cmd+Tabbing, that the
|
||||
// NSWindowDelegate will receive a didResignKey event despite no event
|
||||
|
@ -349,12 +343,11 @@ extern "C" fn window_did_resign_key(this: &Object, _: Sel, _: id) {
|
|||
|
||||
state.emit_event(WindowEvent::Focused(false));
|
||||
});
|
||||
trace!("Completed `windowDidResignKey:`");
|
||||
}
|
||||
|
||||
/// Invoked when the dragged image enters destination bounds or frame
|
||||
extern "C" fn dragging_entered(this: &Object, _: Sel, sender: id) -> BOOL {
|
||||
trace!("Triggered `draggingEntered:`");
|
||||
trace_scope!("draggingEntered:");
|
||||
|
||||
use cocoa::{appkit::NSPasteboard, foundation::NSFastEnumeration};
|
||||
use std::path::PathBuf;
|
||||
|
@ -376,20 +369,18 @@ extern "C" fn dragging_entered(this: &Object, _: Sel, sender: id) -> BOOL {
|
|||
}
|
||||
}
|
||||
|
||||
trace!("Completed `draggingEntered:`");
|
||||
YES
|
||||
}
|
||||
|
||||
/// Invoked when the image is released
|
||||
extern "C" fn prepare_for_drag_operation(_: &Object, _: Sel, _: id) -> BOOL {
|
||||
trace!("Triggered `prepareForDragOperation:`");
|
||||
trace!("Completed `prepareForDragOperation:`");
|
||||
trace_scope!("prepareForDragOperation:");
|
||||
YES
|
||||
}
|
||||
|
||||
/// Invoked after the released image has been removed from the screen
|
||||
extern "C" fn perform_drag_operation(this: &Object, _: Sel, sender: id) -> BOOL {
|
||||
trace!("Triggered `performDragOperation:`");
|
||||
trace_scope!("performDragOperation:");
|
||||
|
||||
use cocoa::{appkit::NSPasteboard, foundation::NSFastEnumeration};
|
||||
use std::path::PathBuf;
|
||||
|
@ -411,35 +402,31 @@ extern "C" fn perform_drag_operation(this: &Object, _: Sel, sender: id) -> BOOL
|
|||
}
|
||||
}
|
||||
|
||||
trace!("Completed `performDragOperation:`");
|
||||
YES
|
||||
}
|
||||
|
||||
/// Invoked when the dragging operation is complete
|
||||
extern "C" fn conclude_drag_operation(_: &Object, _: Sel, _: id) {
|
||||
trace!("Triggered `concludeDragOperation:`");
|
||||
trace!("Completed `concludeDragOperation:`");
|
||||
trace_scope!("concludeDragOperation:");
|
||||
}
|
||||
|
||||
/// Invoked when the dragging operation is cancelled
|
||||
extern "C" fn dragging_exited(this: &Object, _: Sel, _: id) {
|
||||
trace!("Triggered `draggingExited:`");
|
||||
trace_scope!("draggingExited:");
|
||||
with_state(this, |state| {
|
||||
state.emit_event(WindowEvent::HoveredFileCancelled)
|
||||
});
|
||||
trace!("Completed `draggingExited:`");
|
||||
}
|
||||
|
||||
/// Invoked when before enter fullscreen
|
||||
extern "C" fn window_will_enter_fullscreen(this: &Object, _: Sel, _: id) {
|
||||
trace!("Triggered `windowWillEnterFullscreen:`");
|
||||
trace_scope!("windowWillEnterFullscreen:");
|
||||
|
||||
INTERRUPT_EVENT_LOOP_EXIT.store(true, Ordering::SeqCst);
|
||||
|
||||
with_state(this, |state| {
|
||||
state.with_window(|window| {
|
||||
trace!("Locked shared state in `window_will_enter_fullscreen`");
|
||||
let mut shared_state = window.shared_state.lock().unwrap();
|
||||
let mut shared_state = window.lock_shared_state("window_will_enter_fullscreen");
|
||||
shared_state.maximized = window.is_zoomed();
|
||||
match shared_state.fullscreen {
|
||||
// Exclusive mode sets the state in `set_fullscreen` as the user
|
||||
|
@ -458,27 +445,22 @@ extern "C" fn window_will_enter_fullscreen(this: &Object, _: Sel, _: id) {
|
|||
}
|
||||
}
|
||||
shared_state.in_fullscreen_transition = true;
|
||||
trace!("Unlocked shared state in `window_will_enter_fullscreen`");
|
||||
})
|
||||
});
|
||||
trace!("Completed `windowWillEnterFullscreen:`");
|
||||
}
|
||||
|
||||
/// Invoked when before exit fullscreen
|
||||
extern "C" fn window_will_exit_fullscreen(this: &Object, _: Sel, _: id) {
|
||||
trace!("Triggered `windowWillExitFullScreen:`");
|
||||
trace_scope!("windowWillExitFullScreen:");
|
||||
|
||||
INTERRUPT_EVENT_LOOP_EXIT.store(true, Ordering::SeqCst);
|
||||
|
||||
with_state(this, |state| {
|
||||
state.with_window(|window| {
|
||||
trace!("Locked shared state in `window_will_exit_fullscreen`");
|
||||
let mut shared_state = window.shared_state.lock().unwrap();
|
||||
let mut shared_state = window.lock_shared_state("window_will_exit_fullscreen");
|
||||
shared_state.in_fullscreen_transition = true;
|
||||
trace!("Unlocked shared state in `window_will_exit_fullscreen`");
|
||||
});
|
||||
});
|
||||
trace!("Completed `windowWillExitFullScreen:`");
|
||||
}
|
||||
|
||||
extern "C" fn window_will_use_fullscreen_presentation_options(
|
||||
|
@ -487,6 +469,7 @@ extern "C" fn window_will_use_fullscreen_presentation_options(
|
|||
_: id,
|
||||
proposed_options: NSUInteger,
|
||||
) -> NSUInteger {
|
||||
trace_scope!("window:willUseFullScreenPresentationOptions:");
|
||||
// Generally, games will want to disable the menu bar and the dock. Ideally,
|
||||
// this would be configurable by the user. Unfortunately because of our
|
||||
// `CGShieldingWindowLevel() + 1` hack (see `set_fullscreen`), our window is
|
||||
|
@ -498,15 +481,14 @@ extern "C" fn window_will_use_fullscreen_presentation_options(
|
|||
let mut options: NSUInteger = proposed_options;
|
||||
with_state(this, |state| {
|
||||
state.with_window(|window| {
|
||||
trace!("Locked shared state in `window_will_use_fullscreen_presentation_options`");
|
||||
let shared_state = window.shared_state.lock().unwrap();
|
||||
let shared_state =
|
||||
window.lock_shared_state("window_will_use_fullscreen_presentation_options");
|
||||
if let Some(Fullscreen::Exclusive(_)) = shared_state.fullscreen {
|
||||
options = (NSApplicationPresentationOptions::NSApplicationPresentationFullScreen
|
||||
| NSApplicationPresentationOptions::NSApplicationPresentationHideDock
|
||||
| NSApplicationPresentationOptions::NSApplicationPresentationHideMenuBar)
|
||||
.bits();
|
||||
}
|
||||
trace!("Unlocked shared state in `window_will_use_fullscreen_presentation_options`");
|
||||
})
|
||||
});
|
||||
|
||||
|
@ -515,46 +497,40 @@ extern "C" fn window_will_use_fullscreen_presentation_options(
|
|||
|
||||
/// Invoked when entered fullscreen
|
||||
extern "C" fn window_did_enter_fullscreen(this: &Object, _: Sel, _: id) {
|
||||
trace_scope!("windowDidEnterFullscreen:");
|
||||
INTERRUPT_EVENT_LOOP_EXIT.store(false, Ordering::SeqCst);
|
||||
|
||||
trace!("Triggered `windowDidEnterFullscreen:`");
|
||||
with_state(this, |state| {
|
||||
state.initial_fullscreen = false;
|
||||
state.with_window(|window| {
|
||||
trace!("Locked shared state in `window_did_enter_fullscreen`");
|
||||
let mut shared_state = window.shared_state.lock().unwrap();
|
||||
let mut shared_state = window.lock_shared_state("window_did_enter_fullscreen");
|
||||
shared_state.in_fullscreen_transition = false;
|
||||
let target_fullscreen = shared_state.target_fullscreen.take();
|
||||
trace!("Unlocked shared state in `window_did_enter_fullscreen`");
|
||||
drop(shared_state);
|
||||
if let Some(target_fullscreen) = target_fullscreen {
|
||||
window.set_fullscreen(target_fullscreen);
|
||||
}
|
||||
});
|
||||
});
|
||||
trace!("Completed `windowDidEnterFullscreen:`");
|
||||
}
|
||||
|
||||
/// Invoked when exited fullscreen
|
||||
extern "C" fn window_did_exit_fullscreen(this: &Object, _: Sel, _: id) {
|
||||
trace_scope!("windowDidExitFullscreen:");
|
||||
INTERRUPT_EVENT_LOOP_EXIT.store(false, Ordering::SeqCst);
|
||||
|
||||
trace!("Triggered `windowDidExitFullscreen:`");
|
||||
with_state(this, |state| {
|
||||
state.with_window(|window| {
|
||||
window.restore_state_from_fullscreen();
|
||||
trace!("Locked shared state in `window_did_exit_fullscreen`");
|
||||
let mut shared_state = window.shared_state.lock().unwrap();
|
||||
let mut shared_state = window.lock_shared_state("window_did_exit_fullscreen");
|
||||
shared_state.in_fullscreen_transition = false;
|
||||
let target_fullscreen = shared_state.target_fullscreen.take();
|
||||
trace!("Unlocked shared state in `window_did_exit_fullscreen`");
|
||||
drop(shared_state);
|
||||
if let Some(target_fullscreen) = target_fullscreen {
|
||||
window.set_fullscreen(target_fullscreen);
|
||||
}
|
||||
})
|
||||
});
|
||||
trace!("Completed `windowDidExitFullscreen:`");
|
||||
}
|
||||
|
||||
/// Invoked when fail to enter fullscreen
|
||||
|
@ -574,14 +550,12 @@ extern "C" fn window_did_exit_fullscreen(this: &Object, _: Sel, _: id) {
|
|||
/// This method indicates that there was an error, and you should clean up any
|
||||
/// work you may have done to prepare to enter full-screen mode.
|
||||
extern "C" fn window_did_fail_to_enter_fullscreen(this: &Object, _: Sel, _: id) {
|
||||
trace!("Triggered `windowDidFailToEnterFullscreen:`");
|
||||
trace_scope!("windowDidFailToEnterFullscreen:");
|
||||
with_state(this, |state| {
|
||||
state.with_window(|window| {
|
||||
trace!("Locked shared state in `window_did_fail_to_enter_fullscreen`");
|
||||
let mut shared_state = window.shared_state.lock().unwrap();
|
||||
let mut shared_state = window.lock_shared_state("window_did_fail_to_enter_fullscreen");
|
||||
shared_state.in_fullscreen_transition = false;
|
||||
shared_state.target_fullscreen = None;
|
||||
trace!("Unlocked shared state in `window_did_fail_to_enter_fullscreen`");
|
||||
});
|
||||
if state.initial_fullscreen {
|
||||
let _: () = unsafe {
|
||||
|
@ -595,5 +569,4 @@ extern "C" fn window_did_fail_to_enter_fullscreen(this: &Object, _: Sel, _: id)
|
|||
state.with_window(|window| window.restore_state_from_fullscreen());
|
||||
}
|
||||
});
|
||||
trace!("Completed `windowDidFailToEnterFullscreen:`");
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue