refactor and modify events
This commit is contained in:
parent
a4c226277c
commit
1b9fbf9bb8
|
@ -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,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
24
src/event.rs
24
src/event.rs
|
@ -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,
|
||||||
|
|
27
src/lib.rs
27
src/lib.rs
|
@ -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<()>,
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
74
src/window_open_options.rs
Normal file
74
src/window_open_options.rs
Normal 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)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -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,
|
||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -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,
|
||||||
|
);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue