mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-28 15:23:51 +00:00
Bug 552944 - No relationship between tabs and associated property page in new tabbrowser construct, r=enn, davidb, marcoz, sr=neil
--HG-- rename : accessible/tests/mochitest/test_relations.html => accessible/tests/mochitest/relations/test_general.html rename : accessible/tests/mochitest/test_relations.xul => accessible/tests/mochitest/relations/test_general.xul rename : accessible/tests/mochitest/test_relations_tree.xul => accessible/tests/mochitest/relations/test_tree.xul
This commit is contained in:
parent
0fd15d94da
commit
2548445894
@ -45,7 +45,7 @@
|
||||
object. For that XBL binding of element should implement the interface.
|
||||
*/
|
||||
|
||||
[scriptable, uuid(89fb8270-4f25-11df-9879-0800200c9a66)]
|
||||
[scriptable, uuid(ac0639d5-f95b-4e2b-970c-9eab281fb6a5)]
|
||||
interface nsIAccessibleProvider : nsISupports
|
||||
{
|
||||
/**
|
||||
@ -92,15 +92,12 @@ interface nsIAccessibleProvider : nsISupports
|
||||
const long XULRadioButton = 0x00001015;
|
||||
const long XULRadioGroup = 0x00001016;
|
||||
|
||||
/** The single tab in a dialog or tabbrowser/editor interface */
|
||||
/** Used for XUL tab element */
|
||||
const long XULTab = 0x00001017;
|
||||
|
||||
/** A combination of a tabs object and a tabpanels object */
|
||||
const long XULTabBox = 0x00001018;
|
||||
|
||||
/** The collection of tab objects, usable in the TabBox and independent of it
|
||||
as well */
|
||||
const long XULTabs = 0x00001019;
|
||||
/** Used for XUL tabs element, a container for tab elements */
|
||||
const long XULTabs = 0x00001018;
|
||||
/** Used for XUL tabpanels container element */
|
||||
const long XULTabpanels = 0x00001019;
|
||||
|
||||
const long XULText = 0x0000101A;
|
||||
const long XULTextBox = 0x0000101B;
|
||||
|
@ -1916,12 +1916,12 @@ nsAccessibilityService::CreateAccessibleByType(nsIDOMNode *aNode,
|
||||
case nsIAccessibleProvider::XULTab:
|
||||
accessible = new nsXULTabAccessible(aNode, aWeakShell);
|
||||
break;
|
||||
case nsIAccessibleProvider::XULTabBox:
|
||||
accessible = new nsXULTabBoxAccessible(aNode, aWeakShell);
|
||||
break;
|
||||
case nsIAccessibleProvider::XULTabs:
|
||||
accessible = new nsXULTabsAccessible(aNode, aWeakShell);
|
||||
break;
|
||||
case nsIAccessibleProvider::XULTabpanels:
|
||||
accessible = new nsXULTabpanelsAccessible(aNode, aWeakShell);
|
||||
break;
|
||||
case nsIAccessibleProvider::XULText:
|
||||
accessible = new nsXULTextAccessible(aNode, aWeakShell);
|
||||
break;
|
||||
|
@ -47,6 +47,7 @@
|
||||
#include "nsIDOMDocument.h"
|
||||
#include "nsIDOMXULSelectCntrlEl.h"
|
||||
#include "nsIDOMXULSelectCntrlItemEl.h"
|
||||
#include "nsIDOMXULRelatedElement.h"
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// nsXULTabAccessible
|
||||
@ -149,56 +150,20 @@ nsXULTabAccessible::GetRelationByType(PRUint32 aRelationType,
|
||||
return NS_OK;
|
||||
|
||||
// Expose 'LABEL_FOR' relation on tab accessible for tabpanel accessible.
|
||||
// XXX: It makes sense to require the interface from xul:tab to get linked
|
||||
// tabpanel element.
|
||||
nsCOMPtr<nsIContent> content(do_QueryInterface(mDOMNode));
|
||||
|
||||
// Check whether tab and tabpanel are related by 'linkedPanel' attribute on
|
||||
// xul:tab element.
|
||||
rv = nsRelUtils::AddTargetFromIDRefAttr(aRelationType, aRelation, content,
|
||||
nsAccessibilityAtoms::linkedPanel,
|
||||
PR_TRUE);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
if (rv != NS_OK_NO_RELATION_TARGET)
|
||||
nsCOMPtr<nsIDOMXULRelatedElement> tabsElm =
|
||||
do_QueryInterface(content->GetParent());
|
||||
if (!tabsElm)
|
||||
return NS_OK;
|
||||
|
||||
// If there is no 'linkedPanel' attribute on xul:tab element then we
|
||||
// assume tab and tabpanels are related 1 to 1. We follow algorithm from
|
||||
// the setter 'selectedIndex' of tabbox.xml#tabs binding.
|
||||
nsCOMPtr<nsIDOMNode> tabpanelNode;
|
||||
tabsElm->GetRelatedElement(mDOMNode, getter_AddRefs(tabpanelNode));
|
||||
if (!tabpanelNode)
|
||||
return NS_OK;
|
||||
|
||||
nsAccessible* tabsAcc = GetParent();
|
||||
NS_ENSURE_TRUE(nsAccUtils::Role(tabsAcc) == nsIAccessibleRole::ROLE_PAGETABLIST,
|
||||
NS_ERROR_FAILURE);
|
||||
|
||||
PRInt32 tabIndex = -1;
|
||||
|
||||
PRInt32 childCount = tabsAcc->GetChildCount();
|
||||
for (PRInt32 childIdx = 0; childIdx < childCount; childIdx++) {
|
||||
nsAccessible* childAcc = tabsAcc->GetChildAt(childIdx);
|
||||
if (nsAccUtils::Role(childAcc) == nsIAccessibleRole::ROLE_PAGETAB)
|
||||
tabIndex++;
|
||||
|
||||
if (childAcc == this)
|
||||
break;
|
||||
}
|
||||
|
||||
nsAccessible* tabBoxAcc = tabsAcc->GetParent();
|
||||
NS_ENSURE_TRUE(nsAccUtils::Role(tabBoxAcc) == nsIAccessibleRole::ROLE_PANE,
|
||||
NS_ERROR_FAILURE);
|
||||
|
||||
childCount = tabBoxAcc->GetChildCount();
|
||||
for (PRInt32 childIdx = 0; childIdx < childCount; childIdx++) {
|
||||
nsAccessible* childAcc = tabBoxAcc->GetChildAt(childIdx);
|
||||
if (nsAccUtils::Role(childAcc) == nsIAccessibleRole::ROLE_PROPERTYPAGE) {
|
||||
if (tabIndex == 0)
|
||||
return nsRelUtils::AddTarget(aRelationType, aRelation, childAcc);
|
||||
|
||||
tabIndex--;
|
||||
}
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
nsCOMPtr<nsIContent> tabpanelContent(do_QueryInterface(tabpanelNode));
|
||||
return nsRelUtils::AddTargetFromContent(aRelationType, aRelation,
|
||||
tabpanelContent);
|
||||
}
|
||||
|
||||
void
|
||||
@ -211,40 +176,15 @@ nsXULTabAccessible::GetPositionAndSizeInternal(PRInt32 *aPosInSet,
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// nsXULTabBoxAccessible
|
||||
// nsXULTabsAccessible
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/**
|
||||
* XUL TabBox
|
||||
* to facilitate naming of the tabPanels object we will give this the name
|
||||
* of the selected tab in the tabs object.
|
||||
*/
|
||||
|
||||
/** Constructor */
|
||||
nsXULTabBoxAccessible::nsXULTabBoxAccessible(nsIDOMNode* aNode, nsIWeakReference* aShell):
|
||||
nsAccessibleWrap(aNode, aShell)
|
||||
{
|
||||
}
|
||||
|
||||
/** We are a window*/
|
||||
nsresult
|
||||
nsXULTabBoxAccessible::GetRoleInternal(PRUint32 *aRole)
|
||||
nsXULTabsAccessible::
|
||||
nsXULTabsAccessible(nsIDOMNode *aNode, nsIWeakReference *aShell) :
|
||||
nsXULSelectableAccessible(aNode, aShell)
|
||||
{
|
||||
*aRole = nsIAccessibleRole::ROLE_PANE;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* XUL Tabs - the s really stands for strip. this is a collection of tab objects
|
||||
*/
|
||||
|
||||
/** Constructor */
|
||||
nsXULTabsAccessible::nsXULTabsAccessible(nsIDOMNode* aNode, nsIWeakReference* aShell):
|
||||
nsXULSelectableAccessible(aNode, aShell)
|
||||
{
|
||||
}
|
||||
|
||||
/** We are a Page Tab List */
|
||||
nsresult
|
||||
nsXULTabsAccessible::GetRoleInternal(PRUint32 *aRole)
|
||||
{
|
||||
@ -252,10 +192,12 @@ nsXULTabsAccessible::GetRoleInternal(PRUint32 *aRole)
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
/** no actions */
|
||||
NS_IMETHODIMP nsXULTabsAccessible::GetNumActions(PRUint8 *_retval)
|
||||
NS_IMETHODIMP
|
||||
nsXULTabsAccessible::GetNumActions(PRUint8 *aCount)
|
||||
{
|
||||
*_retval = 0;
|
||||
NS_ENSURE_ARG_POINTER(aCount);
|
||||
*aCount = 0;
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
@ -272,8 +214,28 @@ nsXULTabsAccessible::GetNameInternal(nsAString& aName)
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// nsXULTabpanelsAccessible
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
nsXULTabpanelsAccessible::
|
||||
nsXULTabpanelsAccessible(nsIDOMNode *aNode, nsIWeakReference *aShell) :
|
||||
nsAccessibleWrap(aNode, aShell)
|
||||
{
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsXULTabpanelsAccessible::GetRoleInternal(PRUint32 *aRole)
|
||||
{
|
||||
*aRole = nsIAccessibleRole::ROLE_PANE;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// nsXULTabpanelAccessible
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
nsXULTabpanelAccessible::
|
||||
nsXULTabpanelAccessible(nsIDOMNode* aNode, nsIWeakReference* aShell):
|
||||
@ -299,71 +261,18 @@ nsXULTabpanelAccessible::GetRelationByType(PRUint32 aRelationType,
|
||||
return NS_OK;
|
||||
|
||||
// Expose 'LABELLED_BY' relation on tabpanel accessible for tab accessible.
|
||||
nsCOMPtr<nsIAccessible> tabBoxAcc;
|
||||
GetParent(getter_AddRefs(tabBoxAcc));
|
||||
NS_ENSURE_TRUE(nsAccUtils::Role(tabBoxAcc) == nsIAccessibleRole::ROLE_PANE,
|
||||
NS_ERROR_FAILURE);
|
||||
|
||||
PRInt32 tabpanelIndex = -1;
|
||||
nsCOMPtr<nsIAccessible> tabsAcc;
|
||||
|
||||
PRBool isTabpanelFound = PR_FALSE;
|
||||
nsCOMPtr<nsIAccessible> childAcc;
|
||||
tabBoxAcc->GetFirstChild(getter_AddRefs(childAcc));
|
||||
while (childAcc && (!tabsAcc || !isTabpanelFound)) {
|
||||
if (nsAccUtils::Role(childAcc) == nsIAccessibleRole::ROLE_PAGETABLIST)
|
||||
tabsAcc = childAcc;
|
||||
|
||||
if (!isTabpanelFound &&
|
||||
nsAccUtils::Role(childAcc) == nsIAccessibleRole::ROLE_PROPERTYPAGE)
|
||||
tabpanelIndex++;
|
||||
|
||||
if (childAcc == this)
|
||||
isTabpanelFound = PR_TRUE;
|
||||
|
||||
nsCOMPtr<nsIAccessible> acc;
|
||||
childAcc->GetNextSibling(getter_AddRefs(acc));
|
||||
childAcc.swap(acc);
|
||||
}
|
||||
|
||||
if (!tabsAcc || tabpanelIndex == -1)
|
||||
nsCOMPtr<nsIContent> content(do_QueryInterface(mDOMNode));
|
||||
nsCOMPtr<nsIDOMXULRelatedElement> tabpanelsElm =
|
||||
do_QueryInterface(content->GetParent());
|
||||
if (!tabpanelsElm)
|
||||
return NS_OK;
|
||||
|
||||
nsCOMPtr<nsIContent> content(do_QueryInterface(mDOMNode));
|
||||
nsIAtom *atomID = content->GetID();
|
||||
nsCOMPtr<nsIDOMNode> tabNode;
|
||||
tabpanelsElm->GetRelatedElement(mDOMNode, getter_AddRefs(tabNode));
|
||||
if (!tabNode)
|
||||
return NS_OK;
|
||||
|
||||
nsCOMPtr<nsIAccessible> foundTabAcc;
|
||||
tabsAcc->GetFirstChild(getter_AddRefs(childAcc));
|
||||
while (childAcc) {
|
||||
if (nsAccUtils::Role(childAcc) == nsIAccessibleRole::ROLE_PAGETAB) {
|
||||
if (atomID) {
|
||||
nsCOMPtr<nsIAccessNode> tabAccNode(do_QueryInterface(childAcc));
|
||||
nsCOMPtr<nsIDOMNode> tabNode;
|
||||
tabAccNode->GetDOMNode(getter_AddRefs(tabNode));
|
||||
nsCOMPtr<nsIContent> tabContent(do_QueryInterface(tabNode));
|
||||
NS_ENSURE_TRUE(tabContent, NS_ERROR_FAILURE);
|
||||
|
||||
if (tabContent->AttrValueIs(kNameSpaceID_None,
|
||||
nsAccessibilityAtoms::linkedPanel, atomID,
|
||||
eCaseMatters)) {
|
||||
return nsRelUtils::AddTarget(aRelationType, aRelation, childAcc);
|
||||
}
|
||||
}
|
||||
|
||||
if (tabpanelIndex == 0) {
|
||||
foundTabAcc = childAcc;
|
||||
if (!atomID)
|
||||
break;
|
||||
}
|
||||
|
||||
tabpanelIndex--;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIAccessible> acc;
|
||||
childAcc->GetNextSibling(getter_AddRefs(acc));
|
||||
childAcc.swap(acc);
|
||||
}
|
||||
|
||||
return nsRelUtils::AddTarget(aRelationType, aRelation, foundTabAcc);
|
||||
nsCOMPtr<nsIContent> tabContent(do_QueryInterface(tabNode));
|
||||
return nsRelUtils::AddTargetFromContent(aRelationType, aRelation,
|
||||
tabContent);
|
||||
}
|
||||
|
||||
|
@ -44,7 +44,7 @@
|
||||
#include "nsXULMenuAccessible.h"
|
||||
|
||||
/**
|
||||
* An individual tab, xul:tab element
|
||||
* An individual tab, xul:tab element.
|
||||
*/
|
||||
class nsXULTabAccessible : public nsAccessibleWrap
|
||||
{
|
||||
@ -67,22 +67,9 @@ public:
|
||||
virtual nsresult GetStateInternal(PRUint32 *aState, PRUint32 *aExtraState);
|
||||
};
|
||||
|
||||
/**
|
||||
* Contains a tabs object and a tabPanels object. A complete
|
||||
* entity with relationships between tabs and content to
|
||||
* be displayed in the tabpanels object
|
||||
*/
|
||||
class nsXULTabBoxAccessible : public nsAccessibleWrap
|
||||
{
|
||||
public:
|
||||
nsXULTabBoxAccessible(nsIDOMNode* aNode, nsIWeakReference* aShell);
|
||||
|
||||
// nsAccessible
|
||||
virtual nsresult GetRoleInternal(PRUint32 *aRole);
|
||||
};
|
||||
|
||||
/**
|
||||
* A container of tab obejcts, xul:tabs element.
|
||||
* A container of tab objects, xul:tabs element.
|
||||
*/
|
||||
class nsXULTabsAccessible : public nsXULSelectableAccessible
|
||||
{
|
||||
@ -98,11 +85,29 @@ public:
|
||||
virtual nsresult GetRoleInternal(PRUint32 *aRole);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* A container of tab panels, xul:tabpanels element.
|
||||
*/
|
||||
class nsXULTabpanelsAccessible : public nsAccessibleWrap
|
||||
{
|
||||
public:
|
||||
nsXULTabpanelsAccessible(nsIDOMNode *aNode, nsIWeakReference *aShell);
|
||||
|
||||
// nsAccessible
|
||||
virtual nsresult GetRoleInternal(PRUint32 *aRole);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* A tabpanel object, child elements of xul:tabpanels element. Note,the object
|
||||
* is created from nsAccessibilityService::GetAccessibleForDeckChildren()
|
||||
* method and we do not use nsIAccessibleProvider interface here because
|
||||
* all children of xul:tabpanels element acts as xul:tabpanel element.
|
||||
*
|
||||
* XXX: we need to move the class logic into generic class since
|
||||
* for example we do not create instance of this class for XUL textbox used as
|
||||
* a tabpanel.
|
||||
*/
|
||||
class nsXULTabpanelAccessible : public nsAccessibleWrap
|
||||
{
|
||||
|
@ -42,7 +42,7 @@ srcdir = @srcdir@
|
||||
VPATH = @srcdir@
|
||||
relativesrcdir = accessible
|
||||
|
||||
DIRS = actions attributes events selectable states tree
|
||||
DIRS = actions attributes events relations selectable states tree
|
||||
|
||||
include $(DEPTH)/config/autoconf.mk
|
||||
include $(topsrcdir)/config/rules.mk
|
||||
@ -104,9 +104,6 @@ _TEST_FILES =\
|
||||
test_nsIAccessibleImage.html \
|
||||
test_nsIAccessNode_utils.html \
|
||||
test_nsOuterDocAccessible.html \
|
||||
test_relations.html \
|
||||
test_relations.xul \
|
||||
test_relations_tree.xul \
|
||||
test_role_nsHyperTextAcc.html \
|
||||
test_table_1.html \
|
||||
test_table_4.html \
|
||||
|
56
accessible/tests/mochitest/relations/Makefile.in
Normal file
56
accessible/tests/mochitest/relations/Makefile.in
Normal file
@ -0,0 +1,56 @@
|
||||
#
|
||||
# ***** BEGIN LICENSE BLOCK *****
|
||||
# Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
#
|
||||
# The contents of this file are subject to the Mozilla Public License Version
|
||||
# 1.1 (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.mozilla.org/MPL/
|
||||
#
|
||||
# Software distributed under the License is distributed on an "AS IS" basis,
|
||||
# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
# for the specific language governing rights and limitations under the
|
||||
# License.
|
||||
#
|
||||
# The Original Code is mozilla.org code.
|
||||
#
|
||||
# The Initial Developer of the Original Code is
|
||||
# Mozilla Corporation.
|
||||
# Portions created by the Initial Developer are Copyright (C) 2010
|
||||
# the Initial Developer. All Rights Reserved.
|
||||
#
|
||||
# Contributor(s):
|
||||
# Alexander Surkov <surkov.alexander@gmail.com> (original author)
|
||||
#
|
||||
# Alternatively, the contents of this file may be used under the terms of
|
||||
# either of the GNU General Public License Version 2 or later (the "GPL"),
|
||||
# or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
# in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
# of those above. If you wish to allow use of your version of this file only
|
||||
# under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
# use your version of this file under the terms of the MPL, indicate your
|
||||
# decision by deleting the provisions above and replace them with the notice
|
||||
# and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
# the provisions above, a recipient may use your version of this file under
|
||||
# the terms of any one of the MPL, the GPL or the LGPL.
|
||||
#
|
||||
# ***** END LICENSE BLOCK *****
|
||||
|
||||
DEPTH = ../../../..
|
||||
topsrcdir = @top_srcdir@
|
||||
srcdir = @srcdir@
|
||||
VPATH = @srcdir@
|
||||
relativesrcdir = accessible/relations
|
||||
|
||||
include $(DEPTH)/config/autoconf.mk
|
||||
include $(topsrcdir)/config/rules.mk
|
||||
|
||||
_TEST_FILES =\
|
||||
test_general.html \
|
||||
test_general.xul \
|
||||
test_tabbrowser.xul \
|
||||
test_tree.xul \
|
||||
$(NULL)
|
||||
|
||||
libs:: $(_TEST_FILES)
|
||||
$(INSTALL) $(foreach f,$^,"$f") $(DEPTH)/_tests/testing/mochitest/a11y/$(relativesrcdir)
|
121
accessible/tests/mochitest/relations/test_tabbrowser.xul
Normal file
121
accessible/tests/mochitest/relations/test_tabbrowser.xul
Normal file
@ -0,0 +1,121 @@
|
||||
<?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"?>
|
||||
<?xml-stylesheet href="chrome://browser/content/browser.css"
|
||||
type="text/css"?>
|
||||
|
||||
<window xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
|
||||
title="Accessible XUL tabbrowser relation tests">
|
||||
|
||||
<script type="application/javascript"
|
||||
src="chrome://mochikit/content/MochiKit/packed.js" />
|
||||
<script type="application/javascript"
|
||||
src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js" />
|
||||
|
||||
<script type="application/javascript"
|
||||
src="chrome://mochikit/content/a11y/accessible/common.js" />
|
||||
<script type="application/javascript"
|
||||
src="chrome://mochikit/content/a11y/accessible/role.js" />
|
||||
<script type="application/javascript"
|
||||
src="chrome://mochikit/content/a11y/accessible/relations.js" />
|
||||
|
||||
<script type="application/javascript">
|
||||
<![CDATA[
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
// Test
|
||||
|
||||
const Ci = Components.interfaces;
|
||||
|
||||
// Hack to make xul:tabbrowser work.
|
||||
var handleDroppedLink = null;
|
||||
Components.utils.import("resource://gre/modules/Services.jsm");
|
||||
var XULBrowserWindow = {
|
||||
isBusy: false,
|
||||
setOverLink: function (link, b) {
|
||||
}
|
||||
};
|
||||
var gFindBar = {
|
||||
hidden: true
|
||||
};
|
||||
|
||||
function doTest()
|
||||
{
|
||||
var tabBrowser = document.getElementById("tabbrowser");
|
||||
|
||||
var progressListener =
|
||||
{
|
||||
onStateChange: function onStateChange(aWebProgress,
|
||||
aRequest,
|
||||
aStateFlags,
|
||||
aStatus)
|
||||
{
|
||||
if (aStateFlags & Ci.nsIWebProgressListener.STATE_STOP)
|
||||
testRelations();
|
||||
}
|
||||
};
|
||||
|
||||
tabBrowser.addProgressListener(progressListener,
|
||||
Ci.nsIWebProgress.NOTIFY_STATE_WINDOW);
|
||||
|
||||
tabBrowser.loadTabs(["about:", "about:mozilla"], false, true);
|
||||
}
|
||||
|
||||
function testRelations()
|
||||
{
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// 'labelled by'/'label for' relations for xul:tab and xul:tabpanel
|
||||
|
||||
var tabs = getNode("tabbrowser").tabContainer.childNodes;
|
||||
var panels = getNode("tabbrowser").mTabBox.tabpanels.childNodes;
|
||||
|
||||
testRelation(panels[0], RELATION_LABELLED_BY, tabs[0]);
|
||||
testRelation(tabs[0], RELATION_LABEL_FOR, panels[0]);
|
||||
testRelation(panels[1], RELATION_LABELLED_BY, tabs[1]);
|
||||
testRelation(tabs[1], RELATION_LABEL_FOR, panels[1]);
|
||||
|
||||
SimpleTest.finish()
|
||||
}
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
addA11yLoadEvent(doTest);
|
||||
]]>
|
||||
</script>
|
||||
|
||||
<vbox 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=552944"
|
||||
title="No relationship between tabs and associated property page in new tabbrowser construct">
|
||||
Mozilla Bug 552944
|
||||
</a><br/>
|
||||
<p id="display"></p>
|
||||
<div id="content" style="display: none">
|
||||
</div>
|
||||
<pre id="test">
|
||||
</pre>
|
||||
</body>
|
||||
|
||||
<!-- Hack to make xul:tabbrowser work -->
|
||||
<menubar>
|
||||
<menu label="menu">
|
||||
<menupopup>
|
||||
<menuitem label="close window hook" id="menu_closeWindow"/>
|
||||
<menuitem label="close hook" id="menu_close"/>
|
||||
</menupopup>
|
||||
</menu>
|
||||
</menubar>
|
||||
|
||||
<tabs id="tabbrowser-tabs" class="tabbrowser-tabs"
|
||||
tabbrowser="tabbrowser"
|
||||
setfocus="false">
|
||||
<tab class="tabbrowser-tab" selected="true"/>
|
||||
</tabs>
|
||||
<tabbrowser id="tabbrowser"
|
||||
type="content-primary"
|
||||
tabcontainer="tabbrowser-tabs"
|
||||
flex="1"/>
|
||||
</vbox>
|
||||
|
||||
</window>
|
||||
|
@ -27,21 +27,23 @@
|
||||
// tabbox
|
||||
|
||||
var accTree = {
|
||||
role: ROLE_PANE,
|
||||
role: ROLE_PAGETABLIST,
|
||||
children: [
|
||||
{
|
||||
role: ROLE_PAGETABLIST,
|
||||
children: [
|
||||
{
|
||||
role: ROLE_PAGETAB,
|
||||
children: []
|
||||
},
|
||||
{
|
||||
role: ROLE_PAGETAB,
|
||||
children: []
|
||||
}
|
||||
]
|
||||
role: ROLE_PAGETAB,
|
||||
children: []
|
||||
},
|
||||
{
|
||||
role: ROLE_PAGETAB,
|
||||
children: []
|
||||
}
|
||||
]
|
||||
};
|
||||
testAccessibleTree("tabs", accTree);
|
||||
|
||||
accTree = {
|
||||
role: ROLE_PANE,
|
||||
children: [
|
||||
{
|
||||
role: ROLE_PROPERTYPAGE,
|
||||
children: []
|
||||
@ -52,7 +54,7 @@
|
||||
}
|
||||
]
|
||||
};
|
||||
testAccessibleTree("tabbox", accTree);
|
||||
testAccessibleTree("tabpanels", accTree);
|
||||
|
||||
SimpleTest.finish()
|
||||
}
|
||||
@ -69,6 +71,11 @@
|
||||
title=" WARNING: Bad accessible tree!: [tabbrowser tab] ">
|
||||
Mozilla Bug 540389
|
||||
</a><br/>
|
||||
<a target="_blank"
|
||||
href="https://bugzilla.mozilla.org/show_bug.cgi?id=552944"
|
||||
title="No relationship between tabs and associated property page in new tabbrowser construct">
|
||||
Mozilla Bug 552944
|
||||
</a><br/>
|
||||
<p id="display"></p>
|
||||
<div id="content" style="display: none">
|
||||
</div>
|
||||
@ -77,12 +84,12 @@
|
||||
</body>
|
||||
|
||||
<vbox flex="1">
|
||||
<tabbox id="tabbox">
|
||||
<tabs>
|
||||
<tabbox>
|
||||
<tabs id="tabs">
|
||||
<tab label="tab1"/>
|
||||
<tab label="tab2"/>
|
||||
</tabs>
|
||||
<tabpanels>
|
||||
<tabpanels id="tabpanels">
|
||||
<tabpanel/>
|
||||
<tabpanel/>
|
||||
</tabpanels>
|
||||
|
@ -91,6 +91,8 @@
|
||||
}
|
||||
]
|
||||
};
|
||||
testAccessibleTree(getNode("tabbrowser").tabContainer, tabsAccTree);
|
||||
|
||||
var tabboxAccTree = {
|
||||
role: ROLE_PANE,
|
||||
children: [
|
||||
@ -102,8 +104,9 @@
|
||||
}
|
||||
]
|
||||
};
|
||||
testAccessibleTree(getNode("tabbrowser").tabContainer, tabsAccTree);
|
||||
testAccessibleTree(getNode("tabbrowser").mTabBox, tabboxAccTree);
|
||||
|
||||
testAccessibleTree(getNode("tabbrowser").mTabBox.tabpanels,
|
||||
tabboxAccTree);
|
||||
|
||||
SimpleTest.finish()
|
||||
}
|
||||
@ -120,6 +123,11 @@
|
||||
title=" WARNING: Bad accessible tree!: [tabbrowser tab] ">
|
||||
Mozilla Bug 540389
|
||||
</a><br/>
|
||||
<a target="_blank"
|
||||
href="https://bugzilla.mozilla.org/show_bug.cgi?id=552944"
|
||||
title="No relationship between tabs and associated property page in new tabbrowser construct">
|
||||
Mozilla Bug 552944
|
||||
</a><br/>
|
||||
<p id="display"></p>
|
||||
<div id="content" style="display: none">
|
||||
</div>
|
||||
|
@ -61,6 +61,7 @@ XPIDLSRCS = \
|
||||
nsIDOMXULLabeledControlEl.idl \
|
||||
nsIDOMXULMenuListElement.idl \
|
||||
nsIDOMXULPopupElement.idl \
|
||||
nsIDOMXULRelatedElement.idl \
|
||||
nsIDOMXULSelectCntrlEl.idl \
|
||||
nsIDOMXULSelectCntrlItemEl.idl \
|
||||
nsIDOMXULMultSelectCntrlEl.idl \
|
||||
|
51
dom/interfaces/xul/nsIDOMXULRelatedElement.idl
Normal file
51
dom/interfaces/xul/nsIDOMXULRelatedElement.idl
Normal file
@ -0,0 +1,51 @@
|
||||
/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (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.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is mozilla.org code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Mozilla Foundation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2010
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Alexander Surkov <surkov.alexander@gmail.com> (original author)
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either of the GNU General Public License Version 2 or later (the "GPL"),
|
||||
* or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#include "domstubs.idl"
|
||||
|
||||
[scriptable, uuid(9fbac05a-fb27-470d-8e5f-028b2dc54ad0)]
|
||||
interface nsIDOMXULRelatedElement : nsISupports
|
||||
{
|
||||
/**
|
||||
* Retrun an element associated with the given element. It's implemented
|
||||
* by container elements having relation between their items. For example,
|
||||
* this interface is implemented by XUL tabs and XUL tabpanels elements
|
||||
* and used to get XUL tab element by linked tab panel and vice versa.
|
||||
*/
|
||||
nsIDOMNode getRelatedElement(in nsIDOMNode aElement);
|
||||
};
|
@ -13,15 +13,7 @@
|
||||
|
||||
<binding id="tabbox"
|
||||
extends="chrome://global/content/bindings/tabbox.xml#tab-base">
|
||||
<implementation implements="nsIDOMEventListener, nsIAccessibleProvider">
|
||||
<property name="accessibleType" readonly="true">
|
||||
<getter>
|
||||
<![CDATA[
|
||||
return Components.interfaces.nsIAccessibleProvider.XULTabBox;
|
||||
]]>
|
||||
</getter>
|
||||
</property>
|
||||
|
||||
<implementation implements="nsIDOMEventListener">
|
||||
<property name="handleCtrlTab">
|
||||
<setter>
|
||||
<![CDATA[
|
||||
@ -243,7 +235,7 @@
|
||||
<xul:spacer class="tabs-right" flex="1"/>
|
||||
</content>
|
||||
|
||||
<implementation implements="nsIDOMXULSelectControlElement, nsIAccessibleProvider">
|
||||
<implementation implements="nsIDOMXULSelectControlElement, nsIDOMXULRelatedElement, nsIAccessibleProvider">
|
||||
<constructor>
|
||||
<![CDATA[
|
||||
// first and last tabs need to be able to have unique styles
|
||||
@ -278,7 +270,8 @@
|
||||
this.selectedIndex = 0;
|
||||
]]>
|
||||
</constructor>
|
||||
|
||||
|
||||
<!-- nsIAccessibleProvider -->
|
||||
<property name="accessibleType" readonly="true">
|
||||
<getter>
|
||||
<![CDATA[
|
||||
@ -287,6 +280,55 @@
|
||||
</getter>
|
||||
</property>
|
||||
|
||||
<!-- nsIDOMXULRelatedElement -->
|
||||
<method name="getRelatedElement">
|
||||
<parameter name="aTabElm"/>
|
||||
<body>
|
||||
<![CDATA[
|
||||
if (!aTabElm)
|
||||
return null;
|
||||
|
||||
let tabboxElm = this.tabbox;
|
||||
if (!tabboxElm)
|
||||
return null;
|
||||
|
||||
let tabpanelsElm = tabboxElm.tabpanels;
|
||||
if (!tabpanelsElm)
|
||||
return null;
|
||||
|
||||
// Get linked tab panel by 'linkedpanel' attribute on the given tab
|
||||
// element.
|
||||
let linkedPanelElm = null;
|
||||
|
||||
let linkedPanelId = aTabElm.linkedPanel;
|
||||
if (linkedPanelId) {
|
||||
let ownerDoc = this.ownerDocument;
|
||||
|
||||
// XXX bug 565858: if XUL tab element is anonymous element then
|
||||
// suppose linked tab panel is hosted within the same XBL binding
|
||||
// and search it by ID attribute inside an anonymous content of
|
||||
// the binding. This is not robust assumption since tab elements may
|
||||
// live outside a tabbox element so that for example tab elements
|
||||
// can be explicit content but tab panels can be anonymous.
|
||||
|
||||
let bindingParent = ownerDoc.getBindingParent(aTabElm);
|
||||
if (bindingParent)
|
||||
return ownerDoc.getAnonymousElementByAttribute(bindingParent,
|
||||
"id",
|
||||
linkedPanelId);
|
||||
|
||||
return ownerDoc.getElementById(linkedPanelId);
|
||||
}
|
||||
|
||||
// otherwise linked tabpanel element has the same index as the given
|
||||
// tab element.
|
||||
let tabElmIdx = this.getIndexOfItem(aTabElm);
|
||||
return tabpanelsElm.childNodes[tabElmIdx];
|
||||
]]>
|
||||
</body>
|
||||
</method>
|
||||
|
||||
<!-- nsIDOMXULSelectControlElement -->
|
||||
<property name="itemCount" readonly="true"
|
||||
onget="return this.childNodes.length"/>
|
||||
|
||||
@ -347,31 +389,13 @@
|
||||
|
||||
this.setAttribute("value", tab.value);
|
||||
|
||||
if (this.tabbox) {
|
||||
let linkedPanel = this.getRelatedElement(tab);
|
||||
if (linkedPanel) {
|
||||
this.tabbox.setAttribute("selectedIndex", val);
|
||||
var tabpanels = this.tabbox.tabpanels;
|
||||
// This will cause an onselect event to fire for the tabpanel element.
|
||||
if (tabpanels) {
|
||||
// find an id
|
||||
let linkedPanelId = tab.linkedPanel;
|
||||
let linkedPanel = null;
|
||||
if (linkedPanelId) {
|
||||
let ownerDoc = tab.ownerDocument;
|
||||
let bindingParent = ownerDoc.getBindingParent(tab);
|
||||
if (bindingParent) {
|
||||
linkedPanel =
|
||||
ownerDoc.getAnonymousElementByAttribute(bindingParent,
|
||||
"id",
|
||||
linkedPanelId);
|
||||
}
|
||||
else
|
||||
linkedPanel = ownerDoc.getElementById(linkedPanelId);
|
||||
}
|
||||
if (linkedPanel)
|
||||
tabpanels.selectedPanel = linkedPanel;
|
||||
else
|
||||
tabpanels.selectedIndex = val;
|
||||
}
|
||||
|
||||
// This will cause an onselect event to fire for the tabpanel
|
||||
// element.
|
||||
this.tabbox.tabpanels.selectedPanel = linkedPanel;
|
||||
}
|
||||
|
||||
if (!alreadySelected) {
|
||||
@ -555,7 +579,66 @@
|
||||
|
||||
<binding id="tabpanels"
|
||||
extends="chrome://global/content/bindings/tabbox.xml#tab-base">
|
||||
<implementation>
|
||||
<implementation implements="nsIAccessibleProvider, nsIDOMXULRelatedElement">
|
||||
|
||||
<!-- nsIAccessibleProvider -->
|
||||
<property name="accessibleType" readonly="true">
|
||||
<getter>
|
||||
<![CDATA[
|
||||
return Components.interfaces.nsIAccessibleProvider.XULTabpanels;
|
||||
]]>
|
||||
</getter>
|
||||
</property>
|
||||
|
||||
<!-- nsIDOMXULRelatedElement -->
|
||||
<method name="getRelatedElement">
|
||||
<parameter name="aTabPanelElm"/>
|
||||
<body>
|
||||
<![CDATA[
|
||||
if (!aTabPanelElm)
|
||||
return null;
|
||||
|
||||
let tabboxElm = this.tabbox;
|
||||
if (!tabboxElm)
|
||||
return null;
|
||||
|
||||
let tabsElm = tabboxElm.tabs;
|
||||
if (!tabsElm)
|
||||
return null;
|
||||
|
||||
// Return tab element having 'linkedpanel' attribute equal to the id
|
||||
// of the tab panel or the same index as the tab panel element.
|
||||
let tabpanelIdx = Array.indexOf(this.childNodes, aTabPanelElm);
|
||||
if (tabpanelIdx == -1)
|
||||
return null;
|
||||
|
||||
let tabElms = tabsElm.childNodes;
|
||||
let tabElmFromIndex = tabElms[tabpanelIdx];
|
||||
|
||||
let tabpanelId = aTabPanelElm.id;
|
||||
if (tabpanelId) {
|
||||
for (let idx = 0; idx < tabElms.length; idx++) {
|
||||
var tabElm = tabElms[idx];
|
||||
if (tabElm.linkedPanel == tabpanelId)
|
||||
return tabElm;
|
||||
}
|
||||
}
|
||||
|
||||
return tabElmFromIndex;
|
||||
]]>
|
||||
</body>
|
||||
</method>
|
||||
|
||||
<!-- public -->
|
||||
<field name="tabbox" readonly="true"><![CDATA[
|
||||
var parent = this.parentNode;
|
||||
while (parent) {
|
||||
if (parent.localName == "tabbox")
|
||||
break;
|
||||
parent = parent.parentNode;
|
||||
}
|
||||
parent;
|
||||
]]></field>
|
||||
|
||||
<field name="_selectedPanel">this.childNodes.item(this.selectedIndex)</field>
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user