Re: [g-a-devel] Interfacing a non-GTK application with AT-SPI
- From: Daniel Drake <ddrake brontes3d com>
- To: Rodney Dawes <dobey novell com>
- Cc: gnome-accessibility-devel gnome org
- Subject: Re: [g-a-devel] Interfacing a non-GTK application with AT-SPI
- Date: Mon, 18 Dec 2006 11:50:43 -0500
On Mon, 2006-12-18 at 11:22 -0500, Rodney Dawes wrote:
> Are these straight GObjects that don't require a display? I had a
> thought this past week, about writing some regression tests for LDTP
> itself, to make sure that all the bits of the protocol between the
> client/server portions are still working, and all that. Ideally, this
> would not require an X display. If what you've done is along those
> lines, it might be a good place for us to start.
Here is my prototype app - I hope you find it useful. It includes some
hacks but served as a good introduction to Atk, and it does work
(registers a button which you can click through dogtail's at-spi
browser).
Run with:
GTK_MODULES=atk-bridge ./main
--
Daniel Drake
Brontes Technologies, A 3M Company
#include <gtk/gtk.h>
GType acsample_widget_get_type();
GType acsample_accessible_factory_get_type();
GType acsample_accessible_get_type();
/***** CUSTOM WIDGET TYPE *****/
#define ACSAMPLE_WIDGET_TYPE (acsample_widget_get_type())
#define ACSAMPLE_IS_WIDGET(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), ACSAMPLE_WIDGET_TYPE))
#define ACSAMPLE_WIDGET(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), ACSAMPLE_WIDGET_TYPE, AcsampleWidget))
typedef struct
{
GObject parent;
} AcsampleWidget;
typedef struct
{
GObjectClass parent_class;
} AcsampleWidgetClass;
GObject *acsample_widget_new()
{
return g_object_new(ACSAMPLE_WIDGET_TYPE, NULL);
}
GType acsample_widget_get_type()
{
static GType type = 0;
if (!type) {
static const GTypeInfo tinfo = {
sizeof(AcsampleWidgetClass),
(GBaseInitFunc) NULL,
(GBaseFinalizeFunc) NULL,
(GClassInitFunc) NULL,
(GClassFinalizeFunc) NULL,
NULL,
sizeof(AcsampleWidget),
0,
(GInstanceInitFunc) NULL,
NULL
};
type = g_type_register_static(G_TYPE_OBJECT, "AcsampleWidget", &tinfo,
0);
}
return type;
}
/***** ACCESSIBLE OBJECT FOR CUSTOM WIDGET *****/
static AtkGObjectAccessibleClass *goa_parent_class = NULL;
#define ACSAMPLE_ACCESSIBLE_TYPE (acsample_accessible_get_type())
#define ACSAMPLE_ACCESSIBLE(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), ACSAMPLE_ACCESSIBLE_TYPE, AcsampleAccessible))
typedef struct
{
AtkGObjectAccessible parent;
AtkObject *achild;
AtkObject *aparent;
} AcsampleAccessible;
typedef struct
{
AtkGObjectAccessibleClass parent_class;
} AcsampleAccessibleClass;
static void acsample_accessible_real_initialize(AtkObject *obj, gpointer data)
{
ATK_OBJECT_CLASS(goa_parent_class)->initialize(obj, data);
obj->role = ATK_ROLE_PUSH_BUTTON;
}
static int acsample_accessible_get_n_children(AtkObject *obj)
{
AcsampleAccessible *a = ACSAMPLE_ACCESSIBLE(obj);
if (a->achild == NULL)
return 0;
else
return 1;
}
static AtkObject *acsample_accessible_ref_child(AtkObject *obj, gint i)
{
AcsampleAccessible *a;
GtkWidget *widget;
AtkObject *atk_obj;
a = ACSAMPLE_ACCESSIBLE(obj);
atk_obj = a->achild;
if (atk_obj)
g_object_ref(atk_obj);
return atk_obj;
}
static void
acsample_accessible_class_init(AcsampleAccessibleClass *klass)
{
AtkObjectClass *class = ATK_OBJECT_CLASS(klass);
goa_parent_class = g_type_class_peek_parent(klass);
class->initialize = acsample_accessible_real_initialize;
class->get_n_children = acsample_accessible_get_n_children;
class->ref_child = acsample_accessible_ref_child;
g_signal_new("create", G_TYPE_FROM_CLASS(klass), G_SIGNAL_RUN_LAST,
0, /* default signal handler */
NULL, NULL, g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0);
}
static gboolean acsample_accessible_do_action(AtkAction *action, gint i)
{
printf("DO ACTION!!\n");
}
static gint acsample_accessible_get_n_actions(AtkAction *action)
{
return 1;
}
static G_CONST_RETURN gchar *acsample_accessible_action_get_name(
AtkAction *action, gint i)
{
return "click";
}
static void
acsample_accessible_action_interface_init(AtkActionIface *aiface)
{
aiface->do_action = acsample_accessible_do_action;
aiface->get_n_actions = acsample_accessible_get_n_actions;
aiface->get_name = acsample_accessible_action_get_name;
}
GType acsample_accessible_get_type()
{
static GType type = 0;
if (!type) {
static const GTypeInfo tinfo = {
sizeof(AcsampleAccessibleClass),
(GBaseInitFunc) NULL,
(GBaseFinalizeFunc) NULL,
(GClassInitFunc) acsample_accessible_class_init,
(GClassFinalizeFunc) NULL,
NULL,
sizeof(AcsampleAccessible),
0,
(GInstanceInitFunc) NULL,
NULL /* value table */
};
static const GInterfaceInfo atk_action_info =
{
(GInterfaceInitFunc) acsample_accessible_action_interface_init,
(GInterfaceFinalizeFunc) NULL,
NULL
};
static const GInterfaceInfo atk_text_info = {
(GInterfaceInitFunc) acsample_accessible_text_interface_init,
(GInterfaceFinalizeFunc) NULL,
NULL
};
type = g_type_register_static(ATK_TYPE_GOBJECT_ACCESSIBLE,
"AcsampleAccessible", &tinfo, 0);
g_type_add_interface_static(type, ATK_TYPE_ACTION, &atk_action_info);
}
return type;
}
AtkObject *acsample_accessible_new(GObject *obj)
{
gpointer object;
AtkObject *atk_object;
object = g_object_new(ACSAMPLE_ACCESSIBLE_TYPE, NULL);
atk_object = ATK_OBJECT(object);
atk_object_initialize(atk_object, obj);
return atk_object;
}
/***** ACCESSIBLE OBJECT FACTORY TYPE *****/
#define ACSAMPLE_ACCESSIBLE_FACTORY_TYPE (acsample_accessible_factory_get_type())
typedef struct
{
AtkObjectFactory parent;
} AcsampleAccessibleFactory;
typedef struct
{
AtkObjectFactoryClass parent_class;
} AcsampleAccessibleFactoryClass;
GObject *acsample_accessible_factory_new()
{
return g_object_new(ACSAMPLE_ACCESSIBLE_FACTORY_TYPE, NULL);
}
static AtkObject *acsample_accessible_factory_create_accessible(GObject *obj)
{
printf("creating accessible\n");
return acsample_accessible_new(obj);
}
static GType acsample_accessible_factory_get_accessible_type()
{
return ACSAMPLE_ACCESSIBLE_TYPE;
}
static void acsample_accessible_factory_class_init(AcsampleAccessibleFactoryClass *klass)
{
AtkObjectFactoryClass *class = ATK_OBJECT_FACTORY_CLASS(klass);
class->create_accessible = acsample_accessible_factory_create_accessible;
class->get_accessible_type = acsample_accessible_factory_get_accessible_type;
}
GType acsample_accessible_factory_get_type()
{
static GType type = 0;
if (!type) {
static const GTypeInfo tinfo = {
sizeof(AcsampleAccessibleFactoryClass),
(GBaseInitFunc) NULL,
(GBaseFinalizeFunc) NULL,
(GClassInitFunc) acsample_accessible_factory_class_init,
(GClassFinalizeFunc) NULL,
NULL,
sizeof(AcsampleAccessibleFactory),
0,
(GInstanceInitFunc) NULL,
NULL
};
type = g_type_register_static(ATK_TYPE_OBJECT_FACTORY,
"AcsampleAccessibleFactory" , &tinfo, 0);
}
return type;
}
/***** UTIL CLASS *****/
#define ACSAMPLE_UTIL_TYPE (acsample_util_get_type())
static AtkObject *util_root;
typedef struct
{
AtkUtil parent;
} AcsampleUtil;
typedef struct
{
AtkUtilClass parent_class;
} AcsampleUtilClass;
static AtkObject *acsample_util_get_root()
{
if (util_root == NULL) {
util_root = g_object_new(ACSAMPLE_ACCESSIBLE_TYPE, NULL);
util_root->role = ATK_ROLE_APPLICATION;
util_root->name = g_get_prgname();
util_root->accessible_parent = NULL;
}
return util_root;
}
static int get_signal_id(const char *name, char *type, char *signal)
{
GType gtype;
guint sig;
gtype = g_type_from_name(type);
if (gtype == 0) {
printf("unrecognized type %s\n", type);
return;
}
sig = g_signal_lookup(signal, gtype);
if (sig == 0) {
printf("unrecognized signal %s\n", signal);
}
return sig;
}
static guint acsample_util_add_global_event_listener(
GSignalEmissionHook listener, const gchar* event_type)
{
gchar **split = NULL;
GType type;
guint sig;
printf("ADD GLOBAL EVENT LISTENER %s\n");
split = g_strsplit(event_type, ":", 3);
if (strcmp(split[0], "window") == 0)
sig = get_signal_id(event_type, "AcsampleAccessible", split[1]);
else
sig = get_signal_id(event_type, split[1], split[2]);
if (sig > 0) {
g_signal_add_emission_hook(sig, 0, listener, g_strdup(event_type),
g_free);
printf("added\n");
}
g_strfreev(split);
}
static G_CONST_RETURN gchar *acsample_util_get_toolkit_name()
{
return "ACSAMPLE";
}
static void acsample_util_class_init(AcsampleUtilClass *klass)
{
gpointer data = g_type_class_peek(ATK_TYPE_UTIL);
AtkUtilClass *atk_class = ATK_UTIL_CLASS(data);
// Must be loaded before add_global_event_listener is called
g_type_class_unref(g_type_class_ref(ACSAMPLE_WIDGET_TYPE));
atk_class->add_global_event_listener = acsample_util_add_global_event_listener;
atk_class->get_root = acsample_util_get_root;
atk_class->get_toolkit_name = acsample_util_get_toolkit_name;
}
GType acsample_util_get_type()
{
static GType type = 0;
if (!type) {
static const GTypeInfo tinfo = {
sizeof(AcsampleUtilClass),
(GBaseInitFunc) NULL,
(GBaseFinalizeFunc) NULL,
(GClassInitFunc) acsample_util_class_init,
(GClassFinalizeFunc) NULL,
NULL,
sizeof(AcsampleUtil),
0,
(GInstanceInitFunc) NULL,
NULL
};
type = g_type_register_static(ATK_TYPE_UTIL,
"AcsampleUtil", &tinfo, 0);
}
return type;
}
int main(int argc, char **argv)
{
GObject *widget;
GObject *factory;
GObject *window;
AtkRegistry *registry;
AtkObject *ao, *root;
g_type_init();
g_type_class_unref(g_type_class_ref(ACSAMPLE_UTIL_TYPE));
gtk_init(&argc, &argv);
registry = atk_get_default_registry();
atk_registry_set_factory_type(registry, ACSAMPLE_ACCESSIBLE_TYPE,
ACSAMPLE_ACCESSIBLE_FACTORY_TYPE);
printf("ATK toolkit: %s\n", atk_get_toolkit_name());
root = atk_get_root();
widget = acsample_widget_new();
factory = acsample_accessible_factory_new();
ao = atk_object_factory_create_accessible(ATK_OBJECT_FACTORY(factory), widget);
atk_object_set_name(ao, "my widget");
atk_object_set_parent(ao, atk_get_root());
ACSAMPLE_ACCESSIBLE(root)->achild = ao;
g_signal_emit_by_name(atk_get_root(), "children_changed::add", 0, ao,
NULL);
g_signal_emit_by_name(atk_get_root(), "create", NULL);
atk_object_notify_state_change(ao, ATK_STATE_VISIBLE, 1);
printf("entering main loop\n");
gtk_main();
}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]