summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTimm Bäder <mail@baedert.org>2018-08-11 22:19:13 +0200
committerTimm Bäder <mail@baedert.org>2019-02-19 08:26:38 +0100
commit410eeec99720c741539ea9e41d7d9f1f54470f95 (patch)
tree2da0feacc8cebde5da4ab09eef96e64f47b0f8e8
parentd7974c40e178032dffc94ae29b20954c649c6ebf (diff)
downloadgtk+-410eeec99720c741539ea9e41d7d9f1f54470f95.tar.gz
Add test for widget transforms
-rw-r--r--tests/meson.build1
-rw-r--r--tests/testwidgettransforms.c353
2 files changed, 354 insertions, 0 deletions
diff --git a/tests/meson.build b/tests/meson.build
index dddd00c124..1f4c8ee8fc 100644
--- a/tests/meson.build
+++ b/tests/meson.build
@@ -123,6 +123,7 @@ gtk_tests = [
['testpopupat'],
['testgaction'],
['testwidgetfocus'],
+ ['testwidgettransforms'],
['testcenterbox'],
['testgridbaseline'],
['showrendernode'],
diff --git a/tests/testwidgettransforms.c b/tests/testwidgettransforms.c
new file mode 100644
index 0000000000..63496472a6
--- /dev/null
+++ b/tests/testwidgettransforms.c
@@ -0,0 +1,353 @@
+
+
+#include <gtk/gtk.h>
+
+static const char *css =
+"test>button {"
+" all: unset; "
+" background-color: white;"
+" border: 30px solid teal;"
+" margin: 40px;"
+" padding: 40px;"
+"}"
+"test>button:hover {"
+" background-color: blue;"
+"}"
+"test image {"
+" background-color: purple;"
+"}"
+;
+
+/* Just so we can avoid a signal */
+GtkWidget *transform_tester;
+GtkWidget *test_widget;
+GtkWidget *test_child;
+float scale = 1;
+gboolean do_picking = TRUE;
+
+static const GdkRGBA RED = {1, 0, 0, 0.4};
+static const GdkRGBA GREEN = {0, 1, 0, 0.7};
+static const GdkRGBA BLUE = {0, 0, 1, 0.4};
+static const GdkRGBA BLACK = {0, 0, 0, 1 };
+
+
+
+/* ######################################################################### */
+/* ############################## MatrixChooser ############################ */
+/* ######################################################################### */
+
+
+#define GTK_TYPE_MATRIX_CHOOSER (gtk_matrix_chooser_get_type ())
+G_DECLARE_FINAL_TYPE (GtkMatrixChooser, gtk_matrix_chooser, GTK, MATRIX_CHOOSER, GtkWidget)
+
+struct _GtkMatrixChooser
+{
+ GtkWidget parent_instance;
+};
+
+G_DEFINE_TYPE (GtkMatrixChooser, gtk_matrix_chooser, GTK_TYPE_WIDGET)
+
+static void
+gtk_matrix_chooser_init (GtkMatrixChooser *self)
+{
+ gtk_widget_set_has_surface (GTK_WIDGET (self), FALSE);
+}
+
+static void
+gtk_matrix_chooser_class_init (GtkMatrixChooserClass *klass)
+{
+
+}
+
+
+/* ######################################################################### */
+/* ############################# TransformTester ########################### */
+/* ######################################################################### */
+
+#define TEST_WIDGET_MIN_SIZE 100
+
+#define GTK_TYPE_TRANSFORM_TESTER (gtk_transform_tester_get_type ())
+G_DECLARE_FINAL_TYPE (GtkTransformTester, gtk_transform_tester, GTK, TRANSFORM_TESTER, GtkWidget);
+
+struct _GtkTransformTester
+{
+ GtkWidget parent_instance;
+
+ GtkWidget *test_widget;
+ int pick_increase;
+};
+
+G_DEFINE_TYPE (GtkTransformTester, gtk_transform_tester, GTK_TYPE_WIDGET);
+
+static void
+gtk_transform_tester_measure (GtkWidget *widget,
+ GtkOrientation orientation,
+ int for_size,
+ int *minimum,
+ int *natural,
+ int *minimum_baseline,
+ int *natural_baseline)
+{
+ GtkTransformTester *self = (GtkTransformTester *)widget;
+
+ if (self->test_widget)
+ {
+ gtk_widget_measure (self->test_widget, orientation, for_size,
+ minimum, natural, NULL, NULL);
+ }
+}
+
+static void
+gtk_transform_tester_size_allocate (GtkWidget *widget,
+ int width,
+ int height,
+ int baseline)
+{
+ GtkTransformTester *self = (GtkTransformTester *)widget;
+ graphene_matrix_t global_transform;
+ int w, h;
+
+ if (!self->test_widget)
+ return;
+
+ scale += 2.5f;
+
+ gtk_widget_measure (self->test_widget, GTK_ORIENTATION_HORIZONTAL, -1,
+ &w, NULL, NULL, NULL);
+ gtk_widget_measure (self->test_widget, GTK_ORIENTATION_VERTICAL, w,
+ &h, NULL, NULL, NULL);
+
+ g_message ("%s: %d, %d", __FUNCTION__, w, h);
+
+ graphene_matrix_init_identity (&global_transform);
+
+ graphene_matrix_translate (&global_transform, &(graphene_point3d_t){ -w/2.0f, -h/2.0f, 0});
+ graphene_matrix_rotate (&global_transform, scale,
+ graphene_vec3_z_axis ());
+
+ graphene_matrix_translate (&global_transform, &(graphene_point3d_t){ width / 2.0f, height / 2.0f, 0});
+
+
+#if 0
+ gtk_widget_size_allocate (self->test_widget,
+ &(GtkAllocation){ (width- w) / 2, (height - h) / 2, w,h }, -1);
+#else
+ gtk_widget_allocate (self->test_widget,
+ w, h,
+ -1,
+ &global_transform);
+#endif
+}
+
+static void
+gtk_transform_tester_snapshot (GtkWidget *widget,
+ GtkSnapshot *snapshot)
+{
+ GtkTransformTester *self = (GtkTransformTester *)widget;
+ const int width = gtk_widget_get_width (widget);
+ const int height = gtk_widget_get_height (widget);
+ const int inc = self->pick_increase;
+ graphene_rect_t child_bounds;
+ graphene_rect_t self_bounds;
+ int x, y;
+
+ GTK_WIDGET_CLASS (gtk_transform_tester_parent_class)->snapshot (widget, snapshot);
+
+ if (!do_picking)
+ return;
+ gtk_widget_compute_bounds (self->test_widget, widget, &child_bounds);
+ gtk_widget_compute_bounds (self->test_widget, self->test_widget, &self_bounds);
+
+ {
+ const struct {
+ graphene_point_t coords;
+ GdkRGBA color;
+ } points[4] = {
+ { self_bounds.origin, {1, 0, 0, 1} },
+ { GRAPHENE_POINT_INIT (self_bounds.origin.x + self_bounds.size.width, self_bounds.origin.y), {0, 1, 0, 1} },
+ { GRAPHENE_POINT_INIT (self_bounds.origin.x + self_bounds.size.width, self_bounds.origin.y + self_bounds.size.height), {0, 0, 1, 1} },
+ { GRAPHENE_POINT_INIT (self_bounds.origin.x, self_bounds.origin.y + self_bounds.size.height), {1, 0, 1, 1} }
+ };
+
+ for (x = 0; x < G_N_ELEMENTS (points); x ++)
+ {
+ int px, py;
+
+ gtk_widget_translate_coordinates (self->test_widget, widget,
+ points[x].coords.x, points[x].coords.y,
+ &px, &py);
+
+ gtk_snapshot_append_color (snapshot, &points[x].color,
+ &GRAPHENE_RECT_INIT (px, py,
+ 4,
+ 4));
+ }
+ }
+
+ /* Now add custom drawing */
+ for (x = 0; x < width; x += inc)
+ {
+ for (y = 0; y < height; y += inc)
+ {
+ const float px = x;
+ const float py = y;
+ GtkWidget *picked;
+#if 1
+ picked = gtk_widget_pick (widget, px, py);
+#else
+ {
+ int dx, dy;
+ gtk_widget_translate_coordinates (widget, self->test_widget, px, py, &dx, &dy);
+ picked = gtk_widget_pick (self->test_widget, dx, dy);
+ }
+#endif
+
+ if (picked == self->test_widget)
+ gtk_snapshot_append_color (snapshot, &GREEN,
+ &GRAPHENE_RECT_INIT (px - (inc / 2), py - (inc / 2), inc, inc));
+ else if (picked == test_child)
+ gtk_snapshot_append_color (snapshot, &BLUE,
+ &GRAPHENE_RECT_INIT (px - (inc / 2), py - (inc / 2), inc, inc));
+
+ else
+ gtk_snapshot_append_color (snapshot, &RED,
+ &GRAPHENE_RECT_INIT (px - (inc / 2), py - (inc / 2), inc, inc));
+ }
+ }
+
+ gtk_snapshot_append_color (snapshot, &BLACK,
+ &GRAPHENE_RECT_INIT (child_bounds.origin.x,
+ child_bounds.origin.y,
+ child_bounds.size.width,
+ 1));
+
+ gtk_snapshot_append_color (snapshot, &BLACK,
+ &GRAPHENE_RECT_INIT (child_bounds.origin.x + child_bounds.size.width,
+ child_bounds.origin.y,
+ 1,
+ child_bounds.size.height));
+
+ gtk_snapshot_append_color (snapshot, &BLACK,
+ &GRAPHENE_RECT_INIT (child_bounds.origin.x,
+ child_bounds.origin.y + child_bounds.size.height,
+ child_bounds.size.width,
+ 1));
+
+ gtk_snapshot_append_color (snapshot, &BLACK,
+ &GRAPHENE_RECT_INIT (child_bounds.origin.x,
+ child_bounds.origin.y,
+ 1,
+ child_bounds.size.height));
+}
+
+static void
+gtk_transform_tester_init (GtkTransformTester *self)
+{
+ gtk_widget_set_has_surface (GTK_WIDGET (self), FALSE);
+
+ self->pick_increase = 4;
+}
+
+static void
+gtk_transform_tester_class_init (GtkTransformTesterClass *klass)
+{
+ GtkWidgetClass *widget_class = (GtkWidgetClass *)klass;
+
+ widget_class->measure = gtk_transform_tester_measure;
+ widget_class->size_allocate = gtk_transform_tester_size_allocate;
+ widget_class->snapshot = gtk_transform_tester_snapshot;
+
+ gtk_widget_class_set_css_name (widget_class, "test");
+}
+
+static gboolean
+tick_cb (GtkWidget *widget,
+ GdkFrameClock *frame_clock,
+ gpointer user_data)
+{
+ gtk_widget_queue_allocate (widget);
+
+ return G_SOURCE_CONTINUE;
+}
+
+static void
+gtk_transform_tester_set_test_widget (GtkTransformTester *self,
+ GtkWidget *test_widget)
+{
+ g_assert (!self->test_widget);
+
+ self->test_widget = test_widget;
+ gtk_widget_set_parent (test_widget, (GtkWidget *)self);
+
+ gtk_widget_add_tick_callback (GTK_WIDGET (self), tick_cb, NULL, NULL);
+}
+
+static void
+toggled_cb (GtkToggleButton *source,
+ gpointer user_data)
+{
+ do_picking = gtk_toggle_button_get_active (source);
+}
+
+int
+main (int argc, char **argv)
+{
+ GtkWidget *window;
+ GtkWidget *matrix_chooser;
+ GtkWidget *box;
+ GtkWidget *titlebar;
+ GtkWidget *toggle_button;
+ GtkCssProvider *provider;
+
+ gtk_init ();
+
+ provider = gtk_css_provider_new ();
+ gtk_css_provider_load_from_data (provider, css, -1);
+ gtk_style_context_add_provider_for_display (gdk_display_get_default (),
+ GTK_STYLE_PROVIDER (provider),
+ GTK_STYLE_PROVIDER_PRIORITY_APPLICATION);
+
+
+ window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
+ matrix_chooser = g_object_new (GTK_TYPE_MATRIX_CHOOSER, NULL);
+ transform_tester = g_object_new (GTK_TYPE_TRANSFORM_TESTER, NULL);
+ box = gtk_box_new (GTK_ORIENTATION_VERTICAL, 12);
+ titlebar = gtk_header_bar_new ();
+
+ gtk_window_set_titlebar (GTK_WINDOW (window), titlebar);
+ gtk_header_bar_set_show_title_buttons (GTK_HEADER_BAR (titlebar), TRUE);
+
+ toggle_button = gtk_toggle_button_new ();
+ gtk_button_set_label (GTK_BUTTON (toggle_button), "Picking");
+ gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (toggle_button), do_picking);
+ g_signal_connect (toggle_button, "toggled", G_CALLBACK (toggled_cb), NULL);
+ gtk_container_add (GTK_CONTAINER (titlebar), toggle_button);
+
+ test_widget = gtk_button_new ();
+ gtk_widget_set_size_request (test_widget, TEST_WIDGET_MIN_SIZE, TEST_WIDGET_MIN_SIZE);
+ gtk_widget_set_halign (test_widget, GTK_ALIGN_CENTER);
+ gtk_widget_set_valign (test_widget, GTK_ALIGN_CENTER);
+
+
+ test_child = gtk_image_new_from_icon_name ("corebird");
+ gtk_widget_set_halign (test_child, GTK_ALIGN_CENTER);
+ gtk_widget_set_valign (test_child, GTK_ALIGN_CENTER);
+ gtk_widget_set_size_request (test_child, TEST_WIDGET_MIN_SIZE / 2, TEST_WIDGET_MIN_SIZE / 2);
+ gtk_container_add (GTK_CONTAINER (test_widget), test_child);
+
+
+ gtk_transform_tester_set_test_widget (GTK_TRANSFORM_TESTER (transform_tester), test_widget);
+
+ gtk_widget_set_vexpand (transform_tester, TRUE);
+ gtk_container_add (GTK_CONTAINER (box), transform_tester);
+ gtk_container_add (GTK_CONTAINER (box), matrix_chooser);
+ gtk_container_add (GTK_CONTAINER (window), box);
+
+ gtk_window_set_default_size ((GtkWindow *)window, 200, 200);
+ g_signal_connect (window, "close-request", G_CALLBACK (gtk_main_quit), NULL);
+ gtk_widget_show (window);
+
+ gtk_main ();
+
+ return 0;
+}