1
0
Fork 0

adapt x11 backend to new api

This commit is contained in:
micah 2020-09-07 14:16:48 -04:00
parent bb6a5eeeac
commit 057324e688

View file

@ -4,20 +4,19 @@ use std::sync::mpsc;
use super::XcbConnection; use super::XcbConnection;
use crate::{ use crate::{
AppWindow, Event, MouseButtonID, MouseScroll, Parent, RawWindow, WindowInfo, WindowOpenOptions, AppWindow, Event, MouseButtonID, MouseScroll, Parent, WindowOpenOptions,
}; };
use raw_window_handle::RawWindowHandle; use raw_window_handle::{unix::XlibHandle, HasRawWindowHandle, RawWindowHandle};
pub struct Window<A: AppWindow> { pub struct Window {
scaling: f64,
xcb_connection: XcbConnection, xcb_connection: XcbConnection,
app_window: A, window_id: u32,
app_message_rx: mpsc::Receiver<A::AppMessage>, scaling: f64,
} }
impl<A: AppWindow> Window<A> { impl Window {
pub fn open(options: WindowOpenOptions, app_message_rx: mpsc::Receiver<A::AppMessage>) -> Self { pub fn open<A: AppWindow>(options: WindowOpenOptions, app_message_rx: mpsc::Receiver<A::AppMessage>) {
// Convert the parent to a X11 window ID if we're given one // Convert the parent to a X11 window ID if we're given one
let parent = match options.parent { let parent = match options.parent {
Parent::None => None, Parent::None => None,
@ -93,131 +92,122 @@ impl<A: AppWindow> Window<A> {
xcb_connection.conn.flush(); xcb_connection.conn.flush();
let raw_handle = RawWindowHandle::Xlib(raw_window_handle::unix::XlibHandle {
window: window_id as c_ulong,
display: xcb_connection.conn.get_raw_dpy() as *mut c_void,
..raw_window_handle::unix::XlibHandle::empty()
});
let raw_window = RawWindow {
raw_window_handle: raw_handle,
};
let scaling = get_scaling_xft(&xcb_connection) let scaling = get_scaling_xft(&xcb_connection)
.or(get_scaling_screen_dimensions(&xcb_connection)) .or(get_scaling_screen_dimensions(&xcb_connection))
.unwrap_or(1.0); .unwrap_or(1.0);
let window_info = WindowInfo { let mut window = Self {
width: options.width as u32,
height: options.height as u32,
scale: scaling,
};
let app_window = A::build(raw_window, &window_info);
let mut x11_window = Self {
scaling,
xcb_connection, xcb_connection,
app_window, window_id,
app_message_rx, scaling,
}; };
x11_window.run_event_loop(); let mut app_window = A::build(&mut window);
x11_window run_event_loop(&mut window, &mut app_window);
} }
}
// Event loop unsafe impl HasRawWindowHandle for Window {
fn run_event_loop(&mut self) { fn raw_window_handle(&self) -> RawWindowHandle {
loop { RawWindowHandle::Xlib(XlibHandle {
// somehow poll self.app_message_rx for messages at the same time window: self.window_id as c_ulong,
display: self.xcb_connection.conn.get_raw_dpy() as *mut c_void,
..raw_window_handle::unix::XlibHandle::empty()
})
}
}
let ev = self.xcb_connection.conn.wait_for_event(); // Event loop
if let Some(event) = ev { fn run_event_loop<A: AppWindow>(window: &mut Window, app_window: &mut A) {
let event_type = event.response_type() & !0x80; loop {
// somehow poll app_message_rx for messages at the same time
// For all of the keyboard and mouse events, you can fetch let ev = window.xcb_connection.conn.wait_for_event();
// `x`, `y`, `detail`, and `state`. if let Some(event) = ev {
// - `x` and `y` are the position inside the window where the cursor currently is let event_type = event.response_type() & !0x80;
// when the event happened.
// - `detail` will tell you which keycode was pressed/released (for keyboard events)
// or which mouse button was pressed/released (for mouse events).
// For mouse events, here's what the value means (at least on my current mouse):
// 1 = left mouse button
// 2 = middle mouse button (scroll wheel)
// 3 = right mouse button
// 4 = scroll wheel up
// 5 = scroll wheel down
// 8 = lower side button ("back" button)
// 9 = upper side button ("forward" button)
// Note that you *will* get a "button released" event for even the scroll wheel
// events, which you can probably ignore.
// - `state` will tell you the state of the main three mouse buttons and some of
// the keyboard modifier keys at the time of the event.
// http://rtbo.github.io/rust-xcb/src/xcb/ffi/xproto.rs.html#445
match event_type { // For all of the keyboard and mouse events, you can fetch
xcb::EXPOSE => { // `x`, `y`, `detail`, and `state`.
self.app_window.draw(); // - `x` and `y` are the position inside the window where the cursor currently is
// when the event happened.
// - `detail` will tell you which keycode was pressed/released (for keyboard events)
// or which mouse button was pressed/released (for mouse events).
// For mouse events, here's what the value means (at least on my current mouse):
// 1 = left mouse button
// 2 = middle mouse button (scroll wheel)
// 3 = right mouse button
// 4 = scroll wheel up
// 5 = scroll wheel down
// 8 = lower side button ("back" button)
// 9 = upper side button ("forward" button)
// Note that you *will* get a "button released" event for even the scroll wheel
// events, which you can probably ignore.
// - `state` will tell you the state of the main three mouse buttons and some of
// the keyboard modifier keys at the time of the event.
// http://rtbo.github.io/rust-xcb/src/xcb/ffi/xproto.rs.html#445
match event_type {
xcb::EXPOSE => {
app_window.draw(window);
}
xcb::MOTION_NOTIFY => {
let event = unsafe { xcb::cast_event::<xcb::MotionNotifyEvent>(&event) };
let detail = event.detail();
if detail != 4 && detail != 5 {
app_window.on_event(window, Event::CursorMotion(
event.event_x() as i32,
event.event_y() as i32,
));
} }
xcb::MOTION_NOTIFY => { }
let event = unsafe { xcb::cast_event::<xcb::MotionNotifyEvent>(&event) }; xcb::BUTTON_PRESS => {
let detail = event.detail(); let event = unsafe { xcb::cast_event::<xcb::ButtonPressEvent>(&event) };
let detail = event.detail();
if detail != 4 && detail != 5 { match detail {
self.app_window.on_event(Event::CursorMotion( 4 => {
event.event_x() as i32, app_window.on_event(window, Event::MouseScroll(MouseScroll {
event.event_y() as i32, x_delta: 0.0,
)); y_delta: 1.0,
}));
} }
} 5 => {
xcb::BUTTON_PRESS => { app_window.on_event(window, Event::MouseScroll(MouseScroll {
let event = unsafe { xcb::cast_event::<xcb::ButtonPressEvent>(&event) }; x_delta: 0.0,
let detail = event.detail(); y_delta: -1.0,
}));
match detail {
4 => {
self.app_window.on_event(Event::MouseScroll(MouseScroll {
x_delta: 0.0,
y_delta: 1.0,
}));
}
5 => {
self.app_window.on_event(Event::MouseScroll(MouseScroll {
x_delta: 0.0,
y_delta: -1.0,
}));
}
detail => {
let button_id = mouse_id(detail);
self.app_window.on_event(Event::MouseDown(button_id));
}
} }
} detail => {
xcb::BUTTON_RELEASE => {
let event = unsafe { xcb::cast_event::<xcb::ButtonPressEvent>(&event) };
let detail = event.detail();
if detail != 4 && detail != 5 {
let button_id = mouse_id(detail); let button_id = mouse_id(detail);
self.app_window.on_event(Event::MouseUp(button_id)); app_window.on_event(window, Event::MouseDown(button_id));
} }
} }
xcb::KEY_PRESS => { }
let event = unsafe { xcb::cast_event::<xcb::KeyPressEvent>(&event) }; xcb::BUTTON_RELEASE => {
let detail = event.detail(); let event = unsafe { xcb::cast_event::<xcb::ButtonPressEvent>(&event) };
let detail = event.detail();
self.app_window.on_event(Event::KeyDown(detail)); if detail != 4 && detail != 5 {
let button_id = mouse_id(detail);
app_window.on_event(window, Event::MouseUp(button_id));
} }
xcb::KEY_RELEASE => { }
let event = unsafe { xcb::cast_event::<xcb::KeyReleaseEvent>(&event) }; xcb::KEY_PRESS => {
let detail = event.detail(); let event = unsafe { xcb::cast_event::<xcb::KeyPressEvent>(&event) };
let detail = event.detail();
self.app_window.on_event(Event::KeyUp(detail)); app_window.on_event(window, Event::KeyDown(detail));
} }
_ => { xcb::KEY_RELEASE => {
println!("Unhandled event type: {:?}", event_type); let event = unsafe { xcb::cast_event::<xcb::KeyReleaseEvent>(&event) };
} let detail = event.detail();
app_window.on_event(window, Event::KeyUp(detail));
}
_ => {
println!("Unhandled event type: {:?}", event_type);
} }
} }
} }