diff --git a/src/lib.rs b/src/lib.rs index 933f7b6..664105a 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -397,6 +397,24 @@ impl Window { self.0.set_position(x, y) } + /// + /// Gets the position of the window. This is useful if you want + /// to store the position of the window across sessions + /// + /// # Examples + /// + /// ```no_run + /// # use minifb::*; + /// # let mut window = Window::new("Test", 640, 400, WindowOptions::default()).unwrap(); + /// // Retrieves the current window position + /// let (x,y) = window.get_position(); + /// ``` + /// + #[inline] + pub fn get_position(&self) -> (isize, isize) { + self.0.get_position() + } + /// /// Makes the window the topmost window and makes it stay always on top. This is useful if you /// want the window to float above all over windows diff --git a/src/native/macosx/MacMiniFB.m b/src/native/macosx/MacMiniFB.m index f4f96be..c310a9d 100644 --- a/src/native/macosx/MacMiniFB.m +++ b/src/native/macosx/MacMiniFB.m @@ -559,6 +559,23 @@ void mfb_set_position(void* window, int x, int y) /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +void mfb_get_position(const void* window, int *px, int *py) +{ + OSXWindow* win = (OSXWindow*)window; + const NSRect rectW = [win frame]; + if( px != NULL ) { + *px = rectW.origin.x; + } + if( py != NULL ) { + const NSRect msf = [[NSScreen mainScreen] frame]; + const float height = msf.size.height; + const float h = rectW.size.height; + *py = height - ( rectW.origin.y + h ); // origin is from bottom + } +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + int mfb_should_close(void* window) { OSXWindow* win = (OSXWindow*)window; diff --git a/src/os/macos/mod.rs b/src/os/macos/mod.rs index 2769692..333b81c 100644 --- a/src/os/macos/mod.rs +++ b/src/os/macos/mod.rs @@ -175,6 +175,7 @@ extern "C" { buf_stride: u32, ); fn mfb_set_position(window: *mut c_void, x: i32, y: i32); + fn mfb_get_position(window: *const c_void, x: *mut i32, y: *mut i32); fn mfb_set_key_callback( window: *mut c_void, target: *mut c_void, @@ -414,6 +415,15 @@ impl Window { unsafe { mfb_set_position(self.window_handle, x as i32, y as i32) } } + #[inline] + pub fn get_position(&self) -> (isize, isize) { + let (mut x, mut y) = (0, 0); + unsafe { + mfb_get_position(self.window_handle, &mut x, &mut y); + } + (x as isize, y as isize) + } + #[inline] pub fn topmost(&self, topmost: bool) { unsafe { mfb_topmost(self.window_handle, topmost) } diff --git a/src/os/posix/mod.rs b/src/os/posix/mod.rs index 66b0ebb..8b239bf 100644 --- a/src/os/posix/mod.rs +++ b/src/os/posix/mod.rs @@ -142,6 +142,15 @@ impl Window { } } + pub fn get_position(&self) -> (isize, isize) { + match *self { + #[cfg(feature = "x11")] + Window::X11(ref w) => w.get_position(), + #[cfg(feature = "wayland")] + Window::Wayland(ref w) => w.get_position(), + } + } + pub fn topmost(&self, _topmost: bool) { // We will just do nothing until it is implemented so that nothing breaks } diff --git a/src/os/posix/wayland.rs b/src/os/posix/wayland.rs index fd2e851..3ea2092 100644 --- a/src/os/posix/wayland.rs +++ b/src/os/posix/wayland.rs @@ -647,6 +647,16 @@ impl Window { .set_geometry((x as i32, y as i32), (self.width, self.height)); } + pub fn get_position(&self) -> (isize, isize) { + let (mut x, mut y) = (0, 0); + + unsafe { + // todo!("get_position"); + } + + (x as isize, y as isize) + } + pub fn set_rate(&mut self, rate: Option) { self.update_rate.set_rate(rate); } diff --git a/src/os/posix/x11.rs b/src/os/posix/x11.rs index 82a76f5..eb17768 100644 --- a/src/os/posix/x11.rs +++ b/src/os/posix/x11.rs @@ -25,7 +25,8 @@ use crate::mouse_handler; use super::common::Menu; use x11_dl::xlib::{ KeyPressMask, KeyReleaseMask, KeySym, Status, XEvent, XIMPreeditNothing, XIMStatusNothing, - XKeyEvent, XNClientWindow, XNFocusWindow, XNInputStyle, XrmDatabase, XIC, XIM, + XKeyEvent, XNClientWindow, XNFocusWindow, XNInputStyle, XWindowAttributes, XrmDatabase, XIC, + XIM, }; // NOTE: the x11-dl crate does not define Button6 or Button7 @@ -680,6 +681,37 @@ impl Window { } } + #[inline] + pub fn get_position(&self) -> (isize, isize) { + let (x, y); + let (mut nx, mut ny) = (0, 0); + + // Create dummy window for child_return value + let mut dummy_window: mem::MaybeUninit = mem::MaybeUninit::uninit(); + let mut attributes: mem::MaybeUninit = mem::MaybeUninit::uninit(); + + unsafe { + let root = (self.d.lib.XDefaultRootWindow)(self.d.display); + + (self.d.lib.XGetWindowAttributes)(self.d.display, self.handle, attributes.as_mut_ptr()); + x = attributes.assume_init().x; + y = attributes.assume_init().y; + + (self.d.lib.XTranslateCoordinates)( + self.d.display, + self.handle, + root, + x, + y, + &mut nx, + &mut ny, + dummy_window.as_mut_ptr() as *mut u64, + ); + } + + (nx as isize, ny as isize) + } + #[inline] pub fn get_size(&self) -> (usize, usize) { (self.width as usize, self.height as usize) diff --git a/src/os/windows/mod.rs b/src/os/windows/mod.rs index 8ef4c1e..01fb69e 100644 --- a/src/os/windows/mod.rs +++ b/src/os/windows/mod.rs @@ -700,6 +700,25 @@ impl Window { } } + #[inline] + pub fn get_position(&self) -> (isize, isize) { + let (mut x, mut y) = (0, 0); + + unsafe { + let mut rect = windef::RECT { + left: 0, + right: 0, + top: 0, + bottom: 0, + }; + if winuser::GetWindowRect(self.window.unwrap(), &mut rect) != 0 { + x = rect.left; + y = rect.top; + } + } + (x as isize, y as isize) + } + #[inline] pub fn topmost(&self, topmost: bool) { unsafe {