office-gobmx/vcl/osx/a11yrolehelper.mm
Michael Weghorn f44eae4912 tdf#135586 a11y: Add a new BLOCK_QUOTE a11y role
A block quote role exists in all of WAI-ARIA 1.3
(role "blockquote", [1]), IAccessible2
(`IA2_ROLE_BLOCK_QUOTE`,  [2]) and AT-SPI
(`ROLE_BLOCK_QUOTE`, [3]).

Take over the definition that is the same in WAI-ARIA
and IAccessible2:

> A section of content that is quoted from another source.

The intended use for now is for a Writer paragraph using
the "Block Quotation" paragraph style, similar to how the
HEADING role is used for paragraphs using a corresponding
paragraph style.

For gtk3 (ATK) and winaccessibility (IAccessible2),
map the new role to the equivalant roles.

For macOS and the gtk4 as well as the Qt-based VCL plugins
on Linux which currently don't have an equivalent role,
fall back to the same role that the PARAGRAPH role is
mapped to.
This way, the behavior there will remain unchanged
once the BLOCK_QUOTE role is used for Writer paragraphs
with the corresponding style.

In general, treat BLOCK_QUOTE like PARAGRAPH
in code applying special handling for the PARAGRAPH
role.

[1] https://w3c.github.io/aria/#blockquote
[2] 3d8c7f0b83/api/AccessibleRole.idl (L318)
[3] 7cc4cee53d/xml/Accessible.xml (L615-616)

Change-Id: I248c183a2e7ec5d6f0a89bf3cb4829bbd8588c77
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/158573
Tested-by: Jenkins
Reviewed-by: Michael Weghorn <m.weghorn@posteo.de>
2023-10-28 05:45:15 +02:00

296 lines
15 KiB
Text

