gecko-dev/accessible/xul/XULFormControlAccessible.cpp
Gabriele Svelto 69790bc62e Bug 1600545 - Remove useless inclusions of header files generated from IDL files in accessible/, browser/, caps/, chrome/, devtools/, docshell/, editor/, extensions/, gfx/, hal/, image/, intl/, ipc/, js/, layout/, and media/ r=Ehsan
The inclusions were removed with the following very crude script and the
resulting breakage was fixed up by hand. The manual fixups did either
revert the changes done by the script, replace a generic header with a more
specific one or replace a header with a forward declaration.

find . -name "*.idl" | grep -v web-platform | grep -v third_party | while read path; do
    interfaces=$(grep "^\(class\|interface\).*:.*" "$path" | cut -d' ' -f2)
    if [ -n "$interfaces" ]; then
        if [[ "$interfaces" == *$'\n'* ]]; then
          regexp="\("
          for i in $interfaces; do regexp="$regexp$i\|"; done
          regexp="${regexp%%\\\|}\)"
        else
          regexp="$interfaces"
        fi
        interface=$(basename "$path")
        rg -l "#include.*${interface%%.idl}.h" . | while read path2; do
            hits=$(grep -v "#include.*${interface%%.idl}.h" "$path2" | grep -c "$regexp" )
            if [ $hits -eq 0 ]; then
                echo "Removing ${interface} from ${path2}"
                grep -v "#include.*${interface%%.idl}.h" "$path2" > "$path2".tmp
                mv -f "$path2".tmp "$path2"
            fi
        done
    fi
done

Differential Revision: https://phabricator.services.mozilla.com/D55443

--HG--
extra : moz-landing-system : lando
2019-12-06 09:16:44 +00:00

440 lines
15 KiB
C++

