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