[g-a-devel]first cut at acute AtkObjectFactory brokenness workaround
- From: Michael Meeks <michael ximian com>
- To: Bill Haneman <bill haneman sun com>
- Cc: accessibility mailing list <gnome-accessibility-devel gnome org>, Tim Janik <timj gtk org>
- Subject: [g-a-devel]first cut at acute AtkObjectFactory brokenness workaround
- Date: 21 Mar 2002 14:09:40 +0000
So,
Please find attached my first cut at a 'solution' - yes it's ugly - but
significantly less ugly than what's there currently. I'll be testing it
out inside libbonoboui - but I'd very much like to move it to gail [
with appropriate release team API addition approval ] and also provide a
simpler API for sub-classing existing Gail classes [ as this will be
used in a good number of places ].
Clearly this doesn't fix the underlying problem - perhaps the best way
to do that is by binning AtkObjectFactory in Gtk+ 2.2 and having
AtkObjectFactoryWorks (or sim.) that replaces it. Alternatively, we
could use the 2 extra spare pointers on the class structure - or
feasibly we could do some nice function casting magic - to allow
ourselves to pass the AtkFactoryObject * as a (hidden) 2nd / 1st
parameter of the methods. All of those approaches suck, but less than
leaving it broken, inefficient and hard to maintain.
So - here is the patch, untested - comments appreciated. NB. if we fold
this into Gail we can kill ~4500 line of cut and paste mess.
Regards,
Michael.
/**
* Bonobo accessibility wrappers
*
* Author:
* Michael Meeks (michael ximian com)
*
* Copyright 2002 Sun Microsystems, Inc.
*/
#ifndef _BONOBO_A11Y_H_
#define _BONOBO_A11Y_H_
#include <glib-object.h>
void bonobo_a11y_clobber_atk_junk_code (void);
void bonobo_a11y_register_type_for (GType atk_object_type,
GType gtk_widget_type);
#endif /* _BONOBO_A11Y_H_ */
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
/**
* Bonobo accessibility wrappers
*
* FIXME: this implementation sucks almost as badly
* as the AtkObjectFactory design does.
*
* Author:
* Michael Meeks (michael ximian com)
*
* Copyright 2002 Sun Microsystems, Inc.
*/
#include <bonobo-a11y.h>
#include <atk/atkobjectfactory.h>
#include <gtk/gtkwidget.h>
typedef AtkObject * (*BonoboA11YGetAccessible) (GtkWidget *widget);
/* To chain to parent get_accessibles methods */
static GHashTable *chain_hash = NULL;
/* To map a11y types to GtkWidget types */
static GHashTable *type_hash = NULL;
static AtkObject *
bonobo_a11y_get_accessible (GtkWidget *widget)
{
AtkObject *accessible;
static GQuark quark_accessible_object = 0;
if (!quark_accessible_object)
quark_accessible_object = g_quark_from_static_string (
"gtk-accessible-object");
accessible = g_object_get_qdata (G_OBJECT (widget),
quark_accessible_object);
if (!accessible) {
GType t;
t = (GType) g_hash_table_lookup (
type_hash, (gpointer) G_TYPE_FROM_INSTANCE (widget));
if (t) {
accessible = g_object_new (t, NULL);
atk_object_initialize (accessible, widget);
g_object_set_qdata (G_OBJECT (widget),
quark_accessible_object,
accessible);
} else {
BonoboA11YGetAccessible parent_impl_fn;
parent_impl_fn = g_hash_table_lookup (
chain_hash, (gpointer) G_TYPE_FROM_INSTANCE (widget));
if (!parent_impl_fn)
g_error ("Serious chain hash error '%s'",
g_type_name_from_instance (
(GTypeInstance *) widget));
else
accessible = parent_impl_fn (widget);
}
}
return accessible;
}
static void
recursive_a11y_clobber (GType type)
{
guint n_children, i;
GType *children;
GtkWidgetClass *w_class;
w_class = g_type_class_peek (type);
if (!w_class)
/* not instantiated yet, no problems */
return;
g_hash_table_insert (chain_hash, (gpointer) type,
w_class->get_accessible);
w_class->get_accessible = bonobo_a11y_get_accessible;
children = g_type_children (type, &n_children);
for (i = 0; i < n_children; i++)
recursive_a11y_clobber (children [i]);
}
/**
* bonobo_a11y_clobber_atk_junk_code:
* @void:
*
* It seems the only way to work around the acute
* lack of forethought is to clobber everything
* derived from GtkWidget so it can't hurt us.
**/
void
bonobo_a11y_clobber_atk_junk_code (void)
{
GType widget_type;
if (type_hash)
return;
type_hash = g_hash_table_new (NULL, NULL);
chain_hash = g_hash_table_new (NULL, NULL);
widget_type = gtk_widget_get_type ();
/*
* Leak this - but we need to keep that
* instantiated, since we don't want it
* re-constructed with the original method
*/
g_type_class_ref (widget_type);
recursive_a11y_clobber (widget_type);
}
void
bonobo_a11y_register_type_for (GType atk_object_type,
GType gtk_widget_type)
{
g_return_if_fail (type_hash != NULL);
g_hash_table_insert (type_hash,
(gpointer) atk_object_type,
(gpointer) gtk_widget_type);
}
--
mmeeks gnu org <><, Pseudo Engineer, itinerant idiot
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]