Bug 173848 the Root/Application object got from an event by "get_parent" is not the same with the original Root/Application Object.

This is NOT for default build
This commit is contained in:
bolian.yin%sun.com 2002-10-24 03:06:04 +00:00
Родитель 75d069ac37
Коммит 6f7d1e2855
13 изменённых файлов: 453 добавлений и 388 удалений

Просмотреть файл

@ -41,15 +41,13 @@
#include "nsIAccessible.h"
#include "nsCOMPtr.h"
#include "nsMaiCache.h"
#include "nsMaiAppRoot.h"
MaiAppRoot::MaiAppRoot()
{
/* for mai root, mAccessible is always NULL */
mTopLevelList = NULL;
mMaiCache = new MaiCache();
NS_ASSERTION(mMaiCache, "Fail to create MaiCache");
}
MaiAppRoot::~MaiAppRoot()
@ -59,23 +57,23 @@ MaiAppRoot::~MaiAppRoot()
if (mTopLevelList) {
GList *tmp_list1, *tmp_list2;
MaiTopLevel *maiTopLevel;
guint uid;
tmp_list1 = tmp_list2 = mTopLevelList;
mTopLevelList = NULL;
#ifdef MAI_LOGGING
while (tmp_list1) {
maiTopLevel = ((TopLevelItem*)tmp_list1->data)->maiTopLevel;
uid = (guint)tmp_list1->data;
maiTopLevel = (MaiTopLevel *) MaiHashTable::Lookup(uid);
if (maiTopLevel)
MAI_LOG_DEBUG(("##toplevel=0x%x (uid=0x%x) still exist !\n",
(guint)maiTopLevel, uid));
tmp_list1 = tmp_list1->next;
g_object_unref(maiTopLevel->GetAtkObject());
}
g_list_free(tmp_list2);
mTopLevelList = NULL;
}
#endif /* #ifdef MAI_LOGGING */
if (mMaiCache) {
delete mMaiCache;
mMaiCache = NULL;
g_list_free(tmp_list2);
}
}
@ -116,107 +114,50 @@ MaiAppRoot::GetNSAccessibleUniqueID()
return 1;
}
gboolean
PRBool
MaiAppRoot::AddMaiTopLevel(MaiTopLevel *aTopLevel)
{
g_return_val_if_fail(aTopLevel != NULL, FALSE);
MAI_LOG_DEBUG(("MaiAppRoot: add MaiTopLevel = 0x%x", (guint)aTopLevel));
/* if the nsIAccessible with the same UniqueID is already added,
* we only increase the count of this item in the list.
* They are same.
*/
TopLevelItem *item = FindTopLevelItem(aTopLevel->GetNSAccessible());
if (!item) {
MAI_LOG_DEBUG(("MaiAppRoot: new item created\n"));
item = new TopLevelItem();
NS_ASSERTION(item, "Fail to create TopLevelItem");
item->ref = 0;
item->maiTopLevel = aTopLevel;
mTopLevelList = g_list_append(mTopLevelList, item);
AtkObject *atkObject = aTopLevel->GetAtkObject();
if (atkObject) {
atk_object_set_parent(atkObject, GetAtkObject());
g_object_ref(atkObject);
}
}
item->ref++;
MAI_LOG_DEBUG(("MaiAppRoot: item ref = %d\n", item->ref));
return TRUE;
}
gboolean
MaiAppRoot::RemoveMaiTopLevel(MaiTopLevel *aTopLevel)
{
g_return_val_if_fail(aTopLevel != NULL, TRUE);
MAI_LOG_DEBUG(("MaiAppRoot: remove MaiTopLevel = 0x%x", (guint)aTopLevel));
TopLevelItem *item = FindTopLevelItem(aTopLevel->GetNSAccessible());
if (!item)
return FALSE;
item->ref--;
MAI_LOG_DEBUG(("MaiAppRoot: item ref = %d\n", item->ref));
if (item->ref == 0) {
mTopLevelList = g_list_remove(mTopLevelList, item);
g_object_unref(item->maiTopLevel->GetAtkObject());
delete item;
MAI_LOG_DEBUG(("MaiAppRoot: Toplevel deleted\n"));
guint uid = aTopLevel->GetNSAccessibleUniqueID();
g_object_ref(aTopLevel->GetAtkObject());
if (!LookupTopLevelID(uid)) {
mTopLevelList = g_list_append(mTopLevelList, GINT_TO_POINTER(uid));
atk_object_set_parent(aTopLevel->GetAtkObject(), GetAtkObject());
}
return TRUE;
}
MaiTopLevel *
MaiAppRoot::FindMaiTopLevel(MaiTopLevel *aTopLevel)
PRBool
MaiAppRoot::RemoveMaiTopLevelByID(guint aID)
{
g_return_val_if_fail(aTopLevel != NULL, FALSE);
return FindMaiTopLevel(aTopLevel->GetNSAccessible());
if (!LookupTopLevelID(aID))
return PR_FALSE;
MaiTopLevel *toplevel = (MaiTopLevel *)MaiHashTable::Lookup(aID);
NS_ASSERTION(toplevel, "Fail to get object from hash table");
MAI_LOG_DEBUG(("MaiAppRoot: remove MaiTopLevel = 0x%x", (guint)toplevel));
if (!toplevel)
return PR_FALSE;
g_object_unref(toplevel->GetAtkObject());
return TRUE;
}
MaiTopLevel *
MaiAppRoot::FindMaiTopLevel(nsIAccessible *aTopLevel)
PRBool
MaiAppRoot::LookupTopLevelID(guint aID)
{
g_return_val_if_fail(aTopLevel != NULL, NULL);
TopLevelItem *item = FindTopLevelItem(aTopLevel);
if (!item)
return NULL;
return item->maiTopLevel;
}
TopLevelItem *
MaiAppRoot::FindTopLevelItem(nsIAccessible *aTopLevel)
{
g_return_val_if_fail(aTopLevel != NULL, NULL);
/* use Unique ID of nsIAccessible to judge equal */
if (mTopLevelList) {
GList *tmp_list;
TopLevelItem *item;
tmp_list = mTopLevelList;
GList *tmp_list = mTopLevelList;
while (tmp_list) {
item = (TopLevelItem*)tmp_list->data;
if (aID == (guint)(tmp_list->data))
return PR_TRUE;
tmp_list = tmp_list->next;
if (item && item->maiTopLevel &&
item->maiTopLevel->GetNSAccessibleUniqueID() ==
::GetNSAccessibleUniqueID(aTopLevel))
return item;
}
}
return NULL;
}
MaiCache *
MaiAppRoot::GetCache(void)
{
// return "NULL" will disable the caching.
return mMaiCache;
return PR_FALSE;
}
/* virtual functions */
@ -296,8 +237,12 @@ MaiAppRoot::RefChild(gint aChildIndex)
return NULL;
}
else {
TopLevelItem *item = (TopLevelItem *)
g_list_nth_data(mTopLevelList, aChildIndex);
return item->maiTopLevel;
guint uid = GPOINTER_TO_UINT(g_list_nth_data(mTopLevelList,
aChildIndex));
MaiTopLevel *maiTopLevel = (MaiTopLevel*)MaiHashTable::Lookup(uid);
NS_ASSERTION(maiTopLevel, "Fail to get object from hash table");
if (maiTopLevel)
g_object_ref(maiTopLevel->GetAtkObject());
return maiTopLevel;
}
}

