accessible/src/mac/AccessibleWrap.mm

Wed, 31 Dec 2014 07:16:47 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 07:16:47 +0100
branch
TOR_BUG_9701
changeset 3
141e0f1194b1
permissions
-rw-r--r--

Revert simplistic fix pending revisit of Mozilla integration attempt.

michael@0 1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
michael@0 2 /* This Source Code Form is subject to the terms of the Mozilla Public
michael@0 3 * License, v. 2.0. If a copy of the MPL was not distributed with this
michael@0 4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
michael@0 5
michael@0 6 #include "DocAccessible.h"
michael@0 7 #include "nsObjCExceptions.h"
michael@0 8
michael@0 9 #include "Accessible-inl.h"
michael@0 10 #include "nsAccUtils.h"
michael@0 11 #include "Role.h"
michael@0 12
michael@0 13 #import "mozAccessible.h"
michael@0 14 #import "mozActionElements.h"
michael@0 15 #import "mozHTMLAccessible.h"
michael@0 16 #import "mozTextAccessible.h"
michael@0 17
michael@0 18 using namespace mozilla::a11y;
michael@0 19
michael@0 20 AccessibleWrap::
michael@0 21 AccessibleWrap(nsIContent* aContent, DocAccessible* aDoc) :
michael@0 22 Accessible(aContent, aDoc), mNativeObject(nil),
michael@0 23 mNativeInited(false)
michael@0 24 {
michael@0 25 }
michael@0 26
michael@0 27 AccessibleWrap::~AccessibleWrap()
michael@0 28 {
michael@0 29 }
michael@0 30
michael@0 31 mozAccessible*
michael@0 32 AccessibleWrap::GetNativeObject()
michael@0 33 {
michael@0 34 NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NIL;
michael@0 35
michael@0 36 if (!mNativeInited && !mNativeObject && !IsDefunct() && !AncestorIsFlat())
michael@0 37 mNativeObject = [[GetNativeType() alloc] initWithAccessible:this];
michael@0 38
michael@0 39 mNativeInited = true;
michael@0 40
michael@0 41 return mNativeObject;
michael@0 42
michael@0 43 NS_OBJC_END_TRY_ABORT_BLOCK_NIL;
michael@0 44 }
michael@0 45
michael@0 46 NS_IMETHODIMP
michael@0 47 AccessibleWrap::GetNativeInterface (void **aOutInterface)
michael@0 48 {
michael@0 49 NS_ENSURE_ARG_POINTER(aOutInterface);
michael@0 50
michael@0 51 *aOutInterface = static_cast<void*>(GetNativeObject());
michael@0 52
michael@0 53 return *aOutInterface ? NS_OK : NS_ERROR_FAILURE;
michael@0 54 }
michael@0 55
michael@0 56 // overridden in subclasses to create the right kind of object. by default we create a generic
michael@0 57 // 'mozAccessible' node.
michael@0 58 Class
michael@0 59 AccessibleWrap::GetNativeType ()
michael@0 60 {
michael@0 61 NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NIL;
michael@0 62
michael@0 63 if (IsXULTabpanels())
michael@0 64 return [mozPaneAccessible class];
michael@0 65
michael@0 66 roles::Role role = Role();
michael@0 67 switch (role) {
michael@0 68 case roles::PUSHBUTTON:
michael@0 69 case roles::SPLITBUTTON:
michael@0 70 case roles::TOGGLE_BUTTON:
michael@0 71 {
michael@0 72 // if this button may show a popup, let's make it of the popupbutton type.
michael@0 73 return HasPopup() ? [mozPopupButtonAccessible class] :
michael@0 74 [mozButtonAccessible class];
michael@0 75 }
michael@0 76
michael@0 77 case roles::PAGETAB:
michael@0 78 return [mozButtonAccessible class];
michael@0 79
michael@0 80 case roles::CHECKBUTTON:
michael@0 81 return [mozCheckboxAccessible class];
michael@0 82
michael@0 83 case roles::HEADING:
michael@0 84 return [mozHeadingAccessible class];
michael@0 85
michael@0 86 case roles::PAGETABLIST:
michael@0 87 return [mozTabsAccessible class];
michael@0 88
michael@0 89 case roles::ENTRY:
michael@0 90 case roles::STATICTEXT:
michael@0 91 case roles::CAPTION:
michael@0 92 case roles::ACCEL_LABEL:
michael@0 93 case roles::PASSWORD_TEXT:
michael@0 94 // normal textfield (static or editable)
michael@0 95 return [mozTextAccessible class];
michael@0 96
michael@0 97 case roles::TEXT_LEAF:
michael@0 98 return [mozTextLeafAccessible class];
michael@0 99
michael@0 100 case roles::LINK:
michael@0 101 return [mozLinkAccessible class];
michael@0 102
michael@0 103 case roles::COMBOBOX:
michael@0 104 return [mozPopupButtonAccessible class];
michael@0 105
michael@0 106 default:
michael@0 107 return [mozAccessible class];
michael@0 108 }
michael@0 109
michael@0 110 return nil;
michael@0 111
michael@0 112 NS_OBJC_END_TRY_ABORT_BLOCK_NIL;
michael@0 113 }
michael@0 114
michael@0 115 // this method is very important. it is fired when an accessible object "dies". after this point
michael@0 116 // the object might still be around (because some 3rd party still has a ref to it), but it is
michael@0 117 // in fact 'dead'.
michael@0 118 void
michael@0 119 AccessibleWrap::Shutdown ()
michael@0 120 {
michael@0 121 // this ensure we will not try to re-create the native object.
michael@0 122 mNativeInited = true;
michael@0 123
michael@0 124 // we really intend to access the member directly.
michael@0 125 if (mNativeObject) {
michael@0 126 [mNativeObject expire];
michael@0 127 [mNativeObject release];
michael@0 128 mNativeObject = nil;
michael@0 129 }
michael@0 130
michael@0 131 Accessible::Shutdown();
michael@0 132 }
michael@0 133
michael@0 134 nsresult
michael@0 135 AccessibleWrap::HandleAccEvent(AccEvent* aEvent)
michael@0 136 {
michael@0 137 NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT;
michael@0 138
michael@0 139 nsresult rv = Accessible::HandleAccEvent(aEvent);
michael@0 140 NS_ENSURE_SUCCESS(rv, rv);
michael@0 141
michael@0 142 uint32_t eventType = aEvent->GetEventType();
michael@0 143
michael@0 144 // ignore everything but focus-changed, value-changed, caret and selection
michael@0 145 // events for now.
michael@0 146 if (eventType != nsIAccessibleEvent::EVENT_FOCUS &&
michael@0 147 eventType != nsIAccessibleEvent::EVENT_VALUE_CHANGE &&
michael@0 148 eventType != nsIAccessibleEvent::EVENT_TEXT_CARET_MOVED &&
michael@0 149 eventType != nsIAccessibleEvent::EVENT_TEXT_SELECTION_CHANGED)
michael@0 150 return NS_OK;
michael@0 151
michael@0 152 Accessible* accessible = aEvent->GetAccessible();
michael@0 153 NS_ENSURE_STATE(accessible);
michael@0 154
michael@0 155 mozAccessible *nativeAcc = nil;
michael@0 156 accessible->GetNativeInterface((void**)&nativeAcc);
michael@0 157 if (!nativeAcc)
michael@0 158 return NS_ERROR_FAILURE;
michael@0 159
michael@0 160 switch (eventType) {
michael@0 161 case nsIAccessibleEvent::EVENT_FOCUS:
michael@0 162 [nativeAcc didReceiveFocus];
michael@0 163 break;
michael@0 164 case nsIAccessibleEvent::EVENT_VALUE_CHANGE:
michael@0 165 [nativeAcc valueDidChange];
michael@0 166 break;
michael@0 167 case nsIAccessibleEvent::EVENT_TEXT_CARET_MOVED:
michael@0 168 case nsIAccessibleEvent::EVENT_TEXT_SELECTION_CHANGED:
michael@0 169 [nativeAcc selectedTextDidChange];
michael@0 170 break;
michael@0 171 }
michael@0 172
michael@0 173 return NS_OK;
michael@0 174
michael@0 175 NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT;
michael@0 176 }
michael@0 177
michael@0 178 void
michael@0 179 AccessibleWrap::InvalidateChildren()
michael@0 180 {
michael@0 181 NS_OBJC_BEGIN_TRY_ABORT_BLOCK;
michael@0 182
michael@0 183 [GetNativeObject() invalidateChildren];
michael@0 184
michael@0 185 Accessible::InvalidateChildren();
michael@0 186
michael@0 187 NS_OBJC_END_TRY_ABORT_BLOCK;
michael@0 188 }
michael@0 189
michael@0 190 bool
michael@0 191 AccessibleWrap::InsertChildAt(uint32_t aIdx, Accessible* aAccessible)
michael@0 192 {
michael@0 193 bool inserted = Accessible::InsertChildAt(aIdx, aAccessible);
michael@0 194 if (inserted && mNativeObject)
michael@0 195 [mNativeObject appendChild:aAccessible];
michael@0 196
michael@0 197 return inserted;
michael@0 198 }
michael@0 199
michael@0 200 bool
michael@0 201 AccessibleWrap::RemoveChild(Accessible* aAccessible)
michael@0 202 {
michael@0 203 bool removed = Accessible::RemoveChild(aAccessible);
michael@0 204
michael@0 205 if (removed && mNativeObject)
michael@0 206 [mNativeObject invalidateChildren];
michael@0 207
michael@0 208 return removed;
michael@0 209 }
michael@0 210
michael@0 211 // if we for some reason have no native accessible, we should be skipped over (and traversed)
michael@0 212 // when fetching all unignored children, etc. when counting unignored children, we will not be counted.
michael@0 213 bool
michael@0 214 AccessibleWrap::IsIgnored()
michael@0 215 {
michael@0 216 NS_OBJC_BEGIN_TRY_ABORT_BLOCK_RETURN;
michael@0 217
michael@0 218 mozAccessible* nativeObject = GetNativeObject();
michael@0 219 return (!nativeObject) || [nativeObject accessibilityIsIgnored];
michael@0 220
michael@0 221 NS_OBJC_END_TRY_ABORT_BLOCK_RETURN(false);
michael@0 222 }
michael@0 223
michael@0 224 void
michael@0 225 AccessibleWrap::GetUnignoredChildren(nsTArray<Accessible*>* aChildrenArray)
michael@0 226 {
michael@0 227 // we're flat; there are no children.
michael@0 228 if (nsAccUtils::MustPrune(this))
michael@0 229 return;
michael@0 230
michael@0 231 uint32_t childCount = ChildCount();
michael@0 232 for (uint32_t childIdx = 0; childIdx < childCount; childIdx++) {
michael@0 233 AccessibleWrap* childAcc =
michael@0 234 static_cast<AccessibleWrap*>(GetChildAt(childIdx));
michael@0 235
michael@0 236 // If element is ignored, then add its children as substitutes.
michael@0 237 if (childAcc->IsIgnored()) {
michael@0 238 childAcc->GetUnignoredChildren(aChildrenArray);
michael@0 239 continue;
michael@0 240 }
michael@0 241
michael@0 242 aChildrenArray->AppendElement(childAcc);
michael@0 243 }
michael@0 244 }
michael@0 245
michael@0 246 Accessible*
michael@0 247 AccessibleWrap::GetUnignoredParent() const
michael@0 248 {
michael@0 249 // Go up the chain to find a parent that is not ignored.
michael@0 250 AccessibleWrap* parentWrap = static_cast<AccessibleWrap*>(Parent());
michael@0 251 while (parentWrap && parentWrap->IsIgnored())
michael@0 252 parentWrap = static_cast<AccessibleWrap*>(parentWrap->Parent());
michael@0 253
michael@0 254 return parentWrap;
michael@0 255 }
michael@0 256
michael@0 257 ////////////////////////////////////////////////////////////////////////////////
michael@0 258 // AccessibleWrap protected
michael@0 259
michael@0 260 bool
michael@0 261 AccessibleWrap::AncestorIsFlat()
michael@0 262 {
michael@0 263 // We don't create a native object if we're child of a "flat" accessible;
michael@0 264 // for example, on OS X buttons shouldn't have any children, because that
michael@0 265 // makes the OS confused.
michael@0 266 //
michael@0 267 // To maintain a scripting environment where the XPCOM accessible hierarchy
michael@0 268 // look the same on all platforms, we still let the C++ objects be created
michael@0 269 // though.
michael@0 270
michael@0 271 Accessible* parent = Parent();
michael@0 272 while (parent) {
michael@0 273 if (nsAccUtils::MustPrune(parent))
michael@0 274 return true;
michael@0 275
michael@0 276 parent = parent->Parent();
michael@0 277 }
michael@0 278 // no parent was flat
michael@0 279 return false;
michael@0 280 }

mercurial