1
0
Fork 0

Add Point and Size structs

This commit is contained in:
Billy Messenger 2020-10-17 14:01:03 -05:00
parent 1b9fbf9bb8
commit dc5d3b9622
7 changed files with 110 additions and 107 deletions

View file

@ -26,9 +26,9 @@ fn main() {
let window_open_options = baseview::WindowOpenOptions { let window_open_options = baseview::WindowOpenOptions {
title: "baseview".into(), title: "baseview".into(),
size: WindowSize::MinMaxLogical { size: WindowSize::MinMaxLogical {
initial_size: (512, 512), initial_size: baseview::Size::new(512, 512),
min_size: (200, 200), min_size: baseview::Size::new(200, 200),
max_size: (1024, 1024), max_size: baseview::Size::new(1024, 1024),
keep_aspect: false, keep_aspect: false,
}, },
scale: WindowScalePolicy::TrySystemScaleFactor, scale: WindowScalePolicy::TrySystemScaleFactor,

View file

@ -1,4 +1,4 @@
use crate::WindowInfo; use crate::{WindowInfo, Point};
#[derive(Debug, Clone, Copy, PartialEq)] #[derive(Debug, Clone, Copy, PartialEq)]
pub enum KeyboardEvent { pub enum KeyboardEvent {
@ -41,28 +41,20 @@ pub enum ScrollDelta {
pub struct MouseClick { pub struct MouseClick {
pub button: MouseButton, pub button: MouseButton,
pub click_count: usize, pub click_count: usize,
/// The logical X coordinate of the mouse position /// The logical coordinates of the mouse position
logical_x: i32, logical_pos: Point<i32>,
/// The logical Y coordinate of the mouse position /// The physical coordinates of the mouse position
logical_y: i32, physical_pos: Point<i32>,
/// The physical X coordinate of the mouse position
physical_x: i32,
/// The physical Y coordinate of the mouse position
physical_y: i32,
} }
#[derive(Debug, Clone, Copy, PartialEq)] #[derive(Debug, Clone, Copy, PartialEq)]
pub enum MouseEvent { pub enum MouseEvent {
/// The mouse cursor was moved /// The mouse cursor was moved
CursorMoved { CursorMoved {
/// The logical X coordinate of the mouse position /// The logical coordinates of the mouse position
logical_x: i32, logical_pos: Point<i32>,
/// The logical Y coordinate of the mouse position /// The physical coordinates of the mouse position
logical_y: i32, physical_pos: Point<i32>,
/// The physical X coordinate of the mouse position
physical_x: i32,
/// The physical Y coordinate of the mouse position
physical_y: i32,
}, },
/// A mouse button was pressed. /// A mouse button was pressed.

View file

@ -45,6 +45,36 @@ impl WindowHandle {
} }
} }
#[derive(Debug, Copy, Clone, PartialEq)]
pub struct Point<T> {
pub x: T,
pub y: T,
}
impl<T> Point<T> {
pub fn new(x: T, y: T) -> Self {
Self { x, y }
}
}
impl From<Point<f64>> for Point<i32> {
fn from(p: Point<f64>) -> Point<i32> {
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<WindowInfo, ()>; type WindowOpenResult = Result<WindowInfo, ()>;
pub trait WindowHandler { pub trait WindowHandler {

View file

@ -1,64 +1,51 @@
use crate::{Size, Point};
/// The info about the window /// The info about the window
#[derive(Debug, Copy, Clone)] #[derive(Debug, Copy, Clone)]
pub struct WindowInfo { pub struct WindowInfo {
/// The physical the width of the window logical_size: Size,
physical_width: u32, physical_size: Size,
/// The physical height of the window
physical_height: u32,
/// The logical width of the window
logical_width: u32,
/// The logical height of the window
logical_height: u32,
/// The scale factor
scale: f64, scale: f64,
scale_recip: f64, scale_recip: f64,
} }
impl WindowInfo { impl WindowInfo {
pub fn from_logical_size(logical_width: u32, logical_height: u32, scale: f64) -> Self { pub fn from_logical_size(logical_size: Size, scale: f64) -> Self {
let scale_recip = 1.0 / scale; let scale_recip = 1.0 / scale;
Self { Self {
physical_width: (logical_width as f64 * scale).round() as u32, logical_size,
physical_height: (logical_height as f64 * scale).round() as u32, physical_size: Size {
logical_width, width: (logical_size.width as f64 * scale).round() as u32,
logical_height, height: (logical_size.height as f64 * scale).round() as u32,
},
scale, scale,
scale_recip, scale_recip,
} }
} }
pub fn from_physical_size(physical_width: u32, physical_height: u32, scale: f64) -> Self { pub fn from_physical_size(physical_size: Size, scale: f64) -> Self {
let scale_recip = 1.0 / scale; let scale_recip = 1.0 / scale;
Self { Self {
physical_width, logical_size: Size {
physical_height, width: (physical_size.width as f64 * scale_recip).round() as u32,
logical_width: (physical_width as f64 * scale_recip).round() as u32, height: (physical_size.height as f64 * scale_recip).round() as u32,
logical_height: (physical_height as f64 * scale_recip).round() as u32, },
physical_size,
scale, scale,
scale_recip, scale_recip,
} }
} }
/// The physical width of the window /// The logical size of the window
pub fn physical_width(&self) -> u32 { pub fn logical_size(&self) -> Size {
self.physical_width self.logical_size
} }
/// The physical height of the window /// The physical size of the window
pub fn physical_height(&self) -> u32 { pub fn physical_size(&self) -> Size {
self.physical_height self.physical_size
}
/// The logical width of the window
pub fn logical_width(&self) -> u32 {
self.logical_width
}
/// The logical height of the window
pub fn logical_height(&self) -> u32 {
self.logical_height
} }
/// The scale factor of the window /// The scale factor of the window
@ -67,18 +54,18 @@ impl WindowInfo {
} }
/// Convert physical coordinates to logical coordinates /// Convert physical coordinates to logical coordinates
pub fn physical_to_logical(&self, x: f64, y: f64) -> (f64, f64) { pub fn physical_to_logical(&self, physical: Point<f64>) -> Point<f64> {
( Point {
x * self.scale_recip, x: physical.x * self.scale_recip,
y * self.scale_recip y: physical.y * self.scale_recip
) }
} }
/// Convert logical coordinates to physical coordinates /// Convert logical coordinates to physical coordinates
pub fn logical_to_physical(&self, x: f64, y: f64) -> (f64, f64) { pub fn logical_to_physical(&self, logical: Point<f64>) -> Point<f64> {
( Point {
x * self.scale, x: logical.x * self.scale,
y * self.scale y: logical.y * self.scale
) }
} }
} }

View file

@ -1,31 +1,31 @@
use crate::{WindowInfo, Parent}; use crate::{WindowInfo, Parent, Size};
/// The size of the window /// The size of the window
#[derive(Debug)] #[derive(Debug)]
pub enum WindowSize { pub enum WindowSize {
/// Use logical width and height /// Use logical width and height
Logical(u32, u32), Logical(Size),
/// Use physical width and height /// Use physical width and height
Physical(u32, u32), Physical(Size),
/// Use minimum and maximum logical width and height /// Use minimum and maximum logical width and height
MinMaxLogical { MinMaxLogical {
/// The initial logical width and height /// The initial logical width and height
initial_size: (u32, u32), initial_size: Size,
/// The minimum logical width and height /// The minimum logical width and height
min_size: (u32, u32), min_size: Size,
/// The maximum logical width and height /// The maximum logical width and height
max_size: (u32, u32), max_size: Size,
/// Whether to keep the aspect ratio when resizing (true), or not (false) /// Whether to keep the aspect ratio when resizing (true), or not (false)
keep_aspect: bool, keep_aspect: bool,
}, },
/// Use minimum and maximum physical width and height /// Use minimum and maximum physical width and height
MinMaxPhysical { MinMaxPhysical {
/// The initial physical width and height /// The initial physical width and height
initial_size: (u32, u32), initial_size: Size,
/// The minimum physical width and height /// The minimum physical width and height
min_size: (u32, u32), min_size: Size,
/// The maximum physical width and height /// The maximum physical width and height
max_size: (u32, u32), max_size: Size,
/// Whether to keep the aspect ratio when resizing (true), or not (false) /// Whether to keep the aspect ratio when resizing (true), or not (false)
keep_aspect: bool, keep_aspect: bool,
}, },
@ -61,13 +61,13 @@ pub struct WindowOpenOptions {
impl WindowOpenOptions { impl WindowOpenOptions {
pub(crate) fn window_info_from_scale(&self, scale: f64) -> WindowInfo { pub(crate) fn window_info_from_scale(&self, scale: f64) -> WindowInfo {
match self.size { match self.size {
WindowSize::Logical(w, h) => WindowInfo::from_logical_size(w, h, scale), WindowSize::Logical(size) => WindowInfo::from_logical_size(size, scale),
WindowSize::Physical(w, h) => WindowInfo::from_physical_size(w, h, scale), WindowSize::Physical(size) => WindowInfo::from_physical_size(size, scale),
WindowSize::MinMaxLogical { initial_size, .. } => { WindowSize::MinMaxLogical { initial_size, .. } => {
WindowInfo::from_logical_size(initial_size.0, initial_size.1, scale) WindowInfo::from_logical_size(initial_size, scale)
}, },
WindowSize::MinMaxPhysical { initial_size, .. } => { WindowSize::MinMaxPhysical { initial_size, .. } => {
WindowInfo::from_logical_size(initial_size.0, initial_size.1, scale) WindowInfo::from_logical_size(initial_size, scale)
} }
} }
} }

View file

@ -13,7 +13,7 @@ use super::XcbConnection;
use crate::{ use crate::{
Event, KeyboardEvent, MouseButton, MouseCursor, MouseEvent, Parent, ScrollDelta, WindowEvent, Event, KeyboardEvent, MouseButton, MouseCursor, MouseEvent, Parent, ScrollDelta, WindowEvent,
WindowHandle, WindowHandler, WindowInfo, WindowOpenOptions, WindowOpenResult, WindowHandle, WindowHandler, WindowInfo, WindowOpenOptions, WindowOpenResult,
WindowScalePolicy, WindowScalePolicy, Size, Point,
}; };
pub struct Window { pub struct Window {
@ -25,7 +25,7 @@ pub struct Window {
frame_interval: Duration, frame_interval: Duration,
event_loop_running: bool, event_loop_running: bool,
new_physical_size: Option<(u32, u32)> new_physical_size: Option<Size>
} }
impl Window { impl Window {
@ -99,8 +99,8 @@ impl Window {
parent_id, parent_id,
0, // x coordinate of the new window 0, // x coordinate of the new window
0, // y coordinate of the new window 0, // y coordinate of the new window
window_info.physical_width() as u16, // window width window_info.physical_size().width as u16, // window width
window_info.physical_height() as u16, // window height window_info.physical_size().height as u16, // window height
0, // window border 0, // window border
xcb::WINDOW_CLASS_INPUT_OUTPUT as u16, xcb::WINDOW_CLASS_INPUT_OUTPUT as u16,
screen.root_visual(), screen.root_visual(),
@ -200,10 +200,9 @@ impl Window {
self.handle_xcb_event(handler, event); self.handle_xcb_event(handler, event);
} }
if let Some((width, height)) = self.new_physical_size.take() { if let Some(size) = self.new_physical_size.take() {
self.window_info = WindowInfo::from_physical_size( self.window_info = WindowInfo::from_physical_size(
width, size,
height,
self.window_info.scale() self.window_info.scale()
); );
@ -308,10 +307,9 @@ impl Window {
xcb::CONFIGURE_NOTIFY => { xcb::CONFIGURE_NOTIFY => {
let event = unsafe { xcb::cast_event::<xcb::ConfigureNotifyEvent>(&event) }; let event = unsafe { xcb::cast_event::<xcb::ConfigureNotifyEvent>(&event) };
let new_physical_size = (event.width() as u32, event.height() as u32); let new_physical_size = Size::new(event.width() as u32, event.height() as u32);
let cur_physical_size = (self.window_info.physical_width(), self.window_info.physical_height());
if self.new_physical_size.is_some() || new_physical_size != cur_physical_size { if self.new_physical_size.is_some() || new_physical_size != self.window_info.physical_size() {
self.new_physical_size = Some(new_physical_size); self.new_physical_size = Some(new_physical_size);
} }
} }
@ -324,18 +322,14 @@ impl Window {
let detail = event.detail(); let detail = event.detail();
if detail != 4 && detail != 5 { if detail != 4 && detail != 5 {
let (logical_x, logical_y) = self.window_info.physical_to_logical( let physical_pos = Point::new(event.event_x() as f64, event.event_y() as f64);
event.event_x() as f64, let logical_pos = self.window_info.physical_to_logical(physical_pos);
event.event_y() as f64
);
handler.on_event( handler.on_event(
self, self,
Event::Mouse(MouseEvent::CursorMoved { Event::Mouse(MouseEvent::CursorMoved {
logical_x: logical_x.round() as i32, logical_pos: logical_pos.into(),
logical_y: logical_y.round() as i32, physical_pos: physical_pos.into(),
physical_x: event.event_x() as i32,
physical_y: event.event_y() as i32,
}), }),
); );
} }

View file

@ -158,10 +158,10 @@ impl XcbConnection {
pub fn set_resize_policy(&self, window_id: u32, size: &WindowSize, scale: f64) { pub fn set_resize_policy(&self, window_id: u32, size: &WindowSize, scale: f64) {
match size { match size {
WindowSize::MinMaxLogical { min_size, max_size, keep_aspect, .. } => { WindowSize::MinMaxLogical { min_size, max_size, keep_aspect, .. } => {
let min_physical_width = (min_size.0 as f64 * scale).round() as i32; let min_physical_width = (min_size.width as f64 * scale).round() as i32;
let min_physical_height = (min_size.1 as f64 * scale).round() as i32; let min_physical_height = (min_size.height as f64 * scale).round() as i32;
let max_physical_width = (max_size.0 as f64 * scale).round() as i32; let max_physical_width = (max_size.width as f64 * scale).round() as i32;
let max_physical_height = (max_size.1 as f64 * scale).round() as i32; let max_physical_height = (max_size.height as f64 * scale).round() as i32;
let size_hints = if *keep_aspect { let size_hints = if *keep_aspect {
xcb_util::icccm::SizeHints::empty() xcb_util::icccm::SizeHints::empty()
@ -192,17 +192,17 @@ impl XcbConnection {
WindowSize::MinMaxPhysical { min_size, max_size, keep_aspect, .. } => { WindowSize::MinMaxPhysical { min_size, max_size, keep_aspect, .. } => {
let size_hints = if *keep_aspect { let size_hints = if *keep_aspect {
xcb_util::icccm::SizeHints::empty() xcb_util::icccm::SizeHints::empty()
.min_size(min_size.0 as i32, min_size.1 as i32) .min_size(min_size.width as i32, min_size.height as i32)
.max_size(max_size.0 as i32, max_size.1 as i32) .max_size(max_size.width as i32, max_size.height as i32)
.aspect( .aspect(
(min_size.0 as i32, min_size.1 as i32), (min_size.width as i32, min_size.height as i32),
(max_size.0 as i32, max_size.1 as i32), (max_size.width as i32, max_size.height as i32),
) )
.build() .build()
} else { } else {
xcb_util::icccm::SizeHints::empty() xcb_util::icccm::SizeHints::empty()
.min_size(min_size.0 as i32, min_size.1 as i32) .min_size(min_size.width as i32, min_size.height as i32)
.max_size(max_size.0 as i32, max_size.1 as i32) .max_size(max_size.width as i32, max_size.height as i32)
.build() .build()
}; };