Index: ChangeLog
===================================================================
RCS file: /cvs/gnome/gail/ChangeLog,v
retrieving revision 1.583
diff -u -p -r1.583 ChangeLog
--- ChangeLog	14 Oct 2003 14:46:15 -0000	1.583
+++ ChangeLog	20 Oct 2003 12:07:41 -0000
@@ -1,3 +1,21 @@
+2003-10-20  Padraig O'Briain  <padraig.obriain@sun.com>
+
+	* gail/gailtreeview.[ch]:
+	Add fields old_hadj and old_vadj to GailTreeView so we can know
+	previous adjustment values when they change.
+	(gail_tree_view_widget_destroyed): New function which removes
+	signal handlers on adjustments when GtkTreeView is destroyed.
+	(gail_tree_view_real_initialize): Set old_hadj and old_vadj values in
+	GailTreeView data structure. Use g_object_add_weak_pointer to ensure
+	that value is set to NULL when adjustment is destroyed.
+	Add signal handler for "set_scroll_adjusments" so we can know
+	when adjustments are changed.
+	(gail_tree_view_notify_gtk): Handle adjustment changes.
+	(gail_widget_set_scroll_adjustments): Handle adjustment changes
+	called by call to gtk_widget_set_scroll_adjustments.
+
+	This fixes bug #119635
+	
 2003-10-13  Padraig O'Briain  <padraig.obriain@sun.com>
 
 	* gail/gailcontainer.c (gail_container_real_remove_gtk): Add
Index: gail/gailtreeview.c
===================================================================
RCS file: /cvs/gnome/gail/gail/gailtreeview.c,v
retrieving revision 1.156
diff -u -p -r1.156 gailtreeview.c
--- gail/gailtreeview.c	24 Sep 2003 18:00:16 -0000	1.156
+++ gail/gailtreeview.c	20 Oct 2003 12:07:42 -0000
@@ -37,6 +37,11 @@ static void             gail_tree_view_r
                                                          GParamSpec		*pspec);
 static void             gail_tree_view_finalize         (GObject                *object);
 
+static void             gail_tree_view_connect_widget_destroyed 
+                                                        (GtkAccessible        
+*accessible);
+static void             gail_tree_view_destroyed        (GtkWidget              *widget,
+                                                         GtkAccessible          *accessible); 
 /* atkobject.h */
 
 static gint             gail_tree_view_get_n_children   (AtkObject              *obj);
@@ -173,6 +178,10 @@ static gboolean         gail_tree_view_c
                                                          GtkTreePath            *path);
 static void             gail_tree_view_size_allocate_gtk (GtkWidget             *widget,
                                                          GtkAllocation          *allocation);
+static void             gail_tree_view_set_scroll_adjustments
+                                                        (GtkWidget              *widget,
+                                                         GtkAdjustment          *hadj,
+                                                         GtkAdjustment          *vadj);
 static void             gail_tree_view_changed_gtk      (GtkTreeSelection       *selection,
                                                          gpointer               data);
 
@@ -327,6 +336,8 @@ static GailWidgetClass *parent_class = N
 static GQuark quark_column_desc_object = 0;
 static GQuark quark_column_header_object = 0;
 static gboolean editing = FALSE;
