mirror of
https://github.com/italicsjenga/winit-sonoma-fix.git
synced 2024-12-23 22:01:31 +11:00
Add methods to get the position of a window's client area, relative to the desktop (#430)
* Add get_inner_position for windows, prototypes for other platforms * Fix linux builds * Implement get_inner_position for osx * Add get_inner_pos implementations for other platforms * Fixed get_inner_position on macOS * Corrected set_position on macOS * Added CHANGELOG entry
This commit is contained in:
parent
10688915eb
commit
8fd49a4dbe
|
@ -10,6 +10,9 @@
|
|||
- Properly calculate the minimum and maximum window size on Windows, including window decorations.
|
||||
- Map more `MouseCursor` variants to cursor icons on Windows.
|
||||
- Discard the stray mouse down event being delivered after window resize on macOS.
|
||||
- Corrected `get_position` on macOS to return outer frame position, not content area position.
|
||||
- Corrected `set_position` on macOS to set outer frame position, not content area position.
|
||||
- Added `get_inner_position` method to `Window`, which gets the position of the window's client area. This is implemented on all applicable platforms (all desktop platforms other than Wayland, where this isn't possible).
|
||||
|
||||
# Version 0.12.0 (2018-04-06)
|
||||
|
||||
|
|
|
@ -243,6 +243,11 @@ impl Window {
|
|||
None
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn get_inner_position(&self) -> Option<(i32, i32)> {
|
||||
None
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn set_position(&self, _x: i32, _y: i32) {
|
||||
}
|
||||
|
|
|
@ -417,6 +417,11 @@ impl Window {
|
|||
Some((0, 0))
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn get_inner_position(&self) -> Option<(i32, i32)> {
|
||||
Some((0, 0))
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn set_position(&self, _: i32, _: i32) {
|
||||
}
|
||||
|
|
|
@ -288,6 +288,11 @@ impl Window {
|
|||
None
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn get_inner_position(&self) -> Option<(i32, i32)> {
|
||||
None
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn set_position(&self, _x: i32, _y: i32) {
|
||||
}
|
||||
|
|
|
@ -162,6 +162,14 @@ impl Window {
|
|||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn get_inner_position(&self) -> Option<(i32, i32)> {
|
||||
match self {
|
||||
&Window::X(ref m) => m.get_inner_position(),
|
||||
&Window::Wayland(ref m) => m.get_inner_position(),
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn set_position(&self, x: i32, y: i32) {
|
||||
match self {
|
||||
|
|
|
@ -113,6 +113,12 @@ impl Window {
|
|||
None
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn get_inner_position(&self) -> Option<(i32, i32)> {
|
||||
// Not possible with wayland
|
||||
None
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn set_position(&self, _x: i32, _y: i32) {
|
||||
// Not possible with wayland
|
||||
|
|
|
@ -919,6 +919,11 @@ impl Window2 {
|
|||
self.get_geometry().map(|geo| geo.get_position())
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn get_inner_position(&self) -> Option<(i32, i32)> {
|
||||
self.get_geometry().map(|geo| geo.get_inner_position())
|
||||
}
|
||||
|
||||
pub fn set_position(&self, mut x: i32, mut y: i32) {
|
||||
if let Some(ref wm_name) = self.wm_name {
|
||||
// There are a few WMs that set client area position rather than window position, so
|
||||
|
|
|
@ -543,41 +543,54 @@ impl Window2 {
|
|||
unsafe { NSWindow::orderOut_(*self.window, nil); }
|
||||
}
|
||||
|
||||
pub fn get_position(&self) -> Option<(i32, i32)> {
|
||||
unsafe {
|
||||
let content_rect = NSWindow::contentRectForFrameRect_(*self.window, NSWindow::frame(*self.window));
|
||||
// For consistency with other platforms, this will...
|
||||
// 1. translate the bottom-left window corner into the top-left window corner
|
||||
// 2. translate the coordinate from a bottom-left origin coordinate system to a top-left one
|
||||
fn bottom_left_to_top_left(rect: NSRect) -> i32 {
|
||||
(CGDisplay::main().pixels_high() as f64 - (rect.origin.y + rect.size.height)) as _
|
||||
}
|
||||
|
||||
// TODO: consider extrapolating the calculations for the y axis to
|
||||
// a private method
|
||||
Some((content_rect.origin.x as i32, (CGDisplay::main().pixels_high() as f64 - (content_rect.origin.y + content_rect.size.height)) as i32))
|
||||
}
|
||||
pub fn get_position(&self) -> Option<(i32, i32)> {
|
||||
let frame_rect = unsafe { NSWindow::frame(*self.window) };
|
||||
Some((
|
||||
frame_rect.origin.x as i32,
|
||||
Self::bottom_left_to_top_left(frame_rect),
|
||||
))
|
||||
}
|
||||
|
||||
pub fn get_inner_position(&self) -> Option<(i32, i32)> {
|
||||
let content_rect = unsafe {
|
||||
NSWindow::contentRectForFrameRect_(
|
||||
*self.window,
|
||||
NSWindow::frame(*self.window),
|
||||
)
|
||||
};
|
||||
Some((
|
||||
content_rect.origin.x as i32,
|
||||
Self::bottom_left_to_top_left(content_rect),
|
||||
))
|
||||
}
|
||||
|
||||
pub fn set_position(&self, x: i32, y: i32) {
|
||||
let dummy = NSRect::new(
|
||||
NSPoint::new(
|
||||
x as f64,
|
||||
// While it's true that we're setting the top-left position, it still needs to be
|
||||
// in a bottom-left coordinate system.
|
||||
CGDisplay::main().pixels_high() as f64 - y as f64,
|
||||
),
|
||||
NSSize::new(0f64, 0f64),
|
||||
);
|
||||
unsafe {
|
||||
let frame = NSWindow::frame(*self.view);
|
||||
|
||||
// NOTE: `setFrameOrigin` might not give desirable results when
|
||||
// setting window, as it treats bottom left as origin.
|
||||
// `setFrameTopLeftPoint` treats top left as origin (duh), but
|
||||
// does not equal the value returned by `get_window_position`
|
||||
// (there is a difference by 22 for me on yosemite)
|
||||
|
||||
// TODO: consider extrapolating the calculations for the y axis to
|
||||
// a private method
|
||||
let dummy = NSRect::new(NSPoint::new(x as f64, CGDisplay::main().pixels_high() as f64 - (frame.size.height + y as f64)), NSSize::new(0f64, 0f64));
|
||||
let conv = NSWindow::frameRectForContentRect_(*self.window, dummy);
|
||||
|
||||
// NSWindow::setFrameTopLeftPoint_(*self.window, conv.origin);
|
||||
NSWindow::setFrameOrigin_(*self.window, conv.origin);
|
||||
NSWindow::setFrameTopLeftPoint_(*self.window, dummy.origin);
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn get_inner_size(&self) -> Option<(u32, u32)> {
|
||||
let factor = self.hidpi_factor() as f64; // API convention is that size is in physical pixels
|
||||
unsafe {
|
||||
let view_frame = NSView::frame(*self.view);
|
||||
let factor = self.hidpi_factor() as f64; // API convention is that size is in physical pixels
|
||||
Some(((view_frame.size.width*factor) as u32, (view_frame.size.height*factor) as u32))
|
||||
}
|
||||
}
|
||||
|
|
|
@ -129,6 +129,17 @@ impl Window {
|
|||
Some((rect.left as i32, rect.top as i32))
|
||||
}
|
||||
|
||||
pub fn get_inner_position(&self) -> Option<(i32, i32)> {
|
||||
use std::mem;
|
||||
|
||||
let mut position: POINT = unsafe{ mem::zeroed() };
|
||||
if unsafe{ winuser::ClientToScreen(self.window.0, &mut position) } == 0 {
|
||||
return None;
|
||||
}
|
||||
|
||||
Some((position.x, position.y))
|
||||
}
|
||||
|
||||
/// See the docs in the crate root file.
|
||||
pub fn set_position(&self, x: i32, y: i32) {
|
||||
unsafe {
|
||||
|
|
|
@ -181,6 +181,15 @@ impl Window {
|
|||
self.window.get_position()
|
||||
}
|
||||
|
||||
/// Returns the position of the top-left hand corner of the window's client area relative to the
|
||||
/// top-left hand corner of the desktop.
|
||||
///
|
||||
/// The same conditions that apply to `get_position` apply to this method.
|
||||
#[inline]
|
||||
pub fn get_inner_position(&self) -> Option<(i32, i32)> {
|
||||
self.window.get_inner_position()
|
||||
}
|
||||
|
||||
/// Modifies the position of the window.
|
||||
///
|
||||
/// See `get_position` for more information about the coordinates.
|
||||
|
|
Loading…
Reference in a new issue