]> Pileus Git - ~andy/gtk/commitdiff
Fix GtkSpinner using style before it's set
authorBastien Nocera <hadess@hadess.net>
Wed, 14 Oct 2009 22:11:43 +0000 (23:11 +0100)
committerBastien Nocera <hadess@hadess.net>
Thu, 15 Oct 2009 00:43:26 +0000 (01:43 +0100)
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
gtk/gtkspinner.c

index f18e1a17eb9dafe66600813d4a5f7cbf11749fb6..314c92220645e89f51265b041255bfb4f3551501 100644 (file)
@@ -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))
index 99dc101685b4d20686bc6cf74dfc76114a96f1b3..624f9ba82c981f67aea55057aef90d68a88ce810 100644 (file)
@@ -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__