+static const gchar* hadjustment = "hadjustment";
+static const gchar* vadjustment = "vadjustment";
 
 struct _GailTreeViewRowInfo
 {
@@ -421,9 +432,11 @@ gail_tree_view_class_init (GailTreeViewC
 {
   AtkObjectClass *class = ATK_OBJECT_CLASS (klass);
   GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
+  GtkAccessibleClass *accessible_class;
   GailWidgetClass *widget_class;
   GailContainerClass *container_class;
 
+  accessible_class = (GtkAccessibleClass*)klass;
   widget_class = (GailWidgetClass*)klass;
   container_class = (GailContainerClass*)klass;
 
@@ -436,6 +449,8 @@ gail_tree_view_class_init (GailTreeViewC
 
   widget_class->notify_gtk = gail_tree_view_real_notify_gtk;
 
+  accessible_class->connect_widget_destroyed = gail_tree_view_connect_widget_destroyed;
+
   /*
    * The children of a GtkTreeView are the buttons at the top of the columns
    * we do not represent these as children so we do not want to report
@@ -470,6 +485,8 @@ gail_tree_view_real_initialize (AtkObjec
   view->col_data = NULL;
   view->cell_data = NULL;
   view->focus_cell = NULL;
+  view->old_hadj = NULL;
+  view->old_vadj = NULL;
 
   view->n_children_deleted = 0;
 
@@ -521,17 +538,25 @@ gail_tree_view_real_initialize (AtkObjec
 
   /* adjustment callbacks */
 
-  g_object_get (tree_view, "hadjustment", &adj, NULL);
+  g_object_get (tree_view, hadjustment, &adj, NULL);
+  view->old_hadj = adj;
+  g_object_add_weak_pointer (G_OBJECT (view->old_hadj), (gpointer *)&view->old_hadj);
   g_signal_connect (adj, 
                     "value_changed",
                     G_CALLBACK (adjustment_changed),
                     tree_view);
 
-  g_object_get (tree_view, "vadjustment", &adj, NULL);
+  g_object_get (tree_view, vadjustment, &adj, NULL);
+  view->old_vadj = adj;
+  g_object_add_weak_pointer (G_OBJECT (view->old_vadj), (gpointer *)&view->old_vadj);
   g_signal_connect (adj, 
                     "value_changed",
                     G_CALLBACK (adjustment_changed),
                     tree_view);
+  g_signal_connect_after (widget,
+                          "set_scroll_adjustments",
+                          G_CALLBACK (gail_tree_view_set_scroll_adjustments),
+                          NULL);
 
   view->col_data = g_array_sized_new (FALSE, TRUE, 
                                       sizeof(GtkTreeViewColumn *), 0);
@@ -559,22 +584,27 @@ static void
 gail_tree_view_real_notify_gtk (GObject             *obj,
                                 GParamSpec          *pspec)
 {
+  GtkWidget *widget = GTK_WIDGET (obj);
+  AtkObject* atk_obj = gtk_widget_get_accessible (widget);
+  GtkTreeView *tree_view;
+  GailTreeView *gailview;
+  GtkAdjustment *adj;
+
+  widget = GTK_WIDGET (obj);
+  atk_obj = gtk_widget_get_accessible (widget);
+  tree_view = GTK_TREE_VIEW (widget);
+  gailview = GAIL_TREE_VIEW (atk_obj);
+
   if (strcmp (pspec->name, "model") == 0)
     {
-      GtkWidget *widget = GTK_WIDGET (obj);
-      AtkObject* atk_obj = gtk_widget_get_accessible (widget);
       GtkTreeModel *tree_model;
-      GtkTreeView *tree_view;
-      GailTreeView *gail_view;
       AtkRole role;
 
-      tree_view = GTK_TREE_VIEW (widget);
       tree_model = gtk_tree_view_get_model (tree_view);
-      gail_view = GAIL_TREE_VIEW (atk_obj);
-      if (gail_view->tree_model)
-        disconnect_model_signals (gail_view->tree_model);
-      clear_cached_data (gail_view);
-      gail_view->tree_model = tree_model;
+      if (gailview->tree_model)
+        disconnect_model_signals (gailview->tree_model);
+      clear_cached_data (gailview);
+      gailview->tree_model = tree_model;
       /*
        * if there is no model the GtkTreeView is probably being destroyed
        */
@@ -600,6 +630,32 @@ gail_tree_view_real_notify_gtk (GObject 
       g_signal_emit_by_name (atk_obj, "visible_data_changed");
       g_object_thaw_notify (G_OBJECT (atk_obj));
     }
+  else if (strcmp (pspec->name, hadjustment) == 0)
+    {
+      g_object_get (tree_view, hadjustment, &adj, NULL);
+      g_signal_handlers_disconnect_by_func (gailview->old_hadj, 
+                                           (gpointer) adjustment_changed,
+                                           widget);
+      gailview->old_hadj = adj;
+      g_object_add_weak_pointer (G_OBJECT (gailview->old_hadj), (gpointer *)&gailview->old_hadj);
+      g_signal_connect (adj, 
+                        "value_changed",
+                        G_CALLBACK (adjustment_changed),
+                        tree_view);
+    }
+  else if (strcmp (pspec->name, vadjustment) == 0)
+    {
+      g_object_get (tree_view, vadjustment, &adj, NULL);
+      g_signal_handlers_disconnect_by_func (gailview->old_vadj, 
+                                           (gpointer) adjustment_changed,
+                                           widget);
+      gailview->old_vadj = adj;
+      g_object_add_weak_pointer (G_OBJECT (gailview->old_hadj), (gpointer *)&gailview->old_vadj);
+      g_signal_connect (adj, 
+                        "value_changed",
+                        G_CALLBACK (adjustment_changed),
+                        tree_view);
+    }
   else
     parent_class->notify_gtk (obj, pspec);
 }
@@ -617,10 +673,6 @@ gail_tree_view_new (GtkWidget *widget)
   accessible = ATK_OBJECT (object);
   atk_object_initialize (accessible, widget);
 
-  /*
-   * The role is set in gail_tree_view_real_initialize()
-   */
-
   return accessible;
 }
 
@@ -656,6 +708,41 @@ gail_tree_view_finalize (GObject	    *ob
   G_OBJECT_CLASS (parent_class)->finalize (object);
 }
 
+static void
+gail_tree_view_connect_widget_destroyed (GtkAccessible *accessible)
+{
+  if (accessible->widget)
+    {
+      g_signal_connect_after (accessible->widget,
+                              "destroy",
+                              G_CALLBACK (gail_tree_view_destroyed),
+                              accessible);
+    }
+  GTK_ACCESSIBLE_CLASS (parent_class)->connect_widget_destroyed (accessible);
+}
+
+static void
+gail_tree_view_destroyed (GtkWidget *widget,
+                          GtkAccessible *accessible)
+{
+  GtkAdjustment *adj;
+  GailTreeView *gailview;
+
+  g_return_if_fail (GTK_IS_TREE_VIEW (widget));
+
+  gailview = GAIL_TREE_VIEW (accessible);
+  adj = gailview->old_hadj;
+  if (adj)
+    g_signal_handlers_disconnect_by_func (adj, 
+                                          (gpointer) adjustment_changed,
+                                          widget);
+  adj = gailview->old_vadj;
+  if (adj)
+    g_signal_handlers_disconnect_by_func (adj, 
+                                          (gpointer) adjustment_changed,
+                                          widget);
+}
+
 AtkObject *
 gail_tree_view_ref_focus_cell (GtkTreeView *tree_view)
 {
@@ -2252,6 +2339,43 @@ gail_tree_view_size_allocate_gtk (GtkWid
    * update the cells visibility.
    */
   traverse_cells (gailview, FALSE, FALSE, FALSE);
+}
+
+static void
+gail_tree_view_set_scroll_adjustments (GtkWidget     *widget,
+                                       GtkAdjustment *hadj,
+                                       GtkAdjustment *vadj)
+{
+  AtkObject *atk_obj = gtk_widget_get_accessible (widget);
+  GailTreeView *gailview = GAIL_TREE_VIEW (atk_obj);
+  GtkAdjustment *adj;
+
+  g_object_get (widget, hadjustment, &adj, NULL);
+  if (gailview->old_hadj != adj)
+     {
+        g_signal_handlers_disconnect_by_func (gailview->old_hadj, 
+                                              (gpointer) adjustment_changed,
+                                              widget);
+        gailview->old_hadj = adj;
+        g_object_add_weak_pointer (G_OBJECT (gailview->old_hadj), (gpointer *)&gailview->old_hadj);
+        g_signal_connect (adj, 
+                          "value_changed",
+                          G_CALLBACK (adjustment_changed),
+                          widget);
+     } 
+  g_object_get (widget, hadjustment, &adj, NULL);
+  if (gailview->old_vadj != adj)
+     {
+        g_signal_handlers_disconnect_by_func (gailview->old_vadj, 
+                                              (gpointer) adjustment_changed,
+                                              widget);
+        gailview->old_vadj = adj;
+        g_object_add_weak_pointer (G_OBJECT (gailview->old_vadj), (gpointer *)&gailview->old_vadj);
+        g_signal_connect (adj, 
+                          "value_changed",
+                          G_CALLBACK (adjustment_changed),
+                          widget);
+     } 
 }
 
 static void
Index: gail/gailtreeview.h
===================================================================
RCS file: /cvs/gnome/gail/gail/gailtreeview.h,v
retrieving revision 1.22
diff -u -p -r1.22 gailtreeview.h
--- gail/gailtreeview.h	10 Dec 2002 16:29:01 -0000	1.22
+++ gail/gailtreeview.h	20 Oct 2003 12:07:42 -0000
@@ -50,6 +50,8 @@ struct _GailTreeView
   GList*        cell_data;
   GtkTreeModel  *tree_model;
   AtkObject     *focus_cell;
+  GtkAdjustment *old_hadj;
+  GtkAdjustment *old_vadj;
 };
 
 GType gail_tree_view_get_type (void);
