зеркало из https://github.com/mozilla/gecko-dev.git
Bug 606125 - develop a way to handle visibility style, r=marcoz, davidb, sr=bz, a=blocking
--HG-- rename : accessible/tests/mochitest/treeupdate/test_tableinsubtree.html => accessible/tests/mochitest/treeupdate/test_ariadialog.html
This commit is contained in:
Родитель
8466507cd8
Коммит
6e8119fa5f
|
@ -113,16 +113,16 @@ nsAccTreeWalker::GetNextChildInternal(PRBool aNoWalkUp)
|
|||
nsIContent* childNode = mState->childList->GetNodeAt(mState->childIdx);
|
||||
mState->childIdx++;
|
||||
|
||||
PRBool isHidden = PR_FALSE;
|
||||
bool isSubtreeHidden = false;
|
||||
nsRefPtr<nsAccessible> accessible =
|
||||
GetAccService()->GetOrCreateAccessible(childNode, presShell, mWeakShell,
|
||||
&isHidden);
|
||||
&isSubtreeHidden);
|
||||
|
||||
if (accessible)
|
||||
return accessible.forget();
|
||||
|
||||
// Walk down into subtree to find accessibles.
|
||||
if (!isHidden) {
|
||||
if (!isSubtreeHidden) {
|
||||
if (!PushState(childNode))
|
||||
break;
|
||||
|
||||
|
|
|
@ -869,13 +869,13 @@ already_AddRefed<nsAccessible>
|
|||
nsAccessibilityService::GetOrCreateAccessible(nsINode* aNode,
|
||||
nsIPresShell* aPresShell,
|
||||
nsIWeakReference* aWeakShell,
|
||||
PRBool* aIsHidden)
|
||||
bool* aIsSubtreeHidden)
|
||||
{
|
||||
if (!aPresShell || !aWeakShell || !aNode || gIsShutdown)
|
||||
return nsnull;
|
||||
|
||||
if (aIsHidden)
|
||||
*aIsHidden = PR_FALSE;
|
||||
if (aIsSubtreeHidden)
|
||||
*aIsSubtreeHidden = false;
|
||||
|
||||
// Check to see if we already have an accessible for this node in the cache.
|
||||
nsAccessible *cachedAccessible = GetCachedAccessible(aNode, aWeakShell);
|
||||
|
@ -916,10 +916,11 @@ nsAccessibilityService::GetOrCreateAccessible(nsINode* aNode,
|
|||
// methods on a dead frame pointer.
|
||||
nsWeakFrame weakFrame = content->GetPrimaryFrame();
|
||||
|
||||
// Check frame to see if it is hidden.
|
||||
if (!weakFrame.GetFrame()) {
|
||||
if (aIsHidden)
|
||||
*aIsHidden = PR_TRUE;
|
||||
// Check frame and its visibility. Note, hidden frame allows visible
|
||||
// elements in subtree.
|
||||
if (!weakFrame.GetFrame() || !weakFrame->GetStyleVisibility()->IsVisible()) {
|
||||
if (aIsSubtreeHidden && !weakFrame.GetFrame())
|
||||
*aIsSubtreeHidden = true;
|
||||
|
||||
return nsnull;
|
||||
}
|
||||
|
@ -953,8 +954,8 @@ nsAccessibilityService::GetOrCreateAccessible(nsINode* aNode,
|
|||
f->GetRenderedText(&renderedWhitespace, nsnull, nsnull, 0, 1);
|
||||
if (renderedWhitespace.IsEmpty()) {
|
||||
// Really empty -- nothing is rendered
|
||||
if (aIsHidden)
|
||||
*aIsHidden = PR_TRUE;
|
||||
if (aIsSubtreeHidden)
|
||||
*aIsSubtreeHidden = true;
|
||||
|
||||
return nsnull;
|
||||
}
|
||||
|
@ -982,8 +983,8 @@ nsAccessibilityService::GetOrCreateAccessible(nsINode* aNode,
|
|||
nsAutoString name;
|
||||
content->GetAttr(kNameSpaceID_None, nsAccessibilityAtoms::name, name);
|
||||
if (!name.IsEmpty()) {
|
||||
if (aIsHidden)
|
||||
*aIsHidden = PR_TRUE;
|
||||
if (aIsSubtreeHidden)
|
||||
*aIsSubtreeHidden = true;
|
||||
|
||||
return nsnull;
|
||||
}
|
||||
|
@ -1107,8 +1108,8 @@ nsAccessibilityService::GetOrCreateAccessible(nsINode* aNode,
|
|||
// captions. This could not be done in
|
||||
// nsTableCaptionFrame::GetAccessible() because the descendants of
|
||||
// the table caption would still be created. By setting
|
||||
// *aIsHidden = PR_TRUE we ensure that no descendant accessibles are
|
||||
// created.
|
||||
// *aIsSubtreeHidden = true we ensure that no descendant accessibles
|
||||
// are created.
|
||||
nsIFrame* f = weakFrame.GetFrame();
|
||||
if (!f) {
|
||||
f = aPresShell->GetRealPrimaryFrameFor(content);
|
||||
|
@ -1117,8 +1118,8 @@ nsAccessibilityService::GetOrCreateAccessible(nsINode* aNode,
|
|||
f->GetRect().IsEmpty()) {
|
||||
// XXX This is not the ideal place for this code, but right now there
|
||||
// is no better place:
|
||||
if (aIsHidden)
|
||||
*aIsHidden = PR_TRUE;
|
||||
if (aIsSubtreeHidden)
|
||||
*aIsSubtreeHidden = true;
|
||||
|
||||
return nsnull;
|
||||
}
|
||||
|
|
|
@ -111,9 +111,9 @@ public:
|
|||
virtual void RemoveNativeRootAccessible(nsAccessible* aRootAccessible);
|
||||
|
||||
virtual void ContentRangeInserted(nsIPresShell* aPresShell,
|
||||
nsIContent* aContainer,
|
||||
nsIContent* aStartChild,
|
||||
nsIContent* aEndChild);
|
||||
nsIContent* aContainer,
|
||||
nsIContent* aStartChild,
|
||||
nsIContent* aEndChild);
|
||||
|
||||
virtual void ContentRemoved(nsIPresShell* aPresShell, nsIContent* aContainer,
|
||||
nsIContent* aChild);
|
||||
|
@ -138,16 +138,16 @@ public:
|
|||
* Return an accessible for the given DOM node from the cache or create new
|
||||
* one.
|
||||
*
|
||||
* @param aNode [in] the given node
|
||||
* @param aPresShell [in] the pres shell of the node
|
||||
* @param aWeakShell [in] the weak shell for the pres shell
|
||||
* @param aIsHidden [out, optional] indicates whether the node's frame is
|
||||
* hidden
|
||||
* @param aNode [in] the given node
|
||||
* @param aPresShell [in] the pres shell of the node
|
||||
* @param aWeakShell [in] the weak shell for the pres shell
|
||||
* @param aIsSubtreeHidden [out, optional] indicates whether the node's
|
||||
* frame and its subtree is hidden
|
||||
*/
|
||||
already_AddRefed<nsAccessible>
|
||||
GetOrCreateAccessible(nsINode* aNode, nsIPresShell* aPresShell,
|
||||
nsIWeakReference* aWeakShell,
|
||||
PRBool* aIsHidden = nsnull);
|
||||
bool* aIsSubtreeHidden = nsnull);
|
||||
|
||||
/**
|
||||
* Return an accessible for the given DOM node.
|
||||
|
|
|
@ -237,11 +237,6 @@ nsresult
|
|||
nsTextEquivUtils::AppendFromAccessible(nsAccessible *aAccessible,
|
||||
nsAString *aString)
|
||||
{
|
||||
// Ignore hidden accessible for name computation.
|
||||
nsIFrame* frame = aAccessible->GetFrame();
|
||||
if (!frame || !frame->GetStyleVisibility()->IsVisible())
|
||||
return NS_OK;
|
||||
|
||||
//XXX: is it necessary to care the accessible is not a document?
|
||||
if (aAccessible->IsContent()) {
|
||||
nsresult rv = AppendTextEquivFromTextContent(aAccessible->GetContent(),
|
||||
|
|
|
@ -320,27 +320,41 @@ function testAccessibleTree(aAccOrElmOrID, aAccTree)
|
|||
if (!acc)
|
||||
return;
|
||||
|
||||
for (var prop in aAccTree) {
|
||||
var accTree = aAccTree;
|
||||
|
||||
// Support of simplified accessible tree object.
|
||||
var key = Object.keys(accTree)[0];
|
||||
var roleName = "ROLE_" + key;
|
||||
if (roleName in nsIAccessibleRole) {
|
||||
accTree = {
|
||||
role: nsIAccessibleRole[roleName],
|
||||
children: accTree[key]
|
||||
};
|
||||
}
|
||||
|
||||
// Test accessible properties.
|
||||
for (var prop in accTree) {
|
||||
var msg = "Wrong value of property '" + prop + "' for " + prettyName(acc) + ".";
|
||||
if (prop == "role") {
|
||||
is(roleToString(acc[prop]), roleToString(aAccTree[prop]), msg);
|
||||
is(roleToString(acc[prop]), roleToString(accTree[prop]), msg);
|
||||
|
||||
} else if (prop == "states") {
|
||||
var statesObj = aAccTree[prop];
|
||||
var statesObj = accTree[prop];
|
||||
testStates(acc, statesObj.states, statesObj.extraStates,
|
||||
statesObj.absentStates, statesObj.absentExtraStates);
|
||||
|
||||
} else if (prop != "children") {
|
||||
is(acc[prop], aAccTree[prop], msg);
|
||||
is(acc[prop], accTree[prop], msg);
|
||||
}
|
||||
}
|
||||
|
||||
if ("children" in aAccTree && aAccTree["children"] instanceof Array) {
|
||||
// Test children.
|
||||
if ("children" in accTree && accTree["children"] instanceof Array) {
|
||||
var children = acc.children;
|
||||
is(children.length, aAccTree.children.length,
|
||||
is(children.length, accTree.children.length,
|
||||
"Different amount of expected children of " + prettyName(acc) + ".");
|
||||
|
||||
if (aAccTree.children.length == children.length) {
|
||||
if (accTree.children.length == children.length) {
|
||||
var childCount = children.length;
|
||||
|
||||
// nsIAccessible::firstChild
|
||||
|
@ -390,7 +404,7 @@ function testAccessibleTree(aAccOrElmOrID, aAccTree)
|
|||
"Wrong previous sibling of " + prettyName(child));
|
||||
|
||||
// Go down through subtree
|
||||
testAccessibleTree(child, aAccTree.children[i]);
|
||||
testAccessibleTree(child, accTree.children[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -293,6 +293,13 @@
|
|||
gQueue.push(new changeStyle(id, "display", "none", kHideEvents));
|
||||
gQueue.push(new changeStyle(id, "display", "inline", kShowEvents));
|
||||
|
||||
// Show/hide events by changing of visibility style of accessible DOM node
|
||||
// from 'visible' to 'hidden', 'hidden' to 'visible'.
|
||||
var id = "link2";
|
||||
getAccessible(id);
|
||||
gQueue.push(new changeStyle(id, "visibility", "hidden", kHideEvents));
|
||||
gQueue.push(new changeStyle(id, "visibility", "visible", kShowEvents));
|
||||
|
||||
// Show/hide events by changing of display style of accessible DOM node
|
||||
// from 'inline' to 'block', 'block' to 'inline'.
|
||||
var id = "link3";
|
||||
|
@ -300,6 +307,12 @@
|
|||
gQueue.push(new changeStyle(id, "display", "block", kHideAndShowEvents));
|
||||
gQueue.push(new changeStyle(id, "display", "inline", kHideAndShowEvents));
|
||||
|
||||
// Show/hide events by changing of visibility style of accessible DOM node
|
||||
// from 'collapse' to 'visible', 'visible' to 'collapse'.
|
||||
var id = "link4";
|
||||
gQueue.push(new changeStyle(id, "visibility", "visible", kShowEvents));
|
||||
gQueue.push(new changeStyle(id, "visibility", "collapse", kHideEvents));
|
||||
|
||||
// Show/hide events by adding new accessible DOM node and removing old one.
|
||||
var id = "link5";
|
||||
gQueue.push(new cloneAndAppendToDOM(id));
|
||||
|
@ -343,6 +356,10 @@
|
|||
gQueue.push(new changeClass("container2", "link7", "displayNone",
|
||||
kHideEvents));
|
||||
|
||||
gQueue.push(new changeClass("container3", "link8", "", kShowEvents));
|
||||
gQueue.push(new changeClass("container3", "link8", "visibilityHidden",
|
||||
kHideEvents));
|
||||
|
||||
gQueue.invoke(); // Will call SimpleTest.finish();
|
||||
}
|
||||
|
||||
|
@ -367,6 +384,11 @@
|
|||
title="Rework accessible tree update code"
|
||||
href="https://bugzilla.mozilla.org/show_bug.cgi?id=570275">
|
||||
Mozilla Bug 570275
|
||||
</a><br>
|
||||
<a target="_blank"
|
||||
title="Develop a way to handle visibility style"
|
||||
href="https://bugzilla.mozilla.org/show_bug.cgi?id=606125">
|
||||
Mozilla Bug 606125
|
||||
</a>
|
||||
|
||||
<p id="display"></p>
|
||||
|
|
|
@ -70,9 +70,6 @@
|
|||
var tabsAccTree = {
|
||||
role: ROLE_PAGETABLIST,
|
||||
children: [
|
||||
{
|
||||
role: ROLE_PUSHBUTTON // tab scroll up button
|
||||
},
|
||||
{
|
||||
role: ROLE_PAGETAB,
|
||||
children: [
|
||||
|
@ -91,9 +88,6 @@
|
|||
},
|
||||
{
|
||||
role: ROLE_PUSHBUTTON
|
||||
},
|
||||
{
|
||||
role: ROLE_PUSHBUTTON // tab scroll down button
|
||||
}
|
||||
]
|
||||
};
|
||||
|
|
|
@ -46,12 +46,13 @@ include $(DEPTH)/config/autoconf.mk
|
|||
include $(topsrcdir)/config/rules.mk
|
||||
|
||||
_TEST_FILES =\
|
||||
test_ariadialog.html \
|
||||
test_doc.html \
|
||||
test_list_editabledoc.html \
|
||||
test_list.html \
|
||||
test_recreation.html \
|
||||
test_tableinsubtree.html \
|
||||
test_textleaf.html \
|
||||
test_visibility.html \
|
||||
$(NULL)
|
||||
|
||||
libs:: $(_TEST_FILES)
|
||||
|
|
|
@ -34,9 +34,10 @@
|
|||
|
||||
this.invoke = function showARIADialog_invoke()
|
||||
{
|
||||
this.node.style.display = "block";
|
||||
getNode("dialog").style.display = "block";
|
||||
getNode("table").style.visibility = "visible";
|
||||
getNode("a").textContent = "link";
|
||||
getNode("input").value = "hello";
|
||||
getNode("cell").textContent = "cell1";
|
||||
getNode("input").focus();
|
||||
}
|
||||
|
||||
|
@ -46,22 +47,11 @@
|
|||
role: ROLE_DIALOG,
|
||||
children: [
|
||||
{
|
||||
role: ROLE_TABLE,
|
||||
children: [
|
||||
{
|
||||
role: ROLE_ROW,
|
||||
children: [
|
||||
{
|
||||
role: ROLE_CELL,
|
||||
children: [ { role: ROLE_TEXT_LEAF } ]
|
||||
},
|
||||
{
|
||||
role: ROLE_CELL,
|
||||
children: [ { role: ROLE_ENTRY } ]
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
role: ROLE_PUSHBUTTON,
|
||||
children: [ { role: ROLE_TEXT_LEAF } ]
|
||||
},
|
||||
{
|
||||
role: ROLE_ENTRY
|
||||
}
|
||||
]
|
||||
};
|
||||
|
@ -110,8 +100,18 @@
|
|||
</pre>
|
||||
|
||||
<div id="dialog" role="dialog" style="display: none;">
|
||||
<table>
|
||||
<tr><td id="cell"></td><td><input id="input"></td>
|
||||
<table id="table" role="presentation"
|
||||
style="display: block; position: fixed; top: 88px; left: 312.5px; z-index: 10010; visibility: hidden;">
|
||||
<tbody>
|
||||
<tr>
|
||||
<td role="presentation">
|
||||
<div role="presentation">
|
||||
<a id="a" role="button">text</a>
|
||||
</div>
|
||||
<input id="input">
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
|
|
@ -0,0 +1,439 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
|
||||
<head>
|
||||
<title>Style visibility tree update test</title>
|
||||
|
||||
<link rel="stylesheet" type="text/css"
|
||||
href="chrome://mochikit/content/tests/SimpleTest/test.css" />
|
||||
|
||||
<script type="application/javascript"
|
||||
src="chrome://mochikit/content/MochiKit/packed.js"></script>
|
||||
<script type="application/javascript"
|
||||
src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
|
||||
|
||||
<script type="application/javascript"
|
||||
src="../common.js"></script>
|
||||
<script type="application/javascript"
|
||||
src="../role.js"></script>
|
||||
<script type="application/javascript"
|
||||
src="../events.js"></script>
|
||||
|
||||
<script type="application/javascript">
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
// Invokers
|
||||
|
||||
/**
|
||||
* Hide parent while child stays visible.
|
||||
*/
|
||||
function test1(aContainerID, aParentID, aChildID)
|
||||
{
|
||||
this.eventSeq = [
|
||||
new invokerChecker(EVENT_HIDE, getNode(aParentID)),
|
||||
new invokerChecker(EVENT_SHOW, getNode(aChildID)),
|
||||
new invokerChecker(EVENT_REORDER, getNode(aContainerID))
|
||||
];
|
||||
|
||||
this.invoke = function invoke()
|
||||
{
|
||||
var tree =
|
||||
{ SECTION: [
|
||||
{ SECTION: [
|
||||
{ SECTION: [
|
||||
{ TEXT_LEAF: [] }
|
||||
] }
|
||||
] }
|
||||
] };
|
||||
testAccessibleTree(aContainerID, tree);
|
||||
|
||||
getNode(aParentID).style.visibility = "hidden";
|
||||
}
|
||||
|
||||
this.finalCheck = function finalCheck()
|
||||
{
|
||||
var tree =
|
||||
{ SECTION: [
|
||||
{ SECTION: [
|
||||
{ TEXT_LEAF: [] }
|
||||
] }
|
||||
] };
|
||||
testAccessibleTree(aContainerID, tree);
|
||||
}
|
||||
|
||||
this.getID = function getID()
|
||||
{
|
||||
return "hide parent while child stays visible";
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Hide grand parent while its children stay visible.
|
||||
*/
|
||||
function test2(aContainerID, aGrandParentID, aChildID, aChild2ID)
|
||||
{
|
||||
this.eventSeq = [
|
||||
new invokerChecker(EVENT_HIDE, getNode(aGrandParentID)),
|
||||
new invokerChecker(EVENT_SHOW, getNode(aChildID)),
|
||||
new invokerChecker(EVENT_SHOW, getNode(aChild2ID)),
|
||||
new invokerChecker(EVENT_REORDER, getNode(aContainerID))
|
||||
];
|
||||
|
||||
this.invoke = function invoke()
|
||||
{
|
||||
var tree =
|
||||
{ SECTION: [ // container
|
||||
{ SECTION: [ // grand parent
|
||||
{ SECTION: [
|
||||
{ SECTION: [ // child
|
||||
{ TEXT_LEAF: [] }
|
||||
] },
|
||||
{ SECTION: [ // child2
|
||||
{ TEXT_LEAF: [] }
|
||||
] }
|
||||
] }
|
||||
] }
|
||||
] };
|
||||
testAccessibleTree(aContainerID, tree);
|
||||
|
||||
getNode(aGrandParentID).style.visibility = "hidden";
|
||||
}
|
||||
|
||||
this.finalCheck = function finalCheck()
|
||||
{
|
||||
var tree =
|
||||
{ SECTION: [ // container
|
||||
{ SECTION: [ // child
|
||||
{ TEXT_LEAF: [] }
|
||||
] },
|
||||
{ SECTION: [ // child2
|
||||
{ TEXT_LEAF: [] }
|
||||
] }
|
||||
] };
|
||||
testAccessibleTree(aContainerID, tree);
|
||||
}
|
||||
|
||||
this.getID = function getID()
|
||||
{
|
||||
return "hide grand parent while its children stay visible";
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Change container style, hide parents while their children stay visible.
|
||||
*/
|
||||
function test3(aContainerID, aParentID, aParent2ID, aChildID, aChild2ID)
|
||||
{
|
||||
this.eventSeq = [
|
||||
new invokerChecker(EVENT_HIDE, getNode(aParentID)),
|
||||
new invokerChecker(EVENT_SHOW, getNode(aChildID)),
|
||||
new invokerChecker(EVENT_HIDE, getNode(aParent2ID)),
|
||||
new invokerChecker(EVENT_SHOW, getNode(aChild2ID)),
|
||||
new invokerChecker(EVENT_REORDER, getNode(aContainerID))
|
||||
];
|
||||
|
||||
this.invoke = function invoke()
|
||||
{
|
||||
var tree =
|
||||
{ SECTION: [ // container
|
||||
{ SECTION: [ // parent
|
||||
{ SECTION: [ // child
|
||||
{ TEXT_LEAF: [] }
|
||||
] }
|
||||
] },
|
||||
{ SECTION: [ // parent2
|
||||
{ SECTION: [ // child2
|
||||
{ TEXT_LEAF: [] }
|
||||
] },
|
||||
] }
|
||||
] };
|
||||
testAccessibleTree(aContainerID, tree);
|
||||
|
||||
getNode(aContainerID).style.color = "red";
|
||||
getNode(aParentID).style.visibility = "hidden";
|
||||
getNode(aParent2ID).style.visibility = "hidden";
|
||||
}
|
||||
|
||||
this.finalCheck = function finalCheck()
|
||||
{
|
||||
var tree =
|
||||
{ SECTION: [ // container
|
||||
{ SECTION: [ // child
|
||||
{ TEXT_LEAF: [] }
|
||||
] },
|
||||
{ SECTION: [ // child2
|
||||
{ TEXT_LEAF: [] }
|
||||
] }
|
||||
] };
|
||||
testAccessibleTree(aContainerID, tree);
|
||||
}
|
||||
|
||||
this.getID = function getID()
|
||||
{
|
||||
return "change container style, hide parents while their children stay visible";
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Change container style and make visible child inside the table.
|
||||
*/
|
||||
function test4(aContainerID, aChildID)
|
||||
{
|
||||
this.eventSeq = [
|
||||
new invokerChecker(EVENT_SHOW, getNode(aChildID)),
|
||||
new invokerChecker(EVENT_REORDER, getNode(aChildID).parentNode)
|
||||
];
|
||||
|
||||
this.invoke = function invoke()
|
||||
{
|
||||
var tree =
|
||||
{ SECTION: [
|
||||
{ TABLE: [
|
||||
{ ROW: [
|
||||
{ CELL: [ ] }
|
||||
] }
|
||||
] }
|
||||
] };
|
||||
testAccessibleTree(aContainerID, tree);
|
||||
|
||||
getNode(aContainerID).style.color = "red";
|
||||
getNode(aChildID).style.visibility = "visible";
|
||||
}
|
||||
|
||||
this.finalCheck = function finalCheck()
|
||||
{
|
||||
var tree =
|
||||
{ SECTION: [
|
||||
{ TABLE: [
|
||||
{ ROW: [
|
||||
{ CELL: [
|
||||
{ SECTION: [
|
||||
{ TEXT_LEAF: [] }
|
||||
] }
|
||||
] }
|
||||
] }
|
||||
] }
|
||||
] };
|
||||
testAccessibleTree(aContainerID, tree);
|
||||
}
|
||||
|
||||
this.getID = function getID()
|
||||
{
|
||||
return "change container style, make visible child insdie the table";
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Hide subcontainer while child inside the table stays visible.
|
||||
*/
|
||||
function test5(aContainerID, aSubContainerID, aChildID)
|
||||
{
|
||||
this.eventSeq = [
|
||||
new invokerChecker(EVENT_HIDE, getNode(aSubContainerID)),
|
||||
new invokerChecker(EVENT_SHOW, getNode(aChildID)),
|
||||
new invokerChecker(EVENT_REORDER, getNode(aContainerID))
|
||||
];
|
||||
|
||||
this.invoke = function invoke()
|
||||
{
|
||||
var tree =
|
||||
{ SECTION: [ // container
|
||||
{ SECTION: [ // subcontainer
|
||||
{ TABLE: [
|
||||
{ ROW: [
|
||||
{ CELL: [
|
||||
{ SECTION: [ // child
|
||||
{ TEXT_LEAF: [] }
|
||||
] }
|
||||
] }
|
||||
] }
|
||||
] }
|
||||
] }
|
||||
] };
|
||||
testAccessibleTree(aContainerID, tree);
|
||||
|
||||
getNode(aSubContainerID).style.visibility = "hidden";
|
||||
}
|
||||
|
||||
this.finalCheck = function finalCheck()
|
||||
{
|
||||
var tree =
|
||||
{ SECTION: [ // container
|
||||
{ SECTION: [ // child
|
||||
{ TEXT_LEAF: [] }
|
||||
] }
|
||||
] };
|
||||
testAccessibleTree(aContainerID, tree);
|
||||
}
|
||||
|
||||
this.getID = function getID()
|
||||
{
|
||||
return "hide subcontainer while child inside the table stays visible";
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Hide subcontainer while its child and child inside the nested table stays visible.
|
||||
*/
|
||||
function test6(aContainerID, aSubContainerID, aChildID, aChild2ID)
|
||||
{
|
||||
this.eventSeq = [
|
||||
new invokerChecker(EVENT_HIDE, getNode(aSubContainerID)),
|
||||
new invokerChecker(EVENT_SHOW, getNode(aChildID)),
|
||||
new invokerChecker(EVENT_SHOW, getNode(aChild2ID)),
|
||||
new invokerChecker(EVENT_REORDER, getNode(aContainerID))
|
||||
];
|
||||
|
||||
this.invoke = function invoke()
|
||||
{
|
||||
var tree =
|
||||
{ SECTION: [ // container
|
||||
{ SECTION: [ // subcontainer
|
||||
{ TABLE: [
|
||||
{ ROW: [
|
||||
{ CELL: [
|
||||
{ TABLE: [ // nested table
|
||||
{ ROW: [
|
||||
{ CELL: [
|
||||
{ SECTION: [ // child
|
||||
{ TEXT_LEAF: [] } ]} ]} ]} ]} ]} ]} ]},
|
||||
{ SECTION: [ // child2
|
||||
{ TEXT_LEAF: [] } ]} ]} ]};
|
||||
|
||||
testAccessibleTree(aContainerID, tree);
|
||||
|
||||
// invoke
|
||||
getNode(aSubContainerID).style.visibility = "hidden";
|
||||
}
|
||||
|
||||
this.finalCheck = function finalCheck()
|
||||
{
|
||||
var tree =
|
||||
{ SECTION: [ // container
|
||||
{ SECTION: [ // child
|
||||
{ TEXT_LEAF: [] } ]},
|
||||
{ SECTION: [ // child2
|
||||
{ TEXT_LEAF: [] } ]} ]};
|
||||
|
||||
testAccessibleTree(aContainerID, tree);
|
||||
}
|
||||
|
||||
this.getID = function getID()
|
||||
{
|
||||
return "hide subcontainer while its child and child inside the nested table stays visible";
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
// Test
|
||||
|
||||
//gA11yEventDumpID = "eventdump"; // debug stuff
|
||||
//gA11yEventDumpToConsole = true;
|
||||
|
||||
var gQueue = null;
|
||||
|
||||
function doTest()
|
||||
{
|
||||
gQueue = new eventQueue();
|
||||
|
||||
gQueue.push(new test1("t1_container", "t1_parent", "t1_child"));
|
||||
gQueue.push(new test2("t2_container", "t2_grandparent", "t2_child", "t2_child2"));
|
||||
gQueue.push(new test3("t3_container", "t3_parent", "t3_parent2", "t3_child", "t3_child2"));
|
||||
gQueue.push(new test4("t4_container", "t4_child"));
|
||||
gQueue.push(new test5("t5_container", "t5_subcontainer", "t5_child"));
|
||||
gQueue.push(new test6("t6_container", "t6_subcontainer", "t6_child", "t6_child2"));
|
||||
|
||||
gQueue.invoke(); // SimpleTest.finish() will be called in the end
|
||||
}
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
addA11yLoadEvent(doTest);
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<a target="_blank"
|
||||
title="Develop a way to handle visibility style"
|
||||
href="https://bugzilla.mozilla.org/show_bug.cgi?id=606125">
|
||||
Mozilla Bug 606125
|
||||
</a>
|
||||
|
||||
<p id="display"></p>
|
||||
<div id="content" style="display: none"></div>
|
||||
<pre id="test">
|
||||
</pre>
|
||||
|
||||
<!-- hide parent while child stays visible -->
|
||||
<div id="t1_container">
|
||||
<div id="t1_parent">
|
||||
<div id="t1_child" style="visibility: visible">text</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- hide grandparent while its children stay visible -->
|
||||
<div id="t2_container">
|
||||
<div id="t2_grandparent">
|
||||
<div>
|
||||
<div id="t2_child" style="visibility: visible">text</div>
|
||||
<div id="t2_child2" style="visibility: visible">text</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- change container style, hide parents while their children stay visible -->
|
||||
<div id="t3_container">
|
||||
<div id="t3_parent">
|
||||
<div id="t3_child" style="visibility: visible">text</div>
|
||||
</div>
|
||||
<div id="t3_parent2">
|
||||
<div id="t3_child2" style="visibility: visible">text</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- change container style, show child inside the table -->
|
||||
<div id="t4_container">
|
||||
<table>
|
||||
<tr>
|
||||
<td>
|
||||
<div id="t4_child" style="visibility: hidden;">text</div>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<!-- hide subcontainer while child inside the table stays visible -->
|
||||
<div id="t5_container">
|
||||
<div id="t5_subcontainer">
|
||||
<table>
|
||||
<tr>
|
||||
<td>
|
||||
<div id="t5_child" style="visibility: visible;">text</div>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- hide subcontainer while its child and child inside the nested table stays visible -->
|
||||
<div id="t6_container">
|
||||
<div id="t6_subcontainer">
|
||||
<table>
|
||||
<tr>
|
||||
<td>
|
||||
<table>
|
||||
<tr>
|
||||
<td>
|
||||
<div id="t6_child" style="visibility: visible;">text</div>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<div id="t6_child2" style="visibility: visible">text</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="eventdump"></div>
|
||||
</body>
|
||||
</html>
|
|
@ -96,6 +96,10 @@
|
|||
|
||||
#include "nsFrameManager.h"
|
||||
|
||||
#ifdef ACCESSIBILITY
|
||||
#include "nsIAccessibilityService.h"
|
||||
#endif
|
||||
|
||||
#ifdef DEBUG
|
||||
//#define NOISY_DEBUG
|
||||
//#define DEBUG_UNDISPLAYED_MAP
|
||||
|
@ -1000,7 +1004,9 @@ nsFrameManager::ReResolveStyleContext(nsPresContext *aPresContext,
|
|||
nsStyleChangeList *aChangeList,
|
||||
nsChangeHint aMinChange,
|
||||
nsRestyleHint aRestyleHint,
|
||||
RestyleTracker& aRestyleTracker)
|
||||
RestyleTracker& aRestyleTracker,
|
||||
DesiredA11yNotifications aDesiredA11yNotifications,
|
||||
nsTArray<nsIContent*>& aVisibleKidsOfHiddenElement)
|
||||
{
|
||||
if (!NS_IsHintSubset(nsChangeHint_NeedDirtyReflow, aMinChange)) {
|
||||
// If aMinChange doesn't include nsChangeHint_NeedDirtyReflow, clear out
|
||||
|
@ -1047,6 +1053,12 @@ nsFrameManager::ReResolveStyleContext(nsPresContext *aPresContext,
|
|||
// could oldContext be null?
|
||||
if (oldContext) {
|
||||
oldContext->AddRef();
|
||||
|
||||
#ifdef ACCESSIBILITY
|
||||
PRBool wasFrameVisible = mPresShell->IsAccessibilityActive() ?
|
||||
oldContext->GetStyleVisibility()->IsVisible() : PR_FALSE;
|
||||
#endif
|
||||
|
||||
nsIAtom* const pseudoTag = oldContext->GetPseudo();
|
||||
const nsCSSPseudoElements::Type pseudoType = oldContext->GetPseudoType();
|
||||
nsIContent* localContent = aFrame->GetContent();
|
||||
|
@ -1100,7 +1112,9 @@ nsFrameManager::ReResolveStyleContext(nsPresContext *aPresContext,
|
|||
assumeDifferenceHint = ReResolveStyleContext(aPresContext, providerFrame,
|
||||
aParentContent, aChangeList,
|
||||
aMinChange, aRestyleHint,
|
||||
aRestyleTracker);
|
||||
aRestyleTracker,
|
||||
aDesiredA11yNotifications,
|
||||
aVisibleKidsOfHiddenElement);
|
||||
|
||||
// The provider's new context becomes the parent context of
|
||||
// aFrame's context.
|
||||
|
@ -1399,7 +1413,44 @@ nsFrameManager::ReResolveStyleContext(nsPresContext *aPresContext,
|
|||
}
|
||||
|
||||
if (!(aMinChange & nsChangeHint_ReconstructFrame)) {
|
||||
|
||||
A11yNotificationType ourA11yNotification = eDontNotify;
|
||||
DesiredA11yNotifications kidsDesiredA11yNotification =
|
||||
aDesiredA11yNotifications;
|
||||
#ifdef ACCESSIBILITY
|
||||
// Notify a11y for primary frame only if it's a root frame of visibility
|
||||
// changes or its parent frame was hidden while it stays visible and
|
||||
// it is not inside a {ib} split or is the first frame of {ib} split.
|
||||
if (mPresShell->IsAccessibilityActive() && !aFrame->GetPrevContinuation() &&
|
||||
!nsLayoutUtils::FrameIsNonFirstInIBSplit(aFrame)) {
|
||||
if (aDesiredA11yNotifications == eSendAllNotifications) {
|
||||
PRBool isFrameVisible = newContext->GetStyleVisibility()->IsVisible();
|
||||
if (isFrameVisible != wasFrameVisible) {
|
||||
if (isFrameVisible) {
|
||||
// Notify a11y the element (perhaps with its children) was shown.
|
||||
// We don't fall into this case if this element gets or stays shown
|
||||
// while its parent becomes hidden.
|
||||
kidsDesiredA11yNotification = eSkipNotifications;
|
||||
ourA11yNotification = eNotifyShown;
|
||||
} else {
|
||||
// The element is being hidden; its children may stay visible, or
|
||||
// become visible after being hidden previously. If we'll find
|
||||
// visible children then we should notify a11y about that as if
|
||||
// they were inserted into tree. Notify a11y this element was
|
||||
// hidden.
|
||||
kidsDesiredA11yNotification = eNotifyIfShown;
|
||||
ourA11yNotification = eNotifyHidden;
|
||||
}
|
||||
}
|
||||
} else if (aDesiredA11yNotifications == eNotifyIfShown &&
|
||||
newContext->GetStyleVisibility()->IsVisible()) {
|
||||
// Notify a11y that element stayed visible while its parent was
|
||||
// hidden.
|
||||
aVisibleKidsOfHiddenElement.AppendElement(aFrame->GetContent());
|
||||
kidsDesiredA11yNotification = eSkipNotifications;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
// There is no need to waste time crawling into a frame's children on a frame change.
|
||||
// The act of reconstructing frames will force new style contexts to be resolved on all
|
||||
// of this frame's descendants anyway, so we want to avoid wasting time processing
|
||||
|
@ -1442,7 +1493,9 @@ nsFrameManager::ReResolveStyleContext(nsPresContext *aPresContext,
|
|||
NS_SubtractHint(aMinChange,
|
||||
nsChangeHint_ReflowFrame),
|
||||
childRestyleHint,
|
||||
aRestyleTracker);
|
||||
aRestyleTracker,
|
||||
kidsDesiredA11yNotification,
|
||||
aVisibleKidsOfHiddenElement);
|
||||
} while (outOfFlowFrame = outOfFlowFrame->GetNextContinuation());
|
||||
|
||||
// reresolve placeholder's context under the same parent
|
||||
|
@ -1450,14 +1503,18 @@ nsFrameManager::ReResolveStyleContext(nsPresContext *aPresContext,
|
|||
ReResolveStyleContext(aPresContext, child, content,
|
||||
aChangeList, aMinChange,
|
||||
childRestyleHint,
|
||||
aRestyleTracker);
|
||||
aRestyleTracker,
|
||||
kidsDesiredA11yNotification,
|
||||
aVisibleKidsOfHiddenElement);
|
||||
}
|
||||
else { // regular child frame
|
||||
if (child != resolvedChild) {
|
||||
ReResolveStyleContext(aPresContext, child, content,
|
||||
aChangeList, aMinChange,
|
||||
childRestyleHint,
|
||||
aRestyleTracker);
|
||||
aRestyleTracker,
|
||||
kidsDesiredA11yNotification,
|
||||
aVisibleKidsOfHiddenElement);
|
||||
} else {
|
||||
NOISY_TRACE_FRAME("child frame already resolved as descendant, skipping",aFrame);
|
||||
}
|
||||
|
@ -1469,8 +1526,40 @@ nsFrameManager::ReResolveStyleContext(nsPresContext *aPresContext,
|
|||
childList = aFrame->GetAdditionalChildListName(listIndex++);
|
||||
} while (childList);
|
||||
// XXX need to do overflow frames???
|
||||
}
|
||||
|
||||
#ifdef ACCESSIBILITY
|
||||
// Send notifications about visibility changes.
|
||||
if (ourA11yNotification == eNotifyShown) {
|
||||
nsCOMPtr<nsIAccessibilityService> accService =
|
||||
do_GetService("@mozilla.org/accessibilityService;1");
|
||||
if (accService) {
|
||||
nsIPresShell* presShell = aFrame->PresContext()->GetPresShell();
|
||||
nsIContent* content = aFrame->GetContent();
|
||||
|
||||
accService->ContentRangeInserted(presShell, content->GetParent(),
|
||||
content,
|
||||
content->GetNextSibling());
|
||||
}
|
||||
} else if (ourA11yNotification == eNotifyHidden) {
|
||||
nsCOMPtr<nsIAccessibilityService> accService =
|
||||
do_GetService("@mozilla.org/accessibilityService;1");
|
||||
if (accService) {
|
||||
nsIPresShell* presShell = aFrame->PresContext()->GetPresShell();
|
||||
nsIContent* content = aFrame->GetContent();
|
||||
accService->ContentRemoved(presShell, content->GetParent(), content);
|
||||
|
||||
// Process children staying shown.
|
||||
PRUint32 visibleContentCount = aVisibleKidsOfHiddenElement.Length();
|
||||
for (PRUint32 idx = 0; idx < visibleContentCount; idx++) {
|
||||
nsIContent* content = aVisibleKidsOfHiddenElement[idx];
|
||||
accService->ContentRangeInserted(presShell, content->GetParent(),
|
||||
content, content->GetNextSibling());
|
||||
}
|
||||
aVisibleKidsOfHiddenElement.Clear();
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
return aMinChange;
|
||||
|
@ -1500,6 +1589,7 @@ nsFrameManager::ComputeStyleChangeFor(nsIFrame *aFrame,
|
|||
|
||||
FramePropertyTable *propTable = GetPresContext()->PropertyTable();
|
||||
|
||||
nsTArray<nsIContent*> visibleKidsOfHiddenElement;
|
||||
do {
|
||||
// Outer loop over special siblings
|
||||
do {
|
||||
|
@ -1509,7 +1599,9 @@ nsFrameManager::ComputeStyleChangeFor(nsIFrame *aFrame,
|
|||
aChangeList, topLevelChange,
|
||||
aRestyleDescendants ?
|
||||
eRestyle_Subtree : eRestyle_Self,
|
||||
aRestyleTracker);
|
||||
aRestyleTracker,
|
||||
eSendAllNotifications,
|
||||
visibleKidsOfHiddenElement);
|
||||
NS_UpdateHint(topLevelChange, frameChange);
|
||||
|
||||
if (topLevelChange & nsChangeHint_ReconstructFrame) {
|
||||
|
|
|
@ -202,6 +202,18 @@ public:
|
|||
}
|
||||
|
||||
private:
|
||||
enum DesiredA11yNotifications {
|
||||
eSkipNotifications,
|
||||
eSendAllNotifications,
|
||||
eNotifyIfShown
|
||||
};
|
||||
|
||||
enum A11yNotificationType {
|
||||
eDontNotify,
|
||||
eNotifyShown,
|
||||
eNotifyHidden
|
||||
};
|
||||
|
||||
// Use eRestyle_Self for the aRestyleHint argument to mean
|
||||
// "reresolve our style context but not kids", use eRestyle_Subtree
|
||||
// to mean "reresolve our style context and kids", and use
|
||||
|
@ -214,7 +226,9 @@ private:
|
|||
nsStyleChangeList *aChangeList,
|
||||
nsChangeHint aMinChange,
|
||||
nsRestyleHint aRestyleHint,
|
||||
RestyleTracker& aRestyleTracker);
|
||||
RestyleTracker& aRestyleTracker,
|
||||
DesiredA11yNotifications aDesiredA11yNotifications,
|
||||
nsTArray<nsIContent*>& aVisibleKidsOfHiddenElement);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
Загрузка…
Ссылка в новой задаче