# Utilities for obtaining role-related information.
#
# Copyright 2023 Igalia, S.L.
# Author: Joanmarie Diggs <[email protected]>
#
# This library is free software; you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public
# License as published by the Free Software Foundation; either
# version 2.1 of the License, or (at your option) any later version.
#
# This library is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public
# License along with this library; if not, write to the
# Free Software Foundation, Inc., Franklin Street, Fifth Floor,
# Boston MA 02110-1301 USA.
# pylint: disable=wrong-import-position
# pylint: disable=too-many-public-methods
# pylint: disable=too-many-lines
# pylint: disable=too-many-branches
# pylint: disable=too-many-return-statements
# pylint: disable=too-many-statements
# pylint: disable=duplicate-code
"""Utilities for obtaining role-related information."""
__id__ = "$Id$"
__version__ = "$Revision$"
__date__ = "$Date$"
__copyright__ = "Copyright (c) 2023 Igalia, S.L."
__license__ = "LGPL"
from typing import Optional
import gi
gi.require_version("Atspi", "2.0")
from gi.repository import Atspi
from . import debug
from . import object_properties
from .ax_object import AXObject
from .ax_utilities_state import AXUtilitiesState
class AXUtilitiesRole:
"""Utilities for obtaining role-related information."""
@staticmethod
def _get_display_style(obj: Atspi.Accessible) -> str:
attrs = AXObject.get_attributes_dict(obj)
return attrs.get("display", "")
@staticmethod
def _get_tag(obj: Atspi.Accessible) -> Optional[str]:
attrs = AXObject.get_attributes_dict(obj)
return attrs.get("tag")
@staticmethod
def _get_xml_roles(obj: Atspi.Accessible) -> list[str]:
attrs = AXObject.get_attributes_dict(obj)
return attrs.get("xml-roles", "").split()
@staticmethod
def children_are_presentational(
obj: Atspi.Accessible,
role: Optional[Atspi.Role] = None
) -> bool:
"""Returns True if the descendants of obj should be ignored. See ARIA spec."""
# Note: We are deliberately leaving out listbox options because they can be complex,
# both in ARIA and in GTK.
roles = [
Atspi.Role.CHECK_BOX,
Atspi.Role.CHECK_MENU_ITEM,
Atspi.Role.IMAGE,
Atspi.Role.LEVEL_BAR,
Atspi.Role.PAGE_TAB,
Atspi.Role.PROGRESS_BAR,
Atspi.Role.PUSH_BUTTON,
Atspi.Role.RADIO_BUTTON,
Atspi.Role.RADIO_MENU_ITEM,
Atspi.Role.SCROLL_BAR,
Atspi.Role.SEPARATOR,
Atspi.Role.SLIDER,
]
# TODO - JD: Remove this check when dependencies are bumped to v2.56.
try:
roles.append(Atspi.Role.SWITCH)
except AttributeError:
pass
if role is None:
role = AXObject.get_role(obj)
# TODO - JD: The is_switch() call be be removed as part of the removal above.
if role in roles or AXUtilitiesRole.is_switch(obj, role):
tokens = ["AXUtilitiesRole:", obj, "has presentational children."]
debug.print_tokens(debug.LEVEL_INFO, tokens, True)
return True
return False
@staticmethod
def get_dialog_roles(include_alert_as_dialog: bool = True) -> list[Atspi.Role]:
"""Returns the list of roles we consider documents"""
roles = [Atspi.Role.COLOR_CHOOSER,
Atspi.Role.DIALOG,
Atspi.Role.FILE_CHOOSER]
if include_alert_as_dialog:
roles.append(Atspi.Role.ALERT)
return roles
@staticmethod
def get_document_roles() -> list[Atspi.Role]:
"""Returns the list of roles we consider documents"""
roles = [Atspi.Role.DOCUMENT_EMAIL,
Atspi.Role.DOCUMENT_FRAME,
Atspi.Role.DOCUMENT_PRESENTATION,
Atspi.Role.DOCUMENT_SPREADSHEET,
Atspi.Role.DOCUMENT_TEXT,
Atspi.Role.DOCUMENT_WEB]
return roles
@staticmethod
def get_form_field_roles() -> list[Atspi.Role]:
"""Returns the list of roles we consider form fields"""
roles = [Atspi.Role.CHECK_BOX,
Atspi.Role.RADIO_BUTTON,
Atspi.Role.COMBO_BOX,
Atspi.Role.DOCUMENT_FRAME, # rich text editing pred recommended
Atspi.Role.TEXT, # predicate recommended to check it is editable
Atspi.Role.LIST_BOX,
Atspi.Role.ENTRY,
Atspi.Role.PASSWORD_TEXT,
Atspi.Role.PUSH_BUTTON,
Atspi.Role.SPIN_BUTTON,
Atspi.Role.TOGGLE_BUTTON]
return roles
@staticmethod
def get_layout_only_roles() -> list[Atspi.Role]:
"""Returns the list of roles we consider are for layout only"""
roles = [Atspi.Role.AUTOCOMPLETE,
Atspi.Role.FILLER,
Atspi.Role.REDUNDANT_OBJECT,
Atspi.Role.UNKNOWN,
Atspi.Role.SCROLL_PANE,
Atspi.Role.TEAROFF_MENU_ITEM]
return roles
@staticmethod
def get_menu_item_roles() -> list[Atspi.Role]:
"""Returns the list of roles we consider menu items"""
roles = [Atspi.Role.MENU_ITEM,
Atspi.Role.CHECK_MENU_ITEM,
Atspi.Role.RADIO_MENU_ITEM,
Atspi.Role.TEAROFF_MENU_ITEM]
return roles
@staticmethod
def get_menu_related_roles() -> list[Atspi.Role]:
"""Returns the list of roles we consider menu related"""
roles = [Atspi.Role.MENU,
Atspi.Role.MENU_BAR,
Atspi.Role.POPUP_MENU,
Atspi.Role.MENU_ITEM,
Atspi.Role.CHECK_MENU_ITEM,
Atspi.Role.RADIO_MENU_ITEM,
Atspi.Role.TEAROFF_MENU_ITEM]
return roles
@staticmethod
def get_roles_to_exclude_from_clickables_list() -> list[Atspi.Role]:
"""Returns the list of roles we want to exclude from the list of clickables"""
roles = [Atspi.Role.COMBO_BOX,
Atspi.Role.ENTRY,
Atspi.Role.LIST_BOX,
Atspi.Role.MENU,
Atspi.Role.MENU_ITEM,
Atspi.Role.CHECK_MENU_ITEM,
Atspi.Role.RADIO_MENU_ITEM,
Atspi.Role.PAGE_TAB,
Atspi.Role.PAGE_TAB_LIST,
Atspi.Role.PASSWORD_TEXT,
Atspi.Role.PROGRESS_BAR,
Atspi.Role.SLIDER,
Atspi.Role.SPIN_BUTTON,
Atspi.Role.TOOL_BAR,
Atspi.Role.TREE_ITEM,
Atspi.Role.TREE_TABLE,
Atspi.Role.TREE]
return roles
@staticmethod
def get_set_container_roles() -> list[Atspi.Role]:
"""Returns the list of roles we consider a set container"""
roles = [Atspi.Role.LIST,
Atspi.Role.MENU,
Atspi.Role.PAGE_TAB_LIST,
Atspi.Role.TABLE,
Atspi.Role.TREE,
Atspi.Role.TREE_TABLE]
return roles
@staticmethod
def get_table_cell_roles(include_headers: bool = True) -> list[Atspi.Role]:
"""Returns the list of roles we consider table cells"""
roles = [Atspi.Role.TABLE_CELL]
if include_headers:
roles.extend([Atspi.Role.TABLE_COLUMN_HEADER,
Atspi.Role.TABLE_ROW_HEADER,
Atspi.Role.COLUMN_HEADER,
Atspi.Role.ROW_HEADER])
return roles
@staticmethod
def get_table_header_roles() -> list[Atspi.Role]:
"""Returns the list of roles we consider table headers"""
roles = [Atspi.Role.TABLE_COLUMN_HEADER,
Atspi.Role.TABLE_ROW_HEADER,
Atspi.Role.COLUMN_HEADER,
Atspi.Role.ROW_HEADER]
return roles
@staticmethod
def get_table_related_roles(include_caption: bool = False) -> list[Atspi.Role]:
"""Returns the list of roles we consider table related"""
roles = [Atspi.Role.TABLE,
Atspi.Role.TABLE_CELL,
Atspi.Role.TABLE_COLUMN_HEADER,
Atspi.Role.TABLE_ROW_HEADER,
Atspi.Role.COLUMN_HEADER,
Atspi.Role.ROW_HEADER]
if include_caption:
roles.append(Atspi.Role.CAPTION)
return roles
@staticmethod
def get_text_ui_roles() -> list[Atspi.Role]:
"""Returns the list of roles we consider UI that displays static text"""
roles = [Atspi.Role.INFO_BAR,
Atspi.Role.LABEL,
Atspi.Role.PAGE_TAB,
Atspi.Role.STATUS_BAR]
return roles
@staticmethod
def get_tree_related_roles() -> list[Atspi.Role]:
"""Returns the list of roles we consider tree related"""
roles = [Atspi.Role.TREE,
Atspi.Role.TREE_ITEM,
Atspi.Role.TREE_TABLE]
return roles
@staticmethod
def get_widget_roles() -> list[Atspi.Role]:
"""Returns the list of roles we consider widgets"""
roles = [Atspi.Role.CHECK_BOX,
Atspi.Role.COMBO_BOX,
Atspi.Role.ENTRY,
Atspi.Role.LIST_BOX,
Atspi.Role.PASSWORD_TEXT,
Atspi.Role.PUSH_BUTTON,
Atspi.Role.RADIO_BUTTON,
Atspi.Role.SLIDER,
Atspi.Role.SPIN_BUTTON,
Atspi.Role.TEXT, # predicate recommended to check it is editable
Atspi.Role.TOGGLE_BUTTON]
# TODO - JD: Remove this check when dependencies are bumped to v2.56.
try:
roles.append(Atspi.Role.SWITCH)
except AttributeError:
pass
return roles
@staticmethod
def get_localized_role_name(obj: Atspi.Accessible, role: Optional[Atspi.Role] = None) -> str:
"""Returns a string representing the localized role name of obj."""
if role is None:
role = AXObject.get_role(obj)
if AXObject.supports_value(obj):
if AXUtilitiesRole.is_horizontal_slider(obj, role):
return object_properties.ROLE_SLIDER_HORIZONTAL
if AXUtilitiesRole.is_vertical_slider(obj, role):
return object_properties.ROLE_SLIDER_VERTICAL
if AXUtilitiesRole.is_horizontal_scrollbar(obj, role):
return object_properties.ROLE_SCROLL_BAR_HORIZONTAL
if AXUtilitiesRole.is_vertical_scrollbar(obj, role):
return object_properties.ROLE_SCROLL_BAR_VERTICAL
if AXUtilitiesRole.is_horizontal_separator(obj, role):
return object_properties.ROLE_SPLITTER_HORIZONTAL
if AXUtilitiesRole.is_vertical_separator(obj, role):
return object_properties.ROLE_SPLITTER_VERTICAL
if AXUtilitiesRole.is_split_pane(obj, role):
# The splitter has the opposite orientation of the split pane.
if AXObject.has_state(obj, Atspi.StateType.HORIZONTAL):
return object_properties.ROLE_SPLITTER_VERTICAL
if AXObject.has_state(obj, Atspi.StateType.VERTICAL):
return object_properties.ROLE_SPLITTER_HORIZONTAL
if AXUtilitiesRole.is_suggestion(obj, role):
return object_properties.ROLE_CONTENT_SUGGESTION
if AXUtilitiesRole.is_feed(obj, role):
return object_properties.ROLE_FEED
if AXUtilitiesRole.is_figure(obj, role):
return object_properties.ROLE_FIGURE
if AXUtilitiesRole.is_switch(obj, role):
return object_properties.ROLE_SWITCH
if AXUtilitiesRole.is_dpub(obj):
if AXUtilitiesRole.is_landmark(obj, role):
if AXUtilitiesRole.is_dpub_acknowledgments(obj, role):
return object_properties.ROLE_ACKNOWLEDGMENTS
if AXUtilitiesRole.is_dpub_afterword(obj, role):
return object_properties.ROLE_AFTERWORD
if AXUtilitiesRole.is_dpub_appendix(obj, role):
return object_properties.ROLE_APPENDIX
if AXUtilitiesRole.is_dpub_bibliography(obj, role):
return object_properties.ROLE_BIBLIOGRAPHY
if AXUtilitiesRole.is_dpub_chapter(obj, role):
return object_properties.ROLE_CHAPTER
if AXUtilitiesRole.is_dpub_conclusion(obj, role):
return object_properties.ROLE_CONCLUSION
if AXUtilitiesRole.is_dpub_credits(obj, role):
return object_properties.ROLE_CREDITS
if AXUtilitiesRole.is_dpub_endnotes(obj, role):
return object_properties.ROLE_ENDNOTES
if AXUtilitiesRole.is_dpub_epilogue(obj, role):
return object_properties.ROLE_EPILOGUE
if AXUtilitiesRole.is_dpub_errata(obj, role):
return object_properties.ROLE_ERRATA
if AXUtilitiesRole.is_dpub_foreword(obj, role):
return object_properties.ROLE_FOREWORD
if AXUtilitiesRole.is_dpub_glossary(obj, role):
return object_properties.ROLE_GLOSSARY
if AXUtilitiesRole.is_dpub_index(obj, role):
return object_properties.ROLE_INDEX
if AXUtilitiesRole.is_dpub_introduction(obj, role):
return object_properties.ROLE_INTRODUCTION
if AXUtilitiesRole.is_dpub_pagelist(obj, role):
return object_properties.ROLE_PAGELIST
if AXUtilitiesRole.is_dpub_part(obj, role):
return object_properties.ROLE_PART
if AXUtilitiesRole.is_dpub_preface(obj, role):
return object_properties.ROLE_PREFACE
if AXUtilitiesRole.is_dpub_prologue(obj, role):
return object_properties.ROLE_PROLOGUE
if AXUtilitiesRole.is_dpub_toc(obj, role):
return object_properties.ROLE_TOC
elif role == "ROLE_DPUB_SECTION":
if AXUtilitiesRole.is_dpub_abstract(obj, role):
return object_properties.ROLE_ABSTRACT
if AXUtilitiesRole.is_dpub_colophon(obj, role):
return object_properties.ROLE_COLOPHON
if AXUtilitiesRole.is_dpub_credit(obj, role):
return object_properties.ROLE_CREDIT
if AXUtilitiesRole.is_dpub_dedication(obj, role):
return object_properties.ROLE_DEDICATION
if AXUtilitiesRole.is_dpub_epigraph(obj, role):
return object_properties.ROLE_EPIGRAPH
if AXUtilitiesRole.is_dpub_example(obj, role):
return object_properties.ROLE_EXAMPLE
if AXUtilitiesRole.is_dpub_pullquote(obj, role):
return object_properties.ROLE_PULLQUOTE
if AXUtilitiesRole.is_dpub_qna(obj, role):
return object_properties.ROLE_QNA
elif AXUtilitiesRole.is_list_item(obj, role):
if AXUtilitiesRole.is_dpub_biblioref(obj, role):
return object_properties.ROLE_BIBLIOENTRY
if AXUtilitiesRole.is_dpub_endnote(obj, role):
return object_properties.ROLE_ENDNOTE
else:
if AXUtilitiesRole.is_dpub_cover(obj, role):
return object_properties.ROLE_COVER
if AXUtilitiesRole.is_dpub_pagebreak(obj, role):
return object_properties.ROLE_PAGEBREAK
if AXUtilitiesRole.is_dpub_subtitle(obj, role):
return object_properties.ROLE_SUBTITLE
if AXUtilitiesRole.is_landmark(obj, role):
if AXUtilitiesRole.is_landmark_without_type(obj, role):
return ""
if AXUtilitiesRole.is_landmark_banner(obj, role):
return object_properties.ROLE_LANDMARK_BANNER
if AXUtilitiesRole.is_landmark_complementary(obj, role):
return object_properties.ROLE_LANDMARK_COMPLEMENTARY
if AXUtilitiesRole.is_landmark_contentinfo(obj, role):
return object_properties.ROLE_LANDMARK_CONTENTINFO
if AXUtilitiesRole.is_landmark_main(obj, role):
return object_properties.ROLE_LANDMARK_MAIN
if AXUtilitiesRole.is_landmark_navigation(obj, role):
return object_properties.ROLE_LANDMARK_NAVIGATION
if AXUtilitiesRole.is_landmark_region(obj, role):
return object_properties.ROLE_LANDMARK_REGION
if AXUtilitiesRole.is_landmark_search(obj, role):
return object_properties.ROLE_LANDMARK_SEARCH
if AXUtilitiesRole.is_landmark_form(obj, role):
role = Atspi.Role.FORM
elif AXUtilitiesRole.is_comment(obj, role):
role = Atspi.Role.COMMENT
if not isinstance(role, Atspi.Role):
return AXObject.get_role_name(obj, True)
return Atspi.role_get_localized_name(role)
@staticmethod
def has_role_from_aria(obj: Atspi.Accessible) -> bool:
"""Returns True if obj's role comes from ARIA"""
return bool(AXUtilitiesRole._get_xml_roles(obj))
@staticmethod
def have_same_role(obj1: Atspi.Accessible, obj2: Atspi.Accessible) -> bool:
"""Returns True if obj1 and obj2 have the same role"""
return AXObject.get_role(obj1) == AXObject.get_role(obj2)
@staticmethod
def is_accelerator_label(obj: Atspi.Accessible, role: Optional[Atspi.Role] = None) -> bool:
"""Returns True if obj has the accelerator label role"""
if role is None:
role = AXObject.get_role(obj)
return role == Atspi.Role.ACCELERATOR_LABEL
@staticmethod
def is_alert(obj: Atspi.Accessible, role: Optional[Atspi.Role] = None) -> bool:
"""Returns True if obj has the alert (a type of dialog) role"""
if role is None:
role = AXObject.get_role(obj)
return role == Atspi.Role.ALERT
@staticmethod
def is_aria_alert(obj: Atspi.Accessible, role: Optional[Atspi.Role] = None) -> bool:
"""Returns True if obj is an ARIA alert (should have notification role)"""
if "alert" not in AXUtilitiesRole._get_xml_roles(obj):
return False
if role is None:
role = AXObject.get_role(obj)
if role != Atspi.Role.NOTIFICATION:
tokens = ["AXUtilitiesRole: Unexpected role for ARIA alert", obj]
debug.print_tokens(debug.LEVEL_INFO, tokens, True)
return True
@staticmethod
def is_animation(obj: Atspi.Accessible, role: Optional[Atspi.Role] = None) -> bool:
"""Returns True if obj has the animation role"""
if role is None:
role = AXObject.get_role(obj)
return role == Atspi.Role.ANIMATION
@staticmethod
def is_application(obj: Atspi.Accessible, role: Optional[Atspi.Role] = None) -> bool:
"""Returns True if obj has the application role"""
if role is None:
role = AXObject.get_role(obj)
return role == Atspi.Role.APPLICATION
@staticmethod
def is_arrow(obj: Atspi.Accessible, role: Optional[Atspi.Role] = None) -> bool:
"""Returns True if obj has the arrow role"""
if role is None:
role = AXObject.get_role(obj)
return role == Atspi.Role.ARROW
@staticmethod
def is_article(obj: Atspi.Accessible, role: Optional[Atspi.Role] = None) -> bool:
"""Returns True if obj has the article role"""
if role is None:
role = AXObject.get_role(obj)
return role == Atspi.Role.ARTICLE
@staticmethod
def is_audio(obj: Atspi.Accessible, role: Optional[Atspi.Role] = None) -> bool:
"""Returns True if obj has the audio role"""
if role is None:
role = AXObject.get_role(obj)
return role == Atspi.Role.AUDIO
@staticmethod
def is_autocomplete(obj: Atspi.Accessible, role: Optional[Atspi.Role] = None) -> bool:
"""Returns True if obj has the autocomplete role"""
if role is None:
role = AXObject.get_role(obj)
return role == Atspi.Role.AUTOCOMPLETE
@staticmethod
def is_block_quote(obj: Atspi.Accessible, role: Optional[Atspi.Role] = None) -> bool:
"""Returns True if obj has the block quote role"""
if role is None:
role = AXObject.get_role(obj)
return role == Atspi.Role.BLOCK_QUOTE or AXUtilitiesRole._get_tag(obj) == "blockquote"
@staticmethod
def is_button(obj: Atspi.Accessible, role: Optional[Atspi.Role] = None) -> bool:
"""Returns True if obj has the push- or toggle-button role"""
if role is None:
role = AXObject.get_role(obj)
return role in [Atspi.Role.PUSH_BUTTON, Atspi.Role.TOGGLE_BUTTON]
@staticmethod
def is_button_with_popup(obj: Atspi.Accessible, role: Optional[Atspi.Role] = None) -> bool:
"""Returns True if obj has the push- or toggle-button role and a popup"""
if not AXUtilitiesRole.is_button(obj, role):
return False
return AXUtilitiesState.has_popup(obj)
@staticmethod
def is_calendar(obj: Atspi.Accessible, role: Optional[Atspi.Role] = None) -> bool:
"""Returns True if obj has the calendar role"""
if role is None:
role = AXObject.get_role(obj)
return role == Atspi.Role.CALENDAR
@staticmethod
def is_canvas(obj: Atspi.Accessible, role: Optional[Atspi.Role] = None) -> bool:
"""Returns True if obj has the canvas role"""
if role is None:
role = AXObject.get_role(obj)
return role == Atspi.Role.CANVAS
@staticmethod
def is_caption(obj: Atspi.Accessible, role: Optional[Atspi.Role] = None) -> bool:
"""Returns True if obj has the caption role"""
if role is None:
role = AXObject.get_role(obj)
return role == Atspi.Role.CAPTION
@staticmethod
def is_chart(obj: Atspi.Accessible, role: Optional[Atspi.Role] = None) -> bool:
"""Returns True if obj has the chart role"""
if role is None:
role = AXObject.get_role(obj)
return role == Atspi.Role.CHART
@staticmethod
def is_check_box(obj: Atspi.Accessible, role: Optional[Atspi.Role] = None) -> bool:
"""Returns True if obj has the checkbox role"""
if role is None:
role = AXObject.get_role(obj)
return role == Atspi.Role.CHECK_BOX
@staticmethod
def is_check_menu_item(obj: Atspi.Accessible, role: Optional[Atspi.Role] = None) -> bool:
"""Returns True if obj has the check menuitem role"""
if role is None:
role = AXObject.get_role(obj)
return role == Atspi.Role.CHECK_MENU_ITEM
@staticmethod
def is_code(obj: Atspi.Accessible, _role: Optional[Atspi.Role] = None) -> bool:
"""Returns True if obj has the code or code-like role"""
return "code" in AXUtilitiesRole._get_xml_roles(obj) \
or AXUtilitiesRole._get_tag(obj) in ["code", "pre"]
@staticmethod
def is_color_chooser(obj: Atspi.Accessible, role: Optional[Atspi.Role] = None) -> bool:
"""Returns True if obj has the color_chooser role"""
if role is None:
role = AXObject.get_role(obj)
return role == Atspi.Role.COLOR_CHOOSER
@staticmethod
def is_column_header(obj: Atspi.Accessible, role: Optional[Atspi.Role] = None) -> bool:
"""Returns True if obj has the column header role"""
if role is None:
role = AXObject.get_role(obj)
return role == Atspi.Role.COLUMN_HEADER
@staticmethod
def is_combo_box(obj: Atspi.Accessible, role: Optional[Atspi.Role] = None) -> bool:
"""Returns True if obj has the combobox role"""
if role is None:
role = AXObject.get_role(obj)
return role == Atspi.Role.COMBO_BOX
@staticmethod
def is_comment(obj: Atspi.Accessible, role: Optional[Atspi.Role] = None) -> bool:
"""Returns True if obj has the comment role"""
if role is None:
role = AXObject.get_role(obj)
return role == Atspi.Role.COMMENT or "comment" in AXUtilitiesRole._get_xml_roles(obj)
@staticmethod
def is_content_deletion(obj: Atspi.Accessible, role: Optional[Atspi.Role] = None) -> bool:
"""Returns True if obj has the content deletion role"""
if role is None:
role = AXObject.get_role(obj)
return role == Atspi.Role.CONTENT_DELETION \
or "deletion" in AXUtilitiesRole._get_xml_roles(obj) \
or "del" == AXUtilitiesRole._get_tag(obj)
@staticmethod
def is_content_insertion(obj: Atspi.Accessible, role: Optional[Atspi.Role] = None) -> bool:
"""Returns True if obj has the content insertion role"""
if role is None:
role = AXObject.get_role(obj)
return role == Atspi.Role.CONTENT_INSERTION \
or "insertion" in AXUtilitiesRole._get_xml_roles(obj) \
or "ins" == AXUtilitiesRole._get_tag(obj)
@staticmethod
def is_date_editor(obj: Atspi.Accessible, role: Optional[Atspi.Role] = None) -> bool:
"""Returns True if obj has the date editor role"""
if role is None:
role = AXObject.get_role(obj)
return role == Atspi.Role.DATE_EDITOR
@staticmethod
def is_default_button(obj: Atspi.Accessible, role: Optional[Atspi.Role] = None) -> bool:
"""Returns True if obj has the push button role the is-default state"""
return AXUtilitiesRole.is_push_button(obj, role) \
and AXObject.has_state(obj, Atspi.StateType.IS_DEFAULT)
@staticmethod
def is_definition(obj: Atspi.Accessible, role: Optional[Atspi.Role] = None) -> bool:
"""Returns True if obj has the definition role"""
if role is None:
role = AXObject.get_role(obj)
return role == Atspi.Role.DEFINITION
@staticmethod
def is_description_list(obj: Atspi.Accessible, role: Optional[Atspi.Role] = None) -> bool:
"""Returns True if obj has the description list role"""
if role is None:
role = AXObject.get_role(obj)
return role == Atspi.Role.DESCRIPTION_LIST \
or "dl" == AXUtilitiesRole._get_tag(obj)
@staticmethod
def is_description_term(obj: Atspi.Accessible, role: Optional[Atspi.Role] = None) -> bool:
"""Returns True if obj has the description term role"""
if role is None:
role = AXObject.get_role(obj)
return role == Atspi.Role.DESCRIPTION_TERM \
or "dt" == AXUtilitiesRole._get_tag(obj)
@staticmethod
def is_description_value(obj: Atspi.Accessible, role: Optional[Atspi.Role] = None) -> bool:
"""Returns True if obj has the description value role"""
if role is None:
role = AXObject.get_role(obj)
return role == Atspi.Role.DESCRIPTION_VALUE \
or "dd" == AXUtilitiesRole._get_tag(obj)
@staticmethod
def is_desktop_frame(obj: Atspi.Accessible, role: Optional[Atspi.Role] = None) -> bool:
"""Returns True if obj has the desktop frame role"""
if role is None:
role = AXObject.get_role(obj)
if role == Atspi.Role.DESKTOP_FRAME:
return True
if role == Atspi.Role.FRAME:
attrs = AXObject.get_attributes_dict(obj)
return attrs.get("is-desktop") == "true"
return False
@staticmethod
def is_desktop_icon(obj: Atspi.Accessible, role: Optional[Atspi.Role] = None) -> bool:
"""Returns True if obj has the desktop icon role"""
if role is None:
role = AXObject.get_role(obj)
return role == Atspi.Role.DESKTOP_ICON
@staticmethod
def is_dial(obj: Atspi.Accessible, role: Optional[Atspi.Role] = None) -> bool:
"""Returns True if obj has the dial role"""
if role is None:
role = AXObject.get_role(obj)
return role == Atspi.Role.DIAL
@staticmethod
def is_dialog(obj: Atspi.Accessible, role: Optional[Atspi.Role] = None) -> bool:
"""Returns True if obj has the dialog role"""
if role is None:
role = AXObject.get_role(obj)
return role == Atspi.Role.DIALOG
@staticmethod
def is_dialog_or_alert(obj: Atspi.Accessible, role: Optional[Atspi.Role] = None) -> bool:
"""Returns True if obj has any dialog or alert role"""
roles = AXUtilitiesRole.get_dialog_roles(True)
if role is None:
role = AXObject.get_role(obj)
return role in roles
@staticmethod
def is_dialog_or_window(obj: Atspi.Accessible, role: Optional[Atspi.Role] = None) -> bool:
"""Returns True if obj has any dialog or window-related role"""
roles = AXUtilitiesRole.get_dialog_roles(False)
roles.extend((Atspi.Role.FRAME, Atspi.Role.WINDOW))
if role is None:
role = AXObject.get_role(obj)
return role in roles
@staticmethod
def is_directory_pane(obj: Atspi.Accessible, role: Optional[Atspi.Role] = None) -> bool:
"""Returns True if obj has the directory pane role"""
if role is None:
role = AXObject.get_role(obj)
return role == Atspi.Role.DIRECTORY_PANE
@staticmethod
def is_docked_frame(obj: Atspi.Accessible, role: Optional[Atspi.Role] = None) -> bool:
"""Returns True if obj has the frame role and is docked."""
if not AXUtilitiesRole.is_frame(obj, role):
return False
attrs = AXObject.get_attributes_dict(obj)
return attrs.get("window-type") == "dock"
@staticmethod
def is_document(obj: Atspi.Accessible, role: Optional[Atspi.Role] = None) -> bool:
"""Returns True if obj has any document-related role"""
roles = AXUtilitiesRole.get_document_roles()
if role is None:
role = AXObject.get_role(obj)
return role in roles
@staticmethod
def is_document_email(obj: Atspi.Accessible, role: Optional[Atspi.Role] = None) -> bool:
"""Returns True if obj has the document email role"""
if role is None:
role = AXObject.get_role(obj)
return role == Atspi.Role.DOCUMENT_EMAIL
@staticmethod
def is_document_frame(obj: Atspi.Accessible, role: Optional[Atspi.Role] = None) -> bool:
"""Returns True if obj has the document frame role"""
if role is None:
role = AXObject.get_role(obj)
return role == Atspi.Role.DOCUMENT_FRAME
@staticmethod
def is_document_presentation(obj: Atspi.Accessible, role: Optional[Atspi.Role] = None) -> bool:
"""Returns True if obj has the document presentation role"""
if role is None:
role = AXObject.get_role(obj)
return role == Atspi.Role.DOCUMENT_PRESENTATION
@staticmethod
def is_document_spreadsheet(obj: Atspi.Accessible, role: Optional[Atspi.Role] = None) -> bool:
"""Returns True if obj has the document spreadsheet role"""
if role is None:
role = AXObject.get_role(obj)
return role == Atspi.Role.DOCUMENT_SPREADSHEET
@staticmethod
def is_document_text(obj: Atspi.Accessible, role: Optional[Atspi.Role] = None) -> bool:
"""Returns True if obj has the document text role"""
if role is None:
role = AXObject.get_role(obj)
return role == Atspi.Role.DOCUMENT_TEXT
@staticmethod
def is_document_web(obj: Atspi.Accessible, role: Optional[Atspi.Role] = None) -> bool:
"""Returns True if obj has the document web role"""
if role is None:
role = AXObject.get_role(obj)
return role == Atspi.Role.DOCUMENT_WEB
@staticmethod
def is_dpub(obj: Atspi.Accessible, _role: Optional[Atspi.Role] = None) -> bool:
"""Returns True if obj has a DPub role."""
roles = AXUtilitiesRole._get_xml_roles(obj)
rv = bool(list(filter(lambda x: x.startswith("doc-"), roles)))
return rv
@staticmethod
def is_dpub_abstract(obj: Atspi.Accessible, _role: Optional[Atspi.Role] = None) -> bool:
"""Returns True if obj has the DPub abstract role."""
return "doc-abstract" in AXUtilitiesRole._get_xml_roles(obj)
@staticmethod
def is_dpub_acknowledgments(obj: Atspi.Accessible, _role: Optional[Atspi.Role] = None) -> bool:
"""Returns True if obj has the DPub acknowledgments role."""
return "doc-acknowledgments" in AXUtilitiesRole._get_xml_roles(obj)
@staticmethod
def is_dpub_afterword(obj: Atspi.Accessible, _role: Optional[Atspi.Role] = None) -> bool:
"""Returns True if obj has the DPub afterword role."""
return "doc-afterword" in AXUtilitiesRole._get_xml_roles(obj)
@staticmethod
def is_dpub_appendix(obj: Atspi.Accessible, _role: Optional[Atspi.Role] = None) -> bool:
"""Returns True if obj has the DPub appendix role."""
return "doc-appendix" in AXUtilitiesRole._get_xml_roles(obj)
@staticmethod
def is_dpub_backlink(obj: Atspi.Accessible, _role: Optional[Atspi.Role] = None) -> bool:
"""Returns True if obj has the DPub backlink role."""
return "doc-backlink" in AXUtilitiesRole._get_xml_roles(obj)
@staticmethod
def is_dpub_biblioref(obj: Atspi.Accessible, _role: Optional[Atspi.Role] = None) -> bool:
"""Returns True if obj has the DPub biblioref role."""
return "doc-biblioref" in AXUtilitiesRole._get_xml_roles(obj)
@staticmethod
def is_dpub_bibliography(obj: Atspi.Accessible, _role: Optional[Atspi.Role] = None) -> bool:
"""Returns True if obj has the DPub bibliography role."""
return "doc-bibliography" in AXUtilitiesRole._get_xml_roles(obj)
@staticmethod
def is_dpub_chapter(obj: Atspi.Accessible, _role: Optional[Atspi.Role] = None) -> bool:
"""Returns True if obj has the DPub chapter role."""
return "doc-chapter" in AXUtilitiesRole._get_xml_roles(obj)
@staticmethod
def is_dpub_colophon(obj: Atspi.Accessible, _role: Optional[Atspi.Role] = None) -> bool:
"""Returns True if obj has the DPub colophon role."""
return "doc-colophon" in AXUtilitiesRole._get_xml_roles(obj)
@staticmethod
def is_dpub_conclusion(obj: Atspi.Accessible, _role: Optional[Atspi.Role] = None) -> bool:
"""Returns True if obj has the DPub conclusion role."""
return "doc-conclusion" in AXUtilitiesRole._get_xml_roles(obj)
@staticmethod
def is_dpub_cover(obj: Atspi.Accessible, _role: Optional[Atspi.Role] = None) -> bool:
"""Returns True if obj has the DPub cover role."""
return "doc-cover" in AXUtilitiesRole._get_xml_roles(obj)
@staticmethod
def is_dpub_credit(obj: Atspi.Accessible, _role: Optional[Atspi.Role] = None) -> bool:
"""Returns True if obj has the DPub credit role."""
return "doc-credit" in AXUtilitiesRole._get_xml_roles(obj)
@staticmethod
def is_dpub_credits(obj: Atspi.Accessible, _role: Optional[Atspi.Role] = None) -> bool:
"""Returns True if obj has the DPub credits role."""
return "doc-credits" in AXUtilitiesRole._get_xml_roles(obj)
@staticmethod
def is_dpub_dedication(obj: Atspi.Accessible, _role: Optional[Atspi.Role] = None) -> bool:
"""Returns True if obj has the DPub dedication role."""
return "doc-dedication" in AXUtilitiesRole._get_xml_roles(obj)
@staticmethod
def is_dpub_endnote(obj: Atspi.Accessible, _role: Optional[Atspi.Role] = None) -> bool:
"""Returns True if obj has the DPub endnote role."""
return "doc-endnote" in AXUtilitiesRole._get_xml_roles(obj)
@staticmethod
def is_dpub_endnotes(obj: Atspi.Accessible, _role: Optional[Atspi.Role] = None) -> bool:
"""Returns True if obj has the DPub endnotes role."""
return "doc-endnotes" in AXUtilitiesRole._get_xml_roles(obj)
@staticmethod
def is_dpub_epigraph(obj: Atspi.Accessible, _role: Optional[Atspi.Role] = None) -> bool:
"""Returns True if obj has the DPub epigraph role."""
return "doc-epigraph" in AXUtilitiesRole._get_xml_roles(obj)
@staticmethod
def is_dpub_epilogue(obj: Atspi.Accessible, _role: Optional[Atspi.Role] = None) -> bool:
"""Returns True if obj has the DPub epilogue role."""
return "doc-epilogue" in AXUtilitiesRole._get_xml_roles(obj)
@staticmethod
def is_dpub_errata(obj: Atspi.Accessible, _role: Optional[Atspi.Role] = None) -> bool:
"""Returns True if obj has the DPub errata role."""
return "doc-errata" in AXUtilitiesRole._get_xml_roles(obj)
@staticmethod
def is_dpub_example(obj: Atspi.Accessible, _role: Optional[Atspi.Role] = None) -> bool:
"""Returns True if obj has the DPub example role."""
return "doc-example" in AXUtilitiesRole._get_xml_roles(obj)
@staticmethod
def is_dpub_footnote(obj: Atspi.Accessible, _role: Optional[Atspi.Role] = None) -> bool:
"""Returns True if obj has the DPub footnote role."""
return "doc-footnote" in AXUtilitiesRole._get_xml_roles(obj)
@staticmethod
def is_dpub_foreword(obj: Atspi.Accessible, _role: Optional[Atspi.Role] = None) -> bool:
"""Returns True if obj has the DPub foreword role."""
return "doc-foreword" in AXUtilitiesRole._get_xml_roles(obj)
@staticmethod
def is_dpub_glossary(obj: Atspi.Accessible, _role: Optional[Atspi.Role] = None) -> bool:
"""Returns True if obj has the DPub glossary role."""
return "doc-glossary" in AXUtilitiesRole._get_xml_roles(obj)
@staticmethod
def is_dpub_glossref(obj: Atspi.Accessible, _role: Optional[Atspi.Role] = None) -> bool:
"""Returns True if obj has the DPub glossref role."""
return "doc-glossref" in AXUtilitiesRole._get_xml_roles(obj)
@staticmethod
def is_dpub_index(obj: Atspi.Accessible, _role: Optional[Atspi.Role] = None) -> bool:
"""Returns True if obj has the DPub index role."""
return "doc-index" in AXUtilitiesRole._get_xml_roles(obj)
@staticmethod
def is_dpub_introduction(obj: Atspi.Accessible, _role: Optional[Atspi.Role] = None) -> bool:
"""Returns True if obj has the DPub introduction role."""
return "doc-introduction" in AXUtilitiesRole._get_xml_roles(obj)
@staticmethod
def is_dpub_noteref(obj: Atspi.Accessible, _role: Optional[Atspi.Role] = None) -> bool:
"""Returns True if obj has the DPub noteref role."""
return "doc-noteref" in AXUtilitiesRole._get_xml_roles(obj)
@staticmethod
def is_dpub_pagelist(obj: Atspi.Accessible, _role: Optional[Atspi.Role] = None) -> bool:
"""Returns True if obj has the DPub pagelist role."""
return "doc-pagelist" in AXUtilitiesRole._get_xml_roles(obj)
@staticmethod
def is_dpub_pagebreak(obj: Atspi.Accessible, _role: Optional[Atspi.Role] = None) -> bool:
"""Returns True if obj has the DPub pagebreak role."""
return "doc-pagebreak" in AXUtilitiesRole._get_xml_roles(obj)
@staticmethod
def is_dpub_part(obj: Atspi.Accessible, _role: Optional[Atspi.Role] = None) -> bool:
"""Returns True if obj has the DPub part role."""
return "doc-part" in AXUtilitiesRole._get_xml_roles(obj)
@staticmethod
def is_dpub_preface(obj: Atspi.Accessible, _role: Optional[Atspi.Role] = None) -> bool:
"""Returns True if obj has the DPub preface role."""
return "doc-preface" in AXUtilitiesRole._get_xml_roles(obj)
@staticmethod
def is_dpub_prologue(obj: Atspi.Accessible, _role: Optional[Atspi.Role] = None) -> bool:
"""Returns True if obj has the DPub prologue role."""
return "doc-prologue" in AXUtilitiesRole._get_xml_roles(obj)
@staticmethod
def is_dpub_pullquote(obj: Atspi.Accessible, _role: Optional[Atspi.Role] = None) -> bool:
"""Returns True if obj has the DPub pullquote role."""
return "doc-pullquote" in AXUtilitiesRole._get_xml_roles(obj)
@staticmethod
def is_dpub_qna(obj: Atspi.Accessible, _role: Optional[Atspi.Role] = None) -> bool:
"""Returns True if obj has the DPub qna role."""
return "doc-qna" in AXUtilitiesRole._get_xml_roles(obj)
@staticmethod
def is_dpub_subtitle(obj: Atspi.Accessible, _role: Optional[Atspi.Role] = None) -> bool:
"""Returns True if obj has the DPub subtitle role."""
return "doc-subtitle" in AXUtilitiesRole._get_xml_roles(obj)
@staticmethod
def is_dpub_toc(obj: Atspi.Accessible, _role: Optional[Atspi.Role] = None) -> bool:
"""Returns True if obj has the DPub toc role."""
return "doc-toc" in AXUtilitiesRole._get_xml_roles(obj)
@staticmethod
def is_drawing_area(obj: Atspi.Accessible, role: Optional[Atspi.Role] = None) -> bool:
"""Returns True if obj has the drawing area role"""
if role is None:
role = AXObject.get_role(obj)
return role == Atspi.Role.DRAWING_AREA
@staticmethod
def is_editable_combo_box(obj: Atspi.Accessible, role: Optional[Atspi.Role] = None) -> bool:
"""Returns True if obj is an editable combobox"""
if role is None:
role = AXObject.get_role(obj)
if role != Atspi.Role.COMBO_BOX:
return False
if AXUtilitiesState.is_editable(obj):
return True
return bool(AXObject.find_descendant(obj, AXUtilitiesRole.is_text_input))
@staticmethod
def is_editbar(obj: Atspi.Accessible, role: Optional[Atspi.Role] = None) -> bool:
"""Returns True if obj has the editbar role"""
if role is None:
role = AXObject.get_role(obj)
return role == Atspi.Role.EDITBAR
@staticmethod
def is_embedded(obj: Atspi.Accessible, role: Optional[Atspi.Role] = None) -> bool:
"""Returns True if obj has the embedded role"""
if role is None:
role = AXObject.get_role(obj)
return role == Atspi.Role.EMBEDDED
@staticmethod
def is_entry(obj: Atspi.Accessible, role: Optional[Atspi.Role] = None) -> bool:
"""Returns True if obj has the entry role"""
if role is None:
role = AXObject.get_role(obj)
return role == Atspi.Role.ENTRY
@staticmethod
def is_extended(obj: Atspi.Accessible, role: Optional[Atspi.Role] = None) -> bool:
"""Returns True if obj has the extended role"""
if role is None:
role = AXObject.get_role(obj)
return role == Atspi.Role.EXTENDED
@staticmethod
def is_feed(obj: Atspi.Accessible, _role: Optional[Atspi.Role] = None) -> bool:
"""Returns True if obj has the feed role"""
return "feed" in AXUtilitiesRole._get_xml_roles(obj)
@staticmethod
def is_feed_article(obj: Atspi.Accessible, role: Optional[Atspi.Role] = None) -> bool:
"""Returns True if obj has the article role and descends from a feed."""
if not AXUtilitiesRole.is_article(obj, role):
return False
return AXObject.find_ancestor(obj, AXUtilitiesRole.is_feed) is not None
@staticmethod
def is_figure(obj: Atspi.Accessible, _role: Optional[Atspi.Role] = None) -> bool:
"""Returns True if obj has the figure role or tag."""
return "figure" in AXUtilitiesRole._get_xml_roles(obj) \
or AXUtilitiesRole._get_tag(obj) == "figure"
@staticmethod
def is_file_chooser(obj: Atspi.Accessible, role: Optional[Atspi.Role] = None) -> bool:
"""Returns True if obj has the file chooser role"""
if role is None:
role = AXObject.get_role(obj)
return role == Atspi.Role.FILE_CHOOSER
@staticmethod
def is_filler(obj: Atspi.Accessible, role: Optional[Atspi.Role] = None) -> bool:
"""Returns True if obj has the filler role"""
if role is None:
role = AXObject.get_role(obj)
return role == Atspi.Role.FILLER
@staticmethod
def is_focus_traversable(obj: Atspi.Accessible, role: Optional[Atspi.Role] = None) -> bool:
"""Returns True if obj has the focus traversable role"""
if role is None:
role = AXObject.get_role(obj)
return role == Atspi.Role.FOCUS_TRAVERSABLE
@staticmethod
def is_font_chooser(obj: Atspi.Accessible, role: Optional[Atspi.Role] = None) -> bool:
"""Returns True if obj has the font chooser role"""
if role is None:
role = AXObject.get_role(obj)
return role == Atspi.Role.FONT_CHOOSER
@staticmethod
def is_footer(obj: Atspi.Accessible, role: Optional[Atspi.Role] = None) -> bool:
"""Returns True if obj has the footer role"""
if role is None:
role = AXObject.get_role(obj)
return role == Atspi.Role.FOOTER
@staticmethod
def is_footnote(obj: Atspi.Accessible, role: Optional[Atspi.Role] = None) -> bool:
"""Returns True if obj has the footnote role"""
if role is None:
role = AXObject.get_role(obj)
return role == Atspi.Role.FOOTNOTE
@staticmethod
def is_form(obj: Atspi.Accessible, role: Optional[Atspi.Role] = None) -> bool:
"""Returns True if obj has the form role"""
if role is None:
role = AXObject.get_role(obj)
return role == Atspi.Role.FORM
@staticmethod
def is_frame(obj: Atspi.Accessible, role: Optional[Atspi.Role] = None) -> bool:
"""Returns True if obj has the frame role"""
if role is None:
role = AXObject.get_role(obj)
return role == Atspi.Role.FRAME
@staticmethod
def is_glass_pane(obj: Atspi.Accessible, role: Optional[Atspi.Role] = None) -> bool:
"""Returns True if obj has the glass pane role"""
if role is None:
role = AXObject.get_role(obj)
return role == Atspi.Role.GLASS_PANE
@staticmethod
def is_grid(obj: Atspi.Accessible, role: Optional[Atspi.Role] = None) -> bool:
"""Returns True if obj has the grid role."""
if not AXUtilitiesRole.is_table(obj, role):
return False
return "grid" in AXUtilitiesRole._get_xml_roles(obj)
@staticmethod
def is_grid_cell(obj: Atspi.Accessible, role: Optional[Atspi.Role] = None) -> bool:
"""Returns True if obj has the gridcell role or the cell role and is in a grid."""
if not AXUtilitiesRole.is_table_cell(obj, role):
return False
roles = AXUtilitiesRole._get_xml_roles(obj)
if "gridcell" in roles:
return True
if "cell" in roles:
return AXObject.find_ancestor(obj, AXUtilitiesRole.is_grid) is not None
return False
@staticmethod
def is_group(obj: Atspi.Accessible, _role: Optional[Atspi.Role] = None) -> bool:
"""Returns True if obj is an ARIA group."""
return "group" in AXUtilitiesRole._get_xml_roles(obj)
@staticmethod
def is_grouping(obj: Atspi.Accessible, role: Optional[Atspi.Role] = None) -> bool:
"""Returns True if obj has the grouping role"""
if role is None:
role = AXObject.get_role(obj)
return role == Atspi.Role.GROUPING
@staticmethod
def is_header(obj: Atspi.Accessible, role: Optional[Atspi.Role] = None) -> bool:
"""Returns True if obj has the header role"""
if role is None:
role = AXObject.get_role(obj)
return role == Atspi.Role.HEADER
@staticmethod
def is_heading(obj: Atspi.Accessible, role: Optional[Atspi.Role] = None) -> bool:
"""Returns True if obj has the heading role"""
if role is None:
role = AXObject.get_role(obj)
return role == Atspi.Role.HEADING
@staticmethod
def is_html_container(obj: Atspi.Accessible, role: Optional[Atspi.Role] = None) -> bool:
"""Returns True if obj has the html container role"""
if role is None:
role = AXObject.get_role(obj)
return role == Atspi.Role.HTML_CONTAINER
@staticmethod
def is_horizontal_scrollbar(obj: Atspi.Accessible, role: Optional[Atspi.Role] = None) -> bool:
"""Returns True if obj is a horizontal scrollbar"""
return AXUtilitiesRole.is_scroll_bar(obj, role) \
and AXObject.has_state(obj, Atspi.StateType.HORIZONTAL)
@staticmethod
def is_horizontal_separator(obj: Atspi.Accessible, role: Optional[Atspi.Role] = None) -> bool:
"""Returns True if obj is a horizontal separator"""
return AXUtilitiesRole.is_separator(obj, role) \
and AXObject.has_state(obj, Atspi.StateType.HORIZONTAL)
@staticmethod
def is_horizontal_slider(obj: Atspi.Accessible, role: Optional[Atspi.Role] = None) -> bool:
"""Returns True if obj is a horizontal slider"""
return AXUtilitiesRole.is_slider(obj, role) \
and AXObject.has_state(obj, Atspi.StateType.HORIZONTAL)
@staticmethod
def is_icon(obj: Atspi.Accessible, role: Optional[Atspi.Role] = None) -> bool:
"""Returns True if obj has the icon role"""
if role is None:
role = AXObject.get_role(obj)
return role == Atspi.Role.ICON
@staticmethod
def is_icon_or_canvas(obj: Atspi.Accessible, role: Optional[Atspi.Role] = None) -> bool:
"""Returns True if obj has the icon or canvas role"""
if role is None:
role = AXObject.get_role(obj)
return role in [Atspi.Role.ICON, Atspi.Role.CANVAS]
@staticmethod
def is_image(obj: Atspi.Accessible, role: Optional[Atspi.Role] = None) -> bool:
"""Returns True if obj has the image role"""
if role is None:
role = AXObject.get_role(obj)
return role == Atspi.Role.IMAGE
@staticmethod
def is_image_or_canvas(obj: Atspi.Accessible, role: Optional[Atspi.Role] = None) -> bool:
"""Returns True if obj has the image or canvas role"""
if role is None:
role = AXObject.get_role(obj)
return role in [Atspi.Role.IMAGE, Atspi.Role.CANVAS]
@staticmethod
def is_image_map(obj: Atspi.Accessible, role: Optional[Atspi.Role] = None) -> bool:
"""Returns True if obj has the image map role"""
if role is None:
role = AXObject.get_role(obj)
return role == Atspi.Role.IMAGE_MAP
@staticmethod
def is_info_bar(obj: Atspi.Accessible, role: Optional[Atspi.Role] = None) -> bool:
"""Returns True if obj has the info bar role"""
if role is None:
role = AXObject.get_role(obj)
return role == Atspi.Role.INFO_BAR
@staticmethod
def is_inline_internal_frame(obj: Atspi.Accessible, role: Optional[Atspi.Role] = None) -> bool:
"""Returns True if obj has the internal frame role and is inline."""
if not AXUtilitiesRole.is_internal_frame(obj, role):
return False
return "inline" in AXUtilitiesRole._get_display_style(obj)
@staticmethod
def is_inline_list_item(obj: Atspi.Accessible, role: Optional[Atspi.Role] = None) -> bool:
"""Returns True if obj has the list item role and is inline."""
if not AXUtilitiesRole.is_list_item(obj, role):
return False
return "inline" in AXUtilitiesRole._get_display_style(obj)
@staticmethod
def is_inline_suggestion(obj: Atspi.Accessible, role: Optional[Atspi.Role] = None) -> bool:
"""Returns True if obj has the suggestion role and is inline."""
if not AXUtilitiesRole.is_suggestion(obj, role):
return False
return "inline" in AXUtilitiesRole._get_display_style(obj)
@staticmethod
def is_input_method_window(obj: Atspi.Accessible, role: Optional[Atspi.Role] = None) -> bool:
"""Returns True if obj has the input method window role"""
if role is None:
role = AXObject.get_role(obj)
return role == Atspi.Role.INPUT_METHOD_WINDOW
@staticmethod
def is_internal_frame(obj: Atspi.Accessible, role: Optional[Atspi.Role] = None) -> bool:
"""Returns True if obj has the internal frame role"""
if role is None:
role = AXObject.get_role(obj)
return role == Atspi.Role.INTERNAL_FRAME or AXUtilitiesRole._get_tag(obj) == "iframe"
@staticmethod
def is_invalid_role(obj: Atspi.Accessible, role: Optional[Atspi.Role] = None) -> bool:
"""Returns True if obj has the invalid role"""
if role is None:
role = AXObject.get_role(obj)
return role == Atspi.Role.INVALID
@staticmethod
def is_label(obj: Atspi.Accessible, role: Optional[Atspi.Role] = None) -> bool:
"""Returns True if obj has the label role"""
if role is None:
role = AXObject.get_role(obj)
return role == Atspi.Role.LABEL
@staticmethod
def is_label_or_caption(obj: Atspi.Accessible, role: Optional[Atspi.Role] = None) -> bool:
"""Returns True if obj has the label or caption role"""
if role is None:
role = AXObject.get_role(obj)
return role in [Atspi.Role.LABEL, Atspi.Role.CAPTION]
@staticmethod
def is_landmark(obj: Atspi.Accessible, role: Optional[Atspi.Role] = None) -> bool:
"""Returns True if obj has the landmark role"""
if role is None:
role = AXObject.get_role(obj)
return role == Atspi.Role.LANDMARK
@staticmethod
def is_landmark_banner(obj: Atspi.Accessible, _role: Optional[Atspi.Role] = None) -> bool:
"""Returns True if obj has the banner landmark role"""
return "banner" in AXUtilitiesRole._get_xml_roles(obj)
@staticmethod
def is_landmark_complementary(
obj: Atspi.Accessible, _role: Optional[Atspi.Role] = None
) -> bool:
"""Returns True if obj has the complementary landmark role"""
return "complementary" in AXUtilitiesRole._get_xml_roles(obj)
@staticmethod
def is_landmark_contentinfo(obj: Atspi.Accessible, _role: Optional[Atspi.Role] = None) -> bool:
"""Returns True if obj has the contentinfo landmark role"""
return "contentinfo" in AXUtilitiesRole._get_xml_roles(obj)
@staticmethod
def is_landmark_form(obj: Atspi.Accessible, _role: Optional[Atspi.Role] = None) -> bool:
"""Returns True if obj has the form landmark role"""
return "form" in AXUtilitiesRole._get_xml_roles(obj)
@staticmethod
def is_landmark_main(obj: Atspi.Accessible, _role: Optional[Atspi.Role] = None) -> bool:
"""Returns True if obj has the main landmark role"""
return "main" in AXUtilitiesRole._get_xml_roles(obj)
@staticmethod
def is_landmark_navigation(obj: Atspi.Accessible, _role: Optional[Atspi.Role] = None) -> bool:
"""Returns True if obj has the navigation landmark role"""
return "navigation" in AXUtilitiesRole._get_xml_roles(obj)
@staticmethod
def is_landmark_region(obj: Atspi.Accessible, _role: Optional[Atspi.Role] = None) -> bool:
"""Returns True if obj has the region landmark role"""
return "region" in AXUtilitiesRole._get_xml_roles(obj)
@staticmethod
def is_landmark_search(obj: Atspi.Accessible, _role: Optional[Atspi.Role] = None) -> bool:
"""Returns True if obj has the search landmark role"""
return "search" in AXUtilitiesRole._get_xml_roles(obj)
@staticmethod
def is_landmark_without_type(obj: Atspi.Accessible, role: Optional[Atspi.Role] = None) -> bool:
"""Returns True if obj has the landmark role but no type"""
if not AXUtilitiesRole.is_landmark(obj, role):
return False
roles = AXUtilitiesRole._get_xml_roles(obj)
return not roles
@staticmethod
def is_layered_pane(obj: Atspi.Accessible, role: Optional[Atspi.Role] = None) -> bool:
"""Returns True if obj has the layered pane role"""
if role is None:
role = AXObject.get_role(obj)
return role == Atspi.Role.LAYERED_PANE
@staticmethod
def is_level_bar(obj: Atspi.Accessible, role: Optional[Atspi.Role] = None) -> bool:
"""Returns True if obj has the level bar role"""
if role is None:
role = AXObject.get_role(obj)
return role == Atspi.Role.LEVEL_BAR
@staticmethod
def is_link(obj: Atspi.Accessible, role: Optional[Atspi.Role] = None) -> bool:
"""Returns True if obj has the link role"""
if role is None:
role = AXObject.get_role(obj)
return role == Atspi.Role.LINK
@staticmethod
def is_list(obj: Atspi.Accessible, role: Optional[Atspi.Role] = None) -> bool:
"""Returns True if obj has the list role"""
if role is None:
role = AXObject.get_role(obj)
return role == Atspi.Role.LIST
@staticmethod
def is_list_box(obj: Atspi.Accessible, role: Optional[Atspi.Role] = None) -> bool:
"""Returns True if obj has the list box role"""
if role is None:
role = AXObject.get_role(obj)
return role == Atspi.Role.LIST_BOX
@staticmethod
def is_list_box_item(obj: Atspi.Accessible, role: Optional[Atspi.Role] = None) -> bool:
"""Returns True if obj is an item in a list box"""
if not AXUtilitiesRole.is_list_item(obj, role):
return False
return AXObject.find_ancestor(obj, AXUtilitiesRole.is_list_box) is not None
@staticmethod
def is_list_item(obj: Atspi.Accessible, role: Optional[Atspi.Role] = None) -> bool:
"""Returns True if obj has the list item role"""
if role is None:
role = AXObject.get_role(obj)
return role == Atspi.Role.LIST_ITEM
@staticmethod
def is_log(obj: Atspi.Accessible, role: Optional[Atspi.Role] = None) -> bool:
"""Returns True if obj has the log role"""
if role is None:
role = AXObject.get_role(obj)
return role == Atspi.Role.LOG
@staticmethod
def is_live_region(obj: Atspi.Accessible, _role: Optional[Atspi.Role] = None) -> bool:
"""Returns True if obj is a live region."""
attrs = AXObject.get_attributes_dict(obj)
return "container-live" in attrs
@staticmethod
def is_mark(obj: Atspi.Accessible, role: Optional[Atspi.Role] = None) -> bool:
"""Returns True if obj has the mark role"""
if role is None:
role = AXObject.get_role(obj)
return role == Atspi.Role.MARK \
or "mark" in AXUtilitiesRole._get_xml_roles(obj) \
or "mark" == AXUtilitiesRole._get_tag(obj)
@staticmethod
def is_marquee(obj: Atspi.Accessible, role: Optional[Atspi.Role] = None) -> bool:
"""Returns True if obj has the marquee role"""
if role is None:
role = AXObject.get_role(obj)
return role == Atspi.Role.MARQUEE
@staticmethod
def is_math(obj: Atspi.Accessible, role: Optional[Atspi.Role] = None) -> bool:
"""Returns True if obj has the math role"""
if role is None:
role = AXObject.get_role(obj)
return role == Atspi.Role.MATH
@staticmethod
def is_math_enclose(obj: Atspi.Accessible) -> bool:
"""Returns True if obj has the math enclose role/tag"""
return AXUtilitiesRole._get_tag(obj) == "menclose"
@staticmethod
def is_math_fenced(obj: Atspi.Accessible) -> bool:
"""Returns True if obj has the math fenced role/tag"""
return AXUtilitiesRole._get_tag(obj) == "mfenced"
@staticmethod
def is_math_fraction(obj: Atspi.Accessible, role: Optional[Atspi.Role] = None) -> bool:
"""Returns True if obj has the math fraction role"""
if role is None:
role = AXObject.get_role(obj)
return role == Atspi.Role.MATH_FRACTION
@staticmethod
def is_math_fraction_without_bar(
obj: Atspi.Accessible, role: Optional[Atspi.Role] = None
) -> bool:
"""Returns True if obj has the math fraction role and lacks the fraction bar"""
if not AXUtilitiesRole.is_math_fraction(obj, role):
return False
line_thickness = AXObject.get_attribute(obj, "linethickness")
if not line_thickness:
return False
for char in line_thickness:
if char.isnumeric() and char != "0":
return False
return True
@staticmethod
def is_math_layout_only(obj: Atspi.Accessible) -> bool:
"""Returns True if obj has a layout-only math role"""
return AXUtilitiesRole._get_tag(obj) \
in ["mrow", "mstyle", "merror", "mpadded", "none", "semantics"]
@staticmethod
def is_math_multi_script(obj: Atspi.Accessible) -> bool:
"""Returns True if obj has the math multi-scripts role/tag"""
return AXUtilitiesRole._get_tag(obj) == "mmultiscripts"
@staticmethod
def is_math_related(obj: Atspi.Accessible, role: Optional[Atspi.Role] = None) -> bool:
"""Returns True if obj has a math-related role"""
if role is None:
role = AXObject.get_role(obj)
if role in [Atspi.Role.MATH, Atspi.Role.MATH_FRACTION, Atspi.Role.MATH_ROOT]:
return True
return AXUtilitiesRole._get_tag(obj) in ["math",
"maction",
"maligngroup",
"malignmark",
"menclose",
"merror",
"mfenced",
"mfrac",
"mglyph",
"mi",
"mlabeledtr",
"mlongdiv",
"mmultiscripts",
"mn",
"mo",
"mover",
"mpadded",
"mphantom",
"mprescripts",
"mroot",
"mrow",
"ms",
"mscarries",
"mscarry",
"msgroup",
"msline",
"mspace",
"msqrt",
"msrow",
"mstack",
"mstyle",
"msub",
"msup",
"msubsup",
"mtable",
"mtd",
"mtext",
"mtr",
"munder",
"munderover"]
@staticmethod
def is_math_root(obj: Atspi.Accessible, role: Optional[Atspi.Role] = None) -> bool:
"""Returns True if obj has the math root role"""
if role is None:
role = AXObject.get_role(obj)
return role == Atspi.Role.MATH_ROOT
@staticmethod
def is_math_square_root(obj: Atspi.Accessible) -> bool:
"""Returns True if obj has the math root role/tag"""
return AXUtilitiesRole._get_tag(obj) == "msqrt"
@staticmethod
def is_math_sub_or_super_script(obj: Atspi.Accessible) -> bool:
"""Returns True if obj has the math subscript or superscript role/tag"""
return AXUtilitiesRole._get_tag(obj) in ["msub", "msup", "msubsup"]
@staticmethod
def is_math_table(obj: Atspi.Accessible) -> bool:
"""Returns True if obj has the math table role/tag"""
return AXUtilitiesRole._get_tag(obj) == "mtable"
@staticmethod
def is_math_table_row(obj: Atspi.Accessible) -> bool:
"""Returns True if obj has the math table row role/tag"""
return AXUtilitiesRole._get_tag(obj) in ["mtr", "mlabeledtr"]
@staticmethod
def is_math_token(obj: Atspi.Accessible) -> bool:
"""Returns True if obj has a math token role/tag"""
return AXUtilitiesRole._get_tag(obj) in ["mi", "mn", "mo", "mtext", "ms", "mspace"]
@staticmethod
def is_math_under_or_over_script(obj: Atspi.Accessible) -> bool:
"""Returns True if obj has the math under-script or over-script role/tag"""
return AXUtilitiesRole._get_tag(obj) in ["mover", "munder", "munderover"]
@staticmethod
def is_menu(obj: Atspi.Accessible, role: Optional[Atspi.Role] = None) -> bool:
"""Returns True if obj has the menu role"""
if role is None:
role = AXObject.get_role(obj)
return role == Atspi.Role.MENU
@staticmethod
def is_menu_bar(obj: Atspi.Accessible, role: Optional[Atspi.Role] = None) -> bool:
"""Returns True if obj has the menubar role"""
if role is None:
role = AXObject.get_role(obj)
return role == Atspi.Role.MENU_BAR
@staticmethod
def is_menu_item(obj: Atspi.Accessible, role: Optional[Atspi.Role] = None) -> bool:
"""Returns True if obj has the menu item role"""
if role is None:
role = AXObject.get_role(obj)
return role == Atspi.Role.MENU_ITEM
@staticmethod
def is_menu_item_of_any_kind(obj: Atspi.Accessible, role: Optional[Atspi.Role] = None) -> bool:
"""Returns True if obj has any menu item role"""
roles = AXUtilitiesRole.get_menu_item_roles()
if role is None:
role = AXObject.get_role(obj)
return role in roles
@staticmethod
def is_menu_related(obj: Atspi.Accessible, role: Optional[Atspi.Role] = None) -> bool:
"""Returns True if obj has any menu-related role"""
roles = AXUtilitiesRole.get_menu_related_roles()
if role is None:
role = AXObject.get_role(obj)
return role in roles
@staticmethod
def is_modal_dialog(obj: Atspi.Accessible, role: Optional[Atspi.Role] = None) -> bool:
"""Returns True if obj has the alert or dialog role and modal state"""
return AXUtilitiesRole.is_dialog_or_alert(obj, role) \
and AXObject.has_state(obj, Atspi.StateType.MODAL)
@staticmethod
def is_multi_line_entry(obj: Atspi.Accessible, role: Optional[Atspi.Role] = None) -> bool:
"""Returns True if obj has the entry role and multiline state"""
return AXUtilitiesRole.is_entry(obj, role) \
and AXObject.has_state(obj, Atspi.StateType.MULTI_LINE)
@staticmethod
def is_notification(obj: Atspi.Accessible, role: Optional[Atspi.Role] = None) -> bool:
"""Returns True if obj has the notification role"""
if role is None:
role = AXObject.get_role(obj)
return role == Atspi.Role.NOTIFICATION
@staticmethod
def is_option_pane(obj: Atspi.Accessible, role: Optional[Atspi.Role] = None) -> bool:
"""Returns True if obj has the option pane role"""
if role is None:
role = AXObject.get_role(obj)
return role == Atspi.Role.OPTION_PANE
@staticmethod
def is_page(obj: Atspi.Accessible, role: Optional[Atspi.Role] = None) -> bool:
"""Returns True if obj has the page role"""
if role is None:
role = AXObject.get_role(obj)
return role == Atspi.Role.PAGE
@staticmethod
def is_page_tab(obj: Atspi.Accessible, role: Optional[Atspi.Role] = None) -> bool:
"""Returns True if obj has the page tab role"""
if role is None:
role = AXObject.get_role(obj)
return role == Atspi.Role.PAGE_TAB
@staticmethod
def is_page_tab_list(obj: Atspi.Accessible, role: Optional[Atspi.Role] = None) -> bool:
"""Returns True if obj has the page tab list role"""
if role is None:
role = AXObject.get_role(obj)
return role == Atspi.Role.PAGE_TAB_LIST
@staticmethod
def is_page_tab_list_related(obj: Atspi.Accessible, role: Optional[Atspi.Role] = None) -> bool:
"""Returns True if obj has the page tab or page tab list role"""
roles = [Atspi.Role.PAGE_TAB_LIST, Atspi.Role.PAGE_TAB]
if role is None:
role = AXObject.get_role(obj)
return role in roles
@staticmethod
def is_panel(obj: Atspi.Accessible, role: Optional[Atspi.Role] = None) -> bool:
"""Returns True if obj has the panel role"""
if role is None:
role = AXObject.get_role(obj)
return role == Atspi.Role.PANEL
@staticmethod
def is_paragraph(obj: Atspi.Accessible, role: Optional[Atspi.Role] = None) -> bool:
"""Returns True if obj has the paragraph role"""
if role is None:
role = AXObject.get_role(obj)
return role == Atspi.Role.PARAGRAPH
@staticmethod
def is_password_text(obj: Atspi.Accessible, role: Optional[Atspi.Role] = None) -> bool:
"""Returns True if obj has the password text role"""
if role is None:
role = AXObject.get_role(obj)
return role == Atspi.Role.PASSWORD_TEXT
@staticmethod
def is_popup_menu(obj: Atspi.Accessible, role: Optional[Atspi.Role] = None) -> bool:
"""Returns True if obj has the popup menu role"""
if role is None:
role = AXObject.get_role(obj)
return role == Atspi.Role.POPUP_MENU
@staticmethod
def is_progress_bar(obj: Atspi.Accessible, role: Optional[Atspi.Role] = None) -> bool:
"""Returns True if obj has the progress bar role"""
if role is None:
role = AXObject.get_role(obj)
return role == Atspi.Role.PROGRESS_BAR
@staticmethod
def is_push_button(obj: Atspi.Accessible, role: Optional[Atspi.Role] = None) -> bool:
"""Returns True if obj has the push button role"""
if role is None:
role = AXObject.get_role(obj)
return role == Atspi.Role.PUSH_BUTTON
@staticmethod
def is_push_button_menu(obj: Atspi.Accessible, role: Optional[Atspi.Role] = None) -> bool:
"""Returns True if obj has the push button menu role"""
if role is None:
role = AXObject.get_role(obj)
return role == Atspi.Role.PUSH_BUTTON_MENU
@staticmethod
def is_radio_button(obj: Atspi.Accessible, role: Optional[Atspi.Role] = None) -> bool:
"""Returns True if obj has the radio button role"""
if role is None:
role = AXObject.get_role(obj)
return role == Atspi.Role.RADIO_BUTTON
@staticmethod
def is_radio_menu_item(obj: Atspi.Accessible, role: Optional[Atspi.Role] = None) -> bool:
"""Returns True if obj has the radio menu item role"""
if role is None:
role = AXObject.get_role(obj)
return role == Atspi.Role.RADIO_MENU_ITEM
@staticmethod
def is_rating(obj: Atspi.Accessible, role: Optional[Atspi.Role] = None) -> bool:
"""Returns True if obj has the rating role"""
if role is None:
role = AXObject.get_role(obj)
return role == Atspi.Role.RATING
@staticmethod
def is_redundant_object_role(obj: Atspi.Accessible, role: Optional[Atspi.Role] = None) -> bool:
"""Returns True if obj has the redundant object role"""
if role is None:
role = AXObject.get_role(obj)
return role == Atspi.Role.REDUNDANT_OBJECT
@staticmethod
def is_root_pane(obj: Atspi.Accessible, role: Optional[Atspi.Role] = None) -> bool:
"""Returns True if obj has the root pane role"""
if role is None:
role = AXObject.get_role(obj)
return role == Atspi.Role.ROOT_PANE
@staticmethod
def is_row_header(obj: Atspi.Accessible, role: Optional[Atspi.Role] = None) -> bool:
"""Returns True if obj has the row header role"""
if role is None:
role = AXObject.get_role(obj)
return role == Atspi.Role.ROW_HEADER
@staticmethod
def is_ruler(obj: Atspi.Accessible, role: Optional[Atspi.Role] = None) -> bool:
"""Returns True if obj has the ruler role"""
if role is None:
role = AXObject.get_role(obj)
return role == Atspi.Role.RULER
@staticmethod
def is_scroll_bar(obj: Atspi.Accessible, role: Optional[Atspi.Role] = None) -> bool:
"""Returns True if obj has the scrollbar role"""
if role is None:
role = AXObject.get_role(obj)
return role == Atspi.Role.SCROLL_BAR
@staticmethod
def is_scroll_pane(obj: Atspi.Accessible, role: Optional[Atspi.Role] = None) -> bool:
"""Returns True if obj has the scroll pane role"""
if role is None:
role = AXObject.get_role(obj)
return role == Atspi.Role.SCROLL_PANE
@staticmethod
def is_section(obj: Atspi.Accessible, role: Optional[Atspi.Role] = None) -> bool:
"""Returns True if obj has the section role"""
if role is None:
role = AXObject.get_role(obj)
return role == Atspi.Role.SECTION
@staticmethod
def is_separator(obj: Atspi.Accessible, role: Optional[Atspi.Role] = None) -> bool:
"""Returns True if obj has the separator role"""
if role is None:
role = AXObject.get_role(obj)
return role == Atspi.Role.SEPARATOR
@staticmethod
def is_single_line_autocomplete_entry(
obj: Atspi.Accessible, role: Optional[Atspi.Role] = None
) -> bool:
"""Returns True if obj has the entry role and single-line state"""
if not AXUtilitiesRole.is_single_line_entry(obj, role):
return False
return AXUtilitiesState.supports_autocompletion(obj)
@staticmethod
def is_single_line_entry(obj: Atspi.Accessible, role: Optional[Atspi.Role] = None) -> bool:
"""Returns True if obj has the entry role and the single-line state"""
if not AXUtilitiesState.is_single_line(obj):
return False
if AXUtilitiesRole.is_entry(obj, role):
return True
if AXUtilitiesRole.is_text(obj, role):
return AXUtilitiesState.is_editable(obj)
return False
@staticmethod
def is_slider(obj: Atspi.Accessible, role: Optional[Atspi.Role] = None) -> bool:
"""Returns True if obj has the slider role"""
if role is None:
role = AXObject.get_role(obj)
return role == Atspi.Role.SLIDER
@staticmethod
def is_spin_button(obj: Atspi.Accessible, role: Optional[Atspi.Role] = None) -> bool:
"""Returns True if obj has the spin button role"""
if role is None:
role = AXObject.get_role(obj)
return role == Atspi.Role.SPIN_BUTTON
@staticmethod
def is_split_pane(obj: Atspi.Accessible, role: Optional[Atspi.Role] = None) -> bool:
"""Returns True if obj has the split pane role"""
if role is None:
role = AXObject.get_role(obj)
return role == Atspi.Role.SPLIT_PANE
@staticmethod
def is_static(obj: Atspi.Accessible, role: Optional[Atspi.Role] = None) -> bool:
"""Returns True if obj has the static role"""
if role is None:
role = AXObject.get_role(obj)
return role == Atspi.Role.STATIC
@staticmethod
def is_status_bar(obj: Atspi.Accessible, role: Optional[Atspi.Role] = None) -> bool:
"""Returns True if obj has the statusbar role"""
if role is None:
role = AXObject.get_role(obj)
return role == Atspi.Role.STATUS_BAR
@staticmethod
def is_subscript(obj: Atspi.Accessible, role: Optional[Atspi.Role] = None) -> bool:
"""Returns True if obj has the subscript role"""
if role is None:
role = AXObject.get_role(obj)
return role == Atspi.Role.SUBSCRIPT
@staticmethod
def is_subscript_or_superscript(
obj: Atspi.Accessible, role: Optional[Atspi.Role] = None
) -> bool:
"""Returns True if obj has the subscript or superscript role"""
if role is None:
role = AXObject.get_role(obj)
return role in [Atspi.Role.SUBSCRIPT, Atspi.Role.SUPERSCRIPT]
@staticmethod
def is_suggestion(obj: Atspi.Accessible, role: Optional[Atspi.Role] = None) -> bool:
"""Returns True if obj has the suggestion role"""
if role is None:
role = AXObject.get_role(obj)
return role == Atspi.Role.SUGGESTION \
or "suggestion" in AXUtilitiesRole._get_xml_roles(obj)
@staticmethod
def is_superscript(obj: Atspi.Accessible, role: Optional[Atspi.Role] = None) -> bool:
"""Returns True if obj has the superscript role"""
if role is None:
role = AXObject.get_role(obj)
return role == Atspi.Role.SUPERSCRIPT
@staticmethod
def is_svg(obj: Atspi.Accessible) -> bool:
"""Returns True if obj is an svg."""
return AXUtilitiesRole._get_tag(obj) == "svg"
@staticmethod
def is_switch(obj: Atspi.Accessible, role: Optional[Atspi.Role] = None) -> bool:
"""Returns True if obj has the switch role."""
if role is None:
role = AXObject.get_role(obj)
# TODO - JD: Remove this check when dependencies are bumped to v2.56.
try:
if role == Atspi.Role.SWITCH:
return True
except AttributeError:
pass
return "switch" in AXUtilitiesRole._get_xml_roles(obj)
@staticmethod
def is_table(obj: Atspi.Accessible, role: Optional[Atspi.Role] = None) -> bool:
"""Returns True if obj has the table role"""
if role is None:
role = AXObject.get_role(obj)
return role == Atspi.Role.TABLE
@staticmethod
def is_table_cell(obj: Atspi.Accessible, role: Optional[Atspi.Role] = None) -> bool:
"""Returns True if obj has the table cell role"""
if role is None:
role = AXObject.get_role(obj)
return role == Atspi.Role.TABLE_CELL
@staticmethod
def is_table_cell_or_header(obj: Atspi.Accessible, role: Optional[Atspi.Role] = None) -> bool:
"""Returns True if obj has the table cell or a header-related role"""
roles = AXUtilitiesRole.get_table_cell_roles()
if role is None:
role = AXObject.get_role(obj)
return role in roles
@staticmethod
def is_table_column_header(obj: Atspi.Accessible, role: Optional[Atspi.Role] = None) -> bool:
"""Returns True if obj has the table column header role"""
if role is None:
role = AXObject.get_role(obj)
return role == Atspi.Role.TABLE_COLUMN_HEADER
@staticmethod
def is_table_header(obj: Atspi.Accessible, role: Optional[Atspi.Role] = None) -> bool:
"""Returns True if obj has a table header related role"""
roles = AXUtilitiesRole.get_table_header_roles()
if role is None:
role = AXObject.get_role(obj)
return role in roles
@staticmethod
def is_table_related(
obj: Atspi.Accessible,
role: Optional[Atspi.Role] = None,
include_caption: bool = False
) -> bool:
"""Returns True if obj has a table-related role"""
roles = AXUtilitiesRole.get_table_related_roles(include_caption)
if role is None:
role = AXObject.get_role(obj)
return role in roles
@staticmethod
def is_table_row(obj: Atspi.Accessible, role: Optional[Atspi.Role] = None) -> bool:
"""Returns True if obj has the table row role"""
if role is None:
role = AXObject.get_role(obj)
return role == Atspi.Role.TABLE_ROW
@staticmethod
def is_table_row_header(obj: Atspi.Accessible, role: Optional[Atspi.Role] = None) -> bool:
"""Returns True if obj has the table row header role"""
if role is None:
role = AXObject.get_role(obj)
return role == Atspi.Role.TABLE_ROW_HEADER
@staticmethod
def is_tearoff_menu_item(obj: Atspi.Accessible, role: Optional[Atspi.Role] = None) -> bool:
"""Returns True if obj has the tearoff menu item role"""
if role is None:
role = AXObject.get_role(obj)
return role == Atspi.Role.TEAROFF_MENU_ITEM
@staticmethod
def is_terminal(obj: Atspi.Accessible, role: Optional[Atspi.Role] = None) -> bool:
"""Returns True if obj has the terminal role"""
if role is None:
role = AXObject.get_role(obj)
return role == Atspi.Role.TERMINAL
@staticmethod
def is_text(obj: Atspi.Accessible, role: Optional[Atspi.Role] = None) -> bool:
"""Returns True if obj has the text role"""
if role is None:
role = AXObject.get_role(obj)
return role == Atspi.Role.TEXT
@staticmethod
def is_text_input(obj: Atspi.Accessible, role: Optional[Atspi.Role] = None) -> bool:
"""Returns True if obj has any role associated with textual input"""
roles = [Atspi.Role.ENTRY, Atspi.Role.PASSWORD_TEXT, Atspi.Role.SPIN_BUTTON]
if role is None:
role = AXObject.get_role(obj)
if role in roles:
return True
if role == Atspi.Role.TEXT:
return AXUtilitiesState.is_editable(obj) and AXUtilitiesState.is_single_line(obj)
if AXUtilitiesRole.is_editable_combo_box(obj):
return True
return False
@staticmethod
def is_text_input_date(obj: Atspi.Accessible, role: Optional[Atspi.Role] = None) -> bool:
"""Returns True if obj is a date text input"""
if not AXUtilitiesRole.is_text_input(obj, role):
return False
attrs = AXObject.get_attributes_dict(obj)
return attrs.get("text-input-type") == "date"
@staticmethod
def is_text_input_email(obj: Atspi.Accessible, role: Optional[Atspi.Role] = None) -> bool:
"""Returns True if obj is an email text input"""
if not AXUtilitiesRole.is_text_input(obj, role):
return False
attrs = AXObject.get_attributes_dict(obj)
return attrs.get("text-input-type") == "email"
@staticmethod
def is_text_input_number(obj: Atspi.Accessible, role: Optional[Atspi.Role] = None) -> bool:
"""Returns True if obj is a numeric text input"""
if not AXUtilitiesRole.is_text_input(obj, role):
return False
attrs = AXObject.get_attributes_dict(obj)
return attrs.get("text-input-type") == "number"
@staticmethod
def is_text_input_search(obj: Atspi.Accessible, role: Optional[Atspi.Role] = None) -> bool:
"""Returns True if obj is a telephone text input"""
if not AXUtilitiesRole.is_text_input(obj, role):
return False
attrs = AXObject.get_attributes_dict(obj)
if attrs.get("text-input-type") == "search":
return True
if "searchbox" in AXUtilitiesRole._get_xml_roles(obj):
return True
ax_id = AXObject.get_accessible_id(obj).lower()
if ax_id:
return "search" in ax_id or "find" in ax_id
child = AXObject.get_child(obj, 0)
if AXUtilitiesRole.is_icon(child) or AXUtilitiesRole.is_image(child):
child_id = AXObject.get_accessible_id(child).lower()
if "search" in child_id or "find" in child_id:
return True
# Some toolkits don't localize the symbolic icon names, so it's worth a try.
child_name = AXObject.get_name(child).lower()
return "search" in child_name or "find" in child_name
return False
@staticmethod
def is_text_input_telephone(obj: Atspi.Accessible, role: Optional[Atspi.Role] = None) -> bool:
"""Returns True if obj is a telephone text input"""
if not AXUtilitiesRole.is_text_input(obj, role):
return False
attrs = AXObject.get_attributes_dict(obj)
return attrs.get("text-input-type") == "telephone"
@staticmethod
def is_text_input_time(obj: Atspi.Accessible, role: Optional[Atspi.Role] = None) -> bool:
"""Returns True if obj is a time text input"""
if not AXUtilitiesRole.is_text_input(obj, role):
return False
attrs = AXObject.get_attributes_dict(obj)
return attrs.get("text-input-type") == "time"
@staticmethod
def is_text_input_url(obj: Atspi.Accessible, role: Optional[Atspi.Role] = None) -> bool:
"""Returns True if obj is a url text input"""
if not AXUtilitiesRole.is_text_input(obj, role):
return False
attrs = AXObject.get_attributes_dict(obj)
return attrs.get("text-input-type") == "url"
@staticmethod
def is_text_input_week(obj: Atspi.Accessible, role: Optional[Atspi.Role] = None) -> bool:
"""Returns True if obj is a week text input"""
if not AXUtilitiesRole.is_text_input(obj, role):
return False
attrs = AXObject.get_attributes_dict(obj)
return attrs.get("text-input-type") == "week"
@staticmethod
def is_time(obj: Atspi.Accessible, _role: Optional[Atspi.Role] = None) -> bool:
"""Returns True if obj has the time role"""
return "time" in AXUtilitiesRole._get_xml_roles(obj) \
or "time" == AXUtilitiesRole._get_tag(obj)
@staticmethod
def is_timer(obj: Atspi.Accessible, role: Optional[Atspi.Role] = None) -> bool:
"""Returns True if obj has the timer role"""
if role is None:
role = AXObject.get_role(obj)
return role == Atspi.Role.TIMER
@staticmethod
def is_title_bar(obj: Atspi.Accessible, role: Optional[Atspi.Role] = None) -> bool:
"""Returns True if obj has the titlebar role"""
if role is None:
role = AXObject.get_role(obj)
return role == Atspi.Role.TITLE_BAR
@staticmethod
def is_toggle_button(obj: Atspi.Accessible, role: Optional[Atspi.Role] = None) -> bool:
"""Returns True if obj has the toggle button role"""
if role is None:
role = AXObject.get_role(obj)
return role == Atspi.Role.TOGGLE_BUTTON
@staticmethod
def is_tool_bar(obj: Atspi.Accessible, role: Optional[Atspi.Role] = None) -> bool:
"""Returns True if obj has the toolbar role"""
if role is None:
role = AXObject.get_role(obj)
return role == Atspi.Role.TOOL_BAR
@staticmethod
def is_tool_tip(obj: Atspi.Accessible, role: Optional[Atspi.Role] = None) -> bool:
"""Returns True if obj has the tooltip role"""
if role is None:
role = AXObject.get_role(obj)
return role == Atspi.Role.TOOL_TIP
@staticmethod
def is_tree(obj: Atspi.Accessible, role: Optional[Atspi.Role] = None) -> bool:
"""Returns True if obj has the tree role"""
if role is None:
role = AXObject.get_role(obj)
return role == Atspi.Role.TREE
@staticmethod
def is_tree_or_tree_table(obj: Atspi.Accessible, role: Optional[Atspi.Role] = None) -> bool:
"""Returns True if obj has the tree or tree table role"""
if role is None:
role = AXObject.get_role(obj)
return role in [Atspi.Role.TREE, Atspi.Role.TREE_TABLE]
@staticmethod
def is_tree_related(obj: Atspi.Accessible, role: Optional[Atspi.Role] = None) -> bool:
"""Returns True if obj has a tree-related role"""
roles = [Atspi.Role.TREE,
Atspi.Role.TREE_ITEM,
Atspi.Role.TREE_TABLE]
if role is None:
role = AXObject.get_role(obj)
return role in roles
@staticmethod
def is_tree_item(obj: Atspi.Accessible, role: Optional[Atspi.Role] = None) -> bool:
"""Returns True if obj has the tree item role"""
if role is None:
role = AXObject.get_role(obj)
return role == Atspi.Role.TREE_ITEM
@staticmethod
def is_tree_table(obj: Atspi.Accessible, role: Optional[Atspi.Role] = None) -> bool:
"""Returns True if obj has the tree table role"""
if role is None:
role = AXObject.get_role(obj)
return role == Atspi.Role.TREE_TABLE
@staticmethod
def is_unknown(obj: Atspi.Accessible, role: Optional[Atspi.Role] = None) -> bool:
"""Returns True if obj has the unknown role"""
if role is None:
role = AXObject.get_role(obj)
return role == Atspi.Role.UNKNOWN
@staticmethod
def is_unknown_or_redundant(obj: Atspi.Accessible, role: Optional[Atspi.Role] = None) -> bool:
"""Returns True if obj has the unknown or redundant object role"""
if role is None:
role = AXObject.get_role(obj)
return role in [Atspi.Role.UNKNOWN, Atspi.Role.REDUNDANT_OBJECT]
@staticmethod
def is_vertical_scrollbar(obj: Atspi.Accessible, role: Optional[Atspi.Role] = None) -> bool:
"""Returns True if obj is a vertical scrollbar"""
return AXUtilitiesRole.is_scroll_bar(obj, role) \
and AXObject.has_state(obj, Atspi.StateType.VERTICAL)
@staticmethod
def is_vertical_separator(obj: Atspi.Accessible, role: Optional[Atspi.Role] = None) -> bool:
"""Returns True if obj is a vertical separator"""
return AXUtilitiesRole.is_separator(obj, role) \
and AXObject.has_state(obj, Atspi.StateType.VERTICAL)
@staticmethod
def is_vertical_slider(obj: Atspi.Accessible, role: Optional[Atspi.Role] = None) -> bool:
"""Returns True if obj is a vertical slider"""
return AXUtilitiesRole.is_slider(obj, role) \
and AXObject.has_state(obj, Atspi.StateType.VERTICAL)
@staticmethod
def is_video(obj: Atspi.Accessible, role: Optional[Atspi.Role] = None) -> bool:
"""Returns True if obj has the video role"""
if role is None:
role = AXObject.get_role(obj)
return role == Atspi.Role.VIDEO
@staticmethod
def is_viewport(obj: Atspi.Accessible, role: Optional[Atspi.Role] = None) -> bool:
"""Returns True if obj has the viewport role"""
if role is None:
role = AXObject.get_role(obj)
return role == Atspi.Role.VIEWPORT
@staticmethod
def is_web_element(obj: Atspi.Accessible, exclude_pseudo_elements: bool = True) -> bool:
"""Returns True if obj is a web element"""
tag = AXUtilitiesRole._get_tag(obj)
if not tag:
return False
if not exclude_pseudo_elements:
return True
exclude = ["::before", "::after", "::marker"]
return tag not in exclude
@staticmethod
def is_web_element_custom(obj: Atspi.Accessible) -> bool:
"""Returns True if obj is a custom web element"""
tag = AXUtilitiesRole._get_tag(obj)
return tag is not None and "-" in tag
@staticmethod
def is_widget(obj: Atspi.Accessible, role: Optional[Atspi.Role] = None) -> bool:
"""Returns True if obj has a widget role"""
if role is None:
role = AXObject.get_role(obj)
return role in AXUtilitiesRole.get_widget_roles()
@staticmethod
def is_widget_controlled_by_line_navigation(
obj: Atspi.Accessible, role: Optional[Atspi.Role] = None
) -> bool:
"""Returns True if obj is a widget controlled by line navigation"""
if role is None:
role = AXObject.get_role(obj)
roles = [Atspi.Role.COMBO_BOX,
Atspi.Role.LIST_BOX,
Atspi.Role.MENU,
Atspi.Role.SPIN_BUTTON,
Atspi.Role.TREE,
Atspi.Role.TREE_TABLE]
if role in roles:
return True
if AXUtilitiesState.is_editable(obj) or AXUtilitiesState.is_selectable(obj):
return AXObject.find_ancestor(obj, lambda x: AXObject.get_role(x) in roles) is not None
if not AXUtilitiesState.is_vertical(obj):
return False
return role in [Atspi.Role.SCROLL_BAR,
Atspi.Role.SEPARATOR,
Atspi.Role.SLIDER,
Atspi.Role.SPLIT_PANE]
@staticmethod
def is_window(obj: Atspi.Accessible, role: Optional[Atspi.Role] = None) -> bool:
"""Returns True if obj has the window role"""
if role is None:
role = AXObject.get_role(obj)
return role == Atspi.Role.WINDOW