display_link/
lib.rs

1pub mod ios;
2pub mod macos;
3
4use std::fmt::{self, Display, Formatter};
5use time_point::TimePoint;
6
7#[cfg(target_os = "ios")]
8use crate::ios::DisplayLink as PlatformDisplayLink;
9#[cfg(target_os = "macos")]
10use crate::macos::DisplayLink as PlatformDisplayLink;
11
12#[derive(Debug)]
13pub enum PauseError {
14    AlreadyPaused,
15}
16
17impl Display for PauseError {
18    fn fmt(&self, formatter: &mut Formatter<'_>) -> fmt::Result {
19        match self {
20            PauseError::AlreadyPaused => write!(formatter, "already paused"),
21        }
22    }
23}
24
25#[derive(Debug)]
26pub enum ResumeError {
27    AlreadyRunning,
28}
29
30impl Display for ResumeError {
31    fn fmt(&self, formatter: &mut Formatter<'_>) -> fmt::Result {
32        match self {
33            ResumeError::AlreadyRunning => write!(formatter, "already running"),
34        }
35    }
36}
37
38/// `DisplayLink` is a timer object used to synchronize drawing with the refresh rate of the
39/// display.
40#[derive(Debug)]
41pub struct DisplayLink(PlatformDisplayLink);
42
43impl DisplayLink {
44    /// Creates a new `DisplayLink` with a callback that will be invoked with the `TimePoint` the
45    /// screen will next refresh.
46    ///
47    /// The returned `DisplayLink` will be in a paused state. Returns `None` if a `DisplayLink`
48    /// could not be created.
49    ///
50    /// ## Panic
51    ///
52    /// If the callback panics, the process will be aborted.
53    pub fn new<F>(callback: F) -> Option<Self>
54    where
55        F: 'static + FnMut(TimePoint) + Send,
56    {
57        PlatformDisplayLink::new(callback).map(DisplayLink)
58    }
59
60    #[cfg(feature = "winit")]
61    pub fn on_monitor<F>(monitor: &winit::monitor::MonitorHandle, callback: F) -> Option<Self>
62    where
63        F: 'static + FnMut(TimePoint) + Send,
64    {
65        PlatformDisplayLink::on_monitor(monitor, callback).map(DisplayLink)
66    }
67
68    #[cfg(feature = "winit")]
69    pub fn set_current_monitor(&mut self, monitor: &winit::monitor::MonitorHandle) {
70        self.0.set_current_monitor(monitor)
71    }
72
73    /// Returns `true` if the `DisplayLink` is currently paused.
74    pub fn is_paused(&self) -> bool {
75        self.0.is_paused()
76    }
77
78    /// Pauses the `DisplayLink`.
79    ///
80    /// A paused `DisplayLink` will not invoke it's callback. On iOS, it is necessary to pause the
81    /// `DisplayLink` in response to events like backgrounding.
82    pub fn pause(&mut self) -> Result<(), PauseError> {
83        self.0.pause()
84    }
85
86    /// Resumes the `DisplayLink`.
87    pub fn resume(&mut self) -> Result<(), ResumeError> {
88        self.0.resume()
89    }
90}