/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "XULFormControlAccessible.h"
#include "Accessible-inl.h"
#include "HTMLFormControlAccessible.h"
#include "nsAccUtils.h"
#include "DocAccessible.h"
#include "Relation.h"
#include "Role.h"
#include "States.h"
#include "TreeWalker.h"
#include "XULMenuAccessible.h"
#include "nsIDOMXULButtonElement.h"
#include "nsIDOMXULMenuListElement.h"
#include "nsIDOMXULRadioGroupElement.h"
#include "nsIDOMXULSelectCntrlItemEl.h"
#include "nsIFrame.h"
#include "nsITextControlFrame.h"
#include "nsMenuPopupFrame.h"
#include "nsNameSpaceManager.h"
#include "mozilla/dom/Element.h"
using namespace mozilla::a11y;
////////////////////////////////////////////////////////////////////////////////
// XULButtonAccessible
////////////////////////////////////////////////////////////////////////////////
XULButtonAccessible::XULButtonAccessible(nsIContent* aContent,
DocAccessible* aDoc)
: AccessibleWrap(aContent, aDoc) {
if (ContainsMenu()) {
mGenericTypes |= eMenuButton;
} else {
mGenericTypes |= eButton;
}
}
XULButtonAccessible::~XULButtonAccessible() {}
////////////////////////////////////////////////////////////////////////////////
// XULButtonAccessible: nsISupports
////////////////////////////////////////////////////////////////////////////////
// XULButtonAccessible: nsIAccessible
uint8_t XULButtonAccessible::ActionCount() const { return 1; }
void XULButtonAccessible::ActionNameAt(uint8_t aIndex, nsAString& aName) {
if (aIndex == eAction_Click) aName.AssignLiteral("press");
}
bool XULButtonAccessible::DoAction(uint8_t aIndex) const {
if (aIndex != 0) return false;
DoCommand();
return true;
}
////////////////////////////////////////////////////////////////////////////////
// XULButtonAccessible: Accessible
role XULButtonAccessible::NativeRole() const { return roles::PUSHBUTTON; }
uint64_t XULButtonAccessible::NativeState() const {
// Possible states: focused, focusable, unavailable(disabled).
// get focus and disable status from base class
uint64_t state = Accessible::NativeState();
// Buttons can be checked -- they simply appear pressed in rather than checked
nsCOMPtr<nsIDOMXULButtonElement> xulButtonElement = Elm()->AsXULButton();
if (xulButtonElement) {
nsAutoString type;
xulButtonElement->GetType(type);
if (type.EqualsLiteral("checkbox") || type.EqualsLiteral("radio")) {
state |= states::CHECKABLE;
}
// Some buttons can have their checked state set without being of type
// checkbox or radio. Expose the pressed state unconditionally.
bool checked = false;
xulButtonElement->GetChecked(&checked);
if (checked) {
state |= states::PRESSED;
}
}
if (ContainsMenu()) state |= states::HASPOPUP;
if (mContent->AsElement()->HasAttr(kNameSpaceID_None, nsGkAtoms::_default))
state |= states::DEFAULT;
return state;
}
////////////////////////////////////////////////////////////////////////////////
// XULButtonAccessible: Widgets
bool XULButtonAccessible::IsWidget() const { return true; }
bool XULButtonAccessible::IsActiveWidget() const {
return FocusMgr()->HasDOMFocus(mContent);
}
bool XULButtonAccessible::AreItemsOperable() const {
if (IsMenuButton()) {
Accessible* menuPopup = mChildren.SafeElementAt(0, nullptr);
if (menuPopup) {
nsMenuPopupFrame* menuPopupFrame = do_QueryFrame(menuPopup->GetFrame());
return menuPopupFrame->IsOpen();
}
}
return false; // no items
}
Accessible* XULButtonAccessible::ContainerWidget() const {
if (IsMenuButton() && mParent && mParent->IsAutoComplete()) return mParent;
return nullptr;
}
bool XULButtonAccessible::IsAcceptableChild(nsIContent* aEl) const {
// In general XUL button has not accessible children. Nevertheless menu
// buttons can have popup accessibles (@type="menu" or columnpicker).
return aEl->IsXULElement(nsGkAtoms::menupopup) ||
aEl->IsXULElement(nsGkAtoms::popup);
}
////////////////////////////////////////////////////////////////////////////////
// XULButtonAccessible protected
bool XULButtonAccessible::ContainsMenu() const {
return mContent->AsElement()->AttrValueIs(kNameSpaceID_None, nsGkAtoms::type,
nsGkAtoms::menu, eCaseMatters);
}
////////////////////////////////////////////////////////////////////////////////
// XULDropmarkerAccessible
////////////////////////////////////////////////////////////////////////////////
XULDropmarkerAccessible::XULDropmarkerAccessible(nsIContent* aContent,
DocAccessible* aDoc)
: LeafAccessible(aContent, aDoc) {}
uint8_t XULDropmarkerAccessible::ActionCount() const { return 1; }
bool XULDropmarkerAccessible::DropmarkerOpen(bool aToggleOpen) const {
bool isOpen = false;
nsIContent* parent = mContent->GetFlattenedTreeParent();
while (parent) {
nsCOMPtr<nsIDOMXULButtonElement> parentButtonElement =
parent->AsElement()->AsXULButton();
if (parentButtonElement) {
parentButtonElement->GetOpen(&isOpen);
if (aToggleOpen) parentButtonElement->SetOpen(!isOpen);
return isOpen;
}
nsCOMPtr<nsIDOMXULMenuListElement> parentMenuListElement =
parent->AsElement()->AsXULMenuList();
if (parentMenuListElement) {
parentMenuListElement->GetOpen(&isOpen);
if (aToggleOpen) parentMenuListElement->SetOpen(!isOpen);
return isOpen;
}
parent = parent->GetFlattenedTreeParent();
}
return isOpen;
}
void XULDropmarkerAccessible::ActionNameAt(uint8_t aIndex, nsAString& aName) {
aName.Truncate();
if (aIndex == eAction_Click) {
if (DropmarkerOpen(false))
aName.AssignLiteral("close");
else
aName.AssignLiteral("open");
}
}
bool XULDropmarkerAccessible::DoAction(uint8_t index) const {
if (index == eAction_Click) {
DropmarkerOpen(true); // Reverse the open attribute
return true;
}
return false;
}
role XULDropmarkerAccessible::NativeRole() const { return roles::PUSHBUTTON; }
uint64_t XULDropmarkerAccessible::NativeState() const {
return DropmarkerOpen(false) ? states::PRESSED : 0;
}
////////////////////////////////////////////////////////////////////////////////
// XULGroupboxAccessible
////////////////////////////////////////////////////////////////////////////////
XULGroupboxAccessible::XULGroupboxAccessible(nsIContent* aContent,
DocAccessible* aDoc)
: AccessibleWrap(aContent, aDoc) {}
role XULGroupboxAccessible::NativeRole() const { return roles::GROUPING; }
ENameValueFlag XULGroupboxAccessible::NativeName(nsString& aName) const {
// XXX: we use the first related accessible only.
Accessible* label = RelationByType(RelationType::LABELLED_BY).Next();
if (label) return label->Name(aName);
return eNameOK;
}
Relation XULGroupboxAccessible::RelationByType(RelationType aType) const {
Relation rel = AccessibleWrap::RelationByType(aType);
// The label for xul:groupbox is generated from the first xul:label
if (aType == RelationType::LABELLED_BY && ChildCount() > 0) {
Accessible* childAcc = GetChildAt(0);
if (childAcc->Role() == roles::LABEL &&
childAcc->GetContent()->IsXULElement(nsGkAtoms::label)) {
rel.AppendTarget(childAcc);
}
}
return rel;
}
////////////////////////////////////////////////////////////////////////////////
// XULRadioButtonAccessible
////////////////////////////////////////////////////////////////////////////////
XULRadioButtonAccessible::XULRadioButtonAccessible(nsIContent* aContent,
DocAccessible* aDoc)
: RadioButtonAccessible(aContent, aDoc) {}
uint64_t XULRadioButtonAccessible::NativeState() const {
uint64_t state = LeafAccessible::NativeState();
state |= states::CHECKABLE;
nsCOMPtr<nsIDOMXULSelectControlItemElement> radioButton =
Elm()->AsXULSelectControlItem();
if (radioButton) {
bool selected = false; // Radio buttons can be selected
radioButton->GetSelected(&selected);
if (selected) {
state |= states::CHECKED;
}
}
return state;
}
uint64_t XULRadioButtonAccessible::NativeInteractiveState() const {
return NativelyUnavailable() ? states::UNAVAILABLE : states::FOCUSABLE;
}
////////////////////////////////////////////////////////////////////////////////
// XULRadioButtonAccessible: Widgets
Accessible* XULRadioButtonAccessible::ContainerWidget() const {
return mParent;
}
////////////////////////////////////////////////////////////////////////////////
// XULRadioGroupAccessible
////////////////////////////////////////////////////////////////////////////////
/**
* XUL Radio Group
* The Radio Group proxies for the Radio Buttons themselves. The Group gets
* focus whereas the Buttons do not. So we only have an accessible object for
* this for the purpose of getting the proper RadioButton. Need this here to
* avoid circular reference problems when navigating the accessible tree and
* for getting to the radiobuttons.
*/
XULRadioGroupAccessible::XULRadioGroupAccessible(nsIContent* aContent,
DocAccessible* aDoc)
: XULSelectControlAccessible(aContent, aDoc) {}
role XULRadioGroupAccessible::NativeRole() const { return roles::RADIO_GROUP; }
uint64_t XULRadioGroupAccessible::NativeInteractiveState() const {
// The radio group is not focusable. Sometimes the focus controller will
// report that it is focused. That means that the actual selected radio button
// should be considered focused.
return NativelyUnavailable() ? states::UNAVAILABLE : 0;
}
////////////////////////////////////////////////////////////////////////////////
// XULRadioGroupAccessible: Widgets
bool XULRadioGroupAccessible::IsWidget() const { return true; }
bool XULRadioGroupAccessible::IsActiveWidget() const {
return FocusMgr()->HasDOMFocus(mContent);
}
bool XULRadioGroupAccessible::AreItemsOperable() const { return true; }
Accessible* XULRadioGroupAccessible::CurrentItem() const {
if (!mSelectControl) {
return nullptr;
}
RefPtr<dom::Element> currentItemElm;
nsCOMPtr<nsIDOMXULRadioGroupElement> group =
mSelectControl->AsXULRadioGroup();
if (group) {
group->GetFocusedItem(getter_AddRefs(currentItemElm));
}
if (currentItemElm) {
DocAccessible* document = Document();
if (document) {
return document->GetAccessible(currentItemElm);
}
}
return nullptr;
}
void XULRadioGroupAccessible::SetCurrentItem(const Accessible* aItem) {
if (!mSelectControl) {
return;
}
nsCOMPtr<dom::Element> itemElm = aItem->Elm();
nsCOMPtr<nsIDOMXULRadioGroupElement> group =
mSelectControl->AsXULRadioGroup();
if (group) {
group->SetFocusedItem(itemElm);
}
}
////////////////////////////////////////////////////////////////////////////////
// XULStatusBarAccessible
////////////////////////////////////////////////////////////////////////////////
XULStatusBarAccessible::XULStatusBarAccessible(nsIContent* aContent,
DocAccessible* aDoc)
: AccessibleWrap(aContent, aDoc) {}
role XULStatusBarAccessible::NativeRole() const { return roles::STATUSBAR; }
////////////////////////////////////////////////////////////////////////////////
// XULToolbarButtonAccessible
////////////////////////////////////////////////////////////////////////////////
XULToolbarButtonAccessible::XULToolbarButtonAccessible(nsIContent* aContent,
DocAccessible* aDoc)
: XULButtonAccessible(aContent, aDoc) {}
void XULToolbarButtonAccessible::GetPositionAndSizeInternal(int32_t* aPosInSet,
int32_t* aSetSize) {
int32_t setSize = 0;
int32_t posInSet = 0;
Accessible* parent = Parent();
if (!parent) return;
uint32_t childCount = parent->ChildCount();
for (uint32_t childIdx = 0; childIdx < childCount; childIdx++) {
Accessible* child = parent->GetChildAt(childIdx);
if (IsSeparator(child)) { // end of a group of buttons
if (posInSet) break; // we've found our group, so we're done
setSize = 0; // not our group, so start a new group
} else {
setSize++; // another button in the group
if (child == this) posInSet = setSize; // we've found our button
}
}
*aPosInSet = posInSet;
*aSetSize = setSize;
}
bool XULToolbarButtonAccessible::IsSeparator(Accessible* aAccessible) {
nsIContent* content = aAccessible->GetContent();
return content && content->IsAnyOfXULElements(nsGkAtoms::toolbarseparator,
nsGkAtoms::toolbarspacer,
nsGkAtoms::toolbarspring);
}
////////////////////////////////////////////////////////////////////////////////
// XULToolbarButtonAccessible: Widgets
bool XULToolbarButtonAccessible::IsAcceptableChild(nsIContent* aEl) const {
// In general XUL button has not accessible children. Nevertheless menu
// buttons can have popup accessibles (@type="menu" or columnpicker).
// Also: Toolbar buttons can have labels as children.
// But only if the label attribute is not present.
return aEl->IsXULElement(nsGkAtoms::menupopup) ||
aEl->IsXULElement(nsGkAtoms::popup) ||
(aEl->IsXULElement(nsGkAtoms::label) &&
!mContent->AsElement()->HasAttr(kNameSpaceID_None, nsGkAtoms::label));
}
////////////////////////////////////////////////////////////////////////////////
// XULToolbarAccessible
////////////////////////////////////////////////////////////////////////////////
XULToolbarAccessible::XULToolbarAccessible(nsIContent* aContent,
DocAccessible* aDoc)
: AccessibleWrap(aContent, aDoc) {}
role XULToolbarAccessible::NativeRole() const { return roles::TOOLBAR; }
ENameValueFlag XULToolbarAccessible::NativeName(nsString& aName) const {
if (mContent->AsElement()->GetAttr(kNameSpaceID_None, nsGkAtoms::toolbarname,
aName))
aName.CompressWhitespace();
return eNameOK;
}
////////////////////////////////////////////////////////////////////////////////
// XULToolbarAccessible
////////////////////////////////////////////////////////////////////////////////
XULToolbarSeparatorAccessible::XULToolbarSeparatorAccessible(
nsIContent* aContent, DocAccessible* aDoc)
: LeafAccessible(aContent, aDoc) {}
role XULToolbarSeparatorAccessible::NativeRole() const {
return roles::SEPARATOR;
}
uint64_t XULToolbarSeparatorAccessible::NativeState() const { return 0; }