Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Switch to a futures-compatible API #126

Merged
merged 14 commits into from
Feb 11, 2017
99 changes: 83 additions & 16 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,18 @@
//!
//! # Building a window
//!
//! There are two ways to create a window:
//! Before you can build a window, you first need to build an `EventsLoop`. This is done with the
//! `EventsLoop::new()` function. Example:
//!
//! - Calling `Window::new()`.
//! - Calling `let builder = WindowBuilder::new()` then `builder.build()`.
//! ```no_run
//! use winit::EventsLoop;
//! let events_loop = EventsLoop::new();
//! ```
//!
//! Once this is done there are two ways to create a window:
//!
//! - Calling `Window::new(&events_loop)`.
//! - Calling `let builder = WindowBuilder::new()` then `builder.build(&events_loop)`.
//!
//! The first way is the simpliest way and will give you default values for everything.
//!
Expand All @@ -14,11 +22,58 @@
//!
//! # Events handling
//!
//! Once a window has been created, you can handle the events that it generates. There are two ways
//! to do so: with `poll_events` or with `wait_events`. The former returns an iterator that ends
//! when no event is available, and the latter returns an iterator that blocks and waits for events
//! if none is available. Depending on which kind of program you're writing, you usually choose
//! one or the other.
//! Once a window has been created, it will *generate events*. For example whenever the user moves
//! the window, resizes the window, moves the mouse, etc. an event is generated.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just a thought, would it be the proper place to add a note that on some platforms, no events will be generated before something is drawn on the window (this is the case of wayland)? This can totally be done in a followup PR btw, it's just that reading this here made me think of it.

//!
//! The events generated by a window can be retreived from the `EventsLoop` the window was created
//! with.
//!
//! There are two ways to do so. The first is to call `events_loop.poll_events(...)`, which will
//! retreive all the events pending on the windows and immediately return after no new event is
//! available. You usually want to use this method in application that render continuously on the
//! screen, such as video games.
//!
//! ```no_run
//! use winit::Event;
//! use winit::WindowEvent;
//! # use winit::EventsLoop;
//! # let events_loop = EventsLoop::new();
//!
//! loop {
//! events_loop.poll_events(|event| {
//! match event {
//! Event::WindowEvent { event: WindowEvent::Resized(w, h), .. } => {
//! println!("The window was resized to {}x{}", w, h);
//! },
//! _ => ()
//! }
//! });
//! }
//! ```
//!
//! The second way is to call `events_loop.run_forever(...)`. As its name tells, it will run
//! forever unless it is stopped by calling `events_loop.interrupt()`.
//!
//! ```no_run
//! use winit::Event;
//! use winit::WindowEvent;
//! # use winit::EventsLoop;
//! # let events_loop = EventsLoop::new();
//!
//! events_loop.run_forever(|event| {
//! match event {
//! Event::WindowEvent { event: WindowEvent::Closed, .. } => {
//! println!("The window was closed ; stopping");
//! events_loop.interrupt();
//! },
//! _ => ()
//! }
//! });
//! ```
//!
//! If you use multiple windows, the `WindowEvent` event has a member named `window_id`. You can
//! compare it with the value returned by the `id()` method of `Window` in order to know which
//! window has received the event.
//!
//! # Drawing on the window
//!
Expand Down Expand Up @@ -86,22 +141,29 @@ pub mod os;
/// # Example
///
/// ```no_run
/// use winit::Event;
/// use winit::EventsLoop;
/// use winit::Window;
/// let window = Window::new().unwrap();
/// use winit::WindowEvent;
///
/// let events_loop = EventsLoop::new();
/// let window = Window::new(&events_loop).unwrap();
///
/// loop {
/// for event in window.wait_events() {
/// match event {
/// // process events here
/// _ => ()
/// }
/// events_loop.run_forever(|event| {
/// match event {
/// Event::WindowEvent { event: WindowEvent::Closed, .. } => {
/// events_loop.interrupt();
/// },
/// _ => ()
/// }
/// }
/// });
/// ```
pub struct Window {
window: platform::Window2,
}

/// Provides a way to retreive events from the windows that were registered to it.
// TODO: document usage in multiple threads
pub struct EventsLoop {
events_loop: Arc<platform::EventsLoop>,
}
Expand All @@ -114,20 +176,25 @@ impl EventsLoop {
}
}

/// Fetches all the events that are pending, calls the callback function for each of them,
/// and returns.
#[inline]
pub fn poll_events<F>(&self, callback: F)
where F: FnMut(Event)
{
self.events_loop.poll_events(callback)
}

/// Runs forever until `interrupt()` is called. Whenever an event happens, calls the callback.
#[inline]
pub fn run_forever<F>(&self, callback: F)
where F: FnMut(Event)
{
self.events_loop.run_forever(callback)
}

/// If we called `run_forever()`, stops the process of waiting for events.
// TODO: what if we're waiting from multiple threads?
#[inline]
pub fn interrupt(&self) {
self.events_loop.interrupt()
Expand Down
2 changes: 1 addition & 1 deletion src/window.rs
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,7 @@ impl WindowBuilder {
impl Window {
/// Creates a new OpenGL context, and a Window for platforms where this is appropriate.
///
/// This function is equivalent to `WindowBuilder::new().build()`.
/// This function is equivalent to `WindowBuilder::new().build(events_loop)`.
///
/// Error should be very rare and only occur in case of permission denied, incompatible system,
/// out of memory, etc.
Expand Down