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
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.
23 * Aaron Leventhal (aaronl@netscape.com)
24 * Kyle Yuan (kyle.yuan@sun.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 "nsHTMLTextAccessible.h"
41 #include "nsAccessibleTreeWalker.h"
42 #include "nsIAccessibleDocument.h"
43 #include "nsIAccessibleEvent.h"
45 #include "nsPresContext.h"
46 #include "nsIPresShell.h"
47 #include "nsISelection.h"
48 #include "nsISelectionController.h"
49 #include "nsComponentManagerUtils.h"
51 nsHTMLTextAccessible::nsHTMLTextAccessible(nsIDOMNode
* aDomNode
, nsIWeakReference
* aShell
):
52 nsTextAccessibleWrap(aDomNode
, aShell
)
57 nsHTMLTextAccessible::GetName(nsAString
& aName
)
59 // Text node, ARIA can't be used.
61 return AppendTextTo(aName
, 0, PR_UINT32_MAX
);
64 NS_IMETHODIMP
nsHTMLTextAccessible::GetRole(PRUint32
*aRole
)
66 nsIFrame
*frame
= GetFrame();
67 // Don't return on null frame -- we still return a role
68 // after accessible is shutdown/DEFUNCT
69 if (frame
&& frame
->IsGeneratedContentFrame()) {
70 *aRole
= nsIAccessibleRole::ROLE_STATICTEXT
;
74 return nsTextAccessible::GetRole(aRole
);
78 nsHTMLTextAccessible::GetStateInternal(PRUint32
*aState
, PRUint32
*aExtraState
)
80 nsresult rv
= nsTextAccessible::GetStateInternal(aState
, aExtraState
);
81 NS_ENSURE_A11Y_SUCCESS(rv
, rv
);
83 nsCOMPtr
<nsIAccessible
> docAccessible
=
84 do_QueryInterface(nsCOMPtr
<nsIAccessibleDocument
>(GetDocAccessible()));
86 PRUint32 state
, extState
;
87 docAccessible
->GetState(&state
, &extState
);
88 if (0 == (extState
& nsIAccessibleStates::EXT_STATE_EDITABLE
)) {
89 *aState
|= nsIAccessibleStates::STATE_READONLY
; // Links not focusable in editor
97 nsHTMLTextAccessible::GetAttributesInternal(nsIPersistentProperties
*aAttributes
)
100 return NS_ERROR_FAILURE
; // Node already shut down
105 if (role
== nsIAccessibleRole::ROLE_STATICTEXT
) {
106 nsAutoString oldValueUnused
;
107 aAttributes
->SetStringProperty(NS_LITERAL_CSTRING("auto-generated"),
108 NS_LITERAL_STRING("true"), oldValueUnused
);
114 nsHTMLHRAccessible::nsHTMLHRAccessible(nsIDOMNode
* aDomNode
, nsIWeakReference
* aShell
):
115 nsLeafAccessible(aDomNode
, aShell
)
119 NS_IMETHODIMP
nsHTMLHRAccessible::GetRole(PRUint32
*aRole
)
121 *aRole
= nsIAccessibleRole::ROLE_SEPARATOR
;
125 nsHTMLBRAccessible::nsHTMLBRAccessible(nsIDOMNode
* aDomNode
, nsIWeakReference
* aShell
):
126 nsLeafAccessible(aDomNode
, aShell
)
130 NS_IMETHODIMP
nsHTMLBRAccessible::GetRole(PRUint32
*aRole
)
132 *aRole
= nsIAccessibleRole::ROLE_WHITESPACE
;
137 nsHTMLBRAccessible::GetStateInternal(PRUint32
*aState
, PRUint32
*aExtraState
)
143 *aExtraState
= nsIAccessibleStates::EXT_STATE_DEFUNCT
;
145 return NS_OK_DEFUNCT_OBJECT
;
148 *aState
= nsIAccessibleStates::STATE_READONLY
;
156 nsHTMLBRAccessible::GetNameInternal(nsAString
& aName
)
158 aName
= static_cast<PRUnichar
>('\n'); // Newline char
162 // A label is an element (not a leaf) and thus can support advanced interfaces.
163 // We need to skip over nsTextAccessible QI which prevents that
164 NS_IMPL_ISUPPORTS_INHERITED0(nsHTMLLabelAccessible
, nsLinkableAccessible
)
166 nsHTMLLabelAccessible::nsHTMLLabelAccessible(nsIDOMNode
* aDomNode
, nsIWeakReference
* aShell
):
167 nsTextAccessible(aDomNode
, aShell
)
172 nsHTMLLabelAccessible::GetNameInternal(nsAString
& aReturn
)
174 nsresult rv
= NS_ERROR_FAILURE
;
175 nsCOMPtr
<nsIContent
> content(do_QueryInterface(mDOMNode
));
179 rv
= AppendFlatStringFromSubtree(content
, &name
);
181 if (NS_SUCCEEDED(rv
)) {
182 // Temp var needed until CompressWhitespace built for nsAString
183 name
.CompressWhitespace();
190 NS_IMETHODIMP
nsHTMLLabelAccessible::GetRole(PRUint32
*aRole
)
192 *aRole
= nsIAccessibleRole::ROLE_LABEL
;
197 nsHTMLLabelAccessible::GetStateInternal(PRUint32
*aState
, PRUint32
*aExtraState
)
199 nsresult rv
= nsTextAccessible::GetStateInternal(aState
, aExtraState
);
200 NS_ENSURE_A11Y_SUCCESS(rv
, rv
);
202 *aState
&= (nsIAccessibleStates::STATE_LINKED
|
203 nsIAccessibleStates::STATE_TRAVERSED
); // Only use link states
208 NS_IMETHODIMP
nsHTMLLabelAccessible::GetFirstChild(nsIAccessible
**aFirstChild
)
210 // A <label> is not necessarily a leaf!
211 return nsAccessible::GetFirstChild(aFirstChild
);
214 /* readonly attribute nsIAccessible accFirstChild; */
215 NS_IMETHODIMP
nsHTMLLabelAccessible::GetLastChild(nsIAccessible
**aLastChild
)
217 // A <label> is not necessarily a leaf!
218 return nsAccessible::GetLastChild(aLastChild
);
221 /* readonly attribute long accChildCount; */
222 NS_IMETHODIMP
nsHTMLLabelAccessible::GetChildCount(PRInt32
*aAccChildCount
)
224 // A <label> is not necessarily a leaf!
225 return nsAccessible::GetChildCount(aAccChildCount
);
228 nsHTMLLIAccessible::nsHTMLLIAccessible(nsIDOMNode
*aDOMNode
, nsIWeakReference
* aShell
,
229 const nsAString
& aBulletText
):
230 nsLinkableAccessible(aDOMNode
, aShell
)
232 if (!aBulletText
.IsEmpty()) {
233 mBulletAccessible
= new nsHTMLListBulletAccessible(mDOMNode
, mWeakShell
,
235 if (mBulletAccessible
)
236 mBulletAccessible
->Init();
241 nsHTMLLIAccessible::Shutdown()
243 if (mBulletAccessible
) {
244 // Ensure that weak pointer to this is nulled out
245 mBulletAccessible
->Shutdown();
247 nsresult rv
= nsLinkableAccessible::Shutdown();
248 mBulletAccessible
= nsnull
;
253 nsHTMLLIAccessible::GetStateInternal(PRUint32
*aState
, PRUint32
*aExtraState
)
255 nsresult rv
= nsAccessibleWrap::GetStateInternal(aState
, aExtraState
);
256 NS_ENSURE_A11Y_SUCCESS(rv
, rv
);
258 *aState
|= nsIAccessibleStates::STATE_READONLY
;
262 NS_IMETHODIMP
nsHTMLLIAccessible::GetBounds(PRInt32
*x
, PRInt32
*y
, PRInt32
*width
, PRInt32
*height
)
264 nsresult rv
= nsAccessibleWrap::GetBounds(x
, y
, width
, height
);
265 if (NS_FAILED(rv
) || !mBulletAccessible
) {
269 PRInt32 bulletX
, bulletY
, bulletWidth
, bulletHeight
;
270 rv
= mBulletAccessible
->GetBounds(&bulletX
, &bulletY
, &bulletWidth
, &bulletHeight
);
271 NS_ENSURE_SUCCESS(rv
, rv
);
273 *x
= bulletX
; // Move x coordinate of list item over to cover bullet as well
274 *width
+= bulletWidth
;
278 void nsHTMLLIAccessible::CacheChildren()
280 if (!mWeakShell
|| mAccChildCount
!= eChildCountUninitialized
) {
284 nsAccessibleWrap::CacheChildren();
286 if (mBulletAccessible
) {
287 mBulletAccessible
->SetNextSibling(mFirstChild
);
288 mBulletAccessible
->SetParent(this); // Set weak parent;
289 SetFirstChild(mBulletAccessible
);
295 // nsHTMLListBulletAccessible
296 nsHTMLListBulletAccessible::
297 nsHTMLListBulletAccessible(nsIDOMNode
* aDomNode
, nsIWeakReference
* aShell
,
298 const nsAString
& aBulletText
) :
299 nsLeafAccessible(aDomNode
, aShell
), mWeakParent(nsnull
),
300 mBulletText(aBulletText
)
302 mBulletText
+= ' '; // Otherwise bullets are jammed up against list text
306 nsHTMLListBulletAccessible::GetUniqueID(void **aUniqueID
)
308 // Since mDOMNode is same as for list item, use |this| pointer as the unique Id
309 *aUniqueID
= static_cast<void*>(this);
314 nsHTMLListBulletAccessible::Shutdown()
316 mBulletText
.Truncate();
317 mWeakParent
= nsnull
;
319 return nsLeafAccessible::Shutdown();
323 nsHTMLListBulletAccessible::GetName(nsAString
&aName
)
325 // Native anonymous content, ARIA can't be used.
331 nsHTMLListBulletAccessible::GetRole(PRUint32
*aRole
)
333 *aRole
= nsIAccessibleRole::ROLE_STATICTEXT
;
338 nsHTMLListBulletAccessible::GetStateInternal(PRUint32
*aState
, PRUint32
*aExtraState
)
340 nsresult rv
= nsLeafAccessible::GetStateInternal(aState
, aExtraState
);
341 NS_ENSURE_A11Y_SUCCESS(rv
, rv
);
343 *aState
&= ~nsIAccessibleStates::STATE_FOCUSABLE
;
344 *aState
|= nsIAccessibleStates::STATE_READONLY
;
349 nsHTMLListBulletAccessible::SetParent(nsIAccessible
*aParentAccessible
)
352 mWeakParent
= aParentAccessible
;
357 nsHTMLListBulletAccessible::GetParent(nsIAccessible
**aParentAccessible
)
359 NS_IF_ADDREF(*aParentAccessible
= mWeakParent
);
364 nsHTMLListBulletAccessible::AppendTextTo(nsAString
& aText
, PRUint32 aStartOffset
,
367 PRUint32 maxLength
= mBulletText
.Length() - aStartOffset
;
368 if (aLength
> maxLength
) {
371 aText
+= nsDependentSubstring(mBulletText
, aStartOffset
, aLength
);
375 // nsHTMLListAccessible
378 nsHTMLListAccessible::GetStateInternal(PRUint32
*aState
, PRUint32
*aExtraState
)
380 nsresult rv
= nsHyperTextAccessibleWrap::GetStateInternal(aState
,
382 NS_ENSURE_A11Y_SUCCESS(rv
, rv
);
384 *aState
|= nsIAccessibleStates::STATE_READONLY
;