diff options
-rw-r--r-- | gtk/gtkrange.c | 57 |
1 files changed, 52 insertions, 5 deletions
diff --git a/gtk/gtkrange.c b/gtk/gtkrange.c index ebe4cb706b..c3f613f2da 100644 --- a/gtk/gtkrange.c +++ b/gtk/gtkrange.c @@ -101,6 +101,8 @@ struct _GtkRangePrivate int slide_initial_slider_position; int slide_initial_coordinate_delta; + guint changed_tick_id; + guint flippable : 1; guint inverted : 1; guint slider_size_fixed : 1; @@ -683,6 +685,12 @@ gtk_range_set_adjustment (GtkRange *range, g_signal_handlers_disconnect_by_func (priv->adjustment, gtk_range_adjustment_value_changed, range); + if (priv->changed_tick_id) + { + gtk_widget_remove_tick_callback (GTK_WIDGET (range), + priv->changed_tick_id); + priv->changed_tick_id = 0; + } g_object_unref (priv->adjustment); } @@ -1308,6 +1316,13 @@ gtk_range_dispose (GObject *object) gtk_range_remove_step_timer (range); + if (priv->changed_tick_id) + { + gtk_widget_remove_tick_callback (GTK_WIDGET (range), + priv->changed_tick_id); + priv->changed_tick_id = 0; + } + if (priv->adjustment) { g_signal_handlers_disconnect_by_func (priv->adjustment, @@ -2339,16 +2354,22 @@ gtk_range_drag_gesture_end (GtkGestureDrag *gesture, stop_scrolling (range); } -static void -gtk_range_adjustment_changed (GtkAdjustment *adjustment, - gpointer data) +static gboolean +gtk_range_adjustment_changed_cb (GtkWidget *widget, + GdkFrameClock *frame_clock, + gpointer unused) { - GtkRange *range = GTK_RANGE (data); + GtkRange *range = GTK_RANGE (widget); GtkRangePrivate *priv = gtk_range_get_instance_private (range); double upper = gtk_adjustment_get_upper (priv->adjustment); double lower = gtk_adjustment_get_lower (priv->adjustment); - gtk_widget_set_visible (priv->slider_widget, upper != lower || !GTK_IS_SCALE (range)); + priv->changed_tick_id = 0; + + if (upper == lower && GTK_IS_SCALE (range)) + gtk_widget_hide (priv->slider_widget); + else + gtk_widget_show (priv->slider_widget); gtk_widget_queue_allocate (priv->trough_widget); @@ -2364,6 +2385,32 @@ gtk_range_adjustment_changed (GtkAdjustment *adjustment, * can input into the adjustment, not a filter that the GtkRange * will enforce on the adjustment. */ + + return G_SOURCE_REMOVE; +} + +static void +gtk_range_adjustment_changed (GtkAdjustment *adjustment, + gpointer data) +{ + GtkRange *range = GTK_RANGE (data); + GtkRangePrivate *priv = gtk_range_get_instance_private (range); + + /* There is a good chance that we will get this notification + * from size_allocate() of another widget. That means we are + * already in the LAYOUT phase of the frame clock. + * + * It's not allowed to call gtk_widget_show()/hide() from that + * point because it will result in a loss of allocations which + * are needed to complete the current frame. + * + * Instead, defer until the next frame to perform adjustments. + */ + if (priv->changed_tick_id == 0) + priv->changed_tick_id = + gtk_widget_add_tick_callback (GTK_WIDGET (range), + gtk_range_adjustment_changed_cb, + NULL, NULL); } static void |