Update iOS for EventsLoop design (#275)

* Inline gen_api_transition! in the ios module

* Event loop proxy work

* Monitors

* Use freestanding functions

* Finish conversion
This commit is contained in:
tomaka
2017-09-04 12:41:10 +02:00
committed by GitHub
parent fe1deb83ae
commit 2a4b381384

View File

@@ -71,7 +71,9 @@ use objc::runtime::{Class, Object, Sel, BOOL, YES };
use objc::declare::{ ClassDecl }; use objc::declare::{ ClassDecl };
use { CreationError, CursorState, MouseCursor, WindowAttributes, FullScreenState }; use { CreationError, CursorState, MouseCursor, WindowAttributes, FullScreenState };
use WindowEvent as Event; use WindowId as RootEventId;
use WindowEvent;
use Event;
use events::{ Touch, TouchPhase }; use events::{ Touch, TouchPhase };
mod ffi; mod ffi;
@@ -96,24 +98,16 @@ static mut jmpbuf: [c_int;27] = [0;27];
#[derive(Clone)] #[derive(Clone)]
pub struct MonitorId; pub struct MonitorId;
pub struct Window { pub struct Window2 {
delegate_state: *mut DelegateState delegate_state: *mut DelegateState
} }
#[derive(Clone)] #[derive(Clone)]
pub struct WindowProxy; pub struct WindowProxy;
pub struct PollEventsIterator<'a> {
window: &'a Window,
}
pub struct WaitEventsIterator<'a> {
window: &'a Window,
}
#[derive(Debug)] #[derive(Debug)]
struct DelegateState { struct DelegateState {
events_queue: VecDeque<Event>, events_queue: VecDeque<WindowEvent>,
window: id, window: id,
controller: id, controller: id,
size: (u32,u32), size: (u32,u32),
@@ -134,18 +128,6 @@ impl DelegateState {
} }
} }
#[inline]
pub fn get_available_monitors() -> VecDeque<MonitorId> {
let mut rb = VecDeque::new();
rb.push_back(MonitorId);
rb
}
#[inline]
pub fn get_primary_monitor() -> MonitorId {
MonitorId
}
impl MonitorId { impl MonitorId {
#[inline] #[inline]
pub fn get_name(&self) -> Option<String> { pub fn get_name(&self) -> Option<String> {
@@ -158,15 +140,14 @@ impl MonitorId {
} }
} }
gen_api_transition!(); pub struct EventsLoop {
delegate_state: *mut DelegateState
}
#[derive(Clone, Default)] pub struct EventsLoopProxy;
pub struct PlatformSpecificWindowBuilderAttributes;
impl Window { impl EventsLoop {
pub fn new() -> EventsLoop {
pub fn new(_: &WindowAttributes, _: &PlatformSpecificWindowBuilderAttributes) -> Result<Window, CreationError>
{
unsafe { unsafe {
if setjmp(mem::transmute(&mut jmpbuf)) != 0 { if setjmp(mem::transmute(&mut jmpbuf)) != 0 {
let app: id = msg_send![Class::get("UIApplication").unwrap(), sharedApplication]; let app: id = msg_send![Class::get("UIApplication").unwrap(), sharedApplication];
@@ -174,22 +155,206 @@ impl Window {
let state: *mut c_void = *(&*delegate).get_ivar("glutinState"); let state: *mut c_void = *(&*delegate).get_ivar("glutinState");
let state = state as *mut DelegateState; let state = state as *mut DelegateState;
let window = Window { let events_loop = EventsLoop {
delegate_state: state delegate_state: state
}; };
return Ok(window) return events_loop;
} }
} }
Window::create_delegate_class(); create_delegate_class();
Window::create_view_class(); create_view_class();
Window::start_app(); start_app();
Err(CreationError::OsError(format!("Couldn't create UIApplication"))) panic!("Couldn't create UIApplication")
} }
fn create_delegate_class() { #[inline]
pub fn get_available_monitors(&self) -> VecDeque<MonitorId> {
let mut rb = VecDeque::new();
rb.push_back(MonitorId);
rb
}
#[inline]
pub fn get_primary_monitor(&self) -> MonitorId {
MonitorId
}
pub fn poll_events<F>(&mut self, mut callback: F)
where F: FnMut(::Event)
{
unsafe {
let state = &mut *self.delegate_state;
if let Some(event) = state.events_queue.pop_front() {
callback(Event::WindowEvent {
window_id: RootEventId(WindowId),
event: event,
});
return;
}
// jump hack, so we won't quit on willTerminate event before processing it
if setjmp(mem::transmute(&mut jmpbuf)) != 0 {
if let Some(event) = state.events_queue.pop_front() {
callback(Event::WindowEvent {
window_id: RootEventId(WindowId),
event: event,
});
return;
}
}
// run runloop
let seconds: CFTimeInterval = 0.000002;
while CFRunLoopRunInMode(kCFRunLoopDefaultMode, seconds, 1) == kCFRunLoopRunHandledSource {}
if let Some(event) = state.events_queue.pop_front() {
callback(Event::WindowEvent {
window_id: RootEventId(WindowId),
event: event,
})
}
}
}
pub fn run_forever<F>(&mut self, mut callback: F)
where F: FnMut(::Event) -> ::ControlFlow,
{
// Yeah that's a very bad implementation.
loop {
let mut control_flow = ::ControlFlow::Continue;
self.poll_events(|e| {
if let ::ControlFlow::Break = callback(e) {
control_flow = ::ControlFlow::Break;
}
});
if let ::ControlFlow::Break = control_flow {
break;
}
::std::thread::sleep(::std::time::Duration::from_millis(5));
}
}
pub fn create_proxy(&self) -> EventsLoopProxy {
EventsLoopProxy
}
}
impl EventsLoopProxy {
pub fn wakeup(&self) -> Result<(), ::EventsLoopClosed> {
unimplemented!()
}
}
#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct WindowId;
#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct DeviceId;
#[derive(Clone, Default)]
pub struct PlatformSpecificWindowBuilderAttributes;
impl Window2 {
pub fn new(ev: &EventsLoop, _: &WindowAttributes, _: &PlatformSpecificWindowBuilderAttributes)
-> Result<Window2, CreationError>
{
Ok(Window2 {
delegate_state: ev.delegate_state,
})
}
#[inline]
pub fn set_title(&self, _: &str) {
}
#[inline]
pub fn show(&self) {
}
#[inline]
pub fn hide(&self) {
}
#[inline]
pub fn get_position(&self) -> Option<(i32, i32)> {
None
}
#[inline]
pub fn set_position(&self, _x: i32, _y: i32) {
}
#[inline]
pub fn get_inner_size(&self) -> Option<(u32, u32)> {
unsafe { Some((&*self.delegate_state).size) }
}
#[inline]
pub fn get_outer_size(&self) -> Option<(u32, u32)> {
self.get_inner_size()
}
#[inline]
pub fn set_inner_size(&self, _x: u32, _y: u32) {
}
#[inline]
pub fn platform_display(&self) -> *mut libc::c_void {
unimplemented!();
}
#[inline]
pub fn platform_window(&self) -> *mut libc::c_void {
unimplemented!()
}
#[inline]
pub fn set_window_resize_callback(&mut self, _: Option<fn(u32, u32)>) {
}
#[inline]
pub fn set_cursor(&self, _: MouseCursor) {
}
#[inline]
pub fn set_cursor_state(&self, _: CursorState) -> Result<(), String> {
Ok(())
}
#[inline]
pub fn hidpi_factor(&self) -> f32 {
unsafe { (&*self.delegate_state) }.scale
}
#[inline]
pub fn set_cursor_position(&self, _x: i32, _y: i32) -> Result<(), ()> {
unimplemented!();
}
#[inline]
pub fn create_window_proxy(&self) -> WindowProxy {
WindowProxy
}
#[inline]
pub fn set_maximized(&self, maximized: bool) {
}
#[inline]
pub fn set_fullscreen(&self, state: FullScreenState) {
}
#[inline]
pub fn id(&self) -> WindowId {
WindowId
}
}
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 {
unsafe { unsafe {
let main_screen: id = msg_send![Class::get("UIScreen").unwrap(), mainScreen]; let main_screen: id = msg_send![Class::get("UIScreen").unwrap(), mainScreen];
@@ -225,7 +390,7 @@ impl Window {
unsafe { unsafe {
let state: *mut c_void = *this.get_ivar("glutinState"); let state: *mut c_void = *this.get_ivar("glutinState");
let state = &mut *(state as *mut DelegateState); let state = &mut *(state as *mut DelegateState);
state.events_queue.push_back(Event::Focused(true)); state.events_queue.push_back(WindowEvent::Focused(true));
} }
} }
@@ -233,7 +398,7 @@ impl Window {
unsafe { unsafe {
let state: *mut c_void = *this.get_ivar("glutinState"); let state: *mut c_void = *this.get_ivar("glutinState");
let state = &mut *(state as *mut DelegateState); let state = &mut *(state as *mut DelegateState);
state.events_queue.push_back(Event::Focused(false)); state.events_queue.push_back(WindowEvent::Focused(false));
} }
} }
@@ -241,7 +406,7 @@ impl Window {
unsafe { unsafe {
let state: *mut c_void = *this.get_ivar("glutinState"); let state: *mut c_void = *this.get_ivar("glutinState");
let state = &mut *(state as *mut DelegateState); let state = &mut *(state as *mut DelegateState);
state.events_queue.push_back(Event::Suspended(false)); state.events_queue.push_back(WindowEvent::Suspended(false));
} }
} }
@@ -249,7 +414,7 @@ impl Window {
unsafe { unsafe {
let state: *mut c_void = *this.get_ivar("glutinState"); let state: *mut c_void = *this.get_ivar("glutinState");
let state = &mut *(state as *mut DelegateState); let state = &mut *(state as *mut DelegateState);
state.events_queue.push_back(Event::Suspended(true)); state.events_queue.push_back(WindowEvent::Suspended(true));
} }
} }
@@ -259,7 +424,7 @@ impl Window {
let state = &mut *(state as *mut DelegateState); let state = &mut *(state as *mut DelegateState);
// 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::Closed); state.events_queue.push_front(WindowEvent::Closed);
longjmp(mem::transmute(&mut jmpbuf),1); longjmp(mem::transmute(&mut jmpbuf),1);
} }
} }
@@ -280,7 +445,7 @@ impl Window {
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::Touch(Touch { state.events_queue.push_back(WindowEvent::Touch(Touch {
device_id: DEVICE_ID, device_id: DEVICE_ID,
id: touch_id, id: touch_id,
location: (location.x as f64, location.y as f64), location: (location.x as f64, location.y as f64),
@@ -340,162 +505,20 @@ impl Window {
decl.register(); decl.register();
} }
} }
fn create_view_class() { fn create_view_class() {
let ui_view_controller = Class::get("UIViewController").unwrap(); let ui_view_controller = Class::get("UIViewController").unwrap();
let decl = ClassDecl::new("MainViewController", ui_view_controller).unwrap(); let decl = ClassDecl::new("MainViewController", ui_view_controller).unwrap();
decl.register(); decl.register();
} }
#[inline] #[inline]
fn start_app() { fn start_app() {
unsafe { unsafe {
UIApplicationMain(0, ptr::null(), nil, NSString::alloc(nil).init_str("AppDelegate")); UIApplicationMain(0, ptr::null(), nil, NSString::alloc(nil).init_str("AppDelegate"));
} }
}
#[inline]
pub fn set_title(&self, _: &str) {
}
#[inline]
pub fn show(&self) {
}
#[inline]
pub fn hide(&self) {
}
#[inline]
pub fn get_position(&self) -> Option<(i32, i32)> {
None
}
#[inline]
pub fn set_position(&self, _x: i32, _y: i32) {
}
#[inline]
pub fn get_inner_size(&self) -> Option<(u32, u32)> {
unsafe { Some((&*self.delegate_state).size) }
}
#[inline]
pub fn get_outer_size(&self) -> Option<(u32, u32)> {
self.get_inner_size()
}
#[inline]
pub fn set_inner_size(&self, _x: u32, _y: u32) {
}
#[inline]
pub fn poll_events(&self) -> PollEventsIterator {
PollEventsIterator {
window: self
}
}
#[inline]
pub fn wait_events(&self) -> WaitEventsIterator {
WaitEventsIterator {
window: self
}
}
#[inline]
pub fn platform_display(&self) -> *mut libc::c_void {
unimplemented!();
}
#[inline]
pub fn platform_window(&self) -> *mut libc::c_void {
unimplemented!()
}
#[inline]
pub fn set_window_resize_callback(&mut self, _: Option<fn(u32, u32)>) {
}
#[inline]
pub fn set_cursor(&self, _: MouseCursor) {
}
#[inline]
pub fn set_cursor_state(&self, _: CursorState) -> Result<(), String> {
Ok(())
}
#[inline]
pub fn hidpi_factor(&self) -> f32 {
unsafe { (&*self.delegate_state) }.scale
}
#[inline]
pub fn set_cursor_position(&self, _x: i32, _y: i32) -> Result<(), ()> {
unimplemented!();
}
#[inline]
pub fn create_window_proxy(&self) -> WindowProxy {
WindowProxy
}
#[inline]
pub fn set_maximized(&self, maximized: bool) {
}
#[inline]
pub fn set_fullscreen(&self, state: FullScreenState) {
}
}
impl WindowProxy {
#[inline]
pub fn wakeup_event_loop(&self) {
unimplemented!()
}
}
impl<'a> Iterator for WaitEventsIterator<'a> {
type Item = Event;
#[inline]
fn next(&mut self) -> Option<Event> {
loop {
if let Some(ev) = self.window.poll_events().next() {
return Some(ev);
}
}
}
}
impl<'a> Iterator for PollEventsIterator<'a> {
type Item = Event;
fn next(&mut self) -> Option<Event> {
unsafe {
let state = &mut *self.window.delegate_state;
if let Some(event) = state.events_queue.pop_front() {
return Some(event)
}
// jump hack, so we won't quit on willTerminate event before processing it
if setjmp(mem::transmute(&mut jmpbuf)) != 0 {
return state.events_queue.pop_front()
}
// run runloop
let seconds: CFTimeInterval = 0.000002;
while CFRunLoopRunInMode(kCFRunLoopDefaultMode, seconds, 1) == kCFRunLoopRunHandledSource {}
state.events_queue.pop_front()
}
}
} }
// Constant device ID, to be removed when this backend is updated to report real device IDs. // Constant device ID, to be removed when this backend is updated to report real device IDs.