adapt x11 backend to new api
This commit is contained in:
parent
bb6a5eeeac
commit
057324e688
|
@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue