1/* Benchmark/Frames
2 *
3 * This demo is intentionally as simple as possible, to see what
4 * framerate the windowing system can deliver on its own.
5 *
6 * It does nothing but change the drawn color, for every frame.
7 */
8
9#include <gtk/gtk.h>
10
11typedef struct
12{
13 GtkWidget parent_instance;
14
15 GdkRGBA color1;
16 GdkRGBA color2;
17 guint64 time2;
18 float t;
19
20 guint tick_cb;
21} ColorWidget;
22
23typedef struct
24{
25 GtkWidgetClass parent_class;
26} ColorWidgetClass;
27
28G_DEFINE_TYPE (ColorWidget, color_widget, GTK_TYPE_WIDGET)
29
30#define TIME_SPAN (3.0 * G_TIME_SPAN_SECOND)
31
32static gboolean
33change_color (GtkWidget *widget,
34 GdkFrameClock *frame_clock,
35 gpointer data)
36{
37 ColorWidget *color = (ColorWidget *)widget;
38 gint64 time;
39
40 time = gdk_frame_clock_get_frame_time (frame_clock);
41
42 if (time >= color->time2)
43 {
44 color->time2 = time + TIME_SPAN;
45
46 color->color1 = color->color2;
47 color->color2.red = g_random_double_range (begin: 0, end: 1);
48 color->color2.green = g_random_double_range (begin: 0, end: 1);
49 color->color2.blue = g_random_double_range (begin: 0, end: 1);
50 color->color2.alpha = 1;
51 }
52
53 color->t = 1 - (color->time2 - time) / TIME_SPAN;
54
55 gtk_widget_queue_draw (widget);
56
57 return G_SOURCE_CONTINUE;
58}
59
60static void
61color_widget_snapshot (GtkWidget *widget,
62 GtkSnapshot *snapshot)
63{
64 ColorWidget *color = (ColorWidget *)widget;
65 float w, h;
66 GdkRGBA c;
67
68 w = gtk_widget_get_width (widget);
69 h = gtk_widget_get_height (widget);
70
71 c.red = (1 - color->t) * color->color1.red + color->t * color->color2.red;
72 c.green = (1 - color->t) * color->color1.green + color->t * color->color2.green;
73 c.blue = (1 - color->t) * color->color1.blue + color->t * color->color2.blue;
74 c.alpha = 1;
75
76 gtk_snapshot_append_color (snapshot, color: &c, bounds: &GRAPHENE_RECT_INIT (0, 0, w, h));
77}
78
79static void
80color_widget_init (ColorWidget *color)
81{
82 gtk_widget_add_tick_callback (GTK_WIDGET (color), callback: change_color, NULL, NULL);
83 gtk_widget_set_hexpand (GTK_WIDGET (color), TRUE);
84 gtk_widget_set_vexpand (GTK_WIDGET (color), TRUE);
85}
86
87static void
88color_widget_class_init (ColorWidgetClass *class)
89{
90 GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (class);
91
92 widget_class->snapshot = color_widget_snapshot;
93}
94
95GtkWidget *
96color_widget_new (void)
97{
98 return g_object_new (object_type: color_widget_get_type (), NULL);
99}
100
101static gboolean
102update_fps_label (gpointer data)
103{
104 GtkWidget *label = GTK_WIDGET (data);
105 GdkFrameClock *frame_clock;
106
107 frame_clock = gtk_widget_get_frame_clock (widget: label);
108
109 if (frame_clock)
110 {
111 char *fps;
112
113 fps = g_strdup_printf (format: "%.2f fps", gdk_frame_clock_get_fps (frame_clock));
114 gtk_label_set_label (GTK_LABEL (label), str: fps);
115 g_free (mem: fps);
116 }
117 else
118 gtk_label_set_label (GTK_LABEL (label), str: "");
119
120 return G_SOURCE_CONTINUE;
121}
122
123static void
124remove_id (gpointer data)
125{
126 guint id = GPOINTER_TO_UINT (data);
127
128 g_source_remove (tag: id);
129}
130
131GtkWidget *
132do_frames (GtkWidget *do_widget)
133{
134 static GtkWidget *window = NULL;
135
136 if (!window)
137 {
138 GtkBuilder *builder;
139 GtkWidget *box;
140 GtkWidget *label;
141 guint id;
142
143 builder = gtk_builder_new_from_resource (resource_path: "/frames/frames.ui");
144 window = GTK_WIDGET (gtk_builder_get_object (builder, "window"));
145 g_object_add_weak_pointer (G_OBJECT (window), weak_pointer_location: (gpointer *)&window);
146 gtk_window_set_display (GTK_WINDOW (window),
147 display: gtk_widget_get_display (widget: do_widget));
148
149 label = GTK_WIDGET (gtk_builder_get_object (builder, "fps"));
150 box = GTK_WIDGET (gtk_builder_get_object (builder, "box"));
151
152 gtk_box_append (GTK_BOX (box), child: color_widget_new ());
153
154 id = g_timeout_add (interval: 500, function: update_fps_label, data: label);
155 g_object_set_data_full (G_OBJECT (label), key: "tick_cb",
156 GUINT_TO_POINTER (id), destroy: remove_id);
157 }
158
159 if (!gtk_widget_get_visible (widget: window))
160 gtk_widget_show (widget: window);
161 else
162 gtk_window_destroy (GTK_WINDOW (window));
163
164 return window;
165}
166

source code of gtk/demos/gtk-demo/frames.c