Skip to content

Commit fd69f5c

Browse files
committed
wip
1 parent 58ed420 commit fd69f5c

4 files changed

Lines changed: 72 additions & 39 deletions

File tree

src/platform/x11/error.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ use x11rb::x11_utils::{TryParse, X11Error};
1313
#[derive(Debug)]
1414
pub enum Error {
1515
CreationFailed(String),
16+
RunError(String),
1617
Io(std::io::Error),
1718
DylibOpen(OpenError),
1819
InitThreadsFailed(InitThreadsFailedError),

src/platform/x11/event_loop.rs

Lines changed: 15 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,13 @@ use super::keyboard::{convert_key_press_event, convert_key_release_event, key_mo
33
use super::*;
44
use std::result::Result;
55

6+
use crate::platform::x11::window_thread::WindowThreadShared;
67
use crate::warn;
78
use crate::wrappers::xkbcommon::XkbcommonState;
89
use crate::{Event, MouseButton, MouseEvent, ScrollDelta, WindowEvent, WindowHandler, WindowSize};
910
use calloop::generic::Generic;
1011
use calloop::timer::{TimeoutAction, Timer};
11-
use calloop::{Interest, LoopHandle, LoopSignal, Mode, PostAction, RegistrationToken};
12+
use calloop::{Interest, LoopSignal, Mode, PostAction};
1213
use dpi::{PhysicalPosition, PhysicalSize};
1314
use std::rc::Rc;
1415
use std::time::{Duration, Instant};
@@ -22,23 +23,25 @@ pub(crate) struct EventLoop {
2223

2324
new_physical_size: Option<PhysicalSize<u16>>,
2425

25-
frame_timer: RegistrationToken,
26-
loop_handle: LoopHandle<'static, Self>,
2726
loop_signal: LoopSignal,
2827

2928
drag_n_drop: DragNDropState,
3029
xkb_state: Option<XkbcommonState>,
30+
31+
run_error: Option<Error>,
32+
pub(crate) shared: Arc<WindowThreadShared>,
3133
}
3234

3335
const FRAME_INTERVAL: Duration = Duration::from_millis(15);
3436

3537
impl EventLoop {
3638
pub fn new(
37-
window: Rc<WindowInner>, handler: Box<dyn WindowHandler>,
39+
window: Rc<WindowInner>, handler: Box<dyn WindowHandler>, shared: Arc<WindowThreadShared>,
3840
inner: &mut calloop::EventLoop<'static, Self>,
3941
) -> Result<Self, Error> {
4042
let loop_handle = inner.handle();
41-
let frame_timer = loop_handle
43+
44+
loop_handle
4245
.insert_source(Timer::from_duration(FRAME_INTERVAL), |i, _, e| e.handle_frame(i))
4346
.map_err(|e| e.error)?;
4447

@@ -50,13 +53,13 @@ impl EventLoop {
5053
.map_err(|e| e.error)?;
5154

5255
Ok(Self {
53-
loop_handle,
5456
loop_signal: inner.get_signal(),
5557
handler,
56-
frame_timer,
5758
new_physical_size: None,
5859
drag_n_drop: DragNDropState::NoCurrentSession,
5960
xkb_state: XkbcommonState::new(&window.connection),
61+
run_error: None,
62+
shared,
6063
window,
6164
})
6265
}
@@ -100,7 +103,7 @@ impl EventLoop {
100103

101104
fn handle_frame(&mut self, previous_deadline: Instant) -> TimeoutAction {
102105
if let Err(e) = self.handler.on_frame() {
103-
// TODO: properly log/bubble up error
106+
self.run_error = Some(e.into());
104107
self.loop_signal.stop();
105108
return TimeoutAction::Drop;
106109
}
@@ -129,6 +132,10 @@ impl EventLoop {
129132

130133
self.handle_event(Event::Window(WindowEvent::WillClose));
131134

135+
if let Some(err) = self.run_error {
136+
return Err(err);
137+
};
138+
132139
Ok(())
133140
}
134141

src/platform/x11/window_thread.rs

Lines changed: 53 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -8,13 +8,24 @@ use std::cell::Cell;
88
use std::num::NonZeroU32;
99
use std::panic::resume_unwind;
1010
use std::rc::Rc;
11-
use std::sync::mpsc;
11+
use std::sync::atomic::{AtomicBool, Ordering};
12+
use std::sync::{mpsc, Mutex};
1213
use std::thread;
1314
use std::thread::JoinHandle;
14-
use std::time::Duration;
15+
16+
pub(crate) struct WindowThreadShared {
17+
stopped: AtomicBool,
18+
final_error: Mutex<Option<String>>,
19+
}
20+
21+
impl WindowThreadShared {
22+
pub fn new() -> Self {
23+
Self { stopped: false.into(), final_error: None.into() }
24+
}
25+
}
1526

1627
pub struct WindowThreadHandle {
17-
window_id: NonZeroU32,
28+
shared: Arc<WindowThreadShared>,
1829
loop_signal: LoopSignal,
1930
event_loop_handle: Cell<Option<JoinHandle<()>>>,
2031
}
@@ -24,33 +35,42 @@ impl WindowThreadHandle {
2435
options: WindowOpenOptions, handler: WindowHandlerBuilder,
2536
) -> Result<Self> {
2637
let (tx, rx) = result_channel();
38+
let shared = Arc::new(WindowThreadShared::new());
2739

28-
let join_handle = thread::spawn(move || {
29-
let thread = match WindowThread::create(options, handler) {
30-
Err(e) => return tx.send_error(e),
31-
Ok(thread) => thread,
32-
};
40+
let join_handle = {
41+
let shared = shared.clone();
3342

34-
if tx.send_success(&thread) {
35-
thread.run()
36-
}
37-
});
43+
thread::spawn(move || {
44+
let thread = match WindowThread::create(options, handler, shared) {
45+
Err(e) => return tx.send_error(e),
46+
Ok(thread) => thread,
47+
};
3848

39-
thread::sleep(Duration::from_millis(2000));
49+
if tx.send_success(&thread) {
50+
thread.run()
51+
}
52+
})
53+
};
4054

41-
rx.receive(join_handle)
55+
rx.receive(join_handle, shared)
4256
}
4357

44-
pub fn run_until_closed(&self) {
45-
let Some(thread) = self.event_loop_handle.take() else { return };
58+
pub fn run_until_closed(&self) -> Result<()> {
59+
let Some(thread) = self.event_loop_handle.take() else { return Ok(()) };
4660

4761
if let Err(panic) = thread.join() {
4862
resume_unwind(panic);
4963
}
64+
65+
if let Some(e) = self.shared.final_error.lock().unwrap().take() {
66+
return Err(Error::RunError(e));
67+
}
68+
69+
Ok(())
5070
}
5171

5272
pub fn is_open(&self) -> bool {
53-
todo!()
73+
!self.shared.stopped.load(Ordering::Relaxed)
5474
}
5575
}
5676

@@ -64,27 +84,32 @@ impl Drop for WindowThreadHandle {
6484
}
6585

6686
enum WindowOpenResult {
67-
Success { window_id: NonZeroU32, loop_signal: LoopSignal },
87+
Success { loop_signal: LoopSignal },
6888
Error(String),
6989
}
7090

7191
struct WindowThread {
7292
event_loop: EventLoop,
7393
ev_loop: calloop::EventLoop<'static, EventLoop>,
94+
shared: Arc<WindowThreadShared>,
7495
}
7596

7697
impl WindowThread {
77-
pub fn create(options: WindowOpenOptions, handler: WindowHandlerBuilder) -> Result<Self> {
98+
pub fn create(
99+
options: WindowOpenOptions, handler: WindowHandlerBuilder, shared: Arc<WindowThreadShared>,
100+
) -> Result<Self> {
78101
let mut ev_loop = calloop::EventLoop::try_new()?;
79102
let inner = WindowInner::create(options, &ev_loop)?;
80103
let handler = handler.build(WindowContext::new(Rc::clone(&inner)))?;
81-
let event_loop = EventLoop::new(inner, handler, &mut ev_loop)?;
104+
let event_loop = EventLoop::new(inner, handler, shared.clone(), &mut ev_loop)?;
82105

83-
Ok(Self { event_loop, ev_loop })
106+
Ok(Self { event_loop, ev_loop, shared })
84107
}
85108

86109
pub fn run(self) {
87-
self.event_loop.run(self.ev_loop).unwrap();
110+
if let Err(e) = self.event_loop.run(self.ev_loop) {
111+
self.shared.final_error.lock().unwrap().replace(e.to_string());
112+
}
88113
}
89114
}
90115

@@ -103,10 +128,7 @@ impl WindowResultSender {
103128
}
104129

105130
pub fn send_success(self, thread: &WindowThread) -> bool {
106-
let msg = WindowOpenResult::Success {
107-
loop_signal: thread.ev_loop.get_signal(),
108-
window_id: thread.event_loop.window_id(),
109-
};
131+
let msg = WindowOpenResult::Success { loop_signal: thread.ev_loop.get_signal() };
110132

111133
if let Err(err) = self.0.send(msg) {
112134
crate::error!("Failed to send created window to main thread: {}. Aborting.", err);
@@ -119,13 +141,15 @@ impl WindowResultSender {
119141

120142
struct WindowResultReceiver(mpsc::Receiver<WindowOpenResult>);
121143
impl WindowResultReceiver {
122-
pub fn receive(self, join_handle: JoinHandle<()>) -> Result<WindowThreadHandle> {
144+
pub fn receive(
145+
self, join_handle: JoinHandle<()>, shared: Arc<WindowThreadShared>,
146+
) -> Result<WindowThreadHandle> {
123147
let result = self.0.recv()?;
124148
match result {
125149
WindowOpenResult::Error(e) => Err(Error::CreationFailed(e)),
126-
WindowOpenResult::Success { window_id, loop_signal } => Ok(WindowThreadHandle {
150+
WindowOpenResult::Success { loop_signal } => Ok(WindowThreadHandle {
127151
event_loop_handle: Some(join_handle).into(),
128-
window_id,
152+
shared,
129153
loop_signal,
130154
}),
131155
}

src/window.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,9 @@ impl WindowHandle {
1515
Self { window_handle, phantom: PhantomData }
1616
}
1717

18-
pub fn run_until_closed(self) {
19-
self.window_handle.run_until_closed()
18+
pub fn run_until_closed(self) -> Result<(), Error> {
19+
self.window_handle.run_until_closed()?;
20+
Ok(())
2021
}
2122

2223
/// Close the window

0 commit comments

Comments
 (0)