mirror of
https://github.com/italicsjenga/winit-sonoma-fix.git
synced 2025-01-26 03:36:32 +11:00
iOS: add support for controlling the home indicator, and Exclusive video mode (#1078)
* iOS: platform specific edge home indicator control * iOS: exclusive video mode support * address nits, and linkify all the ios documentation
This commit is contained in:
parent
5bc3cf18d9
commit
3c27e7d88f
9 changed files with 383 additions and 118 deletions
|
@ -11,6 +11,9 @@
|
||||||
consists of `Fullscreen::Exclusive(VideoMode)` and
|
consists of `Fullscreen::Exclusive(VideoMode)` and
|
||||||
`Fullscreen::Borderless(MonitorHandle)` variants.
|
`Fullscreen::Borderless(MonitorHandle)` variants.
|
||||||
- Adds support for exclusive fullscreen mode.
|
- Adds support for exclusive fullscreen mode.
|
||||||
|
- On iOS, add support for hiding the home indicator.
|
||||||
|
- On iOS, add support for deferring system gestures.
|
||||||
|
- On iOS, fix a crash that occurred while acquiring a monitor's name.
|
||||||
|
|
||||||
# 0.20.0 Alpha 2 (2019-07-09)
|
# 0.20.0 Alpha 2 (2019-07-09)
|
||||||
|
|
||||||
|
|
|
@ -43,7 +43,7 @@ version = "0.1.3"
|
||||||
default_features = false
|
default_features = false
|
||||||
features = ["display_link"]
|
features = ["display_link"]
|
||||||
|
|
||||||
[target.'cfg(target_os = "windows")'.dependencies]
|
[target.'cfg(any(target_os = "ios", target_os = "windows"))'.dependencies]
|
||||||
bitflags = "1"
|
bitflags = "1"
|
||||||
|
|
||||||
[target.'cfg(target_os = "windows")'.dependencies.winapi]
|
[target.'cfg(target_os = "windows")'.dependencies.winapi]
|
||||||
|
|
|
@ -160,7 +160,7 @@ Legend:
|
||||||
|Window maximization toggle |✔️ |✔️ |✔️ |✔️ |**N/A**|**N/A**|**N/A** |
|
|Window maximization toggle |✔️ |✔️ |✔️ |✔️ |**N/A**|**N/A**|**N/A** |
|
||||||
|Fullscreen |✔️ |✔️ |✔️ |✔️ |**N/A**|**N/A**|❌ |
|
|Fullscreen |✔️ |✔️ |✔️ |✔️ |**N/A**|**N/A**|❌ |
|
||||||
|Fullscreen toggle |✔️ |✔️ |✔️ |✔️ |**N/A**|**N/A**|❌ |
|
|Fullscreen toggle |✔️ |✔️ |✔️ |✔️ |**N/A**|**N/A**|❌ |
|
||||||
|Exclusive fullscreen |✔️ |✔️ |✔️ |**N/A** |❌ |❌ |❌ |
|
|Exclusive fullscreen |✔️ |✔️ |✔️ |**N/A** |❌ |✔️ |❌ |
|
||||||
|HiDPI support |✔️ |✔️ |✔️ |✔️ |▢[#721]|✔️ |✔️ |
|
|HiDPI support |✔️ |✔️ |✔️ |✔️ |▢[#721]|✔️ |✔️ |
|
||||||
|Popup windows |❌ |❌ |❌ |❌ |❌ |❌ |❌ |
|
|Popup windows |❌ |❌ |❌ |❌ |❌ |❌ |❌ |
|
||||||
|
|
||||||
|
|
|
@ -123,7 +123,7 @@ extern crate serde;
|
||||||
#[macro_use]
|
#[macro_use]
|
||||||
extern crate derivative;
|
extern crate derivative;
|
||||||
#[macro_use]
|
#[macro_use]
|
||||||
#[cfg(target_os = "windows")]
|
#[cfg(any(target_os = "ios", target_os = "windows"))]
|
||||||
extern crate bitflags;
|
extern crate bitflags;
|
||||||
#[cfg(any(target_os = "macos", target_os = "ios"))]
|
#[cfg(any(target_os = "macos", target_os = "ios"))]
|
||||||
#[macro_use]
|
#[macro_use]
|
||||||
|
|
|
@ -4,13 +4,13 @@ use std::os::raw::c_void;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
event_loop::EventLoop,
|
event_loop::EventLoop,
|
||||||
monitor::MonitorHandle,
|
monitor::{MonitorHandle, VideoMode},
|
||||||
window::{Window, WindowBuilder},
|
window::{Window, WindowBuilder},
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Additional methods on `EventLoop` that are specific to iOS.
|
/// Additional methods on [`EventLoop`] that are specific to iOS.
|
||||||
pub trait EventLoopExtIOS {
|
pub trait EventLoopExtIOS {
|
||||||
/// Returns the idiom (phone/tablet/tv/etc) for the current device.
|
/// Returns the [`Idiom`] (phone/tablet/tv/etc) for the current device.
|
||||||
fn idiom(&self) -> Idiom;
|
fn idiom(&self) -> Idiom;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -20,32 +20,66 @@ impl<T: 'static> EventLoopExtIOS for EventLoop<T> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Additional methods on `Window` that are specific to iOS.
|
/// Additional methods on [`Window`] that are specific to iOS.
|
||||||
pub trait WindowExtIOS {
|
pub trait WindowExtIOS {
|
||||||
/// Returns a pointer to the `UIWindow` that is used by this window.
|
/// Returns a pointer to the [`UIWindow`] that is used by this window.
|
||||||
///
|
///
|
||||||
/// The pointer will become invalid when the `Window` is destroyed.
|
/// The pointer will become invalid when the [`Window`] is destroyed.
|
||||||
|
///
|
||||||
|
/// [`UIWindow`]: https://developer.apple.com/documentation/uikit/uiwindow?language=objc
|
||||||
fn ui_window(&self) -> *mut c_void;
|
fn ui_window(&self) -> *mut c_void;
|
||||||
|
|
||||||
/// Returns a pointer to the `UIViewController` that is used by this window.
|
/// Returns a pointer to the [`UIViewController`] that is used by this window.
|
||||||
///
|
///
|
||||||
/// The pointer will become invalid when the `Window` is destroyed.
|
/// The pointer will become invalid when the [`Window`] is destroyed.
|
||||||
|
///
|
||||||
|
/// [`UIViewController`]: https://developer.apple.com/documentation/uikit/uiviewcontroller?language=objc
|
||||||
fn ui_view_controller(&self) -> *mut c_void;
|
fn ui_view_controller(&self) -> *mut c_void;
|
||||||
|
|
||||||
/// Returns a pointer to the `UIView` that is used by this window.
|
/// Returns a pointer to the [`UIView`] that is used by this window.
|
||||||
///
|
///
|
||||||
/// The pointer will become invalid when the `Window` is destroyed.
|
/// The pointer will become invalid when the [`Window`] is destroyed.
|
||||||
|
///
|
||||||
|
/// [`UIView`]: https://developer.apple.com/documentation/uikit/uiview?language=objc
|
||||||
fn ui_view(&self) -> *mut c_void;
|
fn ui_view(&self) -> *mut c_void;
|
||||||
|
|
||||||
/// Sets the HiDpi factor used by this window.
|
/// Sets the [`contentScaleFactor`] of the underlying [`UIWindow`] to `hidpi_factor`.
|
||||||
///
|
///
|
||||||
/// This translates to `-[UIWindow setContentScaleFactor:hidpi_factor]`.
|
/// The default value is device dependent, and it's recommended GLES or Metal applications set
|
||||||
|
/// this to [`MonitorHandle::hidpi_factor()`].
|
||||||
|
///
|
||||||
|
/// [`UIWindow`]: https://developer.apple.com/documentation/uikit/uiwindow?language=objc
|
||||||
|
/// [`contentScaleFactor`]: https://developer.apple.com/documentation/uikit/uiview/1622657-contentscalefactor?language=objc
|
||||||
fn set_hidpi_factor(&self, hidpi_factor: f64);
|
fn set_hidpi_factor(&self, hidpi_factor: f64);
|
||||||
|
|
||||||
/// Sets the valid orientations for screens showing this `Window`.
|
/// Sets the valid orientations for the [`Window`].
|
||||||
///
|
///
|
||||||
/// On iPhones and iPods upside down portrait is never enabled.
|
/// The default value is [`ValidOrientations::LandscapeAndPortrait`].
|
||||||
|
///
|
||||||
|
/// This changes the value returned by
|
||||||
|
/// [`-[UIViewController supportedInterfaceOrientations]`](https://developer.apple.com/documentation/uikit/uiviewcontroller/1621435-supportedinterfaceorientations?language=objc),
|
||||||
|
/// and then calls
|
||||||
|
/// [`-[UIViewController attemptRotationToDeviceOrientation]`](https://developer.apple.com/documentation/uikit/uiviewcontroller/1621400-attemptrotationtodeviceorientati?language=objc).
|
||||||
fn set_valid_orientations(&self, valid_orientations: ValidOrientations);
|
fn set_valid_orientations(&self, valid_orientations: ValidOrientations);
|
||||||
|
|
||||||
|
/// Sets whether the [`Window`] prefers the home indicator hidden.
|
||||||
|
///
|
||||||
|
/// The default is to prefer showing the home indicator.
|
||||||
|
///
|
||||||
|
/// This changes the value returned by
|
||||||
|
/// [`-[UIViewController prefersHomeIndicatorAutoHidden]`](https://developer.apple.com/documentation/uikit/uiviewcontroller/2887510-prefershomeindicatorautohidden?language=objc),
|
||||||
|
/// and then calls
|
||||||
|
/// [`-[UIViewController setNeedsUpdateOfHomeIndicatorAutoHidden]`](https://developer.apple.com/documentation/uikit/uiviewcontroller/2887509-setneedsupdateofhomeindicatoraut?language=objc).
|
||||||
|
fn set_prefers_home_indicator_hidden(&self, hidden: bool);
|
||||||
|
|
||||||
|
/// Sets the screen edges for which the system gestures will take a lower priority than the
|
||||||
|
/// application's touch handling.
|
||||||
|
///
|
||||||
|
/// This changes the value returned by
|
||||||
|
/// [`-[UIViewController preferredScreenEdgesDeferringSystemGestures]`](https://developer.apple.com/documentation/uikit/uiviewcontroller/2887512-preferredscreenedgesdeferringsys?language=objc),
|
||||||
|
/// and then calls
|
||||||
|
/// [`-[UIViewController setNeedsUpdateOfScreenEdgesDeferringSystemGestures]`](https://developer.apple.com/documentation/uikit/uiviewcontroller/2887507-setneedsupdateofscreenedgesdefer?language=objc).
|
||||||
|
fn set_preferred_screen_edges_deferring_system_gestures(&self, edges: ScreenEdge);
|
||||||
}
|
}
|
||||||
|
|
||||||
impl WindowExtIOS for Window {
|
impl WindowExtIOS for Window {
|
||||||
|
@ -73,23 +107,62 @@ impl WindowExtIOS for Window {
|
||||||
fn set_valid_orientations(&self, valid_orientations: ValidOrientations) {
|
fn set_valid_orientations(&self, valid_orientations: ValidOrientations) {
|
||||||
self.window.set_valid_orientations(valid_orientations)
|
self.window.set_valid_orientations(valid_orientations)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn set_prefers_home_indicator_hidden(&self, hidden: bool) {
|
||||||
|
self.window.set_prefers_home_indicator_hidden(hidden)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Additional methods on `WindowBuilder` that are specific to iOS.
|
#[inline]
|
||||||
|
fn set_preferred_screen_edges_deferring_system_gestures(&self, edges: ScreenEdge) {
|
||||||
|
self.window
|
||||||
|
.set_preferred_screen_edges_deferring_system_gestures(edges)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Additional methods on [`WindowBuilder`] that are specific to iOS.
|
||||||
pub trait WindowBuilderExtIOS {
|
pub trait WindowBuilderExtIOS {
|
||||||
/// Sets the root view class used by the `Window`, otherwise a barebones `UIView` is provided.
|
/// 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]`
|
/// An instance of the class will be initialized by calling [`-[UIView initWithFrame:]`](https://developer.apple.com/documentation/uikit/uiview/1622488-initwithframe?language=objc).
|
||||||
|
///
|
||||||
|
/// [`UIView`]: https://developer.apple.com/documentation/uikit/uiview?language=objc
|
||||||
fn with_root_view_class(self, root_view_class: *const c_void) -> WindowBuilder;
|
fn with_root_view_class(self, root_view_class: *const c_void) -> WindowBuilder;
|
||||||
|
|
||||||
/// Sets the `contentScaleFactor` of the underlying `UIWindow` to `hidpi_factor`.
|
/// Sets the [`contentScaleFactor`] of the underlying [`UIWindow`] to `hidpi_factor`.
|
||||||
///
|
///
|
||||||
/// The default value is device dependent, and it's recommended GLES or Metal applications set
|
/// The default value is device dependent, and it's recommended GLES or Metal applications set
|
||||||
/// this to `MonitorHandle::hidpi_factor()`.
|
/// this to [`MonitorHandle::hidpi_factor()`].
|
||||||
|
///
|
||||||
|
/// [`UIWindow`]: https://developer.apple.com/documentation/uikit/uiwindow?language=objc
|
||||||
|
/// [`contentScaleFactor`]: https://developer.apple.com/documentation/uikit/uiview/1622657-contentscalefactor?language=objc
|
||||||
fn with_hidpi_factor(self, hidpi_factor: f64) -> WindowBuilder;
|
fn with_hidpi_factor(self, hidpi_factor: f64) -> WindowBuilder;
|
||||||
|
|
||||||
/// Sets the valid orientations for the `Window`.
|
/// Sets the valid orientations for the [`Window`].
|
||||||
|
///
|
||||||
|
/// The default value is [`ValidOrientations::LandscapeAndPortrait`].
|
||||||
|
///
|
||||||
|
/// This sets the initial value returned by
|
||||||
|
/// [`-[UIViewController supportedInterfaceOrientations]`](https://developer.apple.com/documentation/uikit/uiviewcontroller/1621435-supportedinterfaceorientations?language=objc).
|
||||||
fn with_valid_orientations(self, valid_orientations: ValidOrientations) -> WindowBuilder;
|
fn with_valid_orientations(self, valid_orientations: ValidOrientations) -> WindowBuilder;
|
||||||
|
|
||||||
|
/// Sets whether the [`Window`] prefers the home indicator hidden.
|
||||||
|
///
|
||||||
|
/// The default is to prefer showing the home indicator.
|
||||||
|
///
|
||||||
|
/// This sets the initial value returned by
|
||||||
|
/// [`-[UIViewController prefersHomeIndicatorAutoHidden]`](https://developer.apple.com/documentation/uikit/uiviewcontroller/2887510-prefershomeindicatorautohidden?language=objc).
|
||||||
|
fn with_prefers_home_indicator_hidden(self, hidden: bool) -> WindowBuilder;
|
||||||
|
|
||||||
|
/// Sets the screen edges for which the system gestures will take a lower priority than the
|
||||||
|
/// application's touch handling.
|
||||||
|
///
|
||||||
|
/// This sets the initial value returned by
|
||||||
|
/// [`-[UIViewController preferredScreenEdgesDeferringSystemGestures]`](https://developer.apple.com/documentation/uikit/uiviewcontroller/2887512-preferredscreenedgesdeferringsys?language=objc).
|
||||||
|
fn with_preferred_screen_edges_deferring_system_gestures(
|
||||||
|
self,
|
||||||
|
edges: ScreenEdge,
|
||||||
|
) -> WindowBuilder;
|
||||||
}
|
}
|
||||||
|
|
||||||
impl WindowBuilderExtIOS for WindowBuilder {
|
impl WindowBuilderExtIOS for WindowBuilder {
|
||||||
|
@ -110,12 +183,35 @@ impl WindowBuilderExtIOS for WindowBuilder {
|
||||||
self.platform_specific.valid_orientations = valid_orientations;
|
self.platform_specific.valid_orientations = valid_orientations;
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn with_prefers_home_indicator_hidden(mut self, hidden: bool) -> WindowBuilder {
|
||||||
|
self.platform_specific.prefers_home_indicator_hidden = hidden;
|
||||||
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Additional methods on `MonitorHandle` that are specific to iOS.
|
#[inline]
|
||||||
|
fn with_preferred_screen_edges_deferring_system_gestures(
|
||||||
|
mut self,
|
||||||
|
edges: ScreenEdge,
|
||||||
|
) -> WindowBuilder {
|
||||||
|
self.platform_specific
|
||||||
|
.preferred_screen_edges_deferring_system_gestures = edges;
|
||||||
|
self
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Additional methods on [`MonitorHandle`] that are specific to iOS.
|
||||||
pub trait MonitorHandleExtIOS {
|
pub trait MonitorHandleExtIOS {
|
||||||
/// Returns a pointer to the `UIScreen` that is used by this monitor.
|
/// Returns a pointer to the [`UIScreen`] that is used by this monitor.
|
||||||
|
///
|
||||||
|
/// [`UIScreen`]: https://developer.apple.com/documentation/uikit/uiscreen?language=objc
|
||||||
fn ui_screen(&self) -> *mut c_void;
|
fn ui_screen(&self) -> *mut c_void;
|
||||||
|
|
||||||
|
/// Returns the preferred [`VideoMode`] for this monitor.
|
||||||
|
///
|
||||||
|
/// This translates to a call to [`-[UIScreen preferredMode]`](https://developer.apple.com/documentation/uikit/uiscreen/1617823-preferredmode?language=objc).
|
||||||
|
fn preferred_video_mode(&self) -> VideoMode;
|
||||||
}
|
}
|
||||||
|
|
||||||
impl MonitorHandleExtIOS for MonitorHandle {
|
impl MonitorHandleExtIOS for MonitorHandle {
|
||||||
|
@ -123,9 +219,14 @@ impl MonitorHandleExtIOS for MonitorHandle {
|
||||||
fn ui_screen(&self) -> *mut c_void {
|
fn ui_screen(&self) -> *mut c_void {
|
||||||
self.inner.ui_screen() as _
|
self.inner.ui_screen() as _
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn preferred_video_mode(&self) -> VideoMode {
|
||||||
|
self.inner.preferred_video_mode()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Valid orientations for a particular `Window`.
|
/// Valid orientations for a particular [`Window`].
|
||||||
#[derive(Clone, Copy, Debug)]
|
#[derive(Clone, Copy, Debug)]
|
||||||
pub enum ValidOrientations {
|
pub enum ValidOrientations {
|
||||||
/// Excludes `PortraitUpsideDown` on iphone
|
/// Excludes `PortraitUpsideDown` on iphone
|
||||||
|
@ -161,3 +262,19 @@ pub enum Idiom {
|
||||||
TV,
|
TV,
|
||||||
CarPlay,
|
CarPlay,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bitflags! {
|
||||||
|
/// The [edges] of a screen.
|
||||||
|
///
|
||||||
|
/// [edges]: https://developer.apple.com/documentation/uikit/uirectedge?language=objc
|
||||||
|
#[derive(Default)]
|
||||||
|
pub struct ScreenEdge: u8 {
|
||||||
|
const NONE = 0;
|
||||||
|
const TOP = 1 << 0;
|
||||||
|
const LEFT = 1 << 1;
|
||||||
|
const BOTTOM = 1 << 2;
|
||||||
|
const RIGHT = 1 << 3;
|
||||||
|
const ALL = ScreenEdge::TOP.bits | ScreenEdge::LEFT.bits
|
||||||
|
| ScreenEdge::BOTTOM.bits | ScreenEdge::RIGHT.bits;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -1,10 +1,10 @@
|
||||||
#![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, ops::BitOr, os::raw::*};
|
use std::{convert::TryInto, ffi::CString, ops::BitOr, os::raw::*};
|
||||||
|
|
||||||
use objc::{runtime::Object, Encode, Encoding};
|
use objc::{runtime::Object, Encode, Encoding};
|
||||||
|
|
||||||
use crate::platform::ios::{Idiom, ValidOrientations};
|
use crate::platform::ios::{Idiom, ScreenEdge, ValidOrientations};
|
||||||
|
|
||||||
pub type id = *mut Object;
|
pub type id = *mut Object;
|
||||||
pub const nil: id = 0 as id;
|
pub const nil: id = 0 as id;
|
||||||
|
@ -173,6 +173,34 @@ impl UIInterfaceOrientationMask {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[repr(transparent)]
|
||||||
|
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
|
||||||
|
pub struct UIRectEdge(NSUInteger);
|
||||||
|
|
||||||
|
unsafe impl Encode for UIRectEdge {
|
||||||
|
fn encode() -> Encoding {
|
||||||
|
NSUInteger::encode()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<ScreenEdge> for UIRectEdge {
|
||||||
|
fn from(screen_edge: ScreenEdge) -> UIRectEdge {
|
||||||
|
assert_eq!(
|
||||||
|
screen_edge.bits() & !ScreenEdge::ALL.bits(),
|
||||||
|
0,
|
||||||
|
"invalid `ScreenEdge`"
|
||||||
|
);
|
||||||
|
UIRectEdge(screen_edge.bits().into())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Into<ScreenEdge> for UIRectEdge {
|
||||||
|
fn into(self) -> ScreenEdge {
|
||||||
|
let bits: u8 = self.0.try_into().expect("invalid `UIRectEdge`");
|
||||||
|
ScreenEdge::from_bits(bits).expect("invalid `ScreenEdge`")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[link(name = "UIKit", kind = "framework")]
|
#[link(name = "UIKit", kind = "framework")]
|
||||||
#[link(name = "CoreFoundation", kind = "framework")]
|
#[link(name = "CoreFoundation", kind = "framework")]
|
||||||
extern "C" {
|
extern "C" {
|
||||||
|
|
|
@ -10,15 +10,50 @@ use crate::{
|
||||||
platform_impl::platform::ffi::{id, nil, CGFloat, CGRect, CGSize, NSInteger, NSUInteger},
|
platform_impl::platform::ffi::{id, nil, CGFloat, CGRect, CGSize, NSInteger, NSUInteger},
|
||||||
};
|
};
|
||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
|
#[derive(Debug, PartialEq, Eq, Hash)]
|
||||||
pub struct VideoMode {
|
pub struct VideoMode {
|
||||||
pub(crate) size: (u32, u32),
|
pub(crate) size: (u32, u32),
|
||||||
pub(crate) bit_depth: u16,
|
pub(crate) bit_depth: u16,
|
||||||
pub(crate) refresh_rate: u16,
|
pub(crate) refresh_rate: u16,
|
||||||
|
pub(crate) screen_mode: id,
|
||||||
pub(crate) monitor: MonitorHandle,
|
pub(crate) monitor: MonitorHandle,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Clone for VideoMode {
|
||||||
|
fn clone(&self) -> VideoMode {
|
||||||
|
VideoMode {
|
||||||
|
size: self.size,
|
||||||
|
bit_depth: self.bit_depth,
|
||||||
|
refresh_rate: self.refresh_rate,
|
||||||
|
screen_mode: unsafe { msg_send![self.screen_mode, retain] },
|
||||||
|
monitor: self.monitor.clone(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Drop for VideoMode {
|
||||||
|
fn drop(&mut self) {
|
||||||
|
unsafe {
|
||||||
|
assert_main_thread!("`VideoMode` can only be dropped on the main thread on iOS");
|
||||||
|
msg_send![self.screen_mode, release];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl VideoMode {
|
impl VideoMode {
|
||||||
|
unsafe fn retained_new(uiscreen: id, screen_mode: id) -> VideoMode {
|
||||||
|
assert_main_thread!("`VideoMode` can only be created on the main thread on iOS");
|
||||||
|
let refresh_rate: NSInteger = msg_send![uiscreen, maximumFramesPerSecond];
|
||||||
|
let size: CGSize = msg_send![screen_mode, size];
|
||||||
|
VideoMode {
|
||||||
|
size: (size.width as u32, size.height as u32),
|
||||||
|
bit_depth: 32,
|
||||||
|
refresh_rate: refresh_rate as u16,
|
||||||
|
screen_mode: msg_send![screen_mode, retain],
|
||||||
|
monitor: MonitorHandle::retained_new(uiscreen),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn size(&self) -> PhysicalSize {
|
pub fn size(&self) -> PhysicalSize {
|
||||||
self.size.into()
|
self.size.into()
|
||||||
}
|
}
|
||||||
|
@ -133,9 +168,10 @@ impl MonitorHandle {
|
||||||
impl Inner {
|
impl Inner {
|
||||||
pub fn name(&self) -> Option<String> {
|
pub fn name(&self) -> Option<String> {
|
||||||
unsafe {
|
unsafe {
|
||||||
if self.uiscreen == main_uiscreen().uiscreen {
|
let main = main_uiscreen();
|
||||||
|
if self.uiscreen == main.uiscreen {
|
||||||
Some("Primary".to_string())
|
Some("Primary".to_string())
|
||||||
} else if self.uiscreen == mirrored_uiscreen().uiscreen {
|
} else if self.uiscreen == mirrored_uiscreen(&main).uiscreen {
|
||||||
Some("Mirrored".to_string())
|
Some("Mirrored".to_string())
|
||||||
} else {
|
} else {
|
||||||
uiscreens()
|
uiscreens()
|
||||||
|
@ -168,25 +204,18 @@ impl Inner {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn video_modes(&self) -> impl Iterator<Item = RootVideoMode> {
|
pub fn video_modes(&self) -> impl Iterator<Item = RootVideoMode> {
|
||||||
let refresh_rate: NSInteger = unsafe { msg_send![self.uiscreen, maximumFramesPerSecond] };
|
|
||||||
|
|
||||||
let available_modes: id = unsafe { msg_send![self.uiscreen, availableModes] };
|
|
||||||
let available_mode_count: NSUInteger = unsafe { msg_send![available_modes, count] };
|
|
||||||
|
|
||||||
let mut modes = BTreeSet::new();
|
let mut modes = BTreeSet::new();
|
||||||
|
unsafe {
|
||||||
|
let available_modes: id = msg_send![self.uiscreen, availableModes];
|
||||||
|
let available_mode_count: NSUInteger = msg_send![available_modes, count];
|
||||||
|
|
||||||
for i in 0..available_mode_count {
|
for i in 0..available_mode_count {
|
||||||
let mode: id = unsafe { msg_send![available_modes, objectAtIndex: i] };
|
let mode: id = msg_send![available_modes, objectAtIndex: i];
|
||||||
let size: CGSize = unsafe { msg_send![mode, size] };
|
|
||||||
modes.insert(RootVideoMode {
|
modes.insert(RootVideoMode {
|
||||||
video_mode: VideoMode {
|
video_mode: VideoMode::retained_new(self.uiscreen, mode),
|
||||||
size: (size.width as u32, size.height as u32),
|
|
||||||
bit_depth: 32,
|
|
||||||
refresh_rate: refresh_rate as u16,
|
|
||||||
monitor: MonitorHandle::retained_new(self.uiscreen),
|
|
||||||
},
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
modes.into_iter()
|
modes.into_iter()
|
||||||
}
|
}
|
||||||
|
@ -197,6 +226,15 @@ impl Inner {
|
||||||
pub fn ui_screen(&self) -> id {
|
pub fn ui_screen(&self) -> id {
|
||||||
self.uiscreen
|
self.uiscreen
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn preferred_video_mode(&self) -> RootVideoMode {
|
||||||
|
unsafe {
|
||||||
|
let mode: id = msg_send![self.uiscreen, preferredMode];
|
||||||
|
RootVideoMode {
|
||||||
|
video_mode: VideoMode::retained_new(self.uiscreen, mode),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// requires being run on main thread
|
// requires being run on main thread
|
||||||
|
@ -206,8 +244,8 @@ pub unsafe fn main_uiscreen() -> MonitorHandle {
|
||||||
}
|
}
|
||||||
|
|
||||||
// requires being run on main thread
|
// requires being run on main thread
|
||||||
unsafe fn mirrored_uiscreen() -> MonitorHandle {
|
unsafe fn mirrored_uiscreen(monitor: &MonitorHandle) -> MonitorHandle {
|
||||||
let uiscreen: id = msg_send![class!(UIScreen), mirroredScreen];
|
let uiscreen: id = msg_send![monitor.uiscreen, mirroredScreen];
|
||||||
MonitorHandle::retained_new(uiscreen)
|
MonitorHandle::retained_new(uiscreen)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -11,13 +11,48 @@ use crate::{
|
||||||
platform_impl::platform::{
|
platform_impl::platform::{
|
||||||
app_state::AppState,
|
app_state::AppState,
|
||||||
event_loop,
|
event_loop,
|
||||||
ffi::{id, nil, CGFloat, CGPoint, CGRect, UIInterfaceOrientationMask, UITouchPhase},
|
ffi::{
|
||||||
|
id, nil, CGFloat, CGPoint, CGRect, UIInterfaceOrientationMask, UIRectEdge, UITouchPhase,
|
||||||
|
},
|
||||||
window::PlatformSpecificWindowBuilderAttributes,
|
window::PlatformSpecificWindowBuilderAttributes,
|
||||||
DeviceId,
|
DeviceId,
|
||||||
},
|
},
|
||||||
window::{Fullscreen, WindowAttributes, WindowId as RootWindowId},
|
window::{Fullscreen, WindowAttributes, WindowId as RootWindowId},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
macro_rules! add_property {
|
||||||
|
(
|
||||||
|
$decl:ident,
|
||||||
|
$name:ident: $t:ty,
|
||||||
|
$setter_name:ident: |$object:ident| $after_set:expr,
|
||||||
|
$getter_name:ident,
|
||||||
|
) => {
|
||||||
|
{
|
||||||
|
const VAR_NAME: &'static str = concat!("_", stringify!($name));
|
||||||
|
$decl.add_ivar::<$t>(VAR_NAME);
|
||||||
|
#[allow(non_snake_case)]
|
||||||
|
extern "C" fn $setter_name($object: &mut Object, _: Sel, value: $t) {
|
||||||
|
unsafe {
|
||||||
|
$object.set_ivar::<$t>(VAR_NAME, value);
|
||||||
|
}
|
||||||
|
$after_set
|
||||||
|
}
|
||||||
|
#[allow(non_snake_case)]
|
||||||
|
extern "C" fn $getter_name($object: &Object, _: Sel) -> $t {
|
||||||
|
unsafe { *$object.get_ivar::<$t>(VAR_NAME) }
|
||||||
|
}
|
||||||
|
$decl.add_method(
|
||||||
|
sel!($setter_name:),
|
||||||
|
$setter_name as extern "C" fn(&mut Object, Sel, $t),
|
||||||
|
);
|
||||||
|
$decl.add_method(
|
||||||
|
sel!($getter_name),
|
||||||
|
$getter_name as extern "C" fn(&Object, Sel) -> $t,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
// requires main thread
|
// requires main thread
|
||||||
unsafe fn get_view_class(root_view_class: &'static Class) -> &'static Class {
|
unsafe fn get_view_class(root_view_class: &'static Class) -> &'static Class {
|
||||||
static mut CLASSES: Option<HashMap<*const Class, &'static Class>> = None;
|
static mut CLASSES: Option<HashMap<*const Class, &'static Class>> = None;
|
||||||
|
@ -91,67 +126,56 @@ unsafe fn get_view_controller_class() -> &'static Class {
|
||||||
if CLASS.is_none() {
|
if CLASS.is_none() {
|
||||||
let uiviewcontroller_class = class!(UIViewController);
|
let uiviewcontroller_class = class!(UIViewController);
|
||||||
|
|
||||||
extern "C" fn set_prefers_status_bar_hidden(object: &mut Object, _: Sel, hidden: BOOL) {
|
|
||||||
unsafe {
|
|
||||||
object.set_ivar::<BOOL>("_prefers_status_bar_hidden", hidden);
|
|
||||||
let () = msg_send![object, setNeedsStatusBarAppearanceUpdate];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
extern "C" fn prefers_status_bar_hidden(object: &Object, _: Sel) -> BOOL {
|
|
||||||
unsafe { *object.get_ivar::<BOOL>("_prefers_status_bar_hidden") }
|
|
||||||
}
|
|
||||||
|
|
||||||
extern "C" fn set_supported_orientations(
|
|
||||||
object: &mut Object,
|
|
||||||
_: Sel,
|
|
||||||
orientations: UIInterfaceOrientationMask,
|
|
||||||
) {
|
|
||||||
unsafe {
|
|
||||||
object.set_ivar::<UIInterfaceOrientationMask>(
|
|
||||||
"_supported_orientations",
|
|
||||||
orientations,
|
|
||||||
);
|
|
||||||
let () = msg_send![class!(UIViewController), attemptRotationToDeviceOrientation];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
extern "C" fn supported_orientations(
|
|
||||||
object: &Object,
|
|
||||||
_: Sel,
|
|
||||||
) -> UIInterfaceOrientationMask {
|
|
||||||
unsafe { *object.get_ivar::<UIInterfaceOrientationMask>("_supported_orientations") }
|
|
||||||
}
|
|
||||||
|
|
||||||
extern "C" fn should_autorotate(_: &Object, _: Sel) -> BOOL {
|
extern "C" fn should_autorotate(_: &Object, _: Sel) -> BOOL {
|
||||||
YES
|
YES
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut decl = ClassDecl::new("WinitUIViewController", uiviewcontroller_class)
|
let mut decl = ClassDecl::new("WinitUIViewController", uiviewcontroller_class)
|
||||||
.expect("Failed to declare class `WinitUIViewController`");
|
.expect("Failed to declare class `WinitUIViewController`");
|
||||||
decl.add_ivar::<BOOL>("_prefers_status_bar_hidden");
|
|
||||||
decl.add_ivar::<UIInterfaceOrientationMask>("_supported_orientations");
|
|
||||||
decl.add_method(
|
|
||||||
sel!(setPrefersStatusBarHidden:),
|
|
||||||
set_prefers_status_bar_hidden as extern "C" fn(&mut Object, Sel, BOOL),
|
|
||||||
);
|
|
||||||
decl.add_method(
|
|
||||||
sel!(prefersStatusBarHidden),
|
|
||||||
prefers_status_bar_hidden as extern "C" fn(&Object, Sel) -> BOOL,
|
|
||||||
);
|
|
||||||
decl.add_method(
|
|
||||||
sel!(setSupportedInterfaceOrientations:),
|
|
||||||
set_supported_orientations
|
|
||||||
as extern "C" fn(&mut Object, Sel, UIInterfaceOrientationMask),
|
|
||||||
);
|
|
||||||
decl.add_method(
|
|
||||||
sel!(supportedInterfaceOrientations),
|
|
||||||
supported_orientations as extern "C" fn(&Object, Sel) -> UIInterfaceOrientationMask,
|
|
||||||
);
|
|
||||||
decl.add_method(
|
decl.add_method(
|
||||||
sel!(shouldAutorotate),
|
sel!(shouldAutorotate),
|
||||||
should_autorotate as extern "C" fn(&Object, Sel) -> BOOL,
|
should_autorotate as extern "C" fn(&Object, Sel) -> BOOL,
|
||||||
);
|
);
|
||||||
|
add_property! {
|
||||||
|
decl,
|
||||||
|
prefers_status_bar_hidden: BOOL,
|
||||||
|
setPrefersStatusBarHidden: |object| {
|
||||||
|
unsafe {
|
||||||
|
let () = msg_send![object, setNeedsStatusBarAppearanceUpdate];
|
||||||
|
}
|
||||||
|
},
|
||||||
|
prefersStatusBarHidden,
|
||||||
|
}
|
||||||
|
add_property! {
|
||||||
|
decl,
|
||||||
|
prefers_home_indicator_auto_hidden: BOOL,
|
||||||
|
setPrefersHomeIndicatorAutoHidden: |object| {
|
||||||
|
unsafe {
|
||||||
|
let () = msg_send![object, setNeedsUpdateOfHomeIndicatorAutoHidden];
|
||||||
|
}
|
||||||
|
},
|
||||||
|
prefersHomeIndicatorAutoHidden,
|
||||||
|
}
|
||||||
|
add_property! {
|
||||||
|
decl,
|
||||||
|
supported_orientations: UIInterfaceOrientationMask,
|
||||||
|
setSupportedInterfaceOrientations: |object| {
|
||||||
|
unsafe {
|
||||||
|
let () = msg_send![class!(UIViewController), attemptRotationToDeviceOrientation];
|
||||||
|
}
|
||||||
|
},
|
||||||
|
supportedInterfaceOrientations,
|
||||||
|
}
|
||||||
|
add_property! {
|
||||||
|
decl,
|
||||||
|
preferred_screen_edges_deferring_system_gestures: UIRectEdge,
|
||||||
|
setPreferredScreenEdgesDeferringSystemGestures: |object| {
|
||||||
|
unsafe {
|
||||||
|
let () = msg_send![object, setNeedsUpdateOfScreenEdgesDeferringSystemGestures];
|
||||||
|
}
|
||||||
|
},
|
||||||
|
preferredScreenEdgesDeferringSystemGestures,
|
||||||
|
}
|
||||||
CLASS = Some(decl.register());
|
CLASS = Some(decl.register());
|
||||||
}
|
}
|
||||||
CLASS.unwrap()
|
CLASS.unwrap()
|
||||||
|
@ -333,6 +357,14 @@ pub unsafe fn create_view_controller(
|
||||||
platform_attributes.valid_orientations,
|
platform_attributes.valid_orientations,
|
||||||
idiom,
|
idiom,
|
||||||
);
|
);
|
||||||
|
let prefers_home_indicator_hidden = if platform_attributes.prefers_home_indicator_hidden {
|
||||||
|
YES
|
||||||
|
} else {
|
||||||
|
NO
|
||||||
|
};
|
||||||
|
let edges: UIRectEdge = platform_attributes
|
||||||
|
.preferred_screen_edges_deferring_system_gestures
|
||||||
|
.into();
|
||||||
let () = msg_send![
|
let () = msg_send![
|
||||||
view_controller,
|
view_controller,
|
||||||
setPrefersStatusBarHidden: status_bar_hidden
|
setPrefersStatusBarHidden: status_bar_hidden
|
||||||
|
@ -341,6 +373,14 @@ pub unsafe fn create_view_controller(
|
||||||
view_controller,
|
view_controller,
|
||||||
setSupportedInterfaceOrientations: supported_orientations
|
setSupportedInterfaceOrientations: supported_orientations
|
||||||
];
|
];
|
||||||
|
let () = msg_send![
|
||||||
|
view_controller,
|
||||||
|
setPrefersHomeIndicatorAutoHidden: prefers_home_indicator_hidden
|
||||||
|
];
|
||||||
|
let () = msg_send![
|
||||||
|
view_controller,
|
||||||
|
setPreferredScreenEdgesDeferringSystemGestures: edges
|
||||||
|
];
|
||||||
let () = msg_send![view_controller, setView: view];
|
let () = msg_send![view_controller, setView: view];
|
||||||
view_controller
|
view_controller
|
||||||
}
|
}
|
||||||
|
@ -366,7 +406,11 @@ pub unsafe fn create_window(
|
||||||
let () = msg_send![window, setContentScaleFactor: hidpi_factor as CGFloat];
|
let () = msg_send![window, setContentScaleFactor: hidpi_factor as CGFloat];
|
||||||
}
|
}
|
||||||
match window_attributes.fullscreen {
|
match window_attributes.fullscreen {
|
||||||
Some(Fullscreen::Exclusive(_)) => unimplemented!(),
|
Some(Fullscreen::Exclusive(ref video_mode)) => {
|
||||||
|
let uiscreen = video_mode.monitor().ui_screen() as id;
|
||||||
|
let () = msg_send![uiscreen, setCurrentMode: video_mode.video_mode.screen_mode];
|
||||||
|
msg_send![window, setScreen:video_mode.monitor().ui_screen()]
|
||||||
|
}
|
||||||
Some(Fullscreen::Borderless(ref monitor)) => {
|
Some(Fullscreen::Borderless(ref monitor)) => {
|
||||||
msg_send![window, setScreen:monitor.ui_screen()]
|
msg_send![window, setScreen:monitor.ui_screen()]
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,11 +10,14 @@ use crate::{
|
||||||
error::{ExternalError, NotSupportedError, OsError as RootOsError},
|
error::{ExternalError, NotSupportedError, OsError as RootOsError},
|
||||||
icon::Icon,
|
icon::Icon,
|
||||||
monitor::MonitorHandle as RootMonitorHandle,
|
monitor::MonitorHandle as RootMonitorHandle,
|
||||||
platform::ios::{MonitorHandleExtIOS, ValidOrientations},
|
platform::ios::{MonitorHandleExtIOS, ScreenEdge, ValidOrientations},
|
||||||
platform_impl::platform::{
|
platform_impl::platform::{
|
||||||
app_state::AppState,
|
app_state::AppState,
|
||||||
event_loop,
|
event_loop,
|
||||||
ffi::{id, CGFloat, CGPoint, CGRect, CGSize, UIEdgeInsets, UIInterfaceOrientationMask},
|
ffi::{
|
||||||
|
id, CGFloat, CGPoint, CGRect, CGSize, UIEdgeInsets, UIInterfaceOrientationMask,
|
||||||
|
UIRectEdge,
|
||||||
|
},
|
||||||
monitor, view, EventLoopWindowTarget, MonitorHandle,
|
monitor, view, EventLoopWindowTarget, MonitorHandle,
|
||||||
},
|
},
|
||||||
window::{CursorIcon, Fullscreen, WindowAttributes},
|
window::{CursorIcon, Fullscreen, WindowAttributes},
|
||||||
|
@ -159,10 +162,19 @@ impl Inner {
|
||||||
|
|
||||||
pub fn set_fullscreen(&self, monitor: Option<Fullscreen>) {
|
pub fn set_fullscreen(&self, monitor: Option<Fullscreen>) {
|
||||||
unsafe {
|
unsafe {
|
||||||
match monitor {
|
let uiscreen = match monitor {
|
||||||
Some(Fullscreen::Exclusive(_)) => unimplemented!("exclusive fullscreen on iOS"), // TODO
|
Some(Fullscreen::Exclusive(video_mode)) => {
|
||||||
Some(Fullscreen::Borderless(monitor)) => {
|
let uiscreen = video_mode.video_mode.monitor.ui_screen() as id;
|
||||||
let uiscreen = monitor.ui_screen() as id;
|
let () = msg_send![uiscreen, setCurrentMode: video_mode.video_mode.screen_mode];
|
||||||
|
uiscreen
|
||||||
|
}
|
||||||
|
Some(Fullscreen::Borderless(monitor)) => monitor.ui_screen() as id,
|
||||||
|
None => {
|
||||||
|
warn!("`Window::set_fullscreen(None)` ignored on iOS");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
let current: id = msg_send![self.window, screen];
|
let current: id = msg_send![self.window, screen];
|
||||||
let bounds: CGRect = msg_send![uiscreen, bounds];
|
let bounds: CGRect = msg_send![uiscreen, bounds];
|
||||||
|
|
||||||
|
@ -172,9 +184,6 @@ impl Inner {
|
||||||
}
|
}
|
||||||
let () = msg_send![self.window, setFrame: bounds];
|
let () = msg_send![self.window, setFrame: bounds];
|
||||||
}
|
}
|
||||||
None => warn!("`Window::set_fullscreen(None)` ignored on iOS"),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn fullscreen(&self) -> Option<Fullscreen> {
|
pub fn fullscreen(&self) -> Option<Fullscreen> {
|
||||||
|
@ -295,7 +304,9 @@ impl Window {
|
||||||
|
|
||||||
unsafe {
|
unsafe {
|
||||||
let screen = match window_attributes.fullscreen {
|
let screen = match window_attributes.fullscreen {
|
||||||
Some(Fullscreen::Exclusive(_)) => unimplemented!("exclusive fullscreen on iOS"), // TODO: do we set the frame to video mode bounds instead of screen bounds?
|
Some(Fullscreen::Exclusive(ref video_mode)) => {
|
||||||
|
video_mode.video_mode.monitor.ui_screen() as id
|
||||||
|
}
|
||||||
Some(Fullscreen::Borderless(ref monitor)) => monitor.ui_screen() as id,
|
Some(Fullscreen::Borderless(ref monitor)) => monitor.ui_screen() as id,
|
||||||
None => monitor::main_uiscreen().ui_screen(),
|
None => monitor::main_uiscreen().ui_screen(),
|
||||||
};
|
};
|
||||||
|
@ -375,6 +386,26 @@ impl Inner {
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn set_prefers_home_indicator_hidden(&self, hidden: bool) {
|
||||||
|
unsafe {
|
||||||
|
let prefers_home_indicator_hidden = if hidden { NO } else { YES };
|
||||||
|
let () = msg_send![
|
||||||
|
self.view_controller,
|
||||||
|
setPrefersHomeIndicatorAutoHidden: prefers_home_indicator_hidden
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn set_preferred_screen_edges_deferring_system_gestures(&self, edges: ScreenEdge) {
|
||||||
|
let edges: UIRectEdge = edges.into();
|
||||||
|
unsafe {
|
||||||
|
let () = msg_send![
|
||||||
|
self.view_controller,
|
||||||
|
setPreferredScreenEdgesDeferringSystemGestures: edges
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Inner {
|
impl Inner {
|
||||||
|
@ -496,6 +527,8 @@ pub struct PlatformSpecificWindowBuilderAttributes {
|
||||||
pub root_view_class: &'static Class,
|
pub root_view_class: &'static Class,
|
||||||
pub hidpi_factor: Option<f64>,
|
pub hidpi_factor: Option<f64>,
|
||||||
pub valid_orientations: ValidOrientations,
|
pub valid_orientations: ValidOrientations,
|
||||||
|
pub prefers_home_indicator_hidden: bool,
|
||||||
|
pub preferred_screen_edges_deferring_system_gestures: ScreenEdge,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for PlatformSpecificWindowBuilderAttributes {
|
impl Default for PlatformSpecificWindowBuilderAttributes {
|
||||||
|
@ -504,6 +537,8 @@ impl Default for PlatformSpecificWindowBuilderAttributes {
|
||||||
root_view_class: class!(UIView),
|
root_view_class: class!(UIView),
|
||||||
hidpi_factor: None,
|
hidpi_factor: None,
|
||||||
valid_orientations: Default::default(),
|
valid_orientations: Default::default(),
|
||||||
|
prefers_home_indicator_hidden: false,
|
||||||
|
preferred_screen_edges_deferring_system_gestures: Default::default(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue