I've made very simple animation with gtk3 and cairo. I've got g_timeout_add
and it should call draw
function every 1ms, but it call draw
much slower than should. Why it happens and how can I fix it?
#include <gtk/gtk.h>
#include <cairo.h>
gboolean timeout(GtkWidget *widget)
{
gtk_widget_queue_draw(widget);
return TRUE;
}
void draw(GtkWidget* widget, cairo_t* cr)
{
static int width, height,
posX = 0,
vX = 1;
GtkWidget* window = gtk_widget_get_toplevel(widget);
gtk_window_get_size(GTK_WINDOW(window), &width, &height);
cairo_set_source_rgb(cr, 0, 0, 0);
cairo_set_line_width(cr, 1);
cairo_rectangle(cr, posX, height/2, 1, 1);
cairo_stroke(cr);
if(posX + vX >= width || posX + vX == 0)
vX = -vX;
posX += vX;
}
int main(int argc, char** argv)
{
GtkWidget* window;
GtkWidget* darea;
gtk_init(&argc, &argv);
window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
darea = gtk_drawing_area_new();
gtk_container_add(GTK_CONTAINER(window), darea);
gtk_window_set_default_size(GTK_WINDOW(window), 500, 400);
g_signal_connect(G_OBJECT(window), "destroy", G_CALLBACK(gtk_main_quit), NULL);
g_signal_connect(G_OBJECT(darea), "draw", G_CALLBACK(draw), NULL);
g_timeout_add(1, (GSourceFunc)timeout, window);
gtk_widget_show_all(window);
gtk_main();
}
Why it happens and
This was answered by Zrax. I just want to add something: I added the following to your draw function (and added the appropriate includes)
struct timeval tv;
gettimeofday(&tv, NULL);
printf("%d.%06d\n", (int) tv.tv_sec, (int) tv.tv_usec);
and I get output like the following:
1518869317.202412
1518869317.218970
1518869317.236563
1518869317.253032
1518869317.269721
1518869317.286305
So your draw function is called about every 17 milliseconds, or about 60 times per second.
how can I fix it?
This raises the question: Why do you want to draw faster than 60 fps anyway?
How about creating a GTimer
and using g_timer_elapsed()
to figure out where you have to draw? I.e. instead of assuming that you are drawing fast enough, you just compute the current graphics state each time you draw.