Bug 149654. Send accessibility events for DOM mutations, invalidate appropriate parts of accessibility cache based on DOM mutation events. Also fixes bug 74218, implement DOMSubtreeModified event. r=kyle, sr=jst

This commit is contained in:
aaronl%netscape.com 2003-04-28 10:24:52 +00:00
parent 3a3c81e016
commit 7ae87df2aa
11 changed files with 341 additions and 65 deletions

View File

@ -80,6 +80,7 @@ interface nsIAccessible : nsISupports
[noscript] void setAccParent(in nsIAccessible aAccParent);
[noscript] void setAccFirstChild(in nsIAccessible aAccFirstChild);
[noscript] void setAccNextSibling(in nsIAccessible aAccNextSibling);
[noscript] void invalidateChildren();
[noscript] void fireToolkitEvent(in unsigned long aEvent, in nsIAccessible aTarget, in voidPtr aData);
[noscript] void getNativeInterface(out voidPtr aOutAccessible);

View File

@ -43,4 +43,5 @@ interface nsIAccessibleDocument : nsISupports
[noscript] readonly attribute voidPtr window;
[noscript] nsIAccessNode getCachedAccessNode(in voidPtr aUniqueID);
[noscript] void cacheAccessNode(in voidPtr aUniqueID, in nsIAccessNode aAccessNode);
[noscript] void destroy();
};

View File

@ -283,7 +283,7 @@ PRIntn PR_CALLBACK nsAccessNode::ClearCacheEntry(nsHashKey *aKey, void *aAccessN
nsIAccessNode* accessNode = NS_STATIC_CAST(nsIAccessNode*, aAccessNode);
accessNode->Shutdown();
return PL_DHASH_NEXT;
return kHashEnumerateRemove;
}
void nsAccessNode::ClearCache(nsSupportsHashtable *aCache)

View File

