Index: gtk3/gtk/a11y/Makefile.inc =================================================================== --- gtk3.orig/gtk/a11y/Makefile.inc +++ gtk3/gtk/a11y/Makefile.inc @@ -30,6 +30,7 @@ a11y_h_sources = \ a11y/gtknotebookaccessible.h \ a11y/gtknotebookpageaccessible.h \ a11y/gtkpanedaccessible.h \ + a11y/gtkplugaccessible.h \ a11y/gtkpopoveraccessible.h \ a11y/gtkprogressbaraccessible.h \ a11y/gtkradiobuttonaccessible.h \ @@ -39,6 +40,7 @@ a11y_h_sources = \ a11y/gtkscaleaccessible.h \ a11y/gtkscalebuttonaccessible.h \ a11y/gtkscrolledwindowaccessible.h \ + a11y/gtksocketaccessible.h \ a11y/gtkspinbuttonaccessible.h \ a11y/gtkspinneraccessible.h \ a11y/gtkstatusbaraccessible.h \ @@ -104,6 +106,7 @@ a11y_c_sources = \ a11y/gtknotebookaccessible.c \ a11y/gtknotebookpageaccessible.c \ a11y/gtkpanedaccessible.c \ + a11y/gtkplugaccessible.c \ a11y/gtkpopoveraccessible.c \ a11y/gtkprogressbaraccessible.c \ a11y/gtkradiobuttonaccessible.c \ @@ -113,6 +116,7 @@ a11y_c_sources = \ a11y/gtkscaleaccessible.c \ a11y/gtkscalebuttonaccessible.c \ a11y/gtkscrolledwindowaccessible.c \ + a11y/gtksocketaccessible.c \ a11y/gtkspinbuttonaccessible.c \ a11y/gtkspinneraccessible.c \ a11y/gtkstatusbaraccessible.c \ Index: gtk3/gtk/gtk-a11y.h =================================================================== --- gtk3.orig/gtk/gtk-a11y.h +++ gtk3/gtk/gtk-a11y.h @@ -57,6 +57,7 @@ #include #include #include +#include #include #include #include @@ -67,6 +68,7 @@ #include #include #include +#include #include #include #include Index: gtk3/gtk/a11y/gtkplugaccessible.c =================================================================== --- /dev/null +++ gtk3/gtk/a11y/gtkplugaccessible.c @@ -0,0 +1,172 @@ +/* GTK+ - accessibility implementations + * Copyright 2019 Samuel Thibault + * + * 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 . + */ + +#include "config.h" + +#include +#include "gtkplugaccessible.h" + +/* We can not make GtkPlugAccessible inherit both from GtkContainerAccessible + * and GtkPlug, so we make it the atk child of an AtkPlug */ + +#ifndef HAVE_ATK_PLUG_NEW_CHILD + +// This could be stuffed into AtkPlug? + +#define ATK_TYPE_PLUG_EXT atk_plug_ext_get_type () +#define ATK_PLUG_EXT(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), ATK_TYPE_PLUG_EXT_PLUG, AtkPlugExt)) + +GType atk_plug_ext_get_type (void); + +typedef struct _AtkPlugExt AtkPlugExt; +typedef struct _AtkPlugExtClass AtkPlugExtClass; + +AtkObject *atk_plug_ext_new (AtkObject *child); + + + + +struct _AtkPlugExt +{ + AtkPlug parent; + + // Private actually + AtkObject *child; +}; + +struct _AtkPlugExtClass +{ + AtkPlugClass parent_class; +}; + +G_DEFINE_TYPE (AtkPlugExt, atk_plug_ext, ATK_TYPE_PLUG) + +static AtkObject* +atk_plug_ext_ref_child (AtkObject *obj, int i) +{ + AtkObject *child; + + if (i != 0) + return NULL; + + child = ATK_PLUG_EXT (obj)->child; + + if (child == NULL) + return NULL; + + return g_object_ref (child); +} + +static int +atk_plug_ext_get_n_children (AtkObject *obj) +{ + if (ATK_PLUG_EXT (obj)->child == NULL) + return 0; + + return 1; +} + +static AtkStateSet* +atk_plug_ext_ref_state_set (AtkObject *object) +{ + AtkObject *child = ATK_PLUG_EXT (object)->child; + + if (child == NULL) + return NULL; + + return atk_object_ref_state_set (child); +} + + +static void +atk_plug_ext_class_init (AtkPlugExtClass *klass) +{ + AtkObjectClass *class = ATK_OBJECT_CLASS (klass); + + class->get_n_children = atk_plug_ext_get_n_children; + class->ref_child = atk_plug_ext_ref_child; + class->ref_state_set = atk_plug_ext_ref_state_set; +} + +static void +atk_plug_ext_init (AtkPlugExt *plug) { +} + +AtkObject *atk_plug_ext_new_child (AtkObject *child) +{ + AtkPlugExt *accessible; + + accessible = g_object_new (ATK_TYPE_PLUG_EXT, NULL); + + accessible->child = child; + atk_object_set_parent (child, ATK_OBJECT (accessible)); + + return ATK_OBJECT (accessible); +} +#define atk_plug_new_child(child) atk_plug_ext_new_child(child) +#endif + + + +struct _GtkPlugAccessiblePrivate +{ + AtkObject *accessible_plug; +}; + +G_DEFINE_TYPE_WITH_CODE (GtkPlugAccessible, gtk_plug_accessible, GTK_TYPE_WINDOW_ACCESSIBLE, + G_ADD_PRIVATE (GtkPlugAccessible)) + + +static void +gtk_plug_accessible_finalize (GObject *object) +{ + GtkPlugAccessible *plug = GTK_PLUG_ACCESSIBLE (object); + GtkPlugAccessiblePrivate *priv = plug->priv; + + g_clear_object (&priv->accessible_plug); + + G_OBJECT_CLASS (gtk_plug_accessible_parent_class)->finalize (object); +} + +static void +gtk_plug_accessible_initialize (AtkObject *plug, gpointer data) +{ + ATK_OBJECT_CLASS (gtk_plug_accessible_parent_class)->initialize (plug, data); + + GTK_PLUG_ACCESSIBLE (plug)->priv->accessible_plug = atk_plug_ext_new_child (plug); +} + +static void +gtk_plug_accessible_class_init (GtkPlugAccessibleClass *klass) { + AtkObjectClass *atk_class = ATK_OBJECT_CLASS (klass); + GObjectClass *gobject_class = G_OBJECT_CLASS (klass); + + atk_class->initialize = gtk_plug_accessible_initialize; + gobject_class->finalize = gtk_plug_accessible_finalize; +} + +static void +gtk_plug_accessible_init (GtkPlugAccessible *plug) +{ + plug->priv = gtk_plug_accessible_get_instance_private (plug); +} + +gchar * +gtk_plug_accessible_get_id (GtkPlugAccessible *plug) +{ + return atk_plug_get_id (ATK_PLUG (plug->priv->accessible_plug)); +} Index: gtk3/gtk/a11y/gtkplugaccessible.h =================================================================== --- /dev/null +++ gtk3/gtk/a11y/gtkplugaccessible.h @@ -0,0 +1,60 @@ +/* GTK+ - accessibility implementations + * Copyright 2019 Samuel Thibault + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library. If not, see . + */ + +#ifndef __GTK_PLUG_ACCESSIBLE_H__ +#define __GTK_PLUG_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_PLUG_ACCESSIBLE (gtk_plug_accessible_get_type ()) +#define GTK_PLUG_ACCESSIBLE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GTK_TYPE_PLUG_ACCESSIBLE, GtkPlugAccessible)) +#define GTK_PLUG_ACCESSIBLE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GTK_TYPE_PLUG_ACCESSIBLE, GtkPlugAccessibleClass)) +#define GTK_IS_PLUG_ACCESSIBLE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GTK_TYPE_PLUG_ACCESSIBLE)) +#define GTK_IS_PLUG_ACCESSIBLE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GTK_TYPE_PLUG_ACCESSIBLE)) +#define GTK_PLUG_ACCESSIBLE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GTK_TYPE_PLUG_ACCESSIBLE, GtkPlugAccessibleClass)) + +typedef struct _GtkPlugAccessible GtkPlugAccessible; +typedef struct _GtkPlugAccessibleClass GtkPlugAccessibleClass; +typedef struct _GtkPlugAccessiblePrivate GtkPlugAccessiblePrivate; + +struct _GtkPlugAccessible +{ + GtkWindowAccessible parent; + + GtkPlugAccessiblePrivate *priv; +}; + +struct _GtkPlugAccessibleClass +{ + GtkWindowAccessibleClass parent_class; +}; + +GDK_AVAILABLE_IN_ALL +GType gtk_plug_accessible_get_type (void); + +GDK_AVAILABLE_IN_ALL +gchar *gtk_plug_accessible_get_id (GtkPlugAccessible *plug); + +G_END_DECLS + +#endif /* __GTK_PLUG_ACCESSIBLE_H__ */ Index: gtk3/gtk/a11y/gtksocketaccessible.c =================================================================== --- /dev/null +++ gtk3/gtk/a11y/gtksocketaccessible.c @@ -0,0 +1,102 @@ +/* GTK+ - accessibility implementations + * Copyright 2019 Samuel Thibault + * + * 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 . + */ + +#include "config.h" + +#include +#include "gtksocketaccessible.h" + +/* We can not make GtkSocketAccessible inherit both from GtkContainerAccessible + * and GtkSocket, so we make it the atk parent of an AtkSocket */ + +struct _GtkSocketAccessiblePrivate +{ + AtkObject *accessible_socket; +}; + +G_DEFINE_TYPE_WITH_CODE (GtkSocketAccessible, gtk_socket_accessible, GTK_TYPE_CONTAINER_ACCESSIBLE, + G_ADD_PRIVATE (GtkSocketAccessible)) + +static AtkObject* +gtk_socket_accessible_ref_child (AtkObject *obj, int i) +{ + GtkSocketAccessible *socket = GTK_SOCKET_ACCESSIBLE (obj); + + if (i != 0) + return NULL; + + return g_object_ref (socket->priv->accessible_socket); +} + +static int +gtk_socket_accessible_get_n_children (AtkObject *obj) +{ + return 1; +} + +static void +gtk_socket_accessible_finalize (GObject *object) +{ + GtkSocketAccessible *socket = GTK_SOCKET_ACCESSIBLE (object); + GtkSocketAccessiblePrivate *priv = socket->priv; + + g_clear_object (&priv->accessible_socket); + + G_OBJECT_CLASS (gtk_socket_accessible_parent_class)->finalize (object); +} + +static void +gtk_socket_accessible_initialize (AtkObject *socket, gpointer data) +{ + AtkObject *atk_socket; + + ATK_OBJECT_CLASS (gtk_socket_accessible_parent_class)->initialize (socket, data); + + atk_socket = atk_socket_new (); + + GTK_SOCKET_ACCESSIBLE(socket)->priv->accessible_socket = atk_socket; + atk_object_set_parent (atk_socket, socket); +} + +static void +gtk_socket_accessible_class_init (GtkSocketAccessibleClass *klass) +{ + GtkContainerAccessibleClass *container_class = (GtkContainerAccessibleClass*)klass; + AtkObjectClass *atk_class = ATK_OBJECT_CLASS (klass); + GObjectClass *gobject_class = G_OBJECT_CLASS (klass); + + container_class->add_gtk = NULL; + container_class->remove_gtk = NULL; + + atk_class->initialize = gtk_socket_accessible_initialize; + atk_class->get_n_children = gtk_socket_accessible_get_n_children; + atk_class->ref_child = gtk_socket_accessible_ref_child; + + gobject_class->finalize = gtk_socket_accessible_finalize; +} + +static void +gtk_socket_accessible_init (GtkSocketAccessible *socket) +{ + socket->priv = gtk_socket_accessible_get_instance_private (socket); +} + +void +gtk_socket_accessible_embed (GtkSocketAccessible *socket, gchar *path) +{ + atk_socket_embed (ATK_SOCKET (socket->priv->accessible_socket), path); +} Index: gtk3/gtk/a11y/gtksocketaccessible.h =================================================================== --- /dev/null +++ gtk3/gtk/a11y/gtksocketaccessible.h @@ -0,0 +1,60 @@ +/* GTK+ - accessibility implementations + * Copyright 2019 Samuel Thibault + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library. If not, see . + */ + +#ifndef __GTK_SOCKET_ACCESSIBLE_H__ +#define __GTK_SOCKET_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_SOCKET_ACCESSIBLE (gtk_socket_accessible_get_type ()) +#define GTK_SOCKET_ACCESSIBLE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GTK_TYPE_SOCKET_ACCESSIBLE, GtkSocketAccessible)) +#define GTK_SOCKET_ACCESSIBLE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GTK_TYPE_SOCKET_ACCESSIBLE, GtkSocketAccessibleClass)) +#define GTK_IS_SOCKET_ACCESSIBLE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GTK_TYPE_SOCKET_ACCESSIBLE)) +#define GTK_IS_SOCKET_ACCESSIBLE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GTK_TYPE_SOCKET_ACCESSIBLE)) +#define GTK_SOCKET_ACCESSIBLE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GTK_TYPE_SOCKET_ACCESSIBLE, GtkSocketAccessibleClass)) + +typedef struct _GtkSocketAccessible GtkSocketAccessible; +typedef struct _GtkSocketAccessibleClass GtkSocketAccessibleClass; +typedef struct _GtkSocketAccessiblePrivate GtkSocketAccessiblePrivate; + +struct _GtkSocketAccessible +{ + GtkContainerAccessible parent; + + GtkSocketAccessiblePrivate *priv; +}; + +struct _GtkSocketAccessibleClass +{ + GtkContainerAccessibleClass parent_class; +}; + +GDK_AVAILABLE_IN_ALL +GType gtk_socket_accessible_get_type (void); + +GDK_AVAILABLE_IN_ALL +void gtk_socket_accessible_embed (GtkSocketAccessible *socket, gchar *path); + +G_END_DECLS + +#endif /* __GTK_SOCKET_ACCESSIBLE_H__ */ Index: gtk3/gtk/gtkplug.c =================================================================== --- gtk3.orig/gtk/gtkplug.c +++ gtk3/gtk/gtkplug.c @@ -39,6 +39,8 @@ #include "gtkwindowprivate.h" #include "gtkxembed.h" +#include "a11y/gtkplugaccessible.h" + #include /** @@ -227,6 +229,8 @@ gtk_plug_class_init (GtkPlugClass *class NULL, NULL, NULL, G_TYPE_NONE, 0); + + gtk_widget_class_set_accessible_type (widget_class, GTK_TYPE_PLUG_ACCESSIBLE); } static void @@ -710,6 +714,24 @@ xembed_set_info (GdkWindow *window, (unsigned char *)buffer, 2); } +static void +_gtk_plug_accessible_embed_set_info (GtkWidget *widget, GdkWindow *window) +{ + GdkDisplay *display = gdk_window_get_display (window); + gchar *buffer = gtk_plug_accessible_get_id (GTK_PLUG_ACCESSIBLE (gtk_widget_get_accessible (widget))); + Atom net_at_spi_path_atom = gdk_x11_get_xatom_by_name_for_display (display, "_XEMBED_AT_SPI_PATH"); + + if (!buffer) + return; + + XChangeProperty (GDK_DISPLAY_XDISPLAY (display), + GDK_WINDOW_XID (window), + net_at_spi_path_atom, net_at_spi_path_atom, 8, + PropModeReplace, + (unsigned char *)buffer, strlen(buffer)); + g_free (buffer); +} + /** * gtk_plug_focus_first_last: * @plug: a #GtkPlug @@ -1097,6 +1119,8 @@ gtk_plug_realize (GtkWidget *widget) } gtk_widget_register_window (widget, gdk_window); + + _gtk_plug_accessible_embed_set_info (widget, gdk_window); } static void Index: gtk3/gtk/gtksocket.c =================================================================== --- gtk3.orig/gtk/gtksocket.c +++ gtk3/gtk/gtksocket.c @@ -51,6 +51,8 @@ #include "gtkxembed.h" +#include "a11y/gtksocketaccessible.h" + /** * SECTION:gtksocket @@ -152,6 +154,9 @@ static gboolean xembed_get_info unsigned long *version, unsigned long *flags); +static void _gtk_socket_accessible_embed (GtkWidget *socket, + GdkWindow *window); + /* From Tk */ #define EMBEDDED_APP_WANTS_FOCUS NotifyNormal+20 @@ -264,6 +269,9 @@ gtk_socket_class_init (GtkSocketClass *c _gtk_boolean_handled_accumulator, NULL, _gtk_marshal_BOOLEAN__VOID, G_TYPE_BOOLEAN, 0); + + + gtk_widget_class_set_accessible_type (widget_class, GTK_TYPE_SOCKET_ACCESSIBLE); } static void @@ -1145,6 +1153,8 @@ G_GNUC_END_IGNORE_DEPRECATIONS socket_update_focus_in (socket); gtk_widget_queue_resize (GTK_WIDGET (socket)); + + _gtk_socket_accessible_embed (GTK_WIDGET (socket), private->plug_window); } if (private->plug_window) @@ -1368,6 +1378,58 @@ handle_xembed_message (GtkSocket } } +static void +_gtk_socket_accessible_embed (GtkWidget *socket, GdkWindow *window) +{ + GdkDisplay *display = gdk_window_get_display (window); + Atom net_at_spi_path_atom = gdk_x11_get_xatom_by_name_for_display (display, "_XEMBED_AT_SPI_PATH"); + Atom type; + int format; + unsigned long nitems, bytes_after; + unsigned char *data; + int status; + + gdk_error_trap_push (); + status = XGetWindowProperty (GDK_DISPLAY_XDISPLAY (display), + GDK_WINDOW_XID (window), + net_at_spi_path_atom, + 0, INT_MAX / 4, False, + net_at_spi_path_atom, &type, &format, + &nitems, &bytes_after, &data); + gdk_error_trap_pop_ignored (); + + if (status != Success) + return; /* Window vanished? */ + + if (type == None) /* No info property */ + return; + + if (type != net_at_spi_path_atom) + { + g_warning ("_XEMBED_AT_SPI_PATH property has wrong type"); + return; + } + + if (nitems == 0) + { + g_warning ("_XEMBED_AT_SPI_PATH too short"); + XFree (data); + return; + } + + if (nitems > INT_MAX) + { + g_warning ("_XEMBED_AT_SPI_PATH too long"); + XFree (data); + return; + } + + gtk_socket_accessible_embed (GTK_SOCKET_ACCESSIBLE (gtk_widget_get_accessible (socket)), (gchar*) data); + XFree (data); + + return; +} + static GdkFilterReturn gtk_socket_filter_func (GdkXEvent *gdk_xevent, GdkEvent *event,