@@ -4,6 +4,7 @@ use super::*;
44use std:: result:: Result ;
55
66use crate :: host:: HostMainThreadCaller ;
7+ use crate :: platform:: x11:: error:: FatalError ;
78use crate :: platform:: x11:: window_thread:: {
89 HostCallback , WindowThreadRequest , WindowThreadResponse , WindowThreadResponseMessage ,
910} ;
@@ -16,11 +17,36 @@ use calloop::{Interest, LoopSignal, Mode, PostAction};
1617use dpi:: { PhysicalPosition , PhysicalSize } ;
1718use std:: rc:: Rc ;
1819use std:: sync:: mpsc;
20+ use std:: sync:: mpsc:: Receiver ;
1921use std:: time:: { Duration , Instant } ;
2022use x11rb:: connection:: Connection ;
2123use x11rb:: errors:: ConnectionError ;
2224use x11rb:: protocol:: Event as XEvent ;
2325
26+ pub struct MainThreadCaller {
27+ sender : mpsc:: Sender < HostCallback > ,
28+ caller : Box < dyn HostMainThreadCaller > ,
29+ }
30+
31+ impl MainThreadCaller {
32+ pub ( crate ) fn new (
33+ main_thread : Option < Box < dyn HostMainThreadCaller > > ,
34+ ) -> ( Option < Self > , Option < Receiver < HostCallback > > ) {
35+ let Some ( main_thread) = main_thread else {
36+ return ( None , None ) ;
37+ } ;
38+
39+ let ( sender, receiver) = mpsc:: channel ( ) ;
40+ ( Some ( Self { sender, caller : main_thread } ) , Some ( receiver) )
41+ }
42+
43+ pub fn send ( & mut self , msg : HostCallback ) -> Result < ( ) , FatalError > {
44+ self . sender . send ( msg) . map_err ( |_| FatalError :: SendMainThread ) ?;
45+ self . caller . call_main_thread ( ) ;
46+ Ok ( ( ) )
47+ }
48+ }
49+
2450pub ( crate ) struct EventLoop {
2551 handler : Box < dyn WindowHandler > ,
2652 window : Rc < WindowInner > ,
@@ -35,8 +61,7 @@ pub(crate) struct EventLoop {
3561 run_error : Option < Error > ,
3662
3763 response_sender : mpsc:: Sender < WindowThreadResponseMessage > ,
38- callback_sender : mpsc:: Sender < HostCallback > ,
39- main_thread_caller : Option < Box < dyn HostMainThreadCaller > > ,
64+ main_thread : Option < MainThreadCaller > ,
4065}
4166
4267const FRAME_INTERVAL : Duration = Duration :: from_millis ( 15 ) ;
@@ -46,9 +71,7 @@ impl EventLoop {
4671 window : Rc < WindowInner > , handler : Box < dyn WindowHandler > ,
4772 request_receiver : calloop:: channel:: Channel < WindowThreadRequest > ,
4873 response_sender : mpsc:: Sender < WindowThreadResponseMessage > ,
49- callback_sender : mpsc:: Sender < HostCallback > ,
50- main_thread_caller : Option < Box < dyn HostMainThreadCaller > > ,
51- inner : & mut calloop:: EventLoop < ' static , Self > ,
74+ main_thread : Option < MainThreadCaller > , inner : & mut calloop:: EventLoop < ' static , Self > ,
5275 ) -> Result < Self , Error > {
5376 let loop_handle = inner. handle ( ) ;
5477
@@ -74,16 +97,15 @@ impl EventLoop {
7497 drag_n_drop : DragNDropState :: NoCurrentSession ,
7598 xkb_state : XkbcommonState :: new ( & window. connection ) ,
7699 run_error : None ,
77- callback_sender,
78- main_thread_caller,
100+ main_thread,
79101
80102 window,
81103 response_sender,
82104 } )
83105 }
84106
85107 #[ inline]
86- fn drain_xcb_events ( & mut self ) -> Result < ( ) , ConnectionError > {
108+ fn drain_xcb_events ( & mut self ) -> Result < ( ) , FatalError > {
87109 // the X server has a tendency to send spurious/extraneous configure notify events when a
88110 // window is resized, and we need to batch those together and just send one resize event
89111 // when they've all been coalesced.
@@ -93,28 +115,31 @@ impl EventLoop {
93115 self . handle_xcb_event ( event) ?;
94116 }
95117
96- if let Some ( size) = self . new_physical_size . take ( ) {
97- let previous = self . window . store_size ( size) ;
98-
99- let scale_factor = self . window . scaling_factor . get ( ) ;
100- let new_size = WindowSize :: from_physical ( size. cast ( ) , scale_factor) ;
101-
102- if let Err ( e) = self . handler . resized ( new_size) {
103- warn ! ( "Window Handler failed to resize: {}" , e) ;
104- self . window . store_size ( previous) ;
105- self . window . xcb_window . resize ( previous. cast ( ) ) ?. check_warn ( ) ;
106- } else {
107- // TODO: only if this wansn't the result of a host request
108- // TODO: do not allocate channel if no host callback is present
109- if let Some ( main_thread) = self . main_thread_caller . as_mut ( ) {
110- self . callback_sender
111- . send ( HostCallback :: Resized {
112- new_size,
113- previous : WindowSize :: from_physical ( previous. cast ( ) , scale_factor) ,
114- } )
115- . unwrap ( ) ; // TODO: unwrap
116- main_thread. call_main_thread ( ) ;
117- }
118+ self . handle_coalesced_resize_events ( )
119+ }
120+
121+ fn handle_coalesced_resize_events ( & mut self ) -> Result < ( ) , FatalError > {
122+ let Some ( new_size) = self . new_physical_size . take ( ) else { return Ok ( ( ) ) } ;
123+ let previous = self . window . store_size ( new_size) ;
124+
125+ if previous == new_size {
126+ return Ok ( ( ) ) ;
127+ } ;
128+
129+ let scale_factor = self . window . scaling_factor . get ( ) ;
130+ let new_size = WindowSize :: from_physical ( new_size. cast ( ) , scale_factor) ;
131+
132+ if let Err ( e) = self . handler . resized ( new_size) {
133+ warn ! ( "Window Handler failed to resize: {}" , e) ;
134+ self . window . store_size ( previous) ;
135+ self . window . xcb_window . resize ( previous. cast ( ) ) ?. check_warn ( ) ;
136+ } else {
137+ // TODO: only if this wansn't the result of a host request
138+ if let Some ( host) = self . main_thread . as_mut ( ) {
139+ host. send ( HostCallback :: Resized {
140+ new_size,
141+ previous : WindowSize :: from_physical ( previous. cast ( ) , scale_factor) ,
142+ } ) ?;
118143 }
119144 }
120145
@@ -177,7 +202,7 @@ impl EventLoop {
177202 }
178203 }
179204
180- fn handle_connection_event_ready ( & mut self ) -> Result < PostAction , ConnectionError > {
205+ fn handle_connection_event_ready ( & mut self ) -> Result < PostAction , FatalError > {
181206 self . drain_xcb_events ( ) ?;
182207
183208 Ok ( PostAction :: Continue )
@@ -214,6 +239,15 @@ impl EventLoop {
214239
215240 self . handle_event ( Event :: Window ( WindowEvent :: WillClose ) ) ;
216241
242+ // If the event loop doesn't stop because the host asked it to, then we should notify it
243+ if !self . window . main_thread_shared . is_stop_host_requested ( ) {
244+ if let Some ( main_thread) = self . main_thread . as_mut ( ) {
245+ if let Err ( e) = main_thread. send ( HostCallback :: Destroyed ) {
246+ warn ! ( "Could not notify host that X11 thread is stopping: {}" , e)
247+ }
248+ }
249+ }
250+
217251 if let Some ( err) = self . run_error {
218252 return Err ( err) ;
219253 } ;
0 commit comments