Bug 460926 A11y hierachy is broken on Ubuntu 8.10 (GNOME 2.24), r=Evan.Yan sr=roc
[wine-gecko.git] / accessible / src / base / nsBaseWidgetAccessible.cpp
blob015c6c1389bbfc086e260214e4d794ac7e0fa554
1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* ***** BEGIN LICENSE BLOCK *****
3 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
5 * The contents of this file are subject to the Mozilla Public License Version
6 * 1.1 (the "License"); you may not use this file except in compliance with
7 * the License. You may obtain a copy of the License at
8 * http://www.mozilla.org/MPL/
10 * Software distributed under the License is distributed on an "AS IS" basis,
11 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
12 * for the specific language governing rights and limitations under the
13 * License.
15 * The Original Code is mozilla.org code.
17 * The Initial Developer of the Original Code is
18 * Netscape Communications Corporation.
19 * Portions created by the Initial Developer are Copyright (C) 1998
20 * the Initial Developer. All Rights Reserved.
22 * Contributor(s):
23 * John Gaunt (jgaunt@netscape.com)
24 * Alexander Surkov <surkov.alexander@gmail.com>
26 * Alternatively, the contents of this file may be used under the terms of
27 * either of the GNU General Public License Version 2 or later (the "GPL"),
28 * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
29 * in which case the provisions of the GPL or the LGPL are applicable instead
30 * of those above. If you wish to allow use of your version of this file only
31 * under the terms of either the GPL or the LGPL, and not to allow others to
32 * use your version of this file under the terms of the MPL, indicate your
33 * decision by deleting the provisions above and replace them with the notice
34 * and other provisions required by the GPL or the LGPL. If you do not delete
35 * the provisions above, a recipient may use your version of this file under
36 * the terms of any one of the MPL, the GPL or the LGPL.
38 * ***** END LICENSE BLOCK ***** */
40 #include "nsBaseWidgetAccessible.h"
41 #include "nsAccessibilityAtoms.h"
42 #include "nsIAccessibilityService.h"
43 #include "nsIAccessibleDocument.h"
44 #include "nsAccessibleWrap.h"
45 #include "nsCoreUtils.h"
46 #include "nsIDOMNSHTMLElement.h"
47 #include "nsGUIEvent.h"
48 #include "nsHyperTextAccessibleWrap.h"
49 #include "nsILink.h"
50 #include "nsIFrame.h"
51 #include "nsINameSpaceManager.h"
52 #include "nsPresContext.h"
53 #include "nsIPresShell.h"
54 #include "nsIServiceManager.h"
55 #include "nsIURI.h"
57 //-------------
58 // nsLeafAccessible
59 //-------------
61 nsLeafAccessible::nsLeafAccessible(nsIDOMNode* aNode, nsIWeakReference* aShell):
62 nsAccessibleWrap(aNode, aShell)
66 NS_IMPL_ISUPPORTS_INHERITED0(nsLeafAccessible, nsAccessible)
68 /* nsIAccessible getFirstChild (); */
69 NS_IMETHODIMP nsLeafAccessible::GetFirstChild(nsIAccessible **_retval)
71 *_retval = nsnull;
72 return NS_OK;
75 /* nsIAccessible getLastChild (); */
76 NS_IMETHODIMP nsLeafAccessible::GetLastChild(nsIAccessible **_retval)
78 *_retval = nsnull;
79 return NS_OK;
82 /* long getAccChildCount (); */
83 NS_IMETHODIMP nsLeafAccessible::GetChildCount(PRInt32 *_retval)
85 *_retval = 0;
86 return NS_OK;
89 /* readonly attribute boolean allowsAnonChildAccessibles; */
90 NS_IMETHODIMP
91 nsLeafAccessible::GetAllowsAnonChildAccessibles(PRBool *aAllowsAnonChildren)
93 *aAllowsAnonChildren = PR_FALSE;
94 return NS_OK;
97 ////////////////////////////////////////////////////////////////////////////////
98 // nsLinkableAccessible
100 nsLinkableAccessible::
101 nsLinkableAccessible(nsIDOMNode* aNode, nsIWeakReference* aShell) :
102 nsHyperTextAccessibleWrap(aNode, aShell),
103 mActionContent(nsnull),
104 mIsLink(PR_FALSE),
105 mIsOnclick(PR_FALSE)
109 NS_IMPL_ISUPPORTS_INHERITED0(nsLinkableAccessible, nsHyperTextAccessibleWrap)
111 ////////////////////////////////////////////////////////////////////////////////
112 // nsLinkableAccessible. nsIAccessible
114 NS_IMETHODIMP
115 nsLinkableAccessible::TakeFocus()
117 nsCOMPtr<nsIAccessible> actionAcc = GetActionAccessible();
118 if (actionAcc)
119 return actionAcc->TakeFocus();
121 return nsHyperTextAccessibleWrap::TakeFocus();
124 nsresult
125 nsLinkableAccessible::GetStateInternal(PRUint32 *aState, PRUint32 *aExtraState)
127 nsresult rv = nsHyperTextAccessibleWrap::GetStateInternal(aState,
128 aExtraState);
129 NS_ENSURE_A11Y_SUCCESS(rv, rv);
131 if (mIsLink) {
132 *aState |= nsIAccessibleStates::STATE_LINKED;
133 nsCOMPtr<nsIAccessible> actionAcc = GetActionAccessible();
134 if (nsAccUtils::State(actionAcc) & nsIAccessibleStates::STATE_TRAVERSED)
135 *aState |= nsIAccessibleStates::STATE_TRAVERSED;
138 return NS_OK;
141 NS_IMETHODIMP
142 nsLinkableAccessible::GetValue(nsAString& aValue)
144 aValue.Truncate();
146 nsHyperTextAccessible::GetValue(aValue);
147 if (!aValue.IsEmpty())
148 return NS_OK;
150 if (mIsLink) {
151 nsCOMPtr<nsIAccessible> actionAcc = GetActionAccessible();
152 if (actionAcc)
153 return actionAcc->GetValue(aValue);
156 return NS_ERROR_NOT_IMPLEMENTED;
160 NS_IMETHODIMP
161 nsLinkableAccessible::GetNumActions(PRUint8 *aNumActions)
163 NS_ENSURE_ARG_POINTER(aNumActions);
165 *aNumActions = mActionContent ? 1 : 0;
166 return NS_OK;
169 NS_IMETHODIMP
170 nsLinkableAccessible::GetActionName(PRUint8 aIndex, nsAString& aName)
172 aName.Truncate();
174 // Action 0 (default action): Jump to link
175 if (aIndex == eAction_Jump) {
176 if (mIsLink) {
177 aName.AssignLiteral("jump");
178 return NS_OK;
180 else if (mIsOnclick) {
181 aName.AssignLiteral("click");
182 return NS_OK;
184 return NS_ERROR_NOT_IMPLEMENTED;
186 return NS_ERROR_INVALID_ARG;
189 NS_IMETHODIMP
190 nsLinkableAccessible::DoAction(PRUint8 aIndex)
192 if (aIndex != eAction_Jump)
193 return NS_ERROR_INVALID_ARG;
195 nsCOMPtr<nsIAccessible> actionAcc = GetActionAccessible();
196 if (actionAcc)
197 return actionAcc->DoAction(aIndex);
199 return nsHyperTextAccessibleWrap::DoAction(aIndex);
202 NS_IMETHODIMP
203 nsLinkableAccessible::GetKeyboardShortcut(nsAString& aKeyboardShortcut)
205 aKeyboardShortcut.Truncate();
207 nsCOMPtr<nsIAccessible> actionAcc = GetActionAccessible();
208 if (actionAcc)
209 return actionAcc->GetKeyboardShortcut(aKeyboardShortcut);
211 return nsAccessible::GetKeyboardShortcut(aKeyboardShortcut);
214 ////////////////////////////////////////////////////////////////////////////////
215 // nsLinkableAccessible. nsIAccessibleHyperLink
217 NS_IMETHODIMP
218 nsLinkableAccessible::GetURI(PRInt32 aIndex, nsIURI **aURI)
220 if (mIsLink) {
221 nsCOMPtr<nsIAccessible> actionAcc = GetActionAccessible();
222 if (actionAcc) {
223 nsCOMPtr<nsIAccessibleHyperLink> hyperLinkAcc =
224 do_QueryInterface(actionAcc);
225 NS_ASSERTION(hyperLinkAcc,
226 "nsIAccessibleHyperLink isn't implemented.");
228 if (hyperLinkAcc)
229 return hyperLinkAcc->GetURI(aIndex, aURI);
233 return NS_ERROR_INVALID_ARG;
236 ////////////////////////////////////////////////////////////////////////////////
237 // nsLinkableAccessible. nsAccessNode
239 nsresult
240 nsLinkableAccessible::Init()
242 CacheActionContent();
243 return nsHyperTextAccessibleWrap::Init();
246 nsresult
247 nsLinkableAccessible::Shutdown()
249 mActionContent = nsnull;
250 return nsHyperTextAccessibleWrap::Shutdown();
253 ////////////////////////////////////////////////////////////////////////////////
254 // nsLinkableAccessible
256 void
257 nsLinkableAccessible::CacheActionContent()
259 nsCOMPtr<nsIContent> walkUpContent(do_QueryInterface(mDOMNode));
260 PRBool isOnclick = nsCoreUtils::HasListener(walkUpContent,
261 NS_LITERAL_STRING("click"));
263 if (isOnclick) {
264 mActionContent = walkUpContent;
265 mIsOnclick = PR_TRUE;
266 return;
269 while ((walkUpContent = walkUpContent->GetParent())) {
270 isOnclick = nsCoreUtils::HasListener(walkUpContent,
271 NS_LITERAL_STRING("click"));
273 nsCOMPtr<nsIDOMNode> walkUpNode(do_QueryInterface(walkUpContent));
275 nsCOMPtr<nsIAccessible> walkUpAcc;
276 GetAccService()->GetAccessibleInWeakShell(walkUpNode, mWeakShell,
277 getter_AddRefs(walkUpAcc));
279 if (nsAccUtils::Role(walkUpAcc) == nsIAccessibleRole::ROLE_LINK &&
280 nsAccUtils::State(walkUpAcc) & nsIAccessibleStates::STATE_LINKED) {
281 mIsLink = PR_TRUE;
282 mActionContent = walkUpContent;
283 return;
286 if (isOnclick) {
287 mActionContent = walkUpContent;
288 mIsOnclick = PR_TRUE;
289 return;
294 already_AddRefed<nsIAccessible>
295 nsLinkableAccessible::GetActionAccessible()
297 // Return accessible for the action content if it's different from node of
298 // this accessible. If the action accessible is not null then it is used to
299 // redirect methods calls otherwise we use method implementation from the
300 // base class.
301 nsCOMPtr<nsIDOMNode> actionNode(do_QueryInterface(mActionContent));
302 if (!actionNode || mDOMNode == actionNode)
303 return nsnull;
305 nsIAccessible *accessible = nsnull;
306 GetAccService()->GetAccessibleInWeakShell(actionNode, mWeakShell,
307 &accessible);
308 return accessible;
311 //---------------------
312 // nsEnumRoleAccessible
313 //---------------------
315 nsEnumRoleAccessible::nsEnumRoleAccessible(nsIDOMNode* aNode, nsIWeakReference* aShell, PRUint32 aRole) :
316 nsAccessibleWrap(aNode, aShell),
317 mRole(aRole)
321 NS_IMPL_ISUPPORTS_INHERITED0(nsEnumRoleAccessible, nsAccessible)