mirror of
https://github.com/italicsjenga/winit-sonoma-fix.git
synced 2025-02-24 00:37:43 +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
src/platform_impl/macos
|
@ -75,7 +75,6 @@ extern "C" fn dealloc(this: &Object, _: Sel) {
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "C" fn did_finish_launching(this: &Object, _: Sel, _: id) {
|
extern "C" fn did_finish_launching(this: &Object, _: Sel, _: id) {
|
||||||
trace!("Triggered `applicationDidFinishLaunching`");
|
trace_scope!("applicationDidFinishLaunching:");
|
||||||
AppState::launched(this);
|
AppState::launched(this);
|
||||||
trace!("Completed `applicationDidFinishLaunching`");
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,8 @@
|
||||||
#![cfg(target_os = "macos")]
|
#![cfg(target_os = "macos")]
|
||||||
|
|
||||||
|
#[macro_use]
|
||||||
|
mod util;
|
||||||
|
|
||||||
mod app;
|
mod app;
|
||||||
mod app_delegate;
|
mod app_delegate;
|
||||||
mod app_state;
|
mod app_state;
|
||||||
|
@ -9,7 +12,6 @@ mod ffi;
|
||||||
mod menu;
|
mod menu;
|
||||||
mod monitor;
|
mod monitor;
|
||||||
mod observer;
|
mod observer;
|
||||||
mod util;
|
|
||||||
mod view;
|
mod view;
|
||||||
mod window;
|
mod window;
|
||||||
mod window_delegate;
|
mod window_delegate;
|
||||||
|
|
|
@ -14,7 +14,11 @@ use objc::runtime::{BOOL, NO};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
dpi::LogicalSize,
|
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.
|
// 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) {
|
if !curr_mask.contains(required) {
|
||||||
set_style_mask(*ns_window, *ns_view, required);
|
set_style_mask(*ns_window, *ns_view, required);
|
||||||
if let Some(shared_state) = shared_state.upgrade() {
|
if let Some(shared_state) = shared_state.upgrade() {
|
||||||
trace!("Locked shared state in `toggle_full_screen_callback`");
|
let mut shared_state_lock = SharedStateMutexGuard::new(
|
||||||
let mut shared_state_lock = shared_state.lock().unwrap();
|
shared_state.lock().unwrap(),
|
||||||
|
"toggle_full_screen_callback",
|
||||||
|
);
|
||||||
(*shared_state_lock).saved_style = Some(curr_mask);
|
(*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);
|
let shared_state = MainThreadSafe(shared_state);
|
||||||
Queue::main().exec_async(move || {
|
Queue::main().exec_async(move || {
|
||||||
if let Some(shared_state) = shared_state.upgrade() {
|
if let Some(shared_state) = shared_state.upgrade() {
|
||||||
trace!("Locked shared state in `set_maximized`");
|
let mut shared_state_lock =
|
||||||
let mut shared_state_lock = shared_state.lock().unwrap();
|
SharedStateMutexGuard::new(shared_state.lock().unwrap(), "set_maximized");
|
||||||
|
|
||||||
// Save the standard frame sized if it is not zoomed
|
// Save the standard frame sized if it is not zoomed
|
||||||
if !is_zoomed {
|
if !is_zoomed {
|
||||||
|
@ -171,8 +176,6 @@ pub unsafe fn set_maximized_async(
|
||||||
};
|
};
|
||||||
ns_window.setFrame_display_(new_rect, NO);
|
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},
|
foundation::{NSPoint, NSRect, NSString, NSUInteger},
|
||||||
};
|
};
|
||||||
use core_graphics::display::CGDisplay;
|
use core_graphics::display::CGDisplay;
|
||||||
use objc::runtime::{Class, Object, Sel, BOOL, YES};
|
use objc::runtime::{Class, Object};
|
||||||
|
|
||||||
use crate::dpi::LogicalPosition;
|
use crate::dpi::LogicalPosition;
|
||||||
use crate::platform_impl::platform::ffi;
|
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...
|
// For consistency with other platforms, this will...
|
||||||
// 1. translate the bottom-left window corner into the top-left window corner
|
// 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
|
// 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];
|
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) {
|
pub unsafe fn toggle_style_mask(window: id, view: id, mask: NSWindowStyleMask, on: bool) {
|
||||||
use cocoa::appkit::NSWindow;
|
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) {
|
extern "C" fn view_did_move_to_window(this: &Object, _sel: Sel) {
|
||||||
trace!("Triggered `viewDidMoveToWindow`");
|
trace_scope!("viewDidMoveToWindow");
|
||||||
unsafe {
|
unsafe {
|
||||||
let state_ptr: *mut c_void = *this.get_ivar("winitState");
|
let state_ptr: *mut c_void = *this.get_ivar("winitState");
|
||||||
let state = &mut *(state_ptr as *mut ViewState);
|
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);
|
state.tracking_rect = Some(tracking_rect);
|
||||||
}
|
}
|
||||||
trace!("Completed `viewDidMoveToWindow`");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "C" fn frame_did_change(this: &Object, _sel: Sel, _event: id) {
|
extern "C" fn frame_did_change(this: &Object, _sel: Sel, _event: id) {
|
||||||
|
trace_scope!("frameDidChange:");
|
||||||
unsafe {
|
unsafe {
|
||||||
let state_ptr: *mut c_void = *this.get_ivar("winitState");
|
let state_ptr: *mut c_void = *this.get_ivar("winitState");
|
||||||
let state = &mut *(state_ptr as *mut ViewState);
|
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) {
|
extern "C" fn draw_rect(this: &Object, _sel: Sel, rect: NSRect) {
|
||||||
|
trace_scope!("drawRect:");
|
||||||
unsafe {
|
unsafe {
|
||||||
let state_ptr: *mut c_void = *this.get_ivar("winitState");
|
let state_ptr: *mut c_void = *this.get_ivar("winitState");
|
||||||
let state = &mut *(state_ptr as *mut ViewState);
|
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 {
|
extern "C" fn accepts_first_responder(_this: &Object, _sel: Sel) -> BOOL {
|
||||||
|
trace_scope!("acceptsFirstResponder");
|
||||||
YES
|
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
|
// 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`
|
// TODO: Add an API extension for using `NSTouchBar`
|
||||||
extern "C" fn touch_bar(_this: &Object, _sel: Sel) -> BOOL {
|
extern "C" fn touch_bar(_this: &Object, _sel: Sel) -> BOOL {
|
||||||
|
trace_scope!("touchBar");
|
||||||
NO
|
NO
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "C" fn reset_cursor_rects(this: &Object, _sel: Sel) {
|
extern "C" fn reset_cursor_rects(this: &Object, _sel: Sel) {
|
||||||
|
trace_scope!("resetCursorRects");
|
||||||
unsafe {
|
unsafe {
|
||||||
let state_ptr: *mut c_void = *this.get_ivar("winitState");
|
let state_ptr: *mut c_void = *this.get_ivar("winitState");
|
||||||
let state = &mut *(state_ptr as *mut ViewState);
|
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 {
|
extern "C" fn has_marked_text(this: &Object, _sel: Sel) -> BOOL {
|
||||||
|
trace_scope!("hasMarkedText");
|
||||||
unsafe {
|
unsafe {
|
||||||
trace!("Triggered `hasMarkedText`");
|
|
||||||
let marked_text: id = *this.get_ivar("markedText");
|
let marked_text: id = *this.get_ivar("markedText");
|
||||||
trace!("Completed `hasMarkedText`");
|
|
||||||
(marked_text.length() > 0) as BOOL
|
(marked_text.length() > 0) as BOOL
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "C" fn marked_range(this: &Object, _sel: Sel) -> NSRange {
|
extern "C" fn marked_range(this: &Object, _sel: Sel) -> NSRange {
|
||||||
|
trace_scope!("markedRange");
|
||||||
unsafe {
|
unsafe {
|
||||||
trace!("Triggered `markedRange`");
|
|
||||||
let marked_text: id = *this.get_ivar("markedText");
|
let marked_text: id = *this.get_ivar("markedText");
|
||||||
let length = marked_text.length();
|
let length = marked_text.length();
|
||||||
trace!("Completed `markedRange`");
|
|
||||||
if length > 0 {
|
if length > 0 {
|
||||||
NSRange::new(0, length - 1)
|
NSRange::new(0, length - 1)
|
||||||
} else {
|
} 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 {
|
extern "C" fn selected_range(_this: &Object, _sel: Sel) -> NSRange {
|
||||||
trace!("Triggered `selectedRange`");
|
trace_scope!("selectedRange");
|
||||||
trace!("Completed `selectedRange`");
|
|
||||||
util::EMPTY_RANGE
|
util::EMPTY_RANGE
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -421,7 +422,7 @@ extern "C" fn set_marked_text(
|
||||||
_selected_range: NSRange,
|
_selected_range: NSRange,
|
||||||
_replacement_range: NSRange,
|
_replacement_range: NSRange,
|
||||||
) {
|
) {
|
||||||
trace!("Triggered `setMarkedText`");
|
trace_scope!("setMarkedText:selectedRange:replacementRange:");
|
||||||
unsafe {
|
unsafe {
|
||||||
let marked_text_ref: &mut id = this.get_mut_ivar("markedText");
|
let marked_text_ref: &mut id = this.get_mut_ivar("markedText");
|
||||||
let _: () = msg_send![(*marked_text_ref), release];
|
let _: () = msg_send![(*marked_text_ref), release];
|
||||||
|
@ -434,11 +435,10 @@ extern "C" fn set_marked_text(
|
||||||
};
|
};
|
||||||
*marked_text_ref = marked_text;
|
*marked_text_ref = marked_text;
|
||||||
}
|
}
|
||||||
trace!("Completed `setMarkedText`");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "C" fn unmark_text(this: &Object, _sel: Sel) {
|
extern "C" fn unmark_text(this: &Object, _sel: Sel) {
|
||||||
trace!("Triggered `unmarkText`");
|
trace_scope!("unmarkText");
|
||||||
unsafe {
|
unsafe {
|
||||||
let marked_text: id = *this.get_ivar("markedText");
|
let marked_text: id = *this.get_ivar("markedText");
|
||||||
let mutable_string = marked_text.mutableString();
|
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 input_context: id = msg_send![this, inputContext];
|
||||||
let _: () = msg_send![input_context, discardMarkedText];
|
let _: () = msg_send![input_context, discardMarkedText];
|
||||||
}
|
}
|
||||||
trace!("Completed `unmarkText`");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "C" fn valid_attributes_for_marked_text(_this: &Object, _sel: Sel) -> id {
|
extern "C" fn valid_attributes_for_marked_text(_this: &Object, _sel: Sel) -> id {
|
||||||
trace!("Triggered `validAttributesForMarkedText`");
|
trace_scope!("validAttributesForMarkedText");
|
||||||
trace!("Completed `validAttributesForMarkedText`");
|
|
||||||
unsafe { msg_send![class!(NSArray), array] }
|
unsafe { msg_send![class!(NSArray), array] }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -463,14 +461,12 @@ extern "C" fn attributed_substring_for_proposed_range(
|
||||||
_range: NSRange,
|
_range: NSRange,
|
||||||
_actual_range: *mut c_void, // *mut NSRange
|
_actual_range: *mut c_void, // *mut NSRange
|
||||||
) -> id {
|
) -> id {
|
||||||
trace!("Triggered `attributedSubstringForProposedRange`");
|
trace_scope!("attributedSubstringForProposedRange:actualRange:");
|
||||||
trace!("Completed `attributedSubstringForProposedRange`");
|
|
||||||
nil
|
nil
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "C" fn character_index_for_point(_this: &Object, _sel: Sel, _point: NSPoint) -> NSUInteger {
|
extern "C" fn character_index_for_point(_this: &Object, _sel: Sel, _point: NSPoint) -> NSUInteger {
|
||||||
trace!("Triggered `characterIndexForPoint`");
|
trace_scope!("characterIndexForPoint:");
|
||||||
trace!("Completed `characterIndexForPoint`");
|
|
||||||
0
|
0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -480,8 +476,8 @@ extern "C" fn first_rect_for_character_range(
|
||||||
_range: NSRange,
|
_range: NSRange,
|
||||||
_actual_range: *mut c_void, // *mut NSRange
|
_actual_range: *mut c_void, // *mut NSRange
|
||||||
) -> NSRect {
|
) -> NSRect {
|
||||||
|
trace_scope!("firstRectForCharacterRange:actualRange:");
|
||||||
unsafe {
|
unsafe {
|
||||||
trace!("Triggered `firstRectForCharacterRange`");
|
|
||||||
let state_ptr: *mut c_void = *this.get_ivar("winitState");
|
let state_ptr: *mut c_void = *this.get_ivar("winitState");
|
||||||
let state = &mut *(state_ptr as *mut ViewState);
|
let state = &mut *(state_ptr as *mut ViewState);
|
||||||
let (x, y) = state.ime_spot.unwrap_or_else(|| {
|
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);
|
let y = util::bottom_left_to_top_left(content_rect);
|
||||||
(x, y)
|
(x, y)
|
||||||
});
|
});
|
||||||
trace!("Completed `firstRectForCharacterRange`");
|
|
||||||
NSRect::new(NSPoint::new(x as _, y as _), NSSize::new(0.0, 0.0))
|
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) {
|
extern "C" fn insert_text(this: &Object, _sel: Sel, string: id, _replacement_range: NSRange) {
|
||||||
trace!("Triggered `insertText`");
|
trace_scope!("insertText:replacementRange:");
|
||||||
unsafe {
|
unsafe {
|
||||||
let state_ptr: *mut c_void = *this.get_ivar("winitState");
|
let state_ptr: *mut c_void = *this.get_ivar("winitState");
|
||||||
let state = &mut *(state_ptr as *mut ViewState);
|
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);
|
AppState::queue_events(events);
|
||||||
}
|
}
|
||||||
trace!("Completed `insertText`");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "C" fn do_command_by_selector(this: &Object, _sel: Sel, command: Sel) {
|
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
|
// 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.
|
// happens, i.e. newlines, tabs, and Ctrl+C.
|
||||||
unsafe {
|
unsafe {
|
||||||
|
@ -567,7 +561,6 @@ extern "C" fn do_command_by_selector(this: &Object, _sel: Sel, command: Sel) {
|
||||||
|
|
||||||
AppState::queue_events(events);
|
AppState::queue_events(events);
|
||||||
}
|
}
|
||||||
trace!("Completed `doCommandBySelector`");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_characters(event: id, ignore_modifiers: bool) -> String {
|
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) {
|
extern "C" fn key_down(this: &Object, _sel: Sel, event: id) {
|
||||||
trace!("Triggered `keyDown`");
|
trace_scope!("keyDown:");
|
||||||
unsafe {
|
unsafe {
|
||||||
let state_ptr: *mut c_void = *this.get_ivar("winitState");
|
let state_ptr: *mut c_void = *this.get_ivar("winitState");
|
||||||
let state = &mut *(state_ptr as *mut ViewState);
|
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];
|
let _: () = msg_send![this, interpretKeyEvents: array];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
trace!("Completed `keyDown`");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "C" fn key_up(this: &Object, _sel: Sel, event: id) {
|
extern "C" fn key_up(this: &Object, _sel: Sel, event: id) {
|
||||||
trace!("Triggered `keyUp`");
|
trace_scope!("keyUp:");
|
||||||
unsafe {
|
unsafe {
|
||||||
let state_ptr: *mut c_void = *this.get_ivar("winitState");
|
let state_ptr: *mut c_void = *this.get_ivar("winitState");
|
||||||
let state = &mut *(state_ptr as *mut ViewState);
|
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));
|
AppState::queue_event(EventWrapper::StaticEvent(window_event));
|
||||||
}
|
}
|
||||||
trace!("Completed `keyUp`");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "C" fn flags_changed(this: &Object, _sel: Sel, event: id) {
|
extern "C" fn flags_changed(this: &Object, _sel: Sel, event: id) {
|
||||||
trace!("Triggered `flagsChanged`");
|
trace_scope!("flagsChanged:");
|
||||||
unsafe {
|
unsafe {
|
||||||
let state_ptr: *mut c_void = *this.get_ivar("winitState");
|
let state_ptr: *mut c_void = *this.get_ivar("winitState");
|
||||||
let state = &mut *(state_ptr as *mut ViewState);
|
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),
|
event: WindowEvent::ModifiersChanged(state.modifiers),
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
trace!("Completed `flagsChanged`");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "C" fn insert_tab(this: &Object, _sel: Sel, _sender: id) {
|
extern "C" fn insert_tab(this: &Object, _sel: Sel, _sender: id) {
|
||||||
|
trace_scope!("insertTab:");
|
||||||
unsafe {
|
unsafe {
|
||||||
let window: id = msg_send![this, window];
|
let window: id = msg_send![this, window];
|
||||||
let first_responder: id = msg_send![window, firstResponder];
|
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) {
|
extern "C" fn insert_back_tab(this: &Object, _sel: Sel, _sender: id) {
|
||||||
|
trace_scope!("insertBackTab:");
|
||||||
unsafe {
|
unsafe {
|
||||||
let window: id = msg_send![this, window];
|
let window: id = msg_send![this, window];
|
||||||
let first_responder: id = msg_send![window, firstResponder];
|
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)
|
// Allows us to receive Cmd-. (the shortcut for closing a dialog)
|
||||||
// https://bugs.eclipse.org/bugs/show_bug.cgi?id=300620#c6
|
// https://bugs.eclipse.org/bugs/show_bug.cgi?id=300620#c6
|
||||||
extern "C" fn cancel_operation(this: &Object, _sel: Sel, _sender: id) {
|
extern "C" fn cancel_operation(this: &Object, _sel: Sel, _sender: id) {
|
||||||
trace!("Triggered `cancelOperation`");
|
trace_scope!("cancelOperation:");
|
||||||
unsafe {
|
unsafe {
|
||||||
let state_ptr: *mut c_void = *this.get_ivar("winitState");
|
let state_ptr: *mut c_void = *this.get_ivar("winitState");
|
||||||
let state = &mut *(state_ptr as *mut ViewState);
|
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));
|
AppState::queue_event(EventWrapper::StaticEvent(window_event));
|
||||||
}
|
}
|
||||||
trace!("Completed `cancelOperation`");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn mouse_click(this: &Object, event: id, button: MouseButton, button_state: ElementState) {
|
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) {
|
extern "C" fn mouse_down(this: &Object, _sel: Sel, event: id) {
|
||||||
|
trace_scope!("mouseDown:");
|
||||||
mouse_motion(this, event);
|
mouse_motion(this, event);
|
||||||
mouse_click(this, event, MouseButton::Left, ElementState::Pressed);
|
mouse_click(this, event, MouseButton::Left, ElementState::Pressed);
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "C" fn mouse_up(this: &Object, _sel: Sel, event: id) {
|
extern "C" fn mouse_up(this: &Object, _sel: Sel, event: id) {
|
||||||
|
trace_scope!("mouseUp:");
|
||||||
mouse_motion(this, event);
|
mouse_motion(this, event);
|
||||||
mouse_click(this, event, MouseButton::Left, ElementState::Released);
|
mouse_click(this, event, MouseButton::Left, ElementState::Released);
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "C" fn right_mouse_down(this: &Object, _sel: Sel, event: id) {
|
extern "C" fn right_mouse_down(this: &Object, _sel: Sel, event: id) {
|
||||||
|
trace_scope!("rightMouseDown:");
|
||||||
mouse_motion(this, event);
|
mouse_motion(this, event);
|
||||||
mouse_click(this, event, MouseButton::Right, ElementState::Pressed);
|
mouse_click(this, event, MouseButton::Right, ElementState::Pressed);
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "C" fn right_mouse_up(this: &Object, _sel: Sel, event: id) {
|
extern "C" fn right_mouse_up(this: &Object, _sel: Sel, event: id) {
|
||||||
|
trace_scope!("rightMouseUp:");
|
||||||
mouse_motion(this, event);
|
mouse_motion(this, event);
|
||||||
mouse_click(this, event, MouseButton::Right, ElementState::Released);
|
mouse_click(this, event, MouseButton::Right, ElementState::Released);
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "C" fn other_mouse_down(this: &Object, _sel: Sel, event: id) {
|
extern "C" fn other_mouse_down(this: &Object, _sel: Sel, event: id) {
|
||||||
|
trace_scope!("otherMouseDown:");
|
||||||
mouse_motion(this, event);
|
mouse_motion(this, event);
|
||||||
mouse_click(this, event, MouseButton::Middle, ElementState::Pressed);
|
mouse_click(this, event, MouseButton::Middle, ElementState::Pressed);
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "C" fn other_mouse_up(this: &Object, _sel: Sel, event: id) {
|
extern "C" fn other_mouse_up(this: &Object, _sel: Sel, event: id) {
|
||||||
|
trace_scope!("otherMouseUp:");
|
||||||
mouse_motion(this, event);
|
mouse_motion(this, event);
|
||||||
mouse_click(this, event, MouseButton::Middle, ElementState::Released);
|
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) {
|
extern "C" fn mouse_moved(this: &Object, _sel: Sel, event: id) {
|
||||||
mouse_motion(this, event);
|
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) {
|
extern "C" fn mouse_entered(this: &Object, _sel: Sel, _event: id) {
|
||||||
trace!("Triggered `mouseEntered`");
|
trace_scope!("mouseEntered:");
|
||||||
unsafe {
|
unsafe {
|
||||||
let state_ptr: *mut c_void = *this.get_ivar("winitState");
|
let state_ptr: *mut c_void = *this.get_ivar("winitState");
|
||||||
let state = &mut *(state_ptr as *mut ViewState);
|
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));
|
AppState::queue_event(EventWrapper::StaticEvent(enter_event));
|
||||||
}
|
}
|
||||||
trace!("Completed `mouseEntered`");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "C" fn mouse_exited(this: &Object, _sel: Sel, _event: id) {
|
extern "C" fn mouse_exited(this: &Object, _sel: Sel, _event: id) {
|
||||||
trace!("Triggered `mouseExited`");
|
trace_scope!("mouseExited:");
|
||||||
unsafe {
|
unsafe {
|
||||||
let state_ptr: *mut c_void = *this.get_ivar("winitState");
|
let state_ptr: *mut c_void = *this.get_ivar("winitState");
|
||||||
let state = &mut *(state_ptr as *mut ViewState);
|
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));
|
AppState::queue_event(EventWrapper::StaticEvent(window_event));
|
||||||
}
|
}
|
||||||
trace!("Completed `mouseExited`");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "C" fn scroll_wheel(this: &Object, _sel: Sel, event: id) {
|
extern "C" fn scroll_wheel(this: &Object, _sel: Sel, event: id) {
|
||||||
trace!("Triggered `scrollWheel`");
|
trace_scope!("scrollWheel:");
|
||||||
|
|
||||||
mouse_motion(this, event);
|
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(device_event));
|
||||||
AppState::queue_event(EventWrapper::StaticEvent(window_event));
|
AppState::queue_event(EventWrapper::StaticEvent(window_event));
|
||||||
}
|
}
|
||||||
trace!("Completed `scrollWheel`");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "C" fn pressure_change_with_event(this: &Object, _sel: Sel, event: id) {
|
extern "C" fn pressure_change_with_event(this: &Object, _sel: Sel, event: id) {
|
||||||
trace!("Triggered `pressureChangeWithEvent`");
|
trace_scope!("pressureChangeWithEvent:");
|
||||||
|
|
||||||
mouse_motion(this, event);
|
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));
|
AppState::queue_event(EventWrapper::StaticEvent(window_event));
|
||||||
}
|
}
|
||||||
trace!("Completed `pressureChangeWithEvent`");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Allows us to receive Ctrl-Tab and Ctrl-Esc.
|
// Allows us to receive Ctrl-Tab and Ctrl-Esc.
|
||||||
// Note that this *doesn't* help with any missing Cmd inputs.
|
// 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
|
// 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 {
|
extern "C" fn wants_key_down_for_event(_this: &Object, _sel: Sel, _event: id) -> BOOL {
|
||||||
|
trace_scope!("_wantsKeyDownForEvent:");
|
||||||
YES
|
YES
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "C" fn accepts_first_mouse(_this: &Object, _sel: Sel, _event: id) -> BOOL {
|
extern "C" fn accepts_first_mouse(_this: &Object, _sel: Sel, _event: id) -> BOOL {
|
||||||
|
trace_scope!("acceptsFirstMouse:");
|
||||||
YES
|
YES
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,11 +2,11 @@ use raw_window_handle::{AppKitHandle, RawWindowHandle};
|
||||||
use std::{
|
use std::{
|
||||||
collections::VecDeque,
|
collections::VecDeque,
|
||||||
convert::TryInto,
|
convert::TryInto,
|
||||||
f64,
|
f64, ops,
|
||||||
os::raw::c_void,
|
os::raw::c_void,
|
||||||
sync::{
|
sync::{
|
||||||
atomic::{AtomicBool, Ordering},
|
atomic::{AtomicBool, Ordering},
|
||||||
Arc, Mutex, Weak,
|
Arc, Mutex, MutexGuard, Weak,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -251,13 +251,24 @@ lazy_static! {
|
||||||
static ref WINDOW_CLASS: WindowClass = unsafe {
|
static ref WINDOW_CLASS: WindowClass = unsafe {
|
||||||
let window_superclass = class!(NSWindow);
|
let window_superclass = class!(NSWindow);
|
||||||
let mut decl = ClassDecl::new("WinitWindow", window_superclass).unwrap();
|
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(
|
decl.add_method(
|
||||||
sel!(canBecomeMainWindow),
|
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(
|
decl.add_method(
|
||||||
sel!(canBecomeKeyWindow),
|
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())
|
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 struct UnownedWindow {
|
||||||
pub ns_window: IdRef, // never changes
|
pub ns_window: IdRef, // never changes
|
||||||
pub ns_view: IdRef, // never changes
|
pub ns_view: IdRef, // never changes
|
||||||
input_context: IdRef, // never changes
|
input_context: IdRef, // never changes
|
||||||
pub shared_state: Arc<Mutex<SharedState>>,
|
shared_state: Arc<Mutex<SharedState>>,
|
||||||
decorations: AtomicBool,
|
decorations: AtomicBool,
|
||||||
cursor_state: Weak<Mutex<CursorState>>,
|
cursor_state: Weak<Mutex<CursorState>>,
|
||||||
pub inner_rect: Option<PhysicalSize<u32>>,
|
pub inner_rect: Option<PhysicalSize<u32>>,
|
||||||
|
@ -420,6 +469,14 @@ impl UnownedWindow {
|
||||||
Ok((window, delegate))
|
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) {
|
fn set_style_mask_async(&self, mask: NSWindowStyleMask) {
|
||||||
unsafe { util::set_style_mask_async(*self.ns_window, *self.ns_view, mask) };
|
unsafe { util::set_style_mask_async(*self.ns_window, *self.ns_view, mask) };
|
||||||
}
|
}
|
||||||
|
@ -530,10 +587,8 @@ impl UnownedWindow {
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn set_resizable(&self, resizable: bool) {
|
pub fn set_resizable(&self, resizable: bool) {
|
||||||
let fullscreen = {
|
let fullscreen = {
|
||||||
trace!("Locked shared state in `set_resizable`");
|
let mut shared_state_lock = self.lock_shared_state("set_resizable");
|
||||||
let mut shared_state_lock = self.shared_state.lock().unwrap();
|
|
||||||
shared_state_lock.resizable = resizable;
|
shared_state_lock.resizable = resizable;
|
||||||
trace!("Unlocked shared state in `set_resizable`");
|
|
||||||
shared_state_lock.fullscreen.is_some()
|
shared_state_lock.fullscreen.is_some()
|
||||||
};
|
};
|
||||||
if !fullscreen {
|
if !fullscreen {
|
||||||
|
@ -653,8 +708,7 @@ impl UnownedWindow {
|
||||||
/// user clicking on the green fullscreen button or programmatically by
|
/// user clicking on the green fullscreen button or programmatically by
|
||||||
/// `toggleFullScreen:`
|
/// `toggleFullScreen:`
|
||||||
pub(crate) fn restore_state_from_fullscreen(&self) {
|
pub(crate) fn restore_state_from_fullscreen(&self) {
|
||||||
trace!("Locked shared state in `restore_state_from_fullscreen`");
|
let mut shared_state_lock = self.lock_shared_state("restore_state_from_fullscreen");
|
||||||
let mut shared_state_lock = self.shared_state.lock().unwrap();
|
|
||||||
|
|
||||||
shared_state_lock.fullscreen = None;
|
shared_state_lock.fullscreen = None;
|
||||||
|
|
||||||
|
@ -662,7 +716,6 @@ impl UnownedWindow {
|
||||||
let mask = self.saved_style(&mut *shared_state_lock);
|
let mask = self.saved_style(&mut *shared_state_lock);
|
||||||
|
|
||||||
drop(shared_state_lock);
|
drop(shared_state_lock);
|
||||||
trace!("Unocked shared state in `restore_state_from_fullscreen`");
|
|
||||||
|
|
||||||
self.set_style_mask_async(mask);
|
self.set_style_mask_async(mask);
|
||||||
self.set_maximized(maximized);
|
self.set_maximized(maximized);
|
||||||
|
@ -705,7 +758,7 @@ impl UnownedWindow {
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn fullscreen(&self) -> Option<Fullscreen> {
|
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()
|
shared_state_lock.fullscreen.clone()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -716,25 +769,20 @@ impl UnownedWindow {
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn set_fullscreen(&self, fullscreen: Option<Fullscreen>) {
|
pub fn set_fullscreen(&self, fullscreen: Option<Fullscreen>) {
|
||||||
trace!("Locked shared state in `set_fullscreen`");
|
let mut shared_state_lock = self.lock_shared_state("set_fullscreen");
|
||||||
let mut shared_state_lock = self.shared_state.lock().unwrap();
|
|
||||||
if shared_state_lock.is_simple_fullscreen {
|
if shared_state_lock.is_simple_fullscreen {
|
||||||
trace!("Unlocked shared state in `set_fullscreen`");
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if shared_state_lock.in_fullscreen_transition {
|
if shared_state_lock.in_fullscreen_transition {
|
||||||
// We can't set fullscreen here.
|
// We can't set fullscreen here.
|
||||||
// Set fullscreen after transition.
|
// Set fullscreen after transition.
|
||||||
shared_state_lock.target_fullscreen = Some(fullscreen);
|
shared_state_lock.target_fullscreen = Some(fullscreen);
|
||||||
trace!("Unlocked shared state in `set_fullscreen`");
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
let old_fullscreen = shared_state_lock.fullscreen.clone();
|
let old_fullscreen = shared_state_lock.fullscreen.clone();
|
||||||
if fullscreen == old_fullscreen {
|
if fullscreen == old_fullscreen {
|
||||||
trace!("Unlocked shared state in `set_fullscreen`");
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
trace!("Unlocked shared state in `set_fullscreen`");
|
|
||||||
drop(shared_state_lock);
|
drop(shared_state_lock);
|
||||||
|
|
||||||
// If the fullscreen is on a different monitor, we must move the window
|
// 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(_))) {
|
if matches!(old_fullscreen, Some(Fullscreen::Borderless(_))) {
|
||||||
unsafe {
|
unsafe {
|
||||||
let app = NSApp();
|
let app = NSApp();
|
||||||
trace!("Locked shared state in `set_fullscreen`");
|
let mut shared_state_lock = self.lock_shared_state("set_fullscreen");
|
||||||
let mut shared_state_lock = self.shared_state.lock().unwrap();
|
|
||||||
shared_state_lock.save_presentation_opts = Some(app.presentationOptions_());
|
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.lock_shared_state("set_fullscreen");
|
||||||
let mut shared_state_lock = self.shared_state.lock().unwrap();
|
|
||||||
shared_state_lock.fullscreen = fullscreen.clone();
|
shared_state_lock.fullscreen = fullscreen.clone();
|
||||||
|
|
||||||
INTERRUPT_EVENT_LOOP_EXIT.store(true, Ordering::SeqCst);
|
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
|
// that the menu bar is disabled. This is done in the window
|
||||||
// delegate in `window:willUseFullScreenPresentationOptions:`.
|
// delegate in `window:willUseFullScreenPresentationOptions:`.
|
||||||
let app = NSApp();
|
let app = NSApp();
|
||||||
trace!("Locked shared state in `set_fullscreen`");
|
|
||||||
shared_state_lock.save_presentation_opts = Some(app.presentationOptions_());
|
shared_state_lock.save_presentation_opts = Some(app.presentationOptions_());
|
||||||
|
|
||||||
let presentation_options =
|
let presentation_options =
|
||||||
|
@ -918,7 +963,6 @@ impl UnownedWindow {
|
||||||
},
|
},
|
||||||
_ => INTERRUPT_EVENT_LOOP_EXIT.store(false, Ordering::SeqCst),
|
_ => INTERRUPT_EVENT_LOOP_EXIT.store(false, Ordering::SeqCst),
|
||||||
};
|
};
|
||||||
trace!("Unlocked shared state in `set_fullscreen`");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
|
@ -927,9 +971,7 @@ impl UnownedWindow {
|
||||||
self.decorations.store(decorations, Ordering::Release);
|
self.decorations.store(decorations, Ordering::Release);
|
||||||
|
|
||||||
let (fullscreen, resizable) = {
|
let (fullscreen, resizable) = {
|
||||||
trace!("Locked shared state in `set_decorations`");
|
let shared_state_lock = self.lock_shared_state("set_decorations");
|
||||||
let shared_state_lock = self.shared_state.lock().unwrap();
|
|
||||||
trace!("Unlocked shared state in `set_decorations`");
|
|
||||||
(
|
(
|
||||||
shared_state_lock.fullscreen.is_some(),
|
shared_state_lock.fullscreen.is_some(),
|
||||||
shared_state_lock.resizable,
|
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 {
|
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));
|
with_state(this, |state| state.emit_event(WindowEvent::CloseRequested));
|
||||||
trace!("Completed `windowShouldClose:`");
|
|
||||||
NO
|
NO
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "C" fn window_will_close(this: &Object, _: Sel, _: id) {
|
extern "C" fn window_will_close(this: &Object, _: Sel, _: id) {
|
||||||
trace!("Triggered `windowWillClose:`");
|
trace_scope!("windowWillClose:");
|
||||||
with_state(this, |state| unsafe {
|
with_state(this, |state| unsafe {
|
||||||
// `setDelegate:` retains the previous value and then autoreleases it
|
// `setDelegate:` retains the previous value and then autoreleases it
|
||||||
autoreleasepool(|| {
|
autoreleasepool(|| {
|
||||||
|
@ -282,47 +281,42 @@ extern "C" fn window_will_close(this: &Object, _: Sel, _: id) {
|
||||||
});
|
});
|
||||||
state.emit_event(WindowEvent::Destroyed);
|
state.emit_event(WindowEvent::Destroyed);
|
||||||
});
|
});
|
||||||
trace!("Completed `windowWillClose:`");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "C" fn window_did_resize(this: &Object, _: Sel, _: id) {
|
extern "C" fn window_did_resize(this: &Object, _: Sel, _: id) {
|
||||||
trace!("Triggered `windowDidResize:`");
|
trace_scope!("windowDidResize:");
|
||||||
with_state(this, |state| {
|
with_state(this, |state| {
|
||||||
state.emit_resize_event();
|
state.emit_resize_event();
|
||||||
state.emit_move_event();
|
state.emit_move_event();
|
||||||
});
|
});
|
||||||
trace!("Completed `windowDidResize:`");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// This won't be triggered if the move was part of a resize.
|
// This won't be triggered if the move was part of a resize.
|
||||||
extern "C" fn window_did_move(this: &Object, _: Sel, _: id) {
|
extern "C" fn window_did_move(this: &Object, _: Sel, _: id) {
|
||||||
trace!("Triggered `windowDidMove:`");
|
trace_scope!("windowDidMove:");
|
||||||
with_state(this, |state| {
|
with_state(this, |state| {
|
||||||
state.emit_move_event();
|
state.emit_move_event();
|
||||||
});
|
});
|
||||||
trace!("Completed `windowDidMove:`");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "C" fn window_did_change_backing_properties(this: &Object, _: Sel, _: id) {
|
extern "C" fn window_did_change_backing_properties(this: &Object, _: Sel, _: id) {
|
||||||
trace!("Triggered `windowDidChangeBackingProperties:`");
|
trace_scope!("windowDidChangeBackingProperties:");
|
||||||
with_state(this, |state| {
|
with_state(this, |state| {
|
||||||
state.emit_static_scale_factor_changed_event();
|
state.emit_static_scale_factor_changed_event();
|
||||||
});
|
});
|
||||||
trace!("Completed `windowDidChangeBackingProperties:`");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "C" fn window_did_become_key(this: &Object, _: Sel, _: id) {
|
extern "C" fn window_did_become_key(this: &Object, _: Sel, _: id) {
|
||||||
trace!("Triggered `windowDidBecomeKey:`");
|
trace_scope!("windowDidBecomeKey:");
|
||||||
with_state(this, |state| {
|
with_state(this, |state| {
|
||||||
// TODO: center the cursor if the window had mouse grab when it
|
// TODO: center the cursor if the window had mouse grab when it
|
||||||
// lost focus
|
// lost focus
|
||||||
state.emit_event(WindowEvent::Focused(true));
|
state.emit_event(WindowEvent::Focused(true));
|
||||||
});
|
});
|
||||||
trace!("Completed `windowDidBecomeKey:`");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "C" fn window_did_resign_key(this: &Object, _: Sel, _: id) {
|
extern "C" fn window_did_resign_key(this: &Object, _: Sel, _: id) {
|
||||||
trace!("Triggered `windowDidResignKey:`");
|
trace_scope!("windowDidResignKey:");
|
||||||
with_state(this, |state| {
|
with_state(this, |state| {
|
||||||
// It happens rather often, e.g. when the user is Cmd+Tabbing, that the
|
// It happens rather often, e.g. when the user is Cmd+Tabbing, that the
|
||||||
// NSWindowDelegate will receive a didResignKey event despite no event
|
// 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));
|
state.emit_event(WindowEvent::Focused(false));
|
||||||
});
|
});
|
||||||
trace!("Completed `windowDidResignKey:`");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Invoked when the dragged image enters destination bounds or frame
|
/// Invoked when the dragged image enters destination bounds or frame
|
||||||
extern "C" fn dragging_entered(this: &Object, _: Sel, sender: id) -> BOOL {
|
extern "C" fn dragging_entered(this: &Object, _: Sel, sender: id) -> BOOL {
|
||||||
trace!("Triggered `draggingEntered:`");
|
trace_scope!("draggingEntered:");
|
||||||
|
|
||||||
use cocoa::{appkit::NSPasteboard, foundation::NSFastEnumeration};
|
use cocoa::{appkit::NSPasteboard, foundation::NSFastEnumeration};
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
|
@ -376,20 +369,18 @@ extern "C" fn dragging_entered(this: &Object, _: Sel, sender: id) -> BOOL {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
trace!("Completed `draggingEntered:`");
|
|
||||||
YES
|
YES
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Invoked when the image is released
|
/// Invoked when the image is released
|
||||||
extern "C" fn prepare_for_drag_operation(_: &Object, _: Sel, _: id) -> BOOL {
|
extern "C" fn prepare_for_drag_operation(_: &Object, _: Sel, _: id) -> BOOL {
|
||||||
trace!("Triggered `prepareForDragOperation:`");
|
trace_scope!("prepareForDragOperation:");
|
||||||
trace!("Completed `prepareForDragOperation:`");
|
|
||||||
YES
|
YES
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Invoked after the released image has been removed from the screen
|
/// Invoked after the released image has been removed from the screen
|
||||||
extern "C" fn perform_drag_operation(this: &Object, _: Sel, sender: id) -> BOOL {
|
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 cocoa::{appkit::NSPasteboard, foundation::NSFastEnumeration};
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
|
@ -411,35 +402,31 @@ extern "C" fn perform_drag_operation(this: &Object, _: Sel, sender: id) -> BOOL
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
trace!("Completed `performDragOperation:`");
|
|
||||||
YES
|
YES
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Invoked when the dragging operation is complete
|
/// Invoked when the dragging operation is complete
|
||||||
extern "C" fn conclude_drag_operation(_: &Object, _: Sel, _: id) {
|
extern "C" fn conclude_drag_operation(_: &Object, _: Sel, _: id) {
|
||||||
trace!("Triggered `concludeDragOperation:`");
|
trace_scope!("concludeDragOperation:");
|
||||||
trace!("Completed `concludeDragOperation:`");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Invoked when the dragging operation is cancelled
|
/// Invoked when the dragging operation is cancelled
|
||||||
extern "C" fn dragging_exited(this: &Object, _: Sel, _: id) {
|
extern "C" fn dragging_exited(this: &Object, _: Sel, _: id) {
|
||||||
trace!("Triggered `draggingExited:`");
|
trace_scope!("draggingExited:");
|
||||||
with_state(this, |state| {
|
with_state(this, |state| {
|
||||||
state.emit_event(WindowEvent::HoveredFileCancelled)
|
state.emit_event(WindowEvent::HoveredFileCancelled)
|
||||||
});
|
});
|
||||||
trace!("Completed `draggingExited:`");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Invoked when before enter fullscreen
|
/// Invoked when before enter fullscreen
|
||||||
extern "C" fn window_will_enter_fullscreen(this: &Object, _: Sel, _: id) {
|
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);
|
INTERRUPT_EVENT_LOOP_EXIT.store(true, Ordering::SeqCst);
|
||||||
|
|
||||||
with_state(this, |state| {
|
with_state(this, |state| {
|
||||||
state.with_window(|window| {
|
state.with_window(|window| {
|
||||||
trace!("Locked shared state in `window_will_enter_fullscreen`");
|
let mut shared_state = window.lock_shared_state("window_will_enter_fullscreen");
|
||||||
let mut shared_state = window.shared_state.lock().unwrap();
|
|
||||||
shared_state.maximized = window.is_zoomed();
|
shared_state.maximized = window.is_zoomed();
|
||||||
match shared_state.fullscreen {
|
match shared_state.fullscreen {
|
||||||
// Exclusive mode sets the state in `set_fullscreen` as the user
|
// 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;
|
shared_state.in_fullscreen_transition = true;
|
||||||
trace!("Unlocked shared state in `window_will_enter_fullscreen`");
|
|
||||||
})
|
})
|
||||||
});
|
});
|
||||||
trace!("Completed `windowWillEnterFullscreen:`");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Invoked when before exit fullscreen
|
/// Invoked when before exit fullscreen
|
||||||
extern "C" fn window_will_exit_fullscreen(this: &Object, _: Sel, _: id) {
|
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);
|
INTERRUPT_EVENT_LOOP_EXIT.store(true, Ordering::SeqCst);
|
||||||
|
|
||||||
with_state(this, |state| {
|
with_state(this, |state| {
|
||||||
state.with_window(|window| {
|
state.with_window(|window| {
|
||||||
trace!("Locked shared state in `window_will_exit_fullscreen`");
|
let mut shared_state = window.lock_shared_state("window_will_exit_fullscreen");
|
||||||
let mut shared_state = window.shared_state.lock().unwrap();
|
|
||||||
shared_state.in_fullscreen_transition = true;
|
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(
|
extern "C" fn window_will_use_fullscreen_presentation_options(
|
||||||
|
@ -487,6 +469,7 @@ extern "C" fn window_will_use_fullscreen_presentation_options(
|
||||||
_: id,
|
_: id,
|
||||||
proposed_options: NSUInteger,
|
proposed_options: NSUInteger,
|
||||||
) -> NSUInteger {
|
) -> NSUInteger {
|
||||||
|
trace_scope!("window:willUseFullScreenPresentationOptions:");
|
||||||
// Generally, games will want to disable the menu bar and the dock. Ideally,
|
// Generally, games will want to disable the menu bar and the dock. Ideally,
|
||||||
// this would be configurable by the user. Unfortunately because of our
|
// this would be configurable by the user. Unfortunately because of our
|
||||||
// `CGShieldingWindowLevel() + 1` hack (see `set_fullscreen`), our window is
|
// `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;
|
let mut options: NSUInteger = proposed_options;
|
||||||
with_state(this, |state| {
|
with_state(this, |state| {
|
||||||
state.with_window(|window| {
|
state.with_window(|window| {
|
||||||
trace!("Locked shared state in `window_will_use_fullscreen_presentation_options`");
|
let shared_state =
|
||||||
let shared_state = window.shared_state.lock().unwrap();
|
window.lock_shared_state("window_will_use_fullscreen_presentation_options");
|
||||||
if let Some(Fullscreen::Exclusive(_)) = shared_state.fullscreen {
|
if let Some(Fullscreen::Exclusive(_)) = shared_state.fullscreen {
|
||||||
options = (NSApplicationPresentationOptions::NSApplicationPresentationFullScreen
|
options = (NSApplicationPresentationOptions::NSApplicationPresentationFullScreen
|
||||||
| NSApplicationPresentationOptions::NSApplicationPresentationHideDock
|
| NSApplicationPresentationOptions::NSApplicationPresentationHideDock
|
||||||
| NSApplicationPresentationOptions::NSApplicationPresentationHideMenuBar)
|
| NSApplicationPresentationOptions::NSApplicationPresentationHideMenuBar)
|
||||||
.bits();
|
.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
|
/// Invoked when entered fullscreen
|
||||||
extern "C" fn window_did_enter_fullscreen(this: &Object, _: Sel, _: id) {
|
extern "C" fn window_did_enter_fullscreen(this: &Object, _: Sel, _: id) {
|
||||||
|
trace_scope!("windowDidEnterFullscreen:");
|
||||||
INTERRUPT_EVENT_LOOP_EXIT.store(false, Ordering::SeqCst);
|
INTERRUPT_EVENT_LOOP_EXIT.store(false, Ordering::SeqCst);
|
||||||
|
|
||||||
trace!("Triggered `windowDidEnterFullscreen:`");
|
|
||||||
with_state(this, |state| {
|
with_state(this, |state| {
|
||||||
state.initial_fullscreen = false;
|
state.initial_fullscreen = false;
|
||||||
state.with_window(|window| {
|
state.with_window(|window| {
|
||||||
trace!("Locked shared state in `window_did_enter_fullscreen`");
|
let mut shared_state = window.lock_shared_state("window_did_enter_fullscreen");
|
||||||
let mut shared_state = window.shared_state.lock().unwrap();
|
|
||||||
shared_state.in_fullscreen_transition = false;
|
shared_state.in_fullscreen_transition = false;
|
||||||
let target_fullscreen = shared_state.target_fullscreen.take();
|
let target_fullscreen = shared_state.target_fullscreen.take();
|
||||||
trace!("Unlocked shared state in `window_did_enter_fullscreen`");
|
|
||||||
drop(shared_state);
|
drop(shared_state);
|
||||||
if let Some(target_fullscreen) = target_fullscreen {
|
if let Some(target_fullscreen) = target_fullscreen {
|
||||||
window.set_fullscreen(target_fullscreen);
|
window.set_fullscreen(target_fullscreen);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
trace!("Completed `windowDidEnterFullscreen:`");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Invoked when exited fullscreen
|
/// Invoked when exited fullscreen
|
||||||
extern "C" fn window_did_exit_fullscreen(this: &Object, _: Sel, _: id) {
|
extern "C" fn window_did_exit_fullscreen(this: &Object, _: Sel, _: id) {
|
||||||
|
trace_scope!("windowDidExitFullscreen:");
|
||||||
INTERRUPT_EVENT_LOOP_EXIT.store(false, Ordering::SeqCst);
|
INTERRUPT_EVENT_LOOP_EXIT.store(false, Ordering::SeqCst);
|
||||||
|
|
||||||
trace!("Triggered `windowDidExitFullscreen:`");
|
|
||||||
with_state(this, |state| {
|
with_state(this, |state| {
|
||||||
state.with_window(|window| {
|
state.with_window(|window| {
|
||||||
window.restore_state_from_fullscreen();
|
window.restore_state_from_fullscreen();
|
||||||
trace!("Locked shared state in `window_did_exit_fullscreen`");
|
let mut shared_state = window.lock_shared_state("window_did_exit_fullscreen");
|
||||||
let mut shared_state = window.shared_state.lock().unwrap();
|
|
||||||
shared_state.in_fullscreen_transition = false;
|
shared_state.in_fullscreen_transition = false;
|
||||||
let target_fullscreen = shared_state.target_fullscreen.take();
|
let target_fullscreen = shared_state.target_fullscreen.take();
|
||||||
trace!("Unlocked shared state in `window_did_exit_fullscreen`");
|
|
||||||
drop(shared_state);
|
drop(shared_state);
|
||||||
if let Some(target_fullscreen) = target_fullscreen {
|
if let Some(target_fullscreen) = target_fullscreen {
|
||||||
window.set_fullscreen(target_fullscreen);
|
window.set_fullscreen(target_fullscreen);
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
});
|
});
|
||||||
trace!("Completed `windowDidExitFullscreen:`");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Invoked when fail to enter fullscreen
|
/// 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
|
/// 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.
|
/// 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) {
|
extern "C" fn window_did_fail_to_enter_fullscreen(this: &Object, _: Sel, _: id) {
|
||||||
trace!("Triggered `windowDidFailToEnterFullscreen:`");
|
trace_scope!("windowDidFailToEnterFullscreen:");
|
||||||
with_state(this, |state| {
|
with_state(this, |state| {
|
||||||
state.with_window(|window| {
|
state.with_window(|window| {
|
||||||
trace!("Locked shared state in `window_did_fail_to_enter_fullscreen`");
|
let mut shared_state = window.lock_shared_state("window_did_fail_to_enter_fullscreen");
|
||||||
let mut shared_state = window.shared_state.lock().unwrap();
|
|
||||||
shared_state.in_fullscreen_transition = false;
|
shared_state.in_fullscreen_transition = false;
|
||||||
shared_state.target_fullscreen = None;
|
shared_state.target_fullscreen = None;
|
||||||
trace!("Unlocked shared state in `window_did_fail_to_enter_fullscreen`");
|
|
||||||
});
|
});
|
||||||
if state.initial_fullscreen {
|
if state.initial_fullscreen {
|
||||||
let _: () = unsafe {
|
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());
|
state.with_window(|window| window.restore_state_from_fullscreen());
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
trace!("Completed `windowDidFailToEnterFullscreen:`");
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue