diff --git a/examples/open_window.rs b/examples/open_window.rs index 8834368..7a04268 100644 --- a/examples/open_window.rs +++ b/examples/open_window.rs @@ -26,9 +26,9 @@ fn main() { let window_open_options = baseview::WindowOpenOptions { title: "baseview".into(), size: WindowSize::MinMaxLogical { - initial_size: baseview::Size::new(512, 512), - min_size: baseview::Size::new(200, 200), - max_size: baseview::Size::new(1024, 1024), + initial_size: baseview::Size::new(512.0, 512.0), + min_size: baseview::Size::new(200.0, 200.0), + max_size: baseview::Size::new(1024.0, 1024.0), keep_aspect: false, }, scale: WindowScalePolicy::TrySystemScaleFactor, diff --git a/src/coordinates.rs b/src/coordinates.rs new file mode 100644 index 0000000..286c50f --- /dev/null +++ b/src/coordinates.rs @@ -0,0 +1,93 @@ +use crate::WindowInfo; + +/// A point in logical coordinates +#[derive(Debug, Copy, Clone, PartialEq)] +pub struct Point { + pub x: f64, + pub y: f64 +} + +impl Point { + /// Create a new point in logical coordinates + pub fn new(x: f64, y: f64) -> Self { + Self { x, y } + } + + /// Convert to actual physical coordinates + #[inline] + pub fn to_physical(&self, window_info: &WindowInfo) -> PhyPoint { + PhyPoint { + x: (self.x * window_info.scale()).round() as i32, + y: (self.y * window_info.scale()).round() as i32, + } + } +} + +/// A point in actual physical coordinates +#[derive(Debug, Copy, Clone, PartialEq)] +pub struct PhyPoint { + pub x: i32, + pub y: i32 +} + +impl PhyPoint { + /// Create a new point in actual physical coordinates + pub fn new(x: i32, y: i32) -> Self { + Self { x, y } + } + + /// Convert to logical coordinates + #[inline] + pub fn to_logical(&self, window_info: &WindowInfo) -> Point { + Point { + x: f64::from(self.x) * window_info.scale_recip(), + y: f64::from(self.y) * window_info.scale_recip(), + } + } +} + +/// A size in logical coordinates +#[derive(Debug, Copy, Clone, PartialEq)] +pub struct Size { + pub width: f64, + pub height: f64, +} + +impl Size { + /// Create a new size in logical coordinates + pub fn new(width: f64, height: f64) -> Self { + Self { width, height } + } + + /// Convert to actual physical size + #[inline] + pub fn to_physical(&self, window_info: &WindowInfo) -> PhySize { + PhySize { + width: (self.width * window_info.scale()).round() as u32, + height: (self.height * window_info.scale()).round() as u32, + } + } +} + +/// An actual size in physical coordinates +#[derive(Debug, Copy, Clone, PartialEq)] +pub struct PhySize { + pub width: u32, + pub height: u32, +} + +impl PhySize { + /// Create a new size in actual physical coordinates + pub fn new(width: u32, height: u32) -> Self { + Self { width, height } + } + + /// Convert to logical size + #[inline] + pub fn to_logical(&self, window_info: &WindowInfo) -> Size { + Size { + width: f64::from(self.width) * window_info.scale_recip(), + height: f64::from(self.height) * window_info.scale_recip(), + } + } +} \ No newline at end of file diff --git a/src/event.rs b/src/event.rs index 31d5e24..6fae242 100644 --- a/src/event.rs +++ b/src/event.rs @@ -42,9 +42,7 @@ pub struct MouseClick { pub button: MouseButton, pub click_count: usize, /// The logical coordinates of the mouse position - logical_pos: Point, - /// The physical coordinates of the mouse position - physical_pos: Point, + pub position: Point, } #[derive(Debug, Clone, Copy, PartialEq)] @@ -52,9 +50,7 @@ pub enum MouseEvent { /// The mouse cursor was moved CursorMoved { /// The logical coordinates of the mouse position - logical_pos: Point, - /// The physical coordinates of the mouse position - physical_pos: Point, + position: Point, }, /// A mouse button was pressed. diff --git a/src/lib.rs b/src/lib.rs index 88d4fa3..97a1f25 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -15,11 +15,13 @@ mod macos; #[cfg(target_os = "macos")] pub use macos::*; +mod coordinates; mod event; mod keyboard; mod mouse_cursor; mod window_info; mod window_open_options; +pub use coordinates::*; pub use event::*; pub use keyboard::*; pub use mouse_cursor::MouseCursor; @@ -45,36 +47,6 @@ impl WindowHandle { } } -#[derive(Debug, Copy, Clone, PartialEq)] -pub struct Point { - pub x: T, - pub y: T, -} - -impl Point { - pub fn new(x: T, y: T) -> Self { - Self { x, y } - } -} - -impl From> for Point { - fn from(p: Point) -> Point { - Point::new(p.x.round() as i32, p.y.round() as i32) - } -} - -#[derive(Debug, Copy, Clone, PartialEq)] -pub struct Size { - pub width: u32, - pub height: u32, -} - -impl Size { - pub fn new(width: u32, height: u32) -> Self { - Self { width, height } - } -} - type WindowOpenResult = Result; pub trait WindowHandler { diff --git a/src/win/window.rs b/src/win/window.rs index 872f751..a2bf4f6 100644 --- a/src/win/window.rs +++ b/src/win/window.rs @@ -25,6 +25,7 @@ use raw_window_handle::{ use crate::{ Event, KeyboardEvent, MouseButton, MouseEvent, Parent::WithParent, ScrollDelta, WindowEvent, WindowHandler, WindowInfo, WindowOpenOptions, WindowOpenResult, WindowScalePolicy, Size, Point, + PhySize, PhyPoint, }; unsafe fn message_box(title: &str, msg: &str) { @@ -76,19 +77,19 @@ unsafe extern "system" fn wnd_proc( match msg { WM_MOUSEMOVE => { - let x = (lparam & 0xFFFF) as f64; - let y = ((lparam >> 16) & 0xFFFF) as f64; - let physical_pos = Point::new(x, y); + let x = (lparam & 0xFFFF) as i32; + let y = ((lparam >> 16) & 0xFFFF) as i32; + + let physical_pos = PhyPoint { x, y }; let mut window_state = window_state.borrow_mut(); - let logical_pos = window_state.window_info.physical_to_logical(physical_pos); + let logical_pos = physical_pos.to_logical(&window_state.window_info); window_state.handler.on_event( &mut window, Event::Mouse(MouseEvent::CursorMoved { - logical_pos: logical_pos.into(), - physical_pos: physical_pos.into(), + position: logical_pos, }), ); return 0; diff --git a/src/window_info.rs b/src/window_info.rs index ba0a2a7..e37d52c 100644 --- a/src/window_info.rs +++ b/src/window_info.rs @@ -1,26 +1,21 @@ -use crate::{Size, Point}; +use crate::{Size, PhySize}; /// The info about the window #[derive(Debug, Copy, Clone)] pub struct WindowInfo { logical_size: Size, - physical_size: Size, + physical_size: PhySize, scale: f64, scale_recip: f64, } impl WindowInfo { pub fn from_logical_size(logical_size: Size, scale: f64) -> Self { - let (scale_recip, physical_size) = if scale == 1.0 { - (1.0, logical_size) - } else { - ( - 1.0 / scale, - Size { - width: (logical_size.width as f64 * scale).round() as u32, - height: (logical_size.height as f64 * scale).round() as u32, - } - ) + let scale_recip = if scale == 1.0 { 1.0 } else { 1.0 / scale }; + + let physical_size = PhySize { + width: (logical_size.width * scale).round() as u32, + height: (logical_size.height * scale).round() as u32, }; Self { @@ -31,18 +26,12 @@ impl WindowInfo { } } - pub fn from_physical_size(physical_size: Size, scale: f64) -> Self { - let (scale_recip, logical_size) = if scale == 1.0 { - (1.0, physical_size) - } else { - let scale_recip = 1.0 / scale; - ( - scale_recip, - Size { - width: (physical_size.width as f64 * scale_recip).round() as u32, - height: (physical_size.height as f64 * scale_recip).round() as u32, - } - ) + pub fn from_physical_size(physical_size: PhySize, scale: f64) -> Self { + let scale_recip = if scale == 1.0 { 1.0 } else { 1.0 / scale }; + + let logical_size = Size { + width: f64::from(physical_size.width) * scale_recip, + height: f64::from(physical_size.height) * scale_recip, }; Self { @@ -59,7 +48,7 @@ impl WindowInfo { } /// The physical size of the window - pub fn physical_size(&self) -> Size { + pub fn physical_size(&self) -> PhySize { self.physical_size } @@ -68,19 +57,8 @@ impl WindowInfo { self.scale } - /// Convert physical coordinates to logical coordinates - pub fn physical_to_logical(&self, physical: Point) -> Point { - Point { - x: physical.x * self.scale_recip, - y: physical.y * self.scale_recip - } - } - - /// Convert logical coordinates to physical coordinates - pub fn logical_to_physical(&self, logical: Point) -> Point { - Point { - x: logical.x * self.scale, - y: logical.y * self.scale - } + /// The reciprocal of the scale factor of the window + pub fn scale_recip(&self) -> f64 { + self.scale_recip } } \ No newline at end of file diff --git a/src/window_open_options.rs b/src/window_open_options.rs index ef30b25..08409df 100644 --- a/src/window_open_options.rs +++ b/src/window_open_options.rs @@ -1,4 +1,4 @@ -use crate::{WindowInfo, Parent, Size}; +use crate::{WindowInfo, Parent, Size, PhySize}; /// The size of the window #[derive(Debug)] @@ -6,7 +6,7 @@ pub enum WindowSize { /// Use logical width and height Logical(Size), /// Use physical width and height - Physical(Size), + Physical(PhySize), /// Use minimum and maximum logical width and height MinMaxLogical { /// The initial logical width and height @@ -21,11 +21,11 @@ pub enum WindowSize { /// Use minimum and maximum physical width and height MinMaxPhysical { /// The initial physical width and height - initial_size: Size, + initial_size: PhySize, /// The minimum physical width and height - min_size: Size, + min_size: PhySize, /// The maximum physical width and height - max_size: Size, + max_size: PhySize, /// Whether to keep the aspect ratio when resizing (true), or not (false) keep_aspect: bool, },