1
1
2
+ #![ feature( fnbox) ]
2
3
#![ feature( const_fn) ]
3
4
#![ feature( libc) ]
4
5
#![ feature( trace_macros) ]
@@ -19,6 +20,7 @@ use rjs::jslib::eventloop;
19
20
use tokio_core:: reactor:: Timeout ;
20
21
use tokio_core:: reactor:: Core ;
21
22
use futures:: future:: Future ;
23
+ use futures:: IntoFuture ;
22
24
23
25
use std:: os:: raw:: c_void;
24
26
use mozjs:: jsapi;
@@ -64,6 +66,7 @@ use mozjs::jsapi::JSPropertySpec;
64
66
use mozjs:: jsapi:: { JS_GetContext , JS_SetPrivate , JS_GetPrivate , JS_InitStandardClasses } ;
65
67
use futures:: sync:: mpsc:: { unbounded, UnboundedSender , UnboundedReceiver } ;
66
68
use futures:: Stream ;
69
+ use tokio_core:: reactor:: Interval ;
67
70
68
71
use glutin:: GlContext ;
69
72
@@ -83,6 +86,7 @@ use std::ffi::CString;
83
86
//use std::fmt::Display;
84
87
use std:: sync:: { Once , ONCE_INIT } ;
85
88
use std:: thread;
89
+ use std:: boxed:: FnBox ;
86
90
87
91
88
92
@@ -302,6 +306,15 @@ struct Window {
302
306
send_msg : UnboundedSender < WindowMsg > ,
303
307
}
304
308
309
+ macro_rules! window_get_private {
310
+ ( $this: ident) => {
311
+ unsafe {
312
+ let win = JS_GetPrivate ( $this. to_object( ) ) as * mut Window ;
313
+ & * win
314
+ }
315
+ }
316
+ }
317
+
305
318
js_class ! { Window
306
319
[ JSCLASS_HAS_PRIVATE ]
307
320
@@ -352,25 +365,17 @@ js_class!{ Window
352
365
}
353
366
354
367
fn ping( this: @this) -> JSRet <( ) > {
355
- unsafe {
356
- let win = JS_GetPrivate ( this. to_object( ) ) as * mut Window ;
368
+ let win = window_get_private!( this) ;
357
369
358
- ( * win) . send_msg. unbounded_send(
359
- WindowMsg :: Ping
360
- ) ;
361
- }
370
+ win. send_msg. unbounded_send( WindowMsg :: Ping ) ;
362
371
363
372
Ok ( ( ) )
364
373
}
365
374
366
375
fn close( this: @this) -> JSRet <( ) > {
367
- unsafe {
368
- let win = JS_GetPrivate ( this. to_object( ) ) as * mut Window ;
376
+ let win = window_get_private!( this) ;
369
377
370
- ( * win) . send_msg. unbounded_send(
371
- WindowMsg :: Close
372
- ) ;
373
- }
378
+ win. send_msg. unbounded_send( WindowMsg :: Close ) ;
374
379
375
380
Ok ( ( ) )
376
381
}
@@ -394,12 +399,13 @@ js_class!{ Window
394
399
}
395
400
}
396
401
397
- #[ derive( Debug ) ]
398
402
enum WindowMsg {
403
+ Do ( Box < FnBox ( & glutin:: GlWindow ) + Send > ) ,
399
404
Ping ,
400
405
Close ,
401
406
}
402
407
408
+
403
409
#[ derive( Debug ) ]
404
410
enum WindowEvent {
405
411
Closed ,
@@ -408,6 +414,7 @@ enum WindowEvent {
408
414
use std:: cell:: RefCell ;
409
415
use std:: rc:: Rc ;
410
416
417
+
411
418
fn window_thread ( recv_msg : UnboundedReceiver < WindowMsg > , send_events : UnboundedSender < WindowEvent > ) {
412
419
let mut core = Core :: new ( ) . unwrap ( ) ;
413
420
@@ -425,65 +432,80 @@ fn window_thread(recv_msg: UnboundedReceiver<WindowMsg>, send_events: UnboundedS
425
432
gl:: ClearColor ( 0.0 , 0.0 , 0.0 , 1.0 ) ;
426
433
}
427
434
435
+ let ( stop_send, stop_recv) = futures:: sync:: oneshot:: channel ( ) ;
436
+ let stop_recv = stop_recv. map_err ( |err| ( ) ) ;
437
+
428
438
struct WindowStuff {
429
439
gl_window : glutin:: GlWindow ,
430
- run : bool ,
440
+ stop : Option < futures:: sync:: oneshot:: Sender < ( ) > > ,
441
+ }
442
+
443
+ impl WindowStuff {
444
+ fn stop ( & mut self ) {
445
+ let stop = self . stop . take ( ) ;
446
+ stop. map ( |stop| stop. send ( ( ) ) ) ;
447
+ }
431
448
}
432
449
433
450
// This could just be a let mut if tokio used lifetimes
434
451
let stuff = Rc :: new ( RefCell :: new ( WindowStuff {
435
452
gl_window : gl_window,
436
- run : true ,
453
+ stop : Some ( stop_send ) ,
437
454
} ) ) ;
438
455
439
- {
440
- let stuff = stuff. clone ( ) ; // grrr. Why no clone closures?
441
- core. handle ( ) . spawn (
442
- recv_msg. for_each ( move |msg| -> Result < ( ) , ( ) > {
443
- println ! ( "Window msg: {:?}" , & msg) ;
456
+
457
+ let recv_msgs = {
458
+ let stuff = stuff. clone ( ) ;
459
+ recv_msg. for_each ( move |msg| -> Result < ( ) , ( ) > {
460
+ let mut stuff = stuff. borrow_mut ( ) ;
461
+ let stuff = & mut * stuff;
462
+ match msg {
463
+ WindowMsg :: Do ( func) => { func. call_box ( ( & stuff. gl_window , ) ) ; } ,
464
+ WindowMsg :: Ping => { println ! ( "ping" ) ; } ,
465
+ WindowMsg :: Close => {
466
+ println ! ( "close" ) ;
467
+ stuff. stop ( ) ;
468
+ stuff. gl_window . hide ( ) ;
469
+ } ,
470
+ }
471
+
472
+ Ok ( ( ) )
473
+ } ) . map_err ( |_| ( ) )
474
+ } ;
475
+
476
+ let handle_window_events =
477
+ Interval :: new ( Duration :: from_millis ( 16 ) , & core. handle ( ) ) . unwrap ( )
478
+ . map_err ( |err| { println ! ( "Interval err: {}" , err) ; ( ) } )
479
+ . for_each ( move |( ) | -> Result < ( ) , ( ) > {
444
480
let mut stuff = stuff. borrow_mut ( ) ;
445
481
let stuff = & mut * stuff;
446
- match msg {
447
- WindowMsg :: Ping => { println ! ( "ping" ) ; } ,
448
- WindowMsg :: Close => {
449
- stuff. run = false ;
450
- stuff. gl_window . hide ( ) ;
451
- } ,
482
+
483
+ unsafe {
484
+ gl:: Clear ( gl:: COLOR_BUFFER_BIT ) ;
452
485
}
486
+ stuff. gl_window . swap_buffers ( ) . unwrap ( ) ;
487
+
488
+ events_loop. poll_events ( |event| {
489
+ println ! ( "glutin event: {:?}" , event) ;
490
+ match event {
491
+ glutin:: Event :: WindowEvent { event, .. } => match event {
492
+ glutin:: WindowEvent :: Closed => {
493
+ stuff. stop ( ) ;
494
+ stuff. gl_window . hide ( ) ;
495
+ send_events. unbounded_send ( WindowEvent :: Closed ) ;
496
+ } ,
497
+ glutin:: WindowEvent :: Resized ( w, h) => stuff. gl_window . resize ( w, h) ,
498
+ _ => ( )
499
+ } ,
500
+ _ => ( )
501
+ }
502
+ } ) ;
453
503
454
504
Ok ( ( ) )
455
505
} )
456
- ) ;
457
- }
458
-
459
- while ( * stuff. borrow ( ) ) . run {
460
- core. turn ( Some ( Duration :: from_millis ( 16 ) ) ) ;
461
-
462
- let mut stuff = stuff. borrow_mut ( ) ;
463
- let stuff = & mut * stuff;
506
+ ;
464
507
465
- unsafe {
466
- gl:: Clear ( gl:: COLOR_BUFFER_BIT ) ;
467
- }
468
- stuff. gl_window . swap_buffers ( ) . unwrap ( ) ;
469
-
470
- events_loop. poll_events ( |event| {
471
- println ! ( "glutin event: {:?}" , event) ;
472
- match event {
473
- glutin:: Event :: WindowEvent { event, .. } => match event {
474
- glutin:: WindowEvent :: Closed => {
475
- stuff. run = false ;
476
- stuff. gl_window . hide ( ) ;
477
- send_events. unbounded_send ( WindowEvent :: Closed ) ;
478
- } ,
479
- glutin:: WindowEvent :: Resized ( w, h) => stuff. gl_window . resize ( w, h) ,
480
- _ => ( )
481
- } ,
482
- _ => ( )
483
- }
484
- } )
485
- }
508
+ core. run ( stop_recv. select ( handle_window_events) . then ( |_| -> Result < ( ) , ( ) > { Ok ( ( ) ) } ) . select ( recv_msgs) ) ;
486
509
487
510
println ! ( "window_thread exiting" ) ;
488
-
489
511
}
0 commit comments