From b0232ca225256e8543116c289bcd60ef54ee28cb Mon Sep 17 00:00:00 2001 From: Ryan McGrath Date: Wed, 25 Mar 2020 19:57:47 -0700 Subject: [PATCH] Window movement delegate callback support --- appkit/window/class.rs | 69 ++++++++++++++++++++++++++++++++- appkit/window/controller/mod.rs | 16 -------- appkit/window/traits.rs | 8 ++++ 3 files changed, 76 insertions(+), 17 deletions(-) diff --git a/appkit/window/class.rs b/appkit/window/class.rs index 2782895..4a3f360 100644 --- a/appkit/window/class.rs +++ b/appkit/window/class.rs @@ -12,7 +12,7 @@ use crate::foundation::id; use crate::utils::load; use crate::window::{WindowDelegate, WINDOW_DELEGATE_PTR}; -/// Called when an `NSWindow` receives a `windowWillClose:` event. +/// Called when an `NSWindowDelegate` receives a `windowWillClose:` event. /// Good place to clean up memory and what not. extern fn will_close(this: &Object, _: Sel, _: id) { let window = load::(this, WINDOW_DELEGATE_PTR); @@ -25,6 +25,66 @@ extern fn will_close(this: &Object, _: Sel, _: id) { Rc::into_raw(window); } +/// Called when an `NSWindowDelegate` receives a `windowWillMove:` event. +extern fn will_move(this: &Object, _: Sel, _: id) { + let window = load::(this, WINDOW_DELEGATE_PTR); + + { + let window = window.borrow(); + (*window).will_move(); + } + + Rc::into_raw(window); +} + +/// Called when an `NSWindowDelegate` receives a `windowDidMove:` event. +extern fn did_move(this: &Object, _: Sel, _: id) { + let window = load::(this, WINDOW_DELEGATE_PTR); + + { + let window = window.borrow(); + (*window).did_move(); + } + + Rc::into_raw(window); +} + +/// Called when an `NSWindowDelegate` receives a `windowDidChangeScreen:` event. +extern fn did_change_screen(this: &Object, _: Sel, _: id) { + let window = load::(this, WINDOW_DELEGATE_PTR); + + { + let window = window.borrow(); + (*window).did_change_screen(); + } + + Rc::into_raw(window); +} + +/// Called when an `NSWindowDelegate` receives a `windowDidChangeScreenProfile:` event. +extern fn did_change_screen_profile(this: &Object, _: Sel, _: id) { + let window = load::(this, WINDOW_DELEGATE_PTR); + + { + let window = window.borrow(); + (*window).did_change_screen_profile(); + } + + Rc::into_raw(window); +} + +/// Called when an `NSWindowDelegate` receives a `windowDidChangeBackingProperties:` event. +extern fn did_change_backing_properties(this: &Object, _: Sel, _: id) { + let window = load::(this, WINDOW_DELEGATE_PTR); + + { + let window = window.borrow(); + (*window).did_change_backing_properties(); + } + + Rc::into_raw(window); +} + /// Injects an `NSWindow` subclass, with some callback and pointer ivars for what we /// need to do. pub(crate) fn register_window_class() -> *const Class { @@ -58,6 +118,13 @@ pub(crate) fn register_window_class_with_delegate() -> *const // NSWindowDelegate methods decl.add_method(sel!(windowWillClose:), will_close:: as extern fn(&Object, _, _)); + + // Moving Windows + decl.add_method(sel!(windowWillMove:), will_move:: as extern fn(&Object, _, _)); + decl.add_method(sel!(windowDidMove:), did_move:: as extern fn(&Object, _, _)); + decl.add_method(sel!(windowDidChangeScreen:), did_change_screen:: as extern fn(&Object, _, _)); + decl.add_method(sel!(windowDidChangeScreenProfile:), did_change_screen_profile:: as extern fn(&Object, _, _)); + decl.add_method(sel!(windowDidChangeBackingProperties:), did_change_backing_properties:: as extern fn(&Object, _, _)); DELEGATE_CLASS = decl.register(); }); diff --git a/appkit/window/controller/mod.rs b/appkit/window/controller/mod.rs index ca4552b..f8ce31a 100644 --- a/appkit/window/controller/mod.rs +++ b/appkit/window/controller/mod.rs @@ -74,19 +74,3 @@ impl WindowController where T: WindowDelegate + 'static { } } } - -/*impl Drop for Window { - /// When a Window is dropped on the Rust side, we want to ensure that we break the delegate - /// link on the Objective-C side. While this shouldn't actually be an issue, I'd rather be - /// safer than sorry. - /// - /// We also clean up our loopback pointer that we use for callbacks. - fn drop(&mut self) { - unsafe { - let window: id = msg_send![*objc_controller, window]; - let _: () = msg_send![window, setDelegate:nil]; - - let _ = Rc::from_raw(self.internal_callback_ptr); - } - } -}*/ diff --git a/appkit/window/traits.rs b/appkit/window/traits.rs index e0a5e1c..af82826 100644 --- a/appkit/window/traits.rs +++ b/appkit/window/traits.rs @@ -28,6 +28,14 @@ pub trait WindowDelegate { /// such as rendering in retina vs non-retina environments. fn did_change_screen(&self) {} + /// Fired when the window profile changes screens - you might find this useful for certain scenarios, + /// such as rendering in retina vs non-retina environments. + fn did_change_screen_profile(&self) {} + + /// Fired when the window backing properties change - you might find this useful for certain scenarios, + /// such as rendering in retina vs non-retina environments. It's rare to need this though. + fn did_change_backing_properties(&self) {} + /// Fires when this window is about to become the key window. fn did_become_key(&self) {}