mirror of
https://github.com/italicsjenga/winit-sonoma-fix.git
synced 2024-12-24 06:11:30 +11:00
Fix null window on initial HiDpiFactorChanged
event on iOS (#1167)
This commit is contained in:
parent
3716f13d8e
commit
95581ab92f
|
@ -11,6 +11,7 @@
|
||||||
- Officially remove the Emscripten backend.
|
- Officially remove the Emscripten backend.
|
||||||
- On Windows, fix handling of surrogate pairs when dispatching `ReceivedCharacter`.
|
- On Windows, fix handling of surrogate pairs when dispatching `ReceivedCharacter`.
|
||||||
- On macOS 10.15, fix freeze upon exiting exclusive fullscreen mode.
|
- On macOS 10.15, fix freeze upon exiting exclusive fullscreen mode.
|
||||||
|
- On iOS, fix null window on initial `HiDpiFactorChanged` event.
|
||||||
|
|
||||||
# 0.20.0 Alpha 3 (2019-08-14)
|
# 0.20.0 Alpha 3 (2019-08-14)
|
||||||
|
|
||||||
|
|
|
@ -101,6 +101,7 @@ unsafe fn get_view_class(root_view_class: &'static Class) -> &'static Class {
|
||||||
extern "C" fn draw_rect(object: &Object, _: Sel, rect: CGRect) {
|
extern "C" fn draw_rect(object: &Object, _: Sel, rect: CGRect) {
|
||||||
unsafe {
|
unsafe {
|
||||||
let window: id = msg_send![object, window];
|
let window: id = msg_send![object, window];
|
||||||
|
assert!(!window.is_null());
|
||||||
app_state::handle_nonuser_event(Event::WindowEvent {
|
app_state::handle_nonuser_event(Event::WindowEvent {
|
||||||
window_id: RootWindowId(window.into()),
|
window_id: RootWindowId(window.into()),
|
||||||
event: WindowEvent::RedrawRequested,
|
event: WindowEvent::RedrawRequested,
|
||||||
|
@ -116,6 +117,7 @@ unsafe fn get_view_class(root_view_class: &'static Class) -> &'static Class {
|
||||||
let () = msg_send![super(object, superclass), layoutSubviews];
|
let () = msg_send![super(object, superclass), layoutSubviews];
|
||||||
|
|
||||||
let window: id = msg_send![object, window];
|
let window: id = msg_send![object, window];
|
||||||
|
assert!(!window.is_null());
|
||||||
let bounds: CGRect = msg_send![window, bounds];
|
let bounds: CGRect = msg_send![window, bounds];
|
||||||
let screen: id = msg_send![window, screen];
|
let screen: id = msg_send![window, screen];
|
||||||
let screen_space: id = msg_send![screen, coordinateSpace];
|
let screen_space: id = msg_send![screen, coordinateSpace];
|
||||||
|
@ -144,23 +146,24 @@ unsafe fn get_view_class(root_view_class: &'static Class) -> &'static Class {
|
||||||
setContentScaleFactor: untrusted_hidpi_factor
|
setContentScaleFactor: untrusted_hidpi_factor
|
||||||
];
|
];
|
||||||
|
|
||||||
// On launch, iOS sets the contentScaleFactor to 0.0. This is a sentinel value that
|
let window: id = msg_send![object, window];
|
||||||
// iOS appears to use to "reset" the contentScaleFactor to the device specific
|
// `window` is null when `setContentScaleFactor` is invoked prior to `[UIWindow
|
||||||
// default value.
|
// makeKeyAndVisible]` at window creation time (either manually or internally by
|
||||||
//
|
// UIKit when the `UIView` is first created), in which case we send no events here
|
||||||
// The workaround is to not trust the value received by this function, and always
|
if window.is_null() {
|
||||||
// go through the getter.
|
return;
|
||||||
|
}
|
||||||
|
// `setContentScaleFactor` may be called with a value of 0, which means "reset the
|
||||||
|
// content scale factor to a device-specific default value", so we can't use the
|
||||||
|
// parameter here. We can query the actual factor using the getter
|
||||||
let hidpi_factor: CGFloat = msg_send![object, contentScaleFactor];
|
let hidpi_factor: CGFloat = msg_send![object, contentScaleFactor];
|
||||||
assert!(
|
assert!(
|
||||||
!hidpi_factor.is_nan()
|
!hidpi_factor.is_nan()
|
||||||
&& hidpi_factor.is_finite()
|
&& hidpi_factor.is_finite()
|
||||||
&& hidpi_factor.is_sign_positive()
|
&& hidpi_factor.is_sign_positive()
|
||||||
&& hidpi_factor > 0.0,
|
&& hidpi_factor > 0.0,
|
||||||
"invalid hidpi_factor set on UIWindow",
|
"invalid hidpi_factor set on UIView",
|
||||||
);
|
);
|
||||||
|
|
||||||
let window: id = msg_send![object, window];
|
|
||||||
|
|
||||||
let bounds: CGRect = msg_send![object, bounds];
|
let bounds: CGRect = msg_send![object, bounds];
|
||||||
let screen: id = msg_send![window, screen];
|
let screen: id = msg_send![window, screen];
|
||||||
let screen_space: id = msg_send![screen, coordinateSpace];
|
let screen_space: id = msg_send![screen, coordinateSpace];
|
||||||
|
@ -186,6 +189,7 @@ unsafe fn get_view_class(root_view_class: &'static Class) -> &'static Class {
|
||||||
extern "C" fn handle_touches(object: &Object, _: Sel, touches: id, _: id) {
|
extern "C" fn handle_touches(object: &Object, _: Sel, touches: id, _: id) {
|
||||||
unsafe {
|
unsafe {
|
||||||
let window: id = msg_send![object, window];
|
let window: id = msg_send![object, window];
|
||||||
|
assert!(!window.is_null());
|
||||||
let uiscreen: id = msg_send![window, screen];
|
let uiscreen: id = msg_send![window, screen];
|
||||||
let touches_enum: id = msg_send![touches, objectEnumerator];
|
let touches_enum: id = msg_send![touches, objectEnumerator];
|
||||||
let mut touch_events = Vec::new();
|
let mut touch_events = Vec::new();
|
||||||
|
|
|
@ -9,6 +9,7 @@ use objc::runtime::{Class, Object, BOOL, NO, YES};
|
||||||
use crate::{
|
use crate::{
|
||||||
dpi::{self, LogicalPosition, LogicalSize},
|
dpi::{self, LogicalPosition, LogicalSize},
|
||||||
error::{ExternalError, NotSupportedError, OsError as RootOsError},
|
error::{ExternalError, NotSupportedError, OsError as RootOsError},
|
||||||
|
event::{Event, WindowEvent},
|
||||||
icon::Icon,
|
icon::Icon,
|
||||||
monitor::MonitorHandle as RootMonitorHandle,
|
monitor::MonitorHandle as RootMonitorHandle,
|
||||||
platform::ios::{MonitorHandleExtIOS, ScreenEdge, ValidOrientations},
|
platform::ios::{MonitorHandleExtIOS, ScreenEdge, ValidOrientations},
|
||||||
|
@ -20,7 +21,7 @@ use crate::{
|
||||||
},
|
},
|
||||||
monitor, view, EventLoopWindowTarget, MonitorHandle,
|
monitor, view, EventLoopWindowTarget, MonitorHandle,
|
||||||
},
|
},
|
||||||
window::{CursorIcon, Fullscreen, WindowAttributes},
|
window::{CursorIcon, Fullscreen, WindowAttributes, WindowId as RootWindowId},
|
||||||
};
|
};
|
||||||
|
|
||||||
pub struct Inner {
|
pub struct Inner {
|
||||||
|
@ -377,6 +378,32 @@ impl Window {
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
app_state::set_key_window(window);
|
app_state::set_key_window(window);
|
||||||
|
|
||||||
|
// Like the Windows and macOS backends, we send a `HiDpiFactorChanged` and `Resized`
|
||||||
|
// event on window creation if the DPI factor != 1.0
|
||||||
|
let hidpi_factor: CGFloat = msg_send![view, contentScaleFactor];
|
||||||
|
if hidpi_factor != 1.0 {
|
||||||
|
let bounds: CGRect = msg_send![view, bounds];
|
||||||
|
let screen: id = msg_send![window, screen];
|
||||||
|
let screen_space: id = msg_send![screen, coordinateSpace];
|
||||||
|
let screen_frame: CGRect =
|
||||||
|
msg_send![view, convertRect:bounds toCoordinateSpace:screen_space];
|
||||||
|
let size = crate::dpi::LogicalSize {
|
||||||
|
width: screen_frame.size.width as _,
|
||||||
|
height: screen_frame.size.height as _,
|
||||||
|
};
|
||||||
|
app_state::handle_nonuser_events(
|
||||||
|
std::iter::once(Event::WindowEvent {
|
||||||
|
window_id: RootWindowId(window.into()),
|
||||||
|
event: WindowEvent::HiDpiFactorChanged(hidpi_factor as _),
|
||||||
|
})
|
||||||
|
.chain(std::iter::once(Event::WindowEvent {
|
||||||
|
window_id: RootWindowId(window.into()),
|
||||||
|
event: WindowEvent::Resized(size),
|
||||||
|
})),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
Ok(result)
|
Ok(result)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue