Question

Background

I want to synchronize the updating of a widget to the screen refresh rate using GdkFrameClock. This is for visual stimulation response measurements off of an LCD screen (and therefore requiring as-close-to-exact frame synchronization as possible for purity of the signal).

I've read the documentation for the class, but it's limited in scope; I'm missing some overarching understanding of GdkFrameClock's place in the GTK world. Perusing the demos in the GTK source tree on GitHub has been fruitless for me.

Question

Assuming that I can, how do I use GdkFrameClock to synchronize the updating of the screen representation of a GtkDrawingArea (assume Cairo) to the screen refresh rate?

If I can't, what's the purpose of GdkFrameClock?

Was it helpful?

Solution

I haven't used GdkFrameClock in anger, just for a little bit of testing, but the following seems quite easy and works for me:

  1. Call gtk_widget_add_tick_callback(), passing the function you want to run on each refresh
  2. Roughly 60 times a second (or as appropriate for your system), your callback will be called
  3. When you're done, call gtk_widget_remove_tick_callback() or return FALSE from your callback to stop receiving updates.

In step 2, you are passed the GdkFrameClock in use, so you can call gdk_frame_clock_get_frame_time() to get the exact frame timestamp, or use gdk_frame_clock_get_timings() and the GdkFrameTimings API to do more interesting things.

The following Vala code (easily convertible to D I'm sure :-)) shows this in action:

private static bool on_frame_tick(Gtk.Widget widget, Gdk.FrameClock frame_clock)
{
    print("Got frame tick with timestamp %lld\n", frame_clock.get_frame_time());

    return true; // Keep going
}

void main(string[] args)
{
    Gtk.init(ref args);

    var w = new Gtk.Window(Gtk.WindowType.TOPLEVEL);
    w.add_tick_callback(on_frame_tick, null);
    w.show_all();

    Gtk.main();
}

Note that as per the docs, you'll need to call gtk_widget_queue_draw() (or queue_draw_area()) in your handler get it to get GTK to actually perform the redraw. This will in turn call the draw() function of the widget in question.

As such, what I'd do is to save the frame timing information in my tick callback, call queue_redraw(), then use the saved timing info in the draw() implementation of my GtkDrawingArea.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top