1+ use crate :: x11:: handle:: ParentHandle ;
12use crate :: x11:: keyboard:: { convert_key_press_event, convert_key_release_event, key_mods} ;
2- use crate :: x11:: { ParentHandle , Window , WindowInner } ;
3+ use crate :: x11:: Window ;
34use crate :: {
45 Event , MouseButton , MouseEvent , PhyPoint , PhySize , ScrollDelta , WindowEvent , WindowHandler ,
56 WindowInfo ,
67} ;
78use std:: error:: Error ;
9+ use std:: os:: fd:: AsRawFd ;
810use std:: rc:: Rc ;
911use std:: time:: { Duration , Instant } ;
1012use x11rb:: connection:: Connection ;
11-
1213use x11rb:: protocol:: Event as XEvent ;
1314
1415pub ( super ) struct EventLoop {
15- // Using the trait object will be necessary when we add multi-window support anyway
1616 handler : Box < dyn WindowHandler > ,
1717 window : Rc < Window > ,
1818
19- handle_receiver : Option < WindowHandleReceiver > ,
19+ parent_handle : Option < ParentHandle > ,
2020
21+ new_physical_size : Option < PhySize > ,
2122 frame_interval : Duration ,
22-
2323 event_loop_running : bool ,
24- close_request_handled : bool ,
25-
26- new_size : Option < PhySize > ,
2724}
2825
2926impl EventLoop {
3027 pub fn new (
31- window : Rc < Window > , handler : impl WindowHandler ,
32- handle_receiver : Option < WindowHandleReceiver > ,
28+ window : Rc < Window > , handler : impl WindowHandler , parent_handle : Option < ParentHandle > ,
3329 ) -> Self {
3430 Self {
3531 window,
3632 handler : Box :: new ( handler) ,
37- handle_receiver ,
33+ parent_handle ,
3834 frame_interval : Duration :: from_millis ( 15 ) ,
3935 event_loop_running : false ,
40- close_request_handled : false ,
41- new_size : None ,
36+ new_physical_size : None ,
37+ }
38+ }
39+
40+ #[ inline]
41+ fn drain_xcb_events ( & mut self ) -> Result < ( ) , Box < dyn Error > > {
42+ // the X server has a tendency to send spurious/extraneous configure notify events when a
43+ // window is resized, and we need to batch those together and just send one resize event
44+ // when they've all been coalesced.
45+ self . new_physical_size = None ;
46+
47+ while let Some ( event) = self . window . xcb_connection . conn . poll_for_event ( ) ? {
48+ self . handle_xcb_event ( event) ;
49+ }
50+
51+ if let Some ( size) = self . new_physical_size . take ( ) {
52+ let window_info =
53+ WindowInfo :: from_physical_size ( size, self . window . x11_window . dpi_scale_factor ) ;
54+
55+ self . handler . on_event ( Event :: Window ( WindowEvent :: Resized ( window_info) ) ) ;
4256 }
57+
58+ Ok ( ( ) )
4359 }
4460
4561 // Event loop
4662 // FIXME: poll() acts fine on linux, sometimes funky on *BSD. XCB upstream uses a define to
4763 // switch between poll() and select() (the latter of which is fine on *BSD), and we should do
4864 // the same.
49- // NOTE: x11rb uses calloop under the hood, so that won't be an issue anymore once we switch to
50- // it
5165 pub fn run ( & mut self ) -> Result < ( ) , Box < dyn Error > > {
5266 use nix:: poll:: * ;
5367
54- let xcb_fd = self . window . xcb_connection . file_descriptor ( ) ;
68+ let xcb_fd = self . window . xcb_connection . conn . as_raw_fd ( ) ;
5569
5670 let mut last_frame = Instant :: now ( ) ;
5771 self . event_loop_running = true ;
@@ -95,40 +109,25 @@ impl EventLoop {
95109 // FIXME: This will need to be changed from just setting an atomic to somehow
96110 // synchronizing with the window being closed (using a synchronous channel, or
97111 // by joining on the event loop thread).
98- if let Some ( parent_handle) = & self . handle_receiver {
99- if parent_handle. close_requested ( ) {
112+ if let Some ( parent_handle) = & self . parent_handle {
113+ if parent_handle. parent_did_drop ( ) {
100114 self . handle_must_close ( ) ;
115+ self . window . close_requested . set ( false ) ;
101116 }
102117 }
103118
104119 // Check if the user has requested the window to close
105120 if self . window . close_requested . get ( ) {
106121 self . handle_must_close ( ) ;
122+ self . window . close_requested . set ( false ) ;
107123 }
108124 }
109125
110126 Ok ( ( ) )
111127 }
112128
113- fn handle_close_requested ( & mut self ) {
114- // FIXME: handler should decide whether window stays open or not
115- self . handle_must_close ( ) ;
116- }
117-
118- fn handle_must_close ( & mut self ) {
119- if self . close_request_handled {
120- return ;
121- }
122- self . handler . on_event ( Event :: Window ( WindowEvent :: WillClose ) ) ;
123-
124- self . event_loop_running = false ;
125- self . close_request_handled = true ;
126- }
127-
128129 fn handle_xcb_event ( & mut self , event : XEvent ) {
129- let xcb_connection = & self . window . xcb_connection ;
130-
131- // For all of the keyboard and mouse events, you can fetch
130+ // For all the keyboard and mouse events, you can fetch
132131 // `x`, `y`, `detail`, and `state`.
133132 // - `x` and `y` are the position inside the window where the cursor currently is
134133 // when the event happened.
@@ -154,18 +153,21 @@ impl EventLoop {
154153 ////
155154 XEvent :: ClientMessage ( event) => {
156155 if event. format == 32
157- && event. data . as_data32 ( ) [ 0 ] == xcb_connection. atoms . WM_DELETE_WINDOW
156+ && event. data . as_data32 ( ) [ 0 ]
157+ == self . window . xcb_connection . atoms . WM_DELETE_WINDOW
158158 {
159159 self . handle_close_requested ( ) ;
160160 }
161161 }
162162
163163 XEvent :: ConfigureNotify ( event) => {
164- let new_size = PhySize :: new ( event. width as u32 , event. height as u32 ) ;
164+ let new_physical_size = PhySize :: new ( event. width as u32 , event. height as u32 ) ;
165165
166- match self . new_size {
167- None => self . new_size = Some ( new_size) ,
168- Some ( s) if s != new_size => self . new_size = Some ( new_size) ,
166+ match self . new_physical_size {
167+ None => self . new_physical_size = Some ( new_physical_size) ,
168+ Some ( s) if s != new_physical_size => {
169+ self . new_physical_size = Some ( new_physical_size)
170+ }
169171 _ => { }
170172 }
171173 }
@@ -249,24 +251,15 @@ impl EventLoop {
249251 }
250252 }
251253
252- fn drain_xcb_events ( & mut self ) -> Result < ( ) , Box < dyn Error > > {
253- // the X server has a tendency to send spurious/extraneous configure notify events when a
254- // window is resized, and we need to batch those together and just send one resize event
255- // when they've all been coalesced.
256- self . new_size = None ;
257-
258- while let Some ( event) = self . window . xcb_connection . conn . poll_for_event ( ) ? {
259- self . handle_xcb_event ( event) ;
260- }
261-
262- if let Some ( size) = self . new_size . take ( ) {
263- let window_info =
264- WindowInfo :: from_physical_size ( size, self . window . x11_window . dpi_scale_factor ) ;
254+ fn handle_close_requested ( & mut self ) {
255+ // FIXME: handler should decide whether window stays open or not
256+ self . handle_must_close ( ) ;
257+ }
265258
266- self . handler . on_event ( Event :: Window ( WindowEvent :: Resized ( window_info ) ) ) ;
267- }
259+ fn handle_must_close ( & mut self ) {
260+ self . handler . on_event ( Event :: Window ( WindowEvent :: WillClose ) ) ;
268261
269- Ok ( ( ) )
262+ self . event_loop_running = false ;
270263 }
271264}
272265
0 commit comments