1
0
Fork 0

Merge pull request #45 from BillyDM/master

Detect window resize in x11
This commit is contained in:
william light 2020-09-11 22:18:32 +02:00 committed by GitHub
commit 877c913a0c
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 88 additions and 67 deletions

View file

@ -15,7 +15,7 @@ impl WindowHandler for MyProgram {
match event { match event {
Event::Mouse(e) => println!("Mouse event: {:?}", e), Event::Mouse(e) => println!("Mouse event: {:?}", e),
Event::Keyboard(e) => println!("Keyboard event: {:?}", e), Event::Keyboard(e) => println!("Keyboard event: {:?}", e),
Event::Window(e) => println!("Window event: {:?}", e) Event::Window(e) => println!("Window event: {:?}", e),
} }
} }

View file

@ -91,5 +91,5 @@ pub enum WindowEvent {
pub enum Event { pub enum Event {
Mouse(MouseEvent), Mouse(MouseEvent),
Keyboard(KeyboardEvent), Keyboard(KeyboardEvent),
Window(WindowEvent) Window(WindowEvent),
} }

View file

@ -11,8 +11,8 @@ use cocoa::foundation::{NSAutoreleasePool, NSPoint, NSRect, NSSize, NSString};
use raw_window_handle::{macos::MacOSHandle, HasRawWindowHandle, RawWindowHandle}; use raw_window_handle::{macos::MacOSHandle, HasRawWindowHandle, RawWindowHandle};
use crate::{ use crate::{
Event, KeyboardEvent, MouseButton, MouseEvent, ScrollDelta, WindowEvent, Event, KeyboardEvent, MouseButton, MouseEvent, ScrollDelta, WindowEvent, WindowHandler,
WindowHandler, WindowOpenOptions, WindowOpenOptions,
}; };
pub struct Window { pub struct Window {

View file

@ -19,8 +19,8 @@ use std::rc::Rc;
use raw_window_handle::{windows::WindowsHandle, HasRawWindowHandle, RawWindowHandle}; use raw_window_handle::{windows::WindowsHandle, HasRawWindowHandle, RawWindowHandle};
use crate::{ use crate::{
Event, KeyboardEvent, MouseButton, MouseEvent, Parent::WithParent, ScrollDelta, Event, KeyboardEvent, MouseButton, MouseEvent, Parent::WithParent, ScrollDelta, WindowEvent,
WindowEvent, WindowHandler, WindowInfo, WindowOpenOptions, WindowHandler, WindowInfo, WindowOpenOptions,
}; };
unsafe fn message_box(title: &str, msg: &str) { unsafe fn message_box(title: &str, msg: &str) {
@ -142,7 +142,7 @@ pub struct Window {
} }
pub struct WindowHandle { pub struct WindowHandle {
hwnd: HWND hwnd: HWND,
} }
impl WindowHandle { impl WindowHandle {
@ -193,7 +193,7 @@ impl Window {
WithParent(p) => { WithParent(p) => {
flags = WS_CHILD | WS_VISIBLE; flags = WS_CHILD | WS_VISIBLE;
p p
}, }
_ => { _ => {
AdjustWindowRectEx(&mut rect, flags, FALSE, 0); AdjustWindowRectEx(&mut rect, flags, FALSE, 0);
@ -232,9 +232,7 @@ impl Window {
SetWindowLongPtrA(hwnd, GWLP_USERDATA, Rc::into_raw(win) as *const _ as _); SetWindowLongPtrA(hwnd, GWLP_USERDATA, Rc::into_raw(win) as *const _ as _);
SetTimer(hwnd, 4242, 13, None); SetTimer(hwnd, 4242, 13, None);
WindowHandle { WindowHandle { hwnd }
hwnd
}
} }
} }
} }

View file

@ -1,29 +1,29 @@
use std::os::raw::{c_ulong, c_void}; use std::os::raw::{c_ulong, c_void};
use std::sync::mpsc; use std::sync::mpsc;
use std::time::*;
use std::thread; use std::thread;
use std::time::*;
use std::time::*;
use raw_window_handle::{unix::XlibHandle, HasRawWindowHandle, RawWindowHandle}; use raw_window_handle::{unix::XlibHandle, HasRawWindowHandle, RawWindowHandle};
use super::XcbConnection; use super::XcbConnection;
use crate::{ use crate::{
Event, KeyboardEvent, MouseButton, MouseEvent, Parent, ScrollDelta, WindowEvent, Event, KeyboardEvent, MouseButton, MouseEvent, Parent, ScrollDelta, WindowEvent, WindowHandler,
WindowHandler, WindowOpenOptions, WindowInfo, WindowOpenOptions,
}; };
pub struct Window { pub struct Window {
xcb_connection: XcbConnection, xcb_connection: XcbConnection,
window_id: u32, window_id: u32,
scaling: f64, window_info: WindowInfo,
frame_interval: Duration, frame_interval: Duration,
event_loop_running: bool event_loop_running: bool,
} }
// FIXME: move to outer crate context // FIXME: move to outer crate context
pub struct WindowHandle { pub struct WindowHandle {
thread: std::thread::JoinHandle<()> thread: std::thread::JoinHandle<()>,
} }
impl WindowHandle { impl WindowHandle {
@ -47,12 +47,13 @@ impl Window {
// FIXME: placeholder types for returning errors in the future // FIXME: placeholder types for returning errors in the future
let _ = rx.recv(); let _ = rx.recv();
WindowHandle { WindowHandle { thread }
thread
}
} }
fn window_thread<H: WindowHandler>(options: WindowOpenOptions, tx: mpsc::SyncSender<WindowOpenResult>) -> WindowOpenResult { fn window_thread<H: WindowHandler>(
options: WindowOpenOptions,
tx: mpsc::SyncSender<WindowOpenResult>,
) -> WindowOpenResult {
// Connect to the X server // Connect to the X server
// FIXME: baseview error type instead of unwrap() // FIXME: baseview error type instead of unwrap()
let xcb_connection = XcbConnection::new().unwrap(); let xcb_connection = XcbConnection::new().unwrap();
@ -102,7 +103,8 @@ impl Window {
| xcb::EVENT_MASK_BUTTON_PRESS | xcb::EVENT_MASK_BUTTON_PRESS
| xcb::EVENT_MASK_BUTTON_RELEASE | xcb::EVENT_MASK_BUTTON_RELEASE
| xcb::EVENT_MASK_KEY_PRESS | xcb::EVENT_MASK_KEY_PRESS
| xcb::EVENT_MASK_KEY_RELEASE, | xcb::EVENT_MASK_KEY_RELEASE
| xcb::EVENT_MASK_STRUCTURE_NOTIFY,
)], )],
); );
@ -120,14 +122,16 @@ impl Window {
title.as_bytes(), title.as_bytes(),
); );
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)| {
xcb_util::icccm::set_wm_protocols( xcb_util::icccm::set_wm_protocols(
&xcb_connection.conn, &xcb_connection.conn,
window_id, window_id,
wm_protocols, wm_protocols,
&[wm_delete_window] &[wm_delete_window],
); );
}); });
@ -135,13 +139,19 @@ impl Window {
let scaling = xcb_connection.get_scaling().unwrap_or(1.0); 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 { let mut window = Self {
xcb_connection, xcb_connection,
window_id, window_id,
scaling, window_info,
frame_interval: Duration::from_millis(15), frame_interval: Duration::from_millis(15),
event_loop_running: false event_loop_running: false,
}; };
let mut handler = H::build(&mut window); let mut handler = H::build(&mut window);
@ -152,6 +162,10 @@ impl Window {
Ok(()) Ok(())
} }
pub fn window_info(&self) -> &WindowInfo {
&self.window_info
}
#[inline] #[inline]
fn drain_xcb_events<H: WindowHandler>(&mut self, handler: &mut H) { fn drain_xcb_events<H: WindowHandler>(&mut self, handler: &mut H) {
while let Some(event) = self.xcb_connection.conn.poll_for_event() { while let Some(event) = self.xcb_connection.conn.poll_for_event() {
@ -176,8 +190,7 @@ impl Window {
while self.event_loop_running { while self.event_loop_running {
let now = Instant::now(); let now = Instant::now();
let until_next_frame = let until_next_frame = if now > next_frame {
if now > next_frame {
handler.on_frame(); handler.on_frame();
next_frame = now + self.frame_interval; next_frame = now + self.frame_interval;
@ -186,13 +199,10 @@ impl Window {
next_frame - now next_frame - now
}; };
let mut fds = [ let mut fds = [PollFd::new(xcb_fd, PollFlags::POLLIN)];
PollFd::new(xcb_fd, PollFlags::POLLIN)
];
// FIXME: handle errors // FIXME: handle errors
poll(&mut fds, until_next_frame.subsec_millis() as i32) poll(&mut fds, until_next_frame.subsec_millis() as i32).unwrap();
.unwrap();
if let Some(revents) = fds[0].revents() { if let Some(revents) = fds[0].revents() {
if revents.contains(PollFlags::POLLERR) { if revents.contains(PollFlags::POLLERR) {
@ -231,9 +241,8 @@ impl Window {
match event_type { match event_type {
//// ////
// keys // window
//// ////
xcb::EXPOSE => { xcb::EXPOSE => {
handler.on_frame(); handler.on_frame();
} }
@ -245,7 +254,11 @@ impl Window {
let data = event.data().data; let data = event.data().data;
let (_, data32, _) = unsafe { data.align_to::<u32>() }; let (_, data32, _) = unsafe { data.align_to::<u32>() };
let wm_delete_window = self.xcb_connection.atoms.wm_delete_window.unwrap_or(xcb::NONE); let wm_delete_window = self
.xcb_connection
.atoms
.wm_delete_window
.unwrap_or(xcb::NONE);
if wm_delete_window == data32[0] { if wm_delete_window == data32[0] {
handler.on_event(self, Event::Window(WindowEvent::WillClose)); handler.on_event(self, Event::Window(WindowEvent::WillClose));
@ -255,10 +268,22 @@ impl Window {
} }
} }
xcb::CONFIGURE_NOTIFY => {
let event = unsafe { xcb::cast_event::<xcb::ConfigureNotifyEvent>(&event) };
if self.window_info.width != event.width() as u32
|| self.window_info.height != event.height() as u32
{
self.window_info.width = event.width() as u32;
self.window_info.height = event.height() as u32;
handler.on_event(self, Event::Window(WindowEvent::Resized(self.window_info)))
}
}
//// ////
// mouse // mouse
//// ////
xcb::MOTION_NOTIFY => { xcb::MOTION_NOTIFY => {
let event = unsafe { xcb::cast_event::<xcb::MotionNotifyEvent>(&event) }; let event = unsafe { xcb::cast_event::<xcb::MotionNotifyEvent>(&event) };
let detail = event.detail(); let detail = event.detail();
@ -266,7 +291,10 @@ impl Window {
if detail != 4 && detail != 5 { if detail != 4 && detail != 5 {
handler.on_event( handler.on_event(
self, self,
Event::Mouse(MouseEvent::CursorMoved { x: event.event_x() as i32, y: event.event_y() as i32 }), Event::Mouse(MouseEvent::CursorMoved {
x: event.event_x() as i32,
y: event.event_y() as i32,
}),
); );
} }
} }
@ -314,19 +342,24 @@ impl Window {
//// ////
// keys // keys
//// ////
xcb::KEY_PRESS => { xcb::KEY_PRESS => {
let event = unsafe { xcb::cast_event::<xcb::KeyPressEvent>(&event) }; let event = unsafe { xcb::cast_event::<xcb::KeyPressEvent>(&event) };
let detail = event.detail(); let detail = event.detail();
handler.on_event(self, Event::Keyboard(KeyboardEvent::KeyPressed(detail as u32))); handler.on_event(
self,
Event::Keyboard(KeyboardEvent::KeyPressed(detail as u32)),
);
} }
xcb::KEY_RELEASE => { xcb::KEY_RELEASE => {
let event = unsafe { xcb::cast_event::<xcb::KeyReleaseEvent>(&event) }; let event = unsafe { xcb::cast_event::<xcb::KeyReleaseEvent>(&event) };
let detail = event.detail(); let detail = event.detail();
handler.on_event(self, Event::Keyboard(KeyboardEvent::KeyReleased(detail as u32))); handler.on_event(
self,
Event::Keyboard(KeyboardEvent::KeyReleased(detail as u32)),
);
} }
_ => { _ => {

View file

@ -1,22 +1,18 @@
/// A very light abstraction around the XCB connection. /// A very light abstraction around the XCB connection.
/// ///
/// Keeps track of the xcb connection itself and the xlib display ID that was used to connect. /// Keeps track of the xcb connection itself and the xlib display ID that was used to connect.
use std::ffi::{CStr, CString};
use std::ffi::{
CString,
CStr
};
pub(crate) struct Atoms { pub(crate) struct Atoms {
pub wm_protocols: Option<u32>, pub wm_protocols: Option<u32>,
pub wm_delete_window: Option<u32> pub wm_delete_window: Option<u32>,
} }
pub struct XcbConnection { pub struct XcbConnection {
pub conn: xcb::Connection, pub conn: xcb::Connection,
pub xlib_display: i32, pub xlib_display: i32,
pub(crate) atoms: Atoms pub(crate) atoms: Atoms,
} }
macro_rules! intern_atoms { macro_rules! intern_atoms {
@ -36,15 +32,11 @@ macro_rules! intern_atoms {
}}; }};
} }
impl XcbConnection { impl XcbConnection {
pub fn new() -> Result<Self, xcb::base::ConnError> { pub fn new() -> Result<Self, xcb::base::ConnError> {
let (conn, xlib_display) = xcb::Connection::connect_with_xlib_display()?; let (conn, xlib_display) = xcb::Connection::connect_with_xlib_display()?;
let (wm_protocols, wm_delete_window) = let (wm_protocols, wm_delete_window) = intern_atoms!(&conn, WM_PROTOCOLS, WM_DELETE_WINDOW);
intern_atoms!(&conn,
WM_PROTOCOLS,
WM_DELETE_WINDOW);
Ok(Self { Ok(Self {
conn, conn,
@ -52,8 +44,8 @@ impl XcbConnection {
atoms: Atoms { atoms: Atoms {
wm_protocols, wm_protocols,
wm_delete_window wm_delete_window,
} },
}) })
} }
@ -62,7 +54,8 @@ impl XcbConnection {
// If neither work, I guess just assume 96.0 and don't do any scaling. // If neither work, I guess just assume 96.0 and don't do any scaling.
fn get_scaling_xft(&self) -> Option<f64> { fn get_scaling_xft(&self) -> Option<f64> {
use x11::xlib::{ use x11::xlib::{
XResourceManagerString, XrmDestroyDatabase, XrmGetResource, XrmGetStringDatabase, XrmValue, XResourceManagerString, XrmDestroyDatabase, XrmGetResource, XrmGetStringDatabase,
XrmValue,
}; };
let display = self.conn.get_raw_dpy(); let display = self.conn.get_raw_dpy();
@ -113,10 +106,7 @@ impl XcbConnection {
fn get_scaling_screen_dimensions(&self) -> Option<f64> { fn get_scaling_screen_dimensions(&self) -> Option<f64> {
// Figure out screen information // Figure out screen information
let setup = self.conn.get_setup(); let setup = self.conn.get_setup();
let screen = setup let screen = setup.roots().nth(self.xlib_display as usize).unwrap();
.roots()
.nth(self.xlib_display as usize)
.unwrap();
// Get the DPI from the screen struct // Get the DPI from the screen struct
// //