From 623803c1fe8692ae2809ab7a502a1bce38ddf2f3 Mon Sep 17 00:00:00 2001 From: "Owen W. Taylor" Date: Tue, 18 Sep 2012 18:21:08 -0400 Subject: [PATCH] Add a test of an animated resizing window Add a test of a window with an animated size and contents. The test accepts load factor command line argument to see how things work as the drawing of the content requires more GPU resources. https://bugzilla.gnome.org/show_bug.cgi?id=685460 --- tests/Makefile.am | 2 + tests/animated-resizing.c | 197 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 199 insertions(+) create mode 100644 tests/animated-resizing.c diff --git a/tests/Makefile.am b/tests/Makefile.am index 1993991869..7917905090 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -25,6 +25,7 @@ testsocket_programs = testsocket testsocket_child endif noinst_PROGRAMS = $(TEST_PROGS) \ + animated-resizing \ simple \ flicker \ print-editor \ @@ -149,6 +150,7 @@ endif endif +animated_resizing_DEPENDENCIES = $(TEST_DEPS) flicker_DEPENDENCIES = $(TEST_DEPS) simple_DEPENDENCIES = $(TEST_DEPS) print_editor_DEPENDENCIES = $(TEST_DEPS) diff --git a/tests/animated-resizing.c b/tests/animated-resizing.c new file mode 100644 index 0000000000..bf36551c58 --- /dev/null +++ b/tests/animated-resizing.c @@ -0,0 +1,197 @@ +/* -*- mode: C; c-basic-offset: 2; indent-tabs-mode: nil; -*- */ + +#include +#include + +#define WIDTH 600 +#define HEIGHT 600 +#define WINDOW_SIZE_JITTER 200 +#define CYCLE_TIME 5. + +static GtkWidget *window; +static int window_width = WIDTH, window_height = HEIGHT; + +static double angle; +static int frames_since_last_print = 0; + +static double load_factor = 1.0; +static double cb_no_resize = FALSE; + +static cairo_surface_t *source_surface; + +static void +ensure_resources(cairo_surface_t *target) +{ + cairo_t *cr; + int i, j; + + if (source_surface != NULL) + return; + + source_surface = cairo_surface_create_similar (target, CAIRO_CONTENT_COLOR_ALPHA, 2048, 2048); + cr = cairo_create(source_surface); + + cairo_save(cr); + cairo_set_source_rgba(cr, 0, 0, 0, 0); + cairo_set_operator(cr, CAIRO_OPERATOR_SOURCE); + cairo_paint(cr); + cairo_restore(cr); + + cairo_set_line_width(cr, 1.0); + + for (j = 0; j < 16; j++) + for (i = 0; i < 16; i++) + { + cairo_set_source_rgba(cr, + ((i * 41) % 16) / 15., + ((i * 31) % 16) / 15., + ((i * 23) % 16) / 15., + 0.25); + cairo_arc(cr, + i * 128 + 64, j * 128 + 64, + 64 - 0.5, 0, 2 * M_PI); + cairo_fill_preserve(cr); + cairo_set_source_rgba(cr, + ((i * 41) % 16) / 15., + ((i * 31) % 16) / 15., + ((i * 23) % 16) / 15., + 1.0); + cairo_stroke(cr); + } +} + +static void +on_window_draw (GtkWidget *widget, + cairo_t *cr) + +{ + GRand *rand = g_rand_new_with_seed(0); + int i; + int width, height; + + width = gtk_widget_get_allocated_width (widget); + height = gtk_widget_get_allocated_height (widget); + + ensure_resources (cairo_get_target (cr)); + + cairo_set_source_rgb(cr, 1, 1, 1); + cairo_paint(cr); + + cairo_set_source_rgb(cr, 0, 0, 0); + cairo_set_line_width(cr, 1.0); + cairo_rectangle (cr, 0.5, 0.5, width - 1, height - 1); + cairo_stroke (cr); + + for(i = 0; i < load_factor * 150; i++) + { + int source = g_rand_int_range(rand, 0, 255); + double phi = g_rand_double_range(rand, 0, 2 * M_PI) + angle; + double r = g_rand_double_range(rand, 0, width / 2 - 64); + int x, y; + + int source_x = (source % 16) * 128; + int source_y = (source / 16) * 128; + + x = round(width / 2 + r * cos(phi) - 64); + y = round(height / 2 - r * sin(phi) - 64); + + cairo_set_source_surface(cr, source_surface, + x - source_x, y - source_y); + cairo_rectangle(cr, x, y, 128, 128); + cairo_fill(cr); + } + + g_rand_free(rand); +} + +static void +on_frame (GtkTimeline *timeline, + double progress) +{ + int jitter; + double current_time; + static double last_print_time = 0; + + current_time = g_get_monotonic_time () / 1000000.; + if (current_time >= last_print_time + 5) + { + if (frames_since_last_print != 0) + { + g_print ("%g\n", frames_since_last_print / (current_time - last_print_time)); + frames_since_last_print = 0; + } + + last_print_time = current_time; + } + frames_since_last_print++; + + angle = 2 * M_PI * progress; + jitter = WINDOW_SIZE_JITTER * sin(angle); + + if (!cb_no_resize) + { + window_width = WIDTH + jitter; + window_height = HEIGHT + jitter; + } + + gtk_window_resize (GTK_WINDOW (window), + window_width, window_height); + + gtk_widget_queue_draw (window); +} + +static GOptionEntry options[] = { + { "factor", 'f', 0, G_OPTION_ARG_DOUBLE, &load_factor, "Load factor", "FACTOR" }, + { "no-resize", 'n', 0, G_OPTION_ARG_NONE, &cb_no_resize, "No Resize", NULL }, + { NULL } +}; + +int +main(int argc, char **argv) +{ + GError *error = NULL; + GdkScreen *screen; + GdkRectangle monitor_bounds; + GtkTimeline *timeline; + + if (!gtk_init_with_args (&argc, &argv, "", + options, NULL, NULL)) + { + g_printerr ("Option parsing failed: %s", error->message); + return 1; + } + + window = gtk_window_new (GTK_WINDOW_TOPLEVEL); + gtk_window_set_keep_above (GTK_WINDOW (window), TRUE); + gtk_window_set_gravity (GTK_WINDOW (window), GDK_GRAVITY_CENTER); + gtk_widget_set_app_paintable (window, TRUE); + + g_signal_connect (window, "draw", + G_CALLBACK (on_window_draw), NULL); + g_signal_connect (window, "destroy", + G_CALLBACK (gtk_main_quit), NULL); + + timeline = gtk_timeline_new (window, CYCLE_TIME * 1000); + gtk_timeline_set_loop (timeline, TRUE); + gtk_timeline_set_progress_type (timeline, GTK_TIMELINE_PROGRESS_LINEAR); + + g_signal_connect (timeline, "frame", + G_CALLBACK (on_frame), NULL); + on_frame (timeline, 0.); + gtk_timeline_start (timeline); + + screen = gtk_widget_get_screen (window); + gdk_screen_get_monitor_geometry (screen, + gdk_screen_get_primary_monitor (screen), + &monitor_bounds); + + gtk_window_move (GTK_WINDOW (window), + monitor_bounds.x + (monitor_bounds.width - window_width) / 2, + monitor_bounds.y + (monitor_bounds.height - window_height) / 2); + + gtk_widget_show (window); + + gtk_main (); + + return 0; +}