Open seivan opened 5 years ago
cc @mtak-. I'd expect this could be handled by adding a WindowBuilderExt
method.
I ended up browsing iOS open issues to survey them a bit; but I think this issue can be closed since it's actually possible to do this, it's just badly documented (and may have been added after this issue got filed).
Call into the WindowBuilder
like this
#[cfg(target_os = "ios")]
{
use winit::platform::ios::WindowBuilderExtIOS;
builder = builder.with_root_view_class(unsafe {
get_ios_uiview_metal_sub_class() as *const _ as *const _
});
}
Create a metal enabled UIView like this:
/// On iOS we need to request the `CAMetalLayer` as part of the `UIView`, this is typically
/// done by subclassing a UIView and overriding the `layerClass` function to return
/// `CAMetalLayer::class`. Since the winit crate doesn't do this for us, we instead do it
/// ourselves. We create the `UIView` subclass and pass it to the `with_root_view_class`
/// function of `winit::WindowBuilderExtIOS`.
#[cfg(target_os = "ios")]
pub unsafe fn get_ios_uiview_metal_sub_class() -> &'static objc::runtime::Class {
use objc::declare::ClassDecl;
use objc::runtime::{Class, Sel};
use objc::*;
extern "C" fn layer_class(_: &Class, _: Sel) -> *const Class {
class!(CAMetalLayer)
}
let mut decl = ClassDecl::new(&"MyUIView", class!(UIView))
.expect("Failed to declare class `MyUIView`");
decl.add_class_method(
sel!(layerClass),
layer_class as extern "C" fn(&Class, Sel) -> *const Class,
);
decl.register()
}
Edit: Just noticed that this doesn't address the specific technical goal in the issue; however it does get to the same goal, of getting metal up and running.
This will be a requirement for the maplibre-rs project. We do not want to render maps fullscreen but in separate views. We also need handling of inputs. Not just Metal rendering.
Is there a way to side step Winit application setup for iOS and macOS and just get the building blocks for rendering Metal or openGL/ES?
I can setup the Application from Xcode and then call Rust code from Swift - so Winit can assume an application context is already setup. All I really need is either a
UIWindow
,UIView
or aUIViewController
from Winit.I did a fork where this works, so there is nothing preventing Winit for taking arguments when initialising
let window = winit::Window::new(args... &events_loop).unwrap();
to not setup the application context. In this case aUIApplicationMain
,UIApplicationDelegate
and the other parts that's not necessary.Instead I rather send events down to Winit with some sort of of a push/pump style for application lifecycle.
Still expecting Winit to tackle touches and other window based events. The issue here is that those events (touches, window) are put on the
UIApplicationDelegate
when setting them on aUIViewController
would suffice.TL;DR would be nice to be able to side step these https://github.com/tomaka/winit/blob/master/src/platform/ios/mod.rs#L367-L368 and also implement the touch & window events on
UIViewController
instead of theUIApplicationDelegate
. For most lifecycle events, there areNSNotificationCenter
keys that can be used instead.