Просмотреть файл

@ -43,21 +43,10 @@
#define __MAI_APP_ROOT_H__
#include "nsIAccessibleEventReceiver.h"
#include "nsMaiCache.h"
#include "nsMaiTopLevel.h"
#define MAI_TYPE_APP_ROOT (MAI_TYPE_ATK_OBJECT)
struct TopLevelItem
{
/* nsIAccessibles for Different toplevel Windows may have same
* Unique ID (why so?), we need to expose only one of them
* "ref" here is used to trace that.
*/
gint ref;
MaiTopLevel *maiTopLevel;
};
/* MaiAppRoot is the MaiObject class for Mozilla, the whole application. Only
* one instance of MaiAppRoot exists for one Mozilla instance. And the one
* should be created when Mozilla Startup (with accessibility feature
@ -77,12 +66,9 @@ public:
virtual guint GetNSAccessibleUniqueID();
gboolean AddMaiTopLevel(MaiTopLevel *aToplevel);
gboolean RemoveMaiTopLevel(MaiTopLevel *aToplevel);
MaiTopLevel *FindMaiTopLevel(MaiTopLevel *aToplevel);
MaiTopLevel *FindMaiTopLevel(nsIAccessible *aToplevel);
MaiCache *GetCache(void);
PRBool AddMaiTopLevel(MaiTopLevel *aToplevel);
PRBool RemoveMaiTopLevelByID(guint aID);
PRBool LookupTopLevelID(guint aID);
public:
/* virtual functions for MaiObject */
virtual AtkObject *GetAtkObject(void);
@ -96,9 +82,6 @@ public:
virtual MaiObject *RefChild(gint aChildIndex);
private:
GList *mTopLevelList;
TopLevelItem *FindTopLevelItem(nsIAccessible *aAccess);
MaiCache *mMaiCache;
};
#endif /* __MAI_APP_ROOT_H__ */

Просмотреть файл

