Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

macOS: Dpi overhaul #997

Merged
merged 27 commits into from
Aug 30, 2019
Merged
Show file tree
Hide file tree
Changes from 17 commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
da2611e
WIP - Make EL2 DPI changes and implement on Windows (#895)
Osspial Jun 19, 2019
c3c12f4
fix app_state errors
vbogaevsky Jun 24, 2019
fec2f80
fixes hidpi related errors in window_delegate
vbogaevsky Jun 25, 2019
73327e0
Merge branch 'dpi-overhaul' of github.com:vbogaevsky/winit into dpi-o…
vbogaevsky Jun 25, 2019
4213c7a
fix bad merge
vbogaevsky Jun 25, 2019
90ed1e4
dpi_factor edits in window_delegate
vbogaevsky Jun 26, 2019
607e6c3
fixes type and lifetime errors in window and window_delegate
vbogaevsky Jun 28, 2019
97ebda6
applies fmt
vbogaevsky Jun 28, 2019
7ac43a4
complies with @aleksijuvani requested changes
vbogaevsky Jun 30, 2019
a3ecb4b
modifies Handler lifetimes
vbogaevsky Jul 2, 2019
5d029ab
fixes lifetime isues, adds propper handling for HiDpiChanged
vbogaevsky Jul 9, 2019
cad8ae3
applies fmt
vbogaevsky Jul 9, 2019
f5a7f40
restore original lifetimes
vbogaevsky Jul 13, 2019
8b64e01
Merge branch 'dpi-overhaul' of github.com:rust-windowing/winit into d…
vbogaevsky Aug 14, 2019
00da630
solution is somewhere out there
vbogaevsky Aug 21, 2019
c7becf9
applies fmt
vbogaevsky Aug 21, 2019
8305206
pass as references
vbogaevsky Aug 21, 2019
189ca8c
resolves issue with HANDLER
vbogaevsky Aug 22, 2019
a76f8e7
crate visible type error
vbogaevsky Aug 23, 2019
c2d99b6
fixes visibility issues
vbogaevsky Aug 23, 2019
8ad50d5
applies fmt
vbogaevsky Aug 23, 2019
938da69
deals with warnings
vbogaevsky Aug 23, 2019
4fc725c
simplifies new_inner_size setting algorthm
vbogaevsky Aug 25, 2019
5aa604f
moves proxy instead of referencing it and removes double deref from p…
vbogaevsky Aug 25, 2019
7f0d3ea
makes @Osspial tests (https://github.com/rust-windowing/winit/pull/99…
vbogaevsky Aug 29, 2019
c6559d0
complies with @aleksijuvani suggested changes
vbogaevsky Aug 29, 2019
1101152
makes max window size std::f32::MAX
vbogaevsky Aug 30, 2019
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ core-foundation = "0.6"
core-graphics = "0.17.3"
core-video-sys = "0.1.2"
dispatch = "0.1.4"
objc = "0.2.3"
objc = "0.2.6"

[target.'cfg(target_os = "windows")'.dependencies]
bitflags = "1"
Expand Down
96 changes: 72 additions & 24 deletions src/platform_impl/macos/app_state.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,21 +10,30 @@ use std::{
time::Instant,
};

use cocoa::{appkit::NSApp, base::nil};
use cocoa::{
appkit::{NSApp, NSWindow},
base::nil,
};

use crate::{
dpi::{LogicalSize, PhysicalSize},
event::{Event, StartCause, WindowEvent},
event_loop::{ControlFlow, EventLoopWindowTarget as RootWindowTarget},
platform_impl::platform::{observer::EventLoopWaker, util::Never},
platform_impl::platform::{
event::{EventProxy, EventWrapper, WindowEventProxy},
observer::EventLoopWaker,
util::{IdRef, Never},
window::get_window_id,
},
window::WindowId,
};

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.
Expand All @@ -33,7 +42,8 @@ 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);
}

Expand All @@ -54,10 +64,10 @@ impl<F, T> Debug for EventLoopHandler<F, T> {

impl<F, T> EventHandler for EventLoopHandler<F, T>
where
F: 'static + FnMut(Event<T>, &RootWindowTarget<T>, &mut ControlFlow),
F: 'static + FnMut(Event<'_, T>, &RootWindowTarget<T>, &mut ControlFlow),
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.callback)(event.userify(), &self.window_target, control_flow);
self.will_exit |= *control_flow == ControlFlow::Exit;
if self.will_exit {
Expand Down Expand Up @@ -86,29 +96,30 @@ struct Handler {
control_flow_prev: Mutex<ControlFlow>,
start_time: Mutex<Option<Instant>>,
callback: Mutex<Option<Box<dyn EventHandler>>>,
pending_events: Mutex<VecDeque<Event<Never>>>,
deferred_events: Mutex<VecDeque<Event<Never>>>,
pending_events: Mutex<VecDeque<Event<'static, Never>>>,
deferred_events: Mutex<VecDeque<EventWrapper>>,
pending_redraw: Mutex<Vec<WindowId>>,
waker: Mutex<EventLoopWaker>,
window_size: Box<Option<PhysicalSize>>,
}

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<Event<'static, Never>>> {
self.pending_events.lock().unwrap()
}

