Skip to content

Commit

Permalink
update x11 backend
Browse files Browse the repository at this point in the history
  • Loading branch information
micahrj committed Dec 17, 2023
1 parent eb2cb60 commit 5a723f9
Showing 1 changed file with 53 additions and 40 deletions.
93 changes: 53 additions & 40 deletions src/x11/window.rs
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@ impl Drop for ParentHandle {
}
}

pub struct Window {
struct WindowInner {
xcb_connection: XcbConnection,
window_id: u32,
window_info: WindowInfo,
Expand All @@ -111,14 +111,18 @@ pub struct Window {
gl_context: Option<GlContext>,
}

pub struct Window<'a> {
inner: &'a mut WindowInner,
}

// Hack to allow sending a RawWindowHandle between threads. Do not make public
struct SendableRwh(RawWindowHandle);

unsafe impl Send for SendableRwh {}

type WindowOpenResult = Result<SendableRwh, ()>;

impl Window {
impl<'a> Window<'a> {
pub fn open_parented<P, H, B>(parent: &P, options: WindowOpenOptions, build: B) -> WindowHandle
where
P: HasRawWindowHandle,
Expand Down Expand Up @@ -315,7 +319,7 @@ impl Window {
GlContext::new(context)
});

let mut window = Self {
let mut inner = WindowInner {
xcb_connection,
window_id,
window_info,
Expand All @@ -333,65 +337,64 @@ impl Window {
gl_context,
};

let mut handler = build(&mut crate::Window::new(&mut window));
let mut window = crate::Window::new(Window { inner: &mut inner });

let mut handler = build(&mut window);

// Send an initial window resized event so the user is alerted of
// the correct dpi scaling.
handler.on_event(
&mut crate::Window::new(&mut window),
Event::Window(WindowEvent::Resized(window_info)),
);
handler.on_event(&mut window, Event::Window(WindowEvent::Resized(window_info)));

let _ = tx.send(Ok(SendableRwh(window.raw_window_handle())));

window.run_event_loop(&mut handler);
inner.run_event_loop(&mut handler);
}

pub fn set_mouse_cursor(&mut self, mouse_cursor: MouseCursor) {
if self.mouse_cursor == mouse_cursor {
if self.inner.mouse_cursor == mouse_cursor {
return;
}

let xid = self.xcb_connection.get_cursor_xid(mouse_cursor);
let xid = self.inner.xcb_connection.get_cursor_xid(mouse_cursor);

if xid != 0 {
xcb::change_window_attributes(
&self.xcb_connection.conn,
self.window_id,
&self.inner.xcb_connection.conn,
self.inner.window_id,
&[(xcb::CW_CURSOR, xid)],
);

self.xcb_connection.conn.flush();
self.inner.xcb_connection.conn.flush();
}

self.mouse_cursor = mouse_cursor;
self.inner.mouse_cursor = mouse_cursor;
}

pub fn close(&mut self) {
self.close_requested = true;
self.inner.close_requested = true;
}

pub fn resize(&mut self, size: Size) {
let scaling = self.window_info.scale();
let scaling = self.inner.window_info.scale();
let new_window_info = WindowInfo::from_logical_size(size, scaling);

xcb::configure_window(
&self.xcb_connection.conn,
self.window_id,
&self.inner.xcb_connection.conn,
self.inner.window_id,
&[
(xcb::CONFIG_WINDOW_WIDTH as u16, new_window_info.physical_size().width),
(xcb::CONFIG_WINDOW_HEIGHT as u16, new_window_info.physical_size().height),
],
);
self.xcb_connection.conn.flush();
self.inner.xcb_connection.conn.flush();

// This will trigger a `ConfigureNotify` event which will in turn change `self.window_info`
// and notify the window handler about it
}

#[cfg(feature = "opengl")]
pub fn gl_context(&self) -> Option<&crate::gl::GlContext> {
self.gl_context.as_ref()
self.inner.gl_context.as_ref()
}

fn find_visual_for_depth(screen: &StructPtr<xcb_screen_t>, depth: u8) -> Option<u32> {
Expand All @@ -409,7 +412,9 @@ impl Window {

None
}
}

impl WindowInner {
#[inline]
fn drain_xcb_events(&mut self, handler: &mut dyn WindowHandler) {
// the X server has a tendency to send spurious/extraneous configure notify events when a
Expand All @@ -427,7 +432,7 @@ impl Window {
let window_info = self.window_info;

handler.on_event(
&mut crate::Window::new(self),
&mut crate::Window::new(Window { inner: self }),
Event::Window(WindowEvent::Resized(window_info)),
);
}
Expand Down Expand Up @@ -457,7 +462,7 @@ impl Window {
// if it's already time to draw a new frame.
let next_frame = last_frame + self.frame_interval;
if Instant::now() >= next_frame {
handler.on_frame(&mut crate::Window::new(self));
handler.on_frame(&mut crate::Window::new(Window { inner: self }));
last_frame = Instant::max(next_frame, Instant::now() - self.frame_interval);
}

Expand Down Expand Up @@ -503,14 +508,20 @@ impl Window {
}

fn handle_close_requested(&mut self, handler: &mut dyn WindowHandler) {
handler.on_event(&mut crate::Window::new(self), Event::Window(WindowEvent::WillClose));
handler.on_event(
&mut crate::Window::new(Window { inner: self }),
Event::Window(WindowEvent::WillClose),
);

// FIXME: handler should decide whether window stays open or not
self.event_loop_running = false;
}

fn handle_must_close(&mut self, handler: &mut dyn WindowHandler) {
handler.on_event(&mut crate::Window::new(self), Event::Window(WindowEvent::WillClose));
handler.on_event(
&mut crate::Window::new(Window { inner: self }),
Event::Window(WindowEvent::WillClose),
);

self.event_loop_running = false;
}
Expand Down Expand Up @@ -582,7 +593,7 @@ impl Window {
let logical_pos = physical_pos.to_logical(&self.window_info);

handler.on_event(
&mut crate::Window::new(self),
&mut crate::Window::new(Window { inner: self }),
Event::Mouse(MouseEvent::CursorMoved {
position: logical_pos,
modifiers: key_mods(event.state()),
Expand All @@ -593,7 +604,7 @@ impl Window {

xcb::ENTER_NOTIFY => {
handler.on_event(
&mut crate::Window::new(self),
&mut crate::Window::new(Window { inner: self }),
Event::Mouse(MouseEvent::CursorEntered),
);
// since no `MOTION_NOTIFY` event is generated when `ENTER_NOTIFY` is generated,
Expand All @@ -602,7 +613,7 @@ impl Window {
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(
&mut crate::Window::new(self),
&mut crate::Window::new(Window { inner: self }),
Event::Mouse(MouseEvent::CursorMoved {
position: logical_pos,
modifiers: key_mods(event.state()),
Expand All @@ -611,8 +622,10 @@ impl Window {
}

xcb::LEAVE_NOTIFY => {
handler
.on_event(&mut crate::Window::new(self), Event::Mouse(MouseEvent::CursorLeft));
handler.on_event(
&mut crate::Window::new(Window { inner: self }),
Event::Mouse(MouseEvent::CursorLeft),
);
}

xcb::BUTTON_PRESS => {
Expand All @@ -622,7 +635,7 @@ impl Window {
match detail {
4..=7 => {
handler.on_event(
&mut crate::Window::new(self),
&mut crate::Window::new(Window { inner: self }),
Event::Mouse(MouseEvent::WheelScrolled {
delta: match detail {
4 => ScrollDelta::Lines { x: 0.0, y: 1.0 },
Expand All @@ -638,7 +651,7 @@ impl Window {
detail => {
let button_id = mouse_id(detail);
handler.on_event(
&mut crate::Window::new(self),
&mut crate::Window::new(Window { inner: self }),
Event::Mouse(MouseEvent::ButtonPressed {
button: button_id,
modifiers: key_mods(event.state()),
Expand All @@ -655,7 +668,7 @@ impl Window {
if !(4..=7).contains(&detail) {
let button_id = mouse_id(detail);
handler.on_event(
&mut crate::Window::new(self),
&mut crate::Window::new(Window { inner: self }),
Event::Mouse(MouseEvent::ButtonReleased {
button: button_id,
modifiers: key_mods(event.state()),
Expand All @@ -671,7 +684,7 @@ impl Window {
let event = unsafe { xcb::cast_event::<xcb::KeyPressEvent>(&event) };

handler.on_event(
&mut crate::Window::new(self),
&mut crate::Window::new(Window { inner: self }),
Event::Keyboard(convert_key_press_event(event)),
);
}
Expand All @@ -680,7 +693,7 @@ impl Window {
let event = unsafe { xcb::cast_event::<xcb::KeyReleaseEvent>(&event) };

handler.on_event(
&mut crate::Window::new(self),
&mut crate::Window::new(Window { inner: self }),
Event::Keyboard(convert_key_release_event(event)),
);
}
Expand All @@ -690,20 +703,20 @@ impl Window {
}
}

unsafe impl HasRawWindowHandle for Window {
unsafe impl<'a> HasRawWindowHandle for Window<'a> {
fn raw_window_handle(&self) -> RawWindowHandle {
let mut handle = XlibWindowHandle::empty();

handle.window = self.window_id.into();
handle.visual_id = self.visual_id.into();
handle.window = self.inner.window_id.into();
handle.visual_id = self.inner.visual_id.into();

RawWindowHandle::Xlib(handle)
}
}

unsafe impl HasRawDisplayHandle for Window {
unsafe impl<'a> HasRawDisplayHandle for Window<'a> {
fn raw_display_handle(&self) -> RawDisplayHandle {
let display = self.xcb_connection.conn.get_raw_dpy();
let display = self.inner.xcb_connection.conn.get_raw_dpy();
let mut handle = XlibDisplayHandle::empty();

handle.display = display as *mut c_void;
Expand Down

0 comments on commit 5a723f9

Please sign in to comment.