Issue #11339: color selection sliders don't always update for slow increments.

Rather than the previously reverted commit, the proper solution is:

* gimp_color_selector_set_color() must not test for perceptual identity
  because GimpColorSelector is too much of a generic class. In some
  case, such a test may be worth it to limit costly updates (in
  particular when it implies some rendering of color surfaces), but this
  would happen in specific subclasses.
* In GimpColorSelection, the GimpColorScales show numbers, so any change
  in them will likely trigger other scales to change as a side effect.
  Therefore when handling the "color-changed" signal on these scales,
  however small the change may be, we want to run the update.

Now removing this test in gimp_color_selector_set_color() also revealed
a serious bug which I fix in this commit, which is that the binding
between the "value" of a GimpLabelSpin with the "value" of its
adjustment was still triggering repeated property-setting, which was
enough to freeze the GUI for a while. The logic of using only the
GtkAdjustment's value as a source while also binding both properties was
not robust enough. Instead the GimpLabelSpin will now store its own
value and the binding will simply keep it in sync with the one in the
adjustment.

Note that this is also part of the solution for #10998, because it means
there were cases where the color displayed in scales of the color
selection dialog was not actually the color set as foreground or
background.
This commit is contained in:
Jehan 2024-10-10 03:12:34 +02:00
parent 079a68a920
commit a040dfd6e4
3 changed files with 16 additions and 28 deletions

View file

@ -753,21 +753,15 @@ gimp_color_selection_scales_changed (GimpColorSelector *selector,
GimpColorSelection *selection) GimpColorSelection *selection)
{ {
GimpColorSelectionPrivate *priv; GimpColorSelectionPrivate *priv;
GeglColor *old_color;
priv = gimp_color_selection_get_instance_private (selection); priv = gimp_color_selection_get_instance_private (selection);
old_color = priv->color; g_object_unref (priv->color);
priv->color = gegl_color_duplicate (color); priv->color = gegl_color_duplicate (color);
if (! gimp_color_is_perceptually_identical (priv->color, old_color)) gimp_color_selection_update (selection,
{ UPDATE_ENTRY | UPDATE_NOTEBOOK | UPDATE_COLOR);
gimp_color_selection_update (selection, gimp_color_selection_color_changed (selection);
UPDATE_ENTRY | UPDATE_NOTEBOOK | UPDATE_COLOR);
gimp_color_selection_color_changed (selection);
}
g_object_unref (old_color);
} }
static void static void

View file

@ -407,27 +407,21 @@ gimp_color_selector_set_color (GimpColorSelector *selector,
{ {
GimpColorSelectorClass *selector_class; GimpColorSelectorClass *selector_class;
GimpColorSelectorPrivate *priv; GimpColorSelectorPrivate *priv;
GeglColor *old_color;
g_return_if_fail (GIMP_IS_COLOR_SELECTOR (selector)); g_return_if_fail (GIMP_IS_COLOR_SELECTOR (selector));
g_return_if_fail (GEGL_IS_COLOR (color)); g_return_if_fail (GEGL_IS_COLOR (color));
priv = gimp_color_selector_get_instance_private (selector); priv = gimp_color_selector_get_instance_private (selector);
old_color = priv->color; g_object_unref (priv->color);
priv->color = gegl_color_duplicate (color); priv->color = gegl_color_duplicate (color);
selector_class = GIMP_COLOR_SELECTOR_GET_CLASS (selector); selector_class = GIMP_COLOR_SELECTOR_GET_CLASS (selector);
if (! gimp_color_is_perceptually_identical (priv->color, old_color)) if (selector_class->set_color)
{ selector_class->set_color (selector, priv->color);
if (selector_class->set_color)
selector_class->set_color (selector, priv->color);
gimp_color_selector_emit_color_changed (selector); gimp_color_selector_emit_color_changed (selector);
}
g_object_unref (old_color);
} }
/** /**

View file

@ -62,6 +62,8 @@ typedef struct _GimpLabelSpinPrivate
GtkAdjustment *spin_adjustment; GtkAdjustment *spin_adjustment;
gint digits; gint digits;
gdouble value;
} GimpLabelSpinPrivate; } GimpLabelSpinPrivate;
static void gimp_label_spin_constructed (GObject *object); static void gimp_label_spin_constructed (GObject *object);
@ -216,13 +218,11 @@ gimp_label_spin_set_property (GObject *object,
switch (property_id) switch (property_id)
{ {
case PROP_VALUE: case PROP_VALUE:
/* Avoid looping forever since we have bound this widget's if (priv->value != g_value_get_double (value))
* "value" property with the spin button "value" property. {
*/ priv->value = g_value_get_double (value);
if (gtk_adjustment_get_value (priv->spin_adjustment) != g_value_get_double (value)) g_signal_emit (object, gimp_label_spin_signals[VALUE_CHANGED], 0);
gtk_adjustment_set_value (priv->spin_adjustment, g_value_get_double (value)); }
g_signal_emit (object, gimp_label_spin_signals[VALUE_CHANGED], 0);
break; break;
case PROP_LOWER: case PROP_LOWER:
gtk_adjustment_set_lower (priv->spin_adjustment, gtk_adjustment_set_lower (priv->spin_adjustment,
@ -267,7 +267,7 @@ gimp_label_spin_get_property (GObject *object,
switch (property_id) switch (property_id)
{ {
case PROP_VALUE: case PROP_VALUE:
g_value_set_double (value, gtk_adjustment_get_value (priv->spin_adjustment)); g_value_set_double (value, priv->value);
break; break;
case PROP_LOWER: case PROP_LOWER:
g_value_set_double (value, gtk_adjustment_get_lower (priv->spin_adjustment)); g_value_set_double (value, gtk_adjustment_get_lower (priv->spin_adjustment));