Clean up some pointer shuffling stuff

This commit is contained in:
Ryan McGrath 2020-03-11 18:38:33 -07:00
parent f49eff24f9
commit 8a5af12b47
No known key found for this signature in database
GPG key ID: 811674B62B666830
4 changed files with 79 additions and 83 deletions

View file

@ -2,6 +2,8 @@
//! belong to. These are typically internal, and if you rely on them... well, don't be surprised if //! belong to. These are typically internal, and if you rely on them... well, don't be surprised if
//! they go away one day. //! they go away one day.
use std::rc::Rc;
use std::cell::RefCell;
use std::{slice, str}; use std::{slice, str};
use std::os::raw::c_char; use std::os::raw::c_char;
@ -9,6 +11,7 @@ use cocoa::base::id;
use cocoa::foundation::NSString; use cocoa::foundation::NSString;
use objc::{msg_send, sel, sel_impl}; use objc::{msg_send, sel, sel_impl};
use objc::runtime::Object;
/// A utility method for taking an `NSString` and bridging it to a Rust `&str`. /// A utility method for taking an `NSString` and bridging it to a Rust `&str`.
pub fn str_from(nsstring: id) -> &'static str { pub fn str_from(nsstring: id) -> &'static str {
@ -23,3 +26,14 @@ pub fn str_from(nsstring: id) -> &'static str {
str::from_utf8(bytes).unwrap() str::from_utf8(bytes).unwrap()
} }
} }
/// Used for moving a pointer back into an Rc, so we can work with the object held behind it. Note
/// that it's very important to make sure you reverse this when you're done (using
/// `Rc::into_raw()`) otherwise you'll cause problems due to the `Drop` logic.
pub fn load<T>(this: &Object, ptr: &str) -> Rc<RefCell<T>> {
unsafe {
let ptr: usize = *this.get_ivar(ptr);
let view_ptr = ptr as *const RefCell<T>;
Rc::from_raw(view_ptr)
}
}

View file

