macOS: Clean up coordinate system calculations (#3302)

* Clean up macOS and iOS monitor code a bit

* Clean up window size methods

Use `setContentSize`, `setContentMinSize`, `setContentMaxSize` and `contentRectForFrameRect` to let the windowing system figure out the required scaling, instead of us doing it manually.

* Use a flipped NSView coordinate system

* Clean up window position methods
This commit is contained in:
Mads Marquart 2023-12-24 10:12:09 +01:00 committed by GitHub
parent 5a43ea8cd6
commit 4f6fd44c6c
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
9 changed files with 173 additions and 217 deletions

View file

@ -7,16 +7,18 @@ use icrate::AppKit::{
NSApplicationPresentationHideMenuBar, NSApplicationPresentationOptions, NSDraggingDestination,
NSFilenamesPboardType, NSPasteboard, NSWindowDelegate, NSWindowOcclusionStateVisible,
};
use icrate::Foundation::{MainThreadMarker, NSArray, NSObject, NSObjectProtocol, NSSize, NSString};
use icrate::Foundation::{
MainThreadMarker, NSArray, NSObject, NSObjectProtocol, NSPoint, NSSize, NSString,
};
use objc2::rc::{autoreleasepool, Id};
use objc2::runtime::{AnyObject, ProtocolObject};
use objc2::{
class, declare_class, msg_send, msg_send_id, mutability, sel, ClassType, DeclaredClass,
};
use super::monitor::flip_window_screen_coordinates;
use super::{
app_state::AppState,
util,
window::{get_ns_theme, WinitWindow},
Fullscreen,
};
@ -35,7 +37,9 @@ pub(crate) struct State {
initial_fullscreen: Cell<bool>,
// During `windowDidResize`, we use this to only send Moved if the position changed.
previous_position: Cell<Option<(f64, f64)>>,
//
// This is expressed in native screen coordinates.
previous_position: Cell<Option<NSPoint>>,
// Used to prevent redundant events.
previous_scale_factor: Cell<f64>,
@ -450,34 +454,33 @@ impl WinitWindowDelegate {
}
fn queue_static_scale_factor_changed_event(&self) {
let scale_factor = self.ivars().window.scale_factor();
let window = &self.ivars().window;
let scale_factor = window.scale_factor();
if scale_factor == self.ivars().previous_scale_factor.get() {
return;
};
self.ivars().previous_scale_factor.set(scale_factor);
let suggested_size = self.view_size();
let content_size = window.contentRectForFrameRect(window.frame()).size;
let content_size = LogicalSize::new(content_size.width, content_size.height);
AppState::queue_static_scale_factor_changed_event(
self.ivars().window.clone(),
suggested_size.to_physical(scale_factor),
window.clone(),
content_size.to_physical(scale_factor),
scale_factor,
);
}
fn emit_move_event(&self) {
let rect = self.ivars().window.frame();
let x = rect.origin.x as f64;
let y = util::bottom_left_to_top_left(rect);
if self.ivars().previous_position.get() != Some((x, y)) {
self.ivars().previous_position.set(Some((x, y)));
let scale_factor = self.ivars().window.scale_factor();
let physical_pos = LogicalPosition::<f64>::from((x, y)).to_physical(scale_factor);
self.queue_event(WindowEvent::Moved(physical_pos));
let window = &self.ivars().window;
let frame = window.frame();
if self.ivars().previous_position.get() == Some(frame.origin) {
return;
}
}
self.ivars().previous_position.set(Some(frame.origin));
fn view_size(&self) -> LogicalSize<f64> {
let size = self.ivars().window.contentView().unwrap().frame().size;
LogicalSize::new(size.width as f64, size.height as f64)
let position = flip_window_screen_coordinates(frame);
let position =
LogicalPosition::new(position.x, position.y).to_physical(window.scale_factor());
self.queue_event(WindowEvent::Moved(position));
}
}