]> Pileus Git - ~andy/gtk/blob - tests/animated-resizing.c
Add a test of an animated resizing window
[~andy/gtk] / tests / animated-resizing.c
1 /* -*- mode: C; c-basic-offset: 2; indent-tabs-mode: nil; -*- */
2
3 #include <gtk/gtk.h>
4 #include <math.h>
5
6 #define WIDTH 600
7 #define HEIGHT 600
8 #define WINDOW_SIZE_JITTER 200
9 #define CYCLE_TIME 5.
10
11 static GtkWidget *window;
12 static int window_width = WIDTH, window_height = HEIGHT;
13
14 static double angle;
15 static int frames_since_last_print = 0;
16
17 static double load_factor = 1.0;
18 static double cb_no_resize = FALSE;
19
20 static cairo_surface_t *source_surface;
21
22 static void
23 ensure_resources(cairo_surface_t *target)
24 {
25   cairo_t *cr;
26   int i, j;
27
28   if (source_surface != NULL)
29     return;
30
31   source_surface = cairo_surface_create_similar (target, CAIRO_CONTENT_COLOR_ALPHA, 2048, 2048);
32   cr = cairo_create(source_surface);
33
34   cairo_save(cr);
35   cairo_set_source_rgba(cr, 0, 0, 0, 0);
36   cairo_set_operator(cr, CAIRO_OPERATOR_SOURCE);
37   cairo_paint(cr);
38   cairo_restore(cr);
39
40   cairo_set_line_width(cr, 1.0);
41
42   for (j = 0; j < 16; j++)
43     for (i = 0; i < 16; i++)
44       {
45         cairo_set_source_rgba(cr,
46                               ((i * 41) % 16) / 15.,
47                               ((i * 31) % 16) / 15.,
48                               ((i * 23) % 16) / 15.,
49                               0.25);
50         cairo_arc(cr,
51                   i * 128 + 64, j * 128 + 64,
52                   64 - 0.5, 0, 2 * M_PI);
53         cairo_fill_preserve(cr);
54         cairo_set_source_rgba(cr,
55                               ((i * 41) % 16) / 15.,
56                               ((i * 31) % 16) / 15.,
57                               ((i * 23) % 16) / 15.,
58                               1.0);
59         cairo_stroke(cr);
60       }
61 }
62
63 static void
64 on_window_draw (GtkWidget *widget,
65                 cairo_t   *cr)
66
67 {
68   GRand *rand = g_rand_new_with_seed(0);
69   int i;
70   int width, height;
71
72   width = gtk_widget_get_allocated_width (widget);
73   height = gtk_widget_get_allocated_height (widget);
74
75   ensure_resources (cairo_get_target (cr));
76
77   cairo_set_source_rgb(cr, 1, 1, 1);
78   cairo_paint(cr);
79
80   cairo_set_source_rgb(cr, 0, 0, 0);
81   cairo_set_line_width(cr, 1.0);
82   cairo_rectangle (cr, 0.5, 0.5, width - 1, height - 1);
83   cairo_stroke (cr);
84
85   for(i = 0; i < load_factor * 150; i++)
86     {
87       int source = g_rand_int_range(rand, 0, 255);
88       double phi = g_rand_double_range(rand, 0, 2 * M_PI) + angle;
89       double r = g_rand_double_range(rand, 0, width / 2 - 64);
90       int x, y;
91
92       int source_x = (source % 16) * 128;
93       int source_y = (source / 16) * 128;
94
95       x = round(width / 2 + r * cos(phi) - 64);
96       y = round(height / 2 - r * sin(phi) - 64);
97
98       cairo_set_source_surface(cr, source_surface,
99                                x - source_x, y - source_y);
100       cairo_rectangle(cr, x, y, 128, 128);
101       cairo_fill(cr);
102     }
103
104   g_rand_free(rand);
105 }
106
107 static void
108 on_frame (GtkTimeline *timeline,
109           double       progress)
110 {
111   int jitter;
112   double current_time;
113   static double last_print_time = 0;
114
115   current_time = g_get_monotonic_time () / 1000000.;
116   if (current_time >= last_print_time + 5)
117     {
118       if (frames_since_last_print != 0)
119         {
120           g_print ("%g\n", frames_since_last_print / (current_time - last_print_time));
121           frames_since_last_print = 0;
122         }
123
124       last_print_time = current_time;
125     }
126   frames_since_last_print++;
127
128   angle = 2 * M_PI * progress;
129   jitter = WINDOW_SIZE_JITTER * sin(angle);
130
131   if (!cb_no_resize)
132     {
133       window_width = WIDTH + jitter;
134       window_height = HEIGHT + jitter;
135     }
136
137   gtk_window_resize (GTK_WINDOW (window),
138                      window_width, window_height);
139
140   gtk_widget_queue_draw (window);
141 }
142
143 static GOptionEntry options[] = {
144   { "factor", 'f', 0, G_OPTION_ARG_DOUBLE, &load_factor, "Load factor", "FACTOR" },
145   { "no-resize", 'n', 0, G_OPTION_ARG_NONE, &cb_no_resize, "No Resize", NULL },
146   { NULL }
147 };
148
149 int
150 main(int argc, char **argv)
151 {
152   GError *error = NULL;
153   GdkScreen *screen;
154   GdkRectangle monitor_bounds;
155   GtkTimeline *timeline;
156
157   if (!gtk_init_with_args (&argc, &argv, "",
158                            options, NULL, NULL))
159     {
160       g_printerr ("Option parsing failed: %s", error->message);
161       return 1;
162     }
163
164   window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
165   gtk_window_set_keep_above (GTK_WINDOW (window), TRUE);
166   gtk_window_set_gravity (GTK_WINDOW (window), GDK_GRAVITY_CENTER);
167   gtk_widget_set_app_paintable (window, TRUE);
168
169   g_signal_connect (window, "draw",
170                     G_CALLBACK (on_window_draw), NULL);
171   g_signal_connect (window, "destroy",
172                     G_CALLBACK (gtk_main_quit), NULL);
173
174   timeline = gtk_timeline_new (window, CYCLE_TIME * 1000);
175   gtk_timeline_set_loop (timeline, TRUE);
176   gtk_timeline_set_progress_type (timeline, GTK_TIMELINE_PROGRESS_LINEAR);
177
178   g_signal_connect (timeline, "frame",
179                     G_CALLBACK (on_frame), NULL);
180   on_frame (timeline, 0.);
181   gtk_timeline_start (timeline);
182
183   screen = gtk_widget_get_screen (window);
184   gdk_screen_get_monitor_geometry (screen,
185                                    gdk_screen_get_primary_monitor (screen),
186                                    &monitor_bounds);
187
188   gtk_window_move (GTK_WINDOW (window),
189                    monitor_bounds.x + (monitor_bounds.width - window_width) / 2,
190                    monitor_bounds.y + (monitor_bounds.height - window_height) / 2);
191
192   gtk_widget_show (window);
193
194   gtk_main ();
195
196   return 0;
197 }