-
Notifications
You must be signed in to change notification settings - Fork 5
/
Copy pathmacos.rs
117 lines (105 loc) · 2.88 KB
/
macos.rs
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
#![cfg(target_os = "macos")]
pub mod cvdisplaylink;
use crate::{
macos::cvdisplaylink::{CVDisplayLink, CVTimeStamp, DisplayLink as RawDisplayLink},
PauseError, ResumeError,
};
use std::{any::Any, ffi::c_void};
use time_point::TimePoint;
unsafe extern "C" fn render<F>(
_: *mut CVDisplayLink,
_: *const CVTimeStamp,
in_out_timestamp: *const CVTimeStamp,
_: i64,
_: *mut i64,
display_link_context: *mut c_void,
) -> i32
where
F: FnMut(TimePoint),
{
let in_out_timestamp = &*in_out_timestamp;
let f = &mut *(display_link_context as *mut F);
f(TimePoint::new(in_out_timestamp.host_time as _));
0
}
#[derive(Debug)]
pub struct DisplayLink {
is_paused: bool,
func: Box<dyn Any>,
display_link: RawDisplayLink,
}
impl Drop for DisplayLink {
fn drop(&mut self) {
if !self.is_paused {
unsafe {
self.display_link.stop();
}
}
}
}
impl DisplayLink {
fn new_impl<R, F>(make_raw: R, callback: F) -> Option<Self>
where
R: FnOnce() -> Option<RawDisplayLink>,
F: 'static + FnMut(TimePoint) + Send,
{
let func = Box::new(callback);
unsafe {
let raw = Box::into_raw(func);
let func = Box::from_raw(raw);
let mut display_link = make_raw()?;
display_link.set_output_callback(render::<F>, raw as *mut c_void);
Some(DisplayLink {
is_paused: true,
func,
display_link,
})
}
}
/// Creates a new iOS `DisplayLink` instance.
///
/// macos _does_ require the callback to be `Send`.
pub fn new<F>(callback: F) -> Option<Self>
where
F: 'static + FnMut(TimePoint) + Send,
{
Self::new_impl(|| unsafe { RawDisplayLink::new() }, callback)
}
pub fn on_display<F>(display_id: u32, callback: F) -> Option<Self>
where
F: 'static + FnMut(TimePoint) + Send,
{
Self::new_impl(
|| unsafe { RawDisplayLink::on_display(display_id) },
callback,
)
}
pub fn set_current_display(&mut self, display_id: u32) {
unsafe { self.display_link.set_current_display(display_id) }
}
pub fn is_paused(&self) -> bool {
self.is_paused
}
pub fn pause(&mut self) -> Result<(), PauseError> {
if self.is_paused {
Err(PauseError::AlreadyPaused)
} else {
unsafe {
self.display_link.stop();
self.is_paused = true;
Ok(())
}
}
}
pub fn resume(&mut self) -> Result<(), ResumeError> {
if !self.is_paused {
Err(ResumeError::AlreadyRunning)
} else {
unsafe {
self.display_link.start();
self.is_paused = false;
Ok(())
}
}
}
}