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 9 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
33 changes: 17 additions & 16 deletions src/platform_impl/macos/app_state.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,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.
Expand All @@ -33,7 +33,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 +55,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,8 +87,8 @@ 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<Event<'static, Never>>>,
pending_redraw: Mutex<Vec<WindowId>>,
waker: Mutex<EventLoopWaker>,
}
Expand All @@ -96,11 +97,11 @@ unsafe impl Send for Handler {}
unsafe impl Sync for Handler {}

impl Handler {
fn events<'a>(&'a self) -> MutexGuard<'a, VecDeque<Event<Never>>> {
fn events<'a>(&'a self) -> MutexGuard<'a, VecDeque<Event<'static, Never>>> {
self.pending_events.lock().unwrap()
}

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

Expand Down Expand Up @@ -144,11 +145,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<Event<'_, Never>> {
mem::replace(&mut *self.deferred(), Default::default())
}

Expand All @@ -164,7 +165,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 @@ -182,7 +183,7 @@ 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,21 +246,21 @@ 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(event: Event<'static, Never>) {
if !unsafe { msg_send![class!(NSThread), isMainThread] } {
panic!("Event sent from different thread: {:#?}", event);
}
Expand Down
2 changes: 1 addition & 1 deletion src/platform_impl/macos/event.rs
Original file line number Diff line number Diff line change
Expand Up @@ -244,7 +244,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
114 changes: 73 additions & 41 deletions src/platform_impl/macos/window.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,9 @@ use objc::{
};

use crate::{
dpi::{LogicalPosition, LogicalSize},
dpi::{
LogicalPosition, LogicalSize, PhysicalPosition, PhysicalSize, Position, Size, Size::Logical,
},
error::{ExternalError, NotSupportedError, OsError as RootOsError},
icon::Icon,
monitor::MonitorHandle as RootMonitorHandle,
Expand Down Expand Up @@ -122,10 +124,17 @@ fn create_window(
let frame = match screen {
Some(screen) => appkit::NSScreen::frame(screen),
None => {
let (width, height) = attrs
.inner_size
.map(|logical| (logical.width, logical.height))
.unwrap_or_else(|| (800.0, 600.0));
// Not sure what dpi_factor we need here.
// If i understand correctly, here we fail to create NSScreen frame, so we've got
// no dpi_factor
vbogaevsky marked this conversation as resolved.
Show resolved Hide resolved
let hidpi_factor = 1.0;
let (width, height) = match attrs.inner_size {
Some(size) => {
let logical = size.to_logical(hidpi_factor);
(logical.width, logical.height)
}
None => (800.0, 600.0),
};
NSRect::new(NSPoint::new(0.0, 0.0), NSSize::new(width, height))
}
};
Expand Down Expand Up @@ -315,13 +324,15 @@ impl UnownedWindow {
}

ns_app.activateIgnoringOtherApps_(YES);

win_attribs
.min_inner_size
.map(|dim| set_min_inner_size(*ns_window, dim));
win_attribs
.max_inner_size
.map(|dim| set_max_inner_size(*ns_window, dim));
let dpi_factor = NSWindow::backingScaleFactor(*ns_window) as f64;
win_attribs.min_inner_size.map(|dim| {
let logical_dim = dim.to_logical(dpi_factor);
set_min_inner_size(*ns_window, logical_dim)
});
win_attribs.max_inner_size.map(|dim| {
let logical_dim = dim.to_logical(dpi_factor);
set_max_inner_size(*ns_window, logical_dim)
});

use cocoa::foundation::NSArray;
// register for drag and drop operations.
Expand Down Expand Up @@ -415,27 +426,31 @@ impl UnownedWindow {
AppState::queue_redraw(RootWindowId(self.id()));
}

pub fn outer_position(&self) -> Result<LogicalPosition, NotSupportedError> {
pub fn outer_position(&self) -> Result<PhysicalPosition, NotSupportedError> {
let frame_rect = unsafe { NSWindow::frame(*self.ns_window) };
Ok((
let position = LogicalPosition::new(
frame_rect.origin.x as f64,
util::bottom_left_to_top_left(frame_rect),
)
.into())
);
let dpi_factor = self.hidpi_factor();
Ok(position.to_physical(dpi_factor))
}

pub fn inner_position(&self) -> Result<LogicalPosition, NotSupportedError> {
pub fn inner_position(&self) -> Result<PhysicalPosition, NotSupportedError> {
let content_rect = unsafe {
NSWindow::contentRectForFrameRect_(*self.ns_window, NSWindow::frame(*self.ns_window))
};
Ok((
let position = LogicalPosition::new(
content_rect.origin.x as f64,
util::bottom_left_to_top_left(content_rect),
)
.into())
);
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, position: Position) {
let dpi_factor = self.hidpi_factor();
let position = position.to_logical(dpi_factor);
let dummy = NSRect::new(
NSPoint::new(
position.x,
Expand All @@ -451,35 +466,50 @@ impl UnownedWindow {
}

#[inline]
pub fn inner_size(&self) -> LogicalSize {
pub fn inner_size(&self) -> PhysicalSize {
let view_frame = unsafe { NSView::frame(*self.ns_view) };
(view_frame.size.width as f64, view_frame.size.height as f64).into()
let logical: LogicalSize =
(view_frame.size.width as f64, view_frame.size.height as f64).into();
let dpi_factor = self.hidpi_factor();
logical.to_physical(dpi_factor)
}

#[inline]
pub fn outer_size(&self) -> LogicalSize {
pub fn outer_size(&self) -> PhysicalSize {
let view_frame = unsafe { NSWindow::frame(*self.ns_window) };
(view_frame.size.width as f64, view_frame.size.height as f64).into()
let logical: LogicalSize =
(view_frame.size.width as f64, view_frame.size.height as f64).into();
let dpi_factor = self.hidpi_factor();
logical.to_physical(dpi_factor)
}

#[inline]
pub fn set_inner_size(&self, size: LogicalSize) {
pub fn set_inner_size(&self, size: Size) {
unsafe {
util::set_content_size_async(*self.ns_window, size);
let dpi_factor = self.hidpi_factor();
util::set_content_size_async(*self.ns_window, size.to_logical(dpi_factor));
}
}

pub fn set_min_inner_size(&self, dimensions: Option<LogicalSize>) {
pub fn set_min_inner_size(&self, dimensions: Option<Size>) {
unsafe {
let dimensions = dimensions.unwrap_or_else(|| (0, 0).into());
set_min_inner_size(*self.ns_window, dimensions);
let dimensions = dimensions.unwrap_or(Logical(LogicalSize {
width: 0.0,
height: 0.0,
}));
let dpi_factor = self.hidpi_factor();
set_min_inner_size(*self.ns_window, dimensions.to_logical(dpi_factor));
}
}

pub fn set_max_inner_size(&self, dimensions: Option<LogicalSize>) {
pub fn set_max_inner_size(&self, dimensions: Option<Size>) {
unsafe {
let dimensions = dimensions.unwrap_or_else(|| (!0, !0).into());
set_max_inner_size(*self.ns_window, dimensions);
let dimensions = dimensions.unwrap_or(Logical(LogicalSize {
width: 0.0,
vbogaevsky marked this conversation as resolved.
Show resolved Hide resolved
height: 0.0,
}));
let dpi_factor = self.hidpi_factor();
set_max_inner_size(*self.ns_window, dimensions.to_logical(dpi_factor));
}
}

Expand Down Expand Up @@ -543,14 +573,14 @@ impl UnownedWindow {
}

#[inline]
pub fn set_cursor_position(
&self,
cursor_position: LogicalPosition,
) -> Result<(), ExternalError> {
let window_position = self.inner_position().unwrap();
pub fn set_cursor_position(&self, cursor_position: Position) -> Result<(), ExternalError> {
let physical_window_position = self.inner_position().unwrap();
let dpi_factor = self.hidpi_factor();
let window_position = physical_window_position.to_logical(dpi_factor);
let logical_cursor_position = cursor_position.to_logical(dpi_factor);
let point = appkit::CGPoint {
x: (cursor_position.x + window_position.x) as CGFloat,
y: (cursor_position.y + window_position.y) as CGFloat,
x: (logical_cursor_position.x + window_position.x) as CGFloat,
vbogaevsky marked this conversation as resolved.
Show resolved Hide resolved
y: (logical_cursor_position.y + window_position.y) as CGFloat,
};
CGDisplay::warp_mouse_cursor_position(point)
.map_err(|e| ExternalError::Os(os_error!(OsError::CGError(e))))?;
Expand Down Expand Up @@ -730,7 +760,9 @@ impl UnownedWindow {
}

#[inline]
pub fn set_ime_position(&self, logical_spot: LogicalPosition) {
pub fn set_ime_position(&self, spot: Position) {
let dpi_factor = self.hidpi_factor();
let logical_spot = spot.to_logical(dpi_factor);
unsafe {
view::set_ime_position(
*self.ns_view,
Expand Down
Loading