fn deferred<'a>(&'a self) -> MutexGuard<'a, VecDeque<Event<Never>>> {
fn deferred(&self) -> MutexGuard<'_, VecDeque<EventWrapper>> {
self.deferred_events.lock().unwrap()
}

fn redraw<'a>(&'a self) -> MutexGuard<'a, Vec<WindowId>> {
fn redraw(&self) -> MutexGuard<'_, Vec<WindowId>> {
self.pending_redraw.lock().unwrap()
}

fn waker<'a>(&'a self) -> MutexGuard<'a, EventLoopWaker> {
fn waker(&self) -> MutexGuard<'_, EventLoopWaker> {
self.waker.lock().unwrap()
}

Expand Down Expand Up @@ -144,11 +155,11 @@ impl Handler {
*self.start_time.lock().unwrap() = Some(Instant::now());
}

fn take_events(&self) -> VecDeque<Event<Never>> {
fn take_events(&self) -> VecDeque<Event<'_, Never>> {
mem::replace(&mut *self.events(), Default::default())
}

fn take_deferred(&self) -> VecDeque<Event<Never>> {
fn take_deferred(&self) -> VecDeque<EventWrapper> {
mem::replace(&mut *self.deferred(), Default::default())
}

Expand All @@ -164,7 +175,7 @@ impl Handler {
self.in_callback.store(in_callback, Ordering::Release);
}

fn handle_nonuser_event(&self, event: Event<Never>) {
fn handle_nonuser_event(&self, event: Event<'_, Never>) {
if let Some(ref mut callback) = *self.callback.lock().unwrap() {
callback.handle_nonuser_event(event, &mut *self.control_flow.lock().unwrap());
}
Expand All @@ -175,14 +186,38 @@ impl Handler {
callback.handle_user_events(&mut *self.control_flow.lock().unwrap());
}
}

fn create_hidpi_factor_changed_event(&mut self, ns_window: &IdRef) -> Event<'_, Never> {
let hidpi_factor = unsafe { NSWindow::backingScaleFactor(**ns_window) } as f64;
let ns_size = unsafe { NSWindow::frame(**ns_window).size };
let new_size = LogicalSize::new(ns_size.width, ns_size.height).to_physical(hidpi_factor);
self.window_size = Box::new(Some(new_size));
// let new_inner_size: &'static mut Option<PhysicalSize> =
Event::WindowEvent {
window_id: WindowId(get_window_id(**ns_window)),
event: WindowEvent::HiDpiFactorChanged {
hidpi_factor,
new_inner_size: &mut *self.window_size,
},
}
}

fn make_event(&mut self, proxy: &EventProxy) -> Event<'_, Never> {
match proxy {
EventProxy::WindowEvent {
ns_window,
proxy: WindowEventProxy::HiDpiFactorChangedProxy,
} => self.create_hidpi_factor_changed_event(ns_window),
}
}
}

pub enum AppState {}

