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
//! they go away one day.
use std::rc::Rc;
use std::cell::RefCell;
use std::{slice, str};
use std::os::raw::c_char;
@ -9,6 +11,7 @@ use cocoa::base::id;
use cocoa::foundation::NSString;
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`.
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()
}
}
/// 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
//! color, and enforcing layer backing by default.
use std::cell::RefCell;
use std::rc::Rc;
use std::sync::Once;
@ -22,6 +21,8 @@ use objc_id::Id;
use crate::constants::{BACKGROUND_COLOR, VIEW_CONTROLLER_PTR};
use crate::dragdrop::DragInfo;
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.
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.
extern fn dragging_entered<T: ViewController>(this: &mut Object, _: Sel, info: id) -> NSUInteger {
unsafe {
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 view = load::<T>(this, VIEW_CONTROLLER_PTR);
let response = {
let v = view.borrow();
(*v).dragging_entered(DragInfo {
info: Id::from_ptr(info)
info: unsafe { Id::from_ptr(info) }
}).into()
};
Rc::into_raw(view);
response
}
}
/// 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 {
unsafe {
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 view = load::<T>(this, VIEW_CONTROLLER_PTR);
let response = {
let v = view.borrow();
match (*v).prepare_for_drag_operation(DragInfo {
info: Id::from_ptr(info)
info: unsafe { Id::from_ptr(info) }
}) {
true => YES,
false => NO
@ -80,21 +74,17 @@ extern fn prepare_for_drag_operation<T: ViewController>(this: &mut Object, _: Se
Rc::into_raw(view);
response
}
}
/// Called when a drag/drop operation has entered this view.
extern fn perform_drag_operation<T: ViewController>(this: &mut Object, _: Sel, info: id) -> BOOL {
unsafe {
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 view = load::<T>(this, VIEW_CONTROLLER_PTR);
let response = {
let v = view.borrow();
match (*v).perform_drag_operation(DragInfo {
info: Id::from_ptr(info)
info: unsafe { Id::from_ptr(info) }
}) {
true => YES,
false => NO
@ -103,45 +93,34 @@ extern fn perform_drag_operation<T: ViewController>(this: &mut Object, _: Sel, i
Rc::into_raw(view);
response
}
}
/// Called when a drag/drop operation has entered this view.
extern fn conclude_drag_operation<T: ViewController>(this: &mut Object, _: Sel, info: id) {
unsafe {
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 view = load::<T>(this, VIEW_CONTROLLER_PTR);
let response = {
{
let v = view.borrow();
(*v).conclude_drag_operation(DragInfo {
info: Id::from_ptr(info)
info: unsafe { Id::from_ptr(info) }
});
};
}
Rc::into_raw(view);
response
}
}
/// Called when a drag/drop operation has entered this view.
extern fn dragging_exited<T: ViewController>(this: &mut Object, _: Sel, info: id) {
unsafe {
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 view = load::<T>(this, VIEW_CONTROLLER_PTR);
let response = {
{
let v = view.borrow();
(*v).dragging_exited(DragInfo {
info: Id::from_ptr(info)
info: unsafe { Id::from_ptr(info) }
});
};
}
Rc::into_raw(view);
response
}
}
/// 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
//! into the Objective C runtime, which loops back to give us lifecycle methods.
use std::rc::Rc;
use std::sync::Once;
use cocoa::base::id;
@ -9,18 +10,21 @@ use objc::declare::ClassDecl;
use objc::runtime::{Class, Object, Sel};
use objc::{class, sel, sel_impl};
use crate::constants::WINDOW_CONTROLLER_PTR;
use crate::utils::load;
use crate::window::WindowController;
static WINDOW_CONTROLLER_PTR: &str = "rstWindowController";
/// Called when an `NSWindow` receives a `windowWillClose:` event.
/// Good place to clean up memory and what not.
extern fn will_close<T: WindowController>(this: &Object, _: Sel, _: id) {
unsafe {
let window_ptr: usize = *this.get_ivar(WINDOW_CONTROLLER_PTR);
let window = window_ptr as *const T;
let window = load::<T>(this, WINDOW_CONTROLLER_PTR);
{
let window = window.borrow();
(*window).will_close();
}
Rc::into_raw(window);
}
/// 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::cell::RefCell;
use cocoa::base::{id, nil, YES, NO};
use cocoa::foundation::{NSSize, NSString};
use cocoa::base::{id, nil};
use objc::{msg_send, sel, sel_impl};
use objc_id::ShareId;