2007-03-22 10:30:00 -07:00
|
|
|
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
|
|
|
/* vim:expandtab:shiftwidth=4:tabstop=4:
|
|
|
|
*/
|
|
|
|
/* ***** BEGIN LICENSE BLOCK *****
|
|
|
|
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
|
|
|
*
|
|
|
|
* The contents of this file are subject to the Mozilla Public License Version
|
|
|
|
* 1.1 (the "License"); you may not use this file except in compliance with
|
|
|
|
* the License. You may obtain a copy of the License at
|
|
|
|
* http://www.mozilla.org/MPL/
|
|
|
|
*
|
|
|
|
* Software distributed under the License is distributed on an "AS IS" basis,
|
|
|
|
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
|
|
|
* for the specific language governing rights and limitations under the
|
|
|
|
* License.
|
|
|
|
*
|
|
|
|
* The Original Code is mozilla.org code.
|
|
|
|
*
|
|
|
|
* The Initial Developer of the Original Code is
|
|
|
|
* Sun Microsystems, Inc.
|
|
|
|
* Portions created by the Initial Developer are Copyright (C) 2002
|
|
|
|
* the Initial Developer. All Rights Reserved.
|
|
|
|
*
|
|
|
|
* Contributor(s):
|
|
|
|
* Bolian Yin (bolian.yin@sun.com)
|
|
|
|
* John Sun (john.sun@sun.com)
|
|
|
|
*
|
|
|
|
* Alternatively, the contents of this file may be used under the terms of
|
|
|
|
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
|
|
|
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
|
|
|
* in which case the provisions of the GPL or the LGPL are applicable instead
|
|
|
|
* of those above. If you wish to allow use of your version of this file only
|
|
|
|
* under the terms of either the GPL or the LGPL, and not to allow others to
|
|
|
|
* use your version of this file under the terms of the MPL, indicate your
|
|
|
|
* decision by deleting the provisions above and replace them with the notice
|
|
|
|
* and other provisions required by the GPL or the LGPL. If you do not delete
|
|
|
|
* the provisions above, a recipient may use your version of this file under
|
|
|
|
* the terms of any one of the MPL, the GPL or the LGPL.
|
|
|
|
*
|
|
|
|
* ***** END LICENSE BLOCK ***** */
|
|
|
|
|
|
|
|
#include "nsAccessibleWrap.h"
|
2007-06-17 22:47:33 -07:00
|
|
|
#include "nsRootAccessible.h"
|
|
|
|
#include "nsDocAccessibleWrap.h"
|
|
|
|
#include "nsIAccessibleValue.h"
|
2007-03-22 10:30:00 -07:00
|
|
|
#include "nsString.h"
|
2007-06-01 20:01:38 -07:00
|
|
|
#include "nsAutoPtr.h"
|
2007-03-22 10:30:00 -07:00
|
|
|
#include "prprf.h"
|
|
|
|
#include "nsRoleMap.h"
|
|
|
|
#include "nsStateMap.h"
|
|
|
|
|
|
|
|
#include "nsMaiInterfaceComponent.h"
|
|
|
|
#include "nsMaiInterfaceAction.h"
|
|
|
|
#include "nsMaiInterfaceText.h"
|
|
|
|
#include "nsMaiInterfaceEditableText.h"
|
|
|
|
#include "nsMaiInterfaceSelection.h"
|
|
|
|
#include "nsMaiInterfaceValue.h"
|
|
|
|
#include "nsMaiInterfaceHypertext.h"
|
|
|
|
#include "nsMaiInterfaceHyperlinkImpl.h"
|
|
|
|
#include "nsMaiInterfaceTable.h"
|
|
|
|
#include "nsXPCOMStrings.h"
|
|
|
|
#include "nsComponentManagerUtils.h"
|
|
|
|
#include "nsMaiInterfaceDocument.h"
|
|
|
|
#include "nsMaiInterfaceImage.h"
|
|
|
|
|
2007-06-01 20:01:38 -07:00
|
|
|
#include "nsAppRootAccessible.h"
|
|
|
|
|
2007-03-22 10:30:00 -07:00
|
|
|
extern "C" GType g_atk_hyperlink_impl_type; //defined in nsAppRootAccessible.cpp
|
|
|
|
|
|
|
|
/* MaiAtkObject */
|
|
|
|
|
|
|
|
enum {
|
|
|
|
ACTIVATE,
|
|
|
|
CREATE,
|
|
|
|
DEACTIVATE,
|
|
|
|
DESTROY,
|
|
|
|
MAXIMIZE,
|
|
|
|
MINIMIZE,
|
|
|
|
RESIZE,
|
|
|
|
RESTORE,
|
|
|
|
LAST_SIGNAL
|
|
|
|
};
|
|
|
|
|
|
|
|
enum MaiInterfaceType {
|
|
|
|
MAI_INTERFACE_COMPONENT, /* 0 */
|
|
|
|
MAI_INTERFACE_ACTION,
|
|
|
|
MAI_INTERFACE_VALUE,
|
|
|
|
MAI_INTERFACE_EDITABLE_TEXT,
|
|
|
|
MAI_INTERFACE_HYPERTEXT,
|
|
|
|
MAI_INTERFACE_HYPERLINK_IMPL,
|
|
|
|
MAI_INTERFACE_SELECTION,
|
|
|
|
MAI_INTERFACE_TABLE,
|
|
|
|
MAI_INTERFACE_TEXT,
|
|
|
|
MAI_INTERFACE_DOCUMENT,
|
|
|
|
MAI_INTERFACE_IMAGE /* 10 */
|
|
|
|
};
|
|
|
|
|
|
|
|
static GType GetAtkTypeForMai(MaiInterfaceType type)
|
|
|
|
{
|
|
|
|
switch (type) {
|
|
|
|
case MAI_INTERFACE_COMPONENT:
|
|
|
|
return ATK_TYPE_COMPONENT;
|
|
|
|
case MAI_INTERFACE_ACTION:
|
|
|
|
return ATK_TYPE_ACTION;
|
|
|
|
case MAI_INTERFACE_VALUE:
|
|
|
|
return ATK_TYPE_VALUE;
|
|
|
|
case MAI_INTERFACE_EDITABLE_TEXT:
|
|
|
|
return ATK_TYPE_EDITABLE_TEXT;
|
|
|
|
case MAI_INTERFACE_HYPERTEXT:
|
|
|
|
return ATK_TYPE_HYPERTEXT;
|
|
|
|
case MAI_INTERFACE_HYPERLINK_IMPL:
|
|
|
|
return g_atk_hyperlink_impl_type;
|
|
|
|
case MAI_INTERFACE_SELECTION:
|
|
|
|
return ATK_TYPE_SELECTION;
|
|
|
|
case MAI_INTERFACE_TABLE:
|
|
|
|
return ATK_TYPE_TABLE;
|
|
|
|
case MAI_INTERFACE_TEXT:
|
|
|
|
return ATK_TYPE_TEXT;
|
|
|
|
case MAI_INTERFACE_DOCUMENT:
|
|
|
|
return ATK_TYPE_DOCUMENT;
|
|
|
|
case MAI_INTERFACE_IMAGE:
|
|
|
|
return ATK_TYPE_IMAGE;
|
|
|
|
}
|
|
|
|
return G_TYPE_INVALID;
|
|
|
|
}
|
|
|
|
|
|
|
|
static const GInterfaceInfo atk_if_infos[] = {
|
|
|
|
{(GInterfaceInitFunc)componentInterfaceInitCB,
|
|
|
|
(GInterfaceFinalizeFunc) NULL, NULL},
|
|
|
|
{(GInterfaceInitFunc)actionInterfaceInitCB,
|
|
|
|
(GInterfaceFinalizeFunc) NULL, NULL},
|
|
|
|
{(GInterfaceInitFunc)valueInterfaceInitCB,
|
|
|
|
(GInterfaceFinalizeFunc) NULL, NULL},
|
|
|
|
{(GInterfaceInitFunc)editableTextInterfaceInitCB,
|
|
|
|
(GInterfaceFinalizeFunc) NULL, NULL},
|
|
|
|
{(GInterfaceInitFunc)hypertextInterfaceInitCB,
|
|
|
|
(GInterfaceFinalizeFunc) NULL, NULL},
|
|
|
|
{(GInterfaceInitFunc)hyperlinkImplInterfaceInitCB,
|
|
|
|
(GInterfaceFinalizeFunc) NULL, NULL},
|
|
|
|
{(GInterfaceInitFunc)selectionInterfaceInitCB,
|
|
|
|
(GInterfaceFinalizeFunc) NULL, NULL},
|
|
|
|
{(GInterfaceInitFunc)tableInterfaceInitCB,
|
|
|
|
(GInterfaceFinalizeFunc) NULL, NULL},
|
|
|
|
{(GInterfaceInitFunc)textInterfaceInitCB,
|
|
|
|
(GInterfaceFinalizeFunc) NULL, NULL},
|
|
|
|
{(GInterfaceInitFunc)documentInterfaceInitCB,
|
|
|
|
(GInterfaceFinalizeFunc) NULL, NULL},
|
|
|
|
{(GInterfaceInitFunc)imageInterfaceInitCB,
|
|
|
|
(GInterfaceFinalizeFunc) NULL, NULL}
|
|
|
|
};
|
|
|
|
|
|
|
|
/**
|
|
|
|
* This MaiAtkObject is a thin wrapper, in the MAI namespace, for AtkObject
|
|
|
|
*/
|
|
|
|
struct MaiAtkObject
|
|
|
|
{
|
|
|
|
AtkObject parent;
|
|
|
|
/*
|
|
|
|
* The nsAccessibleWrap whose properties and features are exported
|
|
|
|
* via this object instance.
|
|
|
|
*/
|
|
|
|
nsAccessibleWrap *accWrap;
|
|
|
|
};
|
|
|
|
|
|
|
|
struct MaiAtkObjectClass
|
|
|
|
{
|
|
|
|
AtkObjectClass parent_class;
|
|
|
|
};
|
|
|
|
|
|
|
|
static guint mai_atk_object_signals [LAST_SIGNAL] = { 0, };
|
|
|
|
|
|
|
|
#ifdef MAI_LOGGING
|
|
|
|
PRInt32 sMaiAtkObjCreated = 0;
|
|
|
|
PRInt32 sMaiAtkObjDeleted = 0;
|
|
|
|
#endif
|
|
|
|
|
|
|
|
G_BEGIN_DECLS
|
|
|
|
/* callbacks for MaiAtkObject */
|
|
|
|
static void classInitCB(AtkObjectClass *aClass);
|
|
|
|
static void initializeCB(AtkObject *aAtkObj, gpointer aData);
|
|
|
|
static void finalizeCB(GObject *aObj);
|
|
|
|
|
|
|
|
/* callbacks for AtkObject virtual functions */
|
|
|
|
static const gchar* getNameCB (AtkObject *aAtkObj);
|
|
|
|
/* getDescriptionCB is also used by image interface */
|
|
|
|
const gchar* getDescriptionCB (AtkObject *aAtkObj);
|
|
|
|
static AtkRole getRoleCB(AtkObject *aAtkObj);
|
|
|
|
static AtkAttributeSet* getAttributesCB(AtkObject *aAtkObj);
|
|
|
|
static AtkObject* getParentCB(AtkObject *aAtkObj);
|
|
|
|
static gint getChildCountCB(AtkObject *aAtkObj);
|
|
|
|
static AtkObject* refChildCB(AtkObject *aAtkObj, gint aChildIndex);
|
|
|
|
static gint getIndexInParentCB(AtkObject *aAtkObj);
|
|
|
|
static AtkStateSet* refStateSetCB(AtkObject *aAtkObj);
|
|
|
|
static AtkRelationSet* refRelationSetCB(AtkObject *aAtkObj);
|
|
|
|
|
|
|
|
/* the missing atkobject virtual functions */
|
|
|
|
/*
|
|
|
|
static AtkLayer getLayerCB(AtkObject *aAtkObj);
|
|
|
|
static gint getMdiZorderCB(AtkObject *aAtkObj);
|
|
|
|
static void SetNameCB(AtkObject *aAtkObj,
|
|
|
|
const gchar *name);
|
|
|
|
static void SetDescriptionCB(AtkObject *aAtkObj,
|
|
|
|
const gchar *description);
|
|
|
|
static void SetParentCB(AtkObject *aAtkObj,
|
|
|
|
AtkObject *parent);
|
|
|
|
static void SetRoleCB(AtkObject *aAtkObj,
|
|
|
|
AtkRole role);
|
|
|
|
static guint ConnectPropertyChangeHandlerCB(
|
|
|
|
AtkObject *aObj,
|
|
|
|
AtkPropertyChangeHandler *handler);
|
|
|
|
static void RemovePropertyChangeHandlerCB(
|
|
|
|
AtkObject *aAtkObj,
|
|
|
|
guint handler_id);
|
|
|
|
static void InitializeCB(AtkObject *aAtkObj,
|
|
|
|
gpointer data);
|
|
|
|
static void ChildrenChangedCB(AtkObject *aAtkObj,
|
|
|
|
guint change_index,
|
|
|
|
gpointer changed_child);
|
|
|
|
static void FocusEventCB(AtkObject *aAtkObj,
|
|
|
|
gboolean focus_in);
|
|
|
|
static void PropertyChangeCB(AtkObject *aAtkObj,
|
|
|
|
AtkPropertyValues *values);
|
|
|
|
static void StateChangeCB(AtkObject *aAtkObj,
|
|
|
|
const gchar *name,
|
|
|
|
gboolean state_set);
|
|
|
|
static void VisibleDataChangedCB(AtkObject *aAtkObj);
|
|
|
|
*/
|
|
|
|
G_END_DECLS
|
|
|
|
|
|
|
|
static GType GetMaiAtkType(PRUint16 interfacesBits);
|
|
|
|
static const char * GetUniqueMaiAtkTypeName(PRUint16 interfacesBits);
|
|
|
|
|
|
|
|
static gpointer parent_class = NULL;
|
|
|
|
|
2007-05-28 23:41:14 -07:00
|
|
|
static GQuark quark_mai_hyperlink = 0;
|
|
|
|
|
2007-03-22 10:30:00 -07:00
|
|
|
GType
|
|
|
|
mai_atk_object_get_type(void)
|
|
|
|
{
|
|
|
|
static GType type = 0;
|
|
|
|
|
|
|
|
if (!type) {
|
|
|
|
static const GTypeInfo tinfo = {
|
|
|
|
sizeof(MaiAtkObjectClass),
|
|
|
|
(GBaseInitFunc)NULL,
|
|
|
|
(GBaseFinalizeFunc)NULL,
|
|
|
|
(GClassInitFunc)classInitCB,
|
|
|
|
(GClassFinalizeFunc)NULL,
|
|
|
|
NULL, /* class data */
|
|
|
|
sizeof(MaiAtkObject), /* instance size */
|
|
|
|
0, /* nb preallocs */
|
|
|
|
(GInstanceInitFunc)NULL,
|
|
|
|
NULL /* value table */
|
|
|
|
};
|
|
|
|
|
|
|
|
type = g_type_register_static(ATK_TYPE_OBJECT,
|
|
|
|
"MaiAtkObject", &tinfo, GTypeFlags(0));
|
2007-05-28 23:41:14 -07:00
|
|
|
quark_mai_hyperlink = g_quark_from_static_string("MaiHyperlink");
|
2007-03-22 10:30:00 -07:00
|
|
|
}
|
|
|
|
return type;
|
|
|
|
}
|
|
|
|
|
2007-04-20 00:29:08 -07:00
|
|
|
/*
|
|
|
|
* Must keep sychronization with enumerate AtkProperty in
|
|
|
|
* accessible/src/base/nsAccessibleEventData.h
|
|
|
|
*/
|
|
|
|
static char * sAtkPropertyNameArray[PROP_LAST] = {
|
|
|
|
0,
|
|
|
|
"accessible-name",
|
|
|
|
"accessible-description",
|
|
|
|
"accessible-parent",
|
|
|
|
"accessible-role",
|
|
|
|
"accessible-layer",
|
|
|
|
"accessible-mdi-zorder",
|
|
|
|
"accessible-table-caption",
|
|
|
|
"accessible-table-column-description",
|
|
|
|
"accessible-table-column-header",
|
|
|
|
"accessible-table-row-description",
|
|
|
|
"accessible-table-row-header",
|
|
|
|
"accessible-table-summary"
|
|
|
|
};
|
|
|
|
|
2007-03-22 10:30:00 -07:00
|
|
|
#ifdef MAI_LOGGING
|
|
|
|
PRInt32 nsAccessibleWrap::mAccWrapCreated = 0;
|
|
|
|
PRInt32 nsAccessibleWrap::mAccWrapDeleted = 0;
|
|
|
|
#endif
|
|
|
|
|
|
|
|
nsAccessibleWrap::nsAccessibleWrap(nsIDOMNode* aNode,
|
|
|
|
nsIWeakReference *aShell)
|
|
|
|
: nsAccessible(aNode, aShell),
|
|
|
|
mAtkObject(nsnull)
|
|
|
|
{
|
|
|
|
#ifdef MAI_LOGGING
|
|
|
|
++mAccWrapCreated;
|
|
|
|
#endif
|
|
|
|
MAI_LOG_DEBUG(("==nsAccessibleWrap creating: this=%p,total=%d left=%d\n",
|
|
|
|
(void*)this, mAccWrapCreated,
|
|
|
|
(mAccWrapCreated-mAccWrapDeleted)));
|
|
|
|
}
|
|
|
|
|
|
|
|
nsAccessibleWrap::~nsAccessibleWrap()
|
|
|
|
{
|
|
|
|
|
|
|
|
#ifdef MAI_LOGGING
|
|
|
|
++mAccWrapDeleted;
|
|
|
|
#endif
|
|
|
|
MAI_LOG_DEBUG(("==nsAccessibleWrap deleting: this=%p,total=%d left=%d\n",
|
|
|
|
(void*)this, mAccWrapDeleted,
|
|
|
|
(mAccWrapCreated-mAccWrapDeleted)));
|
2007-05-28 23:41:14 -07:00
|
|
|
}
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2007-07-02 04:18:07 -07:00
|
|
|
void nsAccessibleWrap::ShutdownAtkObject()
|
2007-05-28 23:41:14 -07:00
|
|
|
{
|
2007-03-22 10:30:00 -07:00
|
|
|
if (mAtkObject) {
|
|
|
|
if (IS_MAI_OBJECT(mAtkObject)) {
|
|
|
|
MAI_ATK_OBJECT(mAtkObject)->accWrap = nsnull;
|
|
|
|
}
|
2007-05-28 23:41:14 -07:00
|
|
|
SetMaiHyperlink(nsnull);
|
2007-03-22 10:30:00 -07:00
|
|
|
g_object_unref(mAtkObject);
|
2007-05-28 23:41:14 -07:00
|
|
|
mAtkObject = nsnull;
|
|
|
|
}
|
2007-07-02 04:18:07 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP nsAccessibleWrap::Shutdown()
|
|
|
|
{
|
|
|
|
ShutdownAtkObject();
|
2007-05-28 23:41:14 -07:00
|
|
|
return nsAccessible::Shutdown();
|
|
|
|
}
|
|
|
|
|
|
|
|
MaiHyperlink* nsAccessibleWrap::GetMaiHyperlink(PRBool aCreate /* = PR_TRUE */)
|
|
|
|
{
|
|
|
|
// make sure mAtkObject is created
|
|
|
|
GetAtkObject();
|
|
|
|
|
|
|
|
NS_ASSERTION(quark_mai_hyperlink, "quark_mai_hyperlink not initialized");
|
|
|
|
NS_ASSERTION(IS_MAI_OBJECT(mAtkObject), "Invalid AtkObject");
|
|
|
|
MaiHyperlink* maiHyperlink = nsnull;
|
|
|
|
if (quark_mai_hyperlink && IS_MAI_OBJECT(mAtkObject)) {
|
|
|
|
maiHyperlink = (MaiHyperlink*)g_object_get_qdata(G_OBJECT(mAtkObject),
|
|
|
|
quark_mai_hyperlink);
|
|
|
|
if (!maiHyperlink && aCreate) {
|
|
|
|
maiHyperlink = new MaiHyperlink(this);
|
|
|
|
SetMaiHyperlink(maiHyperlink);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return maiHyperlink;
|
|
|
|
}
|
|
|
|
|
|
|
|
void nsAccessibleWrap::SetMaiHyperlink(MaiHyperlink* aMaiHyperlink)
|
|
|
|
{
|
|
|
|
NS_ASSERTION(quark_mai_hyperlink, "quark_mai_hyperlink not initialized");
|
|
|
|
NS_ASSERTION(IS_MAI_OBJECT(mAtkObject), "Invalid AtkObject");
|
|
|
|
if (quark_mai_hyperlink && IS_MAI_OBJECT(mAtkObject)) {
|
|
|
|
MaiHyperlink* maiHyperlink = GetMaiHyperlink(PR_FALSE);
|
|
|
|
if (!maiHyperlink && !aMaiHyperlink) {
|
|
|
|
return; // Never set and we're shutting down
|
|
|
|
}
|
|
|
|
if (maiHyperlink) {
|
|
|
|
delete maiHyperlink;
|
|
|
|
}
|
|
|
|
g_object_set_qdata(G_OBJECT(mAtkObject), quark_mai_hyperlink,
|
|
|
|
aMaiHyperlink);
|
2007-03-22 10:30:00 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP nsAccessibleWrap::GetNativeInterface(void **aOutAccessible)
|
|
|
|
{
|
|
|
|
*aOutAccessible = nsnull;
|
|
|
|
|
|
|
|
if (!mAtkObject) {
|
2007-06-04 01:37:33 -07:00
|
|
|
if (!IsEmbeddedObject(this)) {
|
|
|
|
// We don't create ATK objects for nsIAccessible plain text leaves
|
|
|
|
return NS_ERROR_FAILURE;
|
|
|
|
}
|
|
|
|
|
2007-03-22 10:30:00 -07:00
|
|
|
GType type = GetMaiAtkType(CreateMaiInterfaces());
|
|
|
|
NS_ENSURE_TRUE(type, NS_ERROR_FAILURE);
|
|
|
|
mAtkObject =
|
2007-07-08 00:08:04 -07:00
|
|
|
reinterpret_cast<AtkObject *>
|
|
|
|
(g_object_new(type, NULL));
|
2007-03-22 10:30:00 -07:00
|
|
|
NS_ENSURE_TRUE(mAtkObject, NS_ERROR_OUT_OF_MEMORY);
|
|
|
|
|
|
|
|
atk_object_initialize(mAtkObject, this);
|
|
|
|
mAtkObject->role = ATK_ROLE_INVALID;
|
|
|
|
mAtkObject->layer = ATK_LAYER_INVALID;
|
|
|
|
}
|
|
|
|
|
|
|
|
*aOutAccessible = mAtkObject;
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
AtkObject *
|
|
|
|
nsAccessibleWrap::GetAtkObject(void)
|
|
|
|
{
|
|
|
|
void *atkObj = nsnull;
|
|
|
|
GetNativeInterface(&atkObj);
|
2007-07-08 00:08:04 -07:00
|
|
|
return static_cast<AtkObject *>(atkObj);
|
2007-03-22 10:30:00 -07:00
|
|
|
}
|
|
|
|
|
2007-06-08 02:09:24 -07:00
|
|
|
// Get AtkObject from nsIAccessible interface
|
|
|
|
/* static */
|
|
|
|
AtkObject *
|
|
|
|
nsAccessibleWrap::GetAtkObject(nsIAccessible * acc)
|
|
|
|
{
|
|
|
|
void *atkObjPtr = nsnull;
|
|
|
|
acc->GetNativeInterface(&atkObjPtr);
|
|
|
|
return atkObjPtr ? ATK_OBJECT(atkObjPtr) : nsnull;
|
|
|
|
}
|
|
|
|
|
2007-03-22 10:30:00 -07:00
|
|
|
/* private */
|
|
|
|
PRUint16
|
|
|
|
nsAccessibleWrap::CreateMaiInterfaces(void)
|
|
|
|
{
|
|
|
|
PRUint16 interfacesBits = 0;
|
|
|
|
|
|
|
|
// Add Interfaces for each nsIAccessible.ext interfaces
|
|
|
|
|
|
|
|
// the Component interface are supported by all nsIAccessible
|
|
|
|
interfacesBits |= 1 << MAI_INTERFACE_COMPONENT;
|
|
|
|
|
|
|
|
// Add Action interface if the action count is more than zero.
|
|
|
|
PRUint8 actionCount = 0;
|
|
|
|
nsresult rv = GetNumActions(&actionCount);
|
|
|
|
if (NS_SUCCEEDED(rv) && actionCount > 0) {
|
|
|
|
interfacesBits |= 1 << MAI_INTERFACE_ACTION;
|
|
|
|
}
|
|
|
|
|
|
|
|
PRUint32 accRole;
|
|
|
|
GetRole(&accRole);
|
|
|
|
|
|
|
|
//nsIAccessibleText
|
|
|
|
nsCOMPtr<nsIAccessibleText> accessInterfaceText;
|
|
|
|
QueryInterface(NS_GET_IID(nsIAccessibleText),
|
|
|
|
getter_AddRefs(accessInterfaceText));
|
|
|
|
if (accessInterfaceText) {
|
|
|
|
interfacesBits |= 1 << MAI_INTERFACE_TEXT;
|
|
|
|
}
|
|
|
|
|
|
|
|
//nsIAccessibleEditableText
|
|
|
|
nsCOMPtr<nsIAccessibleEditableText> accessInterfaceEditableText;
|
|
|
|
QueryInterface(NS_GET_IID(nsIAccessibleEditableText),
|
|
|
|
getter_AddRefs(accessInterfaceEditableText));
|
|
|
|
if (accessInterfaceEditableText) {
|
|
|
|
interfacesBits |= 1 << MAI_INTERFACE_EDITABLE_TEXT;
|
|
|
|
}
|
|
|
|
|
|
|
|
//nsIAccessibleSelection
|
|
|
|
nsCOMPtr<nsIAccessibleSelectable> accessInterfaceSelection;
|
|
|
|
QueryInterface(NS_GET_IID(nsIAccessibleSelectable),
|
|
|
|
getter_AddRefs(accessInterfaceSelection));
|
|
|
|
if (accessInterfaceSelection) {
|
|
|
|
interfacesBits |= 1 << MAI_INTERFACE_SELECTION;
|
|
|
|
}
|
|
|
|
|
|
|
|
//nsIAccessibleValue
|
|
|
|
nsCOMPtr<nsIAccessibleValue> accessInterfaceValue;
|
|
|
|
QueryInterface(NS_GET_IID(nsIAccessibleValue),
|
|
|
|
getter_AddRefs(accessInterfaceValue));
|
|
|
|
if (accessInterfaceValue) {
|
|
|
|
interfacesBits |= 1 << MAI_INTERFACE_VALUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
//nsIAccessibleHypertext
|
|
|
|
PRInt32 linkCount = 0;
|
|
|
|
nsCOMPtr<nsIAccessibleHyperText> accessInterfaceHypertext;
|
|
|
|
QueryInterface(NS_GET_IID(nsIAccessibleHyperText),
|
|
|
|
getter_AddRefs(accessInterfaceHypertext));
|
|
|
|
if (accessInterfaceHypertext) {
|
|
|
|
nsresult rv = accessInterfaceHypertext->GetLinks(&linkCount);
|
|
|
|
if (NS_SUCCEEDED(rv) && (linkCount > 0)) {
|
|
|
|
interfacesBits |= 1 << MAI_INTERFACE_HYPERTEXT;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
//nsIAccessibleHyperLink
|
|
|
|
nsCOMPtr<nsIAccessibleHyperLink> accessInterfaceHyperlink;
|
|
|
|
QueryInterface(NS_GET_IID(nsIAccessibleHyperLink),
|
|
|
|
getter_AddRefs(accessInterfaceHyperlink));
|
|
|
|
if (accessInterfaceHyperlink) {
|
|
|
|
interfacesBits |= 1 << MAI_INTERFACE_HYPERLINK_IMPL;
|
|
|
|
}
|
|
|
|
|
|
|
|
//nsIAccessibleTable
|
|
|
|
nsCOMPtr<nsIAccessibleTable> accessInterfaceTable;
|
|
|
|
QueryInterface(NS_GET_IID(nsIAccessibleTable),
|
|
|
|
getter_AddRefs(accessInterfaceTable));
|
|
|
|
if (accessInterfaceTable) {
|
|
|
|
interfacesBits |= 1 << MAI_INTERFACE_TABLE;
|
|
|
|
}
|
|
|
|
|
|
|
|
//nsIAccessibleDocument
|
|
|
|
nsCOMPtr<nsIAccessibleDocument> accessInterfaceDocument;
|
|
|
|
QueryInterface(NS_GET_IID(nsIAccessibleDocument),
|
|
|
|
getter_AddRefs(accessInterfaceDocument));
|
|
|
|
if (accessInterfaceDocument) {
|
|
|
|
interfacesBits |= 1 << MAI_INTERFACE_DOCUMENT;
|
|
|
|
}
|
|
|
|
|
|
|
|
//nsIAccessibleImage
|
|
|
|
nsCOMPtr<nsIAccessibleImage> accessInterfaceImage;
|
|
|
|
QueryInterface(NS_GET_IID(nsIAccessibleImage),
|
|
|
|
getter_AddRefs(accessInterfaceImage));
|
|
|
|
if (accessInterfaceImage) {
|
|
|
|
interfacesBits |= 1 << MAI_INTERFACE_IMAGE;
|
|
|
|
}
|
|
|
|
|
|
|
|
return interfacesBits;
|
|
|
|
}
|
|
|
|
|
|
|
|
static GType
|
|
|
|
GetMaiAtkType(PRUint16 interfacesBits)
|
|
|
|
{
|
|
|
|
GType type;
|
|
|
|
static const GTypeInfo tinfo = {
|
|
|
|
sizeof(MaiAtkObjectClass),
|
|
|
|
(GBaseInitFunc) NULL,
|
|
|
|
(GBaseFinalizeFunc) NULL,
|
|
|
|
(GClassInitFunc) NULL,
|
|
|
|
(GClassFinalizeFunc) NULL,
|
|
|
|
NULL, /* class data */
|
|
|
|
sizeof(MaiAtkObject), /* instance size */
|
|
|
|
0, /* nb preallocs */
|
|
|
|
(GInstanceInitFunc) NULL,
|
|
|
|
NULL /* value table */
|
|
|
|
};
|
|
|
|
|
|
|
|
/*
|
|
|
|
* The members we use to register GTypes are GetAtkTypeForMai
|
|
|
|
* and atk_if_infos, which are constant values to each MaiInterface
|
|
|
|
* So we can reuse the registered GType when having
|
|
|
|
* the same MaiInterface types.
|
|
|
|
*/
|
|
|
|
const char *atkTypeName = GetUniqueMaiAtkTypeName(interfacesBits);
|
|
|
|
type = g_type_from_name(atkTypeName);
|
|
|
|
if (type) {
|
|
|
|
return type;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* gobject limits the number of types that can directly derive from any
|
|
|
|
* given object type to 4095.
|
|
|
|
*/
|
|
|
|
static PRUint16 typeRegCount = 0;
|
|
|
|
if (typeRegCount++ >= 4095) {
|
|
|
|
return G_TYPE_INVALID;
|
|
|
|
}
|
|
|
|
type = g_type_register_static(MAI_TYPE_ATK_OBJECT,
|
|
|
|
atkTypeName,
|
|
|
|
&tinfo, GTypeFlags(0));
|
|
|
|
|
|
|
|
for (PRUint32 index = 0; index < NS_ARRAY_LENGTH(atk_if_infos); index++) {
|
|
|
|
if (interfacesBits & (1 << index)) {
|
|
|
|
g_type_add_interface_static(type,
|
|
|
|
GetAtkTypeForMai((MaiInterfaceType)index),
|
|
|
|
&atk_if_infos[index]);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return type;
|
|
|
|
}
|
|
|
|
|
|
|
|
static const char *
|
|
|
|
GetUniqueMaiAtkTypeName(PRUint16 interfacesBits)
|
|
|
|
{
|
|
|
|
#define MAI_ATK_TYPE_NAME_LEN (30) /* 10+sizeof(PRUint16)*8/4+1 < 30 */
|
|
|
|
|
|
|
|
static gchar namePrefix[] = "MaiAtkType"; /* size = 10 */
|
|
|
|
static gchar name[MAI_ATK_TYPE_NAME_LEN + 1];
|
|
|
|
|
|
|
|
PR_snprintf(name, MAI_ATK_TYPE_NAME_LEN, "%s%x", namePrefix,
|
|
|
|
interfacesBits);
|
|
|
|
name[MAI_ATK_TYPE_NAME_LEN] = '\0';
|
|
|
|
|
|
|
|
MAI_LOG_DEBUG(("MaiWidget::LastedTypeName=%s\n", name));
|
|
|
|
|
|
|
|
return name;
|
|
|
|
}
|
|
|
|
|
|
|
|
PRBool nsAccessibleWrap::IsValidObject()
|
|
|
|
{
|
|
|
|
// to ensure we are not shut down
|
|
|
|
return (mDOMNode != nsnull);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* static functions for ATK callbacks */
|
|
|
|
void
|
|
|
|
classInitCB(AtkObjectClass *aClass)
|
|
|
|
{
|
|
|
|
GObjectClass *gobject_class = G_OBJECT_CLASS(aClass);
|
|
|
|
|
|
|
|
parent_class = g_type_class_peek_parent(aClass);
|
|
|
|
|
|
|
|
aClass->get_name = getNameCB;
|
|
|
|
aClass->get_description = getDescriptionCB;
|
|
|
|
aClass->get_parent = getParentCB;
|
|
|
|
aClass->get_n_children = getChildCountCB;
|
|
|
|
aClass->ref_child = refChildCB;
|
|
|
|
aClass->get_index_in_parent = getIndexInParentCB;
|
|
|
|
aClass->get_role = getRoleCB;
|
|
|
|
aClass->get_attributes = getAttributesCB;
|
|
|
|
aClass->ref_state_set = refStateSetCB;
|
|
|
|
aClass->ref_relation_set = refRelationSetCB;
|
|
|
|
|
|
|
|
aClass->initialize = initializeCB;
|
|
|
|
|
|
|
|
gobject_class->finalize = finalizeCB;
|
|
|
|
|
|
|
|
mai_atk_object_signals [ACTIVATE] =
|
|
|
|
g_signal_new ("activate",
|
|
|
|
MAI_TYPE_ATK_OBJECT,
|
|
|
|
G_SIGNAL_RUN_LAST,
|
|
|
|
0, /* default signal handler */
|
|
|
|
NULL, NULL,
|
|
|
|
g_cclosure_marshal_VOID__VOID,
|
|
|
|
G_TYPE_NONE, 0);
|
|
|
|
mai_atk_object_signals [CREATE] =
|
|
|
|
g_signal_new ("create",
|
|
|
|
MAI_TYPE_ATK_OBJECT,
|
|
|
|
G_SIGNAL_RUN_LAST,
|
|
|
|
0, /* default signal handler */
|
|
|
|
NULL, NULL,
|
|
|
|
g_cclosure_marshal_VOID__VOID,
|
|
|
|
G_TYPE_NONE, 0);
|
|
|
|
mai_atk_object_signals [DEACTIVATE] =
|
|
|
|
g_signal_new ("deactivate",
|
|
|
|
MAI_TYPE_ATK_OBJECT,
|
|
|
|
G_SIGNAL_RUN_LAST,
|
|
|
|
0, /* default signal handler */
|
|
|
|
NULL, NULL,
|
|
|
|
g_cclosure_marshal_VOID__VOID,
|
|
|
|
G_TYPE_NONE, 0);
|
|
|
|
mai_atk_object_signals [DESTROY] =
|
|
|
|
g_signal_new ("destroy",
|
|
|
|
MAI_TYPE_ATK_OBJECT,
|
|
|
|
G_SIGNAL_RUN_LAST,
|
|
|
|
0, /* default signal handler */
|
|
|
|
NULL, NULL,
|
|
|
|
g_cclosure_marshal_VOID__VOID,
|
|
|
|
G_TYPE_NONE, 0);
|
|
|
|
mai_atk_object_signals [MAXIMIZE] =
|
|
|
|
g_signal_new ("maximize",
|
|
|
|
MAI_TYPE_ATK_OBJECT,
|
|
|
|
G_SIGNAL_RUN_LAST,
|
|
|
|
0, /* default signal handler */
|
|
|
|
NULL, NULL,
|
|
|
|
g_cclosure_marshal_VOID__VOID,
|
|
|
|
G_TYPE_NONE, 0);
|
|
|
|
mai_atk_object_signals [MINIMIZE] =
|
|
|
|
g_signal_new ("minimize",
|
|
|
|
MAI_TYPE_ATK_OBJECT,
|
|
|
|
G_SIGNAL_RUN_LAST,
|
|
|
|
0, /* default signal handler */
|
|
|
|
NULL, NULL,
|
|
|
|
g_cclosure_marshal_VOID__VOID,
|
|
|
|
G_TYPE_NONE, 0);
|
|
|
|
mai_atk_object_signals [RESIZE] =
|
|
|
|
g_signal_new ("resize",
|
|
|
|
MAI_TYPE_ATK_OBJECT,
|
|
|
|
G_SIGNAL_RUN_LAST,
|
|
|
|
0, /* default signal handler */
|
|
|
|
NULL, NULL,
|
|
|
|
g_cclosure_marshal_VOID__VOID,
|
|
|
|
G_TYPE_NONE, 0);
|
|
|
|
mai_atk_object_signals [RESTORE] =
|
|
|
|
g_signal_new ("restore",
|
|
|
|
MAI_TYPE_ATK_OBJECT,
|
|
|
|
G_SIGNAL_RUN_LAST,
|
|
|
|
0, /* default signal handler */
|
|
|
|
NULL, NULL,
|
|
|
|
g_cclosure_marshal_VOID__VOID,
|
|
|
|
G_TYPE_NONE, 0);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
initializeCB(AtkObject *aAtkObj, gpointer aData)
|
|
|
|
{
|
|
|
|
NS_ASSERTION((IS_MAI_OBJECT(aAtkObj)), "Invalid AtkObject");
|
|
|
|
NS_ASSERTION(aData, "Invalid Data to init AtkObject");
|
|
|
|
if (!aAtkObj || !aData)
|
|
|
|
return;
|
|
|
|
|
|
|
|
/* call parent init function */
|
|
|
|
/* AtkObjectClass has not a "initialize" function now,
|
|
|
|
* maybe it has later
|
|
|
|
*/
|
|
|
|
|
|
|
|
if (ATK_OBJECT_CLASS(parent_class)->initialize)
|
|
|
|
ATK_OBJECT_CLASS(parent_class)->initialize(aAtkObj, aData);
|
|
|
|
|
|
|
|
/* initialize object */
|
|
|
|
MAI_ATK_OBJECT(aAtkObj)->accWrap =
|
2007-07-08 00:08:04 -07:00
|
|
|
static_cast<nsAccessibleWrap*>(aData);
|
2007-03-22 10:30:00 -07:00
|
|
|
|
|
|
|
#ifdef MAI_LOGGING
|
|
|
|
++sMaiAtkObjCreated;
|
|
|
|
#endif
|
|
|
|
MAI_LOG_DEBUG(("MaiAtkObj Create obj=%p for AccWrap=%p, all=%d, left=%d\n",
|
|
|
|
(void*)aAtkObj, (void*)aData, sMaiAtkObjCreated,
|
|
|
|
(sMaiAtkObjCreated-sMaiAtkObjDeleted)));
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
finalizeCB(GObject *aObj)
|
|
|
|
{
|
|
|
|
if (!IS_MAI_OBJECT(aObj))
|
|
|
|
return;
|
|
|
|
NS_ASSERTION(MAI_ATK_OBJECT(aObj)->accWrap == nsnull, "AccWrap NOT null");
|
|
|
|
|
|
|
|
#ifdef MAI_LOGGING
|
|
|
|
++sMaiAtkObjDeleted;
|
|
|
|
#endif
|
|
|
|
MAI_LOG_DEBUG(("MaiAtkObj Delete obj=%p, all=%d, left=%d\n",
|
|
|
|
(void*)aObj, sMaiAtkObjCreated,
|
|
|
|
(sMaiAtkObjCreated-sMaiAtkObjDeleted)));
|
|
|
|
|
|
|
|
// call parent finalize function
|
|
|
|
// finalize of GObjectClass will unref the accessible parent if has
|
|
|
|
if (G_OBJECT_CLASS (parent_class)->finalize)
|
|
|
|
G_OBJECT_CLASS (parent_class)->finalize(aObj);
|
|
|
|
}
|
|
|
|
|
|
|
|
const gchar *
|
|
|
|
getNameCB(AtkObject *aAtkObj)
|
|
|
|
{
|
2007-06-04 02:39:15 -07:00
|
|
|
nsAccessibleWrap *accWrap = GetAccessibleWrap(aAtkObj);
|
2007-06-08 02:09:24 -07:00
|
|
|
if (!accWrap) {
|
|
|
|
return nsnull;
|
|
|
|
}
|
2007-03-22 10:30:00 -07:00
|
|
|
|
|
|
|
/* nsIAccessible is responsible for the non-NULL name */
|
2007-06-08 02:09:24 -07:00
|
|
|
nsAutoString uniName;
|
2007-03-22 10:30:00 -07:00
|
|
|
nsresult rv = accWrap->GetName(uniName);
|
|
|
|
NS_ENSURE_SUCCESS(rv, nsnull);
|
|
|
|
|
2007-06-08 02:09:24 -07:00
|
|
|
NS_ConvertUTF8toUTF16 objName(aAtkObj->name);
|
|
|
|
if (!uniName.Equals(objName)) {
|
|
|
|
atk_object_set_name(aAtkObj,
|
|
|
|
NS_ConvertUTF16toUTF8(uniName).get());
|
2007-03-22 10:30:00 -07:00
|
|
|
}
|
|
|
|
return aAtkObj->name;
|
|
|
|
}
|
|
|
|
|
|
|
|
const gchar *
|
|
|
|
getDescriptionCB(AtkObject *aAtkObj)
|
|
|
|
{
|
2007-06-08 02:09:24 -07:00
|
|
|
nsAccessibleWrap *accWrap = GetAccessibleWrap(aAtkObj);
|
|
|
|
if (!accWrap) {
|
|
|
|
return nsnull;
|
2007-04-30 22:57:51 -07:00
|
|
|
}
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2007-06-08 02:09:24 -07:00
|
|
|
/* nsIAccessible is responsible for the non-NULL description */
|
|
|
|
nsAutoString uniDesc;
|
|
|
|
nsresult rv = accWrap->GetDescription(uniDesc);
|
|
|
|
NS_ENSURE_SUCCESS(rv, nsnull);
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2007-06-08 02:09:24 -07:00
|
|
|
NS_ConvertUTF8toUTF16 objDesc(aAtkObj->description);
|
|
|
|
if (!uniDesc.Equals(objDesc)) {
|
|
|
|
atk_object_set_description(aAtkObj,
|
|
|
|
NS_ConvertUTF16toUTF8(uniDesc).get());
|
2007-03-22 10:30:00 -07:00
|
|
|
}
|
|
|
|
return aAtkObj->description;
|
|
|
|
}
|
|
|
|
|
|
|
|
AtkRole
|
|
|
|
getRoleCB(AtkObject *aAtkObj)
|
|
|
|
{
|
2007-06-08 02:09:24 -07:00
|
|
|
nsAccessibleWrap *accWrap = GetAccessibleWrap(aAtkObj);
|
|
|
|
if (!accWrap) {
|
|
|
|
return ATK_ROLE_INVALID;
|
2007-04-30 22:57:51 -07:00
|
|
|
}
|
2007-03-22 10:30:00 -07:00
|
|
|
|
|
|
|
#ifdef DEBUG_A11Y
|
2007-06-08 02:09:24 -07:00
|
|
|
NS_ASSERTION(nsAccessible::IsTextInterfaceSupportCorrect(accWrap), "Does not support nsIAccessibleText when it should");
|
2007-03-22 10:30:00 -07:00
|
|
|
#endif
|
|
|
|
|
|
|
|
if (aAtkObj->role == ATK_ROLE_INVALID) {
|
|
|
|
PRUint32 accRole, atkRole;
|
|
|
|
nsresult rv = accWrap->GetFinalRole(&accRole);
|
|
|
|
NS_ENSURE_SUCCESS(rv, ATK_ROLE_INVALID);
|
|
|
|
|
|
|
|
atkRole = atkRoleMap[accRole]; // map to the actual value
|
|
|
|
NS_ASSERTION(atkRoleMap[nsIAccessibleRole::ROLE_LAST_ENTRY] ==
|
|
|
|
kROLE_ATK_LAST_ENTRY, "ATK role map skewed");
|
2007-07-08 00:08:04 -07:00
|
|
|
aAtkObj->role = static_cast<AtkRole>(atkRole);
|
2007-03-22 10:30:00 -07:00
|
|
|
}
|
|
|
|
return aAtkObj->role;
|
|
|
|
}
|
|
|
|
|
|
|
|
AtkAttributeSet *
|
|
|
|
GetAttributeSet(nsIAccessible* aAccessible)
|
|
|
|
{
|
|
|
|
AtkAttributeSet *objAttributeSet = nsnull;
|
|
|
|
nsCOMPtr<nsIPersistentProperties> attributes;
|
|
|
|
aAccessible->GetAttributes(getter_AddRefs(attributes));
|
2007-07-04 00:54:56 -07:00
|
|
|
|
2007-03-22 10:30:00 -07:00
|
|
|
if (attributes) {
|
2007-07-04 00:54:56 -07:00
|
|
|
// Deal with attributes that we only need to expose in ATK
|
2007-07-04 01:49:00 -07:00
|
|
|
PRUint32 state, extraState;
|
|
|
|
aAccessible->GetFinalState(&state, &extraState);
|
2007-07-04 01:38:54 -07:00
|
|
|
if (state & nsIAccessibleStates::STATE_HASPOPUP) {
|
2007-07-04 00:54:56 -07:00
|
|
|
// There is no ATK state for haspopup, must use object attribute to expose the same info
|
|
|
|
nsAutoString oldValueUnused;
|
2007-07-04 01:24:23 -07:00
|
|
|
attributes->SetStringProperty(NS_LITERAL_CSTRING("haspopup"), NS_LITERAL_STRING("true"),
|
2007-07-04 00:54:56 -07:00
|
|
|
oldValueUnused);
|
|
|
|
}
|
2007-07-06 00:50:34 -07:00
|
|
|
if (state & nsIAccessibleStates::STATE_CHECKABLE) {
|
|
|
|
// There is no ATK state for haspopup, must use object attribute to expose the same info
|
|
|
|
nsAutoString oldValueUnused;
|
|
|
|
attributes->SetStringProperty(NS_LITERAL_CSTRING("checkable"), NS_LITERAL_STRING("true"),
|
|
|
|
oldValueUnused);
|
|
|
|
}
|
2007-07-04 00:54:56 -07:00
|
|
|
|
2007-03-22 10:30:00 -07:00
|
|
|
nsCOMPtr<nsISimpleEnumerator> propEnum;
|
|
|
|
nsresult rv = attributes->Enumerate(getter_AddRefs(propEnum));
|
|
|
|
NS_ENSURE_SUCCESS(rv, nsnull);
|
|
|
|
|
|
|
|
PRBool hasMore;
|
|
|
|
while (NS_SUCCEEDED(propEnum->HasMoreElements(&hasMore)) && hasMore) {
|
|
|
|
nsCOMPtr<nsISupports> sup;
|
|
|
|
rv = propEnum->GetNext(getter_AddRefs(sup));
|
|
|
|
nsCOMPtr<nsIPropertyElement> propElem(do_QueryInterface(sup));
|
|
|
|
NS_ENSURE_TRUE(propElem, nsnull);
|
|
|
|
|
|
|
|
nsCAutoString name;
|
|
|
|
rv = propElem->GetKey(name);
|
|
|
|
NS_ENSURE_SUCCESS(rv, nsnull);
|
|
|
|
|
|
|
|
nsAutoString value;
|
|
|
|
rv = propElem->GetValue(value);
|
|
|
|
NS_ENSURE_SUCCESS(rv, nsnull);
|
|
|
|
|
|
|
|
AtkAttribute *objAttribute = (AtkAttribute *)g_malloc(sizeof(AtkAttribute));
|
|
|
|
objAttribute->name = g_strdup(name.get());
|
|
|
|
objAttribute->value = g_strdup(NS_ConvertUTF16toUTF8(value).get());
|
|
|
|
objAttributeSet = g_slist_prepend(objAttributeSet, objAttribute);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return objAttributeSet;
|
|
|
|
}
|
|
|
|
|
|
|
|
AtkAttributeSet *
|
|
|
|
getAttributesCB(AtkObject *aAtkObj)
|
|
|
|
{
|
2007-06-04 02:39:15 -07:00
|
|
|
nsAccessibleWrap *accWrap = GetAccessibleWrap(aAtkObj);
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2007-06-08 02:09:24 -07:00
|
|
|
return accWrap ? GetAttributeSet(accWrap) : nsnull;
|
2007-03-22 10:30:00 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
AtkObject *
|
|
|
|
getParentCB(AtkObject *aAtkObj)
|
|
|
|
{
|
2007-06-08 02:09:24 -07:00
|
|
|
if (!aAtkObj->accessible_parent) {
|
|
|
|
nsAccessibleWrap *accWrap = GetAccessibleWrap(aAtkObj);
|
|
|
|
if (!accWrap) {
|
|
|
|
return nsnull;
|
|
|
|
}
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2007-06-08 02:09:24 -07:00
|
|
|
nsCOMPtr<nsIAccessible> accParent;
|
|
|
|
nsresult rv = accWrap->GetParent(getter_AddRefs(accParent));
|
|
|
|
if (NS_FAILED(rv) || !accParent)
|
|
|
|
return nsnull;
|
2007-06-04 02:39:15 -07:00
|
|
|
|
2007-06-08 02:09:24 -07:00
|
|
|
atk_object_set_parent(aAtkObj,
|
|
|
|
nsAccessibleWrap::GetAtkObject(accParent));
|
2007-03-22 10:30:00 -07:00
|
|
|
}
|
2007-06-04 02:39:15 -07:00
|
|
|
return aAtkObj->accessible_parent;
|
2007-03-22 10:30:00 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
gint
|
|
|
|
getChildCountCB(AtkObject *aAtkObj)
|
|
|
|
{
|
2007-06-04 02:39:15 -07:00
|
|
|
nsAccessibleWrap *accWrap = GetAccessibleWrap(aAtkObj);
|
2007-06-08 02:09:24 -07:00
|
|
|
if (!accWrap) {
|
|
|
|
return 0;
|
|
|
|
}
|
2007-03-22 10:30:00 -07:00
|
|
|
|
|
|
|
PRInt32 count = 0;
|
|
|
|
nsCOMPtr<nsIAccessibleHyperText> hyperText;
|
|
|
|
accWrap->QueryInterface(NS_GET_IID(nsIAccessibleHyperText), getter_AddRefs(hyperText));
|
|
|
|
if (hyperText) {
|
|
|
|
// If HyperText, then number of links matches number of children
|
|
|
|
hyperText->GetLinks(&count);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
nsCOMPtr<nsIAccessibleText> accText;
|
|
|
|
accWrap->QueryInterface(NS_GET_IID(nsIAccessibleText), getter_AddRefs(accText));
|
|
|
|
if (!accText) { // Accessible text that is not a HyperText has no children
|
|
|
|
accWrap->GetChildCount(&count);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return count;
|
|
|
|
}
|
|
|
|
|
|
|
|
AtkObject *
|
|
|
|
refChildCB(AtkObject *aAtkObj, gint aChildIndex)
|
|
|
|
{
|
|
|
|
// aChildIndex should not be less than zero
|
|
|
|
if (aChildIndex < 0) {
|
|
|
|
return nsnull;
|
|
|
|
}
|
|
|
|
|
|
|
|
// XXX Fix this so it is not O(n^2) to walk through the children!
|
|
|
|
// Either we can cache the last accessed child so that we can just GetNextSibling()
|
|
|
|
// or we should cache an array of children in each nsAccessible
|
|
|
|
// (instead of mNextSibling on the children)
|
2007-06-04 02:39:15 -07:00
|
|
|
nsAccessibleWrap *accWrap = GetAccessibleWrap(aAtkObj);
|
2007-06-08 02:09:24 -07:00
|
|
|
if (!accWrap) {
|
|
|
|
return nsnull;
|
|
|
|
}
|
2007-03-22 10:30:00 -07:00
|
|
|
|
|
|
|
nsresult rv;
|
|
|
|
nsCOMPtr<nsIAccessible> accChild;
|
|
|
|
nsCOMPtr<nsIAccessibleHyperText> hyperText;
|
|
|
|
accWrap->QueryInterface(NS_GET_IID(nsIAccessibleHyperText), getter_AddRefs(hyperText));
|
|
|
|
if (hyperText) {
|
|
|
|
// If HyperText, then number of links matches number of children
|
|
|
|
nsCOMPtr<nsIAccessibleHyperLink> hyperLink;
|
|
|
|
rv = hyperText->GetLink(aChildIndex, getter_AddRefs(hyperLink));
|
|
|
|
accChild = do_QueryInterface(hyperLink);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
nsCOMPtr<nsIAccessibleText> accText;
|
|
|
|
accWrap->QueryInterface(NS_GET_IID(nsIAccessibleText), getter_AddRefs(accText));
|
|
|
|
if (!accText) { // Accessible Text that is not HyperText has no children
|
|
|
|
rv = accWrap->GetChildAt(aChildIndex, getter_AddRefs(accChild));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (NS_FAILED(rv) || !accChild)
|
|
|
|
return nsnull;
|
|
|
|
|
2007-06-08 02:09:24 -07:00
|
|
|
AtkObject* childAtkObj = nsAccessibleWrap::GetAtkObject(accChild);
|
2007-03-22 10:30:00 -07:00
|
|
|
|
2007-06-08 02:09:24 -07:00
|
|
|
NS_ASSERTION(childAtkObj, "Fail to get AtkObj");
|
|
|
|
if (!childAtkObj)
|
2007-03-22 10:30:00 -07:00
|
|
|
return nsnull;
|
2007-06-04 02:39:15 -07:00
|
|
|
|
|
|
|
//this will addref parent
|
|
|
|
atk_object_set_parent(childAtkObj, aAtkObj);
|
2007-03-22 10:30:00 -07:00
|
|
|
g_object_ref(childAtkObj);
|
|
|
|
return childAtkObj;
|
|
|
|
}
|
|
|
|
|
|
|
|
gint
|
|
|
|
getIndexInParentCB(AtkObject *aAtkObj)
|
|
|
|
{
|
|
|
|
// We don't use nsIAccessible::GetIndexInParent() because
|
|
|
|
// for ATK we don't want to include text leaf nodes as children
|
2007-06-04 02:39:15 -07:00
|
|
|
nsAccessibleWrap *accWrap = GetAccessibleWrap(aAtkObj);
|
2007-06-08 02:09:24 -07:00
|
|
|
if (!accWrap) {
|
|
|
|
return -1;
|
|
|
|
}
|
2007-03-22 10:30:00 -07:00
|
|
|
|
|
|
|
nsCOMPtr<nsIAccessible> parent;
|
|
|
|
accWrap->GetParent(getter_AddRefs(parent));
|
|
|
|
if (!parent) {
|
|
|
|
return -1; // No parent
|
|
|
|
}
|
|
|
|
|
|
|
|
nsCOMPtr<nsIAccessible> sibling;
|
|
|
|
parent->GetFirstChild(getter_AddRefs(sibling));
|
|
|
|
if (!sibling) {
|
|
|
|
return -1; // Error, parent has no children
|
|
|
|
}
|
|
|
|
|
|
|
|
PRInt32 currentIndex = 0;
|
|
|
|
|
2007-07-08 00:08:04 -07:00
|
|
|
while (sibling != static_cast<nsIAccessible*>(accWrap)) {
|
2007-03-22 10:30:00 -07:00
|
|
|
NS_ASSERTION(sibling, "Never ran into the same child that we started from");
|
|
|
|
|
|
|
|
if (!sibling) {
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
if (nsAccessible::IsEmbeddedObject(sibling)) {
|
|
|
|
++ currentIndex;
|
|
|
|
}
|
|
|
|
|
|
|
|
nsCOMPtr<nsIAccessible> tempAccessible;
|
|
|
|
sibling->GetNextSibling(getter_AddRefs(tempAccessible));
|
|
|
|
sibling.swap(tempAccessible);
|
|
|
|
}
|
|
|
|
|
|
|
|
return currentIndex;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void TranslateStates(PRUint32 aState, const AtkStateMap *aStateMap,
|
|
|
|
AtkStateSet *aStateSet)
|
|
|
|
{
|
|
|
|
NS_ASSERTION(aStateSet, "Can't pass in null state set");
|
|
|
|
|
|
|
|
// Convert every state to an entry in AtkStateMap
|
|
|
|
PRUint32 stateIndex = 0;
|
|
|
|
PRUint32 bitMask = 1;
|
|
|
|
while (aStateMap[stateIndex].stateMapEntryType != kNoSuchState) {
|
|
|
|
if (aStateMap[stateIndex].atkState) { // There's potentially an ATK state for this
|
|
|
|
PRBool isStateOn = (aState & bitMask) != 0;
|
|
|
|
if (aStateMap[stateIndex].stateMapEntryType == kMapOpposite) {
|
|
|
|
isStateOn = !isStateOn;
|
|
|
|
}
|
|
|
|
if (isStateOn) {
|
|
|
|
atk_state_set_add_state(aStateSet, aStateMap[stateIndex].atkState);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
// Map extended state
|
|
|
|
bitMask <<= 1;
|
|
|
|
++ stateIndex;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
AtkStateSet *
|
|
|
|
refStateSetCB(AtkObject *aAtkObj)
|
|
|
|
{
|
|
|
|
AtkStateSet *state_set = nsnull;
|
|
|
|
state_set = ATK_OBJECT_CLASS(parent_class)->ref_state_set(aAtkObj);
|
|
|
|
|
2007-06-08 02:09:24 -07:00
|
|
|
nsAccessibleWrap *accWrap = GetAccessibleWrap(aAtkObj);
|
|
|
|
if (!accWrap) {
|
2007-05-10 22:51:46 -07:00
|
|
|
TranslateStates(nsIAccessibleStates::EXT_STATE_DEFUNCT,
|
|
|
|
gAtkStateMapExt, state_set);
|
|
|
|
return state_set;
|
2007-04-30 22:57:51 -07:00
|
|
|
}
|
2007-05-10 22:51:46 -07:00
|
|
|
|
2007-03-22 10:30:00 -07:00
|
|
|
// Map states
|
2007-04-02 08:56:24 -07:00
|
|
|
PRUint32 accState = 0, accExtState = 0;
|
|
|
|
nsresult rv = accWrap->GetFinalState(&accState, &accExtState);
|
2007-03-22 10:30:00 -07:00
|
|
|
NS_ENSURE_SUCCESS(rv, state_set);
|
|
|
|
|
2007-04-02 08:56:24 -07:00
|
|
|
TranslateStates(accState, gAtkStateMap, state_set);
|
2007-03-22 10:30:00 -07:00
|
|
|
TranslateStates(accExtState, gAtkStateMapExt, state_set);
|
|
|
|
|
|
|
|
return state_set;
|
|
|
|
}
|
|
|
|
|
|
|
|
AtkRelationSet *
|
|
|
|
refRelationSetCB(AtkObject *aAtkObj)
|
|
|
|
{
|
|
|
|
AtkRelationSet *relation_set = nsnull;
|
|
|
|
relation_set = ATK_OBJECT_CLASS(parent_class)->ref_relation_set(aAtkObj);
|
|
|
|
|
2007-06-04 02:39:15 -07:00
|
|
|
nsAccessibleWrap *accWrap = GetAccessibleWrap(aAtkObj);
|
2007-06-08 02:09:24 -07:00
|
|
|
if (!accWrap) {
|
|
|
|
return relation_set;
|
|
|
|
}
|
2007-03-22 10:30:00 -07:00
|
|
|
|
|
|
|
AtkObject *accessible_array[1];
|
|
|
|
AtkRelation* relation;
|
|
|
|
|
2007-05-19 19:41:33 -07:00
|
|
|
PRUint32 relationType[] = {nsIAccessibleRelation::RELATION_LABELLED_BY,
|
|
|
|
nsIAccessibleRelation::RELATION_LABEL_FOR,
|
|
|
|
nsIAccessibleRelation::RELATION_NODE_CHILD_OF,
|
|
|
|
nsIAccessibleRelation::RELATION_CONTROLLED_BY,
|
|
|
|
nsIAccessibleRelation::RELATION_CONTROLLER_FOR,
|
|
|
|
nsIAccessibleRelation::RELATION_EMBEDS,
|
|
|
|
nsIAccessibleRelation::RELATION_FLOWS_TO,
|
|
|
|
nsIAccessibleRelation::RELATION_FLOWS_FROM,
|
|
|
|
nsIAccessibleRelation::RELATION_DESCRIBED_BY,
|
|
|
|
nsIAccessibleRelation::RELATION_DESCRIPTION_FOR,
|
2007-03-22 10:30:00 -07:00
|
|
|
};
|
|
|
|
|
|
|
|
for (PRUint32 i = 0; i < NS_ARRAY_LENGTH(relationType); i++) {
|
2007-07-08 00:08:04 -07:00
|
|
|
relation = atk_relation_set_get_relation_by_type(relation_set, static_cast<AtkRelationType>(relationType[i]));
|
2007-03-22 10:30:00 -07:00
|
|
|
if (relation) {
|
|
|
|
atk_relation_set_remove(relation_set, relation);
|
|
|
|
}
|
|
|
|
|
|
|
|
nsIAccessible* accRelated;
|
|
|
|
nsresult rv = accWrap->GetAccessibleRelated(relationType[i], &accRelated);
|
|
|
|
if (NS_SUCCEEDED(rv) && accRelated) {
|
2007-06-08 02:09:24 -07:00
|
|
|
accessible_array[0] = nsAccessibleWrap::GetAtkObject(accRelated);
|
2007-03-22 10:30:00 -07:00
|
|
|
relation = atk_relation_new(accessible_array, 1,
|
2007-07-08 00:08:04 -07:00
|
|
|
static_cast<AtkRelationType>(relationType[i]));
|
2007-03-22 10:30:00 -07:00
|
|
|
atk_relation_set_add(relation_set, relation);
|
|
|
|
g_object_unref(relation);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return relation_set;
|
|
|
|
}
|
|
|
|
|
2007-06-08 02:09:24 -07:00
|
|
|
// Check if aAtkObj is a valid MaiAtkObject, and return the nsAccessibleWrap
|
|
|
|
// for it.
|
|
|
|
nsAccessibleWrap *GetAccessibleWrap(AtkObject *aAtkObj)
|
2007-03-22 10:30:00 -07:00
|
|
|
{
|
2007-06-08 02:09:24 -07:00
|
|
|
NS_ENSURE_TRUE(IS_MAI_OBJECT(aAtkObj), nsnull);
|
|
|
|
nsAccessibleWrap *tmpAccWrap = MAI_ATK_OBJECT(aAtkObj)->accWrap;
|
2007-05-10 22:51:46 -07:00
|
|
|
|
|
|
|
// Check if AccessibleWrap was deconstructed
|
|
|
|
if (tmpAccWrap == nsnull) {
|
2007-06-08 02:09:24 -07:00
|
|
|
return nsnull;
|
2007-05-10 22:51:46 -07:00
|
|
|
}
|
|
|
|
|
2007-06-08 02:09:24 -07:00
|
|
|
NS_ENSURE_TRUE(tmpAccWrap->GetAtkObject() == aAtkObj, nsnull);
|
|
|
|
|
2007-06-01 20:01:38 -07:00
|
|
|
nsRefPtr<nsApplicationAccessibleWrap> appAccWrap =
|
|
|
|
nsAccessNode::GetApplicationAccessible();
|
|
|
|
nsAccessibleWrap* tmpAppAccWrap =
|
2007-07-08 00:08:04 -07:00
|
|
|
static_cast<nsAccessibleWrap*>(appAccWrap.get());
|
2007-06-01 20:01:38 -07:00
|
|
|
|
|
|
|
if (tmpAppAccWrap != tmpAccWrap && !tmpAccWrap->IsValidObject())
|
2007-06-08 02:09:24 -07:00
|
|
|
return nsnull;
|
2007-03-22 10:30:00 -07:00
|
|
|
|
|
|
|
return tmpAccWrap;
|
|
|
|
}
|
2007-04-15 19:21:49 -07:00
|
|
|
|
|
|
|
NS_IMETHODIMP
|
|
|
|
nsAccessibleWrap::FireAccessibleEvent(nsIAccessibleEvent *aEvent)
|
|
|
|
{
|
|
|
|
nsresult rv = nsAccessible::FireAccessibleEvent(aEvent);
|
|
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
|
|
|
|
nsCOMPtr<nsIAccessible> accessible;
|
|
|
|
aEvent->GetAccessible(getter_AddRefs(accessible));
|
2007-06-04 02:39:15 -07:00
|
|
|
NS_ENSURE_TRUE(accessible, NS_ERROR_FAILURE);
|
|
|
|
|
2007-04-15 19:21:49 -07:00
|
|
|
PRUint32 type = 0;
|
|
|
|
rv = aEvent->GetEventType(&type);
|
|
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
|
2007-07-08 00:08:04 -07:00
|
|
|
nsAccEvent *event = reinterpret_cast<nsAccEvent*>(aEvent);
|
2007-06-17 22:47:33 -07:00
|
|
|
void *eventData = event->mEventData;
|
|
|
|
|
2007-06-08 02:09:24 -07:00
|
|
|
AtkObject *atkObj = nsAccessibleWrap::GetAtkObject(accessible);
|
|
|
|
|
2007-06-06 19:47:30 -07:00
|
|
|
// We don't create ATK objects for nsIAccessible plain text leaves,
|
|
|
|
// just return NS_OK in such case
|
|
|
|
if (!atkObj) {
|
|
|
|
NS_ASSERTION(type == nsIAccessibleEvent::EVENT_SHOW ||
|
|
|
|
type == nsIAccessibleEvent::EVENT_HIDE,
|
|
|
|
"Event other than SHOW and HIDE fired for plain text leaves");
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
2007-06-17 22:47:33 -07:00
|
|
|
nsAccessibleWrap *accWrap = GetAccessibleWrap(atkObj);
|
2007-06-21 02:16:32 -07:00
|
|
|
if (!accWrap) {
|
|
|
|
return NS_OK; // Node is shut down
|
|
|
|
}
|
2007-06-17 22:47:33 -07:00
|
|
|
|
|
|
|
AtkTableChange * pAtkTableChange = nsnull;
|
|
|
|
|
2007-04-15 19:21:49 -07:00
|
|
|
switch (type) {
|
|
|
|
case nsIAccessibleEvent::EVENT_STATE_CHANGE:
|
2007-04-20 00:29:08 -07:00
|
|
|
return FireAtkStateChangeEvent(aEvent, atkObj);
|
|
|
|
|
|
|
|
case nsIAccessibleEvent::EVENT_TEXT_CHANGED:
|
|
|
|
return FireAtkTextChangedEvent(aEvent, atkObj);
|
|
|
|
|
|
|
|
case nsIAccessibleEvent::EVENT_PROPERTY_CHANGED:
|
|
|
|
return FireAtkPropChangedEvent(aEvent, atkObj);
|
2007-06-17 22:47:33 -07:00
|
|
|
|
|
|
|
case nsIAccessibleEvent::EVENT_FOCUS:
|
|
|
|
{
|
|
|
|
MAI_LOG_DEBUG(("\n\nReceived: EVENT_FOCUS\n"));
|
|
|
|
nsRefPtr<nsRootAccessible> rootAccWrap = accWrap->GetRootAccessible();
|
|
|
|
if (rootAccWrap && rootAccWrap->mActivated) {
|
|
|
|
atk_focus_tracker_notify(atkObj);
|
2007-06-25 01:28:22 -07:00
|
|
|
// Fire state change event for focus
|
|
|
|
nsCOMPtr<nsIAccessibleStateChangeEvent> stateChangeEvent =
|
|
|
|
new nsAccStateChangeEvent(accessible,
|
|
|
|
nsIAccessibleStates::STATE_FOCUSED,
|
|
|
|
PR_FALSE, PR_TRUE);
|
|
|
|
return FireAtkStateChangeEvent(stateChangeEvent, atkObj);
|
2007-06-17 22:47:33 -07:00
|
|
|
}
|
|
|
|
} break;
|
|
|
|
|
|
|
|
case nsIAccessibleEvent::EVENT_VALUE_CHANGE:
|
|
|
|
{
|
|
|
|
MAI_LOG_DEBUG(("\n\nReceived: EVENT_VALUE_CHANGE\n"));
|
|
|
|
nsCOMPtr<nsIAccessibleValue> value(do_QueryInterface(accessible));
|
|
|
|
if (value) { // Make sure this is a numeric value
|
|
|
|
// Don't fire for MSAA string value changes (e.g. text editing)
|
|
|
|
// ATK values are always numeric
|
|
|
|
g_object_notify( (GObject*)atkObj, "accessible-value" );
|
|
|
|
}
|
|
|
|
} break;
|
|
|
|
|
|
|
|
case nsIAccessibleEvent::EVENT_SELECTION_CHANGED:
|
|
|
|
MAI_LOG_DEBUG(("\n\nReceived: EVENT_SELECTION_CHANGED\n"));
|
|
|
|
g_signal_emit_by_name(atkObj, "selection_changed");
|
|
|
|
break;
|
|
|
|
|
|
|
|
case nsIAccessibleEvent::EVENT_TEXT_SELECTION_CHANGED:
|
|
|
|
MAI_LOG_DEBUG(("\n\nReceived: EVENT_TEXT_SELECTION_CHANGED\n"));
|
|
|
|
g_signal_emit_by_name(atkObj, "text_selection_changed");
|
|
|
|
break;
|
|
|
|
|
|
|
|
case nsIAccessibleEvent::EVENT_TEXT_CARET_MOVED:
|
2007-06-22 02:27:22 -07:00
|
|
|
{
|
2007-06-17 22:47:33 -07:00
|
|
|
MAI_LOG_DEBUG(("\n\nReceived: EVENT_TEXT_CARET_MOVED\n"));
|
2007-06-22 02:27:22 -07:00
|
|
|
|
|
|
|
nsCOMPtr<nsIAccessibleCaretMoveEvent> caretMoveEvent(do_QueryInterface(aEvent));
|
|
|
|
NS_ASSERTION(caretMoveEvent, "Event needs event data");
|
|
|
|
if (!caretMoveEvent)
|
2007-06-17 22:47:33 -07:00
|
|
|
break;
|
|
|
|
|
2007-06-22 02:27:22 -07:00
|
|
|
PRInt32 caretOffset = -1;
|
|
|
|
caretMoveEvent->GetCaretOffset(&caretOffset);
|
|
|
|
|
2007-06-24 19:33:18 -07:00
|
|
|
MAI_LOG_DEBUG(("\n\nCaret postion: %d", caretOffset));
|
2007-06-17 22:47:33 -07:00
|
|
|
g_signal_emit_by_name(atkObj,
|
|
|
|
"text_caret_moved",
|
|
|
|
// Curent caret position
|
2007-06-24 19:33:18 -07:00
|
|
|
caretOffset);
|
2007-06-22 02:27:22 -07:00
|
|
|
} break;
|
2007-06-17 22:47:33 -07:00
|
|
|
|
|
|
|
case nsIAccessibleEvent::EVENT_TABLE_MODEL_CHANGED:
|
|
|
|
MAI_LOG_DEBUG(("\n\nReceived: EVENT_TABLE_MODEL_CHANGED\n"));
|
|
|
|
g_signal_emit_by_name(atkObj, "model_changed");
|
|
|
|
break;
|
|
|
|
|
|
|
|
case nsIAccessibleEvent::EVENT_TABLE_ROW_INSERT:
|
|
|
|
MAI_LOG_DEBUG(("\n\nReceived: EVENT_TABLE_ROW_INSERT\n"));
|
|
|
|
NS_ASSERTION(eventData, "Event needs event data");
|
|
|
|
if (!eventData)
|
|
|
|
break;
|
|
|
|
|
2007-07-08 00:08:04 -07:00
|
|
|
pAtkTableChange = reinterpret_cast<AtkTableChange *>(eventData);
|
2007-06-17 22:47:33 -07:00
|
|
|
|
|
|
|
g_signal_emit_by_name(atkObj,
|
|
|
|
"row_inserted",
|
|
|
|
// After which the rows are inserted
|
|
|
|
pAtkTableChange->index,
|
|
|
|
// The number of the inserted
|
|
|
|
pAtkTableChange->count);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case nsIAccessibleEvent::EVENT_TABLE_ROW_DELETE:
|
|
|
|
MAI_LOG_DEBUG(("\n\nReceived: EVENT_TABLE_ROW_DELETE\n"));
|
|
|
|
NS_ASSERTION(eventData, "Event needs event data");
|
|
|
|
if (!eventData)
|
|
|
|
break;
|
|
|
|
|
2007-07-08 00:08:04 -07:00
|
|
|
pAtkTableChange = reinterpret_cast<AtkTableChange *>(eventData);
|
2007-06-17 22:47:33 -07:00
|
|
|
|
|
|
|
g_signal_emit_by_name(atkObj,
|
|
|
|
"row_deleted",
|
|
|
|
// After which the rows are deleted
|
|
|
|
pAtkTableChange->index,
|
|
|
|
// The number of the deleted
|
|
|
|
pAtkTableChange->count);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case nsIAccessibleEvent::EVENT_TABLE_ROW_REORDER:
|
|
|
|
MAI_LOG_DEBUG(("\n\nReceived: EVENT_TABLE_ROW_REORDER\n"));
|
|
|
|
g_signal_emit_by_name(atkObj, "row_reordered");
|
|
|
|
break;
|
|
|
|
|
|
|
|
case nsIAccessibleEvent::EVENT_TABLE_COLUMN_INSERT:
|
|
|
|
MAI_LOG_DEBUG(("\n\nReceived: EVENT_TABLE_COLUMN_INSERT\n"));
|
|
|
|
NS_ASSERTION(eventData, "Event needs event data");
|
|
|
|
if (!eventData)
|
|
|
|
break;
|
|
|
|
|
2007-07-08 00:08:04 -07:00
|
|
|
pAtkTableChange = reinterpret_cast<AtkTableChange *>(eventData);
|
2007-06-17 22:47:33 -07:00
|
|
|
|
|
|
|
g_signal_emit_by_name(atkObj,
|
|
|
|
"column_inserted",
|
|
|
|
// After which the columns are inserted
|
|
|
|
pAtkTableChange->index,
|
|
|
|
// The number of the inserted
|
|
|
|
pAtkTableChange->count);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case nsIAccessibleEvent::EVENT_TABLE_COLUMN_DELETE:
|
|
|
|
MAI_LOG_DEBUG(("\n\nReceived: EVENT_TABLE_COLUMN_DELETE\n"));
|
|
|
|
NS_ASSERTION(eventData, "Event needs event data");
|
|
|
|
if (!eventData)
|
|
|
|
break;
|
|
|
|
|
2007-07-08 00:08:04 -07:00
|
|
|
pAtkTableChange = reinterpret_cast<AtkTableChange *>(eventData);
|
2007-06-17 22:47:33 -07:00
|
|
|
|
|
|
|
g_signal_emit_by_name(atkObj,
|
|
|
|
"column_deleted",
|
|
|
|
// After which the columns are deleted
|
|
|
|
pAtkTableChange->index,
|
|
|
|
// The number of the deleted
|
|
|
|
pAtkTableChange->count);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case nsIAccessibleEvent::EVENT_TABLE_COLUMN_REORDER:
|
|
|
|
MAI_LOG_DEBUG(("\n\nReceived: EVENT_TABLE_COLUMN_REORDER\n"));
|
|
|
|
g_signal_emit_by_name(atkObj, "column_reordered");
|
|
|
|
break;
|
|
|
|
|
|
|
|
case nsIAccessibleEvent::EVENT_SECTION_CHANGED:
|
|
|
|
MAI_LOG_DEBUG(("\n\nReceived: EVENT_SECTION_CHANGED\n"));
|
|
|
|
g_signal_emit_by_name(atkObj, "visible_data_changed");
|
|
|
|
break;
|
|
|
|
|
|
|
|
case nsIAccessibleEvent::EVENT_HYPERTEXT_LINK_SELECTED:
|
|
|
|
MAI_LOG_DEBUG(("\n\nReceived: EVENT_HYPERTEXT_LINK_SELECTED\n"));
|
|
|
|
atk_focus_tracker_notify(atkObj);
|
|
|
|
g_signal_emit_by_name(atkObj,
|
|
|
|
"link_selected",
|
|
|
|
// Selected link index
|
|
|
|
*(gint *)eventData);
|
|
|
|
break;
|
|
|
|
|
2007-06-29 19:49:32 -07:00
|
|
|
case nsIAccessibleEvent::EVENT_SHOW:
|
|
|
|
return FireAtkShowHideEvent(aEvent, atkObj, PR_TRUE);
|
|
|
|
|
|
|
|
case nsIAccessibleEvent::EVENT_HIDE:
|
|
|
|
return FireAtkShowHideEvent(aEvent, atkObj, PR_FALSE);
|
2007-06-17 22:47:33 -07:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Because dealing with menu is very different between nsIAccessible
|
|
|
|
* and ATK, and the menu activity is important, specially transfer the
|
|
|
|
* following two event.
|
|
|
|
* Need more verification by AT test.
|
|
|
|
*/
|
|
|
|
case nsIAccessibleEvent::EVENT_MENU_START:
|
|
|
|
MAI_LOG_DEBUG(("\n\nReceived: EVENT_MENU_START\n"));
|
|
|
|
break;
|
|
|
|
|
|
|
|
case nsIAccessibleEvent::EVENT_MENU_END:
|
|
|
|
MAI_LOG_DEBUG(("\n\nReceived: EVENT_MENU_END\n"));
|
|
|
|
break;
|
|
|
|
|
|
|
|
case nsIAccessibleEvent::EVENT_WINDOW_ACTIVATE:
|
|
|
|
{
|
|
|
|
MAI_LOG_DEBUG(("\n\nReceived: EVENT_WINDOW_ACTIVATED\n"));
|
|
|
|
nsDocAccessibleWrap *accDocWrap =
|
2007-07-08 00:08:04 -07:00
|
|
|
static_cast<nsDocAccessibleWrap *>(accessible.get());
|
2007-06-17 22:47:33 -07:00
|
|
|
accDocWrap->mActivated = PR_TRUE;
|
|
|
|
guint id = g_signal_lookup ("activate", MAI_TYPE_ATK_OBJECT);
|
|
|
|
g_signal_emit(atkObj, id, 0);
|
|
|
|
} break;
|
|
|
|
|
|
|
|
case nsIAccessibleEvent::EVENT_WINDOW_DEACTIVATE:
|
|
|
|
{
|
|
|
|
MAI_LOG_DEBUG(("\n\nReceived: EVENT_WINDOW_DEACTIVATED\n"));
|
|
|
|
nsDocAccessibleWrap *accDocWrap =
|
2007-07-08 00:08:04 -07:00
|
|
|
static_cast<nsDocAccessibleWrap *>(accessible.get());
|
2007-06-17 22:47:33 -07:00
|
|
|
accDocWrap->mActivated = PR_FALSE;
|
|
|
|
guint id = g_signal_lookup ("deactivate", MAI_TYPE_ATK_OBJECT);
|
|
|
|
g_signal_emit(atkObj, id, 0);
|
|
|
|
} break;
|
|
|
|
|
|
|
|
case nsIAccessibleEvent::EVENT_DOCUMENT_LOAD_COMPLETE:
|
|
|
|
{
|
|
|
|
MAI_LOG_DEBUG(("\n\nReceived: EVENT_DOCUMENT_LOAD_COMPLETE\n"));
|
|
|
|
g_signal_emit_by_name (atkObj, "load_complete");
|
|
|
|
} break;
|
|
|
|
|
|
|
|
case nsIAccessibleEvent::EVENT_DOCUMENT_RELOAD:
|
|
|
|
{
|
|
|
|
MAI_LOG_DEBUG(("\n\nReceived: EVENT_DOCUMENT_RELOAD\n"));
|
|
|
|
g_signal_emit_by_name (atkObj, "reload");
|
|
|
|
} break;
|
|
|
|
|
|
|
|
case nsIAccessibleEvent::EVENT_DOCUMENT_LOAD_STOPPED:
|
|
|
|
{
|
|
|
|
MAI_LOG_DEBUG(("\n\nReceived: EVENT_DOCUMENT_LOAD_STOPPED\n"));
|
|
|
|
g_signal_emit_by_name (atkObj, "load_stopped");
|
|
|
|
} break;
|
|
|
|
case nsIAccessibleEvent::EVENT_DOCUMENT_ATTRIBUTES_CHANGED:
|
|
|
|
{
|
|
|
|
MAI_LOG_DEBUG(("\n\nReceived: EVENT_DOCUMENT_ATTRIBUTES_CHANGED\n"));
|
|
|
|
g_signal_emit_by_name (atkObj, "attributes_changed");
|
|
|
|
} break;
|
|
|
|
|
|
|
|
case nsIAccessibleEvent::EVENT_MENUPOPUP_START:
|
2007-06-29 19:49:32 -07:00
|
|
|
MAI_LOG_DEBUG(("\n\nReceived: EVENT_MENUPOPUP_START\n"));
|
|
|
|
atk_focus_tracker_notify(atkObj); // fire extra focus event
|
2007-06-17 22:47:33 -07:00
|
|
|
atk_object_notify_state_change(atkObj, ATK_STATE_VISIBLE, PR_TRUE);
|
|
|
|
atk_object_notify_state_change(atkObj, ATK_STATE_SHOWING, PR_TRUE);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case nsIAccessibleEvent::EVENT_MENUPOPUP_END:
|
2007-06-29 19:49:32 -07:00
|
|
|
MAI_LOG_DEBUG(("\n\nReceived: EVENT_MENUPOPUP_END\n"));
|
2007-06-17 22:47:33 -07:00
|
|
|
atk_object_notify_state_change(atkObj, ATK_STATE_VISIBLE, PR_FALSE);
|
|
|
|
atk_object_notify_state_change(atkObj, ATK_STATE_SHOWING, PR_FALSE);
|
2007-06-29 19:49:32 -07:00
|
|
|
break;
|
2007-04-20 00:29:08 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
return NS_OK;
|
|
|
|
}
|
2007-04-15 19:21:49 -07:00
|
|
|
|
2007-04-20 00:29:08 -07:00
|
|
|
nsresult
|
|
|
|
nsAccessibleWrap::FireAtkStateChangeEvent(nsIAccessibleEvent *aEvent,
|
|
|
|
AtkObject *aObject)
|
|
|
|
{
|
|
|
|
MAI_LOG_DEBUG(("\n\nReceived: EVENT_STATE_CHANGE\n"));
|
|
|
|
|
|
|
|
nsCOMPtr<nsIAccessibleStateChangeEvent> event =
|
|
|
|
do_QueryInterface(aEvent);
|
|
|
|
NS_ENSURE_TRUE(event, NS_ERROR_FAILURE);
|
2007-04-15 19:21:49 -07:00
|
|
|
|
2007-04-20 00:29:08 -07:00
|
|
|
PRUint32 state = 0;
|
|
|
|
event->GetState(&state);
|
2007-04-15 19:21:49 -07:00
|
|
|
|
2007-04-20 00:29:08 -07:00
|
|
|
PRBool isExtra;
|
|
|
|
event->IsExtraState(&isExtra);
|
2007-04-15 19:21:49 -07:00
|
|
|
|
2007-04-20 00:29:08 -07:00
|
|
|
PRBool isEnabled;
|
|
|
|
event->IsEnabled(&isEnabled);
|
2007-04-15 19:21:49 -07:00
|
|
|
|
2007-04-20 00:29:08 -07:00
|
|
|
PRInt32 stateIndex = AtkStateMap::GetStateIndexFor(state);
|
|
|
|
if (stateIndex >= 0) {
|
|
|
|
const AtkStateMap *atkStateMap = isExtra ? gAtkStateMapExt : gAtkStateMap;
|
|
|
|
NS_ASSERTION(atkStateMap[stateIndex].stateMapEntryType != kNoSuchState,
|
|
|
|
"No such state");
|
2007-04-15 19:21:49 -07:00
|
|
|
|
2007-04-20 00:29:08 -07:00
|
|
|
if (atkStateMap[stateIndex].atkState != kNone) {
|
|
|
|
NS_ASSERTION(atkStateMap[stateIndex].stateMapEntryType != kNoStateChange,
|
|
|
|
"State changes should not fired for this state");
|
2007-04-15 19:21:49 -07:00
|
|
|
|
2007-04-20 00:29:08 -07:00
|
|
|
if (atkStateMap[stateIndex].stateMapEntryType == kMapOpposite)
|
|
|
|
isEnabled = !isEnabled;
|
2007-04-15 19:21:49 -07:00
|
|
|
|
2007-04-20 00:29:08 -07:00
|
|
|
// Fire state change for first state if there is one to map
|
|
|
|
atk_object_notify_state_change(aObject,
|
|
|
|
atkStateMap[stateIndex].atkState,
|
|
|
|
isEnabled);
|
2007-04-15 19:21:49 -07:00
|
|
|
}
|
2007-04-20 00:29:08 -07:00
|
|
|
}
|
2007-04-16 23:52:52 -07:00
|
|
|
|
2007-04-20 00:29:08 -07:00
|
|
|
return NS_OK;
|
|
|
|
}
|
2007-04-16 23:52:52 -07:00
|
|
|
|
2007-04-20 00:29:08 -07:00
|
|
|
nsresult
|
|
|
|
nsAccessibleWrap::FireAtkTextChangedEvent(nsIAccessibleEvent *aEvent,
|
|
|
|
AtkObject *aObject)
|
|
|
|
{
|
|
|
|
MAI_LOG_DEBUG(("\n\nReceived: EVENT_TEXT_CHANGED\n"));
|
2007-04-16 23:52:52 -07:00
|
|
|
|
2007-04-20 00:29:08 -07:00
|
|
|
nsCOMPtr<nsIAccessibleTextChangeEvent> event =
|
|
|
|
do_QueryInterface(aEvent);
|
|
|
|
NS_ENSURE_TRUE(event, NS_ERROR_FAILURE);
|
2007-04-16 23:52:52 -07:00
|
|
|
|
2007-04-20 00:29:08 -07:00
|
|
|
PRInt32 start = 0;
|
|
|
|
event->GetStart(&start);
|
2007-04-16 23:52:52 -07:00
|
|
|
|
2007-04-20 00:29:08 -07:00
|
|
|
PRUint32 length = 0;
|
|
|
|
event->GetLength(&length);
|
2007-04-16 23:52:52 -07:00
|
|
|
|
2007-04-20 00:29:08 -07:00
|
|
|
PRBool isInserted;
|
|
|
|
event->IsInserted(&isInserted);
|
|
|
|
|
|
|
|
g_signal_emit_by_name (aObject,
|
|
|
|
isInserted ? \
|
|
|
|
"text_changed::insert":"text_changed::delete",
|
|
|
|
start,
|
|
|
|
length);
|
|
|
|
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
nsresult
|
|
|
|
nsAccessibleWrap::FireAtkPropChangedEvent(nsIAccessibleEvent *aEvent,
|
|
|
|
AtkObject *aObject)
|
|
|
|
{
|
|
|
|
MAI_LOG_DEBUG(("\n\nReceived: EVENT_PROPERTY_CHANGED\n"));
|
|
|
|
|
|
|
|
AtkPropertyChange *pAtkPropChange;
|
|
|
|
AtkPropertyValues values = { NULL };
|
|
|
|
nsAccessibleWrap *oldAccWrap = nsnull, *newAccWrap = nsnull;
|
|
|
|
|
2007-07-08 00:08:04 -07:00
|
|
|
nsAccEvent *event = reinterpret_cast<nsAccEvent*>(aEvent);
|
2007-04-20 00:29:08 -07:00
|
|
|
|
2007-07-08 00:08:04 -07:00
|
|
|
pAtkPropChange = reinterpret_cast<AtkPropertyChange *>(event->mEventData);
|
2007-04-20 00:29:08 -07:00
|
|
|
values.property_name = sAtkPropertyNameArray[pAtkPropChange->type];
|
|
|
|
|
|
|
|
NS_ASSERTION(pAtkPropChange, "Event needs event data");
|
|
|
|
if (!pAtkPropChange)
|
|
|
|
return NS_OK;
|
|
|
|
|
|
|
|
MAI_LOG_DEBUG(("\n\nthe type of EVENT_PROPERTY_CHANGED: %d\n\n",
|
|
|
|
pAtkPropChange->type));
|
|
|
|
|
|
|
|
switch (pAtkPropChange->type) {
|
|
|
|
case PROP_TABLE_CAPTION:
|
|
|
|
case PROP_TABLE_SUMMARY:
|
|
|
|
|
|
|
|
if (pAtkPropChange->oldvalue)
|
2007-07-08 00:08:04 -07:00
|
|
|
oldAccWrap = reinterpret_cast<nsAccessibleWrap *>
|
|
|
|
(pAtkPropChange->oldvalue);
|
2007-04-20 00:29:08 -07:00
|
|
|
|
|
|
|
if (pAtkPropChange->newvalue)
|
2007-07-08 00:08:04 -07:00
|
|
|
newAccWrap = reinterpret_cast<nsAccessibleWrap *>
|
|
|
|
(pAtkPropChange->newvalue);
|
2007-04-20 00:29:08 -07:00
|
|
|
|
|
|
|
if (oldAccWrap && newAccWrap) {
|
|
|
|
g_value_init(&values.old_value, G_TYPE_POINTER);
|
|
|
|
g_value_set_pointer(&values.old_value,
|
|
|
|
oldAccWrap->GetAtkObject());
|
|
|
|
g_value_init(&values.new_value, G_TYPE_POINTER);
|
|
|
|
g_value_set_pointer(&values.new_value,
|
|
|
|
newAccWrap->GetAtkObject());
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case PROP_TABLE_COLUMN_DESCRIPTION:
|
|
|
|
case PROP_TABLE_COLUMN_HEADER:
|
|
|
|
case PROP_TABLE_ROW_HEADER:
|
|
|
|
case PROP_TABLE_ROW_DESCRIPTION:
|
|
|
|
g_value_init(&values.new_value, G_TYPE_INT);
|
|
|
|
g_value_set_int(&values.new_value,
|
2007-07-08 00:08:04 -07:00
|
|
|
*reinterpret_cast<gint *>
|
|
|
|
(pAtkPropChange->newvalue));
|
2007-04-16 23:52:52 -07:00
|
|
|
break;
|
2007-04-20 00:29:08 -07:00
|
|
|
|
|
|
|
//Perhaps need more cases in the future
|
|
|
|
default:
|
|
|
|
g_value_init (&values.old_value, G_TYPE_POINTER);
|
|
|
|
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);
|
2007-04-15 19:21:49 -07:00
|
|
|
}
|
|
|
|
|
2007-04-20 00:29:08 -07:00
|
|
|
char *signal_name = g_strconcat("property_change::",
|
|
|
|
values.property_name, NULL);
|
|
|
|
g_signal_emit_by_name(aObject, signal_name, &values, NULL);
|
|
|
|
g_free (signal_name);
|
|
|
|
|
2007-04-15 19:21:49 -07:00
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
2007-06-29 19:49:32 -07:00
|
|
|
nsresult
|
|
|
|
nsAccessibleWrap::FireAtkShowHideEvent(nsIAccessibleEvent *aEvent,
|
|
|
|
AtkObject *aObject, PRBool aIsAdded)
|
|
|
|
{
|
|
|
|
if (aIsAdded)
|
|
|
|
MAI_LOG_DEBUG(("\n\nReceived: EVENT_SHOW\n"));
|
|
|
|
else
|
|
|
|
MAI_LOG_DEBUG(("\n\nReceived: EVENT_HIDE\n"));
|
|
|
|
|
|
|
|
nsCOMPtr<nsIAccessible> accessible;
|
|
|
|
aEvent->GetAccessible(getter_AddRefs(accessible));
|
|
|
|
NS_ENSURE_STATE(accessible);
|
|
|
|
|
|
|
|
nsCOMPtr<nsIAccessible> parentAccessible;
|
|
|
|
accessible->GetParent(getter_AddRefs(parentAccessible));
|
|
|
|
NS_ENSURE_STATE(parentAccessible);
|
|
|
|
|
|
|
|
PRInt32 indexInParent = -1;
|
|
|
|
accessible->GetIndexInParent(&indexInParent);
|
|
|
|
|
|
|
|
AtkObject *parentObject = GetAtkObject(parentAccessible);
|
|
|
|
NS_ENSURE_STATE(parentObject);
|
|
|
|
|
|
|
|
g_signal_emit_by_name(parentObject,
|
|
|
|
aIsAdded ? \
|
|
|
|
"children_changed::add" : \
|
|
|
|
"children_changed::remove",
|
|
|
|
indexInParent,
|
|
|
|
aObject,
|
|
|
|
NULL);
|
|
|
|
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|