[g-a-devel]first cut at acute AtkObjectFactory brokenness workaround



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]