Ongoing work on supporting GTK, had to rework some concepts due to the way gtk-rs works.
This commit is contained in:
parent
f15cf258af
commit
0d8a14ce67
20 changed files with 378 additions and 301 deletions
|
|
@ -2,6 +2,8 @@
|
|||
//! Cocoa and associated widgets. This also handles looping back
|
||||
//! lifecycle events, such as window resizing or close events.
|
||||
|
||||
use std::cell::RefCell;
|
||||
|
||||
use std::sync::{Once, ONCE_INIT};
|
||||
|
||||
use cocoa::base::{id, nil, YES, NO};
|
||||
|
|
@ -13,11 +15,10 @@ use objc::declare::ClassDecl;
|
|||
use objc::runtime::{Class, Object, Sel};
|
||||
use objc::{msg_send, sel, sel_impl};
|
||||
|
||||
use alchemy_lifecycle::traits::{AppDelegate, Component};
|
||||
use alchemy_lifecycle::traits::WindowDelegate;
|
||||
use alchemy_styles::Appearance;
|
||||
|
||||
static APP_PTR: &str = "alchemyAppPtr";
|
||||
static WINDOW_MANAGER_ID: &str = "alchemyWindowManagerID";
|
||||
static WINDOW_PTR: &str = "alchemyWindowPtr";
|
||||
|
||||
/// A wrapper for `NSWindow`. Holds (retains) pointers for the Objective-C runtime
|
||||
/// where our `NSWindow` and associated delegate live.
|
||||
|
|
@ -30,7 +31,7 @@ impl Window {
|
|||
/// Creates a new `NSWindow` instance, configures it appropriately (e.g, titlebar appearance),
|
||||
/// injects an `NSObject` delegate wrapper, and retains the necessary Objective-C runtime
|
||||
/// pointers.
|
||||
pub fn new<T: AppDelegate>(window_id: usize, content_view: ShareId<Object>, app_ptr: *const T) -> Window {
|
||||
pub fn new<T: WindowDelegate>(content_view: ShareId<Object>, window_ptr: *const RefCell<T>) -> Window {
|
||||
let dimensions = NSRect::new(NSPoint::new(0., 0.), NSSize::new(0., 0.));
|
||||
|
||||
let style = NSWindowStyleMask::NSResizableWindowMask |
|
||||
|
|
@ -45,17 +46,13 @@ impl Window {
|
|||
NO
|
||||
).autorelease();
|
||||
|
||||
msg_send![window, setTitlebarAppearsTransparent:YES];
|
||||
//msg_send![window, setTitleVisibility:1];
|
||||
|
||||
// This is very important! NSWindow is an old class and has some behavior that we need
|
||||
// to disable, like... this. If we don't set this, we'll segfault entirely because the
|
||||
// Objective-C runtime gets out of sync.
|
||||
msg_send![window, setReleasedWhenClosed:NO];
|
||||
|
||||
//if let Some(view_ptr) = content_view.borrow_native_backing_node() {
|
||||
msg_send![window, setContentView:content_view];
|
||||
//}
|
||||
msg_send![window, setTitlebarAppearsTransparent:YES];
|
||||
msg_send![window, setContentView:content_view];
|
||||
|
||||
ShareId::from_ptr(window)
|
||||
};
|
||||
|
|
@ -63,8 +60,7 @@ impl Window {
|
|||
let delegate = unsafe {
|
||||
let delegate_class = register_window_class::<T>();
|
||||
let delegate: id = msg_send![delegate_class, new];
|
||||
(&mut *delegate).set_ivar(APP_PTR, app_ptr as usize);
|
||||
(&mut *delegate).set_ivar(WINDOW_MANAGER_ID, window_id);
|
||||
(&mut *delegate).set_ivar(WINDOW_PTR, window_ptr as usize);
|
||||
msg_send![inner, setDelegate:delegate];
|
||||
ShareId::from_ptr(delegate)
|
||||
};
|
||||
|
|
@ -136,27 +132,25 @@ impl Drop for Window {
|
|||
|
||||
/// Called when a Window receives a `windowWillClose:` event. Loops back to the shared
|
||||
/// Alchemy app instance, so that our window manager can act appropriately.
|
||||
extern fn will_close<T: AppDelegate>(this: &Object, _: Sel, _: id) {
|
||||
extern fn will_close<T: WindowDelegate>(this: &Object, _: Sel, _: id) {
|
||||
unsafe {
|
||||
let app_ptr: usize = *this.get_ivar(APP_PTR);
|
||||
let window_id: usize = *this.get_ivar(WINDOW_MANAGER_ID);
|
||||
let app = app_ptr as *mut T;
|
||||
(*app)._window_will_close(window_id);
|
||||
let window_ptr: usize = *this.get_ivar(WINDOW_PTR);
|
||||
let window = window_ptr as *mut T;
|
||||
(*window).will_close();
|
||||
};
|
||||
}
|
||||
|
||||
/// Injects an `NSObject` delegate subclass, with some callback and pointer ivars for what we
|
||||
/// need to do.
|
||||
fn register_window_class<T: AppDelegate>() -> *const Class {
|
||||
fn register_window_class<T: WindowDelegate>() -> *const Class {
|
||||
static mut DELEGATE_CLASS: *const Class = 0 as *const Class;
|
||||
static INIT: Once = ONCE_INIT;
|
||||
|
||||
INIT.call_once(|| unsafe {
|
||||
let superclass = Class::get("NSObject").unwrap();
|
||||
let mut decl = ClassDecl::new("alchemyWindowDelegateShim", superclass).unwrap();
|
||||
let mut decl = ClassDecl::new("AlchemyWindowDelegateShim", superclass).unwrap();
|
||||
|
||||
decl.add_ivar::<usize>(APP_PTR);
|
||||
decl.add_ivar::<usize>(WINDOW_MANAGER_ID);
|
||||
decl.add_ivar::<usize>(WINDOW_PTR);
|
||||
|
||||
decl.add_method(sel!(windowWillClose:), will_close::<T> as extern fn(&Object, _, _));
|
||||
|
||||
|
|
|
|||
Reference in a new issue