Skip to content

Commit 2c18b80

Browse files
committed
Fix thread executor not executing closure when called from non-loop thread
1 parent 5a3a5e2 commit 2c18b80

File tree

1 file changed

+18
-13
lines changed

1 file changed

+18
-13
lines changed

src/platform_impl/windows/event_loop.rs

+18-13
Original file line numberDiff line numberDiff line change
@@ -140,15 +140,14 @@ impl<T> ThreadMsgTargetSubclassInput<T> {
140140
}
141141

142142
pub struct EventLoop<T: 'static> {
143-
// Id of the background thread from the Win32 API.
144-
thread_msg_target: HWND,
145143
thread_msg_sender: Sender<T>,
146144
window_target: RootELW<T>
147145
}
148146

149147
pub struct EventLoopWindowTarget<T> {
150148
thread_id: DWORD,
151149
trigger_newevents_on_redraw: Arc<AtomicBool>,
150+
thread_msg_target: HWND,
152151
pub(crate) runner_shared: EventLoopRunnerShared<T>,
153152
}
154153

@@ -172,11 +171,12 @@ impl<T: 'static> EventLoop<T> {
172171
let (thread_msg_target, thread_msg_sender) = thread_event_target_window(runner_shared.clone());
173172

174173
EventLoop {
175-
thread_msg_target, thread_msg_sender,
174+
thread_msg_sender,
176175
window_target: RootELW {
177176
p: EventLoopWindowTarget {
178177
thread_id,
179178
trigger_newevents_on_redraw: Arc::new(AtomicBool::new(true)),
179+
thread_msg_target,
180180
runner_shared
181181
},
182182
_marker: PhantomData
@@ -261,7 +261,7 @@ impl<T: 'static> EventLoop<T> {
261261

262262
pub fn create_proxy(&self) -> EventLoopProxy<T> {
263263
EventLoopProxy {
264-
target_window: self.thread_msg_target,
264+
target_window: self.window_target.p.thread_msg_target,
265265
event_send: self.thread_msg_sender.clone()
266266
}
267267
}
@@ -272,7 +272,8 @@ impl<T> EventLoopWindowTarget<T> {
272272
pub(crate) fn create_thread_executor(&self) -> EventLoopThreadExecutor {
273273
EventLoopThreadExecutor {
274274
thread_id: self.thread_id,
275-
trigger_newevents_on_redraw: self.trigger_newevents_on_redraw.clone()
275+
trigger_newevents_on_redraw: self.trigger_newevents_on_redraw.clone(),
276+
target_window: self.thread_msg_target
276277
}
277278
}
278279
}
@@ -327,7 +328,7 @@ impl<T> EventLoopRunner<T> {
327328
control_flow: ControlFlow::default(),
328329
runner_state: RunnerState::New,
329330
in_modal_loop: false,
330-
modal_redraw_window: event_loop.thread_msg_target,
331+
modal_redraw_window: event_loop.window_target.p.thread_msg_target,
331332
event_handler: mem::transmute::<
332333
Box<FnMut(Event<T>, &mut ControlFlow)>,
333334
Box<FnMut(Event<T>, &mut ControlFlow)>
@@ -558,16 +559,20 @@ fn dur2timeout(dur: Duration) -> DWORD {
558559
impl<T> Drop for EventLoop<T> {
559560
fn drop(&mut self) {
560561
unsafe {
561-
winuser::DestroyWindow(self.thread_msg_target);
562+
winuser::DestroyWindow(self.window_target.p.thread_msg_target);
562563
}
563564
}
564565
}
565566

566567
pub(crate) struct EventLoopThreadExecutor {
567568
thread_id: DWORD,
568-
trigger_newevents_on_redraw: Arc<AtomicBool>
569+
trigger_newevents_on_redraw: Arc<AtomicBool>,
570+
target_window: HWND
569571
}
570572

573+
unsafe impl Send for EventLoopThreadExecutor {}
574+
unsafe impl Sync for EventLoopThreadExecutor {}
575+
571576
impl EventLoopThreadExecutor {
572577
/// Check to see if we're in the parent event loop's thread.
573578
pub(super) fn in_event_loop_thread(&self) -> bool {
@@ -605,11 +610,11 @@ impl EventLoopThreadExecutor {
605610

606611
let raw = Box::into_raw(boxed2);
607612

608-
let res = winuser::PostThreadMessageA(self.thread_id, *EXEC_MSG_ID,
609-
raw as *mut () as usize as WPARAM, 0);
610-
// PostThreadMessage can only fail if the thread ID is invalid (which shouldn't happen
611-
// as the events loop is still alive) or if the queue is full.
612-
assert!(res != 0, "PostThreadMessage failed ; is the messages queue full?");
613+
let res = winuser::PostMessageW(
614+
self.target_window, *EXEC_MSG_ID,
615+
raw as *mut () as usize as WPARAM, 0
616+
);
617+
assert!(res != 0, "PostMessage failed ; is the messages queue full?");
613618
}
614619
}
615620
}

0 commit comments

Comments
 (0)