mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 814836 - <xul:deck> element messes up screen readers, r=tbsaunde, sr=roc
This commit is contained in:
parent
091db0d136
commit
4bb31ec532
@ -62,8 +62,8 @@ interface nsIAccessibleProvider : nsISupports
|
||||
const long XULTab = 0x00001017;
|
||||
/** Used for XUL tabs element, a container for tab elements */
|
||||
const long XULTabs = 0x00001018;
|
||||
/** Used for XUL deck frame */
|
||||
const long XULDeck = 0x00001019;
|
||||
/** Used for XUL tabpanels element */
|
||||
const long XULTabpanels = 0x00001019;
|
||||
|
||||
const long XULText = 0x0000101A;
|
||||
const long XULTextBox = 0x0000101B;
|
||||
|
@ -52,7 +52,7 @@ enum AccType {
|
||||
eMenuPopupType,
|
||||
eProgressType,
|
||||
eRootType,
|
||||
eXULDeckType,
|
||||
eXULTabpanelsType,
|
||||
eXULTreeType,
|
||||
|
||||
eLastAccType = eXULTreeType
|
||||
|
@ -60,6 +60,7 @@
|
||||
#include "mozilla/Preferences.h"
|
||||
#include "mozilla/Services.h"
|
||||
#include "mozilla/Util.h"
|
||||
#include "nsDeckFrame.h"
|
||||
|
||||
#ifdef MOZ_XUL
|
||||
#include "XULAlertAccessible.h"
|
||||
@ -254,6 +255,47 @@ nsAccessibilityService::CreatePluginAccessible(nsObjectFrame* aFrame,
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void
|
||||
nsAccessibilityService::DeckPanelSwitched(nsIPresShell* aPresShell,
|
||||
nsIContent* aDeckNode,
|
||||
nsIFrame* aPrevBoxFrame,
|
||||
nsIFrame* aCurrentBoxFrame)
|
||||
{
|
||||
// Ignore tabpanels elements (a deck having an accessible) since their
|
||||
// children are accessible not depending on selected tab.
|
||||
DocAccessible* document = GetDocAccessible(aPresShell);
|
||||
if (!document || document->HasAccessible(aDeckNode))
|
||||
return;
|
||||
|
||||
if (aPrevBoxFrame) {
|
||||
nsIContent* panelNode = aPrevBoxFrame->GetContent();
|
||||
#ifdef A11Y_LOG
|
||||
if (logging::IsEnabled(logging::eTree)) {
|
||||
logging::MsgBegin("TREE", "deck panel unselected");
|
||||
logging::Node("container", panelNode);
|
||||
logging::Node("content", aDeckNode);
|
||||
logging::MsgEnd();
|
||||
}
|
||||
#endif
|
||||
|
||||
document->ContentRemoved(aDeckNode, panelNode);
|
||||
}
|
||||
|
||||
if (aCurrentBoxFrame) {
|
||||
nsIContent* panelNode = aCurrentBoxFrame->GetContent();
|
||||
#ifdef A11Y_LOG
|
||||
if (logging::IsEnabled(logging::eTree)) {
|
||||
logging::MsgBegin("TREE", "deck panel selected");
|
||||
logging::Node("container", panelNode);
|
||||
logging::Node("content", aDeckNode);
|
||||
logging::MsgEnd();
|
||||
}
|
||||
#endif
|
||||
|
||||
document->ContentInserted(aDeckNode, panelNode, panelNode->GetNextSibling());
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
nsAccessibilityService::ContentRangeInserted(nsIPresShell* aPresShell,
|
||||
nsIContent* aContainer,
|
||||
@ -843,28 +885,43 @@ nsAccessibilityService::GetOrCreateAccessible(nsINode* aNode,
|
||||
}
|
||||
}
|
||||
|
||||
if (!newAcc) {
|
||||
// Accessible XBL types and deck stuff are used in XUL only currently.
|
||||
if (!newAcc && content->IsXUL()) {
|
||||
// No accessible for not selected deck panel and its children.
|
||||
if (!aContext->IsXULTabpanels()) {
|
||||
nsDeckFrame* deckFrame = do_QueryFrame(frame->GetParent());
|
||||
if (deckFrame && deckFrame->GetSelectedBox() != frame) {
|
||||
if (aIsSubtreeHidden)
|
||||
*aIsSubtreeHidden = true;
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
// Elements may implement nsIAccessibleProvider via XBL. This allows them to
|
||||
// say what kind of accessible to create.
|
||||
newAcc = CreateAccessibleByType(content, document);
|
||||
|
||||
// Any XUL box can be used as tabpanel, make sure we create a proper
|
||||
// accessible for it.
|
||||
if (!newAcc && aContext->IsXULTabpanels() &&
|
||||
content->GetParent() == aContext->GetContent()) {
|
||||
nsIAtom* frameType = frame->GetType();
|
||||
if (frameType == nsGkAtoms::boxFrame ||
|
||||
frameType == nsGkAtoms::scrollFrame) {
|
||||
newAcc = new XULTabpanelAccessible(content, document);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!newAcc) {
|
||||
// xul:deck does not have XBL and nsIFrame::CreateAccessible() is only called
|
||||
// on HTML elements
|
||||
nsIAtom* tag = content->Tag();
|
||||
if ((tag == nsGkAtoms::deck) || (tag == nsGkAtoms::tabpanels)) {
|
||||
newAcc = new XULDeckAccessible(content, document);
|
||||
} else if (content->IsSVG(nsGkAtoms::svg)) {
|
||||
if (content->IsSVG(nsGkAtoms::svg)) {
|
||||
newAcc = new EnumRoleAccessible(content, document, roles::DIAGRAM);
|
||||
} else if (content->IsMathML(nsGkAtoms::math)) {
|
||||
newAcc = new EnumRoleAccessible(content, document, roles::EQUATION);
|
||||
}
|
||||
}
|
||||
|
||||
if (!newAcc)
|
||||
newAcc = CreateAccessibleForDeckChild(frame, content, document);
|
||||
|
||||
// If no accessible, see if we need to create a generic accessible because
|
||||
// of some property that makes this object interesting
|
||||
// We don't do this for <body>, <html>, <window>, <dialog> etc. which
|
||||
@ -1011,8 +1068,8 @@ nsAccessibilityService::CreateAccessibleByType(nsIContent* aContent,
|
||||
accessible = new XULComboboxAccessible(aContent, aDoc);
|
||||
break;
|
||||
|
||||
case nsIAccessibleProvider::XULDeck:
|
||||
accessible = new XULDeckAccessible(aContent, aDoc);
|
||||
case nsIAccessibleProvider::XULTabpanels:
|
||||
accessible = new XULTabpanelsAccessible(aContent, aDoc);
|
||||
break;
|
||||
|
||||
case nsIAccessibleProvider::XULDropmarker:
|
||||
@ -1480,37 +1537,6 @@ NS_GetAccessibilityService(nsIAccessibilityService** aResult)
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// nsAccessibilityService private (DON'T put methods here)
|
||||
|
||||
already_AddRefed<Accessible>
|
||||
nsAccessibilityService::CreateAccessibleForDeckChild(nsIFrame* aFrame,
|
||||
nsIContent* aContent,
|
||||
DocAccessible* aDoc)
|
||||
{
|
||||
if (aFrame->GetType() == nsGkAtoms::boxFrame ||
|
||||
aFrame->GetType() == nsGkAtoms::scrollFrame) {
|
||||
|
||||
nsIFrame* parentFrame = aFrame->GetParent();
|
||||
if (parentFrame && parentFrame->GetType() == nsGkAtoms::deckFrame) {
|
||||
// If deck frame is for xul:tabpanels element then the given node has
|
||||
// tabpanel accessible.
|
||||
nsIContent* parentContent = parentFrame->GetContent();
|
||||
#ifdef MOZ_XUL
|
||||
if (parentContent->NodeInfo()->Equals(nsGkAtoms::tabpanels,
|
||||
kNameSpaceID_XUL)) {
|
||||
Accessible* accessible = new XULTabpanelAccessible(aContent, aDoc);
|
||||
NS_ADDREF(accessible);
|
||||
return accessible;
|
||||
}
|
||||
#endif
|
||||
Accessible* accessible = new EnumRoleAccessible(aContent, aDoc,
|
||||
roles::PROPERTYPAGE);
|
||||
NS_ADDREF(accessible);
|
||||
return accessible;
|
||||
}
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
#ifdef MOZ_XUL
|
||||
already_AddRefed<Accessible>
|
||||
nsAccessibilityService::CreateAccessibleForXULTree(nsIContent* aContent,
|
||||
|
@ -64,6 +64,13 @@ public:
|
||||
virtual Accessible* AddNativeRootAccessible(void* aAtkAccessible);
|
||||
virtual void RemoveNativeRootAccessible(Accessible* aRootAccessible);
|
||||
|
||||
/**
|
||||
* Notification used to update the accessible tree when deck panel is
|
||||
* switched.
|
||||
*/
|
||||
void DeckPanelSwitched(nsIPresShell* aPresShell, nsIContent* aDeckNode,
|
||||
nsIFrame* aPrevBoxFrame, nsIFrame* aCurrentBoxFrame);
|
||||
|
||||
/**
|
||||
* Notification used to update the accessible tree when new content is
|
||||
* inserted.
|
||||
@ -173,13 +180,6 @@ private:
|
||||
CreateAccessibleByFrameType(nsIFrame* aFrame, nsIContent* aContent,
|
||||
Accessible* aContext);
|
||||
|
||||
/**
|
||||
* Create accessible if parent is a deck frame.
|
||||
*/
|
||||
already_AddRefed<Accessible>
|
||||
CreateAccessibleForDeckChild(nsIFrame* aFrame, nsIContent* aContent,
|
||||
DocAccessible* aDoc);
|
||||
|
||||
#ifdef MOZ_XUL
|
||||
/**
|
||||
* Create accessible for XUL tree element.
|
||||
|
@ -612,6 +612,7 @@ Accessible::VisibilityState()
|
||||
deckFrame->GetContent()->Tag() == nsGkAtoms::tabpanels)
|
||||
return states::OFFSCREEN;
|
||||
|
||||
NS_NOTREACHED("Children of not selected deck panel are not accessible.");
|
||||
return states::INVISIBLE;
|
||||
}
|
||||
|
||||
|
@ -520,7 +520,7 @@ public:
|
||||
bool IsTextLeaf() const { return mType == eTextLeafType; }
|
||||
TextLeafAccessible* AsTextLeaf();
|
||||
|
||||
bool IsXULDeck() const { return mType == eXULDeckType; }
|
||||
bool IsXULTabpanels() const { return mType == eXULTabpanelsType; }
|
||||
|
||||
bool IsXULTree() const { return mType == eXULTreeType; }
|
||||
XULTreeAccessible* AsXULTree();
|
||||
|
@ -60,9 +60,9 @@ AccessibleWrap::GetNativeType ()
|
||||
{
|
||||
NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NIL;
|
||||
|
||||
if (IsXULDeck())
|
||||
if (IsXULTabpanels())
|
||||
return [mozPaneAccessible class];
|
||||
|
||||
|
||||
roles::Role role = Role();
|
||||
switch (role) {
|
||||
case roles::PUSHBUTTON:
|
||||
|
@ -163,11 +163,11 @@ XULTabsAccessible::NativeName(nsString& aName)
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// XULDeckAccessible
|
||||
// XULTabpanelsAccessible
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
role
|
||||
XULDeckAccessible::NativeRole()
|
||||
XULTabpanelsAccessible::NativeRole()
|
||||
{
|
||||
return roles::PANE;
|
||||
}
|
||||
|
@ -62,12 +62,12 @@ protected:
|
||||
/**
|
||||
* A container of tab panels, xul:tabpanels element.
|
||||
*/
|
||||
class XULDeckAccessible : public AccessibleWrap
|
||||
class XULTabpanelsAccessible : public AccessibleWrap
|
||||
{
|
||||
public:
|
||||
XULDeckAccessible(nsIContent* aContent, DocAccessible* aDoc) :
|
||||
XULTabpanelsAccessible(nsIContent* aContent, DocAccessible* aDoc) :
|
||||
AccessibleWrap(aContent, aDoc)
|
||||
{ mType = eXULDeckType; }
|
||||
{ mType = eXULTabpanelsType; }
|
||||
|
||||
// Accessible
|
||||
virtual a11y::role NativeRole();
|
||||
|
@ -20,7 +20,6 @@
|
||||
<![CDATA[
|
||||
function doTest()
|
||||
{
|
||||
testStates("deck_pane1", STATE_INVISIBLE, 0, STATE_OFFSCREEN);
|
||||
testStates("deck_pane2", 0, 0, STATE_INVISIBLE | STATE_OFFSCREEN);
|
||||
testStates("tabs_pane1", 0, 0, STATE_INVISIBLE | STATE_OFFSCREEN);
|
||||
testStates("tabs_pane2", STATE_OFFSCREEN, 0, STATE_INVISIBLE);
|
||||
|
@ -17,6 +17,7 @@ MOCHITEST_A11Y_FILES =\
|
||||
test_colorpicker.xul \
|
||||
test_cssoverflow.html \
|
||||
test_contextmenu.xul \
|
||||
test_deck.xul \
|
||||
test_doc.html \
|
||||
test_gencontent.html \
|
||||
test_hidden.html \
|
||||
|
109
accessible/tests/mochitest/treeupdate/test_deck.xul
Normal file
109
accessible/tests/mochitest/treeupdate/test_deck.xul
Normal file
@ -0,0 +1,109 @@
|
||||
<?xml version="1.0"?>
|
||||
<?xml-stylesheet href="chrome://global/skin" type="text/css"?>
|
||||
<?xml-stylesheet href="chrome://mochikit/content/tests/SimpleTest/test.css"
|
||||
type="text/css"?>
|
||||
|
||||
<window xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
|
||||
title="Tree update on XUL deck panel switching">
|
||||
|
||||
<script type="application/javascript"
|
||||
src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js" />
|
||||
|
||||
<script type="application/javascript"
|
||||
src="../common.js" />
|
||||
<script type="application/javascript"
|
||||
src="../role.js" />
|
||||
<script type="application/javascript"
|
||||
src="../states.js" />
|
||||
<script type="application/javascript"
|
||||
src="../events.js" />
|
||||
|
||||
<script type="application/javascript">
|
||||
<![CDATA[
|
||||
function switchDeckPanel(aContainerID, aDeckID)
|
||||
{
|
||||
this.panelIndex = 0;
|
||||
|
||||
this.container = getAccessible(aContainerID);
|
||||
this.deckNode = getNode(aDeckID);
|
||||
this.prevPanel = getAccessible(this.deckNode.selectedPanel);
|
||||
this.panelNode = this.deckNode.childNodes[this.panelIndex];
|
||||
|
||||
this.eventSeq = [
|
||||
new invokerChecker(EVENT_HIDE, this.prevPanel),
|
||||
new invokerChecker(EVENT_SHOW, this.panelNode),
|
||||
new invokerChecker(EVENT_REORDER, this.container)
|
||||
];
|
||||
|
||||
this.invoke = function switchDeckPanel_invoke()
|
||||
{
|
||||
var tree =
|
||||
{ GROUPING: [ // role="group"
|
||||
{ GROUPING: [ // groupbox, a selected panel #2
|
||||
{ PUSHBUTTON: [ ] } // button
|
||||
] }
|
||||
] };
|
||||
testAccessibleTree(this.container, tree);
|
||||
|
||||
this.deckNode.selectedIndex = this.panelIndex;
|
||||
}
|
||||
|
||||
this.finalCheck = function switchDeckPanel_finalCheck()
|
||||
{
|
||||
var tree =
|
||||
{ GROUPING: [ // role="group"
|
||||
{ LABEL: [ // description, a selected panel #1
|
||||
{ TEXT_LEAF: [] } // text leaf, a description value
|
||||
] }
|
||||
] };
|
||||
testAccessibleTree(this.container, tree);
|
||||
}
|
||||
|
||||
this.getID = function switchDeckPanel_getID()
|
||||
{
|
||||
return "switch deck panel";
|
||||
}
|
||||
}
|
||||
|
||||
var gQueue = null;
|
||||
function doTest()
|
||||
{
|
||||
gQueue = new eventQueue();
|
||||
gQueue.push(new switchDeckPanel("container", "deck"));
|
||||
gQueue.invoke(); // will call SimpleTest.finish();
|
||||
}
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
addA11yLoadEvent(doTest);
|
||||
]]>
|
||||
</script>
|
||||
|
||||
<hbox flex="1" style="overflow: auto;">
|
||||
<body xmlns="http://www.w3.org/1999/xhtml">
|
||||
<a target="_blank"
|
||||
href="https://bugzilla.mozilla.org/show_bug.cgi?id=814836"
|
||||
title=" xul:deck element messes up screen reader">
|
||||
Mozilla Bug 814836
|
||||
</a>
|
||||
|
||||
<p id="display"></p>
|
||||
<div id="content" style="display: none">
|
||||
</div>
|
||||
<pre id="test">
|
||||
</pre>
|
||||
</body>
|
||||
|
||||
<vbox flex="1" id="container" role="group">
|
||||
|
||||
<deck id="deck" selectedIndex="1">
|
||||
<description>This is the first page</description>
|
||||
<groupbox>
|
||||
<button label="This is the second page"/>
|
||||
</groupbox>
|
||||
</deck>
|
||||
|
||||
</vbox>
|
||||
</hbox>
|
||||
|
||||
</window>
|
||||
|
@ -26,6 +26,10 @@
|
||||
#include "nsDisplayList.h"
|
||||
#include "nsContainerFrame.h"
|
||||
|
||||
#ifdef ACCESSIBILITY
|
||||
#include "nsAccessibilityService.h"
|
||||
#endif
|
||||
|
||||
nsIFrame*
|
||||
NS_NewDeckFrame(nsIPresShell* aPresShell, nsStyleContext* aContext)
|
||||
{
|
||||
@ -105,6 +109,14 @@ nsDeckFrame::IndexChanged()
|
||||
HideBox(currentBox);
|
||||
|
||||
mIndex = index;
|
||||
|
||||
#ifdef ACCESSIBILITY
|
||||
nsAccessibilityService* accService = GetAccService();
|
||||
if (accService) {
|
||||
accService->DeckPanelSwitched(PresContext()->GetPresShell(), mContent,
|
||||
currentBox, GetSelectedBox());
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
int32_t
|
||||
|
@ -601,7 +601,7 @@
|
||||
<property name="accessibleType" readonly="true">
|
||||
<getter>
|
||||
<![CDATA[
|
||||
return Components.interfaces.nsIAccessibleProvider.XULDeck;
|
||||
return Components.interfaces.nsIAccessibleProvider.XULTabpanels;
|
||||
]]>
|
||||
</getter>
|
||||
</property>
|
||||
|
Loading…
Reference in New Issue
Block a user