mirror of
https://gitlab.gnome.org/GNOME/gtk.git
synced 2024-11-11 19:30:10 +00:00
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.
This commit is contained in:
parent
9cf9abd5b0
commit
790d8e324b
@ -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 = g_hash_table_lookup (gail_notebook->pages,
|
||||
gtk_notebook_get_nth_page (gtk_notebook, i));
|
||||
/* can return NULL when i >= n_children */
|
||||
|
||||
accessible = find_child_in_list (gail_notebook->page_cache, i);
|
||||
|
||||
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);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user