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
This commit is contained in:
Bastien Nocera 2009-10-14 23:11:43 +01:00
parent 6f44b00935
commit 7fd79f42ab
2 changed files with 49 additions and 4 deletions

View File

@ -77,6 +77,10 @@ do_spinner (GtkWidget *do_widget)
g_signal_connect (G_OBJECT (button), "clicked", g_signal_connect (G_OBJECT (button), "clicked",
G_CALLBACK (on_stop_clicked), spinner); G_CALLBACK (on_stop_clicked), spinner);
gtk_container_add (GTK_CONTAINER (vbox), button); 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)) if (!GTK_WIDGET_VISIBLE (window))

View File

@ -68,12 +68,15 @@ struct _GtkSpinnerPrivate
guint current; guint current;
guint num_steps; guint num_steps;
guint cycle_duration; guint cycle_duration;
gboolean active;
guint timeout; guint timeout;
}; };
static void gtk_spinner_class_init (GtkSpinnerClass *klass); static void gtk_spinner_class_init (GtkSpinnerClass *klass);
static void gtk_spinner_init (GtkSpinner *spinner); static void gtk_spinner_init (GtkSpinner *spinner);
static void gtk_spinner_dispose (GObject *gobject); 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, static gboolean gtk_spinner_expose (GtkWidget *widget,
GdkEventExpose *event); GdkEventExpose *event);
static void gtk_spinner_screen_changed (GtkWidget *widget, 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 = GTK_WIDGET_CLASS(klass);
widget_class->expose_event = gtk_spinner_expose; 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->screen_changed = gtk_spinner_screen_changed;
widget_class->style_set = gtk_spinner_style_set; widget_class->style_set = gtk_spinner_style_set;
widget_class->get_accessible = gtk_spinner_get_accessible; widget_class->get_accessible = gtk_spinner_get_accessible;
@ -173,7 +178,7 @@ gtk_spinner_get_property (GObject *object,
switch (param_id) switch (param_id)
{ {
case PROP_ACTIVE: case PROP_ACTIVE:
g_value_set_boolean (value, priv->timeout != 0); g_value_set_boolean (value, priv->active);
break; break;
default: default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec); G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
@ -240,6 +245,35 @@ gtk_spinner_expose (GtkWidget *widget, GdkEventExpose *event)
return FALSE; 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 static void
gtk_spinner_screen_changed (GtkWidget* widget, GdkScreen* old_screen) 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 = GTK_SPINNER_GET_PRIVATE (spinner);
priv->active = TRUE;
g_object_notify (G_OBJECT (spinner), "active");
if (priv->timeout != 0) if (priv->timeout != 0)
return; 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); priv->timeout = gdk_threads_add_timeout ((guint) priv->cycle_duration / priv->num_steps, gtk_spinner_timeout, spinner);
g_object_notify (G_OBJECT (spinner), "active");
} }
/** /**
@ -554,12 +592,15 @@ gtk_spinner_stop (GtkSpinner *spinner)
g_return_if_fail (GTK_IS_SPINNER (spinner)); g_return_if_fail (GTK_IS_SPINNER (spinner));
priv = GTK_SPINNER_GET_PRIVATE (spinner); priv = GTK_SPINNER_GET_PRIVATE (spinner);
priv->active = FALSE;
g_object_notify (G_OBJECT (spinner), "active");
if (priv->timeout == 0) if (priv->timeout == 0)
return; return;
g_source_remove (priv->timeout); g_source_remove (priv->timeout);
priv->timeout = 0; priv->timeout = 0;
g_object_notify (G_OBJECT (spinner), "active");
} }
#define __GTK_SPINNER_C__ #define __GTK_SPINNER_C__