Skip to content

Commit

Permalink
Post-rebase fixes
Browse files Browse the repository at this point in the history
  • Loading branch information
prokopyl committed Apr 6, 2024
1 parent 0bc974a commit 0b58445
Show file tree
Hide file tree
Showing 4 changed files with 57 additions and 70 deletions.
107 changes: 50 additions & 57 deletions src/x11/event_loop.rs
Original file line number Diff line number Diff line change
@@ -1,57 +1,71 @@
use crate::x11::handle::ParentHandle;
use crate::x11::keyboard::{convert_key_press_event, convert_key_release_event, key_mods};
use crate::x11::{ParentHandle, Window, WindowInner};
use crate::x11::Window;
use crate::{
Event, MouseButton, MouseEvent, PhyPoint, PhySize, ScrollDelta, WindowEvent, WindowHandler,
WindowInfo,
};
use std::error::Error;
use std::os::fd::AsRawFd;
use std::rc::Rc;
use std::time::{Duration, Instant};
use x11rb::connection::Connection;

use x11rb::protocol::Event as XEvent;

pub(super) struct EventLoop {
// Using the trait object will be necessary when we add multi-window support anyway
handler: Box<dyn WindowHandler>,
window: Rc<Window>,

handle_receiver: Option<WindowHandleReceiver>,
parent_handle: Option<ParentHandle>,

new_physical_size: Option<PhySize>,
frame_interval: Duration,

event_loop_running: bool,
close_request_handled: bool,

new_size: Option<PhySize>,
}

