Commit 790d8e32 authored by Benjamin Otte's avatar Benjamin Otte Committed by Matthias Clasen
Browse files

a11y: Redo notebook page management

Previously, the code tried to track the indexes of the pages and keep
them up to date in a list and tracking the index in the
GtkNotebookPage. Now, we store the widget we are tracking in the
GailNotebookPage and keep a hash table of widget=>GailNotebookPage in the
GailNotebook. This frees us from the burden of tracking page changes.
parent 9cf9abd5
......@@ -43,20 +43,9 @@ static AtkObject* gail_notebook_ref_selection (AtkSelection *selection
static gint gail_notebook_get_selection_count (AtkSelection *selection);
static gboolean gail_notebook_is_child_selected (AtkSelection *selection,
gint i);
static AtkObject* find_child_in_list (GList *list,
gint index);
static void check_cache (GailNotebook *gail_notebook,
GtkNotebook *notebook);
static void reset_cache (GailNotebook *gail_notebook,
gint index);
static void create_notebook_page_accessible (GailNotebook *gail_notebook,
GtkNotebook *notebook,
gint index,
gboolean insert_before,
GList *list);
static void gail_notebook_child_parent_set (GtkWidget *widget,
GtkWidget *old_parent,
gpointer data);
GtkWidget *child);
static gboolean gail_notebook_focus_cb (GtkWidget *widget,
GtkDirectionType type);
static gboolean gail_notebook_check_focus_tab (gpointer data);
......@@ -91,10 +80,12 @@ gail_notebook_class_init (GailNotebookClass *klass)
static void
gail_notebook_init (GailNotebook *notebook)
{
notebook->page_cache = NULL;
notebook->pages = g_hash_table_new_full (g_direct_hash,
g_direct_equal,
NULL,
g_object_unref);
notebook->selected_page = -1;
notebook->focus_tab_page = -1;
notebook->remove_index = -1;
notebook->idle_focus_id = 0;
}
......@@ -115,15 +106,13 @@ gail_notebook_ref_child (AtkObject *obj,
return NULL;
gail_notebook = GAIL_NOTEBOOK (obj);
gtk_notebook = GTK_NOTEBOOK (widget);
if (gail_notebook->page_count < gtk_notebook_get_n_pages (gtk_notebook))
check_cache (gail_notebook, gtk_notebook);
accessible = find_child_in_list (gail_notebook->page_cache, i);
accessible = g_hash_table_lookup (gail_notebook->pages,
gtk_notebook_get_nth_page (gtk_notebook, i));
/* can return NULL when i >= n_children */
if (accessible != NULL)
if (accessible)
g_object_ref (accessible);
return accessible;
......@@ -140,8 +129,7 @@ gail_notebook_page_added (GtkNotebook *gtk_notebook,
atk_obj = gtk_widget_get_accessible (GTK_WIDGET (gtk_notebook));
notebook = GAIL_NOTEBOOK (atk_obj);
create_notebook_page_accessible (notebook, gtk_notebook, page_num, FALSE, NULL);
notebook->page_count++;
create_notebook_page_accessible (notebook, gtk_notebook, child);
}
static void
......@@ -152,24 +140,18 @@ gail_notebook_page_removed (GtkNotebook *notebook,
{
GailNotebook *gail_notebook;
AtkObject *obj;
gint index;
gail_notebook = GAIL_NOTEBOOK (gtk_widget_get_accessible (GTK_WIDGET (notebook)));
index = gail_notebook->remove_index;
gail_notebook->remove_index = -1;
obj = find_child_in_list (gail_notebook->page_cache, index);
obj = g_hash_table_lookup (gail_notebook->pages, widget);
g_return_if_fail (obj);
gail_notebook->page_cache = g_list_remove (gail_notebook->page_cache, obj);
gail_notebook->page_count -= 1;
reset_cache (gail_notebook, index);
g_signal_emit_by_name (gail_notebook,
"children_changed::remove",
page_num,
obj,
NULL);
gail_notebook_page_invalidate (GAIL_NOTEBOOK_PAGE (obj));
g_object_unref (obj);
g_hash_table_remove (gail_notebook->pages, widget);
}
static void
......@@ -186,9 +168,10 @@ gail_notebook_real_initialize (AtkObject *obj,
gtk_notebook = GTK_NOTEBOOK (data);
for (i = 0; i < gtk_notebook_get_n_pages (gtk_notebook); i++)
{
create_notebook_page_accessible (notebook, gtk_notebook, i, FALSE, NULL);
create_notebook_page_accessible (notebook,
gtk_notebook,
gtk_notebook_get_nth_page (gtk_notebook, i));
}
notebook->page_count = i;
notebook->selected_page = gtk_notebook_get_current_page (gtk_notebook);
g_signal_connect (gtk_notebook,
......@@ -231,8 +214,6 @@ gail_notebook_real_notify_gtk (GObject *obj,
gail_notebook = GAIL_NOTEBOOK (atk_obj);
gtk_notebook = GTK_NOTEBOOK (widget);
if (gail_notebook->page_count < gtk_notebook_get_n_pages (gtk_notebook))
check_cache (gail_notebook, gtk_notebook);
/*
* Notify SELECTED state change for old and new page
*/
......@@ -290,22 +271,8 @@ static void
gail_notebook_finalize (GObject *object)
{
GailNotebook *notebook = GAIL_NOTEBOOK (object);
GList *list;
/*
* Get rid of the GailNotebookPage objects which we have cached.
*/
list = notebook->page_cache;
if (list != NULL)
{
while (list)
{
g_object_unref (list->data);
list = list->next;
}
}
g_list_free (notebook->page_cache);
g_hash_table_destroy (notebook->pages);
if (notebook->idle_focus_id)
g_source_remove (notebook->idle_focus_id);
......@@ -428,103 +395,17 @@ gail_notebook_is_child_selected (AtkSelection *selection,
return FALSE;
}
static AtkObject*
find_child_in_list (GList *list,
gint index)
{
AtkObject *obj = NULL;
while (list)
{
if (GAIL_NOTEBOOK_PAGE (list->data)->index == index)
{
obj = ATK_OBJECT (list->data);
break;
}
list = list->next;
}
return obj;
}
static void
check_cache (GailNotebook *gail_notebook,
GtkNotebook *notebook)
{
GList *gtk_list;
GList *gail_list;
gint i;
gtk_list = gtk_container_get_children (GTK_CONTAINER (notebook));
gail_list = gail_notebook->page_cache;
i = 0;
while (gtk_list)
{
if (!gail_list)
{
create_notebook_page_accessible (gail_notebook, notebook, i, FALSE, NULL);
}
else if (GAIL_NOTEBOOK_PAGE (gail_list->data)->page != gtk_list->data)
{
create_notebook_page_accessible (gail_notebook, notebook, i, TRUE, gail_list);
}
else
{
gail_list = gail_list->next;
}
i++;
gtk_list = gtk_list->next;
}
g_list_free (gtk_list);
gail_notebook->page_count = i;
}
static void
reset_cache (GailNotebook *gail_notebook,
gint index)
{
GList *l;
for (l = gail_notebook->page_cache; l; l = l->next)
{
if (GAIL_NOTEBOOK_PAGE (l->data)->index > index)
GAIL_NOTEBOOK_PAGE (l->data)->index -= 1;
}
}
static void
create_notebook_page_accessible (GailNotebook *gail_notebook,
GtkNotebook *notebook,
gint index,
gboolean insert_before,
GList *list)
GtkWidget *child)
{
AtkObject *obj;
obj = gail_notebook_page_new (notebook, index);
g_object_ref (obj);
if (insert_before)
gail_notebook->page_cache = g_list_insert_before (gail_notebook->page_cache, list, obj);
else
gail_notebook->page_cache = g_list_append (gail_notebook->page_cache, obj);
g_signal_connect (gtk_notebook_get_nth_page (notebook, index),
"parent_set",
G_CALLBACK (gail_notebook_child_parent_set),
obj);
}
static void
gail_notebook_child_parent_set (GtkWidget *widget,
GtkWidget *old_parent,
gpointer data)
{
GailNotebook *gail_notebook;
if (!old_parent)
return;
gail_notebook = GAIL_NOTEBOOK (gtk_widget_get_accessible (old_parent));
gail_notebook->remove_index = GAIL_NOTEBOOK_PAGE (data)->index;
obj = gail_notebook_page_new (notebook, child);
g_hash_table_insert (gail_notebook->pages,
child,
obj);
}
static gboolean
......
......@@ -44,13 +44,10 @@ struct _GailNotebook
* If the page is found in the list then a new page does not
* need to be created
*/
GList* page_cache;
GHashTable * pages;
gint selected_page;
gint focus_tab_page;
gint page_count;
guint idle_focus_id;
gint remove_index;
};
GType gail_notebook_get_type (void);
......
......@@ -156,7 +156,11 @@ notify_child_added (gpointer data)
{
atk_parent = gtk_widget_get_accessible (GTK_WIDGET (page->notebook));
atk_object_set_parent (atk_object, atk_parent);
g_signal_emit_by_name (atk_parent, "children_changed::add", page->index, atk_object, NULL);
g_signal_emit_by_name (atk_parent,
"children_changed::add",
gtk_notebook_page_num (page->notebook, page->child),
atk_object,
NULL);
}
return FALSE;
......@@ -164,30 +168,20 @@ notify_child_added (gpointer data)
AtkObject*
gail_notebook_page_new (GtkNotebook *notebook,
gint pagenum)
GtkWidget *child)
{
GObject *object;
AtkObject *atk_object;
GailNotebookPage *page;
GtkWidget *child;
GtkWidget *label;
GtkWidget *widget_page;
g_return_val_if_fail (GTK_IS_NOTEBOOK (notebook), NULL);
child = gtk_notebook_get_nth_page (notebook, pagenum);
if (!child)
return NULL;
object = g_object_new (GAIL_TYPE_NOTEBOOK_PAGE, NULL);
g_return_val_if_fail (object != NULL, NULL);
page = GAIL_NOTEBOOK_PAGE (object);
page->notebook = notebook;
page->index = pagenum;
widget_page = gtk_notebook_get_nth_page (notebook, pagenum);
page->page = widget_page;
page->child = child;
page->textutil = NULL;
atk_object = ATK_OBJECT (page);
......@@ -223,6 +217,7 @@ gail_notebook_page_invalidate (GailNotebookPage *page)
TRUE);
atk_object_set_parent (ATK_OBJECT (page), NULL);
page->notebook = NULL;
page->child = NULL;
}
static void
......@@ -349,7 +344,6 @@ static AtkObject*
gail_notebook_page_ref_child (AtkObject *accessible,
gint i)
{
GtkWidget *child;
AtkObject *child_obj;
GailNotebookPage *page = NULL;
......@@ -361,11 +355,7 @@ gail_notebook_page_ref_child (AtkObject *accessible,
if (!page->notebook)
return NULL;
child = gtk_notebook_get_nth_page (page->notebook, page->index);
if (!GTK_IS_WIDGET (child))
return NULL;
child_obj = gtk_widget_get_accessible (child);
child_obj = gtk_widget_get_accessible (page->child);
g_object_ref (child_obj);
return child_obj;
}
......@@ -375,10 +365,11 @@ gail_notebook_page_get_index_in_parent (AtkObject *accessible)
{
GailNotebookPage *page;
g_return_val_if_fail (GAIL_IS_NOTEBOOK_PAGE (accessible), -1);
page = GAIL_NOTEBOOK_PAGE (accessible);
if (!page->notebook || !page->child)
return -1;
return page->index;
return gtk_notebook_page_num (page->notebook, page->child);
}
static AtkStateSet*
......@@ -794,11 +785,7 @@ get_label_from_notebook_page (GailNotebookPage *page)
if (!gtk_notebook_get_show_tabs (notebook))
return NULL;
child = gtk_notebook_get_nth_page (notebook, page->index);
if (child == NULL) return NULL;
g_return_val_if_fail (GTK_IS_WIDGET (child), NULL);
child = gtk_notebook_get_tab_label (notebook, child);
child = gtk_notebook_get_tab_label (notebook, page->child);
if (GTK_IS_LABEL (child))
return child;
......
......@@ -40,13 +40,8 @@ struct _GailNotebookPage
AtkObject parent;
GtkNotebook *notebook;
#ifndef GTK_DISABLE_DEPRECATED
GtkNotebookPage *page;
#else
gpointer page;
#endif
gint index;
GtkWidget *child;
guint notify_child_added_id;
GailTextUtil *textutil;
......@@ -59,7 +54,7 @@ struct _GailNotebookPageClass
AtkObjectClass parent_class;
};
AtkObject *gail_notebook_page_new(GtkNotebook *notebook, gint pagenum);
AtkObject *gail_notebook_page_new(GtkNotebook *notebook, GtkWidget *child);
void gail_notebook_page_invalidate (GailNotebookPage *page);
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment