commit
b57fd5db85
|
@ -1,4 +1,4 @@
|
|||
use baseview::{Event, Window, WindowHandler};
|
||||
use baseview::{Event, Window, WindowHandler, WindowSize, WindowScalePolicy};
|
||||
|
||||
struct OpenWindowExample;
|
||||
|
||||
|
@ -21,8 +21,8 @@ impl WindowHandler for OpenWindowExample {
|
|||
fn main() {
|
||||
let window_open_options = baseview::WindowOpenOptions {
|
||||
title: "baseview".into(),
|
||||
width: 512,
|
||||
height: 512,
|
||||
size: WindowSize::Logical(baseview::Size::new(512.0, 512.0)),
|
||||
scale: WindowScalePolicy::TrySystemScaleFactor,
|
||||
parent: baseview::Parent::None,
|
||||
};
|
||||
|
||||
|
|
21
src/event.rs
21
src/event.rs
|
@ -1,3 +1,5 @@
|
|||
use crate::{WindowInfo, Point};
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq)]
|
||||
pub enum KeyboardEvent {
|
||||
KeyPressed(u32),
|
||||
|
@ -39,18 +41,16 @@ pub enum ScrollDelta {
|
|||
pub struct MouseClick {
|
||||
pub button: MouseButton,
|
||||
pub click_count: usize,
|
||||
pub x: i32,
|
||||
pub y: i32,
|
||||
/// The logical coordinates of the mouse position
|
||||
pub position: Point,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq)]
|
||||
pub enum MouseEvent {
|
||||
/// The mouse cursor was moved
|
||||
CursorMoved {
|
||||
/// The X coordinate of the mouse position
|
||||
x: i32,
|
||||
/// The Y coordinate of the mouse position
|
||||
y: i32,
|
||||
/// The logical coordinates of the mouse position
|
||||
position: Point,
|
||||
},
|
||||
|
||||
/// A mouse button was pressed.
|
||||
|
@ -72,14 +72,7 @@ pub enum MouseEvent {
|
|||
CursorLeft,
|
||||
}
|
||||
|
||||
#[derive(Debug, Copy, Clone, PartialEq)]
|
||||
pub struct WindowInfo {
|
||||
pub width: u32,
|
||||
pub height: u32,
|
||||
pub scale: f64,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq)]
|
||||
#[derive(Debug)]
|
||||
pub enum WindowEvent {
|
||||
Resized(WindowInfo),
|
||||
Focused,
|
||||
|
|
14
src/lib.rs
14
src/lib.rs
|
@ -18,10 +18,15 @@ pub use macos::*;
|
|||
mod event;
|
||||
mod keyboard;
|
||||
mod mouse_cursor;
|
||||
mod window_info;
|
||||
mod window_open_options;
|
||||
pub use event::*;
|
||||
pub use keyboard::*;
|
||||
pub use mouse_cursor::MouseCursor;
|
||||
pub use window_info::*;
|
||||
pub use window_open_options::*;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum Parent {
|
||||
None,
|
||||
AsIfParented,
|
||||
|
@ -30,15 +35,6 @@ pub enum Parent {
|
|||
|
||||
unsafe impl Send for Parent {}
|
||||
|
||||
pub struct WindowOpenOptions {
|
||||
pub title: String,
|
||||
|
||||
pub width: usize,
|
||||
pub height: usize,
|
||||
|
||||
pub parent: Parent,
|
||||
}
|
||||
|
||||
pub trait WindowHandler {
|
||||
type Message;
|
||||
|
||||
|
|
|
@ -12,7 +12,7 @@ use raw_window_handle::{macos::MacOSHandle, HasRawWindowHandle, RawWindowHandle}
|
|||
|
||||
use crate::{
|
||||
Event, KeyboardEvent, MouseButton, MouseEvent, ScrollDelta, WindowEvent, WindowHandler,
|
||||
WindowOpenOptions,
|
||||
WindowOpenOptions, WindowScalePolicy,
|
||||
};
|
||||
|
||||
pub struct Window {
|
||||
|
@ -41,9 +41,22 @@ impl Window {
|
|||
unsafe {
|
||||
let _pool = NSAutoreleasePool::new(nil);
|
||||
|
||||
let scaling = match options.scale {
|
||||
// TODO: Find system scale factor
|
||||
WindowScalePolicy::TrySystemScaleFactor => get_scaling().unwrap_or(1.0),
|
||||
WindowScalePolicy::TrySystemScaleFactorTimes(user_scale) => get_scaling().unwrap_or(1.0) * user_scale,
|
||||
WindowScalePolicy::UseScaleFactor(user_scale) => user_scale,
|
||||
WindowScalePolicy::NoScaling => 1.0,
|
||||
};
|
||||
|
||||
let window_info = options.window_info_from_scale(scaling);
|
||||
|
||||
let rect = NSRect::new(
|
||||
NSPoint::new(0.0, 0.0),
|
||||
NSSize::new(options.width as f64, options.height as f64),
|
||||
NSSize::new(
|
||||
window_info.logical_size().width as f64,
|
||||
window_info.logical_size().height as f64
|
||||
),
|
||||
);
|
||||
|
||||
let ns_window = NSWindow::alloc(nil)
|
||||
|
@ -83,3 +96,8 @@ unsafe impl HasRawWindowHandle for Window {
|
|||
})
|
||||
}
|
||||
}
|
||||
|
||||
fn get_scaling() -> Option<f64> {
|
||||
// TODO: find system scaling
|
||||
None
|
||||
}
|
||||
|
|
|
@ -8,7 +8,7 @@ use winapi::um::winuser::{
|
|||
SetWindowLongPtrA, TranslateMessage, UnregisterClassA, CS_OWNDC, GWLP_USERDATA, MB_ICONERROR,
|
||||
MB_OK, MB_TOPMOST, MSG, WM_CLOSE, WM_CREATE, WM_MOUSEMOVE, WM_PAINT, WM_SHOWWINDOW, WM_TIMER,
|
||||
WNDCLASSA, WS_CAPTION, WS_CHILD, WS_CLIPSIBLINGS, WS_MAXIMIZEBOX, WS_MINIMIZEBOX,
|
||||
WS_POPUPWINDOW, WS_SIZEBOX, WS_VISIBLE,
|
||||
WS_POPUPWINDOW, WS_SIZEBOX, WS_VISIBLE, WM_DPICHANGED,
|
||||
};
|
||||
|
||||
use std::cell::RefCell;
|
||||
|
@ -24,7 +24,7 @@ use raw_window_handle::{
|
|||
|
||||
use crate::{
|
||||
Event, KeyboardEvent, MouseButton, MouseEvent, Parent::WithParent, ScrollDelta, WindowEvent,
|
||||
WindowHandler, WindowInfo, WindowOpenOptions,
|
||||
WindowHandler, WindowInfo, WindowOpenOptions, WindowScalePolicy, Size, Point, PhySize, PhyPoint,
|
||||
};
|
||||
|
||||
unsafe fn message_box(title: &str, msg: &str) {
|
||||
|
@ -78,11 +78,17 @@ unsafe extern "system" fn wnd_proc<H: WindowHandler>(
|
|||
WM_MOUSEMOVE => {
|
||||
let x = (lparam & 0xFFFF) as i32;
|
||||
let y = ((lparam >> 16) & 0xFFFF) as i32;
|
||||
window_state.borrow_mut().handler.on_event(
|
||||
|
||||
let physical_pos = PhyPoint { x, y };
|
||||
|
||||
let mut window_state = window_state.borrow_mut();
|
||||
|
||||
let logical_pos = physical_pos.to_logical(&window_state.window_info);
|
||||
|
||||
window_state.handler.on_event(
|
||||
&mut window,
|
||||
Event::Mouse(MouseEvent::CursorMoved {
|
||||
x: x as i32,
|
||||
y: y as i32,
|
||||
position: logical_pos,
|
||||
}),
|
||||
);
|
||||
return 0;
|
||||
|
@ -101,6 +107,9 @@ unsafe extern "system" fn wnd_proc<H: WindowHandler>(
|
|||
.on_event(&mut window, Event::Window(WindowEvent::WillClose));
|
||||
return DefWindowProcA(hwnd, msg, wparam, lparam);
|
||||
}
|
||||
WM_DPICHANGED => {
|
||||
// TODO: Notify app of DPI change
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
|
@ -134,7 +143,7 @@ unsafe fn unregister_wnd_class(wnd_class: ATOM) {
|
|||
|
||||
struct WindowState<H> {
|
||||
window_class: ATOM,
|
||||
scaling: Option<f64>, // DPI scale, 96.0 is "default".
|
||||
window_info: WindowInfo,
|
||||
handler: H,
|
||||
}
|
||||
|
||||
|
@ -184,13 +193,23 @@ impl Window {
|
|||
| WS_MINIMIZEBOX
|
||||
| WS_MAXIMIZEBOX
|
||||
| WS_CLIPSIBLINGS;
|
||||
|
||||
let scaling = match options.scale {
|
||||
// TODO: Find system scale factor
|
||||
WindowScalePolicy::TrySystemScaleFactor => get_scaling().unwrap_or(1.0),
|
||||
WindowScalePolicy::TrySystemScaleFactorTimes(user_scale) => get_scaling().unwrap_or(1.0) * user_scale,
|
||||
WindowScalePolicy::UseScaleFactor(user_scale) => user_scale,
|
||||
WindowScalePolicy::NoScaling => 1.0,
|
||||
};
|
||||
|
||||
let window_info = options.window_info_from_scale(scaling);
|
||||
|
||||
let mut rect = RECT {
|
||||
left: 0,
|
||||
top: 0,
|
||||
// todo: check if usize fits into i32
|
||||
right: options.width as i32,
|
||||
bottom: options.height as i32,
|
||||
right: window_info.physical_size().width as i32,
|
||||
bottom: window_info.physical_size().height as i32,
|
||||
};
|
||||
|
||||
// todo: add check flags https://github.com/wrl/rutabaga/blob/f30ff67e157375cafdbafe5fb549f1790443a3a8/src/platform/win/window.c#L351
|
||||
|
@ -228,15 +247,13 @@ impl Window {
|
|||
|
||||
let handler = build(&mut window);
|
||||
|
||||
let window_state = Rc::new(RefCell::new(WindowState {
|
||||
let window_state = Box::new(RefCell::new(WindowState {
|
||||
window_class,
|
||||
scaling: None,
|
||||
window_info,
|
||||
handler,
|
||||
}));
|
||||
|
||||
let win = Rc::new(RefCell::new(window));
|
||||
|
||||
SetWindowLongPtrA(hwnd, GWLP_USERDATA, Rc::into_raw(win) as *const _ as _);
|
||||
SetWindowLongPtrA(hwnd, GWLP_USERDATA, Box::into_raw(window_state) as *const _ as _);
|
||||
SetTimer(hwnd, 4242, 13, None);
|
||||
|
||||
WindowHandle { hwnd }
|
||||
|
@ -252,3 +269,8 @@ unsafe impl HasRawWindowHandle for Window {
|
|||
})
|
||||
}
|
||||
}
|
||||
|
||||
fn get_scaling() -> Option<f64> {
|
||||
// TODO: find system scaling
|
||||
None
|
||||
}
|
154
src/window_info.rs
Normal file
154
src/window_info.rs
Normal file
|
@ -0,0 +1,154 @@
|
|||
/// The info about the window
|
||||
#[derive(Debug, Copy, Clone)]
|
||||
pub struct WindowInfo {
|
||||
logical_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 = 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 {
|
||||
logical_size,
|
||||
physical_size,
|
||||
scale,
|
||||
scale_recip,
|
||||
}
|
||||
}
|
||||
|
||||
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 {
|
||||
logical_size,
|
||||
physical_size,
|
||||
scale,
|
||||
scale_recip,
|
||||
}
|
||||
}
|
||||
|
||||
/// The logical size of the window
|
||||
pub fn logical_size(&self) -> Size {
|
||||
self.logical_size
|
||||
}
|
||||
|
||||
/// The physical size of the window
|
||||
pub fn physical_size(&self) -> PhySize {
|
||||
self.physical_size
|
||||
}
|
||||
|
||||
/// The scale factor of the window
|
||||
pub fn scale(&self) -> f64 {
|
||||
self.scale
|
||||
}
|
||||
|
||||
/// The reciprocal of the scale factor of the window
|
||||
pub fn scale_recip(&self) -> f64 {
|
||||
self.scale_recip
|
||||
}
|
||||
}
|
||||
|
||||
/// 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(),
|
||||
}
|
||||
}
|
||||
}
|
46
src/window_open_options.rs
Normal file
46
src/window_open_options.rs
Normal file
|
@ -0,0 +1,46 @@
|
|||
use crate::{WindowInfo, Parent, Size, PhySize};
|
||||
|
||||
/// The size of the window
|
||||
#[derive(Debug)]
|
||||
pub enum WindowSize {
|
||||
/// Use logical width and height
|
||||
Logical(Size),
|
||||
/// Use physical width and height
|
||||
Physical(PhySize),
|
||||
}
|
||||
|
||||
/// 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(size) => WindowInfo::from_logical_size(size, scale),
|
||||
WindowSize::Physical(size) => WindowInfo::from_physical_size(size, scale),
|
||||
}
|
||||
}
|
||||
}
|
|
@ -12,7 +12,7 @@ use raw_window_handle::{
|
|||
use super::XcbConnection;
|
||||
use crate::{
|
||||
Event, KeyboardEvent, MouseButton, MouseCursor, MouseEvent, Parent, ScrollDelta, WindowEvent,
|
||||
WindowHandler,WindowInfo, WindowOpenOptions,
|
||||
WindowHandler, WindowInfo, WindowOpenOptions, WindowScalePolicy, PhyPoint, PhySize,
|
||||
};
|
||||
|
||||
pub struct Window {
|
||||
|
@ -24,7 +24,7 @@ pub struct Window {
|
|||
frame_interval: Duration,
|
||||
event_loop_running: bool,
|
||||
|
||||
new_size: Option<(u32, u32)>
|
||||
new_physical_size: Option<PhySize>
|
||||
}
|
||||
|
||||
// FIXME: move to outer crate context
|
||||
|
@ -99,6 +99,17 @@ impl Window {
|
|||
],
|
||||
);
|
||||
|
||||
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 window_info = options.window_info_from_scale(scaling);
|
||||
|
||||
let window_id = xcb_connection.conn.generate_id();
|
||||
xcb::create_window(
|
||||
&xcb_connection.conn,
|
||||
|
@ -107,8 +118,8 @@ impl Window {
|
|||
parent_id,
|
||||
0, // x coordinate of the new window
|
||||
0, // y coordinate of the new window
|
||||
options.width as u16, // window width
|
||||
options.height as u16, // window height
|
||||
window_info.physical_size().width as u16, // window width
|
||||
window_info.physical_size().height as u16, // window height
|
||||
0, // window border
|
||||
xcb::WINDOW_CLASS_INPUT_OUTPUT as u16,
|
||||
screen.root_visual(),
|
||||
|
@ -151,14 +162,6 @@ impl Window {
|
|||
|
||||
xcb_connection.conn.flush();
|
||||
|
||||
let scaling = xcb_connection.get_scaling().unwrap_or(1.0);
|
||||
|
||||
let window_info = WindowInfo {
|
||||
width: options.width as u32,
|
||||
height: options.height as u32,
|
||||
scale: scaling,
|
||||
};
|
||||
|
||||
let mut window = Self {
|
||||
xcb_connection,
|
||||
window_id,
|
||||
|
@ -168,7 +171,7 @@ impl Window {
|
|||
frame_interval: Duration::from_millis(15),
|
||||
event_loop_running: false,
|
||||
|
||||
new_size: None
|
||||
new_physical_size: None,
|
||||
};
|
||||
|
||||
let mut handler = build(&mut window);
|
||||
|
@ -208,15 +211,17 @@ impl Window {
|
|||
// the X server has a tendency to send spurious/extraneous configure notify events when a
|
||||
// window is resized, and we need to batch those together and just send one resize event
|
||||
// when they've all been coalesced.
|
||||
self.new_size = None;
|
||||
self.new_physical_size = None;
|
||||
|
||||
while let Some(event) = self.xcb_connection.conn.poll_for_event() {
|
||||
self.handle_xcb_event(handler, event);
|
||||
}
|
||||
|
||||
if let Some((width, height)) = self.new_size.take() {
|
||||
self.window_info.width = width;
|
||||
self.window_info.height = height;
|
||||
if let Some(size) = self.new_physical_size.take() {
|
||||
self.window_info = WindowInfo::from_physical_size(
|
||||
size,
|
||||
self.window_info.scale()
|
||||
);
|
||||
|
||||
handler.on_event(self, Event::Window(
|
||||
WindowEvent::Resized(self.window_info)
|
||||
|
@ -319,11 +324,10 @@ impl Window {
|
|||
xcb::CONFIGURE_NOTIFY => {
|
||||
let event = unsafe { xcb::cast_event::<xcb::ConfigureNotifyEvent>(&event) };
|
||||
|
||||
let new_size = (event.width() as u32, event.height() as u32);
|
||||
let cur_size = (self.window_info.width, self.window_info.height);
|
||||
let new_physical_size = PhySize::new(event.width() as u32, event.height() as u32);
|
||||
|
||||
if self.new_size.is_some() || new_size != cur_size {
|
||||
self.new_size = Some(new_size);
|
||||
if self.new_physical_size.is_some() || new_physical_size != self.window_info.physical_size() {
|
||||
self.new_physical_size = Some(new_physical_size);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -335,11 +339,13 @@ impl Window {
|
|||
let detail = event.detail();
|
||||
|
||||
if detail != 4 && detail != 5 {
|
||||
let physical_pos = PhyPoint::new(event.event_x() as i32, event.event_y() as i32);
|
||||
let logical_pos = physical_pos.to_logical(&self.window_info);
|
||||
|
||||
handler.on_event(
|
||||
self,
|
||||
Event::Mouse(MouseEvent::CursorMoved {
|
||||
x: event.event_x() as i32,
|
||||
y: event.event_y() as i32,
|
||||
position: logical_pos,
|
||||
}),
|
||||
);
|
||||
}
|
||||
|
|
|
@ -13,6 +13,7 @@ use super::cursor;
|
|||
pub(crate) struct Atoms {
|
||||
pub wm_protocols: Option<u32>,
|
||||
pub wm_delete_window: Option<u32>,
|
||||
pub wm_normal_hints: Option<u32>,
|
||||
}
|
||||
|
||||
pub struct XcbConnection {
|
||||
|
@ -45,7 +46,7 @@ impl XcbConnection {
|
|||
pub fn new() -> Result<Self, xcb::base::ConnError> {
|
||||
let (conn, xlib_display) = xcb::Connection::connect_with_xlib_display()?;
|
||||
|
||||
let (wm_protocols, wm_delete_window) = intern_atoms!(&conn, WM_PROTOCOLS, WM_DELETE_WINDOW);
|
||||
let (wm_protocols, wm_delete_window, wm_normal_hints) = intern_atoms!(&conn, WM_PROTOCOLS, WM_DELETE_WINDOW, WM_NORMAL_HINTS);
|
||||
|
||||
Ok(Self {
|
||||
conn,
|
||||
|
@ -54,6 +55,7 @@ impl XcbConnection {
|
|||
atoms: Atoms {
|
||||
wm_protocols,
|
||||
wm_delete_window,
|
||||
wm_normal_hints,
|
||||
},
|
||||
|
||||
cursor_cache: HashMap::new()
|
||||
|
|
Loading…
Reference in a new issue