@ -45,123 +45,179 @@ MaiCache::MaiCache()
{
/* cache index always point to the last item */
mCacheIndex = -1;
for (int index = 0; index < MAI_CACHE_SIZE; index++) {
mCache[index].uid = 0;
mCache[index].maiObject = NULL;
}
for (int index = 0; index < MAI_CACHE_SIZE; index++)
mCache[index]= 0;
}
MaiCache::~MaiCache()
{
AtkObject *tmpAtkObj = NULL;
MaiObject *maiObj = NULL;
for (int index = 0; index < MAI_CACHE_SIZE; index++) {
if (mCache[index].maiObject && mCache[index].uid != 0) {
tmpAtkObj = mCache[index].maiObject->GetAtkObject();
MAI_LOG_DEBUG(("Mai Cache: de-caching, maiAtkObj=0x%x, ref=%d\
maiObj=0x%x, uid=%x\n", (guint)tmpAtkObj,
G_OBJECT(tmpAtkObj)->ref_count,
(guint)mCache[index].maiObject, mCache[index].uid));
g_object_unref(tmpAtkObj);
mCache[index].uid = 0;
mCache[index].maiObject = NULL;
if ((maiObj = MaiHashTable::Lookup(mCache[index]))) {
MAI_LOG_DEBUG(("Mai Cache: de-caching, uid=0x%x, maiObj=0x%x \n",
mCache[index], maiObj));
mCache[index] = 0;
g_object_unref(maiObj->GetAtkObject());
}
}
}
/* more advanced replacing algorithm can be employed for performance
* later in MaiCache::Add
*/
gboolean
PRBool
MaiCache::Add(MaiObject *aMaiObj)
{
g_return_val_if_fail(aMaiObj != NULL, FALSE);
// different nsIAccessible object can have the same ID,
// but we deem them equal for accessible user.
if (Fetch(aMaiObj)) {
MAI_LOG_DEBUG(("Mai Cache: already in Cache: aMaiObj=0x%x, uid=%x\n",
(guint)aMaiObj, aMaiObj->GetNSAccessibleUniqueID()));
return TRUE;
}
g_return_val_if_fail(aMaiObj != NULL, PR_FALSE);
guint uid = aMaiObj->GetNSAccessibleUniqueID();
NS_ASSERTION((uid > 0), "Invalid nsAccessible ID");
if (uid < 0)
return PR_FALSE;
gint counter = 0;
/* try to find a vacant place */
/* if it has been in cache */
while (counter < MAI_CACHE_SIZE) {
counter++;
++counter;
mCacheIndex = (++mCacheIndex) % MAI_CACHE_SIZE;
if ((mCache[mCacheIndex].maiObject == NULL) &&
(mCache[mCacheIndex].uid == 0))
if ((mCache[mCacheIndex] == uid))
return PR_TRUE;
}
/* try to find a vacant place */
counter = 0;
while (counter < MAI_CACHE_SIZE) {
++counter;
mCacheIndex = (++mCacheIndex) % MAI_CACHE_SIZE;
if ((mCache[mCacheIndex] == 0))
break;
}
/* if fail to find a vacant place, remove the old */
AtkObject *tmpAtkObj = NULL;
/* if fail to find a vacant place, remove an old one*/
if (counter >= MAI_CACHE_SIZE) {
mCacheIndex = (++mCacheIndex) % MAI_CACHE_SIZE;
tmpAtkObj = mCache[mCacheIndex].maiObject->GetAtkObject();
MAI_LOG_DEBUG(("Mai Cache: de-caching, maiAtkObj=0x%x, ref=%d \
maiObj=0x%x, uid=%x\n", (guint)tmpAtkObj,
G_OBJECT(tmpAtkObj)->ref_count,
(guint)mCache[mCacheIndex].maiObject,
(guint)mCache[mCacheIndex].uid));
MaiObject *tmpMaiObj = MaiHashTable::Lookup(mCache[mCacheIndex]);
NS_ASSERTION(tmpMaiObj, "Fail to lookup from hash table");
MAI_LOG_DEBUG(("Mai Cache: de-caching, uid=0x%x, maiObj=0x%x \n",
mCache[mCacheIndex], tmpMaiObj));
MAI_LOG_DEBUG(("Mai Cache: added in %d, replace", mCacheIndex));
g_object_unref(tmpAtkObj);
g_object_unref(tmpMaiObj->GetAtkObject());
}
else
MAI_LOG_DEBUG(("Mai Cache: added in %d, vacant", mCacheIndex));
g_object_ref(aMaiObj->GetAtkObject());
mCache[mCacheIndex].uid = aMaiObj->GetNSAccessibleUniqueID();
mCache[mCacheIndex].maiObject = aMaiObj;
mCache[mCacheIndex] = uid;
MAI_LOG_DEBUG(("Mai Cache: Add in Cache, aMaiObj=0x%x, uid=%x\n",
(guint)aMaiObj, mCache[mCacheIndex].uid));
(guint)aMaiObj, mCache[mCacheIndex]));
return TRUE;
return PR_TRUE;
}
gboolean
MaiCache::Remove(MaiObject *aMaiObj)
{
g_return_val_if_fail(aMaiObj != NULL, FALSE);
guint uid = aMaiObj->GetNSAccessibleUniqueID();
/**************************************
nsMaiHashTable
*************************************/
for (int index = 0; index < MAI_CACHE_SIZE; index++) {
if (mCache[index].uid == uid && mCache[index].maiObject) {
g_object_unref(mCache[index].maiObject->GetAtkObject());
mCache[index].uid = 0;
mCache[index].maiObject = NULL;
return TRUE;
}
PLHashTable *MaiHashTable::mMaiObjectHashTable = NULL;
PRBool MaiHashTable::mInitialized = PR_FALSE;
static PLHashNumber IntHashKey(PRInt32 key);
#ifdef MAI_LOGGING
static PRIntn printHashEntry(PLHashEntry *he, PRIntn index, void *arg);
#endif
PRBool
MaiHashTable::Init()
{
if (!mInitialized) {
mMaiObjectHashTable = PL_NewHashTable(0,
(PLHashFunction)IntHashKey,
PL_CompareValues,
PL_CompareValues,
0, 0);
NS_ASSERTION(mMaiObjectHashTable, "Fail to create Hash Table");
mInitialized = PR_TRUE;
}
return FALSE;
return mInitialized;
}
/* the Unique ID of nsIAccessible is the only way to judge if two MaiObject
are equal. So the Fetch(guint uid) is the base for all the other Fetchs
*/
MaiObject *
MaiCache::Fetch(guint uid)
void
MaiHashTable::Destroy()
{
for (int index = 0; index < MAI_CACHE_SIZE; index++) {
if (mCache[index].uid == uid)
return mCache[index].maiObject;
if (mInitialized && mMaiObjectHashTable) {
mInitialized = PR_FALSE;
#ifdef MAI_LOGGING
MAI_LOG_DEBUG(("Destroying hash table, but some objs are in it:\n"));
gint count = PL_HashTableEnumerateEntries(mMaiObjectHashTable,
printHashEntry,
(void*)NULL);
MAI_LOG_DEBUG(("Total %d entries still in the hash table\n", count));
#endif /* #ifdef MAI_LOGGING */
PL_HashTableDestroy(mMaiObjectHashTable);
mMaiObjectHashTable = nsnull;
}
return NULL;
}
PRBool
MaiHashTable::Add(MaiObject *aMaiObject)
{
if (!mInitialized)
return FALSE;
guint uid = aMaiObject->GetNSAccessibleUniqueID();
PLHashEntry *newEntry = PL_HashTableAdd(mMaiObjectHashTable,
GINT_TO_POINTER(uid),
GINT_TO_POINTER(aMaiObject));
MAI_LOG_DEBUG(("--Add in hash table uid=0x%x, obj=0x%x\n",
uid, (guint)aMaiObject));
return newEntry ? PR_TRUE : PR_FALSE;
}
PRBool
MaiHashTable::Remove(MaiObject *aMaiObject)
{
if (!mInitialized)
return FALSE;
guint uid = aMaiObject->GetNSAccessibleUniqueID();
MAI_LOG_DEBUG(("--Remove in hash table uid=0x%x, obj=0x%x\n",
uid, (guint)aMaiObject));
return PL_HashTableRemove(mMaiObjectHashTable, GINT_TO_POINTER(uid));
}
MaiObject *
MaiCache::Fetch(MaiObject *aMaiObj)
MaiHashTable::Lookup(guint uid)
{
return Fetch(aMaiObj->GetNSAccessibleUniqueID());
if (!mInitialized)
return FALSE;
return NS_REINTERPRET_CAST(MaiObject*,
PL_HashTableLookup(mMaiObjectHashTable,
GINT_TO_POINTER(uid)));
}
MaiObject *
MaiCache::Fetch(nsIAccessible *aAccess)
MaiHashTable::Lookup(nsIAccessible *aAcc)
{
return Fetch(GetNSAccessibleUniqueID(aAccess));
return Lookup(::GetNSAccessibleUniqueID(aAcc));
}
MaiObject *
MaiCache::Fetch(AtkObject *aAtkObj)
PLHashNumber
IntHashKey(PRInt32 key)
{
MAI_CHECK_ATK_OBJECT_RETURN_VAL_IF_FAIL(aAtkObj, NULL);
return Fetch(MAI_ATK_OBJECT(aAtkObj)->maiObject);
return PLHashNumber(key);
}
#ifdef MAI_LOGGING
PRIntn
printHashEntry(PLHashEntry *he, PRIntn index, void *arg)
{
if (he) {
MAI_LOG_DEBUG((" Entry: uid=0x%x, maiObj=0x%x\n",
(guint)he->key, (guint)he->value));
}
return HT_ENUMERATE_NEXT;
}
#endif /* #ifdef MAI_LOGGING */

Просмотреть файл

@ -42,13 +42,21 @@
#ifndef __MAI_CACHE_H__
#define __MAI_CACHE_H__
#include "plhash.h"
#include "nsMaiObject.h"
struct MaiCacheItem
{
guint uid;
MaiObject *maiObject;
};
////////////////////////////////////////////////////////////////
// Class MaiCache
// ----------------------
//
// MaiCache keeps some maiObjects in memory for a longer time
// when they are going to be released in the normal case (no cache)
// For this aim, MaiCache increases the maiobject refcount by one,
// thus the maiobject will reside in memory at least when MaiCache
// releases it.
// The cached maiobjects are not needed to be saved in cache, they are
// in hash table. MaiCache only saves the IDs of cached objects.
//////////////////////////////////////////////////////////////////
class MaiCache
{
@ -56,17 +64,29 @@ public:
MaiCache();
~MaiCache();
gboolean Add(MaiObject *aMaiObj);
gboolean Remove(MaiObject *aMaiObj);
MaiObject *Fetch(guint uid);
MaiObject *Fetch(MaiObject *aMaiObj);
MaiObject *Fetch(nsIAccessible *aAccess);
MaiObject *Fetch(AtkObject *aAtkObj);
PRBool Add(MaiObject *aMaiObj);
private:
enum { MAI_CACHE_SIZE = 10 };
MaiCacheItem mCache [MAI_CACHE_SIZE];
guint mCache[MAI_CACHE_SIZE];
gint mCacheIndex;
};
class MaiHashTable
{
public:
MaiHashTable() {}
~MaiHashTable() {}
public:
static PRBool Init(void);
static void Destroy(void);
static PRBool Add(MaiObject *);
static PRBool Remove(MaiObject *);
static MaiObject *Lookup(guint uid);
static MaiObject *Lookup(nsIAccessible *aAcc);
private:
static PLHashTable *mMaiObjectHashTable;
static PRBool mInitialized;
};
#endif /* __MAI_CACHE_H__ */

Просмотреть файл

@ -156,8 +156,7 @@ MaiHyperlink::GetObject(gint aLinkIndex)
if (NS_FAILED(rv) || !accObj)
return NULL;
/* ??? when the new one get freed? */
MaiWidget *maiObj = new MaiWidget(accObj);
MaiWidget *maiObj = MaiWidget::CreateAndCache(accObj);
return maiObj;
}

Просмотреть файл

@ -344,7 +344,7 @@ MaiInterfaceTable::GetSummary()
gint
MaiInterfaceTable::GetSelectedColumns(gint **aSelected)
{
MAI_IFACE_RETURN_VAL_IF_FAIL(accessIface, NULL);
MAI_IFACE_RETURN_VAL_IF_FAIL(accessIface, 0);
PRUint32 size = 0;
PRInt32 *columns = NULL;
@ -358,7 +358,7 @@ MaiInterfaceTable::GetSelectedColumns(gint **aSelected)
NS_ASSERTION(atkColumns, "Fail to get memory for columns");
//copy
for (int index = 0; index < size; ++index)
for (PRUint32 index = 0; index < size; ++index)
atkColumns[index] = NS_STATIC_CAST(gint, columns[index]);
nsMemory::Free(columns);
@ -369,7 +369,7 @@ MaiInterfaceTable::GetSelectedColumns(gint **aSelected)
gint
MaiInterfaceTable::GetSelectedRows(gint **aSelected)
{
MAI_IFACE_RETURN_VAL_IF_FAIL(accessIface, NULL);
MAI_IFACE_RETURN_VAL_IF_FAIL(accessIface, 0);
PRUint32 size = 0;
PRInt32 *rows = NULL;
@ -383,7 +383,7 @@ MaiInterfaceTable::GetSelectedRows(gint **aSelected)
NS_ASSERTION(atkRows, "Fail to get memory for rows");
//copy
for (int index = 0; index < size; ++index)
for (PRUint32 index = 0; index < size; ++index)
atkRows[index] = NS_STATIC_CAST(gint, rows[index]);
nsMemory::Free(rows);

Просмотреть файл

@ -40,6 +40,8 @@
* ***** END LICENSE BLOCK ***** */
#include "nsMaiObject.h"
#include "nsMaiUtil.h"
#include "nsMaiCache.h"
#include "nsIAccessibleEventListener.h"
#include "nsString.h"
@ -139,6 +141,7 @@ MaiObject::MaiObject(nsIAccessible *aAcc)
#endif
MAI_LOG_DEBUG(("====MaiObject creating this=0x%x,total =%d= created\n",
(unsigned int)this, num_created_mai_object));
}
MaiObject::~MaiObject()
@ -323,6 +326,9 @@ finalizeCB(GObject *aObj)
MaiObject *maiObject = MAI_ATK_OBJECT(aObj)->maiObject;
MAI_LOG_DEBUG(("====release MaiAtkObject=0x%x, MaiObject=0x%x\n",
(guint)aObj, (guint)maiObject));
MaiHashTable::Remove(maiObject);
maiObject->Finalize();
// never call MaiObject later
@ -385,14 +391,7 @@ refChildCB(AtkObject *aObj, gint aChildIndex)
if (!childObject)
return NULL;
AtkObject *childAtkObj = childObject->GetAtkObject();
if (childAtkObj) {
g_object_ref(childAtkObj);
if (!childAtkObj->accessible_parent)
//this will addref parent
atk_object_set_parent(childAtkObj, aObj);
}
return childAtkObj;
return childObject->GetAtkObject();
}
gint

Просмотреть файл

@ -88,40 +88,83 @@ MaiTopLevel::~MaiTopLevel()
receiver->RemoveAccessibleEventListener();
}
//////////////////////////////////////////////////////////////////////
// See the comments in
// MaiWidget::Create(nsIAccessible *aAcc);
/////////////////////////////////////////////////////////////////////
MaiTopLevel *
MaiTopLevel::Create(nsIAccessible *aAcc)
{
if (!aAcc)
return NULL;
MaiTopLevel *maiTopLevel = NS_REINTERPRET_CAST(MaiTopLevel *,
MaiHashTable::Lookup(aAcc));
if (!maiTopLevel) {
maiTopLevel = new MaiTopLevel(aAcc);
NS_ASSERTION(maiTopLevel, "Fail to create Object\n");
NS_IF_ADDREF(maiTopLevel);
MaiHashTable::Add(maiTopLevel);
}
else {
g_object_ref(maiTopLevel->GetAtkObject());
}
return maiTopLevel;
}
//////////////////////////////////////////////////////////////////////
// See the comments in
// MaiWidget::CreateAndCache(nsIAccessible *aAcc);
/////////////////////////////////////////////////////////////////////
MaiTopLevel *
MaiTopLevel::CreateAndCache(nsIAccessible *aAcc)
{
if (!aAcc)
return NULL;
MaiCache *maiCache = mai_get_cache();
if (!maiCache)
return NULL;
MaiTopLevel *retWidget = MaiTopLevel::Create(aAcc);
maiCache->Add(retWidget);
return retWidget;
}
NS_IMETHODIMP
MaiTopLevel::HandleEvent(PRUint32 aEvent, nsIAccessible *aAccessible,
AccessibleEventData * aEventData)
{
MaiWidget *pMaiObject;
nsresult rv = NS_ERROR_FAILURE;
MaiWidget *pMaiObject = NULL;
AtkTableChange * pAtkTableChange;
MAI_LOG_DEBUG(("\n\nReceived event: aEvent=%u, obj=0x%x, data=0x%x \n",
aEvent, aAccessible, aEventData));
if (mAccessible == aAccessible)
pMaiObject = this;
else
pMaiObject = CreateMaiWidgetFor(aAccessible);
pMaiObject = CreateMaiWidgetFor(aAccessible);
if (!pMaiObject) {
MAI_LOG_DEBUG(("\n\nFail to Create MaiObject for obj=0x%x\n",
aAccessible));
return NS_ERROR_FAILURE;
return NS_ERROR_OUT_OF_MEMORY;
}
MaiObject *oldMaiObj = NULL, *newMaiObj = NULL;
switch (aEvent) {
case nsIAccessibleEventListener::EVENT_FOCUS:
MAI_LOG_DEBUG(("\n\nReceived: EVENT_FOCUS\n"));
atk_focus_tracker_notify(ATK_OBJECT(pMaiObject->GetAtkObject()));
rv = NS_OK;
break;
case nsIAccessibleEventListener::EVENT_STATE_CHANGE:
AtkStateChange *pAtkStateChange;
AtkStateType atkState;
MAI_LOG_DEBUG(("\n\nReceived: EVENT_STATE_CHANGE\n"));
if (!aEventData)
return NS_ERROR_FAILURE;
break;
pAtkStateChange = NS_REINTERPRET_CAST(AtkStateChange *, aEventData);
@ -138,6 +181,7 @@ MaiTopLevel::HandleEvent(PRUint32 aEvent, nsIAccessible *aAccessible,
atk_object_notify_state_change(ATK_OBJECT(pMaiObject->GetAtkObject()),
atkState, pAtkStateChange->enable);
rv = NS_OK;
break;
/*
@ -150,37 +194,42 @@ MaiTopLevel::HandleEvent(PRUint32 aEvent, nsIAccessible *aAccessible,
MAI_LOG_DEBUG(("\n\nReceived: EVENT_ATK_PROPERTY_CHANGE\n"));
if (!aEventData)
return NS_ERROR_FAILURE;
break;
pAtkPropChange = NS_REINTERPRET_CAST(AtkPropertyChange *, aEventData);
values.property_name = pAtkPropertyNameArray[pAtkPropChange->type];
MAI_LOG_DEBUG(("\n\nthe type of EVENT_ATK_PROPERTY_CHANGE: %d\n\n",
pAtkPropChange->type));
switch (pAtkPropChange->type) {
case PROP_TABLE_CAPTION:
case PROP_TABLE_SUMMARY:
MaiObject *aOldMaiObj, *aNewMaiObj;
if (pAtkPropChange->oldvalue)
aOldMaiObj = CreateMaiWidgetFor(NS_REINTERPRET_CAST
(nsIAccessible *,
pAtkPropChange->oldvalue));
oldMaiObj = CreateMaiWidgetFor(NS_REINTERPRET_CAST
(nsIAccessible *,
pAtkPropChange->oldvalue));
if (pAtkPropChange->newvalue)
aNewMaiObj = CreateMaiWidgetFor(NS_REINTERPRET_CAST
(nsIAccessible *,
pAtkPropChange->newvalue));
newMaiObj = CreateMaiWidgetFor(NS_REINTERPRET_CAST
(nsIAccessible *,
pAtkPropChange->newvalue));
if (!aOldMaiObj || !aNewMaiObj )
return NS_ERROR_FAILURE;
if (oldMaiObj && newMaiObj) {
g_value_init(&values.old_value, G_TYPE_POINTER);
g_value_set_pointer(&values.old_value,
ATK_OBJECT(oldMaiObj->GetAtkObject()));
g_value_init(&values.new_value, G_TYPE_POINTER);
g_value_set_pointer(&values.new_value,
ATK_OBJECT(newMaiObj->GetAtkObject()));
rv = NS_OK;
}
if (oldMaiObj)
g_object_unref(oldMaiObj->GetAtkObject());
if (newMaiObj)
g_object_unref(newMaiObj->GetAtkObject());
g_value_init(&values.old_value, G_TYPE_POINTER);
g_value_set_pointer(&values.old_value,
ATK_OBJECT(aOldMaiObj->GetAtkObject()));
g_value_init(&values.new_value, G_TYPE_POINTER);
g_value_set_pointer(&values.new_value,
ATK_OBJECT(aNewMaiObj->GetAtkObject()));
break;
case PROP_TABLE_COLUMN_DESCRIPTION:
@ -191,6 +240,7 @@ MaiTopLevel::HandleEvent(PRUint32 aEvent, nsIAccessible *aAccessible,
g_value_set_int(&values.new_value,
*NS_REINTERPRET_CAST(gint *,
pAtkPropChange->newvalue));
rv = NS_OK;
break;
//Perhaps need more cases in the future
@ -199,12 +249,13 @@ MaiTopLevel::HandleEvent(PRUint32 aEvent, nsIAccessible *aAccessible,
g_value_set_pointer (&values.old_value, pAtkPropChange->oldvalue);
g_value_init (&values.new_value, G_TYPE_POINTER);
g_value_set_pointer (&values.new_value, pAtkPropChange->newvalue);
rv = NS_OK;
}
g_signal_emit_by_name(ATK_OBJECT(pMaiObject->GetAtkObject()),
g_strconcat("property_change::",
values.property_name),
&values, NULL);
if (NS_SUCCEEDED(rv))
g_signal_emit_by_name(ATK_OBJECT(pMaiObject->GetAtkObject()),
g_strconcat("property_change::",
values.property_name),
&values, NULL);
break;
@ -212,6 +263,7 @@ MaiTopLevel::HandleEvent(PRUint32 aEvent, nsIAccessible *aAccessible,
MAI_LOG_DEBUG(("\n\nReceived: EVENT_ATK_SELECTION_CHANGE\n"));
g_signal_emit_by_name(ATK_OBJECT(pMaiObject->GetAtkObject()),
"selection_changed");
rv = NS_OK;
break;
case nsIAccessibleEventListener::EVENT_ATK_TEXT_CHANGE:
@ -219,7 +271,7 @@ MaiTopLevel::HandleEvent(PRUint32 aEvent, nsIAccessible *aAccessible,
MAI_LOG_DEBUG(("\n\nReceived: EVENT_ATK_TEXT_CHANGE\n"));
if (!aEventData)
return NS_ERROR_FAILURE;
break;
pAtkTextChange = NS_REINTERPRET_CAST(AtkTextChange *, aEventData);
g_signal_emit_by_name (ATK_OBJECT(pMaiObject->GetAtkObject()),
@ -227,36 +279,40 @@ MaiTopLevel::HandleEvent(PRUint32 aEvent, nsIAccessible *aAccessible,
"text_changed::insert":"text_changed::delete",
pAtkTextChange->start,
pAtkTextChange->length);
rv = NS_OK;
break;
case nsIAccessibleEventListener::EVENT_ATK_TEXT_SELECTION_CHANGE:
MAI_LOG_DEBUG(("\n\nReceived: EVENT_ATK_TEXT_SELECTION_CHANGE\n"));
g_signal_emit_by_name(ATK_OBJECT(pMaiObject->GetAtkObject()),
"text_selection_changed");
rv = NS_OK;
break;
case nsIAccessibleEventListener::EVENT_ATK_TEXT_CARET_MOVE:
MAI_LOG_DEBUG(("\n\nReceived: EVENT_ATK_TEXT_CARET_MOVE\n"));
if (!aEventData)
return NS_ERROR_FAILURE;
break;
MAI_LOG_DEBUG(("\n\nCaret postion: %d", *(gint *)aEventData ));
g_signal_emit_by_name(ATK_OBJECT(pMaiObject->GetAtkObject()),
"text_caret_moved",
// Curent caret position
*(gint *)aEventData);
rv = NS_OK;
break;
case nsIAccessibleEventListener::EVENT_ATK_TABLE_MODEL_CHANGE:
MAI_LOG_DEBUG(("\n\nReceived: EVENT_ATK_TABLE_MODEL_CHANGE\n"));
g_signal_emit_by_name(ATK_OBJECT(pMaiObject->GetAtkObject()),
"model_changed");
rv = NS_OK;
break;
case nsIAccessibleEventListener::EVENT_ATK_TABLE_ROW_INSERT:
MAI_LOG_DEBUG(("\n\nReceived: EVENT_ATK_TABLE_ROW_INSERT\n"));
if (!aEventData)
return NS_ERROR_FAILURE;
break;
pAtkTableChange = NS_REINTERPRET_CAST(AtkTableChange *, aEventData);
@ -266,12 +322,13 @@ MaiTopLevel::HandleEvent(PRUint32 aEvent, nsIAccessible *aAccessible,
pAtkTableChange->index,
// The number of the inserted
pAtkTableChange->count);
rv = NS_OK;
break;
case nsIAccessibleEventListener::EVENT_ATK_TABLE_ROW_DELETE:
MAI_LOG_DEBUG(("\n\nReceived: EVENT_ATK_TABLE_ROW_DELETE\n"));
if (!aEventData)
return NS_ERROR_FAILURE;
break;
pAtkTableChange = NS_REINTERPRET_CAST(AtkTableChange *, aEventData);
@ -281,18 +338,20 @@ MaiTopLevel::HandleEvent(PRUint32 aEvent, nsIAccessible *aAccessible,
pAtkTableChange->index,
// The number of the deleted
pAtkTableChange->count);
rv = NS_OK;
break;
case nsIAccessibleEventListener::EVENT_ATK_TABLE_ROW_REORDER:
MAI_LOG_DEBUG(("\n\nReceived: EVENT_ATK_TABLE_ROW_REORDER\n"));
g_signal_emit_by_name(ATK_OBJECT(pMaiObject->GetAtkObject()),
"row_reordered");
rv = NS_OK;
break;
case nsIAccessibleEventListener::EVENT_ATK_TABLE_COLUMN_INSERT:
MAI_LOG_DEBUG(("\n\nReceived: EVENT_ATK_TABLE_COLUMN_INSERT\n"));
if (!aEventData)
return NS_ERROR_FAILURE;
break;
pAtkTableChange = NS_REINTERPRET_CAST(AtkTableChange *, aEventData);
@ -302,12 +361,13 @@ MaiTopLevel::HandleEvent(PRUint32 aEvent, nsIAccessible *aAccessible,
pAtkTableChange->index,
// The number of the inserted
pAtkTableChange->count);
rv = NS_OK;
break;
case nsIAccessibleEventListener::EVENT_ATK_TABLE_COLUMN_DELETE:
MAI_LOG_DEBUG(("\n\nReceived: EVENT_ATK_TABLE_COLUMN_DELETE\n"));
if (!aEventData)
return NS_ERROR_FAILURE;
break;
pAtkTableChange = NS_REINTERPRET_CAST(AtkTableChange *, aEventData);
@ -317,18 +377,21 @@ MaiTopLevel::HandleEvent(PRUint32 aEvent, nsIAccessible *aAccessible,
pAtkTableChange->index,
// The number of the deleted
pAtkTableChange->count);
rv = NS_OK;
break;
case nsIAccessibleEventListener::EVENT_ATK_TABLE_COLUMN_REORDER:
MAI_LOG_DEBUG(("\n\nReceived: EVENT_ATK_TABLE_COLUMN_REORDER\n"));
g_signal_emit_by_name(ATK_OBJECT(pMaiObject->GetAtkObject()),
"column_reordered");
rv = NS_OK;
break;
case nsIAccessibleEventListener::EVENT_ATK_VISIBLE_DATA_CHANGE:
MAI_LOG_DEBUG(("\n\nReceived: EVENT_ATK_VISIBLE_DATA_CHANGE\n"));
g_signal_emit_by_name(ATK_OBJECT(pMaiObject->GetAtkObject()),
"visible_data_changed");
rv = NS_OK;
break;
// Is a superclass of ATK event children_changed
@ -352,6 +415,7 @@ MaiTopLevel::HandleEvent(PRUint32 aEvent, nsIAccessible *aAccessible,
pAtkChildrenChange->index,
ATK_OBJECT(childMaiObject->GetAtkObject()),
NULL);
g_object_unref(childMaiObject->GetAtkObject());
}
else {
g_signal_emit_by_name (ATK_OBJECT(pMaiObject->GetAtkObject()),
@ -359,6 +423,7 @@ MaiTopLevel::HandleEvent(PRUint32 aEvent, nsIAccessible *aAccessible,
-1, NULL, NULL);
}
rv = NS_OK;
break;
/*
@ -372,12 +437,14 @@ MaiTopLevel::HandleEvent(PRUint32 aEvent, nsIAccessible *aAccessible,
atk_focus_tracker_notify(ATK_OBJECT(pMaiObject->GetAtkObject()));
g_signal_emit_by_name(ATK_OBJECT(pMaiObject->GetAtkObject()),
"selection_changed");
rv = NS_OK;
break;
case nsIAccessibleEventListener::EVENT_MENUEND:
MAI_LOG_DEBUG(("\n\nReceived: EVENT_MENUEND\n"));
g_signal_emit_by_name(ATK_OBJECT(pMaiObject->GetAtkObject()),
"selection_changed");
rv = NS_OK;
break;
default:
@ -386,7 +453,9 @@ MaiTopLevel::HandleEvent(PRUint32 aEvent, nsIAccessible *aAccessible,
break;
}
return NS_OK;
if (pMaiObject)
g_object_unref(pMaiObject->GetAtkObject());
return rv;
}
/******************************************************************
@ -400,41 +469,6 @@ MaiTopLevel::CreateMaiWidgetFor(nsIAccessible *aAccessible)
return MaiWidget::CreateAndCache(aAccessible);
}
/*static*/
//////////////////////////////////////////////////////////////////////
// See the comments in
// MaiWidget::CreateAndCache(nsIAccessible *aAcc);
/////////////////////////////////////////////////////////////////////
MaiTopLevel *
MaiTopLevel::CreateAndCache(nsIAccessible *aAcc)
{
if (!aAcc)
return NULL;
MaiCache *maiCache = mai_get_cache();
if (!maiCache)
return NULL;
MaiTopLevel *retWidget =
NS_STATIC_CAST(MaiTopLevel*, maiCache->Fetch(aAcc));
//there is a maiWidget in cache for the nsIAccessible already.
if (retWidget) {
MAI_LOG_DEBUG(("MaiTopLevel::CreateAndCache, already added\n"));
return retWidget;
}
//create one, and cache it.
retWidget = new MaiTopLevel(aAcc);
NS_ASSERTION(retWidget, "Fail to create mai object");
MAI_LOG_DEBUG(("MaiTopLevel::CreateAndCache, new one created\n"));
maiCache->Add(retWidget);
//cache should have add ref, release ours
g_object_unref(retWidget->GetAtkObject());
return retWidget;
}
/* static */
AtkStateType
MaiTopLevel::TranslateAState(PRUint32 aAccState)

Просмотреть файл

@ -56,6 +56,7 @@ class MaiTopLevel: public MaiWidget, public nsIAccessibleEventListener
public:
MaiTopLevel(nsIAccessible *aAcc);
virtual ~MaiTopLevel();
static MaiTopLevel * Create(nsIAccessible *aAcc);
NS_DECL_ISUPPORTS
// nsIAccessibleEventListener

Просмотреть файл

@ -42,12 +42,17 @@
#include <stdlib.h>
#include "nsMaiUtil.h"
#include "nsMaiCache.h"
#include "nsMaiAppRoot.h"
static gboolean mai_shutdown(void);
static void mai_delete_root(void);
static MaiAppRoot *mai_create_root(void);
MaiCache *mai_create_cache(void);
MaiCache *mai_get_cache(void);
void mai_delete_cache(void);
static void mai_util_class_init(MaiUtilClass *klass);
/* atkutil.h */
@ -305,6 +310,9 @@ mai_init(MaiHook **aMaiHook)
/* Initialize the MAI Utility class */
g_type_class_unref(g_type_class_ref(MAI_TYPE_UTIL));
MaiHashTable::Init();
mai_create_cache();
return TRUE;
}
@ -323,6 +331,9 @@ mai_shutdown(void)
sMaiHook.RemoveTopLevelAccessible = NULL;
mai_delete_root();
mai_delete_cache();
MaiHashTable::Destroy();
return TRUE;
}
@ -338,6 +349,7 @@ mai_create_root(void)
}
if (!sRootAccessible) {
sRootAccessible = new MaiAppRoot();
MaiHashTable::Add(sRootAccessible);
NS_ASSERTION(sRootAccessible, "Fail to create MaiAppRoot");
/* initialize the MAI hook
@ -363,23 +375,41 @@ void
mai_delete_root(void)
{
if (sRootAccessible) {
delete sRootAccessible;
g_object_unref(sRootAccessible->GetAtkObject());
sRootAccessible = NULL;
}
}
/* return the reference of MaiCache.
*/
static MaiCache *sMaiCache = NULL;
MaiCache *
mai_get_cache(void)
mai_create_cache(void)
{
if (!mai_initialized) {
return NULL;
}
MaiAppRoot *root = mai_get_root();
if (root)
return root->GetCache();
return NULL;
if (!sMaiCache) {
sMaiCache = new MaiCache();
NS_ASSERTION(sMaiCache, "Fail to create MaiCache");
}
return sMaiCache;
}
MaiCache *
mai_get_cache(void)
{
return sMaiCache;
}
void
mai_delete_cache(void)
{
if (sMaiCache) {
delete sMaiCache;
sMaiCache = NULL;
}
}
gboolean
@ -387,35 +417,16 @@ mai_add_toplevel_accessible(nsIAccessible *toplevel)
{
g_return_val_if_fail(toplevel != NULL, TRUE);
#if 1
MaiAppRoot *root;
root = mai_get_root();
if (!root)
return FALSE;
MaiTopLevel *mai_top_level = new MaiTopLevel(toplevel);
MaiTopLevel *mai_top_level = MaiTopLevel::Create(toplevel);
g_return_val_if_fail(mai_top_level != NULL, PR_FALSE);
gboolean res = root->AddMaiTopLevel(mai_top_level);
/* root will add ref for itself use */
g_object_unref(mai_top_level->GetAtkObject());
return res;
#endif
#if 0
MaiAppRoot *root;
root = mai_get_root();
if (!root)
return FALSE;
MaiTopLevel *mai_top_level =
NS_STATIC_CAST(MaiTopLevel*, MaiTopLevel::CreateAndCache(toplevel));
g_return_val_if_fail(mai_top_level != NULL, PR_FALSE);
gboolean res = root->AddMaiTopLevel(mai_top_level);
return res;
#endif
}
gboolean
@ -426,8 +437,9 @@ mai_remove_toplevel_accessible(nsIAccessible *toplevel)
MaiAppRoot *root;
root = mai_get_root();
if (root) {
MaiTopLevel *mai_top_level = root->FindMaiTopLevel(toplevel);
return root->RemoveMaiTopLevel(mai_top_level);
guint uid = ::GetNSAccessibleUniqueID(toplevel);
gboolean res = root->RemoveMaiTopLevelByID(uid);
return res;
}
else
return FALSE;

Просмотреть файл

@ -77,7 +77,7 @@ struct _MaiUtilClass
};
#define MAI_VERSION "0.0.6"
#define MAI_NAME "MAI-Mozilla Atk Interface"
#define MAI_NAME "mozilla"
MaiAppRoot *mai_get_root(void);
MaiCache *mai_get_cache(void);

Просмотреть файл

@ -60,6 +60,7 @@
#include "nsMaiInterfaceValue.h"
#include "nsMaiUtil.h"
#include "nsMaiCache.h"
G_BEGIN_DECLS
@ -120,6 +121,69 @@ MaiWidget::~MaiWidget()
g_hash_table_destroy(mChildren);
}
///////////////////////////////////////////////////////////////////////
// MaiWidget *
// MaiWidget::Create(nsIAccessible *aAcc)
//-------------------------------------------------------------------
//
// This method return a maiWidget for |aAcc|. If There is a maiWidget whose
// ID is same with |aAcc|, the old one is returned and |aAcc| is discarded.
// Otherwise, a new MaiWidget is created and returned, which will ADDREF
// |aAcc|. In both cases, the atkObject for the maiWidget returned has been
// addrefed. That is to say, a the refcount of the gobject is one for a new
// created maiWidget, or increased by one for a already existing maiWidget.
// The caller is REQUIRED to release the refcount.
//
// **Note**
// Any active mai object is saved in the MaiHashTable, until it is deleted.
// An Mai Object can only be deleted when its atk object refcount reachs
// zero.
MaiWidget *
MaiWidget::Create(nsIAccessible *aAcc)
{
if (!aAcc)
return NULL;
MaiWidget *maiWidget = NS_REINTERPRET_CAST(MaiWidget *,
MaiHashTable::Lookup(aAcc));
if (!maiWidget) {
//atkObject born with refcount=1, no need to addref it.
maiWidget = new MaiWidget(aAcc);
NS_ASSERTION(maiWidget, "Fail to create Object\n");
MaiHashTable::Add(maiWidget);
}
else {
MAI_LOG_DEBUG(("find maiWidget=0x%x in hash table for uid=0x%x\n",
(guint)maiWidget, ::GetNSAccessibleUniqueID(aAcc)));
g_object_ref(maiWidget->GetAtkObject());
}
return maiWidget;
}
/*static*/
//////////////////////////////////////////////////////////////////////
// MaiWidget *
// MaiWidget::CreateAndCache(nsIAccessible *aAcc);
//
// this function will call MaiWidget::Create, and cache the result.
////////////////////////////////////////////////////////////////////////
MaiWidget *
MaiWidget::CreateAndCache(nsIAccessible *aAcc)
{
if (!aAcc)
return NULL;
MaiCache *maiCache = mai_get_cache();
if (!maiCache)
return NULL;
//create one, and cache it.
MaiWidget *retWidget = MaiWidget::Create(aAcc);
maiCache->Add(retWidget);
return retWidget;
}
#ifdef MAI_LOGGING
void
MaiWidget::DumpMaiObjectInfo(gint aDepth)
@ -167,61 +231,12 @@ MaiWidget::GetMaiInterface(MaiInterfaceType aIfaceType)
return mMaiInterface[aIfaceType];
}
/*static*/
//////////////////////////////////////////////////////////////////////
// MaiWidget *
// MaiWidget::CreateAndCache(nsIAccessible *aAcc);
//
// A helper to create a new MaiWidget and cache it.
//-------------------------------------------------------------------
// This Method gets a cached MaiWidget for the nsIAccessible, create one
// if needed and cache it. Only when create a new MaiWidget, |aAcc| will
// be addrefed.
//
// **Note**
// The returned cached MaiWidget object is NOT guaranteed to be there when
// you fetch it next time. Accordingly, DO NOT keep the returned pointer
// and use it later. Typically, you pass the result of this method to a
// callback.
// If it is really needed to keep the result for later use, please use
// g_object_ref(maiWidget->GetAtkObject());
// to ensure the |maiWidget| pointer is still valid, even when the MaiWidget
// is removed from the cache. And when you do not need it, you have to use:
// g_object_unref(maiWidget->GetAtkObject());
// to release your reference.
////////////////////////////////////////////////////////////////////////
MaiWidget *
MaiWidget::CreateAndCache(nsIAccessible *aAcc)
{
if (!aAcc)
return NULL;
MaiCache *maiCache = mai_get_cache();
if (!maiCache)
return NULL;
MaiWidget *retWidget = NS_STATIC_CAST(MaiWidget*, maiCache->Fetch(aAcc));
//there is a maiWidget in cache for the nsIAccessible already.
if (retWidget)
return retWidget;
//create one, and cache it.
retWidget = new MaiWidget(aAcc);
NS_ASSERTION(retWidget, "Fail to create mai object");
maiCache->Add(retWidget);
//cache should have add ref, release ours
g_object_unref(retWidget->GetAtkObject());
return retWidget;
}
void
MaiWidget::ChildrenChange(AtkChildrenChange *event)
{
MaiWidget *maiChild;
if (event && event->child &&
(maiChild = CreateAndCache(event->child))) {
(maiChild = Create(event->child))) {
//update the specified child, but now use the easiest way.
g_hash_table_destroy(mChildren);
mChildren = g_hash_table_new(g_direct_hash, NULL);
@ -407,7 +422,7 @@ MaiWidget::GetParent(void)
return NULL;
/* create a maiWidget for parent */
return CreateAndCache(accParent);
return Create(accParent);
}
gint
@ -430,16 +445,19 @@ MaiWidget::RefChild(gint aChildIndex)
MaiObject *maiChild = NULL;
guint uid;
// look in cache first
MaiCache *maiCache = mai_get_cache();
if (maiCache) {
uid = GetChildUniqueID(aChildIndex);
if (uid > 0 && (maiChild = maiCache->Fetch(uid))) {
MAI_LOG_DEBUG(("got child 0x%x from cache\n", (guint)maiChild));
return maiChild;
}
// look in hashtable first
uid = GetChildUniqueID(aChildIndex);
if (uid > 0 && (maiChild = MaiHashTable::Lookup(uid))) {
MAI_LOG_DEBUG(("got child 0x%x from hash table\n", (guint)maiChild));
g_object_ref(maiChild->GetAtkObject());
//this will addref parent
atk_object_set_parent(maiChild->GetAtkObject(), GetAtkObject());
return maiChild;
}
// :( not cached yet, get and cache it is possible
// :( not in child list or hash table yet
// nsIAccessible child index starts with 1
gint accChildIndex = 1;
nsCOMPtr<nsIAccessible> accChild = NULL;
@ -459,16 +477,12 @@ MaiWidget::RefChild(gint aChildIndex)
// user, since they point to the same dom node.
// So, maybe the it has been cached.
uid = ::GetNSAccessibleUniqueID(accChild);
g_return_val_if_fail(uid != 0, NULL);
if (maiCache)
maiChild = maiCache->Fetch(uid);
// not cached, create one
if (!maiChild) {
maiChild = CreateAndCache(accChild);
}
// update children uid list
SetChildUniqueID(aChildIndex, uid);
maiChild = Create(accChild);
//this will addref parent
atk_object_set_parent(maiChild->GetAtkObject(), GetAtkObject());
return maiChild;
}
@ -552,7 +566,7 @@ MaiWidget::SetChildUniqueID(gint aChildIndex, guint aChildUid)
void
classInitCB(AtkObjectClass *aClass)
{
GObjectClass *gobject_class = G_OBJECT_CLASS(aClass);
// GObjectClass *gobject_class = G_OBJECT_CLASS(aClass);
parent_class = g_type_class_peek_parent(aClass);

Просмотреть файл

@ -85,6 +85,8 @@ class MaiWidget: public MaiObject
public:
MaiWidget(nsIAccessible *aAcc);
virtual ~MaiWidget();
static MaiWidget *Create(nsIAccessible *aAcc);
#ifdef MAI_LOGGING
virtual void DumpMaiObjectInfo(int aDepth);
#endif