impl EventLoop {
pub fn new(
window: Rc<Window>, handler: impl WindowHandler,
handle_receiver: Option<WindowHandleReceiver>,
window: Rc<Window>, handler: impl WindowHandler, parent_handle: Option<ParentHandle>,
) -> Self {
Self {
window,
handler: Box::new(handler),
handle_receiver,
parent_handle,
frame_interval: Duration::from_millis(15),
event_loop_running: false,
close_request_handled: false,
new_size: None,
new_physical_size: None,
}
}

#[inline]
fn drain_xcb_events(&mut self) -> Result<(), Box<dyn Error>> {
// the X server has a tendency to send spurious/extraneous configure notify events when a
// window is resized, and we need to batch those together and just send one resize event
// when they've all been coalesced.
self.new_physical_size = None;

while let Some(event) = self.window.xcb_connection.conn.poll_for_event()? {
self.handle_xcb_event(event);
}

if let Some(size) = self.new_physical_size.take() {
let window_info =
WindowInfo::from_physical_size(size, self.window.x11_window.dpi_scale_factor);

self.handler.on_event(Event::Window(WindowEvent::Resized(window_info)));
}

Ok(())
}

// Event loop
// FIXME: poll() acts fine on linux, sometimes funky on *BSD. XCB upstream uses a define to
// switch between poll() and select() (the latter of which is fine on *BSD), and we should do
// the same.
// NOTE: x11rb uses calloop under the hood, so that won't be an issue anymore once we switch to
// it
pub fn run(&mut self) -> Result<(), Box<dyn Error>> {
use nix::poll::*;

let xcb_fd = self.window.xcb_connection.file_descriptor();
let xcb_fd = self.window.xcb_connection.conn.as_raw_fd();

let mut last_frame = Instant::now();
self.event_loop_running = true;
Expand Down Expand Up @@ -95,40 +109,25 @@ impl EventLoop {
// FIXME: This will need to be changed from just setting an atomic to somehow
// synchronizing with the window being closed (using a synchronous channel, or
// by joining on the event loop thread).
if let Some(parent_handle) = &self.handle_receiver {
if parent_handle.close_requested() {
if let Some(parent_handle) = &self.parent_handle {
if parent_handle.parent_did_drop() {
self.handle_must_close();
self.window.close_requested.set(false);
}
}

// Check if the user has requested the window to close
if self.window.close_requested.get() {
self.handle_must_close();
self.window.close_requested.set(false);
}
}

Ok(())
}

fn handle_close_requested(&mut self) {
// FIXME: handler should decide whether window stays open or not
self.handle_must_close();
}

fn handle_must_close(&mut self) {
if self.close_request_handled {
return;
}
self.handler.on_event(Event::Window(WindowEvent::WillClose));

self.event_loop_running = false;
self.close_request_handled = true;
}

fn handle_xcb_event(&mut self, event: XEvent) {
let xcb_connection = &self.window.xcb_connection;

// For all of the keyboard and mouse events, you can fetch
// For all 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.
Expand All @@ -154,18 +153,21 @@ impl EventLoop {
////
XEvent::ClientMessage(event) => {
if event.format == 32
&& event.data.as_data32()[0] == xcb_connection.atoms.WM_DELETE_WINDOW
&& event.data.as_data32()[0]
== self.window.xcb_connection.atoms.WM_DELETE_WINDOW
{
self.handle_close_requested();
}
}

XEvent::ConfigureNotify(event) => {
let new_size = PhySize::new(event.width as u32, event.height as u32);
let new_physical_size = PhySize::new(event.width as u32, event.height as u32);

match self.new_size {
None => self.new_size = Some(new_size),
Some(s) if s != new_size => self.new_size = Some(new_size),
match self.new_physical_size {
None => self.new_physical_size = Some(new_physical_size),
Some(s) if s != new_physical_size => {
self.new_physical_size = Some(new_physical_size)
}
_ => {}
}
}
Expand Down Expand Up @@ -249,24 +251,15 @@ impl EventLoop {
}
}

fn drain_xcb_events(&mut self) -> Result<(), Box<dyn Error>> {
// the X server has a tendency to send spurious/extraneous configure notify events when a
// window is resized, and we need to batch those together and just send one resize event
// when they've all been coalesced.
self.new_size = None;

while let Some(event) = self.window.xcb_connection.conn.poll_for_event()? {
self.handle_xcb_event(event);
}

if let Some(size) = self.new_size.take() {
let window_info =
WindowInfo::from_physical_size(size, self.window.x11_window.dpi_scale_factor);
fn handle_close_requested(&mut self) {
// FIXME: handler should decide whether window stays open or not
self.handle_must_close();
}

self.handler.on_event(Event::Window(WindowEvent::Resized(window_info)));
}
fn handle_must_close(&mut self) {
self.handler.on_event(Event::Window(WindowEvent::WillClose));

Ok(())
self.event_loop_running = false;
}
}

Expand Down
8 changes: 4 additions & 4 deletions src/x11/handle.rs
Original file line number Diff line number Diff line change
Expand Up @@ -45,11 +45,11 @@ impl WindowHandle {
}

/// Receives the requests sent from the [`WindowHandle`]
pub struct WindowHandleReceiver {
pub struct ParentHandle {
shared: Arc<HandleShared>,
}

impl WindowHandleReceiver {
impl ParentHandle {
pub fn new() -> (Self, UninitializedWindowHandle) {
let shared = Arc::new(HandleShared {
close_requested: AtomicBool::new(false),
Expand All @@ -59,13 +59,13 @@ impl WindowHandleReceiver {
(Self { shared: shared.clone() }, UninitializedWindowHandle { shared })
}

pub fn close_requested(&self) -> bool {
pub fn parent_did_drop(&self) -> bool {
self.shared.close_requested.load(Ordering::Relaxed)
}
}

// Notify the external handles that the window has been closed
impl Drop for WindowHandleReceiver {
impl Drop for ParentHandle {
fn drop(&mut self) {
self.shared.is_open.store(false, Ordering::Relaxed);
}
Expand Down
7 changes: 3 additions & 4 deletions src/x11/window.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ use std::thread;
use raw_window_handle::{HasRawWindowHandle, RawDisplayHandle, RawWindowHandle, XcbWindowHandle};

use crate::x11::event_loop::EventLoop;
use crate::x11::handle::{WindowHandle, WindowHandleReceiver};
use crate::x11::handle::{ParentHandle, WindowHandle};
use crate::{Event, MouseCursor, Size, WindowEvent, WindowHandler, WindowInfo, WindowOpenOptions};

use crate::x11::x11_window::X11Window;
Expand Down Expand Up @@ -41,7 +41,7 @@ impl Window {

let (tx, rx) = mpsc::sync_channel::<XcbWindowHandle>(1);

let (parent_handle, window_handle) = WindowHandleReceiver::new();
let (parent_handle, window_handle) = ParentHandle::new();

// TODO: handle window creation errors
thread::spawn(move || {
Expand All @@ -64,8 +64,7 @@ impl Window {

fn window_thread<H, B>(
parent: Option<u32>, options: WindowOpenOptions, build: B,
tx: Option<mpsc::SyncSender<XcbWindowHandle>>,
handle_receiver: Option<WindowHandleReceiver>,
tx: Option<mpsc::SyncSender<XcbWindowHandle>>, handle_receiver: Option<ParentHandle>,
) -> Result<(), Box<dyn Error>>
where
H: WindowHandler,
Expand Down
5 changes: 0 additions & 5 deletions src/x11/xcb_connection.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ use std::cell::RefCell;
use std::collections::hash_map::{Entry, HashMap};
use std::error::Error;
use std::ffi::{c_int, c_void};
use std::os::fd::{AsRawFd, RawFd};

use x11::{xlib, xlib::Display, xlib_xcb};

Expand Down Expand Up @@ -125,10 +124,6 @@ impl XcbConnection {
&self.conn.setup().roots[self.screen]
}

pub fn file_descriptor(&self) -> RawFd {
self.conn.as_raw_fd()
}

pub fn raw_display_handle(&self) -> RawDisplayHandle {
let mut handle = XlibDisplayHandle::empty();

Expand Down

0 comments on commit 0b58445

Please sign in to comment.