@ -7,7 +7,6 @@
//! for in the modern era. It also implements a few helpers for things like setting a background //! for in the modern era. It also implements a few helpers for things like setting a background
//! color, and enforcing layer backing by default. //! color, and enforcing layer backing by default.
use std::cell::RefCell;
use std::rc::Rc; use std::rc::Rc;
use std::sync::Once; use std::sync::Once;
@ -22,6 +21,8 @@ use objc_id::Id;
use crate::constants::{BACKGROUND_COLOR, VIEW_CONTROLLER_PTR}; use crate::constants::{BACKGROUND_COLOR, VIEW_CONTROLLER_PTR};
use crate::dragdrop::DragInfo; use crate::dragdrop::DragInfo;
use crate::view::traits::ViewController; use crate::view::traits::ViewController;
use crate::utils::load;
/// Enforces normalcy, or: a needlessly cruel method in terms of the name. You get the idea though. /// Enforces normalcy, or: a needlessly cruel method in terms of the name. You get the idea though.
extern fn enforce_normalcy(_: &Object, _: Sel) -> BOOL { extern fn enforce_normalcy(_: &Object, _: Sel) -> BOOL {
@ -42,36 +43,29 @@ extern fn update_layer(this: &Object, _: Sel) {
/// Called when a drag/drop operation has entered this view. /// Called when a drag/drop operation has entered this view.
extern fn dragging_entered<T: ViewController>(this: &mut Object, _: Sel, info: id) -> NSUInteger { extern fn dragging_entered<T: ViewController>(this: &mut Object, _: Sel, info: id) -> NSUInteger {
unsafe { let view = load::<T>(this, VIEW_CONTROLLER_PTR);
let ptr: usize = *this.get_ivar(VIEW_CONTROLLER_PTR);
let view_ptr = ptr as *const RefCell<T>;
let view = Rc::from_raw(view_ptr);
let response = { let response = {
let v = view.borrow(); let v = view.borrow();
(*v).dragging_entered(DragInfo { (*v).dragging_entered(DragInfo {
info: Id::from_ptr(info) info: unsafe { Id::from_ptr(info) }
}).into() }).into()
}; };
Rc::into_raw(view); Rc::into_raw(view);
response response
} }
}
/// Called when a drag/drop operation has entered this view. /// Called when a drag/drop operation has entered this view.
extern fn prepare_for_drag_operation<T: ViewController>(this: &mut Object, _: Sel, info: id) -> BOOL { extern fn prepare_for_drag_operation<T: ViewController>(this: &mut Object, _: Sel, info: id) -> BOOL {
unsafe { let view = load::<T>(this, VIEW_CONTROLLER_PTR);
let ptr: usize = *this.get_ivar(VIEW_CONTROLLER_PTR);
let view_ptr = ptr as *const RefCell<T>;
let view = Rc::from_raw(view_ptr);
let response = { let response = {
let v = view.borrow(); let v = view.borrow();
match (*v).prepare_for_drag_operation(DragInfo { match (*v).prepare_for_drag_operation(DragInfo {
info: Id::from_ptr(info) info: unsafe { Id::from_ptr(info) }
}) { }) {
true => YES, true => YES,
false => NO false => NO
@ -81,20 +75,16 @@ extern fn prepare_for_drag_operation<T: ViewController>(this: &mut Object, _: Se
Rc::into_raw(view); Rc::into_raw(view);
response response
} }
}
/// Called when a drag/drop operation has entered this view. /// Called when a drag/drop operation has entered this view.
extern fn perform_drag_operation<T: ViewController>(this: &mut Object, _: Sel, info: id) -> BOOL { extern fn perform_drag_operation<T: ViewController>(this: &mut Object, _: Sel, info: id) -> BOOL {
unsafe { let view = load::<T>(this, VIEW_CONTROLLER_PTR);
let ptr: usize = *this.get_ivar(VIEW_CONTROLLER_PTR);
let view_ptr = ptr as *const RefCell<T>;
let view = Rc::from_raw(view_ptr);
let response = { let response = {
let v = view.borrow(); let v = view.borrow();
match (*v).perform_drag_operation(DragInfo { match (*v).perform_drag_operation(DragInfo {
info: Id::from_ptr(info) info: unsafe { Id::from_ptr(info) }
}) { }) {
true => YES, true => YES,
false => NO false => NO
@ -104,44 +94,33 @@ extern fn perform_drag_operation<T: ViewController>(this: &mut Object, _: Sel, i
Rc::into_raw(view); Rc::into_raw(view);
response response
} }
}
/// Called when a drag/drop operation has entered this view. /// Called when a drag/drop operation has entered this view.
extern fn conclude_drag_operation<T: ViewController>(this: &mut Object, _: Sel, info: id) { extern fn conclude_drag_operation<T: ViewController>(this: &mut Object, _: Sel, info: id) {
unsafe { let view = load::<T>(this, VIEW_CONTROLLER_PTR);
let ptr: usize = *this.get_ivar(VIEW_CONTROLLER_PTR);
let view_ptr = ptr as *const RefCell<T>;
let view = Rc::from_raw(view_ptr);
let response = { {
let v = view.borrow(); let v = view.borrow();
(*v).conclude_drag_operation(DragInfo { (*v).conclude_drag_operation(DragInfo {
info: Id::from_ptr(info) info: unsafe { Id::from_ptr(info) }
}); });
}; }
Rc::into_raw(view); Rc::into_raw(view);
response
}
} }
/// Called when a drag/drop operation has entered this view. /// Called when a drag/drop operation has entered this view.
extern fn dragging_exited<T: ViewController>(this: &mut Object, _: Sel, info: id) { extern fn dragging_exited<T: ViewController>(this: &mut Object, _: Sel, info: id) {
unsafe { let view = load::<T>(this, VIEW_CONTROLLER_PTR);
let ptr: usize = *this.get_ivar(VIEW_CONTROLLER_PTR);
let view_ptr = ptr as *const RefCell<T>;
let view = Rc::from_raw(view_ptr);
let response = { {
let v = view.borrow(); let v = view.borrow();
(*v).dragging_exited(DragInfo { (*v).dragging_exited(DragInfo {
info: Id::from_ptr(info) info: unsafe { Id::from_ptr(info) }
}); });
}; }
Rc::into_raw(view); Rc::into_raw(view);
response
}
} }
/// Injects an `NSView` subclass, with some callback and pointer ivars for what we /// Injects an `NSView` subclass, with some callback and pointer ivars for what we

View file

@ -1,6 +1,7 @@
//! Everything useful for the `WindowController`. Handles injecting an `NSWindowController` subclass //! Everything useful for the `WindowController`. Handles injecting an `NSWindowController` subclass
//! into the Objective C runtime, which loops back to give us lifecycle methods. //! into the Objective C runtime, which loops back to give us lifecycle methods.
use std::rc::Rc;
use std::sync::Once; use std::sync::Once;
use cocoa::base::id; use cocoa::base::id;
@ -9,18 +10,21 @@ use objc::declare::ClassDecl;
use objc::runtime::{Class, Object, Sel}; use objc::runtime::{Class, Object, Sel};
use objc::{class, sel, sel_impl}; use objc::{class, sel, sel_impl};
use crate::constants::WINDOW_CONTROLLER_PTR;
use crate::utils::load;
use crate::window::WindowController; use crate::window::WindowController;
static WINDOW_CONTROLLER_PTR: &str = "rstWindowController";
/// Called when an `NSWindow` receives a `windowWillClose:` event. /// Called when an `NSWindow` receives a `windowWillClose:` event.
/// Good place to clean up memory and what not. /// Good place to clean up memory and what not.
extern fn will_close<T: WindowController>(this: &Object, _: Sel, _: id) { extern fn will_close<T: WindowController>(this: &Object, _: Sel, _: id) {
unsafe { let window = load::<T>(this, WINDOW_CONTROLLER_PTR);
let window_ptr: usize = *this.get_ivar(WINDOW_CONTROLLER_PTR);
let window = window_ptr as *const T; {
let window = window.borrow();
(*window).will_close(); (*window).will_close();
} }
Rc::into_raw(window);
} }
/// Injects an `NSWindowController` subclass, with some callback and pointer ivars for what we /// Injects an `NSWindowController` subclass, with some callback and pointer ivars for what we

View file

@ -4,8 +4,7 @@
use std::rc::Rc; use std::rc::Rc;
use std::cell::RefCell; use std::cell::RefCell;
use cocoa::base::{id, nil, YES, NO}; use cocoa::base::{id, nil};
use cocoa::foundation::{NSSize, NSString};
use objc::{msg_send, sel, sel_impl}; use objc::{msg_send, sel, sel_impl};
use objc_id::ShareId; use objc_id::ShareId;