From: Benjamin Otte Date: Fri, 8 Feb 2019 17:02:40 +0000 (+0100) Subject: widget: Add gtk_widget_set_overflow() X-Git-Tag: archive/raspbian/4.4.1+ds1-2+rpi1^2~18^2~21^2~744 X-Git-Url: https://dgit.raspbian.org/?a=commitdiff_plain;h=49cbf2a16b07c71d23a68bdde09d7390b2a53714;p=gtk4.git widget: Add gtk_widget_set_overflow() This adds a simple abilities for widget implementations to clip their content. See future commits for users of this. --- diff --git a/docs/reference/gtk/gtk4-sections.txt b/docs/reference/gtk/gtk4-sections.txt index 27c18bb3e9..1929eaf4a1 100644 --- a/docs/reference/gtk/gtk4-sections.txt +++ b/docs/reference/gtk/gtk4-sections.txt @@ -4486,6 +4486,8 @@ gtk_widget_get_modifier_mask gtk_widget_insert_action_group gtk_widget_get_opacity gtk_widget_set_opacity +gtk_widget_get_overflow +gtk_widget_set_overflow gtk_widget_list_action_prefixes gtk_widget_get_action_group gtk_widget_measure diff --git a/gtk/gtkenums.h b/gtk/gtkenums.h index e6ea7b3bb4..7eab7923e3 100644 --- a/gtk/gtkenums.h +++ b/gtk/gtkenums.h @@ -341,6 +341,23 @@ typedef enum GTK_ORIENTATION_VERTICAL } GtkOrientation; +/** + * GtkOverflow: + * @GTK_OVERFLOW_VISIBLE: No change is applied. Content is drawn at the specified + * position. + * @GTK_OVERFLOW_HIDDEN: Content is clipped to the bounds of the area. Content + * outside the area is not drawn and cannot be interacted with. + * + * Defines how content overflowing a given area should be handled, such as + * with gtk_widget_set_overflow(). This property is modeled after the CSS overflow + * property, but implements it only partially. + */ +typedef enum +{ + GTK_OVERFLOW_VISIBLE, + GTK_OVERFLOW_HIDDEN +} GtkOverflow; + /** * GtkPackType: * @GTK_PACK_START: The child is packed into the start of the box diff --git a/gtk/gtkwidget.c b/gtk/gtkwidget.c index 782888e310..db8434998d 100644 --- a/gtk/gtkwidget.c +++ b/gtk/gtkwidget.c @@ -524,6 +524,7 @@ enum { PROP_TOOLTIP_TEXT, PROP_SURFACE, PROP_OPACITY, + PROP_OVERFLOW, PROP_HALIGN, PROP_VALIGN, PROP_MARGIN_START, @@ -1305,6 +1306,19 @@ gtk_widget_class_init (GtkWidgetClass *klass) 1.0, GTK_PARAM_READWRITE|G_PARAM_EXPLICIT_NOTIFY); + /** + * GtkWidget:overflow: + * + * How content outside the widget's content area is treated. + */ + widget_props[PROP_OVERFLOW] = + g_param_spec_enum ("overflow", + P_("Overflow"), + P_("How content outside the widget's content area is treated"), + GTK_TYPE_OVERFLOW, + GTK_OVERFLOW_VISIBLE, + GTK_PARAM_READWRITE|G_PARAM_EXPLICIT_NOTIFY); + /** * GtkWidget:scale-factor: * @@ -2319,6 +2333,9 @@ gtk_widget_set_property (GObject *object, case PROP_OPACITY: gtk_widget_set_opacity (widget, g_value_get_double (value)); break; + case PROP_OVERFLOW: + gtk_widget_set_overflow (widget, g_value_get_enum (value)); + break; case PROP_CSS_NAME: if (g_value_get_string (value) != NULL) gtk_css_node_set_name (priv->cssnode, g_intern_string (g_value_get_string (value))); @@ -2459,6 +2476,9 @@ gtk_widget_get_property (GObject *object, case PROP_OPACITY: g_value_set_double (value, gtk_widget_get_opacity (widget)); break; + case PROP_OVERFLOW: + g_value_set_enum (value, gtk_widget_get_overflow (widget)); + break; case PROP_SCALE_FACTOR: g_value_set_int (value, gtk_widget_get_scale_factor (widget)); break; @@ -11179,6 +11199,8 @@ gtk_widget_pick (GtkWidget *widget, gdouble x, gdouble y) { + GtkWidgetPrivate *priv = gtk_widget_get_instance_private (widget); + g_return_val_if_fail (GTK_IS_WIDGET (widget), NULL); if (gtk_widget_get_pass_through (widget) || @@ -11186,6 +11208,31 @@ gtk_widget_pick (GtkWidget *widget, !_gtk_widget_is_drawable (widget)) return NULL; + switch (priv->overflow) + { + default: + case GTK_OVERFLOW_VISIBLE: + break; + + case GTK_OVERFLOW_HIDDEN: + { + GtkBorder margin, border, padding; + GtkCssStyle *style; + + style = gtk_css_node_get_style (priv->cssnode); + get_box_margin (style, &margin); + get_box_border (style, &border); + get_box_padding (style, &padding); + + if (x < -padding.left || + y < -padding.top || + x >= priv->allocation.width - margin.left - margin.right - border.left - border.right - padding.left || + y >= priv->allocation.height - margin.top - margin.bottom - border.top - border.bottom - padding.top) + return NULL; + } + break; + } + return GTK_WIDGET_GET_CLASS (widget)->pick (widget, x, y); } @@ -11574,6 +11621,55 @@ gtk_widget_get_opacity (GtkWidget *widget) return priv->user_alpha / 255.0; } +/** + * gtk_widget_set_overflow: + * @self: a #GtkWidget + * @overflow: desired overflow + * + * Sets how @self treats content that is drawn outside the widget's content area. + * See the definition of #GtkOverflow for details. + * + * This setting is provided for widget implementations and should not be used by + * application code. + * + * The default value is %GTK_OVERFLOW_VISIBLE. + **/ +void +gtk_widget_set_overflow (GtkWidget *self, + GtkOverflow overflow) +{ + GtkWidgetPrivate *priv = gtk_widget_get_instance_private (self); + + g_return_if_fail (GTK_IS_WIDGET (self)); + + if (priv->overflow == overflow) + return; + + priv->overflow = overflow; + + gtk_widget_queue_draw (self); + + g_object_notify_by_pspec (G_OBJECT (self), widget_props[PROP_OVERFLOW]); +} + +/** + * gtk_widget_get_overflow: + * @self: a #GtkWidget + * + * Returns the value set via gtk_widget_set_overflow(). + * + * Returns: The widget's overflow. + **/ +GtkOverflow +gtk_widget_get_overflow (GtkWidget *self) +{ + GtkWidgetPrivate *priv = gtk_widget_get_instance_private (self); + + g_return_val_if_fail (GTK_IS_WIDGET (self), GTK_OVERFLOW_VISIBLE); + + return priv->overflow; +} + /** * gtk_widget_send_focus_change: * @widget: a #GtkWidget @@ -12959,7 +13055,21 @@ gtk_widget_create_render_node (GtkWidget *widget, /* Offset to content allocation */ gtk_snapshot_offset (snapshot, margin.left + padding.left + border.left, margin.top + border.top + padding.top); + + if (priv->overflow == GTK_OVERFLOW_HIDDEN) + { + gtk_snapshot_push_clip (snapshot, + &GRAPHENE_RECT_INIT (- padding.left, + - padding.top, + allocation.width - margin.left - margin.right - border.left - border.right, + allocation.height - margin.top - margin.bottom - border.top - border.bottom)); + } + klass->snapshot (widget, snapshot); + + if (priv->overflow == GTK_OVERFLOW_HIDDEN) + gtk_snapshot_pop (snapshot); + gtk_snapshot_offset (snapshot, - (padding.left + border.left), -(border.top + padding.top)); gtk_css_style_snapshot_outline (style, diff --git a/gtk/gtkwidget.h b/gtk/gtkwidget.h index a9aba23eb7..9b89f70246 100644 --- a/gtk/gtkwidget.h +++ b/gtk/gtkwidget.h @@ -631,6 +631,12 @@ void gtk_widget_set_opacity (GtkWidget *widget, double opacity); GDK_AVAILABLE_IN_ALL double gtk_widget_get_opacity (GtkWidget *widget); +GDK_AVAILABLE_IN_ALL +void gtk_widget_set_overflow (GtkWidget *widget, + GtkOverflow overflow); +GDK_AVAILABLE_IN_ALL +GtkOverflow gtk_widget_get_overflow (GtkWidget *widget); + GDK_AVAILABLE_IN_ALL GtkWidget* gtk_widget_get_toplevel (GtkWidget *widget); diff --git a/gtk/gtkwidgetprivate.h b/gtk/gtkwidgetprivate.h index c70a5e9e62..26c33ba0bc 100644 --- a/gtk/gtkwidgetprivate.h +++ b/gtk/gtkwidgetprivate.h @@ -99,6 +99,7 @@ struct _GtkWidgetPrivate guint halign : 4; guint valign : 4; + GtkOverflow overflow; guint8 alpha; guint8 user_alpha;