From 9fde0137a052ebdb0374a1303a70517cd43afa72 Mon Sep 17 00:00:00 2001 From: Matthias Clasen Date: Wed, 23 Sep 2020 22:53:21 -0400 Subject: [PATCH 1/3] listview: Avoid a critical when reordering When sorting a cell into the place its already at, we were triggering criticals. Avoid that. Fixes: #3180 --- gtk/gtklistitemwidget.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/gtk/gtklistitemwidget.c b/gtk/gtklistitemwidget.c index 5c57d1b257..ce4f505039 100644 --- a/gtk/gtklistitemwidget.c +++ b/gtk/gtklistitemwidget.c @@ -629,10 +629,13 @@ gtk_list_item_widget_reorder_child (GtkListItemWidget *self, } } - gtk_widget_insert_after (child, widget, sibling); - gtk_css_node_insert_after (gtk_widget_get_css_node (widget), - gtk_widget_get_css_node (child), - sibling ? gtk_widget_get_css_node (sibling) : NULL); + if (child != sibling) + { + gtk_widget_insert_after (child, widget, sibling); + gtk_css_node_insert_after (gtk_widget_get_css_node (widget), + gtk_widget_get_css_node (child), + sibling ? gtk_widget_get_css_node (sibling) : NULL); + } } void From 7eb0ae39c5549bfaa4efb879ef49b1186f48c5c1 Mon Sep 17 00:00:00 2001 From: Matthias Clasen Date: Thu, 24 Sep 2020 14:18:38 -0400 Subject: [PATCH 2/3] columview: Fix column resizing We were not handling the fixed_width quite right, and that was causing screaming from the GTK size allocation machinery. Fixes: #3178 --- gtk/gtkcolumnviewcell.c | 54 ++++++++++++++++++++++++++++++++++++--- gtk/gtkcolumnviewlayout.c | 6 +++-- gtk/gtkcolumnviewtitle.c | 52 ++++++++++++++++++++++++++++++++++--- 3 files changed, 102 insertions(+), 10 deletions(-) diff --git a/gtk/gtkcolumnviewcell.c b/gtk/gtkcolumnviewcell.c index ace8037188..0881a6ccd3 100644 --- a/gtk/gtkcolumnviewcell.c +++ b/gtk/gtkcolumnviewcell.c @@ -25,6 +25,9 @@ #include "gtkintl.h" #include "gtklistitemwidgetprivate.h" #include "gtkwidgetprivate.h" +#include "gtkcssnodeprivate.h" +#include "gtkcssnumbervalueprivate.h" + struct _GtkColumnViewCell { @@ -44,6 +47,37 @@ struct _GtkColumnViewCellClass G_DEFINE_TYPE (GtkColumnViewCell, gtk_column_view_cell, GTK_TYPE_LIST_ITEM_WIDGET) +static int +get_number (GtkCssValue *value) +{ + double d = _gtk_css_number_value_get (value, 100); + + if (d < 1) + return ceil (d); + else + return floor (d); +} + +static int +unadjust_width (GtkWidget *widget, + int width) +{ + GtkCssStyle *style; + int widget_margins; + int css_extra; + + style = gtk_css_node_get_style (gtk_widget_get_css_node (widget)); + css_extra = get_number (style->size->margin_left) + + get_number (style->size->margin_right) + + get_number (style->border->border_left_width) + + get_number (style->border->border_right_width) + + get_number (style->size->padding_left) + + get_number (style->size->padding_right); + widget_margins = widget->priv->margin.left + widget->priv->margin.right; + + return MAX (0, width - widget_margins - css_extra); +} + static void gtk_column_view_cell_measure (GtkWidget *widget, GtkOrientation orientation, @@ -56,15 +90,18 @@ gtk_column_view_cell_measure (GtkWidget *widget, GtkColumnViewCell *cell = GTK_COLUMN_VIEW_CELL (widget); GtkWidget *child = gtk_widget_get_first_child (widget); int fixed_width = gtk_column_view_column_get_fixed_width (cell->column); + int unadj_width; + + unadj_width = unadjust_width (widget, fixed_width); if (orientation == GTK_ORIENTATION_VERTICAL) { if (fixed_width > -1) { if (for_size == -1) - for_size = fixed_width; + for_size = unadj_width; else - for_size = MIN (for_size, fixed_width); + for_size = MIN (for_size, unadj_width); } } @@ -74,7 +111,10 @@ gtk_column_view_cell_measure (GtkWidget *widget, if (orientation == GTK_ORIENTATION_HORIZONTAL) { if (fixed_width > -1) - *minimum = *natural = fixed_width; + { + *minimum = 0; + *natural = unadj_width; + } } } @@ -84,10 +124,16 @@ gtk_column_view_cell_size_allocate (GtkWidget *widget, int height, int baseline) { + GtkColumnViewCell *self = GTK_COLUMN_VIEW_CELL (widget); GtkWidget *child = gtk_widget_get_first_child (widget); if (child) - gtk_widget_allocate (child, width, height, baseline, NULL); + { + if (gtk_column_view_column_get_fixed_width (self->column) > -1) + gtk_widget_measure (child, GTK_ORIENTATION_HORIZONTAL, height, NULL, &width, NULL, NULL); + + gtk_widget_allocate (child, width, height, baseline, NULL); + } } static void diff --git a/gtk/gtkcolumnviewlayout.c b/gtk/gtkcolumnviewlayout.c index 1b56a3b6ff..6f9dfdb13c 100644 --- a/gtk/gtkcolumnviewlayout.c +++ b/gtk/gtkcolumnviewlayout.c @@ -128,7 +128,7 @@ gtk_column_view_layout_allocate (GtkLayoutManager *layout_manager, child = _gtk_widget_get_next_sibling (child)) { GtkColumnViewColumn *column; - int col_x, col_width; + int col_x, col_width, min; if (!gtk_widget_should_layout (child)) continue; @@ -144,7 +144,9 @@ gtk_column_view_layout_allocate (GtkLayoutManager *layout_manager, gtk_column_view_column_get_header_allocation (column, &col_x, &col_width); } - gtk_widget_size_allocate (child, &(GtkAllocation) { col_x, 0, col_width, height }, baseline); + gtk_widget_measure (child, GTK_ORIENTATION_HORIZONTAL, -1, &min, NULL, NULL, NULL); + + gtk_widget_size_allocate (child, &(GtkAllocation) { col_x, 0, MAX (min, col_width), height }, baseline); } } diff --git a/gtk/gtkcolumnviewtitle.c b/gtk/gtkcolumnviewtitle.c index 12c39d9ba3..bc06da1670 100644 --- a/gtk/gtkcolumnviewtitle.c +++ b/gtk/gtkcolumnviewtitle.c @@ -32,6 +32,8 @@ #include "gtkgestureclick.h" #include "gtkpopovermenu.h" #include "gtknative.h" +#include "gtkcssnodeprivate.h" +#include "gtkcssnumbervalueprivate.h" struct _GtkColumnViewTitle { @@ -52,6 +54,37 @@ struct _GtkColumnViewTitleClass G_DEFINE_TYPE (GtkColumnViewTitle, gtk_column_view_title, GTK_TYPE_WIDGET) +static int +get_number (GtkCssValue *value) +{ + double d = _gtk_css_number_value_get (value, 100); + + if (d < 1) + return ceil (d); + else + return floor (d); +} + +static int +unadjust_width (GtkWidget *widget, + int width) +{ + GtkCssStyle *style; + int widget_margins; + int css_extra; + + style = gtk_css_node_get_style (gtk_widget_get_css_node (widget)); + css_extra = get_number (style->size->margin_left) + + get_number (style->size->margin_right) + + get_number (style->border->border_left_width) + + get_number (style->border->border_right_width) + + get_number (style->size->padding_left) + + get_number (style->size->padding_right); + widget_margins = widget->priv->margin.left + widget->priv->margin.right; + + return MAX (0, width - widget_margins - css_extra); +} + static void gtk_column_view_title_measure (GtkWidget *widget, GtkOrientation orientation, @@ -64,15 +97,18 @@ gtk_column_view_title_measure (GtkWidget *widget, GtkColumnViewTitle *self = GTK_COLUMN_VIEW_TITLE (widget); GtkWidget *child = gtk_widget_get_first_child (widget); int fixed_width = gtk_column_view_column_get_fixed_width (self->column); + int unadj_width; + + unadj_width = unadjust_width (widget, fixed_width); if (orientation == GTK_ORIENTATION_VERTICAL) { if (fixed_width > -1) { if (for_size == -1) - for_size = fixed_width; + for_size = unadj_width; else - for_size = MIN (for_size, fixed_width); + for_size = MIN (for_size, unadj_width); } } @@ -82,7 +118,10 @@ gtk_column_view_title_measure (GtkWidget *widget, if (orientation == GTK_ORIENTATION_HORIZONTAL) { if (fixed_width > -1) - *minimum = *natural = fixed_width; + { + *minimum = 0; + *natural = unadj_width; + } } } @@ -96,7 +135,12 @@ gtk_column_view_title_size_allocate (GtkWidget *widget, GtkWidget *child = gtk_widget_get_first_child (widget); if (child) - gtk_widget_allocate (child, width, height, baseline, NULL); + { + if (gtk_column_view_column_get_fixed_width (self->column) > -1) + gtk_widget_measure (child, GTK_ORIENTATION_HORIZONTAL, height, NULL, &width, NULL, NULL); + + gtk_widget_allocate (child, width, height, baseline, NULL); + } if (self->popup_menu) gtk_native_check_resize (GTK_NATIVE (self->popup_menu)); From e70ed905d19acba7f93ffb9586d8166b4dc15984 Mon Sep 17 00:00:00 2001 From: Matthias Clasen Date: Thu, 24 Sep 2020 14:30:40 -0400 Subject: [PATCH 3/3] columview: Don't overdraw Just always tell the title and cell widgets to clip their children to the right size. Otherwise we risk things getting out of sync and unintended overdraw. Fixes: #3179 --- gtk/gtkcolumnviewcell.c | 1 + gtk/gtkcolumnviewcolumn.c | 18 ------------------ gtk/gtkcolumnviewtitle.c | 2 ++ 3 files changed, 3 insertions(+), 18 deletions(-) diff --git a/gtk/gtkcolumnviewcell.c b/gtk/gtkcolumnviewcell.c index 0881a6ccd3..0b94fe7bcd 100644 --- a/gtk/gtkcolumnviewcell.c +++ b/gtk/gtkcolumnviewcell.c @@ -221,6 +221,7 @@ gtk_column_view_cell_init (GtkColumnViewCell *self) GtkWidget *widget = GTK_WIDGET (self); gtk_widget_set_focusable (widget, FALSE); + gtk_widget_set_overflow (widget, GTK_OVERFLOW_HIDDEN); /* FIXME: Figure out if setting the manager class to INVALID should work */ gtk_widget_set_layout_manager (widget, NULL); widget->priv->resize_func = gtk_column_view_cell_resize_func; diff --git a/gtk/gtkcolumnviewcolumn.c b/gtk/gtkcolumnviewcolumn.c index 4c738fd6fc..c1e7c18317 100644 --- a/gtk/gtkcolumnviewcolumn.c +++ b/gtk/gtkcolumnviewcolumn.c @@ -994,8 +994,6 @@ void gtk_column_view_column_set_fixed_width (GtkColumnViewColumn *self, int fixed_width) { - GtkOverflow overflow; - g_return_if_fail (GTK_IS_COLUMN_VIEW_COLUMN (self)); g_return_if_fail (fixed_width >= -1); @@ -1004,22 +1002,6 @@ gtk_column_view_column_set_fixed_width (GtkColumnViewColumn *self, self->fixed_width = fixed_width; - if (fixed_width > -1) - overflow = GTK_OVERFLOW_HIDDEN; - else - overflow = GTK_OVERFLOW_VISIBLE; - - if (self->header && - overflow != gtk_widget_get_overflow (GTK_WIDGET (self->header))) - { - GtkColumnViewCell *cell; - - gtk_widget_set_overflow (GTK_WIDGET (self->header), overflow); - - for (cell = self->first_cell; cell; cell = gtk_column_view_cell_get_next (cell)) - gtk_widget_set_overflow (GTK_WIDGET (cell), overflow); - } - gtk_column_view_column_queue_resize (self); g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_FIXED_WIDTH]); diff --git a/gtk/gtkcolumnviewtitle.c b/gtk/gtkcolumnviewtitle.c index bc06da1670..9291bd01b6 100644 --- a/gtk/gtkcolumnviewtitle.c +++ b/gtk/gtkcolumnviewtitle.c @@ -256,6 +256,8 @@ gtk_column_view_title_init (GtkColumnViewTitle *self) widget->priv->resize_func = gtk_column_view_title_resize_func; + gtk_widget_set_overflow (widget, GTK_OVERFLOW_HIDDEN); + self->box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0); gtk_widget_set_parent (self->box, widget);