mirror of
https://github.com/italicsjenga/winit-sonoma-fix.git
synced 2024-12-24 06:11:30 +11:00
Merge pull request #321 from SSheldon/objc_lib
Use objc crate for Objective-C runtime functionality
This commit is contained in:
commit
eeb314d3aa
22
Cargo.toml
22
Cargo.toml
|
@ -30,23 +30,11 @@ clock_ticks = "*"
|
||||||
[target.arm-linux-androideabi.dependencies.android_glue]
|
[target.arm-linux-androideabi.dependencies.android_glue]
|
||||||
version = "0"
|
version = "0"
|
||||||
|
|
||||||
[target.i686-apple-darwin.dependencies.glutin_cocoa]
|
[target.x86_64-apple-darwin.dependencies]
|
||||||
version = "0"
|
objc = "0.1"
|
||||||
|
glutin_cocoa = "0"
|
||||||
[target.x86_64-apple-darwin.dependencies.glutin_cocoa]
|
glutin_core_graphics = "0"
|
||||||
version = "0"
|
glutin_core_foundation = "0"
|
||||||
|
|
||||||
[target.i686-apple-darwin.dependencies.glutin_core_graphics]
|
|
||||||
version = "0"
|
|
||||||
|
|
||||||
[target.x86_64-apple-darwin.dependencies.glutin_core_graphics]
|
|
||||||
version = "0"
|
|
||||||
|
|
||||||
[target.i686-apple-darwin.dependencies.glutin_core_foundation]
|
|
||||||
version = "0"
|
|
||||||
|
|
||||||
[target.x86_64-apple-darwin.dependencies.glutin_core_foundation]
|
|
||||||
version = "0"
|
|
||||||
|
|
||||||
[target.i686-pc-windows-gnu.dependencies]
|
[target.i686-pc-windows-gnu.dependencies]
|
||||||
winapi = "0.1"
|
winapi = "0.1"
|
||||||
|
|
140
src/cocoa/mod.rs
140
src/cocoa/mod.rs
|
@ -10,9 +10,10 @@ use BuilderAttribs;
|
||||||
use GlRequest;
|
use GlRequest;
|
||||||
use native_monitor::NativeMonitorId;
|
use native_monitor::NativeMonitorId;
|
||||||
|
|
||||||
use cocoa::base::{Class, id, YES, NO, NSUInteger, nil, objc_allocateClassPair, class, objc_registerClassPair};
|
use objc::runtime::{Class, Object, Sel, BOOL, YES, NO};
|
||||||
use cocoa::base::{selector, msg_send, msg_send_stret, class_addMethod, class_addIvar};
|
use objc::declare::ClassDecl;
|
||||||
use cocoa::base::{object_setInstanceVariable, object_getInstanceVariable};
|
|
||||||
|
use cocoa::base::{id, nil, NSUInteger};
|
||||||
use cocoa::appkit;
|
use cocoa::appkit;
|
||||||
use cocoa::appkit::*;
|
use cocoa::appkit::*;
|
||||||
use cocoa::appkit::NSEventSubtype::*;
|
use cocoa::appkit::NSEventSubtype::*;
|
||||||
|
@ -22,8 +23,7 @@ use core_foundation::string::CFString;
|
||||||
use core_foundation::bundle::{CFBundleGetBundleWithIdentifier, CFBundleGetFunctionPointerForName};
|
use core_foundation::bundle::{CFBundleGetBundleWithIdentifier, CFBundleGetFunctionPointerForName};
|
||||||
|
|
||||||
use std::cell::Cell;
|
use std::cell::Cell;
|
||||||
use std::ffi::{CString, CStr};
|
use std::ffi::CStr;
|
||||||
use std::mem;
|
|
||||||
use std::ptr;
|
use std::ptr;
|
||||||
use std::collections::VecDeque;
|
use std::collections::VecDeque;
|
||||||
use std::str::FromStr;
|
use std::str::FromStr;
|
||||||
|
@ -63,35 +63,25 @@ struct WindowDelegate {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl WindowDelegate {
|
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
|
/// Get the delegate class, initiailizing it neccessary
|
||||||
fn class() -> Class {
|
fn class() -> *const Class {
|
||||||
use std::sync::{Once, ONCE_INIT};
|
use std::sync::{Once, ONCE_INIT};
|
||||||
use std::rt;
|
|
||||||
|
|
||||||
extern fn window_should_close(this: id, _: id) -> id {
|
extern fn window_should_close(this: &Object, _: Sel, _: id) -> BOOL {
|
||||||
unsafe {
|
unsafe {
|
||||||
let delegate = WindowDelegate { this: this };
|
let state: *mut libc::c_void = *this.get_ivar("glutinState");
|
||||||
(*delegate.get_state()).is_closed = true;
|
let state = state as *mut DelegateState;
|
||||||
mem::forget(delegate);
|
(*state).is_closed = true;
|
||||||
}
|
}
|
||||||
0
|
NO
|
||||||
}
|
}
|
||||||
|
|
||||||
extern fn window_did_resize(this: id, _: id) -> id {
|
extern fn window_did_resize(this: &Object, _: Sel, _: id) {
|
||||||
unsafe {
|
unsafe {
|
||||||
let delegate = WindowDelegate { this: this };
|
let state: *mut libc::c_void = *this.get_ivar("glutinState");
|
||||||
let state = &mut *delegate.get_state();
|
let state = &mut *(state as *mut DelegateState);
|
||||||
mem::forget(delegate);
|
|
||||||
|
|
||||||
let _: id = msg_send()(*state.context, selector("update"));
|
let _: id = msg_send![*state.context, update];
|
||||||
|
|
||||||
if let Some(handler) = state.handler {
|
if let Some(handler) = state.handler {
|
||||||
let rect = NSView::frame(*state.view);
|
let rect = NSView::frame(*state.view);
|
||||||
|
@ -100,64 +90,43 @@ impl WindowDelegate {
|
||||||
(scale_factor * rect.size.height as f32) as u32);
|
(scale_factor * rect.size.height as f32) as u32);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
0
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static mut delegate_class: Class = nil;
|
static mut delegate_class: *const Class = 0 as *const Class;
|
||||||
static mut init: Once = ONCE_INIT;
|
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));
|
||||||
|
|
||||||
|
// Store internal state as user data
|
||||||
|
decl.add_ivar::<*mut libc::c_void>("glutinState");
|
||||||
|
|
||||||
|
delegate_class = decl.register();
|
||||||
|
});
|
||||||
|
|
||||||
unsafe {
|
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::new("B@:@").unwrap().as_ptr());
|
|
||||||
class_addMethod(delegate_class,
|
|
||||||
selector("windowDidResize:"),
|
|
||||||
window_did_resize,
|
|
||||||
CString::new("V@:@").unwrap().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::new("?").unwrap().as_ptr());
|
|
||||||
objc_registerClassPair(delegate_class);
|
|
||||||
// Free class at exit
|
|
||||||
rt::at_exit(|| {
|
|
||||||
// objc_disposeClassPair(delegate_class);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
delegate_class
|
delegate_class
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn new(window: id) -> WindowDelegate {
|
fn new(window: id) -> WindowDelegate {
|
||||||
unsafe {
|
unsafe {
|
||||||
let delegate: id = msg_send()(WindowDelegate::class(), selector("new"));
|
let delegate: id = msg_send![WindowDelegate::class(), new];
|
||||||
let _: id = msg_send()(window, selector("setDelegate:"), delegate);
|
let _: id = msg_send![window, setDelegate:delegate];
|
||||||
WindowDelegate { this: delegate }
|
WindowDelegate { this: delegate }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe fn set_state(&self, state: *mut DelegateState) {
|
unsafe fn set_state(&self, state: *mut DelegateState) {
|
||||||
object_setInstanceVariable(self.this,
|
(&mut *self.this).set_ivar("glutinState", state as *mut libc::c_void);
|
||||||
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
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -234,7 +203,7 @@ impl<'a> Iterator for PollEventsIterator<'a> {
|
||||||
self.window.is_closed.set(ds.is_closed);
|
self.window.is_closed.set(ds.is_closed);
|
||||||
}
|
}
|
||||||
|
|
||||||
let event = match msg_send()(event, selector("type")) {
|
let event = match msg_send![event, type] {
|
||||||
NSLeftMouseDown => { Some(MouseInput(Pressed, MouseButton::Left)) },
|
NSLeftMouseDown => { Some(MouseInput(Pressed, MouseButton::Left)) },
|
||||||
NSLeftMouseUp => { Some(MouseInput(Released, MouseButton::Left)) },
|
NSLeftMouseUp => { Some(MouseInput(Released, MouseButton::Left)) },
|
||||||
NSRightMouseDown => { Some(MouseInput(Pressed, MouseButton::Right)) },
|
NSRightMouseDown => { Some(MouseInput(Pressed, MouseButton::Right)) },
|
||||||
|
@ -244,8 +213,8 @@ impl<'a> Iterator for PollEventsIterator<'a> {
|
||||||
NSOtherMouseDragged |
|
NSOtherMouseDragged |
|
||||||
NSRightMouseDragged => {
|
NSRightMouseDragged => {
|
||||||
let window_point = event.locationInWindow();
|
let window_point = event.locationInWindow();
|
||||||
let window: id = msg_send()(event, selector("window"));
|
let window: id = msg_send![event, window];
|
||||||
let view_point = if window == 0 {
|
let view_point = if window == nil {
|
||||||
let window_rect = self.window.window.convertRectFromScreen_(NSRect::new(window_point, NSSize::new(0.0, 0.0)));
|
let window_rect = self.window.window.convertRectFromScreen_(NSRect::new(window_point, NSSize::new(0.0, 0.0)));
|
||||||
self.window.view.convertPoint_fromView_(window_rect.origin, nil)
|
self.window.view.convertPoint_fromView_(window_rect.origin, nil)
|
||||||
} else {
|
} else {
|
||||||
|
@ -416,15 +385,15 @@ impl Window {
|
||||||
};
|
};
|
||||||
let matching_screen = {
|
let matching_screen = {
|
||||||
let screens = NSScreen::screens(nil);
|
let screens = NSScreen::screens(nil);
|
||||||
let count: NSUInteger = msg_send()(screens, selector("count"));
|
let count: NSUInteger = msg_send![screens, count];
|
||||||
let key = IdRef::new(NSString::alloc(nil).init_str("NSScreenNumber"));
|
let key = IdRef::new(NSString::alloc(nil).init_str("NSScreenNumber"));
|
||||||
let mut matching_screen: Option<id> = None;
|
let mut matching_screen: Option<id> = None;
|
||||||
for i in (0..count) {
|
for i in (0..count) {
|
||||||
let screen = msg_send()(screens, selector("objectAtIndex:"), i as NSUInteger);
|
let screen = msg_send![screens, objectAtIndex:i as NSUInteger];
|
||||||
let device_description = NSScreen::deviceDescription(screen);
|
let device_description = NSScreen::deviceDescription(screen);
|
||||||
let value = msg_send()(device_description, selector("objectForKey:"), *key);
|
let value = msg_send![device_description, objectForKey:*key];
|
||||||
if value != nil {
|
if value != nil {
|
||||||
let screen_number: NSUInteger = msg_send()(value, selector("unsignedIntValue"));
|
let screen_number: NSUInteger = msg_send![value, unsignedIntValue];
|
||||||
if screen_number as u32 == native_id {
|
if screen_number as u32 == native_id {
|
||||||
matching_screen = Some(screen);
|
matching_screen = Some(screen);
|
||||||
break;
|
break;
|
||||||
|
@ -605,7 +574,7 @@ impl Window {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub unsafe fn make_current(&self) {
|
pub unsafe fn make_current(&self) {
|
||||||
let _: id = msg_send()(*self.context, selector("update"));
|
let _: id = msg_send![*self.context, update];
|
||||||
self.context.makeCurrentContext();
|
self.context.makeCurrentContext();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -613,7 +582,7 @@ impl Window {
|
||||||
unsafe {
|
unsafe {
|
||||||
let current = NSOpenGLContext::currentContext(nil);
|
let current = NSOpenGLContext::currentContext(nil);
|
||||||
if current != nil {
|
if current != nil {
|
||||||
let is_equal: bool = msg_send()(current, selector("isEqual:"), *self.context);
|
let is_equal: bool = msg_send![current, isEqual:*self.context];
|
||||||
is_equal
|
is_equal
|
||||||
} else {
|
} else {
|
||||||
false
|
false
|
||||||
|
@ -683,9 +652,12 @@ impl Window {
|
||||||
MouseCursor::Move | MouseCursor::AllScroll | MouseCursor::ZoomIn |
|
MouseCursor::Move | MouseCursor::AllScroll | MouseCursor::ZoomIn |
|
||||||
MouseCursor::ZoomOut => "arrowCursor",
|
MouseCursor::ZoomOut => "arrowCursor",
|
||||||
};
|
};
|
||||||
|
let sel = Sel::register(cursor_name);
|
||||||
|
let cls = Class::get("NSCursor").unwrap();
|
||||||
unsafe {
|
unsafe {
|
||||||
let cursor : id = msg_send()(class("NSCursor"), selector(cursor_name));
|
use objc::MessageArguments;
|
||||||
let _ : id = msg_send()(cursor, selector("set"));
|
let cursor: id = ().send(cls as *const _ as id, sel);
|
||||||
|
let _: id = msg_send![cursor, set];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -709,7 +681,7 @@ impl IdRef {
|
||||||
|
|
||||||
fn retain(i: id) -> IdRef {
|
fn retain(i: id) -> IdRef {
|
||||||
if i != nil {
|
if i != nil {
|
||||||
unsafe { msg_send::<()>()(i, selector("retain")) };
|
unsafe { msg_send![i, retain] }
|
||||||
}
|
}
|
||||||
IdRef(i)
|
IdRef(i)
|
||||||
}
|
}
|
||||||
|
@ -722,7 +694,7 @@ impl IdRef {
|
||||||
impl Drop for IdRef {
|
impl Drop for IdRef {
|
||||||
fn drop(&mut self) {
|
fn drop(&mut self) {
|
||||||
if self.0 != nil {
|
if self.0 != nil {
|
||||||
unsafe { msg_send::<()>()(self.0, selector("release")) };
|
unsafe { msg_send![self.0, release] }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -737,17 +709,17 @@ impl Deref for IdRef {
|
||||||
impl Clone for IdRef {
|
impl Clone for IdRef {
|
||||||
fn clone(&self) -> IdRef {
|
fn clone(&self) -> IdRef {
|
||||||
if self.0 != nil {
|
if self.0 != nil {
|
||||||
unsafe { msg_send::<()>()(self.0, selector("retain")) };
|
unsafe { msg_send![self.0, retain] }
|
||||||
}
|
}
|
||||||
IdRef(self.0)
|
IdRef(self.0)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn clone_from(&mut self, source: &IdRef) {
|
fn clone_from(&mut self, source: &IdRef) {
|
||||||
if source.0 != nil {
|
if source.0 != nil {
|
||||||
unsafe { msg_send::<()>()(source.0, selector("retain")) };
|
unsafe { msg_send![source.0, retain] }
|
||||||
}
|
}
|
||||||
if self.0 != nil {
|
if self.0 != nil {
|
||||||
unsafe { msg_send::<()>()(self.0, selector("release")) };
|
unsafe { msg_send![self.0, release] }
|
||||||
}
|
}
|
||||||
self.0 = source.0;
|
self.0 = source.0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -38,6 +38,9 @@ extern crate gdi32_sys as gdi32;
|
||||||
#[cfg(target_os = "windows")]
|
#[cfg(target_os = "windows")]
|
||||||
extern crate user32_sys as user32;
|
extern crate user32_sys as user32;
|
||||||
#[cfg(target_os = "macos")]
|
#[cfg(target_os = "macos")]
|
||||||
|
#[macro_use]
|
||||||
|
extern crate objc;
|
||||||
|
#[cfg(target_os = "macos")]
|
||||||
extern crate cocoa;
|
extern crate cocoa;
|
||||||
#[cfg(target_os = "macos")]
|
#[cfg(target_os = "macos")]
|
||||||
extern crate core_foundation;
|
extern crate core_foundation;
|
||||||
|
|
Loading…
Reference in a new issue