Window movement delegate callback support

This commit is contained in:
Ryan McGrath 2020-03-25 19:57:47 -07:00
parent 34b02b28b5
commit b0232ca225
No known key found for this signature in database
GPG key ID: 811674B62B666830
3 changed files with 76 additions and 17 deletions

View file

@ -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<T: WindowDelegate>(this: &Object, _: Sel, _: id) {
let window = load::<T>(this, WINDOW_DELEGATE_PTR);
@ -25,6 +25,66 @@ extern fn will_close<T: WindowDelegate>(this: &Object, _: Sel, _: id) {
Rc::into_raw(window);
}
/// Called when an `NSWindowDelegate` receives a `windowWillMove:` event.
extern fn will_move<T: WindowDelegate>(this: &Object, _: Sel, _: id) {
let window = load::<T>(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<T: WindowDelegate>(this: &Object, _: Sel, _: id) {
let window = load::<T>(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<T: WindowDelegate>(this: &Object, _: Sel, _: id) {
let window = load::<T>(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<T: WindowDelegate>(this: &Object, _: Sel, _: id) {
let window = load::<T>(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<T: WindowDelegate>(this: &Object, _: Sel, _: id) {
let window = load::<T>(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<T: WindowDelegate>() -> *const
// NSWindowDelegate methods
decl.add_method(sel!(windowWillClose:), will_close::<T> as extern fn(&Object, _, _));
// Moving Windows
decl.add_method(sel!(windowWillMove:), will_move::<T> as extern fn(&Object, _, _));
decl.add_method(sel!(windowDidMove:), did_move::<T> as extern fn(&Object, _, _));
decl.add_method(sel!(windowDidChangeScreen:), did_change_screen::<T> as extern fn(&Object, _, _));
decl.add_method(sel!(windowDidChangeScreenProfile:), did_change_screen_profile::<T> as extern fn(&Object, _, _));
decl.add_method(sel!(windowDidChangeBackingProperties:), did_change_backing_properties::<T> as extern fn(&Object, _, _));
DELEGATE_CLASS = decl.register();
});

View file

@ -74,19 +74,3 @@ impl<T> WindowController<T> where T: WindowDelegate + 'static {
}
}
}
/*impl<T> Drop for Window<T> {
/// 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);
}
}
}*/

View file

@ -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) {}