mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-10 03:45:46 +00:00
Merge mozilla-central to tracemonkey.
This commit is contained in:
commit
5a9450dd7a
@ -848,9 +848,8 @@ getParentCB(AtkObject *aAtkObj)
|
||||
return nsnull;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIAccessible> accParent;
|
||||
nsresult rv = accWrap->GetParent(getter_AddRefs(accParent));
|
||||
if (NS_FAILED(rv) || !accParent)
|
||||
nsAccessible* accParent = accWrap->GetParent();
|
||||
if (!accParent)
|
||||
return nsnull;
|
||||
|
||||
AtkObject *parent = nsAccessibleWrap::GetAtkObject(accParent);
|
||||
@ -868,11 +867,7 @@ getChildCountCB(AtkObject *aAtkObj)
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Links within hypertext accessible play role of accessible children in
|
||||
// ATK since every embedded object is a link and text accessibles are
|
||||
// ignored.
|
||||
nsRefPtr<nsHyperTextAccessible> hyperText = do_QueryObject(accWrap);
|
||||
return hyperText ? hyperText->GetLinkCount() : accWrap->GetChildCount();
|
||||
return accWrap->GetEmbeddedChildCount();
|
||||
}
|
||||
|
||||
AtkObject *
|
||||
@ -888,12 +883,7 @@ refChildCB(AtkObject *aAtkObj, gint aChildIndex)
|
||||
return nsnull;
|
||||
}
|
||||
|
||||
// Links within hypertext accessible play role of accessible children in
|
||||
// ATK since every embedded object is a link and text accessibles are
|
||||
// ignored.
|
||||
nsRefPtr<nsHyperTextAccessible> hyperText = do_QueryObject(accWrap);
|
||||
nsAccessible* accChild = hyperText ? hyperText->GetLinkAt(aChildIndex) :
|
||||
accWrap->GetChildAt(aChildIndex);
|
||||
nsAccessible* accChild = accWrap->GetEmbeddedChildAt(aChildIndex);
|
||||
if (!accChild)
|
||||
return nsnull;
|
||||
|
||||
@ -924,12 +914,7 @@ getIndexInParentCB(AtkObject *aAtkObj)
|
||||
return -1; // No parent
|
||||
}
|
||||
|
||||
// Links within hypertext accessible play role of accessible children in
|
||||
// ATK since every embedded object is a link and text accessibles are
|
||||
// ignored.
|
||||
nsRefPtr<nsHyperTextAccessible> hyperTextParent(do_QueryObject(parent));
|
||||
return hyperTextParent ?
|
||||
hyperTextParent->GetLinkIndex(accWrap) : accWrap->GetIndexInParent();
|
||||
return parent->GetIndexOfEmbeddedChild(accWrap);
|
||||
}
|
||||
|
||||
static void TranslateStates(PRUint32 aState, const AtkStateMap *aStateMap,
|
||||
|
@ -319,9 +319,12 @@ getCharacterExtentsCB(AtkText *aText, gint aOffset,
|
||||
else
|
||||
geckoCoordType = nsIAccessibleCoordinateType::COORDTYPE_WINDOW_RELATIVE;
|
||||
|
||||
nsresult rv = accText->GetCharacterExtents(aOffset, &extX, &extY,
|
||||
&extWidth, &extHeight,
|
||||
geckoCoordType);
|
||||
#ifdef DEBUG
|
||||
nsresult rv =
|
||||
#endif
|
||||
accText->GetCharacterExtents(aOffset, &extX, &extY,
|
||||
&extWidth, &extHeight,
|
||||
geckoCoordType);
|
||||
*aX = extX;
|
||||
*aY = extY;
|
||||
*aWidth = extWidth;
|
||||
@ -353,10 +356,13 @@ getRangeExtentsCB(AtkText *aText, gint aStartOffset, gint aEndOffset,
|
||||
else
|
||||
geckoCoordType = nsIAccessibleCoordinateType::COORDTYPE_WINDOW_RELATIVE;
|
||||
|
||||
nsresult rv = accText->GetRangeExtents(aStartOffset, aEndOffset,
|
||||
&extX, &extY,
|
||||
&extWidth, &extHeight,
|
||||
geckoCoordType);
|
||||
#ifdef DEBUG
|
||||
nsresult rv =
|
||||
#endif
|
||||
accText->GetRangeExtents(aStartOffset, aEndOffset,
|
||||
&extX, &extY,
|
||||
&extWidth, &extHeight,
|
||||
geckoCoordType);
|
||||
aRect->x = extX;
|
||||
aRect->y = extY;
|
||||
aRect->width = extWidth;
|
||||
|
@ -92,7 +92,7 @@ AccCollector::EnsureNGetObject(PRUint32 aIndex)
|
||||
if (!mFilterFunc(child))
|
||||
continue;
|
||||
|
||||
mObjects.AppendElement(child);
|
||||
AppendObject(child);
|
||||
if (mObjects.Length() - 1 == aIndex)
|
||||
return mObjects[aIndex];
|
||||
}
|
||||
@ -109,10 +109,39 @@ AccCollector::EnsureNGetIndex(nsAccessible* aAccessible)
|
||||
if (!mFilterFunc(child))
|
||||
continue;
|
||||
|
||||
mObjects.AppendElement(child);
|
||||
AppendObject(child);
|
||||
if (child == aAccessible)
|
||||
return mObjects.Length() - 1;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
void
|
||||
AccCollector::AppendObject(nsAccessible* aAccessible)
|
||||
{
|
||||
mObjects.AppendElement(aAccessible);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// EmbeddedObjCollector
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
PRInt32
|
||||
EmbeddedObjCollector::GetIndexAt(nsAccessible *aAccessible)
|
||||
{
|
||||
if (aAccessible->mParent != mRoot)
|
||||
return -1;
|
||||
|
||||
if (aAccessible->mIndexOfEmbeddedChild != -1)
|
||||
return aAccessible->mIndexOfEmbeddedChild;
|
||||
|
||||
return mFilterFunc(aAccessible) ? EnsureNGetIndex(aAccessible) : -1;
|
||||
}
|
||||
|
||||
void
|
||||
EmbeddedObjCollector::AppendObject(nsAccessible* aAccessible)
|
||||
{
|
||||
aAccessible->mIndexOfEmbeddedChild = mObjects.Length();
|
||||
mObjects.AppendElement(aAccessible);
|
||||
}
|
||||
|
@ -66,7 +66,7 @@ public:
|
||||
/**
|
||||
* Return index of the given accessible within the collection.
|
||||
*/
|
||||
PRInt32 GetIndexAt(nsAccessible* aAccessible);
|
||||
virtual PRInt32 GetIndexAt(nsAccessible* aAccessible);
|
||||
|
||||
protected:
|
||||
/**
|
||||
@ -79,6 +79,11 @@ protected:
|
||||
*/
|
||||
PRInt32 EnsureNGetIndex(nsAccessible* aAccessible);
|
||||
|
||||
/**
|
||||
* Append the object to collection.
|
||||
*/
|
||||
virtual void AppendObject(nsAccessible* aAccessible);
|
||||
|
||||
filters::FilterFuncPtr mFilterFunc;
|
||||
nsAccessible* mRoot;
|
||||
PRInt32 mRootChildIdx;
|
||||
@ -91,4 +96,26 @@ private:
|
||||
AccCollector& operator =(const AccCollector&);
|
||||
};
|
||||
|
||||
/**
|
||||
* Collect embedded objects. Provide quick access to accessible by index and
|
||||
* vice versa.
|
||||
*/
|
||||
class EmbeddedObjCollector : public AccCollector
|
||||
{
|
||||
public:
|
||||
virtual ~EmbeddedObjCollector() { };
|
||||
|
||||
public:
|
||||
virtual PRInt32 GetIndexAt(nsAccessible* aAccessible);
|
||||
|
||||
protected:
|
||||
// Make sure it's used by nsAccessible class only.
|
||||
EmbeddedObjCollector(nsAccessible* aRoot) :
|
||||
AccCollector(aRoot, filters::GetEmbeddedObject) { }
|
||||
|
||||
virtual void AppendObject(nsAccessible* aAccessible);
|
||||
|
||||
friend class nsAccessible;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
@ -390,10 +390,14 @@ NS_IMPL_ISUPPORTS_INHERITED1(nsAccTextChangeEvent, nsAccEvent,
|
||||
nsAccTextChangeEvent::
|
||||
nsAccTextChangeEvent(nsAccessible *aAccessible, PRInt32 aStart,
|
||||
nsAString& aModifiedText, PRBool aIsInserted,
|
||||
PRBool aIsAsynch, EIsFromUserInput aIsFromUserInput) :
|
||||
nsAccEvent(aIsInserted ? nsIAccessibleEvent::EVENT_TEXT_INSERTED : nsIAccessibleEvent::EVENT_TEXT_REMOVED,
|
||||
aAccessible, aIsAsynch, aIsFromUserInput, eAllowDupes),
|
||||
mStart(aStart), mIsInserted(aIsInserted), mModifiedText(aModifiedText)
|
||||
PRBool aIsAsynch, EIsFromUserInput aIsFromUserInput)
|
||||
: nsAccEvent(aIsInserted ?
|
||||
static_cast<PRUint32>(nsIAccessibleEvent::EVENT_TEXT_INSERTED) :
|
||||
static_cast<PRUint32>(nsIAccessibleEvent::EVENT_TEXT_REMOVED),
|
||||
aAccessible, aIsAsynch, aIsFromUserInput, eAllowDupes)
|
||||
, mStart(aStart)
|
||||
, mIsInserted(aIsInserted)
|
||||
, mModifiedText(aModifiedText)
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -103,6 +103,8 @@
|
||||
#include "nsIDOMCharacterData.h"
|
||||
#endif
|
||||
|
||||
#include "mozilla/unused.h"
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// nsAccessible. nsISupports
|
||||
@ -193,8 +195,8 @@ nsresult nsAccessible::QueryInterface(REFNSIID aIID, void** aInstancePtr)
|
||||
|
||||
nsAccessible::nsAccessible(nsIContent *aContent, nsIWeakReference *aShell) :
|
||||
nsAccessNodeWrap(aContent, aShell),
|
||||
mParent(nsnull), mAreChildrenInitialized(PR_FALSE), mIndexInParent(-1),
|
||||
mRoleMapEntry(nsnull)
|
||||
mParent(nsnull), mIndexInParent(-1), mChildrenFlags(eChildrenUninitialized),
|
||||
mIndexOfEmbeddedChild(-1), mRoleMapEntry(nsnull)
|
||||
{
|
||||
#ifdef NS_DEBUG_X
|
||||
{
|
||||
@ -1100,7 +1102,7 @@ nsAccessible::TakeFocus()
|
||||
nsIContent* focusContent = mContent;
|
||||
|
||||
// If the current element can't take real DOM focus and if it has an ID and
|
||||
// ancestor with a the aria-activedescendant attribute present, then set DOM
|
||||
// an ancestor with an aria-activedescendant attribute present, then set DOM
|
||||
// focus to that ancestor and set aria-activedescendant on the ancestor to
|
||||
// the ID of the desired element.
|
||||
if (!frame->IsFocusable()) {
|
||||
@ -2751,6 +2753,7 @@ nsAccessible::UnbindFromParent()
|
||||
{
|
||||
mParent = nsnull;
|
||||
mIndexInParent = -1;
|
||||
mIndexOfEmbeddedChild = -1;
|
||||
mGroupInfo = nsnull;
|
||||
}
|
||||
|
||||
@ -2763,8 +2766,9 @@ nsAccessible::InvalidateChildren()
|
||||
child->UnbindFromParent();
|
||||
}
|
||||
|
||||
mEmbeddedObjCollector = nsnull;
|
||||
mChildren.Clear();
|
||||
mAreChildrenInitialized = PR_FALSE;
|
||||
mChildrenFlags = eChildrenUninitialized;
|
||||
}
|
||||
|
||||
PRBool
|
||||
@ -2773,6 +2777,9 @@ nsAccessible::AppendChild(nsAccessible* aChild)
|
||||
if (!mChildren.AppendElement(aChild))
|
||||
return PR_FALSE;
|
||||
|
||||
if (nsAccUtils::IsText(aChild))
|
||||
mChildrenFlags = eMixedChildren;
|
||||
|
||||
aChild->BindToParent(this, mChildren.Length() - 1);
|
||||
return PR_TRUE;
|
||||
}
|
||||
@ -2786,6 +2793,11 @@ nsAccessible::InsertChildAt(PRUint32 aIndex, nsAccessible* aChild)
|
||||
for (PRUint32 idx = aIndex + 1; idx < mChildren.Length(); idx++)
|
||||
mChildren[idx]->mIndexInParent++;
|
||||
|
||||
if (nsAccUtils::IsText(aChild))
|
||||
mChildrenFlags = eMixedChildren;
|
||||
|
||||
mEmbeddedObjCollector = nsnull;
|
||||
|
||||
aChild->BindToParent(this, aIndex);
|
||||
return PR_TRUE;
|
||||
}
|
||||
@ -2800,6 +2812,8 @@ nsAccessible::RemoveChild(nsAccessible* aChild)
|
||||
mChildren[idx]->mIndexInParent--;
|
||||
|
||||
mChildren.RemoveElementAt(aChild->mIndexInParent);
|
||||
mEmbeddedObjCollector = nsnull;
|
||||
|
||||
aChild->UnbindFromParent();
|
||||
return PR_TRUE;
|
||||
}
|
||||
@ -2873,10 +2887,57 @@ PRInt32
|
||||
nsAccessible::GetIndexInParent()
|
||||
{
|
||||
// XXX: call GetParent() to repair the tree if it's broken.
|
||||
nsAccessible* parent = GetParent();
|
||||
GetParent();
|
||||
return mIndexInParent;
|
||||
}
|
||||
|
||||
PRInt32
|
||||
nsAccessible::GetEmbeddedChildCount()
|
||||
{
|
||||
if (EnsureChildren())
|
||||
return -1;
|
||||
|
||||
if (mChildrenFlags == eMixedChildren) {
|
||||
if (!mEmbeddedObjCollector)
|
||||
mEmbeddedObjCollector = new EmbeddedObjCollector(this);
|
||||
return mEmbeddedObjCollector ? mEmbeddedObjCollector->Count() : -1;
|
||||
}
|
||||
|
||||
return GetChildCount();
|
||||
}
|
||||
|
||||
nsAccessible*
|
||||
nsAccessible::GetEmbeddedChildAt(PRUint32 aIndex)
|
||||
{
|
||||
if (EnsureChildren())
|
||||
return nsnull;
|
||||
|
||||
if (mChildrenFlags == eMixedChildren) {
|
||||
if (!mEmbeddedObjCollector)
|
||||
mEmbeddedObjCollector = new EmbeddedObjCollector(this);
|
||||
return mEmbeddedObjCollector ?
|
||||
mEmbeddedObjCollector->GetAccessibleAt(aIndex) : nsnull;
|
||||
}
|
||||
|
||||
return GetChildAt(aIndex);
|
||||
}
|
||||
|
||||
PRInt32
|
||||
nsAccessible::GetIndexOfEmbeddedChild(nsAccessible* aChild)
|
||||
{
|
||||
if (EnsureChildren())
|
||||
return -1;
|
||||
|
||||
if (mChildrenFlags == eMixedChildren) {
|
||||
if (!mEmbeddedObjCollector)
|
||||
mEmbeddedObjCollector = new EmbeddedObjCollector(this);
|
||||
return mEmbeddedObjCollector ?
|
||||
mEmbeddedObjCollector->GetIndexAt(aChild) : -1;
|
||||
}
|
||||
|
||||
return GetIndexOf(aChild);
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
PRBool
|
||||
nsAccessible::IsInCache()
|
||||
@ -2912,7 +2973,8 @@ nsAccessible::TestChildCache(nsAccessible *aCachedChild)
|
||||
#ifdef DEBUG
|
||||
PRInt32 childCount = mChildren.Length();
|
||||
if (childCount == 0) {
|
||||
NS_ASSERTION(!mAreChildrenInitialized, "No children but initialized!");
|
||||
NS_ASSERTION(mChildrenFlags == eChildrenUninitialized,
|
||||
"No children but initialized!");
|
||||
return;
|
||||
}
|
||||
|
||||
@ -2933,14 +2995,15 @@ PRBool
|
||||
nsAccessible::EnsureChildren()
|
||||
{
|
||||
if (IsDefunct()) {
|
||||
mAreChildrenInitialized = PR_FALSE;
|
||||
mChildrenFlags = eChildrenUninitialized;
|
||||
return PR_TRUE;
|
||||
}
|
||||
|
||||
if (mAreChildrenInitialized)
|
||||
if (mChildrenFlags != eChildrenUninitialized)
|
||||
return PR_FALSE;
|
||||
|
||||
mAreChildrenInitialized = PR_TRUE; // Prevent reentry
|
||||
// State is embedded children until text leaf accessible is appended.
|
||||
mChildrenFlags = eEmbeddedChildren; // Prevent reentry
|
||||
CacheChildren();
|
||||
|
||||
return PR_FALSE;
|
||||
|
@ -53,6 +53,7 @@
|
||||
#include "nsRefPtrHashtable.h"
|
||||
|
||||
class AccGroupInfo;
|
||||
class EmbeddedObjCollector;
|
||||
class nsAccessible;
|
||||
class nsAccEvent;
|
||||
struct nsRoleMapEntry;
|
||||
@ -256,6 +257,21 @@ public:
|
||||
*/
|
||||
PRBool HasChildren() { return !!GetChildAt(0); }
|
||||
|
||||
/**
|
||||
* Return embedded accessible children count.
|
||||
*/
|
||||
PRInt32 GetEmbeddedChildCount();
|
||||
|
||||
/**
|
||||
* Return embedded accessible child at the given index.
|
||||
*/
|
||||
nsAccessible* GetEmbeddedChildAt(PRUint32 aIndex);
|
||||
|
||||
/**
|
||||
* Return index of the given embedded accessible child.
|
||||
*/
|
||||
PRInt32 GetIndexOfEmbeddedChild(nsAccessible* aChild);
|
||||
|
||||
/**
|
||||
* Return cached accessible of parent-child relatives.
|
||||
*/
|
||||
@ -271,7 +287,7 @@ public:
|
||||
mParent->mChildren.SafeElementAt(mIndexInParent - 1, nsnull).get() : nsnull;
|
||||
}
|
||||
PRUint32 GetCachedChildCount() const { return mChildren.Length(); }
|
||||
PRBool AreChildrenCached() const { return mAreChildrenInitialized; }
|
||||
PRBool AreChildrenCached() const { return mChildrenFlags != eChildrenUninitialized; }
|
||||
|
||||
#ifdef DEBUG
|
||||
/**
|
||||
@ -443,9 +459,19 @@ protected:
|
||||
// Data Members
|
||||
nsRefPtr<nsAccessible> mParent;
|
||||
nsTArray<nsRefPtr<nsAccessible> > mChildren;
|
||||
PRBool mAreChildrenInitialized;
|
||||
PRInt32 mIndexInParent;
|
||||
|
||||
enum ChildrenFlags {
|
||||
eChildrenUninitialized = 0x00,
|
||||
eMixedChildren = 0x01,
|
||||
eEmbeddedChildren = 0x02
|
||||
};
|
||||
ChildrenFlags mChildrenFlags;
|
||||
|
||||
nsAutoPtr<EmbeddedObjCollector> mEmbeddedObjCollector;
|
||||
PRInt32 mIndexOfEmbeddedChild;
|
||||
friend class EmbeddedObjCollector;
|
||||
|
||||
nsAutoPtr<AccGroupInfo> mGroupInfo;
|
||||
friend class AccGroupInfo;
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
||||
/* vim:expandtab:shiftwidth=4:tabstop=4:
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim:expandtab:shiftwidth=2:tabstop=2:
|
||||
*/
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
@ -63,6 +63,8 @@ class nsApplicationAccessible: public nsAccessibleWrap,
|
||||
public nsIAccessibleApplication
|
||||
{
|
||||
public:
|
||||
using nsAccessible::GetChildAtPoint;
|
||||
|
||||
nsApplicationAccessible();
|
||||
|
||||
// nsISupports
|
||||
|
@ -55,6 +55,8 @@
|
||||
class nsLeafAccessible : public nsAccessibleWrap
|
||||
{
|
||||
public:
|
||||
using nsAccessible::GetChildAtPoint;
|
||||
|
||||
nsLeafAccessible(nsIContent *aContent, nsIWeakReference *aShell);
|
||||
|
||||
// nsISupports
|
||||
|
@ -1710,9 +1710,11 @@ nsDocAccessible::InvalidateCacheSubtree(nsIContent *aChild,
|
||||
aChangeType == nsIAccessibilityService::FRAME_SHOW ||
|
||||
aChangeType == nsIAccessibilityService::NODE_APPEND;
|
||||
|
||||
#ifdef DEBUG
|
||||
PRBool isChanging =
|
||||
aChangeType == nsIAccessibilityService::NODE_SIGNIFICANT_CHANGE ||
|
||||
aChangeType == nsIAccessibilityService::FRAME_SIGNIFICANT_CHANGE;
|
||||
#endif
|
||||
|
||||
NS_ASSERTION(isChanging || isHiding || isShowing,
|
||||
"Incorrect aChangeEventType passed in");
|
||||
|
@ -82,6 +82,8 @@ class nsDocAccessible : public nsHyperTextAccessibleWrap,
|
||||
NS_DECL_NSIOBSERVER
|
||||
|
||||
public:
|
||||
using nsAccessible::GetParent;
|
||||
|
||||
nsDocAccessible(nsIDocument *aDocument, nsIContent *aRootContent,
|
||||
nsIWeakReference* aShell);
|
||||
virtual ~nsDocAccessible();
|
||||
|
@ -191,7 +191,7 @@ nsOuterDocAccessible::InvalidateChildren()
|
||||
// then allow nsAccDocManager to handle this case since the document
|
||||
// accessible is created and appended as a child when it's requested.
|
||||
|
||||
mAreChildrenInitialized = PR_FALSE;
|
||||
mChildrenFlags = eChildrenUninitialized;
|
||||
}
|
||||
|
||||
PRBool
|
||||
|
@ -465,9 +465,10 @@ nsFontSizeTextAttr::Format(const nscoord& aValue, nsAString& aFormattedValue)
|
||||
// ATK does not specify a unit and will likely follow IA2 here.
|
||||
//
|
||||
// XXX todo: consider sharing this code with layout module? (bug 474621)
|
||||
float inches = static_cast<float>(aValue) /
|
||||
static_cast<float>(mDC->AppUnitsPerInch());
|
||||
int pts = static_cast<int>(inches * 72 + .5); // 72 pts per inch
|
||||
float px =
|
||||
NSAppUnitsToFloatPixels(aValue, nsIDeviceContext::AppUnitsPerCSSPixel());
|
||||
// Each pt is 4/3 of a CSS pixel.
|
||||
int pts = NS_lround(px*3/4);
|
||||
|
||||
nsAutoString value;
|
||||
value.AppendInt(pts);
|
||||
|
@ -81,8 +81,9 @@ private:
|
||||
*/
|
||||
class nsHTMLAreaAccessible : public nsHTMLLinkAccessible
|
||||
{
|
||||
|
||||
public:
|
||||
using nsAccessible::GetChildAtPoint;
|
||||
|
||||
nsHTMLAreaAccessible(nsIContent *aContent, nsIWeakReference *aShell);
|
||||
|
||||
// nsIAccessible
|
||||
|
@ -1091,11 +1091,8 @@ nsHyperTextAccessible::GetTextAttributes(PRBool aIncludeDefAttrs,
|
||||
NS_ADDREF(*aAttributes = attributes);
|
||||
}
|
||||
|
||||
PRInt32 offsetAccIdx = -1;
|
||||
PRInt32 startOffset = 0, endOffset = 0;
|
||||
nsAccessible *offsetAcc = GetAccessibleAtOffset(aOffset, &offsetAccIdx,
|
||||
&startOffset, &endOffset);
|
||||
if (!offsetAcc) {
|
||||
nsAccessible* accAtOffset = GetChildAtOffset(aOffset);
|
||||
if (!accAtOffset) {
|
||||
// Offset 0 is correct offset when accessible has empty text. Include
|
||||
// default attributes if they were requested, otherwise return empty set.
|
||||
if (aOffset == 0) {
|
||||
@ -1108,17 +1105,21 @@ nsHyperTextAccessible::GetTextAttributes(PRBool aIncludeDefAttrs,
|
||||
return NS_ERROR_INVALID_ARG;
|
||||
}
|
||||
|
||||
PRInt32 accAtOffsetIdx = accAtOffset->GetIndexInParent();
|
||||
PRInt32 startOffset = GetChildOffset(accAtOffsetIdx);
|
||||
PRInt32 endOffset = GetChildOffset(accAtOffsetIdx + 1);
|
||||
PRInt32 offsetInAcc = aOffset - startOffset;
|
||||
|
||||
nsTextAttrsMgr textAttrsMgr(this, aIncludeDefAttrs, offsetAcc, offsetAccIdx);
|
||||
nsTextAttrsMgr textAttrsMgr(this, aIncludeDefAttrs, accAtOffset,
|
||||
accAtOffsetIdx);
|
||||
nsresult rv = textAttrsMgr.GetAttributes(*aAttributes, &startOffset,
|
||||
&endOffset);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
// Compute spelling attributes on text accessible only.
|
||||
nsIFrame *offsetFrame = offsetAcc->GetFrame();
|
||||
nsIFrame *offsetFrame = accAtOffset->GetFrame();
|
||||
if (offsetFrame && offsetFrame->GetType() == nsAccessibilityAtoms::textFrame) {
|
||||
nsCOMPtr<nsIDOMNode> node = offsetAcc->GetDOMNode();
|
||||
nsCOMPtr<nsIDOMNode> node = accAtOffset->GetDOMNode();
|
||||
|
||||
PRInt32 nodeOffset = 0;
|
||||
nsresult rv = RenderedToContentOffset(offsetFrame, offsetInAcc,
|
||||
@ -1369,7 +1370,7 @@ nsHyperTextAccessible::GetLinkIndex(nsIAccessibleHyperLink* aLink,
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsHyperTextAccessible::GetLinkIndexAtOffset(PRInt32 aCharIndex,
|
||||
nsHyperTextAccessible::GetLinkIndexAtOffset(PRInt32 aOffset,
|
||||
PRInt32* aLinkIndex)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(aLinkIndex);
|
||||
@ -1378,29 +1379,7 @@ nsHyperTextAccessible::GetLinkIndexAtOffset(PRInt32 aCharIndex,
|
||||
if (IsDefunct())
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
PRInt32 characterCount = 0;
|
||||
PRInt32 linkIndex = 0;
|
||||
|
||||
PRInt32 childCount = GetChildCount();
|
||||
for (PRInt32 childIdx = 0;
|
||||
childIdx < childCount && characterCount <= aCharIndex; childIdx++) {
|
||||
nsAccessible *childAcc = mChildren[childIdx];
|
||||
|
||||
PRUint32 role = nsAccUtils::Role(childAcc);
|
||||
if (role == nsIAccessibleRole::ROLE_TEXT_LEAF ||
|
||||
role == nsIAccessibleRole::ROLE_STATICTEXT) {
|
||||
characterCount += nsAccUtils::TextLength(childAcc);
|
||||
}
|
||||
else {
|
||||
if (characterCount ++ == aCharIndex) {
|
||||
*aLinkIndex = linkIndex;
|
||||
break;
|
||||
}
|
||||
if (role != nsIAccessibleRole::ROLE_WHITESPACE) {
|
||||
++ linkIndex;
|
||||
}
|
||||
}
|
||||
}
|
||||
*aLinkIndex = GetLinkIndexAtOffset(aOffset);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
@ -2043,7 +2022,6 @@ nsHyperTextAccessible::ScrollSubstringToPoint(PRInt32 aStartIndex,
|
||||
void
|
||||
nsHyperTextAccessible::InvalidateChildren()
|
||||
{
|
||||
mLinks = nsnull;
|
||||
mOffsets.Clear();
|
||||
|
||||
nsAccessibleWrap::InvalidateChildren();
|
||||
@ -2110,70 +2088,77 @@ nsresult nsHyperTextAccessible::RenderedToContentOffset(nsIFrame *aFrame, PRUint
|
||||
// nsHyperTextAccessible public
|
||||
|
||||
PRInt32
|
||||
nsHyperTextAccessible::GetChildOffset(nsAccessible* aChild,
|
||||
nsHyperTextAccessible::GetChildOffset(PRUint32 aChildIndex,
|
||||
PRBool aInvalidateAfter)
|
||||
{
|
||||
PRInt32 index = GetIndexOf(aChild);
|
||||
if (index == -1 || index == 0)
|
||||
return index;
|
||||
if (aChildIndex == 0)
|
||||
return aChildIndex;
|
||||
|
||||
PRInt32 count = mOffsets.Length() - index;
|
||||
PRInt32 count = mOffsets.Length() - aChildIndex;
|
||||
if (count > 0) {
|
||||
if (aInvalidateAfter)
|
||||
mOffsets.RemoveElementsAt(index, count);
|
||||
mOffsets.RemoveElementsAt(aChildIndex, count);
|
||||
|
||||
return mOffsets[index - 1];
|
||||
return mOffsets[aChildIndex - 1];
|
||||
}
|
||||
|
||||
PRUint32 lastOffset = mOffsets.IsEmpty() ?
|
||||
0 : mOffsets[mOffsets.Length() - 1];
|
||||
|
||||
EnsureChildren();
|
||||
while (mOffsets.Length() < index) {
|
||||
while (mOffsets.Length() < aChildIndex) {
|
||||
nsAccessible* child = mChildren[mOffsets.Length()];
|
||||
lastOffset += nsAccUtils::TextLength(child);
|
||||
mOffsets.AppendElement(lastOffset);
|
||||
}
|
||||
|
||||
return mOffsets[index - 1];
|
||||
}
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// nsHyperTextAccessible protected
|
||||
|
||||
AccCollector*
|
||||
nsHyperTextAccessible::GetLinkCollector()
|
||||
{
|
||||
if (IsDefunct())
|
||||
return nsnull;
|
||||
|
||||
if (!mLinks)
|
||||
mLinks = new AccCollector(this, filters::GetEmbeddedObject);
|
||||
return mLinks;
|
||||
return mOffsets[aChildIndex - 1];
|
||||
}
|
||||
|
||||
nsAccessible *
|
||||
nsHyperTextAccessible::GetAccessibleAtOffset(PRInt32 aOffset, PRInt32 *aAccIdx,
|
||||
PRInt32 *aStartOffset,
|
||||
PRInt32 *aEndOffset)
|
||||
PRInt32
|
||||
nsHyperTextAccessible::GetChildIndexAtOffset(PRUint32 aOffset)
|
||||
{
|
||||
PRInt32 startOffset = 0, endOffset = 0;
|
||||
PRInt32 childCount = GetChildCount();
|
||||
for (PRInt32 childIdx = 0; childIdx < childCount; childIdx++) {
|
||||
nsAccessible *child = mChildren[childIdx];
|
||||
endOffset += nsAccUtils::TextLength(child);
|
||||
if (endOffset > aOffset) {
|
||||
*aStartOffset = startOffset;
|
||||
*aEndOffset = endOffset;
|
||||
*aAccIdx = childIdx;
|
||||
return child;
|
||||
PRUint32 lastOffset = 0;
|
||||
PRUint32 offsetCount = mOffsets.Length();
|
||||
if (offsetCount > 0) {
|
||||
lastOffset = mOffsets[offsetCount - 1];
|
||||
if (aOffset < lastOffset) {
|
||||
PRUint32 low = 0, high = offsetCount;
|
||||
while (high > low) {
|
||||
PRUint32 mid = (high + low) >> 1;
|
||||
if (mOffsets[mid] == aOffset)
|
||||
return mid < offsetCount - 1 ? mid + 1 : mid;
|
||||
|
||||
if (mOffsets[mid] < aOffset)
|
||||
low = mid + 1;
|
||||
else
|
||||
high = mid;
|
||||
}
|
||||
if (high == offsetCount)
|
||||
return -1;
|
||||
|
||||
return low;
|
||||
}
|
||||
|
||||
startOffset = endOffset;
|
||||
}
|
||||
|
||||
return nsnull;
|
||||
PRUint32 childCount = GetChildCount();
|
||||
while (mOffsets.Length() < childCount) {
|
||||
nsAccessible* child = GetChildAt(mOffsets.Length());
|
||||
lastOffset += nsAccUtils::TextLength(child);
|
||||
mOffsets.AppendElement(lastOffset);
|
||||
if (aOffset < lastOffset)
|
||||
return mOffsets.Length() - 1;
|
||||
}
|
||||
|
||||
if (aOffset == lastOffset)
|
||||
return mOffsets.Length() - 1;
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// nsHyperTextAccessible protected
|
||||
|
||||
nsresult
|
||||
nsHyperTextAccessible::GetDOMPointByFrameOffset(nsIFrame *aFrame,
|
||||
PRInt32 aOffset,
|
||||
|
@ -106,8 +106,7 @@ public:
|
||||
*/
|
||||
inline PRUint32 GetLinkCount()
|
||||
{
|
||||
AccCollector* links = GetLinkCollector();
|
||||
return links ? links->Count() : 0;
|
||||
return GetEmbeddedChildCount();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -115,8 +114,7 @@ public:
|
||||
*/
|
||||
inline nsAccessible* GetLinkAt(PRUint32 aIndex)
|
||||
{
|
||||
AccCollector* links = GetLinkCollector();
|
||||
return links ? links->GetAccessibleAt(aIndex) : nsnull;
|
||||
return GetEmbeddedChildAt(aIndex);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -124,8 +122,16 @@ public:
|
||||
*/
|
||||
inline PRInt32 GetLinkIndex(nsAccessible* aLink)
|
||||
{
|
||||
AccCollector* links = GetLinkCollector();
|
||||
return links ? links->GetIndexAt(aLink) : -1;
|
||||
return GetIndexOfEmbeddedChild(aLink);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return link accessible at the given text offset.
|
||||
*/
|
||||
inline PRInt32 GetLinkIndexAtOffset(PRUint32 aOffset)
|
||||
{
|
||||
nsAccessible* child = GetChildAtOffset(aOffset);
|
||||
return GetLinkIndex(child);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -187,23 +193,46 @@ public:
|
||||
PRInt32 *aEndOffset);
|
||||
|
||||
/**
|
||||
* Return text offset the given child accessible of hypertext accessible.
|
||||
* Return text offset of the given child accessible within hypertext
|
||||
* accessible.
|
||||
*
|
||||
* @param aChild [in] accessible child to get text offset for
|
||||
* @param aInvalidateAfter [in, optional] indicates whether invalidate
|
||||
* cached offsets for next siblings of the child
|
||||
*/
|
||||
PRInt32 GetChildOffset(nsAccessible* aChild,
|
||||
PRBool aInvalidateAfter = PR_FALSE)
|
||||
{
|
||||
PRInt32 index = GetIndexOf(aChild);
|
||||
return index == -1 ? -1 : GetChildOffset(index, aInvalidateAfter);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return text offset for the child accessible index.
|
||||
*/
|
||||
PRInt32 GetChildOffset(PRUint32 aChildIndex,
|
||||
PRBool aInvalidateAfter = PR_FALSE);
|
||||
|
||||
/**
|
||||
* Return child accessible at the given text offset.
|
||||
*
|
||||
* @param aOffset [in] the given text offset
|
||||
*/
|
||||
PRInt32 GetChildIndexAtOffset(PRUint32 aOffset);
|
||||
|
||||
/**
|
||||
* Return child accessible at the given text offset.
|
||||
*
|
||||
* @param aOffset [in] the given text offset
|
||||
*/
|
||||
nsAccessible* GetChildAtOffset(PRUint32 aOffset)
|
||||
{
|
||||
return GetChildAt(GetChildIndexAtOffset(aOffset));
|
||||
}
|
||||
|
||||
protected:
|
||||
// nsHyperTextAccessible
|
||||
|
||||
/**
|
||||
* Return link collection, create it if necessary.
|
||||
*/
|
||||
AccCollector* GetLinkCollector();
|
||||
|
||||
/*
|
||||
* This does the work for nsIAccessibleText::GetText[At|Before|After]Offset
|
||||
* @param aType, eGetBefore, eGetAt, eGetAfter
|
||||
@ -299,18 +328,6 @@ protected:
|
||||
*/
|
||||
PRInt32 GetCaretLineNumber();
|
||||
|
||||
/**
|
||||
* Return an accessible at the given hypertext offset.
|
||||
*
|
||||
* @param aOffset [out] the given hypertext offset
|
||||
* @param aAccIdx [out] child index of returned accessible
|
||||
* @param aStartOffset [out] start hypertext offset of returned accessible
|
||||
* @param aEndOffset [out] end hypertext offset of returned accessible
|
||||
*/
|
||||
nsAccessible *GetAccessibleAtOffset(PRInt32 aOffset, PRInt32 *aAccIdx,
|
||||
PRInt32 *aStartOffset,
|
||||
PRInt32 *aEndOffset);
|
||||
|
||||
// Helpers
|
||||
nsresult GetDOMPointByFrameOffset(nsIFrame *aFrame, PRInt32 aOffset,
|
||||
nsIAccessible *aAccessible,
|
||||
|
@ -117,16 +117,11 @@ CAccessibleHypertext::get_hyperlinkIndex(long aCharIndex, long *aHyperlinkIndex)
|
||||
__try {
|
||||
*aHyperlinkIndex = 0;
|
||||
|
||||
nsCOMPtr<nsIAccessibleHyperText> hyperAcc(do_QueryObject(this));
|
||||
nsRefPtr<nsHyperTextAccessible> hyperAcc(do_QueryObject(this));
|
||||
if (!hyperAcc)
|
||||
return E_FAIL;
|
||||
|
||||
PRInt32 index = 0;
|
||||
nsresult rv = hyperAcc->GetLinkIndexAtOffset(aCharIndex, &index);
|
||||
if (NS_FAILED(rv))
|
||||
return GetHRESULT(rv);
|
||||
|
||||
*aHyperlinkIndex = index;
|
||||
*aHyperlinkIndex = hyperAcc->GetLinkIndexAtOffset(aCharIndex);
|
||||
return S_OK;
|
||||
|
||||
} __except(nsAccessNodeWrap::FilterA11yExceptions(::GetExceptionCode(), GetExceptionInformation())) { }
|
||||
|
@ -197,8 +197,8 @@ nsXULTreeAccessible::GetRoleInternal(PRUint32 *aRole)
|
||||
cols->GetPrimaryColumn(getter_AddRefs(primaryCol));
|
||||
|
||||
*aRole = primaryCol ?
|
||||
nsIAccessibleRole::ROLE_OUTLINE :
|
||||
nsIAccessibleRole::ROLE_LIST;
|
||||
static_cast<PRUint32>(nsIAccessibleRole::ROLE_OUTLINE) :
|
||||
static_cast<PRUint32>(nsIAccessibleRole::ROLE_LIST);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
@ -989,8 +989,8 @@ nsXULTreeItemAccessibleBase::GetStateInternal(PRUint32 *aState,
|
||||
PRBool isContainerOpen;
|
||||
mTreeView->IsContainerOpen(mRow, &isContainerOpen);
|
||||
*aState |= isContainerOpen ?
|
||||
nsIAccessibleStates::STATE_EXPANDED:
|
||||
nsIAccessibleStates::STATE_COLLAPSED;
|
||||
static_cast<PRUint32>(nsIAccessibleStates::STATE_EXPANDED) :
|
||||
static_cast<PRUint32>(nsIAccessibleStates::STATE_COLLAPSED);
|
||||
}
|
||||
|
||||
// selected state
|
||||
@ -1178,8 +1178,8 @@ nsXULTreeItemAccessible::GetRoleInternal(PRUint32 *aRole)
|
||||
columns->GetPrimaryColumn(getter_AddRefs(primaryColumn));
|
||||
|
||||
*aRole = primaryColumn ?
|
||||
nsIAccessibleRole::ROLE_OUTLINEITEM :
|
||||
nsIAccessibleRole::ROLE_LISTITEM;
|
||||
static_cast<PRUint32>(nsIAccessibleRole::ROLE_OUTLINEITEM) :
|
||||
static_cast<PRUint32>(nsIAccessibleRole::ROLE_LISTITEM);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
@ -64,6 +64,10 @@ const PRUint32 kDefaultTreeCacheSize = 256;
|
||||
class nsXULTreeAccessible : public nsXULSelectableAccessible
|
||||
{
|
||||
public:
|
||||
using nsAccessible::GetChildCount;
|
||||
using nsAccessible::GetChildAt;
|
||||
using nsAccessible::GetChildAtPoint;
|
||||
|
||||
nsXULTreeAccessible(nsIContent *aContent, nsIWeakReference *aShell);
|
||||
|
||||
// nsISupports and cycle collection
|
||||
@ -162,6 +166,8 @@ NS_DEFINE_STATIC_IID_ACCESSOR(nsXULTreeAccessible,
|
||||
class nsXULTreeItemAccessibleBase : public nsAccessibleWrap
|
||||
{
|
||||
public:
|
||||
using nsAccessible::GetParent;
|
||||
|
||||
nsXULTreeItemAccessibleBase(nsIContent *aContent, nsIWeakReference *aShell,
|
||||
nsAccessible *aParent, nsITreeBoxObject *aTree,
|
||||
nsITreeView *aTreeView, PRInt32 aRow);
|
||||
|
@ -586,8 +586,8 @@ nsXULTreeGridAccessible::GetRoleInternal(PRUint32 *aRole)
|
||||
treeColumns->GetPrimaryColumn(getter_AddRefs(primaryColumn));
|
||||
|
||||
*aRole = primaryColumn ?
|
||||
nsIAccessibleRole::ROLE_TREE_TABLE :
|
||||
nsIAccessibleRole::ROLE_TABLE;
|
||||
static_cast<PRUint32>(nsIAccessibleRole::ROLE_TREE_TABLE) :
|
||||
static_cast<PRUint32>(nsIAccessibleRole::ROLE_TABLE);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
@ -75,6 +75,10 @@ protected:
|
||||
class nsXULTreeGridRowAccessible : public nsXULTreeItemAccessibleBase
|
||||
{
|
||||
public:
|
||||
using nsAccessible::GetChildCount;
|
||||
using nsAccessible::GetChildAt;
|
||||
using nsAccessible::GetChildAtPoint;
|
||||
|
||||
nsXULTreeGridRowAccessible(nsIContent *aContent, nsIWeakReference *aShell,
|
||||
nsAccessible *aParent, nsITreeBoxObject *aTree,
|
||||
nsITreeView *aTreeView, PRInt32 aRow);
|
||||
@ -127,6 +131,8 @@ class nsXULTreeGridCellAccessible : public nsLeafAccessible,
|
||||
public nsIAccessibleTableCell
|
||||
{
|
||||
public:
|
||||
using nsAccessible::GetParent;
|
||||
|
||||
nsXULTreeGridCellAccessible(nsIContent *aContent, nsIWeakReference *aShell,
|
||||
nsXULTreeGridRowAccessible *aRowAcc,
|
||||
nsITreeBoxObject *aTree, nsITreeView *aTreeView,
|
||||
|
@ -428,8 +428,12 @@
|
||||
|
||||
ID = "area14";
|
||||
defAttrs = buildDefaultTextAttrs(ID, kInputFontSize);
|
||||
attrs = { };
|
||||
testTextAttrs(ID, 0, attrs, defAttrs, 0, 0);
|
||||
|
||||
// XXX: While we expose text leaf accessibles for placeholder we grab its
|
||||
// style, bug 545817.
|
||||
// attrs = { color: "rgb(109, 109, 109)" };
|
||||
//testTextAttrs(ID, 0, attrs, defAttrs, 0, 0);
|
||||
todo(false, "enable commented tests when bug 545817 is fixed");
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// area15, embed char tests, "*plain*plain**bold*bold*"
|
||||
|
@ -26,6 +26,10 @@
|
||||
|
||||
function doTest()
|
||||
{
|
||||
// Actually, just disable this test everywhere -- bug 586818.
|
||||
SimpleTest.finish();
|
||||
return;
|
||||
|
||||
if (LINUX) {
|
||||
todo(false, "Enable test on Linux - see bug 525175.");
|
||||
SimpleTest.finish();
|
||||
|
@ -18,10 +18,16 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=428248
|
||||
<script type="application/javascript">
|
||||
var gParagraphAcc;
|
||||
|
||||
function testLinkIndexAtOffset(aID, aOffset, aIndex)
|
||||
{
|
||||
var htAcc = getAccessible(aID, [nsIAccessibleHyperText]);
|
||||
is(htAcc.getLinkIndexAtOffset(aOffset), aIndex,
|
||||
"Wrong link index at offset " + aOffset + " for ID " + aID + "!");
|
||||
}
|
||||
|
||||
function testThis(aID, aCharIndex, aExpectedLinkIndex, aName)
|
||||
{
|
||||
is(gParagraphAcc.getLinkIndexAtOffset(aCharIndex), aExpectedLinkIndex,
|
||||
"Wrong link index at offset " + aCharIndex + " for ID " + aID + "!");
|
||||
testLinkIndexAtOffset(gParagraphAcc, aCharIndex, aExpectedLinkIndex);
|
||||
|
||||
var linkAcc = gParagraphAcc.getLinkAt(aExpectedLinkIndex);
|
||||
ok(linkAcc, "No accessible for link " + aID + "!");
|
||||
@ -95,6 +101,27 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=428248
|
||||
is(linkIdx, jdx, "Wrong link index for 'p3'!");
|
||||
};
|
||||
|
||||
// getLinkIndexAtOffset, causes the offsets to be cached;
|
||||
testLinkIndexAtOffset("p4", 0, 0); // 1st 'mozilla' link
|
||||
testLinkIndexAtOffset("p4", 1, 1); // 2nd 'mozilla' link
|
||||
testLinkIndexAtOffset("p4", 2, -1); // ' ' of ' te' text node
|
||||
testLinkIndexAtOffset("p4", 3, -1); // 't' of ' te' text node
|
||||
testLinkIndexAtOffset("p4", 5, -1); // 'x' of 'xt ' text node
|
||||
testLinkIndexAtOffset("p4", 7, -1); // ' ' of 'xt ' text node
|
||||
testLinkIndexAtOffset("p4", 8, 2); // 3d 'mozilla' link
|
||||
testLinkIndexAtOffset("p4", 9, 2); // the end, latest link
|
||||
|
||||
// the second pass to make sure link indexes are calculated propertly from
|
||||
// cached offsets.
|
||||
testLinkIndexAtOffset("p4", 0, 0); // 1st 'mozilla' link
|
||||
testLinkIndexAtOffset("p4", 1, 1); // 2nd 'mozilla' link
|
||||
testLinkIndexAtOffset("p4", 2, -1); // ' ' of ' te' text node
|
||||
testLinkIndexAtOffset("p4", 3, -1); // 't' of ' te' text node
|
||||
testLinkIndexAtOffset("p4", 5, -1); // 'x' of 'xt ' text node
|
||||
testLinkIndexAtOffset("p4", 7, -1); // ' ' of 'xt ' text node
|
||||
testLinkIndexAtOffset("p4", 8, 2); // 3d 'mozilla' link
|
||||
testLinkIndexAtOffset("p4", 9, 2); // the end, latest link
|
||||
|
||||
SimpleTest.finish();
|
||||
}
|
||||
|
||||
@ -150,5 +177,6 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=428248
|
||||
</p>
|
||||
<p id="p2"><a href="http://mozilla.org">mozilla.org</a></p>
|
||||
<p id="p3"></p>
|
||||
<p id="p4"><a href="www">mozilla</a><a href="www">mozilla</a><span> te</span><span>xt </span><a href="www">mozilla</a></p>
|
||||
</body>
|
||||
</html>
|
||||
|
@ -96,13 +96,13 @@
|
||||
</preferences>
|
||||
<vbox style="padding: 12px;">
|
||||
<groupbox>
|
||||
<caption label="Data Submission" />
|
||||
<caption label="&testpilot.settings.dataSubmission.label;" />
|
||||
<checkbox label="&testpilot.settings.alwaysSubmitData.label;"
|
||||
preference="always-submit-data"/>
|
||||
</groupbox>
|
||||
<groupbox>
|
||||
<caption label="Notifications" />
|
||||
<label value="&testpilot.settings.notifyMeWhen.label;"/>
|
||||
<caption label="&testpilot.settings.notifications.label;" />
|
||||
<label value="&testpilot.settings.notifyWhen.label;"/>
|
||||
<hbox>
|
||||
<separator orient="vertical" />
|
||||
<vbox>
|
||||
|
@ -71,7 +71,7 @@
|
||||
oncommand="TestPilotWindowUtils.openFeedbackPage(false);"/>
|
||||
<menuseparator/>
|
||||
<menuitem id="feedback-menu-show-studies"
|
||||
label="&testpilot.allStudies.label;..."
|
||||
label="&testpilot.allYourStudies.label;"
|
||||
oncommand="TestPilotWindowUtils.openAllStudiesWindow();"/>
|
||||
<menuitem id="feedback-menu-enable-studies"
|
||||
label="&testpilot.enable.label;"
|
||||
|
@ -24,7 +24,7 @@
|
||||
<menu id="pilot-notification-settings" label="&testpilot.settings.label;">
|
||||
<menupopup onpopupshowing="TestPilotMenuUtils.updateSubmenu();">
|
||||
<menuitem class="pilot-notify-me-when"
|
||||
label="&testpilot.settings.notifyMeWhen.label;..."
|
||||
label="&testpilot.settings.notifyWhen.label;"
|
||||
disabled="true"/>
|
||||
<menuitem id="pilot-menu-notify-finished"
|
||||
label="&testpilot.settings.readyToSubmit.label;"
|
||||
@ -48,7 +48,7 @@
|
||||
TestPilotMenuUtils.togglePref('alwaysSubmitData');"/>
|
||||
</menupopup>
|
||||
</menu>
|
||||
<menuitem label="&testpilot.allStudies.label;..."
|
||||
<menuitem label="&testpilot.allYourStudies.label;"
|
||||
oncommand="TestPilotWindowUtils.openAllStudiesWindow();"/>
|
||||
<menuitem label="&testpilot.about.label;"
|
||||
oncommand="TestPilotWindowUtils.openHomepage();"/>
|
||||
|
@ -1,5 +1,7 @@
|
||||
pref("extensions.testpilot.indexFileName", "index.json");
|
||||
|
||||
pref("extensions.testpilot@labs.mozilla.com.description", "chrome://testpilot/locale/main.properties");
|
||||
|
||||
pref("extensions.testpilot.popup.delayAfterStartup", 180000); // 3 minutes
|
||||
pref("extensions.testpilot.popup.timeBetweenChecks", 86400000); // 24 hours
|
||||
pref("extensions.testpilot.uploadRetryInterval", 3600000); // 1 hour
|
||||
|
@ -4,7 +4,7 @@
|
||||
xmlns:em="http://www.mozilla.org/2004/em-rdf#">
|
||||
<Description about="urn:mozilla:install-manifest">
|
||||
<em:id>testpilot@labs.mozilla.com</em:id>
|
||||
<em:version>1.0.1</em:version>
|
||||
<em:version>1.0.2</em:version>
|
||||
<em:type>2</em:type>
|
||||
|
||||
<!-- Target Application this extension can install into,
|
||||
@ -13,7 +13,7 @@
|
||||
<Description>
|
||||
<em:id>{ec8030f7-c20a-464f-9b0e-13a3a9e97384}</em:id>
|
||||
<em:minVersion>3.5</em:minVersion>
|
||||
<em:maxVersion>4.0b3</em:maxVersion>
|
||||
<em:maxVersion>4.0b4</em:maxVersion>
|
||||
</Description>
|
||||
</em:targetApplication>
|
||||
|
||||
|
@ -169,18 +169,26 @@ var TestPilotTask = {
|
||||
// event handlers:
|
||||
|
||||
onExperimentStartup: function TestPilotTask_onExperimentStartup() {
|
||||
// Called when experiment is to start running (either on Firefox
|
||||
// startup, or when study first becomes IN_PROGRESS)
|
||||
},
|
||||
|
||||
onExperimentShutdown: function TestPilotTask_onExperimentShutdown() {
|
||||
// Called when experiment needs to stop running (either on Firefox
|
||||
// shutdown, or on experiment reload, or on finishing or being canceled.)
|
||||
},
|
||||
|
||||
doExperimentCleanup: function TestPilotTask_onExperimentCleanup() {
|
||||
// Called when experiment has finished or been canceled; do any cleanup
|
||||
// of user's profile.
|
||||
},
|
||||
|
||||
onAppStartup: function TestPilotTask_onAppStartup() {
|
||||
// Called by extension core when startup is complete.
|
||||
// Called by extension core when Firefox startup is complete.
|
||||
},
|
||||
|
||||
onAppShutdown: function TestPilotTask_onAppShutdown() {
|
||||
// TODO: not implemented - should be called when firefox is ready to
|
||||
// shut down.
|
||||
// Called by extension core when Firefox is shutting down.
|
||||
},
|
||||
|
||||
onEnterPrivateBrowsing: function TestPilotTask_onEnterPrivate() {
|
||||
@ -494,6 +502,13 @@ TestPilotExperiment.prototype = {
|
||||
}
|
||||
},
|
||||
|
||||
doExperimentCleanup: function TestPilotExperiment_doExperimentCleanup() {
|
||||
if (this._handlers.doExperimentCleanup) {
|
||||
this._logger.trace("Doing experiment cleanup.");
|
||||
this._handlers.doExperimentCleanup();
|
||||
}
|
||||
},
|
||||
|
||||
onEnterPrivateBrowsing: function TestPilotExperiment_onEnterPrivate() {
|
||||
this._logger.trace("Task is entering private browsing.");
|
||||
if (this.experimentIsRunning()) {
|
||||
@ -633,6 +648,7 @@ TestPilotExperiment.prototype = {
|
||||
this._logger.info("Passed End Date - Switched Task Status to Finished");
|
||||
this.changeStatus(TaskConstants.STATUS_FINISHED);
|
||||
this.onExperimentShutdown();
|
||||
this.doExperimentCleanup();
|
||||
|
||||
if (this._recursAutomatically) {
|
||||
this._reschedule();
|
||||
@ -800,8 +816,11 @@ TestPilotExperiment.prototype = {
|
||||
// database table of just opt-out messages; include study ID in metadata.
|
||||
let url = Application.prefs.getValue(DATA_UPLOAD_PREF, "") + "opt-out";
|
||||
let logger = this._logger;
|
||||
|
||||
this.onExperimentShutdown();
|
||||
this.changeStatus(TaskConstants.STATUS_CANCELLED);
|
||||
this._dataStore.wipeAllData();
|
||||
this.doExperimentCleanup();
|
||||
this._dateForDataDeletion = null;
|
||||
this._expirationDateForDataSubmission = null;
|
||||
logger.info("Opting out of test with reason " + reason);
|
||||
|
@ -0,0 +1,4 @@
|
||||
|
||||
#pilot-notification-popup {
|
||||
color: -moz-dialogtext;
|
||||
}
|
@ -183,7 +183,9 @@ pref("xpinstall.whitelist.add.36", "getpersonas.com");
|
||||
pref("lightweightThemes.update.enabled", true);
|
||||
|
||||
pref("keyword.enabled", true);
|
||||
pref("keyword.URL", "chrome://browser-region/locale/region.properties");
|
||||
// Override the default keyword.URL. Empty value means
|
||||
// "use the search service's default engine"
|
||||
pref("keyword.URL", "");
|
||||
|
||||
pref("general.useragent.locale", "@AB_CD@");
|
||||
pref("general.skins.selectedSkin", "classic/1.0");
|
||||
|
@ -83,3 +83,6 @@ endif
|
||||
ifneq (,$(filter windows, $(MOZ_WIDGET_TOOLKIT)))
|
||||
DEFINES += -DMENUBAR_CAN_AUTOHIDE=1
|
||||
endif
|
||||
|
||||
libs::
|
||||
$(NSINSTALL) $(srcdir)/content/tabview/modules/* $(FINAL_TARGET)/modules/tabview
|
||||
|
@ -208,6 +208,10 @@
|
||||
<menu id="view-menu" label="&viewMenu.label;"
|
||||
accesskey="&viewMenu.accesskey;">
|
||||
<menupopup id="menu_viewPopup">
|
||||
<menuitem id="menu_tabview"
|
||||
label="&showTabView2.label;"
|
||||
accesskey="&showTabView2.accesskey;"
|
||||
command="Browser:ToggleTabView"/>
|
||||
<menu id="viewToolbarsMenu"
|
||||
label="&viewToolbarsMenu.label;"
|
||||
accesskey="&viewToolbarsMenu.accesskey;">
|
||||
@ -590,7 +594,11 @@
|
||||
<menu id="tools-menu"
|
||||
label="&toolsMenu.label;"
|
||||
accesskey="&toolsMenu.accesskey;">
|
||||
<menupopup id="menu_ToolsPopup">
|
||||
<menupopup id="menu_ToolsPopup"
|
||||
#ifdef MOZ_SERVICES_SYNC
|
||||
onpopupshowing="gSyncUI.updateUI();"
|
||||
#endif
|
||||
>
|
||||
<menuitem id="menu_search"
|
||||
label="&search.label;"
|
||||
accesskey="&search.accesskey;"
|
||||
|
@ -117,6 +117,7 @@
|
||||
<command id="Browser:NextTab" oncommand="gBrowser.tabContainer.advanceSelectedTab(1, true);"/>
|
||||
<command id="Browser:PrevTab" oncommand="gBrowser.tabContainer.advanceSelectedTab(-1, true);"/>
|
||||
<command id="Browser:ShowAllTabs" oncommand="allTabs.open();"/>
|
||||
<command id="Browser:ToggleTabView" oncommand="TabView.toggle();"/>
|
||||
<command id="cmd_fullZoomReduce" oncommand="FullZoom.reduce()"/>
|
||||
<command id="cmd_fullZoomEnlarge" oncommand="FullZoom.enlarge()"/>
|
||||
<command id="cmd_fullZoomReset" oncommand="FullZoom.reset()"/>
|
||||
@ -150,8 +151,6 @@
|
||||
<command id="Inspector:Next"
|
||||
oncommand="InspectorUI.inspectNext();"
|
||||
disabled="true"/>
|
||||
<command id="Inspector:Style"
|
||||
oncommand="InspectorUI.toggleStylePanel();"/>
|
||||
</commandset>
|
||||
|
||||
<broadcasterset id="mainBroadcasterSet">
|
||||
|
@ -40,37 +40,31 @@
|
||||
// gSyncUI handles updating the tools menu
|
||||
let gSyncUI = {
|
||||
init: function SUI_init() {
|
||||
let obs = [["weave:service:sync:start", "onActivityStart"],
|
||||
["weave:service:sync:finish", "onSyncFinish"],
|
||||
["weave:service:sync:error", "onSyncError"],
|
||||
["weave:service:sync:delayed", "onSyncDelay"],
|
||||
["weave:service:setup-complete", "onLoginFinish"],
|
||||
["weave:service:login:start", "onActivityStart"],
|
||||
["weave:service:login:finish", "onLoginFinish"],
|
||||
["weave:service:login:error", "onLoginError"],
|
||||
["weave:service:logout:finish", "onLogout"],
|
||||
["weave:service:start-over", "onStartOver"]];
|
||||
// this will be the first notification fired during init
|
||||
// we can set up everything else later
|
||||
Services.obs.addObserver(this, "weave:service:ready", true);
|
||||
},
|
||||
initUI: function SUI_initUI() {
|
||||
let obs = ["weave:service:sync:start",
|
||||
"weave:service:sync:finish",
|
||||
"weave:service:sync:error",
|
||||
"weave:service:sync:delayed",
|
||||
"weave:service:setup-complete",
|
||||
"weave:service:login:start",
|
||||
"weave:service:login:finish",
|
||||
"weave:service:login:error",
|
||||
"weave:service:logout:finish",
|
||||
"weave:service:start-over"];
|
||||
|
||||
// If this is a browser window?
|
||||
if (gBrowser) {
|
||||
obs.push(["weave:notification:added", "onNotificationAdded"],
|
||||
["weave:notification:removed", "onNotificationRemoved"]);
|
||||
obs.push("weave:notification:added", "weave:notification:removed");
|
||||
}
|
||||
|
||||
// Add the observers now and remove them on unload
|
||||
let self = this;
|
||||
let addRem = function(add) {
|
||||
obs.forEach(function([topic, func]) {
|
||||
//XXXzpao This should use Services.obs.* but Weave's Obs does nice handling
|
||||
// of `this`. Fix in a followup. (bug 583347)
|
||||
if (add)
|
||||
Weave.Svc.Obs.add(topic, self[func], self);
|
||||
else
|
||||
Weave.Svc.Obs.remove(topic, self[func], self);
|
||||
});
|
||||
};
|
||||
addRem(true);
|
||||
window.addEventListener("unload", function() addRem(false), false);
|
||||
obs.forEach(function(topic) {
|
||||
Services.obs.addObserver(self, topic, true);
|
||||
});
|
||||
|
||||
// Find the alltabs-popup, only if there is a gBrowser
|
||||
if (gBrowser) {
|
||||
@ -80,7 +74,6 @@ let gSyncUI = {
|
||||
self.alltabsPopupShowing();
|
||||
}, true);
|
||||
}
|
||||
|
||||
this.updateUI();
|
||||
},
|
||||
|
||||
@ -242,7 +235,6 @@ let gSyncUI = {
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
// Commands
|
||||
doUpdateMenu: function SUI_doUpdateMenu(event) {
|
||||
this._updateLastSyncItem();
|
||||
@ -369,7 +361,50 @@ let gSyncUI = {
|
||||
|
||||
this.updateUI();
|
||||
this._updateLastSyncItem();
|
||||
}
|
||||
},
|
||||
|
||||
observe: function SUI_observe(subject, topic, data) {
|
||||
switch (topic) {
|
||||
case "weave:service:sync:start":
|
||||
this.onActivityStart();
|
||||
break;
|
||||
case "weave:service:sync:finish":
|
||||
this.onSyncFinish();
|
||||
break;
|
||||
case "weave:service:sync:error":
|
||||
this.onSyncError();
|
||||
break;
|
||||
case "weave:service:sync:delayed":
|
||||
this.onSyncDelay();
|
||||
break;
|
||||
case "weave:service:setup-complete":
|
||||
this.onLoginFinish();
|
||||
break;
|
||||
case "weave:service:login:start":
|
||||
this.onActivityStart();
|
||||
break;
|
||||
case "weave:service:login:finish":
|
||||
this.onLoginFinish();
|
||||
break;
|
||||
case "weave:service:login:error":
|
||||
this.onLoginError();
|
||||
break;
|
||||
case "weave:service:logout:finish":
|
||||
this.onLogout();
|
||||
break;
|
||||
case "weave:service:start-over":
|
||||
this.onStartOver();
|
||||
break;
|
||||
case "weave:service:ready":
|
||||
this.initUI();
|
||||
break;
|
||||
}
|
||||
},
|
||||
|
||||
QueryInterface: XPCOMUtils.generateQI([
|
||||
Ci.nsIObserver,
|
||||
Ci.nsISupportsWeakReference
|
||||
])
|
||||
};
|
||||
|
||||
XPCOMUtils.defineLazyGetter(gSyncUI, "_stringBundle", function() {
|
||||
|
248
browser/base/content/browser-tabview.js
Normal file
248
browser/base/content/browser-tabview.js
Normal file
@ -0,0 +1,248 @@
|
||||
# ***** BEGIN LICENSE BLOCK *****
|
||||
# Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
#
|
||||
# The contents of this file are subject to the Mozilla Public License Version
|
||||
# 1.1 (the "License"); you may not use this file except in compliance with
|
||||
# the License. You may obtain a copy of the License at
|
||||
# http://www.mozilla.org/MPL/
|
||||
#
|
||||
# Software distributed under the License is distributed on an "AS IS" basis,
|
||||
# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
# for the specific language governing rights and limitations under the
|
||||
# License.
|
||||
#
|
||||
# The Original Code is the Tab View
|
||||
#
|
||||
# The Initial Developer of the Original Code is Mozilla Foundation.
|
||||
# Portions created by the Initial Developer are Copyright (C) 2010
|
||||
# the Initial Developer. All Rights Reserved.
|
||||
#
|
||||
# Contributor(s):
|
||||
# Raymond Lee <raymond@appcoast.com>
|
||||
# Ian Gilman <ian@iangilman.com>
|
||||
#
|
||||
# Alternatively, the contents of this file may be used under the terms of
|
||||
# either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
# in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
# of those above. If you wish to allow use of your version of this file only
|
||||
# under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
# use your version of this file under the terms of the MPL, indicate your
|
||||
# decision by deleting the provisions above and replace them with the notice
|
||||
# and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
# the provisions above, a recipient may use your version of this file under
|
||||
# the terms of any one of the MPL, the GPL or the LGPL.
|
||||
#
|
||||
# ***** END LICENSE BLOCK *****
|
||||
|
||||
let TabView = {
|
||||
_deck: null,
|
||||
_window: null,
|
||||
_sessionstore: null,
|
||||
_visibilityID: "tabview-visibility",
|
||||
|
||||
// ----------
|
||||
get windowTitle() {
|
||||
delete this.windowTitle;
|
||||
let brandBundle = document.getElementById("bundle_brand");
|
||||
let brandShortName = brandBundle.getString("brandShortName");
|
||||
let title = gNavigatorBundle.getFormattedString("tabView2.title", [brandShortName]);
|
||||
return this.windowTitle = title;
|
||||
},
|
||||
|
||||
// ----------
|
||||
init: function TabView_init() {
|
||||
// ___ keys
|
||||
this._setBrowserKeyHandlers();
|
||||
|
||||
// ___ visibility
|
||||
this._sessionstore =
|
||||
Cc["@mozilla.org/browser/sessionstore;1"].
|
||||
getService(Ci.nsISessionStore);
|
||||
|
||||
let data = this._sessionstore.getWindowValue(window, this._visibilityID);
|
||||
if (data && data == "true")
|
||||
this.show();
|
||||
},
|
||||
|
||||
// ----------
|
||||
// Creates the frame and calls the callback once it's loaded.
|
||||
// If the frame already exists, calls the callback immediately.
|
||||
_initFrame: function TabView__initFrame(callback) {
|
||||
if (this._window) {
|
||||
if (typeof callback == "function")
|
||||
callback();
|
||||
} else {
|
||||
// ___ find the deck
|
||||
this._deck = document.getElementById("tab-view-deck");
|
||||
|
||||
// ___ create the frame
|
||||
let iframe = document.createElement("iframe");
|
||||
iframe.id = "tab-view";
|
||||
iframe.setAttribute("transparent", "true");
|
||||
iframe.flex = 1;
|
||||
|
||||
if (typeof callback == "function")
|
||||
iframe.addEventListener("DOMContentLoaded", callback, false);
|
||||
|
||||
iframe.setAttribute("src", "chrome://browser/content/tabview.html");
|
||||
this._deck.appendChild(iframe);
|
||||
this._window = iframe.contentWindow;
|
||||
|
||||
// ___ visibility storage handler
|
||||
let self = this;
|
||||
function observer(subject, topic, data) {
|
||||
if (topic == "quit-application-requested") {
|
||||
let data = (self.isVisible() ? "true" : "false");
|
||||
self._sessionstore.setWindowValue(window, self._visibilityID, data);
|
||||
}
|
||||
}
|
||||
|
||||
Services.obs.addObserver(observer, "quit-application-requested", false);
|
||||
}
|
||||
},
|
||||
|
||||
// ----------
|
||||
isVisible: function() {
|
||||
return (this._deck ? this._deck.selectedIndex == 1 : false);
|
||||
},
|
||||
|
||||
// ----------
|
||||
show: function() {
|
||||
if (this.isVisible())
|
||||
return;
|
||||
|
||||
this._initFrame(function() {
|
||||
let event = document.createEvent("Events");
|
||||
event.initEvent("tabviewshow", false, false);
|
||||
dispatchEvent(event);
|
||||
});
|
||||
},
|
||||
|
||||
// ----------
|
||||
hide: function() {
|
||||
if (!this.isVisible())
|
||||
return;
|
||||
|
||||
let event = document.createEvent("Events");
|
||||
event.initEvent("tabviewhide", false, false);
|
||||
dispatchEvent(event);
|
||||
},
|
||||
|
||||
// ----------
|
||||
toggle: function() {
|
||||
if (this.isVisible())
|
||||
this.hide();
|
||||
else
|
||||
this.show();
|
||||
},
|
||||
|
||||
// ----------
|
||||
updateContextMenu: function(tab, popup) {
|
||||
let isEmpty = true;
|
||||
|
||||
while(popup.lastChild && popup.lastChild.id != "context_namedGroups")
|
||||
popup.removeChild(popup.lastChild);
|
||||
|
||||
let self = this;
|
||||
this._initFrame(function() {
|
||||
let activeGroup = tab.tabItem.parent;
|
||||
let groupItems = self._window.GroupItems.groupItems;
|
||||
|
||||
groupItems.forEach(function(groupItem) {
|
||||
if (groupItem.getTitle().length > 0 &&
|
||||
(!activeGroup || activeGroup.id != groupItem.id)) {
|
||||
let menuItem = self._createGroupMenuItem(groupItem);
|
||||
popup.appendChild(menuItem);
|
||||
isEmpty = false;
|
||||
}
|
||||
});
|
||||
document.getElementById("context_namedGroups").hidden = isEmpty;
|
||||
});
|
||||
},
|
||||
|
||||
// ----------
|
||||
_createGroupMenuItem : function(groupItem) {
|
||||
let menuItem = document.createElement("menuitem")
|
||||
menuItem.setAttribute("class", "group");
|
||||
menuItem.setAttribute("label", groupItem.getTitle());
|
||||
menuItem.setAttribute(
|
||||
"oncommand",
|
||||
"TabView.moveTabTo(TabContextMenu.contextTab,'" + groupItem.id + "')");
|
||||
|
||||
return menuItem;
|
||||
},
|
||||
|
||||
// ----------
|
||||
moveTabTo: function(tab, groupItemId) {
|
||||
if (this._window)
|
||||
this._window.GroupItems.moveTabToGroupItem(tab, groupItemId);
|
||||
},
|
||||
|
||||
// ----------
|
||||
// Adds new key commands to the browser, for invoking the Tab Candy UI
|
||||
// and for switching between groups of tabs when outside of the Tab Candy UI.
|
||||
_setBrowserKeyHandlers : function() {
|
||||
let self = this;
|
||||
|
||||
window.addEventListener("keypress", function(event) {
|
||||
if (self.isVisible())
|
||||
return;
|
||||
|
||||
let charCode = event.charCode;
|
||||
#ifdef XP_MACOSX
|
||||
// if a text box in a webpage has the focus, the event.altKey would
|
||||
// return false so we are depending on the charCode here.
|
||||
if (!event.ctrlKey && !event.metaKey && !event.shiftKey &&
|
||||
charCode == 160) { // alt + space
|
||||
#else
|
||||
if (event.ctrlKey && !event.metaKey && !event.shiftKey &&
|
||||
!event.altKey && charCode == 32) { // ctrl + space
|
||||
#endif
|
||||
|
||||
// Don't handle this event if it's coming from a node that might allow
|
||||
// multiple keyboard selection like selects or trees
|
||||
let node = event.target;
|
||||
switch (node.namespaceURI) {
|
||||
case "http://www.w3.org/1999/xhtml":
|
||||
// xhtml:select only allows multiple when the attr is set
|
||||
if (node.localName == "select" && node.hasAttribute("multiple"))
|
||||
return;
|
||||
break;
|
||||
|
||||
case "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul":
|
||||
switch (node.localName) {
|
||||
case "listbox":
|
||||
// xul:listbox is by default single
|
||||
if (node.getAttribute("seltype") == "multiple")
|
||||
return;
|
||||
break;
|
||||
case "tree":
|
||||
// xul:tree is by default multiple
|
||||
if (node.getAttribute("seltype") != "single")
|
||||
return;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
event.stopPropagation();
|
||||
event.preventDefault();
|
||||
self.show();
|
||||
return;
|
||||
}
|
||||
|
||||
// Control (+ Shift) + `
|
||||
if (event.ctrlKey && !event.metaKey && !event.altKey &&
|
||||
(charCode == 96 || charCode == 126)) {
|
||||
event.stopPropagation();
|
||||
event.preventDefault();
|
||||
|
||||
self._initFrame(function() {
|
||||
let tabItem = self._window.GroupItems.getNextGroupItemTab(event.shiftKey);
|
||||
if (tabItem)
|
||||
window.gBrowser.selectedTab = tabItem.tab;
|
||||
});
|
||||
}
|
||||
}, true);
|
||||
}
|
||||
};
|
@ -178,6 +178,7 @@ let gInitialPages = [
|
||||
#include inspector.js
|
||||
#include browser-places.js
|
||||
#include browser-tabPreviews.js
|
||||
#include browser-tabview.js
|
||||
|
||||
#ifdef MOZ_SERVICES_SYNC
|
||||
#include browser-syncui.js
|
||||
@ -749,7 +750,7 @@ const gXPInstallObserver = {
|
||||
PopupNotifications.remove(notification);
|
||||
|
||||
var needsRestart = installInfo.installs.some(function(i) {
|
||||
return (i.addon.pendingOperations & AddonManager.PENDING_INSTALL) != 0;
|
||||
return i.addon.pendingOperations != AddonManager.PENDING_NONE;
|
||||
});
|
||||
|
||||
if (needsRestart) {
|
||||
@ -1524,6 +1525,8 @@ function delayedStartup(isLoadingBlank, mustLoadSidebar) {
|
||||
gSyncUI.init();
|
||||
#endif
|
||||
|
||||
TabView.init();
|
||||
|
||||
Services.obs.notifyObservers(window, "browser-delayed-startup-finished", "");
|
||||
}
|
||||
|
||||
@ -2357,10 +2360,11 @@ function losslessDecodeURI(aURI) {
|
||||
value = value.replace(/[\v\x0c\x1c\x1d\x1e\x1f\u2028\u2029\ufffc]/g,
|
||||
encodeURIComponent);
|
||||
|
||||
// Encode default ignorable characters. (bug 546013)
|
||||
// Encode default ignorable characters (bug 546013)
|
||||
// except ZWNJ (U+200C) and ZWJ (U+200D) (bug 582186).
|
||||
// This includes all bidirectional formatting characters.
|
||||
// (RFC 3987 sections 3.2 and 4.1 paragraph 6)
|
||||
value = value.replace(/[\u00ad\u034f\u115f-\u1160\u17b4-\u17b5\u180b-\u180d\u200b-\u200f\u202a-\u202e\u2060-\u206f\u3164\ufe00-\ufe0f\ufeff\uffa0\ufff0-\ufff8]|\ud834[\udd73-\udd7a]|[\udb40-\udb43][\udc00-\udfff]/g,
|
||||
value = value.replace(/[\u00ad\u034f\u115f-\u1160\u17b4-\u17b5\u180b-\u180d\u200b\u200e-\u200f\u202a-\u202e\u2060-\u206f\u3164\ufe00-\ufe0f\ufeff\uffa0\ufff0-\ufff8]|\ud834[\udd73-\udd7a]|[\udb40-\udb43][\udc00-\udfff]/g,
|
||||
encodeURIComponent);
|
||||
return value;
|
||||
}
|
||||
@ -6769,6 +6773,8 @@ var gBookmarkAllTabsHandler = {
|
||||
this._command = document.getElementById("Browser:BookmarkAllTabs");
|
||||
gBrowser.tabContainer.addEventListener("TabOpen", this, true);
|
||||
gBrowser.tabContainer.addEventListener("TabClose", this, true);
|
||||
gBrowser.tabContainer.addEventListener("TabShow", this, true);
|
||||
gBrowser.tabContainer.addEventListener("TabHide", this, true);
|
||||
this._updateCommandState();
|
||||
},
|
||||
|
||||
|
@ -102,7 +102,7 @@
|
||||
|
||||
<script type="application/javascript" src="chrome://browser/content/places/editBookmarkOverlay.js"/>
|
||||
|
||||
# All sets except for popupsets (commands, keys, stringbundles and broadcasters) *must* go into the
|
||||
# All sets except for popupsets (commands, keys, stringbundles and broadcasters) *must* go into the
|
||||
# browser-sets.inc file for sharing with hiddenWindow.xul.
|
||||
#include browser-sets.inc
|
||||
|
||||
@ -126,6 +126,17 @@
|
||||
<menuitem id="context_unpinTab" label="&unpinTab.label;" hidden="true"
|
||||
accesskey="&unpinTab.accesskey;"
|
||||
oncommand="gBrowser.unpinTab(TabContextMenu.contextTab);"/>
|
||||
<menu id="context_tabViewMenu" label="&moveToGroup.label;"
|
||||
accesskey="&moveToGroup.accesskey;">
|
||||
<menupopup id="context_tabViewMenuPopup"
|
||||
onpopupshowing="if (event.target == this) TabView.updateContextMenu(TabContextMenu.contextTab, this);">
|
||||
<menuitem label="&moveToNewGroup.label;"
|
||||
accesskey="&moveToNewGroup.accesskey;"
|
||||
oncommand="TabView.moveTabTo(TabContextMenu.contextTab, null);"/>
|
||||
<menuitem id="context_namedGroups" label="&namedGroups.label;"
|
||||
disabled="true"/>
|
||||
</menupopup>
|
||||
</menu>
|
||||
<menuseparator/>
|
||||
<menuitem id="context_bookmarkTab"
|
||||
label="&bookmarkThisTab.label;"
|
||||
@ -231,7 +242,6 @@
|
||||
ignorekeys="true"
|
||||
noautofocus="true"
|
||||
noautohide="true"
|
||||
level="top"
|
||||
titlebar="normal"
|
||||
label="&inspectPanelTitle.label;">
|
||||
<toolbar id="inspector-toolbar"
|
||||
@ -255,7 +265,12 @@
|
||||
label="&inspectStyleButton.label;"
|
||||
accesskey="&inspectStyleButton.accesskey;"
|
||||
class="toolbarbutton-text"
|
||||
command="Inspector:Style"/>
|
||||
oncommand="InspectorUI.toggleStylePanel();'"/>
|
||||
<toolbarbutton id="inspector-dom-toolbutton"
|
||||
label="&inspectDOMButton.label;"
|
||||
accesskey="&inspectDOMButton.accesskey;"
|
||||
class="toolbarbutton-text"
|
||||
oncommand="InspectorUI.toggleDOMPanel();"/>
|
||||
</toolbar>
|
||||
<tree id="inspector-tree" class="plain"
|
||||
seltype="single"
|
||||
@ -283,13 +298,12 @@
|
||||
ignorekeys="true"
|
||||
noautofocus="true"
|
||||
noautohide="true"
|
||||
level="top"
|
||||
titlebar="normal"
|
||||
label="&inspectStylePanelTitle.label;">
|
||||
<listbox id="inspector-style-listbox" flex="1"/>
|
||||
<hbox align="end">
|
||||
<spacer flex="1" />
|
||||
<resizer dir="bottomend" />
|
||||
<resizer dir="bottomend"/>
|
||||
</hbox>
|
||||
</panel>
|
||||
|
||||
@ -519,6 +533,7 @@
|
||||
command="View:PageSource"/>
|
||||
<menuseparator/>
|
||||
<menuitem id="appmenu_pageInspect"
|
||||
type="checkbox"
|
||||
label="&inspectMenu.label;"
|
||||
command="Tools:Inspect"/>
|
||||
<menuitem id="appmenu_webConsole"
|
||||
@ -580,6 +595,9 @@
|
||||
</hbox>
|
||||
#endif
|
||||
|
||||
<deck flex="1" id="tab-view-deck">
|
||||
<vbox flex="1">
|
||||
|
||||
<toolbox id="navigator-toolbox"
|
||||
defaultmode="icons" mode="icons"
|
||||
#ifdef WINCE
|
||||
@ -893,7 +911,7 @@
|
||||
iconsize="small" defaulticonsize="small" lockiconsize="true"
|
||||
aria-label="&tabsToolbar.label;"
|
||||
context="toolbar-context-menu"
|
||||
defaultset="tabbrowser-tabs,new-tab-button,alltabs-button,tabs-closebutton"
|
||||
defaultset="tabbrowser-tabs,new-tab-button,tabview-button,alltabs-button,tabs-closebutton"
|
||||
collapsed="true">
|
||||
|
||||
<tabs id="tabbrowser-tabs"
|
||||
@ -927,6 +945,12 @@
|
||||
position="after_end"/>
|
||||
</toolbarbutton>
|
||||
|
||||
<toolbarbutton id="tabview-button" class="toolbarbutton-1 chromeclass-toolbar-additional"
|
||||
label="&tabViewButton2.label;"
|
||||
command="Browser:ToggleTabView"
|
||||
tooltiptext="&tabViewButton2.tooltip;"
|
||||
removable="true"/>
|
||||
|
||||
<toolbarbutton id="tabs-closebutton"
|
||||
class="close-button tabs-closebutton"
|
||||
command="cmd_close"
|
||||
@ -1040,7 +1064,7 @@
|
||||
onclick="if (event.button == 0 && event.detail == 1) displaySecurityInfo();"/>
|
||||
#ifdef MOZ_SERVICES_SYNC
|
||||
<statusbarpanel id="sync-status-button"
|
||||
class="statusbarpanel-iconic-text"
|
||||
class="statusbarpanel-iconic"
|
||||
image="chrome://browser/skin/sync-16.png"
|
||||
label="&syncLogInItem.label;"
|
||||
oncommand="gSyncUI.handleStatusbarButton();"
|
||||
@ -1081,4 +1105,11 @@
|
||||
</svg:mask>
|
||||
</svg:svg>
|
||||
#endif
|
||||
|
||||
</vbox>
|
||||
# <iframe id="tab-view"> is dynamically appended as the 2nd child of #tab-view-deck.
|
||||
# Introducing the iframe dynamically, as needed, was found to be better than
|
||||
# starting with an empty iframe here in browser.xul from a Ts standpoint.
|
||||
</deck>
|
||||
|
||||
</window>
|
||||
|
@ -61,40 +61,16 @@ const INSPECTOR_INVISIBLE_ELEMENTS = {
|
||||
*
|
||||
* @param aBrowser
|
||||
* The XUL browser object for the content window being highlighted.
|
||||
* @param aColor
|
||||
* A string containing an RGB color for the panel background.
|
||||
* @param aBorderSize
|
||||
* A number representing the border thickness of the panel.
|
||||
* @param anOpacity
|
||||
* A number representing the alpha value of the panel background.
|
||||
*/
|
||||
function PanelHighlighter(aBrowser, aColor, aBorderSize, anOpacity)
|
||||
function PanelHighlighter(aBrowser)
|
||||
{
|
||||
this.panel = document.getElementById("highlighter-panel");
|
||||
this.panel.hidden = false;
|
||||
this.browser = aBrowser;
|
||||
this.win = this.browser.contentWindow;
|
||||
this.backgroundColor = aColor;
|
||||
this.border = aBorderSize;
|
||||
this.opacity = anOpacity;
|
||||
this.updatePanelStyles();
|
||||
}
|
||||
|
||||
PanelHighlighter.prototype = {
|
||||
|
||||
/**
|
||||
* Update the panel's style object with current settings.
|
||||
* TODO see bugXXXXXX, https://wiki.mozilla.org/Firefox/Projects/Inspector#0.7
|
||||
* and, https://wiki.mozilla.org/Firefox/Projects/Inspector#1.0.
|
||||
*/
|
||||
updatePanelStyles: function PanelHighlighter_updatePanelStyles()
|
||||
{
|
||||
let style = this.panel.style;
|
||||
style.backgroundColor = this.backgroundColor;
|
||||
style.border = "solid blue " + this.border + "px";
|
||||
style.MozBorderRadius = "4px";
|
||||
style.opacity = this.opacity;
|
||||
},
|
||||
|
||||
/**
|
||||
* Highlight this.node, unhilighting first if necessary.
|
||||
@ -517,12 +493,6 @@ InspectorTreeView.prototype = {
|
||||
*/
|
||||
var InspectorUI = {
|
||||
browser: null,
|
||||
_showTreePanel: true,
|
||||
_showStylePanel: true,
|
||||
_showDOMPanel: false,
|
||||
highlightColor: "#EEEE66",
|
||||
highlightThickness: 4,
|
||||
highlightOpacity: 0.4,
|
||||
selectEventsSuppressed: false,
|
||||
inspecting: false,
|
||||
|
||||
@ -559,7 +529,7 @@ var InspectorUI = {
|
||||
*/
|
||||
toggleStylePanel: function IUI_toggleStylePanel()
|
||||
{
|
||||
if (this._showStylePanel) {
|
||||
if (this.isStylePanelOpen) {
|
||||
this.stylePanel.hidePopup();
|
||||
} else {
|
||||
this.openStylePanel();
|
||||
@ -567,7 +537,21 @@ var InspectorUI = {
|
||||
this.updateStylePanel(this.treeView.selectedNode);
|
||||
}
|
||||
}
|
||||
this._showStylePanel = !this._showStylePanel;
|
||||
},
|
||||
|
||||
/**
|
||||
* Toggle the DOM panel. Invoked from the toolbar's DOM button.
|
||||
*/
|
||||
toggleDOMPanel: function IUI_toggleDOMPanel()
|
||||
{
|
||||
if (this.isDOMPanelOpen) {
|
||||
this.domPanel.hidePopup();
|
||||
} else {
|
||||
this.openDOMPanel();
|
||||
if (this.treeView.selectedNode) {
|
||||
this.updateDOMPanel(this.treeView.selectedNode);
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
@ -590,6 +574,16 @@ var InspectorUI = {
|
||||
return this.stylePanel && this.stylePanel.state == "open";
|
||||
},
|
||||
|
||||
/**
|
||||
* Is the DOM panel open?
|
||||
*
|
||||
* @returns boolean
|
||||
*/
|
||||
get isDOMPanelOpen()
|
||||
{
|
||||
return this.domPanel && this.domPanel.state == "open";
|
||||
},
|
||||
|
||||
/**
|
||||
* Open the inspector's tree panel and initialize it.
|
||||
*/
|
||||
@ -603,7 +597,8 @@ var InspectorUI = {
|
||||
const panelWidthRatio = 7 / 8;
|
||||
const panelHeightRatio = 1 / 5;
|
||||
let bar = document.getElementById("status-bar");
|
||||
this.treePanel.openPopup(bar, "overlap", 120, -120, false, false);
|
||||
this.treePanel.openPopupAtScreen(this.win.screenX + 80,
|
||||
this.win.outerHeight + this.win.screenY);
|
||||
this.treePanel.sizeTo(this.win.outerWidth * panelWidthRatio,
|
||||
this.win.outerHeight * panelHeightRatio);
|
||||
this.tree = document.getElementById("inspector-tree");
|
||||
@ -616,11 +611,10 @@ var InspectorUI = {
|
||||
*/
|
||||
openStylePanel: function IUI_openStylePanel()
|
||||
{
|
||||
if (!this.stylePanel) {
|
||||
if (!this.stylePanel)
|
||||
this.stylePanel = document.getElementById("inspector-style-panel");
|
||||
this.stylePanel.hidden = false;
|
||||
}
|
||||
if (!this.isStylePanelOpen) {
|
||||
this.stylePanel.hidden = false;
|
||||
// open at top right of browser panel, offset by 20px from top.
|
||||
this.stylePanel.openPopup(this.browser, "end_before", 0, 20, false, false);
|
||||
// size panel to 200px wide by half browser height - 60.
|
||||
@ -628,6 +622,20 @@ var InspectorUI = {
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Open the DOM panel if not already onscreen.
|
||||
*/
|
||||
openDOMPanel: function IUI_openDOMPanel()
|
||||
{
|
||||
if (!this.isDOMPanelOpen) {
|
||||
// open at middle right of browser panel, offset by 20px from middle.
|
||||
this.domPanel.openPopup(this.browser, "end_before", 0,
|
||||
this.win.outerHeight / 2 - 20, false, false);
|
||||
// size panel to 200px wide by half browser height - 60.
|
||||
this.domPanel.sizeTo(200, this.win.outerHeight / 2 - 60);
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Toggle the dimmed (semi-transparent) state for a panel by setting or
|
||||
* removing a dimmed attribute.
|
||||
@ -644,11 +652,6 @@ var InspectorUI = {
|
||||
}
|
||||
},
|
||||
|
||||
openDOMPanel: function IUI_openDOMPanel()
|
||||
{
|
||||
// # todo bug 561782
|
||||
},
|
||||
|
||||
/**
|
||||
* Open inspector UI. tree, style and DOM panels if enabled. Add listeners for
|
||||
* document scrolling, resize and tabContainer.TabSelect.
|
||||
@ -658,24 +661,31 @@ var InspectorUI = {
|
||||
// initialization
|
||||
this.browser = gBrowser.selectedBrowser;
|
||||
this.win = this.browser.contentWindow;
|
||||
if (!this.style) {
|
||||
Cu.import("resource:///modules/stylePanel.jsm", this);
|
||||
this.style.initialize();
|
||||
}
|
||||
|
||||
// DOM panel initialization and loading (via PropertyPanel.jsm)
|
||||
let domPanelTitle = this.strings.GetStringFromName("dom.domPanelTitle");
|
||||
let parent = document.getElementById("inspector-style-panel").parentNode;
|
||||
this.propertyPanel = new (this.PropertyPanel)(parent, document, domPanelTitle, {});
|
||||
|
||||
// additional DOM panel setup needed for unittest identification and use
|
||||
this.domPanel = this.propertyPanel.panel;
|
||||
this.domPanel.setAttribute("id", "inspector-dom-panel");
|
||||
this.domBox = this.propertyPanel.tree;
|
||||
this.domTreeView = this.propertyPanel.treeView;
|
||||
|
||||
// open inspector UI
|
||||
if (this._showTreePanel) {
|
||||
this.openTreePanel();
|
||||
}
|
||||
if (this._showStylePanel) {
|
||||
this.styleBox = document.getElementById("inspector-style-listbox");
|
||||
this.clearStylePanel();
|
||||
this.openStylePanel();
|
||||
}
|
||||
if (this._showDOMPanel) {
|
||||
this.openDOMPanel();
|
||||
}
|
||||
this.inspectorBundle = Services.strings.createBundle("chrome://browser/locale/inspector.properties");
|
||||
this.openTreePanel();
|
||||
|
||||
// style panel setup and activation
|
||||
this.styleBox = document.getElementById("inspector-style-listbox");
|
||||
this.clearStylePanel();
|
||||
this.openStylePanel();
|
||||
|
||||
// DOM panel setup and activation
|
||||
this.clearDOMPanel();
|
||||
this.openDOMPanel();
|
||||
|
||||
// setup highlighter and start inspecting
|
||||
this.initializeHighlighter();
|
||||
this.startInspecting();
|
||||
this.win.document.addEventListener("scroll", this, false);
|
||||
@ -689,8 +699,7 @@ var InspectorUI = {
|
||||
*/
|
||||
initializeHighlighter: function IUI_initializeHighlighter()
|
||||
{
|
||||
this.highlighter = new PanelHighlighter(this.browser, this.highlightColor,
|
||||
this.highlightThickness, this.highlightOpacity);
|
||||
this.highlighter = new PanelHighlighter(this.browser);
|
||||
},
|
||||
|
||||
/**
|
||||
@ -714,6 +723,12 @@ var InspectorUI = {
|
||||
if (this.isStylePanelOpen) {
|
||||
this.stylePanel.hidePopup();
|
||||
}
|
||||
if (this.domPanel) {
|
||||
this.domPanel.hidePopup();
|
||||
this.domBox = null;
|
||||
this.domTreeView = null;
|
||||
this.propertyPanel.destroy();
|
||||
}
|
||||
this.inspectCmd.setAttribute("checked", false);
|
||||
this.browser = this.win = null; // null out references to browser and window
|
||||
},
|
||||
@ -727,6 +742,7 @@ var InspectorUI = {
|
||||
this.attachPageListeners();
|
||||
this.inspecting = true;
|
||||
this.toggleDimForPanel(this.stylePanel);
|
||||
this.toggleDimForPanel(this.domPanel);
|
||||
},
|
||||
|
||||
/**
|
||||
@ -740,8 +756,10 @@ var InspectorUI = {
|
||||
this.detachPageListeners();
|
||||
this.inspecting = false;
|
||||
this.toggleDimForPanel(this.stylePanel);
|
||||
this.toggleDimForPanel(this.domPanel);
|
||||
if (this.treeView.selection) {
|
||||
this.updateStylePanel(this.treeView.selectedNode);
|
||||
this.updateDOMPanel(this.treeView.selectedNode);
|
||||
}
|
||||
},
|
||||
|
||||
@ -757,7 +775,7 @@ var InspectorUI = {
|
||||
},
|
||||
|
||||
/**
|
||||
* add a new item to the listbox
|
||||
* Add a new item to the style panel listbox.
|
||||
*
|
||||
* @param aLabel
|
||||
* A bit of text to put in the listitem's label attribute.
|
||||
@ -768,7 +786,7 @@ var InspectorUI = {
|
||||
*/
|
||||
addStyleItem: function IUI_addStyleItem(aLabel, aType, aContent)
|
||||
{
|
||||
let itemLabelString = this.inspectorBundle.GetStringFromName("style.styleItemLabel");
|
||||
let itemLabelString = this.strings.GetStringFromName("style.styleItemLabel");
|
||||
let item = document.createElement("listitem");
|
||||
|
||||
// Do not localize these strings
|
||||
@ -791,7 +809,7 @@ var InspectorUI = {
|
||||
*/
|
||||
createStyleRuleItems: function IUI_createStyleRuleItems(aRules)
|
||||
{
|
||||
let selectorLabel = this.inspectorBundle.GetStringFromName("style.selectorLabel");
|
||||
let selectorLabel = this.strings.GetStringFromName("style.selectorLabel");
|
||||
|
||||
aRules.forEach(function(rule) {
|
||||
this.addStyleItem(selectorLabel, "selector", rule.id);
|
||||
@ -821,7 +839,7 @@ var InspectorUI = {
|
||||
{
|
||||
this.createStyleRuleItems(aRules);
|
||||
let inheritedString =
|
||||
this.inspectorBundle.GetStringFromName("style.inheritedFrom");
|
||||
this.strings.GetStringFromName("style.inheritedFrom");
|
||||
aSections.forEach(function(section) {
|
||||
let sectionTitle = section.element.tagName;
|
||||
if (section.element.id)
|
||||
@ -841,6 +859,14 @@ var InspectorUI = {
|
||||
this.styleBox.removeItemAt(i);
|
||||
},
|
||||
|
||||
/**
|
||||
* Remove all items from the DOM Panel's listbox.
|
||||
*/
|
||||
clearDOMPanel: function IUI_clearStylePanel()
|
||||
{
|
||||
this.domTreeView.data = {};
|
||||
},
|
||||
|
||||
/**
|
||||
* Update the contents of the style panel with styles for the currently
|
||||
* inspected node.
|
||||
@ -850,8 +876,10 @@ var InspectorUI = {
|
||||
*/
|
||||
updateStylePanel: function IUI_updateStylePanel(aNode)
|
||||
{
|
||||
if (this.inspecting || !this.isStylePanelOpen)
|
||||
if (this.inspecting || !this.isStylePanelOpen) {
|
||||
return;
|
||||
}
|
||||
|
||||
let rules = [], styleSections = [], usedProperties = {};
|
||||
this.style.getInheritedRules(aNode, styleSections, usedProperties);
|
||||
this.style.getElementRules(aNode, rules, usedProperties);
|
||||
@ -859,6 +887,19 @@ var InspectorUI = {
|
||||
this.createStyleItems(rules, styleSections);
|
||||
},
|
||||
|
||||
/**
|
||||
* Update the contents of the DOM panel with name/value pairs for the
|
||||
* currently-inspected node.
|
||||
*/
|
||||
updateDOMPanel: function IUI_updateDOMPanel(aNode)
|
||||
{
|
||||
if (this.inspecting || !this.isDOMPanelOpen) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.domTreeView.data = aNode;
|
||||
},
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
//// Event Handling
|
||||
|
||||
@ -908,11 +949,11 @@ var InspectorUI = {
|
||||
return false;
|
||||
}
|
||||
|
||||
let treeView = this.treeView;
|
||||
let node = treeView.selectedNode;
|
||||
let node = this.treeView.selectedNode;
|
||||
this.highlighter.highlightNode(node);
|
||||
this.stopInspecting();
|
||||
this.updateStylePanel(node);
|
||||
this.updateDOMPanel(node);
|
||||
return true;
|
||||
},
|
||||
|
||||
@ -955,6 +996,7 @@ var InspectorUI = {
|
||||
this.treeView.selectedNode = aNode;
|
||||
this.selectEventsSuppressed = false;
|
||||
this.updateStylePanel(aNode);
|
||||
this.updateDOMPanel(aNode);
|
||||
},
|
||||
|
||||
/**
|
||||
@ -1000,7 +1042,33 @@ var InspectorUI = {
|
||||
},
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
//// Initializors
|
||||
|
||||
XPCOMUtils.defineLazyGetter(InspectorUI, "inspectCmd", function () {
|
||||
return document.getElementById("Tools:Inspect");
|
||||
});
|
||||
|
||||
XPCOMUtils.defineLazyGetter(InspectorUI, "strings", function () {
|
||||
return Services.strings.createBundle("chrome://browser/locale/inspector.properties");
|
||||
});
|
||||
|
||||
XPCOMUtils.defineLazyGetter(InspectorUI, "PropertyTreeView", function () {
|
||||
var obj = {};
|
||||
Cu.import("resource://gre/modules/PropertyPanel.jsm", obj);
|
||||
return obj.PropertyTreeView;
|
||||
});
|
||||
|
||||
XPCOMUtils.defineLazyGetter(InspectorUI, "PropertyPanel", function () {
|
||||
var obj = {};
|
||||
Cu.import("resource://gre/modules/PropertyPanel.jsm", obj);
|
||||
return obj.PropertyPanel;
|
||||
});
|
||||
|
||||
XPCOMUtils.defineLazyGetter(InspectorUI, "style", function () {
|
||||
var obj = {};
|
||||
Cu.import("resource:///modules/stylePanel.jsm", obj);
|
||||
obj.style.initialize();
|
||||
return obj.style;
|
||||
});
|
||||
|
||||
|
@ -88,8 +88,13 @@
|
||||
<field name="tabs" readonly="true">
|
||||
this.tabContainer.childNodes;
|
||||
</field>
|
||||
<property name="visibleTabs" readonly="true"
|
||||
onget="return Array.filter(this.tabs, function(tab) !tab.hidden);"/>
|
||||
<property name="visibleTabs" readonly="true">
|
||||
<getter><![CDATA[
|
||||
return Array.filter(this.tabs, function(tab) {
|
||||
return !tab.hidden && this._removingTabs.indexOf(tab) == -1;
|
||||
}, this);
|
||||
]]></getter>
|
||||
</property>
|
||||
<field name="mURIFixup" readonly="true">
|
||||
Components.classes["@mozilla.org/docshell/urifixup;1"]
|
||||
.getService(Components.interfaces.nsIURIFixup);
|
||||
@ -510,9 +515,12 @@
|
||||
this.mBrowser.mIconURL = null;
|
||||
|
||||
let browserHistory = this.mTabBrowser.mBrowserHistory;
|
||||
if (this.mBrowser.lastURI)
|
||||
browserHistory.unregisterOpenPage(this.mBrowser.lastURI);
|
||||
if (this.mBrowser.registeredOpenURI) {
|
||||
browserHistory.unregisterOpenPage(this.mBrowser.registeredOpenURI);
|
||||
delete this.mBrowser.registeredOpenURI;
|
||||
}
|
||||
browserHistory.registerOpenPage(aLocation);
|
||||
this.mBrowser.registeredOpenURI = aLocation;
|
||||
}
|
||||
|
||||
if (!this.mBlank) {
|
||||
@ -723,7 +731,13 @@
|
||||
<method name="updateTitlebar">
|
||||
<body>
|
||||
<![CDATA[
|
||||
this.ownerDocument.title = this.getWindowTitleForBrowser(this.mCurrentBrowser);
|
||||
if (window.TabView && TabView.isVisible()) {
|
||||
// ToDo: this will be removed when we gain ability to draw to the menu bar.
|
||||
// Bug 586175
|
||||
this.ownerDocument.title = TabView.windowTitle;
|
||||
} else {
|
||||
this.ownerDocument.title = this.getWindowTitleForBrowser(this.mCurrentBrowser);
|
||||
}
|
||||
]]>
|
||||
</body>
|
||||
</method>
|
||||
@ -760,7 +774,7 @@
|
||||
newBrowser.docShell.isActive = true;
|
||||
this.mCurrentBrowser = newBrowser;
|
||||
this.mCurrentTab = this.selectedTab;
|
||||
this.mCurrentTab.hidden = false;
|
||||
this.showTab(this.mCurrentTab);
|
||||
|
||||
if (updatePageReport)
|
||||
this.mCurrentBrowser.updatePageReport();
|
||||
@ -1429,8 +1443,10 @@
|
||||
filter.removeProgressListener(this.mTabListeners[aTab._tPos]);
|
||||
this.mTabListeners[aTab._tPos].destroy();
|
||||
|
||||
if (browser.currentURI)
|
||||
this.mBrowserHistory.unregisterOpenPage(browser.currentURI);
|
||||
if (browser.registeredOpenURI) {
|
||||
this.mBrowserHistory.unregisterOpenPage(browser.registeredOpenURI);
|
||||
delete browser.registeredOpenURI;
|
||||
}
|
||||
|
||||
// We are no longer the primary content area.
|
||||
browser.setAttribute("type", "content-targetable");
|
||||
@ -1578,17 +1594,15 @@
|
||||
return;
|
||||
}
|
||||
|
||||
let removing = this._removingTabs;
|
||||
function keepRemaining(tab) {
|
||||
// A tab remains only if it's not being removed nor blurred
|
||||
return removing.indexOf(tab) == -1 && tab != aTab;
|
||||
// Switch to a visible tab unless there aren't any others remaining
|
||||
let remainingTabs = this.visibleTabs;
|
||||
let numTabs = remainingTabs.length;
|
||||
if (numTabs == 0 || numTabs == 1 && remainingTabs[0] == aTab) {
|
||||
remainingTabs = Array.filter(this.tabs, function(tab) {
|
||||
return this._removingTabs.indexOf(tab) == -1;
|
||||
}, this);
|
||||
}
|
||||
|
||||
// Switch to a visible tab unless there aren't any remaining
|
||||
let remainingTabs = this.visibleTabs.filter(keepRemaining);
|
||||
if (remainingTabs.length == 0)
|
||||
remainingTabs = Array.filter(this.tabs, keepRemaining);
|
||||
|
||||
// Try to find a remaining tab that comes after the given tab
|
||||
var tab = aTab;
|
||||
do {
|
||||
@ -1782,8 +1796,40 @@
|
||||
<body>
|
||||
<![CDATA[
|
||||
Array.forEach(this.tabs, function(tab) {
|
||||
tab.hidden = aTabs.indexOf(tab) == -1 && !tab.pinned && !tab.selected;
|
||||
});
|
||||
if (aTabs.indexOf(tab) == -1)
|
||||
this.hideTab(tab);
|
||||
else
|
||||
this.showTab(tab);
|
||||
}, this);
|
||||
]]>
|
||||
</body>
|
||||
</method>
|
||||
|
||||
<method name="showTab">
|
||||
<parameter name="aTab"/>
|
||||
<body>
|
||||
<![CDATA[
|
||||
if (aTab.hidden) {
|
||||
aTab.hidden = false;
|
||||
let event = document.createEvent("Events");
|
||||
event.initEvent("TabShow", true, false);
|
||||
aTab.dispatchEvent(event);
|
||||
}
|
||||
]]>
|
||||
</body>
|
||||
</method>
|
||||
|
||||
<method name="hideTab">
|
||||
<parameter name="aTab"/>
|
||||
<body>
|
||||
<![CDATA[
|
||||
if (!aTab.hidden && !aTab.pinned && !aTab.selected &&
|
||||
this._removingTabs.indexOf(aTab) == -1) {
|
||||
aTab.hidden = true;
|
||||
let event = document.createEvent("Events");
|
||||
event.initEvent("TabHide", true, false);
|
||||
aTab.dispatchEvent(event);
|
||||
}
|
||||
]]>
|
||||
</body>
|
||||
</method>
|
||||
@ -2305,7 +2351,10 @@
|
||||
<![CDATA[
|
||||
for (var i = 0; i < this.mTabListeners.length; ++i) {
|
||||
let browser = this.getBrowserAtIndex(i);
|
||||
this.mBrowserHistory.unregisterOpenPage(browser.currentURI);
|
||||
if (browser.registeredOpenURI) {
|
||||
this.mBrowserHistory.unregisterOpenPage(browser.registeredOpenURI);
|
||||
delete browser.registeredOpenURI;
|
||||
}
|
||||
browser.webProgress.removeProgressListener(this.mTabFilters[i]);
|
||||
this.mTabFilters[i].removeProgressListener(this.mTabListeners[i]);
|
||||
this.mTabFilters[i] = null;
|
||||
@ -2606,8 +2655,7 @@
|
||||
if (this.childNodes.length == 1 && this._closeWindowWithLastTab)
|
||||
this.setAttribute("closebuttons", "noclose");
|
||||
else {
|
||||
// Grab the last tab for size comparison
|
||||
let tab = this.tabbrowser.visibleTabs.pop();
|
||||
let tab = this.tabbrowser.visibleTabs[this.tabbrowser._numPinnedTabs];
|
||||
if (tab && tab.getBoundingClientRect().width > this.mTabClipWidth)
|
||||
this.setAttribute("closebuttons", "alltabs");
|
||||
else
|
||||
|
296
browser/base/content/tabview/drag.js
Normal file
296
browser/base/content/tabview/drag.js
Normal file
@ -0,0 +1,296 @@
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is drag.js.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* the Mozilla Foundation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2010
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Michael Yoshitaka Erlewine <mitcho@mitcho.com>
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
// **********
|
||||
// Title: drag.js
|
||||
|
||||
// ----------
|
||||
// Variable: drag
|
||||
// The Drag that's currently in process.
|
||||
var drag = {
|
||||
info: null,
|
||||
zIndex: 100
|
||||
};
|
||||
|
||||
|
||||
// ##########
|
||||
// Class: Drag (formerly DragInfo)
|
||||
// Helper class for dragging <Item>s
|
||||
//
|
||||
// ----------
|
||||
// Constructor: Drag
|
||||
// Called to create a Drag in response to an <Item> draggable "start" event.
|
||||
// Note that it is also used partially during <Item>'s resizable method as well.
|
||||
//
|
||||
// Parameters:
|
||||
// item - The <Item> being dragged
|
||||
// event - The DOM event that kicks off the drag
|
||||
// isResizing - (boolean) is this a resizing instance? or (if false) dragging?
|
||||
// isFauxDrag - (boolean) true if a faux drag, which is used when simply snapping.
|
||||
var Drag = function(item, event, isResizing, isFauxDrag) {
|
||||
Utils.assert(item && (item.isAnItem || item.isAFauxItem),
|
||||
'must be an item, or at least a faux item');
|
||||
|
||||
this.isResizing = isResizing || false;
|
||||
this.item = item;
|
||||
this.el = item.container;
|
||||
this.$el = iQ(this.el);
|
||||
this.parent = this.item.parent;
|
||||
this.startPosition = new Point(event.clientX, event.clientY);
|
||||
this.startTime = Date.now();
|
||||
|
||||
this.item.isDragging = true;
|
||||
this.item.setZ(999999);
|
||||
|
||||
this.safeWindowBounds = Items.getSafeWindowBounds();
|
||||
|
||||
Trenches.activateOthersTrenches(this.el);
|
||||
|
||||
if (!isFauxDrag) {
|
||||
// When a tab drag starts, make it the focused tab.
|
||||
if (this.item.isAGroupItem) {
|
||||
var tab = UI.getActiveTab();
|
||||
if (!tab || tab.parent != this.item) {
|
||||
if (this.item._children.length)
|
||||
UI.setActiveTab(this.item._children[0]);
|
||||
}
|
||||
} else if (this.item.isATabItem) {
|
||||
UI.setActiveTab(this.item);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
Drag.prototype = {
|
||||
// ----------
|
||||
// Function: snapBounds
|
||||
// Adjusts the given bounds according to the currently active trenches. Used by <Drag.snap>
|
||||
//
|
||||
// Parameters:
|
||||
// bounds - (<Rect>) bounds
|
||||
// stationaryCorner - which corner is stationary? by default, the top left.
|
||||
// "topleft", "bottomleft", "topright", "bottomright"
|
||||
// assumeConstantSize - (boolean) whether the bounds' dimensions are sacred or not.
|
||||
// keepProportional - (boolean) if assumeConstantSize is false, whether we should resize
|
||||
// proportionally or not
|
||||
// checkItemStatus - (boolean) make sure this is a valid item which should be snapped
|
||||
snapBounds: function Drag_snapBounds(bounds, stationaryCorner, assumeConstantSize, keepProportional, checkItemStatus) {
|
||||
if (!stationaryCorner)
|
||||
stationaryCorner || 'topleft';
|
||||
var update = false; // need to update
|
||||
var updateX = false;
|
||||
var updateY = false;
|
||||
var newRect;
|
||||
var snappedTrenches = {};
|
||||
|
||||
// OH SNAP!
|
||||
|
||||
// if we aren't holding down the meta key...
|
||||
if (!Keys.meta) {
|
||||
// snappable = true if we aren't a tab on top of something else, and
|
||||
// there's no active drop site...
|
||||
let snappable = !(this.item.isATabItem &&
|
||||
this.item.overlapsWithOtherItems()) &&
|
||||
!iQ(".acceptsDrop").length;
|
||||
if (!checkItemStatus || snappable) {
|
||||
newRect = Trenches.snap(bounds, stationaryCorner, assumeConstantSize,
|
||||
keepProportional);
|
||||
if (newRect) { // might be false if no changes were made
|
||||
update = true;
|
||||
snappedTrenches = newRect.snappedTrenches || {};
|
||||
bounds = newRect;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// make sure the bounds are in the window.
|
||||
newRect = this.snapToEdge(bounds, stationaryCorner, assumeConstantSize,
|
||||
keepProportional);
|
||||
if (newRect) {
|
||||
update = true;
|
||||
bounds = newRect;
|
||||
Utils.extend(snappedTrenches, newRect.snappedTrenches);
|
||||
}
|
||||
|
||||
Trenches.hideGuides();
|
||||
for (var edge in snappedTrenches) {
|
||||
var trench = snappedTrenches[edge];
|
||||
if (typeof trench == 'object') {
|
||||
trench.showGuide = true;
|
||||
trench.show();
|
||||
}
|
||||
}
|
||||
|
||||
return update ? bounds : false;
|
||||
},
|
||||
|
||||
// ----------
|
||||
// Function: snap
|
||||
// Called when a drag or mousemove occurs. Set the bounds based on the mouse move first, then
|
||||
// call snap and it will adjust the item's bounds if appropriate. Also triggers the display of
|
||||
// trenches that it snapped to.
|
||||
//
|
||||
// Parameters:
|
||||
// stationaryCorner - which corner is stationary? by default, the top left.
|
||||
// "topleft", "bottomleft", "topright", "bottomright"
|
||||
// assumeConstantSize - (boolean) whether the bounds' dimensions are sacred or not.
|
||||
// keepProportional - (boolean) if assumeConstantSize is false, whether we should resize
|
||||
// proportionally or not
|
||||
snap: function Drag_snap(stationaryCorner, assumeConstantSize, keepProportional) {
|
||||
var bounds = this.item.getBounds();
|
||||
bounds = this.snapBounds(bounds, stationaryCorner, assumeConstantSize, keepProportional, true);
|
||||
if (bounds) {
|
||||
this.item.setBounds(bounds, true);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
},
|
||||
|
||||
// --------
|
||||
// Function: snapToEdge
|
||||
// Returns a version of the bounds snapped to the edge if it is close enough. If not,
|
||||
// returns false. If <Keys.meta> is true, this function will simply enforce the
|
||||
// window edges.
|
||||
//
|
||||
// Parameters:
|
||||
// rect - (<Rect>) current bounds of the object
|
||||
// stationaryCorner - which corner is stationary? by default, the top left.
|
||||
// "topleft", "bottomleft", "topright", "bottomright"
|
||||
// assumeConstantSize - (boolean) whether the rect's dimensions are sacred or not
|
||||
// keepProportional - (boolean) if we are allowed to change the rect's size, whether the
|
||||
// dimensions should scaled proportionally or not.
|
||||
snapToEdge: function Drag_snapToEdge(rect, stationaryCorner, assumeConstantSize, keepProportional) {
|
||||
|
||||
var swb = this.safeWindowBounds;
|
||||
var update = false;
|
||||
var updateX = false;
|
||||
var updateY = false;
|
||||
var snappedTrenches = {};
|
||||
|
||||
var snapRadius = (Keys.meta ? 0 : Trenches.defaultRadius);
|
||||
if (rect.left < swb.left + snapRadius ) {
|
||||
if (stationaryCorner.indexOf('right') > -1)
|
||||
rect.width = rect.right - swb.left;
|
||||
rect.left = swb.left;
|
||||
update = true;
|
||||
updateX = true;
|
||||
snappedTrenches.left = 'edge';
|
||||
}
|
||||
|
||||
if (rect.right > swb.right - snapRadius) {
|
||||
if (updateX || !assumeConstantSize) {
|
||||
var newWidth = swb.right - rect.left;
|
||||
if (keepProportional)
|
||||
rect.height = rect.height * newWidth / rect.width;
|
||||
rect.width = newWidth;
|
||||
update = true;
|
||||
} else if (!updateX || !Trenches.preferLeft) {
|
||||
rect.left = swb.right - rect.width;
|
||||
update = true;
|
||||
}
|
||||
snappedTrenches.right = 'edge';
|
||||
delete snappedTrenches.left;
|
||||
}
|
||||
if (rect.top < swb.top + snapRadius) {
|
||||
if (stationaryCorner.indexOf('bottom') > -1)
|
||||
rect.height = rect.bottom - swb.top;
|
||||
rect.top = swb.top;
|
||||
update = true;
|
||||
updateY = true;
|
||||
snappedTrenches.top = 'edge';
|
||||
}
|
||||
if (rect.bottom > swb.bottom - snapRadius) {
|
||||
if (updateY || !assumeConstantSize) {
|
||||
var newHeight = swb.bottom - rect.top;
|
||||
if (keepProportional)
|
||||
rect.width = rect.width * newHeight / rect.height;
|
||||
rect.height = newHeight;
|
||||
update = true;
|
||||
} else if (!updateY || !Trenches.preferTop) {
|
||||
rect.top = swb.bottom - rect.height;
|
||||
update = true;
|
||||
}
|
||||
snappedTrenches.top = 'edge';
|
||||
delete snappedTrenches.bottom;
|
||||
}
|
||||
|
||||
if (update) {
|
||||
rect.snappedTrenches = snappedTrenches;
|
||||
return rect;
|
||||
}
|
||||
return false;
|
||||
},
|
||||
|
||||
// ----------
|
||||
// Function: drag
|
||||
// Called in response to an <Item> draggable "drag" event.
|
||||
drag: function(event) {
|
||||
this.snap('topleft', true);
|
||||
|
||||
if (this.parent && this.parent.expanded) {
|
||||
var distance = this.startPosition.distance(new Point(event.clientX, event.clientY));
|
||||
if (distance > 100) {
|
||||
this.parent.remove(this.item);
|
||||
this.parent.collapse();
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
// ----------
|
||||
// Function: stop
|
||||
// Called in response to an <Item> draggable "stop" event.
|
||||
stop: function() {
|
||||
Trenches.hideGuides();
|
||||
this.item.isDragging = false;
|
||||
|
||||
if (this.parent && !this.parent.locked.close && this.parent != this.item.parent &&
|
||||
this.parent.isEmpty()) {
|
||||
this.parent.close();
|
||||
}
|
||||
|
||||
if (this.parent && this.parent.expanded)
|
||||
this.parent.arrange();
|
||||
|
||||
if (this.item && !this.item.parent) {
|
||||
this.item.setZ(drag.zIndex);
|
||||
drag.zIndex++;
|
||||
|
||||
this.item.pushAway();
|
||||
}
|
||||
|
||||
Trenches.disactivate();
|
||||
}
|
||||
};
|
1771
browser/base/content/tabview/groupitems.js
Normal file
1771
browser/base/content/tabview/groupitems.js
Normal file
File diff suppressed because it is too large
Load Diff
258
browser/base/content/tabview/infoitems.js
Normal file
258
browser/base/content/tabview/infoitems.js
Normal file
@ -0,0 +1,258 @@
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is infoitems.js.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* the Mozilla Foundation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2010
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Ian Gilman <ian@iangilman.com>
|
||||
* Aza Raskin <aza@mozilla.com>
|
||||
* Michael Yoshitaka Erlewine <mitcho@mitcho.com>
|
||||
* Ehsan Akhgari <ehsan@mozilla.com>
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
// **********
|
||||
// Title: infoitems.js
|
||||
|
||||
(function() {
|
||||
|
||||
// ##########
|
||||
// Class: InfoItem
|
||||
// An <Item> in TabView used for displaying information, such as the welcome video.
|
||||
// Note that it implements the <Subscribable> interface.
|
||||
//
|
||||
// ----------
|
||||
// Constructor: InfoItem
|
||||
//
|
||||
// Parameters:
|
||||
// bounds - a <Rect> for where the item should be located
|
||||
// options - various options for this infoItem (see below)
|
||||
//
|
||||
// Possible options:
|
||||
// locked - see <Item.locked>; default is {}
|
||||
// dontPush - true if this infoItem shouldn't push away on creation; default is false
|
||||
window.InfoItem = function(bounds, options) {
|
||||
try {
|
||||
Utils.assertThrow(Utils.isRect(bounds), 'bounds');
|
||||
|
||||
if (typeof options == 'undefined')
|
||||
options = {};
|
||||
|
||||
this._inited = false;
|
||||
this.isAnInfoItem = true;
|
||||
this.defaultSize = bounds.size();
|
||||
this.locked = (options.locked ? Utils.copy(options.locked) : {});
|
||||
this.bounds = new Rect(bounds);
|
||||
this.isDragging = false;
|
||||
|
||||
var self = this;
|
||||
|
||||
var $container = iQ('<div>')
|
||||
.addClass('info-item')
|
||||
.css(this.bounds)
|
||||
.appendTo('body');
|
||||
|
||||
this.$contents = iQ('<div>')
|
||||
.appendTo($container);
|
||||
|
||||
var $close = iQ('<div>')
|
||||
.addClass('close')
|
||||
.click(function() {
|
||||
self.close();
|
||||
})
|
||||
.appendTo($container);
|
||||
|
||||
// ___ locking
|
||||
if (this.locked.bounds)
|
||||
$container.css({cursor: 'default'});
|
||||
|
||||
if (this.locked.close)
|
||||
$close.hide();
|
||||
|
||||
// ___ Superclass initialization
|
||||
this._init($container[0]);
|
||||
|
||||
if (this.$debug)
|
||||
this.$debug.css({zIndex: -1000});
|
||||
|
||||
// ___ Finish Up
|
||||
if (!this.locked.bounds)
|
||||
this.draggable();
|
||||
|
||||
// ___ Position
|
||||
this.snap();
|
||||
|
||||
// ___ Push other objects away
|
||||
if (!options.dontPush)
|
||||
this.pushAway();
|
||||
|
||||
this._inited = true;
|
||||
this.save();
|
||||
} catch(e) {
|
||||
Utils.log(e);
|
||||
}
|
||||
};
|
||||
|
||||
// ----------
|
||||
window.InfoItem.prototype = Utils.extend(new Item(), new Subscribable(), {
|
||||
|
||||
// ----------
|
||||
// Function: getStorageData
|
||||
// Returns all of the info worth storing about this item.
|
||||
getStorageData: function() {
|
||||
var data = null;
|
||||
|
||||
try {
|
||||
data = {
|
||||
bounds: this.getBounds(),
|
||||
locked: Utils.copy(this.locked)
|
||||
};
|
||||
} catch(e) {
|
||||
Utils.log(e);
|
||||
}
|
||||
|
||||
return data;
|
||||
},
|
||||
|
||||
// ----------
|
||||
// Function: save
|
||||
// Saves this item to persistent storage.
|
||||
save: function() {
|
||||
try {
|
||||
if (!this._inited) // too soon to save now
|
||||
return;
|
||||
|
||||
var data = this.getStorageData();
|
||||
|
||||
} catch(e) {
|
||||
Utils.log(e);
|
||||
}
|
||||
},
|
||||
|
||||
// ----------
|
||||
// Function: setBounds
|
||||
// Sets the bounds with the given <Rect>, animating unless "immediately" is false.
|
||||
setBounds: function(rect, immediately) {
|
||||
try {
|
||||
Utils.assertThrow(Utils.isRect(rect), 'InfoItem.setBounds: rect must be a real rectangle!');
|
||||
|
||||
// ___ Determine what has changed
|
||||
var css = {};
|
||||
|
||||
if (rect.left != this.bounds.left)
|
||||
css.left = rect.left;
|
||||
|
||||
if (rect.top != this.bounds.top)
|
||||
css.top = rect.top;
|
||||
|
||||
if (rect.width != this.bounds.width)
|
||||
css.width = rect.width;
|
||||
|
||||
if (rect.height != this.bounds.height)
|
||||
css.height = rect.height;
|
||||
|
||||
if (Utils.isEmptyObject(css))
|
||||
return;
|
||||
|
||||
this.bounds = new Rect(rect);
|
||||
Utils.assertThrow(Utils.isRect(this.bounds),
|
||||
'InfoItem.setBounds: this.bounds must be a real rectangle!');
|
||||
|
||||
// ___ Update our representation
|
||||
if (immediately) {
|
||||
iQ(this.container).css(css);
|
||||
} else {
|
||||
TabItems.pausePainting();
|
||||
iQ(this.container).animate(css, {
|
||||
duration: 350,
|
||||
easing: "tabviewBounce",
|
||||
complete: function() {
|
||||
TabItems.resumePainting();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
this._updateDebugBounds();
|
||||
this.setTrenches(rect);
|
||||
this.save();
|
||||
} catch(e) {
|
||||
Utils.log(e);
|
||||
}
|
||||
},
|
||||
|
||||
// ----------
|
||||
// Function: setZ
|
||||
// Set the Z order for the item's container.
|
||||
setZ: function(value) {
|
||||
try {
|
||||
Utils.assertThrow(typeof value == 'number', 'value must be a number');
|
||||
|
||||
this.zIndex = value;
|
||||
|
||||
iQ(this.container).css({zIndex: value});
|
||||
|
||||
if (this.$debug)
|
||||
this.$debug.css({zIndex: value + 1});
|
||||
} catch(e) {
|
||||
Utils.log(e);
|
||||
}
|
||||
},
|
||||
|
||||
// ----------
|
||||
// Function: close
|
||||
// Closes the item.
|
||||
close: function() {
|
||||
try {
|
||||
this._sendToSubscribers("close");
|
||||
this.removeTrenches();
|
||||
iQ(this.container).fadeOut(function() {
|
||||
iQ(this).remove();
|
||||
Items.unsquish();
|
||||
});
|
||||
|
||||
} catch(e) {
|
||||
Utils.log(e);
|
||||
}
|
||||
},
|
||||
|
||||
// ----------
|
||||
// Function: html
|
||||
// Sets the item's container's html to the specified value.
|
||||
html: function(value) {
|
||||
try {
|
||||
Utils.assertThrow(typeof value == 'string', 'value must be a string');
|
||||
this.$contents.html(value);
|
||||
} catch(e) {
|
||||
Utils.log(e);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
})();
|
@ -531,9 +531,7 @@ iQClass.prototype = {
|
||||
options = {};
|
||||
|
||||
let easings = {
|
||||
tabviewBounce: "cubic-bezier(0.0, 0.63, .6, 1.0)",
|
||||
// TODO: change 1.0 above to 1.29 after bug 575672 is fixed
|
||||
|
||||
tabviewBounce: "cubic-bezier(0.0, 0.63, .6, 1.29)",
|
||||
easeInQuad: 'ease-in', // TODO: make it a real easeInQuad, or decide we don't care
|
||||
fast: 'cubic-bezier(0.7,0,1,1)'
|
||||
};
|
||||
|
1067
browser/base/content/tabview/items.js
Normal file
1067
browser/base/content/tabview/items.js
Normal file
File diff suppressed because it is too large
Load Diff
70
browser/base/content/tabview/modules/groups.jsm
Normal file
70
browser/base/content/tabview/modules/groups.jsm
Normal file
@ -0,0 +1,70 @@
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is TabView Groups.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Mozilla Foundation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2010
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Edward Lee <edilee@mozilla.com>
|
||||
* Ian Gilman <ian@iangilman.com>
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
const Cc = Components.classes;
|
||||
const Ci = Components.interfaces;
|
||||
const Cu = Components.utils;
|
||||
const Cr = Components.results;
|
||||
|
||||
Cu.import("resource://gre/modules/Services.jsm");
|
||||
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||
|
||||
let EXPORTED_SYMBOLS = ["Groups"];
|
||||
|
||||
let Groups = let (T = {
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//// Public
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//// Private
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
init: function init() {
|
||||
// Only allow calling init once
|
||||
T.init = function() T;
|
||||
|
||||
// load all groups data
|
||||
// presumably we can load from app global, not a window
|
||||
// how do we know which window has which group?
|
||||
// load tab data to figure out which go into which group
|
||||
// set up interface for subscribing to our data
|
||||
|
||||
return T;
|
||||
}
|
||||
}) T.init();
|
213
browser/base/content/tabview/storage.js
Normal file
213
browser/base/content/tabview/storage.js
Normal file
@ -0,0 +1,213 @@
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is storage.js.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* the Mozilla Foundation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2010
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Ehsan Akhgari <ehsan@mozilla.com>
|
||||
* Ian Gilman <ian@iangilman.com>
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
// **********
|
||||
// Title: storage.js
|
||||
|
||||
// ##########
|
||||
// Class: Storage
|
||||
// Singleton for permanent storage of TabView data.
|
||||
let Storage = {
|
||||
GROUP_DATA_IDENTIFIER: "tabview-group",
|
||||
GROUPS_DATA_IDENTIFIER: "tabview-groups",
|
||||
TAB_DATA_IDENTIFIER: "tabview-tab",
|
||||
UI_DATA_IDENTIFIER: "tabview-ui",
|
||||
|
||||
// ----------
|
||||
// Function: init
|
||||
// Sets up the object.
|
||||
init: function() {
|
||||
this._sessionStore =
|
||||
Cc["@mozilla.org/browser/sessionstore;1"].
|
||||
getService(Ci.nsISessionStore);
|
||||
},
|
||||
|
||||
// ----------
|
||||
// Function: uninit
|
||||
uninit : function() {
|
||||
this._sessionStore = null;
|
||||
},
|
||||
|
||||
// ----------
|
||||
// Function: wipe
|
||||
// Cleans out all the stored data, leaving empty objects.
|
||||
wipe: function() {
|
||||
try {
|
||||
var self = this;
|
||||
|
||||
// ___ Tabs
|
||||
AllTabs.tabs.forEach(function(tab) {
|
||||
if (tab.ownerDocument.defaultView != gWindow)
|
||||
return;
|
||||
|
||||
self.saveTab(tab, null);
|
||||
});
|
||||
|
||||
// ___ Other
|
||||
this.saveGroupItemsData(gWindow, {});
|
||||
this.saveUIData(gWindow, {});
|
||||
|
||||
this._sessionStore.setWindowValue(gWindow, this.GROUP_DATA_IDENTIFIER,
|
||||
JSON.stringify({}));
|
||||
} catch (e) {
|
||||
Utils.log("Error in wipe: "+e);
|
||||
}
|
||||
},
|
||||
|
||||
// ----------
|
||||
// Function: saveTab
|
||||
// Saves the data for a single tab.
|
||||
saveTab: function(tab, data) {
|
||||
Utils.assert(tab, "tab");
|
||||
|
||||
this._sessionStore.setTabValue(tab, this.TAB_DATA_IDENTIFIER,
|
||||
JSON.stringify(data));
|
||||
},
|
||||
|
||||
// ----------
|
||||
// Function: getTabData
|
||||
// Returns the data object associated with a single tab.
|
||||
getTabData: function(tab) {
|
||||
Utils.assert(tab, "tab");
|
||||
|
||||
var existingData = null;
|
||||
try {
|
||||
var tabData = this._sessionStore.getTabValue(tab, this.TAB_DATA_IDENTIFIER);
|
||||
if (tabData != "") {
|
||||
existingData = JSON.parse(tabData);
|
||||
}
|
||||
} catch (e) {
|
||||
// getWindowValue will fail if the property doesn't exist
|
||||
Utils.log(e);
|
||||
}
|
||||
|
||||
return existingData;
|
||||
},
|
||||
|
||||
// ----------
|
||||
// Function: saveGroupItem
|
||||
// Saves the data for a single groupItem, associated with a specific window.
|
||||
saveGroupItem: function(win, data) {
|
||||
var id = data.id;
|
||||
var existingData = this.readGroupItemData(win);
|
||||
existingData[id] = data;
|
||||
this._sessionStore.setWindowValue(win, this.GROUP_DATA_IDENTIFIER,
|
||||
JSON.stringify(existingData));
|
||||
},
|
||||
|
||||
// ----------
|
||||
// Function: deleteGroupItem
|
||||
// Deletes the data for a single groupItem from the given window.
|
||||
deleteGroupItem: function(win, id) {
|
||||
var existingData = this.readGroupItemData(win);
|
||||
delete existingData[id];
|
||||
this._sessionStore.setWindowValue(win, this.GROUP_DATA_IDENTIFIER,
|
||||
JSON.stringify(existingData));
|
||||
},
|
||||
|
||||
// ----------
|
||||
// Function: readGroupItemData
|
||||
// Returns the data for all groupItems associated with the given window.
|
||||
readGroupItemData: function(win) {
|
||||
var existingData = {};
|
||||
try {
|
||||
existingData = JSON.parse(
|
||||
this._sessionStore.getWindowValue(win, this.GROUP_DATA_IDENTIFIER)
|
||||
);
|
||||
} catch (e) {
|
||||
// getWindowValue will fail if the property doesn't exist
|
||||
Utils.log("Error in readGroupItemData: "+e);
|
||||
}
|
||||
return existingData;
|
||||
},
|
||||
|
||||
// ----------
|
||||
// Function: saveGroupItemsData
|
||||
// Saves the global data for the <GroupItems> singleton for the given window.
|
||||
saveGroupItemsData: function(win, data) {
|
||||
this.saveData(win, this.GROUPS_DATA_IDENTIFIER, data);
|
||||
},
|
||||
|
||||
// ----------
|
||||
// Function: readGroupItemsData
|
||||
// Reads the global data for the <GroupItems> singleton for the given window.
|
||||
readGroupItemsData: function(win) {
|
||||
return this.readData(win, this.GROUPS_DATA_IDENTIFIER);
|
||||
},
|
||||
|
||||
// ----------
|
||||
// Function: saveUIData
|
||||
// Saves the global data for the <UIManager> singleton for the given window.
|
||||
saveUIData: function(win, data) {
|
||||
this.saveData(win, this.UI_DATA_IDENTIFIER, data);
|
||||
},
|
||||
|
||||
// ----------
|
||||
// Function: readUIData
|
||||
// Reads the global data for the <UIManager> singleton for the given window.
|
||||
readUIData: function(win) {
|
||||
return this.readData(win, this.UI_DATA_IDENTIFIER);
|
||||
},
|
||||
|
||||
// ----------
|
||||
// Function: saveData
|
||||
// Generic routine for saving data to a window.
|
||||
saveData: function(win, id, data) {
|
||||
try {
|
||||
this._sessionStore.setWindowValue(win, id, JSON.stringify(data));
|
||||
} catch (e) {
|
||||
Utils.log("Error in saveData: "+e);
|
||||
}
|
||||
},
|
||||
|
||||
// ----------
|
||||
// Function: readData
|
||||
// Generic routine for reading data from a window.
|
||||
readData: function(win, id) {
|
||||
var existingData = {};
|
||||
try {
|
||||
var data = this._sessionStore.getWindowValue(win, id);
|
||||
if (data)
|
||||
existingData = JSON.parse(data);
|
||||
} catch (e) {
|
||||
Utils.log("Error in readData: "+e);
|
||||
}
|
||||
|
||||
return existingData;
|
||||
}
|
||||
};
|
1099
browser/base/content/tabview/tabitems.js
Normal file
1099
browser/base/content/tabview/tabitems.js
Normal file
File diff suppressed because it is too large
Load Diff
479
browser/base/content/tabview/tabview.css
Normal file
479
browser/base/content/tabview/tabview.css
Normal file
@ -0,0 +1,479 @@
|
||||
html {
|
||||
overflow: hidden;
|
||||
/* image-rendering: -moz-crisp-edges; */
|
||||
}
|
||||
|
||||
body {
|
||||
background-color: transparent;
|
||||
font-family: Tahoma, sans-serif !important;
|
||||
padding: 0px;
|
||||
color: rgba(0,0,0,0.4);
|
||||
font-size: 12px;
|
||||
line-height: 16px;
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
#content {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
#bg {
|
||||
background: -moz-linear-gradient(top,#C4C4C4,#9E9E9E);
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
z-index: -999999;
|
||||
}
|
||||
|
||||
/* Tab Styling
|
||||
----------------------------------*/
|
||||
|
||||
|
||||
.tab {
|
||||
position: absolute;
|
||||
padding: 4px 6px 6px 4px;
|
||||
border: 1px solid rgba(230,230,230,1);
|
||||
background-color: rgba(245,245,245,1);
|
||||
overflow: visible !important;
|
||||
-moz-border-radius: 0.4em;
|
||||
-moz-box-shadow: inset rgba(255, 255, 255, 0.6) 0 0 0 2px;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.tab canvas,
|
||||
.cached-thumb {
|
||||
border: 1px solid rgba(0,0,0,0.2);
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
position: absolute;
|
||||
top: 0px;
|
||||
left: 0px;
|
||||
}
|
||||
|
||||
.thumb {
|
||||
position: relative;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.thumb-shadow {
|
||||
position: absolute;
|
||||
border-bottom: 5px solid rgba(0,0,0,0.05);
|
||||
margin-right: -12px;
|
||||
bottom: 2px;
|
||||
width: 94.5%;
|
||||
}
|
||||
|
||||
.favicon {
|
||||
position: absolute;
|
||||
background-color: rgba(245,245,245,1);
|
||||
-moz-border-radius-bottomright: 0.4em;
|
||||
-moz-box-shadow:
|
||||
inset rgba(255, 255, 255, 0.6) 0 -2px 0px,
|
||||
inset rgba(255, 255, 255, 0.6) -2px 0px 0px;
|
||||
padding: 4px 6px 6px 4px;
|
||||
top: 4px;
|
||||
left: 4px;
|
||||
border-right: 1px solid rgba(0,0,0,0.2);
|
||||
border-bottom: 1px solid rgba(0,0,0,0.2);
|
||||
height: 17px;
|
||||
width: 17px;
|
||||
}
|
||||
|
||||
.favicon img {
|
||||
border: none;
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
}
|
||||
|
||||
.close {
|
||||
position: absolute;
|
||||
top: 6px;
|
||||
right: 6px;
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
/* background is set in platform.css */
|
||||
opacity: 0.2;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.close:hover {
|
||||
opacity: 1.0;
|
||||
}
|
||||
|
||||
.expander {
|
||||
position: absolute;
|
||||
bottom: 6px;
|
||||
right: 6px;
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
background: url(chrome://global/skin/icons/resizer.png) no-repeat;
|
||||
opacity: 0.2;
|
||||
}
|
||||
|
||||
.expander:hover {
|
||||
opacity: 1.0;
|
||||
}
|
||||
|
||||
.favicon img:hover,
|
||||
.close img:hover,
|
||||
.expander img:hover {
|
||||
opacity: 1;
|
||||
border: none;
|
||||
}
|
||||
|
||||
.tab-title {
|
||||
position: absolute;
|
||||
top: 100%;
|
||||
text-align: center;
|
||||
width: 94.5%;
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.stacked {
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.stacked .tab-title {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.stacked .thumb-shadow {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.stacked .thumb {
|
||||
-moz-box-shadow: rgba(0,0,0,.2) 1px 1px 6px;
|
||||
}
|
||||
|
||||
.stack-trayed .tab-title {
|
||||
display: block !important;
|
||||
text-shadow: rgba(0,0,0,1) 1px 1px 2px;
|
||||
color: #EEE;
|
||||
font-size: 11px;
|
||||
}
|
||||
|
||||
.stack-trayed .thumb {
|
||||
-moz-box-shadow: none !important;
|
||||
}
|
||||
|
||||
.focus {
|
||||
-moz-box-shadow: rgba(54,79,225,1) 0px 0px 5px -1px !important;
|
||||
}
|
||||
|
||||
.front .tab-title,
|
||||
.front .close,
|
||||
.front .favicon,
|
||||
.front .expander,
|
||||
.front .thumb-shadow {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.front .focus {
|
||||
-moz-box-shadow: none !important;
|
||||
}
|
||||
|
||||
/* Tab GroupItem
|
||||
----------------------------------*/
|
||||
|
||||
.tabInGroupItem {
|
||||
border: none;
|
||||
-moz-box-shadow: none !important;
|
||||
}
|
||||
|
||||
|
||||
.groupItem {
|
||||
position: absolute;
|
||||
/* float: left; */
|
||||
cursor: move;
|
||||
border: 1px solid rgba(230,230,230,1);
|
||||
background-color: rgba(248,248,248,1);
|
||||
-moz-border-radius: 0.4em;
|
||||
-moz-box-shadow:
|
||||
inset rgba(255, 255, 255, 0.6) 0 0 0 2px,
|
||||
rgba(0,0,0,0.2) 1px 1px 4px;
|
||||
}
|
||||
|
||||
.groupItem.activeGroupItem {
|
||||
-moz-box-shadow:
|
||||
rgba(0,0,0,0.6) 1px 1px 8px;
|
||||
}
|
||||
|
||||
.phantom {
|
||||
border: 1px solid rgba(190,190,190,1);
|
||||
}
|
||||
|
||||
.overlay {
|
||||
background-color: rgba(0,0,0,.7) !important;
|
||||
-moz-box-shadow: 3px 3px 8px rgba(0,0,0,.5);
|
||||
-moz-border-radius: 0.4em;
|
||||
/*
|
||||
border: 1px solid rgba(230,230,230,1);
|
||||
background-color: rgba(248,248,248,1);
|
||||
-moz-box-shadow:
|
||||
rgba(0,0,0, .3) 2px 2px 8px,
|
||||
inset rgba(255, 255, 255, 0.6) 0 0 0 2px; */
|
||||
}
|
||||
|
||||
/* InfoItems
|
||||
----------------------------------*/
|
||||
|
||||
.info-item {
|
||||
position: absolute;
|
||||
cursor: move;
|
||||
border: 1px solid rgba(230,230,230,1);
|
||||
background-color: rgba(248,248,248,1);
|
||||
-moz-border-radius: 0.4em;
|
||||
-moz-box-shadow:
|
||||
inset rgba(255, 255, 255, 0.6) 0 0 0 2px,
|
||||
rgba(0,0,0, .2) 1px 1px 4px;
|
||||
}
|
||||
|
||||
.intro {
|
||||
margin: 10px;
|
||||
}
|
||||
|
||||
/* Trenches
|
||||
----------------------------------*/
|
||||
|
||||
.guideTrench,
|
||||
.visibleTrench,
|
||||
.activeVisibleTrench {
|
||||
position: absolute;
|
||||
}
|
||||
|
||||
.guideTrench {
|
||||
z-index: -101;
|
||||
opacity: 0.9;
|
||||
border: 1px dashed rgba(0,0,0,.12);
|
||||
border-bottom: none;
|
||||
border-right: none;
|
||||
-moz-box-shadow: 1px 1px 0 rgba(255,255,255,.15);
|
||||
}
|
||||
|
||||
.visibleTrench {
|
||||
z-index: -103;
|
||||
opacity: 0.05;
|
||||
}
|
||||
|
||||
.activeVisibleTrench {
|
||||
z-index: -102;
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
.activeVisibleTrench.activeTrench {
|
||||
opacity: 0.45;
|
||||
}
|
||||
|
||||
.visibleTrench.border,
|
||||
.activeVisibleTrench.border {
|
||||
background-color: red;
|
||||
}
|
||||
|
||||
.visibleTrench.guide,
|
||||
.activeVisibleTrench.guide {
|
||||
background-color: blue;
|
||||
}
|
||||
|
||||
/* Other
|
||||
----------------------------------*/
|
||||
|
||||
.newTabButton {
|
||||
width: 16px;
|
||||
height: 15px;
|
||||
bottom: 10px;
|
||||
left: 10px;
|
||||
position: absolute !important;
|
||||
cursor: pointer;
|
||||
opacity: .3;
|
||||
background-image: url(chrome://browser/skin/tabview/new-tab.png);
|
||||
z-index: 99999;
|
||||
}
|
||||
|
||||
.newTabButton:hover {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
.newTabButtonAlt {
|
||||
position: absolute;
|
||||
cursor: pointer;
|
||||
z-index: 99999;
|
||||
border: none;
|
||||
-moz-border-radius: 4px;
|
||||
font-size: 50px;
|
||||
line-height: 50px;
|
||||
height: 57px !important;
|
||||
width: 70px !important;
|
||||
margin-top: 4px !important;
|
||||
text-align: center;
|
||||
background-color: #888888;
|
||||
-moz-box-shadow: inset 0px 0px 5px rgba(0,0,0,.5), 0 1px 0 rgba(255,255,255,.3);
|
||||
}
|
||||
|
||||
.newTabButtonAlt > span {
|
||||
color: #909090;
|
||||
text-shadow: 0px 0px 7px rgba(0,0,0,.4), 0 -1px 0 rgba(255,255,255,.6);
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.active {
|
||||
-moz-box-shadow: 5px 5px 4px rgba(0,0,0,.5);
|
||||
}
|
||||
|
||||
.acceptsDrop {
|
||||
-moz-box-shadow: 2px 2px 10px -1px rgba(0,0,0,.6);
|
||||
}
|
||||
|
||||
.titlebar {
|
||||
font-size: 12px;
|
||||
line-height: 18px;
|
||||
height: 18px;
|
||||
}
|
||||
|
||||
input.name {
|
||||
background: transparent;
|
||||
border: 1px solid transparent;
|
||||
color: #999;
|
||||
margin: 3px 0px 0px 3px;
|
||||
padding: 1px;
|
||||
background-image: url(chrome://browser/skin/tabview/edit-light.png);
|
||||
padding-left: 20px;
|
||||
}
|
||||
|
||||
.title-container:hover input.name {
|
||||
border: 1px solid #ddd;
|
||||
}
|
||||
|
||||
.title-container:hover input.name-locked {
|
||||
border: 1px solid transparent !important;
|
||||
cursor: default;
|
||||
}
|
||||
|
||||
input.name:focus {
|
||||
color: #555;
|
||||
}
|
||||
|
||||
input.defaultName {
|
||||
font-style: italic !important;
|
||||
background-image-opacity: .1;
|
||||
color: transparent;
|
||||
}
|
||||
|
||||
.title-container:hover input.defaultName {
|
||||
color: #CCC;
|
||||
}
|
||||
|
||||
.title-container {
|
||||
cursor: text;
|
||||
}
|
||||
|
||||
.title-shield {
|
||||
position: absolute;
|
||||
margin: 3px 0px 0px 3px;
|
||||
padding: 1px;
|
||||
left: 0;
|
||||
top: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
z-index: 10;
|
||||
}
|
||||
|
||||
.transparentBorder {
|
||||
border: 1px solid transparent !important;
|
||||
}
|
||||
|
||||
.stackExpander {
|
||||
position: absolute;
|
||||
opacity: .4;
|
||||
cursor: pointer;
|
||||
background-image: url(chrome://browser/skin/tabview/stack-expander.png);
|
||||
width: 24px;
|
||||
height: 24px;
|
||||
}
|
||||
|
||||
.stackExpander:hover {
|
||||
opacity: .7 !important;
|
||||
}
|
||||
|
||||
.shield {
|
||||
left: 0;
|
||||
top: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
position: absolute;
|
||||
}
|
||||
|
||||
/* Resizable
|
||||
----------------------------------*/
|
||||
.resizer {
|
||||
background-image: url(chrome://global/skin/icons/resizer.png);
|
||||
position: absolute;
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
bottom: 0px;
|
||||
right: 0px;
|
||||
opacity: .2;
|
||||
}
|
||||
|
||||
.iq-resizable { }
|
||||
|
||||
.iq-resizable-handle {
|
||||
position: absolute;
|
||||
font-size: 0.1px;
|
||||
z-index: 99999;
|
||||
display: block;
|
||||
}
|
||||
|
||||
.iq-resizable-disabled .iq-resizable-handle,
|
||||
.iq-resizable-autohide .iq-resizable-handle {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.iq-resizable-se {
|
||||
cursor: se-resize;
|
||||
width: 12px;
|
||||
height: 12px;
|
||||
right: 1px;
|
||||
bottom: 1px;
|
||||
}
|
||||
|
||||
/* Utils
|
||||
----------------------------------*/
|
||||
|
||||
.front {
|
||||
z-index: 999999 !important;
|
||||
-moz-border-radius: 0 !important;
|
||||
-moz-box-shadow: none !important;
|
||||
-moz-transform: none !important;
|
||||
image-rendering: -moz-crisp-edges;
|
||||
}
|
||||
|
||||
/* Feedback
|
||||
----------------------------------*/
|
||||
|
||||
.bottomButton {
|
||||
position: absolute;
|
||||
bottom: 0px;
|
||||
width: 100px;
|
||||
height: 20px;
|
||||
line-height: 20px;
|
||||
z-index: 99999 !important;
|
||||
background-color: blue;
|
||||
text-align: center;
|
||||
color: white;
|
||||
background-color: #9E9E9E;
|
||||
-moz-box-shadow: 0px 0px 4px rgba(0,0,0,.3), inset 0px 1px 0px rgba(255,255,255,.4);
|
||||
}
|
||||
|
||||
.bottomButton:hover {
|
||||
cursor: pointer;
|
||||
background-color: #A5A5A5;
|
||||
-moz-box-shadow: 0px 0px 5px rgba(0,0,0,.6), inset 0px 1px 0px rgba(255,255,255,.4);
|
||||
}
|
19
browser/base/content/tabview/tabview.html
Normal file
19
browser/base/content/tabview/tabview.html
Normal file
@ -0,0 +1,19 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!DOCTYPE html>
|
||||
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en-US">
|
||||
<head>
|
||||
<title> </title>
|
||||
<meta http-equiv="Content-Type" content="application/xhtml+xml; charset=utf-8" />
|
||||
<link rel="stylesheet" href="tabview.css" type="text/css"/>
|
||||
<link rel="stylesheet" href="chrome://browser/skin/tabview/tabview.css" type="text/css"/>
|
||||
</head>
|
||||
|
||||
<body transparent="true">
|
||||
<div id="content">
|
||||
<div id="bg" />
|
||||
</div>
|
||||
|
||||
<script type="text/javascript;version=1.8" src="tabview.js"></script>
|
||||
|
||||
</body>
|
||||
</html>
|
38
browser/base/content/tabview/tabview.js
Normal file
38
browser/base/content/tabview/tabview.js
Normal file
@ -0,0 +1,38 @@
|
||||
const Cc = Components.classes;
|
||||
const Ci = Components.interfaces;
|
||||
const Cu = Components.utils;
|
||||
|
||||
Cu.import("resource://gre/modules/tabview/AllTabs.jsm");
|
||||
Cu.import("resource://gre/modules/tabview/groups.jsm");
|
||||
Cu.import("resource://gre/modules/tabview/utils.jsm");
|
||||
Cu.import("resource://gre/modules/Services.jsm");
|
||||
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||
|
||||
XPCOMUtils.defineLazyGetter(this, "gWindow", function() {
|
||||
return window.QueryInterface(Ci.nsIInterfaceRequestor).
|
||||
getInterface(Ci.nsIWebNavigation).
|
||||
QueryInterface(Ci.nsIDocShell).
|
||||
chromeEventHandler.ownerDocument.defaultView;
|
||||
});
|
||||
|
||||
XPCOMUtils.defineLazyGetter(this, "gBrowser", function() gWindow.gBrowser);
|
||||
|
||||
XPCOMUtils.defineLazyGetter(this, "gTabViewDeck", function() {
|
||||
return gWindow.document.getElementById("tab-view-deck");
|
||||
});
|
||||
|
||||
XPCOMUtils.defineLazyGetter(this, "gTabViewFrame", function() {
|
||||
return gWindow.document.getElementById("tab-view");
|
||||
});
|
||||
|
||||
# NB: Certain files need to evaluate before others
|
||||
|
||||
#include iq.js
|
||||
#include storage.js
|
||||
#include items.js
|
||||
#include groupitems.js
|
||||
#include tabitems.js
|
||||
#include drag.js
|
||||
#include trench.js
|
||||
#include infoitems.js
|
||||
#include ui.js
|
677
browser/base/content/tabview/trench.js
Normal file
677
browser/base/content/tabview/trench.js
Normal file
@ -0,0 +1,677 @@
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is trench.js.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* the Mozilla Foundation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2010
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Michael Yoshitaka Erlewine <mitcho@mitcho.com>
|
||||
* Ian Gilman <ian@iangilman.com>
|
||||
* Aza Raskin <aza@mozilla.com>
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
// **********
|
||||
// Title: trench.js
|
||||
|
||||
// ##########
|
||||
// Class: Trench
|
||||
//
|
||||
// Class for drag-snapping regions; called "trenches" as they are long and narrow.
|
||||
|
||||
// Constructor: Trench
|
||||
//
|
||||
// Parameters:
|
||||
// element - the DOM element for Item (GroupItem or TabItem) from which the trench is projected
|
||||
// xory - either "x" or "y": whether the trench's <position> is along the x- or y-axis.
|
||||
// In other words, if "x", the trench is vertical; if "y", the trench is horizontal.
|
||||
// type - either "border" or "guide". Border trenches mark the border of an Item.
|
||||
// Guide trenches extend out (unless they are intercepted) and act as "guides".
|
||||
// edge - which edge of the Item that this trench corresponds to.
|
||||
// Either "top", "left", "bottom", or "right".
|
||||
var Trench = function(element, xory, type, edge) {
|
||||
//----------
|
||||
// Variable: id
|
||||
// (integer) The id for the Trench. Set sequentially via <Trenches.nextId>
|
||||
this.id = Trenches.nextId++;
|
||||
|
||||
// ---------
|
||||
// Variables: Initial parameters
|
||||
// element - (DOMElement)
|
||||
// parentItem - <Item> which projects this trench; to be set with setParentItem
|
||||
// xory - (string) "x" or "y"
|
||||
// type - (string) "border" or "guide"
|
||||
// edge - (string) "top", "left", "bottom", or "right"
|
||||
this.el = element;
|
||||
this.parentItem = null;
|
||||
this.xory = xory; // either "x" or "y"
|
||||
this.type = type; // "border" or "guide"
|
||||
this.edge = edge; // "top", "left", "bottom", or "right"
|
||||
|
||||
this.$el = iQ(this.el);
|
||||
|
||||
//----------
|
||||
// Variable: dom
|
||||
// (array) DOM elements for visible reflexes of the Trench
|
||||
this.dom = [];
|
||||
|
||||
//----------
|
||||
// Variable: showGuide
|
||||
// (boolean) Whether this trench will project a visible guide (dotted line) or not.
|
||||
this.showGuide = false;
|
||||
|
||||
//----------
|
||||
// Variable: active
|
||||
// (boolean) Whether this trench is currently active or not.
|
||||
// Basically every trench aside for those projected by the Item currently being dragged
|
||||
// all become active.
|
||||
this.active = false;
|
||||
this.gutter = Items.defaultGutter;
|
||||
|
||||
//----------
|
||||
// Variable: position
|
||||
// (integer) position is the position that we should snap to.
|
||||
this.position = 0;
|
||||
|
||||
//----------
|
||||
// Variables: some Ranges
|
||||
// range - (<Range>) explicit range; this is along the transverse axis
|
||||
// minRange - (<Range>) the minimum active range
|
||||
// activeRange - (<Range>) the currently active range
|
||||
this.range = new Range(0,10000);
|
||||
this.minRange = new Range(0,0);
|
||||
this.activeRange = new Range(0,10000);
|
||||
};
|
||||
|
||||
Trench.prototype = {
|
||||
//----------
|
||||
// Variable: radius
|
||||
// (integer) radius is how far away we should snap from
|
||||
get radius() this.customRadius || Trenches.defaultRadius,
|
||||
|
||||
setParentItem: function Trench_setParentItem(item) {
|
||||
if (!item.isAnItem) {
|
||||
Utils.assert(false, "parentItem must be an Item");
|
||||
return false;
|
||||
}
|
||||
this.parentItem = item;
|
||||
return true;
|
||||
},
|
||||
|
||||
//----------
|
||||
// Function: setPosition
|
||||
// set the trench's position.
|
||||
//
|
||||
// Parameters:
|
||||
// position - (integer) px center position of the trench
|
||||
// range - (<Range>) the explicit active range of the trench
|
||||
// minRange - (<Range>) the minimum range of the trench
|
||||
setPosition: function Trench_setPos(position, range, minRange) {
|
||||
this.position = position;
|
||||
|
||||
var page = Items.getPageBounds(true);
|
||||
|
||||
// optionally, set the range.
|
||||
if (Utils.isRange(range)) {
|
||||
this.range = range;
|
||||
} else {
|
||||
this.range = new Range(0, (this.xory == 'x' ? page.height : page.width));
|
||||
}
|
||||
|
||||
// if there's a minRange, set that too.
|
||||
if (Utils.isRange(minRange))
|
||||
this.minRange = minRange;
|
||||
|
||||
// set the appropriate bounds as a rect.
|
||||
if (this.xory == "x") // vertical
|
||||
this.rect = new Rect(this.position - this.radius, this.range.min, 2 * this.radius, this.range.extent);
|
||||
else // horizontal
|
||||
this.rect = new Rect(this.range.min, this.position - this.radius, this.range.extent, 2 * this.radius);
|
||||
|
||||
this.show(); // DEBUG
|
||||
},
|
||||
|
||||
//----------
|
||||
// Function: setActiveRange
|
||||
// set the trench's currently active range.
|
||||
//
|
||||
// Parameters:
|
||||
// activeRange - (<Range>)
|
||||
setActiveRange: function Trench_setActiveRect(activeRange) {
|
||||
if (!Utils.isRange(activeRange))
|
||||
return false;
|
||||
this.activeRange = activeRange;
|
||||
if (this.xory == "x") { // horizontal
|
||||
this.activeRect = new Rect(this.position - this.radius, this.activeRange.min, 2 * this.radius, this.activeRange.extent);
|
||||
this.guideRect = new Rect(this.position, this.activeRange.min, 0, this.activeRange.extent);
|
||||
} else { // vertical
|
||||
this.activeRect = new Rect(this.activeRange.min, this.position - this.radius, this.activeRange.extent, 2 * this.radius);
|
||||
this.guideRect = new Rect(this.activeRange.min, this.position, this.activeRange.extent, 0);
|
||||
}
|
||||
return true;
|
||||
},
|
||||
|
||||
//----------
|
||||
// Function: setWithRect
|
||||
// Set the trench's position using the given rect. We know which side of the rect we should match
|
||||
// because we've already recorded this information in <edge>.
|
||||
//
|
||||
// Parameters:
|
||||
// rect - (<Rect>)
|
||||
setWithRect: function Trench_setWithRect(rect) {
|
||||
|
||||
if (!Utils.isRect(rect))
|
||||
Utils.error('argument must be Rect');
|
||||
|
||||
// First, calculate the range for this trench.
|
||||
// Border trenches are always only active for the length of this range.
|
||||
// Guide trenches, however, still use this value as its minRange.
|
||||
if (this.xory == "x")
|
||||
var range = new Range(rect.top - this.gutter, rect.bottom + this.gutter);
|
||||
else
|
||||
var range = new Range(rect.left - this.gutter, rect.right + this.gutter);
|
||||
|
||||
if (this.type == "border") {
|
||||
// border trenches have a range, so set that too.
|
||||
if (this.edge == "left")
|
||||
this.setPosition(rect.left - this.gutter, range);
|
||||
else if (this.edge == "right")
|
||||
this.setPosition(rect.right + this.gutter, range);
|
||||
else if (this.edge == "top")
|
||||
this.setPosition(rect.top - this.gutter, range);
|
||||
else if (this.edge == "bottom")
|
||||
this.setPosition(rect.bottom + this.gutter, range);
|
||||
} else if (this.type == "guide") {
|
||||
// guide trenches have no range, but do have a minRange.
|
||||
if (this.edge == "left")
|
||||
this.setPosition(rect.left, false, range);
|
||||
else if (this.edge == "right")
|
||||
this.setPosition(rect.right, false, range);
|
||||
else if (this.edge == "top")
|
||||
this.setPosition(rect.top, false, range);
|
||||
else if (this.edge == "bottom")
|
||||
this.setPosition(rect.bottom, false, range);
|
||||
}
|
||||
},
|
||||
|
||||
//----------
|
||||
// Function: show
|
||||
//
|
||||
// Show guide (dotted line), if <showGuide> is true.
|
||||
//
|
||||
// If <Trenches.showDebug> is true, we will draw the trench. Active portions are drawn with 0.5
|
||||
// opacity. If <active> is false, the entire trench will be
|
||||
// very translucent.
|
||||
show: function Trench_show() { // DEBUG
|
||||
if (this.active && this.showGuide) {
|
||||
if (!this.dom.guideTrench)
|
||||
this.dom.guideTrench = iQ("<div/>").addClass('guideTrench').css({id: 'guideTrench'+this.id});
|
||||
var guideTrench = this.dom.guideTrench;
|
||||
guideTrench.css(this.guideRect.css());
|
||||
iQ("body").append(guideTrench);
|
||||
} else {
|
||||
if (this.dom.guideTrench) {
|
||||
this.dom.guideTrench.remove();
|
||||
delete this.dom.guideTrench;
|
||||
}
|
||||
}
|
||||
|
||||
if (!Trenches.showDebug) {
|
||||
this.hide(true); // true for dontHideGuides
|
||||
return;
|
||||
}
|
||||
|
||||
if (!this.dom.visibleTrench)
|
||||
this.dom.visibleTrench = iQ("<div/>")
|
||||
.addClass('visibleTrench')
|
||||
.addClass(this.type) // border or guide
|
||||
.css({id: 'visibleTrench'+this.id});
|
||||
var visibleTrench = this.dom.visibleTrench;
|
||||
|
||||
if (!this.dom.activeVisibleTrench)
|
||||
this.dom.activeVisibleTrench = iQ("<div/>")
|
||||
.addClass('activeVisibleTrench')
|
||||
.addClass(this.type) // border or guide
|
||||
.css({id: 'activeVisibleTrench'+this.id});
|
||||
var activeVisibleTrench = this.dom.activeVisibleTrench;
|
||||
|
||||
if (this.active)
|
||||
activeVisibleTrench.addClass('activeTrench');
|
||||
else
|
||||
activeVisibleTrench.removeClass('activeTrench');
|
||||
|
||||
visibleTrench.css(this.rect.css());
|
||||
activeVisibleTrench.css((this.activeRect || this.rect).css());
|
||||
iQ("body").append(visibleTrench);
|
||||
iQ("body").append(activeVisibleTrench);
|
||||
},
|
||||
|
||||
//----------
|
||||
// Function: hide
|
||||
// Hide the trench.
|
||||
hide: function Trench_hide(dontHideGuides) {
|
||||
if (this.dom.visibleTrench)
|
||||
this.dom.visibleTrench.remove();
|
||||
if (this.dom.activeVisibleTrench)
|
||||
this.dom.activeVisibleTrench.remove();
|
||||
if (!dontHideGuides && this.dom.guideTrench)
|
||||
this.dom.guideTrench.remove();
|
||||
},
|
||||
|
||||
//----------
|
||||
// Function: rectOverlaps
|
||||
// Given a <Rect>, compute whether it overlaps with this trench. If it does, return an
|
||||
// adjusted ("snapped") <Rect>; if it does not overlap, simply return false.
|
||||
//
|
||||
// Note that simply overlapping is not all that is required to be affected by this function.
|
||||
// Trenches can only affect certain edges of rectangles... for example, a "left"-edge guide
|
||||
// trench should only affect left edges of rectangles. We don't snap right edges to left-edged
|
||||
// guide trenches. For border trenches, the logic is a bit different, so left snaps to right and
|
||||
// top snaps to bottom.
|
||||
//
|
||||
// Parameters:
|
||||
// rect - (<Rect>) the rectangle in question
|
||||
// stationaryCorner - which corner is stationary? by default, the top left.
|
||||
// "topleft", "bottomleft", "topright", "bottomright"
|
||||
// assumeConstantSize - (boolean) whether the rect's dimensions are sacred or not
|
||||
// keepProportional - (boolean) if we are allowed to change the rect's size, whether the
|
||||
// dimensions should scaled proportionally or not.
|
||||
//
|
||||
// Returns:
|
||||
// false - if rect does not overlap with this trench
|
||||
// newRect - (<Rect>) an adjusted version of rect, if it is affected by this trench
|
||||
rectOverlaps: function Trench_rectOverlaps(rect,stationaryCorner,assumeConstantSize,keepProportional) {
|
||||
var edgeToCheck;
|
||||
if (this.type == "border") {
|
||||
if (this.edge == "left")
|
||||
edgeToCheck = "right";
|
||||
else if (this.edge == "right")
|
||||
edgeToCheck = "left";
|
||||
else if (this.edge == "top")
|
||||
edgeToCheck = "bottom";
|
||||
else if (this.edge == "bottom")
|
||||
edgeToCheck = "top";
|
||||
} else { // if trench type is guide or barrier...
|
||||
edgeToCheck = this.edge;
|
||||
}
|
||||
|
||||
rect.adjustedEdge = edgeToCheck;
|
||||
|
||||
switch (edgeToCheck) {
|
||||
case "left":
|
||||
if (this.ruleOverlaps(rect.left, rect.yRange)) {
|
||||
if (stationaryCorner.indexOf('right') > -1)
|
||||
rect.width = rect.right - this.position;
|
||||
rect.left = this.position;
|
||||
return rect;
|
||||
}
|
||||
break;
|
||||
case "right":
|
||||
if (this.ruleOverlaps(rect.right, rect.yRange)) {
|
||||
if (assumeConstantSize) {
|
||||
rect.left = this.position - rect.width;
|
||||
} else {
|
||||
var newWidth = this.position - rect.left;
|
||||
if (keepProportional)
|
||||
rect.height = rect.height * newWidth / rect.width;
|
||||
rect.width = newWidth;
|
||||
}
|
||||
return rect;
|
||||
}
|
||||
break;
|
||||
case "top":
|
||||
if (this.ruleOverlaps(rect.top, rect.xRange)) {
|
||||
if (stationaryCorner.indexOf('bottom') > -1)
|
||||
rect.height = rect.bottom - this.position;
|
||||
rect.top = this.position;
|
||||
return rect;
|
||||
}
|
||||
break;
|
||||
case "bottom":
|
||||
if (this.ruleOverlaps(rect.bottom, rect.xRange)) {
|
||||
if (assumeConstantSize) {
|
||||
rect.top = this.position - rect.height;
|
||||
} else {
|
||||
var newHeight = this.position - rect.top;
|
||||
if (keepProportional)
|
||||
rect.width = rect.width * newHeight / rect.height;
|
||||
rect.height = newHeight;
|
||||
}
|
||||
return rect;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
},
|
||||
|
||||
//----------
|
||||
// Function: ruleOverlaps
|
||||
// Computes whether the given "rule" (a line segment, essentially), given by the position and
|
||||
// range arguments, overlaps with the current trench. Note that this function assumes that
|
||||
// the rule and the trench are in the same direction: both horizontal, or both vertical.
|
||||
//
|
||||
// Parameters:
|
||||
// position - (integer) a position in px
|
||||
// range - (<Range>) the rule's range
|
||||
ruleOverlaps: function Trench_ruleOverlaps(position, range) {
|
||||
return (this.position - this.radius < position &&
|
||||
position < this.position + this.radius &&
|
||||
this.activeRange.contains(range));
|
||||
},
|
||||
|
||||
//----------
|
||||
// Function: adjustRangeIfIntercept
|
||||
// Computes whether the given boundary (given as a position and its active range), perpendicular
|
||||
// to the trench, intercepts the trench or not. If it does, it returns an adjusted <Range> for
|
||||
// the trench. If not, it returns false.
|
||||
//
|
||||
// Parameters:
|
||||
// position - (integer) the position of the boundary
|
||||
// range - (<Range>) the target's range, on the trench's transverse axis
|
||||
adjustRangeIfIntercept: function Trench_adjustRangeIfIntercept(position, range) {
|
||||
if (this.position - this.radius > range.min && this.position + this.radius < range.max) {
|
||||
var activeRange = new Range(this.activeRange);
|
||||
|
||||
// there are three ways this can go:
|
||||
// 1. position < minRange.min
|
||||
// 2. position > minRange.max
|
||||
// 3. position >= minRange.min && position <= minRange.max
|
||||
|
||||
if (position < this.minRange.min) {
|
||||
activeRange.min = Math.min(this.minRange.min,position);
|
||||
} else if (position > this.minRange.max) {
|
||||
activeRange.max = Math.max(this.minRange.max,position);
|
||||
} else {
|
||||
// this should be impossible because items can't overlap and we've already checked
|
||||
// that the range intercepts.
|
||||
}
|
||||
return activeRange;
|
||||
}
|
||||
return false;
|
||||
},
|
||||
|
||||
//----------
|
||||
// Function: calculateActiveRange
|
||||
// Computes and sets the <activeRange> for the trench, based on the <GroupItems> around.
|
||||
// This makes it so trenches' active ranges don't extend through other groupItems.
|
||||
calculateActiveRange: function Trench_calculateActiveRange() {
|
||||
|
||||
// set it to the default: just the range itself.
|
||||
this.setActiveRange(this.range);
|
||||
|
||||
// only guide-type trenches need to set a separate active range
|
||||
if (this.type != 'guide')
|
||||
return;
|
||||
|
||||
var groupItems = GroupItems.groupItems;
|
||||
var trench = this;
|
||||
groupItems.forEach(function(groupItem) {
|
||||
if (groupItem.isDragging) // floating groupItems don't block trenches
|
||||
return;
|
||||
if (trench.el == groupItem.container) // groupItems don't block their own trenches
|
||||
return;
|
||||
var bounds = groupItem.getBounds();
|
||||
var activeRange = new Range();
|
||||
if (trench.xory == 'y') { // if this trench is horizontal...
|
||||
activeRange = trench.adjustRangeIfIntercept(bounds.left, bounds.yRange);
|
||||
if (activeRange)
|
||||
trench.setActiveRange(activeRange);
|
||||
activeRange = trench.adjustRangeIfIntercept(bounds.right, bounds.yRange);
|
||||
if (activeRange)
|
||||
trench.setActiveRange(activeRange);
|
||||
} else { // if this trench is vertical...
|
||||
activeRange = trench.adjustRangeIfIntercept(bounds.top, bounds.xRange);
|
||||
if (activeRange)
|
||||
trench.setActiveRange(activeRange);
|
||||
activeRange = trench.adjustRangeIfIntercept(bounds.bottom, bounds.xRange);
|
||||
if (activeRange)
|
||||
trench.setActiveRange(activeRange);
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
// ##########
|
||||
// Class: Trenches
|
||||
// Singelton for managing all <Trench>es.
|
||||
var Trenches = {
|
||||
// ---------
|
||||
// Variables:
|
||||
// nextId - (integer) a counter for the next <Trench>'s <Trench.id> value.
|
||||
// showDebug - (boolean) whether to draw the <Trench>es or not.
|
||||
// defaultRadius - (integer) the default radius for new <Trench>es.
|
||||
nextId: 0,
|
||||
showDebug: false,
|
||||
defaultRadius: 10,
|
||||
|
||||
// ---------
|
||||
// Variables: snapping preferences; used to break ties in snapping.
|
||||
// preferTop - (boolean) prefer snapping to the top to the bottom
|
||||
// preferLeft - (boolean) prefer snapping to the left to the right
|
||||
preferTop: true,
|
||||
preferLeft: true,
|
||||
|
||||
trenches: [],
|
||||
|
||||
// ---------
|
||||
// Function: getById
|
||||
// Return the specified <Trench>.
|
||||
//
|
||||
// Parameters:
|
||||
// id - (integer)
|
||||
getById: function Trenches_getById(id) {
|
||||
return this.trenches[id];
|
||||
},
|
||||
|
||||
// ---------
|
||||
// Function: register
|
||||
// Register a new <Trench> and returns the resulting <Trench> ID.
|
||||
//
|
||||
// Parameters:
|
||||
// See the constructor <Trench.Trench>'s parameters.
|
||||
//
|
||||
// Returns:
|
||||
// id - (int) the new <Trench>'s ID.
|
||||
register: function Trenches_register(element, xory, type, edge) {
|
||||
var trench = new Trench(element, xory, type, edge);
|
||||
this.trenches[trench.id] = trench;
|
||||
return trench.id;
|
||||
},
|
||||
|
||||
// ---------
|
||||
// Function: registerWithItem
|
||||
// Register a whole set of <Trench>es using an <Item> and returns the resulting <Trench> IDs.
|
||||
//
|
||||
// Parameters:
|
||||
// item - the <Item> to project trenches
|
||||
// type - either "border" or "guide"
|
||||
//
|
||||
// Returns:
|
||||
// ids - array of the new <Trench>es' IDs.
|
||||
registerWithItem: function Trenches_registerWithItem(item, type) {
|
||||
var container = item.container;
|
||||
var ids = {};
|
||||
ids.left = Trenches.register(container,"x",type,"left");
|
||||
ids.right = Trenches.register(container,"x",type,"right");
|
||||
ids.top = Trenches.register(container,"y",type,"top");
|
||||
ids.bottom = Trenches.register(container,"y",type,"bottom");
|
||||
|
||||
this.getById(ids.left).setParentItem(item);
|
||||
this.getById(ids.right).setParentItem(item);
|
||||
this.getById(ids.top).setParentItem(item);
|
||||
this.getById(ids.bottom).setParentItem(item);
|
||||
|
||||
return ids;
|
||||
},
|
||||
|
||||
// ---------
|
||||
// Function: unregister
|
||||
// Unregister one or more <Trench>es.
|
||||
//
|
||||
// Parameters:
|
||||
// ids - (integer) a single <Trench> ID or (array) a list of <Trench> IDs.
|
||||
unregister: function Trenches_unregister(ids) {
|
||||
if (!Array.isArray(ids))
|
||||
ids = [ids];
|
||||
var self = this;
|
||||
ids.forEach(function(id) {
|
||||
self.trenches[id].hide();
|
||||
delete self.trenches[id];
|
||||
});
|
||||
},
|
||||
|
||||
// ---------
|
||||
// Function: activateOthersTrenches
|
||||
// Activate all <Trench>es other than those projected by the current element.
|
||||
//
|
||||
// Parameters:
|
||||
// element - (DOMElement) the DOM element of the Item being dragged or resized.
|
||||
activateOthersTrenches: function Trenches_activateOthersTrenches(element) {
|
||||
this.trenches.forEach(function(t) {
|
||||
if (t.el === element)
|
||||
return;
|
||||
if (t.parentItem && (t.parentItem.isAFauxItem ||
|
||||
t.parentItem.isDragging ||
|
||||
t.parentItem.isDropTarget))
|
||||
return;
|
||||
t.active = true;
|
||||
t.calculateActiveRange();
|
||||
t.show(); // debug
|
||||
});
|
||||
},
|
||||
|
||||
// ---------
|
||||
// Function: disactivate
|
||||
// After <activateOthersTrenches>, disactivates all the <Trench>es again.
|
||||
disactivate: function Trenches_disactivate() {
|
||||
this.trenches.forEach(function(t) {
|
||||
t.active = false;
|
||||
t.showGuide = false;
|
||||
t.show();
|
||||
});
|
||||
},
|
||||
|
||||
// ---------
|
||||
// Function: hideGuides
|
||||
// Hide all guides (dotted lines) en masse.
|
||||
hideGuides: function Trenches_hideGuides() {
|
||||
this.trenches.forEach(function(t) {
|
||||
t.showGuide = false;
|
||||
t.show();
|
||||
});
|
||||
},
|
||||
|
||||
// ---------
|
||||
// Function: snap
|
||||
// Used to "snap" an object's bounds to active trenches and to the edge of the window.
|
||||
// If the meta key is down (<Key.meta>), it will not snap but will still enforce the rect
|
||||
// not leaving the safe bounds of the window.
|
||||
//
|
||||
// Parameters:
|
||||
// rect - (<Rect>) the object's current bounds
|
||||
// stationaryCorner - which corner is stationary? by default, the top left.
|
||||
// "topleft", "bottomleft", "topright", "bottomright"
|
||||
// assumeConstantSize - (boolean) whether the rect's dimensions are sacred or not
|
||||
// keepProportional - (boolean) if we are allowed to change the rect's size, whether the
|
||||
// dimensions should scaled proportionally or not.
|
||||
//
|
||||
// Returns:
|
||||
// (<Rect>) - the updated bounds, if they were updated
|
||||
// false - if the bounds were not updated
|
||||
snap: function Trenches_snap(rect,stationaryCorner,assumeConstantSize,keepProportional) {
|
||||
// hide all the guide trenches, because the correct ones will be turned on later.
|
||||
Trenches.hideGuides();
|
||||
|
||||
var updated = false;
|
||||
var updatedX = false;
|
||||
var updatedY = false;
|
||||
|
||||
var snappedTrenches = {};
|
||||
|
||||
for (var i in this.trenches) {
|
||||
var t = this.trenches[i];
|
||||
if (!t.active || t.parentItem.isDropTarget)
|
||||
continue;
|
||||
// newRect will be a new rect, or false
|
||||
var newRect = t.rectOverlaps(rect,stationaryCorner,assumeConstantSize,keepProportional);
|
||||
|
||||
if (newRect) { // if rectOverlaps returned an updated rect...
|
||||
|
||||
if (assumeConstantSize && updatedX && updatedY)
|
||||
break;
|
||||
if (assumeConstantSize && updatedX && (newRect.adjustedEdge == "left"||newRect.adjustedEdge == "right"))
|
||||
continue;
|
||||
if (assumeConstantSize && updatedY && (newRect.adjustedEdge == "top"||newRect.adjustedEdge == "bottom"))
|
||||
continue;
|
||||
|
||||
rect = newRect;
|
||||
updated = true;
|
||||
|
||||
// register this trench as the "snapped trench" for the appropriate edge.
|
||||
snappedTrenches[newRect.adjustedEdge] = t;
|
||||
|
||||
// if updatedX, we don't need to update x any more.
|
||||
if (newRect.adjustedEdge == "left" && this.preferLeft)
|
||||
updatedX = true;
|
||||
if (newRect.adjustedEdge == "right" && !this.preferLeft)
|
||||
updatedX = true;
|
||||
|
||||
// if updatedY, we don't need to update x any more.
|
||||
if (newRect.adjustedEdge == "top" && this.preferTop)
|
||||
updatedY = true;
|
||||
if (newRect.adjustedEdge == "bottom" && !this.preferTop)
|
||||
updatedY = true;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
if (updated) {
|
||||
rect.snappedTrenches = snappedTrenches;
|
||||
return rect;
|
||||
}
|
||||
return false;
|
||||
},
|
||||
|
||||
// ---------
|
||||
// Function: show
|
||||
// <Trench.show> all <Trench>es.
|
||||
show: function Trenches_show() {
|
||||
this.trenches.forEach(function(t) {
|
||||
t.show();
|
||||
});
|
||||
},
|
||||
|
||||
// ---------
|
||||
// Function: toggleShown
|
||||
// Toggle <Trenches.showDebug> and trigger <Trenches.show>
|
||||
toggleShown: function Trenches_toggleShown() {
|
||||
this.showDebug = !this.showDebug;
|
||||
this.show();
|
||||
}
|
||||
};
|
1052
browser/base/content/tabview/ui.js
Normal file
1052
browser/base/content/tabview/ui.js
Normal file
File diff suppressed because it is too large
Load Diff
@ -40,6 +40,8 @@ srcdir = @srcdir@
|
||||
VPATH = @srcdir@
|
||||
relativesrcdir = browser/base/content/test
|
||||
|
||||
DIRS += tabview
|
||||
|
||||
include $(DEPTH)/config/autoconf.mk
|
||||
include $(topsrcdir)/config/rules.mk
|
||||
|
||||
@ -134,6 +136,7 @@ _BROWSER_FILES = \
|
||||
browser_bug555224.js \
|
||||
browser_bug555767.js \
|
||||
browser_bug556061.js \
|
||||
browser_bug561623.js \
|
||||
browser_bug562649.js \
|
||||
browser_bug563588.js \
|
||||
browser_bug577121.js \
|
||||
@ -145,10 +148,12 @@ _BROWSER_FILES = \
|
||||
browser_drag.js \
|
||||
browser_gestureSupport.js \
|
||||
browser_getshortcutoruri.js \
|
||||
browser_hide_removing.js \
|
||||
browser_inspector_initialization.js \
|
||||
browser_inspector_treeSelection.js \
|
||||
browser_inspector_highlighter.js \
|
||||
browser_inspector_stylePanel.js \
|
||||
browser_inspector_domPanel.js \
|
||||
browser_inspector_iframeTest.js \
|
||||
browser_inspector_scrolling.js \
|
||||
browser_pageInfo.js \
|
||||
@ -167,6 +172,10 @@ _BROWSER_FILES = \
|
||||
browser_tabfocus.js \
|
||||
browser_tabs_owner.js \
|
||||
browser_visibleTabs.js \
|
||||
browser_visibleTabs_contextMenu.js \
|
||||
browser_visibleTabs_bookmarkAllPages.js \
|
||||
browser_visibleTabs_bookmarkAllTabs.js \
|
||||
browser_visibleTabs_tabPreview.js \
|
||||
discovery.html \
|
||||
moz.png \
|
||||
test_bug435035.html \
|
||||
|
@ -406,6 +406,36 @@ function test_reload() {
|
||||
gBrowser.loadURI(TESTROOT2 + "enabled.html");
|
||||
});
|
||||
});
|
||||
},
|
||||
|
||||
function test_theme() {
|
||||
var pm = Services.perms;
|
||||
pm.add(makeURI("http://example.com/"), "install", pm.ALLOW_ACTION);
|
||||
|
||||
var triggers = encodeURIComponent(JSON.stringify({
|
||||
"Theme XPI": "theme.xpi"
|
||||
}));
|
||||
gBrowser.selectedTab = gBrowser.addTab();
|
||||
gBrowser.loadURI(TESTROOT + "installtrigger.html?" + triggers);
|
||||
|
||||
// Wait for the install confirmation dialog
|
||||
wait_for_install_dialog(function(aWindow) {
|
||||
aWindow.document.documentElement.acceptDialog();
|
||||
|
||||
// Wait for the complete notification
|
||||
wait_for_notification(function(aPanel) {
|
||||
let notification = aPanel.childNodes[0];
|
||||
is(notification.id, "addon-install-complete", "Should have seen the install complete");
|
||||
is(notification.button.label, "Restart Now", "Should have seen the right button");
|
||||
is(notification.getAttribute("label"),
|
||||
"Theme Test will be installed after you restart " + gApp + ".",
|
||||
"Should have seen the right message");
|
||||
|
||||
gBrowser.removeTab(gBrowser.selectedTab);
|
||||
Services.perms.remove("example.com", "install");
|
||||
runNextTest();
|
||||
});
|
||||
});
|
||||
}
|
||||
];
|
||||
|
||||
|
29
browser/base/content/test/browser_bug561623.js
Normal file
29
browser/base/content/test/browser_bug561623.js
Normal file
@ -0,0 +1,29 @@
|
||||
function test() {
|
||||
waitForExplicitFinish();
|
||||
gBrowser.selectedTab = gBrowser.addTab();
|
||||
gBrowser.selectedBrowser.addEventListener("load", function () {
|
||||
gBrowser.selectedBrowser.removeEventListener("load", arguments.callee, true);
|
||||
|
||||
let doc = gBrowser.contentDocument;
|
||||
let tooltip = document.getElementById("aHTMLTooltip");
|
||||
let i = doc.getElementById("i");
|
||||
|
||||
ok(!FillInHTMLTooltip(i),
|
||||
"No tooltip should be shown when @title is null");
|
||||
|
||||
i.title = "foo";
|
||||
ok(FillInHTMLTooltip(i),
|
||||
"A tooltip should be shown when @title is not the empty string");
|
||||
|
||||
i.pattern = "bar";
|
||||
ok(FillInHTMLTooltip(i),
|
||||
"A tooltip should be shown when @title is not the empty string");
|
||||
|
||||
gBrowser.removeCurrentTab();
|
||||
finish();
|
||||
}, true);
|
||||
|
||||
content.location =
|
||||
"data:text/html,<!DOCTYPE html><html><body><input id='i'></body></html>";
|
||||
}
|
||||
|
68
browser/base/content/test/browser_hide_removing.js
Normal file
68
browser/base/content/test/browser_hide_removing.js
Normal file
@ -0,0 +1,68 @@
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is tabbrowser hide removing tab test.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Mozilla Foundation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2010
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Edward Lee <edilee@mozilla.com>
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
// Bug 587922: tabs don't get removed if they're hidden
|
||||
|
||||
function test() {
|
||||
waitForExplicitFinish();
|
||||
|
||||
// Add a tab that will get removed and hidden
|
||||
let testTab = gBrowser.addTab("about:blank", {skipAnimation: true});
|
||||
is(gBrowser.visibleTabs.length, 2, "just added a tab, so 2 tabs");
|
||||
gBrowser.selectedTab = testTab;
|
||||
|
||||
let numVisBeforeHide, numVisAfterHide;
|
||||
gBrowser.tabContainer.addEventListener("TabSelect", function() {
|
||||
gBrowser.tabContainer.removeEventListener("TabSelect", arguments.callee, false);
|
||||
|
||||
// While the next tab is being selected, hide the removing tab
|
||||
numVisBeforeHide = gBrowser.visibleTabs.length;
|
||||
gBrowser.hideTab(testTab);
|
||||
numVisAfterHide = gBrowser.visibleTabs.length;
|
||||
}, false);
|
||||
gBrowser.removeTab(testTab, {animate: true});
|
||||
|
||||
// Make sure the tab gets removed at the end of the animation by polling
|
||||
(function checkRemoved() setTimeout(function() {
|
||||
if (gBrowser.tabs.length != 1)
|
||||
return checkRemoved();
|
||||
|
||||
is(numVisBeforeHide, 1, "animated remove has in 1 tab left");
|
||||
is(numVisAfterHide, 1, "hiding a removing tab is also has 1 tab");
|
||||
finish();
|
||||
}, 50))();
|
||||
}
|
128
browser/base/content/test/browser_inspector_domPanel.js
Normal file
128
browser/base/content/test/browser_inspector_domPanel.js
Normal file
@ -0,0 +1,128 @@
|
||||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=2 et sw=2 tw=80: */
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is Inspector DOM Panel Tests.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* The Mozilla Foundation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2010
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Rob Campbell <rcampbell@mozilla.com>
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
let doc;
|
||||
let testGen;
|
||||
|
||||
function createDocument()
|
||||
{
|
||||
doc.body.innerHTML = '<div id="first" style="{ margin: 10em; ' +
|
||||
'font-size: 14pt; font-family: helvetica, sans-serif; color: #AAA}">\n' +
|
||||
'<h1>Some header text</h1>\n' +
|
||||
'<p id="salutation" style="{font-size: 12pt}">hi.</p>\n' +
|
||||
'<p id="body" style="{font-size: 12pt}">I am a test-case. This text exists ' +
|
||||
'solely to provide some things to <span style="{color: yellow}">' +
|
||||
'highlight</span> and <span style="{font-weight: bold}">count</span> ' +
|
||||
'DOM list-items in the box at right. If you are reading this, ' +
|
||||
'you should go do something else instead. Maybe read a book. Or better ' +
|
||||
'yet, write some test-cases for another bit of code. ' +
|
||||
'<span style="{font-style: italic}">Maybe more inspector test-cases!</span></p>\n' +
|
||||
'<p id="closing">end transmission</p>\n' +
|
||||
'</div>';
|
||||
doc.title = "Inspector DOM Test";
|
||||
document.addEventListener("popupshown", runDOMTests, false);
|
||||
InspectorUI.openInspectorUI();
|
||||
}
|
||||
|
||||
function nodeGenerator()
|
||||
{
|
||||
let body = doc.body;
|
||||
InspectorUI.inspectNode(body);
|
||||
yield;
|
||||
let h1 = doc.querySelector("h1");
|
||||
InspectorUI.inspectNode(h1);
|
||||
yield;
|
||||
let first = doc.getElementById("first");
|
||||
InspectorUI.inspectNode(first);
|
||||
yield;
|
||||
let closing = doc.getElementById("#closing");
|
||||
InspectorUI.inspectNode(closing);
|
||||
yield;
|
||||
}
|
||||
|
||||
function runDOMTests(evt)
|
||||
{
|
||||
if (evt.target.id != "inspector-dom-panel")
|
||||
return true;
|
||||
InspectorUI._log("runDOMtests");
|
||||
document.removeEventListener("popupshown", runDOMTests, false);
|
||||
InspectorUI.stopInspecting();
|
||||
document.addEventListener("popupshown", performTestComparisons, false);
|
||||
testGen = nodeGenerator();
|
||||
testGen.next();
|
||||
}
|
||||
|
||||
function performTestComparisons(evt)
|
||||
{
|
||||
InspectorUI._log("performTestComparisons");
|
||||
if (evt.target.id != "highlighter-panel")
|
||||
return true;
|
||||
|
||||
ok(InspectorUI.treeView.selectedNode, "selection");
|
||||
ok(InspectorUI.isDOMPanelOpen, "DOM panel is open?");
|
||||
ok(InspectorUI.highlighter.isHighlighting, "panel is highlighting");
|
||||
ok(InspectorUI.domTreeView.rowCount > 0, "domBox has items");
|
||||
|
||||
try {
|
||||
testGen.next();
|
||||
} catch(StopIteration) {
|
||||
document.removeEventListener("popupshown", performTestComparisons, false);
|
||||
finishUp();
|
||||
}
|
||||
}
|
||||
|
||||
function finishUp() {
|
||||
InspectorUI.closeInspectorUI();
|
||||
gBrowser.removeCurrentTab();
|
||||
finish();
|
||||
}
|
||||
|
||||
function test()
|
||||
{
|
||||
waitForExplicitFinish();
|
||||
gBrowser.selectedTab = gBrowser.addTab();
|
||||
gBrowser.selectedBrowser.addEventListener("load", function() {
|
||||
gBrowser.selectedBrowser.removeEventListener("load", arguments.callee, true);
|
||||
doc = content.document;
|
||||
waitForFocus(createDocument, content);
|
||||
}, true);
|
||||
|
||||
content.location = "data:text/html,basic tests for inspector";
|
||||
}
|
||||
|
@ -48,20 +48,20 @@ function startInspectorTests()
|
||||
|
||||
function runInspectorTests(evt)
|
||||
{
|
||||
if (evt.target.id != "inspector-panel")
|
||||
if (evt.target.id != "inspector-dom-panel")
|
||||
return true;
|
||||
document.removeEventListener("popupshown", runInspectorTests, false);
|
||||
document.addEventListener("popuphidden", finishInspectorTests, false);
|
||||
ok(InspectorUI.inspecting, "Inspector is highlighting");
|
||||
ok(InspectorUI.isPanelOpen, "Inspector Tree Panel is open");
|
||||
ok(InspectorUI.isStylePanelOpen, "Inspector Style Panel is open");
|
||||
todo(InspectorUI.isDOMPanelOpen, "Inspector DOM Panel is open");
|
||||
ok(InspectorUI.isDOMPanelOpen, "Inspector DOM Panel is open");
|
||||
InspectorUI.toggleInspectorUI();
|
||||
}
|
||||
|
||||
function finishInspectorTests(evt)
|
||||
{
|
||||
if (evt.target.id != "inspector-style-panel")
|
||||
if (evt.target.id != "inspector-dom-panel")
|
||||
return true;
|
||||
document.removeEventListener("popuphidden", finishInspectorTests, false);
|
||||
ok(!InspectorUI.isDOMPanelOpen, "Inspector DOM Panel is closed");
|
||||
|
@ -93,8 +93,7 @@ function performTestComparisons(evt)
|
||||
return true;
|
||||
|
||||
ok(InspectorUI.treeView.selectedNode, "selection");
|
||||
ok(InspectorUI._showStylePanel, "_showStylePanel");
|
||||
is(InspectorUI.isStylePanelOpen, InspectorUI._showStylePanel, "style panel matches _showStylePanel?");
|
||||
ok(InspectorUI.isStylePanelOpen, "style panel is open?");
|
||||
ok(InspectorUI.highlighter.isHighlighting, "panel is highlighting");
|
||||
ok(InspectorUI.styleBox.itemCount > 0, "styleBox has items");
|
||||
|
||||
|
@ -37,7 +37,6 @@
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
Components.utils.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||
Components.utils.import("resource://gre/modules/Services.jsm");
|
||||
|
||||
const TEST_URL_BASES = [
|
||||
"http://example.org/browser/browser/base/content/test/dummy_page.html#tabmatch",
|
||||
@ -119,7 +118,14 @@ var gTestSteps = [
|
||||
});
|
||||
}, true);
|
||||
tab.linkedBrowser.loadURI('data:text/html,<body><iframe src=""></iframe></body>');
|
||||
}
|
||||
},
|
||||
function() {
|
||||
info("Running step 7 - remove tab immediately");
|
||||
let tab = gBrowser.addTab("about:blank");
|
||||
gBrowser.removeTab(tab);
|
||||
ensure_opentabs_match_db();
|
||||
nextStep();
|
||||
},
|
||||
];
|
||||
|
||||
|
||||
@ -130,22 +136,32 @@ function test() {
|
||||
}
|
||||
|
||||
function loadTab(tab, url) {
|
||||
// Because adding visits is async, we will not be notified immediately.
|
||||
let visited = false;
|
||||
|
||||
tab.linkedBrowser.addEventListener("load", function (event) {
|
||||
tab.linkedBrowser.removeEventListener("load", arguments.callee, true);
|
||||
|
||||
if (--gTabWaitCount > 0)
|
||||
return;
|
||||
is(gTabWaitCount, 0,
|
||||
"sanity check, gTabWaitCount should not be decremented below 0");
|
||||
Services.obs.addObserver(
|
||||
function (aSubject, aTopic, aData) {
|
||||
if (url != aSubject.QueryInterface(Ci.nsIURI).spec)
|
||||
return;
|
||||
Services.obs.removeObserver(arguments.callee, aTopic);
|
||||
if (--gTabWaitCount > 0)
|
||||
return;
|
||||
is(gTabWaitCount, 0,
|
||||
"sanity check, gTabWaitCount should not be decremented below 0");
|
||||
|
||||
try {
|
||||
ensure_opentabs_match_db();
|
||||
} catch (e) {
|
||||
ok(false, "exception from ensure_openpages_match_db: " + e);
|
||||
}
|
||||
try {
|
||||
ensure_opentabs_match_db();
|
||||
} catch (e) {
|
||||
ok(false, "exception from ensure_openpages_match_db: " + e);
|
||||
}
|
||||
|
||||
executeSoon(nextStep);
|
||||
executeSoon(nextStep);
|
||||
}, "uri-visit-saved", false);
|
||||
}, true);
|
||||
|
||||
gTabWaitCount++;
|
||||
tab.linkedBrowser.loadURI(url);
|
||||
}
|
||||
@ -191,10 +207,10 @@ function ensure_opentabs_match_db() {
|
||||
|
||||
try {
|
||||
var stmt = db.createStatement(
|
||||
"SELECT IFNULL(p_t.url, p.url) AS url, open_count, place_id " +
|
||||
"FROM moz_openpages_temp " +
|
||||
"LEFT JOIN moz_places p ON p.id=place_id " +
|
||||
"LEFT JOIN moz_places_temp p_t ON p_t.id=place_id");
|
||||
"SELECT t.url, open_count, IFNULL(p_t.id, p.id) " +
|
||||
"FROM moz_openpages_temp t " +
|
||||
"LEFT JOIN moz_places p ON p.url = t.url " +
|
||||
"LEFT JOIN moz_places_temp p_t ON p_t.url = t.url");
|
||||
} catch (e) {
|
||||
ok(false, "error creating db statement: " + e);
|
||||
return;
|
||||
@ -216,19 +232,11 @@ function ensure_opentabs_match_db() {
|
||||
}
|
||||
|
||||
for (let url in tabs) {
|
||||
// ignore URLs that should never be in the places db
|
||||
if (!is_expected_in_db(url))
|
||||
continue;
|
||||
ok(dbtabs.indexOf(url) > -1,
|
||||
"tab is open (" + tabs[url] + " times) and should recorded in db: " + url);
|
||||
}
|
||||
}
|
||||
|
||||
function is_expected_in_db(url) {
|
||||
var uri = Services.io.newURI(url, null, null);
|
||||
return PlacesUtils.history.canAddURI(uri);
|
||||
}
|
||||
|
||||
/**
|
||||
* Clears history invoking callback when done.
|
||||
*/
|
||||
|
@ -0,0 +1,67 @@
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is bookmark all pages test with tab view.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Mozilla Foundation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2010
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Raymond Lee <raymond@appcoast.com>
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
function test() {
|
||||
waitForExplicitFinish();
|
||||
|
||||
let tabOne = gBrowser.addTab("about:blank");
|
||||
let tabTwo = gBrowser.addTab("http://mochi.test:8888/");
|
||||
gBrowser.selectedTab = tabTwo;
|
||||
|
||||
let browser = gBrowser.getBrowserForTab(tabTwo);
|
||||
let onLoad = function() {
|
||||
browser.removeEventListener("load", onLoad, true);
|
||||
|
||||
gBrowser.showOnlyTheseTabs([tabTwo]);
|
||||
|
||||
is(gBrowser.visibleTabs.length, 1, "Only one tab is visible");
|
||||
|
||||
let uris = PlacesCommandHook._getUniqueTabInfo();
|
||||
is(uris.length, 1, "Only one uri is returned");
|
||||
|
||||
is(uris[0].spec, tabTwo.linkedBrowser.currentURI.spec, "It's the correct URI");
|
||||
|
||||
gBrowser.removeTab(tabOne);
|
||||
gBrowser.removeTab(tabTwo);
|
||||
Array.forEach(gBrowser.tabs, function(tab) {
|
||||
gBrowser.showTab(tab);
|
||||
});
|
||||
|
||||
finish();
|
||||
}
|
||||
browser.addEventListener("load", onLoad, true);
|
||||
}
|
@ -0,0 +1,78 @@
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is tabbrowser visibleTabs Bookmark All Tabs test.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Mozilla Foundation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2010
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Michael Yoshitaka Erlewine <mitcho@mitcho.com>
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
function test() {
|
||||
// There should be one tab when we start the test
|
||||
let [origTab] = gBrowser.visibleTabs;
|
||||
is(gBrowser.visibleTabs.length, 1, "1 tab should be open");
|
||||
is(Disabled(), true, "Bookmark All Tabs should be hidden");
|
||||
|
||||
// Add a tab
|
||||
let testTab = gBrowser.addTab();
|
||||
is(gBrowser.visibleTabs.length, 2, "2 tabs should be open");
|
||||
is(Disabled(), false, "Bookmark All Tabs should be available");
|
||||
|
||||
// Hide the original tab
|
||||
gBrowser.selectedTab = testTab;
|
||||
gBrowser.showOnlyTheseTabs([testTab]);
|
||||
is(gBrowser.visibleTabs.length, 1, "1 tab should be visible");
|
||||
is(Disabled(), true, "Bookmark All Tabs should be hidden as there is only one visible tab");
|
||||
|
||||
// Add a tab that will get pinned
|
||||
let pinned = gBrowser.addTab();
|
||||
gBrowser.pinTab(pinned);
|
||||
is(gBrowser.visibleTabs.length, 2, "2 tabs should be visible now");
|
||||
is(Disabled(), false, "Bookmark All Tabs should be available as there are two visible tabs");
|
||||
|
||||
// Show all tabs
|
||||
let allTabs = [tab for each (tab in gBrowser.tabs)];
|
||||
gBrowser.showOnlyTheseTabs(allTabs);
|
||||
|
||||
// reset the environment
|
||||
gBrowser.removeTab(testTab);
|
||||
gBrowser.removeTab(pinned);
|
||||
is(gBrowser.visibleTabs.length, 1, "only orig is left and visible");
|
||||
is(gBrowser.tabs.length, 1, "sanity check that it matches");
|
||||
is(Disabled(), true, "Bookmark All Tabs should be hidden");
|
||||
is(gBrowser.selectedTab, origTab, "got the orig tab");
|
||||
is(origTab.hidden, false, "and it's not hidden -- visible!");
|
||||
}
|
||||
|
||||
function Disabled() {
|
||||
let command = document.getElementById("Browser:BookmarkAllTabs");
|
||||
return command.hasAttribute("disabled") && command.getAttribute("disabled") === "true";
|
||||
}
|
89
browser/base/content/test/browser_visibleTabs_contextMenu.js
Normal file
89
browser/base/content/test/browser_visibleTabs_contextMenu.js
Normal file
@ -0,0 +1,89 @@
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is tabbrowser visibleTabs context menu test.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Mozilla Foundation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2010
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Michael Yoshitaka Erlewine <mitcho@mitcho.com>
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
function test() {
|
||||
// There should be one tab when we start the test
|
||||
let [origTab] = gBrowser.visibleTabs;
|
||||
is(gBrowser.visibleTabs.length, 1, "there is one visible tab");
|
||||
let testTab = gBrowser.addTab();
|
||||
is(gBrowser.visibleTabs.length, 2, "there are now two visible tabs");
|
||||
|
||||
// Check the context menu with two tabs
|
||||
popup(origTab);
|
||||
is(TabContextMenu.contextTab, origTab, "TabContextMenu context is the original tab");
|
||||
is(document.getElementById("context_closeTab").disabled, false, "Close Tab is enabled");
|
||||
is(document.getElementById("context_reloadAllTabs").disabled, false, "Reload All Tabs is enabled");
|
||||
|
||||
// Hide the original tab.
|
||||
gBrowser.selectedTab = testTab;
|
||||
gBrowser.showOnlyTheseTabs([testTab]);
|
||||
is(gBrowser.visibleTabs.length, 1, "now there is only one visible tab");
|
||||
|
||||
// Check the context menu with one tab.
|
||||
popup(testTab);
|
||||
is(TabContextMenu.contextTab, testTab, "TabContextMenu context is the test tab");
|
||||
is(document.getElementById("context_closeTab").disabled, true, "Close Tab is disabled");
|
||||
is(document.getElementById("context_reloadAllTabs").disabled, true, "Reload All Tabs is disabled");
|
||||
|
||||
// Add a tab that will get pinned
|
||||
// So now there's one pinned tab, one visible unpinned tab, and one hidden tab
|
||||
let pinned = gBrowser.addTab();
|
||||
gBrowser.pinTab(pinned);
|
||||
is(gBrowser.visibleTabs.length, 2, "now there are two visible tabs");
|
||||
|
||||
// Check the context menu on the unpinned visible tab
|
||||
popup(testTab);
|
||||
is(TabContextMenu.contextTab, testTab, "TabContextMenu context is again the test tab");
|
||||
is(document.getElementById("context_closeOtherTabs").disabled, true, "Close Other Tabs is disabled");
|
||||
|
||||
// Show all tabs
|
||||
let allTabs = [tab for each (tab in gBrowser.tabs)];
|
||||
gBrowser.showOnlyTheseTabs(allTabs);
|
||||
|
||||
// Check the context menu now
|
||||
popup(testTab);
|
||||
is(TabContextMenu.contextTab, testTab, "TabContextMenu context is yet again the test tab");
|
||||
is(document.getElementById("context_closeOtherTabs").disabled, false, "Close Other Tabs is enabled");
|
||||
|
||||
gBrowser.removeTab(testTab);
|
||||
gBrowser.removeTab(pinned);
|
||||
}
|
||||
|
||||
function popup(tab) {
|
||||
document.popupNode = tab;
|
||||
TabContextMenu.updateContextMenu(document.getElementById("tabContextMenu"));
|
||||
}
|
74
browser/base/content/test/browser_visibleTabs_tabPreview.js
Normal file
74
browser/base/content/test/browser_visibleTabs_tabPreview.js
Normal file
@ -0,0 +1,74 @@
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is tab preview with tab view.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Mozilla Foundation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2010
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Raymond Lee <raymond@appcoast.com>
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
function test() {
|
||||
gPrefService.setBoolPref("browser.ctrlTab.previews", true);
|
||||
|
||||
let [origTab] = gBrowser.visibleTabs;
|
||||
let tabOne = gBrowser.addTab();
|
||||
let tabTwo = gBrowser.addTab();
|
||||
|
||||
// test the ctrlTab.tabList
|
||||
pressCtrlTab();
|
||||
ok(ctrlTab.tabList.length, 3, "Show 3 tabs in tab preview");
|
||||
releaseCtrl();
|
||||
|
||||
gBrowser.showOnlyTheseTabs([origTab]);
|
||||
pressCtrlTab();
|
||||
ok(ctrlTab.tabList.length, 1, "Show 1 tab in tab preview");
|
||||
ok(!ctrlTab.isOpen, "With 1 tab open, Ctrl+Tab doesn't open the preview panel");
|
||||
|
||||
gBrowser.showOnlyTheseTabs([origTab, tabOne, tabTwo]);
|
||||
pressCtrlTab();
|
||||
ok(ctrlTab.isOpen, "With 3 tabs open, Ctrl+Tab does open the preview panel");
|
||||
releaseCtrl();
|
||||
|
||||
// cleanup
|
||||
gBrowser.removeTab(tabOne);
|
||||
gBrowser.removeTab(tabTwo);
|
||||
|
||||
if (gPrefService.prefHasUserValue("browser.ctrlTab.previews"))
|
||||
gPrefService.clearUserPref("browser.ctrlTab.previews");
|
||||
}
|
||||
|
||||
function pressCtrlTab(aShiftKey) {
|
||||
EventUtils.synthesizeKey("VK_TAB", { ctrlKey: true, shiftKey: !!aShiftKey });
|
||||
}
|
||||
|
||||
function releaseCtrl() {
|
||||
EventUtils.synthesizeKey("VK_CONTROL", { type: "keyup" });
|
||||
}
|
55
browser/base/content/test/tabview/Makefile.in
Normal file
55
browser/base/content/test/tabview/Makefile.in
Normal file
@ -0,0 +1,55 @@
|
||||
# ***** BEGIN LICENSE BLOCK *****
|
||||
# Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
#
|
||||
# The contents of this file are subject to the Mozilla Public License Version
|
||||
# 1.1 (the "License"); you may not use this file except in compliance with
|
||||
# the License. You may obtain a copy of the License at
|
||||
# http://www.mozilla.org/MPL/
|
||||
#
|
||||
# Software distributed under the License is distributed on an "AS IS" basis,
|
||||
# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
# for the specific language governing rights and limitations under the
|
||||
# License.
|
||||
#
|
||||
# The Original Code is mozilla.org code.
|
||||
#
|
||||
# The Initial Developer of the Original Code is
|
||||
# Mozilla Foundation.
|
||||
# Portions created by the Initial Developer are Copyright (C) 2007
|
||||
# the Initial Developer. All Rights Reserved.
|
||||
#
|
||||
# Contributor(s):
|
||||
#
|
||||
# Alternatively, the contents of this file may be used under the terms of
|
||||
# either of the GNU General Public License Version 2 or later (the "GPL"),
|
||||
# or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
# in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
# of those above. If you wish to allow use of your version of this file only
|
||||
# under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
# use your version of this file under the terms of the MPL, indicate your
|
||||
# decision by deleting the provisions above and replace them with the notice
|
||||
# and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
# the provisions above, a recipient may use your version of this file under
|
||||
# the terms of any one of the MPL, the GPL or the LGPL.
|
||||
#
|
||||
# ***** END LICENSE BLOCK *****
|
||||
|
||||
DEPTH = ../../../../..
|
||||
topsrcdir = @top_srcdir@
|
||||
srcdir = @srcdir@
|
||||
VPATH = @srcdir@
|
||||
relativesrcdir = browser/base/content/test/tabview
|
||||
|
||||
include $(DEPTH)/config/autoconf.mk
|
||||
include $(topsrcdir)/config/rules.mk
|
||||
|
||||
$(warning All TabView tests are disabled for now while we iterate on the UI)
|
||||
|
||||
_BROWSER_FILES = \
|
||||
browser_tabview_launch.js \
|
||||
$(NULL)
|
||||
# browser_tabview_dragdrop.js \
|
||||
# browser_tabview_group.js \
|
||||
|
||||
libs:: $(_BROWSER_FILES)
|
||||
$(INSTALL) $(foreach f,$^,"$f") $(DEPTH)/_tests/testing/mochitest/browser/$(relativesrcdir)
|
159
browser/base/content/test/tabview/browser_tabview_dragdrop.js
Normal file
159
browser/base/content/test/tabview/browser_tabview_dragdrop.js
Normal file
@ -0,0 +1,159 @@
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is tabview drag and drop test.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Mozilla Foundation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2010
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Raymond Lee <raymond@appcoast.com>
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
function test() {
|
||||
waitForExplicitFinish();
|
||||
|
||||
window.addEventListener("tabviewshown", onTabViewWindowLoaded, false);
|
||||
setTimeout(function() { TabView.toggle(); }, 0);
|
||||
}
|
||||
|
||||
function onTabViewWindowLoaded() {
|
||||
window.removeEventListener("tabviewshown", onTabViewWindowLoaded, false);
|
||||
|
||||
ok(TabView.isVisible(), "Tab View is visible");
|
||||
|
||||
let contentWindow = document.getElementById("tab-view").contentWindow;
|
||||
|
||||
// create group one and two
|
||||
let padding = 10;
|
||||
let pageBounds = contentWindow.Items.getPageBounds();
|
||||
pageBounds.inset(padding, padding);
|
||||
|
||||
let box = new contentWindow.Rect(pageBounds);
|
||||
box.width = 300;
|
||||
box.height = 300;
|
||||
|
||||
let groupOne = new contentWindow.GroupItem([], { bounds: box });
|
||||
ok(groupOne.isEmpty(), "This group is empty");
|
||||
|
||||
let groupTwo = new contentWindow.GroupItem([], { bounds: box });
|
||||
|
||||
groupOne.addSubscriber(groupOne, "tabAdded", function() {
|
||||
groupOne.removeSubscriber(groupOne, "tabAdded");
|
||||
groupTwo.newTab("");
|
||||
});
|
||||
groupTwo.addSubscriber(groupTwo, "tabAdded", function() {
|
||||
groupTwo.removeSubscriber(groupTwo, "tabAdded");
|
||||
// carry on testing
|
||||
addTest(contentWindow, groupOne.id, groupTwo.id);
|
||||
});
|
||||
|
||||
let count = 0;
|
||||
let onTabViewHidden = function() {
|
||||
// show the tab view.
|
||||
TabView.toggle();
|
||||
if (++count == 2) {
|
||||
window.removeEventListener("tabviewhidden", onTabViewHidden, false);
|
||||
}
|
||||
};
|
||||
window.addEventListener("tabviewhidden", onTabViewHidden, false);
|
||||
|
||||
// open tab in group
|
||||
groupOne.newTab("");
|
||||
}
|
||||
|
||||
function addTest(contentWindow, groupOneId, groupTwoId) {
|
||||
let groupOne = contentWindow.GroupItems.groupItem(groupOneId);
|
||||
let groupTwo = contentWindow.GroupItems.groupItem(groupTwoId);
|
||||
let groupOneTabItemCount = groupOne.getChildren().length;
|
||||
let groupTwoTabItemCount = groupTwo.getChildren().length;
|
||||
is(groupOneTabItemCount, 1, "GroupItem one has a tab");
|
||||
is(groupTwoTabItemCount, 1, "GroupItem two has two tabs");
|
||||
|
||||
let srcElement = groupOne.getChild(0).container;
|
||||
ok(srcElement, "The source element exists");
|
||||
|
||||
// calculate the offsets
|
||||
let groupTwoRect = groupTwo.container.getBoundingClientRect();
|
||||
let srcElementRect = srcElement.getBoundingClientRect();
|
||||
let offsetX =
|
||||
Math.round(groupTwoRect.left + groupTwoRect.width/5) - srcElementRect.left;
|
||||
let offsetY =
|
||||
Math.round(groupTwoRect.top + groupTwoRect.height/5) - srcElementRect.top;
|
||||
|
||||
simulateDragDrop(srcElement, offsetX, offsetY, contentWindow);
|
||||
|
||||
is(groupOne.getChildren().length, --groupOneTabItemCount,
|
||||
"The number of children in group one is decreased by 1");
|
||||
is(groupTwo.getChildren().length, ++groupTwoTabItemCount,
|
||||
"The number of children in group two is increased by 1");
|
||||
|
||||
let onTabViewHidden = function() {
|
||||
window.removeEventListener("tabviewhidden", onTabViewHidden, false);
|
||||
finish();
|
||||
};
|
||||
window.addEventListener("tabviewhidden", onTabViewHidden, false);
|
||||
|
||||
groupTwo.addSubscriber(groupTwo, "close", function() {
|
||||
groupTwo.removeSubscriber(groupTwo, "close");
|
||||
contentWindow.UI.hideTabView();
|
||||
});
|
||||
groupTwo.closeAll();
|
||||
}
|
||||
|
||||
function simulateDragDrop(srcElement, offsetX, offsetY, contentWindow) {
|
||||
// enter drag mode
|
||||
let dataTransfer;
|
||||
|
||||
EventUtils.synthesizeMouse(
|
||||
srcElement, 1, 1, { type: "mousedown" }, contentWindow);
|
||||
event = contentWindow.document.createEvent("DragEvents");
|
||||
event.initDragEvent(
|
||||
"dragenter", true, true, contentWindow, 0, 0, 0, 0, 0,
|
||||
false, false, false, false, 1, null, dataTransfer);
|
||||
srcElement.dispatchEvent(event);
|
||||
|
||||
// drag over
|
||||
for (let i = 4; i >= 0; i--)
|
||||
EventUtils.synthesizeMouse(
|
||||
srcElement, Math.round(offsetX/5), Math.round(offsetY/4),
|
||||
{ type: "mousemove" }, contentWindow);
|
||||
event = contentWindow.document.createEvent("DragEvents");
|
||||
event.initDragEvent(
|
||||
"dragover", true, true, contentWindow, 0, 0, 0, 0, 0,
|
||||
false, false, false, false, 0, null, dataTransfer);
|
||||
srcElement.dispatchEvent(event);
|
||||
|
||||
// drop
|
||||
EventUtils.synthesizeMouse(srcElement, 0, 0, { type: "mouseup" }, contentWindow);
|
||||
event = contentWindow.document.createEvent("DragEvents");
|
||||
event.initDragEvent(
|
||||
"drop", true, true, contentWindow, 0, 0, 0, 0, 0,
|
||||
false, false, false, false, 0, null, dataTransfer);
|
||||
srcElement.dispatchEvent(event);
|
||||
}
|
140
browser/base/content/test/tabview/browser_tabview_group.js
Normal file
140
browser/base/content/test/tabview/browser_tabview_group.js
Normal file
@ -0,0 +1,140 @@
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is tabview group test.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Mozilla Foundation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2010
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Raymond Lee <raymond@appcoast.com>
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
function test() {
|
||||
waitForExplicitFinish();
|
||||
|
||||
window.addEventListener("tabviewshown", onTabViewWindowLoaded, false);
|
||||
TabView.toggle();
|
||||
}
|
||||
|
||||
function onTabViewWindowLoaded() {
|
||||
window.removeEventListener("tabviewshown", onTabViewWindowLoaded, false);
|
||||
ok(TabView.isVisible(), "Tab View is visible");
|
||||
|
||||
let contentWindow = document.getElementById("tab-view").contentWindow;
|
||||
testEmptyGroupItem(contentWindow);
|
||||
}
|
||||
|
||||
function testEmptyGroupItem(contentWindow) {
|
||||
let groupItemCount = contentWindow.GroupItems.groupItems.length;
|
||||
|
||||
// create empty group item
|
||||
let emptyGroupItem = createEmptyGroupItem(contentWindow, 100);
|
||||
ok(emptyGroupItem.isEmpty(), "This group is empty");
|
||||
|
||||
is(contentWindow.GroupItems.groupItems.length, ++groupItemCount,
|
||||
"The number of groups is increased by 1");
|
||||
|
||||
emptyGroupItem.addSubscriber(emptyGroupItem, "close", function() {
|
||||
emptyGroupItem.removeSubscriber(emptyGroupItem, "close");
|
||||
|
||||
// check the number of groups.
|
||||
is(contentWindow.GroupItems.groupItems.length, --groupItemCount,
|
||||
"The number of groups is decreased by 1");
|
||||
|
||||
testGroupItemWithTabItem(contentWindow);
|
||||
});
|
||||
|
||||
let closeButton = emptyGroupItem.container.getElementsByClassName("close");
|
||||
ok(closeButton[0], "Group close button exists");
|
||||
|
||||
// click the close button
|
||||
EventUtils.synthesizeMouse(closeButton[0], 1, 1, {}, contentWindow);
|
||||
}
|
||||
|
||||
function testGroupItemWithTabItem(contentWindow) {
|
||||
let groupItem = createEmptyGroupItem(contentWindow, 200);
|
||||
let tabItemCount = 0;
|
||||
|
||||
groupItem.addSubscriber(groupItem, "tabAdded", function() {
|
||||
groupItem.removeSubscriber(groupItem, "tabAdded");
|
||||
TabView.toggle();
|
||||
});
|
||||
|
||||
let onTabViewHidden = function() {
|
||||
window.removeEventListener("tabviewhidden", onTabViewHidden, false);
|
||||
|
||||
is(groupItem.getChildren().length, ++tabItemCount,
|
||||
"The number of children in new tab group is increased by 1");
|
||||
|
||||
let tabItem = groupItem.getChild(groupItem.getChildren().length - 1);
|
||||
ok(tabItem, "Tab item exists");
|
||||
|
||||
let tabRemoved = false;
|
||||
tabItem.addSubscriber(tabItem, "close", function() {
|
||||
tabItem.removeSubscriber(tabItem, "close");
|
||||
|
||||
ok(tabRemoved, "Tab is removed");
|
||||
// tabItem would get destroyed after the close event is sent so we have a 0 delay here.
|
||||
is(groupItem.getChildren().length, --tabItemCount,
|
||||
"The number of children in new tab group is decreased by 1");
|
||||
finish();
|
||||
});
|
||||
tabItem.addSubscriber(tabItem, "tabRemoved", function() {
|
||||
tabItem.removeSubscriber(tabItem, "tabRemoved");
|
||||
tabRemoved = true;
|
||||
});
|
||||
|
||||
// remove the tab item. The code detects mousedown and mouseup so we stimulate here
|
||||
let closeButton = tabItem.container.getElementsByClassName("close");
|
||||
ok(closeButton, "Tab item close button exists");
|
||||
|
||||
EventUtils.sendMouseEvent({ type: "mousedown" }, closeButton[0], contentWindow);
|
||||
EventUtils.sendMouseEvent({ type: "mouseup" }, closeButton[0], contentWindow);
|
||||
};
|
||||
|
||||
window.addEventListener("tabviewhidden", onTabViewHidden, false);
|
||||
// click on the + button
|
||||
let newTabButton = groupItem.container.getElementsByClassName("newTabButton");
|
||||
ok(newTabButton[0], "New tab button exists");
|
||||
|
||||
EventUtils.synthesizeMouse(newTabButton[0], 1, 1, {}, contentWindow);
|
||||
}
|
||||
|
||||
function createEmptyGroupItem(contentWindow, padding) {
|
||||
let pageBounds = contentWindow.Items.getPageBounds();
|
||||
pageBounds.inset(padding, padding);
|
||||
|
||||
let box = new contentWindow.Rect(pageBounds);
|
||||
box.width = 300;
|
||||
box.height = 300;
|
||||
|
||||
let emptyGroupItem = new contentWindow.GroupItem([], { bounds: box });
|
||||
|
||||
return emptyGroupItem;
|
||||
}
|
87
browser/base/content/test/tabview/browser_tabview_launch.js
Normal file
87
browser/base/content/test/tabview/browser_tabview_launch.js
Normal file
@ -0,0 +1,87 @@
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is tabview launch test.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Mozilla Foundation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2010
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Raymond Lee <raymond@appcoast.com>
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
function test() {
|
||||
waitForExplicitFinish();
|
||||
|
||||
let tabViewShownCount = 0;
|
||||
let onTabViewHidden = function() {
|
||||
ok(!TabView.isVisible(), "Tab View is hidden");
|
||||
|
||||
if (tabViewShownCount == 1) {
|
||||
document.getElementById("menu_tabview").doCommand();
|
||||
} else if (tabViewShownCount == 2) {
|
||||
var utils = window.QueryInterface(Components.interfaces.nsIInterfaceRequestor).
|
||||
getInterface(Components.interfaces.nsIDOMWindowUtils);
|
||||
if (utils) {
|
||||
var keyCode = 0;
|
||||
var charCode;
|
||||
var eventObject;
|
||||
if (navigator.platform.indexOf("Mac") != -1) {
|
||||
charCode = 160;
|
||||
eventObject = { altKey: true };
|
||||
} else {
|
||||
charCode = 32;
|
||||
eventObject = { ctrlKey: true };
|
||||
}
|
||||
var modifiers = EventUtils._parseModifiers(eventObject);
|
||||
var keyDownDefaultHappened =
|
||||
utils.sendKeyEvent("keydown", keyCode, charCode, modifiers);
|
||||
utils.sendKeyEvent("keypress", keyCode, charCode, modifiers,
|
||||
!keyDownDefaultHappened);
|
||||
utils.sendKeyEvent("keyup", keyCode, charCode, modifiers);
|
||||
}
|
||||
} else if (tabViewShownCount == 3) {
|
||||
window.removeEventListener("tabviewshown", onTabViewShown, false);
|
||||
window.removeEventListener("tabviewhidden", onTabViewHidden, false);
|
||||
finish();
|
||||
}
|
||||
}
|
||||
let onTabViewShown = function() {
|
||||
ok(TabView.isVisible(), "Tab View is visible");
|
||||
tabViewShownCount++
|
||||
TabView.toggle();
|
||||
}
|
||||
window.addEventListener("tabviewshown", onTabViewShown, false);
|
||||
window.addEventListener("tabviewhidden", onTabViewHidden, false);
|
||||
|
||||
ok(!TabView.isVisible(), "Tab View is hidden");
|
||||
|
||||
let button = document.getElementById("tabview-button");
|
||||
ok(button, "Tab View button exists");
|
||||
EventUtils.synthesizeMouse(button, 1, 1, {});
|
||||
}
|
@ -46,6 +46,9 @@ browser.jar:
|
||||
content/browser/sanitizeDialog.css (content/sanitizeDialog.css)
|
||||
* content/browser/tabbrowser.css (content/tabbrowser.css)
|
||||
* content/browser/tabbrowser.xml (content/tabbrowser.xml)
|
||||
content/browser/tabview.css (content/tabview/tabview.css)
|
||||
* content/browser/tabview.js (content/tabview/tabview.js)
|
||||
content/browser/tabview.html (content/tabview/tabview.html)
|
||||
* content/browser/urlbarBindings.xml (content/urlbarBindings.xml)
|
||||
* content/browser/utilityOverlay.js (content/utilityOverlay.js)
|
||||
* content/browser/web-panels.js (content/web-panels.js)
|
||||
|
@ -853,8 +853,7 @@ nsDefaultCommandLineHandler.prototype = {
|
||||
}
|
||||
},
|
||||
|
||||
// XXX localize me... how?
|
||||
helpInfo : "Usage: firefox [-flags] [<url>]\n",
|
||||
helpInfo : "",
|
||||
};
|
||||
|
||||
var components = [nsBrowserContentHandler, nsDefaultCommandLineHandler];
|
||||
|
@ -128,6 +128,31 @@ BrowserGlue.prototype = {
|
||||
Services.prefs.savePrefFile(null);
|
||||
},
|
||||
|
||||
#ifdef MOZ_SERVICES_SYNC
|
||||
_setSyncAutoconnectDelay: function BG__setSyncAutoconnectDelay() {
|
||||
// Assume that a non-zero value for services.sync.autoconnectDelay should override
|
||||
if (Services.prefs.prefHasUserValue("services.sync.autoconnectDelay")) {
|
||||
let prefDelay = Services.prefs.getIntPref("services.sync.autoconnectDelay");
|
||||
|
||||
if (prefDelay > 0)
|
||||
return;
|
||||
}
|
||||
|
||||
// delays are in seconds
|
||||
const MAX_DELAY = 300;
|
||||
let delay = 3;
|
||||
let enum = Services.wm.getEnumerator("navigator:browser");
|
||||
while (enum.hasMoreElements()) {
|
||||
delay += enum.getNext().gBrowser.tabs.length;
|
||||
}
|
||||
delay = delay <= MAX_DELAY ? delay : MAX_DELAY;
|
||||
|
||||
let syncTemp = {};
|
||||
Cu.import("resource://services-sync/service.js", syncTemp);
|
||||
syncTemp.Weave.Service.delayedAutoConnect(delay);
|
||||
},
|
||||
#endif
|
||||
|
||||
// nsIObserver implementation
|
||||
observe: function BG_observe(subject, topic, data) {
|
||||
switch (topic) {
|
||||
@ -165,6 +190,11 @@ BrowserGlue.prototype = {
|
||||
case "browser-lastwindow-close-granted":
|
||||
this._setPrefToSaveSession();
|
||||
break;
|
||||
#endif
|
||||
#ifdef MOZ_SERVICES_SYNC
|
||||
case "weave:service:ready":
|
||||
this._setSyncAutoconnectDelay();
|
||||
break;
|
||||
#endif
|
||||
case "session-save":
|
||||
this._setPrefToSaveSession(true);
|
||||
@ -238,6 +268,9 @@ BrowserGlue.prototype = {
|
||||
#ifdef OBSERVE_LASTWINDOW_CLOSE_TOPICS
|
||||
os.addObserver(this, "browser-lastwindow-close-requested", false);
|
||||
os.addObserver(this, "browser-lastwindow-close-granted", false);
|
||||
#endif
|
||||
#ifdef MOZ_SERVICES_SYNC
|
||||
os.addObserver(this, "weave:service:ready", false);
|
||||
#endif
|
||||
os.addObserver(this, "session-save", false);
|
||||
os.addObserver(this, "places-init-complete", false);
|
||||
@ -262,6 +295,9 @@ BrowserGlue.prototype = {
|
||||
#ifdef OBSERVE_LASTWINDOW_CLOSE_TOPICS
|
||||
os.removeObserver(this, "browser-lastwindow-close-requested");
|
||||
os.removeObserver(this, "browser-lastwindow-close-granted");
|
||||
#endif
|
||||
#ifdef MOZ_SERVICES_SYNC
|
||||
os.removeObserver(this, "weave:service:ready", false);
|
||||
#endif
|
||||
os.removeObserver(this, "session-save");
|
||||
if (this._isIdleObserver)
|
||||
@ -385,29 +421,6 @@ BrowserGlue.prototype = {
|
||||
temp.WinTaskbarJumpList.startup();
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef MOZ_SERVICES_SYNC
|
||||
// Assume that a non-zero value for services.sync.autoconnectDelay should override
|
||||
if (Services.prefs.prefHasUserValue("services.sync.autoconnectDelay")) {
|
||||
let prefDelay = Services.prefs.getIntPref("services.sync.autoconnectDelay");
|
||||
|
||||
if (prefDelay > 0)
|
||||
return;
|
||||
}
|
||||
|
||||
// delays are in seconds
|
||||
const MAX_DELAY = 300;
|
||||
let delay = 3;
|
||||
let enum = Services.wm.getEnumerator("navigator:browser");
|
||||
while (enum.hasMoreElements()) {
|
||||
delay += enum.getNext().gBrowser.tabs.length;
|
||||
}
|
||||
delay = delay <= MAX_DELAY ? delay : MAX_DELAY;
|
||||
|
||||
let syncTemp = {};
|
||||
Cu.import("resource://services-sync/service.js", syncTemp);
|
||||
syncTemp.Weave.Service.delayedAutoConnect(delay);
|
||||
#endif
|
||||
},
|
||||
|
||||
@ -1387,7 +1400,7 @@ GeolocationPrompt.prototype = {
|
||||
|
||||
chromeWin.PopupNotifications.show(browser, "geolocation", message, "geo-notification-icon",
|
||||
mainAction, secondaryActions);
|
||||
},
|
||||
}
|
||||
};
|
||||
|
||||
var components = [BrowserGlue, GeolocationPrompt];
|
||||
|
@ -46,11 +46,8 @@ include $(topsrcdir)/config/rules.mk
|
||||
|
||||
_BROWSER_TEST_FILES = \
|
||||
browser_console_clear.js \
|
||||
browser_privatebrowsing_beforeunload_enter.js \
|
||||
browser_privatebrowsing_beforeunload_exit.js \
|
||||
browser_privatebrowsing_certexceptionsui.js \
|
||||
browser_privatebrowsing_commandline_toggle.js \
|
||||
browser_privatebrowsing_cookieacceptdialog.js \
|
||||
browser_privatebrowsing_crh.js \
|
||||
browser_privatebrowsing_downloadmonitor.js \
|
||||
browser_privatebrowsing_fastswitch.js \
|
||||
@ -87,5 +84,14 @@ _BROWSER_TEST_FILES = \
|
||||
title.sjs \
|
||||
$(NULL)
|
||||
|
||||
# Turn off private browsing tests that perma-timeout on Linux.
|
||||
ifneq (Linux,$(OS_ARCH))
|
||||
_BROWSER_TEST_FILES += \
|
||||
browser_privatebrowsing_beforeunload_enter.js \
|
||||
browser_privatebrowsing_beforeunload_exit.js \
|
||||
browser_privatebrowsing_cookieacceptdialog.js \
|
||||
$(NULL)
|
||||
endif
|
||||
|
||||
libs:: $(_BROWSER_TEST_FILES)
|
||||
$(INSTALL) $(foreach f,$^,"$f") $(DEPTH)/_tests/testing/mochitest/browser/$(relativesrcdir)
|
||||
|
@ -143,14 +143,6 @@ function restoreSession() {
|
||||
}, true);
|
||||
}
|
||||
|
||||
function startNewSession() {
|
||||
var prefBranch = Cc["@mozilla.org/preferences-service;1"].getService(Ci.nsIPrefBranch);
|
||||
if (prefBranch.getIntPref("browser.startup.page") == 0)
|
||||
getBrowserWindow().gBrowser.loadURI("about:blank");
|
||||
else
|
||||
getBrowserWindow().BrowserHome();
|
||||
}
|
||||
|
||||
function onListClick(aEvent) {
|
||||
// don't react to right-clicks
|
||||
if (aEvent.button == 2)
|
||||
|
@ -103,21 +103,9 @@
|
||||
|
||||
<!-- Buttons -->
|
||||
<hbox xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul" id="buttons">
|
||||
#ifdef XP_UNIX
|
||||
<button id="errorCancel" label="&restorepage.cancelButton;"
|
||||
accesskey="&restorepage.cancel.access;"
|
||||
oncommand="startNewSession();"/>
|
||||
<button id="errorTryAgain" label="&restorepage.tryagainButton;"
|
||||
accesskey="&restorepage.restore.access;"
|
||||
oncommand="restoreSession();"/>
|
||||
#else
|
||||
<button id="errorTryAgain" label="&restorepage.tryagainButton;"
|
||||
accesskey="&restorepage.restore.access;"
|
||||
oncommand="restoreSession();"/>
|
||||
<button id="errorCancel" label="&restorepage.cancelButton;"
|
||||
accesskey="&restorepage.cancel.access;"
|
||||
oncommand="startNewSession();"/>
|
||||
#endif
|
||||
</hbox>
|
||||
<!-- holds the session data for when the tab is closed -->
|
||||
<input type="text" id="sessionData" style="display: none;"/>
|
||||
|
@ -1,3 +1,3 @@
|
||||
browser.jar:
|
||||
* content/browser/aboutSessionRestore.xhtml (content/aboutSessionRestore.xhtml)
|
||||
content/browser/aboutSessionRestore.xhtml (content/aboutSessionRestore.xhtml)
|
||||
* content/browser/aboutSessionRestore.js (content/aboutSessionRestore.js)
|
||||
|
@ -99,7 +99,6 @@ _BROWSER_TEST_FILES = \
|
||||
browser_476161_sample.html \
|
||||
browser_477657.js \
|
||||
browser_480148.js \
|
||||
browser_480893.js \
|
||||
browser_483330.js \
|
||||
browser_485482.js \
|
||||
browser_485482_sample.html \
|
||||
|
@ -80,8 +80,9 @@ function test() {
|
||||
"text containing | and # is correctly restored");
|
||||
is(win.frames[1].document.getElementById("out2").value, "",
|
||||
"id prefixes can't be faked");
|
||||
isnot(win.frames[0].frames[1].document.getElementById("in1").value, "",
|
||||
"id prefixes aren't mixed up");
|
||||
// Disabled for now, Bug 588077
|
||||
// isnot(win.frames[0].frames[1].document.getElementById("in1").value, "",
|
||||
// "id prefixes aren't mixed up");
|
||||
is(win.frames[1].frames[0].document.getElementById("in1").value, "",
|
||||
"id prefixes aren't mixed up");
|
||||
|
||||
|
@ -1,90 +0,0 @@
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is sessionstore test code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Michael Kohler <michaelkohler@live.com>.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2009
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
function test() {
|
||||
/** Test for Bug 480893 **/
|
||||
|
||||
waitForExplicitFinish();
|
||||
|
||||
// Test that starting a new session loads a blank page if Firefox is
|
||||
// configured to display a blank page at startup (browser.startup.page = 0)
|
||||
gPrefService.setIntPref("browser.startup.page", 0);
|
||||
let tab = gBrowser.addTab("about:sessionrestore");
|
||||
gBrowser.selectedTab = tab;
|
||||
let browser = tab.linkedBrowser;
|
||||
browser.addEventListener("load", function(aEvent) {
|
||||
browser.removeEventListener("load", arguments.callee, true);
|
||||
let doc = browser.contentDocument;
|
||||
|
||||
// click on the "Start New Session" button after about:sessionrestore is loaded
|
||||
doc.getElementById("errorCancel").click();
|
||||
browser.addEventListener("load", function(aEvent) {
|
||||
browser.removeEventListener("load", arguments.callee, true);
|
||||
let doc = browser.contentDocument;
|
||||
|
||||
is(doc.URL, "about:blank", "loaded page is about:blank");
|
||||
|
||||
// Test that starting a new session loads the homepage (set to http://mochi.test:8888)
|
||||
// if Firefox is configured to display a homepage at startup (browser.startup.page = 1)
|
||||
let homepage = "http://mochi.test:8888/";
|
||||
gPrefService.setCharPref("browser.startup.homepage", homepage);
|
||||
gPrefService.setIntPref("browser.startup.page", 1);
|
||||
gBrowser.loadURI("about:sessionrestore");
|
||||
browser.addEventListener("load", function(aEvent) {
|
||||
browser.removeEventListener("load", arguments.callee, true);
|
||||
let doc = browser.contentDocument;
|
||||
|
||||
// click on the "Start New Session" button after about:sessionrestore is loaded
|
||||
doc.getElementById("errorCancel").click();
|
||||
browser.addEventListener("load", function(aEvent) {
|
||||
browser.removeEventListener("load", arguments.callee, true);
|
||||
let doc = browser.contentDocument;
|
||||
|
||||
is(doc.URL, homepage, "loaded page is the homepage");
|
||||
|
||||
// close tab, restore default values and finish the test
|
||||
gBrowser.removeTab(tab);
|
||||
// we need this if-statement because if there is no user set value,
|
||||
// clearUserPref throws a uncatched exception and finish is not called
|
||||
if (gPrefService.prefHasUserValue("browser.startup.page"))
|
||||
gPrefService.clearUserPref("browser.startup.page");
|
||||
gPrefService.clearUserPref("browser.startup.homepage");
|
||||
finish();
|
||||
}, true);
|
||||
}, true);
|
||||
}, true);
|
||||
}, true);
|
||||
}
|
@ -1 +1 @@
|
||||
4.0b4pre
|
||||
4.0b5pre
|
||||
|
@ -41,11 +41,12 @@ MOZ_UPDATER=1
|
||||
MOZ_PHOENIX=1
|
||||
|
||||
MOZ_ENABLE_LIBXUL=1
|
||||
MOZ_CHROME_FILE_FORMAT=omni
|
||||
MOZ_STATIC_BUILD_UNSUPPORTED=1
|
||||
# always enabled for form history
|
||||
MOZ_MORKREADER=1
|
||||
MOZ_SAFE_BROWSING=1
|
||||
MOZ_SERVICES_SYNC=
|
||||
MOZ_SERVICES_SYNC=1
|
||||
MOZ_APP_VERSION=$FIREFOX_VERSION
|
||||
MOZ_EXTENSIONS_DEFAULT=" gnomevfs reporter"
|
||||
# MOZ_APP_DISPLAYNAME will be set by branding/configure.sh
|
||||
|
@ -82,6 +82,12 @@ ifdef _MSC_VER
|
||||
DEFINES += -D_MSC_VER=$(_MSC_VER)
|
||||
endif
|
||||
|
||||
ifeq ($(MOZ_CHROME_FILE_FORMAT),jar)
|
||||
DEFINES += -DJAREXT=.jar
|
||||
else
|
||||
DEFINES += -DJAREXT=
|
||||
endif
|
||||
|
||||
# Don't ifdef MOZ_IPC this because mac ppc needs it too.
|
||||
include $(topsrcdir)/ipc/app/defs.mk
|
||||
DEFINES += -DMOZ_CHILD_PROCESS_NAME=$(MOZ_CHILD_PROCESS_NAME)
|
||||
|
@ -19,7 +19,7 @@
|
||||
#endif
|
||||
|
||||
[@AB_CD@]
|
||||
@BINPATH@/chrome/@AB_CD@.jar
|
||||
@BINPATH@/chrome/@AB_CD@@JAREXT@
|
||||
@BINPATH@/chrome/@AB_CD@.manifest
|
||||
@BINPATH@/@PREF_DIR@/firefox-l10n.js
|
||||
@BINPATH@/searchplugins/*
|
||||
@ -38,7 +38,9 @@
|
||||
|
||||
[xpcom]
|
||||
@BINPATH@/dependentlibs.list
|
||||
#ifndef MOZ_STATIC_JS
|
||||
@BINPATH@/@DLL_PREFIX@mozjs@DLL_SUFFIX@
|
||||
#endif
|
||||
@BINPATH@/@DLL_PREFIX@plc4@DLL_SUFFIX@
|
||||
@BINPATH@/@DLL_PREFIX@plds4@DLL_SUFFIX@
|
||||
@BINPATH@/@DLL_PREFIX@xpcom@DLL_SUFFIX@
|
||||
@ -185,6 +187,7 @@
|
||||
@BINPATH@/components/jetpack.xpt
|
||||
@BINPATH@/components/jsdservice.xpt
|
||||
@BINPATH@/components/layout_base.xpt
|
||||
@BINPATH@/components/layout_forms.xpt
|
||||
#ifdef NS_PRINTING
|
||||
@BINPATH@/components/layout_printing.xpt
|
||||
#endif
|
||||
@ -233,7 +236,6 @@
|
||||
#ifdef MOZ_ENABLE_XREMOTE
|
||||
@BINPATH@/components/toolkitremote.xpt
|
||||
#endif
|
||||
@BINPATH@/components/toolkitsearch.xpt
|
||||
@BINPATH@/components/txtsvc.xpt
|
||||
@BINPATH@/components/txmgr.xpt
|
||||
#ifdef MOZ_USE_NATIVE_UCONV
|
||||
@ -401,7 +403,7 @@
|
||||
#endif
|
||||
|
||||
; [Browser Chrome Files]
|
||||
@BINPATH@/chrome/browser.jar
|
||||
@BINPATH@/chrome/browser@JAREXT@
|
||||
@BINPATH@/chrome/browser.manifest
|
||||
@BINPATH@/extensions/{972ce4c6-7e08-4474-a285-3208198ce6fd}/install.rdf
|
||||
@BINPATH@/extensions/{972ce4c6-7e08-4474-a285-3208198ce6fd}/icon.png
|
||||
@ -409,7 +411,7 @@
|
||||
#if MOZ_UPDATE_CHANNEL == beta
|
||||
@BINPATH@/extensions/testpilot@labs.mozilla.com/*
|
||||
#endif
|
||||
@BINPATH@/chrome/toolkit.jar
|
||||
@BINPATH@/chrome/toolkit@JAREXT@
|
||||
@BINPATH@/chrome/toolkit.manifest
|
||||
@BINPATH@/@PREF_DIR@/reporter.js
|
||||
#ifdef XP_UNIX
|
||||
@ -508,7 +510,7 @@
|
||||
@BINPATH@/@DLL_PREFIX@nssdbm3.chk
|
||||
#endif
|
||||
#endif
|
||||
@BINPATH@/chrome/pippki.jar
|
||||
@BINPATH@/chrome/pippki@JAREXT@
|
||||
@BINPATH@/chrome/pippki.manifest
|
||||
|
||||
; for Solaris SPARC
|
||||
|
@ -9,6 +9,9 @@
|
||||
@DLL_PREFIX@xpcom_compat@DLL_SUFFIX@
|
||||
@DLL_PREFIX@xpistub@DLL_SUFFIX@
|
||||
@DLL_PREFIX@zlib@DLL_SUFFIX@
|
||||
#ifdef MOZ_STATIC_JS
|
||||
@DLL_PREFIX@mozjs@DLL_SUFFIX@
|
||||
#endif
|
||||
LICENSE
|
||||
browserconfig.properties
|
||||
chrome/US.jar
|
||||
@ -21,7 +24,7 @@ chrome/classic.manifest
|
||||
chrome/comm.jar
|
||||
chrome/comm.manifest
|
||||
chrome/en-win.jar
|
||||
chrome/en-US.manifest
|
||||
chrome/@AB_CD@.manifest
|
||||
chrome/help.jar
|
||||
chrome/installed-chrome.txt
|
||||
chrome/m3ffxtbr.jar
|
||||
@ -545,6 +548,219 @@ uninstall/UninstallFirefox.exe
|
||||
uninstall/uninst.exe
|
||||
uninstall/uninstall.exe
|
||||
xpicleanup@BIN_SUFFIX@
|
||||
#ifdef MOZ_OMNIJAR
|
||||
chrome/@AB_CD@.jar
|
||||
chrome/browser.jar
|
||||
chrome/localized.manifest
|
||||
chrome/nonlocalized.manifest
|
||||
chrome/pippki.jar
|
||||
chrome/toolkit.jar
|
||||
components/addonManager.js
|
||||
components/amContentHandler.js
|
||||
components/amWebInstallListener.js
|
||||
components/browser.xpt
|
||||
components/components.manifest
|
||||
components/contentAreaDropListener.js
|
||||
components/contentSecurityPolicy.js
|
||||
components/crypto-SDR.js
|
||||
components/FeedConverter.js
|
||||
components/FeedProcessor.js
|
||||
components/FeedWriter.js
|
||||
components/fuelApplication.js
|
||||
components/GPSDGeolocationProvider.js
|
||||
components/interfaces.manifest
|
||||
components/jsconsole-clhandler.js
|
||||
components/NetworkGeolocationProvider.js
|
||||
components/nsBadCertHandler.js
|
||||
components/nsBlocklistService.js
|
||||
components/nsBrowserContentHandler.js
|
||||
components/nsBrowserGlue.js
|
||||
components/nsContentDispatchChooser.js
|
||||
components/nsContentPrefService.js
|
||||
components/nsDefaultCLH.js
|
||||
components/nsDownloadManagerUI.js
|
||||
#ifdef XP_UNIX
|
||||
#ifndef XP_MACOSX
|
||||
components/nsFilePicker.js
|
||||
#endif
|
||||
#endif
|
||||
components/nsFormAutoComplete.js
|
||||
components/nsFormHistory.js
|
||||
components/nsHandlerService.js
|
||||
components/nsHelperAppDlg.js
|
||||
components/nsINIProcessor.js
|
||||
components/nsLivemarkService.js
|
||||
components/nsLoginInfo.js
|
||||
components/nsLoginManager.js
|
||||
components/nsLoginManagerPrompter.js
|
||||
components/nsMicrosummaryService.js
|
||||
components/nsPlacesAutoComplete.js
|
||||
components/nsPlacesDBFlush.js
|
||||
components/nsPlacesExpiration.js
|
||||
components/nsPrivateBrowsingService.js
|
||||
components/nsPrompter.js
|
||||
components/nsProxyAutoConfig.js
|
||||
components/nsSafebrowsingApplication.js
|
||||
components/nsSearchService.js
|
||||
components/nsSearchSuggestions.js
|
||||
components/nsSessionStartup.js
|
||||
components/nsSessionStore.js
|
||||
components/nsSetDefaultBrowser.js
|
||||
components/nsSidebar.js
|
||||
components/nsTaggingService.js
|
||||
components/nsTryToClose.js
|
||||
components/nsUpdateService.js
|
||||
components/nsUpdateServiceStub.js
|
||||
components/nsUpdateTimerManager.js
|
||||
components/nsUrlClassifierLib.js
|
||||
components/nsUrlClassifierListManager.js
|
||||
components/nsURLFormatter.js
|
||||
components/nsWebHandlerApp.js
|
||||
components/PlacesProtocolHandler.js
|
||||
components/storage-Legacy.js
|
||||
components/storage-mozStorage.js
|
||||
components/txEXSLTRegExFunctions.js
|
||||
components/WeaveCrypto.js
|
||||
components/Weave.js
|
||||
components/WebContentConverter.js
|
||||
defaults/autoconfig/platform.js
|
||||
defaults/autoconfig/prefcalls.js
|
||||
defaults/pref/channel-prefs.js
|
||||
defaults/pref/firefox-branding.js
|
||||
defaults/pref/firefox.js
|
||||
defaults/pref/firefox-l10n.js
|
||||
defaults/pref/reporter.js
|
||||
defaults/pref/services-sync.js
|
||||
defaults/profile/bookmarks.html
|
||||
defaults/profile/chrome/userChrome-example.css
|
||||
defaults/profile/chrome/userContent-example.css
|
||||
defaults/profile/localstore.rdf
|
||||
defaults/profile/mimeTypes.rdf
|
||||
defaults/profile/prefs.js
|
||||
greprefs.js
|
||||
modules/AddonLogging.jsm
|
||||
modules/AddonManager.jsm
|
||||
modules/AddonRepository.jsm
|
||||
modules/AddonUpdateChecker.jsm
|
||||
modules/CertUtils.jsm
|
||||
modules/CrashSubmit.jsm
|
||||
modules/CSPUtils.jsm
|
||||
modules/ctypes.jsm
|
||||
modules/debug.js
|
||||
modules/distribution.js
|
||||
modules/DownloadLastDir.jsm
|
||||
modules/DownloadPaths.jsm
|
||||
modules/DownloadUtils.jsm
|
||||
modules/FileUtils.jsm
|
||||
modules/Geometry.jsm
|
||||
modules/HUDService.jsm
|
||||
modules/InlineSpellChecker.jsm
|
||||
modules/ISO8601DateUtils.jsm
|
||||
modules/LightweightThemeConsumer.jsm
|
||||
modules/LightweightThemeManager.jsm
|
||||
modules/Microformats.js
|
||||
modules/NetUtil.jsm
|
||||
modules/NetworkPrioritizer.jsm
|
||||
modules/openLocationLastURL.jsm
|
||||
modules/PerfMeasurement.jsm
|
||||
modules/PlacesDBUtils.jsm
|
||||
modules/PlacesUIUtils.jsm
|
||||
modules/PlacesUtils.jsm
|
||||
modules/PluginProvider.jsm
|
||||
modules/PluralForm.jsm
|
||||
modules/PopupNotifications.jsm
|
||||
modules/Services.jsm
|
||||
modules/services-sync/auth.js
|
||||
modules/services-sync/base_records/collection.js
|
||||
modules/services-sync/base_records/crypto.js
|
||||
modules/services-sync/base_records/keys.js
|
||||
modules/services-sync/base_records/wbo.js
|
||||
modules/services-sync/constants.js
|
||||
modules/services-sync/engines/bookmarks.js
|
||||
modules/services-sync/engines/clients.js
|
||||
modules/services-sync/engines/forms.js
|
||||
modules/services-sync/engines/history.js
|
||||
modules/services-sync/engines.js
|
||||
modules/services-sync/engines/passwords.js
|
||||
modules/services-sync/engines/prefs.js
|
||||
modules/services-sync/engines/tabs.js
|
||||
modules/services-sync/ext/Observers.js
|
||||
modules/services-sync/ext/Preferences.js
|
||||
modules/services-sync/ext/StringBundle.js
|
||||
modules/services-sync/ext/Sync.js
|
||||
modules/services-sync/identity.js
|
||||
modules/services-sync/log4moz.js
|
||||
modules/services-sync/notifications.js
|
||||
modules/services-sync/resource.js
|
||||
modules/services-sync/service.js
|
||||
modules/services-sync/status.js
|
||||
modules/services-sync/stores.js
|
||||
modules/services-sync/trackers.js
|
||||
modules/services-sync/type_records/bookmark.js
|
||||
modules/services-sync/type_records/clients.js
|
||||
modules/services-sync/type_records/forms.js
|
||||
modules/services-sync/type_records/history.js
|
||||
modules/services-sync/type_records/passwords.js
|
||||
modules/services-sync/type_records/prefs.js
|
||||
modules/services-sync/type_records/tabs.js
|
||||
modules/services-sync/util.js
|
||||
modules/SpatialNavigation.js
|
||||
modules/stylePanel.jsm
|
||||
modules/tabview/AllTabs.jsm
|
||||
modules/tabview/groups.jsm
|
||||
modules/tabview/utils.jsm
|
||||
modules/utils.js
|
||||
modules/WindowDraggingUtils.jsm
|
||||
#ifdef XP_WIN
|
||||
modules/WindowsJumpLists.jsm
|
||||
modules/WindowsPreviewPerTab.jsm
|
||||
#endif
|
||||
modules/XPCOMUtils.jsm
|
||||
modules/XPIProvider.jsm
|
||||
res/contenteditable.css
|
||||
res/designmode.css
|
||||
res/dtd/mathml.dtd
|
||||
res/dtd/xhtml11.dtd
|
||||
res/EditorOverride.css
|
||||
res/entityTables/html40Latin1.properties
|
||||
res/entityTables/html40Special.properties
|
||||
res/entityTables/html40Symbols.properties
|
||||
res/entityTables/htmlEntityVersions.properties
|
||||
res/entityTables/mathml20.properties
|
||||
res/entityTables/transliterate.properties
|
||||
res/fonts/mathfont.properties
|
||||
res/fonts/mathfontStandardSymbolsL.properties
|
||||
res/fonts/mathfontSTIXNonUnicode.properties
|
||||
res/fonts/mathfontSTIXSize1.properties
|
||||
res/fonts/mathfontSTIXSizeOneSym.properties
|
||||
res/fonts/mathfontUnicode.properties
|
||||
res/grabber.gif
|
||||
res/html/folder.png
|
||||
res/langGroups.properties
|
||||
res/language.properties
|
||||
res/svg.css
|
||||
res/table-add-column-after-active.gif
|
||||
res/table-add-column-after.gif
|
||||
res/table-add-column-after-hover.gif
|
||||
res/table-add-column-before-active.gif
|
||||
res/table-add-column-before.gif
|
||||
res/table-add-column-before-hover.gif
|
||||
res/table-add-row-after-active.gif
|
||||
res/table-add-row-after.gif
|
||||
res/table-add-row-after-hover.gif
|
||||
res/table-add-row-before-active.gif
|
||||
res/table-add-row-before.gif
|
||||
res/table-add-row-before-hover.gif
|
||||
res/table-remove-column-active.gif
|
||||
res/table-remove-column.gif
|
||||
res/table-remove-column-hover.gif
|
||||
res/table-remove-row-active.gif
|
||||
res/table-remove-row.gif
|
||||
res/table-remove-row-hover.gif
|
||||
#else
|
||||
components/binary.manifest
|
||||
omni.jar
|
||||
#endif
|
||||
#ifdef XP_MACOSX
|
||||
../Plug-Ins/PrintPDE.plugin/Contents/Info.plist
|
||||
../Plug-Ins/PrintPDE.plugin/Contents/MacOS/PrintPDE
|
||||
@ -568,7 +784,6 @@ xpicleanup@BIN_SUFFIX@
|
||||
components/commandlines.xpt
|
||||
components/composer.xpt
|
||||
components/content.xpt
|
||||
components/content.xpt
|
||||
components/content_base.xpt
|
||||
components/content_html.xpt
|
||||
components/content_htmldoc.xpt
|
||||
|
@ -22,6 +22,14 @@
|
||||
!define PreReleaseSuffix "@PRE_RELEASE_SUFFIX@"
|
||||
!define BrandFullName "${BrandFullNameInternal}${PreReleaseSuffix}"
|
||||
|
||||
# LSP_CATEGORIES is the permitted LSP categories for the application. Each LSP
|
||||
# category value is ANDed together to set multiple permitted categories.
|
||||
# See http://msdn.microsoft.com/en-us/library/ms742253%28VS.85%29.aspx
|
||||
# The value below permits the LSP_INSPECTOR, LSP_REDIRECTOR, LSP_PROXY,
|
||||
# LSP_FIREWALL, LSP_INBOUND_MODIFY, LSP_OUTBOUND_MODIFY, LSP_CRYPTO_COMPRESS,
|
||||
# and LSP_LOCAL_CACHE LSP categories.
|
||||
!define LSP_CATEGORIES "0x000000ff"
|
||||
|
||||
# NO_INSTDIR_FROM_REG is defined for pre-releases which have a PreReleaseSuffix
|
||||
# (e.g. Alpha X, Beta X, etc.) to prevent finding a non-default installation
|
||||
# directory in the registry and using that as the default. This prevents
|
||||
|
@ -113,6 +113,7 @@ VIAddVersionKey "OriginalFilename" "setup.exe"
|
||||
!insertmacro RegCleanAppHandler
|
||||
!insertmacro RegCleanMain
|
||||
!insertmacro RegCleanUninstall
|
||||
!insertmacro SetAppLSPCategories
|
||||
!insertmacro SetBrandNameVars
|
||||
!insertmacro UpdateShortcutAppModelIDs
|
||||
!insertmacro UnloadUAC
|
||||
@ -236,7 +237,7 @@ Section "-Application" APP_IDX
|
||||
SetDetailsPrint none
|
||||
|
||||
${LogHeader} "Installing Main Files"
|
||||
${CopyFilesFromDir} "$EXEDIR\nonlocalized" "$INSTDIR" \
|
||||
${CopyFilesFromDir} "$EXEDIR\core" "$INSTDIR" \
|
||||
"$(ERROR_CREATE_DIRECTORY_PREFIX)" \
|
||||
"$(ERROR_CREATE_DIRECTORY_SUFFIX)"
|
||||
|
||||
@ -267,15 +268,6 @@ Section "-Application" APP_IDX
|
||||
${LogUninstall} "File: \install_wizard.log"
|
||||
${LogUninstall} "File: \updates.xml"
|
||||
|
||||
SetDetailsPrint both
|
||||
DetailPrint $(STATUS_INSTALL_LANG)
|
||||
SetDetailsPrint none
|
||||
|
||||
${LogHeader} "Installing Localized Files"
|
||||
${CopyFilesFromDir} "$EXEDIR\localized" "$INSTDIR" \
|
||||
"$(ERROR_CREATE_DIRECTORY_PREFIX)" \
|
||||
"$(ERROR_CREATE_DIRECTORY_SUFFIX)"
|
||||
|
||||
; Check if QuickTime is installed and copy the nsIQTScriptablePlugin.xpt from
|
||||
; its plugins directory into the app's components directory.
|
||||
ClearErrors
|
||||
@ -374,7 +366,6 @@ Section "-Application" APP_IDX
|
||||
${If} $TmpVal == "HKLM"
|
||||
; Set the Start Menu Internet and Vista Registered App HKLM registry keys.
|
||||
${SetStartMenuInternet}
|
||||
|
||||
${FixShellIconHandler}
|
||||
|
||||
; If we are writing to HKLM and create the quick launch and the desktop
|
||||
@ -398,6 +389,11 @@ Section "-Application" APP_IDX
|
||||
StrCpy $0 "Software\Microsoft\MediaPlayer\ShimInclusionList\$R9"
|
||||
${CreateRegKey} "$TmpVal" "$0" 0
|
||||
|
||||
${If} $TmpVal == "HKLM"
|
||||
; Set the permitted LSP Categories for WinVista and above
|
||||
${SetAppLSPCategories} ${LSP_CATEGORIES}
|
||||
${EndIf}
|
||||
|
||||
; Create shortcuts
|
||||
${LogHeader} "Adding Shortcuts"
|
||||
|
||||
@ -524,8 +520,8 @@ SectionEnd
|
||||
Function CustomAbort
|
||||
${If} "${AB_CD}" == "en-US"
|
||||
${AndIf} "$PageName" != ""
|
||||
${AndIf} ${FileExists} "$EXEDIR\nonlocalized\distribution\distribution.ini"
|
||||
ReadINIStr $0 "$EXEDIR\nonlocalized\distribution\distribution.ini" "Global" "about"
|
||||
${AndIf} ${FileExists} "$EXEDIR\core\distribution\distribution.ini"
|
||||
ReadINIStr $0 "$EXEDIR\core\distribution\distribution.ini" "Global" "about"
|
||||
ClearErrors
|
||||
${WordFind} "$0" "Funnelcake" "E#" $1
|
||||
${Unless} ${Errors}
|
||||
@ -684,18 +680,18 @@ BrandingText " "
|
||||
|
||||
Function preWelcome
|
||||
StrCpy $PageName "Welcome"
|
||||
${If} ${FileExists} "$EXEDIR\localized\distribution\modern-wizard.bmp"
|
||||
${If} ${FileExists} "$EXEDIR\core\distribution\modern-wizard.bmp"
|
||||
Delete "$PLUGINSDIR\modern-wizard.bmp"
|
||||
CopyFiles /SILENT "$EXEDIR\localized\distribution\modern-wizard.bmp" "$PLUGINSDIR\modern-wizard.bmp"
|
||||
CopyFiles /SILENT "$EXEDIR\core\distribution\modern-wizard.bmp" "$PLUGINSDIR\modern-wizard.bmp"
|
||||
${EndIf}
|
||||
FunctionEnd
|
||||
|
||||
Function preOptions
|
||||
StrCpy $PageName "Options"
|
||||
${If} ${FileExists} "$EXEDIR\localized\distribution\modern-header.bmp"
|
||||
${If} ${FileExists} "$EXEDIR\core\distribution\modern-header.bmp"
|
||||
${AndIf} $hHeaderBitmap == ""
|
||||
Delete "$PLUGINSDIR\modern-header.bmp"
|
||||
CopyFiles /SILENT "$EXEDIR\localized\distribution\modern-header.bmp" "$PLUGINSDIR\modern-header.bmp"
|
||||
CopyFiles /SILENT "$EXEDIR\core\distribution\modern-header.bmp" "$PLUGINSDIR\modern-header.bmp"
|
||||
${ChangeMUIHeaderImage} "$PLUGINSDIR\modern-header.bmp"
|
||||
${EndIf}
|
||||
!insertmacro MUI_HEADER_TEXT "$(OPTIONS_PAGE_TITLE)" "$(OPTIONS_PAGE_SUBTITLE)"
|
||||
@ -921,7 +917,7 @@ FunctionEnd
|
||||
Function .onInit
|
||||
StrCpy $PageName ""
|
||||
StrCpy $LANGUAGE 0
|
||||
${SetBrandNameVars} "$EXEDIR\localized\distribution\setup.ini"
|
||||
${SetBrandNameVars} "$EXEDIR\core\distribution\setup.ini"
|
||||
|
||||
${InstallOnInitCommon} "$(WARN_MIN_SUPPORTED_OS_MSG)"
|
||||
|
||||
@ -1004,9 +1000,8 @@ Function .onInit
|
||||
WriteINIStr "$PLUGINSDIR\shortcuts.ini" "Field 4" Bottom "70"
|
||||
WriteINIStr "$PLUGINSDIR\shortcuts.ini" "Field 4" State "1"
|
||||
|
||||
; There must always be nonlocalized and localized directories.
|
||||
${GetSize} "$EXEDIR\nonlocalized\" "/S=0K" $R5 $R7 $R8
|
||||
${GetSize} "$EXEDIR\localized\" "/S=0K" $R6 $R7 $R8
|
||||
; There must always be a core directory.
|
||||
${GetSize} "$EXEDIR\core\" "/S=0K" $R5 $R7 $R8
|
||||
IntOp $R8 $R5 + $R6
|
||||
SectionSetSize ${APP_IDX} $R8
|
||||
|
||||
|
@ -57,6 +57,7 @@
|
||||
${RegCleanUninstall}
|
||||
${UpdateProtocolHandlers}
|
||||
${FixShellIconHandler}
|
||||
${SetAppLSPCategories} ${LSP_CATEGORIES}
|
||||
|
||||
; Only update the Clients\StartMenuInternet registry key values if they
|
||||
; don't exist or this installation is the same as the one set in those keys.
|
||||
|
@ -100,6 +100,7 @@ VIAddVersionKey "OriginalFilename" "helper.exe"
|
||||
!insertmacro RegCleanAppHandler
|
||||
!insertmacro RegCleanMain
|
||||
!insertmacro RegCleanUninstall
|
||||
!insertmacro SetAppLSPCategories
|
||||
!insertmacro SetBrandNameVars
|
||||
!insertmacro UpdateShortcutAppModelIDs
|
||||
!insertmacro UnloadUAC
|
||||
@ -122,6 +123,7 @@ VIAddVersionKey "OriginalFilename" "helper.exe"
|
||||
!insertmacro un.RegCleanUninstall
|
||||
!insertmacro un.RegCleanProtocolHandler
|
||||
!insertmacro un.RemoveQuotesFromPath
|
||||
!insertmacro un.SetAppLSPCategories
|
||||
!insertmacro un.SetBrandNameVars
|
||||
|
||||
!include shared.nsh
|
||||
@ -240,6 +242,7 @@ Section "Uninstall"
|
||||
${un.RegCleanMain} "Software\Mozilla"
|
||||
${un.RegCleanUninstall}
|
||||
${un.DeleteShortcuts}
|
||||
${un.SetAppLSPCategories}
|
||||
${EndIf}
|
||||
|
||||
${un.RegCleanAppHandler} "FirefoxURL"
|
||||
|
@ -100,6 +100,8 @@ ifeq (WINNT,$(OS_ARCH))
|
||||
UNINSTALLER_PACKAGE_HOOK = $(RM) -r $(STAGEDIST)/uninstall; \
|
||||
$(NSINSTALL) -D $(STAGEDIST)/uninstall; \
|
||||
cp ../installer/windows/l10ngen/helper.exe $(STAGEDIST)/uninstall; \
|
||||
$(RM) $(_ABS_DIST)/l10n-stage/setup.exe; \
|
||||
cp ../installer/windows/l10ngen/setup.exe $(_ABS_DIST)/l10n-stage; \
|
||||
$(NULL)
|
||||
endif
|
||||
|
||||
@ -195,30 +197,14 @@ repackage-win32-installer: WIN32_INSTALLER_OUT="$(_ABS_DIST)/$(PKG_INST_PATH)$(P
|
||||
repackage-win32-installer: $(WIN32_INSTALLER_IN) $(SUBMAKEFILES)
|
||||
@echo "Repackaging $(WIN32_INSTALLER_IN) into $(WIN32_INSTALLER_OUT)."
|
||||
$(MAKE) -C $(DEPTH)/$(MOZ_BRANDING_DIRECTORY) export
|
||||
if test ! -d $(_ABS_DIST)/$(PKG_INST_PATH); then \
|
||||
$(NSINSTALL) -D $(_ABS_DIST)/$(PKG_INST_PATH); \
|
||||
fi
|
||||
$(RM) -rf l10n-stage
|
||||
$(NSINSTALL) -D l10n-stage
|
||||
$(CYGWIN_WRAPPER) 7z x -ol10n-stage $(WIN32_INSTALLER_IN)
|
||||
$(RM) -r l10n-stage/localized
|
||||
$(RM) l10n-stage/setup.exe
|
||||
# copy xpi-stage over, but not install.rdf and chrome.manifest,
|
||||
# those are just for language packs
|
||||
cp -r $(DIST)/xpi-stage/locale-$(AB_CD) l10n-stage/localized
|
||||
$(RM) l10n-stage/localized/install.rdf l10n-stage/localized/chrome.manifest
|
||||
mv l10n-stage/localized/chrome/$(AB_CD).manifest l10n-stage/localized/chrome/localized.manifest
|
||||
$(MAKE) -C ../installer/windows CONFIG_DIR=l10ngen l10ngen/setup.exe l10ngen/7zSD.sfx
|
||||
cp ../installer/windows/l10ngen/setup.exe l10n-stage
|
||||
$(NSINSTALL) -D l10n-stage/localized/uninstall
|
||||
cp ../installer/windows/l10ngen/helper.exe l10n-stage/localized/uninstall
|
||||
rm -f app.7z
|
||||
cd l10n-stage && \
|
||||
$(CYGWIN_WRAPPER) 7z a -r -t7z ../app.7z -mx -m0=BCJ2 -m1=LZMA:d24 -m2=LZMA:d19 -m3=LZMA:d19 -mb0:1 -mb0s1:2 -mb0s2:3
|
||||
cat ../installer/windows/l10ngen/7zSD.sfx \
|
||||
$(topsrcdir)/browser/installer/windows/app.tag \
|
||||
app.7z > $(WIN32_INSTALLER_OUT)
|
||||
chmod 0755 $(WIN32_INSTALLER_OUT)
|
||||
$(MAKE) repackage-zip \
|
||||
AB_CD=$(AB_CD) \
|
||||
MOZ_PKG_FORMAT=SFX7Z \
|
||||
ZIP_IN=$(WIN32_INSTALLER_IN) \
|
||||
ZIP_OUT=$(WIN32_INSTALLER_OUT) \
|
||||
SFX_HEADER="$(PWD)/../installer/windows/l10ngen/7zSD.sfx \
|
||||
$(topsrcdir)/browser/installer/windows/app.tag"
|
||||
|
||||
ifeq (WINNT,$(OS_ARCH))
|
||||
repackage-win32-installer-%: $(WIN32_INSTALLER_IN) libs-%
|
||||
|
@ -14,9 +14,6 @@ browser.contentHandlers.types.1.uri=http://add.my.yahoo.com/rss?url=%s
|
||||
browser.contentHandlers.types.2.title=Google
|
||||
browser.contentHandlers.types.2.uri=http://fusion.google.com/add?feedurl=%s
|
||||
|
||||
# Keyword URL (for location bar searches)
|
||||
keyword.URL=http://www.google.com/search?ie=UTF-8&oe=UTF-8&sourceid=navclient&gfns=1&q=
|
||||
|
||||
# URL for site-specific search engines
|
||||
# TRANSLATION NOTE: {moz:domain} and {searchTerms} are placeholders for the site
|
||||
# to be searched and the user's search query. Place them in the appropriate location
|
||||
|
@ -10,8 +10,6 @@
|
||||
|
||||
<!ENTITY restorepage.tryagainButton "Restore">
|
||||
<!ENTITY restorepage.restore.access "R">
|
||||
<!ENTITY restorepage.cancelButton "Start New Session">
|
||||
<!ENTITY restorepage.cancel.access "S">
|
||||
|
||||
<!ENTITY restorepage.restoreHeader "Restore">
|
||||
<!ENTITY restorepage.listHeader "Windows and Tabs">
|
||||
|
@ -24,6 +24,11 @@
|
||||
<!ENTITY pinTab.accesskey "p">
|
||||
<!ENTITY unpinTab.label "Make into Normal Tab">
|
||||
<!ENTITY unpinTab.accesskey "k">
|
||||
<!ENTITY moveToGroup.label "Move to Group">
|
||||
<!ENTITY moveToGroup.accesskey "M">
|
||||
<!ENTITY moveToNewGroup.label "New Group">
|
||||
<!ENTITY moveToNewGroup.accesskey "N">
|
||||
<!ENTITY namedGroups.label "Named Groups">
|
||||
<!ENTITY bookmarkThisTab.label "Bookmark This Tab">
|
||||
<!ENTITY bookmarkThisTab.accesskey "B">
|
||||
<!ENTITY bookmarkAllTabs.label "Bookmark All Tabs…">
|
||||
@ -127,6 +132,8 @@
|
||||
|
||||
<!-- Toolbar items -->
|
||||
<!ENTITY homeButton.label "Home">
|
||||
<!ENTITY tabViewButton2.label "Tab Groups">
|
||||
<!ENTITY tabViewButton2.tooltip "Group Your Tabs">
|
||||
|
||||
<!ENTITY bookmarksButton.label "Bookmarks">
|
||||
<!ENTITY bookmarksButton.tooltip "Display your bookmarks">
|
||||
@ -186,6 +193,12 @@
|
||||
<!ENTITY inspectStyleButton.label "Style">
|
||||
<!ENTITY inspectStyleButton.accesskey "S">
|
||||
<!ENTITY inspectStylePanelTitle.label "Style">
|
||||
<!-- LOCALIZATION NOTE (inspectDOMButton.label): This button label
|
||||
- stands for Document Object Model and appears on the inspector's toolbar.
|
||||
- It is used to open and closed the DOM panel. There is also a DOM label in
|
||||
- inspector.properties for the panel titlebar. -->
|
||||
<!ENTITY inspectDOMButton.label "DOM">
|
||||
<!ENTITY inspectDOMButton.accesskey "D">
|
||||
|
||||
<!ENTITY fileMenu.label "File">
|
||||
<!ENTITY fileMenu.accesskey "F">
|
||||
@ -233,6 +246,8 @@
|
||||
|
||||
<!ENTITY viewMenu.label "View">
|
||||
<!ENTITY viewMenu.accesskey "V">
|
||||
<!ENTITY showTabView2.label "Group Your Tabs…">
|
||||
<!ENTITY showTabView2.accesskey "G">
|
||||
<!ENTITY viewToolbarsMenu.label "Toolbars">
|
||||
<!ENTITY viewToolbarsMenu.accesskey "T">
|
||||
<!ENTITY viewSidebarMenu.label "Sidebar">
|
||||
|
@ -275,5 +275,8 @@ ctrlTab.showAll.label=;Show all #1 tabs
|
||||
# Used as the bookmark name when saving a keyword for a search field.
|
||||
addKeywordTitleAutoFill=Search %S
|
||||
|
||||
# TabView
|
||||
tabView2.title=%S - Group Your Tabs
|
||||
|
||||
extensions.{972ce4c6-7e08-4474-a285-3208198ce6fd}.name=Default
|
||||
extensions.{972ce4c6-7e08-4474-a285-3208198ce6fd}.description=The default theme.
|
||||
|
@ -6,6 +6,12 @@ style.selectorLabel=Selector
|
||||
# inspector. Describes which tagname[#id] the properties are inherited from.
|
||||
style.inheritedFrom=Inherited from: #1
|
||||
|
||||
# LOCALIZATION NOTE (style.styleItemLabel: used in Style panel in inspector.
|
||||
# LOCALIZATION NOTE (style.styleItemLabel): used in Style panel in inspector.
|
||||
# Used for construction of list items, #1 = label, #2 = content.
|
||||
style.styleItemLabel=#1: #2
|
||||
|
||||
# LOCALIZATION NOTE (dom.domPanelTitle): used in DOM Panel in inspector.
|
||||
# Stands for "Document Object Model". Also referenced in in browser.dtd
|
||||
# and used as a button title.
|
||||
# Unsure if this localizes well, but including just in case
|
||||
dom.domPanelTitle=DOM
|
||||
|
@ -1,12 +1,14 @@
|
||||
<!ENTITY testpilot.brand.label "Test Pilot">
|
||||
<!-- browser window: menu and status bar -->
|
||||
<!ENTITY testpilot.settings.label "Settings">
|
||||
<!ENTITY testpilot.settings.notifyMeWhen.label "Notify me when">
|
||||
<!ENTITY testpilot.settings.dataSubmission.label "Data Submission">
|
||||
<!ENTITY testpilot.settings.notifications.label "Notifications">
|
||||
<!ENTITY testpilot.settings.notifyWhen.label "Notify me when…">
|
||||
<!ENTITY testpilot.settings.readyToSubmit.label "A study is ready to submit">
|
||||
<!ENTITY testpilot.settings.newStudy.label "There's a new study">
|
||||
<!ENTITY testpilot.settings.hasNewResults.label "A study has new results">
|
||||
<!ENTITY testpilot.settings.alwaysSubmitData.label "Automatically submit my data (don't ask me)">
|
||||
<!ENTITY testpilot.allStudies.label "All Your User Studies">
|
||||
<!ENTITY testpilot.allYourStudies.label "All Your User Studies…">
|
||||
<!ENTITY testpilot.about.label "About Test Pilot">
|
||||
|
||||
<!-- all studies window -->
|
||||
|
@ -1,3 +1,6 @@
|
||||
# description for add-on manager
|
||||
extensions.testpilot@labs.mozilla.com.description = Help make Firefox better by running user studies.
|
||||
|
||||
# common
|
||||
testpilot.fullBrandName = Mozilla Labs Test Pilot
|
||||
testpilot.moreInfo = More Info
|
||||
|
@ -5,18 +5,24 @@ da
|
||||
de
|
||||
el
|
||||
en-US
|
||||
eo
|
||||
es-AR
|
||||
es-ES
|
||||
et
|
||||
fi
|
||||
fr
|
||||
ga-IE
|
||||
he
|
||||
hu
|
||||
id
|
||||
is
|
||||
it
|
||||
ja linux win32
|
||||
ja-JP-mac osx
|
||||
ko
|
||||
ku
|
||||
lt
|
||||
lv
|
||||
nb-NO
|
||||
nl
|
||||
nn-NO
|
||||
|
@ -563,6 +563,10 @@ toolbar[mode="full"] .toolbarbutton-menubutton-button {
|
||||
list-style-image: url("moz-icon://stock/gtk-home?size=toolbar&state=disabled");
|
||||
}
|
||||
|
||||
#tabview-button {
|
||||
list-style-image: url(chrome://browser/skin/tabview/tabview.png);
|
||||
}
|
||||
|
||||
#downloads-button {
|
||||
-moz-image-region: rect(0px 24px 24px 0px);
|
||||
}
|
||||
@ -1506,6 +1510,9 @@ toolbar[mode="text"] toolbarbutton.chevron > .toolbarbutton-icon {
|
||||
#highlighter-panel {
|
||||
-moz-appearance: none;
|
||||
-moz-window-shadow: none;
|
||||
background: -moz-linear-gradient(top -1deg, #ffdd88, #ffeeaa);
|
||||
border: none;
|
||||
opacity: 0.35;
|
||||
}
|
||||
|
||||
listitem.style-selector {
|
||||
@ -1523,3 +1530,8 @@ panel[dimmed="true"] {
|
||||
opacity: 0.5;
|
||||
}
|
||||
|
||||
/* Tab view context menu */
|
||||
|
||||
#context_tabViewMenuPopup > menuitem.group {
|
||||
-moz-padding-start: 40px;
|
||||
}
|
||||
|
@ -71,6 +71,12 @@ browser.jar:
|
||||
skin/classic/browser/tabbrowser/progress.png (tabbrowser/progress.png)
|
||||
skin/classic/browser/tabbrowser/progress-pulsing.png (tabbrowser/progress-pulsing.png)
|
||||
skin/classic/browser/tabbrowser/tabDragIndicator.png (tabbrowser/tabDragIndicator.png)
|
||||
skin/classic/browser/tabview/edit-light.png (tabview/edit-light.png)
|
||||
skin/classic/browser/tabview/edit.png (tabview/edit.png)
|
||||
skin/classic/browser/tabview/new-tab.png (tabview/new-tab.png)
|
||||
skin/classic/browser/tabview/tabview.css (tabview/tabview.css)
|
||||
skin/classic/browser/tabview/stack-expander.png (tabview/stack-expander.png)
|
||||
skin/classic/browser/tabview/tabview.png (tabview/tabview.png)
|
||||
#ifdef MOZ_SERVICES_SYNC
|
||||
skin/classic/browser/sync-16-throbber.png
|
||||
skin/classic/browser/sync-16.png
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user