1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117
/// Returned by the user callback given to the `EventsLoop::run` method. /// /// Indicates whether the `run` method should continue or complete. #[derive(Copy, Clone, Debug, PartialEq, Eq)] pub enum ControlFlow { /// Continue looping and waiting for events. Continue, /// Break from the event loop. Break, } /// Provides a way to retrieve events from the system and from the windows that were registered to /// the events loop. /// /// An `EventsLoop` can be seen more or less as a "context". Calling `EventsLoop::new()` /// initializes everything that will be required to create windows. For example on Linux creating /// an events loop opens a connection to the X or Wayland server. /// /// To wake up an `EventsLoop` from a another thread, see the `EventsLoopProxy` docs. /// /// Note that the `EventsLoop` cannot be shared accross threads (due to platform-dependant logic /// forbiding it), as such it is neither `Send` nor `Sync`. If you need cross-thread access, the /// `Window` created from this `EventsLoop` _can_ be sent to an other thread, and the /// `EventsLoopProxy` allows you to wakeup an `EventsLoop` from an other thread. pub trait EventsLoop<Event> { /// Fetches all the events that are pending, calls the callback function for each of them, /// and returns. fn poll_events(&mut self, callback: &mut dyn FnMut(Event)); /// Calls `callback` every time an event is received. If no event is available, sleeps the /// current thread and waits for an event. If the callback returns `ControlFlow::Break` then /// `run` will immediately return. /// /// # Danger! /// /// The callback is run after *every* event, so if its execution time is non-trivial the event queue may not empty /// at a sufficient rate. Rendering in the callback with vsync enabled **will** cause significant lag. fn run(&mut self, callback: &mut dyn FnMut(Event) -> ControlFlow); /// Creates an `EventsLoopProxy` that can be used to wake up the `EventsLoop` from another /// thread. fn create_proxy(&self) -> Box<dyn EventsLoopProxy>; } /// Used to wake up the `EventsLoop` from another thread. pub trait EventsLoopProxy : Send { /// Wake up the `EventsLoop` from which this proxy was created. /// /// This causes the `EventsLoop` to emit an `Awakened` event. /// /// Returns an `Err` if the associated `EventsLoop` no longer exists. fn wakeup(&self) -> Result<(), EventsLoopClosed>; fn clone(&self) -> Box<dyn EventsLoopProxy>; } impl Clone for Box<dyn EventsLoopProxy> { fn clone(&self) -> Box<dyn EventsLoopProxy> { use std::ops::Deref; self.deref().clone() } } /// The error that is returned when an `EventsLoopProxy` attempts to wake up an `EventsLoop` that /// no longer exists. #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] pub struct EventsLoopClosed; impl std::fmt::Display for EventsLoopClosed { fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { write!(f, "{}", self.to_string()) } } impl std::error::Error for EventsLoopClosed { fn description(&self) -> &str { "Tried to wake up a closed `EventsLoop`" } } #[cfg(test)] mod tests { #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] enum Events { A, B, C } struct Loop; impl ::EventsLoop<Events> for Loop { fn poll_events(&mut self, callback: &mut dyn FnMut(Events)) { callback(Events::A); callback(Events::B); } fn run(&mut self, callback: &mut dyn FnMut(Events) -> ::ControlFlow){ while callback(Events::C) == ::ControlFlow::Continue { } } fn create_proxy(&self) -> Box<dyn (::EventsLoopProxy)> { unimplemented!(); } } #[test] fn it_works() { use ::EventsLoop; let mut l = Loop{}; l.poll_events(&mut |e| println!("{:?}", e)); l.run(&mut |e| {println!("{:?}", e); ::ControlFlow::Break}); } }