mirror of
https://github.com/italicsjenga/winit-sonoma-fix.git
synced 2025-01-11 13:31:29 +11:00
iOS os version checking around certain APIs (#1094)
* iOS os version checking * iOS, fix some incorrect msg_send return types * address nits, and fix OS version check for unsupported os versions * source for 60fps guarantee
This commit is contained in:
parent
7b707e7d75
commit
f53683f01f
|
@ -29,6 +29,7 @@
|
|||
- On iOS, add touch pressure information for touch events.
|
||||
- Implement `raw_window_handle::HasRawWindowHandle` for `Window` type on all supported platforms.
|
||||
- On macOS, fix the signature of `-[NSView drawRect:]`.
|
||||
- On iOS, fix improper `msg_send` usage that was UB and/or would break if `!` is stabilized.
|
||||
|
||||
# 0.20.0 Alpha 2 (2019-07-09)
|
||||
|
||||
|
|
|
@ -134,6 +134,7 @@ If your PR makes notable changes to Winit's features, please update this section
|
|||
* Base window size
|
||||
|
||||
### iOS
|
||||
* `winit` has a minimum OS requirement of iOS 8
|
||||
* Get the `UIWindow` object pointer
|
||||
* Get the `UIViewController` object pointer
|
||||
* Get the `UIView` object pointer
|
||||
|
|
|
@ -329,7 +329,7 @@ pub struct Touch {
|
|||
///
|
||||
/// ## Platform-specific
|
||||
///
|
||||
/// - Only available on **iOS**.
|
||||
/// - Only available on **iOS** 9.0+.
|
||||
pub force: Option<Force>,
|
||||
/// Unique identifier of a finger.
|
||||
pub id: u64,
|
||||
|
|
|
@ -70,6 +70,8 @@ pub trait WindowExtIOS {
|
|||
/// [`-[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).
|
||||
///
|
||||
/// This only has an effect on iOS 11.0+.
|
||||
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
|
||||
|
@ -79,6 +81,8 @@ pub trait WindowExtIOS {
|
|||
/// [`-[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).
|
||||
///
|
||||
/// This only has an effect on iOS 11.0+.
|
||||
fn set_preferred_screen_edges_deferring_system_gestures(&self, edges: ScreenEdge);
|
||||
|
||||
/// Sets whether the [`Window`] prefers the status bar hidden.
|
||||
|
@ -167,6 +171,8 @@ pub trait WindowBuilderExtIOS {
|
|||
///
|
||||
/// This sets the initial value returned by
|
||||
/// [`-[UIViewController prefersHomeIndicatorAutoHidden]`](https://developer.apple.com/documentation/uikit/uiviewcontroller/2887510-prefershomeindicatorautohidden?language=objc).
|
||||
///
|
||||
/// This only has an effect on iOS 11.0+.
|
||||
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
|
||||
|
@ -174,6 +180,8 @@ pub trait WindowBuilderExtIOS {
|
|||
///
|
||||
/// This sets the initial value returned by
|
||||
/// [`-[UIViewController preferredScreenEdgesDeferringSystemGestures]`](https://developer.apple.com/documentation/uikit/uiviewcontroller/2887512-preferredscreenedgesdeferringsys?language=objc).
|
||||
///
|
||||
/// This only has an effect on iOS 11.0+.
|
||||
fn with_preferred_screen_edges_deferring_system_gestures(
|
||||
self,
|
||||
edges: ScreenEdge,
|
||||
|
|
|
@ -6,6 +6,8 @@ use std::{
|
|||
time::Instant,
|
||||
};
|
||||
|
||||
use objc::runtime::{BOOL, YES};
|
||||
|
||||
use crate::{
|
||||
event::{Event, StartCause},
|
||||
event_loop::ControlFlow,
|
||||
|
@ -16,7 +18,8 @@ use crate::platform_impl::platform::{
|
|||
ffi::{
|
||||
id, kCFRunLoopCommonModes, CFAbsoluteTimeGetCurrent, CFRelease, CFRunLoopAddTimer,
|
||||
CFRunLoopGetMain, CFRunLoopRef, CFRunLoopTimerCreate, CFRunLoopTimerInvalidate,
|
||||
CFRunLoopTimerRef, CFRunLoopTimerSetNextFireDate, NSUInteger,
|
||||
CFRunLoopTimerRef, CFRunLoopTimerSetNextFireDate, NSInteger, NSOperatingSystemVersion,
|
||||
NSUInteger,
|
||||
},
|
||||
};
|
||||
|
||||
|
@ -126,7 +129,7 @@ impl AppState {
|
|||
..
|
||||
} => {
|
||||
queued_windows.push(window);
|
||||
msg_send![window, retain];
|
||||
let _: id = msg_send![window, retain];
|
||||
return;
|
||||
}
|
||||
&mut AppStateImpl::ProcessingEvents { .. } => {}
|
||||
|
@ -199,7 +202,7 @@ impl AppState {
|
|||
// completed. This may result in incorrect visual appearance.
|
||||
// ```
|
||||
let screen: id = msg_send![window, screen];
|
||||
let () = msg_send![screen, retain];
|
||||
let _: id = msg_send![screen, retain];
|
||||
let () = msg_send![window, setScreen:0 as id];
|
||||
let () = msg_send![window, setScreen: screen];
|
||||
let () = msg_send![screen, release];
|
||||
|
@ -618,3 +621,95 @@ impl EventLoopWaker {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
macro_rules! os_capabilities {
|
||||
(
|
||||
$(
|
||||
$(#[$attr:meta])*
|
||||
$error_name:ident: $objc_call:literal,
|
||||
$name:ident: $major:literal-$minor:literal
|
||||
),*
|
||||
$(,)*
|
||||
) => {
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct OSCapabilities {
|
||||
$(
|
||||
pub $name: bool,
|
||||
)*
|
||||
|
||||
os_version: NSOperatingSystemVersion,
|
||||
}
|
||||
|
||||
impl From<NSOperatingSystemVersion> for OSCapabilities {
|
||||
fn from(os_version: NSOperatingSystemVersion) -> OSCapabilities {
|
||||
$(let $name = os_version.meets_requirements($major, $minor);)*
|
||||
OSCapabilities { $($name,)* os_version, }
|
||||
}
|
||||
}
|
||||
|
||||
impl OSCapabilities {$(
|
||||
$(#[$attr])*
|
||||
pub fn $error_name(&self, extra_msg: &str) {
|
||||
log::warn!(
|
||||
concat!("`", $objc_call, "` requires iOS {}.{}+. This device is running iOS {}.{}.{}. {}"),
|
||||
$major, $minor, self.os_version.major, self.os_version.minor, self.os_version.patch,
|
||||
extra_msg
|
||||
)
|
||||
}
|
||||
)*}
|
||||
};
|
||||
}
|
||||
|
||||
os_capabilities! {
|
||||
/// https://developer.apple.com/documentation/uikit/uiview/2891103-safeareainsets?language=objc
|
||||
#[allow(unused)] // error message unused
|
||||
safe_area_err_msg: "-[UIView safeAreaInsets]",
|
||||
safe_area: 11-0,
|
||||
/// https://developer.apple.com/documentation/uikit/uiviewcontroller/2887509-setneedsupdateofhomeindicatoraut?language=objc
|
||||
home_indicator_hidden_err_msg: "-[UIViewController setNeedsUpdateOfHomeIndicatorAutoHidden]",
|
||||
home_indicator_hidden: 11-0,
|
||||
/// https://developer.apple.com/documentation/uikit/uiviewcontroller/2887507-setneedsupdateofscreenedgesdefer?language=objc
|
||||
defer_system_gestures_err_msg: "-[UIViewController setNeedsUpdateOfScreenEdgesDeferringSystem]",
|
||||
defer_system_gestures: 11-0,
|
||||
/// https://developer.apple.com/documentation/uikit/uiscreen/2806814-maximumframespersecond?language=objc
|
||||
maximum_frames_per_second_err_msg: "-[UIScreen maximumFramesPerSecond]",
|
||||
maximum_frames_per_second: 10-3,
|
||||
/// https://developer.apple.com/documentation/uikit/uitouch/1618110-force?language=objc
|
||||
#[allow(unused)] // error message unused
|
||||
force_touch_err_msg: "-[UITouch force]",
|
||||
force_touch: 9-0,
|
||||
}
|
||||
|
||||
impl NSOperatingSystemVersion {
|
||||
fn meets_requirements(&self, required_major: NSInteger, required_minor: NSInteger) -> bool {
|
||||
(self.major, self.minor) >= (required_major, required_minor)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn os_capabilities() -> OSCapabilities {
|
||||
lazy_static! {
|
||||
static ref OS_CAPABILITIES: OSCapabilities = {
|
||||
let version: NSOperatingSystemVersion = unsafe {
|
||||
let process_info: id = msg_send![class!(NSProcessInfo), processInfo];
|
||||
let atleast_ios_8: BOOL = msg_send![
|
||||
process_info,
|
||||
respondsToSelector: sel!(operatingSystemVersion)
|
||||
];
|
||||
// winit requires atleast iOS 8 because no one has put the time into supporting earlier os versions.
|
||||
// Older iOS versions are increasingly difficult to test. For example, Xcode 11 does not support
|
||||
// debugging on devices with an iOS version of less than 8. Another example, in order to use an iOS
|
||||
// simulator older than iOS 8, you must download an older version of Xcode (<9), and at least Xcode 7
|
||||
// has been tested to not even run on macOS 10.15 - Xcode 8 might?
|
||||
//
|
||||
// The minimum required iOS version is likely to grow in the future.
|
||||
assert!(
|
||||
atleast_ios_8 == YES,
|
||||
"`winit` requires iOS version 8 or greater"
|
||||
);
|
||||
msg_send![process_info, operatingSystemVersion]
|
||||
};
|
||||
version.into()
|
||||
};
|
||||
}
|
||||
OS_CAPABILITIES.clone()
|
||||
}
|
||||
|
|
|
@ -23,8 +23,7 @@ use crate::platform_impl::platform::{
|
|||
CFRunLoopActivity, CFRunLoopAddObserver, CFRunLoopAddSource, CFRunLoopGetMain,
|
||||
CFRunLoopObserverCreate, CFRunLoopObserverRef, CFRunLoopSourceContext,
|
||||
CFRunLoopSourceCreate, CFRunLoopSourceInvalidate, CFRunLoopSourceRef,
|
||||
CFRunLoopSourceSignal, CFRunLoopWakeUp, NSOperatingSystemVersion, NSString,
|
||||
UIApplicationMain, UIUserInterfaceIdiom,
|
||||
CFRunLoopSourceSignal, CFRunLoopWakeUp, NSString, UIApplicationMain, UIUserInterfaceIdiom,
|
||||
},
|
||||
monitor, view, MonitorHandle,
|
||||
};
|
||||
|
@ -32,13 +31,6 @@ use crate::platform_impl::platform::{
|
|||
pub struct EventLoopWindowTarget<T: 'static> {
|
||||
receiver: Receiver<T>,
|
||||
sender_to_clone: Sender<T>,
|
||||
capabilities: Capabilities,
|
||||
}
|
||||
|
||||
impl<T: 'static> EventLoopWindowTarget<T> {
|
||||
pub fn capabilities(&self) -> &Capabilities {
|
||||
&self.capabilities
|
||||
}
|
||||
}
|
||||
|
||||
pub struct EventLoop<T: 'static> {
|
||||
|
@ -64,18 +56,11 @@ impl<T: 'static> EventLoop<T> {
|
|||
// this line sets up the main run loop before `UIApplicationMain`
|
||||
setup_control_flow_observers();
|
||||
|
||||
let version: NSOperatingSystemVersion = unsafe {
|
||||
let process_info: id = msg_send![class!(NSProcessInfo), processInfo];
|
||||
msg_send![process_info, operatingSystemVersion]
|
||||
};
|
||||
let capabilities = version.into();
|
||||
|
||||
EventLoop {
|
||||
window_target: RootEventLoopWindowTarget {
|
||||
p: EventLoopWindowTarget {
|
||||
receiver,
|
||||
sender_to_clone,
|
||||
capabilities,
|
||||
},
|
||||
_marker: PhantomData,
|
||||
},
|
||||
|
@ -296,20 +281,3 @@ pub unsafe fn get_idiom() -> Idiom {
|
|||
let raw_idiom: UIUserInterfaceIdiom = msg_send![device, userInterfaceIdiom];
|
||||
raw_idiom.into()
|
||||
}
|
||||
|
||||
pub struct Capabilities {
|
||||
pub supports_safe_area: bool,
|
||||
}
|
||||
|
||||
impl From<NSOperatingSystemVersion> for Capabilities {
|
||||
fn from(os_version: NSOperatingSystemVersion) -> Capabilities {
|
||||
assert!(
|
||||
os_version.major >= 8,
|
||||
"`winit` current requires iOS version 8 or greater"
|
||||
);
|
||||
|
||||
let supports_safe_area = os_version.major >= 11;
|
||||
|
||||
Capabilities { supports_safe_area }
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,7 +7,10 @@ use std::{
|
|||
use crate::{
|
||||
dpi::{PhysicalPosition, PhysicalSize},
|
||||
monitor::{MonitorHandle as RootMonitorHandle, VideoMode as RootVideoMode},
|
||||
platform_impl::platform::ffi::{id, nil, CGFloat, CGRect, CGSize, NSInteger, NSUInteger},
|
||||
platform_impl::platform::{
|
||||
app_state,
|
||||
ffi::{id, nil, CGFloat, CGRect, CGSize, NSInteger, NSUInteger},
|
||||
},
|
||||
};
|
||||
|
||||
#[derive(Debug, PartialEq, Eq, Hash)]
|
||||
|
@ -35,7 +38,7 @@ 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];
|
||||
let () = msg_send![self.screen_mode, release];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -43,7 +46,23 @@ impl Drop for 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 os_capabilities = app_state::os_capabilities();
|
||||
let refresh_rate: NSInteger = if os_capabilities.maximum_frames_per_second {
|
||||
msg_send![uiscreen, maximumFramesPerSecond]
|
||||
} else {
|
||||
// https://developer.apple.com/library/archive/technotes/tn2460/_index.html
|
||||
// https://en.wikipedia.org/wiki/IPad_Pro#Model_comparison
|
||||
//
|
||||
// All iOS devices support 60 fps, and on devices where `maximumFramesPerSecond` is not
|
||||
// supported, they are all guaranteed to have 60hz refresh rates. This does not
|
||||
// correctly handle external displays. ProMotion displays support 120fps, but they were
|
||||
// introduced at the same time as the `maximumFramesPerSecond` API.
|
||||
//
|
||||
// FIXME: earlier OSs could calculate the refresh rate using
|
||||
// `-[CADisplayLink duration]`.
|
||||
os_capabilities.maximum_frames_per_second_err_msg("defaulting to 60 fps");
|
||||
60
|
||||
};
|
||||
let size: CGSize = msg_send![screen_mode, size];
|
||||
VideoMode {
|
||||
size: (size.width as u32, size.height as u32),
|
||||
|
|
|
@ -9,7 +9,7 @@ use crate::{
|
|||
event::{DeviceId as RootDeviceId, Event, Force, Touch, TouchPhase, WindowEvent},
|
||||
platform::ios::MonitorHandleExtIOS,
|
||||
platform_impl::platform::{
|
||||
app_state::AppState,
|
||||
app_state::{self, AppState, OSCapabilities},
|
||||
event_loop,
|
||||
ffi::{
|
||||
id, nil, CGFloat, CGPoint, CGRect, UIForceTouchCapability, UIInterfaceOrientationMask,
|
||||
|
@ -27,10 +27,24 @@ macro_rules! add_property {
|
|||
$name:ident: $t:ty,
|
||||
$setter_name:ident: |$object:ident| $after_set:expr,
|
||||
$getter_name:ident,
|
||||
) => {
|
||||
add_property!(
|
||||
$decl,
|
||||
$name: $t,
|
||||
$setter_name: true, |_, _|{}; |$object| $after_set,
|
||||
$getter_name,
|
||||
)
|
||||
};
|
||||
(
|
||||
$decl:ident,
|
||||
$name:ident: $t:ty,
|
||||
$setter_name:ident: $capability:expr, $err:expr; |$object:ident| $after_set:expr,
|
||||
$getter_name:ident,
|
||||
) => {
|
||||
{
|
||||
const VAR_NAME: &'static str = concat!("_", stringify!($name));
|
||||
$decl.add_ivar::<$t>(VAR_NAME);
|
||||
let setter = if $capability {
|
||||
#[allow(non_snake_case)]
|
||||
extern "C" fn $setter_name($object: &mut Object, _: Sel, value: $t) {
|
||||
unsafe {
|
||||
|
@ -38,13 +52,24 @@ macro_rules! add_property {
|
|||
}
|
||||
$after_set
|
||||
}
|
||||
$setter_name
|
||||
} else {
|
||||
#[allow(non_snake_case)]
|
||||
extern "C" fn $setter_name($object: &mut Object, _: Sel, value: $t) {
|
||||
unsafe {
|
||||
$object.set_ivar::<$t>(VAR_NAME, value);
|
||||
}
|
||||
$err(&app_state::os_capabilities(), "ignoring")
|
||||
}
|
||||
$setter_name
|
||||
};
|
||||
#[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),
|
||||
setter as extern "C" fn(&mut Object, Sel, $t),
|
||||
);
|
||||
$decl.add_method(
|
||||
sel!($getter_name),
|
||||
|
@ -125,6 +150,8 @@ unsafe fn get_view_class(root_view_class: &'static Class) -> &'static Class {
|
|||
unsafe fn get_view_controller_class() -> &'static Class {
|
||||
static mut CLASS: Option<&'static Class> = None;
|
||||
if CLASS.is_none() {
|
||||
let os_capabilities = app_state::os_capabilities();
|
||||
|
||||
let uiviewcontroller_class = class!(UIViewController);
|
||||
|
||||
extern "C" fn should_autorotate(_: &Object, _: Sel) -> BOOL {
|
||||
|
@ -150,7 +177,10 @@ unsafe fn get_view_controller_class() -> &'static Class {
|
|||
add_property! {
|
||||
decl,
|
||||
prefers_home_indicator_auto_hidden: BOOL,
|
||||
setPrefersHomeIndicatorAutoHidden: |object| {
|
||||
setPrefersHomeIndicatorAutoHidden:
|
||||
os_capabilities.home_indicator_hidden,
|
||||
OSCapabilities::home_indicator_hidden_err_msg;
|
||||
|object| {
|
||||
unsafe {
|
||||
let () = msg_send![object, setNeedsUpdateOfHomeIndicatorAutoHidden];
|
||||
}
|
||||
|
@ -170,7 +200,10 @@ unsafe fn get_view_controller_class() -> &'static Class {
|
|||
add_property! {
|
||||
decl,
|
||||
preferred_screen_edges_deferring_system_gestures: UIRectEdge,
|
||||
setPreferredScreenEdgesDeferringSystemGestures: |object| {
|
||||
setPreferredScreenEdgesDeferringSystemGestures:
|
||||
os_capabilities.defer_system_gestures,
|
||||
OSCapabilities::defer_system_gestures_err_msg;
|
||||
|object| {
|
||||
unsafe {
|
||||
let () = msg_send![object, setNeedsUpdateOfScreenEdgesDeferringSystemGestures];
|
||||
}
|
||||
|
@ -213,6 +246,7 @@ unsafe fn get_window_class() -> &'static Class {
|
|||
let uiscreen = msg_send![object, screen];
|
||||
let touches_enum: id = msg_send![touches, objectEnumerator];
|
||||
let mut touch_events = Vec::new();
|
||||
let os_supports_force = app_state::os_capabilities().force_touch;
|
||||
loop {
|
||||
let touch: id = msg_send![touches_enum, nextObject];
|
||||
if touch == nil {
|
||||
|
@ -220,12 +254,15 @@ unsafe fn get_window_class() -> &'static Class {
|
|||
}
|
||||
let location: CGPoint = msg_send![touch, locationInView: nil];
|
||||
let touch_type: UITouchType = msg_send![touch, type];
|
||||
let force = if os_supports_force {
|
||||
let trait_collection: id = msg_send![object, traitCollection];
|
||||
let touch_capability: UIForceTouchCapability =
|
||||
msg_send![trait_collection, forceTouchCapability];
|
||||
let force = if touch_capability == UIForceTouchCapability::Available {
|
||||
// Both the OS _and_ the device need to be checked for force touch support.
|
||||
if touch_capability == UIForceTouchCapability::Available {
|
||||
let force: CGFloat = msg_send![touch, force];
|
||||
let max_possible_force: CGFloat = msg_send![touch, maximumPossibleForce];
|
||||
let max_possible_force: CGFloat =
|
||||
msg_send![touch, maximumPossibleForce];
|
||||
let altitude_angle: Option<f64> = if touch_type == UITouchType::Pencil {
|
||||
let angle: CGFloat = msg_send![touch, altitudeAngle];
|
||||
Some(angle as _)
|
||||
|
@ -239,6 +276,9 @@ unsafe fn get_window_class() -> &'static Class {
|
|||
})
|
||||
} else {
|
||||
None
|
||||
}
|
||||
} else {
|
||||
None
|
||||
};
|
||||
let touch_id = touch as u64;
|
||||
let phase: UITouchPhase = msg_send![touch, phase];
|
||||
|
|
|
@ -13,7 +13,7 @@ use crate::{
|
|||
monitor::MonitorHandle as RootMonitorHandle,
|
||||
platform::ios::{MonitorHandleExtIOS, ScreenEdge, ValidOrientations},
|
||||
platform_impl::platform::{
|
||||
app_state::AppState,
|
||||
app_state::{self, AppState},
|
||||
event_loop,
|
||||
ffi::{
|
||||
id, CGFloat, CGPoint, CGRect, CGSize, UIEdgeInsets, UIInterfaceOrientationMask,
|
||||
|
@ -28,7 +28,6 @@ pub struct Inner {
|
|||
pub window: id,
|
||||
pub view_controller: id,
|
||||
pub view: id,
|
||||
supports_safe_area: bool,
|
||||
}
|
||||
|
||||
impl Drop for Inner {
|
||||
|
@ -300,7 +299,7 @@ impl DerefMut for Window {
|
|||
|
||||
impl Window {
|
||||
pub fn new<T>(
|
||||
event_loop: &EventLoopWindowTarget<T>,
|
||||
_event_loop: &EventLoopWindowTarget<T>,
|
||||
window_attributes: WindowAttributes,
|
||||
platform_attributes: PlatformSpecificWindowBuilderAttributes,
|
||||
) -> Result<Window, RootOsError> {
|
||||
|
@ -347,14 +346,11 @@ impl Window {
|
|||
view_controller,
|
||||
);
|
||||
|
||||
let supports_safe_area = event_loop.capabilities().supports_safe_area;
|
||||
|
||||
let result = Window {
|
||||
inner: Inner {
|
||||
window,
|
||||
view_controller,
|
||||
view,
|
||||
supports_safe_area,
|
||||
},
|
||||
};
|
||||
AppState::set_key_window(window);
|
||||
|
@ -396,7 +392,7 @@ impl Inner {
|
|||
msg_send![
|
||||
self.view_controller,
|
||||
setSupportedInterfaceOrientations: supported_orientations
|
||||
];
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -462,7 +458,7 @@ impl Inner {
|
|||
// requires main thread
|
||||
unsafe fn safe_area_screen_space(&self) -> CGRect {
|
||||
let bounds: CGRect = msg_send![self.window, bounds];
|
||||
if self.supports_safe_area {
|
||||
if app_state::os_capabilities().safe_area {
|
||||
let safe_area: UIEdgeInsets = msg_send![self.window, safeAreaInsets];
|
||||
let safe_bounds = CGRect {
|
||||
origin: CGPoint {
|
||||
|
|
Loading…
Reference in a new issue