From 37e9d926329b8d9fd91f8022bff7c5e2c75dc7e5 Mon Sep 17 00:00:00 2001 From: Matthias Clasen Date: Thu, 3 Dec 2015 21:56:25 -0500 Subject: [PATCH] button: Convert to gadgets --- gtk/gtkbutton.c | 344 ++++++++++++++++------------------------- gtk/gtkbuttonprivate.h | 2 + 2 files changed, 133 insertions(+), 213 deletions(-) diff --git a/gtk/gtkbutton.c b/gtk/gtkbutton.c index 43473da4f4..ce0c272c50 100644 --- a/gtk/gtkbutton.c +++ b/gtk/gtkbutton.c @@ -72,9 +72,8 @@ #include "a11y/gtkbuttonaccessible.h" #include "gtkapplicationprivate.h" #include "gtkactionhelper.h" - -static const GtkBorder default_default_border = { 0, 0, 0, 0 }; -static const GtkBorder default_default_outside_border = { 0, 0, 0, 0 }; +#include "gtkcsscustomgadgetprivate.h" +#include "gtkcontainerprivate.h" /* Time out before giving up on getting a key release when animating * the close button. @@ -195,7 +194,28 @@ static void gtk_button_get_preferred_height_and_baseline_for_width (GtkWidget *w gint *natural_size, gint *minimum_baseline, gint *natural_baseline); - + +static void gtk_button_measure (GtkCssGadget *gadget, + GtkOrientation orientation, + int for_size, + int *minimum_size, + int *natural_size, + int *minimum_baseline, + int *natural_baseline, + gpointer data); +static void gtk_button_allocate (GtkCssGadget *gadget, + const GtkAllocation *allocation, + int baseline, + GtkAllocation *out_clip, + gpointer data); +static gboolean gtk_button_render (GtkCssGadget *gadget, + cairo_t *cr, + int x, + int y, + int width, + int height, + gpointer data); + static GParamSpec *props[LAST_PROP] = { NULL, }; static guint button_signals[LAST_SIGNAL] = { 0 }; @@ -493,7 +513,8 @@ gtk_button_class_init (GtkButtonClass *klass) * around a button that can become the default widget of its window. * For more information about default widgets, see gtk_widget_grab_default(). * - * Deprecated: 3.14: use CSS margins and padding instead. + * Deprecated: 3.14: Use CSS margins and padding instead; + * the value of this style property is ignored. */ gtk_widget_class_install_style_property (widget_class, @@ -511,7 +532,8 @@ gtk_button_class_init (GtkButtonClass *klass) * window. Extra outside space is always drawn outside the button border. * For more information about default widgets, see gtk_widget_grab_default(). * - * Deprecated: 3.14: use CSS margins and padding instead. + * Deprecated: 3.14: Use CSS margins and padding instead; + * the value of this style property is ignored. */ gtk_widget_class_install_style_property (widget_class, g_param_spec_boxed ("default-outside-border", @@ -720,6 +742,15 @@ gtk_button_init (GtkButton *button) g_signal_connect (priv->gesture, "update", G_CALLBACK (multipress_gesture_update_cb), button); g_signal_connect (priv->gesture, "cancel", G_CALLBACK (multipress_gesture_cancel_cb), button); gtk_event_controller_set_propagation_phase (GTK_EVENT_CONTROLLER (priv->gesture), GTK_PHASE_BUBBLE); + + priv->gadget = gtk_css_custom_gadget_new_for_node (gtk_widget_get_css_node (GTK_WIDGET (button)), + GTK_WIDGET (button), + gtk_button_measure, + gtk_button_allocate, + gtk_button_render, + NULL, + NULL); + } static void @@ -729,8 +760,8 @@ gtk_button_destroy (GtkWidget *widget) GtkButtonPrivate *priv = button->priv; g_clear_pointer (&priv->label_text, g_free); - g_clear_object (&priv->gesture); + g_clear_object (&priv->gadget); GTK_WIDGET_CLASS (gtk_button_parent_class)->destroy (widget); } @@ -787,7 +818,7 @@ gtk_button_add (GtkContainer *container, GTK_CONTAINER_CLASS (gtk_button_parent_class)->add (container, widget); } -static void +static void gtk_button_dispose (GObject *object) { GtkButton *button = GTK_BUTTON (object); @@ -1720,90 +1751,13 @@ gtk_button_style_updated (GtkWidget *widget) gtk_button_update_image_spacing (GTK_BUTTON (widget), context); } -static void -gtk_button_get_props (GtkButton *button, - GtkBorder *default_border, - GtkBorder *default_outside_border, - GtkBorder *padding, - GtkBorder *border) -{ - GtkStyleContext *context; - GtkStateFlags state; - GtkBorder *tmp_border; - - context = gtk_widget_get_style_context (GTK_WIDGET (button)); - state = gtk_style_context_get_state (context); - - if (default_border) - { - gtk_style_context_get_style (context, - "default-border", &tmp_border, - NULL); - - if (tmp_border) - { - *default_border = *tmp_border; - gtk_border_free (tmp_border); - } - else - *default_border = default_default_border; - } - - if (default_outside_border) - { - gtk_style_context_get_style (context, - "default-outside-border", &tmp_border, - NULL); - - if (tmp_border) - { - *default_outside_border = *tmp_border; - gtk_border_free (tmp_border); - } - else - *default_outside_border = default_default_outside_border; - } - - if (padding) - gtk_style_context_get_padding (context, state, padding); - - if (border) - gtk_style_context_get_border (context, state, border); -} - -/* Computes the size of the border around the button's child - * including all CSS and style properties so it can be used - * during size allocation and size request phases. */ -static void -gtk_button_get_full_border (GtkButton *button, - GtkBorder *full_border) -{ - GtkBorder default_border, padding, border; - - gtk_button_get_props (button, &default_border, NULL, - &padding, &border); - - full_border->left = padding.left + border.left; - full_border->right = padding.right + border.right; - full_border->top = padding.top + border.top; - full_border->bottom = padding.bottom + border.bottom; - - if (gtk_widget_get_can_default (GTK_WIDGET (button))) - { - full_border->left += default_border.left; - full_border->right += default_border.right; - full_border->top += default_border.top; - full_border->bottom += default_border.bottom; - } -} - static void gtk_button_size_allocate (GtkWidget *widget, GtkAllocation *allocation) { GtkButton *button = GTK_BUTTON (widget); GtkButtonPrivate *priv = button->priv; - GtkWidget *child; + GtkAllocation clip; gtk_widget_set_allocation (widget, allocation); @@ -1814,91 +1768,58 @@ gtk_button_size_allocate (GtkWidget *widget, allocation->width, allocation->height); - child = gtk_bin_get_child (GTK_BIN (button)); + gtk_css_gadget_allocate (priv->gadget, + allocation, + gtk_widget_get_allocated_baseline (widget), + &clip); + + gtk_widget_set_clip (widget, &clip); +} + +static void +gtk_button_allocate (GtkCssGadget *gadget, + const GtkAllocation *allocation, + int baseline, + GtkAllocation *out_clip, + gpointer unused) +{ + GtkWidget *widget; + GtkWidget *child; + + widget = gtk_css_gadget_get_owner (gadget); + + child = gtk_bin_get_child (GTK_BIN (widget)); if (child && gtk_widget_get_visible (child)) - { - GtkAllocation child_allocation; - GtkBorder border; - gint baseline; + gtk_widget_size_allocate_with_baseline (child, (GtkAllocation *)allocation, baseline); - gtk_button_get_full_border (button, &border); - - child_allocation.x = allocation->x + border.left; - child_allocation.y = allocation->y + border.top; - child_allocation.width = allocation->width - border.left - border.right; - child_allocation.height = allocation->height - border.top - border.bottom; - - baseline = gtk_widget_get_allocated_baseline (widget); - if (baseline != -1) - baseline -= border.top; - - child_allocation.width = MAX (1, child_allocation.width); - child_allocation.height = MAX (1, child_allocation.height); - - gtk_widget_size_allocate_with_baseline (child, &child_allocation, baseline); - } - - _gtk_widget_set_simple_clip (widget, NULL); + gtk_container_get_children_clip (GTK_CONTAINER (widget), out_clip); } static gboolean gtk_button_draw (GtkWidget *widget, cairo_t *cr) { - GtkButton *button = GTK_BUTTON (widget); - gint x, y; - gint width, height; - GtkBorder default_border; - GtkBorder default_outside_border; - GtkStyleContext *context; - GtkStateFlags state; + gtk_css_gadget_draw (GTK_BUTTON (widget)->priv->gadget, cr); - context = gtk_widget_get_style_context (widget); - state = gtk_style_context_get_state (context); + return FALSE; +} - gtk_button_get_props (button, &default_border, &default_outside_border, NULL, NULL); +static gboolean +gtk_button_render (GtkCssGadget *gadget, + cairo_t *cr, + int x, + int y, + int width, + int height, + gpointer data) +{ + GtkWidget *widget; - x = 0; - y = 0; - width = gtk_widget_get_allocated_width (widget); - height = gtk_widget_get_allocated_height (widget); - - if (gtk_widget_has_default (widget) && - gtk_button_get_relief (button) == GTK_RELIEF_NORMAL) - { - x += default_border.left; - y += default_border.top; - width -= default_border.left + default_border.right; - height -= default_border.top + default_border.bottom; - } - else if (gtk_widget_get_can_default (widget)) - { - x += default_outside_border.left; - y += default_outside_border.top; - width -= default_outside_border.left + default_outside_border.right; - height -= default_outside_border.top + default_outside_border.bottom; - } - - gtk_render_background (context, cr, x, y, width, height); - gtk_render_frame (context, cr, x, y, width, height); - - if (gtk_widget_has_visible_focus (widget)) - { - GtkBorder border; - - gtk_style_context_get_border (context, state, &border); - - x += border.left; - y += border.top; - width -= border.left + border.right; - height -= border.top + border.bottom; - - gtk_render_focus (context, cr, x, y, width, height); - } + widget = gtk_css_gadget_get_owner (gadget); GTK_WIDGET_CLASS (gtk_button_parent_class)->draw (widget, cr); - return FALSE; + return gtk_widget_has_visible_focus (widget); } static void @@ -2127,106 +2048,103 @@ gtk_button_finish_activate (GtkButton *button, static void -gtk_button_get_size (GtkWidget *widget, - GtkOrientation orientation, - gint for_size, - gint *minimum_size, - gint *natural_size, - gint *minimum_baseline, - gint *natural_baseline) +gtk_button_measure (GtkCssGadget *gadget, + GtkOrientation orientation, + int for_size, + int *minimum, + int *natural, + int *minimum_baseline, + int *natural_baseline, + gpointer data) { - GtkButton *button = GTK_BUTTON (widget); + GtkWidget *widget; GtkWidget *child; - GtkBorder border; - gint minimum, natural; - gtk_button_get_full_border (button, &border); + widget = gtk_css_gadget_get_owner (gadget); + child = gtk_bin_get_child (GTK_BIN (widget)); - if (orientation == GTK_ORIENTATION_HORIZONTAL) + if (child && gtk_widget_get_visible (child)) { - minimum = border.left + border.right; - natural = minimum; - - if (for_size >= 0) - for_size -= border.top + border.bottom; + _gtk_widget_get_preferred_size_for_size (child, + orientation, + for_size, + minimum, natural, + minimum_baseline, natural_baseline); } else { - minimum = border.top + border.bottom; - natural = minimum; - - if (for_size >= 0) - for_size -= border.left + border.right; + *minimum = 0; + *natural = 0; + if (minimum_baseline) + *minimum_baseline = 0; + if (natural_baseline) + *natural_baseline = 0; } - - if ((child = gtk_bin_get_child (GTK_BIN (button))) && - gtk_widget_get_visible (child)) - { - gint child_min, child_nat; - gint child_min_baseline = -1, child_nat_baseline = -1; - - _gtk_widget_get_preferred_size_for_size (child, - orientation, - for_size, - &child_min, &child_nat, - &child_min_baseline, &child_nat_baseline); - - if (minimum_baseline && child_min_baseline >= 0) - *minimum_baseline = child_min_baseline + border.top; - if (natural_baseline && child_nat_baseline >= 0) - *natural_baseline = child_nat_baseline + border.top; - - minimum += child_min; - natural += child_nat; - } - - *minimum_size = minimum; - *natural_size = natural; } -static void +static void gtk_button_get_preferred_width (GtkWidget *widget, gint *minimum_size, gint *natural_size) { - gtk_button_get_size (widget, GTK_ORIENTATION_HORIZONTAL, -1, minimum_size, natural_size, NULL, NULL); + gtk_css_gadget_get_preferred_size (GTK_BUTTON (widget)->priv->gadget, + GTK_ORIENTATION_HORIZONTAL, + -1, + minimum_size, natural_size, + NULL, NULL); } -static void +static void gtk_button_get_preferred_height (GtkWidget *widget, gint *minimum_size, gint *natural_size) { - gtk_button_get_size (widget, GTK_ORIENTATION_VERTICAL, -1, minimum_size, natural_size, NULL, NULL); + gtk_css_gadget_get_preferred_size (GTK_BUTTON (widget)->priv->gadget, + GTK_ORIENTATION_VERTICAL, + -1, + minimum_size, natural_size, + NULL, NULL); } -static void +static void gtk_button_get_preferred_width_for_height (GtkWidget *widget, gint for_size, gint *minimum_size, gint *natural_size) { - gtk_button_get_size (widget, GTK_ORIENTATION_HORIZONTAL, for_size, minimum_size, natural_size, NULL, NULL); + gtk_css_gadget_get_preferred_size (GTK_BUTTON (widget)->priv->gadget, + GTK_ORIENTATION_HORIZONTAL, + for_size, + minimum_size, natural_size, + NULL, NULL); } -static void +static void gtk_button_get_preferred_height_for_width (GtkWidget *widget, gint for_size, gint *minimum_size, gint *natural_size) { - gtk_button_get_size (widget, GTK_ORIENTATION_VERTICAL, for_size, minimum_size, natural_size, NULL, NULL); + gtk_css_gadget_get_preferred_size (GTK_BUTTON (widget)->priv->gadget, + GTK_ORIENTATION_VERTICAL, + for_size, + minimum_size, natural_size, + NULL, NULL); } static void gtk_button_get_preferred_height_and_baseline_for_width (GtkWidget *widget, - gint width, + gint for_size, gint *minimum_size, gint *natural_size, gint *minimum_baseline, gint *natural_baseline) { - gtk_button_get_size (widget, GTK_ORIENTATION_VERTICAL, width, minimum_size, natural_size, minimum_baseline, natural_baseline); + gtk_css_gadget_get_preferred_size (GTK_BUTTON (widget)->priv->gadget, + GTK_ORIENTATION_VERTICAL, + for_size, + minimum_size, natural_size, + minimum_baseline, natural_baseline); } /** diff --git a/gtk/gtkbuttonprivate.h b/gtk/gtkbuttonprivate.h index 2875660a96..5114a9926b 100644 --- a/gtk/gtkbuttonprivate.h +++ b/gtk/gtkbuttonprivate.h @@ -22,6 +22,7 @@ #include "gtkactionhelper.h" #include "gtkgesturesingle.h" #include "deprecated/gtkaction.h" +#include "gtkcssgadgetprivate.h" G_BEGIN_DECLS @@ -31,6 +32,7 @@ struct _GtkButtonPrivate GtkAction *action; GtkWidget *image; GtkActionHelper *action_helper; + GtkCssGadget *gadget; GdkDevice *grab_keyboard; GdkWindow *event_window;