From 59a31051ec79277cfcd2186e8e735821bcea256e Mon Sep 17 00:00:00 2001 From: Quant1um Date: Mon, 21 Jul 2025 20:51:15 +0400 Subject: [PATCH 1/2] sync close request with the event loop on linux --- src/x11/window.rs | 20 +++++++------------- 1 file changed, 7 insertions(+), 13 deletions(-) diff --git a/src/x11/window.rs b/src/x11/window.rs index ca4db3cd..eda3260f 100644 --- a/src/x11/window.rs +++ b/src/x11/window.rs @@ -31,19 +31,13 @@ use crate::x11::visual_info::WindowVisualConfig; pub struct WindowHandle { raw_window_handle: Option, - close_requested: Arc, + close_requested: mpsc::SyncSender<()>, is_open: Arc, } impl WindowHandle { pub fn close(&mut self) { - if self.raw_window_handle.take().is_some() { - // 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). - - self.close_requested.store(true, Ordering::Relaxed); - } + self.close_requested.send(()).ok(); } pub fn is_open(&self) -> bool { @@ -64,26 +58,26 @@ unsafe impl HasRawWindowHandle for WindowHandle { } pub(crate) struct ParentHandle { - close_requested: Arc, + close_requested: mpsc::Receiver<()>, is_open: Arc, } impl ParentHandle { pub fn new() -> (Self, WindowHandle) { - let close_requested = Arc::new(AtomicBool::new(false)); + let (close_sender, close_receiver) = mpsc::sync_channel(0); let is_open = Arc::new(AtomicBool::new(true)); let handle = WindowHandle { raw_window_handle: None, - close_requested: Arc::clone(&close_requested), + close_requested: close_sender, is_open: Arc::clone(&is_open), }; - (Self { close_requested, is_open }, handle) + (Self { close_requested: close_receiver, is_open }, handle) } pub fn parent_did_drop(&self) -> bool { - self.close_requested.load(Ordering::Relaxed) + self.close_requested.try_recv().is_ok() } } From 5243415134a572e9f84d68f7f7934db7e02b966a Mon Sep 17 00:00:00 2001 From: Quant1um Date: Mon, 17 Nov 2025 01:02:31 +0400 Subject: [PATCH 2/2] x11: WindowHandle::close sync via JoinHandle --- src/x11/event_loop.rs | 4 ---- src/x11/window.rs | 28 +++++++++++++++------------- 2 files changed, 15 insertions(+), 17 deletions(-) diff --git a/src/x11/event_loop.rs b/src/x11/event_loop.rs index 6b6ecd30..53375d6c 100644 --- a/src/x11/event_loop.rs +++ b/src/x11/event_loop.rs @@ -108,10 +108,6 @@ impl EventLoop { // Check if the parents's handle was dropped (such as when the host // requested the window to close) - // - // 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.parent_handle { if parent_handle.parent_did_drop() { self.handle_must_close(); diff --git a/src/x11/window.rs b/src/x11/window.rs index eda3260f..e556fe20 100644 --- a/src/x11/window.rs +++ b/src/x11/window.rs @@ -4,7 +4,7 @@ use std::ffi::c_void; use std::sync::atomic::{AtomicBool, Ordering}; use std::sync::mpsc; use std::sync::Arc; -use std::thread; +use std::thread::{self, JoinHandle}; use raw_window_handle::{ HasRawDisplayHandle, HasRawWindowHandle, RawDisplayHandle, RawWindowHandle, XlibDisplayHandle, @@ -31,13 +31,17 @@ use crate::x11::visual_info::WindowVisualConfig; pub struct WindowHandle { raw_window_handle: Option, - close_requested: mpsc::SyncSender<()>, + event_loop_handle: Option>, + close_requested: Arc, is_open: Arc, } impl WindowHandle { pub fn close(&mut self) { - self.close_requested.send(()).ok(); + self.close_requested.store(true, Ordering::Relaxed); + if let Some(event_loop) = self.event_loop_handle.take() { + let _ = event_loop.join(); + } } pub fn is_open(&self) -> bool { @@ -58,26 +62,26 @@ unsafe impl HasRawWindowHandle for WindowHandle { } pub(crate) struct ParentHandle { - close_requested: mpsc::Receiver<()>, + close_requested: Arc, is_open: Arc, } impl ParentHandle { pub fn new() -> (Self, WindowHandle) { - let (close_sender, close_receiver) = mpsc::sync_channel(0); + let close_requested = Arc::new(AtomicBool::new(false)); let is_open = Arc::new(AtomicBool::new(true)); - let handle = WindowHandle { raw_window_handle: None, - close_requested: close_sender, + event_loop_handle: None, + close_requested: Arc::clone(&close_requested), is_open: Arc::clone(&is_open), }; - (Self { close_requested: close_receiver, is_open }, handle) + (Self { close_requested, is_open }, handle) } pub fn parent_did_drop(&self) -> bool { - self.close_requested.try_recv().is_ok() + self.close_requested.load(Ordering::Relaxed) } } @@ -128,17 +132,15 @@ impl<'a> Window<'a> { }; let (tx, rx) = mpsc::sync_channel::(1); - let (parent_handle, mut window_handle) = ParentHandle::new(); - - thread::spawn(move || { + let join_handle = thread::spawn(move || { Self::window_thread(Some(parent_id), options, build, tx.clone(), Some(parent_handle)) .unwrap(); }); let raw_window_handle = rx.recv().unwrap().unwrap(); window_handle.raw_window_handle = Some(raw_window_handle.0); - + window_handle.event_loop_handle = Some(join_handle); window_handle }