mirror of
https://github.com/italicsjenga/winit-sonoma-fix.git
synced 2024-12-23 22:01:31 +11:00
iOS: Dpi overhaul (#1223)
* WIP - Make EL2 DPI changes and implement on Windows (#895) * Modify DPI API publicly and on Windows * Add generic Position and make dpi creation functions const * Make examples work * Fix fullscreen windows not appearing * Replace Logical coordinates in window events with Physical coordinates * Update HiDpiFactorChanged * Document to_static * On Windows, make AdjustRect calls DPI-aware when possible (#1015) * Use AdjustWidowRectExForDPI when available * Prioritize presevering logical size when handling WM_DPICHANGED * Format * Add changelog entry * macOS: Dpi overhaul (#997) * WIP - Make EL2 DPI changes and implement on Windows (#895) * Modify DPI API publicly and on Windows * Add generic Position and make dpi creation functions const * Make examples work * Fix fullscreen windows not appearing * Replace Logical coordinates in window events with Physical coordinates * Update HiDpiFactorChanged * Document to_static * fix app_state errors * fixes hidpi related errors in window_delegate * fix bad merge * dpi_factor edits in window_delegate * fixes type and lifetime errors in window and window_delegate * applies fmt * complies with @aleksijuvani requested changes * modifies Handler lifetimes * fixes lifetime isues, adds propper handling for HiDpiChanged * applies fmt * restore original lifetimes * solution is somewhere out there * applies fmt * pass as references * resolves issue with HANDLER * crate visible type error * fixes visibility issues * applies fmt * deals with warnings * simplifies new_inner_size setting algorthm * moves proxy instead of referencing it and removes double deref from proxy.ns_window * makes @Osspial tests (https://github.com/rust-windowing/winit/pull/997\#discussion_r301852354) pass * complies with @aleksijuvani suggested changes * makes max window size std::f32::MAX * On Windows, fix new DPI API not setting window size properly (#1130) * First attempt * Second attempt * Maintain cursor horizontal ratio * Fix DPI change handling when maximized * Revert window example * Make new DPI code more understandable * Format * Implement DPI Usability Upgrades for X11 and Wayland (#1098) * Fix compile errors * Use `mio` for the X11 event loop * Removes `calloop` from the X11 event loop, as the method of draining a source using a closure provided to the `calloop::EventLoop` instance conflicts with the need to deliver events directly to the callback provided to `EventLoop::run`, in order to respond to the value provided by `WindowEvent::HiDpiFactorChanged`. * Implement interactive `HiDpiFactorChanged` event for X11 * Implement interactive `HiDpiFactorChanged` event for Wayland * Run cargo fmt * Fix Wayland not processing events from EventQueue * Backport #981 * some lifetime tinkering * finishes lifetime tinkering * fixes all type errors * adds support ffi functions * adds wrappers for nonstatic events * replaces events with event wrappers * reimplementing hidpichanged event in app_state * implements HiDpiFactorChanged for iOS * applies formatter * complies with @aleksijuvani requested changes * resolves conflicts * applies fmt * removes merge blurp * corrects state of CHANGELOG * fix fmt check error * fixes hidpi_factor for armv7-apple-ios
This commit is contained in:
parent
cbf61e5cb9
commit
b16042a047
|
@ -12,15 +12,16 @@ use std::{
|
||||||
use objc::runtime::{BOOL, YES};
|
use objc::runtime::{BOOL, YES};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
event::{Event, StartCause},
|
dpi::LogicalSize,
|
||||||
|
event::{Event, StartCause, WindowEvent},
|
||||||
event_loop::ControlFlow,
|
event_loop::ControlFlow,
|
||||||
platform_impl::platform::{
|
platform_impl::platform::{
|
||||||
event_loop::{EventHandler, Never},
|
event_loop::{EventHandler, EventProxy, EventWrapper, Never},
|
||||||
ffi::{
|
ffi::{
|
||||||
id, kCFRunLoopCommonModes, CFAbsoluteTimeGetCurrent, CFRelease, CFRunLoopAddTimer,
|
id, kCFRunLoopCommonModes, CFAbsoluteTimeGetCurrent, CFRelease, CFRunLoopAddTimer,
|
||||||
CFRunLoopGetMain, CFRunLoopRef, CFRunLoopTimerCreate, CFRunLoopTimerInvalidate,
|
CFRunLoopGetMain, CFRunLoopRef, CFRunLoopTimerCreate, CFRunLoopTimerInvalidate,
|
||||||
CFRunLoopTimerRef, CFRunLoopTimerSetNextFireDate, NSInteger, NSOperatingSystemVersion,
|
CFRunLoopTimerRef, CFRunLoopTimerSetNextFireDate, CGRect, CGSize, NSInteger,
|
||||||
NSUInteger,
|
NSOperatingSystemVersion, NSUInteger,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
window::WindowId as RootWindowId,
|
window::WindowId as RootWindowId,
|
||||||
|
@ -45,11 +46,11 @@ enum UserCallbackTransitionResult<'a> {
|
||||||
processing_redraws: bool,
|
processing_redraws: bool,
|
||||||
},
|
},
|
||||||
ReentrancyPrevented {
|
ReentrancyPrevented {
|
||||||
queued_events: &'a mut Vec<Event<Never>>,
|
queued_events: &'a mut Vec<EventWrapper>,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Event<Never> {
|
impl Event<'static, Never> {
|
||||||
fn is_redraw(&self) -> bool {
|
fn is_redraw(&self) -> bool {
|
||||||
if let Event::RedrawRequested(_) = self {
|
if let Event::RedrawRequested(_) = self {
|
||||||
true
|
true
|
||||||
|
@ -65,12 +66,12 @@ impl Event<Never> {
|
||||||
enum AppStateImpl {
|
enum AppStateImpl {
|
||||||
NotLaunched {
|
NotLaunched {
|
||||||
queued_windows: Vec<id>,
|
queued_windows: Vec<id>,
|
||||||
queued_events: Vec<Event<Never>>,
|
queued_events: Vec<EventWrapper>,
|
||||||
queued_gpu_redraws: HashSet<id>,
|
queued_gpu_redraws: HashSet<id>,
|
||||||
},
|
},
|
||||||
Launching {
|
Launching {
|
||||||
queued_windows: Vec<id>,
|
queued_windows: Vec<id>,
|
||||||
queued_events: Vec<Event<Never>>,
|
queued_events: Vec<EventWrapper>,
|
||||||
queued_event_handler: Box<dyn EventHandler>,
|
queued_event_handler: Box<dyn EventHandler>,
|
||||||
queued_gpu_redraws: HashSet<id>,
|
queued_gpu_redraws: HashSet<id>,
|
||||||
},
|
},
|
||||||
|
@ -81,7 +82,7 @@ enum AppStateImpl {
|
||||||
},
|
},
|
||||||
// special state to deal with reentrancy and prevent mutable aliasing.
|
// special state to deal with reentrancy and prevent mutable aliasing.
|
||||||
InUserCallback {
|
InUserCallback {
|
||||||
queued_events: Vec<Event<Never>>,
|
queued_events: Vec<EventWrapper>,
|
||||||
queued_gpu_redraws: HashSet<id>,
|
queued_gpu_redraws: HashSet<id>,
|
||||||
},
|
},
|
||||||
ProcessingRedraws {
|
ProcessingRedraws {
|
||||||
|
@ -222,7 +223,7 @@ impl AppState {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
fn did_finish_launching_transition(&mut self) -> (Vec<id>, Vec<Event<Never>>) {
|
fn did_finish_launching_transition(&mut self) -> (Vec<id>, Vec<EventWrapper>) {
|
||||||
let (windows, events, event_handler, queued_gpu_redraws) = match self.take_state() {
|
let (windows, events, event_handler, queued_gpu_redraws) = match self.take_state() {
|
||||||
AppStateImpl::Launching {
|
AppStateImpl::Launching {
|
||||||
queued_windows,
|
queued_windows,
|
||||||
|
@ -245,7 +246,7 @@ impl AppState {
|
||||||
(windows, events)
|
(windows, events)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn wakeup_transition(&mut self) -> Option<Event<Never>> {
|
fn wakeup_transition(&mut self) -> Option<EventWrapper> {
|
||||||
// before `AppState::did_finish_launching` is called, pretend there is no running
|
// before `AppState::did_finish_launching` is called, pretend there is no running
|
||||||
// event loop.
|
// event loop.
|
||||||
if !self.has_launched() {
|
if !self.has_launched() {
|
||||||
|
@ -258,7 +259,10 @@ impl AppState {
|
||||||
AppStateImpl::PollFinished {
|
AppStateImpl::PollFinished {
|
||||||
waiting_event_handler,
|
waiting_event_handler,
|
||||||
},
|
},
|
||||||
) => (waiting_event_handler, Event::NewEvents(StartCause::Poll)),
|
) => (
|
||||||
|
waiting_event_handler,
|
||||||
|
EventWrapper::StaticEvent(Event::NewEvents(StartCause::Poll)),
|
||||||
|
),
|
||||||
(
|
(
|
||||||
ControlFlow::Wait,
|
ControlFlow::Wait,
|
||||||
AppStateImpl::Waiting {
|
AppStateImpl::Waiting {
|
||||||
|
@ -267,10 +271,10 @@ impl AppState {
|
||||||
},
|
},
|
||||||
) => (
|
) => (
|
||||||
waiting_event_handler,
|
waiting_event_handler,
|
||||||
Event::NewEvents(StartCause::WaitCancelled {
|
EventWrapper::StaticEvent(Event::NewEvents(StartCause::WaitCancelled {
|
||||||
start,
|
start,
|
||||||
requested_resume: None,
|
requested_resume: None,
|
||||||
}),
|
})),
|
||||||
),
|
),
|
||||||
(
|
(
|
||||||
ControlFlow::WaitUntil(requested_resume),
|
ControlFlow::WaitUntil(requested_resume),
|
||||||
|
@ -280,15 +284,15 @@ impl AppState {
|
||||||
},
|
},
|
||||||
) => {
|
) => {
|
||||||
let event = if Instant::now() >= requested_resume {
|
let event = if Instant::now() >= requested_resume {
|
||||||
Event::NewEvents(StartCause::ResumeTimeReached {
|
EventWrapper::StaticEvent(Event::NewEvents(StartCause::ResumeTimeReached {
|
||||||
start,
|
start,
|
||||||
requested_resume,
|
requested_resume,
|
||||||
})
|
}))
|
||||||
} else {
|
} else {
|
||||||
Event::NewEvents(StartCause::WaitCancelled {
|
EventWrapper::StaticEvent(Event::NewEvents(StartCause::WaitCancelled {
|
||||||
start,
|
start,
|
||||||
requested_resume: Some(requested_resume),
|
requested_resume: Some(requested_resume),
|
||||||
})
|
}))
|
||||||
};
|
};
|
||||||
(waiting_event_handler, event)
|
(waiting_event_handler, event)
|
||||||
}
|
}
|
||||||
|
@ -587,7 +591,10 @@ pub unsafe fn did_finish_launching() {
|
||||||
|
|
||||||
let (windows, events) = AppState::get_mut().did_finish_launching_transition();
|
let (windows, events) = AppState::get_mut().did_finish_launching_transition();
|
||||||
|
|
||||||
let events = std::iter::once(Event::NewEvents(StartCause::Init)).chain(events);
|
let events = std::iter::once(EventWrapper::StaticEvent(Event::NewEvents(
|
||||||
|
StartCause::Init,
|
||||||
|
)))
|
||||||
|
.chain(events);
|
||||||
handle_nonuser_events(events);
|
handle_nonuser_events(events);
|
||||||
|
|
||||||
// the above window dance hack, could possibly trigger new windows to be created.
|
// the above window dance hack, could possibly trigger new windows to be created.
|
||||||
|
@ -616,12 +623,12 @@ pub unsafe fn handle_wakeup_transition() {
|
||||||
}
|
}
|
||||||
|
|
||||||
// requires main thread
|
// requires main thread
|
||||||
pub unsafe fn handle_nonuser_event(event: Event<Never>) {
|
pub unsafe fn handle_nonuser_event(event: EventWrapper) {
|
||||||
handle_nonuser_events(std::iter::once(event))
|
handle_nonuser_events(std::iter::once(event))
|
||||||
}
|
}
|
||||||
|
|
||||||
// requires main thread
|
// requires main thread
|
||||||
pub unsafe fn handle_nonuser_events<I: IntoIterator<Item = Event<Never>>>(events: I) {
|
pub unsafe fn handle_nonuser_events<I: IntoIterator<Item = EventWrapper>>(events: I) {
|
||||||
let mut this = AppState::get_mut();
|
let mut this = AppState::get_mut();
|
||||||
let (mut event_handler, active_control_flow, processing_redraws) =
|
let (mut event_handler, active_control_flow, processing_redraws) =
|
||||||
match this.try_user_callback_transition() {
|
match this.try_user_callback_transition() {
|
||||||
|
@ -638,16 +645,23 @@ pub unsafe fn handle_nonuser_events<I: IntoIterator<Item = Event<Never>>>(events
|
||||||
let mut control_flow = this.control_flow;
|
let mut control_flow = this.control_flow;
|
||||||
drop(this);
|
drop(this);
|
||||||
|
|
||||||
for event in events {
|
for wrapper in events {
|
||||||
if !processing_redraws && event.is_redraw() {
|
match wrapper {
|
||||||
log::info!("processing `RedrawRequested` during the main event loop");
|
EventWrapper::StaticEvent(event) => {
|
||||||
} else if processing_redraws && !event.is_redraw() {
|
if !processing_redraws && event.is_redraw() {
|
||||||
log::warn!(
|
log::info!("processing `RedrawRequested` during the main event loop");
|
||||||
"processing non `RedrawRequested` event after the main event loop: {:#?}",
|
} else if processing_redraws && !event.is_redraw() {
|
||||||
event
|
log::warn!(
|
||||||
);
|
"processing non `RedrawRequested` event after the main event loop: {:#?}",
|
||||||
|
event
|
||||||
|
);
|
||||||
|
}
|
||||||
|
event_handler.handle_nonuser_event(event, &mut control_flow)
|
||||||
|
}
|
||||||
|
EventWrapper::EventProxy(proxy) => {
|
||||||
|
handle_event_proxy(&mut event_handler, control_flow, proxy)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
event_handler.handle_nonuser_event(event, &mut control_flow)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
loop {
|
loop {
|
||||||
|
@ -688,16 +702,23 @@ pub unsafe fn handle_nonuser_events<I: IntoIterator<Item = Event<Never>>>(events
|
||||||
}
|
}
|
||||||
drop(this);
|
drop(this);
|
||||||
|
|
||||||
for event in queued_events {
|
for wrapper in queued_events {
|
||||||
if !processing_redraws && event.is_redraw() {
|
match wrapper {
|
||||||
log::info!("processing `RedrawRequested` during the main event loop");
|
EventWrapper::StaticEvent(event) => {
|
||||||
} else if processing_redraws && !event.is_redraw() {
|
if !processing_redraws && event.is_redraw() {
|
||||||
log::warn!(
|
log::info!("processing `RedrawRequested` during the main event loop");
|
||||||
"processing non-`RedrawRequested` event after the main event loop: {:#?}",
|
} else if processing_redraws && !event.is_redraw() {
|
||||||
event
|
log::warn!(
|
||||||
);
|
"processing non-`RedrawRequested` event after the main event loop: {:#?}",
|
||||||
|
event
|
||||||
|
);
|
||||||
|
}
|
||||||
|
event_handler.handle_nonuser_event(event, &mut control_flow)
|
||||||
|
}
|
||||||
|
EventWrapper::EventProxy(proxy) => {
|
||||||
|
handle_event_proxy(&mut event_handler, control_flow, proxy)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
event_handler.handle_nonuser_event(event, &mut control_flow)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -751,8 +772,15 @@ unsafe fn handle_user_events() {
|
||||||
}
|
}
|
||||||
drop(this);
|
drop(this);
|
||||||
|
|
||||||
for event in queued_events {
|
for wrapper in queued_events {
|
||||||
event_handler.handle_nonuser_event(event, &mut control_flow)
|
match wrapper {
|
||||||
|
EventWrapper::StaticEvent(event) => {
|
||||||
|
event_handler.handle_nonuser_event(event, &mut control_flow)
|
||||||
|
}
|
||||||
|
EventWrapper::EventProxy(proxy) => {
|
||||||
|
handle_event_proxy(&mut event_handler, control_flow, proxy)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
event_handler.handle_user_events(&mut control_flow);
|
event_handler.handle_user_events(&mut control_flow);
|
||||||
}
|
}
|
||||||
|
@ -772,13 +800,13 @@ pub unsafe fn handle_main_events_cleared() {
|
||||||
|
|
||||||
// User events are always sent out at the end of the "MainEventLoop"
|
// User events are always sent out at the end of the "MainEventLoop"
|
||||||
handle_user_events();
|
handle_user_events();
|
||||||
handle_nonuser_event(Event::MainEventsCleared);
|
handle_nonuser_event(EventWrapper::StaticEvent(Event::MainEventsCleared));
|
||||||
|
|
||||||
let mut this = AppState::get_mut();
|
let mut this = AppState::get_mut();
|
||||||
let mut redraw_events: Vec<Event<Never>> = this
|
let mut redraw_events: Vec<Event<Never>> = this
|
||||||
.main_events_cleared_transition()
|
.main_events_cleared_transition()
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.map(|window| Event::RedrawRequested(RootWindowId(window.into())))
|
.map(|window| EventWrapper::StaticEvent(Event::RedrawRequested(RootWindowId(window.into()))))
|
||||||
.collect();
|
.collect();
|
||||||
|
|
||||||
if !redraw_events.is_empty() {
|
if !redraw_events.is_empty() {
|
||||||
|
@ -804,6 +832,67 @@ pub unsafe fn terminated() {
|
||||||
event_handler.handle_nonuser_event(Event::LoopDestroyed, &mut control_flow)
|
event_handler.handle_nonuser_event(Event::LoopDestroyed, &mut control_flow)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn handle_event_proxy(
|
||||||
|
event_handler: &mut Box<dyn EventHandler>,
|
||||||
|
control_flow: ControlFlow,
|
||||||
|
proxy: EventProxy,
|
||||||
|
) {
|
||||||
|
match proxy {
|
||||||
|
EventProxy::HiDpiFactorChangedProxy {
|
||||||
|
suggested_size,
|
||||||
|
hidpi_factor,
|
||||||
|
window_id,
|
||||||
|
} => handle_hidpi_proxy(
|
||||||
|
event_handler,
|
||||||
|
control_flow,
|
||||||
|
suggested_size,
|
||||||
|
hidpi_factor,
|
||||||
|
window_id,
|
||||||
|
),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn handle_hidpi_proxy(
|
||||||
|
event_handler: &mut Box<dyn EventHandler>,
|
||||||
|
mut control_flow: ControlFlow,
|
||||||
|
suggested_size: LogicalSize,
|
||||||
|
hidpi_factor: f64,
|
||||||
|
window_id: id,
|
||||||
|
) {
|
||||||
|
let size = suggested_size.to_physical(hidpi_factor);
|
||||||
|
let new_inner_size = &mut Some(size);
|
||||||
|
let event = Event::WindowEvent {
|
||||||
|
window_id: RootWindowId(window_id.into()),
|
||||||
|
event: WindowEvent::HiDpiFactorChanged {
|
||||||
|
hidpi_factor,
|
||||||
|
new_inner_size,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
event_handler.handle_nonuser_event(event, &mut control_flow);
|
||||||
|
let (view, screen_frame) = get_view_and_screen_frame(window_id);
|
||||||
|
if let Some(physical_size) = new_inner_size {
|
||||||
|
let logical_size = physical_size.to_logical(hidpi_factor);
|
||||||
|
let size = CGSize::new(logical_size);
|
||||||
|
let new_frame: CGRect = CGRect::new(screen_frame.origin, size);
|
||||||
|
unsafe {
|
||||||
|
let () = msg_send![view, setFrame: new_frame];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_view_and_screen_frame(window_id: id) -> (id, CGRect) {
|
||||||
|
unsafe {
|
||||||
|
let view_controller: id = msg_send![window_id, rootViewController];
|
||||||
|
let view: id = msg_send![view_controller, view];
|
||||||
|
let bounds: CGRect = msg_send![window_id, bounds];
|
||||||
|
let screen: id = msg_send![window_id, screen];
|
||||||
|
let screen_space: id = msg_send![screen, coordinateSpace];
|
||||||
|
let screen_frame: CGRect =
|
||||||
|
msg_send![window_id, convertRect:bounds toCoordinateSpace:screen_space];
|
||||||
|
(view, screen_frame)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
struct EventLoopWaker {
|
struct EventLoopWaker {
|
||||||
timer: CFRunLoopTimerRef,
|
timer: CFRunLoopTimerRef,
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,6 +8,7 @@ use std::{
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
|
dpi::LogicalSize,
|
||||||
event::Event,
|
event::Event,
|
||||||
event_loop::{
|
event_loop::{
|
||||||
ControlFlow, EventLoopClosed, EventLoopWindowTarget as RootEventLoopWindowTarget,
|
ControlFlow, EventLoopClosed, EventLoopWindowTarget as RootEventLoopWindowTarget,
|
||||||
|
@ -28,6 +29,21 @@ use crate::platform_impl::platform::{
|
||||||
monitor, view, MonitorHandle,
|
monitor, view, MonitorHandle,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub enum EventWrapper {
|
||||||
|
StaticEvent(Event<'static, Never>),
|
||||||
|
EventProxy(EventProxy),
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, PartialEq)]
|
||||||
|
pub enum EventProxy {
|
||||||
|
HiDpiFactorChangedProxy {
|
||||||
|
window_id: id,
|
||||||
|
suggested_size: LogicalSize,
|
||||||
|
hidpi_factor: f64,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
pub struct EventLoopWindowTarget<T: 'static> {
|
pub struct EventLoopWindowTarget<T: 'static> {
|
||||||
receiver: Receiver<T>,
|
receiver: Receiver<T>,
|
||||||
sender_to_clone: Sender<T>,
|
sender_to_clone: Sender<T>,
|
||||||
|
@ -69,7 +85,7 @@ impl<T: 'static> EventLoop<T> {
|
||||||
|
|
||||||
pub fn run<F>(self, event_handler: F) -> !
|
pub fn run<F>(self, event_handler: F) -> !
|
||||||
where
|
where
|
||||||
F: 'static + FnMut(Event<T>, &RootEventLoopWindowTarget<T>, &mut ControlFlow),
|
F: 'static + FnMut(Event<'_, T>, &RootEventLoopWindowTarget<T>, &mut ControlFlow),
|
||||||
{
|
{
|
||||||
unsafe {
|
unsafe {
|
||||||
let application: *mut c_void = msg_send![class!(UIApplication), sharedApplication];
|
let application: *mut c_void = msg_send![class!(UIApplication), sharedApplication];
|
||||||
|
@ -277,7 +293,7 @@ fn setup_control_flow_observers() {
|
||||||
pub enum Never {}
|
pub enum Never {}
|
||||||
|
|
||||||
pub trait EventHandler: Debug {
|
pub trait EventHandler: Debug {
|
||||||
fn handle_nonuser_event(&mut self, event: Event<Never>, control_flow: &mut ControlFlow);
|
fn handle_nonuser_event(&mut self, event: Event<'_, Never>, control_flow: &mut ControlFlow);
|
||||||
fn handle_user_events(&mut self, control_flow: &mut ControlFlow);
|
fn handle_user_events(&mut self, control_flow: &mut ControlFlow);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -296,10 +312,10 @@ impl<F, T: 'static> Debug for EventLoopHandler<F, T> {
|
||||||
|
|
||||||
impl<F, T> EventHandler for EventLoopHandler<F, T>
|
impl<F, T> EventHandler for EventLoopHandler<F, T>
|
||||||
where
|
where
|
||||||
F: 'static + FnMut(Event<T>, &RootEventLoopWindowTarget<T>, &mut ControlFlow),
|
F: 'static + FnMut(Event<'_, T>, &RootEventLoopWindowTarget<T>, &mut ControlFlow),
|
||||||
T: 'static,
|
T: 'static,
|
||||||
{
|
{
|
||||||
fn handle_nonuser_event(&mut self, event: Event<Never>, control_flow: &mut ControlFlow) {
|
fn handle_nonuser_event(&mut self, event: Event<'_, Never>, control_flow: &mut ControlFlow) {
|
||||||
(self.f)(
|
(self.f)(
|
||||||
event.map_nonuser_event().unwrap(),
|
event.map_nonuser_event().unwrap(),
|
||||||
&self.event_loop,
|
&self.event_loop,
|
||||||
|
|
|
@ -4,7 +4,10 @@ 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, ScreenEdge, ValidOrientations};
|
use crate::{
|
||||||
|
dpi::LogicalSize,
|
||||||
|
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;
|
||||||
|
@ -39,6 +42,15 @@ pub struct CGSize {
|
||||||
pub height: CGFloat,
|
pub height: CGFloat,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl CGSize {
|
||||||
|
pub fn new(size: LogicalSize) -> CGSize {
|
||||||
|
CGSize {
|
||||||
|
width: size.width as _,
|
||||||
|
height: size.height as _,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct CGRect {
|
pub struct CGRect {
|
||||||
|
@ -46,6 +58,12 @@ pub struct CGRect {
|
||||||
pub size: CGSize,
|
pub size: CGSize,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl CGRect {
|
||||||
|
pub fn new(origin: CGPoint, size: CGSize) -> CGRect {
|
||||||
|
CGRect { origin, size }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
unsafe impl Encode for CGRect {
|
unsafe impl Encode for CGRect {
|
||||||
fn encode() -> Encoding {
|
fn encode() -> Encoding {
|
||||||
unsafe {
|
unsafe {
|
||||||
|
|
|
@ -219,7 +219,7 @@ impl Inner {
|
||||||
pub fn size(&self) -> PhysicalSize {
|
pub fn size(&self) -> PhysicalSize {
|
||||||
unsafe {
|
unsafe {
|
||||||
let bounds: CGRect = msg_send![self.ui_screen(), nativeBounds];
|
let bounds: CGRect = msg_send![self.ui_screen(), nativeBounds];
|
||||||
(bounds.size.width as f64, bounds.size.height as f64).into()
|
PhysicalSize::new(bounds.size.width as u32, bounds.size.height as u32)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -10,7 +10,7 @@ use crate::{
|
||||||
platform::ios::MonitorHandleExtIOS,
|
platform::ios::MonitorHandleExtIOS,
|
||||||
platform_impl::platform::{
|
platform_impl::platform::{
|
||||||
app_state::{self, OSCapabilities},
|
app_state::{self, OSCapabilities},
|
||||||
event_loop,
|
event_loop::{self, EventProxy, EventWrapper},
|
||||||
ffi::{
|
ffi::{
|
||||||
id, nil, CGFloat, CGPoint, CGRect, UIForceTouchCapability, UIInterfaceOrientationMask,
|
id, nil, CGFloat, CGPoint, CGRect, UIForceTouchCapability, UIInterfaceOrientationMask,
|
||||||
UIRectEdge, UITouchPhase, UITouchType,
|
UIRectEdge, UITouchPhase, UITouchType,
|
||||||
|
@ -103,8 +103,8 @@ unsafe fn get_view_class(root_view_class: &'static Class) -> &'static Class {
|
||||||
let window: id = msg_send![object, window];
|
let window: id = msg_send![object, window];
|
||||||
assert!(!window.is_null());
|
assert!(!window.is_null());
|
||||||
app_state::handle_nonuser_events(
|
app_state::handle_nonuser_events(
|
||||||
std::iter::once(Event::RedrawRequested(RootWindowId(window.into())))
|
std::iter::once(EventWrapper::StaticEvent(Event::RedrawRequested(RootWindowId(window.into()))))
|
||||||
.chain(std::iter::once(Event::RedrawEventsCleared)),
|
.chain(std::iter::once(EventWrapper::StaticEvent(Event::RedrawEventsCleared))),
|
||||||
);
|
);
|
||||||
let superclass: &'static Class = msg_send![object, superclass];
|
let superclass: &'static Class = msg_send![object, superclass];
|
||||||
let () = msg_send![super(object, superclass), drawRect: rect];
|
let () = msg_send![super(object, superclass), drawRect: rect];
|
||||||
|
@ -123,14 +123,16 @@ unsafe fn get_view_class(root_view_class: &'static Class) -> &'static Class {
|
||||||
let screen_space: id = msg_send![screen, coordinateSpace];
|
let screen_space: id = msg_send![screen, coordinateSpace];
|
||||||
let screen_frame: CGRect =
|
let screen_frame: CGRect =
|
||||||
msg_send![object, convertRect:bounds toCoordinateSpace:screen_space];
|
msg_send![object, convertRect:bounds toCoordinateSpace:screen_space];
|
||||||
|
let dpi_factor: CGFloat = msg_send![screen, scale];
|
||||||
let size = crate::dpi::LogicalSize {
|
let size = crate::dpi::LogicalSize {
|
||||||
width: screen_frame.size.width as _,
|
width: screen_frame.size.width as _,
|
||||||
height: screen_frame.size.height as _,
|
height: screen_frame.size.height as _,
|
||||||
};
|
}
|
||||||
app_state::handle_nonuser_event(Event::WindowEvent {
|
.to_physical(dpi_factor.into());
|
||||||
|
app_state::handle_nonuser_event(EventWrapper::StaticEvent(Event::WindowEvent {
|
||||||
window_id: RootWindowId(window.into()),
|
window_id: RootWindowId(window.into()),
|
||||||
event: WindowEvent::Resized(size),
|
event: WindowEvent::Resized(size),
|
||||||
});
|
}));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -156,14 +158,15 @@ unsafe fn get_view_class(root_view_class: &'static Class) -> &'static Class {
|
||||||
// `setContentScaleFactor` may be called with a value of 0, which means "reset the
|
// `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
|
// 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
|
// parameter here. We can query the actual factor using the getter
|
||||||
let hidpi_factor: CGFloat = msg_send![object, contentScaleFactor];
|
let dpi_factor: CGFloat = msg_send![object, contentScaleFactor];
|
||||||
assert!(
|
assert!(
|
||||||
!hidpi_factor.is_nan()
|
!dpi_factor.is_nan()
|
||||||
&& hidpi_factor.is_finite()
|
&& dpi_factor.is_finite()
|
||||||
&& hidpi_factor.is_sign_positive()
|
&& dpi_factor.is_sign_positive()
|
||||||
&& hidpi_factor > 0.0,
|
&& dpi_factor > 0.0,
|
||||||
"invalid hidpi_factor set on UIView",
|
"invalid hidpi_factor set on UIView",
|
||||||
);
|
);
|
||||||
|
let hidpi_factor: f64 = dpi_factor.into();
|
||||||
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];
|
||||||
|
@ -174,14 +177,19 @@ unsafe fn get_view_class(root_view_class: &'static Class) -> &'static Class {
|
||||||
height: screen_frame.size.height as _,
|
height: screen_frame.size.height as _,
|
||||||
};
|
};
|
||||||
app_state::handle_nonuser_events(
|
app_state::handle_nonuser_events(
|
||||||
std::iter::once(Event::WindowEvent {
|
std::iter::once(EventWrapper::EventProxy(
|
||||||
window_id: RootWindowId(window.into()),
|
EventProxy::HiDpiFactorChangedProxy {
|
||||||
event: WindowEvent::HiDpiFactorChanged(hidpi_factor as _),
|
window_id: window,
|
||||||
})
|
hidpi_factor,
|
||||||
.chain(std::iter::once(Event::WindowEvent {
|
suggested_size: size,
|
||||||
window_id: RootWindowId(window.into()),
|
},
|
||||||
event: WindowEvent::Resized(size),
|
))
|
||||||
})),
|
.chain(std::iter::once(EventWrapper::StaticEvent(
|
||||||
|
Event::WindowEvent {
|
||||||
|
window_id: RootWindowId(window.into()),
|
||||||
|
event: WindowEvent::Resized(size.to_physical(hidpi_factor)),
|
||||||
|
},
|
||||||
|
))),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -238,7 +246,7 @@ unsafe fn get_view_class(root_view_class: &'static Class) -> &'static Class {
|
||||||
_ => panic!("unexpected touch phase: {:?}", phase as i32),
|
_ => panic!("unexpected touch phase: {:?}", phase as i32),
|
||||||
};
|
};
|
||||||
|
|
||||||
touch_events.push(Event::WindowEvent {
|
touch_events.push(EventWrapper::StaticEvent(Event::WindowEvent {
|
||||||
window_id: RootWindowId(window.into()),
|
window_id: RootWindowId(window.into()),
|
||||||
event: WindowEvent::Touch(Touch {
|
event: WindowEvent::Touch(Touch {
|
||||||
device_id: RootDeviceId(DeviceId { uiscreen }),
|
device_id: RootDeviceId(DeviceId { uiscreen }),
|
||||||
|
@ -247,7 +255,7 @@ unsafe fn get_view_class(root_view_class: &'static Class) -> &'static Class {
|
||||||
force,
|
force,
|
||||||
phase,
|
phase,
|
||||||
}),
|
}),
|
||||||
});
|
}));
|
||||||
}
|
}
|
||||||
app_state::handle_nonuser_events(touch_events);
|
app_state::handle_nonuser_events(touch_events);
|
||||||
}
|
}
|
||||||
|
@ -367,20 +375,20 @@ unsafe fn get_window_class() -> &'static Class {
|
||||||
|
|
||||||
extern "C" fn become_key_window(object: &Object, _: Sel) {
|
extern "C" fn become_key_window(object: &Object, _: Sel) {
|
||||||
unsafe {
|
unsafe {
|
||||||
app_state::handle_nonuser_event(Event::WindowEvent {
|
app_state::handle_nonuser_event(EventWrapper::StaticEvent(Event::WindowEvent {
|
||||||
window_id: RootWindowId(object.into()),
|
window_id: RootWindowId(object.into()),
|
||||||
event: WindowEvent::Focused(true),
|
event: WindowEvent::Focused(true),
|
||||||
});
|
}));
|
||||||
let () = msg_send![super(object, class!(UIWindow)), becomeKeyWindow];
|
let () = msg_send![super(object, class!(UIWindow)), becomeKeyWindow];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "C" fn resign_key_window(object: &Object, _: Sel) {
|
extern "C" fn resign_key_window(object: &Object, _: Sel) {
|
||||||
unsafe {
|
unsafe {
|
||||||
app_state::handle_nonuser_event(Event::WindowEvent {
|
app_state::handle_nonuser_event(EventWrapper::StaticEvent(Event::WindowEvent {
|
||||||
window_id: RootWindowId(object.into()),
|
window_id: RootWindowId(object.into()),
|
||||||
event: WindowEvent::Focused(false),
|
event: WindowEvent::Focused(false),
|
||||||
});
|
}));
|
||||||
let () = msg_send![super(object, class!(UIWindow)), resignKeyWindow];
|
let () = msg_send![super(object, class!(UIWindow)), resignKeyWindow];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -500,9 +508,7 @@ pub unsafe fn create_window(
|
||||||
let () = msg_send![uiscreen, setCurrentMode: video_mode.video_mode.screen_mode.0];
|
let () = msg_send![uiscreen, setCurrentMode: video_mode.video_mode.screen_mode.0];
|
||||||
msg_send![window, setScreen:video_mode.monitor().ui_screen()]
|
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()]
|
|
||||||
}
|
|
||||||
None => (),
|
None => (),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -518,11 +524,11 @@ pub fn create_delegate_class() {
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "C" fn did_become_active(_: &Object, _: Sel, _: id) {
|
extern "C" fn did_become_active(_: &Object, _: Sel, _: id) {
|
||||||
unsafe { app_state::handle_nonuser_event(Event::Resumed) }
|
unsafe { app_state::handle_nonuser_event(EventWrapper::StaticEvent(Event::Resumed)) }
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "C" fn will_resign_active(_: &Object, _: Sel, _: id) {
|
extern "C" fn will_resign_active(_: &Object, _: Sel, _: id) {
|
||||||
unsafe { app_state::handle_nonuser_event(Event::Suspended) }
|
unsafe { app_state::handle_nonuser_event(EventWrapper::StaticEvent(Event::Suspended)) }
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "C" fn will_enter_foreground(_: &Object, _: Sel, _: id) {}
|
extern "C" fn will_enter_foreground(_: &Object, _: Sel, _: id) {}
|
||||||
|
@ -541,10 +547,10 @@ pub fn create_delegate_class() {
|
||||||
}
|
}
|
||||||
let is_winit_window: BOOL = msg_send![window, isKindOfClass: class!(WinitUIWindow)];
|
let is_winit_window: BOOL = msg_send![window, isKindOfClass: class!(WinitUIWindow)];
|
||||||
if is_winit_window == YES {
|
if is_winit_window == YES {
|
||||||
events.push(Event::WindowEvent {
|
events.push(EventWrapper::StaticEvent(Event::WindowEvent {
|
||||||
window_id: RootWindowId(window.into()),
|
window_id: RootWindowId(window.into()),
|
||||||
event: WindowEvent::Destroyed,
|
event: WindowEvent::Destroyed,
|
||||||
});
|
}));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
app_state::handle_nonuser_events(events);
|
app_state::handle_nonuser_events(events);
|
||||||
|
|
|
@ -7,14 +7,15 @@ use std::{
|
||||||
use objc::runtime::{Class, Object, BOOL, NO, YES};
|
use objc::runtime::{Class, Object, BOOL, NO, YES};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
dpi::{self, LogicalPosition, LogicalSize},
|
dpi::{self, LogicalPosition, LogicalSize, PhysicalPosition, PhysicalSize, Position, Size},
|
||||||
error::{ExternalError, NotSupportedError, OsError as RootOsError},
|
error::{ExternalError, NotSupportedError, OsError as RootOsError},
|
||||||
event::{Event, WindowEvent},
|
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},
|
||||||
platform_impl::platform::{
|
platform_impl::platform::{
|
||||||
app_state, event_loop,
|
app_state,
|
||||||
|
event_loop::{self, EventProxy, EventWrapper},
|
||||||
ffi::{
|
ffi::{
|
||||||
id, CGFloat, CGPoint, CGRect, CGSize, UIEdgeInsets, UIInterfaceOrientationMask,
|
id, CGFloat, CGPoint, CGRect, CGSize, UIEdgeInsets, UIInterfaceOrientationMask,
|
||||||
UIRectEdge, UIScreenOverscanCompensation,
|
UIRectEdge, UIScreenOverscanCompensation,
|
||||||
|
@ -75,28 +76,34 @@ impl Inner {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn inner_position(&self) -> Result<LogicalPosition, NotSupportedError> {
|
pub fn inner_position(&self) -> Result<PhysicalPosition, NotSupportedError> {
|
||||||
unsafe {
|
unsafe {
|
||||||
let safe_area = self.safe_area_screen_space();
|
let safe_area = self.safe_area_screen_space();
|
||||||
Ok(LogicalPosition {
|
let position = LogicalPosition {
|
||||||
x: safe_area.origin.x as _,
|
x: safe_area.origin.x as _,
|
||||||
y: safe_area.origin.y as _,
|
y: safe_area.origin.y as _,
|
||||||
})
|
};
|
||||||
|
let dpi_factor = self.hidpi_factor();
|
||||||
|
Ok(position.to_physical(dpi_factor))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn outer_position(&self) -> Result<LogicalPosition, NotSupportedError> {
|
pub fn outer_position(&self) -> Result<PhysicalPosition, NotSupportedError> {
|
||||||
unsafe {
|
unsafe {
|
||||||
let screen_frame = self.screen_frame();
|
let screen_frame = self.screen_frame();
|
||||||
Ok(LogicalPosition {
|
let position = LogicalPosition {
|
||||||
x: screen_frame.origin.x as _,
|
x: screen_frame.origin.x as _,
|
||||||
y: screen_frame.origin.y as _,
|
y: screen_frame.origin.y as _,
|
||||||
})
|
};
|
||||||
|
let dpi_factor = self.hidpi_factor();
|
||||||
|
Ok(position.to_physical(dpi_factor))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn set_outer_position(&self, position: LogicalPosition) {
|
pub fn set_outer_position(&self, physical_position: Position) {
|
||||||
unsafe {
|
unsafe {
|
||||||
|
let dpi_factor = self.hidpi_factor();
|
||||||
|
let position = physical_position.to_logical(dpi_factor);
|
||||||
let screen_frame = self.screen_frame();
|
let screen_frame = self.screen_frame();
|
||||||
let new_screen_frame = CGRect {
|
let new_screen_frame = CGRect {
|
||||||
origin: CGPoint {
|
origin: CGPoint {
|
||||||
|
@ -110,35 +117,39 @@ impl Inner {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn inner_size(&self) -> LogicalSize {
|
pub fn inner_size(&self) -> PhysicalSize {
|
||||||
unsafe {
|
unsafe {
|
||||||
|
let dpi_factor = self.hidpi_factor();
|
||||||
let safe_area = self.safe_area_screen_space();
|
let safe_area = self.safe_area_screen_space();
|
||||||
LogicalSize {
|
let size = LogicalSize {
|
||||||
width: safe_area.size.width as _,
|
width: safe_area.size.width as _,
|
||||||
height: safe_area.size.height as _,
|
height: safe_area.size.height as _,
|
||||||
}
|
};
|
||||||
|
size.to_physical(dpi_factor)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn outer_size(&self) -> LogicalSize {
|
pub fn outer_size(&self) -> PhysicalSize {
|
||||||
unsafe {
|
unsafe {
|
||||||
|
let dpi_factor = self.hidpi_factor();
|
||||||
let screen_frame = self.screen_frame();
|
let screen_frame = self.screen_frame();
|
||||||
LogicalSize {
|
let size = LogicalSize {
|
||||||
width: screen_frame.size.width as _,
|
width: screen_frame.size.width as _,
|
||||||
height: screen_frame.size.height as _,
|
height: screen_frame.size.height as _,
|
||||||
}
|
};
|
||||||
|
size.to_physical(dpi_factor)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn set_inner_size(&self, _size: LogicalSize) {
|
pub fn set_inner_size(&self, _size: Size) {
|
||||||
unimplemented!("not clear what `Window::set_inner_size` means on iOS");
|
unimplemented!("not clear what `Window::set_inner_size` means on iOS");
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn set_min_inner_size(&self, _dimensions: Option<LogicalSize>) {
|
pub fn set_min_inner_size(&self, _dimensions: Option<Size>) {
|
||||||
warn!("`Window::set_min_inner_size` is ignored on iOS")
|
warn!("`Window::set_min_inner_size` is ignored on iOS")
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn set_max_inner_size(&self, _dimensions: Option<LogicalSize>) {
|
pub fn set_max_inner_size(&self, _dimensions: Option<Size>) {
|
||||||
warn!("`Window::set_max_inner_size` is ignored on iOS")
|
warn!("`Window::set_max_inner_size` is ignored on iOS")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -157,7 +168,7 @@ impl Inner {
|
||||||
debug!("`Window::set_cursor_icon` ignored on iOS")
|
debug!("`Window::set_cursor_icon` ignored on iOS")
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn set_cursor_position(&self, _position: LogicalPosition) -> Result<(), ExternalError> {
|
pub fn set_cursor_position(&self, _position: Position) -> Result<(), ExternalError> {
|
||||||
Err(ExternalError::NotSupported(NotSupportedError::new()))
|
Err(ExternalError::NotSupported(NotSupportedError::new()))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -243,7 +254,7 @@ impl Inner {
|
||||||
warn!("`Window::set_window_icon` is ignored on iOS")
|
warn!("`Window::set_window_icon` is ignored on iOS")
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn set_ime_position(&self, _position: LogicalPosition) {
|
pub fn set_ime_position(&self, _position: Position) {
|
||||||
warn!("`Window::set_ime_position` is ignored on iOS")
|
warn!("`Window::set_ime_position` is ignored on iOS")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -343,13 +354,17 @@ impl Window {
|
||||||
let screen_bounds: CGRect = msg_send![screen, bounds];
|
let screen_bounds: CGRect = msg_send![screen, bounds];
|
||||||
|
|
||||||
let frame = match window_attributes.inner_size {
|
let frame = match window_attributes.inner_size {
|
||||||
Some(dim) => CGRect {
|
Some(dim) => {
|
||||||
origin: screen_bounds.origin,
|
let dpi_factor = msg_send![screen, scale];
|
||||||
size: CGSize {
|
let size = dim.to_logical(dpi_factor);
|
||||||
width: dim.width as _,
|
CGRect {
|
||||||
height: dim.height as _,
|
origin: screen_bounds.origin,
|
||||||
},
|
size: CGSize {
|
||||||
},
|
width: size.width as _,
|
||||||
|
height: size.height as _,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
None => screen_bounds,
|
None => screen_bounds,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -385,7 +400,8 @@ impl Window {
|
||||||
|
|
||||||
// Like the Windows and macOS backends, we send a `HiDpiFactorChanged` and `Resized`
|
// Like the Windows and macOS backends, we send a `HiDpiFactorChanged` and `Resized`
|
||||||
// event on window creation if the DPI factor != 1.0
|
// event on window creation if the DPI factor != 1.0
|
||||||
let hidpi_factor: CGFloat = msg_send![view, contentScaleFactor];
|
let dpi_factor: CGFloat = msg_send![view, contentScaleFactor];
|
||||||
|
let hidpi_factor: f64 = dpi_factor.into();
|
||||||
if hidpi_factor != 1.0 {
|
if hidpi_factor != 1.0 {
|
||||||
let bounds: CGRect = msg_send![view, bounds];
|
let bounds: CGRect = msg_send![view, bounds];
|
||||||
let screen: id = msg_send![window, screen];
|
let screen: id = msg_send![window, screen];
|
||||||
|
@ -397,14 +413,19 @@ impl Window {
|
||||||
height: screen_frame.size.height as _,
|
height: screen_frame.size.height as _,
|
||||||
};
|
};
|
||||||
app_state::handle_nonuser_events(
|
app_state::handle_nonuser_events(
|
||||||
std::iter::once(Event::WindowEvent {
|
std::iter::once(EventWrapper::EventProxy(
|
||||||
window_id: RootWindowId(window.into()),
|
EventProxy::HiDpiFactorChangedProxy {
|
||||||
event: WindowEvent::HiDpiFactorChanged(hidpi_factor as _),
|
window_id: window,
|
||||||
})
|
hidpi_factor,
|
||||||
.chain(std::iter::once(Event::WindowEvent {
|
suggested_size: size,
|
||||||
window_id: RootWindowId(window.into()),
|
},
|
||||||
event: WindowEvent::Resized(size),
|
))
|
||||||
})),
|
.chain(std::iter::once(EventWrapper::StaticEvent(
|
||||||
|
Event::WindowEvent {
|
||||||
|
window_id: RootWindowId(window.into()),
|
||||||
|
event: WindowEvent::Resized(size.to_physical(hidpi_factor)),
|
||||||
|
},
|
||||||
|
))),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue