From 31cd153050d74b431070c3f426da95f104eab08f Mon Sep 17 00:00:00 2001 From: Carlos Garnacho Date: Fri, 7 Mar 2014 00:07:54 +0100 Subject: [PATCH] a11y: Add GtkPopopverAccessible And let GtkPopover use it as its GtkAccessible implementation, this accessible sets the POPUP_FOR relationship to the relative-to widget, and keeps track of changes there. https://bugzilla.gnome.org/show_bug.cgi?id=725864 --- gtk/a11y/Makefile.am | 2 + gtk/a11y/gtkpopoveraccessible.c | 160 ++++++++++++++++++++++++++++++++ gtk/a11y/gtkpopoveraccessible.h | 56 +++++++++++ gtk/gtk-a11y.h | 1 + gtk/gtkpopover.c | 2 + 5 files changed, 221 insertions(+) create mode 100644 gtk/a11y/gtkpopoveraccessible.c create mode 100644 gtk/a11y/gtkpopoveraccessible.h diff --git a/gtk/a11y/Makefile.am b/gtk/a11y/Makefile.am index b3c90a563b..df89924ec0 100644 --- a/gtk/a11y/Makefile.am +++ b/gtk/a11y/Makefile.am @@ -37,6 +37,7 @@ gtka11y_c_sources = \ gtknotebookaccessible.c \ gtknotebookpageaccessible.c \ gtkpanedaccessible.c \ + gtkpopoveraccessible.c \ gtkprogressbaraccessible.c \ gtkradiobuttonaccessible.c \ gtkradiomenuitemaccessible.c \ @@ -89,6 +90,7 @@ gtka11yinclude_HEADERS = \ gtknotebookaccessible.h \ gtknotebookpageaccessible.h \ gtkpanedaccessible.h \ + gtkpopoveraccessible.h \ gtkprogressbaraccessible.h \ gtkradiobuttonaccessible.h \ gtkradiomenuitemaccessible.h \ diff --git a/gtk/a11y/gtkpopoveraccessible.c b/gtk/a11y/gtkpopoveraccessible.c new file mode 100644 index 0000000000..b72692506a --- /dev/null +++ b/gtk/a11y/gtkpopoveraccessible.c @@ -0,0 +1,160 @@ +/* GTK - The GIMP Toolkit + * Copyright © 2014 Red Hat Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see . + * + * Author: Carlos Garnacho + */ + +#include "config.h" + +#include +#include +#include "gtkpopoveraccessible.h" + +typedef struct _GtkPopoverAccessiblePrivate GtkPopoverAccessiblePrivate; + +struct _GtkPopoverAccessiblePrivate +{ + GtkWidget *widget; +}; + +G_DEFINE_TYPE_WITH_CODE (GtkPopoverAccessible, gtk_popover_accessible, GTK_TYPE_CONTAINER_ACCESSIBLE, + G_ADD_PRIVATE (GtkPopoverAccessible)) + +static void +popover_update_relative_to (AtkObject *obj, + GtkPopover *popover) +{ + GtkPopoverAccessiblePrivate *priv; + AtkObject *widget_accessible; + GtkWidget *widget; + + priv = gtk_popover_accessible_get_instance_private (GTK_POPOVER_ACCESSIBLE (obj)); + widget = gtk_popover_get_relative_to (popover); + + if (priv->widget == widget) + return; + + if (priv->widget) + { + widget_accessible = gtk_widget_get_accessible (priv->widget); + atk_object_remove_relationship (obj, + ATK_RELATION_POPUP_FOR, + widget_accessible); + } + + priv->widget = widget; + + if (widget) + { + g_object_add_weak_pointer (G_OBJECT (priv->widget), + (gpointer*) &priv->widget); + widget_accessible = gtk_widget_get_accessible (widget); + atk_object_add_relationship (obj, + ATK_RELATION_POPUP_FOR, + widget_accessible); + } +} + +static void +popover_update_modality (AtkObject *object, + GtkPopover *popover) +{ + atk_object_notify_state_change (object, ATK_STATE_MODAL, + gtk_popover_get_modal (popover)); +} + +static void +popover_notify_cb (GtkPopover *popover, + GParamSpec *pspec, + AtkObject *object) +{ + AtkObject *popover_accessible; + + popover_accessible = gtk_widget_get_accessible (GTK_WIDGET (popover)); + + if (strcmp (g_param_spec_get_name (pspec), "relative-to") == 0) + popover_update_relative_to (popover_accessible, popover); + else if (strcmp (g_param_spec_get_name (pspec), "modal") == 0) + popover_update_modality (popover_accessible, popover); +} + +static void +gtk_popover_accessible_initialize (AtkObject *obj, + gpointer data) +{ + GtkPopover *popover; + AtkObject *parent; + + ATK_OBJECT_CLASS (gtk_popover_accessible_parent_class)->initialize (obj, data); + + popover = GTK_POPOVER (data); + + parent = gtk_widget_get_accessible (gtk_popover_get_relative_to (popover)); + + if (parent) + atk_object_set_parent (obj, parent); + + g_signal_connect (popover, "notify", + G_CALLBACK (popover_notify_cb), obj); + popover_update_relative_to (obj, popover); + popover_update_modality (obj, popover); + + obj->role = ATK_ROLE_PANEL; +} + +static AtkStateSet * +gtk_popover_accessible_ref_state_set (AtkObject *obj) +{ + AtkStateSet *state_set; + GtkWidget *widget; + + state_set = ATK_OBJECT_CLASS (gtk_popover_accessible_parent_class)->ref_state_set (obj); + widget = gtk_accessible_get_widget (GTK_ACCESSIBLE (obj)); + + if (gtk_popover_get_modal (GTK_POPOVER (widget))) + atk_state_set_add_state (state_set, ATK_STATE_MODAL); + + return state_set; +} + +static void +gtk_popover_accessible_finalize (GObject *object) +{ + GtkPopoverAccessiblePrivate *priv; + + priv = gtk_popover_accessible_get_instance_private (GTK_POPOVER_ACCESSIBLE (object)); + + if (priv->widget) + g_object_remove_weak_pointer (G_OBJECT (priv->widget), + (gpointer*) &priv->widget); + G_OBJECT_CLASS (gtk_popover_accessible_parent_class)->finalize (object); +} + +static void +gtk_popover_accessible_class_init (GtkPopoverAccessibleClass *klass) +{ + AtkObjectClass *class = ATK_OBJECT_CLASS (klass); + GObjectClass *object_class = G_OBJECT_CLASS (klass); + + object_class->finalize = gtk_popover_accessible_finalize; + class->initialize = gtk_popover_accessible_initialize; + class->ref_state_set = gtk_popover_accessible_ref_state_set; +} + +static void +gtk_popover_accessible_init (GtkPopoverAccessible *popover) +{ +} diff --git a/gtk/a11y/gtkpopoveraccessible.h b/gtk/a11y/gtkpopoveraccessible.h new file mode 100644 index 0000000000..8dcbd34fa6 --- /dev/null +++ b/gtk/a11y/gtkpopoveraccessible.h @@ -0,0 +1,56 @@ +/* GTK - The GIMP Toolkit + * Copyright © 2014 Red Hat Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see . + * + * Author: Carlos Garnacho + */ + +#ifndef __GTK_POPOVER_ACCESSIBLE_H__ +#define __GTK_POPOVER_ACCESSIBLE_H__ + +#if !defined (__GTK_A11Y_H_INSIDE__) && !defined (GTK_COMPILATION) +#error "Only can be included directly." +#endif + +#include + +G_BEGIN_DECLS + +#define GTK_TYPE_POPOVER_ACCESSIBLE (gtk_popover_accessible_get_type ()) +#define GTK_POPOVER_ACCESSIBLE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GTK_TYPE_POPOVER_ACCESSIBLE, GtkPopoverAccessible)) +#define GTK_POPOVER_ACCESSIBLE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GTK_TYPE_POPOVER_ACCESSIBLE, GtkPopoverAccessibleClass)) +#define GTK_IS_POPOVER_ACCESSIBLE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GTK_TYPE_POPOVER_ACCESSIBLE)) +#define GTK_IS_POPOVER_ACCESSIBLE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GTK_TYPE_POPOVER_ACCESSIBLE)) +#define GTK_POPOVER_ACCESSIBLE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GTK_TYPE_POPOVER_ACCESSIBLE, GtkPopoverAccessibleClass)) + +typedef struct _GtkPopoverAccessible GtkPopoverAccessible; +typedef struct _GtkPopoverAccessibleClass GtkPopoverAccessibleClass; + +struct _GtkPopoverAccessible +{ + GtkContainerAccessible parent; +}; + +struct _GtkPopoverAccessibleClass +{ + GtkContainerAccessibleClass parent_class; +}; + +GDK_AVAILABLE_IN_3_12 +GType gtk_popover_accessible_get_type (void); + +G_END_DECLS + +#endif /* __GTK_POPOVER_ACCESSIBLE_H__ */ diff --git a/gtk/gtk-a11y.h b/gtk/gtk-a11y.h index 6be98e6c71..9718f2b8df 100644 --- a/gtk/gtk-a11y.h +++ b/gtk/gtk-a11y.h @@ -57,6 +57,7 @@ #include #include #include +#include #include #include #include diff --git a/gtk/gtkpopover.c b/gtk/gtkpopover.c index a5ed37754f..0112f39ec1 100644 --- a/gtk/gtkpopover.c +++ b/gtk/gtkpopover.c @@ -61,6 +61,7 @@ #include "gtkmenutracker.h" #include "gtkstack.h" #include "gtksizegroup.h" +#include "a11y/gtkpopoveraccessible.h" #define TAIL_GAP_WIDTH 24 #define TAIL_HEIGHT 12 @@ -1346,6 +1347,7 @@ gtk_popover_class_init (GtkPopoverClass *klass) G_TYPE_NONE, 0); quark_widget_popovers = g_quark_from_static_string ("gtk-quark-widget-popovers"); + gtk_widget_class_set_accessible_type (widget_class, GTK_TYPE_POPOVER_ACCESSIBLE); } static void