1
0
Fork 0

refactor and modify events

This commit is contained in:
Billy Messenger 2020-10-17 13:35:39 -05:00
parent a4c226277c
commit 1b9fbf9bb8
7 changed files with 195 additions and 84 deletions

View file

@ -1,4 +1,4 @@
use baseview::{Event, Window, WindowHandler}; use baseview::{Event, Window, WindowHandler, WindowSize, WindowScalePolicy};
struct MyProgram {} struct MyProgram {}
@ -25,9 +25,13 @@ impl WindowHandler for MyProgram {
fn main() { fn main() {
let window_open_options = baseview::WindowOpenOptions { let window_open_options = baseview::WindowOpenOptions {
title: "baseview".into(), title: "baseview".into(),
logical_size: (512, 512), size: WindowSize::MinMaxLogical {
resize: baseview::WindowResize::None, initial_size: (512, 512),
scale: 1.0, min_size: (200, 200),
max_size: (1024, 1024),
keep_aspect: false,
},
scale: WindowScalePolicy::TrySystemScaleFactor,
parent: baseview::Parent::None, parent: baseview::Parent::None,
}; };

View file

@ -41,18 +41,28 @@ pub enum ScrollDelta {
pub struct MouseClick { pub struct MouseClick {
pub button: MouseButton, pub button: MouseButton,
pub click_count: usize, pub click_count: usize,
pub x: i32, /// The logical X coordinate of the mouse position
pub y: i32, logical_x: i32,
/// The logical Y coordinate of the mouse position
logical_y: 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 X coordinate of the mouse position /// The logical X coordinate of the mouse position
x: i32, logical_x: i32,
/// The Y coordinate of the mouse position /// The logical Y coordinate of the mouse position
y: i32, logical_y: 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.
@ -74,7 +84,7 @@ pub enum MouseEvent {
CursorLeft, CursorLeft,
} }
#[derive(Debug, Copy, Clone, PartialEq)] #[derive(Debug)]
pub enum WindowEvent { pub enum WindowEvent {
Resized(WindowInfo), Resized(WindowInfo),
Focused, Focused,

View file

@ -19,11 +19,14 @@ mod event;
mod keyboard; mod keyboard;
mod mouse_cursor; mod mouse_cursor;
mod window_info; mod window_info;
mod window_open_options;
pub use event::*; pub use event::*;
pub use keyboard::*; pub use keyboard::*;
pub use mouse_cursor::MouseCursor; pub use mouse_cursor::MouseCursor;
pub use window_info::WindowInfo; pub use window_info::WindowInfo;
pub use window_open_options::*;
#[derive(Debug)]
pub enum Parent { pub enum Parent {
None, None,
AsIfParented, AsIfParented,
@ -32,30 +35,6 @@ pub enum Parent {
unsafe impl Send for Parent {} unsafe impl Send for Parent {}
pub enum WindowResize {
None,
MinMax {
min_logical_size: (u32, u32),
max_logical_size: (u32, u32),
keep_aspect: bool,
},
}
pub struct WindowOpenOptions {
pub title: String,
/// The logical width and height of the window
pub logical_size: (u32, u32),
pub resize: WindowResize,
/// The dpi scale factor. This will used in conjunction with the dpi scale
/// factor of the system.
pub scale: f64,
pub parent: Parent,
}
pub struct WindowHandle { pub struct WindowHandle {
thread: std::thread::JoinHandle<()>, thread: std::thread::JoinHandle<()>,
} }

View file

@ -1,5 +1,5 @@
/// The info about the window /// The info about the window
#[derive(Debug, Copy, Clone, PartialEq)] #[derive(Debug, Copy, Clone)]
pub struct WindowInfo { pub struct WindowInfo {
/// The physical the width of the window /// The physical the width of the window
physical_width: u32, physical_width: u32,
@ -66,11 +66,19 @@ impl WindowInfo {
self.scale self.scale
} }
/// Convert physical mouse 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, x: f64, y: f64) -> (f64, f64) {
( (
x * self.scale_recip, x * self.scale_recip,
y * self.scale_recip y * self.scale_recip
) )
} }
/// Convert logicalcoordinates to physical coordinates
pub fn logical_to_physical(&self, x: f64, y: f64) -> (f64, f64) {
(
x * self.scale,
y * self.scale
)
}
} }

View file

@ -0,0 +1,74 @@
use crate::{WindowInfo, Parent};
/// The size of the window
#[derive(Debug)]
pub enum WindowSize {
/// Use logical width and height
Logical(u32, u32),
/// Use physical width and height
Physical(u32, u32),
/// Use minimum and maximum logical width and height
MinMaxLogical {
/// The initial logical width and height
initial_size: (u32, u32),
/// The minimum logical width and height
min_size: (u32, u32),
/// The maximum logical width and height
max_size: (u32, u32),
/// Whether to keep the aspect ratio when resizing (true), or not (false)
keep_aspect: bool,
},
/// Use minimum and maximum physical width and height
MinMaxPhysical {
/// The initial physical width and height
initial_size: (u32, u32),
/// The minimum physical width and height
min_size: (u32, u32),
/// The maximum physical width and height
max_size: (u32, u32),
/// Whether to keep the aspect ratio when resizing (true), or not (false)
keep_aspect: bool,
},
}
/// The dpi scaling policy of the window
#[derive(Debug)]
pub enum WindowScalePolicy {
/// Try using the system scale factor
TrySystemScaleFactor,
/// Try using the system scale factor in addition to the given scale factor
TrySystemScaleFactorTimes(f64),
/// Use the given scale factor
UseScaleFactor(f64),
/// No scaling
NoScaling,
}
/// The options for opening a new window
#[derive(Debug)]
pub struct WindowOpenOptions {
pub title: String,
/// The size information about the window
pub size: WindowSize,
/// The scaling of the window
pub scale: WindowScalePolicy,
pub parent: Parent,
}
impl WindowOpenOptions {
pub(crate) fn window_info_from_scale(&self, scale: f64) -> WindowInfo {
match self.size {
WindowSize::Logical(w, h) => WindowInfo::from_logical_size(w, h, scale),
WindowSize::Physical(w, h) => WindowInfo::from_physical_size(w, h, scale),
WindowSize::MinMaxLogical { initial_size, .. } => {
WindowInfo::from_logical_size(initial_size.0, initial_size.1, scale)
},
WindowSize::MinMaxPhysical { initial_size, .. } => {
WindowInfo::from_logical_size(initial_size.0, initial_size.1, scale)
}
}
}
}

View file

@ -12,7 +12,8 @@ use raw_window_handle::{
use super::XcbConnection; 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, WindowResize, WindowHandle, WindowHandler, WindowInfo, WindowOpenOptions, WindowOpenResult,
WindowScalePolicy,
}; };
pub struct Window { pub struct Window {
@ -79,14 +80,16 @@ impl Window {
], ],
); );
let scaling = xcb_connection.get_scaling().unwrap_or(1.0) * options.scale; let scaling = match options.scale {
WindowScalePolicy::TrySystemScaleFactor =>
xcb_connection.get_scaling().unwrap_or(1.0),
WindowScalePolicy::TrySystemScaleFactorTimes(user_scale) =>
xcb_connection.get_scaling().unwrap_or(1.0) * user_scale,
WindowScalePolicy::UseScaleFactor(user_scale) => user_scale,
WindowScalePolicy::NoScaling => 1.0,
};
let (logical_width, logical_height) = options.logical_size; let window_info = options.window_info_from_scale(scaling);
let window_info = WindowInfo::from_logical_size(
logical_width,
logical_height,
scaling
);
let window_id = xcb_connection.conn.generate_id(); let window_id = xcb_connection.conn.generate_id();
xcb::create_window( xcb::create_window(
@ -127,42 +130,6 @@ impl Window {
title.as_bytes(), title.as_bytes(),
); );
match options.resize {
WindowResize::MinMax { min_logical_size, max_logical_size, keep_aspect } => {
let min_physical_width = (min_logical_size.0 as f64 * scaling).round() as i32;
let min_physical_height = (min_logical_size.1 as f64 * scaling).round() as i32;
let max_physical_width = (max_logical_size.0 as f64 * scaling).round() as i32;
let max_physical_height = (max_logical_size.1 as f64 * scaling).round() as i32;
let size_hints = if keep_aspect {
xcb_util::icccm::SizeHints::empty()
.min_size(min_physical_width, min_physical_height)
.max_size(max_physical_width, max_physical_height)
.aspect(
(min_physical_width, min_physical_height),
(max_physical_width, max_physical_height),
)
.build()
} else {
xcb_util::icccm::SizeHints::empty()
.min_size(min_physical_width, min_physical_height)
.max_size(max_physical_width, max_physical_height)
.build()
};
xcb_connection.atoms.wm_normal_hints
.map(|wm_normal_hints| {
xcb_util::icccm::set_wm_size_hints(
&xcb_connection.conn,
window_id,
wm_normal_hints,
&size_hints,
);
});
}
_ => {}
}
xcb_connection.atoms.wm_protocols xcb_connection.atoms.wm_protocols
.zip(xcb_connection.atoms.wm_delete_window) .zip(xcb_connection.atoms.wm_delete_window)
.map(|(wm_protocols, wm_delete_window)| { .map(|(wm_protocols, wm_delete_window)| {
@ -174,6 +141,8 @@ impl Window {
); );
}); });
xcb_connection.set_resize_policy(window_id, &options.size, scaling);
xcb_connection.conn.flush(); xcb_connection.conn.flush();
let mut window = Self { let mut window = Self {
@ -363,8 +332,10 @@ impl Window {
handler.on_event( handler.on_event(
self, self,
Event::Mouse(MouseEvent::CursorMoved { Event::Mouse(MouseEvent::CursorMoved {
x: logical_x.round() as i32, logical_x: logical_x.round() as i32,
y: logical_y.round() as i32, logical_y: logical_y.round() as i32,
physical_x: event.event_x() as i32,
physical_y: event.event_y() as i32,
}), }),
); );
} }

View file

@ -5,7 +5,7 @@
use std::ffi::{CStr, CString}; use std::ffi::{CStr, CString};
use std::collections::HashMap; use std::collections::HashMap;
use crate::MouseCursor; use crate::{MouseCursor, WindowSize};
use super::cursor; use super::cursor;
@ -154,4 +154,69 @@ impl XcbConnection {
.entry(cursor) .entry(cursor)
.or_insert_with(|| cursor::get_xcursor(dpy, cursor)) .or_insert_with(|| cursor::get_xcursor(dpy, cursor))
} }
pub fn set_resize_policy(&self, window_id: u32, size: &WindowSize, scale: f64) {
match size {
WindowSize::MinMaxLogical { min_size, max_size, keep_aspect, .. } => {
let min_physical_width = (min_size.0 as f64 * scale).round() as i32;
let min_physical_height = (min_size.1 as f64 * scale).round() as i32;
let max_physical_width = (max_size.0 as f64 * scale).round() as i32;
let max_physical_height = (max_size.1 as f64 * scale).round() as i32;
let size_hints = if *keep_aspect {
xcb_util::icccm::SizeHints::empty()
.min_size(min_physical_width, min_physical_height)
.max_size(max_physical_width, max_physical_height)
.aspect(
(min_physical_width, min_physical_height),
(max_physical_width, max_physical_height),
)
.build()
} else {
xcb_util::icccm::SizeHints::empty()
.min_size(min_physical_width, min_physical_height)
.max_size(max_physical_width, max_physical_height)
.build()
};
self.atoms.wm_normal_hints
.map(|wm_normal_hints| {
xcb_util::icccm::set_wm_size_hints(
&self.conn,
window_id,
wm_normal_hints,
&size_hints,
);
});
}
WindowSize::MinMaxPhysical { min_size, max_size, keep_aspect, .. } => {
let size_hints = if *keep_aspect {
xcb_util::icccm::SizeHints::empty()
.min_size(min_size.0 as i32, min_size.1 as i32)
.max_size(max_size.0 as i32, max_size.1 as i32)
.aspect(
(min_size.0 as i32, min_size.1 as i32),
(max_size.0 as i32, max_size.1 as i32),
)
.build()
} else {
xcb_util::icccm::SizeHints::empty()
.min_size(min_size.0 as i32, min_size.1 as i32)
.max_size(max_size.0 as i32, max_size.1 as i32)
.build()
};
self.atoms.wm_normal_hints
.map(|wm_normal_hints| {
xcb_util::icccm::set_wm_size_hints(
&self.conn,
window_id,
wm_normal_hints,
&size_hints,
);
});
}
_ => {}
}
}
} }