diff --git a/src/x11/window.rs b/src/x11/window.rs index 3f23726..5d3a896 100644 --- a/src/x11/window.rs +++ b/src/x11/window.rs @@ -4,20 +4,19 @@ use std::sync::mpsc; use super::XcbConnection; 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 { - scaling: f64, +pub struct Window { xcb_connection: XcbConnection, - app_window: A, - app_message_rx: mpsc::Receiver, + window_id: u32, + scaling: f64, } -impl Window { - pub fn open(options: WindowOpenOptions, app_message_rx: mpsc::Receiver) -> Self { +impl Window { + pub fn open(options: WindowOpenOptions, app_message_rx: mpsc::Receiver) { // Convert the parent to a X11 window ID if we're given one let parent = match options.parent { Parent::None => None, @@ -93,131 +92,122 @@ impl Window { 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) .or(get_scaling_screen_dimensions(&xcb_connection)) .unwrap_or(1.0); - let window_info = WindowInfo { - 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, + let mut window = Self { xcb_connection, - app_window, - app_message_rx, + window_id, + 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 - fn run_event_loop(&mut self) { - loop { - // somehow poll self.app_message_rx for messages at the same time +unsafe impl HasRawWindowHandle for Window { + fn raw_window_handle(&self) -> RawWindowHandle { + RawWindowHandle::Xlib(XlibHandle { + 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(); - if let Some(event) = ev { - let event_type = event.response_type() & !0x80; +// Event loop +fn run_event_loop(window: &mut Window, app_window: &mut A) { + loop { + // somehow poll app_message_rx for messages at the same time - // For all of the keyboard and mouse events, you can fetch - // `x`, `y`, `detail`, and `state`. - // - `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 + let ev = window.xcb_connection.conn.wait_for_event(); + if let Some(event) = ev { + let event_type = event.response_type() & !0x80; - match event_type { - xcb::EXPOSE => { - self.app_window.draw(); + // For all of the keyboard and mouse events, you can fetch + // `x`, `y`, `detail`, and `state`. + // - `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::(&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::(&event) }; - let detail = event.detail(); + } + xcb::BUTTON_PRESS => { + let event = unsafe { xcb::cast_event::(&event) }; + let detail = event.detail(); - if detail != 4 && detail != 5 { - self.app_window.on_event(Event::CursorMotion( - event.event_x() as i32, - event.event_y() as i32, - )); + match detail { + 4 => { + app_window.on_event(window, Event::MouseScroll(MouseScroll { + x_delta: 0.0, + y_delta: 1.0, + })); } - } - xcb::BUTTON_PRESS => { - let event = unsafe { xcb::cast_event::(&event) }; - let detail = event.detail(); - - 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)); - } + 5 => { + app_window.on_event(window, Event::MouseScroll(MouseScroll { + x_delta: 0.0, + y_delta: -1.0, + })); } - } - xcb::BUTTON_RELEASE => { - let event = unsafe { xcb::cast_event::(&event) }; - let detail = event.detail(); - - if detail != 4 && detail != 5 { + 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::(&event) }; - let detail = event.detail(); + } + xcb::BUTTON_RELEASE => { + let event = unsafe { xcb::cast_event::(&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::(&event) }; - let detail = event.detail(); + } + xcb::KEY_PRESS => { + let event = unsafe { xcb::cast_event::(&event) }; + let detail = event.detail(); - self.app_window.on_event(Event::KeyUp(detail)); - } - _ => { - println!("Unhandled event type: {:?}", event_type); - } + app_window.on_event(window, Event::KeyDown(detail)); + } + xcb::KEY_RELEASE => { + let event = unsafe { xcb::cast_event::(&event) }; + let detail = event.detail(); + + app_window.on_event(window, Event::KeyUp(detail)); + } + _ => { + println!("Unhandled event type: {:?}", event_type); } } }