Skip to content

Commit 650f9ea

Browse files
vbogaevskyOsspial
authored andcommitted
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
1 parent f527e4b commit 650f9ea

File tree

10 files changed

+273
-153
lines changed

10 files changed

+273
-153
lines changed

Cargo.toml

+1-1
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ cocoa = "0.19.1"
4242
core-foundation = "0.6"
4343
core-graphics = "0.17.3"
4444
dispatch = "0.1.4"
45-
objc = "0.2.3"
45+
objc = "0.2.6"
4646

4747
[target.'cfg(target_os = "macos")'.dependencies.core-video-sys]
4848
version = "0.1.3"

examples/multithreaded.rs

+13-7
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ fn main() {
55
use std::{collections::HashMap, sync::mpsc, thread, time::Duration};
66

77
use winit::{
8-
dpi::{PhysicalPosition, PhysicalSize},
8+
dpi::{PhysicalPosition, PhysicalSize, Position, Size},
99
event::{ElementState, Event, KeyboardInput, VirtualKeyCode, WindowEvent},
1010
event_loop::{ControlFlow, EventLoop},
1111
window::{CursorIcon, Fullscreen, WindowBuilder},
@@ -122,12 +122,18 @@ fn main() {
122122
),
123123
false => WINDOW_SIZE,
124124
}),
125-
W => window
126-
.set_cursor_position(PhysicalPosition::new(
127-
WINDOW_SIZE.width as f64 / 2.0,
128-
WINDOW_SIZE.height as f64 / 2.0,
129-
))
130-
.unwrap(),
125+
W => {
126+
if let Size::Physical(size) = WINDOW_SIZE.into() {
127+
window
128+
.set_cursor_position(Position::Physical(
129+
PhysicalPosition::new(
130+
size.width as f64 / 2.0,
131+
size.height as f64 / 2.0,
132+
),
133+
))
134+
.unwrap()
135+
}
136+
}
131137
Z => {
132138
window.set_visible(false);
133139
thread::sleep(Duration::from_secs(1));

src/platform_impl/macos/app.rs

+11-11
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ use objc::{
1111

1212
use crate::{
1313
event::{DeviceEvent, ElementState, Event},
14-
platform_impl::platform::{app_state::AppState, util, DEVICE_ID},
14+
platform_impl::platform::{app_state::AppState, event::EventWrapper, util, DEVICE_ID},
1515
};
1616

1717
pub struct AppClass(pub *const Class);
@@ -71,59 +71,59 @@ unsafe fn maybe_dispatch_device_event(event: id) {
7171
let delta_y = event.deltaY() as f64;
7272

7373
if delta_x != 0.0 {
74-
events.push_back(Event::DeviceEvent {
74+
events.push_back(EventWrapper::StaticEvent(Event::DeviceEvent {
7575
device_id: DEVICE_ID,
7676
event: DeviceEvent::Motion {
7777
axis: 0,
7878
value: delta_x,
7979
},
80-
});
80+
}));
8181
}
8282

8383
if delta_y != 0.0 {
84-
events.push_back(Event::DeviceEvent {
84+
events.push_back(EventWrapper::StaticEvent(Event::DeviceEvent {
8585
device_id: DEVICE_ID,
8686
event: DeviceEvent::Motion {
8787
axis: 1,
8888
value: delta_y,
8989
},
90-
});
90+
}));
9191
}
9292

9393
if delta_x != 0.0 || delta_y != 0.0 {
94-
events.push_back(Event::DeviceEvent {
94+
events.push_back(EventWrapper::StaticEvent(Event::DeviceEvent {
9595
device_id: DEVICE_ID,
9696
event: DeviceEvent::MouseMotion {
9797
delta: (delta_x, delta_y),
9898
},
99-
});
99+
}));
100100
}
101101

102102
AppState::queue_events(events);
103103
}
104104
appkit::NSLeftMouseDown | appkit::NSRightMouseDown | appkit::NSOtherMouseDown => {
105105
let mut events = VecDeque::with_capacity(1);
106106

107-
events.push_back(Event::DeviceEvent {
107+
events.push_back(EventWrapper::StaticEvent(Event::DeviceEvent {
108108
device_id: DEVICE_ID,
109109
event: DeviceEvent::Button {
110110
button: event.buttonNumber() as u32,
111111
state: ElementState::Pressed,
112112
},
113-
});
113+
}));
114114

115115
AppState::queue_events(events);
116116
}
117117
appkit::NSLeftMouseUp | appkit::NSRightMouseUp | appkit::NSOtherMouseUp => {
118118
let mut events = VecDeque::with_capacity(1);
119119

120-
events.push_back(Event::DeviceEvent {
120+
events.push_back(EventWrapper::StaticEvent(Event::DeviceEvent {
121121
device_id: DEVICE_ID,
122122
event: DeviceEvent::Button {
123123
button: event.buttonNumber() as u32,
124124
state: ElementState::Released,
125125
},
126-
});
126+
}));
127127

128128
AppState::queue_events(events);
129129
}

src/platform_impl/macos/app_state.rs

+86-30
Original file line numberDiff line numberDiff line change
@@ -12,15 +12,21 @@ use std::{
1212
};
1313

1414
use cocoa::{
15-
appkit::NSApp,
15+
appkit::{NSApp, NSWindow},
1616
base::nil,
17-
foundation::{NSAutoreleasePool, NSString},
17+
foundation::{NSAutoreleasePool, NSSize, NSString},
1818
};
1919

2020
use crate::{
21-
event::{Event, StartCause},
21+
dpi::LogicalSize,
22+
event::{Event, StartCause, WindowEvent},
2223
event_loop::{ControlFlow, EventLoopWindowTarget as RootWindowTarget},
23-
platform_impl::platform::{observer::EventLoopWaker, util::Never},
24+
platform_impl::platform::{
25+
event::{EventProxy, EventWrapper},
26+
observer::EventLoopWaker,
27+
util::{IdRef, Never},
28+
window::get_window_id,
29+
},
2430
window::WindowId,
2531
};
2632
use objc::runtime::Object;
@@ -29,8 +35,8 @@ lazy_static! {
2935
static ref HANDLER: Handler = Default::default();
3036
}
3137

32-
impl Event<Never> {
33-
fn userify<T: 'static>(self) -> Event<T> {
38+
impl<'a, Never> Event<'a, Never> {
39+
fn userify<T: 'static>(self) -> Event<'a, T> {
3440
self.map_nonuser_event()
3541
// `Never` can't be constructed, so the `UserEvent` variant can't
3642
// be present here.
@@ -39,12 +45,13 @@ impl Event<Never> {
3945
}
4046

4147
pub trait EventHandler: Debug {
42-
fn handle_nonuser_event(&mut self, event: Event<Never>, control_flow: &mut ControlFlow);
48+
// Not sure probably it should accept Event<'static, Never>
49+
fn handle_nonuser_event(&mut self, event: Event<'_, Never>, control_flow: &mut ControlFlow);
4350
fn handle_user_events(&mut self, control_flow: &mut ControlFlow);
4451
}
4552

4653
struct EventLoopHandler<T: 'static> {
47-
callback: Box<dyn FnMut(Event<T>, &RootWindowTarget<T>, &mut ControlFlow)>,
54+
callback: Box<dyn FnMut(Event<'_, T>, &RootWindowTarget<T>, &mut ControlFlow)>,
4855
will_exit: bool,
4956
window_target: Rc<RootWindowTarget<T>>,
5057
}
@@ -59,7 +66,7 @@ impl<T> Debug for EventLoopHandler<T> {
5966
}
6067

6168
impl<T> EventHandler for EventLoopHandler<T> {
62-
fn handle_nonuser_event(&mut self, event: Event<Never>, control_flow: &mut ControlFlow) {
69+
fn handle_nonuser_event(&mut self, event: Event<'_, Never>, control_flow: &mut ControlFlow) {
6370
(self.callback)(event.userify(), &self.window_target, control_flow);
6471
self.will_exit |= *control_flow == ControlFlow::Exit;
6572
if self.will_exit {
@@ -88,7 +95,7 @@ struct Handler {
8895
control_flow_prev: Mutex<ControlFlow>,
8996
start_time: Mutex<Option<Instant>>,
9097
callback: Mutex<Option<Box<dyn EventHandler>>>,
91-
pending_events: Mutex<VecDeque<Event<Never>>>,
98+
pending_events: Mutex<VecDeque<EventWrapper>>,
9299
pending_redraw: Mutex<Vec<WindowId>>,
93100
waker: Mutex<EventLoopWaker>,
94101
}
@@ -97,15 +104,15 @@ unsafe impl Send for Handler {}
97104
unsafe impl Sync for Handler {}
98105

99106
impl Handler {
100-
fn events<'a>(&'a self) -> MutexGuard<'a, VecDeque<Event<Never>>> {
107+
fn events(&self) -> MutexGuard<'_, VecDeque<EventWrapper>> {
101108
self.pending_events.lock().unwrap()
102109
}
103110

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

108-
fn waker<'a>(&'a self) -> MutexGuard<'a, EventLoopWaker> {
115+
fn waker(&self) -> MutexGuard<'_, EventLoopWaker> {
109116
self.waker.lock().unwrap()
110117
}
111118

@@ -141,7 +148,7 @@ impl Handler {
141148
*self.start_time.lock().unwrap() = Some(Instant::now());
142149
}
143150

144-
fn take_events(&self) -> VecDeque<Event<Never>> {
151+
fn take_events(&self) -> VecDeque<EventWrapper> {
145152
mem::replace(&mut *self.events(), Default::default())
146153
}
147154

@@ -157,9 +164,14 @@ impl Handler {
157164
self.in_callback.store(in_callback, Ordering::Release);
158165
}
159166

160-
fn handle_nonuser_event(&self, event: Event<Never>) {
167+
fn handle_nonuser_event(&self, wrapper: EventWrapper) {
161168
if let Some(ref mut callback) = *self.callback.lock().unwrap() {
162-
callback.handle_nonuser_event(event, &mut *self.control_flow.lock().unwrap());
169+
match wrapper {
170+
EventWrapper::StaticEvent(event) => {
171+
callback.handle_nonuser_event(event, &mut *self.control_flow.lock().unwrap())
172+
}
173+
EventWrapper::EventProxy(proxy) => self.handle_proxy(proxy, callback),
174+
}
163175
}
164176
}
165177

@@ -168,6 +180,46 @@ impl Handler {
168180
callback.handle_user_events(&mut *self.control_flow.lock().unwrap());
169181
}
170182
}
183+
184+
fn handle_hidpi_factor_changed_event(
185+
&self,
186+
callback: &mut Box<dyn EventHandler + 'static>,
187+
ns_window: IdRef,
188+
suggested_size: LogicalSize,
189+
hidpi_factor: f64,
190+
) {
191+
let size = suggested_size.to_physical(hidpi_factor);
192+
let new_inner_size = &mut Some(size);
193+
let event = Event::WindowEvent {
194+
window_id: WindowId(get_window_id(*ns_window)),
195+
event: WindowEvent::HiDpiFactorChanged {
196+
hidpi_factor,
197+
new_inner_size,
198+
},
199+
};
200+
201+
callback.handle_nonuser_event(event, &mut *self.control_flow.lock().unwrap());
202+
203+
let physical_size = new_inner_size.unwrap_or(size);
204+
let logical_size = physical_size.to_logical(hidpi_factor);
205+
let size = NSSize::new(logical_size.width, logical_size.height);
206+
unsafe { NSWindow::setContentSize_(*ns_window, size) };
207+
}
208+
209+
fn handle_proxy(&self, proxy: EventProxy, callback: &mut Box<dyn EventHandler + 'static>) {
210+
match proxy {
211+
EventProxy::HiDpiFactorChangedProxy {
212+
ns_window,
213+
suggested_size,
214+
hidpi_factor,
215+
} => self.handle_hidpi_factor_changed_event(
216+
callback,
217+
ns_window,
218+
suggested_size,
219+
hidpi_factor,
220+
),
221+
}
222+
}
171223
}
172224

173225
pub enum AppState {}
@@ -176,16 +228,16 @@ impl AppState {
176228
// This function extends lifetime of `callback` to 'static as its side effect
177229
pub unsafe fn set_callback<F, T>(callback: F, window_target: Rc<RootWindowTarget<T>>)
178230
where
179-
F: FnMut(Event<T>, &RootWindowTarget<T>, &mut ControlFlow),
231+
F: FnMut(Event<'_, T>, &RootWindowTarget<T>, &mut ControlFlow),
180232
{
181233
*HANDLER.callback.lock().unwrap() = Some(Box::new(EventLoopHandler {
182234
// This transmute is always safe, in case it was reached through `run`, since our
183235
// lifetime will be already 'static. In other cases caller should ensure that all data
184236
// they passed to callback will actually outlive it, some apps just can't move
185237
// everything to event loop, so this is something that they should care about.
186238
callback: mem::transmute::<
187-
Box<dyn FnMut(Event<T>, &RootWindowTarget<T>, &mut ControlFlow)>,
188-
Box<dyn FnMut(Event<T>, &RootWindowTarget<T>, &mut ControlFlow)>,
239+
Box<dyn FnMut(Event<'_, T>, &RootWindowTarget<T>, &mut ControlFlow)>,
240+
Box<dyn FnMut(Event<'_, T>, &RootWindowTarget<T>, &mut ControlFlow)>,
189241
>(Box::new(callback)),
190242
will_exit: false,
191243
window_target,
@@ -194,7 +246,7 @@ impl AppState {
194246

195247
pub fn exit() {
196248
HANDLER.set_in_callback(true);
197-
HANDLER.handle_nonuser_event(Event::LoopDestroyed);
249+
HANDLER.handle_nonuser_event(EventWrapper::StaticEvent(Event::LoopDestroyed));
198250
HANDLER.set_in_callback(false);
199251
HANDLER.callback.lock().unwrap().take();
200252
}
@@ -203,7 +255,9 @@ impl AppState {
203255
HANDLER.set_ready();
204256
HANDLER.waker().start();
205257
HANDLER.set_in_callback(true);
206-
HANDLER.handle_nonuser_event(Event::NewEvents(StartCause::Init));
258+
HANDLER.handle_nonuser_event(EventWrapper::StaticEvent(Event::NewEvents(
259+
StartCause::Init,
260+
)));
207261
HANDLER.set_in_callback(false);
208262
}
209263

@@ -234,7 +288,7 @@ impl AppState {
234288
ControlFlow::Exit => StartCause::Poll, //panic!("unexpected `ControlFlow::Exit`"),
235289
};
236290
HANDLER.set_in_callback(true);
237-
HANDLER.handle_nonuser_event(Event::NewEvents(cause));
291+
HANDLER.handle_nonuser_event(EventWrapper::StaticEvent(Event::NewEvents(cause)));
238292
HANDLER.set_in_callback(false);
239293
}
240294

@@ -246,18 +300,18 @@ impl AppState {
246300
}
247301
}
248302

249-
pub fn queue_event(event: Event<Never>) {
303+
pub fn queue_event(wrapper: EventWrapper) {
250304
if !unsafe { msg_send![class!(NSThread), isMainThread] } {
251-
panic!("Event queued from different thread: {:#?}", event);
305+
panic!("Event queued from different thread: {:#?}", wrapper);
252306
}
253-
HANDLER.events().push_back(event);
307+
HANDLER.events().push_back(wrapper);
254308
}
255309

256-
pub fn queue_events(mut events: VecDeque<Event<Never>>) {
310+
pub fn queue_events(mut wrappers: VecDeque<EventWrapper>) {
257311
if !unsafe { msg_send![class!(NSThread), isMainThread] } {
258-
panic!("Events queued from different thread: {:#?}", events);
312+
panic!("Events queued from different thread: {:#?}", wrappers);
259313
}
260-
HANDLER.events().append(&mut events);
314+
HANDLER.events().append(&mut wrappers);
261315
}
262316

263317
pub fn cleared() {
@@ -270,11 +324,13 @@ impl AppState {
270324
for event in HANDLER.take_events() {
271325
HANDLER.handle_nonuser_event(event);
272326
}
273-
HANDLER.handle_nonuser_event(Event::MainEventsCleared);
327+
HANDLER.handle_nonuser_event(EventWrapper::StaticEvent(Event::MainEventsCleared));
274328
for window_id in HANDLER.should_redraw() {
275-
HANDLER.handle_nonuser_event(Event::RedrawRequested(window_id));
329+
HANDLER.handle_nonuser_event(EventWrapper::StaticEvent(Event::RedrawRequested(
330+
window_id,
331+
)));
276332
}
277-
HANDLER.handle_nonuser_event(Event::RedrawEventsCleared);
333+
HANDLER.handle_nonuser_event(EventWrapper::StaticEvent(Event::RedrawEventsCleared));
278334
HANDLER.set_in_callback(false);
279335
}
280336
if HANDLER.should_exit() {

0 commit comments

Comments
 (0)