@ -762,15 +762,16 @@ nsAccessibilityService::CreateHTMLTextAccessible(nsISupports *aFrame, nsIAccessi
nsCOMPtr<nsITextContent> textContent(do_QueryInterface(node));
if (textContent) {
// If empty text string, don't include in accessible tree
// Items with length 0 are already gone, we just need to check for single NBSP's
// Items with length 0 are already gone, we also need to check for single NBSP's
// or newlines, both of which indicate an empty text object
PRInt32 textLength = 0;
textContent->GetTextLength(&textLength);
if (textLength == 1) {
const PRUnichar NBSP = 160;
const nsTextFragment *textFrag;
textContent->GetText(&textFrag);
PRUnichar theChar = textFrag->CharAt(0);
if (theChar == NBSP)
// Check for NBSP (160) or newline
if (theChar == 160 || theChar=='\n')
return NS_ERROR_FAILURE;
}
nsCOMPtr<nsIDOMNode> parentNode;

View File

@ -209,6 +209,14 @@ NS_IMETHODIMP nsAccessible::SetAccNextSibling(nsIAccessible *aNextSibling)
return NS_OK;
}
NS_IMETHODIMP nsAccessible::InvalidateChildren()
{
// Document has transformed, reset our invalid children and child count
mAccChildCount = -1;
mFirstChild = mNextSibling = mParent = nsnull;
return NS_OK;
}
NS_IMETHODIMP nsAccessible::GetAccParent(nsIAccessible ** aAccParent)
{
if (mParent) {
@ -1293,6 +1301,8 @@ NS_IMETHODIMP nsAccessible::GetXULAccName(nsAString& _retval)
NS_IMETHODIMP nsAccessible::FireToolkitEvent(PRUint32 aEvent, nsIAccessible *aTarget, void * aData)
{
if (!mWeakShell)
return NS_ERROR_FAILURE; // Don't fire event for accessible that has been shut down
nsCOMPtr<nsIAccessibleDocument> docAccessible(GetDocAccessible());
nsCOMPtr<nsIAccessible> eventHandlingAccessible(do_QueryInterface(docAccessible));
if (eventHandlingAccessible) {

View File

@ -41,9 +41,12 @@
#include "nsIPresShell.h"
#include "nsIFrame.h"
#include "nsIDOMDocument.h"
#include "nsIDOMNSDocument.h"
#include "nsIDOMEventTarget.h"
#include "nsIDOMEvent.h"
#include "nsIDOMDocument.h"
#include "nsIDOMDocumentType.h"
#include "nsIDOMNSDocument.h"
#include "nsIDOMMutationEvent.h"
#ifdef MOZ_XUL
#include "nsIXULDocument.h"
#endif
@ -109,8 +112,9 @@ nsDocAccessible::~nsDocAccessible()
{
}
NS_IMPL_ISUPPORTS_INHERITED5(nsDocAccessible, nsAccessible, nsIAccessibleDocument,
NS_IMPL_ISUPPORTS_INHERITED6(nsDocAccessible, nsAccessible, nsIAccessibleDocument,
nsIAccessibleEventReceiver, nsIWebProgressListener,
nsIDOMMutationListener,
nsIScrollPositionListener, nsISupportsWeakReference)
NS_IMETHODIMP nsDocAccessible::AddEventListeners()
@ -244,17 +248,34 @@ NS_IMETHODIMP nsDocAccessible::CacheAccessNode(void *aUniqueID, nsIAccessNode *a
return NS_OK;
}
NS_IMETHODIMP nsDocAccessible::Destroy()
{
#ifdef OLD_HASH
nsVoidKey key(NS_STATIC_CAST(void*, mWeakShell));
gGlobalDocAccessibleCache->Remove(&key);
#else
gGlobalDocAccessibleCache->Remove(NS_STATIC_CAST(void*, mWeakShell));
#endif
return Shutdown();
}
NS_IMETHODIMP nsDocAccessible::Shutdown()
{
if (!mWeakShell) {
return NS_OK; // Already shutdown
}
void* presShellKey = NS_STATIC_CAST(void*, mWeakShell);
mWeakShell = nsnull; // Avoid reentrancy
RemoveEventListeners();
mScrollWatchTimer = mDocLoadTimer = nsnull;
if (mScrollWatchTimer) {
mScrollWatchTimer->Cancel();
mScrollWatchTimer = nsnull;
}
if (mDocLoadTimer) {
mDocLoadTimer->Cancel();
mDocLoadTimer = nsnull;
}
mWebProgress = nsnull;
if (mAccessNodeCache) {
@ -269,12 +290,6 @@ NS_IMETHODIMP nsDocAccessible::Shutdown()
}
NS_ASSERTION(gGlobalDocAccessibleCache, "Global doc cache does not exist");
#ifdef OLD_HASH
nsVoidKey key(presShellKey);
gGlobalDocAccessibleCache->Remove(&key);
#else
gGlobalDocAccessibleCache->Remove(presShellKey);
#endif
mDocument = nsnull;
return nsAccessibleWrap::Shutdown();
}
@ -363,6 +378,29 @@ void nsDocAccessible::AddContentDocListeners()
nsITimer::TYPE_ONE_SHOT);
}
}
// add ourself as a mutation event listener
// (this slows down mozilla about 3%, but only used when accessibility APIs active)
nsCOMPtr<nsIDOMEventTarget> target(do_QueryInterface(mDocument));
NS_ASSERTION(target, "No dom event target for document");
nsresult rv = target->AddEventListener(NS_LITERAL_STRING("DOMAttrModified"),
this, PR_TRUE);
NS_ASSERTION(NS_SUCCEEDED(rv), "failed to register listener");
rv = target->AddEventListener(NS_LITERAL_STRING("DOMSubtreeModified"),
this, PR_TRUE);
NS_ASSERTION(NS_SUCCEEDED(rv), "failed to register listener");
rv = target->AddEventListener(NS_LITERAL_STRING("DOMNodeInserted"),
this, PR_TRUE);
NS_ASSERTION(NS_SUCCEEDED(rv), "failed to register listener");
rv = target->AddEventListener(NS_LITERAL_STRING("DOMNodeRemoved"),
this, PR_TRUE);
NS_ASSERTION(NS_SUCCEEDED(rv), "failed to register listener");
rv = target->AddEventListener(NS_LITERAL_STRING("DOMNodeInsertedIntoDocument"),
this, PR_TRUE);
NS_ASSERTION(NS_SUCCEEDED(rv), "failed to register listener");
rv = target->AddEventListener(NS_LITERAL_STRING("DOMNodeRemovedFromDocument"),
this, PR_TRUE);
NS_ASSERTION(NS_SUCCEEDED(rv), "failed to register listener");
}
void nsDocAccessible::RemoveContentDocListeners()
@ -378,13 +416,21 @@ void nsDocAccessible::RemoveContentDocListeners()
// Remove scroll position listener
nsCOMPtr<nsIPresShell> presShell(do_QueryReferent(mWeakShell));
RemoveScrollListener(presShell);
nsCOMPtr<nsIDOMEventTarget> target(do_QueryInterface(mDocument));
NS_ASSERTION(target, "No dom event target for document");
target->RemoveEventListener(NS_LITERAL_STRING("DOMAttrModified"), this, PR_TRUE);
target->RemoveEventListener(NS_LITERAL_STRING("DOMSubtreeModified"), this, PR_TRUE);
target->RemoveEventListener(NS_LITERAL_STRING("DOMNodeInserted"), this, PR_TRUE);
target->RemoveEventListener(NS_LITERAL_STRING("DOMNodeRemoved"), this, PR_TRUE);
target->RemoveEventListener(NS_LITERAL_STRING("DOMNodeInsertedIntoDocument"), this, PR_TRUE);
target->RemoveEventListener(NS_LITERAL_STRING("DOMNodeRemovedFromDocument"), this, PR_TRUE);
}
void nsDocAccessible::FireDocLoadFinished()
{
NS_ASSERTION(mDocument, "No Document - Bug 202972");
if (!mDocument)
return;
if (!mDocument || !mWeakShell)
return; // Document has been shut down
// Hook up our new accessible with our parent
if (!mParent) {
@ -535,8 +581,8 @@ NS_IMETHODIMP nsDocAccessible::OnLocationChange(nsIWebProgress *aWebProgress,
{
// Load has been verified, it will occur, about to commence
// We won't fire a "doc finished loading" event on this nsRootAccessible
// Instead we fire that on the new nsRootAccessible that is created for the new doc
// We won't fire a "doc finished loading" event on this nsDocAccessible
// Instead we fire that on the new nsDocAccessible that is created for the new doc
mIsNewDocument = PR_FALSE; // We're a doc that's going away
if (mBusy != eBusyStateLoading) {
@ -572,3 +618,187 @@ NS_IMETHODIMP nsDocAccessible::OnSecurityChange(nsIWebProgress *aWebProgress,
return NS_OK;
}
// ---------- Mutation event listeners ------------
NS_IMETHODIMP nsDocAccessible::NodeInserted(nsIDOMEvent* aEvent)
{
HandleMutationEvent(aEvent, nsIAccessibleEventReceiver::EVENT_CREATE);
return NS_OK;
}
NS_IMETHODIMP nsDocAccessible::NodeRemoved(nsIDOMEvent* aEvent)
{
// The related node for the event will be the parent of the removed node or subtree
HandleMutationEvent(aEvent, nsIAccessibleEventReceiver::EVENT_DESTROY);
return NS_OK;
}
NS_IMETHODIMP nsDocAccessible::SubtreeModified(nsIDOMEvent* aEvent)
{
HandleMutationEvent(aEvent, nsIAccessibleEventReceiver::EVENT_REORDER);
return NS_OK;
}
NS_IMETHODIMP nsDocAccessible::AttrModified(nsIDOMEvent* aMutationEvent)
{
// XXX todo
// We will probably need to handle special cases here
// For example, if an <img>'s usemap attribute is modified
// Otherwise it may just be a state change, for example an object changing
// its visibility.
return NS_OK;
}
NS_IMETHODIMP nsDocAccessible::NodeRemovedFromDocument(nsIDOMEvent* aMutationEvent)
{
// Not implemented yet, see bug 74220
return NS_OK;
}
NS_IMETHODIMP nsDocAccessible::NodeInsertedIntoDocument(nsIDOMEvent* aMutationEvent)
{
// Not implemented yet, see bug 74219
// This is different from NodeInserted() in that it's fired when
// a node is inserted into a document, but isn't necessarily mean that
// it's becoming part of the DOM tree.
return NS_OK;
}
NS_IMETHODIMP nsDocAccessible::HandleEvent(nsIDOMEvent* aEvent)
{
NS_NOTREACHED("Should be handled by specific methods like NodeInserted, etc.");
return NS_OK;
}
NS_IMETHODIMP nsDocAccessible::CharacterDataModified(nsIDOMEvent* aMutationEvent)
{
return NS_OK;
}
void nsDocAccessible::InvalidateCacheSubtree(nsIDOMNode *aStartNode)
{
// Invalidate cache subtree
// We have to check for accessibles for each dom node by traversing DOM tree
// instead of just the accessible tree, although that would be faster
// Otherwise we might miss the nsAccessNode's that are not nsAccessible's.
if (!aStartNode)
return;
nsCOMPtr<nsIDOMNode> iterNode(aStartNode), nextNode;
nsCOMPtr<nsIAccessNode> accessNode;
do {
GetCachedAccessNode(NS_STATIC_CAST(void*, iterNode),
getter_AddRefs(accessNode));
if (accessNode) {
// XXX aaronl todo: accessibles that implement their own subtrees,
// like html combo boxes and xul trees, need to shutdown all of their own
// children when they override Shutdown()
accessNode->Shutdown();
}
iterNode->GetFirstChild(getter_AddRefs(nextNode));
if (nextNode) {
iterNode = nextNode;
continue;
}
if (iterNode == aStartNode)
break;
iterNode->GetNextSibling(getter_AddRefs(nextNode));
if (nextNode) {
iterNode = nextNode;
continue;
}
do {
iterNode->GetParentNode(getter_AddRefs(nextNode));
if (!nextNode || nextNode == aStartNode) {
return;
}
nextNode->GetNextSibling(getter_AddRefs(iterNode));
if (iterNode)
break;
iterNode = nextNode;
} while (PR_TRUE);
}
while (iterNode && iterNode != aStartNode);
}
void nsDocAccessible::HandleMutationEvent(nsIDOMEvent *aEvent, PRUint32 aAccessibleEventType)
{
if (mBusy != eBusyStateDone)
return; // We don't want mutation events until doc is fully loaded
nsCOMPtr<nsIDOMEvent> domEvent(do_QueryInterface(aEvent));
nsCOMPtr<nsIDOMEventTarget> domEventTarget;
if (domEvent) {
domEvent->GetTarget(getter_AddRefs(domEventTarget));
}
nsCOMPtr<nsIDOMNode> targetNode(do_QueryInterface(domEventTarget));
if (!targetNode)
return;
nsCOMPtr<nsIDOMNode> subTreeNode;
if (aAccessibleEventType == nsIAccessibleEventReceiver::EVENT_CREATE) {
// DOMNodeInserted
// We'll need to invalidate the child count and cached children of
// the direct parent, otherwise no new accessibles will appear at this
// place in the tree.
// However, don't invalidate the entire subtree - most of it is still good.
targetNode->GetParentNode(getter_AddRefs(subTreeNode));
NS_ASSERTION(subTreeNode, "No valid parent of insertion");
targetNode = subTreeNode;
}
else {
if (aAccessibleEventType == nsIAccessibleEventReceiver::EVENT_REORDER) {
// DOMSubtreeModified
// The event target is the parent of the reordered tree
// We don't want to invalidate that entire subtree.
nsCOMPtr<nsIDOMMutationEvent> mutationEvent(do_QueryInterface(aEvent));
NS_ASSERTION(mutationEvent, "Not a mutation event!");
mutationEvent->GetRelatedNode(getter_AddRefs(subTreeNode));
NS_ASSERTION(subTreeNode, "No old sub tree being replaced in DOMSubtreeModified");
}
else {
// nsIAccessibleEventReceiver::EVENT_DESTROY / DOMNodeRemoved
subTreeNode = targetNode;
}
InvalidateCacheSubtree(subTreeNode);
}
// We need to get an accessible for the mutation event's target node
// If there is no accessible for that node, we need to keep moving up the parent
// chain so there is some accessible.
// We will use this accessible to fire the accessible mutation event.
// We're guaranteed success, because we will eventually end up at the doc accessible,
// and there is always one of those.
// XXX aaronl todo: are MSAA mutation events always fired on the container?
// if so, we always need to get the dom parent at least once
nsCOMPtr<nsIAccessibilityService> accService =
do_GetService("@mozilla.org/accessibilityService;1");
if (!accService)
return;
nsCOMPtr<nsIAccessible> accessible;
while (NS_FAILED(accService->GetAccessibleInWeakShell(targetNode, mWeakShell,
getter_AddRefs(accessible)))) {
targetNode->GetParentNode(getter_AddRefs(subTreeNode));
NS_ASSERTION(subTreeNode, "Crawled up parent chain without finding accessible");
targetNode = subTreeNode;
}
accessible->InvalidateChildren();
#ifdef XP_WIN
// Windows MSAA clients crash if the listen to create or destroy events
aAccessibleEventType = nsIAccessibleEventReceiver::EVENT_REORDER;
#endif
accessible->FireToolkitEvent(aAccessibleEventType, accessible, nsnull);
}

View File

@ -40,15 +40,16 @@
#define _nsDocAccessible_H_
#include "nsAccessibleWrap.h"
#include "nsIAccessibleDocument.h"
#include "nsIDocument.h"
#include "nsIAccessibleEventReceiver.h"
#include "nsHashtable.h"
#include "nsIWebProgressListener.h"
#include "nsITimer.h"
#include "nsIWebProgress.h"
#include "nsIAccessibleDocument.h"
#include "nsIAccessibleEventReceiver.h"
#include "nsIDocument.h"
#include "nsIDOMMutationListener.h"
#include "nsIScrollPositionListener.h"
#include "nsITimer.h"
#include "nsIWeakReference.h"
#include "nsIWebProgress.h"
#include "nsIWebProgressListener.h"
class nsIScrollableView;
@ -58,11 +59,12 @@ class nsDocAccessible : public nsAccessibleWrap,
public nsIAccessibleDocument,
public nsIAccessibleEventReceiver,
public nsIWebProgressListener,
public nsIDOMMutationListener,
public nsIScrollPositionListener,
public nsSupportsWeakReference
{
enum EBusyState {eBusyStateUninitialized, eBusyStateLoading, eBusyStateDone};
NS_DECL_ISUPPORTS_INHERITED
NS_DECL_NSIACCESSIBLEDOCUMENT
NS_DECL_NSIACCESSIBLEEVENTRECEIVER
@ -80,12 +82,22 @@ class nsDocAccessible : public nsAccessibleWrap,
NS_IMETHOD ScrollPositionWillChange(nsIScrollableView *aView, nscoord aX, nscoord aY);
NS_IMETHOD ScrollPositionDidChange(nsIScrollableView *aView, nscoord aX, nscoord aY);
// ----- nsIDOMMutationListener -------------------------
NS_IMETHOD HandleEvent(nsIDOMEvent* aEvent);
NS_IMETHOD SubtreeModified(nsIDOMEvent* aMutationEvent);
NS_IMETHOD NodeInserted(nsIDOMEvent* aMutationEvent);
NS_IMETHOD NodeRemoved(nsIDOMEvent* aMutationEvent);
NS_IMETHOD NodeRemovedFromDocument(nsIDOMEvent* aMutationEvent);
NS_IMETHOD NodeInsertedIntoDocument(nsIDOMEvent* aMutationEvent);
NS_IMETHOD AttrModified(nsIDOMEvent* aMutationEvent);
NS_IMETHOD CharacterDataModified(nsIDOMEvent* aMutationEvent);
NS_DECL_NSIWEBPROGRESSLISTENER
// nsIAccessNode
NS_IMETHOD Shutdown();
protected:
protected:
virtual void GetBounds(nsRect& aRect, nsIFrame** aRelativeFrame);
virtual nsIFrame* GetFrame();
void AddContentDocListeners();
@ -93,6 +105,8 @@ class nsDocAccessible : public nsAccessibleWrap,
void AddScrollListener(nsIPresShell *aPresShell);
void RemoveScrollListener(nsIPresShell *aPresShell);
void FireDocLoadFinished();
void InvalidateCacheSubtree(nsIDOMNode *aStartNode);
void HandleMutationEvent(nsIDOMEvent *aEvent, PRUint32 aEventType);
static void DocLoadCallback(nsITimer *aTimer, void *aClosure);
static void ScrollTimerCallback(nsITimer *aTimer, void *aClosure);
@ -111,5 +125,4 @@ class nsDocAccessible : public nsAccessibleWrap,
PRPackedBool mIsNewDocument;
};
#endif

View File

@ -175,7 +175,7 @@ NS_IMETHODIMP nsRootAccessible::AddEventListeners()
rv = target->AddEventListener(NS_LITERAL_STRING("DOMMenuBarInactive"), NS_STATIC_CAST(nsIDOMXULListener*, this), PR_TRUE);
NS_ASSERTION(NS_SUCCEEDED(rv), "failed to register listener");
AddContentDocListeners();
}
if (!mCaretAccessible)
@ -198,6 +198,9 @@ NS_IMETHODIMP nsRootAccessible::RemoveEventListeners()
target->RemoveEventListener(NS_LITERAL_STRING("DOMMenuItemActive"), NS_STATIC_CAST(nsIDOMXULListener*, this), PR_TRUE);
target->RemoveEventListener(NS_LITERAL_STRING("DOMMenuBarActive"), NS_STATIC_CAST(nsIDOMXULListener*, this), PR_TRUE);
target->RemoveEventListener(NS_LITERAL_STRING("DOMMenuBarInactive"), NS_STATIC_CAST(nsIDOMXULListener*, this), PR_TRUE);
target->RemoveEventListener(NS_LITERAL_STRING("DOMMenuBarInactive"), NS_STATIC_CAST(nsIDOMXULListener*, this), PR_TRUE);
target->RemoveEventListener(NS_LITERAL_STRING("RadioStateChange"), NS_STATIC_CAST(nsIDOMXULListener*, this), PR_TRUE);
target->RemoveEventListener(NS_LITERAL_STRING("ListitemStateChange"), NS_STATIC_CAST(nsIDOMXULListener*, this), PR_TRUE);
}
if (mScrollWatchTimer) {
@ -246,6 +249,21 @@ void nsRootAccessible::FireAccessibleFocusEvent(nsIAccessible *focusAccessible,
}
}
void nsRootAccessible::GetEventShell(nsIDOMNode *aNode, nsIPresShell **aEventShell)
{
// XXX aaronl - this is not ideal.
// We could avoid this whole section and the fallible
// doc->GetShellAt(0, ...) by putting the event handler
// on nsDocAccessible instead.
// The disadvantage would be that we would be seeing some events
// for inner documents that we don't care about.
nsCOMPtr<nsIDOMDocument> domDocument;
aNode->GetOwnerDocument(getter_AddRefs(domDocument));
nsCOMPtr<nsIDocument> doc(do_QueryInterface(domDocument));
if (doc)
doc->GetShellAt(0, aEventShell);
}
// --------------- nsIDOMEventListener Methods (3) ------------------------
NS_IMETHODIMP nsRootAccessible::HandleEvent(nsIDOMEvent* aEvent)
@ -279,21 +297,10 @@ NS_IMETHODIMP nsRootAccessible::HandleEvent(nsIDOMEvent* aEvent)
}
#endif
nsCOMPtr<nsIAccessible> accessible;
// XXX aaronl - this is not ideal.
// We could avoid this whole section and the fallible
// doc->GetShellAt(0, ...) by putting the event handler
// on nsDocAccessible instead.
// The disadvantage would be that we would be seeing some events
// for inner documents that we don't care about.
nsCOMPtr<nsIDOMDocument> domDocument;
targetNode->GetOwnerDocument(getter_AddRefs(domDocument));
nsCOMPtr<nsIDocument> doc(do_QueryInterface(domDocument));
nsCOMPtr<nsIPresShell> eventShell;
if (doc) {
doc->GetShellAt(0, getter_AddRefs(eventShell));
}
GetEventShell(targetNode, getter_AddRefs(eventShell));
nsCOMPtr<nsIAccessible> accessible;
if (!eventShell ||
NS_FAILED(mAccService->GetAccessibleInShell(targetNode, eventShell,
getter_AddRefs(accessible))))

View File

@ -40,14 +40,14 @@
#define _nsRootAccessible_H_
#include "nsDocAccessibleWrap.h"
#include "nsHashtable.h"
#include "nsIAccessibilityService.h"
#include "nsIAccessibleEventReceiver.h"
#include "nsIAccessibleDocument.h"
#include "nsIDocument.h"
#include "nsIDOMFocusListener.h"
#include "nsIDOMFormListener.h"
#include "nsIDOMXULListener.h"
#include "nsIDOMFocusListener.h"
#include "nsIDocument.h"
#include "nsIAccessibilityService.h"
#include "nsHashtable.h"
class nsIAccessibleEventListener;
@ -102,8 +102,9 @@ class nsRootAccessible : public nsDocAccessibleWrap,
void ShutdownAll();
protected:
void GetTargetNode(nsIDOMEvent *aEvent, nsIDOMNode **aTargetNode);
static void GetTargetNode(nsIDOMEvent *aEvent, nsIDOMNode **aTargetNode);
void FireAccessibleFocusEvent(nsIAccessible *focusAccessible, nsIDOMNode *focusNode);
void GetEventShell(nsIDOMNode *aNode, nsIPresShell **aEventShell);
nsCOMPtr<nsIAccessibilityService> mAccService;
nsCOMPtr<nsIAccessibleCaret> mCaretAccessible;
};

View File

@ -3726,6 +3726,18 @@ nsGenericHTMLContainerElement::ReplaceChildAt(nsIContent* aKid,
doc->ContentReplaced(this, oldKid, aKid, aIndex);
}
}
if (nsGenericElement::HasMutationListeners(this, NS_EVENT_BITS_MUTATION_SUBTREEMODIFIED)) {
nsMutationEvent mutation;
mutation.eventStructType = NS_MUTATION_EVENT;
mutation.message = NS_MUTATION_SUBTREEMODIFIED;
mutation.mTarget = do_QueryInterface(this);
mutation.mRelatedNode = do_QueryInterface(oldKid);
nsEventStatus status = nsEventStatus_eIgnore;
HandleDOMEvent(nsnull, &mutation, nsnull,
NS_EVENT_FLAG_INIT, &status);
}
if (oldKid) {
oldKid->SetDocument(nsnull, PR_TRUE, PR_TRUE);
oldKid->SetParent(nsnull);

View File

@ -817,9 +817,9 @@ nsWindow::~nsWindow()
{
#ifdef ACCESSIBILITY
if (mRootAccessible) {
nsCOMPtr<nsIAccessNode> accessNode(do_QueryInterface(mRootAccessible));
if (accessNode) {
accessNode->Shutdown();
nsCOMPtr<nsIAccessibleDocument> accessDoc(do_QueryInterface(mRootAccessible));
if (accessDoc) {
accessDoc->Destroy();
}
mRootAccessible->Release();
mRootAccessible = nsnull;
@ -4669,24 +4669,24 @@ LPCWSTR nsWindow::WindowPopupClassW()
LPCTSTR nsWindow::WindowClass()
{
// Call into the wide version to make sure things get
// registered properly.
WindowClassW();
// XXX: The class name used here must be kept in sync with
// the classname used in WindowClassW();
return "MozillaWindowClass";
// Call into the wide version to make sure things get
// registered properly.
WindowClassW();
// XXX: The class name used here must be kept in sync with
// the classname used in WindowClassW();
return "MozillaWindowClass";
}
LPCTSTR nsWindow::WindowPopupClass()
{
// Call into the wide version to make sure things get
// registered properly.
WindowPopupClassW();
// XXX: The class name used here must be kept in sync with
// the classname used in WindowPopupClassW();
return "MozillaDropShadowWindowClass";
// Call into the wide version to make sure things get
// registered properly.
WindowPopupClassW();
// XXX: The class name used here must be kept in sync with
// the classname used in WindowPopupClassW();
return "MozillaDropShadowWindowClass";
}
//-------------------------------------------------------------------------