Bug 453883, ensure true/false marcos are available, r=joshmoz, sr=jst
[wine-gecko.git] / accessible / src / msaa / nsDocAccessibleWrap.cpp
blob5293ffe0963b098533b771c0d5685ca6dab3a2dc
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) 2003
20 * the Initial Developer. All Rights Reserved.
22 * Contributor(s):
23 * Original Author: Aaron Leventhal (aaronl@netscape.com)
25 * Alternatively, the contents of this file may be used under the terms of
26 * either of the GNU General Public License Version 2 or later (the "GPL"),
27 * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
28 * in which case the provisions of the GPL or the LGPL are applicable instead
29 * of those above. If you wish to allow use of your version of this file only
30 * under the terms of either the GPL or the LGPL, and not to allow others to
31 * use your version of this file under the terms of the MPL, indicate your
32 * decision by deleting the provisions above and replace them with the notice
33 * and other provisions required by the GPL or the LGPL. If you do not delete
34 * the provisions above, a recipient may use your version of this file under
35 * the terms of any one of the MPL, the GPL or the LGPL.
37 * ***** END LICENSE BLOCK ***** */
39 #include "nsDocAccessibleWrap.h"
40 #include "ISimpleDOMDocument_i.c"
41 #include "nsIAccessibilityService.h"
42 #include "nsIDocShell.h"
43 #include "nsIDocShellTreeNode.h"
44 #include "nsIFrame.h"
45 #include "nsIInterfaceRequestorUtils.h"
46 #include "nsIPresShell.h"
47 #include "nsISelectionController.h"
48 #include "nsIServiceManager.h"
49 #include "nsIURI.h"
50 #include "nsIViewManager.h"
51 #include "nsIWebNavigation.h"
52 #include "nsIWidget.h"
54 /* For documentation of the accessibility architecture,
55 * see http://lxr.mozilla.org/seamonkey/source/accessible/accessible-docs.html
58 //----- nsDocAccessibleWrap -----
60 nsDocAccessibleWrap::nsDocAccessibleWrap(nsIDOMNode *aDOMNode, nsIWeakReference *aShell):
61 nsDocAccessible(aDOMNode, aShell)
65 nsDocAccessibleWrap::~nsDocAccessibleWrap()
69 //-----------------------------------------------------
70 // IUnknown interface methods - see iunknown.h for documentation
71 //-----------------------------------------------------
72 STDMETHODIMP_(ULONG) nsDocAccessibleWrap::AddRef()
74 return nsAccessNode::AddRef();
77 STDMETHODIMP_(ULONG) nsDocAccessibleWrap::Release()
79 return nsAccessNode::Release();
82 // Microsoft COM QueryInterface
83 STDMETHODIMP nsDocAccessibleWrap::QueryInterface(REFIID iid, void** ppv)
85 *ppv = NULL;
87 if (IID_ISimpleDOMDocument == iid)
88 *ppv = static_cast<ISimpleDOMDocument*>(this);
90 if (NULL == *ppv)
91 return nsHyperTextAccessibleWrap::QueryInterface(iid, ppv);
93 (reinterpret_cast<IUnknown*>(*ppv))->AddRef();
94 return S_OK;
97 void nsDocAccessibleWrap::GetXPAccessibleFor(const VARIANT& aVarChild, nsIAccessible **aXPAccessible)
99 *aXPAccessible = nsnull;
100 if (!mWeakShell)
101 return; // This document has been shut down
103 if (aVarChild.lVal < 0) {
104 // Get from hash table
105 void *uniqueID = (void*)(-aVarChild.lVal); // Convert child ID back to unique ID
106 nsCOMPtr<nsIAccessNode> accessNode;
107 GetCachedAccessNode(uniqueID, getter_AddRefs(accessNode));
108 nsCOMPtr<nsIAccessible> accessible(do_QueryInterface(accessNode));
109 NS_IF_ADDREF(*aXPAccessible = accessible);
110 return;
113 nsDocAccessible::GetXPAccessibleFor(aVarChild, aXPAccessible);
116 STDMETHODIMP nsDocAccessibleWrap::get_accChild(
117 /* [in] */ VARIANT varChild,
118 /* [retval][out] */ IDispatch __RPC_FAR *__RPC_FAR *ppdispChild)
120 __try {
121 *ppdispChild = NULL;
123 if (varChild.vt == VT_I4 && varChild.lVal < 0) {
124 // AccessibleObjectFromEvent() being called
125 // that's why the lVal < 0
126 nsCOMPtr<nsIAccessible> xpAccessible;
127 GetXPAccessibleFor(varChild, getter_AddRefs(xpAccessible));
128 if (xpAccessible) {
129 IAccessible *msaaAccessible;
130 xpAccessible->GetNativeInterface((void**)&msaaAccessible);
131 *ppdispChild = static_cast<IDispatch*>(msaaAccessible);
132 return S_OK;
134 else if (mDocument) {
135 // If child ID from event can't be found in this window, ask parent.
136 // This is especially relevant for times when a xul menu item
137 // has focus, but the system thinks the content window has focus.
138 nsIDocument* parentDoc = mDocument->GetParentDocument();
139 if (parentDoc) {
140 nsIPresShell *parentShell = parentDoc->GetPrimaryShell();
141 nsCOMPtr<nsIWeakReference> weakParentShell(do_GetWeakReference(parentShell));
142 if (weakParentShell) {
143 nsCOMPtr<nsIAccessibleDocument> parentDocAccessible =
144 nsAccessNode::GetDocAccessibleFor(weakParentShell);
145 nsCOMPtr<nsIAccessible> accessible(do_QueryInterface(parentDocAccessible));
146 IAccessible *msaaParentDoc;
147 if (accessible) {
148 accessible->GetNativeInterface((void**)&msaaParentDoc);
149 HRESULT rv = msaaParentDoc->get_accChild(varChild, ppdispChild);
150 msaaParentDoc->Release();
151 return rv;
156 return E_FAIL;
159 // Otherwise, the normal get_accChild() will do
160 return nsAccessibleWrap::get_accChild(varChild, ppdispChild);
161 } __except(FilterA11yExceptions(::GetExceptionCode(), GetExceptionInformation())) { }
162 return E_FAIL;
165 NS_IMETHODIMP nsDocAccessibleWrap::FireAnchorJumpEvent()
167 // Staying on the same page, jumping to a named anchor
168 // Fire EVENT_SCROLLING_START on first leaf accessible -- because some
169 // assistive technologies only cache the child numbers for leaf accessibles
170 // the can only relate events back to their internal model if it's a leaf.
171 // There is usually an accessible for the focus node, but if it's an empty text node
172 // we have to move forward in the document to get one
173 nsDocAccessible::FireAnchorJumpEvent();
174 if (!mIsAnchorJumped)
175 return NS_OK;
177 nsCOMPtr<nsIDOMNode> focusNode;
178 if (mIsAnchor) {
179 nsCOMPtr<nsISelectionController> selCon(do_QueryReferent(mWeakShell));
180 if (!selCon) {
181 return NS_OK;
183 nsCOMPtr<nsISelection> domSel;
184 selCon->GetSelection(nsISelectionController::SELECTION_NORMAL, getter_AddRefs(domSel));
185 if (!domSel) {
186 return NS_OK;
188 domSel->GetFocusNode(getter_AddRefs(focusNode));
190 else {
191 focusNode = mDOMNode; // Moved to top, so event is for 1st leaf after root
194 nsCOMPtr<nsIAccessible> accessible = GetFirstAvailableAccessible(focusNode, PR_TRUE);
195 nsAccUtils::FireAccEvent(nsIAccessibleEvent::EVENT_SCROLLING_START,
196 accessible);
198 return NS_OK;
201 STDMETHODIMP nsDocAccessibleWrap::get_URL(/* [out] */ BSTR __RPC_FAR *aURL)
203 __try {
204 *aURL = NULL;
206 nsAutoString URL;
207 nsresult rv = GetURL(URL);
208 if (NS_FAILED(rv))
209 return E_FAIL;
211 if (URL.IsEmpty())
212 return S_FALSE;
214 *aURL = ::SysAllocStringLen(URL.get(), URL.Length());
215 return *aURL ? S_OK : E_OUTOFMEMORY;
217 } __except(FilterA11yExceptions(::GetExceptionCode(), GetExceptionInformation())) { }
218 return E_FAIL;
221 STDMETHODIMP nsDocAccessibleWrap::get_title( /* [out] */ BSTR __RPC_FAR *aTitle)
223 __try {
224 *aTitle = NULL;
226 nsAutoString title;
227 nsresult rv = GetTitle(title);
228 if (NS_FAILED(rv))
229 return E_FAIL;
231 *aTitle = ::SysAllocStringLen(title.get(), title.Length());
232 return *aTitle ? S_OK : E_OUTOFMEMORY;
234 } __except(FilterA11yExceptions(::GetExceptionCode(), GetExceptionInformation())) { }
235 return E_FAIL;
238 STDMETHODIMP nsDocAccessibleWrap::get_mimeType(/* [out] */ BSTR __RPC_FAR *aMimeType)
240 __try {
241 *aMimeType = NULL;
243 nsAutoString mimeType;
244 nsresult rv = GetMimeType(mimeType);
245 if (NS_FAILED(rv))
246 return E_FAIL;
248 if (mimeType.IsEmpty())
249 return S_FALSE;
251 *aMimeType = ::SysAllocStringLen(mimeType.get(), mimeType.Length());
252 return *aMimeType ? S_OK : E_OUTOFMEMORY;
254 } __except(FilterA11yExceptions(::GetExceptionCode(), GetExceptionInformation())) { }
255 return E_FAIL;
258 STDMETHODIMP nsDocAccessibleWrap::get_docType(/* [out] */ BSTR __RPC_FAR *aDocType)
260 __try {
261 *aDocType = NULL;
263 nsAutoString docType;
264 nsresult rv = GetDocType(docType);
265 if (NS_FAILED(rv))
266 return E_FAIL;
268 if (docType.IsEmpty())
269 return S_FALSE;
271 *aDocType = ::SysAllocStringLen(docType.get(), docType.Length());
272 return *aDocType ? S_OK : E_OUTOFMEMORY;
274 } __except(FilterA11yExceptions(::GetExceptionCode(), GetExceptionInformation())) { }
275 return E_FAIL;
278 STDMETHODIMP nsDocAccessibleWrap::get_nameSpaceURIForID(/* [in] */ short aNameSpaceID,
279 /* [out] */ BSTR __RPC_FAR *aNameSpaceURI)
281 __try {
282 *aNameSpaceURI = NULL;
284 if (aNameSpaceID < 0)
285 return E_INVALIDARG; // -1 is kNameSpaceID_Unknown
287 nsAutoString nameSpaceURI;
288 nsresult rv = GetNameSpaceURIForID(aNameSpaceID, nameSpaceURI);
289 if (NS_FAILED(rv))
290 return E_FAIL;
292 if (nameSpaceURI.IsEmpty())
293 return S_FALSE;
295 *aNameSpaceURI = ::SysAllocStringLen(nameSpaceURI.get(),
296 nameSpaceURI.Length());
298 return *aNameSpaceURI ? S_OK : E_OUTOFMEMORY;
300 } __except(FilterA11yExceptions(::GetExceptionCode(), GetExceptionInformation())) { }
301 return E_FAIL;
304 STDMETHODIMP
305 nsDocAccessibleWrap::put_alternateViewMediaTypes( /* [in] */ BSTR __RPC_FAR *aCommaSeparatedMediaTypes)
307 __try {
308 *aCommaSeparatedMediaTypes = NULL;
309 } __except(FilterA11yExceptions(::GetExceptionCode(), GetExceptionInformation())) { }
311 return E_NOTIMPL;
314 STDMETHODIMP nsDocAccessibleWrap::get_accValue(
315 /* [optional][in] */ VARIANT varChild,
316 /* [retval][out] */ BSTR __RPC_FAR *pszValue)
318 // For backwards-compat, we still support old MSAA hack to provide URL in accValue
319 *pszValue = NULL;
320 // Check for real value first
321 HRESULT hr = nsAccessibleWrap::get_accValue(varChild, pszValue);
322 if (FAILED(hr) || *pszValue || varChild.lVal != CHILDID_SELF)
323 return hr;
324 // If document is being used to create a widget, don't use the URL hack
325 PRUint32 role = Role(this);
326 if (role != nsIAccessibleRole::ROLE_DOCUMENT &&
327 role != nsIAccessibleRole::ROLE_APPLICATION &&
328 role != nsIAccessibleRole::ROLE_DIALOG &&
329 role != nsIAccessibleRole::ROLE_ALERT)
330 return hr;
332 return get_URL(pszValue);