PRUint64 HTMLSelectOptionAccessible::NativeState() { // As a HTMLSelectOptionAccessible we can have the following states: // SELECTABLE, SELECTED, FOCUSED, FOCUSABLE, OFFSCREEN // Upcall to Accessible, but skip HyperTextAccessible impl // because we don't want EDITABLE or SELECTABLE_TEXT PRUint64 state = Accessible::NativeState(); Accessible* select = GetSelect(); if (!select) return state; PRUint64 selectState = select->State(); if (selectState & states::INVISIBLE) return state; // Are we selected? bool isSelected = false; nsCOMPtr<nsIDOMHTMLOptionElement> option(do_QueryInterface(mContent)); if (option) { option->GetSelected(&isSelected); if (isSelected) state |= states::SELECTED; } if (selectState & states::OFFSCREEN) { state |= states::OFFSCREEN; } else if (selectState & states::COLLAPSED) { // <select> is COLLAPSED: add OFFSCREEN, if not the currently // visible option if (!isSelected) { state |= states::OFFSCREEN; } else { // Clear offscreen and invisible for currently showing option state &= ~(states::OFFSCREEN | states::INVISIBLE); state |= selectState & states::OPAQUE1; } } else { // XXX list frames are weird, don't rely on Accessible's general // visibility implementation unless they get reimplemented in layout state &= ~states::OFFSCREEN; // <select> is not collapsed: compare bounds to calculate OFFSCREEN Accessible* listAcc = Parent(); if (listAcc) { PRInt32 optionX, optionY, optionWidth, optionHeight; PRInt32 listX, listY, listWidth, listHeight; GetBounds(&optionX, &optionY, &optionWidth, &optionHeight); listAcc->GetBounds(&listX, &listY, &listWidth, &listHeight); if (optionY < listY || optionY + optionHeight > listY + listHeight) { state |= states::OFFSCREEN; } } } return state; }
NS_IMETHODIMP nsAccessiblePivot::MoveToPoint(nsIAccessibleTraversalRule* aRule, int32_t aX, int32_t aY, bool aIgnoreNoMatch, bool aIsFromUserInput, uint8_t aArgc, bool* aResult) { NS_ENSURE_ARG_POINTER(aResult); NS_ENSURE_ARG_POINTER(aRule); *aResult = false; Accessible* root = GetActiveRoot(); NS_ENSURE_TRUE(root && !root->IsDefunct(), NS_ERROR_NOT_IN_TREE); RuleCache cache(aRule); Accessible* match = nullptr; Accessible* child = root->ChildAtPoint(aX, aY, Accessible::eDeepestChild); while (child && root != child) { uint16_t filtered = nsIAccessibleTraversalRule::FILTER_IGNORE; nsresult rv = cache.ApplyFilter(child, &filtered); NS_ENSURE_SUCCESS(rv, rv); // Ignore any matching nodes that were below this one if (filtered & nsIAccessibleTraversalRule::FILTER_IGNORE_SUBTREE) match = nullptr; // Match if no node below this is a match if ((filtered & nsIAccessibleTraversalRule::FILTER_MATCH) && !match) { int32_t childX, childY, childWidth, childHeight; child->GetBounds(&childX, &childY, &childWidth, &childHeight); // Double-check child's bounds since the deepest child may have been out // of bounds. This assures we don't return a false positive. if (aX >= childX && aX < childX + childWidth && aY >= childY && aY < childY + childHeight) match = child; } child = child->Parent(); } if (match || !aIgnoreNoMatch) *aResult = MovePivotInternal(match, nsIAccessiblePivot::REASON_POINT, (aArgc > 0) ? aIsFromUserInput : true); return NS_OK; }