This will be used to let the inspector and other users pick insensitive widgets again. For now, update all callers to pass no flags, preserving the current behavior.
348 lines
11 KiB
C
348 lines
11 KiB
C
|
|
|
|
#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;
|
|
GskTransform *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);
|
|
|
|
global_transform = NULL;
|
|
|
|
global_transform = gsk_transform_translate (global_transform, &GRAPHENE_POINT_INIT (width / 2.0f, height / 2.0f));
|
|
global_transform = gsk_transform_rotate (global_transform, scale);
|
|
global_transform = gsk_transform_translate (global_transform, &GRAPHENE_POINT_INIT (-w / 2.0f, -h / 2.0f));
|
|
|
|
gtk_widget_allocate (self->test_widget,
|
|
w, h,
|
|
-1,
|
|
global_transform);
|
|
|
|
gsk_transform_unref (global_transform);
|
|
}
|
|
|
|
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 ||
|
|
!gtk_widget_compute_bounds (self->test_widget, widget, &child_bounds) ||
|
|
!gtk_widget_compute_bounds (self->test_widget, self->test_widget, &self_bounds))
|
|
return;
|
|
|
|
{
|
|
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, 0);
|
|
#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 ("weather-clear");
|
|
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;
|
|
}
|