diff --git a/accessible/public/nsIAccessibleTable.idl b/accessible/public/nsIAccessibleTable.idl index 8ac7e7f5428d..265a6a1ae568 100644 --- a/accessible/public/nsIAccessibleTable.idl +++ b/accessible/public/nsIAccessibleTable.idl @@ -45,7 +45,7 @@ interface nsIAccessible; interface nsIArray; -[scriptable, uuid(035c0c0e-41e3-4985-8ad9-d9f14cdc667a)] +[scriptable, uuid(cb0bf7b9-117e-40e2-9e46-189c3d43ce4a)] interface nsIAccessibleTable : nsISupports { /** @@ -104,6 +104,17 @@ interface nsIAccessibleTable : nsISupports */ long getRowIndexAt(in long cellIndex); + /** + * Translate the given cell index into the corresponding row and column + * indices. + * + * @param cellIndex [in] cell index to return row and column indices for + * @param rowIndex [out] row index at the given cell index + * @param columnIndex [out] column index at the given cell index + */ + void getRowAndColumnIndicesAt(in long cellIndex, + out long rowIndex, out long columnIndex); + /** * Return the number of columns occupied by the accessible cell at * the specified row and column in the table. The result differs from 1 if diff --git a/accessible/src/base/AccGroupInfo.cpp b/accessible/src/base/AccGroupInfo.cpp new file mode 100644 index 000000000000..61ece7a36c55 --- /dev/null +++ b/accessible/src/base/AccGroupInfo.cpp @@ -0,0 +1,169 @@ +/* ***** 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 (original author) + * + * Alternatively, the contents of this file may be used under the terms of + * either 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 "AccGroupInfo.h" + +AccGroupInfo::AccGroupInfo(nsAccessible* aItem, PRUint32 aRole) : + mPosInSet(0), mSetSize(0), mParent(nsnull) +{ + nsAccessible* parent = aItem->GetParent(); + if (!parent) + return; + + PRInt32 indexInParent = aItem->GetIndexInParent(); + PRInt32 level = nsAccUtils::GetARIAOrDefaultLevel(aItem); + + // Compute position in set. + mPosInSet = 1; + for (PRInt32 idx = indexInParent - 1; idx >=0 ; idx--) { + nsAccessible* sibling = parent->GetChildAt(idx); + PRUint32 siblingRole = nsAccUtils::Role(sibling); + + // If the sibling is separator then the group is ended. + if (siblingRole == nsIAccessibleRole::ROLE_SEPARATOR) + break; + + // If sibling is not visible and hasn't the same base role. + if (BaseRole(siblingRole) != aRole || + nsAccUtils::State(sibling) & nsIAccessibleStates::STATE_INVISIBLE) + continue; + + // Check if it's hierarchical flatten structure, i.e. if the sibling + // level is lesser than this one then group is ended, if the sibling level + // is greater than this one then the group is split by some child elements + // (group will be continued). + PRInt32 siblingLevel = nsAccUtils::GetARIAOrDefaultLevel(sibling); + if (siblingLevel < level) { + mParent = sibling; + break; + } + + // Skip subset. + if (siblingLevel > level) + continue; + + // If the previous item in the group has calculated group information then + // build group information for this item based on found one. + if (sibling->mGroupInfo) { + mPosInSet += sibling->mGroupInfo->mPosInSet; + mParent = sibling->mGroupInfo->mParent; + mSetSize = sibling->mGroupInfo->mSetSize; + return; + } + + mPosInSet++; + } + + // Compute set size. + mSetSize = mPosInSet; + + PRInt32 siblingCount = parent->GetChildCount(); + for (PRInt32 idx = indexInParent + 1; idx < siblingCount; idx++) { + nsAccessible* sibling = parent->GetChildAt(idx); + + PRUint32 siblingRole = nsAccUtils::Role(sibling); + + // If the sibling is separator then the group is ended. + if (siblingRole == nsIAccessibleRole::ROLE_SEPARATOR) + break; + + // If sibling is visible and has the same base role + if (BaseRole(siblingRole) != aRole || + nsAccUtils::State(sibling) & nsIAccessibleStates::STATE_INVISIBLE) + continue; + + // and check if it's hierarchical flatten structure. + PRInt32 siblingLevel = nsAccUtils::GetARIAOrDefaultLevel(sibling); + if (siblingLevel < level) + break; + + // Skip subset. + if (siblingLevel > level) + continue; + + // If the next item in the group has calculated group information then + // build group information for this item based on found one. + if (sibling->mGroupInfo) { + mParent = sibling->mGroupInfo->mParent; + mSetSize = sibling->mGroupInfo->mSetSize; + return; + } + + mSetSize++; + } + + if (mParent) + return; + + // Compute parent. + PRUint32 parentRole = nsAccUtils::Role(parent); + + // In the case of ARIA row in treegrid, return treegrid since ARIA + // groups aren't used to organize levels in ARIA treegrids. + if (aRole == nsIAccessibleRole::ROLE_ROW && + parentRole == nsIAccessibleRole::ROLE_TREE_TABLE) { + mParent = parent; + return; + } + + // In the case of ARIA tree, a tree can be arranged by using ARIA groups + // to organize levels. In this case the parent of the tree item will be + // a group and the previous treeitem of that should be the tree item + // parent. Or, if the parent is something other than a tree we will + // return that. + + if (parentRole != nsIAccessibleRole::ROLE_GROUPING) { + mParent = parent; + return; + } + + nsAccessible* parentPrevSibling = parent->GetSiblingAtOffset(-1); + PRUint32 parentPrevSiblingRole = nsAccUtils::Role(parentPrevSibling); + if (parentPrevSiblingRole == nsIAccessibleRole::ROLE_TEXT_LEAF) { + // XXX Sometimes an empty text accessible is in the hierarchy here, + // although the text does not appear to be rendered, GetRenderedText() + // says that it is so we need to skip past it to find the true + // previous sibling. + parentPrevSibling = parentPrevSibling->GetSiblingAtOffset(-1); + parentPrevSiblingRole = nsAccUtils::Role(parentPrevSibling); + } + + // Previous sibling of parent group is a tree item, this is the + // conceptual tree item parent. + if (parentPrevSiblingRole == nsIAccessibleRole::ROLE_OUTLINEITEM) + mParent = parentPrevSibling; +} diff --git a/accessible/src/base/AccGroupInfo.h b/accessible/src/base/AccGroupInfo.h new file mode 100644 index 000000000000..9a0dbce43e8d --- /dev/null +++ b/accessible/src/base/AccGroupInfo.h @@ -0,0 +1,96 @@ +/* ***** 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 (original author) + * + * Alternatively, the contents of this file may be used under the terms of + * either 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 ***** */ + +#ifndef AccGroupInfo_h_ +#define AccGroupInfo_h_ + +#include "nsAccessible.h" +#include "nsAccUtils.h" + +/** + * Calculate and store group information. + */ +class AccGroupInfo +{ +public: + AccGroupInfo(nsAccessible* aItem, PRUint32 aRole); + ~AccGroupInfo() { } + + PRInt32 PosInSet() const { return mPosInSet; } + PRUint32 SetSize() const { return mSetSize; } + nsAccessible* GetConceptualParent() const { return mParent; } + + /** + * Create group info. + */ + static AccGroupInfo* CreateGroupInfo(nsAccessible* aAccessible) + { + PRUint32 role = nsAccUtils::Role(aAccessible); + if (role != nsIAccessibleRole::ROLE_ROW && + role != nsIAccessibleRole::ROLE_GRID_CELL && + role != nsIAccessibleRole::ROLE_OUTLINEITEM && + role != nsIAccessibleRole::ROLE_OPTION && + role != nsIAccessibleRole::ROLE_LISTITEM && + role != nsIAccessibleRole::ROLE_MENUITEM && + role != nsIAccessibleRole::ROLE_CHECK_MENU_ITEM && + role != nsIAccessibleRole::ROLE_RADIO_MENU_ITEM && + role != nsIAccessibleRole::ROLE_RADIOBUTTON && + role != nsIAccessibleRole::ROLE_PAGETAB) + return nsnull; + + AccGroupInfo* info = new AccGroupInfo(aAccessible, BaseRole(role)); + return info; + } + +private: + AccGroupInfo(const AccGroupInfo&); + AccGroupInfo& operator =(const AccGroupInfo&); + + static PRUint32 BaseRole(PRUint32 aRole) + { + if (aRole == nsIAccessibleRole::ROLE_CHECK_MENU_ITEM || + aRole == nsIAccessibleRole::ROLE_RADIO_MENU_ITEM) + return nsIAccessibleRole::ROLE_MENUITEM; + return aRole; + } + + PRUint32 mPosInSet; + PRUint32 mSetSize; + nsAccessible* mParent; +}; + +#endif diff --git a/accessible/src/base/Makefile.in b/accessible/src/base/Makefile.in index a3dcba12db8b..494d8d0bbd7d 100644 --- a/accessible/src/base/Makefile.in +++ b/accessible/src/base/Makefile.in @@ -49,6 +49,7 @@ LIBXUL_LIBRARY = 1 CPPSRCS = \ AccCollector.cpp \ + AccGroupInfo.cpp \ AccIterator.cpp \ filters.cpp \ nsAccDocManager.cpp \ diff --git a/accessible/src/base/nsARIAGridAccessible.cpp b/accessible/src/base/nsARIAGridAccessible.cpp index 66f48f519fd9..e6be8113f3a0 100644 --- a/accessible/src/base/nsARIAGridAccessible.cpp +++ b/accessible/src/base/nsARIAGridAccessible.cpp @@ -221,6 +221,34 @@ nsARIAGridAccessible::GetRowIndexAt(PRInt32 aCellIndex, PRInt32 *aRowIndex) return NS_OK; } +NS_IMETHODIMP +nsARIAGridAccessible::GetRowAndColumnIndicesAt(PRInt32 aCellIndex, + PRInt32* aRowIndex, + PRInt32* aColumnIndex) +{ + NS_ENSURE_ARG_POINTER(aRowIndex); + *aRowIndex = -1; + NS_ENSURE_ARG_POINTER(aColumnIndex); + *aColumnIndex = -1; + + if (IsDefunct()) + return NS_ERROR_FAILURE; + + NS_ENSURE_ARG(aCellIndex >= 0); + + PRInt32 rowCount = 0; + GetRowCount(&rowCount); + + PRInt32 colsCount = 0; + GetColumnCount(&colsCount); + + NS_ENSURE_ARG(aCellIndex < rowCount * colsCount); + + *aColumnIndex = aCellIndex % colsCount; + *aRowIndex = aCellIndex / colsCount; + return NS_OK; +} + NS_IMETHODIMP nsARIAGridAccessible::GetColumnExtentAt(PRInt32 aRow, PRInt32 aColumn, PRInt32 *aExtentCount) diff --git a/accessible/src/base/nsAccUtils.cpp b/accessible/src/base/nsAccUtils.cpp index 4e6bff38a092..15f5fe51bed6 100644 --- a/accessible/src/base/nsAccUtils.cpp +++ b/accessible/src/base/nsAccUtils.cpp @@ -367,106 +367,6 @@ nsAccUtils::GetAncestorWithRole(nsAccessible *aDescendant, PRUint32 aRole) return nsnull; } -void -nsAccUtils::GetARIATreeItemParent(nsIAccessible *aStartTreeItem, - nsIContent *aStartContent, - nsIAccessible **aTreeItemParentResult) -{ - *aTreeItemParentResult = nsnull; - - nsCOMPtr parentAccessible; - aStartTreeItem->GetParent(getter_AddRefs(parentAccessible)); - if (!parentAccessible) - return; - - PRUint32 startTreeItemRole = nsAccUtils::Role(aStartTreeItem); - - // Calculate tree grid row parent only if the row inside of ARIA treegrid. - if (startTreeItemRole == nsIAccessibleRole::ROLE_ROW) { - PRUint32 role = nsAccUtils::Role(parentAccessible); - if (role != nsIAccessibleRole::ROLE_TREE_TABLE) - return; - } - - // This is a tree or treegrid that uses aria-level to define levels, so find - // the first previous sibling accessible where level is defined to be less - // than the current level. - nsAutoString levelStr; - if (nsAccUtils::HasDefinedARIAToken(aStartContent, nsAccessibilityAtoms::aria_level) && - aStartContent->GetAttr(kNameSpaceID_None, nsAccessibilityAtoms::aria_level, levelStr)) { - - PRInt32 success; - PRInt32 level = levelStr.ToInteger(&success); - if (level > 1 && NS_SUCCEEDED(success)) { - nsCOMPtr currentAccessible = aStartTreeItem, prevAccessible; - while (PR_TRUE) { - currentAccessible->GetPreviousSibling(getter_AddRefs(prevAccessible)); - currentAccessible.swap(prevAccessible); - nsCOMPtr accessNode = do_QueryInterface(currentAccessible); - if (!accessNode) { - break; // Reached top of tree, no higher level found - } - PRUint32 role = nsAccUtils::Role(currentAccessible); - if (role != startTreeItemRole) - continue; - - nsCOMPtr treeItemNode; - accessNode->GetDOMNode(getter_AddRefs(treeItemNode)); - nsCOMPtr treeItemContent = do_QueryInterface(treeItemNode); - if (treeItemContent && - nsAccUtils::HasDefinedARIAToken(treeItemContent, - nsAccessibilityAtoms::aria_level) && - treeItemContent->GetAttr(kNameSpaceID_None, - nsAccessibilityAtoms::aria_level, levelStr)) { - if (levelStr.ToInteger(&success) < level && NS_SUCCEEDED(success)) { - NS_ADDREF(*aTreeItemParentResult = currentAccessible); - return; - } - } - } - } - } - - // In the case of ARIA treegrid, return its parent since ARIA group isn't - // used to organize levels in ARIA treegrids. - - if (startTreeItemRole == nsIAccessibleRole::ROLE_ROW) { - NS_ADDREF(*aTreeItemParentResult = parentAccessible); - return; // The container for the tree grid rows - } - - // In the case of ARIA tree, a tree can be arranged by using role="group" to - // organize levels. In this case the parent of the tree item will be a group - // and the previous sibling of that should be the tree item parent. Or, if - // the parent is something other than a tree we will return that. - - PRUint32 role = nsAccUtils::Role(parentAccessible); - if (role != nsIAccessibleRole::ROLE_GROUPING) { - NS_ADDREF(*aTreeItemParentResult = parentAccessible); - return; // The container for the tree items - } - - nsCOMPtr prevAccessible; - parentAccessible->GetPreviousSibling(getter_AddRefs(prevAccessible)); - if (!prevAccessible) - return; - role = nsAccUtils::Role(prevAccessible); - if (role == nsIAccessibleRole::ROLE_TEXT_LEAF) { - // XXX Sometimes an empty text accessible is in the hierarchy here, - // although the text does not appear to be rendered, GetRenderedText() says that it is - // so we need to skip past it to find the true previous sibling - nsCOMPtr tempAccessible = prevAccessible; - tempAccessible->GetPreviousSibling(getter_AddRefs(prevAccessible)); - if (!prevAccessible) - return; - role = nsAccUtils::Role(prevAccessible); - } - if (role == nsIAccessibleRole::ROLE_OUTLINEITEM) { - // Previous sibling of parent group is a tree item -- this is the conceptual tree item parent - NS_ADDREF(*aTreeItemParentResult = prevAccessible); - } -} - nsAccessible * nsAccUtils::GetSelectableContainer(nsAccessible *aAccessible, PRUint32 aState) { diff --git a/accessible/src/base/nsAccUtils.h b/accessible/src/base/nsAccUtils.h index 1aaadd01edd3..85fd591c19bb 100644 --- a/accessible/src/base/nsAccUtils.h +++ b/accessible/src/base/nsAccUtils.h @@ -198,19 +198,6 @@ public: static nsAccessible * GetAncestorWithRole(nsAccessible *aDescendant, PRUint32 aRole); - /** - * For an ARIA tree item , get the accessible that represents its conceptual parent. - * This method will use the correct method for the given way the tree is constructed. - * The conceptual parent is what the user sees as the parent, not the DOM or accessible parent. - * @param aStartTreeItem The tree item to get the parent for - * @param aStartTreeItemContent The content node for the tree item - * @param The tree item's parent, or null if none - */ - static void - GetARIATreeItemParent(nsIAccessible *aStartTreeItem, - nsIContent *aStartTreeItemContent, - nsIAccessible **aTreeItemParent); - /** * Return single or multi selectable container for the given item. * diff --git a/accessible/src/base/nsAccessNode.cpp b/accessible/src/base/nsAccessNode.cpp index acf154e13e97..e78aec468271 100644 --- a/accessible/src/base/nsAccessNode.cpp +++ b/accessible/src/base/nsAccessNode.cpp @@ -131,7 +131,7 @@ void nsAccessNode::LastRelease() NS_ASSERTION(!mWeakShell, "A Shutdown() impl forgot to call its parent's Shutdown?"); } // ... then die. - NS_DELETEXPCOM(this); + delete this; } //////////////////////////////////////////////////////////////////////////////// diff --git a/accessible/src/base/nsAccessible.cpp b/accessible/src/base/nsAccessible.cpp index 08086a4ade5b..c710d89e13e1 100644 --- a/accessible/src/base/nsAccessible.cpp +++ b/accessible/src/base/nsAccessible.cpp @@ -41,6 +41,7 @@ #include "nsIXBLAccessible.h" +#include "AccGroupInfo.h" #include "AccIterator.h" #include "nsAccUtils.h" #include "nsARIAMap.h" @@ -2125,11 +2126,12 @@ nsAccessible::GetRelationByType(PRUint32 aRelationType, (mRoleMapEntry->role == nsIAccessibleRole::ROLE_OUTLINEITEM || mRoleMapEntry->role == nsIAccessibleRole::ROLE_ROW)) { - nsCOMPtr accTarget; - nsAccUtils::GetARIATreeItemParent(this, mContent, - getter_AddRefs(accTarget)); + AccGroupInfo* groupInfo = GetGroupInfo(); + if (!groupInfo) + return NS_OK_NO_RELATION_TARGET; - return nsRelUtils::AddTarget(aRelationType, aRelation, accTarget); + return nsRelUtils::AddTarget(aRelationType, aRelation, + groupInfo->GetConceptualParent()); } // If accessible is in its own Window, or is the root of a document, @@ -3091,98 +3093,24 @@ nsAccessible::GetActionRule(PRUint32 aStates) return eNoAction; } +AccGroupInfo* +nsAccessible::GetGroupInfo() +{ + if (mGroupInfo) + return mGroupInfo; + + mGroupInfo = AccGroupInfo::CreateGroupInfo(this); + return mGroupInfo; +} + void nsAccessible::GetPositionAndSizeInternal(PRInt32 *aPosInSet, PRInt32 *aSetSize) { - PRUint32 role = nsAccUtils::Role(this); - if (role != nsIAccessibleRole::ROLE_LISTITEM && - role != nsIAccessibleRole::ROLE_MENUITEM && - role != nsIAccessibleRole::ROLE_CHECK_MENU_ITEM && - role != nsIAccessibleRole::ROLE_RADIO_MENU_ITEM && - role != nsIAccessibleRole::ROLE_RADIOBUTTON && - role != nsIAccessibleRole::ROLE_PAGETAB && - role != nsIAccessibleRole::ROLE_OPTION && - role != nsIAccessibleRole::ROLE_OUTLINEITEM && - role != nsIAccessibleRole::ROLE_ROW && - role != nsIAccessibleRole::ROLE_GRID_CELL) - return; - - PRUint32 baseRole = role; - if (role == nsIAccessibleRole::ROLE_CHECK_MENU_ITEM || - role == nsIAccessibleRole::ROLE_RADIO_MENU_ITEM) - baseRole = nsIAccessibleRole::ROLE_MENUITEM; - - nsAccessible* parent = GetParent(); - NS_ENSURE_TRUE(parent,); - - PRInt32 level = nsAccUtils::GetARIAOrDefaultLevel(this); - - // Compute 'posinset'. - PRInt32 positionInGroup = 1; - for (PRInt32 idx = mIndexInParent - 1; idx >= 0; idx--) { - nsAccessible* sibling = parent->GetChildAt(idx); - - PRUint32 siblingRole = nsAccUtils::Role(sibling); - - // If the sibling is separator then the group is ended. - if (siblingRole == nsIAccessibleRole::ROLE_SEPARATOR) - break; - - PRUint32 siblingBaseRole = siblingRole; - if (siblingRole == nsIAccessibleRole::ROLE_CHECK_MENU_ITEM || - siblingRole == nsIAccessibleRole::ROLE_RADIO_MENU_ITEM) - siblingBaseRole = nsIAccessibleRole::ROLE_MENUITEM; - - // If sibling is visible and has the same base role - if (siblingBaseRole == baseRole && - !(nsAccUtils::State(sibling) & nsIAccessibleStates::STATE_INVISIBLE)) { - - // and check if it's hierarchical flatten structure, i.e. if the sibling - // level is lesser than this one then group is ended, if the sibling level - // is greater than this one then the group is splited by some child - // elements (group will be continued). - PRInt32 siblingLevel = nsAccUtils::GetARIAOrDefaultLevel(sibling); - if (siblingLevel < level) - break; - else if (level == siblingLevel) - ++ positionInGroup; - } + AccGroupInfo* groupInfo = GetGroupInfo(); + if (groupInfo) { + *aPosInSet = groupInfo->PosInSet(); + *aSetSize = groupInfo->SetSize(); } - - // Compute 'setsize'. - PRInt32 setSize = positionInGroup; - - PRInt32 siblingCount = parent->GetChildCount(); - for (PRInt32 idx = mIndexInParent + 1; idx < siblingCount; idx++) { - nsAccessible* sibling = parent->GetChildAt(idx); - NS_ENSURE_TRUE(sibling,); - - PRUint32 siblingRole = nsAccUtils::Role(sibling); - - // If the sibling is separator then the group is ended. - if (siblingRole == nsIAccessibleRole::ROLE_SEPARATOR) - break; - - PRUint32 siblingBaseRole = siblingRole; - if (siblingRole == nsIAccessibleRole::ROLE_CHECK_MENU_ITEM || - siblingRole == nsIAccessibleRole::ROLE_RADIO_MENU_ITEM) - siblingBaseRole = nsIAccessibleRole::ROLE_MENUITEM; - - // If sibling is visible and has the same base role - if (siblingBaseRole == baseRole && - !(nsAccUtils::State(sibling) & nsIAccessibleStates::STATE_INVISIBLE)) { - - // and check if it's hierarchical flatten structure. - PRInt32 siblingLevel = nsAccUtils::GetARIAOrDefaultLevel(sibling); - if (siblingLevel < level) - break; - else if (level == siblingLevel) - ++ setSize; - } - } - - *aPosInSet = positionInGroup; - *aSetSize = setSize; } PRInt32 diff --git a/accessible/src/base/nsAccessible.h b/accessible/src/base/nsAccessible.h index 6c55149a15e3..422b72a844f8 100644 --- a/accessible/src/base/nsAccessible.h +++ b/accessible/src/base/nsAccessible.h @@ -52,6 +52,7 @@ #include "nsTArray.h" #include "nsRefPtrHashtable.h" +class AccGroupInfo; class nsAccessible; class nsAccEvent; struct nsRoleMapEntry; @@ -324,7 +325,12 @@ protected: * Set accessible parent and index in parent. */ void BindToParent(nsAccessible* aParent, PRUint32 aIndexInParent); - void UnbindFromParent() { mParent = nsnull; mIndexInParent = -1; } + void UnbindFromParent() + { + mParent = nsnull; + mIndexInParent = -1; + mGroupInfo = nsnull; + } /** * Return sibling accessible at the given offset. @@ -424,6 +430,11 @@ protected: */ PRUint32 GetActionRule(PRUint32 aStates); + /** + * Return group info. + */ + AccGroupInfo* GetGroupInfo(); + /** * Fires platform accessible event. It's notification method only. It does * change nothing on Gecko side. Don't use it until you're sure what you do @@ -440,6 +451,9 @@ protected: PRBool mAreChildrenInitialized; PRInt32 mIndexInParent; + nsAutoPtr mGroupInfo; + friend class AccGroupInfo; + nsRoleMapEntry *mRoleMapEntry; // Non-null indicates author-supplied role; possibly state & value as well }; diff --git a/accessible/src/html/nsHTMLTableAccessible.cpp b/accessible/src/html/nsHTMLTableAccessible.cpp index 3aefd5db1d33..2ead768140e6 100644 --- a/accessible/src/html/nsHTMLTableAccessible.cpp +++ b/accessible/src/html/nsHTMLTableAccessible.cpp @@ -953,6 +953,26 @@ nsHTMLTableAccessible::GetRowIndexAt(PRInt32 aIndex, PRInt32 *aRow) return (*aRow == -1 || column == -1) ? NS_ERROR_INVALID_ARG : NS_OK; } +NS_IMETHODIMP +nsHTMLTableAccessible::GetRowAndColumnIndicesAt(PRInt32 aIndex, + PRInt32* aRowIdx, + PRInt32* aColumnIdx) +{ + NS_ENSURE_ARG_POINTER(aRowIdx); + *aRowIdx = -1; + NS_ENSURE_ARG_POINTER(aColumnIdx); + *aColumnIdx = -1; + + if (IsDefunct()) + return NS_ERROR_FAILURE; + + nsITableLayout* tableLayout = GetTableLayout(); + if (tableLayout) + tableLayout->GetRowAndColumnByIndex(aIndex, aRowIdx, aColumnIdx); + + return (*aRowIdx == -1 || *aColumnIdx == -1) ? NS_ERROR_INVALID_ARG : NS_OK; +} + NS_IMETHODIMP nsHTMLTableAccessible::GetColumnExtentAt(PRInt32 aRowIndex, PRInt32 aColumnIndex, diff --git a/accessible/src/msaa/CAccessibleTable.cpp b/accessible/src/msaa/CAccessibleTable.cpp index c98cb8db9139..7d0cd0fe992f 100644 --- a/accessible/src/msaa/CAccessibleTable.cpp +++ b/accessible/src/msaa/CAccessibleTable.cpp @@ -666,33 +666,28 @@ __try { if (!tableAcc) return E_FAIL; - PRInt32 row = -1; - nsresult rv = tableAcc->GetRowIndexAt(aIndex, &row); - if (NS_FAILED(rv)) - return GetHRESULT(rv); - - PRInt32 column = -1; - rv = tableAcc->GetColumnIndexAt(aIndex, &column); + PRInt32 rowIdx = -1, columnIdx = -1; + nsresult rv = tableAcc->GetRowAndColumnIndicesAt(aIndex, &rowIdx, &columnIdx); if (NS_FAILED(rv)) return GetHRESULT(rv); PRInt32 rowExtents = 0; - rv = tableAcc->GetRowExtentAt(row, column, &rowExtents); + rv = tableAcc->GetRowExtentAt(rowIdx, columnIdx, &rowExtents); if (NS_FAILED(rv)) return GetHRESULT(rv); PRInt32 columnExtents = 0; - rv = tableAcc->GetColumnExtentAt(row, column, &columnExtents); + rv = tableAcc->GetColumnExtentAt(rowIdx, columnIdx, &columnExtents); if (NS_FAILED(rv)) return GetHRESULT(rv); PRBool isSelected = PR_FALSE; - rv = tableAcc->IsCellSelected(row, column, &isSelected); + rv = tableAcc->IsCellSelected(rowIdx, columnIdx, &isSelected); if (NS_FAILED(rv)) return GetHRESULT(rv); - *aRow = row; - *aColumn = column; + *aRow = rowIdx; + *aColumn = columnIdx; *aRowExtents = rowExtents; *aColumnExtents = columnExtents; *aIsSelected = isSelected; diff --git a/accessible/src/xul/nsXULListboxAccessible.cpp b/accessible/src/xul/nsXULListboxAccessible.cpp index af87e5209577..2864c2afbbd2 100644 --- a/accessible/src/xul/nsXULListboxAccessible.cpp +++ b/accessible/src/xul/nsXULListboxAccessible.cpp @@ -412,6 +412,28 @@ nsXULListboxAccessible::GetRowIndexAt(PRInt32 aIndex, PRInt32 *aRow) return NS_OK; } +NS_IMETHODIMP +nsXULListboxAccessible::GetRowAndColumnIndicesAt(PRInt32 aCellIndex, + PRInt32* aRowIndex, + PRInt32* aColumnIndex) +{ + NS_ENSURE_ARG_POINTER(aRowIndex); + *aRowIndex = -1; + NS_ENSURE_ARG_POINTER(aColumnIndex); + *aColumnIndex = -1; + + if (IsDefunct()) + return NS_ERROR_FAILURE; + + PRInt32 columnCount = 0; + nsresult rv = GetColumnCount(&columnCount); + NS_ENSURE_SUCCESS(rv, rv); + + *aColumnIndex = aCellIndex % columnCount; + *aRowIndex = aCellIndex / columnCount; + return NS_OK; +} + NS_IMETHODIMP nsXULListboxAccessible::GetColumnExtentAt(PRInt32 aRow, PRInt32 aColumn, PRInt32 *aCellSpans) diff --git a/accessible/src/xul/nsXULTreeGridAccessible.cpp b/accessible/src/xul/nsXULTreeGridAccessible.cpp index 60ce6a9b63db..373de2b6379c 100644 --- a/accessible/src/xul/nsXULTreeGridAccessible.cpp +++ b/accessible/src/xul/nsXULTreeGridAccessible.cpp @@ -411,6 +411,28 @@ nsXULTreeGridAccessible::GetRowIndexAt(PRInt32 aCellIndex, PRInt32 *aRowIndex) return NS_OK; } +NS_IMETHODIMP +nsXULTreeGridAccessible::GetRowAndColumnIndicesAt(PRInt32 aCellIndex, + PRInt32* aRowIndex, + PRInt32* aColumnIndex) +{ + NS_ENSURE_ARG_POINTER(aRowIndex); + *aRowIndex = -1; + NS_ENSURE_ARG_POINTER(aColumnIndex); + *aColumnIndex = -1; + + if (IsDefunct()) + return NS_ERROR_FAILURE; + + PRInt32 columnCount = 0; + nsresult rv = GetColumnCount(&columnCount); + NS_ENSURE_SUCCESS(rv, rv); + + *aColumnIndex = aCellIndex % columnCount; + *aRowIndex = aCellIndex / columnCount; + return NS_OK; +} + NS_IMETHODIMP nsXULTreeGridAccessible::GetColumnExtentAt(PRInt32 aRowIndex, PRInt32 aColumnIndex, diff --git a/accessible/tests/mochitest/table.js b/accessible/tests/mochitest/table.js index 9c57ad8e29fb..f3dc85baa3a8 100644 --- a/accessible/tests/mochitest/table.js +++ b/accessible/tests/mochitest/table.js @@ -224,7 +224,7 @@ function testTableIndexes(aIdentifier, aIdxes) if (idx != - 1) { - // getRowAtIndex + // getRowIndexAt var origRowIdx = rowIdx; while (origRowIdx > 0 && aIdxes[rowIdx][colIdx] == aIdxes[origRowIdx - 1][colIdx]) @@ -237,9 +237,9 @@ function testTableIndexes(aIdentifier, aIdxes) } is(obtainedRowIdx, origRowIdx, - id + ": row for index " + idx +" is not correct"); + id + ": row for index " + idx + " is not correct (getRowIndexAt)"); - // getColumnAtIndex + // getColumnIndexAt var origColIdx = colIdx; while (origColIdx > 0 && aIdxes[rowIdx][colIdx] == aIdxes[rowIdx][origColIdx - 1]) @@ -252,7 +252,21 @@ function testTableIndexes(aIdentifier, aIdxes) } is(obtainedColIdx, origColIdx, - id + ": column for index " + idx +" is not correct"); + id + ": column for index " + idx + " is not correct (getColumnIndexAt)"); + + // getRowAndColumnIndicesAt + var obtainedRowIdxObj = { }, obtainedColIdxObj = { }; + try { + tableAcc.getRowAndColumnIndicesAt(idx, obtainedRowIdxObj, + obtainedColIdxObj); + } catch (e) { + ok(false, id + ": can't get row and column indices for cell index " + idx + "," + e); + } + + is(obtainedRowIdxObj.value, origRowIdx, + id + ": row for index " + idx + " is not correct (getRowAndColumnIndicesAt)"); + is(obtainedColIdxObj.value, origColIdx, + id + ": column for index " + idx + " is not correct (getRowAndColumnIndicesAt)"); if (cellAcc) { diff --git a/browser/app/profile/firefox.js b/browser/app/profile/firefox.js index 342cac5ef011..ce3bf272a6ef 100644 --- a/browser/app/profile/firefox.js +++ b/browser/app/profile/firefox.js @@ -320,8 +320,6 @@ pref("browser.tabs.loadInBackground", true); pref("browser.tabs.opentabfor.middleclick", true); pref("browser.tabs.loadDivertedInBackground", false); pref("browser.tabs.loadBookmarksInBackground", false); -pref("browser.tabs.tabMinWidth", 100); -pref("browser.tabs.tabMaxWidth", 250); pref("browser.tabs.tabClipWidth", 140); // Where to show tab close buttons: diff --git a/browser/base/content/browser.css b/browser/base/content/browser.css index 92df2611e2f9..41d30f02741d 100644 --- a/browser/base/content/browser.css +++ b/browser/base/content/browser.css @@ -22,12 +22,18 @@ tabbrowser { .tabbrowser-tab { -moz-binding: url("chrome://browser/content/tabbrowser.xml#tabbrowser-tab"); +} + +.tabbrowser-tab:not([pinned]) { -moz-box-flex: 100; + max-width: 250px; + min-width: 100px; + width: 0; } .tabbrowser-tab:not([fadein]) { - max-width: 1px !important; - min-width: 1px !important; + max-width: 1px; + min-width: 1px; } .tabbrowser-tab[fadein]:not([pinned]) { @@ -48,9 +54,6 @@ tabbrowser { .tabbrowser-tab[pinned] { position: fixed; - -moz-box-flex: 0; - min-width: 0 !important; - max-width: none !important; } .tabbrowser-tab[pinned] > .tab-text { @@ -81,6 +84,12 @@ toolbar[printpreview="true"] { -moz-box-ordinal-group: 10; } +%ifdef MENUBAR_CAN_AUTOHIDE +#main-window[inFullscreen] > #appmenu-button-container { + display: none; +} +%endif + toolbarpaletteitem[place="palette"] > toolbaritem > hbox[type="places"] { display: none; } diff --git a/browser/base/content/browser.js b/browser/base/content/browser.js index 0e9ff2a2a461..220e33079ae5 100644 --- a/browser/base/content/browser.js +++ b/browser/base/content/browser.js @@ -4727,12 +4727,12 @@ var TabsOnTop = { #ifdef MENUBAR_CAN_AUTOHIDE function updateAppButtonDisplay() { - var menubarHidden = + var displayAppButton = window.menubar.visible && document.getElementById("toolbar-menubar").getAttribute("autohide") == "true"; - document.getElementById("appmenu-button-container").hidden = !menubarHidden; + document.getElementById("appmenu-button-container").hidden = !displayAppButton; - if (menubarHidden) + if (displayAppButton) document.documentElement.setAttribute("chromemargin", "0,-1,-1,-1"); else document.documentElement.removeAttribute("chromemargin"); @@ -7772,6 +7772,10 @@ var TabContextMenu = { Cc["@mozilla.org/browser/sessionstore;1"]. getService(Ci.nsISessionStore). getClosedTabCount(window) == 0; + + // Only one of pin/unpin should be visible + document.getElementById("context_pinTab").hidden = this.contextTab.pinned; + document.getElementById("context_unpinTab").hidden = !this.contextTab.pinned; } }; diff --git a/browser/base/content/browser.xul b/browser/base/content/browser.xul index 232aff9d214c..814fdafddcd9 100644 --- a/browser/base/content/browser.xul +++ b/browser/base/content/browser.xul @@ -126,6 +126,12 @@ accesskey="&openTabInNewWindow.accesskey;" tbattr="tabbrowser-multiple" oncommand="gBrowser.replaceTabWithWindow(TabContextMenu.contextTab);"/> + +