1
1
use crate :: select:: handle_select;
2
+ use raw_window_handle:: { HasRawDisplayHandle , RawDisplayHandle } ;
2
3
use std:: {
3
- sync:: Mutex ,
4
+ cell:: RefCell ,
5
+ sync:: { Arc , Mutex } ,
4
6
time:: { Duration , Instant } ,
5
7
} ;
6
8
@@ -17,7 +19,7 @@ use copypasta::{
17
19
18
20
use libc:: { c_void, fd_set, pselect, sigset_t, timespec} ;
19
21
use once_cell:: sync:: Lazy ;
20
- #[ cfg( wayland_platform ) ]
22
+ #[ cfg( free_unix ) ]
21
23
use winit:: platform:: wayland:: EventLoopWindowTargetExtWayland ;
22
24
use winit:: {
23
25
event:: { Event , StartCause , WindowEvent } ,
@@ -49,7 +51,7 @@ unsafe impl Send for Platform {}
49
51
50
52
pub struct WrEventLoop {
51
53
clipboard : Box < dyn ClipboardProvider > ,
52
- pub el : EventLoop < i32 > ,
54
+ el : EventLoop < i32 > ,
53
55
pub connection : Option < Connection > ,
54
56
}
55
57
@@ -61,19 +63,16 @@ impl WrEventLoop {
61
63
& self . el
62
64
}
63
65
64
- pub fn connection ( & mut self ) -> & Connection {
65
- if self . connection . is_none ( ) {
66
- self . open_native_display ( ) ;
67
- }
68
- self . connection . as_ref ( ) . unwrap ( )
69
- }
70
-
71
66
pub fn create_proxy ( & self ) -> EventLoopProxy < i32 > {
72
67
self . el . create_proxy ( )
73
68
}
74
69
75
- pub fn new_webrender_surfman ( & mut self , window : & Window ) -> WebrenderSurfman {
76
- let connection = self . connection ( ) ;
70
+ pub fn new_webrender_surfman (
71
+ & mut self ,
72
+ window : & Window ,
73
+ connection : Option < & Connection > ,
74
+ ) -> WebrenderSurfman {
75
+ let connection = connection. expect ( "device not open" ) ;
77
76
let adapter = connection
78
77
. create_adapter ( )
79
78
. expect ( "Failed to create adapter" ) ;
@@ -87,17 +86,16 @@ impl WrEventLoop {
87
86
webrender_surfman
88
87
}
89
88
90
- pub fn open_native_display ( & mut self ) -> & Option < Connection > {
89
+ pub fn open_native_display ( & mut self ) -> ( Connection , RawDisplayHandle ) {
91
90
let window_builder = winit:: window:: WindowBuilder :: new ( ) . with_visible ( false ) ;
92
91
let window = window_builder. build ( & self . el ) . unwrap ( ) ;
92
+ let rwh = window. raw_display_handle ( ) ;
93
93
94
94
// Initialize surfman
95
95
let connection =
96
96
Connection :: from_winit_window ( & window) . expect ( "Failed to create connection" ) ;
97
97
98
- self . connection = Some ( connection) ;
99
-
100
- & self . connection
98
+ ( connection, rwh)
101
99
}
102
100
103
101
pub fn wait_for_window_resize ( & mut self , target_window_id : WindowId ) {
@@ -160,16 +158,16 @@ fn build_clipboard(_event_loop: &EventLoop<i32>) -> Box<dyn ClipboardProvider> {
160
158
}
161
159
}
162
160
163
- pub static EVENT_LOOP : Lazy < Mutex < WrEventLoop > > = Lazy :: new ( || {
161
+ pub static EVENT_LOOP : Lazy < Arc < Mutex < WrEventLoop > > > = Lazy :: new ( || {
164
162
let el = winit:: event_loop:: EventLoopBuilder :: < i32 > :: with_user_event ( ) . build ( ) ;
165
163
let clipboard = build_clipboard ( & el) ;
166
164
let connection = None ;
167
165
168
- Mutex :: new ( WrEventLoop {
166
+ Arc :: new ( Mutex :: new ( WrEventLoop {
169
167
clipboard,
170
168
el,
171
169
connection,
172
- } )
170
+ } ) )
173
171
} ) ;
174
172
175
173
pub static EVENT_BUFFER : Lazy < Mutex < Vec < GUIEvent > > > = Lazy :: new ( || Mutex :: new ( Vec :: new ( ) ) ) ;
@@ -183,7 +181,13 @@ pub extern "C" fn wr_select(
183
181
timeout : * mut timespec ,
184
182
_sigmask : * mut sigset_t ,
185
183
) -> i32 {
186
- if unsafe { inhibit_window_system } {
184
+ let lock_result = EVENT_LOOP . try_lock ( ) ;
185
+
186
+ if lock_result. is_err ( ) || unsafe { inhibit_window_system } {
187
+ if lock_result. is_err ( ) {
188
+ log:: debug!( "Failed to grab a lock {:?}" , lock_result. err( ) ) ;
189
+ }
190
+
187
191
return unsafe {
188
192
thread_select (
189
193
Some ( pselect) ,
@@ -197,5 +201,58 @@ pub extern "C" fn wr_select(
197
201
} ;
198
202
}
199
203
200
- handle_select ( nfds, readfds, writefds, _exceptfds, timeout, _sigmask)
204
+ let mut event_loop = lock_result. unwrap ( ) ;
205
+
206
+ handle_select (
207
+ & mut event_loop. el ,
208
+ nfds,
209
+ readfds,
210
+ writefds,
211
+ _exceptfds,
212
+ timeout,
213
+ _sigmask,
214
+ )
215
+ }
216
+
217
+ // Polling C-g when emacs is blocked
218
+ pub fn poll_a_event ( timeout : Duration ) -> Option < GUIEvent > {
219
+ log:: trace!( "poll a event {:?}" , timeout) ;
220
+ let result = EVENT_LOOP . try_lock ( ) ;
221
+ if result. is_err ( ) {
222
+ log:: trace!( "failed to grab a EVENT_LOOP lock" ) ;
223
+ return None ;
224
+ }
225
+ let mut event_loop = result. unwrap ( ) ;
226
+ let deadline = Instant :: now ( ) + timeout;
227
+ let result = RefCell :: new ( None ) ;
228
+ event_loop. el . run_return ( |e, _target, control_flow| {
229
+ control_flow. set_wait_until ( deadline) ;
230
+
231
+ if let Event :: WindowEvent { event, .. } = & e {
232
+ log:: trace!( "{:?}" , event) ;
233
+ }
234
+
235
+ match e {
236
+ Event :: WindowEvent { ref event, .. } => match event {
237
+ WindowEvent :: Resized ( _)
238
+ | WindowEvent :: KeyboardInput { .. }
239
+ | WindowEvent :: ReceivedCharacter ( _)
240
+ | WindowEvent :: ModifiersChanged ( _)
241
+ | WindowEvent :: MouseInput { .. }
242
+ | WindowEvent :: CursorMoved { .. }
243
+ | WindowEvent :: Focused ( _)
244
+ | WindowEvent :: MouseWheel { .. }
245
+ | WindowEvent :: CloseRequested => {
246
+ result. replace ( Some ( e. to_static ( ) . unwrap ( ) ) ) ;
247
+ control_flow. set_exit ( ) ;
248
+ }
249
+ _ => { }
250
+ } ,
251
+ Event :: RedrawEventsCleared => {
252
+ control_flow. set_exit ( ) ;
253
+ }
254
+ _ => { }
255
+ } ;
256
+ } ) ;
257
+ result. into_inner ( )
201
258
}
0 commit comments