From 08028c1e542db816280ac333d5a609f6ff0b8cf0 Mon Sep 17 00:00:00 2001 From: Daniel Collin Date: Sat, 19 Dec 2015 08:25:04 +0100 Subject: [PATCH] WIP on Mac version --- src/macos.rs | 130 ++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 128 insertions(+), 2 deletions(-) diff --git a/src/macos.rs b/src/macos.rs index b634b84..7c1150f 100644 --- a/src/macos.rs +++ b/src/macos.rs @@ -4,7 +4,7 @@ use Scale; use Vsync; use Key; -//use libc; +use libc; //use cocoa::appkit; use cocoa::appkit::*; //use cocoa::appkit::NSEventSubtype::*; @@ -13,6 +13,7 @@ use cocoa::appkit::*; use cocoa::base::{id, nil}; #[allow(unused_imports)] use objc::runtime::{Class, Object, Sel, BOOL, YES, NO}; +use objc::declare::ClassDecl; #[allow(unused_imports)] use cocoa::foundation::{NSAutoreleasePool, NSDate, NSDefaultRunLoopMode, NSPoint, NSRect, NSSize, @@ -23,8 +24,126 @@ use std::ops::Deref; pub struct Window { view: IdRef, window: IdRef, + delegate: WindowDelegate, } +struct DelegateState { + view: IdRef, + window: IdRef, + resize_handler: Option, +} + +struct WindowDelegate { + state: Box, + _this: IdRef, +} + +//sthou + +impl WindowDelegate { + /// Get the delegate class, initiailizing it neccessary + fn class() -> *const Class { + use std::sync::{Once, ONCE_INIT}; + + extern fn window_should_close(this: &Object, _: Sel, _: id) -> BOOL { + unsafe { + let state: *mut libc::c_void = *this.get_ivar("glutinState"); + let state = state as *mut DelegateState; + //(*state).pending_events.lock().unwrap().push_back(Closed); + } + YES + } + + extern fn window_did_resize(this: &Object, _: Sel, _: id) { + unsafe { + let state: *mut libc::c_void = *this.get_ivar("glutinState"); + let state = &mut *(state as *mut DelegateState); + + //let _: () = msg_send![*state.context, update]; + + if let Some(handler) = state.resize_handler { + let rect = NSView::frame(*state.view); + let scale_factor = NSWindow::backingScaleFactor(*state.window) as f32; + (handler)((scale_factor * rect.size.width as f32) as u32, + (scale_factor * rect.size.height as f32) as u32); + } + } + } + + extern fn window_did_become_key(this: &Object, _: Sel, _: id) { + unsafe { + // TODO: center the cursor if the window had mouse grab when it + // lost focus + + let state: *mut libc::c_void = *this.get_ivar("glutinState"); + let state = state as *mut DelegateState; + //(*state).pending_events.lock().unwrap().push_back(Focused(true)); + } + } + + extern fn window_did_resign_key(this: &Object, _: Sel, _: id) { + unsafe { + let state: *mut libc::c_void = *this.get_ivar("glutinState"); + let state = state as *mut DelegateState; + //(*state).pending_events.lock().unwrap().push_back(Focused(false)); + } + } + + static mut delegate_class: *const Class = 0 as *const Class; + static INIT: Once = ONCE_INIT; + + INIT.call_once(|| unsafe { + // Create new NSWindowDelegate + let superclass = Class::get("NSObject").unwrap(); + let mut decl = ClassDecl::new(superclass, "GlutinWindowDelegate").unwrap(); + + // Add callback methods + decl.add_method(sel!(windowShouldClose:), + window_should_close as extern fn(&Object, Sel, id) -> BOOL); + decl.add_method(sel!(windowDidResize:), + window_did_resize as extern fn(&Object, Sel, id)); + + decl.add_method(sel!(windowDidBecomeKey:), + window_did_become_key as extern fn(&Object, Sel, id)); + decl.add_method(sel!(windowDidResignKey:), + window_did_resign_key as extern fn(&Object, Sel, id)); + + // Store internal state as user data + decl.add_ivar::<*mut libc::c_void>("glutinState"); + + delegate_class = decl.register(); + }); + + unsafe { + delegate_class + } + } + + fn new(state: DelegateState) -> WindowDelegate { + // Box the state so we can give a pointer to it + let mut state = Box::new(state); + let state_ptr: *mut DelegateState = &mut *state; + unsafe { + let delegate = IdRef::new(msg_send![WindowDelegate::class(), new]); + + (&mut **delegate).set_ivar("glutinState", state_ptr as *mut libc::c_void); + let _: () = msg_send![*state.window, setDelegate:*delegate]; + + WindowDelegate { state: state, _this: delegate } + } + } +} + +impl Drop for WindowDelegate { + fn drop(&mut self) { + unsafe { + // Nil the window's delegate so it doesn't still reference us + let _: () = msg_send![*self.state.window, setDelegate:nil]; + } + } +} + + impl Window { pub fn new(name: &str, width: usize, height: usize, _: Scale, _: Vsync) -> Result { unsafe { @@ -51,11 +170,18 @@ impl Window { app.activateIgnoringOtherApps_(YES); + let ds = DelegateState { + view: view.clone(), + window: window.clone(), + resize_handler: None, + }; + println!("Created window and view"); return Ok(Window { window: window, - view: view + view: view, + delegate: WindowDelegate::new(ds), }); } }