void
HTMLImageMapAccessible::UpdateChildAreas(bool aDoFireEvents)
{
  nsImageFrame* imageFrame = do_QueryFrame(mContent->GetPrimaryFrame());

  // If image map is not initialized yet then we trigger one time more later.
  nsImageMap* imageMapObj = imageFrame->GetExistingImageMap();
  if (!imageMapObj)
    return;

  bool doReorderEvent = false;

  // Remove areas that are not a valid part of the image map anymore.
  for (int32_t childIdx = mChildren.Length() - 1; childIdx >= 0; childIdx--) {
    Accessible* area = mChildren.ElementAt(childIdx);
    if (area->GetContent()->GetPrimaryFrame())
      continue;

    if (aDoFireEvents) {
      nsRefPtr<AccEvent> event = new AccHideEvent(area, area->GetContent());
      mDoc->FireDelayedAccessibleEvent(event);
      doReorderEvent = true;
    }

    RemoveChild(area);
  }

  // Insert new areas into the tree.
  uint32_t areaElmCount = imageMapObj->AreaCount();
  for (uint32_t idx = 0; idx < areaElmCount; idx++) {
    nsIContent* areaContent = imageMapObj->GetAreaAt(idx);

    Accessible* area = mChildren.SafeElementAt(idx);
    if (!area || area->GetContent() != areaContent) {
      nsRefPtr<Accessible> area = new HTMLAreaAccessible(areaContent, mDoc);
      if (!mDoc->BindToDocument(area, aria::GetRoleMap(areaContent)))
        break;

      if (!InsertChildAt(idx, area)) {
        mDoc->UnbindFromDocument(area);
        break;
      }

      if (aDoFireEvents) {
        nsRefPtr<AccEvent> event = new AccShowEvent(area, areaContent);
        mDoc->FireDelayedAccessibleEvent(event);
        doReorderEvent = true;
      }
    }
  }

  // Fire reorder event if needed.
  if (doReorderEvent) {
    nsRefPtr<AccEvent> reorderEvent =
      new AccEvent(nsIAccessibleEvent::EVENT_REORDER, mContent,
                   eAutoDetect, AccEvent::eCoalesceFromSameSubtree);
    mDoc->FireDelayedAccessibleEvent(reorderEvent);
  }
}
Beispiel #2
0
void
TextAttrsMgr::GetRange(TextAttr* aAttrArray[], uint32_t aAttrArrayLen,
                       uint32_t* aStartOffset, uint32_t* aEndOffset)
{
  // Navigate backward from anchor accessible to find start offset.
  for (int32_t childIdx = mOffsetAccIdx - 1; childIdx >= 0; childIdx--) {
    Accessible* currAcc = mHyperTextAcc->GetChildAt(childIdx);

    // Stop on embedded accessible since embedded accessibles are combined into
    // own range.
    if (!currAcc->IsText())
      break;

    MOZ_ASSERT(nsCoreUtils::GetDOMElementFor(currAcc->GetContent()),
               "Text accessible has to have an associated DOM element");

    bool offsetFound = false;
    for (uint32_t attrIdx = 0; attrIdx < aAttrArrayLen; attrIdx++) {
      TextAttr* textAttr = aAttrArray[attrIdx];
      if (!textAttr->Equal(currAcc)) {
        offsetFound = true;
        break;
      }
    }

    if (offsetFound)
      break;

    *(aStartOffset) -= nsAccUtils::TextLength(currAcc);
  }

  // Navigate forward from anchor accessible to find end offset.
  uint32_t childLen = mHyperTextAcc->ChildCount();
  for (uint32_t childIdx = mOffsetAccIdx + 1; childIdx < childLen; childIdx++) {
    Accessible* currAcc = mHyperTextAcc->GetChildAt(childIdx);
    if (!currAcc->IsText())
      break;

    MOZ_ASSERT(nsCoreUtils::GetDOMElementFor(currAcc->GetContent()),
               "Text accessible has to have an associated DOM element");

    bool offsetFound = false;
    for (uint32_t attrIdx = 0; attrIdx < aAttrArrayLen; attrIdx++) {
      TextAttr* textAttr = aAttrArray[attrIdx];

      // Alter the end offset when text attribute changes its value and stop
      // the search.
      if (!textAttr->Equal(currAcc)) {
        offsetFound = true;
        break;
      }
    }

    if (offsetFound)
      break;

    (*aEndOffset) += nsAccUtils::TextLength(currAcc);
  }
}
Beispiel #3
0
Accessible* HTMLLabelIterator::Next() {
  // Get either <label for="[id]"> element which explicitly points to given
  // element, or <label> ancestor which implicitly point to it.
  Accessible* label = nullptr;
  while ((label = mRelIter.Next())) {
    if (IsLabel(label)) {
      return label;
    }
  }

  // Ignore ancestor label on not widget accessible.
  if (mLabelFilter == eSkipAncestorLabel || !mAcc->IsWidget()) return nullptr;

  // Go up tree to get a name of ancestor label if there is one (an ancestor
  // <label> implicitly points to us). Don't go up farther than form or
  // document.
  Accessible* walkUp = mAcc->Parent();
  while (walkUp && !walkUp->IsDoc()) {
    nsIContent* walkUpEl = walkUp->GetContent();
    if (IsLabel(walkUp) &&
        !walkUpEl->AsElement()->HasAttr(kNameSpaceID_None, nsGkAtoms::_for)) {
      mLabelFilter = eSkipAncestorLabel;  // prevent infinite loop
      return walkUp;
    }

    if (walkUpEl->IsHTMLElement(nsGkAtoms::form)) break;

    walkUp = walkUp->Parent();
  }

  return nullptr;
}
Beispiel #4
0
void
LinkableAccessible::BindToParent(Accessible* aParent,
                                 uint32_t aIndexInParent)
{
    AccessibleWrap::BindToParent(aParent, aIndexInParent);

    // Cache action content.
    mActionAcc = nullptr;
    mIsLink = false;
    mIsOnclick = false;

    if (nsCoreUtils::HasClickListener(mContent)) {
        mIsOnclick = true;
        return;
    }

    // XXX: The logic looks broken since the click listener may be registered
    // on non accessible node in parent chain but this node is skipped when tree
    // is traversed.
    Accessible* walkUpAcc = this;
    while ((walkUpAcc = walkUpAcc->Parent()) && !walkUpAcc->IsDoc()) {
        if (walkUpAcc->LinkState() & states::LINKED) {
            mIsLink = true;
            mActionAcc = walkUpAcc;
            return;
        }

        if (nsCoreUtils::HasClickListener(walkUpAcc->GetContent())) {
            mActionAcc = walkUpAcc;
            mIsOnclick = true;
            return;
        }
    }
}
bool
XULSelectControlAccessible::RemoveItemFromSelection(uint32_t aIndex)
{
  Accessible* item = GetChildAt(aIndex);
  if (!item)
    return false;

  nsCOMPtr<nsIDOMXULSelectControlItemElement> itemElm =
      do_QueryInterface(item->GetContent());
  if (!itemElm)
    return false;

  bool isItemSelected = false;
  itemElm->GetSelected(&isItemSelected);
  if (!isItemSelected)
    return true;

  nsCOMPtr<nsIDOMXULMultiSelectControlElement> multiSelectControl =
    do_QueryInterface(mSelectControl);

  if (multiSelectControl)
    multiSelectControl->RemoveItemFromSelection(itemElm);
  else
    mSelectControl->SetSelectedItem(nullptr);

  return true;
}
nsIContent*
nsXFormsSelectableAccessible::GetItemByIndex(PRUint32* aIndex,
                                             Accessible* aAccessible)
{
  Accessible* accessible = aAccessible ? aAccessible : this;
  PRUint32 childCount = accessible->ChildCount();
  for (PRUint32 childIdx = 0; childIdx < childCount; childIdx++) {
    Accessible* child = accessible->GetChildAt(childIdx);
    nsIContent* childContent = child->GetContent();
    nsINodeInfo *nodeInfo = childContent->NodeInfo();
    if (nodeInfo->NamespaceEquals(NS_LITERAL_STRING(NS_NAMESPACE_XFORMS))) {
      if (nodeInfo->Equals(nsGkAtoms::item)) {
        if (!*aIndex)
          return childContent;

        --*aIndex;
      } else if (nodeInfo->Equals(nsGkAtoms::choices)) {
        nsIContent* itemContent = GetItemByIndex(aIndex, child);
        if (itemContent)
          return itemContent;
      }
    }
  }

  return nsnull;
}
void
HTMLTableAccessible::Description(nsString& aDescription)
{
  // Helpful for debugging layout vs. data tables
  aDescription.Truncate();
  Accessible::Description(aDescription);
  if (!aDescription.IsEmpty())
    return;

  // Use summary as description if it weren't used as a name.
  // XXX: get rid code duplication with NameInternal().
  Accessible* caption = Caption();
  if (caption) {
    nsIContent* captionContent = caption->GetContent();
    if (captionContent) {
      nsAutoString captionText;
      nsTextEquivUtils::AppendTextEquivFromContent(this, captionContent,
                                                   &captionText);

      if (!captionText.IsEmpty()) { // summary isn't used as a name.
        mContent->AsElement()->GetAttr(kNameSpaceID_None, nsGkAtoms::summary,
                                       aDescription);
      }
    }
  }

#ifdef SHOW_LAYOUT_HEURISTIC
  if (aDescription.IsEmpty()) {
    bool isProbablyForLayout = IsProbablyLayoutTable();
    aDescription = mLayoutHeuristic;
  }
  printf("\nTABLE: %s\n", NS_ConvertUTF16toUTF8(mLayoutHeuristic).get());
#endif
}
uint64_t
XULMenupopupAccessible::NativeState() const
{
  uint64_t state = Accessible::NativeState();

#ifdef DEBUG
  // We are onscreen if our parent is active
  bool isActive =
    mContent->AsElement()->HasAttr(kNameSpaceID_None, nsGkAtoms::menuactive);
  if (!isActive) {
    Accessible* parent = Parent();
    if (parent) {
      nsIContent* parentContent = parent->GetContent();
      if (parentContent && parentContent->IsElement())
        isActive = parentContent->AsElement()->HasAttr(kNameSpaceID_None, nsGkAtoms::open);
    }
  }

  NS_ASSERTION(isActive || (state & states::INVISIBLE),
               "XULMenupopup doesn't have INVISIBLE when it's inactive");
#endif

  if (state & states::INVISIBLE)
    state |= states::OFFSCREEN | states::COLLAPSED;

  return state;
}
Beispiel #9
0
Accessible* HTMLOutputIterator::Next() {
  Accessible* output = nullptr;
  while ((output = mRelIter.Next())) {
    if (output->GetContent()->IsHTMLElement(nsGkAtoms::output)) return output;
  }

  return nullptr;
}
Beispiel #10
0
Accessible* XULDescriptionIterator::Next() {
  Accessible* descr = nullptr;
  while ((descr = mRelIter.Next())) {
    if (descr->GetContent()->IsXULElement(nsGkAtoms::description)) return descr;
  }

  return nullptr;
}
Beispiel #11
0
Accessible* XULLabelIterator::Next() {
  Accessible* label = nullptr;
  while ((label = mRelIter.Next())) {
    if (label->GetContent()->IsXULElement(nsGkAtoms::label)) return label;
  }

  return nullptr;
}
already_AddRefed<nsIPersistentProperties>
HTMLTableCellAccessible::NativeAttributes()
{
  nsCOMPtr<nsIPersistentProperties> attributes =
    HyperTextAccessibleWrap::NativeAttributes();

  // table-cell-index attribute
  TableAccessible* table = Table();
  if (!table)
    return attributes.forget();

  int32_t rowIdx = -1, colIdx = -1;
  nsresult rv = GetCellIndexes(rowIdx, colIdx);
  if (NS_FAILED(rv))
    return attributes.forget();

  nsAutoString stringIdx;
  stringIdx.AppendInt(table->CellIndexAt(rowIdx, colIdx));
  nsAccUtils::SetAccAttr(attributes, nsGkAtoms::tableCellIndex, stringIdx);

  // abbr attribute

  // Pick up object attribute from abbr DOM element (a child of the cell) or
  // from abbr DOM attribute.
  nsAutoString abbrText;
  if (ChildCount() == 1) {
    Accessible* abbr = FirstChild();
    if (abbr->IsAbbreviation()) {
      nsIContent* firstChildNode = abbr->GetContent()->GetFirstChild();
      if (firstChildNode) {
        nsTextEquivUtils::
          AppendTextEquivFromTextContent(firstChildNode, &abbrText);
      }
    }
  }
  if (abbrText.IsEmpty())
    mContent->AsElement()->GetAttr(kNameSpaceID_None, nsGkAtoms::abbr, abbrText);

  if (!abbrText.IsEmpty())
    nsAccUtils::SetAccAttr(attributes, nsGkAtoms::abbr, abbrText);

  // axis attribute
  nsAutoString axisText;
  mContent->AsElement()->GetAttr(kNameSpaceID_None, nsGkAtoms::axis, axisText);
  if (!axisText.IsEmpty())
    nsAccUtils::SetAccAttr(attributes, nsGkAtoms::axis, axisText);

#ifdef DEBUG
  nsAutoString unused;
  attributes->SetStringProperty(NS_LITERAL_CSTRING("cppclass"),
                                NS_LITERAL_STRING("HTMLTableCellAccessible"),
                                unused);
#endif

  return attributes.forget();
}
already_AddRefed<nsIURI>
HTMLImageMapAccessible::AnchorURIAt(uint32_t aAnchorIndex)
{
  Accessible* area = GetChildAt(aAnchorIndex);
  if (!area)
    return nullptr;

  nsIContent* linkContent = area->GetContent();
  return linkContent ? linkContent->GetHrefURI() : nullptr;
}
role
HTMLTableHeaderCellAccessible::NativeRole()
{
  // Check value of @scope attribute.
  static Element::AttrValuesArray scopeValues[] =
    { &nsGkAtoms::col, &nsGkAtoms::colgroup,
      &nsGkAtoms::row, &nsGkAtoms::rowgroup, nullptr };
  int32_t valueIdx =
    mContent->AsElement()->FindAttrValueIn(kNameSpaceID_None, nsGkAtoms::scope,
                                           scopeValues, eCaseMatters);

  switch (valueIdx) {
    case 0:
    case 1:
      return roles::COLUMNHEADER;
    case 2:
    case 3:
      return roles::ROWHEADER;
  }

  TableAccessible* table = Table();
  if (!table)
    return roles::NOTHING;

  // If the cell next to this one is not a header cell then assume this cell is
  // a row header for it.
  uint32_t rowIdx = RowIdx(), colIdx = ColIdx();
  Accessible* cell = table->CellAt(rowIdx, colIdx + ColExtent());
  if (cell && !nsCoreUtils::IsHTMLTableHeader(cell->GetContent()))
    return roles::ROWHEADER;

  // If the cell below this one is not a header cell then assume this cell is
  // a column header for it.
  uint32_t rowExtent = RowExtent();
  cell = table->CellAt(rowIdx + rowExtent, colIdx);
  if (cell && !nsCoreUtils::IsHTMLTableHeader(cell->GetContent()))
    return roles::COLUMNHEADER;

  // Otherwise if this cell is surrounded by header cells only then make a guess
  // based on its cell spanning. In other words if it is row spanned then assume
  // it's a row header, otherwise it's a column header.
  return rowExtent > 1 ? roles::ROWHEADER : roles::COLUMNHEADER;
}
Beispiel #15
0
Accessible*
HTMLOutputIterator::Next()
{
  Accessible* output = nsnull;
  while ((output = mRelIter.Next())) {
    if (output->GetContent()->Tag() == nsGkAtoms::output)
      return output;
  }

  return nsnull;
}
Beispiel #16
0
Accessible*
XULDescriptionIterator::Next()
{
  Accessible* descr = nsnull;
  while ((descr = mRelIter.Next())) {
    if (descr->GetContent()->Tag() == nsGkAtoms::description)
      return descr;
  }

  return nsnull;
}
Beispiel #17
0
Accessible*
XULLabelIterator::Next()
{
  Accessible* label = nsnull;
  while ((label = mRelIter.Next())) {
    if (label->GetContent()->Tag() == nsGkAtoms::label)
      return label;
  }

  return nsnull;
}
nsresult
nsHTMLTableCellAccessible::GetAttributesInternal(nsIPersistentProperties *aAttributes)
{
  if (IsDefunct())
    return NS_ERROR_FAILURE;

  nsresult rv = HyperTextAccessibleWrap::GetAttributesInternal(aAttributes);
  NS_ENSURE_SUCCESS(rv, rv);

  // table-cell-index attribute
  nsCOMPtr<nsIAccessibleTable> tableAcc(GetTableAccessible());
  if (!tableAcc)
    return NS_OK;

  PRInt32 rowIdx = -1, colIdx = -1;
  rv = GetCellIndexes(rowIdx, colIdx);
  NS_ENSURE_SUCCESS(rv, rv);

  PRInt32 idx = -1;
  rv = tableAcc->GetCellIndexAt(rowIdx, colIdx, &idx);
  NS_ENSURE_SUCCESS(rv, rv);

  nsAutoString stringIdx;
  stringIdx.AppendInt(idx);
  nsAccUtils::SetAccAttr(aAttributes, nsGkAtoms::tableCellIndex, stringIdx);

  // abbr attribute

  // Pick up object attribute from abbr DOM element (a child of the cell) or
  // from abbr DOM attribute.
  nsAutoString abbrText;
  if (ChildCount() == 1) {
    Accessible* abbr = FirstChild();
    if (abbr->IsAbbreviation()) {
      nsTextEquivUtils::
        AppendTextEquivFromTextContent(abbr->GetContent()->GetFirstChild(),
                                       &abbrText);
    }
  }
  if (abbrText.IsEmpty())
    mContent->GetAttr(kNameSpaceID_None, nsGkAtoms::abbr, abbrText);

  if (!abbrText.IsEmpty())
    nsAccUtils::SetAccAttr(aAttributes, nsGkAtoms::abbr, abbrText);

  // axis attribute
  nsAutoString axisText;
  mContent->GetAttr(kNameSpaceID_None, nsGkAtoms::axis, axisText);
  if (!axisText.IsEmpty())
    nsAccUtils::SetAccAttr(aAttributes, nsGkAtoms::axis, axisText);

  return NS_OK;
}
Beispiel #19
0
GroupPos ARIARowAccessible::GroupPosition() {
  int32_t count = 0, index = 0;
  Accessible* table = nsAccUtils::TableFor(this);
  if (table &&
      nsCoreUtils::GetUIntAttr(table->GetContent(), nsGkAtoms::aria_rowcount,
                               &count) &&
      nsCoreUtils::GetUIntAttr(mContent, nsGkAtoms::aria_rowindex, &index)) {
    return GroupPos(0, index, count);
  }

  return AccessibleWrap::GroupPosition();
}
Relation HTMLFigcaptionAccessible::RelationByType(RelationType aType) const {
  Relation rel = HyperTextAccessibleWrap::RelationByType(aType);
  if (aType != RelationType::LABEL_FOR) return rel;

  Accessible* figure = Parent();
  if (figure && figure->GetContent()->NodeInfo()->Equals(
                    nsGkAtoms::figure, mContent->GetNameSpaceID())) {
    rel.AppendTarget(figure);
  }

  return rel;
}
Accessible*
HTMLImageMapAccessible::GetChildAccessibleFor(const nsINode* aNode) const
{
  uint32_t length = mChildren.Length();
  for (uint32_t i = 0; i < length; i++) {
    Accessible* area = mChildren[i];
    if (area->GetContent() == aNode)
      return area;
  }

  return nullptr;
}
bool
XULSelectControlAccessible::IsItemSelected(uint32_t aIndex)
{
  Accessible* item = GetChildAt(aIndex);
  if (!item)
    return false;

  nsCOMPtr<nsIDOMXULSelectControlItemElement> itemElm =
    do_QueryInterface(item->GetContent());
  if (!itemElm)
    return false;

  bool isItemSelected = false;
  itemElm->GetSelected(&isItemSelected);
  return isItemSelected;
}
Beispiel #23
0
void ARIAGridCellAccessible::ApplyARIAState(uint64_t* aState) const {
  HyperTextAccessibleWrap::ApplyARIAState(aState);

  // Return if the gridcell has aria-selected="true".
  if (*aState & states::SELECTED) return;

  // Check aria-selected="true" on the row.
  Accessible* row = Parent();
  if (!row || row->Role() != roles::ROW) return;

  nsIContent* rowContent = row->GetContent();
  if (nsAccUtils::HasDefinedARIAToken(rowContent, nsGkAtoms::aria_selected) &&
      !rowContent->AsElement()->AttrValueIs(kNameSpaceID_None,
                                            nsGkAtoms::aria_selected,
                                            nsGkAtoms::_false, eCaseMatters))
    *aState |= states::SELECTABLE | states::SELECTED;
}
ENameValueFlag
HTMLTableAccessible::NativeName(nsString& aName)
{
  ENameValueFlag nameFlag = Accessible::NativeName(aName);
  if (!aName.IsEmpty())
    return nameFlag;

  // Use table caption as a name.
  Accessible* caption = Caption();
  if (caption) {
    nsIContent* captionContent = caption->GetContent();
    if (captionContent) {
      nsTextEquivUtils::AppendTextEquivFromContent(this, captionContent, &aName);
      if (!aName.IsEmpty())
        return eNameOK;
    }
  }

  // If no caption then use summary as a name.
  mContent->AsElement()->GetAttr(kNameSpaceID_None, nsGkAtoms::summary, aName);
  return eNameOK;
}
Beispiel #25
0
nsIContent*
TreeWalker::Next(ChildrenIterator* aIter, Accessible** aAccesible,
                 bool* aSkipSubtree)
{
  nsIContent* childEl = aIter->mDOMIter.GetNextChild();
  if (!aAccesible)
    return childEl;

  *aAccesible = nullptr;
  *aSkipSubtree = false;

  if (childEl) {
    Accessible* accessible = mFlags & eWalkCache ?
      mDoc->GetAccessible(childEl) :
      GetAccService()->GetOrCreateAccessible(childEl, mContext, aSkipSubtree);

    // Ignore the accessible and its subtree if it was repositioned by means of
    // aria-owns.
    if (accessible) {
      if (accessible->IsRelocated()) {
        *aSkipSubtree = true;
      } else {
        *aAccesible = accessible;
      }
    }
    return childEl;
  }

  // At last iterate over ARIA owned children.
  Accessible* parent = mDoc->GetAccessible(aIter->mDOMIter.Parent());
  if (parent) {
    Accessible* child = mDoc->ARIAOwnedAt(parent, aIter->mARIAOwnsIdx++);
    if (child) {
      *aAccesible = child;
      return child->GetContent();
    }
  }
  return nullptr;
}
nsresult
nsHTMLTableAccessible::GetNameInternal(nsAString& aName)
{
  Accessible::GetNameInternal(aName);
  if (!aName.IsEmpty())
    return NS_OK;

  // Use table caption as a name.
  Accessible* caption = Caption();
  if (caption) {
    nsIContent* captionContent = caption->GetContent();
    if (captionContent) {
      nsTextEquivUtils::AppendTextEquivFromContent(this, captionContent, &aName);
      if (!aName.IsEmpty())
        return NS_OK;
    }
  }

  // If no caption then use summary as a name.
  mContent->GetAttr(kNameSpaceID_None, nsGkAtoms::summary, aName);
  return NS_OK;
}
Beispiel #27
0
void
TextAttrsMgr::GetRange(TextAttr* aAttrArray[], PRUint32 aAttrArrayLen,
                       PRInt32* aStartHTOffset, PRInt32* aEndHTOffset)
{
  // Navigate backward from anchor accessible to find start offset.
  for (PRInt32 childIdx = mOffsetAccIdx - 1; childIdx >= 0; childIdx--) {
    Accessible* currAcc = mHyperTextAcc->GetChildAt(childIdx);

    // Stop on embedded accessible since embedded accessibles are combined into
    // own range.
    if (nsAccUtils::IsEmbeddedObject(currAcc))
      break;

    nsIContent* currElm = nsCoreUtils::GetDOMElementFor(currAcc->GetContent());
    if (!currElm)
      return;

    bool offsetFound = false;
    for (PRUint32 attrIdx = 0; attrIdx < aAttrArrayLen; attrIdx++) {
      TextAttr* textAttr = aAttrArray[attrIdx];
      if (!textAttr->Equal(currElm)) {
        offsetFound = true;
        break;
      }
    }

    if (offsetFound)
      break;

    *(aStartHTOffset) -= nsAccUtils::TextLength(currAcc);
  }

  // Navigate forward from anchor accessible to find end offset.
  PRUint32 childLen = mHyperTextAcc->ChildCount();
  for (PRUint32 childIdx = mOffsetAccIdx + 1; childIdx < childLen; childIdx++) {
    Accessible* currAcc = mHyperTextAcc->GetChildAt(childIdx);
    if (nsAccUtils::IsEmbeddedObject(currAcc))
      break;

    nsIContent* currElm = nsCoreUtils::GetDOMElementFor(currAcc->GetContent());
    if (!currElm)
      return;

    bool offsetFound = false;
    for (PRUint32 attrIdx = 0; attrIdx < aAttrArrayLen; attrIdx++) {
      TextAttr* textAttr = aAttrArray[attrIdx];

      // Alter the end offset when text attribute changes its value and stop
      // the search.
      if (!textAttr->Equal(currElm)) {
        offsetFound = true;
        break;
      }
    }

    if (offsetFound)
      break;

    (*aEndHTOffset) += nsAccUtils::TextLength(currAcc);
  }
}
void
HTMLImageMapAccessible::UpdateChildAreas(bool aDoFireEvents)
{
  nsImageFrame* imageFrame = do_QueryFrame(mContent->GetPrimaryFrame());

  // If image map is not initialized yet then we trigger one time more later.
  nsImageMap* imageMapObj = imageFrame->GetExistingImageMap();
  if (!imageMapObj)
    return;

  bool treeChanged = false;
  AutoTreeMutation mut(this);
  nsRefPtr<AccReorderEvent> reorderEvent = new AccReorderEvent(this);

  // Remove areas that are not a valid part of the image map anymore.
  for (int32_t childIdx = mChildren.Length() - 1; childIdx >= 0; childIdx--) {
    Accessible* area = mChildren.ElementAt(childIdx);
    if (area->GetContent()->GetPrimaryFrame())
      continue;

    if (aDoFireEvents) {
      nsRefPtr<AccHideEvent> event = new AccHideEvent(area, area->GetContent());
      mDoc->FireDelayedEvent(event);
      reorderEvent->AddSubMutationEvent(event);
    }

    RemoveChild(area);
    treeChanged = true;
  }

  // Insert new areas into the tree.
  uint32_t areaElmCount = imageMapObj->AreaCount();
  for (uint32_t idx = 0; idx < areaElmCount; idx++) {
    nsIContent* areaContent = imageMapObj->GetAreaAt(idx);

    Accessible* area = mChildren.SafeElementAt(idx);
    if (!area || area->GetContent() != areaContent) {
      nsRefPtr<Accessible> area = new HTMLAreaAccessible(areaContent, mDoc);
      mDoc->BindToDocument(area, aria::GetRoleMap(areaContent));

      if (!InsertChildAt(idx, area)) {
        mDoc->UnbindFromDocument(area);
        break;
      }

      if (aDoFireEvents) {
        nsRefPtr<AccShowEvent> event = new AccShowEvent(area, areaContent);
        mDoc->FireDelayedEvent(event);
        reorderEvent->AddSubMutationEvent(event);
      }

      treeChanged = true;
    }
  }

  // Fire reorder event if needed.
  if (treeChanged && aDoFireEvents)
    mDoc->FireDelayedEvent(reorderEvent);

  if (!treeChanged)
    mut.mInvalidationRequired = false;
}
Beispiel #29
0
void
FocusManager::ProcessFocusEvent(AccEvent* aEvent)
{
  NS_PRECONDITION(aEvent->GetEventType() == nsIAccessibleEvent::EVENT_FOCUS,
                  "Focus event is expected!");

  // Emit focus event if event target is the active item. Otherwise then check
  // if it's still focused and then update active item and emit focus event.
  Accessible* target = aEvent->GetAccessible();
  if (target != mActiveItem) {

    // Check if still focused. Otherwise we can end up with storing the active
    // item for control that isn't focused anymore.
    DocAccessible* document = aEvent->GetDocAccessible();
    nsINode* focusedNode = FocusedDOMNode();
    if (!focusedNode)
      return;

    Accessible* DOMFocus =
      document->GetAccessibleEvenIfNotInMapOrContainer(focusedNode);
    if (target != DOMFocus)
      return;

    Accessible* activeItem = target->CurrentItem();
    if (activeItem) {
      mActiveItem = activeItem;
      target = activeItem;
    }
  }

  // Fire menu start/end events for ARIA menus.
  if (target->IsARIARole(nsGkAtoms::menuitem)) {
    // The focus was moved into menu.
    bool tryOwnsParent = true;
    Accessible* ARIAMenubar = nullptr;
    Accessible* child = target;
    Accessible* parent = child->Parent();
    while (parent) {
      nsRoleMapEntry* roleMap = parent->ARIARoleMap();
      if (roleMap) {
        if (roleMap->Is(nsGkAtoms::menubar)) {
          ARIAMenubar = parent;
          break;
        }

        // Go up in the parent chain of the menu hierarchy.
        if (roleMap->Is(nsGkAtoms::menuitem) || roleMap->Is(nsGkAtoms::menu)) {
          child = parent;
          parent = child->Parent();
          tryOwnsParent = true;
          continue;
        }
      }

      // If no required context role then check aria-owns relation.
      if (!tryOwnsParent)
        break;

      RelatedAccIterator iter(child->Document(), child->GetContent(),
                              nsGkAtoms::aria_owns);
      parent = iter.Next();
      tryOwnsParent = false;
    }

    if (ARIAMenubar != mActiveARIAMenubar) {
      // Leaving ARIA menu. Fire menu_end event on current menubar.
      if (mActiveARIAMenubar) {
        nsRefPtr<AccEvent> menuEndEvent =
          new AccEvent(nsIAccessibleEvent::EVENT_MENU_END, mActiveARIAMenubar,
                       aEvent->FromUserInput());
        nsEventShell::FireEvent(menuEndEvent);
      }

      mActiveARIAMenubar = ARIAMenubar;

      // Entering ARIA menu. Fire menu_start event.
      if (mActiveARIAMenubar) {
        nsRefPtr<AccEvent> menuStartEvent =
          new AccEvent(nsIAccessibleEvent::EVENT_MENU_START,
                       mActiveARIAMenubar, aEvent->FromUserInput());
        nsEventShell::FireEvent(menuStartEvent);
      }
    }
  } else if (mActiveARIAMenubar) {
    // Focus left a menu. Fire menu_end event.
    nsRefPtr<AccEvent> menuEndEvent =
      new AccEvent(nsIAccessibleEvent::EVENT_MENU_END, mActiveARIAMenubar,
                   aEvent->FromUserInput());
    nsEventShell::FireEvent(menuEndEvent);

    mActiveARIAMenubar = nullptr;
  }

#ifdef A11Y_LOG
  if (logging::IsEnabled(logging::eFocus))
    logging::FocusNotificationTarget("fire focus event", "Target", target);
#endif

  nsRefPtr<AccEvent> focusEvent =
    new AccEvent(nsIAccessibleEvent::EVENT_FOCUS, target, aEvent->FromUserInput());
  nsEventShell::FireEvent(focusEvent);

  // Fire scrolling_start event when the document receives the focus if it has
  // an anchor jump. If an accessible within the document receive the focus
  // then null out the anchor jump because it no longer applies.
  DocAccessible* targetDocument = target->Document();
  Accessible* anchorJump = targetDocument->AnchorJump();
  if (anchorJump) {
    if (target == targetDocument) {
      // XXX: bug 625699, note in some cases the node could go away before we
      // we receive focus event, for example if the node is removed from DOM.
      nsEventShell::FireEvent(nsIAccessibleEvent::EVENT_SCROLLING_START,
                              anchorJump, aEvent->FromUserInput());
    }
    targetDocument->SetAnchorJump(nullptr);
  }
}