From 7fd79f42ab7f5ab19df4033309ecdcc113c7f32b Mon Sep 17 00:00:00 2001 From: Bastien Nocera Date: Wed, 14 Oct 2009 23:11:43 +0100 Subject: [PATCH] Fix GtkSpinner using style before it's set Fix a possible division by zero when the spinner is started before it's realized (eg. before it has a style set). https://bugzilla.gnome.org/show_bug.cgi?id=598496 --- demos/gtk-demo/spinner.c | 4 ++++ gtk/gtkspinner.c | 49 ++++++++++++++++++++++++++++++++++++---- 2 files changed, 49 insertions(+), 4 deletions(-) diff --git a/demos/gtk-demo/spinner.c b/demos/gtk-demo/spinner.c index f18e1a17e..314c92220 100644 --- a/demos/gtk-demo/spinner.c +++ b/demos/gtk-demo/spinner.c @@ -77,6 +77,10 @@ do_spinner (GtkWidget *do_widget) g_signal_connect (G_OBJECT (button), "clicked", G_CALLBACK (on_stop_clicked), spinner); gtk_container_add (GTK_CONTAINER (vbox), button); + + /* Start by default to test for: + * https://bugzilla.gnome.org/show_bug.cgi?id=598496 */ + on_play_clicked (NULL, NULL); } if (!GTK_WIDGET_VISIBLE (window)) diff --git a/gtk/gtkspinner.c b/gtk/gtkspinner.c index 99dc10168..624f9ba82 100644 --- a/gtk/gtkspinner.c +++ b/gtk/gtkspinner.c @@ -68,12 +68,15 @@ struct _GtkSpinnerPrivate guint current; guint num_steps; guint cycle_duration; + gboolean active; guint timeout; }; static void gtk_spinner_class_init (GtkSpinnerClass *klass); static void gtk_spinner_init (GtkSpinner *spinner); static void gtk_spinner_dispose (GObject *gobject); +static void gtk_spinner_realize (GtkWidget *widget); +static void gtk_spinner_unrealize (GtkWidget *widget); static gboolean gtk_spinner_expose (GtkWidget *widget, GdkEventExpose *event); static void gtk_spinner_screen_changed (GtkWidget *widget, @@ -108,6 +111,8 @@ gtk_spinner_class_init (GtkSpinnerClass *klass) widget_class = GTK_WIDGET_CLASS(klass); widget_class->expose_event = gtk_spinner_expose; + widget_class->realize = gtk_spinner_realize; + widget_class->unrealize = gtk_spinner_unrealize; widget_class->screen_changed = gtk_spinner_screen_changed; widget_class->style_set = gtk_spinner_style_set; widget_class->get_accessible = gtk_spinner_get_accessible; @@ -173,7 +178,7 @@ gtk_spinner_get_property (GObject *object, switch (param_id) { case PROP_ACTIVE: - g_value_set_boolean (value, priv->timeout != 0); + g_value_set_boolean (value, priv->active); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec); @@ -240,6 +245,35 @@ gtk_spinner_expose (GtkWidget *widget, GdkEventExpose *event) return FALSE; } +static void +gtk_spinner_realize (GtkWidget *widget) +{ + GtkSpinnerPrivate *priv; + + priv = GTK_SPINNER_GET_PRIVATE (widget); + + GTK_WIDGET_CLASS (gtk_spinner_parent_class)->realize (widget); + + if (priv->active) + gtk_spinner_start (GTK_SPINNER (widget)); +} + +static void +gtk_spinner_unrealize (GtkWidget *widget) +{ + GtkSpinnerPrivate *priv; + + priv = GTK_SPINNER_GET_PRIVATE (widget); + + if (priv->timeout != 0) + { + g_source_remove (priv->timeout); + priv->timeout = 0; + } + + GTK_WIDGET_CLASS (gtk_spinner_parent_class)->unrealize (widget); +} + static void gtk_spinner_screen_changed (GtkWidget* widget, GdkScreen* old_screen) { @@ -531,11 +565,15 @@ gtk_spinner_start (GtkSpinner *spinner) priv = GTK_SPINNER_GET_PRIVATE (spinner); + priv->active = TRUE; + g_object_notify (G_OBJECT (spinner), "active"); + if (priv->timeout != 0) return; + if (!GTK_WIDGET_REALIZED (GTK_WIDGET (spinner))) + return; - priv->timeout = gdk_threads_add_timeout (priv->cycle_duration / priv->num_steps, gtk_spinner_timeout, spinner); - g_object_notify (G_OBJECT (spinner), "active"); + priv->timeout = gdk_threads_add_timeout ((guint) priv->cycle_duration / priv->num_steps, gtk_spinner_timeout, spinner); } /** @@ -554,12 +592,15 @@ gtk_spinner_stop (GtkSpinner *spinner) g_return_if_fail (GTK_IS_SPINNER (spinner)); priv = GTK_SPINNER_GET_PRIVATE (spinner); + + priv->active = FALSE; + g_object_notify (G_OBJECT (spinner), "active"); + if (priv->timeout == 0) return; g_source_remove (priv->timeout); priv->timeout = 0; - g_object_notify (G_OBJECT (spinner), "active"); } #define __GTK_SPINNER_C__ -- 2.43.2