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
118
119
120
121
122
123
124
125
//! # luminance windowing
//!
//! This is the base, abstract crate for windowing common types and functions in luminance. The
//! `luminance` crate provides you with abstracting over OpenGL, but it doesn’t give you a way to
//! create an OpenGL context. This is due to the fact that creating and managing OpenGL contexts is
//! tightly related to the type of application you target. Typical PC applications might need
//! something like **GLFW** or **glutin** whilst others will directly bind to **X11** or **Windows
//! API**. Several crates – `luminance-*` – exist to solve that problem. They all provide a
//! different implementation for a simple need: opening an OpenGL context, opening a window and
//! manage events. In theory, you could even have a `luminance-gtk` or `luminance-qt` to embed
//! `luminance` in surfaces in those libraries.
//!
//! # What’s included
//!
//! This crate exposes several important types that all backends must use. Among them, you’ll find:
//!
//! - `WindowDim`: abstraction over the dimension of a window and its mode (windowed, fullscreen,
//!   fullscreen restricted).
//! - `WindowOpt`: an opaque type giving access to hints to customize the window integration, such
//!   as whether the cursor should be hidden or not.
//!
//! The `Device` trait must be implemented by a backend so that an application is completely
//! agnostic of the backend. This trait defines several basic methods that will help you to:
//!
//! - Retrieve the dimension of the window / framebuffer.
//! - Iterate over the system events captured by your application.
//! - Draw and swap the buffer chain.

extern crate luminance;

use luminance::context::GraphicsContext;

/// Dimension metrics.
///
///   - `Windowed(width, height)` opens in windowed mode with the wished resolution.
///   - `Fullscreen` opens in fullscreen mode by using the primary monitor resolution.
///   - `FullscreenRestricted(width, height)` is a mix between `Windowed(width, height)` and
///     `Fullscreen`. It opens in fullscreen mode by using the wished resolution.
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub enum WindowDim {
  /// Windowed mode.
  Windowed(u32, u32),
  /// Fullscreen mode (adapt to your screen).
  Fullscreen,
  /// Fullscreen mode with restricted viewport dimension.
  FullscreenRestricted(u32, u32)
}

/// Different window options.
///
/// Feel free to look at the different methods available to tweak the options. You may want to start
/// with `default()` though.
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub struct WindowOpt {
  hide_cursor: bool
}

impl Default for WindowOpt {
  /// Defaults:
  ///
  /// - `hide_cursor(false)`
  fn default() -> Self {
    WindowOpt {
      hide_cursor: false
    }
  }
}

impl WindowOpt {
  /// Hide or unhide the cursor. Default to `false`.
  #[inline]
  pub fn hide_cursor(self, hide: bool) -> Self {
    WindowOpt { hide_cursor: hide, ..self }
  }

  #[inline]
  pub fn is_cursor_hidden(&self) -> bool {
    self.hide_cursor
  }
}

/// Rendering surface.
///
/// This type holds anything related to rendering. The interface is straight forward, so feel
/// free to have a look around.
pub trait Surface: GraphicsContext + Sized {
  /// Type of events.
  type Event;

  /// Type of surface errors.
  type Error;

  /// Create a surface along with its associated event stream and bootstrap a luminance environment
  /// that it lives as long as the surface lives.
  fn new(dim: WindowDim, title: &str, win_opt: WindowOpt) -> Result<Self, Self::Error>;

  /// Size of the surface’s framebuffer.
  fn size(&self) -> [u32; 2];

  /// Width of the surface’s framebuffer.
  ///
  /// # Defaults
  ///
  /// Defaults to `.size()[0]`.
  fn width(&self) -> u32 {
    self.size()[0]
  }

  /// Height of the surface’s framebuffer.
  ///
  /// # Defaults
  ///
  /// Defaults to `.size()[1]`.
  fn height(&self) -> u32 {
    self.size()[1]
  }

  // FIXME: existential impl trait
  /// Get an iterator over events by blocking until the first event happens.
  fn wait_events<'a>(&'a mut self) -> Box<Iterator<Item = Self::Event> + 'a>;

  // FIXME: existential impl trait
  /// Get an iterator over events without blocking if no event is there.
  fn poll_events<'a>(&'a mut self) -> Box<Iterator<Item = Self::Event> + 'a>;
}