mirror of
https://github.com/italicsjenga/winit-sonoma-fix.git
synced 2024-12-24 22:31:30 +11:00
iOS Abstract Out the UIView type from winit (#609)
* remove opengl code from winit * iOS: restrict EventsLoop to be created on the main thread iOS: Window can only be made once, make Drop on Window thread safe iOS: make DelegateState owned by Window, cleanup iOS: fixes from merge (class! macro) * update the changelog * Fixed nitpicks
This commit is contained in:
parent
01cb8e59e3
commit
72b24a9348
|
@ -3,6 +3,8 @@
|
||||||
- On MacOS, the key state for modifiers key events is now properly set.
|
- On MacOS, the key state for modifiers key events is now properly set.
|
||||||
- On iOS, the view is now set correctly. This makes it possible to render things (instead of being stuck on a black screen), and touch events work again.
|
- On iOS, the view is now set correctly. This makes it possible to render things (instead of being stuck on a black screen), and touch events work again.
|
||||||
- Added NetBSD support.
|
- Added NetBSD support.
|
||||||
|
- **Breaking:** On iOS, `UIView` is now the default root view. `WindowBuilderExt::with_root_view_class` can be used to set the root view objective-c class to `GLKView` (OpenGLES) or `MTKView` (Metal/MoltenVK).
|
||||||
|
- On iOS, the `UIApplication` is not started until `Window::new` is called.
|
||||||
|
|
||||||
# Version 0.16.2 (2018-07-07)
|
# Version 0.16.2 (2018-07-07)
|
||||||
|
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
use std::os::raw::c_void;
|
use std::os::raw::c_void;
|
||||||
|
|
||||||
use {MonitorId, Window};
|
use {MonitorId, Window, WindowBuilder};
|
||||||
|
|
||||||
/// Additional methods on `Window` that are specific to iOS.
|
/// Additional methods on `Window` that are specific to iOS.
|
||||||
pub trait WindowExt {
|
pub trait WindowExt {
|
||||||
|
@ -29,6 +29,22 @@ impl WindowExt for Window {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Additional methods on `WindowBuilder` that are specific to iOS.
|
||||||
|
pub trait WindowBuilderExt {
|
||||||
|
/// Sets the root view class used by the `Window`, otherwise a barebones `UIView` is provided.
|
||||||
|
///
|
||||||
|
/// The class will be initialized by calling `[root_view initWithFrame:CGRect]`
|
||||||
|
fn with_root_view_class(self, root_view_class: *const c_void) -> WindowBuilder;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl WindowBuilderExt for WindowBuilder {
|
||||||
|
#[inline]
|
||||||
|
fn with_root_view_class(mut self, root_view_class: *const c_void) -> WindowBuilder {
|
||||||
|
self.platform_specific.root_view_class = unsafe { &*(root_view_class as *const _) };
|
||||||
|
self
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Additional methods on `MonitorId` that are specific to iOS.
|
/// Additional methods on `MonitorId` that are specific to iOS.
|
||||||
pub trait MonitorIdExt {
|
pub trait MonitorIdExt {
|
||||||
/// Returns a pointer to the `UIScreen` that is used by this monitor.
|
/// Returns a pointer to the `UIScreen` that is used by this monitor.
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
#![allow(non_camel_case_types, non_snake_case, non_upper_case_globals)]
|
#![allow(non_camel_case_types, non_snake_case, non_upper_case_globals)]
|
||||||
|
|
||||||
use std::ffi::CString;
|
use std::ffi::CString;
|
||||||
use std::mem;
|
|
||||||
use std::os::raw::*;
|
use std::os::raw::*;
|
||||||
|
|
||||||
use objc::runtime::Object;
|
use objc::runtime::Object;
|
||||||
|
@ -15,19 +14,11 @@ pub type Boolean = u32;
|
||||||
|
|
||||||
pub const kCFRunLoopRunHandledSource: i32 = 4;
|
pub const kCFRunLoopRunHandledSource: i32 = 4;
|
||||||
|
|
||||||
pub const UIViewAutoresizingFlexibleWidth: NSUInteger = 1 << 1;
|
|
||||||
pub const UIViewAutoresizingFlexibleHeight: NSUInteger = 1 << 4;
|
|
||||||
|
|
||||||
#[cfg(target_pointer_width = "32")]
|
#[cfg(target_pointer_width = "32")]
|
||||||
pub type CGFloat = f32;
|
pub type CGFloat = f32;
|
||||||
#[cfg(target_pointer_width = "64")]
|
#[cfg(target_pointer_width = "64")]
|
||||||
pub type CGFloat = f64;
|
pub type CGFloat = f64;
|
||||||
|
|
||||||
#[cfg(target_pointer_width = "32")]
|
|
||||||
pub type NSUInteger = u32;
|
|
||||||
#[cfg(target_pointer_width = "64")]
|
|
||||||
pub type NSUInteger = u64;
|
|
||||||
|
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct CGPoint {
|
pub struct CGPoint {
|
||||||
|
@ -76,6 +67,8 @@ extern {
|
||||||
pub fn longjmp(env: *mut c_void, val: c_int);
|
pub fn longjmp(env: *mut c_void, val: c_int);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub type JmpBuf = [c_int; 27];
|
||||||
|
|
||||||
pub trait NSString: Sized {
|
pub trait NSString: Sized {
|
||||||
unsafe fn alloc(_: Self) -> id {
|
unsafe fn alloc(_: Self) -> id {
|
||||||
msg_send![class!(NSString), alloc]
|
msg_send![class!(NSString), alloc]
|
||||||
|
|
|
@ -61,8 +61,10 @@
|
||||||
#![cfg(target_os = "ios")]
|
#![cfg(target_os = "ios")]
|
||||||
|
|
||||||
use std::{fmt, mem, ptr};
|
use std::{fmt, mem, ptr};
|
||||||
|
use std::cell::RefCell;
|
||||||
use std::collections::VecDeque;
|
use std::collections::VecDeque;
|
||||||
use std::os::raw::*;
|
use std::os::raw::*;
|
||||||
|
use std::sync::Arc;
|
||||||
|
|
||||||
use objc::declare::ClassDecl;
|
use objc::declare::ClassDecl;
|
||||||
use objc::runtime::{BOOL, Class, Object, Sel, YES};
|
use objc::runtime::{BOOL, Class, Object, Sel, YES};
|
||||||
|
@ -90,6 +92,7 @@ use self::ffi::{
|
||||||
CGPoint,
|
CGPoint,
|
||||||
CGRect,
|
CGRect,
|
||||||
id,
|
id,
|
||||||
|
JmpBuf,
|
||||||
kCFRunLoopDefaultMode,
|
kCFRunLoopDefaultMode,
|
||||||
kCFRunLoopRunHandledSource,
|
kCFRunLoopRunHandledSource,
|
||||||
longjmp,
|
longjmp,
|
||||||
|
@ -97,14 +100,13 @@ use self::ffi::{
|
||||||
NSString,
|
NSString,
|
||||||
setjmp,
|
setjmp,
|
||||||
UIApplicationMain,
|
UIApplicationMain,
|
||||||
UIViewAutoresizingFlexibleWidth,
|
|
||||||
UIViewAutoresizingFlexibleHeight,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
static mut JMPBUF: [c_int; 27] = [0; 27];
|
static mut JMPBUF: Option<Box<JmpBuf>> = None;
|
||||||
|
|
||||||
pub struct Window {
|
pub struct Window {
|
||||||
delegate_state: *mut DelegateState,
|
_events_queue: Arc<RefCell<VecDeque<Event>>>,
|
||||||
|
delegate_state: Box<DelegateState>,
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe impl Send for Window {}
|
unsafe impl Send for Window {}
|
||||||
|
@ -112,7 +114,6 @@ unsafe impl Sync for Window {}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
struct DelegateState {
|
struct DelegateState {
|
||||||
events_queue: VecDeque<Event>,
|
|
||||||
window: id,
|
window: id,
|
||||||
controller: id,
|
controller: id,
|
||||||
view: id,
|
view: id,
|
||||||
|
@ -123,7 +124,6 @@ struct DelegateState {
|
||||||
impl DelegateState {
|
impl DelegateState {
|
||||||
fn new(window: id, controller: id, view: id, size: LogicalSize, scale: f64) -> DelegateState {
|
fn new(window: id, controller: id, view: id, size: LogicalSize, scale: f64) -> DelegateState {
|
||||||
DelegateState {
|
DelegateState {
|
||||||
events_queue: VecDeque::new(),
|
|
||||||
window,
|
window,
|
||||||
controller,
|
controller,
|
||||||
view,
|
view,
|
||||||
|
@ -199,7 +199,7 @@ impl MonitorId {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct EventsLoop {
|
pub struct EventsLoop {
|
||||||
delegate_state: *mut DelegateState,
|
events_queue: Arc<RefCell<VecDeque<Event>>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
|
@ -208,21 +208,11 @@ pub struct EventsLoopProxy;
|
||||||
impl EventsLoop {
|
impl EventsLoop {
|
||||||
pub fn new() -> EventsLoop {
|
pub fn new() -> EventsLoop {
|
||||||
unsafe {
|
unsafe {
|
||||||
if setjmp(mem::transmute(&mut JMPBUF)) != 0 {
|
if !msg_send![class!(NSThread), isMainThread] {
|
||||||
let app_class = class!(UIApplication);
|
panic!("`Window` can only be created on the main thread on iOS");
|
||||||
let app: id = msg_send![app_class, sharedApplication];
|
|
||||||
let delegate: id = msg_send![app, delegate];
|
|
||||||
let state: *mut c_void = *(&*delegate).get_ivar("winitState");
|
|
||||||
let delegate_state = state as *mut DelegateState;
|
|
||||||
return EventsLoop { delegate_state };
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
EventsLoop { events_queue: Default::default() }
|
||||||
create_view_class();
|
|
||||||
create_delegate_class();
|
|
||||||
start_app();
|
|
||||||
|
|
||||||
panic!("Couldn't create `UIApplication`!")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
|
@ -240,29 +230,30 @@ impl EventsLoop {
|
||||||
pub fn poll_events<F>(&mut self, mut callback: F)
|
pub fn poll_events<F>(&mut self, mut callback: F)
|
||||||
where F: FnMut(::Event)
|
where F: FnMut(::Event)
|
||||||
{
|
{
|
||||||
|
if let Some(event) = self.events_queue.borrow_mut().pop_front() {
|
||||||
|
callback(event);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
unsafe {
|
unsafe {
|
||||||
let state = &mut *self.delegate_state;
|
|
||||||
|
|
||||||
if let Some(event) = state.events_queue.pop_front() {
|
|
||||||
callback(event);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// jump hack, so we won't quit on willTerminate event before processing it
|
// jump hack, so we won't quit on willTerminate event before processing it
|
||||||
if setjmp(mem::transmute(&mut JMPBUF)) != 0 {
|
assert!(JMPBUF.is_some(), "`EventsLoop::poll_events` must be called after window creation on iOS");
|
||||||
if let Some(event) = state.events_queue.pop_front() {
|
if setjmp(mem::transmute_copy(&mut JMPBUF)) != 0 {
|
||||||
|
if let Some(event) = self.events_queue.borrow_mut().pop_front() {
|
||||||
callback(event);
|
callback(event);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
unsafe {
|
||||||
// run runloop
|
// run runloop
|
||||||
let seconds: CFTimeInterval = 0.000002;
|
let seconds: CFTimeInterval = 0.000002;
|
||||||
while CFRunLoopRunInMode(kCFRunLoopDefaultMode, seconds, 1) == kCFRunLoopRunHandledSource {}
|
while CFRunLoopRunInMode(kCFRunLoopDefaultMode, seconds, 1) == kCFRunLoopRunHandledSource {}
|
||||||
|
|
||||||
if let Some(event) = state.events_queue.pop_front() {
|
|
||||||
callback(event)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if let Some(event) = self.events_queue.borrow_mut().pop_front() {
|
||||||
|
callback(event)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -301,8 +292,18 @@ pub struct WindowId;
|
||||||
#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
||||||
pub struct DeviceId;
|
pub struct DeviceId;
|
||||||
|
|
||||||
#[derive(Clone, Default)]
|
#[derive(Clone)]
|
||||||
pub struct PlatformSpecificWindowBuilderAttributes;
|
pub struct PlatformSpecificWindowBuilderAttributes {
|
||||||
|
pub root_view_class: &'static Class,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for PlatformSpecificWindowBuilderAttributes {
|
||||||
|
fn default() -> Self {
|
||||||
|
PlatformSpecificWindowBuilderAttributes {
|
||||||
|
root_view_class: class!(UIView),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// TODO: AFAIK transparency is enabled by default on iOS,
|
// TODO: AFAIK transparency is enabled by default on iOS,
|
||||||
// so to be consistent with other platforms we have to change that.
|
// so to be consistent with other platforms we have to change that.
|
||||||
|
@ -310,19 +311,60 @@ impl Window {
|
||||||
pub fn new(
|
pub fn new(
|
||||||
ev: &EventsLoop,
|
ev: &EventsLoop,
|
||||||
_attributes: WindowAttributes,
|
_attributes: WindowAttributes,
|
||||||
_pl_alltributes: PlatformSpecificWindowBuilderAttributes,
|
pl_attributes: PlatformSpecificWindowBuilderAttributes,
|
||||||
) -> Result<Window, CreationError> {
|
) -> Result<Window, CreationError> {
|
||||||
Ok(Window { delegate_state: ev.delegate_state })
|
unsafe {
|
||||||
|
debug_assert!(mem::size_of_val(&JMPBUF) == mem::size_of::<Box<JmpBuf>>());
|
||||||
|
assert!(mem::replace(&mut JMPBUF, Some(Box::new([0; 27]))).is_none(), "Only one `Window` is supported on iOS");
|
||||||
|
}
|
||||||
|
|
||||||
|
unsafe {
|
||||||
|
if setjmp(mem::transmute_copy(&mut JMPBUF)) != 0 {
|
||||||
|
let app_class = class!(UIApplication);
|
||||||
|
let app: id = msg_send![app_class, sharedApplication];
|
||||||
|
let delegate: id = msg_send![app, delegate];
|
||||||
|
let state: *mut c_void = *(&*delegate).get_ivar("winitState");
|
||||||
|
let mut delegate_state = Box::from_raw(state as *mut DelegateState);
|
||||||
|
let events_queue = &*ev.events_queue;
|
||||||
|
(&mut *delegate).set_ivar("eventsQueue", mem::transmute::<_, *mut c_void>(events_queue));
|
||||||
|
|
||||||
|
// easiest? way to get access to PlatformSpecificWindowBuilderAttributes to configure the view
|
||||||
|
let rect: CGRect = msg_send![MonitorId.get_uiscreen(), bounds];
|
||||||
|
|
||||||
|
let uiview_class = class!(UIView);
|
||||||
|
let root_view_class = pl_attributes.root_view_class;
|
||||||
|
let is_uiview: BOOL = msg_send![root_view_class, isSubclassOfClass:uiview_class];
|
||||||
|
assert!(is_uiview == YES, "`root_view_class` must inherit from `UIView`");
|
||||||
|
|
||||||
|
delegate_state.view = msg_send![root_view_class, alloc];
|
||||||
|
assert!(!delegate_state.view.is_null(), "Failed to create `UIView` instance");
|
||||||
|
delegate_state.view = msg_send![delegate_state.view, initWithFrame:rect];
|
||||||
|
assert!(!delegate_state.view.is_null(), "Failed to initialize `UIView` instance");
|
||||||
|
|
||||||
|
let _: () = msg_send![delegate_state.controller, setView:delegate_state.view];
|
||||||
|
let _: () = msg_send![delegate_state.window, makeKeyAndVisible];
|
||||||
|
|
||||||
|
return Ok(Window {
|
||||||
|
_events_queue: ev.events_queue.clone(),
|
||||||
|
delegate_state,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
create_delegate_class();
|
||||||
|
start_app();
|
||||||
|
|
||||||
|
panic!("Couldn't create `UIApplication`!")
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn get_uiwindow(&self) -> id {
|
pub fn get_uiwindow(&self) -> id {
|
||||||
unsafe { (*self.delegate_state).window }
|
self.delegate_state.window
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn get_uiview(&self) -> id {
|
pub fn get_uiview(&self) -> id {
|
||||||
unsafe { (*self.delegate_state).view }
|
self.delegate_state.view
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
|
@ -359,7 +401,7 @@ impl Window {
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn get_inner_size(&self) -> Option<LogicalSize> {
|
pub fn get_inner_size(&self) -> Option<LogicalSize> {
|
||||||
unsafe { Some((&*self.delegate_state).size) }
|
Some(self.delegate_state.size)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
|
@ -404,7 +446,7 @@ impl Window {
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn get_hidpi_factor(&self) -> f64 {
|
pub fn get_hidpi_factor(&self) -> f64 {
|
||||||
unsafe { (&*self.delegate_state) }.scale
|
self.delegate_state.scale
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
|
@ -471,8 +513,7 @@ fn create_delegate_class() {
|
||||||
extern fn did_finish_launching(this: &mut Object, _: Sel, _: id, _: id) -> BOOL {
|
extern fn did_finish_launching(this: &mut Object, _: Sel, _: id, _: id) -> BOOL {
|
||||||
let screen_class = class!(UIScreen);
|
let screen_class = class!(UIScreen);
|
||||||
let window_class = class!(UIWindow);
|
let window_class = class!(UIWindow);
|
||||||
let controller_class = class!(MainViewController);
|
let controller_class = class!(UIViewController);
|
||||||
let view_class = class!(MainView);
|
|
||||||
unsafe {
|
unsafe {
|
||||||
let main_screen: id = msg_send![screen_class, mainScreen];
|
let main_screen: id = msg_send![screen_class, mainScreen];
|
||||||
let bounds: CGRect = msg_send![main_screen, bounds];
|
let bounds: CGRect = msg_send![main_screen, bounds];
|
||||||
|
@ -486,32 +527,28 @@ fn create_delegate_class() {
|
||||||
let view_controller: id = msg_send![controller_class, alloc];
|
let view_controller: id = msg_send![controller_class, alloc];
|
||||||
let view_controller: id = msg_send![view_controller, init];
|
let view_controller: id = msg_send![view_controller, init];
|
||||||
|
|
||||||
let view: id = msg_send![view_class, alloc];
|
|
||||||
let view: id = msg_send![view, initForGl:&bounds];
|
|
||||||
|
|
||||||
let _: () = msg_send![view_controller, setView:view];
|
|
||||||
|
|
||||||
let _: () = msg_send![window, setRootViewController:view_controller];
|
let _: () = msg_send![window, setRootViewController:view_controller];
|
||||||
let _: () = msg_send![window, makeKeyAndVisible];
|
|
||||||
|
|
||||||
let state = Box::new(DelegateState::new(window, view_controller, view, size, scale as f64));
|
let state = Box::new(DelegateState::new(window, view_controller, ptr::null_mut(), size, scale as f64));
|
||||||
let state_ptr: *mut DelegateState = mem::transmute(state);
|
let state_ptr: *mut DelegateState = mem::transmute(state);
|
||||||
this.set_ivar("winitState", state_ptr as *mut c_void);
|
this.set_ivar("winitState", state_ptr as *mut c_void);
|
||||||
|
|
||||||
|
// The `UIView` is setup in `Window::new` which gets `longjmp`'ed to here.
|
||||||
|
// This makes it easier to configure the specific `UIView` type.
|
||||||
let _: () = msg_send![this, performSelector:sel!(postLaunch:) withObject:nil afterDelay:0.0];
|
let _: () = msg_send![this, performSelector:sel!(postLaunch:) withObject:nil afterDelay:0.0];
|
||||||
}
|
}
|
||||||
YES
|
YES
|
||||||
}
|
}
|
||||||
|
|
||||||
extern fn post_launch(_: &Object, _: Sel, _: id) {
|
extern fn post_launch(_: &Object, _: Sel, _: id) {
|
||||||
unsafe { longjmp(mem::transmute(&mut JMPBUF),1); }
|
unsafe { longjmp(mem::transmute_copy(&mut JMPBUF), 1); }
|
||||||
}
|
}
|
||||||
|
|
||||||
extern fn did_become_active(this: &Object, _: Sel, _: id) {
|
extern fn did_become_active(this: &Object, _: Sel, _: id) {
|
||||||
unsafe {
|
unsafe {
|
||||||
let state: *mut c_void = *this.get_ivar("winitState");
|
let events_queue: *mut c_void = *this.get_ivar("eventsQueue");
|
||||||
let state = &mut *(state as *mut DelegateState);
|
let events_queue = &*(events_queue as *const RefCell<VecDeque<Event>>);
|
||||||
state.events_queue.push_back(Event::WindowEvent {
|
events_queue.borrow_mut().push_back(Event::WindowEvent {
|
||||||
window_id: RootEventId(WindowId),
|
window_id: RootEventId(WindowId),
|
||||||
event: WindowEvent::Focused(true),
|
event: WindowEvent::Focused(true),
|
||||||
});
|
});
|
||||||
|
@ -520,9 +557,9 @@ fn create_delegate_class() {
|
||||||
|
|
||||||
extern fn will_resign_active(this: &Object, _: Sel, _: id) {
|
extern fn will_resign_active(this: &Object, _: Sel, _: id) {
|
||||||
unsafe {
|
unsafe {
|
||||||
let state: *mut c_void = *this.get_ivar("winitState");
|
let events_queue: *mut c_void = *this.get_ivar("eventsQueue");
|
||||||
let state = &mut *(state as *mut DelegateState);
|
let events_queue = &*(events_queue as *const RefCell<VecDeque<Event>>);
|
||||||
state.events_queue.push_back(Event::WindowEvent {
|
events_queue.borrow_mut().push_back(Event::WindowEvent {
|
||||||
window_id: RootEventId(WindowId),
|
window_id: RootEventId(WindowId),
|
||||||
event: WindowEvent::Focused(false),
|
event: WindowEvent::Focused(false),
|
||||||
});
|
});
|
||||||
|
@ -531,38 +568,38 @@ fn create_delegate_class() {
|
||||||
|
|
||||||
extern fn will_enter_foreground(this: &Object, _: Sel, _: id) {
|
extern fn will_enter_foreground(this: &Object, _: Sel, _: id) {
|
||||||
unsafe {
|
unsafe {
|
||||||
let state: *mut c_void = *this.get_ivar("winitState");
|
let events_queue: *mut c_void = *this.get_ivar("eventsQueue");
|
||||||
let state = &mut *(state as *mut DelegateState);
|
let events_queue = &*(events_queue as *const RefCell<VecDeque<Event>>);
|
||||||
state.events_queue.push_back(Event::Suspended(false));
|
events_queue.borrow_mut().push_back(Event::Suspended(false));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
extern fn did_enter_background(this: &Object, _: Sel, _: id) {
|
extern fn did_enter_background(this: &Object, _: Sel, _: id) {
|
||||||
unsafe {
|
unsafe {
|
||||||
let state: *mut c_void = *this.get_ivar("winitState");
|
let events_queue: *mut c_void = *this.get_ivar("eventsQueue");
|
||||||
let state = &mut *(state as *mut DelegateState);
|
let events_queue = &*(events_queue as *const RefCell<VecDeque<Event>>);
|
||||||
state.events_queue.push_back(Event::Suspended(true));
|
events_queue.borrow_mut().push_back(Event::Suspended(true));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
extern fn will_terminate(this: &Object, _: Sel, _: id) {
|
extern fn will_terminate(this: &Object, _: Sel, _: id) {
|
||||||
unsafe {
|
unsafe {
|
||||||
let state: *mut c_void = *this.get_ivar("winitState");
|
let events_queue: *mut c_void = *this.get_ivar("eventsQueue");
|
||||||
let state = &mut *(state as *mut DelegateState);
|
let events_queue = &*(events_queue as *const RefCell<VecDeque<Event>>);
|
||||||
// push event to the front to garantee that we'll process it
|
// push event to the front to garantee that we'll process it
|
||||||
// immidiatly after jump
|
// immidiatly after jump
|
||||||
state.events_queue.push_front(Event::WindowEvent {
|
events_queue.borrow_mut().push_front(Event::WindowEvent {
|
||||||
window_id: RootEventId(WindowId),
|
window_id: RootEventId(WindowId),
|
||||||
event: WindowEvent::Destroyed,
|
event: WindowEvent::Destroyed,
|
||||||
});
|
});
|
||||||
longjmp(mem::transmute(&mut JMPBUF),1);
|
longjmp(mem::transmute_copy(&mut JMPBUF), 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
extern fn handle_touches(this: &Object, _: Sel, touches: id, _:id) {
|
extern fn handle_touches(this: &Object, _: Sel, touches: id, _:id) {
|
||||||
unsafe {
|
unsafe {
|
||||||
let state: *mut c_void = *this.get_ivar("winitState");
|
let events_queue: *mut c_void = *this.get_ivar("eventsQueue");
|
||||||
let state = &mut *(state as *mut DelegateState);
|
let events_queue = &*(events_queue as *const RefCell<VecDeque<Event>>);
|
||||||
|
|
||||||
let touches_enum: id = msg_send![touches, objectEnumerator];
|
let touches_enum: id = msg_send![touches, objectEnumerator];
|
||||||
|
|
||||||
|
@ -575,7 +612,7 @@ fn create_delegate_class() {
|
||||||
let touch_id = touch as u64;
|
let touch_id = touch as u64;
|
||||||
let phase: i32 = msg_send![touch, phase];
|
let phase: i32 = msg_send![touch, phase];
|
||||||
|
|
||||||
state.events_queue.push_back(Event::WindowEvent {
|
events_queue.borrow_mut().push_back(Event::WindowEvent {
|
||||||
window_id: RootEventId(WindowId),
|
window_id: RootEventId(WindowId),
|
||||||
event: WindowEvent::Touch(Touch {
|
event: WindowEvent::Touch(Touch {
|
||||||
device_id: DEVICE_ID,
|
device_id: DEVICE_ID,
|
||||||
|
@ -635,46 +672,12 @@ fn create_delegate_class() {
|
||||||
post_launch as extern fn(&Object, Sel, id));
|
post_launch as extern fn(&Object, Sel, id));
|
||||||
|
|
||||||
decl.add_ivar::<*mut c_void>("winitState");
|
decl.add_ivar::<*mut c_void>("winitState");
|
||||||
|
decl.add_ivar::<*mut c_void>("eventsQueue");
|
||||||
|
|
||||||
decl.register();
|
decl.register();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: winit shouldn't contain GL-specfiic code
|
|
||||||
pub fn create_view_class() {
|
|
||||||
let superclass = class!(UIViewController);
|
|
||||||
let decl = ClassDecl::new("MainViewController", superclass).expect("Failed to declare class `MainViewController`");
|
|
||||||
decl.register();
|
|
||||||
|
|
||||||
extern fn init_for_gl(this: &Object, _: Sel, frame: *const c_void) -> id {
|
|
||||||
unsafe {
|
|
||||||
let bounds = frame as *const CGRect;
|
|
||||||
let view: id = msg_send![this, initWithFrame:(*bounds).clone()];
|
|
||||||
|
|
||||||
let mask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
|
|
||||||
let _: () = msg_send![view, setAutoresizingMask:mask];
|
|
||||||
let _: () = msg_send![view, setAutoresizesSubviews:YES];
|
|
||||||
|
|
||||||
let layer: id = msg_send![view, layer];
|
|
||||||
let _ : () = msg_send![layer, setOpaque:YES];
|
|
||||||
|
|
||||||
view
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
extern fn layer_class(_: &Class, _: Sel) -> *const Class {
|
|
||||||
class!(CAEAGLLayer)
|
|
||||||
}
|
|
||||||
|
|
||||||
let superclass = class!(GLKView);
|
|
||||||
let mut decl = ClassDecl::new("MainView", superclass).expect("Failed to declare class `MainView`");
|
|
||||||
unsafe {
|
|
||||||
decl.add_method(sel!(initForGl:), init_for_gl as extern fn(&Object, Sel, *const c_void) -> id);
|
|
||||||
decl.add_class_method(sel!(layerClass), layer_class as extern fn(&Class, Sel) -> *const Class);
|
|
||||||
decl.register();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn start_app() {
|
fn start_app() {
|
||||||
unsafe {
|
unsafe {
|
||||||
|
|
Loading…
Reference in a new issue