1 /*
2  * This file is part of gtkD.
3  *
4  * gtkD is free software; you can redistribute it and/or modify
5  * it under the terms of the GNU Lesser General Public License
6  * as published by the Free Software Foundation; either version 3
7  * of the License, or (at your option) any later version, with
8  * some exceptions, please read the COPYING file.
9  *
10  * gtkD is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU Lesser General Public License for more details.
14  *
15  * You should have received a copy of the GNU Lesser General Public License
16  * along with gtkD; if not, write to the Free Software
17  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA
18  */
19 
20 // generated automatically - do not change
21 // find conversion definition on APILookup.txt
22 // implement new conversion functionalities on the wrap.utils pakage
23 
24 
25 module gdk.FrameClock;
26 
27 private import gdk.FrameTimings;
28 private import gdk.c.functions;
29 public  import gdk.c.types;
30 private import gobject.ObjectG;
31 private import gobject.Signals;
32 public  import gtkc.gdktypes;
33 private import std.algorithm;
34 
35 
36 /**
37  * A #GdkFrameClock tells the application when to update and repaint a
38  * window. This may be synced to the vertical refresh rate of the
39  * monitor, for example. Even when the frame clock uses a simple timer
40  * rather than a hardware-based vertical sync, the frame clock helps
41  * because it ensures everything paints at the same time (reducing the
42  * total number of frames). The frame clock can also automatically
43  * stop painting when it knows the frames will not be visible, or
44  * scale back animation framerates.
45  * 
46  * #GdkFrameClock is designed to be compatible with an OpenGL-based
47  * implementation or with mozRequestAnimationFrame in Firefox,
48  * for example.
49  * 
50  * A frame clock is idle until someone requests a frame with
51  * gdk_frame_clock_request_phase(). At some later point that makes
52  * sense for the synchronization being implemented, the clock will
53  * process a frame and emit signals for each phase that has been
54  * requested. (See the signals of the #GdkFrameClock class for
55  * documentation of the phases. %GDK_FRAME_CLOCK_PHASE_UPDATE and the
56  * #GdkFrameClock::update signal are most interesting for application
57  * writers, and are used to update the animations, using the frame time
58  * given by gdk_frame_clock_get_frame_time().
59  * 
60  * The frame time is reported in microseconds and generally in the same
61  * timescale as g_get_monotonic_time(), however, it is not the same
62  * as g_get_monotonic_time(). The frame time does not advance during
63  * the time a frame is being painted, and outside of a frame, an attempt
64  * is made so that all calls to gdk_frame_clock_get_frame_time() that
65  * are called at a “similar” time get the same value. This means that
66  * if different animations are timed by looking at the difference in
67  * time between an initial value from gdk_frame_clock_get_frame_time()
68  * and the value inside the #GdkFrameClock::update signal of the clock,
69  * they will stay exactly synchronized.
70  */
71 public class FrameClock : ObjectG
72 {
73 	/** the main Gtk struct */
74 	protected GdkFrameClock* gdkFrameClock;
75 
76 	/** Get the main Gtk struct */
77 	public GdkFrameClock* getFrameClockStruct(bool transferOwnership = false)
78 	{
79 		if (transferOwnership)
80 			ownedRef = false;
81 		return gdkFrameClock;
82 	}
83 
84 	/** the main Gtk struct as a void* */
85 	protected override void* getStruct()
86 	{
87 		return cast(void*)gdkFrameClock;
88 	}
89 
90 	protected override void setStruct(GObject* obj)
91 	{
92 		gdkFrameClock = cast(GdkFrameClock*)obj;
93 		super.setStruct(obj);
94 	}
95 
96 	/**
97 	 * Sets our main struct and passes it to the parent class.
98 	 */
99 	public this (GdkFrameClock* gdkFrameClock, bool ownedRef = false)
100 	{
101 		this.gdkFrameClock = gdkFrameClock;
102 		super(cast(GObject*)gdkFrameClock, ownedRef);
103 	}
104 
105 
106 	/** */
107 	public static GType getType()
108 	{
109 		return gdk_frame_clock_get_type();
110 	}
111 
112 	/**
113 	 * Starts updates for an animation. Until a matching call to
114 	 * gdk_frame_clock_end_updating() is made, the frame clock will continually
115 	 * request a new frame with the %GDK_FRAME_CLOCK_PHASE_UPDATE phase.
116 	 * This function may be called multiple times and frames will be
117 	 * requested until gdk_frame_clock_end_updating() is called the same
118 	 * number of times.
119 	 *
120 	 * Since: 3.8
121 	 */
122 	public void beginUpdating()
123 	{
124 		gdk_frame_clock_begin_updating(gdkFrameClock);
125 	}
126 
127 	/**
128 	 * Stops updates for an animation. See the documentation for
129 	 * gdk_frame_clock_begin_updating().
130 	 *
131 	 * Since: 3.8
132 	 */
133 	public void endUpdating()
134 	{
135 		gdk_frame_clock_end_updating(gdkFrameClock);
136 	}
137 
138 	/**
139 	 * Gets the frame timings for the current frame.
140 	 *
141 	 * Returns: the #GdkFrameTimings for the frame currently
142 	 *     being processed, or even no frame is being processed, for the
143 	 *     previous frame. Before any frames have been procesed, returns
144 	 *     %NULL.
145 	 *
146 	 * Since: 3.8
147 	 */
148 	public FrameTimings getCurrentTimings()
149 	{
150 		auto p = gdk_frame_clock_get_current_timings(gdkFrameClock);
151 
152 		if(p is null)
153 		{
154 			return null;
155 		}
156 
157 		return ObjectG.getDObject!(FrameTimings)(cast(GdkFrameTimings*) p, true);
158 	}
159 
160 	/**
161 	 * A #GdkFrameClock maintains a 64-bit counter that increments for
162 	 * each frame drawn.
163 	 *
164 	 * Returns: inside frame processing, the value of the frame counter
165 	 *     for the current frame. Outside of frame processing, the frame
166 	 *     counter for the last frame.
167 	 *
168 	 * Since: 3.8
169 	 */
170 	public long getFrameCounter()
171 	{
172 		return gdk_frame_clock_get_frame_counter(gdkFrameClock);
173 	}
174 
175 	/**
176 	 * Gets the time that should currently be used for animations.  Inside
177 	 * the processing of a frame, it’s the time used to compute the
178 	 * animation position of everything in a frame. Outside of a frame, it's
179 	 * the time of the conceptual “previous frame,” which may be either
180 	 * the actual previous frame time, or if that’s too old, an updated
181 	 * time.
182 	 *
183 	 * Returns: a timestamp in microseconds, in the timescale of
184 	 *     of g_get_monotonic_time().
185 	 *
186 	 * Since: 3.8
187 	 */
188 	public long getFrameTime()
189 	{
190 		return gdk_frame_clock_get_frame_time(gdkFrameClock);
191 	}
192 
193 	/**
194 	 * #GdkFrameClock internally keeps a history of #GdkFrameTimings
195 	 * objects for recent frames that can be retrieved with
196 	 * gdk_frame_clock_get_timings(). The set of stored frames
197 	 * is the set from the counter values given by
198 	 * gdk_frame_clock_get_history_start() and
199 	 * gdk_frame_clock_get_frame_counter(), inclusive.
200 	 *
201 	 * Returns: the frame counter value for the oldest frame
202 	 *     that is available in the internal frame history of the
203 	 *     #GdkFrameClock.
204 	 *
205 	 * Since: 3.8
206 	 */
207 	public long getHistoryStart()
208 	{
209 		return gdk_frame_clock_get_history_start(gdkFrameClock);
210 	}
211 
212 	/**
213 	 * Using the frame history stored in the frame clock, finds the last
214 	 * known presentation time and refresh interval, and assuming that
215 	 * presentation times are separated by the refresh interval,
216 	 * predicts a presentation time that is a multiple of the refresh
217 	 * interval after the last presentation time, and later than @base_time.
218 	 *
219 	 * Params:
220 	 *     baseTime = base time for determining a presentaton time
221 	 *     refreshIntervalReturn = a location to store the determined refresh
222 	 *         interval, or %NULL. A default refresh interval of 1/60th of
223 	 *         a second will be stored if no history is present.
224 	 *     presentationTimeReturn = a location to store the next
225 	 *         candidate presentation time after the given base time.
226 	 *         0 will be will be stored if no history is present.
227 	 *
228 	 * Since: 3.8
229 	 */
230 	public void getRefreshInfo(long baseTime, long* refreshIntervalReturn, long* presentationTimeReturn)
231 	{
232 		gdk_frame_clock_get_refresh_info(gdkFrameClock, baseTime, refreshIntervalReturn, presentationTimeReturn);
233 	}
234 
235 	/**
236 	 * Retrieves a #GdkFrameTimings object holding timing information
237 	 * for the current frame or a recent frame. The #GdkFrameTimings
238 	 * object may not yet be complete: see gdk_frame_timings_get_complete().
239 	 *
240 	 * Params:
241 	 *     frameCounter = the frame counter value identifying the frame to
242 	 *         be received.
243 	 *
244 	 * Returns: the #GdkFrameTimings object for the specified
245 	 *     frame, or %NULL if it is not available. See
246 	 *     gdk_frame_clock_get_history_start().
247 	 *
248 	 * Since: 3.8
249 	 */
250 	public FrameTimings getTimings(long frameCounter)
251 	{
252 		auto p = gdk_frame_clock_get_timings(gdkFrameClock, frameCounter);
253 
254 		if(p is null)
255 		{
256 			return null;
257 		}
258 
259 		return ObjectG.getDObject!(FrameTimings)(cast(GdkFrameTimings*) p, true);
260 	}
261 
262 	/**
263 	 * Asks the frame clock to run a particular phase. The signal
264 	 * corresponding the requested phase will be emitted the next
265 	 * time the frame clock processes. Multiple calls to
266 	 * gdk_frame_clock_request_phase() will be combined together
267 	 * and only one frame processed. If you are displaying animated
268 	 * content and want to continually request the
269 	 * %GDK_FRAME_CLOCK_PHASE_UPDATE phase for a period of time,
270 	 * you should use gdk_frame_clock_begin_updating() instead, since
271 	 * this allows GTK+ to adjust system parameters to get maximally
272 	 * smooth animations.
273 	 *
274 	 * Params:
275 	 *     phase = the phase that is requested
276 	 *
277 	 * Since: 3.8
278 	 */
279 	public void requestPhase(GdkFrameClockPhase phase)
280 	{
281 		gdk_frame_clock_request_phase(gdkFrameClock, phase);
282 	}
283 
284 	protected class OnAfterPaintDelegateWrapper
285 	{
286 		void delegate(FrameClock) dlg;
287 		gulong handlerId;
288 
289 		this(void delegate(FrameClock) dlg)
290 		{
291 			this.dlg = dlg;
292 			onAfterPaintListeners ~= this;
293 		}
294 
295 		void remove(OnAfterPaintDelegateWrapper source)
296 		{
297 			foreach(index, wrapper; onAfterPaintListeners)
298 			{
299 				if (wrapper.handlerId == source.handlerId)
300 				{
301 					onAfterPaintListeners[index] = null;
302 					onAfterPaintListeners = std.algorithm.remove(onAfterPaintListeners, index);
303 					break;
304 				}
305 			}
306 		}
307 	}
308 	OnAfterPaintDelegateWrapper[] onAfterPaintListeners;
309 
310 	/**
311 	 * This signal ends processing of the frame. Applications
312 	 * should generally not handle this signal.
313 	 */
314 	gulong addOnAfterPaint(void delegate(FrameClock) dlg, ConnectFlags connectFlags=cast(ConnectFlags)0)
315 	{
316 		auto wrapper = new OnAfterPaintDelegateWrapper(dlg);
317 		wrapper.handlerId = Signals.connectData(
318 			this,
319 			"after-paint",
320 			cast(GCallback)&callBackAfterPaint,
321 			cast(void*)wrapper,
322 			cast(GClosureNotify)&callBackAfterPaintDestroy,
323 			connectFlags);
324 		return wrapper.handlerId;
325 	}
326 
327 	extern(C) static void callBackAfterPaint(GdkFrameClock* frameclockStruct, OnAfterPaintDelegateWrapper wrapper)
328 	{
329 		wrapper.dlg(wrapper.outer);
330 	}
331 
332 	extern(C) static void callBackAfterPaintDestroy(OnAfterPaintDelegateWrapper wrapper, GClosure* closure)
333 	{
334 		wrapper.remove(wrapper);
335 	}
336 
337 	protected class OnBeforePaintDelegateWrapper
338 	{
339 		void delegate(FrameClock) dlg;
340 		gulong handlerId;
341 
342 		this(void delegate(FrameClock) dlg)
343 		{
344 			this.dlg = dlg;
345 			onBeforePaintListeners ~= this;
346 		}
347 
348 		void remove(OnBeforePaintDelegateWrapper source)
349 		{
350 			foreach(index, wrapper; onBeforePaintListeners)
351 			{
352 				if (wrapper.handlerId == source.handlerId)
353 				{
354 					onBeforePaintListeners[index] = null;
355 					onBeforePaintListeners = std.algorithm.remove(onBeforePaintListeners, index);
356 					break;
357 				}
358 			}
359 		}
360 	}
361 	OnBeforePaintDelegateWrapper[] onBeforePaintListeners;
362 
363 	/**
364 	 * This signal begins processing of the frame. Applications
365 	 * should generally not handle this signal.
366 	 */
367 	gulong addOnBeforePaint(void delegate(FrameClock) dlg, ConnectFlags connectFlags=cast(ConnectFlags)0)
368 	{
369 		auto wrapper = new OnBeforePaintDelegateWrapper(dlg);
370 		wrapper.handlerId = Signals.connectData(
371 			this,
372 			"before-paint",
373 			cast(GCallback)&callBackBeforePaint,
374 			cast(void*)wrapper,
375 			cast(GClosureNotify)&callBackBeforePaintDestroy,
376 			connectFlags);
377 		return wrapper.handlerId;
378 	}
379 
380 	extern(C) static void callBackBeforePaint(GdkFrameClock* frameclockStruct, OnBeforePaintDelegateWrapper wrapper)
381 	{
382 		wrapper.dlg(wrapper.outer);
383 	}
384 
385 	extern(C) static void callBackBeforePaintDestroy(OnBeforePaintDelegateWrapper wrapper, GClosure* closure)
386 	{
387 		wrapper.remove(wrapper);
388 	}
389 
390 	protected class OnFlushEventsDelegateWrapper
391 	{
392 		void delegate(FrameClock) dlg;
393 		gulong handlerId;
394 
395 		this(void delegate(FrameClock) dlg)
396 		{
397 			this.dlg = dlg;
398 			onFlushEventsListeners ~= this;
399 		}
400 
401 		void remove(OnFlushEventsDelegateWrapper source)
402 		{
403 			foreach(index, wrapper; onFlushEventsListeners)
404 			{
405 				if (wrapper.handlerId == source.handlerId)
406 				{
407 					onFlushEventsListeners[index] = null;
408 					onFlushEventsListeners = std.algorithm.remove(onFlushEventsListeners, index);
409 					break;
410 				}
411 			}
412 		}
413 	}
414 	OnFlushEventsDelegateWrapper[] onFlushEventsListeners;
415 
416 	/**
417 	 * This signal is used to flush pending motion events that
418 	 * are being batched up and compressed together. Applications
419 	 * should not handle this signal.
420 	 */
421 	gulong addOnFlushEvents(void delegate(FrameClock) dlg, ConnectFlags connectFlags=cast(ConnectFlags)0)
422 	{
423 		auto wrapper = new OnFlushEventsDelegateWrapper(dlg);
424 		wrapper.handlerId = Signals.connectData(
425 			this,
426 			"flush-events",
427 			cast(GCallback)&callBackFlushEvents,
428 			cast(void*)wrapper,
429 			cast(GClosureNotify)&callBackFlushEventsDestroy,
430 			connectFlags);
431 		return wrapper.handlerId;
432 	}
433 
434 	extern(C) static void callBackFlushEvents(GdkFrameClock* frameclockStruct, OnFlushEventsDelegateWrapper wrapper)
435 	{
436 		wrapper.dlg(wrapper.outer);
437 	}
438 
439 	extern(C) static void callBackFlushEventsDestroy(OnFlushEventsDelegateWrapper wrapper, GClosure* closure)
440 	{
441 		wrapper.remove(wrapper);
442 	}
443 
444 	protected class OnLayoutDelegateWrapper
445 	{
446 		void delegate(FrameClock) dlg;
447 		gulong handlerId;
448 
449 		this(void delegate(FrameClock) dlg)
450 		{
451 			this.dlg = dlg;
452 			onLayoutListeners ~= this;
453 		}
454 
455 		void remove(OnLayoutDelegateWrapper source)
456 		{
457 			foreach(index, wrapper; onLayoutListeners)
458 			{
459 				if (wrapper.handlerId == source.handlerId)
460 				{
461 					onLayoutListeners[index] = null;
462 					onLayoutListeners = std.algorithm.remove(onLayoutListeners, index);
463 					break;
464 				}
465 			}
466 		}
467 	}
468 	OnLayoutDelegateWrapper[] onLayoutListeners;
469 
470 	/**
471 	 * This signal is emitted as the second step of toolkit and
472 	 * application processing of the frame. Any work to update
473 	 * sizes and positions of application elements should be
474 	 * performed. GTK+ normally handles this internally.
475 	 */
476 	gulong addOnLayout(void delegate(FrameClock) dlg, ConnectFlags connectFlags=cast(ConnectFlags)0)
477 	{
478 		auto wrapper = new OnLayoutDelegateWrapper(dlg);
479 		wrapper.handlerId = Signals.connectData(
480 			this,
481 			"layout",
482 			cast(GCallback)&callBackLayout,
483 			cast(void*)wrapper,
484 			cast(GClosureNotify)&callBackLayoutDestroy,
485 			connectFlags);
486 		return wrapper.handlerId;
487 	}
488 
489 	extern(C) static void callBackLayout(GdkFrameClock* frameclockStruct, OnLayoutDelegateWrapper wrapper)
490 	{
491 		wrapper.dlg(wrapper.outer);
492 	}
493 
494 	extern(C) static void callBackLayoutDestroy(OnLayoutDelegateWrapper wrapper, GClosure* closure)
495 	{
496 		wrapper.remove(wrapper);
497 	}
498 
499 	protected class OnPaintDelegateWrapper
500 	{
501 		void delegate(FrameClock) dlg;
502 		gulong handlerId;
503 
504 		this(void delegate(FrameClock) dlg)
505 		{
506 			this.dlg = dlg;
507 			onPaintListeners ~= this;
508 		}
509 
510 		void remove(OnPaintDelegateWrapper source)
511 		{
512 			foreach(index, wrapper; onPaintListeners)
513 			{
514 				if (wrapper.handlerId == source.handlerId)
515 				{
516 					onPaintListeners[index] = null;
517 					onPaintListeners = std.algorithm.remove(onPaintListeners, index);
518 					break;
519 				}
520 			}
521 		}
522 	}
523 	OnPaintDelegateWrapper[] onPaintListeners;
524 
525 	/**
526 	 * This signal is emitted as the third step of toolkit and
527 	 * application processing of the frame. The frame is
528 	 * repainted. GDK normally handles this internally and
529 	 * produces expose events, which are turned into GTK+
530 	 * #GtkWidget::draw signals.
531 	 */
532 	gulong addOnPaint(void delegate(FrameClock) dlg, ConnectFlags connectFlags=cast(ConnectFlags)0)
533 	{
534 		auto wrapper = new OnPaintDelegateWrapper(dlg);
535 		wrapper.handlerId = Signals.connectData(
536 			this,
537 			"paint",
538 			cast(GCallback)&callBackPaint,
539 			cast(void*)wrapper,
540 			cast(GClosureNotify)&callBackPaintDestroy,
541 			connectFlags);
542 		return wrapper.handlerId;
543 	}
544 
545 	extern(C) static void callBackPaint(GdkFrameClock* frameclockStruct, OnPaintDelegateWrapper wrapper)
546 	{
547 		wrapper.dlg(wrapper.outer);
548 	}
549 
550 	extern(C) static void callBackPaintDestroy(OnPaintDelegateWrapper wrapper, GClosure* closure)
551 	{
552 		wrapper.remove(wrapper);
553 	}
554 
555 	protected class OnResumeEventsDelegateWrapper
556 	{
557 		void delegate(FrameClock) dlg;
558 		gulong handlerId;
559 
560 		this(void delegate(FrameClock) dlg)
561 		{
562 			this.dlg = dlg;
563 			onResumeEventsListeners ~= this;
564 		}
565 
566 		void remove(OnResumeEventsDelegateWrapper source)
567 		{
568 			foreach(index, wrapper; onResumeEventsListeners)
569 			{
570 				if (wrapper.handlerId == source.handlerId)
571 				{
572 					onResumeEventsListeners[index] = null;
573 					onResumeEventsListeners = std.algorithm.remove(onResumeEventsListeners, index);
574 					break;
575 				}
576 			}
577 		}
578 	}
579 	OnResumeEventsDelegateWrapper[] onResumeEventsListeners;
580 
581 	/**
582 	 * This signal is emitted after processing of the frame is
583 	 * finished, and is handled internally by GTK+ to resume normal
584 	 * event processing. Applications should not handle this signal.
585 	 */
586 	gulong addOnResumeEvents(void delegate(FrameClock) dlg, ConnectFlags connectFlags=cast(ConnectFlags)0)
587 	{
588 		auto wrapper = new OnResumeEventsDelegateWrapper(dlg);
589 		wrapper.handlerId = Signals.connectData(
590 			this,
591 			"resume-events",
592 			cast(GCallback)&callBackResumeEvents,
593 			cast(void*)wrapper,
594 			cast(GClosureNotify)&callBackResumeEventsDestroy,
595 			connectFlags);
596 		return wrapper.handlerId;
597 	}
598 
599 	extern(C) static void callBackResumeEvents(GdkFrameClock* frameclockStruct, OnResumeEventsDelegateWrapper wrapper)
600 	{
601 		wrapper.dlg(wrapper.outer);
602 	}
603 
604 	extern(C) static void callBackResumeEventsDestroy(OnResumeEventsDelegateWrapper wrapper, GClosure* closure)
605 	{
606 		wrapper.remove(wrapper);
607 	}
608 
609 	protected class OnUpdateDelegateWrapper
610 	{
611 		void delegate(FrameClock) dlg;
612 		gulong handlerId;
613 
614 		this(void delegate(FrameClock) dlg)
615 		{
616 			this.dlg = dlg;
617 			onUpdateListeners ~= this;
618 		}
619 
620 		void remove(OnUpdateDelegateWrapper source)
621 		{
622 			foreach(index, wrapper; onUpdateListeners)
623 			{
624 				if (wrapper.handlerId == source.handlerId)
625 				{
626 					onUpdateListeners[index] = null;
627 					onUpdateListeners = std.algorithm.remove(onUpdateListeners, index);
628 					break;
629 				}
630 			}
631 		}
632 	}
633 	OnUpdateDelegateWrapper[] onUpdateListeners;
634 
635 	/**
636 	 * This signal is emitted as the first step of toolkit and
637 	 * application processing of the frame. Animations should
638 	 * be updated using gdk_frame_clock_get_frame_time().
639 	 * Applications can connect directly to this signal, or
640 	 * use gtk_widget_add_tick_callback() as a more convenient
641 	 * interface.
642 	 */
643 	gulong addOnUpdate(void delegate(FrameClock) dlg, ConnectFlags connectFlags=cast(ConnectFlags)0)
644 	{
645 		auto wrapper = new OnUpdateDelegateWrapper(dlg);
646 		wrapper.handlerId = Signals.connectData(
647 			this,
648 			"update",
649 			cast(GCallback)&callBackUpdate,
650 			cast(void*)wrapper,
651 			cast(GClosureNotify)&callBackUpdateDestroy,
652 			connectFlags);
653 		return wrapper.handlerId;
654 	}
655 
656 	extern(C) static void callBackUpdate(GdkFrameClock* frameclockStruct, OnUpdateDelegateWrapper wrapper)
657 	{
658 		wrapper.dlg(wrapper.outer);
659 	}
660 
661 	extern(C) static void callBackUpdateDestroy(OnUpdateDelegateWrapper wrapper, GClosure* closure)
662 	{
663 		wrapper.remove(wrapper);
664 	}
665 }