2007-03-22 10:30:00 -07:00
|
|
|
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
|
|
|
/* ***** 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
|
|
|
|
* Netscape Communications Corporation.
|
|
|
|
* Portions created by the Initial Developer are Copyright (C) 1998
|
|
|
|
* the Initial Developer. All Rights Reserved.
|
|
|
|
*
|
|
|
|
* Contributor(s):
|
|
|
|
*
|
|
|
|
* Alternatively, the contents of this file may be used under the terms of
|
|
|
|
* either of 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 ***** */
|
|
|
|
|
|
|
|
// NOTE: alphabetically ordered
|
|
|
|
#include "nsAccessibilityService.h"
|
|
|
|
#include "nsAccessibleEventData.h"
|
|
|
|
#include "nsHTMLSelectAccessible.h"
|
|
|
|
#include "nsIBaseWindow.h"
|
|
|
|
#include "nsICaret.h"
|
|
|
|
#include "nsIDocShell.h"
|
|
|
|
#include "nsIDocShellTreeItem.h"
|
|
|
|
#include "nsIDocShellTreeNode.h"
|
|
|
|
#include "nsIDocShellTreeOwner.h"
|
|
|
|
#include "nsIDOMDocument.h"
|
|
|
|
#include "nsIDOMElement.h"
|
|
|
|
#include "nsIDOMEventListener.h"
|
|
|
|
#include "nsIDOMEventTarget.h"
|
|
|
|
#include "nsIDOMHTMLAnchorElement.h"
|
|
|
|
#include "nsIDOMHTMLImageElement.h"
|
|
|
|
#include "nsIDOMHTMLInputElement.h"
|
|
|
|
#include "nsIDOMHTMLSelectElement.h"
|
2007-12-11 00:18:04 -08:00
|
|
|
#include "nsIDOMDataContainerEvent.h"
|
2007-03-22 10:30:00 -07:00
|
|
|
#include "nsIDOMNSEvent.h"
|
|
|
|
#include "nsIDOMXULMenuListElement.h"
|
|
|
|
#include "nsIDOMXULMultSelectCntrlEl.h"
|
|
|
|
#include "nsIDOMXULSelectCntrlItemEl.h"
|
|
|
|
#include "nsIDOMXULPopupElement.h"
|
|
|
|
#include "nsIDocument.h"
|
|
|
|
#include "nsIEventListenerManager.h"
|
|
|
|
#include "nsIFocusController.h"
|
|
|
|
#include "nsIFrame.h"
|
2007-07-04 08:49:38 -07:00
|
|
|
#include "nsIMenuFrame.h"
|
2007-04-07 11:48:29 -07:00
|
|
|
#include "nsIHTMLDocument.h"
|
2007-03-22 10:30:00 -07:00
|
|
|
#include "nsIInterfaceRequestorUtils.h"
|
2007-04-07 11:48:29 -07:00
|
|
|
#include "nsIMenuParent.h"
|
2007-03-22 10:30:00 -07:00
|
|
|
#include "nsIScrollableView.h"
|
|
|
|
#include "nsISelectionPrivate.h"
|
|
|
|
#include "nsIServiceManager.h"
|
|
|
|
#include "nsIViewManager.h"
|
|
|
|
#include "nsPIDOMWindow.h"
|
|
|
|
#include "nsIWebBrowserChrome.h"
|
|
|
|
#include "nsReadableUtils.h"
|
|
|
|
#include "nsRootAccessible.h"
|
|
|
|
#include "nsIDOMNSEventTarget.h"
|
|
|
|
#include "nsIDOMDocumentEvent.h"
|
|
|
|
|
|
|
|
#ifdef MOZ_XUL
|
|
|
|
#include "nsXULTreeAccessible.h"
|
|
|
|
#include "nsIXULDocument.h"
|
|
|
|
#include "nsIXULWindow.h"
|
|
|
|
#endif
|
|
|
|
|
2007-06-01 20:01:38 -07:00
|
|
|
#ifdef MOZ_ACCESSIBILITY_ATK
|
|
|
|
#include "nsAppRootAccessible.h"
|
|
|
|
#else
|
|
|
|
#include "nsApplicationAccessibleWrap.h"
|
|
|
|
#endif
|
|
|
|
|
2007-03-22 10:30:00 -07:00
|
|
|
// Expanded version of NS_IMPL_ISUPPORTS_INHERITED2
|
|
|
|
// so we can QI directly to concrete nsRootAccessible
|
|
|
|
NS_IMPL_QUERY_HEAD(nsRootAccessible)
|
|
|
|
NS_IMPL_QUERY_BODY(nsIDOMEventListener)
|
|
|
|
if (aIID.Equals(NS_GET_IID(nsRootAccessible)))
|
2007-07-08 00:08:04 -07:00
|
|
|
foundInterface = reinterpret_cast<nsISupports*>(this);
|
2007-03-22 10:30:00 -07:00
|
|
|
else
|
|
|
|
NS_IMPL_QUERY_TAIL_INHERITING(nsDocAccessible)
|
|
|
|
|
|
|
|
NS_IMPL_ADDREF_INHERITED(nsRootAccessible, nsDocAccessible)
|
|
|
|
NS_IMPL_RELEASE_INHERITED(nsRootAccessible, nsDocAccessible)
|
|
|
|
|
|
|
|
//-----------------------------------------------------
|
|
|
|
// construction
|
|
|
|
//-----------------------------------------------------
|
|
|
|
nsRootAccessible::nsRootAccessible(nsIDOMNode *aDOMNode, nsIWeakReference* aShell):
|
2007-08-20 20:16:27 -07:00
|
|
|
nsDocAccessibleWrap(aDOMNode, aShell)
|
2007-03-22 10:30:00 -07:00
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
//-----------------------------------------------------
|
|
|
|
// destruction
|
|
|
|
//-----------------------------------------------------
|
|
|
|
nsRootAccessible::~nsRootAccessible()
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
// helpers
|
|
|
|
/* readonly attribute AString name; */
|
|
|
|
NS_IMETHODIMP nsRootAccessible::GetName(nsAString& aName)
|
|
|
|
{
|
|
|
|
if (!mDocument) {
|
|
|
|
return NS_ERROR_FAILURE;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (mRoleMapEntry) {
|
|
|
|
nsAccessible::GetName(aName);
|
|
|
|
if (!aName.IsEmpty()) {
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
nsCOMPtr<nsIDocShellTreeItem> docShellAsItem =
|
2007-09-05 00:39:09 -07:00
|
|
|
nsAccUtils::GetDocShellTreeItemFor(mDOMNode);
|
2007-03-22 10:30:00 -07:00
|
|
|
NS_ENSURE_TRUE(docShellAsItem, NS_ERROR_FAILURE);
|
|
|
|
|
|
|
|
nsCOMPtr<nsIDocShellTreeOwner> treeOwner;
|
|
|
|
docShellAsItem->GetTreeOwner(getter_AddRefs(treeOwner));
|
|
|
|
|
|
|
|
nsCOMPtr<nsIBaseWindow> baseWindow(do_QueryInterface(treeOwner));
|
|
|
|
if (baseWindow) {
|
|
|
|
nsXPIDLString title;
|
|
|
|
baseWindow->GetTitle(getter_Copies(title));
|
|
|
|
aName.Assign(title);
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
return NS_ERROR_FAILURE;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* readonly attribute nsIAccessible accParent; */
|
|
|
|
NS_IMETHODIMP nsRootAccessible::GetParent(nsIAccessible * *aParent)
|
2007-06-01 20:01:38 -07:00
|
|
|
{
|
|
|
|
NS_ENSURE_ARG_POINTER(aParent);
|
2007-03-22 10:30:00 -07:00
|
|
|
*aParent = nsnull;
|
2007-06-01 20:01:38 -07:00
|
|
|
|
|
|
|
nsRefPtr<nsApplicationAccessibleWrap> root = GetApplicationAccessible();
|
|
|
|
NS_IF_ADDREF(*aParent = root);
|
|
|
|
|
2007-03-22 10:30:00 -07:00
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* readonly attribute unsigned long accRole; */
|
|
|
|
NS_IMETHODIMP nsRootAccessible::GetRole(PRUint32 *aRole)
|
|
|
|
{
|
|
|
|
if (!mDocument) {
|
|
|
|
return NS_ERROR_FAILURE;
|
|
|
|
}
|
|
|
|
|
|
|
|
// If it's a <dialog> or <wizard>, use nsIAccessibleRole::ROLE_DIALOG instead
|
|
|
|
nsIContent *rootContent = mDocument->GetRootContent();
|
|
|
|
if (rootContent) {
|
|
|
|
nsCOMPtr<nsIDOMElement> rootElement(do_QueryInterface(rootContent));
|
|
|
|
if (rootElement) {
|
|
|
|
nsAutoString name;
|
|
|
|
rootElement->GetLocalName(name);
|
|
|
|
if (name.EqualsLiteral("dialog") || name.EqualsLiteral("wizard")) {
|
|
|
|
*aRole = nsIAccessibleRole::ROLE_DIALOG; // Always at the root
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return nsDocAccessibleWrap::GetRole(aRole);
|
|
|
|
}
|
|
|
|
|
|
|
|
#ifdef MOZ_XUL
|
|
|
|
PRUint32 nsRootAccessible::GetChromeFlags()
|
|
|
|
{
|
|
|
|
// Return the flag set for the top level window as defined
|
|
|
|
// by nsIWebBrowserChrome::CHROME_WINDOW_[FLAGNAME]
|
|
|
|
// Not simple: nsIXULWindow is not just a QI from nsIDOMWindow
|
2007-09-05 00:39:09 -07:00
|
|
|
nsCOMPtr<nsIDocShellTreeItem> treeItem =
|
|
|
|
nsAccUtils::GetDocShellTreeItemFor(mDOMNode);
|
2007-03-22 10:30:00 -07:00
|
|
|
NS_ENSURE_TRUE(treeItem, 0);
|
|
|
|
nsCOMPtr<nsIDocShellTreeOwner> treeOwner;
|
|
|
|
treeItem->GetTreeOwner(getter_AddRefs(treeOwner));
|
|
|
|
NS_ENSURE_TRUE(treeOwner, 0);
|
|
|
|
nsCOMPtr<nsIXULWindow> xulWin(do_GetInterface(treeOwner));
|
|
|
|
if (!xulWin) {
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
PRUint32 chromeFlags;
|
|
|
|
xulWin->GetChromeFlags(&chromeFlags);
|
|
|
|
return chromeFlags;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2007-04-02 08:56:24 -07:00
|
|
|
NS_IMETHODIMP
|
|
|
|
nsRootAccessible::GetState(PRUint32 *aState, PRUint32 *aExtraState)
|
2007-03-22 10:30:00 -07:00
|
|
|
{
|
2007-04-02 08:56:24 -07:00
|
|
|
nsresult rv = nsDocAccessibleWrap::GetState(aState, aExtraState);
|
|
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
2007-11-15 11:53:40 -08:00
|
|
|
if (!mDOMNode)
|
|
|
|
return NS_OK;
|
2007-03-22 10:30:00 -07:00
|
|
|
|
|
|
|
#ifdef MOZ_XUL
|
|
|
|
PRUint32 chromeFlags = GetChromeFlags();
|
|
|
|
if (chromeFlags & nsIWebBrowserChrome::CHROME_WINDOW_RESIZE) {
|
|
|
|
*aState |= nsIAccessibleStates::STATE_SIZEABLE;
|
|
|
|
}
|
|
|
|
if (chromeFlags & nsIWebBrowserChrome::CHROME_TITLEBAR) {
|
|
|
|
// If it has a titlebar it's movable
|
|
|
|
// XXX unless it's minimized or maximized, but not sure
|
|
|
|
// how to detect that
|
|
|
|
*aState |= nsIAccessibleStates::STATE_MOVEABLE;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2007-04-02 08:56:24 -07:00
|
|
|
if (!aExtraState)
|
|
|
|
return NS_OK;
|
2007-03-22 10:30:00 -07:00
|
|
|
|
|
|
|
nsCOMPtr<nsIDOMWindow> domWin;
|
|
|
|
GetWindow(getter_AddRefs(domWin));
|
|
|
|
nsCOMPtr<nsPIDOMWindow> privateDOMWindow(do_QueryInterface(domWin));
|
|
|
|
if (privateDOMWindow) {
|
|
|
|
nsIFocusController *focusController =
|
|
|
|
privateDOMWindow->GetRootFocusController();
|
2008-04-20 23:24:08 -07:00
|
|
|
if (focusController) {
|
|
|
|
PRBool isActive = PR_FALSE;
|
|
|
|
focusController->GetActive(&isActive);
|
|
|
|
if (isActive) {
|
|
|
|
*aExtraState |= nsIAccessibleStates::EXT_STATE_ACTIVE;
|
|
|
|
}
|
2007-03-22 10:30:00 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
#ifdef MOZ_XUL
|
|
|
|
if (GetChromeFlags() & nsIWebBrowserChrome::CHROME_MODAL) {
|
2007-04-02 08:56:24 -07:00
|
|
|
*aExtraState |= nsIAccessibleStates::EXT_STATE_MODAL;
|
2007-03-22 10:30:00 -07:00
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
nsRootAccessible::GetChromeEventHandler(nsIDOMEventTarget **aChromeTarget)
|
|
|
|
{
|
|
|
|
nsCOMPtr<nsIDOMWindow> domWin;
|
|
|
|
GetWindow(getter_AddRefs(domWin));
|
|
|
|
nsCOMPtr<nsPIDOMWindow> privateDOMWindow(do_QueryInterface(domWin));
|
|
|
|
nsCOMPtr<nsPIDOMEventTarget> chromeEventHandler;
|
|
|
|
if (privateDOMWindow) {
|
|
|
|
chromeEventHandler = privateDOMWindow->GetChromeEventHandler();
|
|
|
|
}
|
|
|
|
|
|
|
|
nsCOMPtr<nsIDOMEventTarget> target(do_QueryInterface(chromeEventHandler));
|
|
|
|
|
|
|
|
*aChromeTarget = target;
|
|
|
|
NS_IF_ADDREF(*aChromeTarget);
|
|
|
|
}
|
|
|
|
|
|
|
|
const char* const docEvents[] = {
|
2007-12-10 19:30:02 -08:00
|
|
|
#ifdef DEBUG
|
|
|
|
// Capture mouse over events and fire fake DRAGDROPSTART event to simplify
|
|
|
|
// debugging a11y objects with event viewers
|
|
|
|
"mouseover",
|
|
|
|
#endif
|
2007-03-22 10:30:00 -07:00
|
|
|
// capture DOM focus events
|
|
|
|
"focus",
|
|
|
|
// capture Form change events
|
|
|
|
"select",
|
|
|
|
// capture ValueChange events (fired whenever value changes, immediately after, whether focus moves or not)
|
|
|
|
"ValueChange",
|
|
|
|
// capture AlertActive events (fired whenever alert pops up)
|
|
|
|
"AlertActive",
|
|
|
|
// add ourself as a TreeViewChanged listener (custom event fired in nsTreeBodyFrame.cpp)
|
|
|
|
"TreeViewChanged",
|
2007-12-11 00:18:04 -08:00
|
|
|
"TreeRowCountChanged",
|
2008-02-08 04:55:57 -08:00
|
|
|
"TreeInvalidated",
|
2007-03-22 10:30:00 -07:00
|
|
|
// add ourself as a OpenStateChange listener (custom event fired in tree.xml)
|
|
|
|
"OpenStateChange",
|
|
|
|
// add ourself as a CheckboxStateChange listener (custom event fired in nsHTMLInputElement.cpp)
|
|
|
|
"CheckboxStateChange",
|
|
|
|
// add ourself as a RadioStateChange Listener ( custom event fired in in nsHTMLInputElement.cpp & radio.xml)
|
|
|
|
"RadioStateChange",
|
|
|
|
"popupshown",
|
|
|
|
"popuphiding",
|
|
|
|
"DOMMenuInactive",
|
|
|
|
"DOMMenuItemActive",
|
|
|
|
"DOMMenuBarActive",
|
|
|
|
"DOMMenuBarInactive",
|
|
|
|
"DOMContentLoaded"
|
|
|
|
};
|
|
|
|
|
|
|
|
nsresult nsRootAccessible::AddEventListeners()
|
|
|
|
{
|
|
|
|
// nsIDOMNSEventTarget interface allows to register event listeners to
|
|
|
|
// receive untrusted events (synthetic events generated by untrusted code).
|
|
|
|
// For example, XBL bindings implementations for elements that are hosted in
|
|
|
|
// non chrome document fire untrusted events.
|
|
|
|
nsCOMPtr<nsIDOMNSEventTarget> nstarget(do_QueryInterface(mDocument));
|
|
|
|
|
|
|
|
if (nstarget) {
|
|
|
|
for (const char* const* e = docEvents,
|
|
|
|
* const* e_end = docEvents + NS_ARRAY_LENGTH(docEvents);
|
|
|
|
e < e_end; ++e) {
|
|
|
|
nsresult rv = nstarget->AddEventListener(NS_ConvertASCIItoUTF16(*e),
|
|
|
|
this, PR_TRUE, PR_TRUE);
|
|
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
nsCOMPtr<nsIDOMEventTarget> target;
|
|
|
|
GetChromeEventHandler(getter_AddRefs(target));
|
|
|
|
if (target) {
|
|
|
|
target->AddEventListener(NS_LITERAL_STRING("pagehide"), this, PR_TRUE);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!mCaretAccessible) {
|
2007-06-14 10:12:50 -07:00
|
|
|
mCaretAccessible = new nsCaretAccessible(this);
|
2007-03-22 10:30:00 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
return nsDocAccessible::AddEventListeners();
|
|
|
|
}
|
|
|
|
|
|
|
|
nsresult nsRootAccessible::RemoveEventListeners()
|
|
|
|
{
|
|
|
|
nsCOMPtr<nsIDOMEventTarget> target(do_QueryInterface(mDocument));
|
|
|
|
if (target) {
|
|
|
|
for (const char* const* e = docEvents,
|
|
|
|
* const* e_end = docEvents + NS_ARRAY_LENGTH(docEvents);
|
|
|
|
e < e_end; ++e) {
|
|
|
|
nsresult rv = target->RemoveEventListener(NS_ConvertASCIItoUTF16(*e), this, PR_TRUE);
|
|
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
GetChromeEventHandler(getter_AddRefs(target));
|
|
|
|
if (target) {
|
|
|
|
target->RemoveEventListener(NS_LITERAL_STRING("pagehide"), this, PR_TRUE);
|
|
|
|
}
|
|
|
|
|
2007-11-27 10:08:50 -08:00
|
|
|
// Do this before removing clearing caret accessible, so that it can use
|
|
|
|
// shutdown the caret accessible's selection listener
|
|
|
|
nsDocAccessible::RemoveEventListeners();
|
|
|
|
|
2007-06-14 10:12:50 -07:00
|
|
|
if (mCaretAccessible) {
|
|
|
|
mCaretAccessible->Shutdown();
|
2007-03-22 10:30:00 -07:00
|
|
|
mCaretAccessible = nsnull;
|
|
|
|
}
|
|
|
|
|
2007-11-27 10:08:50 -08:00
|
|
|
return NS_OK;
|
2007-03-22 10:30:00 -07:00
|
|
|
}
|
|
|
|
|
2007-06-14 12:19:19 -07:00
|
|
|
nsCaretAccessible*
|
2007-06-14 10:12:50 -07:00
|
|
|
nsRootAccessible::GetCaretAccessible()
|
2007-03-22 10:30:00 -07:00
|
|
|
{
|
2007-06-14 12:19:19 -07:00
|
|
|
return mCaretAccessible;
|
2007-03-22 10:30:00 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
void nsRootAccessible::TryFireEarlyLoadEvent(nsIDOMNode *aDocNode)
|
|
|
|
{
|
|
|
|
// We can fire an early load event based on DOMContentLoaded unless we
|
|
|
|
// have subdocuments. For that we wait until WebProgressListener
|
|
|
|
// STATE_STOP handling in nsAccessibilityService.
|
|
|
|
|
|
|
|
// Note, we don't fire any page load finished events for chrome or for
|
|
|
|
// frame/iframe page loads during the initial complete page load -- that page
|
|
|
|
// load event for the entire content pane needs to stand alone.
|
|
|
|
|
|
|
|
// This also works for firing events for error pages
|
|
|
|
|
|
|
|
nsCOMPtr<nsIDocShellTreeItem> treeItem =
|
2007-09-05 00:39:09 -07:00
|
|
|
nsAccUtils::GetDocShellTreeItemFor(aDocNode);
|
2007-03-22 10:30:00 -07:00
|
|
|
NS_ASSERTION(treeItem, "No docshelltreeitem for aDocNode");
|
|
|
|
if (!treeItem) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
PRInt32 itemType;
|
|
|
|
treeItem->GetItemType(&itemType);
|
|
|
|
if (itemType != nsIDocShellTreeItem::typeContent) {
|
|
|
|
return;
|
|
|
|
}
|
2007-09-24 18:19:03 -07:00
|
|
|
|
2008-02-08 05:03:14 -08:00
|
|
|
// The doc accessible should already be created as a result of the
|
|
|
|
// OnStateChange() for the initiation of page loading
|
2007-03-22 10:30:00 -07:00
|
|
|
nsCOMPtr<nsIDocShellTreeNode> treeNode(do_QueryInterface(treeItem));
|
|
|
|
if (treeNode) {
|
|
|
|
PRInt32 subDocuments;
|
|
|
|
treeNode->GetChildCount(&subDocuments);
|
|
|
|
if (subDocuments) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
nsCOMPtr<nsIDocShellTreeItem> rootContentTreeItem;
|
|
|
|
treeItem->GetSameTypeRootTreeItem(getter_AddRefs(rootContentTreeItem));
|
|
|
|
NS_ASSERTION(rootContentTreeItem, "No root content tree item");
|
2008-02-26 00:51:10 -08:00
|
|
|
if (rootContentTreeItem == treeItem) {
|
|
|
|
// No frames or iframes, so we can fire the doc load finished event early
|
2008-03-17 01:13:10 -07:00
|
|
|
FireDelayedToolkitEvent(nsIAccessibleEvent::EVENT_INTERNAL_LOAD, aDocNode);
|
2007-03-22 10:30:00 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2007-04-09 06:40:25 -07:00
|
|
|
PRBool nsRootAccessible::FireAccessibleFocusEvent(nsIAccessible *aAccessible,
|
|
|
|
nsIDOMNode *aNode,
|
|
|
|
nsIDOMEvent *aFocusEvent,
|
2007-08-10 18:44:44 -07:00
|
|
|
PRBool aForceEvent,
|
|
|
|
PRBool aIsAsynch)
|
2007-03-22 10:30:00 -07:00
|
|
|
{
|
|
|
|
if (mCaretAccessible) {
|
|
|
|
nsCOMPtr<nsIDOMNSEvent> nsevent(do_QueryInterface(aFocusEvent));
|
|
|
|
if (nsevent) {
|
|
|
|
// Use the originally focused node where the selection lives.
|
|
|
|
// For example, use the anonymous HTML:input instead of the containing
|
|
|
|
// XUL:textbox. In this case, sometimes it is a later focus event
|
|
|
|
// which points to the actual anonymous child with focus, so to be safe
|
|
|
|
// we need to reset the selection listener every time.
|
|
|
|
// This happens because when some bindings handle focus, they retarget
|
|
|
|
// focus to the appropriate child inside of themselves, but DOM focus
|
|
|
|
// stays outside on that binding parent.
|
|
|
|
nsCOMPtr<nsIDOMEventTarget> domEventTarget;
|
|
|
|
nsevent->GetOriginalTarget(getter_AddRefs(domEventTarget));
|
|
|
|
nsCOMPtr<nsIDOMNode> realFocusedNode(do_QueryInterface(domEventTarget));
|
2007-09-18 15:44:41 -07:00
|
|
|
if (!realFocusedNode) {
|
|
|
|
// When FireCurrentFocusEvent() synthesizes a focus event,
|
|
|
|
// the orignal target does not exist, so use the passed-in node
|
|
|
|
// which is the relevant focused node
|
|
|
|
realFocusedNode = aNode;
|
|
|
|
}
|
2007-03-22 10:30:00 -07:00
|
|
|
if (realFocusedNode) {
|
2007-05-07 11:55:17 -07:00
|
|
|
mCaretAccessible->SetControlSelectionListener(realFocusedNode);
|
2007-03-22 10:30:00 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2007-12-11 18:10:26 -08:00
|
|
|
// Check for aria-activedescendant, which changes which element has focus
|
2007-03-22 10:30:00 -07:00
|
|
|
nsCOMPtr<nsIDOMNode> finalFocusNode = aNode;
|
|
|
|
nsCOMPtr<nsIAccessible> finalFocusAccessible = aAccessible;
|
2008-03-14 13:49:38 -07:00
|
|
|
nsCOMPtr<nsIContent> finalFocusContent = GetRoleContent(finalFocusNode);
|
2007-03-22 10:30:00 -07:00
|
|
|
if (finalFocusContent) {
|
|
|
|
nsAutoString id;
|
2007-12-11 18:10:26 -08:00
|
|
|
if (finalFocusContent->GetAttr(kNameSpaceID_None, nsAccessibilityAtoms::aria_activedescendant, id)) {
|
2007-03-22 10:30:00 -07:00
|
|
|
nsCOMPtr<nsIDOMDocument> domDoc;
|
|
|
|
aNode->GetOwnerDocument(getter_AddRefs(domDoc));
|
2008-03-14 13:49:38 -07:00
|
|
|
if (!domDoc) { // Maybe the passed-in node actually is a doc
|
|
|
|
domDoc = do_QueryInterface(aNode);
|
|
|
|
}
|
2007-03-22 10:30:00 -07:00
|
|
|
if (!domDoc) {
|
2007-04-09 06:40:25 -07:00
|
|
|
return PR_FALSE;
|
2007-03-22 10:30:00 -07:00
|
|
|
}
|
|
|
|
nsCOMPtr<nsIDOMElement> relatedEl;
|
|
|
|
domDoc->GetElementById(id, getter_AddRefs(relatedEl));
|
2007-04-27 08:17:07 -07:00
|
|
|
finalFocusNode = do_QueryInterface(relatedEl);
|
|
|
|
if (!finalFocusNode) {
|
2008-03-19 18:10:36 -07:00
|
|
|
// If aria-activedescendant is set to nonextistant ID, then treat as focus
|
|
|
|
// on the activedescendant container (which has real DOM focus)
|
|
|
|
finalFocusNode = aNode;
|
2007-03-22 10:30:00 -07:00
|
|
|
}
|
2008-03-05 19:43:50 -08:00
|
|
|
finalFocusAccessible = nsnull;
|
2007-03-22 10:30:00 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Fire focus only if it changes, but always fire focus events when aForceEvent == PR_TRUE
|
|
|
|
if (gLastFocusedNode == finalFocusNode && !aForceEvent) {
|
2007-04-09 06:40:25 -07:00
|
|
|
return PR_FALSE;
|
2007-03-22 10:30:00 -07:00
|
|
|
}
|
|
|
|
|
2008-03-05 19:43:50 -08:00
|
|
|
if (!finalFocusAccessible) {
|
|
|
|
GetAccService()->GetAccessibleFor(finalFocusNode, getter_AddRefs(finalFocusAccessible));
|
|
|
|
// For activedescendant, the ARIA spec does not require that the user agent
|
|
|
|
// checks whether finalFocusNode is actually a descendant of the element with
|
|
|
|
// the activedescendant attribute.
|
|
|
|
if (!finalFocusAccessible) {
|
|
|
|
return PR_FALSE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2007-09-18 14:36:41 -07:00
|
|
|
gLastFocusedAccessiblesState = State(finalFocusAccessible);
|
2007-04-09 06:40:25 -07:00
|
|
|
PRUint32 role = Role(finalFocusAccessible);
|
2007-03-22 10:30:00 -07:00
|
|
|
if (role == nsIAccessibleRole::ROLE_MENUITEM) {
|
2007-08-20 20:16:27 -07:00
|
|
|
if (!mCurrentARIAMenubar) { // Entering menus
|
2007-03-22 10:30:00 -07:00
|
|
|
PRUint32 naturalRole; // The natural role is the role that this type of element normally has
|
|
|
|
finalFocusAccessible->GetRole(&naturalRole);
|
|
|
|
if (role != naturalRole) { // Must be a DHTML menuitem
|
2007-11-09 10:44:18 -08:00
|
|
|
nsCOMPtr<nsIAccessible> menuBarAccessible =
|
2007-08-20 20:16:27 -07:00
|
|
|
nsAccUtils::GetAncestorWithRole(finalFocusAccessible, nsIAccessibleRole::ROLE_MENUBAR);
|
2007-11-09 10:44:18 -08:00
|
|
|
nsCOMPtr<nsIAccessNode> menuBarAccessNode = do_QueryInterface(menuBarAccessible);
|
|
|
|
if (menuBarAccessNode) {
|
|
|
|
menuBarAccessNode->GetDOMNode(getter_AddRefs(mCurrentARIAMenubar));
|
|
|
|
if (mCurrentARIAMenubar) {
|
|
|
|
nsAccUtils::FireAccEvent(nsIAccessibleEvent::EVENT_MENU_START, menuBarAccessible);
|
|
|
|
}
|
2007-08-20 20:16:27 -07:00
|
|
|
}
|
2007-03-22 10:30:00 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2007-08-20 20:16:27 -07:00
|
|
|
else if (mCurrentARIAMenubar) {
|
|
|
|
nsCOMPtr<nsIAccessibleEvent> menuEndEvent =
|
2008-03-17 01:13:10 -07:00
|
|
|
new nsAccEvent(nsIAccessibleEvent::EVENT_MENU_END, mCurrentARIAMenubar,
|
|
|
|
PR_FALSE, nsAccEvent::eAllowDupes);
|
2007-08-20 20:16:27 -07:00
|
|
|
if (menuEndEvent) {
|
2008-03-17 01:13:10 -07:00
|
|
|
FireDelayedAccessibleEvent(menuEndEvent);
|
2007-08-20 20:16:27 -07:00
|
|
|
}
|
|
|
|
mCurrentARIAMenubar = nsnull;
|
2007-03-22 10:30:00 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
NS_IF_RELEASE(gLastFocusedNode);
|
|
|
|
gLastFocusedNode = finalFocusNode;
|
|
|
|
NS_IF_ADDREF(gLastFocusedNode);
|
|
|
|
|
2008-02-08 18:28:01 -08:00
|
|
|
nsCOMPtr<nsIContent> focusContent = do_QueryInterface(gLastFocusedNode);
|
|
|
|
nsIFrame *focusFrame = nsnull;
|
|
|
|
if (focusContent) {
|
|
|
|
nsCOMPtr<nsIPresShell> shell = nsAccessNode::GetPresShellFor(gLastFocusedNode);
|
|
|
|
focusFrame = shell->GetRealPrimaryFrameFor(focusContent);
|
|
|
|
}
|
|
|
|
gLastFocusedFrameType = (focusFrame && focusFrame->GetStyleVisibility()->IsVisible()) ? focusFrame->GetType() : 0;
|
|
|
|
|
2007-06-17 22:47:33 -07:00
|
|
|
nsCOMPtr<nsIAccessibleDocument> docAccessible = do_QueryInterface(finalFocusAccessible);
|
2007-04-09 06:40:25 -07:00
|
|
|
if (docAccessible) {
|
|
|
|
// Doc is gaining focus, but actual focus may be on an element within document
|
|
|
|
nsCOMPtr<nsIDOMNode> realFocusedNode = GetCurrentFocus();
|
2007-04-10 11:41:40 -07:00
|
|
|
if (realFocusedNode != aNode || realFocusedNode == mDOMNode) {
|
2007-04-09 06:40:25 -07:00
|
|
|
// Suppress document focus, because real DOM focus will be fired next,
|
|
|
|
// and that's what we care about
|
2007-04-10 11:41:40 -07:00
|
|
|
// Make sure we never fire focus for the nsRootAccessible (mDOMNode)
|
2008-02-08 18:28:01 -08:00
|
|
|
|
|
|
|
return PR_FALSE;
|
2007-04-09 06:40:25 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2007-06-17 22:47:33 -07:00
|
|
|
FireDelayedToolkitEvent(nsIAccessibleEvent::EVENT_FOCUS,
|
2008-03-17 01:13:10 -07:00
|
|
|
finalFocusNode, nsAccEvent::eRemoveDupes,
|
|
|
|
aIsAsynch);
|
2007-04-09 06:40:25 -07:00
|
|
|
|
|
|
|
return PR_TRUE;
|
2007-03-22 10:30:00 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
void nsRootAccessible::FireCurrentFocusEvent()
|
|
|
|
{
|
|
|
|
nsCOMPtr<nsIDOMNode> focusedNode = GetCurrentFocus();
|
2007-04-12 07:47:55 -07:00
|
|
|
if (!focusedNode) {
|
|
|
|
return; // No current focus
|
|
|
|
}
|
2007-03-22 10:30:00 -07:00
|
|
|
|
|
|
|
// Simulate a focus event so that we can reuse code that fires focus for container children like treeitems
|
|
|
|
nsCOMPtr<nsIDOMDocumentEvent> docEvent = do_QueryInterface(mDocument);
|
|
|
|
if (docEvent) {
|
|
|
|
nsCOMPtr<nsIDOMEvent> event;
|
|
|
|
if (NS_SUCCEEDED(docEvent->CreateEvent(NS_LITERAL_STRING("Events"),
|
|
|
|
getter_AddRefs(event))) &&
|
|
|
|
NS_SUCCEEDED(event->InitEvent(NS_LITERAL_STRING("focus"), PR_TRUE, PR_TRUE))) {
|
|
|
|
// Get the target node we really want for the event.
|
|
|
|
nsIAccessibilityService* accService = GetAccService();
|
|
|
|
if (accService) {
|
|
|
|
nsCOMPtr<nsIDOMNode> targetNode;
|
|
|
|
accService->GetRelevantContentNodeFor(focusedNode,
|
|
|
|
getter_AddRefs(targetNode));
|
|
|
|
if (targetNode) {
|
|
|
|
HandleEventWithTarget(event, targetNode);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// --------------- nsIDOMEventListener Methods (3) ------------------------
|
|
|
|
|
|
|
|
NS_IMETHODIMP nsRootAccessible::HandleEvent(nsIDOMEvent* aEvent)
|
|
|
|
{
|
|
|
|
// Turn DOM events in accessibility events
|
|
|
|
// Get info about event and target
|
|
|
|
nsCOMPtr<nsIDOMNode> targetNode;
|
|
|
|
GetTargetNode(aEvent, getter_AddRefs(targetNode));
|
|
|
|
if (!targetNode)
|
|
|
|
return NS_ERROR_FAILURE;
|
|
|
|
|
|
|
|
return HandleEventWithTarget(aEvent, targetNode);
|
|
|
|
}
|
|
|
|
|
|
|
|
nsresult nsRootAccessible::HandleEventWithTarget(nsIDOMEvent* aEvent,
|
|
|
|
nsIDOMNode* aTargetNode)
|
|
|
|
{
|
|
|
|
nsAutoString eventType;
|
|
|
|
aEvent->GetType(eventType);
|
|
|
|
nsAutoString localName;
|
|
|
|
aTargetNode->GetLocalName(localName);
|
2008-01-23 15:49:10 -08:00
|
|
|
#ifdef MOZ_XUL
|
|
|
|
PRBool isTree = localName.EqualsLiteral("tree");
|
|
|
|
#endif
|
2007-03-22 10:30:00 -07:00
|
|
|
#ifdef DEBUG_A11Y
|
|
|
|
// Very useful for debugging, please leave this here.
|
2007-04-09 21:37:52 -07:00
|
|
|
if (eventType.EqualsLiteral("AlertActive")) {
|
2007-03-22 10:30:00 -07:00
|
|
|
printf("\ndebugging %s events for %s", NS_ConvertUTF16toUTF8(eventType).get(), NS_ConvertUTF16toUTF8(localName).get());
|
|
|
|
}
|
|
|
|
if (localName.LowerCaseEqualsLiteral("textbox")) {
|
|
|
|
printf("\ndebugging %s events for %s", NS_ConvertUTF16toUTF8(eventType).get(), NS_ConvertUTF16toUTF8(localName).get());
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
nsIAccessibilityService *accService = GetAccService();
|
|
|
|
NS_ENSURE_TRUE(accService, NS_ERROR_FAILURE);
|
|
|
|
|
2007-04-09 21:37:52 -07:00
|
|
|
if (eventType.EqualsLiteral("pagehide")) {
|
2007-03-22 10:30:00 -07:00
|
|
|
// pagehide event can be fired under several conditions, such as HTML
|
|
|
|
// document going away, closing a window/dialog, and wizard page changing.
|
|
|
|
// We only destroy the accessible object when it's a document accessible,
|
|
|
|
// so that we don't destroy something still in use, like wizard page.
|
|
|
|
// And we only get cached document accessible to destroy, so that we don't
|
|
|
|
// create it just to destroy it.
|
2007-11-30 11:47:16 -08:00
|
|
|
nsCOMPtr<nsIDocument> doc(do_QueryInterface(aTargetNode));
|
|
|
|
nsCOMPtr<nsIAccessibleDocument> accDoc = GetDocAccessibleFor(doc);
|
|
|
|
nsCOMPtr<nsPIAccessNode> privateAcc = do_QueryInterface(accDoc);
|
|
|
|
if (privateAcc) {
|
|
|
|
privateAcc->Shutdown();
|
2007-03-22 10:30:00 -07:00
|
|
|
}
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
2007-11-30 11:47:16 -08:00
|
|
|
nsCOMPtr<nsIPresShell> eventShell = GetPresShellFor(aTargetNode);
|
|
|
|
if (!eventShell) {
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
2007-04-09 21:37:52 -07:00
|
|
|
if (eventType.EqualsLiteral("DOMContentLoaded")) {
|
2007-03-22 10:30:00 -07:00
|
|
|
// Don't create the doc accessible until load scripts have a chance to set
|
|
|
|
// role attribute for <body> or <html> element, because the value of
|
|
|
|
// role attribute will be cached when the doc accessible is Init()'d
|
|
|
|
TryFireEarlyLoadEvent(aTargetNode);
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
2008-01-23 15:49:10 -08:00
|
|
|
#ifdef MOZ_XUL
|
2007-08-10 18:44:44 -07:00
|
|
|
if (eventType.EqualsLiteral("TreeViewChanged")) { // Always asynch, always from user input
|
2008-01-23 15:49:10 -08:00
|
|
|
if (!isTree)
|
2007-12-11 00:18:04 -08:00
|
|
|
return NS_OK;
|
|
|
|
|
2007-03-22 10:30:00 -07:00
|
|
|
nsCOMPtr<nsIContent> treeContent = do_QueryInterface(aTargetNode);
|
2007-08-10 18:44:44 -07:00
|
|
|
nsAccEvent::PrepareForEvent(aTargetNode, PR_TRUE);
|
2007-03-22 10:30:00 -07:00
|
|
|
return accService->InvalidateSubtreeFor(eventShell, treeContent,
|
2008-04-10 08:11:15 -07:00
|
|
|
nsIAccessibleEvent::EVENT_DOM_SIGNIFICANT_CHANGE);
|
2007-03-22 10:30:00 -07:00
|
|
|
}
|
2008-01-23 15:49:10 -08:00
|
|
|
#endif
|
|
|
|
|
|
|
|
if (eventType.EqualsLiteral("popuphiding")) {
|
|
|
|
// If accessible focus was on or inside popup that closes,
|
|
|
|
// then restore it to true current focus.
|
|
|
|
// This is the case when we've been getting DOMMenuItemActive events
|
|
|
|
// inside of a combo box that closes. The real focus is on the combo box.
|
|
|
|
// It's also the case when a popup gets focus in ATK -- when it closes
|
|
|
|
// we need to fire an event to restore focus to where it was
|
2008-04-01 13:01:55 -07:00
|
|
|
if (!gLastFocusedNode ||
|
|
|
|
!nsAccUtils::IsAncestorOf(aTargetNode, gLastFocusedNode)) {
|
|
|
|
return NS_OK; // And was not focused on an item inside the popup
|
2008-01-23 15:49:10 -08:00
|
|
|
}
|
|
|
|
// Focus was on or inside of a popup that's being hidden
|
|
|
|
FireCurrentFocusEvent();
|
|
|
|
}
|
2007-03-22 10:30:00 -07:00
|
|
|
|
|
|
|
nsCOMPtr<nsIAccessible> accessible;
|
|
|
|
accService->GetAccessibleInShell(aTargetNode, eventShell,
|
|
|
|
getter_AddRefs(accessible));
|
2007-04-17 05:39:10 -07:00
|
|
|
nsCOMPtr<nsPIAccessible> privAcc(do_QueryInterface(accessible));
|
|
|
|
if (!privAcc)
|
2007-03-22 10:30:00 -07:00
|
|
|
return NS_OK;
|
|
|
|
|
2008-01-23 15:49:10 -08:00
|
|
|
#ifdef MOZ_XUL
|
2008-02-08 04:55:57 -08:00
|
|
|
if (eventType.EqualsLiteral("TreeRowCountChanged"))
|
|
|
|
return HandleTreeRowCountChangedEvent(aEvent, accessible, localName);
|
|
|
|
|
|
|
|
if (eventType.EqualsLiteral("TreeInvalidated"))
|
|
|
|
return HandleTreeInvalidatedEvent(aEvent, accessible, localName);
|
2008-01-23 15:49:10 -08:00
|
|
|
#endif
|
2007-12-11 00:18:04 -08:00
|
|
|
|
2007-04-17 05:39:10 -07:00
|
|
|
if (eventType.EqualsLiteral("RadioStateChange")) {
|
|
|
|
PRUint32 state = State(accessible);
|
2007-05-16 01:21:12 -07:00
|
|
|
|
|
|
|
// radiogroup in prefWindow is exposed as a list,
|
|
|
|
// and panebutton is exposed as XULListitem in A11y.
|
|
|
|
// nsXULListitemAccessible::GetState uses STATE_SELECTED in this case,
|
|
|
|
// so we need to check nsIAccessibleStates::STATE_SELECTED also.
|
|
|
|
PRBool isEnabled = (state & (nsIAccessibleStates::STATE_CHECKED |
|
|
|
|
nsIAccessibleStates::STATE_SELECTED)) != 0;
|
2007-04-17 05:39:10 -07:00
|
|
|
|
|
|
|
nsCOMPtr<nsIAccessibleStateChangeEvent> accEvent =
|
|
|
|
new nsAccStateChangeEvent(accessible, nsIAccessibleStates::STATE_CHECKED,
|
|
|
|
PR_FALSE, isEnabled);
|
|
|
|
privAcc->FireAccessibleEvent(accEvent);
|
|
|
|
|
|
|
|
if (isEnabled)
|
|
|
|
FireAccessibleFocusEvent(accessible, aTargetNode, aEvent);
|
|
|
|
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (eventType.EqualsLiteral("CheckboxStateChange")) {
|
|
|
|
PRUint32 state = State(accessible);
|
|
|
|
|
2007-10-05 11:53:46 -07:00
|
|
|
PRBool isEnabled = !!(state & nsIAccessibleStates::STATE_CHECKED);
|
2007-04-17 05:39:10 -07:00
|
|
|
|
|
|
|
nsCOMPtr<nsIAccessibleStateChangeEvent> accEvent =
|
|
|
|
new nsAccStateChangeEvent(accessible,
|
|
|
|
nsIAccessibleStates::STATE_CHECKED,
|
|
|
|
PR_FALSE, isEnabled);
|
|
|
|
|
|
|
|
return privAcc->FireAccessibleEvent(accEvent);
|
|
|
|
}
|
|
|
|
|
2007-04-09 21:37:52 -07:00
|
|
|
nsCOMPtr<nsIAccessible> treeItemAccessible;
|
2007-03-22 10:30:00 -07:00
|
|
|
#ifdef MOZ_XUL
|
|
|
|
// If it's a tree element, need the currently selected item
|
2008-01-23 15:49:10 -08:00
|
|
|
if (isTree) {
|
2007-03-22 10:30:00 -07:00
|
|
|
nsCOMPtr<nsIDOMXULMultiSelectControlElement> multiSelect =
|
|
|
|
do_QueryInterface(aTargetNode);
|
|
|
|
if (multiSelect) {
|
|
|
|
PRInt32 treeIndex = -1;
|
|
|
|
multiSelect->GetCurrentIndex(&treeIndex);
|
|
|
|
if (treeIndex >= 0) {
|
|
|
|
nsCOMPtr<nsIAccessibleTreeCache> treeCache(do_QueryInterface(accessible));
|
|
|
|
if (!treeCache ||
|
|
|
|
NS_FAILED(treeCache->GetCachedTreeitemAccessible(
|
|
|
|
treeIndex,
|
|
|
|
nsnull,
|
|
|
|
getter_AddRefs(treeItemAccessible))) ||
|
|
|
|
!treeItemAccessible) {
|
|
|
|
return NS_ERROR_OUT_OF_MEMORY;
|
|
|
|
}
|
|
|
|
accessible = treeItemAccessible;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#ifdef MOZ_XUL
|
2007-04-17 05:39:10 -07:00
|
|
|
if (treeItemAccessible && eventType.EqualsLiteral("OpenStateChange")) {
|
|
|
|
PRUint32 state = State(accessible); // collapsed/expanded changed
|
|
|
|
PRBool isEnabled = (state & nsIAccessibleStates::STATE_EXPANDED) != 0;
|
|
|
|
|
|
|
|
nsCOMPtr<nsIAccessibleStateChangeEvent> accEvent =
|
|
|
|
new nsAccStateChangeEvent(accessible, nsIAccessibleStates::STATE_EXPANDED,
|
|
|
|
PR_FALSE, isEnabled);
|
|
|
|
return FireAccessibleEvent(accEvent);
|
2007-04-09 21:37:52 -07:00
|
|
|
}
|
2007-04-17 05:39:10 -07:00
|
|
|
|
|
|
|
if (treeItemAccessible && eventType.EqualsLiteral("select")) {
|
2007-04-09 21:37:52 -07:00
|
|
|
// If multiselect tree, we should fire selectionadd or selection removed
|
|
|
|
if (gLastFocusedNode == aTargetNode) {
|
|
|
|
nsCOMPtr<nsIDOMXULMultiSelectControlElement> multiSel =
|
|
|
|
do_QueryInterface(aTargetNode);
|
|
|
|
nsAutoString selType;
|
|
|
|
multiSel->GetSelType(selType);
|
|
|
|
if (selType.IsEmpty() || !selType.EqualsLiteral("single")) {
|
|
|
|
// XXX: We need to fire EVENT_SELECTION_ADD and EVENT_SELECTION_REMOVE
|
|
|
|
// for each tree item. Perhaps each tree item will need to cache its
|
|
|
|
// selection state and fire an event after a DOM "select" event when
|
|
|
|
// that state changes. nsXULTreeAccessible::UpdateTreeSelection();
|
2007-07-05 09:02:55 -07:00
|
|
|
return nsAccUtils::FireAccEvent(nsIAccessibleEvent::EVENT_SELECTION_WITHIN,
|
|
|
|
accessible);
|
2007-03-22 10:30:00 -07:00
|
|
|
}
|
2007-04-09 21:37:52 -07:00
|
|
|
|
2007-07-05 09:02:55 -07:00
|
|
|
return nsAccUtils::FireAccEvent(nsIAccessibleEvent::EVENT_SELECTION,
|
|
|
|
treeItemAccessible);
|
2007-03-22 10:30:00 -07:00
|
|
|
}
|
|
|
|
}
|
2007-04-09 21:37:52 -07:00
|
|
|
else
|
2007-03-22 10:30:00 -07:00
|
|
|
#endif
|
2007-04-09 21:37:52 -07:00
|
|
|
if (eventType.EqualsLiteral("focus")) {
|
2008-02-06 12:34:35 -08:00
|
|
|
if (aTargetNode == mDOMNode && mDOMNode != gLastFocusedNode) {
|
|
|
|
// Got focus event for the window, we will make sure that an accessible
|
|
|
|
// focus event for initial focus is fired. We do this on a short timer
|
|
|
|
// because the initial focus may not have been set yet.
|
|
|
|
if (!mFireFocusTimer) {
|
|
|
|
mFireFocusTimer = do_CreateInstance("@mozilla.org/timer;1");
|
|
|
|
}
|
|
|
|
if (mFireFocusTimer) {
|
|
|
|
mFireFocusTimer->InitWithFuncCallback(FireFocusCallback, this,
|
|
|
|
0, nsITimer::TYPE_ONE_SHOT);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2007-03-22 10:30:00 -07:00
|
|
|
// Keep a reference to the target node. We might want to change
|
|
|
|
// it to the individual radio button or selected item, and send
|
|
|
|
// the focus event to that.
|
|
|
|
nsCOMPtr<nsIDOMNode> focusedItem(aTargetNode);
|
2007-04-09 21:37:52 -07:00
|
|
|
|
|
|
|
if (!treeItemAccessible) {
|
|
|
|
nsCOMPtr<nsIDOMXULSelectControlElement> selectControl =
|
2007-03-22 10:30:00 -07:00
|
|
|
do_QueryInterface(aTargetNode);
|
2007-04-09 21:37:52 -07:00
|
|
|
if (selectControl) {
|
|
|
|
nsCOMPtr<nsIDOMXULMenuListElement> menuList =
|
|
|
|
do_QueryInterface(aTargetNode);
|
|
|
|
if (!menuList) {
|
|
|
|
// Don't do this for menu lists, the items only get focused
|
|
|
|
// when the list is open, based on DOMMenuitemActive events
|
|
|
|
nsCOMPtr<nsIDOMXULSelectControlItemElement> selectedItem;
|
|
|
|
selectControl->GetSelectedItem(getter_AddRefs(selectedItem));
|
|
|
|
if (selectedItem)
|
|
|
|
focusedItem = do_QueryInterface(selectedItem);
|
|
|
|
|
|
|
|
if (!focusedItem)
|
|
|
|
return NS_OK;
|
|
|
|
|
|
|
|
accService->GetAccessibleInShell(focusedItem, eventShell,
|
|
|
|
getter_AddRefs(accessible));
|
|
|
|
if (!accessible)
|
|
|
|
return NS_OK;
|
2007-03-22 10:30:00 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
FireAccessibleFocusEvent(accessible, focusedItem, aEvent);
|
|
|
|
}
|
|
|
|
else if (eventType.EqualsLiteral("AlertActive")) {
|
2007-07-05 09:02:55 -07:00
|
|
|
nsAccUtils::FireAccEvent(nsIAccessibleEvent::EVENT_ALERT, accessible);
|
2007-03-22 10:30:00 -07:00
|
|
|
}
|
2007-05-28 23:53:50 -07:00
|
|
|
else if (eventType.EqualsLiteral("popupshown")) {
|
2007-05-21 06:53:57 -07:00
|
|
|
// Don't fire menupopup events for combobox and autocomplete lists
|
|
|
|
PRUint32 role = Role(accessible);
|
|
|
|
PRInt32 event = 0;
|
|
|
|
if (role == nsIAccessibleRole::ROLE_MENUPOPUP) {
|
|
|
|
event = nsIAccessibleEvent::EVENT_MENUPOPUP_START;
|
|
|
|
}
|
|
|
|
else if (role == nsIAccessibleRole::ROLE_TOOLTIP) {
|
|
|
|
// There is a single <xul:tooltip> node which Mozilla moves around.
|
|
|
|
// The accessible for it stays the same no matter where it moves.
|
|
|
|
// AT's expect to get an EVENT_SHOW for the tooltip.
|
|
|
|
// In event callback the tooltip's accessible will be ready.
|
2007-08-10 18:44:44 -07:00
|
|
|
event = nsIAccessibleEvent::EVENT_ASYNCH_SHOW;
|
2007-05-21 06:53:57 -07:00
|
|
|
}
|
|
|
|
if (event) {
|
2007-07-05 09:02:55 -07:00
|
|
|
nsAccUtils::FireAccEvent(event, accessible);
|
2007-05-21 06:53:57 -07:00
|
|
|
}
|
|
|
|
}
|
2007-03-22 10:30:00 -07:00
|
|
|
else if (eventType.EqualsLiteral("DOMMenuInactive")) {
|
2007-05-21 06:53:57 -07:00
|
|
|
if (Role(accessible) == nsIAccessibleRole::ROLE_MENUPOPUP) {
|
2007-07-05 09:02:55 -07:00
|
|
|
nsAccUtils::FireAccEvent(nsIAccessibleEvent::EVENT_MENUPOPUP_END,
|
|
|
|
accessible);
|
2007-03-22 10:30:00 -07:00
|
|
|
}
|
|
|
|
}
|
2007-04-09 21:37:52 -07:00
|
|
|
else if (eventType.EqualsLiteral("DOMMenuItemActive")) {
|
2008-03-05 19:43:50 -08:00
|
|
|
PRBool fireFocus = PR_FALSE;
|
2007-04-09 21:37:52 -07:00
|
|
|
if (!treeItemAccessible) {
|
2008-01-23 15:49:10 -08:00
|
|
|
#ifdef MOZ_XUL
|
|
|
|
if (isTree) {
|
|
|
|
return NS_OK; // Tree with nothing selected
|
|
|
|
}
|
|
|
|
#endif
|
2007-07-04 08:49:38 -07:00
|
|
|
nsCOMPtr<nsPIAccessNode> menuAccessNode = do_QueryInterface(accessible);
|
|
|
|
NS_ENSURE_TRUE(menuAccessNode, NS_ERROR_FAILURE);
|
|
|
|
nsIFrame* menuFrame = menuAccessNode->GetFrame();
|
|
|
|
NS_ENSURE_TRUE(menuFrame, NS_ERROR_FAILURE);
|
|
|
|
nsIMenuFrame* imenuFrame;
|
|
|
|
CallQueryInterface(menuFrame, &imenuFrame);
|
2008-03-05 19:43:50 -08:00
|
|
|
if (imenuFrame)
|
|
|
|
fireFocus = PR_TRUE;
|
2007-07-23 00:46:48 -07:00
|
|
|
// QI failed for nsIMenuFrame means it's not on menu bar
|
|
|
|
if (imenuFrame && imenuFrame->IsOnMenuBar() &&
|
|
|
|
!imenuFrame->IsOnActiveMenuBar()) {
|
|
|
|
// It is a top level menuitem. Only fire a focus event when the menu bar
|
|
|
|
// is active.
|
|
|
|
return NS_OK;
|
2007-04-09 21:37:52 -07:00
|
|
|
} else {
|
2007-07-04 08:49:38 -07:00
|
|
|
nsCOMPtr<nsIAccessible> containerAccessible;
|
|
|
|
accessible->GetParent(getter_AddRefs(containerAccessible));
|
|
|
|
NS_ENSURE_TRUE(containerAccessible, NS_ERROR_FAILURE);
|
2007-04-09 21:37:52 -07:00
|
|
|
// It is not top level menuitem
|
|
|
|
// Only fire focus event if it is not inside collapsed popup
|
2007-10-25 22:30:23 -07:00
|
|
|
// and not a listitem of a combo box
|
2008-03-05 19:43:50 -08:00
|
|
|
if (State(containerAccessible) & nsIAccessibleStates::STATE_COLLAPSED) {
|
2007-10-25 22:30:23 -07:00
|
|
|
nsCOMPtr<nsIAccessible> containerParent;
|
|
|
|
containerAccessible->GetParent(getter_AddRefs(containerParent));
|
|
|
|
NS_ENSURE_TRUE(containerParent, NS_ERROR_FAILURE);
|
|
|
|
if (Role(containerParent) != nsIAccessibleRole::ROLE_COMBOBOX) {
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
}
|
2007-04-07 11:48:29 -07:00
|
|
|
}
|
2007-03-22 10:30:00 -07:00
|
|
|
}
|
2008-02-27 08:22:41 -08:00
|
|
|
if (!fireFocus) {
|
|
|
|
nsCOMPtr<nsIDOMNode> realFocusedNode = GetCurrentFocus();
|
|
|
|
nsCOMPtr<nsIContent> realFocusedContent = do_QueryInterface(realFocusedNode);
|
|
|
|
nsCOMPtr<nsIContent> targetContent = do_QueryInterface(aTargetNode);
|
|
|
|
nsIContent *containerContent = targetContent;
|
|
|
|
while (containerContent) {
|
|
|
|
nsCOMPtr<nsIDOMXULPopupElement> popup = do_QueryInterface(containerContent);
|
|
|
|
if (popup || containerContent == realFocusedContent) {
|
|
|
|
// If we're inside the focus or a popup we can fire focus events
|
|
|
|
// for the changed active item
|
2008-03-05 19:43:50 -08:00
|
|
|
fireFocus = PR_TRUE;
|
|
|
|
break;
|
2008-02-27 08:22:41 -08:00
|
|
|
}
|
|
|
|
containerContent = containerContent->GetParent();
|
|
|
|
}
|
|
|
|
}
|
2008-03-05 19:43:50 -08:00
|
|
|
if (fireFocus) {
|
|
|
|
nsAccEvent::PrepareForEvent(aTargetNode, PR_TRUE); // Always asynch, always from user input
|
|
|
|
FireAccessibleFocusEvent(accessible, aTargetNode, aEvent, PR_TRUE, PR_TRUE);
|
|
|
|
}
|
2007-03-22 10:30:00 -07:00
|
|
|
}
|
2007-08-10 18:44:44 -07:00
|
|
|
else if (eventType.EqualsLiteral("DOMMenuBarActive")) { // Always asynch, always from user input
|
|
|
|
nsAccEvent::PrepareForEvent(aTargetNode, PR_TRUE);
|
|
|
|
nsAccUtils::FireAccEvent(nsIAccessibleEvent::EVENT_MENU_START, accessible, PR_TRUE);
|
2007-03-22 10:30:00 -07:00
|
|
|
}
|
2007-08-10 18:44:44 -07:00
|
|
|
else if (eventType.EqualsLiteral("DOMMenuBarInactive")) { // Always asynch, always from user input
|
|
|
|
nsAccEvent::PrepareForEvent(aTargetNode, PR_TRUE);
|
|
|
|
nsAccUtils::FireAccEvent(nsIAccessibleEvent::EVENT_MENU_END, accessible, PR_TRUE);
|
2007-03-22 10:30:00 -07:00
|
|
|
FireCurrentFocusEvent();
|
|
|
|
}
|
|
|
|
else if (eventType.EqualsLiteral("ValueChange")) {
|
2008-03-19 18:58:11 -07:00
|
|
|
FireDelayedToolkitEvent(nsIAccessibleEvent::EVENT_VALUE_CHANGE, aTargetNode, nsAccEvent::eRemoveDupes);
|
2007-03-22 10:30:00 -07:00
|
|
|
}
|
2007-12-10 19:30:02 -08:00
|
|
|
#ifdef DEBUG
|
|
|
|
else if (eventType.EqualsLiteral("mouseover")) {
|
|
|
|
nsAccUtils::FireAccEvent(nsIAccessibleEvent::EVENT_DRAGDROP_START, accessible);
|
|
|
|
}
|
|
|
|
#endif
|
2007-03-22 10:30:00 -07:00
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
void nsRootAccessible::GetTargetNode(nsIDOMEvent *aEvent, nsIDOMNode **aTargetNode)
|
|
|
|
{
|
|
|
|
*aTargetNode = nsnull;
|
|
|
|
|
|
|
|
nsCOMPtr<nsIDOMNSEvent> nsevent(do_QueryInterface(aEvent));
|
|
|
|
|
|
|
|
if (!nsevent)
|
|
|
|
return;
|
|
|
|
|
|
|
|
nsCOMPtr<nsIDOMEventTarget> domEventTarget;
|
|
|
|
nsevent->GetOriginalTarget(getter_AddRefs(domEventTarget));
|
|
|
|
nsCOMPtr<nsIDOMNode> eventTarget(do_QueryInterface(domEventTarget));
|
|
|
|
if (!eventTarget)
|
|
|
|
return;
|
|
|
|
|
|
|
|
nsIAccessibilityService* accService = GetAccService();
|
|
|
|
if (accService) {
|
|
|
|
nsresult rv = accService->GetRelevantContentNodeFor(eventTarget,
|
|
|
|
aTargetNode);
|
|
|
|
if (NS_SUCCEEDED(rv) && *aTargetNode)
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
NS_ADDREF(*aTargetNode = eventTarget);
|
|
|
|
}
|
|
|
|
|
|
|
|
void nsRootAccessible::FireFocusCallback(nsITimer *aTimer, void *aClosure)
|
|
|
|
{
|
2007-07-08 00:08:04 -07:00
|
|
|
nsRootAccessible *rootAccessible = static_cast<nsRootAccessible*>(aClosure);
|
2007-03-22 10:30:00 -07:00
|
|
|
NS_ASSERTION(rootAccessible, "How did we get here without a root accessible?");
|
|
|
|
rootAccessible->FireCurrentFocusEvent();
|
|
|
|
}
|
|
|
|
|
2007-06-01 20:01:38 -07:00
|
|
|
NS_IMETHODIMP
|
|
|
|
nsRootAccessible::Init()
|
|
|
|
{
|
|
|
|
nsresult rv = nsDocAccessibleWrap::Init();
|
|
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
|
|
|
|
nsRefPtr<nsApplicationAccessibleWrap> root = GetApplicationAccessible();
|
|
|
|
NS_ENSURE_STATE(root);
|
|
|
|
|
|
|
|
root->AddRootAccessible(this);
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
2007-03-22 10:30:00 -07:00
|
|
|
NS_IMETHODIMP nsRootAccessible::Shutdown()
|
|
|
|
{
|
2007-10-10 09:51:45 -07:00
|
|
|
// Called manually or by nsAccessNode::LastRelease()
|
|
|
|
if (!mWeakShell) {
|
|
|
|
return NS_OK; // Already shutdown
|
|
|
|
}
|
|
|
|
|
2007-06-01 20:01:38 -07:00
|
|
|
nsRefPtr<nsApplicationAccessibleWrap> root = GetApplicationAccessible();
|
|
|
|
NS_ENSURE_STATE(root);
|
|
|
|
|
|
|
|
root->RemoveRootAccessible(this);
|
|
|
|
|
2007-08-20 20:16:27 -07:00
|
|
|
mCurrentARIAMenubar = nsnull;
|
|
|
|
|
2007-03-22 10:30:00 -07:00
|
|
|
if (mFireFocusTimer) {
|
|
|
|
mFireFocusTimer->Cancel();
|
|
|
|
mFireFocusTimer = nsnull;
|
|
|
|
}
|
|
|
|
|
|
|
|
return nsDocAccessibleWrap::Shutdown();
|
|
|
|
}
|
|
|
|
|
|
|
|
already_AddRefed<nsIDocShellTreeItem>
|
|
|
|
nsRootAccessible::GetContentDocShell(nsIDocShellTreeItem *aStart)
|
|
|
|
{
|
|
|
|
if (!aStart) {
|
|
|
|
return nsnull;
|
|
|
|
}
|
|
|
|
|
|
|
|
PRInt32 itemType;
|
|
|
|
aStart->GetItemType(&itemType);
|
|
|
|
if (itemType == nsIDocShellTreeItem::typeContent) {
|
|
|
|
nsCOMPtr<nsIAccessibleDocument> accDoc =
|
|
|
|
GetDocAccessibleFor(aStart, PR_TRUE);
|
|
|
|
nsCOMPtr<nsIAccessible> accessible = do_QueryInterface(accDoc);
|
|
|
|
// If ancestor chain of accessibles is not completely visible,
|
|
|
|
// don't use this one. This happens for example if it's inside
|
|
|
|
// a background tab (tabbed browsing)
|
|
|
|
while (accessible) {
|
|
|
|
if (State(accessible) & nsIAccessibleStates::STATE_INVISIBLE) {
|
|
|
|
return nsnull;
|
|
|
|
}
|
|
|
|
nsCOMPtr<nsIAccessible> ancestor;
|
|
|
|
accessible->GetParent(getter_AddRefs(ancestor));
|
2007-08-29 18:15:16 -07:00
|
|
|
if (ancestor == this) {
|
|
|
|
break; // Don't check past original root accessible we started with
|
|
|
|
}
|
2007-03-22 10:30:00 -07:00
|
|
|
accessible.swap(ancestor);
|
|
|
|
}
|
|
|
|
|
|
|
|
NS_ADDREF(aStart);
|
|
|
|
return aStart;
|
|
|
|
}
|
|
|
|
nsCOMPtr<nsIDocShellTreeNode> treeNode(do_QueryInterface(aStart));
|
|
|
|
if (treeNode) {
|
|
|
|
PRInt32 subDocuments;
|
|
|
|
treeNode->GetChildCount(&subDocuments);
|
|
|
|
for (PRInt32 count = 0; count < subDocuments; count ++) {
|
|
|
|
nsCOMPtr<nsIDocShellTreeItem> treeItemChild, contentTreeItem;
|
|
|
|
treeNode->GetChildAt(count, getter_AddRefs(treeItemChild));
|
|
|
|
NS_ENSURE_TRUE(treeItemChild, nsnull);
|
|
|
|
contentTreeItem = GetContentDocShell(treeItemChild);
|
|
|
|
if (contentTreeItem) {
|
|
|
|
NS_ADDREF(aStart = contentTreeItem);
|
|
|
|
return aStart;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return nsnull;
|
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP nsRootAccessible::GetAccessibleRelated(PRUint32 aRelationType,
|
|
|
|
nsIAccessible **aRelated)
|
|
|
|
{
|
|
|
|
*aRelated = nsnull;
|
|
|
|
|
2007-05-19 19:41:33 -07:00
|
|
|
if (!mDOMNode || aRelationType != nsIAccessibleRelation::RELATION_EMBEDS) {
|
2007-03-22 10:30:00 -07:00
|
|
|
return nsDocAccessibleWrap::GetAccessibleRelated(aRelationType, aRelated);
|
|
|
|
}
|
|
|
|
|
2007-09-05 00:39:09 -07:00
|
|
|
nsCOMPtr<nsIDocShellTreeItem> treeItem =
|
|
|
|
nsAccUtils::GetDocShellTreeItemFor(mDOMNode);
|
2007-03-22 10:30:00 -07:00
|
|
|
nsCOMPtr<nsIDocShellTreeItem> contentTreeItem = GetContentDocShell(treeItem);
|
|
|
|
// there may be no content area, so we need a null check
|
|
|
|
if (contentTreeItem) {
|
|
|
|
nsCOMPtr<nsIAccessibleDocument> accDoc =
|
|
|
|
GetDocAccessibleFor(contentTreeItem, PR_TRUE);
|
|
|
|
NS_ASSERTION(accDoc, "No EMBEDS document");
|
|
|
|
if (accDoc) {
|
|
|
|
accDoc->QueryInterface(NS_GET_IID(nsIAccessible), (void**)aRelated);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP nsRootAccessible::FireDocLoadEvents(PRUint32 aEventType)
|
|
|
|
{
|
|
|
|
if (!mDocument || !mWeakShell) {
|
|
|
|
return NS_OK; // Document has been shut down
|
|
|
|
}
|
|
|
|
|
|
|
|
nsCOMPtr<nsIDocShellTreeItem> docShellTreeItem =
|
2007-09-05 00:39:09 -07:00
|
|
|
nsAccUtils::GetDocShellTreeItemFor(mDOMNode);
|
2007-03-22 10:30:00 -07:00
|
|
|
NS_ASSERTION(docShellTreeItem, "No doc shell tree item for document");
|
|
|
|
NS_ENSURE_TRUE(docShellTreeItem, NS_ERROR_FAILURE);
|
|
|
|
PRInt32 contentType;
|
|
|
|
docShellTreeItem->GetItemType(&contentType);
|
|
|
|
if (contentType == nsIDocShellTreeItem::typeContent) {
|
|
|
|
return nsDocAccessibleWrap::FireDocLoadEvents(aEventType); // Content might need to fire event
|
|
|
|
}
|
|
|
|
|
|
|
|
// Root chrome: don't fire event
|
|
|
|
mIsContentLoaded = (aEventType == nsIAccessibleEvent::EVENT_DOCUMENT_LOAD_COMPLETE ||
|
|
|
|
aEventType == nsIAccessibleEvent::EVENT_DOCUMENT_LOAD_STOPPED);
|
|
|
|
|
|
|
|
return NS_OK;
|
|
|
|
}
|
2008-02-08 04:55:57 -08:00
|
|
|
|
|
|
|
nsresult
|
|
|
|
nsRootAccessible::HandleTreeRowCountChangedEvent(nsIDOMEvent *aEvent,
|
|
|
|
nsIAccessible *aAccessible,
|
|
|
|
const nsAString& aTargetName)
|
|
|
|
{
|
|
|
|
if (!aTargetName.EqualsLiteral("tree"))
|
|
|
|
return NS_OK;
|
|
|
|
|
|
|
|
nsCOMPtr<nsIDOMDataContainerEvent> dataEvent(do_QueryInterface(aEvent));
|
|
|
|
if (!dataEvent)
|
|
|
|
return NS_OK;
|
|
|
|
|
|
|
|
nsCOMPtr<nsIVariant> indexVariant;
|
|
|
|
dataEvent->GetData(NS_LITERAL_STRING("index"),
|
|
|
|
getter_AddRefs(indexVariant));
|
|
|
|
if (!indexVariant)
|
|
|
|
return NS_OK;
|
|
|
|
|
|
|
|
nsCOMPtr<nsIVariant> countVariant;
|
|
|
|
dataEvent->GetData(NS_LITERAL_STRING("count"),
|
|
|
|
getter_AddRefs(countVariant));
|
|
|
|
if (!countVariant)
|
|
|
|
return NS_OK;
|
|
|
|
|
|
|
|
PRInt32 index, count;
|
|
|
|
indexVariant->GetAsInt32(&index);
|
|
|
|
countVariant->GetAsInt32(&count);
|
|
|
|
|
|
|
|
nsCOMPtr<nsIAccessibleTreeCache> treeAccCache(do_QueryInterface(aAccessible));
|
|
|
|
NS_ENSURE_STATE(treeAccCache);
|
|
|
|
|
|
|
|
return treeAccCache->InvalidateCache(index, count);
|
|
|
|
}
|
|
|
|
|
|
|
|
nsresult
|
|
|
|
nsRootAccessible::HandleTreeInvalidatedEvent(nsIDOMEvent *aEvent,
|
|
|
|
nsIAccessible *aAccessible,
|
|
|
|
const nsAString& aTargetName)
|
|
|
|
{
|
|
|
|
if (!aTargetName.EqualsLiteral("tree"))
|
|
|
|
return NS_OK;
|
|
|
|
|
|
|
|
nsCOMPtr<nsIDOMDataContainerEvent> dataEvent(do_QueryInterface(aEvent));
|
|
|
|
if (!dataEvent)
|
|
|
|
return NS_OK;
|
|
|
|
|
|
|
|
PRInt32 startRow = 0, endRow = -1, startCol = 0, endCol = -1;
|
|
|
|
|
|
|
|
nsCOMPtr<nsIVariant> startRowVariant;
|
|
|
|
dataEvent->GetData(NS_LITERAL_STRING("startrow"),
|
|
|
|
getter_AddRefs(startRowVariant));
|
|
|
|
if (startRowVariant)
|
|
|
|
startRowVariant->GetAsInt32(&startRow);
|
|
|
|
|
|
|
|
nsCOMPtr<nsIVariant> endRowVariant;
|
|
|
|
dataEvent->GetData(NS_LITERAL_STRING("endrow"),
|
|
|
|
getter_AddRefs(endRowVariant));
|
|
|
|
if (endRowVariant)
|
|
|
|
endRowVariant->GetAsInt32(&endRow);
|
|
|
|
|
|
|
|
nsCOMPtr<nsIVariant> startColVariant;
|
|
|
|
dataEvent->GetData(NS_LITERAL_STRING("startcolumn"),
|
|
|
|
getter_AddRefs(startColVariant));
|
|
|
|
if (startColVariant)
|
|
|
|
startColVariant->GetAsInt32(&startCol);
|
|
|
|
|
|
|
|
nsCOMPtr<nsIVariant> endColVariant;
|
|
|
|
dataEvent->GetData(NS_LITERAL_STRING("endcolumn"),
|
|
|
|
getter_AddRefs(endColVariant));
|
|
|
|
if (endColVariant)
|
|
|
|
endColVariant->GetAsInt32(&endCol);
|
|
|
|
|
|
|
|
nsCOMPtr<nsIAccessibleTreeCache> treeAcc(do_QueryInterface(aAccessible));
|
|
|
|
NS_ENSURE_STATE(treeAcc);
|
|
|
|
|
|
|
|
return treeAcc->TreeViewInvalidated(startRow, endRow, startCol, endCol);
|
|
|
|
}
|
|
|
|
|