mirror of
https://github.com/italicsjenga/winit-sonoma-fix.git
synced 2025-01-12 05:31:31 +11:00
Merge pull request #214 from bjz/osx-window
Move osx delegate stuff into separate type
This commit is contained in:
commit
4d12d3ea3d
169
src/osx/mod.rs
169
src/osx/mod.rs
|
@ -7,7 +7,7 @@ use libc;
|
||||||
|
|
||||||
use BuilderAttribs;
|
use BuilderAttribs;
|
||||||
|
|
||||||
use cocoa::base::{id, NSUInteger, nil, objc_allocateClassPair, class, objc_registerClassPair};
|
use cocoa::base::{Class, id, NSUInteger, nil, objc_allocateClassPair, class, objc_registerClassPair};
|
||||||
use cocoa::base::{selector, msg_send, class_addMethod, class_addIvar};
|
use cocoa::base::{selector, msg_send, class_addMethod, class_addIvar};
|
||||||
use cocoa::base::{object_setInstanceVariable, object_getInstanceVariable};
|
use cocoa::base::{object_setInstanceVariable, object_getInstanceVariable};
|
||||||
use cocoa::appkit;
|
use cocoa::appkit;
|
||||||
|
@ -44,9 +44,6 @@ static mut ctrl_pressed: bool = false;
|
||||||
static mut win_pressed: bool = false;
|
static mut win_pressed: bool = false;
|
||||||
static mut alt_pressed: bool = false;
|
static mut alt_pressed: bool = false;
|
||||||
|
|
||||||
static DELEGATE_NAME: &'static [u8] = b"glutin_window_delegate\0";
|
|
||||||
static DELEGATE_STATE_IVAR: &'static [u8] = b"glutin_state";
|
|
||||||
|
|
||||||
struct DelegateState<'a> {
|
struct DelegateState<'a> {
|
||||||
is_closed: bool,
|
is_closed: bool,
|
||||||
context: id,
|
context: id,
|
||||||
|
@ -55,11 +52,114 @@ struct DelegateState<'a> {
|
||||||
handler: Option<fn(u32, u32)>,
|
handler: Option<fn(u32, u32)>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct WindowDelegate {
|
||||||
|
this: id,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl WindowDelegate {
|
||||||
|
fn class_name() -> &'static [u8] {
|
||||||
|
b"GlutinWindowDelegate\0"
|
||||||
|
}
|
||||||
|
|
||||||
|
fn state_ivar_name() -> &'static [u8] {
|
||||||
|
b"glutinState"
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Get the delegate class, initiailizing it neccessary
|
||||||
|
fn class() -> Class {
|
||||||
|
use std::sync::{Once, ONCE_INIT};
|
||||||
|
use std::rt;
|
||||||
|
|
||||||
|
extern fn window_should_close(this: id, _: id) -> id {
|
||||||
|
unsafe {
|
||||||
|
let delegate = WindowDelegate { this: this };
|
||||||
|
(*delegate.get_state()).is_closed = true;
|
||||||
|
mem::forget(delegate);
|
||||||
|
}
|
||||||
|
0
|
||||||
|
}
|
||||||
|
|
||||||
|
extern fn window_did_resize(this: id, _: id) -> id {
|
||||||
|
unsafe {
|
||||||
|
let delegate = WindowDelegate { this: this };
|
||||||
|
let state = &mut *delegate.get_state();
|
||||||
|
mem::forget(delegate);
|
||||||
|
|
||||||
|
let _: id = msg_send()(state.context, selector("update"));
|
||||||
|
|
||||||
|
if let Some(handler) = state.handler {
|
||||||
|
let rect = NSView::frame(state.view);
|
||||||
|
let scale_factor = state.window.backingScaleFactor() as f32;
|
||||||
|
(handler)((scale_factor * rect.size.width as f32) as u32,
|
||||||
|
(scale_factor * rect.size.height as f32) as u32);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
0
|
||||||
|
}
|
||||||
|
|
||||||
|
static mut delegate_class: Class = nil;
|
||||||
|
static mut init: Once = ONCE_INIT;
|
||||||
|
|
||||||
|
unsafe {
|
||||||
|
init.call_once(|| {
|
||||||
|
let ptr_size = mem::size_of::<libc::intptr_t>();
|
||||||
|
// Create new NSWindowDelegate
|
||||||
|
delegate_class = objc_allocateClassPair(
|
||||||
|
class("NSObject"),
|
||||||
|
WindowDelegate::class_name().as_ptr() as *const i8, 0);
|
||||||
|
// Add callback methods
|
||||||
|
class_addMethod(delegate_class,
|
||||||
|
selector("windowShouldClose:"),
|
||||||
|
window_should_close,
|
||||||
|
CString::from_slice("B@:@".as_bytes()).as_ptr());
|
||||||
|
class_addMethod(delegate_class,
|
||||||
|
selector("windowDidResize:"),
|
||||||
|
window_did_resize,
|
||||||
|
CString::from_slice("V@:@".as_bytes()).as_ptr());
|
||||||
|
// Store internal state as user data
|
||||||
|
class_addIvar(delegate_class, WindowDelegate::state_ivar_name().as_ptr() as *const i8,
|
||||||
|
ptr_size as u64, 3,
|
||||||
|
CString::from_slice("?".as_bytes()).as_ptr());
|
||||||
|
objc_registerClassPair(delegate_class);
|
||||||
|
// Free class at exit
|
||||||
|
rt::at_exit(|| {
|
||||||
|
// objc_disposeClassPair(delegate_class);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
delegate_class
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn new(window: id) -> WindowDelegate {
|
||||||
|
unsafe {
|
||||||
|
let delegate: id = msg_send()(WindowDelegate::class(), selector("new"));
|
||||||
|
let _: id = msg_send()(window, selector("setDelegate:"), delegate);
|
||||||
|
WindowDelegate { this: delegate }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
unsafe fn set_state(&self, state: *mut DelegateState) {
|
||||||
|
object_setInstanceVariable(self.this,
|
||||||
|
WindowDelegate::state_ivar_name().as_ptr() as *const i8,
|
||||||
|
state as *mut libc::c_void);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_state(&self) -> *mut DelegateState {
|
||||||
|
unsafe {
|
||||||
|
let mut state = ptr::null_mut();
|
||||||
|
object_getInstanceVariable(self.this,
|
||||||
|
WindowDelegate::state_ivar_name().as_ptr() as *const i8,
|
||||||
|
&mut state);
|
||||||
|
state as *mut DelegateState
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub struct Window {
|
pub struct Window {
|
||||||
view: id,
|
view: id,
|
||||||
window: id,
|
window: id,
|
||||||
context: id,
|
context: id,
|
||||||
delegate: id,
|
delegate: WindowDelegate,
|
||||||
resize: Option<fn(u32, u32)>,
|
resize: Option<fn(u32, u32)>,
|
||||||
|
|
||||||
is_closed: Cell<bool>,
|
is_closed: Cell<bool>,
|
||||||
|
@ -96,37 +196,6 @@ impl WindowProxy {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
extern fn window_should_close(this: id, _: id) -> id {
|
|
||||||
unsafe {
|
|
||||||
let mut stored_value = ptr::null_mut();
|
|
||||||
object_getInstanceVariable(this, DELEGATE_STATE_IVAR.as_ptr() as *const i8, &mut stored_value);
|
|
||||||
let state = stored_value as *mut DelegateState;
|
|
||||||
|
|
||||||
(*state).is_closed = true;
|
|
||||||
}
|
|
||||||
0
|
|
||||||
}
|
|
||||||
|
|
||||||
extern fn window_did_resize(this: id, _: id) -> id {
|
|
||||||
unsafe {
|
|
||||||
let mut stored_value = ptr::null_mut();
|
|
||||||
object_getInstanceVariable(this, DELEGATE_STATE_IVAR.as_ptr() as *const i8, &mut stored_value);
|
|
||||||
let state = &mut *(stored_value as *mut DelegateState);
|
|
||||||
|
|
||||||
let _: id = msg_send()(state.context, selector("update"));
|
|
||||||
|
|
||||||
match state.handler {
|
|
||||||
Some(handler) => {
|
|
||||||
let rect = NSView::frame(state.view);
|
|
||||||
let scale_factor = state.window.backingScaleFactor() as f32;
|
|
||||||
(handler)((scale_factor * rect.size.width as f32) as u32, (scale_factor * rect.size.height as f32) as u32);
|
|
||||||
}
|
|
||||||
None => {}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
0
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Window {
|
impl Window {
|
||||||
#[cfg(feature = "window")]
|
#[cfg(feature = "window")]
|
||||||
pub fn new(builder: BuilderAttribs) -> Result<Window, CreationError> {
|
pub fn new(builder: BuilderAttribs) -> Result<Window, CreationError> {
|
||||||
|
@ -164,29 +233,11 @@ impl Window {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set up the window delegate to receive events
|
|
||||||
let ptr_size = mem::size_of::<libc::intptr_t>() as u64;
|
|
||||||
let ns_object = class("NSObject");
|
|
||||||
|
|
||||||
let delegate = unsafe {
|
|
||||||
// Create a delegate class, add callback methods and store InternalState as user data.
|
|
||||||
let delegate = objc_allocateClassPair(ns_object, DELEGATE_NAME.as_ptr() as *const i8, 0);
|
|
||||||
class_addMethod(delegate, selector("windowShouldClose:"), window_should_close, CString::from_slice("B@:@".as_bytes()).as_ptr());
|
|
||||||
class_addMethod(delegate, selector("windowDidResize:"), window_did_resize, CString::from_slice("V@:@".as_bytes()).as_ptr());
|
|
||||||
class_addIvar(delegate, DELEGATE_STATE_IVAR.as_ptr() as *const i8, ptr_size, 3, CString::from_slice("?".as_bytes()).as_ptr());
|
|
||||||
objc_registerClassPair(delegate);
|
|
||||||
|
|
||||||
let del_obj = msg_send()(delegate, selector("alloc"));
|
|
||||||
let del_obj: id = msg_send()(del_obj, selector("init"));
|
|
||||||
let _: id = msg_send()(window, selector("setDelegate:"), del_obj);
|
|
||||||
del_obj
|
|
||||||
};
|
|
||||||
|
|
||||||
let window = Window {
|
let window = Window {
|
||||||
view: view,
|
view: view,
|
||||||
window: window,
|
window: window,
|
||||||
context: context,
|
context: context,
|
||||||
delegate: delegate,
|
delegate: WindowDelegate::new(window),
|
||||||
resize: None,
|
resize: None,
|
||||||
|
|
||||||
is_closed: Cell::new(false),
|
is_closed: Cell::new(false),
|
||||||
|
@ -366,13 +417,9 @@ impl Window {
|
||||||
view: self.view,
|
view: self.view,
|
||||||
handler: self.resize,
|
handler: self.resize,
|
||||||
};
|
};
|
||||||
object_setInstanceVariable(self.delegate,
|
self.delegate.set_state(&mut ds);
|
||||||
DELEGATE_STATE_IVAR.as_ptr() as *const i8,
|
|
||||||
&mut ds as *mut DelegateState as *mut libc::c_void);
|
|
||||||
NSApp().sendEvent_(event);
|
NSApp().sendEvent_(event);
|
||||||
object_setInstanceVariable(self.delegate,
|
self.delegate.set_state(ptr::null_mut());
|
||||||
DELEGATE_STATE_IVAR.as_ptr() as *const i8,
|
|
||||||
ptr::null_mut());
|
|
||||||
self.is_closed.set(ds.is_closed);
|
self.is_closed.set(ds.is_closed);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue