Anforderungen  |   Konzepte  |   Entwurf  |   Entwicklung  |   Qualitätssicherung  |   Lebenszyklus  |   Steuerung
 
 
 
 


Quelle  RotorRules.mm   Sprache: unbekannt

 
/* clang-format off */
/* -*- Mode: Objective-C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* clang-format on */
/* 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/. */

#import "RotorRules.h"

#include "nsCocoaUtils.h"
#include "DocAccessibleParent.h"
#include "nsIAccessiblePivot.h"
#include "nsAccUtils.h"

#include "nsAccessibilityService.h"

using namespace mozilla;
using namespace mozilla::a11y;

// Generic Rotor Rule

RotorRule::RotorRule(Accessible* aDirectDescendantsFrom,
                     const nsString& aSearchText)
    : mDirectDescendantsFrom(aDirectDescendantsFrom),
      mSearchText(aSearchText) {}

RotorRule::RotorRule(const nsString& aSearchText)
    : mDirectDescendantsFrom(nullptr), mSearchText(aSearchText) {}

uint16_t RotorRule::Match(Accessible* aAcc) {
  uint16_t result = nsIAccessibleTraversalRule::FILTER_IGNORE;

  if (nsAccUtils::MustPrune(aAcc)) {
    result |= nsIAccessibleTraversalRule::FILTER_IGNORE_SUBTREE;
  }

  if (mDirectDescendantsFrom && (aAcc != mDirectDescendantsFrom)) {
    result |= nsIAccessibleTraversalRule::FILTER_IGNORE_SUBTREE;
  }

  if ([GetNativeFromGeckoAccessible(aAcc) isAccessibilityElement]) {
    result |= nsIAccessibleTraversalRule::FILTER_MATCH;
  }

  if ((result & nsIAccessibleTraversalRule::FILTER_MATCH) &&
      !mSearchText.IsEmpty()) {
    // If we have a non-empty search text, there are some roles
    // we can safely ignore.
    switch (aAcc->Role()) {
      case roles::LANDMARK:
      case roles::COMBOBOX:
      case roles::LISTITEM:
      case roles::COMBOBOX_LIST:
      case roles::MENUBAR:
      case roles::MENUPOPUP:
      case roles::DOCUMENT:
      case roles::APPLICATION:
        // XXX: These roles either have AXTitle/AXDescription overridden as
        // empty, or should never be returned in search text results. This
        // should be better mapped somewhere.
        result &= ~nsIAccessibleTraversalRule::FILTER_MATCH;
        break;
      default:
        nsAutoString name;
        aAcc->Name(name);
        if (!CaseInsensitiveFindInReadable(mSearchText, name)) {
          result &= ~nsIAccessibleTraversalRule::FILTER_MATCH;
        }
        break;
    }
  }

  return result;
}

// Rotor Role Rule

RotorRoleRule::RotorRoleRule(role aRole, Accessible* aDirectDescendantsFrom,
                             const nsString& aSearchText)
    : RotorRule(aDirectDescendantsFrom, aSearchText), mRole(aRole) {};

RotorRoleRule::RotorRoleRule(role aRole, const nsString& aSearchText)
    : RotorRule(aSearchText), mRole(aRole) {};

uint16_t RotorRoleRule::Match(Accessible* aAcc) {
  uint16_t result = RotorRule::Match(aAcc);

  // if a match was found in the base-class's Match function,
  // it is valid to consider that match again here. if it is
  // not of the desired role, we flip the match bit to "unmatch"
  // otherwise, the match persists.
  if ((result & nsIAccessibleTraversalRule::FILTER_MATCH) &&
      aAcc->Role() != mRole) {
    result &= ~nsIAccessibleTraversalRule::FILTER_MATCH;
  }

  return result;
}

// Rotor Mac Role Rule

RotorMacRoleRule::RotorMacRoleRule(NSString* aMacRole,
                                   Accessible* aDirectDescendantsFrom,
                                   const nsString& aSearchText)
    : RotorRule(aDirectDescendantsFrom, aSearchText), mMacRole(aMacRole) {
  [mMacRole retain];
};

RotorMacRoleRule::RotorMacRoleRule(NSString* aMacRole,
                                   const nsString& aSearchText)
    : RotorRule(aSearchText), mMacRole(aMacRole) {
  [mMacRole retain];
};

RotorMacRoleRule::~RotorMacRoleRule() { [mMacRole release]; }

uint16_t RotorMacRoleRule::Match(Accessible* aAcc) {
  uint16_t result = RotorRule::Match(aAcc);

  // if a match was found in the base-class's Match function,
  // it is valid to consider that match again here. if it is
  // not of the desired role, we flip the match bit to "unmatch"
  // otherwise, the match persists.
  if ((result & nsIAccessibleTraversalRule::FILTER_MATCH)) {
    mozAccessible* nativeMatch = GetNativeFromGeckoAccessible(aAcc);
    if (![[nativeMatch moxRole] isEqualToString:mMacRole]) {
      result &= ~nsIAccessibleTraversalRule::FILTER_MATCH;
    }
  }

  return result;
}

// Rotor Control Rule

RotorControlRule::RotorControlRule(Accessible* aDirectDescendantsFrom,
                                   const nsString& aSearchText)
    : RotorRule(aDirectDescendantsFrom, aSearchText) {};

RotorControlRule::RotorControlRule(const nsString& aSearchText)
    : RotorRule(aSearchText) {};

uint16_t RotorControlRule::Match(Accessible* aAcc) {
  uint16_t result = RotorRule::Match(aAcc);

  // if a match was found in the base-class's Match function,
  // it is valid to consider that match again here. if it is
  // not of the desired role, we flip the match bit to "unmatch"
  // otherwise, the match persists.
  if ((result & nsIAccessibleTraversalRule::FILTER_MATCH)) {
    switch (aAcc->Role()) {
      case roles::PUSHBUTTON:
      case roles::SPINBUTTON:
      case roles::DETAILS:
      case roles::CHECKBUTTON:
      case roles::LISTBOX:
      case roles::COMBOBOX:
      case roles::EDITCOMBOBOX:
      case roles::RADIOBUTTON:
      case roles::RADIO_GROUP:
      case roles::PAGETAB:
      case roles::SLIDER:
      case roles::SWITCH:
      case roles::ENTRY:
      case roles::OUTLINE:
      case roles::PASSWORD_TEXT:
      case roles::BUTTONMENU:
        return result;

      case roles::DATE_EDITOR:
      case roles::TIME_EDITOR:
        result |= nsIAccessibleTraversalRule::FILTER_IGNORE_SUBTREE;
        return result;

      case roles::GROUPING: {
        // Groupings are sometimes used (like radio groups) to denote
        // sets of controls. If that's the case, we want to surface
        // them. We also want to surface grouped time and date controls.
        for (unsigned int i = 0; i < aAcc->ChildCount(); i++) {
          Accessible* currChild = aAcc->ChildAt(i);
          if (currChild->Role() == roles::CHECKBUTTON ||
              currChild->Role() == roles::SWITCH ||
              currChild->Role() == roles::SPINBUTTON ||
              currChild->Role() == roles::RADIOBUTTON) {
            return result;
          }
        }

        // if we iterated through the groups children and didn't
        // find a control with one of the roles above, we should
        // ignore this grouping
        result &= ~nsIAccessibleTraversalRule::FILTER_MATCH;
        return result;
      }

      default:
        // if we did not match on any above role, we should
        // ignore this accessible.
        result &= ~nsIAccessibleTraversalRule::FILTER_MATCH;
    }
  }

  return result;
}

// Rotor TextEntry Rule

RotorTextEntryRule::RotorTextEntryRule(Accessible* aDirectDescendantsFrom,
                                       const nsString& aSearchText)
    : RotorRule(aDirectDescendantsFrom, aSearchText) {};

RotorTextEntryRule::RotorTextEntryRule(const nsString& aSearchText)
    : RotorRule(aSearchText) {};

uint16_t RotorTextEntryRule::Match(Accessible* aAcc) {
  uint16_t result = RotorRule::Match(aAcc);

  // if a match was found in the base-class's Match function,
  // it is valid to consider that match again here. if it is
  // not of the desired role, we flip the match bit to "unmatch"
  // otherwise, the match persists.
  if ((result & nsIAccessibleTraversalRule::FILTER_MATCH)) {
    if (aAcc->Role() != roles::PASSWORD_TEXT && aAcc->Role() != roles::ENTRY) {
      result &= ~nsIAccessibleTraversalRule::FILTER_MATCH;
    }
  }

  return result;
}