impl AppState {
pub fn set_callback<F, T>(callback: F, window_target: RootWindowTarget<T>)
where
F: 'static + FnMut(Event<T>, &RootWindowTarget<T>, &mut ControlFlow),
F: 'static + FnMut(Event<'_, T>, &RootWindowTarget<T>, &mut ControlFlow),
T: 'static,
{
*HANDLER.callback.lock().unwrap() = Some(Box::new(EventLoopHandler {
Expand Down Expand Up @@ -245,29 +280,42 @@ impl AppState {
}
}

pub fn queue_event(event: Event<Never>) {
pub fn queue_event(event: Event<'static, Never>) {
if !unsafe { msg_send![class!(NSThread), isMainThread] } {
panic!("Event queued from different thread: {:#?}", event);
}
HANDLER.events().push_back(event);
}

pub fn queue_events(mut events: VecDeque<Event<Never>>) {
pub fn queue_events(mut events: VecDeque<Event<'static, Never>>) {
if !unsafe { msg_send![class!(NSThread), isMainThread] } {
panic!("Events queued from different thread: {:#?}", events);
}
HANDLER.events().append(&mut events);
}

pub fn send_event_immediately(event: Event<Never>) {
pub fn send_event_immediately(wrapper: EventWrapper) {
if !unsafe { msg_send![class!(NSThread), isMainThread] } {
panic!("Event sent from different thread: {:#?}", event);
panic!("Event sent from different thread: {:#?}", wrapper);
}
HANDLER.deferred().push_back(event);
HANDLER.deferred().push_back(wrapper);
if !HANDLER.get_in_callback() {
HANDLER.set_in_callback(true);
for event in HANDLER.take_deferred() {
HANDLER.handle_nonuser_event(event);
for wrapper in HANDLER.take_deferred() {
match wrapper {
EventWrapper::StaticEvent(event) => HANDLER.handle_nonuser_event(event),
EventWrapper::EventProxy(proxy) => {
let event = HANDLER.make_event(&proxy);
vbogaevsky marked this conversation as resolved.
Show resolved Hide resolved
HANDLER.handle_nonuser_event(event);
if let Event::WindowEvent {
event: window_event,
..
} = event
{
proxy.callback(&window_event);
};
}
};
}
HANDLER.set_in_callback(false);
}
Expand Down
61 changes: 57 additions & 4 deletions src/platform_impl/macos/event.rs
Original file line number Diff line number Diff line change
@@ -1,15 +1,68 @@
use std::os::raw::c_ushort;

use cocoa::{
appkit::{NSEvent, NSEventModifierFlags},
appkit::{NSEvent, NSEventModifierFlags, NSWindow},
base::id,
foundation::{NSRect, NSSize},
};

use crate::{
event::{ElementState, KeyboardInput, ModifiersState, VirtualKeyCode, WindowEvent},
platform_impl::platform::DEVICE_ID,
event::{ElementState, Event, KeyboardInput, ModifiersState, VirtualKeyCode, WindowEvent},
platform_impl::platform::{
util::{IdRef, Never},
DEVICE_ID,
},
};

#[derive(Debug)]
pub(crate) enum EventWrapper {
StaticEvent(Event<'static, Never>),
EventProxy(EventProxy),
}

#[derive(Debug, PartialEq)]
pub(crate) enum EventProxy {
WindowEvent {
ns_window: IdRef,
proxy: WindowEventProxy,
},
}

impl EventProxy {
pub fn callback(self, event: &WindowEvent<'_>) {
match self {
EventProxy::WindowEvent { ns_window, proxy } => proxy.callback(ns_window, event),
};
}
}

#[derive(Debug, PartialEq)]
pub(crate) enum WindowEventProxy {
HiDpiFactorChangedProxy,
}

impl WindowEventProxy {
fn callback(self, ns_window: IdRef, event: &WindowEvent<'_>) {
match self {
WindowEventProxy::HiDpiFactorChangedProxy => {
if let WindowEvent::HiDpiFactorChanged {
hidpi_factor,
new_inner_size,
} = event
{
let origin = unsafe { NSWindow::frame(*ns_window).origin };
if let Some(physical_size) = new_inner_size {
let logical_size = physical_size.to_logical(*hidpi_factor);
let size = NSSize::new(logical_size.width, logical_size.height);
let rect = NSRect::new(origin, size);
unsafe { ns_window.setFrame_display_(rect, cocoa::base::YES) };
};
};
}
}
}
}

pub fn char_to_keycode(c: char) -> Option<VirtualKeyCode> {
// We only translate keys that are affected by keyboard layout.
//
Expand Down Expand Up @@ -244,7 +297,7 @@ pub unsafe fn modifier_event(
ns_event: id,
keymask: NSEventModifierFlags,
was_key_pressed: bool,
) -> Option<WindowEvent> {
) -> Option<WindowEvent<'static>> {
if !was_key_pressed && NSEvent::modifierFlags(ns_event).contains(keymask)
|| was_key_pressed && !NSEvent::modifierFlags(ns_event).contains(keymask)
{
Expand Down
4 changes: 2 additions & 2 deletions src/platform_impl/macos/event_loop.rs
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ impl<T> EventLoop<T> {

pub fn run<F>(self, callback: F) -> !
where
F: 'static + FnMut(Event<T>, &RootWindowTarget<T>, &mut ControlFlow),
F: 'static + FnMut(Event<'_, T>, &RootWindowTarget<T>, &mut ControlFlow),
{
unsafe {
let _pool = NSAutoreleasePool::new(nil);
Expand All @@ -98,7 +98,7 @@ impl<T> EventLoop<T> {

pub fn run_return<F>(&mut self, _callback: F)
where
F: FnMut(Event<T>, &RootWindowTarget<T>, &mut ControlFlow),
F: FnMut(Event<'_, T>, &RootWindowTarget<T>, &mut ControlFlow),
{
unimplemented!();
}
Expand Down
1 change: 1 addition & 0 deletions src/platform_impl/macos/util/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ pub const EMPTY_RANGE: ffi::NSRange = ffi::NSRange {
length: 0,
};

#[derive(Debug, PartialEq)]
pub struct IdRef(id);

impl IdRef {
Expand Down
Loading