зеркало из https://github.com/mozilla/gecko-dev.git
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:
Родитель
75d069ac37
Коммит
6f7d1e2855
|
@ -41,15 +41,13 @@
|
||||||
|
|
||||||
#include "nsIAccessible.h"
|
#include "nsIAccessible.h"
|
||||||
#include "nsCOMPtr.h"
|
#include "nsCOMPtr.h"
|
||||||
|
#include "nsMaiCache.h"
|
||||||
#include "nsMaiAppRoot.h"
|
#include "nsMaiAppRoot.h"
|
||||||
|
|
||||||
MaiAppRoot::MaiAppRoot()
|
MaiAppRoot::MaiAppRoot()
|
||||||
{
|
{
|
||||||
/* for mai root, mAccessible is always NULL */
|
/* for mai root, mAccessible is always NULL */
|
||||||
mTopLevelList = NULL;
|
mTopLevelList = NULL;
|
||||||
mMaiCache = new MaiCache();
|
|
||||||
NS_ASSERTION(mMaiCache, "Fail to create MaiCache");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
MaiAppRoot::~MaiAppRoot()
|
MaiAppRoot::~MaiAppRoot()
|
||||||
|
@ -59,23 +57,23 @@ MaiAppRoot::~MaiAppRoot()
|
||||||
if (mTopLevelList) {
|
if (mTopLevelList) {
|
||||||
GList *tmp_list1, *tmp_list2;
|
GList *tmp_list1, *tmp_list2;
|
||||||
MaiTopLevel *maiTopLevel;
|
MaiTopLevel *maiTopLevel;
|
||||||
|
guint uid;
|
||||||
|
|
||||||
tmp_list1 = tmp_list2 = mTopLevelList;
|
tmp_list1 = tmp_list2 = mTopLevelList;
|
||||||
mTopLevelList = NULL;
|
mTopLevelList = NULL;
|
||||||
|
|
||||||
|
#ifdef MAI_LOGGING
|
||||||
while (tmp_list1) {
|
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;
|
tmp_list1 = tmp_list1->next;
|
||||||
|
|
||||||
g_object_unref(maiTopLevel->GetAtkObject());
|
|
||||||
}
|
}
|
||||||
g_list_free(tmp_list2);
|
#endif /* #ifdef MAI_LOGGING */
|
||||||
mTopLevelList = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (mMaiCache) {
|
g_list_free(tmp_list2);
|
||||||
delete mMaiCache;
|
|
||||||
mMaiCache = NULL;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -116,107 +114,50 @@ MaiAppRoot::GetNSAccessibleUniqueID()
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
gboolean
|
PRBool
|
||||||
MaiAppRoot::AddMaiTopLevel(MaiTopLevel *aTopLevel)
|
MaiAppRoot::AddMaiTopLevel(MaiTopLevel *aTopLevel)
|
||||||
{
|
{
|
||||||
g_return_val_if_fail(aTopLevel != NULL, FALSE);
|
g_return_val_if_fail(aTopLevel != NULL, FALSE);
|
||||||
MAI_LOG_DEBUG(("MaiAppRoot: add MaiTopLevel = 0x%x", (guint)aTopLevel));
|
MAI_LOG_DEBUG(("MaiAppRoot: add MaiTopLevel = 0x%x", (guint)aTopLevel));
|
||||||
|
|
||||||
/* if the nsIAccessible with the same UniqueID is already added,
|
guint uid = aTopLevel->GetNSAccessibleUniqueID();
|
||||||
* we only increase the count of this item in the list.
|
g_object_ref(aTopLevel->GetAtkObject());
|
||||||
* They are same.
|
if (!LookupTopLevelID(uid)) {
|
||||||
*/
|
mTopLevelList = g_list_append(mTopLevelList, GINT_TO_POINTER(uid));
|
||||||
|
atk_object_set_parent(aTopLevel->GetAtkObject(), GetAtkObject());
|
||||||
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"));
|
|
||||||
}
|
}
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
MaiTopLevel *
|
PRBool
|
||||||
MaiAppRoot::FindMaiTopLevel(MaiTopLevel *aTopLevel)
|
MaiAppRoot::RemoveMaiTopLevelByID(guint aID)
|
||||||
{
|
{
|
||||||
g_return_val_if_fail(aTopLevel != NULL, FALSE);
|
if (!LookupTopLevelID(aID))
|
||||||
return FindMaiTopLevel(aTopLevel->GetNSAccessible());
|
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 *
|
PRBool
|
||||||
MaiAppRoot::FindMaiTopLevel(nsIAccessible *aTopLevel)
|
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) {
|
if (mTopLevelList) {
|
||||||
GList *tmp_list;
|
GList *tmp_list = mTopLevelList;
|
||||||
TopLevelItem *item;
|
|
||||||
|
|
||||||
tmp_list = mTopLevelList;
|
|
||||||
|
|
||||||
while (tmp_list) {
|
while (tmp_list) {
|
||||||
item = (TopLevelItem*)tmp_list->data;
|
if (aID == (guint)(tmp_list->data))
|
||||||
|
return PR_TRUE;
|
||||||
tmp_list = tmp_list->next;
|
tmp_list = tmp_list->next;
|
||||||
if (item && item->maiTopLevel &&
|
|
||||||
item->maiTopLevel->GetNSAccessibleUniqueID() ==
|
|
||||||
::GetNSAccessibleUniqueID(aTopLevel))
|
|
||||||
return item;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return NULL;
|
return PR_FALSE;
|
||||||
}
|
|
||||||
|
|
||||||
MaiCache *
|
|
||||||
MaiAppRoot::GetCache(void)
|
|
||||||
{
|
|
||||||
// return "NULL" will disable the caching.
|
|
||||||
return mMaiCache;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* virtual functions */
|
/* virtual functions */
|
||||||
|
@ -296,8 +237,12 @@ MaiAppRoot::RefChild(gint aChildIndex)
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
TopLevelItem *item = (TopLevelItem *)
|
guint uid = GPOINTER_TO_UINT(g_list_nth_data(mTopLevelList,
|
||||||
g_list_nth_data(mTopLevelList, aChildIndex);
|
aChildIndex));
|
||||||
return item->maiTopLevel;
|
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__
|
#define __MAI_APP_ROOT_H__
|
||||||
|
|
||||||
#include "nsIAccessibleEventReceiver.h"
|
#include "nsIAccessibleEventReceiver.h"
|
||||||
#include "nsMaiCache.h"
|
|
||||||
#include "nsMaiTopLevel.h"
|
#include "nsMaiTopLevel.h"
|
||||||
|
|
||||||
#define MAI_TYPE_APP_ROOT (MAI_TYPE_ATK_OBJECT)
|
#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
|
/* MaiAppRoot is the MaiObject class for Mozilla, the whole application. Only
|
||||||
* one instance of MaiAppRoot exists for one Mozilla instance. And the one
|
* one instance of MaiAppRoot exists for one Mozilla instance. And the one
|
||||||
* should be created when Mozilla Startup (with accessibility feature
|
* should be created when Mozilla Startup (with accessibility feature
|
||||||
|
@ -77,12 +66,9 @@ public:
|
||||||
|
|
||||||
virtual guint GetNSAccessibleUniqueID();
|
virtual guint GetNSAccessibleUniqueID();
|
||||||
|
|
||||||
gboolean AddMaiTopLevel(MaiTopLevel *aToplevel);
|
PRBool AddMaiTopLevel(MaiTopLevel *aToplevel);
|
||||||
gboolean RemoveMaiTopLevel(MaiTopLevel *aToplevel);
|
PRBool RemoveMaiTopLevelByID(guint aID);
|
||||||
MaiTopLevel *FindMaiTopLevel(MaiTopLevel *aToplevel);
|
PRBool LookupTopLevelID(guint aID);
|
||||||
MaiTopLevel *FindMaiTopLevel(nsIAccessible *aToplevel);
|
|
||||||
|
|
||||||
MaiCache *GetCache(void);
|
|
||||||
public:
|
public:
|
||||||
/* virtual functions for MaiObject */
|
/* virtual functions for MaiObject */
|
||||||
virtual AtkObject *GetAtkObject(void);
|
virtual AtkObject *GetAtkObject(void);
|
||||||
|
@ -96,9 +82,6 @@ public:
|
||||||
virtual MaiObject *RefChild(gint aChildIndex);
|
virtual MaiObject *RefChild(gint aChildIndex);
|
||||||
private:
|
private:
|
||||||
GList *mTopLevelList;
|
GList *mTopLevelList;
|
||||||
TopLevelItem *FindTopLevelItem(nsIAccessible *aAccess);
|
|
||||||
|
|
||||||
MaiCache *mMaiCache;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /* __MAI_APP_ROOT_H__ */
|
#endif /* __MAI_APP_ROOT_H__ */
|
||||||
|
|
|
@ -45,123 +45,179 @@ MaiCache::MaiCache()
|
||||||
{
|
{
|
||||||
/* cache index always point to the last item */
|
/* cache index always point to the last item */
|
||||||
mCacheIndex = -1;
|
mCacheIndex = -1;
|
||||||
for (int index = 0; index < MAI_CACHE_SIZE; index++) {
|
for (int index = 0; index < MAI_CACHE_SIZE; index++)
|
||||||
mCache[index].uid = 0;
|
mCache[index]= 0;
|
||||||
mCache[index].maiObject = NULL;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
MaiCache::~MaiCache()
|
MaiCache::~MaiCache()
|
||||||
{
|
{
|
||||||
AtkObject *tmpAtkObj = NULL;
|
MaiObject *maiObj = NULL;
|
||||||
for (int index = 0; index < MAI_CACHE_SIZE; index++) {
|
for (int index = 0; index < MAI_CACHE_SIZE; index++) {
|
||||||
if (mCache[index].maiObject && mCache[index].uid != 0) {
|
if ((maiObj = MaiHashTable::Lookup(mCache[index]))) {
|
||||||
tmpAtkObj = mCache[index].maiObject->GetAtkObject();
|
MAI_LOG_DEBUG(("Mai Cache: de-caching, uid=0x%x, maiObj=0x%x \n",
|
||||||
MAI_LOG_DEBUG(("Mai Cache: de-caching, maiAtkObj=0x%x, ref=%d\
|
mCache[index], maiObj));
|
||||||
maiObj=0x%x, uid=%x\n", (guint)tmpAtkObj,
|
mCache[index] = 0;
|
||||||
G_OBJECT(tmpAtkObj)->ref_count,
|
g_object_unref(maiObj->GetAtkObject());
|
||||||
(guint)mCache[index].maiObject, mCache[index].uid));
|
|
||||||
g_object_unref(tmpAtkObj);
|
|
||||||
mCache[index].uid = 0;
|
|
||||||
mCache[index].maiObject = NULL;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* more advanced replacing algorithm can be employed for performance
|
PRBool
|
||||||
* later in MaiCache::Add
|
|
||||||
*/
|
|
||||||
gboolean
|
|
||||||
MaiCache::Add(MaiObject *aMaiObj)
|
MaiCache::Add(MaiObject *aMaiObj)
|
||||||
{
|
{
|
||||||
g_return_val_if_fail(aMaiObj != NULL, FALSE);
|
g_return_val_if_fail(aMaiObj != NULL, PR_FALSE);
|
||||||
// different nsIAccessible object can have the same ID,
|
|
||||||
// but we deem them equal for accessible user.
|
guint uid = aMaiObj->GetNSAccessibleUniqueID();
|
||||||
if (Fetch(aMaiObj)) {
|
NS_ASSERTION((uid > 0), "Invalid nsAccessible ID");
|
||||||
MAI_LOG_DEBUG(("Mai Cache: already in Cache: aMaiObj=0x%x, uid=%x\n",
|
if (uid < 0)
|
||||||
(guint)aMaiObj, aMaiObj->GetNSAccessibleUniqueID()));
|
return PR_FALSE;
|
||||||
return TRUE;
|
|
||||||
}
|
|
||||||
gint counter = 0;
|
gint counter = 0;
|
||||||
/* try to find a vacant place */
|
/* if it has been in cache */
|
||||||
while (counter < MAI_CACHE_SIZE) {
|
while (counter < MAI_CACHE_SIZE) {
|
||||||
counter++;
|
++counter;
|
||||||
mCacheIndex = (++mCacheIndex) % MAI_CACHE_SIZE;
|
mCacheIndex = (++mCacheIndex) % MAI_CACHE_SIZE;
|
||||||
if ((mCache[mCacheIndex].maiObject == NULL) &&
|
if ((mCache[mCacheIndex] == uid))
|
||||||
(mCache[mCacheIndex].uid == 0))
|
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;
|
break;
|
||||||
}
|
}
|
||||||
/* if fail to find a vacant place, remove the old */
|
/* if fail to find a vacant place, remove an old one*/
|
||||||
AtkObject *tmpAtkObj = NULL;
|
|
||||||
if (counter >= MAI_CACHE_SIZE) {
|
if (counter >= MAI_CACHE_SIZE) {
|
||||||
mCacheIndex = (++mCacheIndex) % MAI_CACHE_SIZE;
|
mCacheIndex = (++mCacheIndex) % MAI_CACHE_SIZE;
|
||||||
tmpAtkObj = mCache[mCacheIndex].maiObject->GetAtkObject();
|
MaiObject *tmpMaiObj = MaiHashTable::Lookup(mCache[mCacheIndex]);
|
||||||
MAI_LOG_DEBUG(("Mai Cache: de-caching, maiAtkObj=0x%x, ref=%d \
|
NS_ASSERTION(tmpMaiObj, "Fail to lookup from hash table");
|
||||||
maiObj=0x%x, uid=%x\n", (guint)tmpAtkObj,
|
|
||||||
G_OBJECT(tmpAtkObj)->ref_count,
|
MAI_LOG_DEBUG(("Mai Cache: de-caching, uid=0x%x, maiObj=0x%x \n",
|
||||||
(guint)mCache[mCacheIndex].maiObject,
|
mCache[mCacheIndex], tmpMaiObj));
|
||||||
(guint)mCache[mCacheIndex].uid));
|
|
||||||
MAI_LOG_DEBUG(("Mai Cache: added in %d, replace", mCacheIndex));
|
MAI_LOG_DEBUG(("Mai Cache: added in %d, replace", mCacheIndex));
|
||||||
g_object_unref(tmpAtkObj);
|
g_object_unref(tmpMaiObj->GetAtkObject());
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
MAI_LOG_DEBUG(("Mai Cache: added in %d, vacant", mCacheIndex));
|
MAI_LOG_DEBUG(("Mai Cache: added in %d, vacant", mCacheIndex));
|
||||||
|
|
||||||
g_object_ref(aMaiObj->GetAtkObject());
|
g_object_ref(aMaiObj->GetAtkObject());
|
||||||
mCache[mCacheIndex].uid = aMaiObj->GetNSAccessibleUniqueID();
|
mCache[mCacheIndex] = uid;
|
||||||
mCache[mCacheIndex].maiObject = aMaiObj;
|
|
||||||
|
|
||||||
MAI_LOG_DEBUG(("Mai Cache: Add in Cache, aMaiObj=0x%x, uid=%x\n",
|
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)
|
nsMaiHashTable
|
||||||
{
|
*************************************/
|
||||||
g_return_val_if_fail(aMaiObj != NULL, FALSE);
|
|
||||||
guint uid = aMaiObj->GetNSAccessibleUniqueID();
|
|
||||||
|
|
||||||
for (int index = 0; index < MAI_CACHE_SIZE; index++) {
|
PLHashTable *MaiHashTable::mMaiObjectHashTable = NULL;
|
||||||
if (mCache[index].uid == uid && mCache[index].maiObject) {
|
PRBool MaiHashTable::mInitialized = PR_FALSE;
|
||||||
g_object_unref(mCache[index].maiObject->GetAtkObject());
|
|
||||||
mCache[index].uid = 0;
|
static PLHashNumber IntHashKey(PRInt32 key);
|
||||||
mCache[index].maiObject = NULL;
|
|
||||||
return TRUE;
|
#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
|
void
|
||||||
are equal. So the Fetch(guint uid) is the base for all the other Fetchs
|
MaiHashTable::Destroy()
|
||||||
*/
|
|
||||||
MaiObject *
|
|
||||||
MaiCache::Fetch(guint uid)
|
|
||||||
{
|
{
|
||||||
for (int index = 0; index < MAI_CACHE_SIZE; index++) {
|
if (mInitialized && mMaiObjectHashTable) {
|
||||||
if (mCache[index].uid == uid)
|
|
||||||
return mCache[index].maiObject;
|
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 *
|
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 *
|
MaiObject *
|
||||||
MaiCache::Fetch(nsIAccessible *aAccess)
|
MaiHashTable::Lookup(nsIAccessible *aAcc)
|
||||||
{
|
{
|
||||||
return Fetch(GetNSAccessibleUniqueID(aAccess));
|
return Lookup(::GetNSAccessibleUniqueID(aAcc));
|
||||||
}
|
}
|
||||||
|
|
||||||
MaiObject *
|
PLHashNumber
|
||||||
MaiCache::Fetch(AtkObject *aAtkObj)
|
IntHashKey(PRInt32 key)
|
||||||
{
|
{
|
||||||
MAI_CHECK_ATK_OBJECT_RETURN_VAL_IF_FAIL(aAtkObj, NULL);
|
return PLHashNumber(key);
|
||||||
return Fetch(MAI_ATK_OBJECT(aAtkObj)->maiObject);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#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__
|
#ifndef __MAI_CACHE_H__
|
||||||
#define __MAI_CACHE_H__
|
#define __MAI_CACHE_H__
|
||||||
|
|
||||||
|
#include "plhash.h"
|
||||||
#include "nsMaiObject.h"
|
#include "nsMaiObject.h"
|
||||||
|
|
||||||
struct MaiCacheItem
|
////////////////////////////////////////////////////////////////
|
||||||
{
|
// Class MaiCache
|
||||||
guint uid;
|
// ----------------------
|
||||||
MaiObject *maiObject;
|
//
|
||||||
};
|
// 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
|
class MaiCache
|
||||||
{
|
{
|
||||||
|
@ -56,17 +64,29 @@ public:
|
||||||
MaiCache();
|
MaiCache();
|
||||||
~MaiCache();
|
~MaiCache();
|
||||||
|
|
||||||
gboolean Add(MaiObject *aMaiObj);
|
PRBool Add(MaiObject *aMaiObj);
|
||||||
gboolean Remove(MaiObject *aMaiObj);
|
|
||||||
MaiObject *Fetch(guint uid);
|
|
||||||
MaiObject *Fetch(MaiObject *aMaiObj);
|
|
||||||
MaiObject *Fetch(nsIAccessible *aAccess);
|
|
||||||
MaiObject *Fetch(AtkObject *aAtkObj);
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
enum { MAI_CACHE_SIZE = 10 };
|
enum { MAI_CACHE_SIZE = 10 };
|
||||||
MaiCacheItem mCache [MAI_CACHE_SIZE];
|
guint mCache[MAI_CACHE_SIZE];
|
||||||
gint mCacheIndex;
|
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__ */
|
#endif /* __MAI_CACHE_H__ */
|
||||||
|
|
|
@ -156,8 +156,7 @@ MaiHyperlink::GetObject(gint aLinkIndex)
|
||||||
if (NS_FAILED(rv) || !accObj)
|
if (NS_FAILED(rv) || !accObj)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
/* ??? when the new one get freed? */
|
MaiWidget *maiObj = MaiWidget::CreateAndCache(accObj);
|
||||||
MaiWidget *maiObj = new MaiWidget(accObj);
|
|
||||||
return maiObj;
|
return maiObj;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -344,7 +344,7 @@ MaiInterfaceTable::GetSummary()
|
||||||
gint
|
gint
|
||||||
MaiInterfaceTable::GetSelectedColumns(gint **aSelected)
|
MaiInterfaceTable::GetSelectedColumns(gint **aSelected)
|
||||||
{
|
{
|
||||||
MAI_IFACE_RETURN_VAL_IF_FAIL(accessIface, NULL);
|
MAI_IFACE_RETURN_VAL_IF_FAIL(accessIface, 0);
|
||||||
|
|
||||||
PRUint32 size = 0;
|
PRUint32 size = 0;
|
||||||
PRInt32 *columns = NULL;
|
PRInt32 *columns = NULL;
|
||||||
|
@ -358,7 +358,7 @@ MaiInterfaceTable::GetSelectedColumns(gint **aSelected)
|
||||||
NS_ASSERTION(atkColumns, "Fail to get memory for columns");
|
NS_ASSERTION(atkColumns, "Fail to get memory for columns");
|
||||||
|
|
||||||
//copy
|
//copy
|
||||||
for (int index = 0; index < size; ++index)
|
for (PRUint32 index = 0; index < size; ++index)
|
||||||
atkColumns[index] = NS_STATIC_CAST(gint, columns[index]);
|
atkColumns[index] = NS_STATIC_CAST(gint, columns[index]);
|
||||||
nsMemory::Free(columns);
|
nsMemory::Free(columns);
|
||||||
|
|
||||||
|
@ -369,7 +369,7 @@ MaiInterfaceTable::GetSelectedColumns(gint **aSelected)
|
||||||
gint
|
gint
|
||||||
MaiInterfaceTable::GetSelectedRows(gint **aSelected)
|
MaiInterfaceTable::GetSelectedRows(gint **aSelected)
|
||||||
{
|
{
|
||||||
MAI_IFACE_RETURN_VAL_IF_FAIL(accessIface, NULL);
|
MAI_IFACE_RETURN_VAL_IF_FAIL(accessIface, 0);
|
||||||
|
|
||||||
PRUint32 size = 0;
|
PRUint32 size = 0;
|
||||||
PRInt32 *rows = NULL;
|
PRInt32 *rows = NULL;
|
||||||
|
@ -383,7 +383,7 @@ MaiInterfaceTable::GetSelectedRows(gint **aSelected)
|
||||||
NS_ASSERTION(atkRows, "Fail to get memory for rows");
|
NS_ASSERTION(atkRows, "Fail to get memory for rows");
|
||||||
|
|
||||||
//copy
|
//copy
|
||||||
for (int index = 0; index < size; ++index)
|
for (PRUint32 index = 0; index < size; ++index)
|
||||||
atkRows[index] = NS_STATIC_CAST(gint, rows[index]);
|
atkRows[index] = NS_STATIC_CAST(gint, rows[index]);
|
||||||
nsMemory::Free(rows);
|
nsMemory::Free(rows);
|
||||||
|
|
||||||
|
|
|
@ -40,6 +40,8 @@
|
||||||
* ***** END LICENSE BLOCK ***** */
|
* ***** END LICENSE BLOCK ***** */
|
||||||
|
|
||||||
#include "nsMaiObject.h"
|
#include "nsMaiObject.h"
|
||||||
|
#include "nsMaiUtil.h"
|
||||||
|
#include "nsMaiCache.h"
|
||||||
#include "nsIAccessibleEventListener.h"
|
#include "nsIAccessibleEventListener.h"
|
||||||
#include "nsString.h"
|
#include "nsString.h"
|
||||||
|
|
||||||
|
@ -139,6 +141,7 @@ MaiObject::MaiObject(nsIAccessible *aAcc)
|
||||||
#endif
|
#endif
|
||||||
MAI_LOG_DEBUG(("====MaiObject creating this=0x%x,total =%d= created\n",
|
MAI_LOG_DEBUG(("====MaiObject creating this=0x%x,total =%d= created\n",
|
||||||
(unsigned int)this, num_created_mai_object));
|
(unsigned int)this, num_created_mai_object));
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
MaiObject::~MaiObject()
|
MaiObject::~MaiObject()
|
||||||
|
@ -323,6 +326,9 @@ finalizeCB(GObject *aObj)
|
||||||
MaiObject *maiObject = MAI_ATK_OBJECT(aObj)->maiObject;
|
MaiObject *maiObject = MAI_ATK_OBJECT(aObj)->maiObject;
|
||||||
MAI_LOG_DEBUG(("====release MaiAtkObject=0x%x, MaiObject=0x%x\n",
|
MAI_LOG_DEBUG(("====release MaiAtkObject=0x%x, MaiObject=0x%x\n",
|
||||||
(guint)aObj, (guint)maiObject));
|
(guint)aObj, (guint)maiObject));
|
||||||
|
|
||||||
|
MaiHashTable::Remove(maiObject);
|
||||||
|
|
||||||
maiObject->Finalize();
|
maiObject->Finalize();
|
||||||
|
|
||||||
// never call MaiObject later
|
// never call MaiObject later
|
||||||
|
@ -385,14 +391,7 @@ refChildCB(AtkObject *aObj, gint aChildIndex)
|
||||||
if (!childObject)
|
if (!childObject)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
AtkObject *childAtkObj = childObject->GetAtkObject();
|
return childObject->GetAtkObject();
|
||||||
if (childAtkObj) {
|
|
||||||
g_object_ref(childAtkObj);
|
|
||||||
if (!childAtkObj->accessible_parent)
|
|
||||||
//this will addref parent
|
|
||||||
atk_object_set_parent(childAtkObj, aObj);
|
|
||||||
}
|
|
||||||
return childAtkObj;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
gint
|
gint
|
||||||
|
|
|
@ -88,31 +88,74 @@ MaiTopLevel::~MaiTopLevel()
|
||||||
receiver->RemoveAccessibleEventListener();
|
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
|
NS_IMETHODIMP
|
||||||
MaiTopLevel::HandleEvent(PRUint32 aEvent, nsIAccessible *aAccessible,
|
MaiTopLevel::HandleEvent(PRUint32 aEvent, nsIAccessible *aAccessible,
|
||||||
AccessibleEventData * aEventData)
|
AccessibleEventData * aEventData)
|
||||||
{
|
{
|
||||||
MaiWidget *pMaiObject;
|
nsresult rv = NS_ERROR_FAILURE;
|
||||||
|
MaiWidget *pMaiObject = NULL;
|
||||||
AtkTableChange * pAtkTableChange;
|
AtkTableChange * pAtkTableChange;
|
||||||
|
|
||||||
MAI_LOG_DEBUG(("\n\nReceived event: aEvent=%u, obj=0x%x, data=0x%x \n",
|
MAI_LOG_DEBUG(("\n\nReceived event: aEvent=%u, obj=0x%x, data=0x%x \n",
|
||||||
aEvent, aAccessible, aEventData));
|
aEvent, aAccessible, aEventData));
|
||||||
|
|
||||||
if (mAccessible == aAccessible)
|
pMaiObject = CreateMaiWidgetFor(aAccessible);
|
||||||
pMaiObject = this;
|
|
||||||
else
|
|
||||||
pMaiObject = CreateMaiWidgetFor(aAccessible);
|
|
||||||
|
|
||||||
if (!pMaiObject) {
|
if (!pMaiObject) {
|
||||||
MAI_LOG_DEBUG(("\n\nFail to Create MaiObject for obj=0x%x\n",
|
MAI_LOG_DEBUG(("\n\nFail to Create MaiObject for obj=0x%x\n",
|
||||||
aAccessible));
|
aAccessible));
|
||||||
return NS_ERROR_FAILURE;
|
return NS_ERROR_OUT_OF_MEMORY;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
MaiObject *oldMaiObj = NULL, *newMaiObj = NULL;
|
||||||
switch (aEvent) {
|
switch (aEvent) {
|
||||||
case nsIAccessibleEventListener::EVENT_FOCUS:
|
case nsIAccessibleEventListener::EVENT_FOCUS:
|
||||||
MAI_LOG_DEBUG(("\n\nReceived: EVENT_FOCUS\n"));
|
MAI_LOG_DEBUG(("\n\nReceived: EVENT_FOCUS\n"));
|
||||||
atk_focus_tracker_notify(ATK_OBJECT(pMaiObject->GetAtkObject()));
|
atk_focus_tracker_notify(ATK_OBJECT(pMaiObject->GetAtkObject()));
|
||||||
|
rv = NS_OK;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case nsIAccessibleEventListener::EVENT_STATE_CHANGE:
|
case nsIAccessibleEventListener::EVENT_STATE_CHANGE:
|
||||||
|
@ -121,7 +164,7 @@ MaiTopLevel::HandleEvent(PRUint32 aEvent, nsIAccessible *aAccessible,
|
||||||
|
|
||||||
MAI_LOG_DEBUG(("\n\nReceived: EVENT_STATE_CHANGE\n"));
|
MAI_LOG_DEBUG(("\n\nReceived: EVENT_STATE_CHANGE\n"));
|
||||||
if (!aEventData)
|
if (!aEventData)
|
||||||
return NS_ERROR_FAILURE;
|
break;
|
||||||
|
|
||||||
pAtkStateChange = NS_REINTERPRET_CAST(AtkStateChange *, aEventData);
|
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()),
|
atk_object_notify_state_change(ATK_OBJECT(pMaiObject->GetAtkObject()),
|
||||||
atkState, pAtkStateChange->enable);
|
atkState, pAtkStateChange->enable);
|
||||||
|
rv = NS_OK;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -150,37 +194,42 @@ MaiTopLevel::HandleEvent(PRUint32 aEvent, nsIAccessible *aAccessible,
|
||||||
|
|
||||||
MAI_LOG_DEBUG(("\n\nReceived: EVENT_ATK_PROPERTY_CHANGE\n"));
|
MAI_LOG_DEBUG(("\n\nReceived: EVENT_ATK_PROPERTY_CHANGE\n"));
|
||||||
if (!aEventData)
|
if (!aEventData)
|
||||||
return NS_ERROR_FAILURE;
|
break;
|
||||||
|
|
||||||
pAtkPropChange = NS_REINTERPRET_CAST(AtkPropertyChange *, aEventData);
|
pAtkPropChange = NS_REINTERPRET_CAST(AtkPropertyChange *, aEventData);
|
||||||
values.property_name = pAtkPropertyNameArray[pAtkPropChange->type];
|
values.property_name = pAtkPropertyNameArray[pAtkPropChange->type];
|
||||||
|
|
||||||
MAI_LOG_DEBUG(("\n\nthe type of EVENT_ATK_PROPERTY_CHANGE: %d\n\n",
|
MAI_LOG_DEBUG(("\n\nthe type of EVENT_ATK_PROPERTY_CHANGE: %d\n\n",
|
||||||
pAtkPropChange->type));
|
pAtkPropChange->type));
|
||||||
|
|
||||||
switch (pAtkPropChange->type) {
|
switch (pAtkPropChange->type) {
|
||||||
case PROP_TABLE_CAPTION:
|
case PROP_TABLE_CAPTION:
|
||||||
case PROP_TABLE_SUMMARY:
|
case PROP_TABLE_SUMMARY:
|
||||||
MaiObject *aOldMaiObj, *aNewMaiObj;
|
|
||||||
|
|
||||||
if (pAtkPropChange->oldvalue)
|
if (pAtkPropChange->oldvalue)
|
||||||
aOldMaiObj = CreateMaiWidgetFor(NS_REINTERPRET_CAST
|
oldMaiObj = CreateMaiWidgetFor(NS_REINTERPRET_CAST
|
||||||
(nsIAccessible *,
|
(nsIAccessible *,
|
||||||
pAtkPropChange->oldvalue));
|
pAtkPropChange->oldvalue));
|
||||||
|
|
||||||
if (pAtkPropChange->newvalue)
|
if (pAtkPropChange->newvalue)
|
||||||
aNewMaiObj = CreateMaiWidgetFor(NS_REINTERPRET_CAST
|
newMaiObj = CreateMaiWidgetFor(NS_REINTERPRET_CAST
|
||||||
(nsIAccessible *,
|
(nsIAccessible *,
|
||||||
pAtkPropChange->newvalue));
|
pAtkPropChange->newvalue));
|
||||||
|
|
||||||
if (!aOldMaiObj || !aNewMaiObj )
|
if (oldMaiObj && newMaiObj) {
|
||||||
return NS_ERROR_FAILURE;
|
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;
|
break;
|
||||||
|
|
||||||
case PROP_TABLE_COLUMN_DESCRIPTION:
|
case PROP_TABLE_COLUMN_DESCRIPTION:
|
||||||
|
@ -191,6 +240,7 @@ MaiTopLevel::HandleEvent(PRUint32 aEvent, nsIAccessible *aAccessible,
|
||||||
g_value_set_int(&values.new_value,
|
g_value_set_int(&values.new_value,
|
||||||
*NS_REINTERPRET_CAST(gint *,
|
*NS_REINTERPRET_CAST(gint *,
|
||||||
pAtkPropChange->newvalue));
|
pAtkPropChange->newvalue));
|
||||||
|
rv = NS_OK;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
//Perhaps need more cases in the future
|
//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_set_pointer (&values.old_value, pAtkPropChange->oldvalue);
|
||||||
g_value_init (&values.new_value, G_TYPE_POINTER);
|
g_value_init (&values.new_value, G_TYPE_POINTER);
|
||||||
g_value_set_pointer (&values.new_value, pAtkPropChange->newvalue);
|
g_value_set_pointer (&values.new_value, pAtkPropChange->newvalue);
|
||||||
|
rv = NS_OK;
|
||||||
}
|
}
|
||||||
|
if (NS_SUCCEEDED(rv))
|
||||||
g_signal_emit_by_name(ATK_OBJECT(pMaiObject->GetAtkObject()),
|
g_signal_emit_by_name(ATK_OBJECT(pMaiObject->GetAtkObject()),
|
||||||
g_strconcat("property_change::",
|
g_strconcat("property_change::",
|
||||||
values.property_name),
|
values.property_name),
|
||||||
&values, NULL);
|
&values, NULL);
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -212,6 +263,7 @@ MaiTopLevel::HandleEvent(PRUint32 aEvent, nsIAccessible *aAccessible,
|
||||||
MAI_LOG_DEBUG(("\n\nReceived: EVENT_ATK_SELECTION_CHANGE\n"));
|
MAI_LOG_DEBUG(("\n\nReceived: EVENT_ATK_SELECTION_CHANGE\n"));
|
||||||
g_signal_emit_by_name(ATK_OBJECT(pMaiObject->GetAtkObject()),
|
g_signal_emit_by_name(ATK_OBJECT(pMaiObject->GetAtkObject()),
|
||||||
"selection_changed");
|
"selection_changed");
|
||||||
|
rv = NS_OK;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case nsIAccessibleEventListener::EVENT_ATK_TEXT_CHANGE:
|
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"));
|
MAI_LOG_DEBUG(("\n\nReceived: EVENT_ATK_TEXT_CHANGE\n"));
|
||||||
if (!aEventData)
|
if (!aEventData)
|
||||||
return NS_ERROR_FAILURE;
|
break;
|
||||||
|
|
||||||
pAtkTextChange = NS_REINTERPRET_CAST(AtkTextChange *, aEventData);
|
pAtkTextChange = NS_REINTERPRET_CAST(AtkTextChange *, aEventData);
|
||||||
g_signal_emit_by_name (ATK_OBJECT(pMaiObject->GetAtkObject()),
|
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",
|
"text_changed::insert":"text_changed::delete",
|
||||||
pAtkTextChange->start,
|
pAtkTextChange->start,
|
||||||
pAtkTextChange->length);
|
pAtkTextChange->length);
|
||||||
|
rv = NS_OK;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case nsIAccessibleEventListener::EVENT_ATK_TEXT_SELECTION_CHANGE:
|
case nsIAccessibleEventListener::EVENT_ATK_TEXT_SELECTION_CHANGE:
|
||||||
MAI_LOG_DEBUG(("\n\nReceived: EVENT_ATK_TEXT_SELECTION_CHANGE\n"));
|
MAI_LOG_DEBUG(("\n\nReceived: EVENT_ATK_TEXT_SELECTION_CHANGE\n"));
|
||||||
g_signal_emit_by_name(ATK_OBJECT(pMaiObject->GetAtkObject()),
|
g_signal_emit_by_name(ATK_OBJECT(pMaiObject->GetAtkObject()),
|
||||||
"text_selection_changed");
|
"text_selection_changed");
|
||||||
|
rv = NS_OK;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case nsIAccessibleEventListener::EVENT_ATK_TEXT_CARET_MOVE:
|
case nsIAccessibleEventListener::EVENT_ATK_TEXT_CARET_MOVE:
|
||||||
MAI_LOG_DEBUG(("\n\nReceived: EVENT_ATK_TEXT_CARET_MOVE\n"));
|
MAI_LOG_DEBUG(("\n\nReceived: EVENT_ATK_TEXT_CARET_MOVE\n"));
|
||||||
if (!aEventData)
|
if (!aEventData)
|
||||||
return NS_ERROR_FAILURE;
|
break;
|
||||||
|
|
||||||
MAI_LOG_DEBUG(("\n\nCaret postion: %d", *(gint *)aEventData ));
|
MAI_LOG_DEBUG(("\n\nCaret postion: %d", *(gint *)aEventData ));
|
||||||
g_signal_emit_by_name(ATK_OBJECT(pMaiObject->GetAtkObject()),
|
g_signal_emit_by_name(ATK_OBJECT(pMaiObject->GetAtkObject()),
|
||||||
"text_caret_moved",
|
"text_caret_moved",
|
||||||
// Curent caret position
|
// Curent caret position
|
||||||
*(gint *)aEventData);
|
*(gint *)aEventData);
|
||||||
|
rv = NS_OK;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case nsIAccessibleEventListener::EVENT_ATK_TABLE_MODEL_CHANGE:
|
case nsIAccessibleEventListener::EVENT_ATK_TABLE_MODEL_CHANGE:
|
||||||
MAI_LOG_DEBUG(("\n\nReceived: EVENT_ATK_TABLE_MODEL_CHANGE\n"));
|
MAI_LOG_DEBUG(("\n\nReceived: EVENT_ATK_TABLE_MODEL_CHANGE\n"));
|
||||||
g_signal_emit_by_name(ATK_OBJECT(pMaiObject->GetAtkObject()),
|
g_signal_emit_by_name(ATK_OBJECT(pMaiObject->GetAtkObject()),
|
||||||
"model_changed");
|
"model_changed");
|
||||||
|
rv = NS_OK;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case nsIAccessibleEventListener::EVENT_ATK_TABLE_ROW_INSERT:
|
case nsIAccessibleEventListener::EVENT_ATK_TABLE_ROW_INSERT:
|
||||||
MAI_LOG_DEBUG(("\n\nReceived: EVENT_ATK_TABLE_ROW_INSERT\n"));
|
MAI_LOG_DEBUG(("\n\nReceived: EVENT_ATK_TABLE_ROW_INSERT\n"));
|
||||||
if (!aEventData)
|
if (!aEventData)
|
||||||
return NS_ERROR_FAILURE;
|
break;
|
||||||
|
|
||||||
pAtkTableChange = NS_REINTERPRET_CAST(AtkTableChange *, aEventData);
|
pAtkTableChange = NS_REINTERPRET_CAST(AtkTableChange *, aEventData);
|
||||||
|
|
||||||
|
@ -266,12 +322,13 @@ MaiTopLevel::HandleEvent(PRUint32 aEvent, nsIAccessible *aAccessible,
|
||||||
pAtkTableChange->index,
|
pAtkTableChange->index,
|
||||||
// The number of the inserted
|
// The number of the inserted
|
||||||
pAtkTableChange->count);
|
pAtkTableChange->count);
|
||||||
|
rv = NS_OK;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case nsIAccessibleEventListener::EVENT_ATK_TABLE_ROW_DELETE:
|
case nsIAccessibleEventListener::EVENT_ATK_TABLE_ROW_DELETE:
|
||||||
MAI_LOG_DEBUG(("\n\nReceived: EVENT_ATK_TABLE_ROW_DELETE\n"));
|
MAI_LOG_DEBUG(("\n\nReceived: EVENT_ATK_TABLE_ROW_DELETE\n"));
|
||||||
if (!aEventData)
|
if (!aEventData)
|
||||||
return NS_ERROR_FAILURE;
|
break;
|
||||||
|
|
||||||
pAtkTableChange = NS_REINTERPRET_CAST(AtkTableChange *, aEventData);
|
pAtkTableChange = NS_REINTERPRET_CAST(AtkTableChange *, aEventData);
|
||||||
|
|
||||||
|
@ -281,18 +338,20 @@ MaiTopLevel::HandleEvent(PRUint32 aEvent, nsIAccessible *aAccessible,
|
||||||
pAtkTableChange->index,
|
pAtkTableChange->index,
|
||||||
// The number of the deleted
|
// The number of the deleted
|
||||||
pAtkTableChange->count);
|
pAtkTableChange->count);
|
||||||
|
rv = NS_OK;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case nsIAccessibleEventListener::EVENT_ATK_TABLE_ROW_REORDER:
|
case nsIAccessibleEventListener::EVENT_ATK_TABLE_ROW_REORDER:
|
||||||
MAI_LOG_DEBUG(("\n\nReceived: EVENT_ATK_TABLE_ROW_REORDER\n"));
|
MAI_LOG_DEBUG(("\n\nReceived: EVENT_ATK_TABLE_ROW_REORDER\n"));
|
||||||
g_signal_emit_by_name(ATK_OBJECT(pMaiObject->GetAtkObject()),
|
g_signal_emit_by_name(ATK_OBJECT(pMaiObject->GetAtkObject()),
|
||||||
"row_reordered");
|
"row_reordered");
|
||||||
|
rv = NS_OK;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case nsIAccessibleEventListener::EVENT_ATK_TABLE_COLUMN_INSERT:
|
case nsIAccessibleEventListener::EVENT_ATK_TABLE_COLUMN_INSERT:
|
||||||
MAI_LOG_DEBUG(("\n\nReceived: EVENT_ATK_TABLE_COLUMN_INSERT\n"));
|
MAI_LOG_DEBUG(("\n\nReceived: EVENT_ATK_TABLE_COLUMN_INSERT\n"));
|
||||||
if (!aEventData)
|
if (!aEventData)
|
||||||
return NS_ERROR_FAILURE;
|
break;
|
||||||
|
|
||||||
pAtkTableChange = NS_REINTERPRET_CAST(AtkTableChange *, aEventData);
|
pAtkTableChange = NS_REINTERPRET_CAST(AtkTableChange *, aEventData);
|
||||||
|
|
||||||
|
@ -302,12 +361,13 @@ MaiTopLevel::HandleEvent(PRUint32 aEvent, nsIAccessible *aAccessible,
|
||||||
pAtkTableChange->index,
|
pAtkTableChange->index,
|
||||||
// The number of the inserted
|
// The number of the inserted
|
||||||
pAtkTableChange->count);
|
pAtkTableChange->count);
|
||||||
|
rv = NS_OK;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case nsIAccessibleEventListener::EVENT_ATK_TABLE_COLUMN_DELETE:
|
case nsIAccessibleEventListener::EVENT_ATK_TABLE_COLUMN_DELETE:
|
||||||
MAI_LOG_DEBUG(("\n\nReceived: EVENT_ATK_TABLE_COLUMN_DELETE\n"));
|
MAI_LOG_DEBUG(("\n\nReceived: EVENT_ATK_TABLE_COLUMN_DELETE\n"));
|
||||||
if (!aEventData)
|
if (!aEventData)
|
||||||
return NS_ERROR_FAILURE;
|
break;
|
||||||
|
|
||||||
pAtkTableChange = NS_REINTERPRET_CAST(AtkTableChange *, aEventData);
|
pAtkTableChange = NS_REINTERPRET_CAST(AtkTableChange *, aEventData);
|
||||||
|
|
||||||
|
@ -317,18 +377,21 @@ MaiTopLevel::HandleEvent(PRUint32 aEvent, nsIAccessible *aAccessible,
|
||||||
pAtkTableChange->index,
|
pAtkTableChange->index,
|
||||||
// The number of the deleted
|
// The number of the deleted
|
||||||
pAtkTableChange->count);
|
pAtkTableChange->count);
|
||||||
|
rv = NS_OK;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case nsIAccessibleEventListener::EVENT_ATK_TABLE_COLUMN_REORDER:
|
case nsIAccessibleEventListener::EVENT_ATK_TABLE_COLUMN_REORDER:
|
||||||
MAI_LOG_DEBUG(("\n\nReceived: EVENT_ATK_TABLE_COLUMN_REORDER\n"));
|
MAI_LOG_DEBUG(("\n\nReceived: EVENT_ATK_TABLE_COLUMN_REORDER\n"));
|
||||||
g_signal_emit_by_name(ATK_OBJECT(pMaiObject->GetAtkObject()),
|
g_signal_emit_by_name(ATK_OBJECT(pMaiObject->GetAtkObject()),
|
||||||
"column_reordered");
|
"column_reordered");
|
||||||
|
rv = NS_OK;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case nsIAccessibleEventListener::EVENT_ATK_VISIBLE_DATA_CHANGE:
|
case nsIAccessibleEventListener::EVENT_ATK_VISIBLE_DATA_CHANGE:
|
||||||
MAI_LOG_DEBUG(("\n\nReceived: EVENT_ATK_VISIBLE_DATA_CHANGE\n"));
|
MAI_LOG_DEBUG(("\n\nReceived: EVENT_ATK_VISIBLE_DATA_CHANGE\n"));
|
||||||
g_signal_emit_by_name(ATK_OBJECT(pMaiObject->GetAtkObject()),
|
g_signal_emit_by_name(ATK_OBJECT(pMaiObject->GetAtkObject()),
|
||||||
"visible_data_changed");
|
"visible_data_changed");
|
||||||
|
rv = NS_OK;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
// Is a superclass of ATK event children_changed
|
// Is a superclass of ATK event children_changed
|
||||||
|
@ -352,6 +415,7 @@ MaiTopLevel::HandleEvent(PRUint32 aEvent, nsIAccessible *aAccessible,
|
||||||
pAtkChildrenChange->index,
|
pAtkChildrenChange->index,
|
||||||
ATK_OBJECT(childMaiObject->GetAtkObject()),
|
ATK_OBJECT(childMaiObject->GetAtkObject()),
|
||||||
NULL);
|
NULL);
|
||||||
|
g_object_unref(childMaiObject->GetAtkObject());
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
g_signal_emit_by_name (ATK_OBJECT(pMaiObject->GetAtkObject()),
|
g_signal_emit_by_name (ATK_OBJECT(pMaiObject->GetAtkObject()),
|
||||||
|
@ -359,6 +423,7 @@ MaiTopLevel::HandleEvent(PRUint32 aEvent, nsIAccessible *aAccessible,
|
||||||
-1, NULL, NULL);
|
-1, NULL, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
rv = NS_OK;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -372,12 +437,14 @@ MaiTopLevel::HandleEvent(PRUint32 aEvent, nsIAccessible *aAccessible,
|
||||||
atk_focus_tracker_notify(ATK_OBJECT(pMaiObject->GetAtkObject()));
|
atk_focus_tracker_notify(ATK_OBJECT(pMaiObject->GetAtkObject()));
|
||||||
g_signal_emit_by_name(ATK_OBJECT(pMaiObject->GetAtkObject()),
|
g_signal_emit_by_name(ATK_OBJECT(pMaiObject->GetAtkObject()),
|
||||||
"selection_changed");
|
"selection_changed");
|
||||||
|
rv = NS_OK;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case nsIAccessibleEventListener::EVENT_MENUEND:
|
case nsIAccessibleEventListener::EVENT_MENUEND:
|
||||||
MAI_LOG_DEBUG(("\n\nReceived: EVENT_MENUEND\n"));
|
MAI_LOG_DEBUG(("\n\nReceived: EVENT_MENUEND\n"));
|
||||||
g_signal_emit_by_name(ATK_OBJECT(pMaiObject->GetAtkObject()),
|
g_signal_emit_by_name(ATK_OBJECT(pMaiObject->GetAtkObject()),
|
||||||
"selection_changed");
|
"selection_changed");
|
||||||
|
rv = NS_OK;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
@ -386,7 +453,9 @@ MaiTopLevel::HandleEvent(PRUint32 aEvent, nsIAccessible *aAccessible,
|
||||||
break;
|
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);
|
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 */
|
/* static */
|
||||||
AtkStateType
|
AtkStateType
|
||||||
MaiTopLevel::TranslateAState(PRUint32 aAccState)
|
MaiTopLevel::TranslateAState(PRUint32 aAccState)
|
||||||
|
|
|
@ -56,6 +56,7 @@ class MaiTopLevel: public MaiWidget, public nsIAccessibleEventListener
|
||||||
public:
|
public:
|
||||||
MaiTopLevel(nsIAccessible *aAcc);
|
MaiTopLevel(nsIAccessible *aAcc);
|
||||||
virtual ~MaiTopLevel();
|
virtual ~MaiTopLevel();
|
||||||
|
static MaiTopLevel * Create(nsIAccessible *aAcc);
|
||||||
|
|
||||||
NS_DECL_ISUPPORTS
|
NS_DECL_ISUPPORTS
|
||||||
// nsIAccessibleEventListener
|
// nsIAccessibleEventListener
|
||||||
|
|
|
@ -42,12 +42,17 @@
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
|
||||||
#include "nsMaiUtil.h"
|
#include "nsMaiUtil.h"
|
||||||
|
#include "nsMaiCache.h"
|
||||||
#include "nsMaiAppRoot.h"
|
#include "nsMaiAppRoot.h"
|
||||||
|
|
||||||
static gboolean mai_shutdown(void);
|
static gboolean mai_shutdown(void);
|
||||||
static void mai_delete_root(void);
|
static void mai_delete_root(void);
|
||||||
static MaiAppRoot *mai_create_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);
|
static void mai_util_class_init(MaiUtilClass *klass);
|
||||||
|
|
||||||
/* atkutil.h */
|
/* atkutil.h */
|
||||||
|
@ -305,6 +310,9 @@ mai_init(MaiHook **aMaiHook)
|
||||||
/* Initialize the MAI Utility class */
|
/* Initialize the MAI Utility class */
|
||||||
g_type_class_unref(g_type_class_ref(MAI_TYPE_UTIL));
|
g_type_class_unref(g_type_class_ref(MAI_TYPE_UTIL));
|
||||||
|
|
||||||
|
MaiHashTable::Init();
|
||||||
|
mai_create_cache();
|
||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -323,6 +331,9 @@ mai_shutdown(void)
|
||||||
sMaiHook.RemoveTopLevelAccessible = NULL;
|
sMaiHook.RemoveTopLevelAccessible = NULL;
|
||||||
|
|
||||||
mai_delete_root();
|
mai_delete_root();
|
||||||
|
mai_delete_cache();
|
||||||
|
MaiHashTable::Destroy();
|
||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -338,6 +349,7 @@ mai_create_root(void)
|
||||||
}
|
}
|
||||||
if (!sRootAccessible) {
|
if (!sRootAccessible) {
|
||||||
sRootAccessible = new MaiAppRoot();
|
sRootAccessible = new MaiAppRoot();
|
||||||
|
MaiHashTable::Add(sRootAccessible);
|
||||||
NS_ASSERTION(sRootAccessible, "Fail to create MaiAppRoot");
|
NS_ASSERTION(sRootAccessible, "Fail to create MaiAppRoot");
|
||||||
|
|
||||||
/* initialize the MAI hook
|
/* initialize the MAI hook
|
||||||
|
@ -363,23 +375,41 @@ void
|
||||||
mai_delete_root(void)
|
mai_delete_root(void)
|
||||||
{
|
{
|
||||||
if (sRootAccessible) {
|
if (sRootAccessible) {
|
||||||
delete sRootAccessible;
|
g_object_unref(sRootAccessible->GetAtkObject());
|
||||||
sRootAccessible = NULL;
|
sRootAccessible = NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* return the reference of MaiCache.
|
/* return the reference of MaiCache.
|
||||||
*/
|
*/
|
||||||
|
static MaiCache *sMaiCache = NULL;
|
||||||
|
|
||||||
MaiCache *
|
MaiCache *
|
||||||
mai_get_cache(void)
|
mai_create_cache(void)
|
||||||
{
|
{
|
||||||
if (!mai_initialized) {
|
if (!mai_initialized) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
MaiAppRoot *root = mai_get_root();
|
if (!sMaiCache) {
|
||||||
if (root)
|
sMaiCache = new MaiCache();
|
||||||
return root->GetCache();
|
NS_ASSERTION(sMaiCache, "Fail to create MaiCache");
|
||||||
return NULL;
|
}
|
||||||
|
return sMaiCache;
|
||||||
|
}
|
||||||
|
|
||||||
|
MaiCache *
|
||||||
|
mai_get_cache(void)
|
||||||
|
{
|
||||||
|
return sMaiCache;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
mai_delete_cache(void)
|
||||||
|
{
|
||||||
|
if (sMaiCache) {
|
||||||
|
delete sMaiCache;
|
||||||
|
sMaiCache = NULL;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
gboolean
|
gboolean
|
||||||
|
@ -387,35 +417,16 @@ mai_add_toplevel_accessible(nsIAccessible *toplevel)
|
||||||
{
|
{
|
||||||
g_return_val_if_fail(toplevel != NULL, TRUE);
|
g_return_val_if_fail(toplevel != NULL, TRUE);
|
||||||
|
|
||||||
#if 1
|
|
||||||
MaiAppRoot *root;
|
MaiAppRoot *root;
|
||||||
root = mai_get_root();
|
root = mai_get_root();
|
||||||
if (!root)
|
if (!root)
|
||||||
return FALSE;
|
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);
|
g_return_val_if_fail(mai_top_level != NULL, PR_FALSE);
|
||||||
gboolean res = root->AddMaiTopLevel(mai_top_level);
|
gboolean res = root->AddMaiTopLevel(mai_top_level);
|
||||||
|
|
||||||
/* root will add ref for itself use */
|
|
||||||
g_object_unref(mai_top_level->GetAtkObject());
|
g_object_unref(mai_top_level->GetAtkObject());
|
||||||
return res;
|
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
|
gboolean
|
||||||
|
@ -426,8 +437,9 @@ mai_remove_toplevel_accessible(nsIAccessible *toplevel)
|
||||||
MaiAppRoot *root;
|
MaiAppRoot *root;
|
||||||
root = mai_get_root();
|
root = mai_get_root();
|
||||||
if (root) {
|
if (root) {
|
||||||
MaiTopLevel *mai_top_level = root->FindMaiTopLevel(toplevel);
|
guint uid = ::GetNSAccessibleUniqueID(toplevel);
|
||||||
return root->RemoveMaiTopLevel(mai_top_level);
|
gboolean res = root->RemoveMaiTopLevelByID(uid);
|
||||||
|
return res;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
|
@ -77,7 +77,7 @@ struct _MaiUtilClass
|
||||||
};
|
};
|
||||||
|
|
||||||
#define MAI_VERSION "0.0.6"
|
#define MAI_VERSION "0.0.6"
|
||||||
#define MAI_NAME "MAI-Mozilla Atk Interface"
|
#define MAI_NAME "mozilla"
|
||||||
|
|
||||||
MaiAppRoot *mai_get_root(void);
|
MaiAppRoot *mai_get_root(void);
|
||||||
MaiCache *mai_get_cache(void);
|
MaiCache *mai_get_cache(void);
|
||||||
|
|
|
@ -60,6 +60,7 @@
|
||||||
#include "nsMaiInterfaceValue.h"
|
#include "nsMaiInterfaceValue.h"
|
||||||
|
|
||||||
#include "nsMaiUtil.h"
|
#include "nsMaiUtil.h"
|
||||||
|
#include "nsMaiCache.h"
|
||||||
|
|
||||||
G_BEGIN_DECLS
|
G_BEGIN_DECLS
|
||||||
|
|
||||||
|
@ -120,6 +121,69 @@ MaiWidget::~MaiWidget()
|
||||||
g_hash_table_destroy(mChildren);
|
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
|
#ifdef MAI_LOGGING
|
||||||
void
|
void
|
||||||
MaiWidget::DumpMaiObjectInfo(gint aDepth)
|
MaiWidget::DumpMaiObjectInfo(gint aDepth)
|
||||||
|
@ -167,61 +231,12 @@ MaiWidget::GetMaiInterface(MaiInterfaceType aIfaceType)
|
||||||
return mMaiInterface[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
|
void
|
||||||
MaiWidget::ChildrenChange(AtkChildrenChange *event)
|
MaiWidget::ChildrenChange(AtkChildrenChange *event)
|
||||||
{
|
{
|
||||||
MaiWidget *maiChild;
|
MaiWidget *maiChild;
|
||||||
if (event && event->child &&
|
if (event && event->child &&
|
||||||
(maiChild = CreateAndCache(event->child))) {
|
(maiChild = Create(event->child))) {
|
||||||
//update the specified child, but now use the easiest way.
|
//update the specified child, but now use the easiest way.
|
||||||
g_hash_table_destroy(mChildren);
|
g_hash_table_destroy(mChildren);
|
||||||
mChildren = g_hash_table_new(g_direct_hash, NULL);
|
mChildren = g_hash_table_new(g_direct_hash, NULL);
|
||||||
|
@ -407,7 +422,7 @@ MaiWidget::GetParent(void)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
/* create a maiWidget for parent */
|
/* create a maiWidget for parent */
|
||||||
return CreateAndCache(accParent);
|
return Create(accParent);
|
||||||
}
|
}
|
||||||
|
|
||||||
gint
|
gint
|
||||||
|
@ -430,16 +445,19 @@ MaiWidget::RefChild(gint aChildIndex)
|
||||||
|
|
||||||
MaiObject *maiChild = NULL;
|
MaiObject *maiChild = NULL;
|
||||||
guint uid;
|
guint uid;
|
||||||
// look in cache first
|
|
||||||
MaiCache *maiCache = mai_get_cache();
|
// look in hashtable first
|
||||||
if (maiCache) {
|
uid = GetChildUniqueID(aChildIndex);
|
||||||
uid = GetChildUniqueID(aChildIndex);
|
if (uid > 0 && (maiChild = MaiHashTable::Lookup(uid))) {
|
||||||
if (uid > 0 && (maiChild = maiCache->Fetch(uid))) {
|
MAI_LOG_DEBUG(("got child 0x%x from hash table\n", (guint)maiChild));
|
||||||
MAI_LOG_DEBUG(("got child 0x%x from cache\n", (guint)maiChild));
|
g_object_ref(maiChild->GetAtkObject());
|
||||||
return maiChild;
|
|
||||||
}
|
//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
|
// nsIAccessible child index starts with 1
|
||||||
gint accChildIndex = 1;
|
gint accChildIndex = 1;
|
||||||
nsCOMPtr<nsIAccessible> accChild = NULL;
|
nsCOMPtr<nsIAccessible> accChild = NULL;
|
||||||
|
@ -459,16 +477,12 @@ MaiWidget::RefChild(gint aChildIndex)
|
||||||
// user, since they point to the same dom node.
|
// user, since they point to the same dom node.
|
||||||
// So, maybe the it has been cached.
|
// So, maybe the it has been cached.
|
||||||
uid = ::GetNSAccessibleUniqueID(accChild);
|
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
|
// update children uid list
|
||||||
SetChildUniqueID(aChildIndex, uid);
|
SetChildUniqueID(aChildIndex, uid);
|
||||||
|
maiChild = Create(accChild);
|
||||||
|
|
||||||
|
//this will addref parent
|
||||||
|
atk_object_set_parent(maiChild->GetAtkObject(), GetAtkObject());
|
||||||
return maiChild;
|
return maiChild;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -552,7 +566,7 @@ MaiWidget::SetChildUniqueID(gint aChildIndex, guint aChildUid)
|
||||||
void
|
void
|
||||||
classInitCB(AtkObjectClass *aClass)
|
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);
|
parent_class = g_type_class_peek_parent(aClass);
|
||||||
|
|
||||||
|
|
|
@ -85,6 +85,8 @@ class MaiWidget: public MaiObject
|
||||||
public:
|
public:
|
||||||
MaiWidget(nsIAccessible *aAcc);
|
MaiWidget(nsIAccessible *aAcc);
|
||||||
virtual ~MaiWidget();
|
virtual ~MaiWidget();
|
||||||
|
static MaiWidget *Create(nsIAccessible *aAcc);
|
||||||
|
|
||||||
#ifdef MAI_LOGGING
|
#ifdef MAI_LOGGING
|
||||||
virtual void DumpMaiObjectInfo(int aDepth);
|
virtual void DumpMaiObjectInfo(int aDepth);
|
||||||
#endif
|
#endif
|
||||||
|
|
Загрузка…
Ссылка в новой задаче