// Rotor Link Rule

RotorLinkRule::RotorLinkRule(Accessible* aDirectDescendantsFrom,
                             const nsString& aSearchText)
    : RotorRule(aDirectDescendantsFrom, aSearchText) {};

RotorLinkRule::RotorLinkRule(const nsString& aSearchText)
    : RotorRule(aSearchText) {};

uint16_t RotorLinkRule::Match(Accessible* aAcc) {
  uint16_t result = RotorRule::Match(aAcc);

  // if a match was found in the base-class's Match function,
  // it is valid to consider that match again here. if it is
  // not of the desired role, we flip the match bit to "unmatch"
  // otherwise, the match persists.
  if ((result & nsIAccessibleTraversalRule::FILTER_MATCH)) {
    mozAccessible* nativeMatch = GetNativeFromGeckoAccessible(aAcc);
    if (![[nativeMatch moxRole] isEqualToString:@"AXLink"]) {
      result &= ~nsIAccessibleTraversalRule::FILTER_MATCH;
    }
  }

  return result;
}

RotorVisitedLinkRule::RotorVisitedLinkRule(const nsString& aSearchText)
    : RotorLinkRule(aSearchText) {}

RotorVisitedLinkRule::RotorVisitedLinkRule(Accessible* aDirectDescendantsFrom,
                                           const nsString& aSearchText)
    : RotorLinkRule(aDirectDescendantsFrom, aSearchText) {}

uint16_t RotorVisitedLinkRule::Match(Accessible* aAcc) {
  uint16_t result = RotorLinkRule::Match(aAcc);

  if (result & nsIAccessibleTraversalRule::FILTER_MATCH) {
    mozAccessible* nativeMatch = GetNativeFromGeckoAccessible(aAcc);
    if (![[nativeMatch moxVisited] boolValue]) {
      result &= ~nsIAccessibleTraversalRule::FILTER_MATCH;
    }
  }

  return result;
}

RotorUnvisitedLinkRule::RotorUnvisitedLinkRule(const nsString& aSearchText)
    : RotorLinkRule(aSearchText) {}

RotorUnvisitedLinkRule::RotorUnvisitedLinkRule(
    Accessible* aDirectDescendantsFrom, const nsString& aSearchText)
    : RotorLinkRule(aDirectDescendantsFrom, aSearchText) {}

uint16_t RotorUnvisitedLinkRule::Match(Accessible* aAcc) {
  uint16_t result = RotorLinkRule::Match(aAcc);

  if (result & nsIAccessibleTraversalRule::FILTER_MATCH) {
    mozAccessible* nativeMatch = GetNativeFromGeckoAccessible(aAcc);
    if ([[nativeMatch moxVisited] boolValue]) {
      result &= ~nsIAccessibleTraversalRule::FILTER_MATCH;
    }
  }

  return result;
}

// Match Not Rule

RotorNotMacRoleRule::RotorNotMacRoleRule(NSString* aMacRole,
                                         Accessible* aDirectDescendantsFrom,
                                         const nsString& aSearchText)
    : RotorMacRoleRule(aMacRole, aDirectDescendantsFrom, aSearchText) {}

RotorNotMacRoleRule::RotorNotMacRoleRule(NSString* aMacRole,
                                         const nsString& aSearchText)
    : RotorMacRoleRule(aMacRole, aSearchText) {}

uint16_t RotorNotMacRoleRule::Match(Accessible* aAcc) {
  uint16_t result = RotorRule::Match(aAcc);

  // if a match was found in the base-class's Match function,
  // it is valid to consider that match again here. if it is
  // not different from the desired role, we flip the
  // match bit to "unmatch" otherwise, the match persists.
  if ((result & nsIAccessibleTraversalRule::FILTER_MATCH)) {
    mozAccessible* nativeMatch = GetNativeFromGeckoAccessible(aAcc);
    if ([[nativeMatch moxRole] isEqualToString:mMacRole]) {
      result &= ~nsIAccessibleTraversalRule::FILTER_MATCH;
    }
  }
  return result;
}

// Rotor Static Text Rule

RotorStaticTextRule::RotorStaticTextRule(Accessible* aDirectDescendantsFrom,
                                         const nsString& aSearchText)
    : RotorRule(aDirectDescendantsFrom, aSearchText) {};

