mirror of
https://github.com/italicsjenga/winit-sonoma-fix.git
synced 2024-12-24 22:31:30 +11:00
Add support for setting a window delegate, and implement close event on mac.
This commit is contained in:
parent
696dcc9216
commit
cac0025abb
|
@ -1,7 +1,6 @@
|
||||||
use {CreationError, Event};
|
use {CreationError, Event};
|
||||||
use CreationError::OsError;
|
use CreationError::OsError;
|
||||||
use libc;
|
use libc;
|
||||||
use std::sync::atomic::AtomicBool;
|
|
||||||
|
|
||||||
#[cfg(feature = "window")]
|
#[cfg(feature = "window")]
|
||||||
use WindowBuilder;
|
use WindowBuilder;
|
||||||
|
@ -9,7 +8,9 @@ use WindowBuilder;
|
||||||
#[cfg(feature = "headless")]
|
#[cfg(feature = "headless")]
|
||||||
use HeadlessRendererBuilder;
|
use HeadlessRendererBuilder;
|
||||||
|
|
||||||
use cocoa::base::{id, NSUInteger, nil};
|
use cocoa::base::{id, NSUInteger, nil, objc_allocateClassPair, class, objc_registerClassPair};
|
||||||
|
use cocoa::base::{selector, msg_send, class_addMethod, class_addIvar};
|
||||||
|
use cocoa::base::{object_setInstanceVariable, object_getInstanceVariable};
|
||||||
use cocoa::appkit;
|
use cocoa::appkit;
|
||||||
use cocoa::appkit::*;
|
use cocoa::appkit::*;
|
||||||
|
|
||||||
|
@ -18,6 +19,9 @@ use core_foundation::string::CFString;
|
||||||
use core_foundation::bundle::{CFBundleGetBundleWithIdentifier, CFBundleGetFunctionPointerForName};
|
use core_foundation::bundle::{CFBundleGetBundleWithIdentifier, CFBundleGetFunctionPointerForName};
|
||||||
|
|
||||||
use std::c_str::CString;
|
use std::c_str::CString;
|
||||||
|
use std::mem;
|
||||||
|
use std::ptr;
|
||||||
|
use std::sync::atomic::{AtomicBool, Relaxed};
|
||||||
|
|
||||||
use events::Event::{MouseInput, MouseMoved, ReceivedCharacter, KeyboardInput};
|
use events::Event::{MouseInput, MouseMoved, ReceivedCharacter, KeyboardInput};
|
||||||
use events::ElementState::{Pressed, Released};
|
use events::ElementState::{Pressed, Released};
|
||||||
|
@ -34,11 +38,26 @@ 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_THIS_IVAR: &'static [u8] = b"glutin_this";
|
||||||
|
|
||||||
|
struct InternalState {
|
||||||
|
is_closed: AtomicBool,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl InternalState {
|
||||||
|
fn new() -> InternalState {
|
||||||
|
InternalState {
|
||||||
|
is_closed: AtomicBool::new(false),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub struct Window {
|
pub struct Window {
|
||||||
view: id,
|
view: id,
|
||||||
window: id,
|
window: id,
|
||||||
context: id,
|
context: id,
|
||||||
is_closed: AtomicBool,
|
state: Box<InternalState>,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct HeadlessContext(Window);
|
pub struct HeadlessContext(Window);
|
||||||
|
@ -64,6 +83,16 @@ impl HeadlessContext {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
extern fn window_should_close(this: id, _: id) -> id {
|
||||||
|
unsafe {
|
||||||
|
let mut stored_value = ptr::null_mut();
|
||||||
|
object_getInstanceVariable(this, DELEGATE_THIS_IVAR.as_ptr() as *const i8, &mut stored_value);
|
||||||
|
let state = stored_value as *mut InternalState;
|
||||||
|
(*state).is_closed.store(true, Relaxed);
|
||||||
|
}
|
||||||
|
0
|
||||||
|
}
|
||||||
|
|
||||||
impl Window {
|
impl Window {
|
||||||
fn new_impl(dimensions: Option<(uint, uint)>, title: &str, monitor: Option<MonitorID>, visible: bool) -> Result<Window, CreationError> {
|
fn new_impl(dimensions: Option<(uint, uint)>, title: &str, monitor: Option<MonitorID>, visible: bool) -> Result<Window, CreationError> {
|
||||||
let app = match Window::create_app() {
|
let app = match Window::create_app() {
|
||||||
|
@ -93,9 +122,27 @@ impl Window {
|
||||||
view: view,
|
view: view,
|
||||||
window: window,
|
window: window,
|
||||||
context: context,
|
context: context,
|
||||||
is_closed: AtomicBool::new(false),
|
state: box InternalState::new(),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Set up the window delegate to receive events
|
||||||
|
let ptr_size = mem::size_of::<libc::intptr_t>() as u64;
|
||||||
|
let ns_object = class("NSObject");
|
||||||
|
|
||||||
|
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, "B@:@".to_c_str().as_ptr());
|
||||||
|
class_addIvar(delegate, DELEGATE_THIS_IVAR.as_ptr() as *const i8, ptr_size, 3, "?".to_c_str().as_ptr());
|
||||||
|
objc_registerClassPair(delegate);
|
||||||
|
|
||||||
|
let del_obj = msg_send()(delegate, selector("alloc"));
|
||||||
|
let del_obj: id = msg_send()(del_obj, selector("init"));
|
||||||
|
object_setInstanceVariable(del_obj, DELEGATE_THIS_IVAR.as_ptr() as *const i8,
|
||||||
|
&*window.state as *const InternalState as *mut libc::c_void);
|
||||||
|
let _: id = msg_send()(window.window, selector("setDelegate:"), del_obj);
|
||||||
|
}
|
||||||
|
|
||||||
Ok(window)
|
Ok(window)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -127,7 +174,10 @@ impl Window {
|
||||||
|
|
||||||
let masks = match monitor {
|
let masks = match monitor {
|
||||||
Some(_) => NSBorderlessWindowMask as NSUInteger,
|
Some(_) => NSBorderlessWindowMask as NSUInteger,
|
||||||
None => NSTitledWindowMask as NSUInteger | NSClosableWindowMask as NSUInteger | NSMiniaturizableWindowMask as NSUInteger,
|
None => NSTitledWindowMask as NSUInteger |
|
||||||
|
NSClosableWindowMask as NSUInteger |
|
||||||
|
NSMiniaturizableWindowMask as NSUInteger |
|
||||||
|
NSResizableWindowMask as NSUInteger,
|
||||||
};
|
};
|
||||||
|
|
||||||
let window = NSWindow::alloc(nil).initWithContentRect_styleMask_backing_defer_(
|
let window = NSWindow::alloc(nil).initWithContentRect_styleMask_backing_defer_(
|
||||||
|
@ -193,8 +243,7 @@ impl Window {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn is_closed(&self) -> bool {
|
pub fn is_closed(&self) -> bool {
|
||||||
use std::sync::atomic::Relaxed;
|
self.state.is_closed.load(Relaxed)
|
||||||
self.is_closed.load(Relaxed)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn set_title(&self, title: &str) {
|
pub fn set_title(&self, title: &str) {
|
||||||
|
|
Loading…
Reference in a new issue