gdk4/auto/frame_clock.rs
1// This file was generated by gir (https://github.com/gtk-rs/gir)
2// from gir-files (https://github.com/gtk-rs/gir-files)
3// DO NOT EDIT
4
5use crate::{ffi, FrameClockPhase, FrameTimings};
6use glib::{
7 object::ObjectType as _,
8 prelude::*,
9 signal::{connect_raw, SignalHandlerId},
10 translate::*,
11};
12use std::boxed::Box as Box_;
13
14glib::wrapper! {
15 /// A [`FrameClock`][crate::FrameClock] tells the application when to update and repaint
16 /// a surface.
17 ///
18 /// This may be synced to the vertical refresh rate of the monitor, for example.
19 /// Even when the frame clock uses a simple timer rather than a hardware-based
20 /// vertical sync, the frame clock helps because it ensures everything paints at
21 /// the same time (reducing the total number of frames).
22 ///
23 /// The frame clock can also automatically stop painting when it knows the frames
24 /// will not be visible, or scale back animation framerates.
25 ///
26 /// [`FrameClock`][crate::FrameClock] is designed to be compatible with an OpenGL-based implementation
27 /// or with mozRequestAnimationFrame in Firefox, for example.
28 ///
29 /// A frame clock is idle until someone requests a frame with
30 /// [`request_phase()`][Self::request_phase()]. At some later point that makes sense
31 /// for the synchronization being implemented, the clock will process a frame and
32 /// emit signals for each phase that has been requested. (See the signals of the
33 /// [`FrameClock`][crate::FrameClock] class for documentation of the phases.
34 /// [`FrameClockPhase::UPDATE`][crate::FrameClockPhase::UPDATE] and the [`update`][struct@crate::FrameClock#update] signal
35 /// are most interesting for application writers, and are used to update the
36 /// animations, using the frame time given by [`frame_time()`][Self::frame_time()].
37 ///
38 /// The frame time is reported in microseconds and generally in the same
39 /// timescale as g_get_monotonic_time(), however, it is not the same
40 /// as g_get_monotonic_time(). The frame time does not advance during
41 /// the time a frame is being painted, and outside of a frame, an attempt
42 /// is made so that all calls to [`frame_time()`][Self::frame_time()] that
43 /// are called at a “similar” time get the same value. This means that
44 /// if different animations are timed by looking at the difference in
45 /// time between an initial value from [`frame_time()`][Self::frame_time()]
46 /// and the value inside the [`update`][struct@crate::FrameClock#update] signal of the clock,
47 /// they will stay exactly synchronized.
48 ///
49 /// This is an Abstract Base Class, you cannot instantiate it.
50 ///
51 /// ## Signals
52 ///
53 ///
54 /// #### `after-paint`
55 /// This signal ends processing of the frame.
56 ///
57 /// Applications should generally not handle this signal.
58 ///
59 ///
60 ///
61 ///
62 /// #### `before-paint`
63 /// Begins processing of the frame.
64 ///
65 /// Applications should generally not handle this signal.
66 ///
67 ///
68 ///
69 ///
70 /// #### `flush-events`
71 /// Used to flush pending motion events that are being batched up and
72 /// compressed together.
73 ///
74 /// Applications should not handle this signal.
75 ///
76 ///
77 ///
78 ///
79 /// #### `layout`
80 /// Emitted as the second step of toolkit and application processing
81 /// of the frame.
82 ///
83 /// Any work to update sizes and positions of application elements
84 /// should be performed. GTK normally handles this internally.
85 ///
86 ///
87 ///
88 ///
89 /// #### `paint`
90 /// Emitted as the third step of toolkit and application processing
91 /// of the frame.
92 ///
93 /// The frame is repainted. GDK normally handles this internally and
94 /// emits [`render`][struct@crate::Surface#render] signals which are turned into
95 /// [GtkWidget::snapshot](../gtk4/signal.Widget.snapshot.html) signals
96 /// by GTK.
97 ///
98 ///
99 ///
100 ///
101 /// #### `resume-events`
102 /// Emitted after processing of the frame is finished.
103 ///
104 /// This signal is handled internally by GTK to resume normal
105 /// event processing. Applications should not handle this signal.
106 ///
107 ///
108 ///
109 ///
110 /// #### `update`
111 /// Emitted as the first step of toolkit and application processing
112 /// of the frame.
113 ///
114 /// Animations should be updated using [`FrameClock::frame_time()`][crate::FrameClock::frame_time()].
115 /// Applications can connect directly to this signal, or use
116 /// [gtk_widget_add_tick_callback()](../gtk4/method.Widget.add_tick_callback.html)
117 /// as a more convenient interface.
118 ///
119 ///
120 #[doc(alias = "GdkFrameClock")]
121 pub struct FrameClock(Object<ffi::GdkFrameClock, ffi::GdkFrameClockClass>);
122
123 match fn {
124 type_ => || ffi::gdk_frame_clock_get_type(),
125 }
126}
127
128impl FrameClock {
129 /// Starts updates for an animation.
130 ///
131 /// Until a matching call to [`end_updating()`][Self::end_updating()] is made,
132 /// the frame clock will continually request a new frame with the
133 /// [`FrameClockPhase::UPDATE`][crate::FrameClockPhase::UPDATE] phase. This function may be called multiple
134 /// times and frames will be requested until gdk_frame_clock_end_updating()
135 /// is called the same number of times.
136 #[doc(alias = "gdk_frame_clock_begin_updating")]
137 pub fn begin_updating(&self) {
138 unsafe {
139 ffi::gdk_frame_clock_begin_updating(self.to_glib_none().0);
140 }
141 }
142
143 /// Stops updates for an animation.
144 ///
145 /// See the documentation for [`begin_updating()`][Self::begin_updating()].
146 #[doc(alias = "gdk_frame_clock_end_updating")]
147 pub fn end_updating(&self) {
148 unsafe {
149 ffi::gdk_frame_clock_end_updating(self.to_glib_none().0);
150 }
151 }
152
153 /// Gets the frame timings for the current frame.
154 ///
155 /// # Returns
156 ///
157 /// the [`FrameTimings`][crate::FrameTimings] for the
158 /// frame currently being processed, or even no frame is being
159 /// processed, for the previous frame. Before any frames have been
160 /// processed, returns [`None`].
161 #[doc(alias = "gdk_frame_clock_get_current_timings")]
162 #[doc(alias = "get_current_timings")]
163 pub fn current_timings(&self) -> Option<FrameTimings> {
164 unsafe {
165 from_glib_none(ffi::gdk_frame_clock_get_current_timings(
166 self.to_glib_none().0,
167 ))
168 }
169 }
170
171 /// Calculates the current frames-per-second, based on the
172 /// frame timings of @self.
173 ///
174 /// # Returns
175 ///
176 /// the current fps, as a `double`
177 #[doc(alias = "gdk_frame_clock_get_fps")]
178 #[doc(alias = "get_fps")]
179 pub fn fps(&self) -> f64 {
180 unsafe { ffi::gdk_frame_clock_get_fps(self.to_glib_none().0) }
181 }
182
183 /// [`FrameClock`][crate::FrameClock] maintains a 64-bit counter that increments for
184 /// each frame drawn.
185 ///
186 /// # Returns
187 ///
188 /// inside frame processing, the value of the frame counter
189 /// for the current frame. Outside of frame processing, the frame
190 /// counter for the last frame.
191 #[doc(alias = "gdk_frame_clock_get_frame_counter")]
192 #[doc(alias = "get_frame_counter")]
193 pub fn frame_counter(&self) -> i64 {
194 unsafe { ffi::gdk_frame_clock_get_frame_counter(self.to_glib_none().0) }
195 }
196
197 /// Gets the time that should currently be used for animations.
198 ///
199 /// Inside the processing of a frame, it’s the time used to compute the
200 /// animation position of everything in a frame. Outside of a frame, it's
201 /// the time of the conceptual “previous frame,” which may be either
202 /// the actual previous frame time, or if that’s too old, an updated
203 /// time.
204 ///
205 /// # Returns
206 ///
207 /// a timestamp in microseconds, in the timescale of
208 /// of g_get_monotonic_time().
209 #[doc(alias = "gdk_frame_clock_get_frame_time")]
210 #[doc(alias = "get_frame_time")]
211 pub fn frame_time(&self) -> i64 {
212 unsafe { ffi::gdk_frame_clock_get_frame_time(self.to_glib_none().0) }
213 }
214
215 /// Returns the frame counter for the oldest frame available in history.
216 ///
217 /// [`FrameClock`][crate::FrameClock] internally keeps a history of [`FrameTimings`][crate::FrameTimings]
218 /// objects for recent frames that can be retrieved with
219 /// [`timings()`][Self::timings()]. The set of stored frames
220 /// is the set from the counter values given by
221 /// [`history_start()`][Self::history_start()] and
222 /// [`frame_counter()`][Self::frame_counter()], inclusive.
223 ///
224 /// # Returns
225 ///
226 /// the frame counter value for the oldest frame
227 /// that is available in the internal frame history of the
228 /// [`FrameClock`][crate::FrameClock]
229 #[doc(alias = "gdk_frame_clock_get_history_start")]
230 #[doc(alias = "get_history_start")]
231 pub fn history_start(&self) -> i64 {
232 unsafe { ffi::gdk_frame_clock_get_history_start(self.to_glib_none().0) }
233 }
234
235 /// Predicts a presentation time, based on history.
236 ///
237 /// Using the frame history stored in the frame clock, finds the last
238 /// known presentation time and refresh interval, and assuming that
239 /// presentation times are separated by the refresh interval,
240 /// predicts a presentation time that is a multiple of the refresh
241 /// interval after the last presentation time, and later than @base_time.
242 /// ## `base_time`
243 /// base time for determining a presentaton time
244 ///
245 /// # Returns
246 ///
247 ///
248 /// ## `refresh_interval_return`
249 /// a location to store the
250 /// determined refresh interval, or [`None`]. A default refresh interval of
251 /// 1/60th of a second will be stored if no history is present.
252 ///
253 /// ## `presentation_time_return`
254 /// a location to store the next
255 /// candidate presentation time after the given base time.
256 /// 0 will be will be stored if no history is present.
257 #[doc(alias = "gdk_frame_clock_get_refresh_info")]
258 #[doc(alias = "get_refresh_info")]
259 pub fn refresh_info(&self, base_time: i64) -> (i64, i64) {
260 unsafe {
261 let mut refresh_interval_return = std::mem::MaybeUninit::uninit();
262 let mut presentation_time_return = std::mem::MaybeUninit::uninit();
263 ffi::gdk_frame_clock_get_refresh_info(
264 self.to_glib_none().0,
265 base_time,
266 refresh_interval_return.as_mut_ptr(),
267 presentation_time_return.as_mut_ptr(),
268 );
269 (
270 refresh_interval_return.assume_init(),
271 presentation_time_return.assume_init(),
272 )
273 }
274 }
275
276 /// Retrieves a [`FrameTimings`][crate::FrameTimings] object holding timing information
277 /// for the current frame or a recent frame.
278 ///
279 /// The [`FrameTimings`][crate::FrameTimings] object may not yet be complete: see
280 /// [`FrameTimings::is_complete()`][crate::FrameTimings::is_complete()] and
281 /// [`history_start()`][Self::history_start()].
282 /// ## `frame_counter`
283 /// the frame counter value identifying the frame to
284 /// be received
285 ///
286 /// # Returns
287 ///
288 /// the [`FrameTimings`][crate::FrameTimings] object
289 /// for the specified frame, or [`None`] if it is not available
290 #[doc(alias = "gdk_frame_clock_get_timings")]
291 #[doc(alias = "get_timings")]
292 pub fn timings(&self, frame_counter: i64) -> Option<FrameTimings> {
293 unsafe {
294 from_glib_none(ffi::gdk_frame_clock_get_timings(
295 self.to_glib_none().0,
296 frame_counter,
297 ))
298 }
299 }
300
301 /// Asks the frame clock to run a particular phase.
302 ///
303 /// The signal corresponding the requested phase will be emitted the next
304 /// time the frame clock processes. Multiple calls to
305 /// gdk_frame_clock_request_phase() will be combined together
306 /// and only one frame processed. If you are displaying animated
307 /// content and want to continually request the
308 /// [`FrameClockPhase::UPDATE`][crate::FrameClockPhase::UPDATE] phase for a period of time,
309 /// you should use [`begin_updating()`][Self::begin_updating()] instead,
310 /// since this allows GTK to adjust system parameters to get maximally
311 /// smooth animations.
312 /// ## `phase`
313 /// the phase that is requested
314 #[doc(alias = "gdk_frame_clock_request_phase")]
315 pub fn request_phase(&self, phase: FrameClockPhase) {
316 unsafe {
317 ffi::gdk_frame_clock_request_phase(self.to_glib_none().0, phase.into_glib());
318 }
319 }
320
321 /// This signal ends processing of the frame.
322 ///
323 /// Applications should generally not handle this signal.
324 #[doc(alias = "after-paint")]
325 pub fn connect_after_paint<F: Fn(&Self) + 'static>(&self, f: F) -> SignalHandlerId {
326 unsafe extern "C" fn after_paint_trampoline<F: Fn(&FrameClock) + 'static>(
327 this: *mut ffi::GdkFrameClock,
328 f: glib::ffi::gpointer,
329 ) {
330 let f: &F = &*(f as *const F);
331 f(&from_glib_borrow(this))
332 }
333 unsafe {
334 let f: Box_<F> = Box_::new(f);
335 connect_raw(
336 self.as_ptr() as *mut _,
337 b"after-paint\0".as_ptr() as *const _,
338 Some(std::mem::transmute::<*const (), unsafe extern "C" fn()>(
339 after_paint_trampoline::<F> as *const (),
340 )),
341 Box_::into_raw(f),
342 )
343 }
344 }
345
346 /// Begins processing of the frame.
347 ///
348 /// Applications should generally not handle this signal.
349 #[doc(alias = "before-paint")]
350 pub fn connect_before_paint<F: Fn(&Self) + 'static>(&self, f: F) -> SignalHandlerId {
351 unsafe extern "C" fn before_paint_trampoline<F: Fn(&FrameClock) + 'static>(
352 this: *mut ffi::GdkFrameClock,
353 f: glib::ffi::gpointer,
354 ) {
355 let f: &F = &*(f as *const F);
356 f(&from_glib_borrow(this))
357 }
358 unsafe {
359 let f: Box_<F> = Box_::new(f);
360 connect_raw(
361 self.as_ptr() as *mut _,
362 b"before-paint\0".as_ptr() as *const _,
363 Some(std::mem::transmute::<*const (), unsafe extern "C" fn()>(
364 before_paint_trampoline::<F> as *const (),
365 )),
366 Box_::into_raw(f),
367 )
368 }
369 }
370
371 /// Used to flush pending motion events that are being batched up and
372 /// compressed together.
373 ///
374 /// Applications should not handle this signal.
375 #[doc(alias = "flush-events")]
376 pub fn connect_flush_events<F: Fn(&Self) + 'static>(&self, f: F) -> SignalHandlerId {
377 unsafe extern "C" fn flush_events_trampoline<F: Fn(&FrameClock) + 'static>(
378 this: *mut ffi::GdkFrameClock,
379 f: glib::ffi::gpointer,
380 ) {
381 let f: &F = &*(f as *const F);
382 f(&from_glib_borrow(this))
383 }
384 unsafe {
385 let f: Box_<F> = Box_::new(f);
386 connect_raw(
387 self.as_ptr() as *mut _,
388 b"flush-events\0".as_ptr() as *const _,
389 Some(std::mem::transmute::<*const (), unsafe extern "C" fn()>(
390 flush_events_trampoline::<F> as *const (),
391 )),
392 Box_::into_raw(f),
393 )
394 }
395 }
396
397 /// Emitted as the second step of toolkit and application processing
398 /// of the frame.
399 ///
400 /// Any work to update sizes and positions of application elements
401 /// should be performed. GTK normally handles this internally.
402 #[doc(alias = "layout")]
403 pub fn connect_layout<F: Fn(&Self) + 'static>(&self, f: F) -> SignalHandlerId {
404 unsafe extern "C" fn layout_trampoline<F: Fn(&FrameClock) + 'static>(
405 this: *mut ffi::GdkFrameClock,
406 f: glib::ffi::gpointer,
407 ) {
408 let f: &F = &*(f as *const F);
409 f(&from_glib_borrow(this))
410 }
411 unsafe {
412 let f: Box_<F> = Box_::new(f);
413 connect_raw(
414 self.as_ptr() as *mut _,
415 b"layout\0".as_ptr() as *const _,
416 Some(std::mem::transmute::<*const (), unsafe extern "C" fn()>(
417 layout_trampoline::<F> as *const (),
418 )),
419 Box_::into_raw(f),
420 )
421 }
422 }
423
424 /// Emitted as the third step of toolkit and application processing
425 /// of the frame.
426 ///
427 /// The frame is repainted. GDK normally handles this internally and
428 /// emits [`render`][struct@crate::Surface#render] signals which are turned into
429 /// [GtkWidget::snapshot](../gtk4/signal.Widget.snapshot.html) signals
430 /// by GTK.
431 #[doc(alias = "paint")]
432 pub fn connect_paint<F: Fn(&Self) + 'static>(&self, f: F) -> SignalHandlerId {
433 unsafe extern "C" fn paint_trampoline<F: Fn(&FrameClock) + 'static>(
434 this: *mut ffi::GdkFrameClock,
435 f: glib::ffi::gpointer,
436 ) {
437 let f: &F = &*(f as *const F);
438 f(&from_glib_borrow(this))
439 }
440 unsafe {
441 let f: Box_<F> = Box_::new(f);
442 connect_raw(
443 self.as_ptr() as *mut _,
444 b"paint\0".as_ptr() as *const _,
445 Some(std::mem::transmute::<*const (), unsafe extern "C" fn()>(
446 paint_trampoline::<F> as *const (),
447 )),
448 Box_::into_raw(f),
449 )
450 }
451 }
452
453 /// Emitted after processing of the frame is finished.
454 ///
455 /// This signal is handled internally by GTK to resume normal
456 /// event processing. Applications should not handle this signal.
457 #[doc(alias = "resume-events")]
458 pub fn connect_resume_events<F: Fn(&Self) + 'static>(&self, f: F) -> SignalHandlerId {
459 unsafe extern "C" fn resume_events_trampoline<F: Fn(&FrameClock) + 'static>(
460 this: *mut ffi::GdkFrameClock,
461 f: glib::ffi::gpointer,
462 ) {
463 let f: &F = &*(f as *const F);
464 f(&from_glib_borrow(this))
465 }
466 unsafe {
467 let f: Box_<F> = Box_::new(f);
468 connect_raw(
469 self.as_ptr() as *mut _,
470 b"resume-events\0".as_ptr() as *const _,
471 Some(std::mem::transmute::<*const (), unsafe extern "C" fn()>(
472 resume_events_trampoline::<F> as *const (),
473 )),
474 Box_::into_raw(f),
475 )
476 }
477 }
478
479 /// Emitted as the first step of toolkit and application processing
480 /// of the frame.
481 ///
482 /// Animations should be updated using [`frame_time()`][Self::frame_time()].
483 /// Applications can connect directly to this signal, or use
484 /// [gtk_widget_add_tick_callback()](../gtk4/method.Widget.add_tick_callback.html)
485 /// as a more convenient interface.
486 #[doc(alias = "update")]
487 pub fn connect_update<F: Fn(&Self) + 'static>(&self, f: F) -> SignalHandlerId {
488 unsafe extern "C" fn update_trampoline<F: Fn(&FrameClock) + 'static>(
489 this: *mut ffi::GdkFrameClock,
490 f: glib::ffi::gpointer,
491 ) {
492 let f: &F = &*(f as *const F);
493 f(&from_glib_borrow(this))
494 }
495 unsafe {
496 let f: Box_<F> = Box_::new(f);
497 connect_raw(
498 self.as_ptr() as *mut _,
499 b"update\0".as_ptr() as *const _,
500 Some(std::mem::transmute::<*const (), unsafe extern "C" fn()>(
501 update_trampoline::<F> as *const (),
502 )),
503 Box_::into_raw(f),
504 )
505 }
506 }
507}