RotorStaticTextRule::RotorStaticTextRule(const nsString& aSearchText)
    : RotorRule(aSearchText) {};

uint16_t RotorStaticTextRule::Match(Accessible* aAcc) {
  uint16_t result = RotorRule::Match(aAcc);

  // if a match was found in the base-class's Match function,
  // it is valid to consider that match again here. if it is
  // not of the desired role, we flip the match bit to "unmatch"
  // otherwise, the match persists.
  if ((result & nsIAccessibleTraversalRule::FILTER_MATCH)) {
    mozAccessible* nativeMatch = GetNativeFromGeckoAccessible(aAcc);
    if (![[nativeMatch moxRole] isEqualToString:@"AXStaticText"]) {
      result &= ~nsIAccessibleTraversalRule::FILTER_MATCH;
    }
  }

  return result;
}

// Rotor Heading Level Rule

RotorHeadingLevelRule::RotorHeadingLevelRule(int32_t aLevel,
                                             Accessible* aDirectDescendantsFrom,
                                             const nsString& aSearchText)
    : RotorRoleRule(roles::HEADING, aDirectDescendantsFrom, aSearchText),
      mLevel(aLevel) {};

RotorHeadingLevelRule::RotorHeadingLevelRule(int32_t aLevel,
                                             const nsString& aSearchText)
    : RotorRoleRule(roles::HEADING, aSearchText), mLevel(aLevel) {};

uint16_t RotorHeadingLevelRule::Match(Accessible* aAcc) {
  uint16_t result = RotorRoleRule::Match(aAcc);

  // if a match was found in the base-class's Match function,
  // it is valid to consider that match again here. if it is
  // not of the desired heading level, we flip the match bit to
  // "unmatch" otherwise, the match persists.
  if ((result & nsIAccessibleTraversalRule::FILTER_MATCH)) {
    int32_t currLevel = aAcc->GroupPosition().level;

    if (currLevel != mLevel) {
      result &= ~nsIAccessibleTraversalRule::FILTER_MATCH;
    }
  }

  return result;
}

uint16_t RotorLiveRegionRule::Match(Accessible* aAcc) {
  uint16_t result = RotorRule::Match(aAcc);

  if ((result & nsIAccessibleTraversalRule::FILTER_MATCH)) {
    mozAccessible* nativeMatch = GetNativeFromGeckoAccessible(aAcc);
    if (![nativeMatch moxIsLiveRegion]) {
      result &= ~nsIAccessibleTraversalRule::FILTER_MATCH;
    }
  }
  return result;
}

// Rotor Focusable Rule

RotorFocusableRule::RotorFocusableRule(Accessible* aDirectDescendantsFrom,
                                       const nsString& aSearchText)
    : RotorRule(aDirectDescendantsFrom, aSearchText) {};

RotorFocusableRule::RotorFocusableRule(const nsString& aSearchText)
    : RotorRule(aSearchText) {};

uint16_t RotorFocusableRule::Match(Accessible* aAcc) {
  uint16_t result = RotorRule::Match(aAcc);
  // if a match was found in the base-class's Match function,
  // it is valid to consider that match again here. if it is
  // not of the desired role, we flip the match bit to "unmatch"
  // otherwise, the match persists.
  if ((result & nsIAccessibleTraversalRule::FILTER_MATCH)) {
    if ((aAcc->State() & states::FOCUSABLE) == 0 || aAcc->ActionCount() == 0) {
      // If the accessible was not focusable, or it is focusable but does not
      // have an action (eg. an overflow: auto container), don't match.
      result &= ~nsIAccessibleTraversalRule::FILTER_MATCH;
    }
  }

  return result;
}

[ Dauer der Verarbeitung: 0.19 Sekunden  (vorverarbeitet)  ]

                                                                                                                                                                                                                                                                                                                                                                                                     


Neuigkeiten

     Aktuelles
     Motto des Tages

Software

     Produkte
     Quellcodebibliothek

Aktivitäten

     Artikel über Sicherheit
     Anleitung zur Aktivierung von SSL

Muße

     Gedichte
     Musik
     Bilder

Jenseits des Üblichen ....
    

Besucherstatistik

Besucherstatistik

Monitoring

Montastic status badge