diff --git a/src/adw-clamp-layout.c b/src/adw-clamp-layout.c index 2b36c69fd9a956dc6545cccce2269a8d915a7116..816419ee345abaea906639c7ca6c3284e2015321 100644 --- a/src/adw-clamp-layout.c +++ b/src/adw-clamp-layout.c @@ -149,10 +149,11 @@ inverse_lerp (double a, static int clamp_size_from_child (AdwClampLayout *self, GtkSettings *settings, - int min, - int nat) + GtkWidget *child, + int child_size) { double max, lower, upper, progress, maximum_size, tightening_threshold; + int min, nat; maximum_size = adw_length_unit_to_px (self->unit, self->maximum_size, @@ -161,16 +162,20 @@ clamp_size_from_child (AdwClampLayout *self, self->tightening_threshold, settings); + gtk_widget_measure (child, self->orientation, -1, &min, &nat, NULL, NULL); + lower = MAX (MIN (tightening_threshold, maximum_size), min); max = MAX (lower, maximum_size); upper = lower + ADW_EASE_OUT_TAN_CUBIC * (max - lower); - if (nat <= lower) - progress = 0; - else if (nat >= max) - progress = 1; + g_assert (child_size != -1); + + if (child_size <= lower) + return child_size; + else if (child_size >= max) + return upper; else { - double ease = inverse_lerp (lower, max, nat); + double ease = inverse_lerp (lower, max, child_size); progress = 1 + cbrt (ease - 1); // inverse ease out cubic } @@ -218,18 +223,7 @@ child_size_from_clamp (AdwClampLayout *self, progress = inverse_lerp (lower, upper, for_size); - return ceil (adw_lerp (lower, max, adw_easing_ease (ADW_EASE_OUT_CUBIC, progress))); -} - -static GtkSizeRequestMode -adw_clamp_layout_get_request_mode (GtkLayoutManager *manager, - GtkWidget *widget) -{ - AdwClampLayout *self = ADW_CLAMP_LAYOUT (manager); - - return self->orientation == GTK_ORIENTATION_HORIZONTAL ? - GTK_SIZE_REQUEST_HEIGHT_FOR_WIDTH : - GTK_SIZE_REQUEST_WIDTH_FOR_HEIGHT; + return floor (adw_lerp (lower, max, adw_easing_ease (ADW_EASE_OUT_CUBIC, progress))); } static void @@ -249,35 +243,67 @@ adw_clamp_layout_measure (GtkLayoutManager *manager, for (child = gtk_widget_get_first_child (widget); child != NULL; child = gtk_widget_get_next_sibling (child)) { + int clamp_min = 0; + int clamp_nat = 0; int child_min = 0; int child_nat = 0; - int child_min_baseline = -1; - int child_nat_baseline = -1; + int min_baseline = -1; + int nat_baseline = -1; if (!gtk_widget_should_layout (child)) continue; if (self->orientation == orientation) { + /* We pass all of for_size to the child, but we have to post-process + * its measurements. + */ gtk_widget_measure (child, orientation, for_size, &child_min, &child_nat, - &child_min_baseline, &child_nat_baseline); - - child_nat = clamp_size_from_child (self, settings, child_min, child_nat); + &min_baseline, &nat_baseline); + + clamp_min = clamp_size_from_child (self, settings, child, child_min); + clamp_nat = clamp_size_from_child (self, settings, child, child_nat); + if (min_baseline > -1) + min_baseline += (clamp_min - child_min) / 2; + if (nat_baseline > -1) + nat_baseline += (clamp_nat - child_nat) / 2; } else { - int child_size = child_size_from_clamp (self, settings, child, for_size, NULL, NULL); + /* We clamp for_size, but after that, child's minimum and natural + * sizes in this orientation are what we report. + */ + int child_maximum = 0; + int child_size = child_size_from_clamp (self, settings, child, + for_size, &child_maximum, + NULL); gtk_widget_measure (child, orientation, child_size, &child_min, &child_nat, - &child_min_baseline, &child_nat_baseline); + &min_baseline, &nat_baseline); + + if (for_size == -1 && child_size < child_maximum) { + /* For any specific for_size, we have a definite child_size that + * we measure the child for. When passed for_size = -1 however, + * we're supposed to report overall minimum size, for any + * potential value of for_size. For that, we have to measure the + * child at the maximum size we could give it. Note that we + * should not use this measurement for the natural size. + */ + gtk_widget_measure (child, orientation, child_maximum, + &child_min, NULL, + &min_baseline, NULL); + } + + clamp_min = child_min; + clamp_nat = child_nat; } - *minimum = MAX (*minimum, child_min); - *natural = MAX (*natural, child_nat); + *minimum = MAX (*minimum, clamp_min); + *natural = MAX (*natural, clamp_nat); - if (child_min_baseline > -1) - *minimum_baseline = MAX (*minimum_baseline, child_min_baseline); - if (child_nat_baseline > -1) - *natural_baseline = MAX (*natural_baseline, child_nat_baseline); + if (min_baseline > -1) + *minimum_baseline = MAX (*minimum_baseline, min_baseline); + if (nat_baseline > -1) + *natural_baseline = MAX (*natural_baseline, nat_baseline); } } @@ -304,7 +330,7 @@ adw_clamp_layout_allocate (GtkLayoutManager *manager, gtk_widget_remove_css_class (child, "medium"); gtk_widget_remove_css_class (child, "large"); - return; + continue; } if (self->orientation == GTK_ORIENTATION_HORIZONTAL) { @@ -361,7 +387,6 @@ adw_clamp_layout_class_init (AdwClampLayoutClass *klass) object_class->get_property = adw_clamp_layout_get_property; object_class->set_property = adw_clamp_layout_set_property; - layout_manager_class->get_request_mode = adw_clamp_layout_get_request_mode; layout_manager_class->measure = adw_clamp_layout_measure; layout_manager_class->allocate = adw_clamp_layout_allocate;