/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
* This file is part of the LibreOffice project.
*
* 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/.
*
* This file incorporates work covered by the following license notice:
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed
* with this work for additional information regarding copyright
* ownership. The ASF licenses this file to you under the Apache
* License, Version 2.0 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.apache.org/licenses/LICENSE-2.0 .
*/
#include <osx/a11yfactory.h>
#include "a11yrolehelper.h"
#include <com/sun/star/accessibility/AccessibleRole.hpp>
#include <com/sun/star/accessibility/AccessibleStateType.hpp>
#include <com/sun/star/lang/IndexOutOfBoundsException.hpp>
#include <sal/log.hxx>
using namespace ::com::sun::star::accessibility;
using namespace ::com::sun::star::lang;
using namespace ::com::sun::star::uno;
@implementation AquaA11yRoleHelper
+(id)simpleMapNativeRoleFrom: (XAccessibleContext *) accessibleContext {
id nativeRole = nil;
if (accessibleContext == nullptr)
return nativeRole;
switch( accessibleContext -> getAccessibleRole() ) {
#define MAP(a,b) \
case a: nativeRole = b; break
MAP( AccessibleRole::UNKNOWN, NSAccessibilityUnknownRole );
MAP( AccessibleRole::ALERT, NSAccessibilityUnknownRole ); // FIXME
MAP( AccessibleRole::BLOCK_QUOTE, NSAccessibilityTextAreaRole );
MAP( AccessibleRole::COLUMN_HEADER, NSAccessibilityColumnRole );
MAP( AccessibleRole::CANVAS, NSAccessibilityUnknownRole ); // FIXME
MAP( AccessibleRole::CHECK_BOX, NSAccessibilityCheckBoxRole );
MAP( AccessibleRole::CHECK_MENU_ITEM, NSAccessibilityUnknownRole ); // FIXME
MAP( AccessibleRole::COLOR_CHOOSER, NSAccessibilityColorWellRole ); // FIXME
MAP( AccessibleRole::COMBO_BOX, NSAccessibilityComboBoxRole );
MAP( AccessibleRole::DATE_EDITOR, NSAccessibilityUnknownRole ); // FIXME
MAP( AccessibleRole::DESKTOP_ICON, NSAccessibilityUnknownRole ); // FIXME
MAP( AccessibleRole::DESKTOP_PANE, NSAccessibilityUnknownRole ); // FIXME
MAP( AccessibleRole::DIRECTORY_PANE, NSAccessibilityUnknownRole ); // FIXME
MAP( AccessibleRole::DIALOG, NSAccessibilityGroupRole );
MAP( AccessibleRole::DOCUMENT, NSAccessibilityGroupRole );
MAP( AccessibleRole::EMBEDDED_OBJECT, NSAccessibilityUnknownRole ); // FIXME
MAP( AccessibleRole::END_NOTE, NSAccessibilityUnknownRole ); // FIXME
MAP( AccessibleRole::FILE_CHOOSER, NSAccessibilityUnknownRole ); // FIXME
MAP( AccessibleRole::FILLER, NSAccessibilityUnknownRole ); // FIXME
MAP( AccessibleRole::FONT_CHOOSER, NSAccessibilityUnknownRole ); // FIXME
MAP( AccessibleRole::FOOTER, NSAccessibilityGroupRole ); // FIXME
MAP( AccessibleRole::FOOTNOTE, NSAccessibilityUnknownRole ); // FIXME
MAP( AccessibleRole::FRAME, NSAccessibilityWindowRole );
MAP( AccessibleRole::GLASS_PANE, NSAccessibilityUnknownRole ); // FIXME
MAP( AccessibleRole::GRAPHIC, NSAccessibilityImageRole );
MAP( AccessibleRole::GROUP_BOX, NSAccessibilityGroupRole );
MAP( AccessibleRole::HEADER, NSAccessibilityGroupRole ); // FIXME
MAP( AccessibleRole::HEADING, NSAccessibilityTextAreaRole ); // FIXME
MAP( AccessibleRole::HYPER_LINK, NSAccessibilityLinkRole );
MAP( AccessibleRole::ICON, NSAccessibilityImageRole );
MAP( AccessibleRole::INTERNAL_FRAME, NSAccessibilityUnknownRole ); // FIXME
MAP( AccessibleRole::LABEL, NSAccessibilityStaticTextRole );
MAP( AccessibleRole::LAYERED_PANE, NSAccessibilityUnknownRole ); // FIXME
MAP( AccessibleRole::LIST, NSAccessibilityMenuRole );
MAP( AccessibleRole::LIST_ITEM, NSAccessibilityMenuItemRole );
MAP( AccessibleRole::MENU, NSAccessibilityMenuRole );
MAP( AccessibleRole::MENU_BAR, NSAccessibilityMenuBarRole );
MAP( AccessibleRole::MENU_ITEM, NSAccessibilityMenuItemRole );
MAP( AccessibleRole::OPTION_PANE, NSAccessibilityUnknownRole ); // FIXME
MAP( AccessibleRole::PAGE_TAB, NSAccessibilityButtonRole );
MAP( AccessibleRole::PAGE_TAB_LIST, NSAccessibilityTabGroupRole );
MAP( AccessibleRole::PANEL, NSAccessibilityGroupRole );
MAP( AccessibleRole::PARAGRAPH, NSAccessibilityTextAreaRole );
MAP( AccessibleRole::PASSWORD_TEXT, NSAccessibilityTextFieldRole );
MAP( AccessibleRole::POPUP_MENU, NSAccessibilityMenuRole );
MAP( AccessibleRole::PUSH_BUTTON, NSAccessibilityButtonRole );
MAP( AccessibleRole::PROGRESS_BAR, NSAccessibilityProgressIndicatorRole );
MAP( AccessibleRole::RADIO_BUTTON, NSAccessibilityRadioButtonRole );
MAP( AccessibleRole::RADIO_MENU_ITEM, NSAccessibilityUnknownRole ); // FIXME
MAP( AccessibleRole::ROW_HEADER, NSAccessibilityRowRole );
MAP( AccessibleRole::ROOT_PANE, NSAccessibilityUnknownRole ); // FIXME
MAP( AccessibleRole::SCROLL_BAR, NSAccessibilityScrollBarRole );
MAP( AccessibleRole::SCROLL_PANE, NSAccessibilityScrollAreaRole );
MAP( AccessibleRole::SHAPE, NSAccessibilityUnknownRole ); // FIXME
MAP( AccessibleRole::SEPARATOR, NSAccessibilitySplitterRole ); // FIXME
MAP( AccessibleRole::SLIDER, NSAccessibilitySliderRole );
MAP( AccessibleRole::SPIN_BOX, NSAccessibilityUnknownRole ); // FIXME
MAP( AccessibleRole::SPLIT_PANE, NSAccessibilitySplitGroupRole );
MAP( AccessibleRole::STATUS_BAR, NSAccessibilityGroupRole ); // FIXME
MAP( AccessibleRole::TABLE, NSAccessibilityTableRole );
MAP( AccessibleRole::TABLE_CELL, NSAccessibilityTextFieldRole );
MAP( AccessibleRole::TEXT, NSAccessibilityTextAreaRole );
MAP( AccessibleRole::TEXT_FRAME, NSAccessibilityGroupRole );
MAP( AccessibleRole::TOGGLE_BUTTON, NSAccessibilityCheckBoxRole );
MAP( AccessibleRole::TOOL_BAR, NSAccessibilityToolbarRole );
MAP( AccessibleRole::TOOL_TIP, NSAccessibilityUnknownRole ); // FIXME
MAP( AccessibleRole::TREE, NSAccessibilityGroupRole );
MAP( AccessibleRole::VIEW_PORT, NSAccessibilityUnknownRole ); // FIXME
MAP( AccessibleRole::WINDOW, NSAccessibilityWindowRole );
MAP( AccessibleRole::BUTTON_DROPDOWN, NSAccessibilityMenuButtonRole );
MAP( AccessibleRole::BUTTON_MENU, NSAccessibilityMenuButtonRole );
MAP( AccessibleRole::CAPTION, NSAccessibilityUnknownRole );
MAP( AccessibleRole::CHART, NSAccessibilityUnknownRole );
MAP( AccessibleRole::FORM, NSAccessibilityUnknownRole );
MAP( AccessibleRole::IMAGE_MAP, NSAccessibilityUnknownRole );
MAP( AccessibleRole::NOTE, NSAccessibilityUnknownRole );
MAP( AccessibleRole::PAGE, NSAccessibilityUnknownRole );
MAP( AccessibleRole::RULER, NSAccessibilityUnknownRole );
MAP( AccessibleRole::SECTION, NSAccessibilityUnknownRole );
MAP( AccessibleRole::TREE_ITEM, NSAccessibilityUnknownRole );
MAP( AccessibleRole::TREE_TABLE, NSAccessibilityUnknownRole );
MAP( AccessibleRole::DOCUMENT_PRESENTATION, NSAccessibilityGroupRole );
MAP( AccessibleRole::DOCUMENT_SPREADSHEET, NSAccessibilityGroupRole );
MAP( AccessibleRole::DOCUMENT_TEXT, NSAccessibilityGroupRole );
MAP( AccessibleRole::STATIC, NSAccessibilityStaticTextRole );
MAP( AccessibleRole::NOTIFICATION, NSAccessibilityStaticTextRole );
#undef MAP
default:
break;
}
return nativeRole;
}
+(id)getNativeRoleFrom: (XAccessibleContext *) accessibleContext {
id nativeRole = [ AquaA11yRoleHelper simpleMapNativeRoleFrom: accessibleContext ];
if ( accessibleContext -> getAccessibleRole() == AccessibleRole::LABEL ) {
if ( accessibleContext -> getAccessibleChildCount() > 0 ) {
[ nativeRole release ];
nativeRole = NSAccessibilityOutlineRole;
} else if ( accessibleContext -> getAccessibleParent().is() ) {
Reference < XAccessibleContext > rxParentContext = accessibleContext -> getAccessibleParent() -> getAccessibleContext();
if ( rxParentContext.is() ) {
NSString * roleParent = static_cast<NSString *>([ AquaA11yRoleHelper simpleMapNativeRoleFrom: rxParentContext.get() ]);
if ( [ roleParent isEqualToString: NSAccessibilityOutlineRole ] ) {
[ nativeRole release ];
nativeRole = NSAccessibilityRowRole;
}
[ roleParent release ];
}
}
} else if ( accessibleContext -> getAccessibleRole() == AccessibleRole::COMBO_BOX ) {
try {
Reference < XAccessible > rxAccessible = accessibleContext -> getAccessibleChild(0);
if ( rxAccessible.is() ) {
Reference < XAccessibleContext > rxAccessibleContext = rxAccessible -> getAccessibleContext();
if ( rxAccessibleContext.is() && rxAccessibleContext -> getAccessibleRole() == AccessibleRole::TEXT ) {
sal_Int64 nStateSet = rxAccessibleContext -> getAccessibleStateSet();
if ( !(nStateSet & AccessibleStateType::EDITABLE ) ) {
[ nativeRole release ];
nativeRole = NSAccessibilityPopUpButtonRole;
}
}
}
}
catch (const IndexOutOfBoundsException&)
{
SAL_WARN("vcl", "No valid accessible objects in parent");
}
}
return nativeRole;
}
+(id)getNativeSubroleFrom: (sal_Int16) nRole {
id nativeSubrole = nil;
switch( nRole ) {
#define MAP(a,b) \
case a: nativeSubrole = b; break
MAP( AccessibleRole::UNKNOWN, NSAccessibilityUnknownSubrole );
MAP( AccessibleRole::ALERT, NSAccessibilitySystemDialogSubrole );
MAP( AccessibleRole::BLOCK_QUOTE, @"" );
MAP( AccessibleRole::COLUMN_HEADER, @"" );
MAP( AccessibleRole::CANVAS, @"" );
MAP( AccessibleRole::CHECK_BOX, @"" );
MAP( AccessibleRole::CHECK_MENU_ITEM, @"" );
MAP( AccessibleRole::COLOR_CHOOSER, @"" );
MAP( AccessibleRole::COMBO_BOX, @"" );
MAP( AccessibleRole::DATE_EDITOR, @"" );
MAP( AccessibleRole::DESKTOP_ICON, @"" );
MAP( AccessibleRole::DESKTOP_PANE, @"" );
MAP( AccessibleRole::DIRECTORY_PANE, @"" );
MAP( AccessibleRole::DIALOG, NSAccessibilityDialogSubrole );
MAP( AccessibleRole::DOCUMENT, @"" );
MAP( AccessibleRole::EMBEDDED_OBJECT, @"" );
MAP( AccessibleRole::END_NOTE, @"" );
MAP( AccessibleRole::FILE_CHOOSER, @"" );
MAP( AccessibleRole::FILLER, @"" );
MAP( AccessibleRole::FONT_CHOOSER, @"" );
MAP( AccessibleRole::FOOTER, @"" );
MAP( AccessibleRole::FOOTNOTE, @"" );
MAP( AccessibleRole::FRAME, @"" );
MAP( AccessibleRole::GLASS_PANE, @"" );
MAP( AccessibleRole::GRAPHIC, @"" );
MAP( AccessibleRole::GROUP_BOX, @"" );
MAP( AccessibleRole::HEADER, @"" );
MAP( AccessibleRole::HEADING, @"" );
MAP( AccessibleRole::HYPER_LINK, NSAccessibilityTextLinkSubrole );
MAP( AccessibleRole::ICON, @"" );
MAP( AccessibleRole::INTERNAL_FRAME, @"" );
MAP( AccessibleRole::LABEL, @"" );
MAP( AccessibleRole::LAYERED_PANE, @"" );
MAP( AccessibleRole::LIST, @"" );
MAP( AccessibleRole::LIST_ITEM, NSAccessibilityOutlineRowSubrole );
MAP( AccessibleRole::MENU, @"" );
MAP( AccessibleRole::MENU_BAR, @"" );
MAP( AccessibleRole::MENU_ITEM, @"" );
MAP( AccessibleRole::OPTION_PANE, @"" );
MAP( AccessibleRole::PAGE_TAB, @"" );
MAP( AccessibleRole::PAGE_TAB_LIST, @"" );
MAP( AccessibleRole::PANEL, @"" );
MAP( AccessibleRole::PARAGRAPH, @"" );
MAP( AccessibleRole::PASSWORD_TEXT, NSAccessibilitySecureTextFieldSubrole );
MAP( AccessibleRole::POPUP_MENU, @"" );
MAP( AccessibleRole::PUSH_BUTTON, @"" );
MAP( AccessibleRole::PROGRESS_BAR, @"" );
MAP( AccessibleRole::RADIO_BUTTON, @"" );
MAP( AccessibleRole::RADIO_MENU_ITEM, @"" );
MAP( AccessibleRole::ROW_HEADER, @"" );
MAP( AccessibleRole::ROOT_PANE, @"" );
MAP( AccessibleRole::SCROLL_BAR, @"" );
MAP( AccessibleRole::SCROLL_PANE, @"" );
MAP( AccessibleRole::SHAPE, @"" );
MAP( AccessibleRole::SEPARATOR, @"" );
MAP( AccessibleRole::SLIDER, @"" );
MAP( AccessibleRole::SPIN_BOX, @"" );
MAP( AccessibleRole::SPLIT_PANE, @"" );
MAP( AccessibleRole::STATUS_BAR, @"" );
MAP( AccessibleRole::TABLE, @"" );
MAP( AccessibleRole::TABLE_CELL, @"" );
MAP( AccessibleRole::TEXT, @"" );
MAP( AccessibleRole::TEXT_FRAME, @"" );
MAP( AccessibleRole::TOGGLE_BUTTON, @"" );
MAP( AccessibleRole::TOOL_BAR, @"" );
MAP( AccessibleRole::TOOL_TIP, @"" );
MAP( AccessibleRole::TREE, @"" );
MAP( AccessibleRole::VIEW_PORT, @"" );
MAP( AccessibleRole::WINDOW, NSAccessibilityStandardWindowSubrole );
MAP( AccessibleRole::BUTTON_DROPDOWN, @"" );
MAP( AccessibleRole::BUTTON_MENU, @"" );
MAP( AccessibleRole::CAPTION, @"" );
MAP( AccessibleRole::CHART, @"" );
MAP( AccessibleRole::FORM, @"" );
MAP( AccessibleRole::IMAGE_MAP, @"" );
MAP( AccessibleRole::NOTE, @"" );
MAP( AccessibleRole::PAGE, @"" );
MAP( AccessibleRole::RULER, @"" );
MAP( AccessibleRole::SECTION, @"" );
MAP( AccessibleRole::TREE_ITEM, @"" );
MAP( AccessibleRole::TREE_TABLE, @"" );
MAP( AccessibleRole::DOCUMENT_PRESENTATION, @"" );
MAP( AccessibleRole::DOCUMENT_SPREADSHEET, @"" );
MAP( AccessibleRole::DOCUMENT_TEXT, @"" );
MAP( AccessibleRole::STATIC, @"" );
MAP( AccessibleRole::NOTIFICATION, @"" );
#undef MAP
default:
break;
}
return nativeSubrole;
}
+(id)getRoleDescriptionFrom: (NSString *) role with: (NSString *) subRole {
id roleDescription;
if ( [ subRole length ] == 0 )
roleDescription = NSAccessibilityRoleDescription( role, nil );
else
roleDescription = NSAccessibilityRoleDescription( role, subRole );
return roleDescription;
}
@end
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */