macOS: Dpi overhaul (#997) (and rebase changes)
* 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 Changes from rebasing: * fixes compile errors * applies fmt * reimplements HiDpiFactorChanged after #1173 merge * uses EventWrappers
This commit is contained in:
parent
7b43b0bc94
commit
077ee4d851
10 changed files with 273 additions and 153 deletions
|
|
@ -12,15 +12,21 @@ use std::{
|
|||
};
|
||||
|
||||
use cocoa::{
|
||||
appkit::NSApp,
|
||||
appkit::{NSApp, NSWindow},
|
||||
base::nil,
|
||||
foundation::{NSAutoreleasePool, NSString},
|
||||
foundation::{NSAutoreleasePool, NSSize, NSString},
|
||||
};
|
||||
|
||||
use crate::{
|
||||
event::{Event, StartCause},
|
||||
dpi::LogicalSize,
|
||||
event::{Event, StartCause, WindowEvent},
|
||||
event_loop::{ControlFlow, EventLoopWindowTarget as RootWindowTarget},
|
||||
platform_impl::platform::{observer::EventLoopWaker, util::Never},
|
||||
platform_impl::platform::{
|
||||
event::{EventProxy, EventWrapper},
|
||||
observer::EventLoopWaker,
|
||||
util::{IdRef, Never},
|
||||
window::get_window_id,
|
||||
},
|
||||
window::WindowId,
|
||||
};
|
||||
use objc::runtime::Object;
|
||||
|
|
@ -29,8 +35,8 @@ lazy_static! {
|
|||
static ref HANDLER: Handler = Default::default();
|
||||
}
|
||||
|
||||
impl Event<Never> {
|
||||
fn userify<T: 'static>(self) -> Event<T> {
|
||||
impl<'a, Never> Event<'a, Never> {
|
||||
fn userify<T: 'static>(self) -> Event<'a, T> {
|
||||
self.map_nonuser_event()
|
||||
// `Never` can't be constructed, so the `UserEvent` variant can't
|
||||
// be present here.
|
||||
|
|
@ -39,12 +45,13 @@ impl Event<Never> {
|
|||
}
|
||||
|
||||
pub trait EventHandler: Debug {
|
||||
fn handle_nonuser_event(&mut self, event: Event<Never>, control_flow: &mut ControlFlow);
|
||||
// Not sure probably it should accept Event<'static, Never>
|
||||
fn handle_nonuser_event(&mut self, event: Event<'_, Never>, control_flow: &mut ControlFlow);
|
||||
fn handle_user_events(&mut self, control_flow: &mut ControlFlow);
|
||||
}
|
||||
|
||||
struct EventLoopHandler<T: 'static> {
|
||||
callback: Box<dyn FnMut(Event<T>, &RootWindowTarget<T>, &mut ControlFlow)>,
|
||||
callback: Box<dyn FnMut(Event<'_, T>, &RootWindowTarget<T>, &mut ControlFlow)>,
|
||||
will_exit: bool,
|
||||
window_target: Rc<RootWindowTarget<T>>,
|
||||
}
|
||||
|
|
@ -59,7 +66,7 @@ impl<T> Debug for EventLoopHandler<T> {
|
|||
}
|
||||
|
||||
impl<T> EventHandler for EventLoopHandler<T> {
|
||||
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.callback)(event.userify(), &self.window_target, control_flow);
|
||||
self.will_exit |= *control_flow == ControlFlow::Exit;
|
||||
if self.will_exit {
|
||||
|
|
@ -88,7 +95,7 @@ struct Handler {
|
|||
control_flow_prev: Mutex<ControlFlow>,
|
||||
start_time: Mutex<Option<Instant>>,
|
||||
callback: Mutex<Option<Box<dyn EventHandler>>>,
|
||||
pending_events: Mutex<VecDeque<Event<Never>>>,
|
||||
pending_events: Mutex<VecDeque<EventWrapper>>,
|
||||
pending_redraw: Mutex<Vec<WindowId>>,
|
||||
waker: Mutex<EventLoopWaker>,
|
||||
}
|
||||
|
|
@ -97,7 +104,7 @@ unsafe impl Send for Handler {}
|
|||
unsafe impl Sync for Handler {}
|
||||
|
||||
impl Handler {
|
||||
fn events<'a>(&'a self) -> MutexGuard<'a, VecDeque<Event<Never>>> {
|
||||
fn events(&self) -> MutexGuard<'_, VecDeque<EventWrapper>> {
|
||||
self.pending_events.lock().unwrap()
|
||||
}
|
||||
|
||||
|
|
@ -105,7 +112,7 @@ impl Handler {
|
|||
self.pending_redraw.lock().unwrap()
|
||||
}
|
||||
|
||||
fn waker<'a>(&'a self) -> MutexGuard<'a, EventLoopWaker> {
|
||||
fn waker(&self) -> MutexGuard<'_, EventLoopWaker> {
|
||||
self.waker.lock().unwrap()
|
||||
}
|
||||
|
||||
|
|
@ -141,7 +148,7 @@ impl Handler {
|
|||
*self.start_time.lock().unwrap() = Some(Instant::now());
|
||||
}
|
||||
|
||||
fn take_events(&self) -> VecDeque<Event<Never>> {
|
||||
fn take_events(&self) -> VecDeque<EventWrapper> {
|
||||
mem::replace(&mut *self.events(), Default::default())
|
||||
}
|
||||
|
||||
|
|
@ -157,9 +164,14 @@ impl Handler {
|
|||
self.in_callback.store(in_callback, Ordering::Release);
|
||||
}
|
||||
|
||||
fn handle_nonuser_event(&self, event: Event<Never>) {
|
||||
fn handle_nonuser_event(&self, wrapper: EventWrapper) {
|
||||
if let Some(ref mut callback) = *self.callback.lock().unwrap() {
|
||||
callback.handle_nonuser_event(event, &mut *self.control_flow.lock().unwrap());
|
||||
match wrapper {
|
||||
EventWrapper::StaticEvent(event) => {
|
||||
callback.handle_nonuser_event(event, &mut *self.control_flow.lock().unwrap())
|
||||
}
|
||||
EventWrapper::EventProxy(proxy) => self.handle_proxy(proxy, callback),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -168,6 +180,46 @@ impl Handler {
|
|||
callback.handle_user_events(&mut *self.control_flow.lock().unwrap());
|
||||
}
|
||||
}
|
||||
|
||||
fn handle_hidpi_factor_changed_event(
|
||||
&self,
|
||||
callback: &mut Box<dyn EventHandler + 'static>,
|
||||
ns_window: IdRef,
|
||||
suggested_size: LogicalSize,
|
||||
hidpi_factor: f64,
|
||||
) {
|
||||
let size = suggested_size.to_physical(hidpi_factor);
|
||||
let new_inner_size = &mut Some(size);
|
||||
let event = Event::WindowEvent {
|
||||
window_id: WindowId(get_window_id(*ns_window)),
|
||||
event: WindowEvent::HiDpiFactorChanged {
|
||||
hidpi_factor,
|
||||
new_inner_size,
|
||||
},
|
||||
};
|
||||
|
||||
callback.handle_nonuser_event(event, &mut *self.control_flow.lock().unwrap());
|
||||
|
||||
let physical_size = new_inner_size.unwrap_or(size);
|
||||
let logical_size = physical_size.to_logical(hidpi_factor);
|
||||
let size = NSSize::new(logical_size.width, logical_size.height);
|
||||
unsafe { NSWindow::setContentSize_(*ns_window, size) };
|
||||
}
|
||||
|
||||
fn handle_proxy(&self, proxy: EventProxy, callback: &mut Box<dyn EventHandler + 'static>) {
|
||||
match proxy {
|
||||
EventProxy::HiDpiFactorChangedProxy {
|
||||
ns_window,
|
||||
suggested_size,
|
||||
hidpi_factor,
|
||||
} => self.handle_hidpi_factor_changed_event(
|
||||
callback,
|
||||
ns_window,
|
||||
suggested_size,
|
||||
hidpi_factor,
|
||||
),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub enum AppState {}
|
||||
|
|
@ -176,7 +228,7 @@ impl AppState {
|
|||
// This function extends lifetime of `callback` to 'static as its side effect
|
||||
pub unsafe fn set_callback<F, T>(callback: F, window_target: Rc<RootWindowTarget<T>>)
|
||||
where
|
||||
F: FnMut(Event<T>, &RootWindowTarget<T>, &mut ControlFlow),
|
||||
F: FnMut(Event<'_, T>, &RootWindowTarget<T>, &mut ControlFlow),
|
||||
{
|
||||
*HANDLER.callback.lock().unwrap() = Some(Box::new(EventLoopHandler {
|
||||
// This transmute is always safe, in case it was reached through `run`, since our
|
||||
|
|
@ -184,8 +236,8 @@ impl AppState {
|
|||
// they passed to callback will actually outlive it, some apps just can't move
|
||||
// everything to event loop, so this is something that they should care about.
|
||||
callback: mem::transmute::<
|
||||
Box<dyn FnMut(Event<T>, &RootWindowTarget<T>, &mut ControlFlow)>,
|
||||
Box<dyn FnMut(Event<T>, &RootWindowTarget<T>, &mut ControlFlow)>,
|
||||
Box<dyn FnMut(Event<'_, T>, &RootWindowTarget<T>, &mut ControlFlow)>,
|
||||
Box<dyn FnMut(Event<'_, T>, &RootWindowTarget<T>, &mut ControlFlow)>,
|
||||
>(Box::new(callback)),
|
||||
will_exit: false,
|
||||
window_target,
|
||||
|
|
@ -194,7 +246,7 @@ impl AppState {
|
|||
|
||||
pub fn exit() {
|
||||
HANDLER.set_in_callback(true);
|
||||
HANDLER.handle_nonuser_event(Event::LoopDestroyed);
|
||||
HANDLER.handle_nonuser_event(EventWrapper::StaticEvent(Event::LoopDestroyed));
|
||||
HANDLER.set_in_callback(false);
|
||||
HANDLER.callback.lock().unwrap().take();
|
||||
}
|
||||
|
|
@ -203,7 +255,9 @@ impl AppState {
|
|||
HANDLER.set_ready();
|
||||
HANDLER.waker().start();
|
||||
HANDLER.set_in_callback(true);
|
||||
HANDLER.handle_nonuser_event(Event::NewEvents(StartCause::Init));
|
||||
HANDLER.handle_nonuser_event(EventWrapper::StaticEvent(Event::NewEvents(
|
||||
StartCause::Init,
|
||||
)));
|
||||
HANDLER.set_in_callback(false);
|
||||
}
|
||||
|
||||
|
|
@ -234,7 +288,7 @@ impl AppState {
|
|||
ControlFlow::Exit => StartCause::Poll, //panic!("unexpected `ControlFlow::Exit`"),
|
||||
};
|
||||
HANDLER.set_in_callback(true);
|
||||
HANDLER.handle_nonuser_event(Event::NewEvents(cause));
|
||||
HANDLER.handle_nonuser_event(EventWrapper::StaticEvent(Event::NewEvents(cause)));
|
||||
HANDLER.set_in_callback(false);
|
||||
}
|
||||
|
||||
|
|
@ -246,18 +300,18 @@ impl AppState {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn queue_event(event: Event<Never>) {
|
||||
pub fn queue_event(wrapper: EventWrapper) {
|
||||
if !unsafe { msg_send![class!(NSThread), isMainThread] } {
|
||||
panic!("Event queued from different thread: {:#?}", event);
|
||||
panic!("Event queued from different thread: {:#?}", wrapper);
|
||||
}
|
||||
HANDLER.events().push_back(event);
|
||||
HANDLER.events().push_back(wrapper);
|
||||
}
|
||||
|
||||
pub fn queue_events(mut events: VecDeque<Event<Never>>) {
|
||||
pub fn queue_events(mut wrappers: VecDeque<EventWrapper>) {
|
||||
if !unsafe { msg_send![class!(NSThread), isMainThread] } {
|
||||
panic!("Events queued from different thread: {:#?}", events);
|
||||
panic!("Events queued from different thread: {:#?}", wrappers);
|
||||
}
|
||||
HANDLER.events().append(&mut events);
|
||||
HANDLER.events().append(&mut wrappers);
|
||||
}
|
||||
|
||||
pub fn cleared() {
|
||||
|
|
@ -270,11 +324,13 @@ impl AppState {
|
|||
for event in HANDLER.take_events() {
|
||||
HANDLER.handle_nonuser_event(event);
|
||||
}
|
||||
HANDLER.handle_nonuser_event(Event::MainEventsCleared);
|
||||
HANDLER.handle_nonuser_event(EventWrapper::StaticEvent(Event::MainEventsCleared));
|
||||
for window_id in HANDLER.should_redraw() {
|
||||
HANDLER.handle_nonuser_event(Event::RedrawRequested(window_id));
|
||||
HANDLER.handle_nonuser_event(EventWrapper::StaticEvent(Event::RedrawRequested(
|
||||
window_id,
|
||||
)));
|
||||
}
|
||||
HANDLER.handle_nonuser_event(Event::RedrawEventsCleared);
|
||||
HANDLER.handle_nonuser_event(EventWrapper::StaticEvent(Event::RedrawEventsCleared));
|
||||
HANDLER.set_in_callback(false);
|
||||
}
|
||||
if HANDLER.should_exit() {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue