mirror of
https://github.com/rust-windowing/winit.git
synced 2026-09-02 23:00:05 -04:00
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:
@@ -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.
|
||||||
|
|||||||
Reference in New Issue
Block a user