Merge mozilla-central and tracemonkey.
1
.hgtags
@ -66,3 +66,4 @@ a95d426422816513477e5863add1b00ac7041dcb AURORA_BASE_20110412
|
||||
9eae975b3d6fb7748fe5a3c0113d449b1c7cc0b2 AURORA_BASE_20110524
|
||||
138f593553b66c9f815e8f57870c19d6347f7702 UPDATE_PACKAGING_R14
|
||||
462c726144bc1fb45b61e774f64ac5d61b4e047c UPDATE_PACKAGING_R14
|
||||
5eb553dd2ceae5f88d80f27afc5ef3935c5d43b0 AURORA_BASE_20110705
|
||||
|
@ -197,6 +197,9 @@ ifdef MOZ_CRASHREPORTER
|
||||
$(SHELL) $(topsrcdir)/toolkit/crashreporter/tools/upload_symbols.sh $(SYMBOL_INDEX_NAME) "$(DIST)/$(PKG_PATH)$(SYMBOL_FULL_ARCHIVE_BASENAME).zip"
|
||||
endif
|
||||
|
||||
codesighs:
|
||||
$(MAKE) -C $(MOZ_BUILD_APP)/installer codesighs
|
||||
|
||||
# defined in package-name.mk
|
||||
export MOZ_SOURCE_STAMP
|
||||
|
||||
|
@ -41,8 +41,6 @@
|
||||
#include "nsApplicationAccessibleWrap.h"
|
||||
#include "nsMaiInterfaceText.h"
|
||||
|
||||
PRBool nsAccessNodeWrap::gHaveNewTextSignals = PR_FALSE;
|
||||
|
||||
/* For documentation of the accessibility architecture,
|
||||
* see http://lxr.mozilla.org/seamonkey/source/accessible/accessible-docs.html
|
||||
*/
|
||||
@ -72,7 +70,6 @@ nsAccessNodeWrap::~nsAccessNodeWrap()
|
||||
void nsAccessNodeWrap::InitAccessibility()
|
||||
{
|
||||
nsAccessNode::InitXPAccessibility();
|
||||
gHaveNewTextSignals = g_signal_lookup("text-insert", ATK_TYPE_TEXT);
|
||||
}
|
||||
|
||||
void nsAccessNodeWrap::ShutdownAccessibility()
|
||||
|
@ -55,12 +55,6 @@ public: // construction, destruction
|
||||
static void InitAccessibility();
|
||||
static void ShutdownAccessibility();
|
||||
|
||||
/*
|
||||
* do we have text-remove and text-insert signals if not we need to use
|
||||
* text-changed see nsAccessibleWrap::FireAtkTextChangedEvent() and
|
||||
* bug 619002
|
||||
*/
|
||||
static PRBool gHaveNewTextSignals;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
@ -67,6 +67,9 @@
|
||||
#include "nsMaiInterfaceDocument.h"
|
||||
#include "nsMaiInterfaceImage.h"
|
||||
|
||||
nsAccessibleWrap::EAvailableAtkSignals nsAccessibleWrap::gAvailableAtkSignals =
|
||||
eUnknown;
|
||||
|
||||
//defined in nsApplicationAccessibleWrap.cpp
|
||||
extern "C" GType g_atk_hyperlink_impl_type;
|
||||
|
||||
@ -1081,7 +1084,7 @@ nsAccessibleWrap::FirePlatformEvent(AccEvent* aEvent)
|
||||
nsString newName;
|
||||
accessible->GetName(newName);
|
||||
NS_ConvertUTF16toUTF8 utf8Name(newName);
|
||||
if (!utf8Name.Equals(atkObj->name))
|
||||
if (!atkObj->name || !utf8Name.Equals(atkObj->name))
|
||||
atk_object_set_name(atkObj, utf8Name.get());
|
||||
|
||||
break;
|
||||
@ -1368,25 +1371,29 @@ nsAccessibleWrap::FireAtkTextChangedEvent(AccEvent* aEvent,
|
||||
PRBool isFromUserInput = aEvent->IsFromUserInput();
|
||||
char* signal_name = nsnull;
|
||||
|
||||
if (gHaveNewTextSignals) {
|
||||
nsAutoString text;
|
||||
event->GetModifiedText(text);
|
||||
signal_name = g_strconcat(isInserted ? "text-insert" : "text-remove",
|
||||
isFromUserInput ? "" : "::system", NULL);
|
||||
g_signal_emit_by_name(aObject, signal_name, start, length,
|
||||
NS_ConvertUTF16toUTF8(text).get());
|
||||
} else {
|
||||
// XXX remove this code and the gHaveNewTextSignals check when we can
|
||||
// stop supporting old atk since it doesn't really work anyway
|
||||
// see bug 619002
|
||||
signal_name = g_strconcat(isInserted ? "text_changed::insert" :
|
||||
"text_changed::delete",
|
||||
isFromUserInput ? "" : kNonUserInputEvent, NULL);
|
||||
g_signal_emit_by_name(aObject, signal_name, start, length);
|
||||
}
|
||||
if (gAvailableAtkSignals == eUnknown)
|
||||
gAvailableAtkSignals = g_signal_lookup("text-insert", ATK_TYPE_TEXT) ?
|
||||
eHaveNewAtkTextSignals : eNoNewAtkSignals;
|
||||
|
||||
g_free(signal_name);
|
||||
return NS_OK;
|
||||
if (gAvailableAtkSignals == eNoNewAtkSignals) {
|
||||
// XXX remove this code and the gHaveNewTextSignals check when we can
|
||||
// stop supporting old atk since it doesn't really work anyway
|
||||
// see bug 619002
|
||||
signal_name = g_strconcat(isInserted ? "text_changed::insert" :
|
||||
"text_changed::delete",
|
||||
isFromUserInput ? "" : kNonUserInputEvent, NULL);
|
||||
g_signal_emit_by_name(aObject, signal_name, start, length);
|
||||
} else {
|
||||
nsAutoString text;
|
||||
event->GetModifiedText(text);
|
||||
signal_name = g_strconcat(isInserted ? "text-insert" : "text-remove",
|
||||
isFromUserInput ? "" : "::system", NULL);
|
||||
g_signal_emit_by_name(aObject, signal_name, start, length,
|
||||
NS_ConvertUTF16toUTF8(text).get());
|
||||
}
|
||||
|
||||
g_free(signal_name);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
|
@ -127,6 +127,20 @@ protected:
|
||||
AtkObject *mAtkObject;
|
||||
|
||||
private:
|
||||
|
||||
/*
|
||||
* do we have text-remove and text-insert signals if not we need to use
|
||||
* text-changed see nsAccessibleWrap::FireAtkTextChangedEvent() and
|
||||
* bug 619002
|
||||
*/
|
||||
enum EAvailableAtkSignals {
|
||||
eUnknown,
|
||||
eHaveNewAtkTextSignals,
|
||||
eNoNewAtkSignals
|
||||
};
|
||||
|
||||
static EAvailableAtkSignals gAvailableAtkSignals;
|
||||
|
||||
PRUint16 CreateMaiInterfaces(void);
|
||||
};
|
||||
|
||||
|
@ -635,6 +635,9 @@ nsAccessibilityService::GetAccessibleFor(nsIDOMNode *aNode,
|
||||
nsIAccessible **aAccessible)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(aAccessible);
|
||||
*aAccessible = nsnull;
|
||||
if (!aNode)
|
||||
return NS_OK;
|
||||
|
||||
nsCOMPtr<nsINode> node(do_QueryInterface(aNode));
|
||||
NS_IF_ADDREF(*aAccessible = GetAccessible(node));
|
||||
@ -1006,12 +1009,13 @@ nsAccessibilityService::GetOrCreateAccessible(nsINode* aNode,
|
||||
}
|
||||
|
||||
nsRoleMapEntry *roleMapEntry = nsAccUtils::GetRoleMapEntry(aNode);
|
||||
if (roleMapEntry && !nsCRT::strcmp(roleMapEntry->roleString, "presentation") &&
|
||||
!content->IsFocusable()) { // For presentation only
|
||||
// Only create accessible for role of "presentation" if it is focusable --
|
||||
// in that case we need an accessible in case it gets focused, we
|
||||
// don't want focus ever to be 'lost'
|
||||
return nsnull;
|
||||
if (roleMapEntry && !nsCRT::strcmp(roleMapEntry->roleString, "presentation")) {
|
||||
// Ignore presentation role if element is focusable (focus event shouldn't
|
||||
// be ever lost and should be sensible).
|
||||
if (content->IsFocusable())
|
||||
roleMapEntry = nsnull;
|
||||
else
|
||||
return nsnull;
|
||||
}
|
||||
|
||||
if (weakFrame.IsAlive() && !newAcc && isHTML) { // HTML accessibles
|
||||
|
@ -2581,7 +2581,7 @@ nsAccessible::GetURI(PRInt32 aIndex, nsIURI **aURI)
|
||||
if (aIndex < 0 || aIndex >= static_cast<PRInt32>(AnchorCount()))
|
||||
return NS_ERROR_INVALID_ARG;
|
||||
|
||||
*aURI = AnchorURIAt(aIndex).get();
|
||||
nsRefPtr<nsIURI>(AnchorURIAt(aIndex)).forget(aURI);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
@ -1255,19 +1255,18 @@ nsHyperTextAccessible::GetAttributesInternal(nsIPersistentProperties *aAttribute
|
||||
}
|
||||
|
||||
// For the html landmark elements we expose them like we do aria landmarks to
|
||||
// make AT navigation schemes "just work".
|
||||
// make AT navigation schemes "just work". Note html:header is redundant as
|
||||
// a landmark since it usually contains headings. We're not yet sure how the
|
||||
// web will use html:footer but our best bet right now is as contentinfo.
|
||||
if (mContent->Tag() == nsAccessibilityAtoms::nav)
|
||||
nsAccUtils::SetAccAttr(aAttributes, nsAccessibilityAtoms::xmlroles,
|
||||
NS_LITERAL_STRING("navigation"));
|
||||
else if (mContent->Tag() == nsAccessibilityAtoms::header)
|
||||
nsAccUtils::SetAccAttr(aAttributes, nsAccessibilityAtoms::xmlroles,
|
||||
NS_LITERAL_STRING("banner"));
|
||||
else if (mContent->Tag() == nsAccessibilityAtoms::footer)
|
||||
nsAccUtils::SetAccAttr(aAttributes, nsAccessibilityAtoms::xmlroles,
|
||||
NS_LITERAL_STRING("contentinfo"));
|
||||
else if (mContent->Tag() == nsAccessibilityAtoms::aside)
|
||||
nsAccUtils::SetAccAttr(aAttributes, nsAccessibilityAtoms::xmlroles,
|
||||
NS_LITERAL_STRING("note"));
|
||||
NS_LITERAL_STRING("complementary"));
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
@ -484,18 +484,22 @@ STDMETHODIMP nsAccessibleWrap::get_accKeyboardShortcut(
|
||||
/* [retval][out] */ BSTR __RPC_FAR *pszKeyboardShortcut)
|
||||
{
|
||||
__try {
|
||||
if (!pszKeyboardShortcut)
|
||||
return E_INVALIDARG;
|
||||
|
||||
*pszKeyboardShortcut = NULL;
|
||||
nsAccessible *xpAccessible = GetXPAccessibleFor(varChild);
|
||||
if (xpAccessible) {
|
||||
nsAutoString shortcut;
|
||||
nsresult rv = xpAccessible->GetKeyboardShortcut(shortcut);
|
||||
if (NS_FAILED(rv))
|
||||
return E_FAIL;
|
||||
if (!xpAccessible || xpAccessible->IsDefunct())
|
||||
return E_FAIL;
|
||||
|
||||
*pszKeyboardShortcut = ::SysAllocStringLen(shortcut.get(),
|
||||
shortcut.Length());
|
||||
return *pszKeyboardShortcut ? S_OK : E_OUTOFMEMORY;
|
||||
}
|
||||
nsAutoString shortcut;
|
||||
nsresult rv = xpAccessible->GetKeyboardShortcut(shortcut);
|
||||
if (NS_FAILED(rv))
|
||||
return GetHRESULT(rv);
|
||||
|
||||
*pszKeyboardShortcut = ::SysAllocStringLen(shortcut.get(),
|
||||
shortcut.Length());
|
||||
return *pszKeyboardShortcut ? S_OK : E_OUTOFMEMORY;
|
||||
} __except(FilterA11yExceptions(::GetExceptionCode(), GetExceptionInformation())) { }
|
||||
return E_FAIL;
|
||||
}
|
||||
|
@ -673,14 +673,19 @@ nsXULTreeGridRowAccessible::GetName(nsAString& aName)
|
||||
if (IsDefunct())
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
nsCOMPtr<nsITreeColumns> columns;
|
||||
mTree->GetColumns(getter_AddRefs(columns));
|
||||
if (columns) {
|
||||
nsCOMPtr<nsITreeColumn> primaryColumn;
|
||||
columns->GetPrimaryColumn(getter_AddRefs(primaryColumn));
|
||||
if (primaryColumn)
|
||||
GetCellName(primaryColumn, aName);
|
||||
// XXX: the row name sholdn't be a concatenation of cell names (bug 664384).
|
||||
nsCOMPtr<nsITreeColumn> column = nsCoreUtils::GetFirstSensibleColumn(mTree);
|
||||
while (column) {
|
||||
if (!aName.IsEmpty())
|
||||
aName.AppendLiteral(" ");
|
||||
|
||||
nsAutoString cellName;
|
||||
GetCellName(column, cellName);
|
||||
aName.Append(cellName);
|
||||
|
||||
column = nsCoreUtils::GetNextSensibleColumn(column);
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
@ -103,7 +103,7 @@
|
||||
<button id="btn_namefromcontent" title="title">1</button>
|
||||
|
||||
<!-- button, no name from content, ARIA role overrides this rule -->
|
||||
<button id="btn_nonamefromcontent" role="presentation">1</button>
|
||||
<button id="btn_nonamefromcontent" role="img">1</button>
|
||||
|
||||
<!-- button, no content, name from @title -->
|
||||
<button id="btn_title" title="title"></button>
|
||||
|
@ -88,8 +88,7 @@
|
||||
title="title"><img alt="img title" /></a>
|
||||
|
||||
<!-- no name from content, ARIA role overrides this rule -->
|
||||
<a id="nonamefromcontent" href="mozilla.org"
|
||||
role="presentation">1</a>
|
||||
<a id="nonamefromcontent" href="mozilla.org" role="img">1</a>
|
||||
<br/>
|
||||
|
||||
<!-- no content, name from @title -->
|
||||
|
@ -86,7 +86,7 @@
|
||||
}
|
||||
}
|
||||
|
||||
function tableTester(aID)
|
||||
function tableTester(aID, aIsTable, aCol1ID, aCol2ID)
|
||||
{
|
||||
this.DOMNode = getNode(aID);
|
||||
|
||||
@ -98,7 +98,7 @@
|
||||
this.check = function tableTester_check(aEvent)
|
||||
{
|
||||
var tree = {
|
||||
role: ROLE_TREE_TABLE,
|
||||
role: aIsTable ? ROLE_TABLE : ROLE_TREE_TABLE,
|
||||
children: [
|
||||
{
|
||||
role: ROLE_LIST
|
||||
@ -109,15 +109,15 @@
|
||||
{
|
||||
role: ROLE_GRID_CELL,
|
||||
children: [],
|
||||
name: "row0_col1"
|
||||
name: "row0_" + aCol1ID
|
||||
},
|
||||
{
|
||||
role: ROLE_GRID_CELL,
|
||||
children: [],
|
||||
name: "row0_col2"
|
||||
name: "row0_" + aCol2ID
|
||||
}
|
||||
],
|
||||
name: "row0_col1"
|
||||
name: "row0_" + aCol1ID + " row0_" + aCol2ID
|
||||
},
|
||||
{
|
||||
role: ROLE_ROW,
|
||||
@ -125,15 +125,15 @@
|
||||
{
|
||||
role: ROLE_GRID_CELL,
|
||||
children: [],
|
||||
name: "row1_col1"
|
||||
name: "row1_" + aCol1ID
|
||||
},
|
||||
{
|
||||
role: ROLE_GRID_CELL,
|
||||
children: [],
|
||||
name: "row1_col2"
|
||||
name: "row1_" + aCol2ID
|
||||
}
|
||||
],
|
||||
name: "row1_col1"
|
||||
name: "row1_" + aCol1ID + " row1_" + aCol2ID
|
||||
}
|
||||
]
|
||||
};
|
||||
@ -152,7 +152,8 @@
|
||||
var gQueue = new eventQueue(EVENT_REORDER);
|
||||
|
||||
gQueue.push(new treeTester("tree"));
|
||||
gQueue.push(new tableTester("table"));
|
||||
gQueue.push(new tableTester("table", true, "t_col1", "t_col2"));
|
||||
gQueue.push(new tableTester("treetable", false, "tt_col1", "tt_col2"));
|
||||
|
||||
gQueue.invoke(); // Will call SimpleTest.finish()
|
||||
}
|
||||
@ -170,7 +171,12 @@
|
||||
title="Treegrid row accessible shouldn't inherit name from tree accessible">
|
||||
Mozilla Bug 546812
|
||||
</a>
|
||||
<p id="display"></p>
|
||||
<a target="_blank"
|
||||
href="https://bugzilla.mozilla.org/show_bug.cgi?id=664376"
|
||||
title="Table rows of XUL trees no longer containing cell content as accessible name">
|
||||
Mozilla Bug 664376
|
||||
</a>
|
||||
<p id="display"></p>
|
||||
<div id="content" style="display: none">
|
||||
</div>
|
||||
<pre id="test">
|
||||
@ -188,8 +194,16 @@
|
||||
|
||||
<tree id="table" flex="1">
|
||||
<treecols>
|
||||
<treecol id="col1" flex="1" label="column" primary="true"/>
|
||||
<treecol id="col2" flex="1" label="column 2"/>
|
||||
<treecol id="t_col1" flex="1" label="column"/>
|
||||
<treecol id="t_col2" flex="1" label="column 2"/>
|
||||
</treecols>
|
||||
<treechildren/>
|
||||
</tree>
|
||||
|
||||
<tree id="treetable" flex="1">
|
||||
<treecols>
|
||||
<treecol id="tt_col1" flex="1" label="column" primary="true"/>
|
||||
<treecol id="tt_col2" flex="1" label="column 2"/>
|
||||
</treecols>
|
||||
<treechildren/>
|
||||
</tree>
|
||||
|
@ -57,6 +57,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=529289
|
||||
is(accessibleTable.getCellAt(0,0).firstChild.name, "hi", "no cell");
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// test gEmptyRoleMap
|
||||
testRole("cell", ROLE_NOTHING);
|
||||
|
||||
@ -67,10 +68,12 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=529289
|
||||
for (a in abstract_roles)
|
||||
testRole(abstract_roles[a], ROLE_SECTION);
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// misc roles
|
||||
testRole("scrollbar", ROLE_SCROLLBAR);
|
||||
testRole("dir", ROLE_LIST);
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// test document role map update
|
||||
var testDoc = getAccessible(document, [nsIAccessibleDocument]);
|
||||
testRole(testDoc, ROLE_DOCUMENT);
|
||||
|
@ -31,9 +31,8 @@
|
||||
|
||||
// Some AT may look for this
|
||||
testAttrs("nav", {"xml-roles" : "navigation"}, true);
|
||||
testAttrs("header", {"xml-roles" : "banner"}, true);
|
||||
testAttrs("footer", {"xml-roles" : "contentinfo"}, true);
|
||||
testAttrs("aside", {"xml-roles" : "note"}, true);
|
||||
testAttrs("aside", {"xml-roles" : "complementary"}, true);
|
||||
testAttrs("main", {"xml-roles" : "main"}, true); // ARIA override
|
||||
|
||||
// And some AT may look for this
|
||||
@ -63,6 +62,11 @@
|
||||
title="Map <article> like we do aria role article">
|
||||
Mozilla Bug 613502
|
||||
</a>
|
||||
<a target="_blank"
|
||||
href="https://bugzilla.mozilla.org/show_bug.cgi?id=610650"
|
||||
title="Change implementation of HTML5 landmark elements to conform">
|
||||
Mozilla Bug 610650
|
||||
</a>
|
||||
<p id="display"></p>
|
||||
<div id="content" style="display: none"></div>
|
||||
<pre id="test">
|
||||
|
@ -50,6 +50,7 @@ _TEST_FILES =\
|
||||
$(warning test_applicationacc.xul temporarily disabled, see bug 561508) \
|
||||
test_aria_globals.html \
|
||||
test_aria_imgmap.html \
|
||||
test_aria_presentation.html \
|
||||
test_button.xul \
|
||||
test_combobox.xul \
|
||||
test_cssoverflow.html \
|
||||
|
104
accessible/tests/mochitest/tree/test_aria_presentation.html
Normal file
@ -0,0 +1,104 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>Test accessible tree when ARIA role presentation is used</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="chrome://mochikit/content/tests/SimpleTest/EventUtils.js"></script>
|
||||
|
||||
<script type="application/javascript"
|
||||
src="../common.js"></script>
|
||||
<script type="application/javascript"
|
||||
src="../role.js"></script>
|
||||
|
||||
<script type="application/javascript">
|
||||
function doTest()
|
||||
{
|
||||
// Presentation role don't allow accessible.
|
||||
var tree =
|
||||
{ SECTION: [ // container
|
||||
{ TEXT_LEAF: [ ] } // child text of presentation node
|
||||
] };
|
||||
testAccessibleTree("div_cnt", tree);
|
||||
|
||||
// Focusable element, presentation role is ignored.
|
||||
tree =
|
||||
{ SECTION: [ // container
|
||||
{ PUSHBUTTON: [ // button
|
||||
{ TEXT_LEAF: [ ] }
|
||||
] }
|
||||
] };
|
||||
testAccessibleTree("btn_cnt", tree);
|
||||
|
||||
// Presentation table, no table structure is exposed.
|
||||
tree =
|
||||
{ SECTION: [ // container
|
||||
{ TEXT_LEAF: [ ] } // cell text
|
||||
] };
|
||||
testAccessibleTree("tbl_cnt", tree);
|
||||
|
||||
// Focusable table, presentation role is ignored.
|
||||
tree =
|
||||
{ SECTION: [ // container
|
||||
{ TABLE: [ // table
|
||||
{ ROW: [ // tr
|
||||
{ CELL: [ //td
|
||||
{ TEXT_LEAF: [ ] }
|
||||
] }
|
||||
] }
|
||||
] }
|
||||
] };
|
||||
testAccessibleTree("tblfocusable_cnt", tree);
|
||||
|
||||
SimpleTest.finish();
|
||||
}
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
addA11yLoadEvent(doTest);
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<a target="_blank"
|
||||
href="https://bugzilla.mozilla.org/show_bug.cgi?id=548291"
|
||||
title="Accessible tree of ARIA image maps">
|
||||
Mozilla Bug 548291
|
||||
</a>
|
||||
<a target="_blank"
|
||||
href="https://bugzilla.mozilla.org/show_bug.cgi?id=666504"
|
||||
title="Ignore role presentation on focusable elements">
|
||||
Mozilla Bug 666504
|
||||
</a>
|
||||
<p id="display"></p>
|
||||
<div id="content" style="display: none"></div>
|
||||
<pre id="test">
|
||||
</pre>
|
||||
|
||||
<div id="div_cnt"><div role="presentation">text</div></div>
|
||||
|
||||
<div id="btn_cnt"><button role="presentation">btn</button></div>
|
||||
|
||||
<div id="tbl_cnt">
|
||||
<table role="presentation">
|
||||
<tr>
|
||||
<td>cell</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<div id="tblfocusable_cnt">
|
||||
<table role="presentation" tabindex="0">
|
||||
<tr>
|
||||
<td>cell</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
</body>
|
||||
</html>
|
@ -18,7 +18,11 @@ function nsTreeTreeView()
|
||||
];
|
||||
}
|
||||
|
||||
function nsTreeView() { }
|
||||
function nsTreeView()
|
||||
{
|
||||
this.mTree = null;
|
||||
this.mData = [];
|
||||
}
|
||||
|
||||
nsTreeView.prototype =
|
||||
{
|
||||
@ -205,8 +209,6 @@ nsTreeView.prototype =
|
||||
return rowIdx;
|
||||
},
|
||||
|
||||
mTree: null,
|
||||
mData: [],
|
||||
mCyclerStates: [
|
||||
createAtom("cyclerState1"),
|
||||
createAtom("cyclerState2"),
|
||||
|
@ -54,8 +54,12 @@ EXTENSIONS = \
|
||||
$(NULL)
|
||||
|
||||
define _INSTALL_EXTENSION
|
||||
cd $(srcdir)/$(dir) && \
|
||||
$(ZIP) -r9XD $(DISTROEXT)/$(dir).xpi *
|
||||
$(NSINSTALL) -D $(dir) && \
|
||||
$(PYTHON) $(MOZILLA_DIR)/config/Preprocessor.py $(DEFINES) $(ACDEFINES) $(srcdir)/$(dir)/install.rdf.in > $(dir)/install.rdf && \
|
||||
cd $(dir) && \
|
||||
$(ZIP) -r9XD $(DISTROEXT)/$(dir).xpi install.rdf && \
|
||||
cd $(srcdir)/$(dir) && \
|
||||
$(ZIP) -r9XD $(DISTROEXT)/$(dir).xpi * -x install.rdf.in
|
||||
|
||||
endef # do not remove the blank line!
|
||||
|
||||
|
@ -1,5 +1,7 @@
|
||||
<?xml version="1.0"?>
|
||||
|
||||
#filter substitution
|
||||
|
||||
<RDF xmlns="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:em="http://www.mozilla.org/2004/em-rdf#">
|
||||
<Description about="urn:mozilla:install-manifest">
|
||||
@ -13,7 +15,7 @@
|
||||
<Description>
|
||||
<em:id>{ec8030f7-c20a-464f-9b0e-13a3a9e97384}</em:id>
|
||||
<em:minVersion>3.5</em:minVersion>
|
||||
<em:maxVersion>6.0</em:maxVersion>
|
||||
<em:maxVersion>@FIREFOX_VERSION@</em:maxVersion>
|
||||
</Description>
|
||||
</em:targetApplication>
|
||||
|
@ -567,6 +567,7 @@ pref("plugins.hide_infobar_for_missing_plugin", false);
|
||||
pref("plugins.hide_infobar_for_outdated_plugin", false);
|
||||
|
||||
#ifdef XP_MACOSX
|
||||
pref("plugins.use_layers", false);
|
||||
pref("plugins.hide_infobar_for_carbon_failure_plugin", false);
|
||||
#endif
|
||||
|
||||
|
@ -108,13 +108,6 @@
|
||||
key="printKb"
|
||||
command="cmd_print"/>
|
||||
<menuseparator/>
|
||||
<menuitem id="menu_import"
|
||||
label="&import.label;"
|
||||
accesskey="&import.accesskey;"
|
||||
oncommand="BrowserImport();"/>
|
||||
#ifndef XP_MACOSX
|
||||
<menuseparator/>
|
||||
#endif
|
||||
<menuitem id="goOfflineMenuitem"
|
||||
label="&goOfflineCmd.label;"
|
||||
accesskey="&goOfflineCmd.accesskey;"
|
||||
|
@ -215,15 +215,17 @@ var ctrlTab = {
|
||||
if (this._tabList)
|
||||
return this._tabList;
|
||||
|
||||
let list = gBrowser.visibleTabs;
|
||||
|
||||
if (this._closing)
|
||||
this.detachTab(this._closing, list);
|
||||
// Using gBrowser.tabs instead of gBrowser.visibleTabs, as the latter
|
||||
// exlcudes closing tabs, breaking the following loop in case the the
|
||||
// selected tab is closing.
|
||||
let list = Array.filter(gBrowser.tabs, function (tab) !tab.hidden);
|
||||
|
||||
// Rotate the list until the selected tab is first
|
||||
while (!list[0].selected)
|
||||
list.push(list.shift());
|
||||
|
||||
list = list.filter(function (tab) !tab.closing);
|
||||
|
||||
if (this.recentlyUsedLimit != 0) {
|
||||
let recentlyUsedTabs = this._recentlyUsedTabs;
|
||||
if (this.recentlyUsedLimit > 0)
|
||||
@ -370,11 +372,10 @@ var ctrlTab = {
|
||||
else
|
||||
this._recentlyUsedTabs.push(aTab);
|
||||
},
|
||||
detachTab: function ctrlTab_detachTab(aTab, aTabs) {
|
||||
var tabs = aTabs || this._recentlyUsedTabs;
|
||||
var i = tabs.indexOf(aTab);
|
||||
detachTab: function ctrlTab_detachTab(aTab) {
|
||||
var i = this._recentlyUsedTabs.indexOf(aTab);
|
||||
if (i >= 0)
|
||||
tabs.splice(i, 1);
|
||||
this._recentlyUsedTabs.splice(i, 1);
|
||||
},
|
||||
|
||||
open: function ctrlTab_open() {
|
||||
@ -498,10 +499,8 @@ var ctrlTab = {
|
||||
return;
|
||||
}
|
||||
|
||||
this._closing = aTab;
|
||||
this._tabList = null;
|
||||
this.updatePreviews();
|
||||
this._closing = null;
|
||||
|
||||
if (this.selected.hidden)
|
||||
this.advanceFocus(false);
|
||||
|
@ -519,13 +519,6 @@ var gPopupBlockerObserver = {
|
||||
else
|
||||
blockedPopupAllowSite.removeAttribute("disabled");
|
||||
|
||||
var item = aEvent.target.lastChild;
|
||||
while (item && item.getAttribute("observes") != "blockedPopupsSeparator") {
|
||||
var next = item.previousSibling;
|
||||
item.parentNode.removeChild(item);
|
||||
item = next;
|
||||
}
|
||||
|
||||
var foundUsablePopupURI = false;
|
||||
var pageReport = gBrowser.pageReport;
|
||||
if (pageReport) {
|
||||
@ -588,6 +581,13 @@ var gPopupBlockerObserver = {
|
||||
onPopupHiding: function (aEvent) {
|
||||
if (aEvent.target.anchorNode.id == "page-report-button")
|
||||
aEvent.target.anchorNode.removeAttribute("open");
|
||||
|
||||
let item = aEvent.target.lastChild;
|
||||
while (item && item.getAttribute("observes") != "blockedPopupsSeparator") {
|
||||
let next = item.previousSibling;
|
||||
item.parentNode.removeChild(item);
|
||||
item = next;
|
||||
}
|
||||
},
|
||||
|
||||
showBlockedPopup: function (aEvent)
|
||||
@ -2617,24 +2617,6 @@ function PageProxyClickHandler(aEvent)
|
||||
middleMousePaste(aEvent);
|
||||
}
|
||||
|
||||
function BrowserImport()
|
||||
{
|
||||
#ifdef XP_MACOSX
|
||||
var wm = Components.classes["@mozilla.org/appshell/window-mediator;1"]
|
||||
.getService(Components.interfaces.nsIWindowMediator);
|
||||
var win = wm.getMostRecentWindow("Browser:MigrationWizard");
|
||||
if (win)
|
||||
win.focus();
|
||||
else {
|
||||
window.openDialog("chrome://browser/content/migration/migration.xul",
|
||||
"migration", "centerscreen,chrome,resizable=no");
|
||||
}
|
||||
#else
|
||||
window.openDialog("chrome://browser/content/migration/migration.xul",
|
||||
"migration", "modal,centerscreen,chrome,resizable=no");
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle load of some pages (about:*) so that we can make modifications
|
||||
* to the DOM for unprivileged pages.
|
||||
@ -2999,9 +2981,8 @@ function FillInHTMLTooltip(tipElement)
|
||||
XLinkTitleText = tipElement.getAttributeNS(XLinkNS, "title");
|
||||
}
|
||||
if (lookingForSVGTitle &&
|
||||
!(tipElement instanceof SVGElement &&
|
||||
tipElement.parentNode instanceof SVGElement &&
|
||||
!(tipElement.parentNode instanceof SVGForeignObjectElement))) {
|
||||
(!(tipElement instanceof SVGElement) ||
|
||||
tipElement.parentNode.nodeType == Node.DOCUMENT_NODE)) {
|
||||
lookingForSVGTitle = false;
|
||||
}
|
||||
if (lookingForSVGTitle) {
|
||||
@ -5481,7 +5462,7 @@ function hrefAndLinkNodeForClickEvent(event)
|
||||
// If there is no linkNode, try simple XLink.
|
||||
let href, baseURI;
|
||||
node = event.target;
|
||||
while (node) {
|
||||
while (node && !href) {
|
||||
if (node.nodeType == Node.ELEMENT_NODE) {
|
||||
href = node.getAttributeNS("http://www.w3.org/1999/xlink", "href");
|
||||
if (href)
|
||||
@ -8135,8 +8116,6 @@ let gPrivateBrowsingUI = {
|
||||
|
||||
this._setPBMenuTitle("stop");
|
||||
|
||||
document.getElementById("menu_import").setAttribute("disabled", "true");
|
||||
|
||||
// Disable the Clear Recent History... menu item when in PB mode
|
||||
// temporary fix until bug 463607 is fixed
|
||||
document.getElementById("Tools:Sanitize").setAttribute("disabled", "true");
|
||||
@ -8184,8 +8163,6 @@ let gPrivateBrowsingUI = {
|
||||
gURLBar.editor.transactionManager.clear();
|
||||
}
|
||||
|
||||
document.getElementById("menu_import").removeAttribute("disabled");
|
||||
|
||||
// Re-enable the Clear Recent History... menu item on exit of PB mode
|
||||
// temporary fix until bug 463607 is fixed
|
||||
document.getElementById("Tools:Sanitize").removeAttribute("disabled");
|
||||
|
@ -701,14 +701,10 @@ var InspectorUI = {
|
||||
if (parentNode.defaultView) {
|
||||
return parentNode.defaultView.frameElement;
|
||||
}
|
||||
if (this.embeddedBrowserParents) {
|
||||
let skipParent = this.embeddedBrowserParents[node];
|
||||
// HTML element? could be iframe?
|
||||
if (skipParent)
|
||||
return skipParent;
|
||||
} else // parent is document element, but no window at defaultView.
|
||||
return null;
|
||||
} else if (!parentNode.localName) {
|
||||
// parent is document element, but no window at defaultView.
|
||||
return null;
|
||||
}
|
||||
if (!parentNode.localName) {
|
||||
return null;
|
||||
}
|
||||
return parentNode;
|
||||
@ -722,25 +718,20 @@ var InspectorUI = {
|
||||
if (node.contentDocument) {
|
||||
// then the node is a frame
|
||||
if (index == 0) {
|
||||
if (!this.embeddedBrowserParents)
|
||||
this.embeddedBrowserParents = {};
|
||||
let skipChild = node.contentDocument.documentElement;
|
||||
this.embeddedBrowserParents[skipChild] = node;
|
||||
return skipChild; // the node's HTMLElement
|
||||
return node.contentDocument.documentElement; // the node's HTMLElement
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
if (node instanceof GetSVGDocument) {
|
||||
// then the node is a frame
|
||||
if (index == 0) {
|
||||
if (!this.embeddedBrowserParents)
|
||||
this.embeddedBrowserParents = {};
|
||||
let skipChild = node.getSVGDocument().documentElement;
|
||||
this.embeddedBrowserParents[skipChild] = node;
|
||||
return skipChild; // the node's SVGElement
|
||||
let svgDocument = node.getSVGDocument();
|
||||
if (svgDocument) {
|
||||
// then the node is a frame
|
||||
if (index == 0) {
|
||||
return svgDocument.documentElement; // the node's SVGElement
|
||||
}
|
||||
return null;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
let child = null;
|
||||
|
@ -125,8 +125,8 @@
|
||||
</hbox>
|
||||
</row>
|
||||
<row id="passwordRow" align="center">
|
||||
<label value="&signIn.password.label;"
|
||||
accesskey="&signIn.password.accesskey;"
|
||||
<label value="&setup.choosePassword.label;"
|
||||
accesskey="&setup.choosePassword.accesskey;"
|
||||
control="weavePassword"/>
|
||||
<textbox id="weavePassword"
|
||||
type="password"
|
||||
|
@ -96,7 +96,7 @@
|
||||
<getter><![CDATA[
|
||||
return Array.filter(this.tabs, function(tab) {
|
||||
return !tab.hidden && !tab.closing;
|
||||
}, this);
|
||||
});
|
||||
]]></getter>
|
||||
</property>
|
||||
<field name="mURIFixup" readonly="true">
|
||||
@ -947,7 +947,15 @@
|
||||
this._tabAttrModified(this.mCurrentTab);
|
||||
|
||||
// Adjust focus
|
||||
oldBrowser._urlbarFocused = (gURLBar && gURLBar.focused);
|
||||
do {
|
||||
// When focus is in the tab bar, retain it there.
|
||||
if (document.activeElement == oldTab) {
|
||||
// We need to explicitly focus the new tab, because
|
||||
// tabbox.xml does this only in some cases.
|
||||
this.mCurrentTab.focus();
|
||||
break;
|
||||
}
|
||||
|
||||
// If there's a tabmodal prompt showing, focus it.
|
||||
if (newBrowser.hasAttribute("tabmodalPromptShowing")) {
|
||||
@ -961,7 +969,6 @@
|
||||
// Focus the location bar if it was previously focused for that tab.
|
||||
// In full screen mode, only bother making the location bar visible
|
||||
// if the tab is a blank one.
|
||||
oldBrowser._urlbarFocused = (gURLBar && gURLBar.focused);
|
||||
if (newBrowser._urlbarFocused && gURLBar) {
|
||||
|
||||
// Explicitly close the popup if the URL bar retains focus
|
||||
@ -2005,13 +2012,18 @@
|
||||
in the current window, in which case this will do nothing. -->
|
||||
<method name="replaceTabWithWindow">
|
||||
<parameter name="aTab"/>
|
||||
<parameter name="aOptions"/>
|
||||
<body>
|
||||
<![CDATA[
|
||||
if (this.tabs.length == 1)
|
||||
return null;
|
||||
|
||||
var options = "chrome,dialog=no,all";
|
||||
for (var name in aOptions)
|
||||
options += "," + name + "=" + aOptions[name];
|
||||
|
||||
// tell a new window to take the "dropped" tab
|
||||
return window.openDialog(getBrowserURL(), "_blank", "dialog=no,all", aTab);
|
||||
return window.openDialog(getBrowserURL(), "_blank", options, aTab);
|
||||
]]>
|
||||
</body>
|
||||
</method>
|
||||
@ -3298,6 +3310,17 @@
|
||||
|
||||
let canvas = tabPreviews.capture(tab, false);
|
||||
dt.setDragImage(canvas, 0, 0);
|
||||
|
||||
// _dragOffsetX/Y give the coordinates that the mouse should be
|
||||
// positioned relative to the corner of the new window created upon
|
||||
// dragend such that the mouse appears to have the same position
|
||||
// relative to the corner of the dragged tab.
|
||||
function clientX(ele) ele.getBoundingClientRect().left;
|
||||
let tabOffsetX = clientX(tab) -
|
||||
clientX(this.children[0].pinned ? this.children[0] : this);
|
||||
tab._dragOffsetX = event.screenX - window.screenX - tabOffsetX;
|
||||
tab._dragOffsetY = event.screenY - window.screenY;
|
||||
|
||||
event.stopPropagation();
|
||||
]]></handler>
|
||||
|
||||
@ -3477,6 +3500,11 @@
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// these offsets are only used in dragend, but we need to free them here
|
||||
// as well
|
||||
delete draggedTab._dragOffsetX;
|
||||
delete draggedTab._dragOffsetY;
|
||||
]]></handler>
|
||||
|
||||
<handler event="dragend"><![CDATA[
|
||||
@ -3491,6 +3519,7 @@
|
||||
|
||||
// Disable detach within the browser toolbox
|
||||
var eX = event.screenX;
|
||||
var eY = event.screenY;
|
||||
var wX = window.screenX;
|
||||
// check if the drop point is horizontally within the window
|
||||
if (eX > wX && eX < (wX + window.outerWidth)) {
|
||||
@ -3498,13 +3527,45 @@
|
||||
// also avoid detaching if the the tab was dropped too close to
|
||||
// the tabbar (half a tab)
|
||||
let endScreenY = bo.screenY + 1.5 * bo.height;
|
||||
let eY = event.screenY;
|
||||
if (eY < endScreenY && eY > window.screenY)
|
||||
return;
|
||||
}
|
||||
|
||||
var draggedTab = dt.mozGetDataAt(TAB_DROP_TYPE, 0);
|
||||
this.tabbrowser.replaceTabWithWindow(draggedTab);
|
||||
// screen.availLeft et. al. only check the screen that this window is on,
|
||||
// but we want to look at the screen the tab is being dropped onto.
|
||||
var sX = {}, sY = {}, sWidth = {}, sHeight = {};
|
||||
Cc["@mozilla.org/gfx/screenmanager;1"]
|
||||
.getService(Ci.nsIScreenManager)
|
||||
.screenForRect(eX, eY, 1, 1)
|
||||
.GetAvailRect(sX, sY, sWidth, sHeight);
|
||||
// ensure new window entirely within screen
|
||||
var winWidth = Math.min(window.outerWidth, sWidth.value);
|
||||
var winHeight = Math.min(window.outerHeight, sHeight.value);
|
||||
var left = Math.min(Math.max(eX - draggedTab._dragOffsetX, sX.value),
|
||||
sX.value + sWidth.value - winWidth);
|
||||
var top = Math.min(Math.max(eY - draggedTab._dragOffsetY, sY.value),
|
||||
sY.value + sHeight.value - winHeight);
|
||||
|
||||
delete draggedTab._dragOffsetX;
|
||||
delete draggedTab._dragOffsetY;
|
||||
|
||||
if (this.tabbrowser.tabs.length == 1) {
|
||||
// resize _before_ move to ensure the window fits the new screen. if
|
||||
// the window is too large for its screen, the window manager may do
|
||||
// automatic repositioning.
|
||||
window.resizeTo(winWidth, winHeight);
|
||||
window.moveTo(left, top);
|
||||
window.focus();
|
||||
} else {
|
||||
this.tabbrowser.replaceTabWithWindow(draggedTab, { screenX: left,
|
||||
screenY: top,
|
||||
#ifndef XP_WIN
|
||||
outerWidth: winWidth,
|
||||
outerHeight: winHeight
|
||||
#endif
|
||||
});
|
||||
}
|
||||
event.stopPropagation();
|
||||
]]></handler>
|
||||
|
||||
@ -3670,7 +3731,7 @@
|
||||
if (this.mOverCloseButton) {
|
||||
event.stopPropagation();
|
||||
}
|
||||
else {
|
||||
else if (this.selected) {
|
||||
this.style.MozUserFocus = 'ignore';
|
||||
this.clientTop; // just using this to flush style updates
|
||||
}
|
||||
|
@ -67,8 +67,7 @@ var resize = {
|
||||
// Parameters:
|
||||
// item - The <Item> being dragged
|
||||
// event - The DOM event that kicks off the drag
|
||||
// isFauxDrag - (boolean) true if a faux drag, which is used when simply snapping.
|
||||
function Drag(item, event, isFauxDrag) {
|
||||
function Drag(item, event) {
|
||||
Utils.assert(item && (item.isAnItem || item.isAFauxItem),
|
||||
'must be an item, or at least a faux item');
|
||||
|
||||
@ -282,13 +281,16 @@ Drag.prototype = {
|
||||
Trenches.hideGuides();
|
||||
this.item.isDragging = false;
|
||||
|
||||
if (this.parent && this.parent != this.item.parent)
|
||||
this.parent.closeIfEmpty();
|
||||
|
||||
if (this.parent && this.parent.expanded)
|
||||
this.parent.arrange();
|
||||
|
||||
if (this.item.parent)
|
||||
this.item.parent.arrange();
|
||||
|
||||
if (!this.item.parent) {
|
||||
if (this.item.isAGroupItem) {
|
||||
this.item.setZ(drag.zIndex);
|
||||
drag.zIndex++;
|
||||
|
||||
|
@ -103,7 +103,7 @@ function GroupItem(listOfEls, options) {
|
||||
|
||||
if (!rectToBe) {
|
||||
rectToBe = GroupItems.getBoundingBox(listOfEls);
|
||||
rectToBe.inset(-30, -30);
|
||||
rectToBe.inset(-42, -42);
|
||||
}
|
||||
|
||||
var $container = options.container;
|
||||
@ -249,7 +249,11 @@ function GroupItem(listOfEls, options) {
|
||||
this._init($container[0]);
|
||||
|
||||
// ___ Children
|
||||
Array.prototype.forEach.call(listOfEls, function(el) {
|
||||
// We explicitly set dontArrange=true to prevent the groupItem from
|
||||
// re-arranging its children after a tabItem has been added. This saves us a
|
||||
// group.arrange() call per child and therefore some tab.setBounds() calls.
|
||||
options.dontArrange = true;
|
||||
listOfEls.forEach(function (el) {
|
||||
self.add(el, options);
|
||||
});
|
||||
|
||||
@ -271,6 +275,9 @@ function GroupItem(listOfEls, options) {
|
||||
if ($container)
|
||||
this.setBounds(rectToBe, immediately);
|
||||
|
||||
if (!options.immediately && listOfEls.length > 0)
|
||||
$container.hide().fadeIn();
|
||||
|
||||
this._inited = true;
|
||||
this.save();
|
||||
|
||||
@ -645,7 +652,7 @@ GroupItem.prototype = Utils.extend(new Item(), new Subscribable(), {
|
||||
// Options:
|
||||
// immediately - (bool) if true, no animation will be used
|
||||
close: function GroupItem_close(options) {
|
||||
this.removeAll();
|
||||
this.removeAll({dontClose: true});
|
||||
GroupItems.unregister(this);
|
||||
|
||||
// remove unfreeze event handlers, if item size is frozen
|
||||
@ -716,7 +723,22 @@ GroupItem.prototype = Utils.extend(new Item(), new Subscribable(), {
|
||||
let closeCenter = this.getBounds().center();
|
||||
// Find closest tab to make active
|
||||
let closestTabItem = UI.getClosestTab(closeCenter);
|
||||
UI.setActive(closestTabItem);
|
||||
if (closestTabItem)
|
||||
UI.setActive(closestTabItem);
|
||||
},
|
||||
|
||||
// ----------
|
||||
// Function: closeIfEmpty
|
||||
// Closes the group if it's empty, is closable, and autoclose is enabled
|
||||
// (see pauseAutoclose()). Returns true if the close occurred and false
|
||||
// otherwise.
|
||||
closeIfEmpty: function GroupItem_closeIfEmpty() {
|
||||
if (this.isEmpty() && !UI._closedLastVisibleTab &&
|
||||
!GroupItems.getUnclosableGroupItemId() && !GroupItems._autoclosePaused) {
|
||||
this.close();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
},
|
||||
|
||||
// ----------
|
||||
@ -758,13 +780,12 @@ GroupItem.prototype = Utils.extend(new Item(), new Subscribable(), {
|
||||
|
||||
this._cancelFadeAwayUndoButtonTimer();
|
||||
|
||||
// When the last non-empty groupItem is closed and there are no orphan or
|
||||
// When the last non-empty groupItem is closed and there are no
|
||||
// pinned tabs then create a new group with a blank tab.
|
||||
let remainingGroups = GroupItems.groupItems.filter(function (groupItem) {
|
||||
return (groupItem != self && groupItem.getChildren().length);
|
||||
});
|
||||
if (!gBrowser._numPinnedTabs && !GroupItems.getOrphanedTabs().length &&
|
||||
!remainingGroups.length) {
|
||||
if (!gBrowser._numPinnedTabs && !remainingGroups.length) {
|
||||
let emptyGroups = GroupItems.groupItems.filter(function (groupItem) {
|
||||
return (groupItem != self && !groupItem.getChildren().length);
|
||||
});
|
||||
@ -829,16 +850,17 @@ GroupItem.prototype = Utils.extend(new Item(), new Subscribable(), {
|
||||
let self = this;
|
||||
|
||||
if (this.$undoContainer) {
|
||||
// if there is one or more orphan tabs or there is more than one group
|
||||
// and other groupS are not empty, fade away the undo button.
|
||||
let shouldFadeAway = GroupItems.getOrphanedTabs().length > 0;
|
||||
|
||||
if (!shouldFadeAway && GroupItems.groupItems.length > 1) {
|
||||
// if there is more than one group and other groups are not empty,
|
||||
// fade away the undo button.
|
||||
let shouldFadeAway = false;
|
||||
|
||||
if (GroupItems.groupItems.length > 1) {
|
||||
shouldFadeAway =
|
||||
GroupItems.groupItems.some(function(groupItem) {
|
||||
return (groupItem != self && groupItem.getChildren().length > 0);
|
||||
});
|
||||
}
|
||||
|
||||
if (shouldFadeAway) {
|
||||
self.$undoContainer.animate({
|
||||
color: "transparent",
|
||||
@ -983,7 +1005,6 @@ GroupItem.prototype = Utils.extend(new Item(), new Subscribable(), {
|
||||
this._children.splice(index, 0, item);
|
||||
|
||||
item.setZ(this.getZ() + 1);
|
||||
$el.addClass("tabInGroupItem");
|
||||
|
||||
if (!wasAlreadyInThisGroupItem) {
|
||||
item.droppable(false);
|
||||
@ -992,7 +1013,8 @@ GroupItem.prototype = Utils.extend(new Item(), new Subscribable(), {
|
||||
item.addSubscriber(this, "close", function() {
|
||||
let count = self._children.length;
|
||||
let dontArrange = self.expanded || !self.shouldStack(count);
|
||||
self.remove(item, {dontArrange: dontArrange});
|
||||
let dontClose = !item.closedManually && gBrowser._numPinnedTabs > 0;
|
||||
self.remove(item, {dontArrange: dontArrange, dontClose: dontClose});
|
||||
|
||||
if (dontArrange)
|
||||
self._freezeItemSize(count);
|
||||
@ -1039,6 +1061,7 @@ GroupItem.prototype = Utils.extend(new Item(), new Subscribable(), {
|
||||
//
|
||||
// Possible options:
|
||||
// dontArrange - don't rearrange the remaining items
|
||||
// dontClose - don't close the group even if it normally would
|
||||
// immediately - don't animate
|
||||
remove: function GroupItem_remove(a, options) {
|
||||
try {
|
||||
@ -1068,7 +1091,6 @@ GroupItem.prototype = Utils.extend(new Item(), new Subscribable(), {
|
||||
}
|
||||
|
||||
item.setParent(null);
|
||||
item.removeClass("tabInGroupItem");
|
||||
item.removeClass("stacked");
|
||||
item.isStacked = false;
|
||||
item.setHidden(false);
|
||||
@ -1087,7 +1109,15 @@ GroupItem.prototype = Utils.extend(new Item(), new Subscribable(), {
|
||||
if (typeof item.setResizable == 'function')
|
||||
item.setResizable(true, options.immediately);
|
||||
|
||||
if (!options.dontArrange) {
|
||||
// if a blank tab is selected while restoring a tab the blank tab gets
|
||||
// removed. we need to keep the group alive for the restored tab.
|
||||
if (item.isRemovedAfterRestore)
|
||||
options.dontClose = true;
|
||||
|
||||
let closed = options.dontClose ? false : this.closeIfEmpty();
|
||||
if (closed)
|
||||
this._makeClosestTabActive();
|
||||
else if (!options.dontArrange) {
|
||||
this.arrange({animate: !options.immediately});
|
||||
this._unfreezeItemSize({dontArrange: true});
|
||||
}
|
||||
@ -1702,7 +1732,7 @@ GroupItem.prototype = Utils.extend(new Item(), new Subscribable(), {
|
||||
self.arrange();
|
||||
var groupItem = drag.info.item.parent;
|
||||
if (groupItem)
|
||||
groupItem.remove(drag.info.$el);
|
||||
groupItem.remove(drag.info.$el, {dontClose: true});
|
||||
iQ(this.container).removeClass("acceptsDrop");
|
||||
}
|
||||
|
||||
@ -1830,12 +1860,12 @@ let GroupItems = {
|
||||
nextID: 1,
|
||||
_inited: false,
|
||||
_activeGroupItem: null,
|
||||
_activeOrphanTab: null,
|
||||
_cleanupFunctions: [],
|
||||
_arrangePaused: false,
|
||||
_arrangesPending: [],
|
||||
_removingHiddenGroups: false,
|
||||
_delayedModUpdates: [],
|
||||
_autoclosePaused: false,
|
||||
minGroupHeight: 110,
|
||||
minGroupWidth: 125,
|
||||
|
||||
@ -2238,84 +2268,56 @@ let GroupItems = {
|
||||
let activeGroupItem = this.getActiveGroupItem();
|
||||
|
||||
// 1. Active group
|
||||
// 2. Active orphan
|
||||
// 3. First visible non-app tab (that's not the tab in question), whether it's an
|
||||
// orphan or not (make a new group if it's an orphan, add it to the group if it's
|
||||
// not)
|
||||
// 4. First group
|
||||
// 5. First orphan that's not the tab in question
|
||||
// 6. At this point there should be no groups or tabs (except for app tabs and the
|
||||
// 2. First visible non-app tab (that's not the tab in question)
|
||||
// 3. First group
|
||||
// 4. At this point there should be no groups or tabs (except for app tabs and the
|
||||
// tab in question): make a new group
|
||||
|
||||
if (activeGroupItem) {
|
||||
if (activeGroupItem && !activeGroupItem.hidden) {
|
||||
activeGroupItem.add(tabItem, options);
|
||||
return;
|
||||
}
|
||||
|
||||
let orphanTabItem = UI.getActiveOrphanTab();
|
||||
if (!orphanTabItem) {
|
||||
let targetGroupItem;
|
||||
// find first visible non-app tab in the tabbar.
|
||||
gBrowser.visibleTabs.some(function(tab) {
|
||||
if (!tab.pinned && tab != tabItem.tab) {
|
||||
if (tab._tabViewTabItem) {
|
||||
if (!tab._tabViewTabItem.parent) {
|
||||
// the first visible tab is an orphan tab, set the orphan tab, and
|
||||
// create a new group for orphan tab and new tabItem
|
||||
orphanTabItem = tab._tabViewTabItem;
|
||||
} else if (!tab._tabViewTabItem.parent.hidden) {
|
||||
// the first visible tab belongs to a group, add the new tabItem to
|
||||
// that group
|
||||
targetGroupItem = tab._tabViewTabItem.parent;
|
||||
}
|
||||
let targetGroupItem;
|
||||
// find first visible non-app tab in the tabbar.
|
||||
gBrowser.visibleTabs.some(function(tab) {
|
||||
if (!tab.pinned && tab != tabItem.tab) {
|
||||
if (tab._tabViewTabItem) {
|
||||
if (!tab._tabViewTabItem.parent && !tab._tabViewTabItem.parent.hidden) {
|
||||
// the first visible tab belongs to a group, add the new tabItem to
|
||||
// that group
|
||||
targetGroupItem = tab._tabViewTabItem.parent;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
});
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
});
|
||||
|
||||
let visibleGroupItems;
|
||||
if (!orphanTabItem) {
|
||||
if (targetGroupItem) {
|
||||
// add the new tabItem to the first group item
|
||||
targetGroupItem.add(tabItem);
|
||||
UI.setActive(targetGroupItem);
|
||||
return;
|
||||
} else {
|
||||
// find the first visible group item
|
||||
visibleGroupItems = this.groupItems.filter(function(groupItem) {
|
||||
return (!groupItem.hidden);
|
||||
});
|
||||
if (visibleGroupItems.length > 0) {
|
||||
visibleGroupItems[0].add(tabItem);
|
||||
UI.setActive(visibleGroupItems[0]);
|
||||
return;
|
||||
}
|
||||
}
|
||||
let orphanedTabs = this.getOrphanedTabs();
|
||||
// set the orphan tab, and create a new group for orphan tab and
|
||||
// new tabItem
|
||||
if (orphanedTabs.length > 0)
|
||||
orphanTabItem = orphanedTabs[0];
|
||||
let visibleGroupItems;
|
||||
if (targetGroupItem) {
|
||||
// add the new tabItem to the first group item
|
||||
targetGroupItem.add(tabItem);
|
||||
UI.setActive(targetGroupItem);
|
||||
return;
|
||||
} else {
|
||||
// find the first visible group item
|
||||
visibleGroupItems = this.groupItems.filter(function(groupItem) {
|
||||
return (!groupItem.hidden);
|
||||
});
|
||||
if (visibleGroupItems.length > 0) {
|
||||
visibleGroupItems[0].add(tabItem);
|
||||
UI.setActive(visibleGroupItems[0]);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// create new group for orphan tab and new tabItem
|
||||
let tabItems;
|
||||
let newGroupItemBounds;
|
||||
// the orphan tab would be the same as tabItem when all tabs are app tabs
|
||||
// and a new tab is created.
|
||||
if (orphanTabItem && orphanTabItem.tab != tabItem.tab) {
|
||||
newGroupItemBounds = orphanTabItem.getBounds();
|
||||
tabItems = [orphanTabItem, tabItem];
|
||||
} else {
|
||||
tabItem.setPosition(60, 60, true);
|
||||
newGroupItemBounds = tabItem.getBounds();
|
||||
tabItems = [tabItem];
|
||||
}
|
||||
// create new group for the new tabItem
|
||||
tabItem.setPosition(60, 60, true);
|
||||
let newGroupItemBounds = tabItem.getBounds();
|
||||
|
||||
newGroupItemBounds.inset(-40,-40);
|
||||
let newGroupItem = new GroupItem(tabItems, { bounds: newGroupItemBounds });
|
||||
let newGroupItem = new GroupItem([tabItem], { bounds: newGroupItemBounds });
|
||||
newGroupItem.snap();
|
||||
UI.setActive(newGroupItem);
|
||||
},
|
||||
@ -2334,16 +2336,14 @@ let GroupItems = {
|
||||
// setting the groupItem which will receive new tabs.
|
||||
//
|
||||
// Paramaters:
|
||||
// groupItem - the active <GroupItem> or <null> if no groupItem is active
|
||||
// (which means we have an orphaned tab selected)
|
||||
// groupItem - the active <GroupItem>
|
||||
setActiveGroupItem: function GroupItems_setActiveGroupItem(groupItem) {
|
||||
Utils.assert(groupItem, "groupItem must be given");
|
||||
|
||||
if (this._activeGroupItem)
|
||||
iQ(this._activeGroupItem.container).removeClass('activeGroupItem');
|
||||
|
||||
if (groupItem !== null) {
|
||||
if (groupItem)
|
||||
iQ(groupItem.container).addClass('activeGroupItem');
|
||||
}
|
||||
iQ(groupItem.container).addClass('activeGroupItem');
|
||||
|
||||
this._activeGroupItem = groupItem;
|
||||
this._save();
|
||||
@ -2351,23 +2351,14 @@ let GroupItems = {
|
||||
|
||||
// ----------
|
||||
// Function: _updateTabBar
|
||||
// Hides and shows tabs in the tab bar based on the active groupItem or
|
||||
// currently active orphan tabItem
|
||||
// Hides and shows tabs in the tab bar based on the active groupItem
|
||||
_updateTabBar: function GroupItems__updateTabBar() {
|
||||
if (!window.UI)
|
||||
return; // called too soon
|
||||
|
||||
let activeOrphanTab;
|
||||
if (!this._activeGroupItem) {
|
||||
activeOrphanTab = UI.getActiveOrphanTab();
|
||||
if (!activeOrphanTab) {
|
||||
Utils.assert(false, "There must be something to show in the tab bar!");
|
||||
return;
|
||||
}
|
||||
}
|
||||
Utils.assert(this._activeGroupItem, "There must be something to show in the tab bar!");
|
||||
|
||||
let tabItems = this._activeGroupItem == null ?
|
||||
[activeOrphanTab] : this._activeGroupItem._children;
|
||||
let tabItems = this._activeGroupItem._children;
|
||||
gBrowser.showOnlyTheseTabs(tabItems.map(function(item) item.tab));
|
||||
},
|
||||
|
||||
@ -2381,17 +2372,6 @@ let GroupItems = {
|
||||
this._updateTabBar();
|
||||
},
|
||||
|
||||
// ----------
|
||||
// Function: getOrphanedTabs
|
||||
// Returns an array of all tabs that aren't in a groupItem.
|
||||
getOrphanedTabs: function GroupItems_getOrphanedTabs() {
|
||||
var tabs = TabItems.getItems();
|
||||
tabs = tabs.filter(function(tab) {
|
||||
return tab.parent == null;
|
||||
});
|
||||
return tabs;
|
||||
},
|
||||
|
||||
// ----------
|
||||
// Function: getNextGroupItemTab
|
||||
// Paramaters:
|
||||
@ -2400,7 +2380,6 @@ let GroupItems = {
|
||||
getNextGroupItemTab: function GroupItems_getNextGroupItemTab(reverse) {
|
||||
var groupItems = Utils.copy(GroupItems.groupItems);
|
||||
var activeGroupItem = GroupItems.getActiveGroupItem();
|
||||
var activeOrphanTab = UI.getActiveOrphanTab();
|
||||
var tabItem = null;
|
||||
|
||||
if (reverse)
|
||||
@ -2453,11 +2432,6 @@ let GroupItems = {
|
||||
}
|
||||
return false;
|
||||
});
|
||||
if (!tabItem) {
|
||||
var orphanedTabs = GroupItems.getOrphanedTabs();
|
||||
if (orphanedTabs.length > 0)
|
||||
tabItem = orphanedTabs[0];
|
||||
}
|
||||
if (!tabItem) {
|
||||
var secondGroupItems = groupItems.slice(0, currentIndex);
|
||||
secondGroupItems.some(function(groupItem) {
|
||||
@ -2532,7 +2506,7 @@ let GroupItems = {
|
||||
box.width = 250;
|
||||
box.height = 200;
|
||||
|
||||
new GroupItem([ tab._tabViewTabItem ], { bounds: box });
|
||||
new GroupItem([ tab._tabViewTabItem ], { bounds: box, immediately: true });
|
||||
}
|
||||
|
||||
if (shouldUpdateTabBar)
|
||||
@ -2607,5 +2581,21 @@ let GroupItems = {
|
||||
return new Point(
|
||||
Math.max(size.x, GroupItems.minGroupWidth),
|
||||
Math.max(size.y, GroupItems.minGroupHeight));
|
||||
},
|
||||
|
||||
// ----------
|
||||
// Function: pauseAutoclose()
|
||||
// Temporarily disable the behavior that closes groups when they become
|
||||
// empty. This is used when entering private browsing, to avoid trashing the
|
||||
// user's groups while private browsing is shuffling things around.
|
||||
pauseAutoclose: function GroupItems_pauseAutoclose() {
|
||||
this._autoclosePaused = true;
|
||||
},
|
||||
|
||||
// ----------
|
||||
// Function: unpauseAutoclose()
|
||||
// Re-enables the auto-close behavior.
|
||||
resumeAutoclose: function GroupItems_resumeAutoclose() {
|
||||
this._autoclosePaused = false;
|
||||
}
|
||||
};
|
||||
|
@ -164,9 +164,13 @@ Item.prototype = {
|
||||
},
|
||||
stop: function() {
|
||||
drag.info.stop();
|
||||
drag.info = null;
|
||||
if (!this.isAGroupItem && !this.parent)
|
||||
|
||||
if (!this.isAGroupItem && !this.parent) {
|
||||
new GroupItem([drag.info.$el], {focusTitle: true});
|
||||
gTabView.firstUseExperienced = true;
|
||||
}
|
||||
|
||||
drag.info = null;
|
||||
},
|
||||
// The minimum the mouse must move after mouseDown in order to move an
|
||||
// item
|
||||
@ -179,7 +183,7 @@ Item.prototype = {
|
||||
out: function() {
|
||||
let groupItem = drag.info.item.parent;
|
||||
if (groupItem)
|
||||
groupItem.remove(drag.info.$el);
|
||||
groupItem.remove(drag.info.$el, {dontClose: true});
|
||||
iQ(this.container).removeClass("acceptsDrop");
|
||||
},
|
||||
drop: function(event) {
|
||||
@ -541,9 +545,7 @@ Item.prototype = {
|
||||
var defaultRadius = Trenches.defaultRadius;
|
||||
Trenches.defaultRadius = 2 * defaultRadius; // bump up from 10 to 20!
|
||||
|
||||
var event = {startPosition:{}}; // faux event
|
||||
var FauxDragInfo = new Drag(this, event, true);
|
||||
// true == isFauxDrag
|
||||
var FauxDragInfo = new Drag(this, {});
|
||||
FauxDragInfo.snap('none', false);
|
||||
FauxDragInfo.stop(immediately);
|
||||
|
||||
|
@ -112,69 +112,9 @@ function TabItem(tab, options) {
|
||||
|
||||
// ___ drag/drop
|
||||
// override dropOptions with custom tabitem methods
|
||||
// This is mostly to support the phantom groupItems.
|
||||
this.dropOptions.drop = function(e) {
|
||||
var $target = this.$container;
|
||||
this.isDropTarget = false;
|
||||
|
||||
var phantom = $target.data("phantomGroupItem");
|
||||
|
||||
var groupItem = drag.info.item.parent;
|
||||
if (groupItem) {
|
||||
groupItem.add(drag.info.$el);
|
||||
} else {
|
||||
phantom.removeClass("phantom acceptsDrop");
|
||||
let opts = {container:phantom, bounds:phantom.bounds(), focusTitle: true};
|
||||
new GroupItem([$target, drag.info.$el], opts);
|
||||
}
|
||||
};
|
||||
|
||||
this.dropOptions.over = function(e) {
|
||||
var $target = this.$container;
|
||||
this.isDropTarget = true;
|
||||
|
||||
$target.removeClass("acceptsDrop");
|
||||
|
||||
var phantomMargin = 40;
|
||||
|
||||
var groupItemBounds = this.getBounds();
|
||||
groupItemBounds.inset(-phantomMargin, -phantomMargin);
|
||||
|
||||
iQ(".phantom").remove();
|
||||
var phantom = iQ("<div>")
|
||||
.addClass("groupItem phantom acceptsDrop")
|
||||
.css({
|
||||
position: "absolute",
|
||||
zIndex: -99
|
||||
})
|
||||
.css(groupItemBounds)
|
||||
.hide()
|
||||
.appendTo("body");
|
||||
|
||||
var defaultRadius = Trenches.defaultRadius;
|
||||
// Extend the margin so that it covers the case where the target tab item
|
||||
// is right next to a trench.
|
||||
Trenches.defaultRadius = phantomMargin + 1;
|
||||
var updatedBounds = drag.info.snapBounds(groupItemBounds,'none');
|
||||
Trenches.defaultRadius = defaultRadius;
|
||||
|
||||
// Utils.log('updatedBounds:',updatedBounds);
|
||||
if (updatedBounds)
|
||||
phantom.css(updatedBounds);
|
||||
|
||||
phantom.fadeIn();
|
||||
|
||||
$target.data("phantomGroupItem", phantom);
|
||||
};
|
||||
|
||||
this.dropOptions.out = function(e) {
|
||||
this.isDropTarget = false;
|
||||
var phantom = this.$container.data("phantomGroupItem");
|
||||
if (phantom) {
|
||||
phantom.fadeOut(function() {
|
||||
iQ(this).remove();
|
||||
});
|
||||
}
|
||||
let groupItem = drag.info.item.parent;
|
||||
groupItem.add(drag.info.$el);
|
||||
};
|
||||
|
||||
this.draggable();
|
||||
@ -201,7 +141,6 @@ function TabItem(tab, options) {
|
||||
}
|
||||
});
|
||||
|
||||
this.setResizable(true, options.immediately);
|
||||
this.droppable(true);
|
||||
|
||||
TabItems.register(this);
|
||||
@ -289,8 +228,6 @@ TabItem.prototype = Utils.extend(new Item(), new Subscribable(), {
|
||||
}
|
||||
|
||||
return {
|
||||
bounds: this.getBounds(),
|
||||
userSize: (Utils.isPoint(this.userSize) ? new Point(this.userSize) : null),
|
||||
url: this.tab.linkedBrowser.currentURI.spec,
|
||||
groupID: (this.parent ? this.parent.id : 0),
|
||||
imageData: imageData,
|
||||
@ -348,47 +285,33 @@ TabItem.prototype = Utils.extend(new Item(), new Subscribable(), {
|
||||
if (self.parent)
|
||||
self.parent.remove(self, {immediately: true});
|
||||
|
||||
self.setBounds(tabData.bounds, true);
|
||||
|
||||
if (Utils.isPoint(tabData.userSize))
|
||||
self.userSize = new Point(tabData.userSize);
|
||||
let groupItem;
|
||||
|
||||
if (tabData.groupID) {
|
||||
var groupItem = GroupItems.groupItem(tabData.groupID);
|
||||
if (groupItem) {
|
||||
groupItem.add(self, {immediately: true});
|
||||
|
||||
// if it matches the selected tab or no active tab and the browser
|
||||
// tab is hidden, the active group item would be set.
|
||||
if (self.tab == gBrowser.selectedTab ||
|
||||
(!GroupItems.getActiveGroupItem() && !self.tab.hidden))
|
||||
UI.setActive(self.parent);
|
||||
}
|
||||
groupItem = GroupItems.groupItem(tabData.groupID);
|
||||
} else {
|
||||
// When duplicating a non-blank orphaned tab, create a group including both of them.
|
||||
// This prevents overlaid tabs in Tab View (only one tab appears to be there).
|
||||
// In addition, as only one active orphaned tab is shown when Tab View is hidden
|
||||
// and there are two tabs shown after the duplication, it also prevents
|
||||
// the inactive tab to suddenly disappear when toggling Tab View twice.
|
||||
//
|
||||
// Fixes:
|
||||
// Bug 645653 - Middle-click on reload button to duplicate orphan tabs does not create a group
|
||||
// Bug 643119 - Ctrl+Drag to duplicate does not work for orphaned tabs
|
||||
// ... (and any other way of duplicating a non-blank orphaned tab).
|
||||
if (GroupItems.getActiveGroupItem() == null)
|
||||
GroupItems.newTab(self, {immediately: true});
|
||||
groupItem = new GroupItem([], {immediately: true, bounds: tabData.bounds});
|
||||
}
|
||||
|
||||
if (groupItem) {
|
||||
groupItem.add(self, {immediately: true});
|
||||
|
||||
// if it matches the selected tab or no active tab and the browser
|
||||
// tab is hidden, the active group item would be set.
|
||||
if (self.tab == gBrowser.selectedTab ||
|
||||
(!GroupItems.getActiveGroupItem() && !self.tab.hidden))
|
||||
UI.setActive(self.parent);
|
||||
}
|
||||
} else {
|
||||
// create tab by double click is handled in UI_init().
|
||||
if (!UI.creatingNewOrphanTab)
|
||||
GroupItems.newTab(self, {immediately: true});
|
||||
// create tab group by double click is handled in UI_init().
|
||||
GroupItems.newTab(self, {immediately: true});
|
||||
}
|
||||
|
||||
self._reconnected = true;
|
||||
self.save();
|
||||
self._sendToSubscribers("reconnected");
|
||||
},
|
||||
|
||||
|
||||
// ----------
|
||||
// Function: setHidden
|
||||
// Hide/unhide this item
|
||||
@ -594,24 +517,6 @@ TabItem.prototype = Utils.extend(new Item(), new Subscribable(), {
|
||||
this.$container.removeClass(className);
|
||||
},
|
||||
|
||||
// ----------
|
||||
// Function: setResizable
|
||||
// If value is true, makes this item resizable, otherwise non-resizable.
|
||||
// Shows/hides a visible resize handle as appropriate.
|
||||
setResizable: function TabItem_setResizable(value, immediately) {
|
||||
var $resizer = iQ('.expander', this.container);
|
||||
|
||||
if (value) {
|
||||
this.resizeOptions.minWidth = TabItems.minTabWidth;
|
||||
this.resizeOptions.minHeight = TabItems.minTabHeight;
|
||||
immediately ? $resizer.show() : $resizer.fadeIn();
|
||||
this.resizable(true);
|
||||
} else {
|
||||
immediately ? $resizer.hide() : $resizer.fadeOut();
|
||||
this.resizable(false);
|
||||
}
|
||||
},
|
||||
|
||||
// ----------
|
||||
// Function: makeActive
|
||||
// Updates this item to visually indicate that it's active.
|
||||
@ -912,8 +817,7 @@ let TabItems = {
|
||||
"<img class='cached-thumb' style='display:none'/><canvas moz-opaque/></div>" +
|
||||
"<div class='favicon'><img/></div>" +
|
||||
"<span class='tab-title'> </span>" +
|
||||
"<div class='close'></div>" +
|
||||
"<div class='expander'></div>";
|
||||
"<div class='close'></div>";
|
||||
this._fragment = document.createDocumentFragment();
|
||||
this._fragment.appendChild(div);
|
||||
|
||||
@ -1073,9 +977,6 @@ let TabItems = {
|
||||
Utils.assertThrow(tab._tabViewTabItem, "should already be linked");
|
||||
// note that it's ok to unlink an app tab; see .handleTabUnpin
|
||||
|
||||
if (tab._tabViewTabItem == UI.getActiveOrphanTab())
|
||||
UI.setActive(null, { onlyRemoveActiveTab: true });
|
||||
|
||||
this.unregister(tab._tabViewTabItem);
|
||||
tab._tabViewTabItem._sendToSubscribers("close");
|
||||
tab._tabViewTabItem.$container.remove();
|
||||
@ -1265,15 +1166,9 @@ let TabItems = {
|
||||
// Function: storageSanity
|
||||
// Checks the specified data (as returned by TabItem.getStorageData or loaded from storage)
|
||||
// and returns true if it looks valid.
|
||||
// TODO: check everything
|
||||
// TODO: this is a stub, please implement
|
||||
storageSanity: function TabItems_storageSanity(data) {
|
||||
var sane = true;
|
||||
if (!Utils.isRect(data.bounds)) {
|
||||
Utils.log('TabItems.storageSanity: bad bounds', data.bounds);
|
||||
sane = false;
|
||||
}
|
||||
|
||||
return sane;
|
||||
return true;
|
||||
},
|
||||
|
||||
// ----------
|
||||
|
@ -72,6 +72,9 @@ body {
|
||||
|
||||
.tab-title {
|
||||
position: absolute;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.stacked .tab-title {
|
||||
|
@ -574,9 +574,7 @@ var Trenches = {
|
||||
this.trenches.forEach(function(t) {
|
||||
if (t.el === element)
|
||||
return;
|
||||
if (t.parentItem && (t.parentItem.isAFauxItem ||
|
||||
t.parentItem.isDragging ||
|
||||
t.parentItem.isDropTarget))
|
||||
if (t.parentItem && (t.parentItem.isAFauxItem || t.parentItem.isDragging))
|
||||
return;
|
||||
t.active = true;
|
||||
t.calculateActiveRange();
|
||||
@ -634,7 +632,7 @@ var Trenches = {
|
||||
|
||||
for (var i in this.trenches) {
|
||||
var t = this.trenches[i];
|
||||
if (!t.active || t.parentItem.isDropTarget)
|
||||
if (!t.active)
|
||||
continue;
|
||||
// newRect will be a new rect, or false
|
||||
var newRect = t.rectOverlaps(rect,stationaryCorner,assumeConstantSize,keepProportional);
|
||||
|
@ -139,10 +139,6 @@ let UI = {
|
||||
// Used to prevent keypress being handled after quitting search mode.
|
||||
ignoreKeypressForSearch: false,
|
||||
|
||||
// Variable: creatingNewOrphanTab
|
||||
// Used to keep track of whether we are creating a new oprhan tab or not.
|
||||
creatingNewOrphanTab: false,
|
||||
|
||||
// Variable: _lastOpenedTab
|
||||
// Used to keep track of the last opened tab.
|
||||
_lastOpenedTab: null,
|
||||
@ -197,29 +193,22 @@ let UI = {
|
||||
self._lastClick = 0;
|
||||
self._lastClickPositions = null;
|
||||
} else {
|
||||
// Create an orphan tab on double click
|
||||
// Create a group with one tab on double click
|
||||
if (Date.now() - self._lastClick <= self.DBLCLICK_INTERVAL &&
|
||||
(self._lastClickPositions.x - self.DBLCLICK_OFFSET) <= e.clientX &&
|
||||
(self._lastClickPositions.x + self.DBLCLICK_OFFSET) >= e.clientX &&
|
||||
(self._lastClickPositions.y - self.DBLCLICK_OFFSET) <= e.clientY &&
|
||||
(self._lastClickPositions.y + self.DBLCLICK_OFFSET) >= e.clientY) {
|
||||
self.setActive(null);
|
||||
self.creatingNewOrphanTab = true;
|
||||
|
||||
let box =
|
||||
new Rect(e.clientX - Math.floor(TabItems.tabWidth/2),
|
||||
e.clientY - Math.floor(TabItems.tabHeight/2),
|
||||
TabItems.tabWidth, TabItems.tabHeight);
|
||||
let newTab =
|
||||
gBrowser.loadOneTab("about:blank", { inBackground: false });
|
||||
box.inset(-30, -30);
|
||||
|
||||
newTab._tabViewTabItem.setBounds(box, true);
|
||||
newTab._tabViewTabItem.pushAway(true);
|
||||
self.setActive(newTab._tabViewTabItem);
|
||||
|
||||
self.creatingNewOrphanTab = false;
|
||||
// the bounds of tab item is set and we can zoom in now.
|
||||
newTab._tabViewTabItem.zoomIn(true);
|
||||
let opts = {immediately: true, bounds: box};
|
||||
let groupItem = new GroupItem([], opts);
|
||||
groupItem.newTab();
|
||||
|
||||
self._lastClick = 0;
|
||||
self._lastClickPositions = null;
|
||||
@ -422,13 +411,6 @@ let UI = {
|
||||
}
|
||||
},
|
||||
|
||||
// ----------
|
||||
// Function: getActiveOrphanTab
|
||||
// Returns the currently active orphan tab as a <TabItem>
|
||||
getActiveOrphanTab: function UI_getActiveOrphanTab() {
|
||||
return (this._activeTab && !this._activeTab.parent) ? this._activeTab : null;
|
||||
},
|
||||
|
||||
// ----------
|
||||
// Function: setActive
|
||||
// Sets the active tab item or group item
|
||||
@ -436,33 +418,18 @@ let UI = {
|
||||
//
|
||||
// options
|
||||
// dontSetActiveTabInGroup bool for not setting active tab in group
|
||||
// onlyRemoveActiveGroup bool for removing active group
|
||||
// onlyRemoveActiveTab bool for removing active tab
|
||||
setActive: function UI_setActive(item, options) {
|
||||
if (item) {
|
||||
if (item.isATabItem) {
|
||||
if (item.parent)
|
||||
GroupItems.setActiveGroupItem(item.parent);
|
||||
else
|
||||
GroupItems.setActiveGroupItem(null);
|
||||
this._setActiveTab(item);
|
||||
} else {
|
||||
GroupItems.setActiveGroupItem(item);
|
||||
if (!options || !options.dontSetActiveTabInGroup) {
|
||||
let activeTab = item.getActiveTab()
|
||||
if (activeTab)
|
||||
this._setActiveTab(activeTab);
|
||||
}
|
||||
}
|
||||
Utils.assert(item, "item must be given");
|
||||
|
||||
if (item.isATabItem) {
|
||||
GroupItems.setActiveGroupItem(item.parent);
|
||||
this._setActiveTab(item);
|
||||
} else {
|
||||
if (options) {
|
||||
if (options.onlyRemoveActiveGroup)
|
||||
GroupItems.setActiveGroupItem(null);
|
||||
else if (options.onlyRemoveActiveTab)
|
||||
this._setActiveTab(null);
|
||||
} else {
|
||||
GroupItems.setActiveGroupItem(null);
|
||||
this._setActiveTab(null);
|
||||
GroupItems.setActiveGroupItem(item);
|
||||
if (!options || !options.dontSetActiveTabInGroup) {
|
||||
let activeTab = item.getActiveTab()
|
||||
if (activeTab)
|
||||
this._setActiveTab(activeTab);
|
||||
}
|
||||
}
|
||||
},
|
||||
@ -523,10 +490,6 @@ let UI = {
|
||||
|
||||
Storage.saveVisibilityData(gWindow, "true");
|
||||
|
||||
let activeGroupItem = null;
|
||||
if (!UI.getActiveOrphanTab())
|
||||
activeGroupItem = GroupItems.getActiveGroupItem();
|
||||
|
||||
if (zoomOut && currentTab && currentTab._tabViewTabItem) {
|
||||
item = currentTab._tabViewTabItem;
|
||||
// If there was a previous currentTab we want to animate
|
||||
@ -549,7 +512,6 @@ let UI = {
|
||||
TabItems.resumePainting();
|
||||
});
|
||||
} else {
|
||||
self.setActive(null, { onlyRemoveActiveTab: true });
|
||||
dispatchEvent(event);
|
||||
|
||||
// Flush pending updates
|
||||
@ -631,8 +593,10 @@ let UI = {
|
||||
// Pauses the storage activity that conflicts with sessionstore updates and
|
||||
// private browsing mode switches. Calls can be nested.
|
||||
storageBusy: function UI_storageBusy() {
|
||||
if (!this._storageBusyCount)
|
||||
if (!this._storageBusyCount) {
|
||||
TabItems.pauseReconnecting();
|
||||
GroupItems.pauseAutoclose();
|
||||
}
|
||||
|
||||
this._storageBusyCount++;
|
||||
},
|
||||
@ -650,6 +614,7 @@ let UI = {
|
||||
|
||||
TabItems.resumeReconnecting();
|
||||
GroupItems._updateTabBar();
|
||||
GroupItems.resumeAutoclose();
|
||||
}
|
||||
},
|
||||
|
||||
@ -726,7 +691,7 @@ let UI = {
|
||||
// if it's an app tab, add it to all the group items
|
||||
if (tab.pinned)
|
||||
GroupItems.addAppTab(tab);
|
||||
else if (self.isTabViewVisible())
|
||||
else if (self.isTabViewVisible() && !self._storageBusyCount)
|
||||
self._lastOpenedTab = tab;
|
||||
};
|
||||
|
||||
@ -868,8 +833,7 @@ let UI = {
|
||||
if (this.isTabViewVisible()) {
|
||||
if (!this.restoredClosedTab && this._lastOpenedTab == tab &&
|
||||
tab._tabViewTabItem) {
|
||||
if (!this.creatingNewOrphanTab)
|
||||
tab._tabViewTabItem.zoomIn(true);
|
||||
tab._tabViewTabItem.zoomIn(true);
|
||||
this._lastOpenedTab = null;
|
||||
return;
|
||||
}
|
||||
@ -917,9 +881,9 @@ let UI = {
|
||||
}
|
||||
} else {
|
||||
// No tabItem; must be an app tab. Base the tab bar on the current group.
|
||||
// If no current group or orphan tab, figure it out based on what's
|
||||
// already in the tab bar.
|
||||
if (!GroupItems.getActiveGroupItem() && !UI.getActiveOrphanTab()) {
|
||||
// If no current group, figure it out based on what's already in the tab
|
||||
// bar.
|
||||
if (!GroupItems.getActiveGroupItem()) {
|
||||
for (let a = 0; a < gBrowser.tabs.length; a++) {
|
||||
let theTab = gBrowser.tabs[a];
|
||||
if (!theTab.pinned) {
|
||||
@ -930,7 +894,7 @@ let UI = {
|
||||
}
|
||||
}
|
||||
|
||||
if (GroupItems.getActiveGroupItem() || UI.getActiveOrphanTab())
|
||||
if (GroupItems.getActiveGroupItem())
|
||||
GroupItems._updateTabBar();
|
||||
}
|
||||
},
|
||||
@ -979,7 +943,7 @@ let UI = {
|
||||
let cl = null;
|
||||
let clDist;
|
||||
TabItems.getItems().forEach(function (item) {
|
||||
if (item.parent && item.parent.hidden)
|
||||
if (!item.parent || item.parent.hidden)
|
||||
return;
|
||||
let testDist = tabCenter.distance(item.bounds.center());
|
||||
if (cl==null || testDist < clDist) {
|
||||
@ -1224,7 +1188,6 @@ let UI = {
|
||||
const minMinSize = 15;
|
||||
|
||||
let lastActiveGroupItem = GroupItems.getActiveGroupItem();
|
||||
this.setActive(null, { onlyRemoveActiveGroup: true });
|
||||
|
||||
var startPos = { x: e.clientX, y: e.clientY };
|
||||
var phantom = iQ("<div>")
|
||||
@ -1317,19 +1280,8 @@ let UI = {
|
||||
let box = item.getBounds();
|
||||
if (box.width > minMinSize && box.height > minMinSize &&
|
||||
(box.width > minSize || box.height > minSize)) {
|
||||
var bounds = item.getBounds();
|
||||
|
||||
// Add all of the orphaned tabs that are contained inside the new groupItem
|
||||
// to that groupItem.
|
||||
var tabs = GroupItems.getOrphanedTabs();
|
||||
var insideTabs = [];
|
||||
for each(let tab in tabs) {
|
||||
if (bounds.contains(tab.bounds))
|
||||
insideTabs.push(tab);
|
||||
}
|
||||
|
||||
let opts = {bounds: bounds, focusTitle: true};
|
||||
let groupItem = new GroupItem(insideTabs, opts);
|
||||
let opts = {bounds: item.getBounds(), focusTitle: true};
|
||||
let groupItem = new GroupItem([], opts);
|
||||
self.setActive(groupItem);
|
||||
phantom.remove();
|
||||
dragOutInfo = null;
|
||||
@ -1505,9 +1457,9 @@ let UI = {
|
||||
let unhiddenGroups = GroupItems.groupItems.filter(function(groupItem) {
|
||||
return (!groupItem.hidden && groupItem.getChildren().length > 0);
|
||||
});
|
||||
// no pinned tabs, no visible groups and no orphaned tabs: open a new
|
||||
// group, a blank tab and return
|
||||
if (!unhiddenGroups.length && !GroupItems.getOrphanedTabs().length) {
|
||||
// no pinned tabs and no visible groups: open a new group. open a blank
|
||||
// tab and return
|
||||
if (!unhiddenGroups.length) {
|
||||
let emptyGroups = GroupItems.groupItems.filter(function (groupItem) {
|
||||
return (!groupItem.hidden && !groupItem.getChildren().length);
|
||||
});
|
||||
|
@ -6,6 +6,10 @@ function test () {
|
||||
|
||||
let doc = gBrowser.contentDocument;
|
||||
let tooltip = document.getElementById("aHTMLTooltip");
|
||||
|
||||
ok(FillInHTMLTooltip(doc.getElementById("svg1"), "should get title"));
|
||||
is(tooltip.getAttribute("label"), "This is a non-root SVG element title");
|
||||
|
||||
ok(FillInHTMLTooltip(doc.getElementById("text1"), "should get title"));
|
||||
is(tooltip.getAttribute("label"), " This is a title ");
|
||||
|
||||
|
@ -53,7 +53,7 @@ let gTests = [
|
||||
setup: function() {},
|
||||
clean: function() {},
|
||||
event: {},
|
||||
target: "commonlink",
|
||||
targets: [ "commonlink", "mathxlink", "svgxlink", "maplink" ],
|
||||
expectedInvokedMethods: [],
|
||||
preventDefault: false,
|
||||
},
|
||||
@ -64,7 +64,7 @@ let gTests = [
|
||||
clean: function() {},
|
||||
event: { ctrlKey: true,
|
||||
metaKey: true },
|
||||
target: "commonlink",
|
||||
targets: [ "commonlink", "mathxlink", "svgxlink", "maplink" ],
|
||||
expectedInvokedMethods: [ "urlSecurityCheck", "openLinkIn" ],
|
||||
preventDefault: true,
|
||||
},
|
||||
@ -77,17 +77,28 @@ let gTests = [
|
||||
clean: function() {},
|
||||
event: { shiftKey: true,
|
||||
altKey: true },
|
||||
target: "commonlink",
|
||||
targets: [ "commonlink", "maplink" ],
|
||||
expectedInvokedMethods: [ "gatherTextUnder", "saveURL" ],
|
||||
preventDefault: true,
|
||||
},
|
||||
|
||||
{
|
||||
desc: "Shift+Alt left click on XLinks",
|
||||
setup: function() {},
|
||||
clean: function() {},
|
||||
event: { shiftKey: true,
|
||||
altKey: true },
|
||||
targets: [ "mathxlink", "svgxlink"],
|
||||
expectedInvokedMethods: [ "saveURL" ],
|
||||
preventDefault: true,
|
||||
},
|
||||
|
||||
{
|
||||
desc: "Shift click",
|
||||
setup: function() {},
|
||||
clean: function() {},
|
||||
event: { shiftKey: true },
|
||||
target: "commonlink",
|
||||
targets: [ "commonlink", "mathxlink", "svgxlink", "maplink" ],
|
||||
expectedInvokedMethods: [ "urlSecurityCheck", "openLinkIn" ],
|
||||
preventDefault: true,
|
||||
},
|
||||
@ -97,17 +108,27 @@ let gTests = [
|
||||
setup: function() {},
|
||||
clean: function() {},
|
||||
event: { altKey: true },
|
||||
target: "commonlink",
|
||||
targets: [ "commonlink", "maplink" ],
|
||||
expectedInvokedMethods: [ "gatherTextUnder", "saveURL" ],
|
||||
preventDefault: true,
|
||||
},
|
||||
|
||||
{
|
||||
desc: "Alt click on XLinks",
|
||||
setup: function() {},
|
||||
clean: function() {},
|
||||
event: { altKey: true },
|
||||
targets: [ "mathxlink", "svgxlink" ],
|
||||
expectedInvokedMethods: [ "saveURL" ],
|
||||
preventDefault: true,
|
||||
},
|
||||
|
||||
{
|
||||
desc: "Panel click",
|
||||
setup: function() {},
|
||||
clean: function() {},
|
||||
event: {},
|
||||
target: "panellink",
|
||||
targets: [ "panellink" ],
|
||||
expectedInvokedMethods: [ "urlSecurityCheck", "getShortcutOrURI", "loadURI" ],
|
||||
preventDefault: true,
|
||||
},
|
||||
@ -117,7 +138,7 @@ let gTests = [
|
||||
setup: function() {},
|
||||
clean: function() {},
|
||||
event: { button: 1 },
|
||||
target: "commonlink",
|
||||
targets: [ "commonlink", "mathxlink", "svgxlink", "maplink" ],
|
||||
expectedInvokedMethods: [ "urlSecurityCheck", "openLinkIn" ],
|
||||
preventDefault: true,
|
||||
},
|
||||
@ -133,7 +154,7 @@ let gTests = [
|
||||
} catch(ex) {}
|
||||
},
|
||||
event: { button: 1 },
|
||||
target: "commonlink",
|
||||
targets: [ "commonlink", "mathxlink", "svgxlink", "maplink" ],
|
||||
expectedInvokedMethods: [ "urlSecurityCheck", "openLinkIn" ],
|
||||
preventDefault: true,
|
||||
},
|
||||
@ -153,7 +174,7 @@ let gTests = [
|
||||
} catch(ex) {}
|
||||
},
|
||||
event: { button: 1 },
|
||||
target: "emptylink",
|
||||
targets: [ "emptylink" ],
|
||||
expectedInvokedMethods: [ "middleMousePaste" ],
|
||||
preventDefault: true,
|
||||
},
|
||||
@ -206,7 +227,7 @@ function test() {
|
||||
// Click handler used to steal click events.
|
||||
let gClickHandler = {
|
||||
handleEvent: function (event) {
|
||||
let linkId = event.target.id;
|
||||
let linkId = event.target.id || event.target.localName;
|
||||
is(event.type, "click",
|
||||
gCurrentTest.desc + ":Handler received a click event on " + linkId);
|
||||
|
||||
@ -223,7 +244,7 @@ let gClickHandler = {
|
||||
});
|
||||
|
||||
if (gInvokedMethods.length != gCurrentTest.expectedInvokedMethods.length) {
|
||||
is(false, "More than the expected methods have been called");
|
||||
ok(false, "Wrong number of invoked methods");
|
||||
gInvokedMethods.forEach(function (method) info(method + " was invoked"));
|
||||
}
|
||||
|
||||
@ -257,35 +278,45 @@ function setupTestBrowserWindow() {
|
||||
let doc = gTestWin.content.document;
|
||||
let mainDiv = doc.createElement("div");
|
||||
mainDiv.innerHTML =
|
||||
'<a id="commonlink" href="http://mochi.test/moz/">Common link</a>' +
|
||||
'<a id="panellink" href="http://mochi.test/moz/">Panel link</a>' +
|
||||
'<a id="emptylink">Empty link</a>';
|
||||
'<p><a id="commonlink" href="http://mochi.test/moz/">Common link</a></p>' +
|
||||
'<p><a id="panellink" href="http://mochi.test/moz/">Panel link</a></p>' +
|
||||
'<p><a id="emptylink">Empty link</a></p>' +
|
||||
'<p><math id="mathxlink" xmlns="http://www.w3.org/1998/Math/MathML" xlink:type="simple" xlink:href="http://mochi.test/moz/"><mtext>MathML XLink</mtext></math></p>' +
|
||||
'<p><svg id="svgxlink" xmlns="http://www.w3.org/2000/svg" width="100px" height="50px" version="1.1"><a xlink:type="simple" xlink:href="http://mochi.test/moz/"><text transform="translate(10, 25)">SVG XLink</text></a></svg></p>' +
|
||||
'<p><map name="map" id="map"><area href="http://mochi.test/moz/" shape="rect" coords="0,0,128,128" /></map><img id="maplink" usemap="#map" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAIAAAACACAIAAABMXPacAAAABGdBTUEAALGPC%2FxhBQAAAOtJREFUeF7t0IEAAAAAgKD9qRcphAoDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGDAgAEDBgwYMGBgwIAAAT0N51AAAAAASUVORK5CYII%3D"/></p>'
|
||||
doc.body.appendChild(mainDiv);
|
||||
}
|
||||
|
||||
function runNextTest() {
|
||||
if (gCurrentTest) {
|
||||
if (!gCurrentTest) {
|
||||
gCurrentTest = gTests.shift();
|
||||
gCurrentTest.setup();
|
||||
}
|
||||
|
||||
if (gCurrentTest.targets.length == 0) {
|
||||
info(gCurrentTest.desc + ": cleaning up...")
|
||||
gCurrentTest.clean();
|
||||
gInvokedMethods.length = 0;
|
||||
|
||||
if (gTests.length > 0) {
|
||||
gCurrentTest = gTests.shift();
|
||||
gCurrentTest.setup();
|
||||
}
|
||||
else {
|
||||
finishTest();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (gTests.length > 0) {
|
||||
gCurrentTest = gTests.shift();
|
||||
// Move to next target.
|
||||
gInvokedMethods.length = 0;
|
||||
let target = gCurrentTest.targets.shift();
|
||||
|
||||
info(gCurrentTest.desc + ": starting...");
|
||||
// Prepare for test.
|
||||
gCurrentTest.setup();
|
||||
info(gCurrentTest.desc + ": testing " + target);
|
||||
|
||||
// Fire click event.
|
||||
let target = gTestWin.content.document.getElementById(gCurrentTest.target);
|
||||
ok(target, gCurrentTest.desc + ": target is valid (" + target.id + ")");
|
||||
EventUtils.synthesizeMouse(target, 2, 2, gCurrentTest.event, gTestWin.content);
|
||||
}
|
||||
else {
|
||||
// No more tests to run.
|
||||
finishTest()
|
||||
}
|
||||
// Fire click event.
|
||||
let targetElt = gTestWin.content.document.getElementById(target);
|
||||
ok(targetElt, gCurrentTest.desc + ": target is valid (" + targetElt.id + ")");
|
||||
EventUtils.synthesizeMouseAtCenter(targetElt, gCurrentTest.event, gTestWin.content);
|
||||
}
|
||||
|
||||
function finishTest() {
|
||||
|
@ -5,7 +5,7 @@ function test() {
|
||||
gBrowser.addTab();
|
||||
gBrowser.addTab();
|
||||
|
||||
assertTabs(4);
|
||||
checkTabs(4);
|
||||
|
||||
ctrlTabTest([2] , 1, 0);
|
||||
ctrlTabTest([2, 3, 1], 2, 2);
|
||||
@ -28,11 +28,21 @@ function test() {
|
||||
releaseCtrl();
|
||||
}
|
||||
|
||||
assertTabs(3);
|
||||
{ // test for bug 667314
|
||||
let tabs = gBrowser.tabs.length;
|
||||
pressCtrlTab();
|
||||
pressCtrlTab(true);
|
||||
EventUtils.synthesizeKey("w", { ctrlKey: true });
|
||||
is(gBrowser.tabs.length, tabs - 1, "Ctrl+Tab -> Ctrl+W removes the selected tab");
|
||||
releaseCtrl();
|
||||
}
|
||||
|
||||
gBrowser.addTab();
|
||||
checkTabs(3);
|
||||
ctrlTabTest([2, 1, 0], 9, 1);
|
||||
|
||||
gBrowser.addTab();
|
||||
assertTabs(4);
|
||||
checkTabs(4);
|
||||
|
||||
{ // test for bug 445369
|
||||
selectTabs([1, 2, 0]);
|
||||
@ -53,12 +63,12 @@ function test() {
|
||||
"Ctrl+Tab*2 -> Ctrl+W -> Ctrl+Shift+Tab*2 keeps the selected tab");
|
||||
}
|
||||
gBrowser.removeTab(gBrowser.tabContainer.lastChild);
|
||||
assertTabs(2);
|
||||
checkTabs(2);
|
||||
|
||||
ctrlTabTest([1], 1, 0);
|
||||
|
||||
gBrowser.removeTab(gBrowser.tabContainer.lastChild);
|
||||
assertTabs(1);
|
||||
checkTabs(1);
|
||||
|
||||
{ // test for bug 445768
|
||||
let focusedWindow = document.commandDispatcher.focusedWindow;
|
||||
@ -89,7 +99,7 @@ function test() {
|
||||
function isOpen()
|
||||
ctrlTab.isOpen;
|
||||
|
||||
function assertTabs(aTabs) {
|
||||
function checkTabs(aTabs) {
|
||||
var tabs = gBrowser.tabs.length;
|
||||
if (tabs != aTabs) {
|
||||
while (gBrowser.tabs.length > 1)
|
||||
|
@ -15,6 +15,7 @@ function test() {
|
||||
if (topic != "page-info-dialog-loaded")
|
||||
return;
|
||||
|
||||
Services.obs.removeObserver(observer, topic);
|
||||
handlePageInfo();
|
||||
}
|
||||
|
||||
|
@ -82,16 +82,30 @@ function test() {
|
||||
"focusedWindow after blur in unfocused tab");
|
||||
is(fm.getFocusedElementForWindow(browser1.contentWindow, false, {}), null, "blur in unfocused tab");
|
||||
|
||||
// focusing the url field should switch active focus away from the tab but
|
||||
// not clear what would be the focus in the tab
|
||||
// When focus is in the tab bar, it should be retained there
|
||||
expectFocusShift(function () gBrowser.selectedTab.focus(),
|
||||
window, gBrowser.selectedTab, true,
|
||||
"focusing tab element");
|
||||
expectFocusShift(function () gBrowser.selectedTab = tab1,
|
||||
window, tab1, true,
|
||||
"tab change when selected tab element was focused");
|
||||
expectFocusShift(function () gBrowser.selectedTab = tab2,
|
||||
window, tab2, true,
|
||||
"tab change when selected tab element was focused");
|
||||
expectFocusShift(function () gBrowser.selectedTab.blur(),
|
||||
window, null, true,
|
||||
"blurring tab element");
|
||||
|
||||
// focusing the url field should switch active focus away from the browser but
|
||||
// not clear what would be the focus in the browser
|
||||
button1.focus();
|
||||
expectFocusShift(function () gURLBar.focus(),
|
||||
window, gURLBar.inputField, true,
|
||||
"focusedWindow after url field focused");
|
||||
is(fm.getFocusedElementForWindow(browser2.contentWindow, false, {}), button2, "url field focused, button in tab");
|
||||
is(fm.getFocusedElementForWindow(browser2.contentWindow, false, {}), button2, "url field focused, button in browser");
|
||||
expectFocusShift(function () gURLBar.blur(),
|
||||
window, null, true,
|
||||
"focusedWindow after browser focused");
|
||||
"blurring url field");
|
||||
|
||||
// when a chrome element is focused, switching tabs to a tab with a button
|
||||
// with the current focus should focus the button
|
||||
|
@ -54,6 +54,7 @@ _BROWSER_FILES = \
|
||||
browser_inspector_treePanel_output.js \
|
||||
browser_inspector_treePanel_input.html \
|
||||
browser_inspector_treePanel_result.html \
|
||||
browser_inspector_bug_665880.js \
|
||||
$(NULL)
|
||||
|
||||
libs:: $(_BROWSER_FILES)
|
||||
|
@ -0,0 +1,62 @@
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
|
||||
function test()
|
||||
{
|
||||
waitForExplicitFinish();
|
||||
|
||||
let doc;
|
||||
let objectNode;
|
||||
|
||||
gBrowser.selectedTab = gBrowser.addTab();
|
||||
gBrowser.selectedBrowser.addEventListener("load", function() {
|
||||
gBrowser.selectedBrowser.removeEventListener("load", arguments.callee, true);
|
||||
doc = content.document;
|
||||
waitForFocus(setupObjectInspectionTest, content);
|
||||
}, true);
|
||||
|
||||
content.location = "data:text/html,<object style='padding: 100px'><p>foobar</p></object>";
|
||||
|
||||
function setupObjectInspectionTest()
|
||||
{
|
||||
objectNode = doc.querySelector("object");
|
||||
ok(objectNode, "we have the object node");
|
||||
Services.obs.addObserver(runObjectInspectionTest,
|
||||
INSPECTOR_NOTIFICATIONS.OPENED, false);
|
||||
InspectorUI.toggleInspectorUI();
|
||||
}
|
||||
|
||||
function runObjectInspectionTest()
|
||||
{
|
||||
Services.obs.removeObserver(runObjectInspectionTest,
|
||||
INSPECTOR_NOTIFICATIONS.OPENED);
|
||||
|
||||
executeSoon(function() {
|
||||
Services.obs.addObserver(performTestComparison,
|
||||
INSPECTOR_NOTIFICATIONS.HIGHLIGHTING, false);
|
||||
|
||||
InspectorUI.inspectNode(objectNode);
|
||||
});
|
||||
}
|
||||
|
||||
function performTestComparison()
|
||||
{
|
||||
Services.obs.removeObserver(performTestComparison,
|
||||
INSPECTOR_NOTIFICATIONS.HIGHLIGHTING);
|
||||
|
||||
is(InspectorUI.selection, objectNode, "selection matches node");
|
||||
|
||||
Services.obs.addObserver(finishUp,
|
||||
INSPECTOR_NOTIFICATIONS.CLOSED, false);
|
||||
InspectorUI.closeInspectorUI();
|
||||
}
|
||||
|
||||
|
||||
function finishUp() {
|
||||
Services.obs.removeObserver(finishUp, INSPECTOR_NOTIFICATIONS.CLOSED);
|
||||
doc = objectNode = null;
|
||||
gBrowser.removeCurrentTab();
|
||||
finish();
|
||||
}
|
||||
}
|
@ -100,7 +100,6 @@ _BROWSER_FILES = \
|
||||
browser_tabview_bug618828.js \
|
||||
browser_tabview_bug619937.js \
|
||||
browser_tabview_bug622835.js \
|
||||
browser_tabview_bug622872.js \
|
||||
browser_tabview_bug623768.js \
|
||||
browser_tabview_bug624265.js \
|
||||
browser_tabview_bug624692.js \
|
||||
@ -130,7 +129,6 @@ _BROWSER_FILES = \
|
||||
browser_tabview_bug633788.js \
|
||||
browser_tabview_bug634077.js \
|
||||
browser_tabview_bug634085.js \
|
||||
browser_tabview_bug634158.js \
|
||||
browser_tabview_bug634672.js \
|
||||
browser_tabview_bug635696.js \
|
||||
browser_tabview_bug640765.js \
|
||||
@ -138,18 +136,19 @@ _BROWSER_FILES = \
|
||||
browser_tabview_bug642793.js \
|
||||
browser_tabview_bug643392.js \
|
||||
browser_tabview_bug644097.js \
|
||||
browser_tabview_bug645653.js \
|
||||
browser_tabview_bug648882.js \
|
||||
browser_tabview_bug649006.js \
|
||||
browser_tabview_bug649307.js \
|
||||
browser_tabview_bug649319.js \
|
||||
browser_tabview_bug650573.js \
|
||||
browser_tabview_bug651311.js \
|
||||
browser_tabview_bug654721.js \
|
||||
browser_tabview_bug654941.js \
|
||||
browser_tabview_bug655269.js \
|
||||
browser_tabview_bug656778.js \
|
||||
browser_tabview_bug656913.js \
|
||||
browser_tabview_bug662266.js \
|
||||
browser_tabview_bug663421.js \
|
||||
browser_tabview_bug665502.js \
|
||||
browser_tabview_dragdrop.js \
|
||||
browser_tabview_exit_button.js \
|
||||
@ -158,7 +157,6 @@ _BROWSER_FILES = \
|
||||
browser_tabview_group.js \
|
||||
browser_tabview_launch.js \
|
||||
browser_tabview_multiwindow_search.js \
|
||||
browser_tabview_orphaned_tabs.js \
|
||||
browser_tabview_privatebrowsing.js \
|
||||
browser_tabview_rtl.js \
|
||||
browser_tabview_search.js \
|
||||
|
@ -72,6 +72,8 @@ function testGroupSwitch(contentWindow, groupItemOne, groupItemTwo) {
|
||||
"The currently selected tab should be the second tab in the groupItemOne");
|
||||
|
||||
// cleanup.
|
||||
gBrowser.removeTab(groupItemTwo.getChild(0).tab);
|
||||
gBrowser.removeTab(newTabOne);
|
||||
closeGroupItem(groupItemTwo, finish);
|
||||
|
||||
finish();
|
||||
}
|
||||
|
@ -58,17 +58,15 @@ function onTabViewWindowLoaded() {
|
||||
gBrowser.unpinTab(appXulTab);
|
||||
gBrowser.removeTab(appXulTab);
|
||||
|
||||
ok(!groupItem.getChildren().length, "the second group is empty");
|
||||
ok(groupItem.closeIfEmpty(), "the second group was empty");
|
||||
|
||||
closeGroupItem(groupItem, function () {
|
||||
// Verify ending state
|
||||
is(gBrowser.tabs.length, 1, "we finish with one tab");
|
||||
is(contentWindow.GroupItems.groupItems.length, 1,
|
||||
"we finish with one group");
|
||||
ok(!TabView.isVisible(), "we finish with Tab View hidden");
|
||||
|
||||
finish();
|
||||
});
|
||||
// Verify ending state
|
||||
is(gBrowser.tabs.length, 1, "we finish with one tab");
|
||||
is(contentWindow.GroupItems.groupItems.length, 1,
|
||||
"we finish with one group");
|
||||
ok(!TabView.isVisible(), "we finish with Tab View hidden");
|
||||
|
||||
finish();
|
||||
}
|
||||
|
||||
window.addEventListener("tabviewhidden", onTabViewHidden, false);
|
||||
|
@ -4,37 +4,27 @@
|
||||
function test() {
|
||||
waitForExplicitFinish();
|
||||
|
||||
window.addEventListener("tabviewshown", onTabViewWindowLoaded, false);
|
||||
TabView.show();
|
||||
}
|
||||
newWindowWithTabView(function (win) {
|
||||
registerCleanupFunction(function () win.close());
|
||||
|
||||
function onTabViewWindowLoaded() {
|
||||
window.removeEventListener("tabviewshown", onTabViewWindowLoaded, false);
|
||||
let cw = win.TabView.getContentWindow();
|
||||
let groupItems = cw.GroupItems.groupItems;
|
||||
let groupItem = groupItems[0];
|
||||
|
||||
let contentWindow = document.getElementById("tab-view").contentWindow;
|
||||
is(contentWindow.GroupItems.groupItems.length, 1,
|
||||
"There is one group item on startup");
|
||||
is(groupItems.length, 1, "There is one group item on startup");
|
||||
|
||||
let groupItem = contentWindow.GroupItems.groupItems[0];
|
||||
groupItem.addSubscriber(groupItem, "groupHidden", function() {
|
||||
groupItem.removeSubscriber(groupItem, "groupHidden");
|
||||
|
||||
let onTabViewHidden = function() {
|
||||
window.removeEventListener("tabviewhidden", onTabViewHidden, false);
|
||||
|
||||
is(contentWindow.GroupItems.groupItems.length, 1,
|
||||
"There is still one group item");
|
||||
isnot(groupItem.id, contentWindow.GroupItems.groupItems[0].id,
|
||||
whenTabViewIsHidden(function () {
|
||||
is(groupItems.length, 1, "There is still one group item");
|
||||
isnot(groupItem.id, groupItems[0].id,
|
||||
"The initial group item is not the same as the final group item");
|
||||
is(gBrowser.tabs.length, 1, "There is only one tab");
|
||||
ok(!TabView.isVisible(), "Tab View is hidden");
|
||||
is(win.gBrowser.tabs.length, 1, "There is only one tab");
|
||||
|
||||
finish();
|
||||
};
|
||||
window.addEventListener("tabviewhidden", onTabViewHidden, false);
|
||||
}, win);
|
||||
|
||||
// create a new tab
|
||||
EventUtils.synthesizeKey("t", { accelKey: true });
|
||||
hideGroupItem(groupItem, function () {
|
||||
// create a new tab
|
||||
EventUtils.synthesizeKey("t", { accelKey: true }, cw);
|
||||
});
|
||||
});
|
||||
groupItem.closeAll();
|
||||
}
|
||||
|
@ -58,10 +58,8 @@ function test() {
|
||||
let onTabViewShow = function() {
|
||||
newWin.removeEventListener("tabviewshown", onTabViewShow, false);
|
||||
|
||||
let contentWindow = newWin.document.getElementById("tab-view").contentWindow;
|
||||
|
||||
let contentWindow = newWin.TabView.getContentWindow();
|
||||
is(contentWindow.GroupItems.groupItems.length, 2, "Has two group items");
|
||||
is(contentWindow.GroupItems.getOrphanedTabs().length, 0, "No orphan tabs");
|
||||
|
||||
// clean up and finish
|
||||
newWin.close();
|
||||
|
@ -28,15 +28,12 @@ function test() {
|
||||
EventUtils.synthesizeMouseAtCenter(targetTab, {type: 'mousemove'}, cw);
|
||||
EventUtils.synthesizeMouseAtCenter(targetTab, {type: 'mouseup'}, cw);
|
||||
|
||||
is(cw.GroupItems.groupItems.length, 2, 'there are two groupItems');
|
||||
is(sourceGroup.getChildren().length, 0, 'source group has no tabs');
|
||||
is(targetGroup.getChildren().length, 2, 'target group has two tabs');
|
||||
is(cw.GroupItems.groupItems.length, 1, 'sourceGroup was closed');
|
||||
isnot(cw.GroupItems.groupItems[0], sourceGroup, 'sourceGroup was closed');
|
||||
|
||||
targetGroup.getChild(0).close();
|
||||
|
||||
closeGroupItem(sourceGroup, function () {
|
||||
hideTabView(finish);
|
||||
});
|
||||
hideTabView(finish);
|
||||
}
|
||||
|
||||
waitForExplicitFinish();
|
||||
|
@ -1,8 +1,6 @@
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
let originalTab;
|
||||
let orphanedTab;
|
||||
let contentWindow;
|
||||
let contentElement;
|
||||
|
||||
@ -18,23 +16,17 @@ function test() {
|
||||
showTabView(function() {
|
||||
contentWindow = TabView.getContentWindow();
|
||||
contentElement = contentWindow.document.getElementById("content");
|
||||
originalTab = gBrowser.visibleTabs[0];
|
||||
test1();
|
||||
});
|
||||
}
|
||||
|
||||
function test1() {
|
||||
is(contentWindow.GroupItems.getOrphanedTabs().length, 0, "No orphaned tabs");
|
||||
let groupItems = contentWindow.GroupItems.groupItems;
|
||||
is(groupItems.length, 1, "there is one groupItem");
|
||||
|
||||
whenTabViewIsHidden(function() {
|
||||
showTabView(function() {
|
||||
is(contentWindow.GroupItems.getOrphanedTabs().length, 1,
|
||||
"An orphaned tab is created");
|
||||
hideTabView(function() {
|
||||
gBrowser.selectedTab = originalTab;
|
||||
finish();
|
||||
});
|
||||
});
|
||||
is(groupItems.length, 2, "there are two groupItems");
|
||||
closeGroupItem(groupItems[1], finish);
|
||||
});
|
||||
|
||||
// first click
|
||||
|
@ -22,13 +22,11 @@ function test() {
|
||||
"Tab width is bigger than tab clip width");
|
||||
is(gBrowser.tabContainer.getAttribute("closebuttons"), "alltabs", "Show button on all tabs.")
|
||||
|
||||
let cw = TabView.getContentWindow();
|
||||
let groupItems = cw.GroupItems.groupItems;
|
||||
is(groupItems.length, 2, "there are two groupItems");
|
||||
|
||||
// clean up and finish
|
||||
newTabs.forEach(function (tab) gBrowser.removeTab(tab));
|
||||
closeGroupItem(groupItems[1], finish);
|
||||
newTabs.forEach(function(tab) {
|
||||
gBrowser.removeTab(tab);
|
||||
});
|
||||
finish();
|
||||
});
|
||||
});
|
||||
}
|
||||
|
@ -22,15 +22,16 @@ function test() {
|
||||
let content = cw.document.getElementById("content");
|
||||
|
||||
// drag to create a new group
|
||||
EventUtils.synthesizeMouse(content, 350, 50, {type: "mousedown"}, cw);
|
||||
EventUtils.synthesizeMouse(content, 400, 50, {type: "mousedown"}, cw);
|
||||
EventUtils.synthesizeMouse(content, 500, 250, {type: "mousemove"}, cw);
|
||||
EventUtils.synthesizeMouse(content, 500, 250, {type: "mouseup"}, cw);
|
||||
|
||||
assertNumberOfGroupItems(2);
|
||||
|
||||
// enter a title for the new group
|
||||
EventUtils.synthesizeKey("t", {}, cw);
|
||||
EventUtils.synthesizeKey("VK_RETURN", {}, cw);
|
||||
|
||||
assertNumberOfGroupItems(2);
|
||||
|
||||
let groupItem = cw.GroupItems.groupItems[1];
|
||||
is(groupItem.getTitle(), "t", "new groupItem's title is correct");
|
||||
@ -43,12 +44,11 @@ function test() {
|
||||
groupItem.closeAll();
|
||||
};
|
||||
|
||||
let testDropOnOrphan = function (callback) {
|
||||
let testDragOutOfGroup = function (callback) {
|
||||
assertNumberOfGroupItems(1);
|
||||
|
||||
let groupItem = cw.GroupItems.groupItems[0];
|
||||
dragTabOutOfGroup(groupItem);
|
||||
dragTabOutOfGroup(groupItem);
|
||||
assertNumberOfGroupItems(2);
|
||||
|
||||
// enter a title for the new group
|
||||
@ -64,7 +64,7 @@ function test() {
|
||||
registerCleanupFunction(function () win.close());
|
||||
|
||||
for (let i = 0; i < 2; i++)
|
||||
win.gBrowser.loadOneTab("about:blank", {inBackground: true});
|
||||
win.gBrowser.addTab();
|
||||
};
|
||||
|
||||
let onShow = function (win) {
|
||||
@ -76,9 +76,7 @@ function test() {
|
||||
|
||||
waitForFocus(function () {
|
||||
testCreateGroup(function () {
|
||||
testDropOnOrphan(function () {
|
||||
waitForFocus(finish);
|
||||
});
|
||||
testDragOutOfGroup(finish);
|
||||
});
|
||||
}, cw);
|
||||
};
|
||||
|
@ -14,11 +14,11 @@ function test() {
|
||||
// make sure the tab one is selected because undoCloseTab() would remove
|
||||
// the selected tab if it's a blank tab.
|
||||
gBrowser.selectedTab = tabOne;
|
||||
showTabView(onTabViewShown);
|
||||
showTabView(onTabViewWindowLoaded);
|
||||
});
|
||||
}
|
||||
|
||||
function onTabViewShown() {
|
||||
function onTabViewWindowLoaded() {
|
||||
let contentWindow = TabView.getContentWindow();
|
||||
let groupItems = contentWindow.GroupItems.groupItems;
|
||||
is(groupItems.length, 1, "There is only one group");
|
||||
@ -28,7 +28,8 @@ function onTabViewShown() {
|
||||
ok(TabView.isVisible(), "Tab View is still visible after removing a tab");
|
||||
is(groupItems[0].getChildren().length, 2, "The group has two tab items");
|
||||
|
||||
restoreTab(function (tabTwo) {
|
||||
tabTwo = undoCloseTab(0);
|
||||
whenTabIsReconnected(tabTwo, function() {
|
||||
ok(TabView.isVisible(), "Tab View is still visible after restoring a tab");
|
||||
is(groupItems[0].getChildren().length, 3, "The group still has three tab items");
|
||||
|
||||
@ -40,3 +41,18 @@ function onTabViewShown() {
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
// ----------
|
||||
function whenTabIsReconnected(tab, callback) {
|
||||
let tabItem = tab._tabViewTabItem;
|
||||
|
||||
if (tabItem._reconnected) {
|
||||
callback();
|
||||
return;
|
||||
}
|
||||
|
||||
tabItem.addSubscriber(tabItem, "reconnected", function () {
|
||||
tabItem.removeSubscriber(tabItem, "reconnected");
|
||||
callback();
|
||||
});
|
||||
}
|
||||
|
@ -25,11 +25,12 @@ function test() {
|
||||
is(gBrowser.visibleTabs.length, 1, "The number of visible tabs is 1");
|
||||
is(gBrowser.visibleTabs[0], origTab,
|
||||
"The original tab is the only visible tab");
|
||||
|
||||
let groupItem = newTab._tabViewTabItem.parent;
|
||||
isnot(groupItem.id, newTabGroupItemId,
|
||||
isnot(newTab._tabViewTabItem.parent.id, newTabGroupItemId,
|
||||
"The moved tab item has a new group id");
|
||||
|
||||
closeGroupItem(groupItem, finish);
|
||||
// clean up
|
||||
gBrowser.removeTab(newTab);
|
||||
|
||||
finish();
|
||||
});
|
||||
}
|
||||
|
@ -36,14 +36,12 @@ function test() {
|
||||
|
||||
// check state after adding tabItem to targetGroup
|
||||
is(tabItem.parent, targetGroup, 'tabItem changed groups');
|
||||
is(sourceGroup.getChildren().length, 0, 'source group has no children');
|
||||
is(cw.GroupItems.groupItems.length, 1, 'source group was closed automatically');
|
||||
is(targetGroup.getChildren().length, 2, 'target group has now two children');
|
||||
|
||||
// cleanup and finish
|
||||
closeGroupItem(sourceGroup, function () {
|
||||
tabItem.close();
|
||||
hideTabView(finishTest);
|
||||
});
|
||||
tabItem.close();
|
||||
hideTabView(finishTest);
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -20,7 +20,8 @@ function test() {
|
||||
groupItem = createEmptyGroupItem(cw, 200, 200, 20);
|
||||
cw.UI.setActive(groupItem);
|
||||
|
||||
executeSoon(function () hideTabView(onHide, win));
|
||||
whenTabViewIsHidden(onHide, win);
|
||||
cw.UI.goToTab(win.gBrowser.tabs[0]);
|
||||
};
|
||||
|
||||
let onHide = function () {
|
||||
@ -35,7 +36,7 @@ function test() {
|
||||
is(win.gBrowser.visibleTabs.length, 1, "There is one tab displayed");
|
||||
is(cw.GroupItems.groupItems.length, 2, "There are two groups still");
|
||||
|
||||
waitForFocus(finish);
|
||||
finish();
|
||||
});
|
||||
};
|
||||
|
||||
|
@ -20,6 +20,23 @@ function test() {
|
||||
return groupItem;
|
||||
}
|
||||
|
||||
let hideGroupItem = function (groupItem, callback) {
|
||||
groupItem.addSubscriber(groupItem, 'groupHidden', function () {
|
||||
groupItem.removeSubscriber(groupItem, 'groupHidden');
|
||||
callback();
|
||||
});
|
||||
groupItem.closeAll();
|
||||
}
|
||||
|
||||
let closeGroupItem = function (groupItem, callback) {
|
||||
afterAllTabsLoaded(function () {
|
||||
hideGroupItem(groupItem, function () {
|
||||
groupItem.closeHidden();
|
||||
callback();
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
let tests = [];
|
||||
|
||||
let next = function () {
|
||||
@ -189,70 +206,6 @@ function test() {
|
||||
});
|
||||
}
|
||||
|
||||
// setup: 1 orphan tab
|
||||
// action: exit panorama
|
||||
// expected: nothing should happen
|
||||
let testOrphanTab1 = function () {
|
||||
let groupItem = getGroupItem(0);
|
||||
let tabItem = groupItem.getChild(0);
|
||||
groupItem.remove(tabItem);
|
||||
|
||||
closeGroupItem(groupItem, function () {
|
||||
assertNumberOfGroupItems(0);
|
||||
|
||||
hideTabView(function () {
|
||||
createGroupItem().add(tabItem);
|
||||
next();
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
// setup: 1 orphan tab, 1 non-empty group
|
||||
// action: close the group
|
||||
// expected: nothing should happen
|
||||
let testOrphanTab2 = function () {
|
||||
let groupItem = getGroupItem(0);
|
||||
let tabItem = groupItem.getChild(0);
|
||||
groupItem.remove(tabItem);
|
||||
|
||||
closeGroupItem(groupItem, function () {
|
||||
assertNumberOfGroupItems(0);
|
||||
|
||||
let newGroupItem = createGroupItem(1);
|
||||
assertNumberOfGroupItems(1);
|
||||
|
||||
closeGroupItem(newGroupItem, function () {
|
||||
assertNumberOfGroupItems(0);
|
||||
createGroupItem().add(tabItem);
|
||||
hideTabView(next);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
// setup: 1 orphan tab, 1 non-empty group
|
||||
// action: hide the group, exit panorama
|
||||
// expected: nothing should happen
|
||||
let testOrphanTab3 = function () {
|
||||
let groupItem = getGroupItem(0);
|
||||
let tabItem = groupItem.getChild(0);
|
||||
groupItem.remove(tabItem);
|
||||
|
||||
closeGroupItem(groupItem, function () {
|
||||
assertNumberOfGroupItems(0);
|
||||
|
||||
let newGroupItem = createGroupItem(1);
|
||||
assertNumberOfGroupItems(1);
|
||||
|
||||
hideGroupItem(newGroupItem, function () {
|
||||
hideTabView(function () {
|
||||
assertNumberOfGroupItems(0);
|
||||
createGroupItem().add(tabItem);
|
||||
next();
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
// setup: 1 non-empty group, 1 empty group
|
||||
// action: close non-empty group
|
||||
// expected: empty group is re-used, new tab is created and zoomed into
|
||||
@ -335,10 +288,6 @@ function test() {
|
||||
tests.push({name: 'testPinnedTab3', func: testPinnedTab3});
|
||||
tests.push({name: 'testPinnedTab4', func: testPinnedTab4});
|
||||
|
||||
tests.push({name: 'testOrphanTab1', func: testOrphanTab1});
|
||||
tests.push({name: 'testOrphanTab2', func: testOrphanTab2});
|
||||
tests.push({name: 'testOrphanTab3', func: testOrphanTab3});
|
||||
|
||||
tests.push({name: 'testEmptyGroup1', func: testEmptyGroup1});
|
||||
tests.push({name: 'testEmptyGroup2', func: testEmptyGroup2});
|
||||
|
||||
|
@ -39,6 +39,10 @@ function test() {
|
||||
tests.push([tab2, tab1]);
|
||||
tests.push([tab1]);
|
||||
|
||||
// test reordering of empty groups - removes the last tab and causes
|
||||
// the groupItem to close
|
||||
tests.push([]);
|
||||
|
||||
while (tests.length) {
|
||||
let test = tests.shift();
|
||||
|
||||
@ -59,7 +63,7 @@ function test() {
|
||||
groupItem.reorderTabsBasedOnTabItemOrder();
|
||||
}
|
||||
|
||||
closeGroupItem(groupItem, testMoveBetweenGroups);
|
||||
testMoveBetweenGroups();
|
||||
}
|
||||
|
||||
let testMoveBetweenGroups = function () {
|
||||
|
@ -1,118 +0,0 @@
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
function test() {
|
||||
waitForExplicitFinish();
|
||||
newWindowWithTabView(part1);
|
||||
}
|
||||
|
||||
// PART 1:
|
||||
// 1. Create a new tab (called newTab)
|
||||
// 2. Orphan it. Activate this orphan tab.
|
||||
// 3. Zoom into it.
|
||||
function part1(win) {
|
||||
ok(win.TabView.isVisible(), "Tab View is visible");
|
||||
|
||||
let contentWindow = win.document.getElementById("tab-view").contentWindow;
|
||||
is(win.gBrowser.tabs.length, 1, "In the beginning, there was one tab.");
|
||||
let [originalTab] = win.gBrowser.visibleTabs;
|
||||
let originalGroup = contentWindow.GroupItems.getActiveGroupItem();
|
||||
ok(originalGroup.getChildren().some(function(child) {
|
||||
return child == originalTab._tabViewTabItem;
|
||||
}),"The current active group is the one with the original tab in it.");
|
||||
|
||||
// Create a new tab and orphan it
|
||||
let newTab = win.gBrowser.loadOneTab("about:mozilla", {inBackground: true});
|
||||
|
||||
let newTabItem = newTab._tabViewTabItem;
|
||||
ok(originalGroup.getChildren().some(function(child) child == newTabItem),"The new tab was made in the current group");
|
||||
contentWindow.GroupItems.getActiveGroupItem().remove(newTabItem);
|
||||
ok(!originalGroup.getChildren().some(function(child) child == newTabItem),"The new tab was orphaned");
|
||||
newTabItem.pushAway();
|
||||
// activate this tab item
|
||||
contentWindow.UI.setActive(newTabItem);
|
||||
|
||||
// PART 2: close this orphan tab (newTab)
|
||||
let part2 = function part2() {
|
||||
win.removeEventListener("tabviewhidden", part2, false);
|
||||
|
||||
is(win.gBrowser.selectedTab, newTab, "We zoomed into that new tab.");
|
||||
ok(!win.TabView.isVisible(), "Tab View is hidden, because we're looking at the new tab");
|
||||
|
||||
newTab.addEventListener("TabClose", function() {
|
||||
newTab.removeEventListener("TabClose", arguments.callee, false);
|
||||
|
||||
win.addEventListener("tabviewshown", part3, false);
|
||||
executeSoon(function() { win.TabView.toggle(); });
|
||||
}, false);
|
||||
win.gBrowser.removeTab(newTab);
|
||||
}
|
||||
|
||||
let secondNewTab;
|
||||
// PART 3: now back in Panorama, open a new tab via the "new tab" menu item (or equivalent)
|
||||
// We call this secondNewTab.
|
||||
let part3 = function part3() {
|
||||
win.removeEventListener("tabviewshown", part3, false);
|
||||
|
||||
ok(win.TabView.isVisible(), "Tab View is visible.");
|
||||
|
||||
is(win.gBrowser.tabs.length, 1, "Only one tab again.");
|
||||
is(win.gBrowser.tabs[0], originalTab, "That one tab is the original tab.");
|
||||
|
||||
let groupItems = contentWindow.GroupItems.groupItems;
|
||||
is(groupItems.length, 1, "Only one group");
|
||||
|
||||
ok(!contentWindow.UI.getActiveOrphanTab(), "There is no active orphan tab.");
|
||||
ok(win.TabView.isVisible(), "Tab View is visible.");
|
||||
|
||||
whenTabViewIsHidden(part4, win);
|
||||
win.document.getElementById("cmd_newNavigatorTab").doCommand();
|
||||
}
|
||||
|
||||
// PART 4: verify it opened in the original group, and go back into Panorama
|
||||
let part4 = function part4() {
|
||||
ok(!win.TabView.isVisible(), "Tab View is hidden");
|
||||
|
||||
is(win.gBrowser.tabs.length, 2, "There are two tabs total now.");
|
||||
is(win.gBrowser.visibleTabs.length, 2, "We're looking at both of them.");
|
||||
|
||||
let foundOriginalTab = false;
|
||||
// we can't use forEach because win.gBrowser.tabs is only array-like.
|
||||
for (let i = 0; i < win.gBrowser.tabs.length; i++) {
|
||||
let tab = win.gBrowser.tabs[i];
|
||||
if (tab === originalTab)
|
||||
foundOriginalTab = true;
|
||||
else
|
||||
secondNewTab = tab;
|
||||
}
|
||||
ok(foundOriginalTab, "One of those tabs is the original tab.");
|
||||
ok(secondNewTab, "We found another tab... this is secondNewTab");
|
||||
|
||||
is(win.gBrowser.selectedTab, secondNewTab, "This second new tab is what we're looking at.");
|
||||
|
||||
win.addEventListener("tabviewshown", part5, false);
|
||||
win.TabView.toggle();
|
||||
}
|
||||
|
||||
// PART 5: make sure we only have one group with both tabs now, and finish.
|
||||
let part5 = function part5() {
|
||||
win.removeEventListener("tabviewshown", part5, false);
|
||||
|
||||
is(win.gBrowser.tabs.length, 2, "There are of course still two tabs.");
|
||||
|
||||
let groupItems = contentWindow.GroupItems.groupItems;
|
||||
is(groupItems.length, 1, "There is one group now");
|
||||
is(groupItems[0], originalGroup, "It's the original group.");
|
||||
is(originalGroup.getChildren().length, 2, "It has two children.");
|
||||
|
||||
// finish!
|
||||
win.close();
|
||||
finish();
|
||||
}
|
||||
|
||||
// Okay, all set up now. Let's get this party started!
|
||||
afterAllTabItemsUpdated(function() {
|
||||
win.addEventListener("tabviewhidden", part2, false);
|
||||
win.TabView.toggle();
|
||||
}, win);
|
||||
}
|
@ -41,6 +41,20 @@ function test() {
|
||||
return createTab('about:blank');
|
||||
}
|
||||
|
||||
let restoreTab = function (callback) {
|
||||
let tab = undoCloseTab(0);
|
||||
|
||||
if (tab._tabViewTabItem._reconnected) {
|
||||
afterAllTabsLoaded(callback);
|
||||
return;
|
||||
}
|
||||
|
||||
tab._tabViewTabItem.addSubscriber(tab, 'reconnected', function () {
|
||||
tab._tabViewTabItem.removeSubscriber(tab, 'reconnected');
|
||||
afterAllTabsLoaded(callback);
|
||||
});
|
||||
}
|
||||
|
||||
let finishTest = function () {
|
||||
prefix = 'finish';
|
||||
assertValidPrerequisites();
|
||||
|
@ -33,10 +33,13 @@ function test() {
|
||||
ok(!document.getElementById("context_closeTab").disabled, "The 'Close tab' menu item is enabled");
|
||||
ok(!document.getElementById("context_openTabInWindow").disabled, "The 'Move to New Window' menu item is enabled");
|
||||
|
||||
let newTabTwo = gBrowser.selectedTab;
|
||||
gBrowser.selected = originalTab;
|
||||
gBrowser.removeTab(newTabOne);
|
||||
|
||||
closeGroupItem(newGroup, finish);
|
||||
gBrowser.removeTab(newTabOne);
|
||||
gBrowser.removeTab(newTabTwo);
|
||||
|
||||
finish();
|
||||
});
|
||||
let newGroup = contentWindow.GroupItems.newGroup();
|
||||
newGroup.newTab();
|
||||
|
@ -9,23 +9,6 @@ function test() {
|
||||
return cw.GroupItems.groupItems[index];
|
||||
}
|
||||
|
||||
let createOrphan = function (callback) {
|
||||
let tab = win.gBrowser.loadOneTab('about:blank', {inBackground: true});
|
||||
afterAllTabsLoaded(function () {
|
||||
let tabItem = tab._tabViewTabItem;
|
||||
tabItem.parent.remove(tabItem);
|
||||
callback(tabItem);
|
||||
});
|
||||
}
|
||||
|
||||
let hideGroupItem = function (groupItem, callback) {
|
||||
groupItem.addSubscriber(groupItem, 'groupHidden', function () {
|
||||
groupItem.removeSubscriber(groupItem, 'groupHidden');
|
||||
callback();
|
||||
});
|
||||
groupItem.closeAll();
|
||||
}
|
||||
|
||||
let newWindow = function (test) {
|
||||
newWindowWithTabView(function (tvwin) {
|
||||
registerCleanupFunction(function () {
|
||||
@ -35,6 +18,11 @@ function test() {
|
||||
|
||||
win = tvwin;
|
||||
cw = win.TabView.getContentWindow();
|
||||
|
||||
// setup group items
|
||||
getGroupItem(0).setSize(200, 200, true);
|
||||
createGroupItemWithBlankTabs(win, 200, 200, 300, 1);
|
||||
|
||||
test();
|
||||
});
|
||||
}
|
||||
@ -45,31 +33,11 @@ function test() {
|
||||
}
|
||||
|
||||
let testDragOnHiddenGroup = function () {
|
||||
createOrphan(function (orphan) {
|
||||
let groupItem = getGroupItem(0);
|
||||
hideGroupItem(groupItem, function () {
|
||||
let drag = orphan.container;
|
||||
let drop = groupItem.$undoContainer[0];
|
||||
let groupItem = getGroupItem(1);
|
||||
|
||||
assertNumberOfTabsInGroupItem(groupItem, 1);
|
||||
|
||||
EventUtils.synthesizeMouseAtCenter(drag, {type: 'mousedown'}, cw);
|
||||
EventUtils.synthesizeMouseAtCenter(drop, {type: 'mousemove'}, cw);
|
||||
EventUtils.synthesizeMouseAtCenter(drop, {type: 'mouseup'}, cw);
|
||||
|
||||
assertNumberOfTabsInGroupItem(groupItem, 1);
|
||||
|
||||
win.close();
|
||||
newWindow(testDragOnVisibleGroup);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
let testDragOnVisibleGroup = function () {
|
||||
createOrphan(function (orphan) {
|
||||
let groupItem = getGroupItem(0);
|
||||
let drag = orphan.container;
|
||||
let drop = groupItem.container;
|
||||
hideGroupItem(groupItem, function () {
|
||||
let drag = groupItem.getChild(0).container;
|
||||
let drop = groupItem.$undoContainer[0];
|
||||
|
||||
assertNumberOfTabsInGroupItem(groupItem, 1);
|
||||
|
||||
@ -77,13 +45,30 @@ function test() {
|
||||
EventUtils.synthesizeMouseAtCenter(drop, {type: 'mousemove'}, cw);
|
||||
EventUtils.synthesizeMouseAtCenter(drop, {type: 'mouseup'}, cw);
|
||||
|
||||
assertNumberOfTabsInGroupItem(groupItem, 2);
|
||||
assertNumberOfTabsInGroupItem(groupItem, 1);
|
||||
|
||||
win.close();
|
||||
finish();
|
||||
newWindow(testDragOnVisibleGroup);
|
||||
});
|
||||
}
|
||||
|
||||
let testDragOnVisibleGroup = function () {
|
||||
let groupItem = getGroupItem(0);
|
||||
let drag = getGroupItem(1).getChild(0).container;
|
||||
let drop = groupItem.container;
|
||||
|
||||
assertNumberOfTabsInGroupItem(groupItem, 1);
|
||||
|
||||
EventUtils.synthesizeMouseAtCenter(drag, {type: 'mousedown'}, cw);
|
||||
EventUtils.synthesizeMouseAtCenter(drop, {type: 'mousemove'}, cw);
|
||||
EventUtils.synthesizeMouseAtCenter(drop, {type: 'mouseup'}, cw);
|
||||
|
||||
assertNumberOfTabsInGroupItem(groupItem, 2);
|
||||
|
||||
win.close();
|
||||
finish();
|
||||
}
|
||||
|
||||
waitForExplicitFinish();
|
||||
newWindow(testDragOnHiddenGroup);
|
||||
}
|
||||
|
@ -39,9 +39,7 @@ function test() {
|
||||
synthesizeMiddleMouseDrag(tabContainer, 10);
|
||||
ok(!groupItem.getChild(0), 'tabItem was closed');
|
||||
|
||||
closeGroupItem(groupItem, function () {
|
||||
hideTabView(finish);
|
||||
});
|
||||
hideTabView(finish);
|
||||
}
|
||||
|
||||
waitForExplicitFinish();
|
||||
|
@ -25,25 +25,20 @@ function onTabViewWindowLoaded(win) {
|
||||
|
||||
is(group.getChildren().length, 1, "The group has one child now.");
|
||||
let tab = group.getChild(0);
|
||||
|
||||
function finalize() {
|
||||
is(contentWindow.GroupItems.getActiveGroupItem(), originalGroup,
|
||||
"The original group is active.");
|
||||
is(contentWindow.UI.getActiveTab(), originalTab._tabViewTabItem,
|
||||
"The original tab is active");
|
||||
|
||||
callback();
|
||||
}
|
||||
|
||||
|
||||
function check() {
|
||||
if (groupOrTab == 'group') {
|
||||
group.removeSubscriber(group, "groupHidden", check);
|
||||
group.closeHidden();
|
||||
finalize();
|
||||
} else {
|
||||
} else
|
||||
tab.removeSubscriber(tab, "tabRemoved", check);
|
||||
closeGroupItem(group, finalize);
|
||||
}
|
||||
|
||||
is(contentWindow.GroupItems.getActiveGroupItem(), originalGroup,
|
||||
"The original group is active.");
|
||||
is(contentWindow.UI.getActiveTab(), originalTab._tabViewTabItem,
|
||||
"The original tab is active");
|
||||
|
||||
callback();
|
||||
}
|
||||
|
||||
if (groupOrTab == 'group') {
|
||||
@ -63,4 +58,4 @@ function onTabViewWindowLoaded(win) {
|
||||
finish();
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
@ -25,6 +25,20 @@ function test() {
|
||||
return cw.GroupItems.groupItems[index];
|
||||
}
|
||||
|
||||
let restoreTab = function (callback) {
|
||||
let tab = undoCloseTab(0);
|
||||
|
||||
if (tab._tabViewTabItem._reconnected) {
|
||||
callback();
|
||||
return;
|
||||
}
|
||||
|
||||
tab._tabViewTabItem.addSubscriber(tab, 'reconnected', function () {
|
||||
tab._tabViewTabItem.removeSubscriber(tab, 'reconnected');
|
||||
afterAllTabsLoaded(callback);
|
||||
});
|
||||
}
|
||||
|
||||
let activateFirstGroupItem = function () {
|
||||
let activeTabItem = getGroupItem(0).getChild(0);
|
||||
cw.GroupItems.updateActiveGroupItemAndTabBar(activeTabItem);
|
||||
@ -77,7 +91,9 @@ function test() {
|
||||
assertNumberOfTabsInGroup(groupItem, 2);
|
||||
|
||||
activateFirstGroupItem();
|
||||
closeGroupItem(groupItem, finishTest);
|
||||
gBrowser.removeTab(gBrowser.tabs[1]);
|
||||
gBrowser.removeTab(gBrowser.tabs[1]);
|
||||
finishTest();
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -33,21 +33,26 @@ function test() {
|
||||
|
||||
EventUtils.synthesizeMouseAtCenter(container, {type: "mouseup"}, cw);
|
||||
ok(aspectRange.contains(getTabItemAspect(tabItem)), "tabItem's aspect is correct");
|
||||
|
||||
tabItem.close();
|
||||
}
|
||||
|
||||
let testDragOutOfStackedGroup = function () {
|
||||
dragTabItem();
|
||||
testDragOutOfExpandedStackedGroup();
|
||||
|
||||
let secondGroup = cw.GroupItems.groupItems[1];
|
||||
closeGroupItem(secondGroup, testDragOutOfExpandedStackedGroup);
|
||||
}
|
||||
|
||||
let testDragOutOfExpandedStackedGroup = function () {
|
||||
groupItem.addSubscriber(groupItem, "expanded", function () {
|
||||
groupItem.removeSubscriber(groupItem, "expanded");
|
||||
|
||||
dragTabItem();
|
||||
closeGroupItem(groupItem, function () hideTabView(finishTest));
|
||||
});
|
||||
|
||||
groupItem.addSubscriber(groupItem, "collapsed", function () {
|
||||
groupItem.removeSubscriber(groupItem, "collapsed");
|
||||
|
||||
let secondGroup = cw.GroupItems.groupItems[1];
|
||||
closeGroupItem(secondGroup, function () hideTabView(finishTest));
|
||||
});
|
||||
|
||||
groupItem.expand();
|
||||
@ -64,14 +69,17 @@ function test() {
|
||||
waitForExplicitFinish();
|
||||
|
||||
newWindowWithTabView(function (win) {
|
||||
registerCleanupFunction(function () {
|
||||
if (!win.closed)
|
||||
win.close();
|
||||
});
|
||||
registerCleanupFunction(function () win.close());
|
||||
|
||||
cw = win.TabView.getContentWindow();
|
||||
groupItem = createGroupItemWithBlankTabs(win, 200, 200, 10, 10);
|
||||
|
||||
groupItem = cw.GroupItems.groupItems[0];
|
||||
groupItem.setSize(200, 200, true);
|
||||
|
||||
for (let i = 0; i < 9; i++)
|
||||
win.gBrowser.addTab();
|
||||
|
||||
ok(groupItem.isStacked(), "groupItem is stacked");
|
||||
testDragOutOfStackedGroup();
|
||||
});
|
||||
}
|
||||
|
@ -1,31 +0,0 @@
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
function test() {
|
||||
waitForExplicitFinish();
|
||||
|
||||
newWindowWithTabView(function (win) {
|
||||
registerCleanupFunction(function () {
|
||||
if (!win.closed)
|
||||
win.close();
|
||||
});
|
||||
|
||||
let tabItem = win.gBrowser.tabs[0]._tabViewTabItem;
|
||||
tabItem.parent.remove(tabItem);
|
||||
|
||||
let cw = win.TabView.getContentWindow();
|
||||
let container = cw.iQ(tabItem.container);
|
||||
let expander = cw.iQ('.expander', container);
|
||||
|
||||
let bounds = container.bounds();
|
||||
let halfWidth = bounds.width / 2;
|
||||
let halfHeight = bounds.height / 2;
|
||||
|
||||
let rect = new cw.Rect(bounds.left + halfWidth, bounds.top + halfHeight,
|
||||
halfWidth, halfHeight);
|
||||
ok(rect.contains(expander.bounds()), "expander is in the tabItem's bottom-right corner");
|
||||
|
||||
win.close();
|
||||
finish();
|
||||
});
|
||||
}
|
@ -17,19 +17,6 @@ function test() {
|
||||
return groupItem;
|
||||
}
|
||||
|
||||
let createOrphan = function () {
|
||||
let tab = gBrowser.loadOneTab('about:blank', {inBackground: true});
|
||||
registerCleanupFunction(function () {
|
||||
if (gBrowser.tabs.length > 1)
|
||||
gBrowser.removeTab(gBrowser.tabs[1])
|
||||
});
|
||||
|
||||
let tabItem = tab._tabViewTabItem;
|
||||
tabItem.parent.remove(tabItem);
|
||||
|
||||
return tabItem;
|
||||
}
|
||||
|
||||
let testSingleGroupItem = function () {
|
||||
let groupItem = cw.GroupItems.groupItems[0];
|
||||
is(cw.GroupItems.getActiveGroupItem(), groupItem, "groupItem is active");
|
||||
@ -38,9 +25,8 @@ function test() {
|
||||
is(cw.UI.getActiveTab(), tabItem, "tabItem is active");
|
||||
|
||||
hideGroupItem(groupItem, function () {
|
||||
is(cw.GroupItems.getActiveGroupItem(), null, "groupItem is not active");
|
||||
unhideGroupItem(groupItem, function () {
|
||||
is(cw.GroupItems.getActiveGroupItem(), groupItem, "groupItem is active again");
|
||||
is(cw.GroupItems.getActiveGroupItem(), groupItem, "groupItem is still active");
|
||||
is(cw.UI.getActiveTab(), tabItem, "tabItem is still active");
|
||||
next();
|
||||
});
|
||||
@ -63,22 +49,7 @@ function test() {
|
||||
});
|
||||
}
|
||||
|
||||
let testOrphanTab = function () {
|
||||
let groupItem = cw.GroupItems.groupItems[0];
|
||||
let tabItem = groupItem.getChild(0);
|
||||
let tabItem2 = createOrphan();
|
||||
|
||||
hideGroupItem(groupItem, function () {
|
||||
is(cw.UI.getActiveTab(), tabItem2, "tabItem2 is active");
|
||||
unhideGroupItem(groupItem, function () {
|
||||
cw.UI.setActive(tabItem);
|
||||
tabItem2.close();
|
||||
next();
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
let tests = [testSingleGroupItem, testTwoGroupItems, testOrphanTab];
|
||||
let tests = [testSingleGroupItem, testTwoGroupItems];
|
||||
|
||||
let next = function () {
|
||||
let test = tests.shift();
|
||||
|
@ -1,8 +1,6 @@
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
const ss = Cc["@mozilla.org/browser/sessionstore;1"].getService(Ci.nsISessionStore);
|
||||
|
||||
let state = {
|
||||
windows: [{
|
||||
tabs: [{
|
||||
|
@ -1,83 +0,0 @@
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
/* Orphans a non-blank tab, duplicates it and checks whether a new group is created with two tabs.
|
||||
* The original one should be the first tab of the new group.
|
||||
*
|
||||
* This prevents overlaid tabs in Tab View (only one tab appears to be there).
|
||||
* In addition, as only one active orphaned tab is shown when Tab View is hidden
|
||||
* and there are two tabs shown after the duplication, it also prevents
|
||||
* the inactive tab to suddenly disappear when toggling Tab View twice.
|
||||
*
|
||||
* Covers:
|
||||
* Bug 645653 - Middle-click on reload button to duplicate orphan tabs does not create a group
|
||||
* Bug 643119 - Ctrl+Drag to duplicate does not work for orphaned tabs
|
||||
* ... (and any other way of duplicating a non-blank orphaned tab).
|
||||
*
|
||||
* See tabitems.js::_reconnect() for the fix.
|
||||
*
|
||||
* Miguel Ojeda <miguel.ojeda.sandonis@gmail.com>
|
||||
*/
|
||||
|
||||
function loadedAboutMozilla(tab) {
|
||||
return tab.linkedBrowser.contentDocument.getElementById('moztext');
|
||||
}
|
||||
|
||||
function test() {
|
||||
waitForExplicitFinish();
|
||||
showTabView(function() {
|
||||
ok(TabView.isVisible(), "Tab View is visible");
|
||||
|
||||
let contentWindow = TabView.getContentWindow();
|
||||
is(contentWindow.GroupItems.groupItems.length, 1, "There is one group item on startup.");
|
||||
|
||||
let originalGroupItem = contentWindow.GroupItems.groupItems[0];
|
||||
is(originalGroupItem.getChildren().length, 1, "There is one tab item in that group.");
|
||||
|
||||
let originalTabItem = originalGroupItem.getChild(0);
|
||||
ok(originalTabItem, "The tabitem has been found.");
|
||||
|
||||
// close the group => orphan the tab
|
||||
originalGroupItem.close();
|
||||
contentWindow.UI.setActive(originalGroupItem);
|
||||
is(contentWindow.GroupItems.groupItems.length, 0, "There are not any groups now.");
|
||||
|
||||
ok(TabView.isVisible(), "Tab View is still shown.");
|
||||
|
||||
hideTabView(function() {
|
||||
ok(!TabView.isVisible(), "Tab View is not shown anymore.");
|
||||
|
||||
// load a non-blank page
|
||||
loadURI('about:mozilla');
|
||||
|
||||
afterAllTabsLoaded(function() {
|
||||
ok(loadedAboutMozilla(originalTabItem.tab), "The original tab loaded about:mozilla.");
|
||||
|
||||
// duplicate it
|
||||
duplicateTabIn(originalTabItem.tab, "tabshift");
|
||||
|
||||
afterAllTabsLoaded(function() {
|
||||
// check
|
||||
is(gBrowser.selectedTab, originalTabItem.tab, "The selected tab is the original one.");
|
||||
is(contentWindow.GroupItems.groupItems.length, 1, "There is one group item again.");
|
||||
let groupItem = contentWindow.GroupItems.groupItems[0];
|
||||
is(groupItem.getChildren().length, 2, "There are two tab items in that group.");
|
||||
is(originalTabItem, groupItem.getChild(0), "The first tab item in the group is the original one.");
|
||||
let otherTab = groupItem.getChild(1);
|
||||
ok(loadedAboutMozilla(otherTab.tab), "The other tab loaded about:mozilla.");
|
||||
|
||||
// clean up
|
||||
gBrowser.removeTab(otherTab.tab);
|
||||
is(contentWindow.GroupItems.groupItems.length, 1, "There is one group item after closing the second tab.");
|
||||
is(groupItem.getChildren().length, 1, "There is only one tab item after closing the second tab.");
|
||||
is(originalTabItem, groupItem.getChild(0), "The first tab item in the group is still the original one.");
|
||||
loadURI("about:blank");
|
||||
afterAllTabsLoaded(function() {
|
||||
finish();
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
|
@ -53,20 +53,10 @@ function testScenarios(win) {
|
||||
is(cw.GroupItems.getActiveGroupItem(), groupItem2, "second groupItem is active");
|
||||
is(cw.UI.getActiveTab(), tabItem, "second groupItem's third tab is active");
|
||||
|
||||
// create orphan
|
||||
// drag tab out of group
|
||||
tabItem = groupItem2.getChild(0);
|
||||
dragOutOfGroup(tabItem.container);
|
||||
|
||||
// move orphan
|
||||
cw.UI.setActive(groupItem2);
|
||||
simulateDragDrop(tabItem.container);
|
||||
assertActiveOrphan(tabItem);
|
||||
|
||||
// resize orphan
|
||||
cw.UI.setActive(groupItem2);
|
||||
let $resizer = cw.iQ('.iq-resizable-handle', tabItem.container);
|
||||
simulateDragDrop($resizer[0]);
|
||||
assertActiveOrphan(tabItem);
|
||||
is(cw.UI.getActiveTab(), tabItem, "the dragged tab is active");
|
||||
|
||||
// drag back into group
|
||||
dragIntoGroup(tabItem.container);
|
||||
|
@ -0,0 +1,63 @@
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
let state = {
|
||||
windows: [{
|
||||
tabs: [{
|
||||
entries: [{ url: "about:home" }],
|
||||
hidden: true,
|
||||
extData: {"tabview-tab": '{"url":"about:home","groupID":1,"bounds":{"left":20,"top":20,"width":20,"height":20}}'}
|
||||
},{
|
||||
entries: [{ url: "about:home" }],
|
||||
hidden: false,
|
||||
// this is an existing orphan tab from a previous Fx version and we want
|
||||
// to make sure this gets transformed into a group
|
||||
extData: {"tabview-tab": '{"url":"about:home","groupID":0,"bounds":{"left":300,"top":300,"width":200,"height":200}}'},
|
||||
}],
|
||||
selected: 2,
|
||||
extData: {
|
||||
"tabview-groups": '{"nextID":3,"activeGroupId":1}',
|
||||
"tabview-group":
|
||||
'{"1":{"bounds":{"left":20,"top":20,"width":200,"height":200},"id":1}}'
|
||||
}
|
||||
}]
|
||||
};
|
||||
|
||||
function test() {
|
||||
waitForExplicitFinish();
|
||||
|
||||
newWindowWithState(state, function (win) {
|
||||
registerCleanupFunction(function () win.close());
|
||||
|
||||
showTabView(function () {
|
||||
let cw = win.TabView.getContentWindow();
|
||||
let groupItems = cw.GroupItems.groupItems;
|
||||
is(groupItems.length, 2, "two groupItems");
|
||||
|
||||
let [group1, group2] = groupItems;
|
||||
|
||||
let bounds1 = new cw.Rect(20, 20, 200, 200);
|
||||
ok(bounds1.equals(group1.getBounds()), "bounds for group1 are correct");
|
||||
|
||||
let bounds2 = new cw.Rect(300, 300, 200, 200);
|
||||
ok(bounds2.equals(group2.getBounds()), "bounds for group2 are correct");
|
||||
|
||||
cw.UI.setActive(group2);
|
||||
win.gBrowser.loadOneTab("about:blank", {inBackground: true});
|
||||
|
||||
let tabItem = group2.getChild(0);
|
||||
let target = tabItem.container;
|
||||
|
||||
EventUtils.synthesizeMouse(target, 10, 10, {type: 'mousedown'}, cw);
|
||||
EventUtils.synthesizeMouse(target, 20, -200, {type: 'mousemove'}, cw);
|
||||
EventUtils.synthesizeMouse(target, 10, 10, {type: 'mouseup'}, cw);
|
||||
|
||||
is(groupItems.length, 3, "three groupItems");
|
||||
|
||||
let latestGroup = groupItems[groupItems.length - 1];
|
||||
is(tabItem, latestGroup.getChild(0), "dragged tab has its own groupItem");
|
||||
|
||||
finish();
|
||||
}, win);
|
||||
});
|
||||
}
|
@ -0,0 +1,88 @@
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
function test() {
|
||||
let win, cw, groupItem;
|
||||
|
||||
function checkNumberOfGroupItems(num) {
|
||||
is(cw.GroupItems.groupItems.length, num, "there are " + num + " groupItems");
|
||||
}
|
||||
|
||||
function next() {
|
||||
if (tests.length)
|
||||
tests.shift()();
|
||||
else
|
||||
finish();
|
||||
}
|
||||
|
||||
// Empty groups should not be closed when toggling Panorama on and off.
|
||||
function test1() {
|
||||
hideTabView(function () {
|
||||
showTabView(function () {
|
||||
checkNumberOfGroupItems(2);
|
||||
next();
|
||||
}, win);
|
||||
}, win);
|
||||
}
|
||||
|
||||
// Groups should not be closed when their last tab is closed outside of Panorama.
|
||||
function test2() {
|
||||
whenTabViewIsHidden(function () {
|
||||
whenTabViewIsShown(function () {
|
||||
checkNumberOfGroupItems(2);
|
||||
next();
|
||||
}, win);
|
||||
|
||||
win.gBrowser.removeTab(win.gBrowser.selectedTab);
|
||||
}, win);
|
||||
|
||||
groupItem.newTab();
|
||||
}
|
||||
|
||||
// Groups should be closed when their last tab is closed.
|
||||
function test3() {
|
||||
whenTabViewIsHidden(function () {
|
||||
showTabView(function () {
|
||||
let tab = win.gBrowser.tabs[1];
|
||||
tab._tabViewTabItem.close();
|
||||
checkNumberOfGroupItems(1);
|
||||
next();
|
||||
}, win);
|
||||
}, win);
|
||||
|
||||
win.gBrowser.addTab();
|
||||
}
|
||||
|
||||
// Groups should be closed when their last tab is dragged out.
|
||||
function test4() {
|
||||
groupItem = createGroupItemWithBlankTabs(win, 200, 200, 20, 1);
|
||||
checkNumberOfGroupItems(2);
|
||||
|
||||
let tab = win.gBrowser.tabs[1];
|
||||
let target = tab._tabViewTabItem.container;
|
||||
|
||||
waitForFocus(function () {
|
||||
EventUtils.synthesizeMouseAtCenter(target, {type: "mousedown"}, cw);
|
||||
EventUtils.synthesizeMouse(target, 600, 5, {type: "mousemove"}, cw);
|
||||
EventUtils.synthesizeMouse(target, 600, 5, {type: "mouseup"}, cw);
|
||||
|
||||
checkNumberOfGroupItems(2);
|
||||
next();
|
||||
}, win);
|
||||
}
|
||||
|
||||
let tests = [test1, test2, test3, test4];
|
||||
|
||||
waitForExplicitFinish();
|
||||
|
||||
newWindowWithTabView(function (aWin) {
|
||||
registerCleanupFunction(function () aWin.close());
|
||||
|
||||
win = aWin;
|
||||
cw = win.TabView.getContentWindow();
|
||||
groupItem = createEmptyGroupItem(cw, 200, 200, 20);
|
||||
|
||||
checkNumberOfGroupItems(2);
|
||||
next();
|
||||
});
|
||||
}
|
@ -85,7 +85,7 @@ function addTest(contentWindow, groupOneId, groupTwoId, originalTab) {
|
||||
};
|
||||
groupTwo.addSubscriber(groupTwo, "close", function() {
|
||||
groupTwo.removeSubscriber(groupTwo, "close");
|
||||
closeGroupItem(groupOne, finish);
|
||||
finish();
|
||||
});
|
||||
window.addEventListener("tabviewhidden", onTabViewHidden, false);
|
||||
gBrowser.selectedTab = originalTab;
|
||||
|
@ -40,10 +40,6 @@ function checkFirstRun(win) {
|
||||
is(groupItems.length, 1, "There should be one group");
|
||||
is(groupItems[0].getChildren().length, 1, "...with one child");
|
||||
|
||||
let orphanTabCount = contentWindow.GroupItems.getOrphanedTabs().length;
|
||||
// Welcome tab disabled by bug 626754. To be fixed via bug 626926.
|
||||
is(orphanTabCount, 0, "There should also be no orphaned tabs");
|
||||
|
||||
ok(!experienced(), "we're not experienced");
|
||||
}
|
||||
|
||||
@ -55,9 +51,6 @@ function checkNotFirstRun(win) {
|
||||
let groupItems = contentWindow.GroupItems.groupItems;
|
||||
is(groupItems.length, 1, "There should be one group");
|
||||
is(groupItems[0].getChildren().length, 1, "...with one child");
|
||||
|
||||
let orphanTabCount = contentWindow.GroupItems.getOrphanedTabs().length;
|
||||
is(orphanTabCount, 0, "There should also be no orphaned tabs");
|
||||
}
|
||||
|
||||
function endGame() {
|
||||
|
@ -95,7 +95,7 @@ function testGroupItemWithTabItem(contentWindow) {
|
||||
let endGame = function() {
|
||||
window.removeEventListener("tabviewhidden", endGame, false);
|
||||
ok(!TabView.isVisible(), "Tab View is hidden");
|
||||
closeGroupItem(groupItem, finish);
|
||||
finish();
|
||||
};
|
||||
window.addEventListener("tabviewhidden", endGame, false);
|
||||
|
||||
|
@ -1,83 +1,57 @@
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
let tabViewShownCount = 0;
|
||||
let timerId;
|
||||
let newWin;
|
||||
|
||||
// ----------
|
||||
function test() {
|
||||
waitForExplicitFinish();
|
||||
|
||||
// verify initial state
|
||||
ok(!TabView.isVisible(), "Tab View starts hidden");
|
||||
|
||||
// launch tab view for the first time
|
||||
window.addEventListener("tabviewshown", onTabViewLoadedAndShown, false);
|
||||
TabView.toggle();
|
||||
newWindowWithTabView(function() {}, function(win) {
|
||||
newWin = win;
|
||||
|
||||
let onSelect = function(event) {
|
||||
if (deck != event.target)
|
||||
return;
|
||||
|
||||
let iframe = win.document.getElementById("tab-view");
|
||||
if (deck.selectedPanel != iframe)
|
||||
return;
|
||||
|
||||
deck.removeEventListener("select", onSelect, true);
|
||||
|
||||
whenTabViewIsShown(function() {
|
||||
executeSoon(function() {
|
||||
testMethodToHideAndShowTabView(function() {
|
||||
newWin.document.getElementById("menu_tabview").doCommand();
|
||||
}, function() {
|
||||
testMethodToHideAndShowTabView(function() {
|
||||
EventUtils.synthesizeKey("E", { accelKey: true, shiftKey: true }, newWin);
|
||||
}, finish);
|
||||
});
|
||||
});
|
||||
}, win);
|
||||
};
|
||||
|
||||
let deck = win.document.getElementById("tab-view-deck");
|
||||
deck.addEventListener("select", onSelect, true);
|
||||
});
|
||||
|
||||
registerCleanupFunction(function () {
|
||||
window.removeEventListener("tabviewshown", onTabViewLoadedAndShown, false);
|
||||
if (timerId)
|
||||
clearTimeout(timerId);
|
||||
TabView.hide()
|
||||
newWin.close();
|
||||
});
|
||||
}
|
||||
|
||||
// ----------
|
||||
function onTabViewLoadedAndShown() {
|
||||
window.removeEventListener("tabviewshown", onTabViewLoadedAndShown, false);
|
||||
|
||||
// Evidently sometimes isVisible (which is based on the selectedIndex of the
|
||||
// tabview deck) isn't updated immediately when called from button.doCommand,
|
||||
// so we add a little timeout here to get outside of the doCommand call.
|
||||
// If the initial timeout isn't enough, we keep waiting in case it's taking
|
||||
// longer than expected.
|
||||
// See bug 594909.
|
||||
let deck = document.getElementById("tab-view-deck");
|
||||
let iframe = document.getElementById("tab-view");
|
||||
ok(iframe, "The tab view iframe exists");
|
||||
|
||||
function waitForSwitch() {
|
||||
if (deck.selectedPanel == iframe) {
|
||||
ok(TabView.isVisible(), "Tab View is visible. Count: " + tabViewShownCount);
|
||||
tabViewShownCount++;
|
||||
|
||||
// kick off the series
|
||||
window.addEventListener("tabviewshown", onTabViewShown, false);
|
||||
window.addEventListener("tabviewhidden", onTabViewHidden, false);
|
||||
|
||||
registerCleanupFunction(function () {
|
||||
window.removeEventListener("tabviewshown", onTabViewShown, false);
|
||||
window.removeEventListener("tabviewhidden", onTabViewHidden, false);
|
||||
});
|
||||
TabView.toggle();
|
||||
} else {
|
||||
timerId = setTimeout(waitForSwitch, 10);
|
||||
}
|
||||
}
|
||||
|
||||
timerId = setTimeout(waitForSwitch, 1);
|
||||
}
|
||||
|
||||
// ----------
|
||||
function onTabViewShown() {
|
||||
// add the count to the message so we can track things more easily.
|
||||
ok(TabView.isVisible(), "Tab View is visible. Count: " + tabViewShownCount);
|
||||
tabViewShownCount++;
|
||||
TabView.toggle();
|
||||
}
|
||||
|
||||
// ----------
|
||||
function onTabViewHidden() {
|
||||
ok(!TabView.isVisible(), "Tab View is hidden. Count: " + tabViewShownCount);
|
||||
|
||||
if (tabViewShownCount == 1) {
|
||||
document.getElementById("menu_tabview").doCommand();
|
||||
} else if (tabViewShownCount == 2) {
|
||||
EventUtils.synthesizeKey("E", { accelKey: true, shiftKey: true });
|
||||
} else if (tabViewShownCount == 3) {
|
||||
window.removeEventListener("tabviewshown", onTabViewShown, false);
|
||||
window.removeEventListener("tabviewhidden", onTabViewHidden, false);
|
||||
finish();
|
||||
}
|
||||
function testMethodToHideAndShowTabView(executeFunc, callback) {
|
||||
whenTabViewIsHidden(function() {
|
||||
ok(!newWin.TabView.isVisible(), "Tab View is not visible after executing the function");
|
||||
whenTabViewIsShown(function() {
|
||||
ok(newWin.TabView.isVisible(), "Tab View is visible after executing the function again");
|
||||
callback();
|
||||
}, newWin);
|
||||
executeFunc();
|
||||
}, newWin);
|
||||
executeFunc();
|
||||
}
|
||||
|
@ -1,81 +0,0 @@
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
let tabOne;
|
||||
let newWin;
|
||||
|
||||
function test() {
|
||||
waitForExplicitFinish();
|
||||
|
||||
newWindowWithTabView(onTabViewWindowLoaded, function(win) {
|
||||
newWin = win;
|
||||
tabOne = newWin.gBrowser.addTab();
|
||||
});
|
||||
}
|
||||
|
||||
function onTabViewWindowLoaded() {
|
||||
newWin.removeEventListener("tabviewshown", onTabViewWindowLoaded, false);
|
||||
|
||||
ok(newWin.TabView.isVisible(), "Tab View is visible");
|
||||
|
||||
let contentWindow = newWin.document.getElementById("tab-view").contentWindow;
|
||||
|
||||
// 1) the tab should belong to a group, and no orphan tabs
|
||||
ok(tabOne._tabViewTabItem.parent, "Tab one belongs to a group");
|
||||
is(contentWindow.GroupItems.getOrphanedTabs().length, 0, "No orphaned tabs");
|
||||
|
||||
// 2) create a group, add a blank tab
|
||||
let groupItem = createEmptyGroupItem(contentWindow, 300, 300, 200);
|
||||
|
||||
let onTabViewHidden = function() {
|
||||
newWin.removeEventListener("tabviewhidden", onTabViewHidden, false);
|
||||
|
||||
// 3) the new group item should have one child and no orphan tab
|
||||
is(groupItem.getChildren().length, 1, "The group item has an item");
|
||||
is(contentWindow.GroupItems.getOrphanedTabs().length, 0, "No orphaned tabs");
|
||||
|
||||
let checkAndFinish = function() {
|
||||
// 4) check existence of stored group data for tab before finishing
|
||||
let tabData = contentWindow.Storage.getTabData(tabItem.tab, function () {});
|
||||
ok(tabData && contentWindow.TabItems.storageSanity(tabData) && tabData.groupID,
|
||||
"Tab two has stored group data");
|
||||
|
||||
// clean up and finish the test
|
||||
newWin.gBrowser.removeTab(tabOne);
|
||||
newWin.gBrowser.removeTab(tabItem.tab);
|
||||
whenWindowObservesOnce(newWin, "domwindowclosed", function() {
|
||||
finish();
|
||||
});
|
||||
newWin.close();
|
||||
};
|
||||
let tabItem = groupItem.getChild(0);
|
||||
// the item may not be connected so subscriber would be used in that case.
|
||||
if (tabItem._reconnected) {
|
||||
checkAndFinish();
|
||||
} else {
|
||||
tabItem.addSubscriber(tabItem, "reconnected", function() {
|
||||
tabItem.removeSubscriber(tabItem, "reconnected");
|
||||
checkAndFinish();
|
||||
});
|
||||
}
|
||||
};
|
||||
newWin.addEventListener("tabviewhidden", onTabViewHidden, false);
|
||||
|
||||
// click on the + button
|
||||
let newTabButton = groupItem.container.getElementsByClassName("newTabButton");
|
||||
ok(newTabButton[0], "New tab button exists");
|
||||
|
||||
EventUtils.sendMouseEvent({ type: "click" }, newTabButton[0], contentWindow);
|
||||
}
|
||||
|
||||
function whenWindowObservesOnce(win, topic, callback) {
|
||||
let windowWatcher =
|
||||
Cc["@mozilla.org/embedcomp/window-watcher;1"].getService(Ci.nsIWindowWatcher);
|
||||
function windowObserver(subject, topicName, aData) {
|
||||
if (win == subject.QueryInterface(Ci.nsIDOMWindow) && topic == topicName) {
|
||||
windowWatcher.unregisterNotification(windowObserver);
|
||||
callback();
|
||||
}
|
||||
}
|
||||
windowWatcher.registerNotification(windowObserver);
|
||||
}
|
@ -81,19 +81,13 @@ function newWindowWithTabView(shownCallback, loadCallback, width, height) {
|
||||
let win = window.openDialog(getBrowserURL(), "_blank",
|
||||
"chrome,all,dialog=no,height=" + winHeight +
|
||||
",width=" + winWidth);
|
||||
let onLoad = function() {
|
||||
win.removeEventListener("load", onLoad, false);
|
||||
|
||||
whenWindowLoaded(win, function () {
|
||||
if (typeof loadCallback == "function")
|
||||
loadCallback(win);
|
||||
|
||||
let onShown = function() {
|
||||
win.removeEventListener("tabviewshown", onShown, false);
|
||||
shownCallback(win);
|
||||
};
|
||||
win.addEventListener("tabviewshown", onShown, false);
|
||||
win.TabView.toggle();
|
||||
}
|
||||
win.addEventListener("load", onLoad, false);
|
||||
showTabView(function () shownCallback(win), win);
|
||||
});
|
||||
}
|
||||
|
||||
// ----------
|
||||
@ -192,7 +186,7 @@ function whenTabViewIsShown(callback, win) {
|
||||
function showSearch(callback, win) {
|
||||
win = win || window;
|
||||
|
||||
let contentWindow = win.document.getElementById("tab-view").contentWindow;
|
||||
let contentWindow = win.TabView.getContentWindow();
|
||||
if (contentWindow.isSearchEnabled()) {
|
||||
callback();
|
||||
return;
|
||||
@ -206,7 +200,7 @@ function showSearch(callback, win) {
|
||||
function hideSearch(callback, win) {
|
||||
win = win || window;
|
||||
|
||||
let contentWindow = win.document.getElementById("tab-view").contentWindow;
|
||||
let contentWindow = win.TabView.getContentWindow();
|
||||
if (!contentWindow.isSearchEnabled()) {
|
||||
callback();
|
||||
return;
|
||||
@ -220,7 +214,7 @@ function hideSearch(callback, win) {
|
||||
function whenSearchIsEnabled(callback, win) {
|
||||
win = win || window;
|
||||
|
||||
let contentWindow = win.document.getElementById("tab-view").contentWindow;
|
||||
let contentWindow = win.TabView.getContentWindow();
|
||||
if (contentWindow.isSearchEnabled()) {
|
||||
callback();
|
||||
return;
|
||||
@ -236,7 +230,7 @@ function whenSearchIsEnabled(callback, win) {
|
||||
function whenSearchIsDisabled(callback, win) {
|
||||
win = win || window;
|
||||
|
||||
let contentWindow = win.document.getElementById("tab-view").contentWindow;
|
||||
let contentWindow = win.TabView.getContentWindow();
|
||||
if (!contentWindow.isSearchEnabled()) {
|
||||
callback();
|
||||
return;
|
||||
@ -313,21 +307,21 @@ function newWindowWithState(state, callback) {
|
||||
let opts = "chrome,all,dialog=no,height=800,width=800";
|
||||
let win = window.openDialog(getBrowserURL(), "_blank", opts);
|
||||
|
||||
let numConditions = 2;
|
||||
let check = function () {
|
||||
if (!--numConditions)
|
||||
callback(win);
|
||||
};
|
||||
|
||||
whenWindowLoaded(win, function () {
|
||||
whenWindowStateReady(win, function () {
|
||||
afterAllTabsLoaded(check, win);
|
||||
});
|
||||
|
||||
ss.setWindowState(win, JSON.stringify(state), true);
|
||||
whenDelayedStartupFinished(win, check);
|
||||
});
|
||||
|
||||
|
||||
let numConditions = 2;
|
||||
let check = function () {
|
||||
if (!--numConditions)
|
||||
callback(win);
|
||||
};
|
||||
whenDelayedStartupFinished(win, check);
|
||||
}
|
||||
|
||||
// ----------
|
||||
|
@ -1,5 +1,14 @@
|
||||
<svg width="640px" height="480px" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.0">
|
||||
<title>This is a root SVG element's title</title>
|
||||
<foreignObject>
|
||||
<html xmlns="http://www.w3.org/1999/xhtml">
|
||||
<body>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" id="svg1">
|
||||
<title>This is a non-root SVG element title</title>
|
||||
</svg>
|
||||
</body>
|
||||
</html>
|
||||
</foreignObject>
|
||||
<text id="text1" x="10px" y="32px" font-size="24px">
|
||||
This contains only <title>
|
||||
<title>
|
||||
|
Before Width: | Height: | Size: 1.5 KiB After Width: | Height: | Size: 1.8 KiB |
@ -1001,7 +1001,7 @@
|
||||
// undetermined state and then schedule a proper check at the next
|
||||
// opportunity
|
||||
this.setProgress(0, -1);
|
||||
setTimeout(this.updateProgress.bind(this), 0);
|
||||
this._updateProgressTimeout = setTimeout(this.updateProgress.bind(this), 0);
|
||||
]]></constructor>
|
||||
|
||||
<destructor><![CDATA[
|
||||
@ -1028,6 +1028,7 @@
|
||||
this.notification.options.installs.forEach(function(aInstall) {
|
||||
aInstall.removeListener(this);
|
||||
}, this);
|
||||
clearTimeout(this._updateProgressTimeout);
|
||||
]]></body>
|
||||
</method>
|
||||
|
||||
|
Before Width: | Height: | Size: 1.1 KiB After Width: | Height: | Size: 88 KiB |
Before Width: | Height: | Size: 19 KiB After Width: | Height: | Size: 24 KiB |
Before Width: | Height: | Size: 1.8 KiB After Width: | Height: | Size: 974 B |
Before Width: | Height: | Size: 3.5 KiB After Width: | Height: | Size: 2.6 KiB |
Before Width: | Height: | Size: 6.0 KiB After Width: | Height: | Size: 5.3 KiB |
Before Width: | Height: | Size: 22 KiB After Width: | Height: | Size: 289 KiB |
Before Width: | Height: | Size: 355 KiB After Width: | Height: | Size: 289 KiB |
Before Width: | Height: | Size: 27 KiB After Width: | Height: | Size: 26 KiB |
Before Width: | Height: | Size: 1.1 KiB After Width: | Height: | Size: 83 KiB |
Before Width: | Height: | Size: 19 KiB After Width: | Height: | Size: 23 KiB |
Before Width: | Height: | Size: 1.7 KiB After Width: | Height: | Size: 924 B |
Before Width: | Height: | Size: 3.4 KiB After Width: | Height: | Size: 2.5 KiB |
Before Width: | Height: | Size: 5.8 KiB After Width: | Height: | Size: 4.9 KiB |
Before Width: | Height: | Size: 22 KiB After Width: | Height: | Size: 289 KiB |