зеркало из https://github.com/mozilla/gecko-dev.git
merge mozilla-inbound to mozilla-central a=merge
This commit is contained in:
Коммит
fd2c2d9b1a
|
@ -52,7 +52,16 @@ NS_IMPL_CYCLE_COLLECTION_UNLINK_END
|
|||
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(NotificationController)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mHangingChildDocuments)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mContentInsertions)
|
||||
for (auto it = tmp->mContentInsertions.ConstIter(); !it.Done(); it.Next()) {
|
||||
NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb, "mContentInsertions key");
|
||||
cb.NoteXPCOMChild(it.Key());
|
||||
nsTArray<nsCOMPtr<nsIContent>>* list = it.UserData();
|
||||
for (uint32_t i = 0; i < list->Length(); i++) {
|
||||
NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb,
|
||||
"mContentInsertions value item");
|
||||
cb.NoteXPCOMChild(list->ElementAt(i));
|
||||
}
|
||||
}
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mEvents)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mRelocations)
|
||||
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
|
||||
|
@ -103,10 +112,23 @@ NotificationController::ScheduleContentInsertion(Accessible* aContainer,
|
|||
nsIContent* aStartChildNode,
|
||||
nsIContent* aEndChildNode)
|
||||
{
|
||||
RefPtr<ContentInsertion> insertion = new ContentInsertion(mDocument,
|
||||
aContainer);
|
||||
if (insertion && insertion->InitChildList(aStartChildNode, aEndChildNode) &&
|
||||
mContentInsertions.AppendElement(insertion)) {
|
||||
nsTArray<nsCOMPtr<nsIContent>>* list =
|
||||
mContentInsertions.LookupOrAdd(aContainer);
|
||||
|
||||
bool needsProcessing = false;
|
||||
nsIContent* node = aStartChildNode;
|
||||
while (node != aEndChildNode) {
|
||||
// Notification triggers for content insertion even if no content was
|
||||
// actually inserted, check if the given content has a frame to discard
|
||||
// this case early.
|
||||
if (node->GetPrimaryFrame()) {
|
||||
if (list->AppendElement(node))
|
||||
needsProcessing = true;
|
||||
}
|
||||
node = node->GetNextSibling();
|
||||
}
|
||||
|
||||
if (needsProcessing) {
|
||||
ScheduleProcessing();
|
||||
}
|
||||
}
|
||||
|
@ -130,7 +152,7 @@ NotificationController::IsUpdatePending()
|
|||
{
|
||||
return mPresShell->IsLayoutFlushObserver() ||
|
||||
mObservingState == eRefreshProcessingForUpdate ||
|
||||
mContentInsertions.Length() != 0 || mNotifications.Length() != 0 ||
|
||||
mContentInsertions.Count() != 0 || mNotifications.Length() != 0 ||
|
||||
mTextHash.Count() != 0 ||
|
||||
!mDocument->HasLoadState(DocAccessible::eTreeConstructed);
|
||||
}
|
||||
|
@ -178,7 +200,7 @@ NotificationController::WillRefresh(mozilla::TimeStamp aTime)
|
|||
|
||||
mDocument->DoInitialUpdate();
|
||||
|
||||
NS_ASSERTION(mContentInsertions.Length() == 0,
|
||||
NS_ASSERTION(mContentInsertions.Count() == 0,
|
||||
"Pending content insertions while initial accessible tree isn't created!");
|
||||
}
|
||||
|
||||
|
@ -196,15 +218,13 @@ NotificationController::WillRefresh(mozilla::TimeStamp aTime)
|
|||
// document accessible.
|
||||
|
||||
// Process only currently queued content inserted notifications.
|
||||
nsTArray<RefPtr<ContentInsertion> > contentInsertions;
|
||||
contentInsertions.SwapElements(mContentInsertions);
|
||||
|
||||
uint32_t insertionCount = contentInsertions.Length();
|
||||
for (uint32_t idx = 0; idx < insertionCount; idx++) {
|
||||
contentInsertions[idx]->Process();
|
||||
if (!mDocument)
|
||||
for (auto iter = mContentInsertions.ConstIter(); !iter.Done(); iter.Next()) {
|
||||
mDocument->ProcessContentInserted(iter.Key(), iter.UserData());
|
||||
if (!mDocument) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
mContentInsertions.Clear();
|
||||
|
||||
// Process rendered text change notifications.
|
||||
for (auto iter = mTextHash.Iter(); !iter.Done(); iter.Next()) {
|
||||
|
@ -403,7 +423,7 @@ NotificationController::WillRefresh(mozilla::TimeStamp aTime)
|
|||
|
||||
// Stop further processing if there are no new notifications of any kind or
|
||||
// events and document load is processed.
|
||||
if (mContentInsertions.IsEmpty() && mNotifications.IsEmpty() &&
|
||||
if (mContentInsertions.Count() == 0 && mNotifications.IsEmpty() &&
|
||||
mEvents.IsEmpty() && mTextHash.Count() == 0 &&
|
||||
mHangingChildDocuments.IsEmpty() &&
|
||||
mDocument->HasLoadState(DocAccessible::eCompletelyLoaded) &&
|
||||
|
@ -411,53 +431,3 @@ NotificationController::WillRefresh(mozilla::TimeStamp aTime)
|
|||
mObservingState = eNotObservingRefresh;
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// NotificationController: content inserted notification
|
||||
|
||||
NotificationController::ContentInsertion::
|
||||
ContentInsertion(DocAccessible* aDocument, Accessible* aContainer) :
|
||||
mDocument(aDocument), mContainer(aContainer)
|
||||
{
|
||||
}
|
||||
|
||||
bool
|
||||
NotificationController::ContentInsertion::
|
||||
InitChildList(nsIContent* aStartChildNode, nsIContent* aEndChildNode)
|
||||
{
|
||||
bool haveToUpdate = false;
|
||||
|
||||
nsIContent* node = aStartChildNode;
|
||||
while (node != aEndChildNode) {
|
||||
// Notification triggers for content insertion even if no content was
|
||||
// actually inserted, check if the given content has a frame to discard
|
||||
// this case early.
|
||||
if (node->GetPrimaryFrame()) {
|
||||
if (mInsertedContent.AppendElement(node))
|
||||
haveToUpdate = true;
|
||||
}
|
||||
|
||||
node = node->GetNextSibling();
|
||||
}
|
||||
|
||||
return haveToUpdate;
|
||||
}
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION(NotificationController::ContentInsertion,
|
||||
mContainer)
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_ROOT_NATIVE(NotificationController::ContentInsertion,
|
||||
AddRef)
|
||||
NS_IMPL_CYCLE_COLLECTION_UNROOT_NATIVE(NotificationController::ContentInsertion,
|
||||
Release)
|
||||
|
||||
void
|
||||
NotificationController::ContentInsertion::Process()
|
||||
{
|
||||
mDocument->ProcessContentInserted(mContainer, &mInsertedContent);
|
||||
|
||||
mDocument = nullptr;
|
||||
mContainer = nullptr;
|
||||
mInsertedContent.Clear();
|
||||
}
|
||||
|
||||
|
|
|
@ -247,44 +247,10 @@ private:
|
|||
nsTArray<RefPtr<DocAccessible> > mHangingChildDocuments;
|
||||
|
||||
/**
|
||||
* Storage for content inserted notification information.
|
||||
* Pending accessible tree update notifications for content insertions.
|
||||
*/
|
||||
class ContentInsertion
|
||||
{
|
||||
public:
|
||||
ContentInsertion(DocAccessible* aDocument, Accessible* aContainer);
|
||||
|
||||
NS_INLINE_DECL_CYCLE_COLLECTING_NATIVE_REFCOUNTING(ContentInsertion)
|
||||
NS_DECL_CYCLE_COLLECTION_NATIVE_CLASS(ContentInsertion)
|
||||
|
||||
bool InitChildList(nsIContent* aStartChildNode, nsIContent* aEndChildNode);
|
||||
void Process();
|
||||
|
||||
protected:
|
||||
virtual ~ContentInsertion() { mDocument = nullptr; }
|
||||
|
||||
private:
|
||||
ContentInsertion();
|
||||
ContentInsertion(const ContentInsertion&);
|
||||
ContentInsertion& operator = (const ContentInsertion&);
|
||||
|
||||
// The document used to process content insertion, matched to document of
|
||||
// the notification controller that this notification belongs to, therefore
|
||||
// it's ok to keep it as weak ref.
|
||||
DocAccessible* mDocument;
|
||||
|
||||
// The container accessible that content insertion occurs within.
|
||||
RefPtr<Accessible> mContainer;
|
||||
|
||||
// Array of inserted contents.
|
||||
nsTArray<nsCOMPtr<nsIContent> > mInsertedContent;
|
||||
};
|
||||
|
||||
/**
|
||||
* A pending accessible tree update notifications for content insertions.
|
||||
* Don't make this an AutoTArray; we use SwapElements() on it.
|
||||
*/
|
||||
nsTArray<RefPtr<ContentInsertion> > mContentInsertions;
|
||||
nsClassHashtable<nsRefPtrHashKey<Accessible>,
|
||||
nsTArray<nsCOMPtr<nsIContent>>> mContentInsertions;
|
||||
|
||||
template<class T>
|
||||
class nsCOMPtrHashKey : public PLDHashEntryHdr
|
||||
|
@ -311,7 +277,7 @@ private:
|
|||
};
|
||||
|
||||
/**
|
||||
* A pending accessible tree update notifications for rendered text changes.
|
||||
* Pending accessible tree update notifications for rendered text changes.
|
||||
*/
|
||||
nsTHashtable<nsCOMPtrHashKey<nsIContent> > mTextHash;
|
||||
|
||||
|
|
|
@ -46,7 +46,7 @@ TreeWalker::~TreeWalker()
|
|||
// TreeWalker: private
|
||||
|
||||
Accessible*
|
||||
TreeWalker::NextChild()
|
||||
TreeWalker::Next()
|
||||
{
|
||||
if (mStateStack.IsEmpty())
|
||||
return nullptr;
|
||||
|
@ -82,7 +82,7 @@ TreeWalker::NextChild()
|
|||
top = PushState(parent);
|
||||
if (top->mDOMIter.Seek(mAnchorNode)) {
|
||||
mAnchorNode = parent;
|
||||
return NextChild();
|
||||
return Next();
|
||||
}
|
||||
|
||||
// XXX We really should never get here, it means we're trying to find an
|
||||
|
|
|
@ -44,13 +44,13 @@ public:
|
|||
~TreeWalker();
|
||||
|
||||
/**
|
||||
* Return the next child accessible.
|
||||
* Return the next accessible.
|
||||
*
|
||||
* @note Returned accessible is bound to the document, if the accessible is
|
||||
* rejected during tree creation then the caller should be unbind it
|
||||
* from the document.
|
||||
*/
|
||||
Accessible* NextChild();
|
||||
Accessible* Next();
|
||||
|
||||
private:
|
||||
TreeWalker();
|
||||
|
|
|
@ -596,7 +596,7 @@ nsAccessibilityService::ContentRemoved(nsIPresShell* aPresShell,
|
|||
Accessible* container = document->GetContainerAccessible(aChildNode);
|
||||
a11y::TreeWalker walker(container ? container : document, aChildNode,
|
||||
a11y::TreeWalker::eWalkCache);
|
||||
child = walker.NextChild();
|
||||
child = walker.Next();
|
||||
}
|
||||
|
||||
if (child) {
|
||||
|
|
|
@ -2508,7 +2508,7 @@ Accessible::CacheChildren()
|
|||
TreeWalker walker(this, mContent);
|
||||
|
||||
Accessible* child = nullptr;
|
||||
while ((child = walker.NextChild()) && AppendChild(child));
|
||||
while ((child = walker.Next()) && AppendChild(child));
|
||||
}
|
||||
|
||||
void
|
||||
|
|
|
@ -1433,7 +1433,7 @@ DocAccessible::CacheChildren()
|
|||
// Ignore last HTML:br, copied from HyperTextAccessible.
|
||||
TreeWalker walker(this, rootElm);
|
||||
Accessible* lastChild = nullptr;
|
||||
while (Accessible* child = walker.NextChild()) {
|
||||
while (Accessible* child = walker.Next()) {
|
||||
if (lastChild)
|
||||
AppendChild(lastChild);
|
||||
|
||||
|
|
|
@ -284,7 +284,7 @@ HyperTextAccessible::DOMPointToOffset(nsINode* aNode, int32_t aNodeOffset,
|
|||
if (container) {
|
||||
TreeWalker walker(container, findNode->AsContent(),
|
||||
TreeWalker::eWalkContextTree);
|
||||
descendant = walker.NextChild();
|
||||
descendant = walker.Next();
|
||||
if (!descendant)
|
||||
descendant = container;
|
||||
}
|
||||
|
@ -1945,7 +1945,7 @@ HyperTextAccessible::CacheChildren()
|
|||
TreeWalker walker(this, mContent);
|
||||
Accessible* child = nullptr;
|
||||
Accessible* lastChild = nullptr;
|
||||
while ((child = walker.NextChild())) {
|
||||
while ((child = walker.Next())) {
|
||||
if (lastChild)
|
||||
AppendChild(lastChild);
|
||||
|
||||
|
|
|
@ -403,10 +403,10 @@ HTMLTableAccessible::CacheChildren()
|
|||
TreeWalker walker(this, mContent);
|
||||
|
||||
Accessible* child = nullptr;
|
||||
while ((child = walker.NextChild())) {
|
||||
while ((child = walker.Next())) {
|
||||
if (child->Role() == roles::CAPTION) {
|
||||
InsertChildAt(0, child);
|
||||
while ((child = walker.NextChild()) && AppendChild(child));
|
||||
while ((child = walker.Next()) && AppendChild(child));
|
||||
break;
|
||||
}
|
||||
AppendChild(child);
|
||||
|
|
|
@ -1878,44 +1878,3 @@ var BookmarkingUI = {
|
|||
Ci.nsINavBookmarkObserver
|
||||
])
|
||||
};
|
||||
|
||||
var AutoShowBookmarksToolbar = {
|
||||
init() {
|
||||
PlacesUtils.addLazyBookmarkObserver(this, false);
|
||||
},
|
||||
|
||||
uninit() {
|
||||
PlacesUtils.removeLazyBookmarkObserver(this);
|
||||
},
|
||||
|
||||
onItemAdded(aItemId, aParentId, aIndex, aItemType, aURI, aTitle, aDateAdded,
|
||||
aGuid, aParentGuid) {
|
||||
this._autoshow(aParentGuid);
|
||||
},
|
||||
onBeginUpdateBatch() {},
|
||||
onEndUpdateBatch() {},
|
||||
onItemRemoved() {},
|
||||
onItemChanged() {},
|
||||
onItemVisited() {},
|
||||
onItemMoved(aItemId, aOldParent, aOldIndex, aNewParent, aNewIndex, aItemType,
|
||||
aGuid, aOldParentGuid, aNewParentGuid) {
|
||||
this._autoshow(aNewParentGuid);
|
||||
},
|
||||
|
||||
_autoshow(aParentGuid) {
|
||||
if (aParentGuid != PlacesUtils.bookmarks.toolbarGuid)
|
||||
return;
|
||||
|
||||
let toolbar = document.getElementById("PersonalToolbar");
|
||||
if (!toolbar.collapsed)
|
||||
return;
|
||||
|
||||
let placement = CustomizableUI.getPlacementOfWidget("personal-bookmarks");
|
||||
let area = placement && placement.area;
|
||||
if (area != CustomizableUI.AREA_BOOKMARKS)
|
||||
return;
|
||||
|
||||
setToolbarVisibility(toolbar, true);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -1200,7 +1200,6 @@ var gBrowserInit = {
|
|||
gBrowser.tabContainer.updateVisibility();
|
||||
|
||||
BookmarkingUI.init();
|
||||
AutoShowBookmarksToolbar.init();
|
||||
|
||||
gPrefService.addObserver(gHomeButton.prefDomain, gHomeButton, false);
|
||||
|
||||
|
@ -1504,7 +1503,6 @@ var gBrowserInit = {
|
|||
IndexedDBPromptHelper.uninit();
|
||||
LightweightThemeListener.uninit();
|
||||
PanelUI.uninit();
|
||||
AutoShowBookmarksToolbar.uninit();
|
||||
}
|
||||
|
||||
// Final window teardown, do this last.
|
||||
|
@ -4715,7 +4713,8 @@ nsBrowserAccess.prototype = {
|
|||
QueryInterface: XPCOMUtils.generateQI([Ci.nsIBrowserDOMWindow, Ci.nsISupports]),
|
||||
|
||||
_openURIInNewTab: function(aURI, aReferrer, aReferrerPolicy, aIsPrivate,
|
||||
aIsExternal, aForceNotRemote=false) {
|
||||
aIsExternal, aForceNotRemote=false,
|
||||
aUserContextId=Ci.nsIScriptSecurityManager.DEFAULT_USER_CONTEXT_ID) {
|
||||
let win, needToFocusWin;
|
||||
|
||||
// try the current window. if we're in a popup, fall back on the most recent browser window
|
||||
|
@ -4742,6 +4741,7 @@ nsBrowserAccess.prototype = {
|
|||
let tab = win.gBrowser.loadOneTab(aURI ? aURI.spec : "about:blank", {
|
||||
referrerURI: aReferrer,
|
||||
referrerPolicy: aReferrerPolicy,
|
||||
userContextId: aUserContextId,
|
||||
fromExternal: aIsExternal,
|
||||
inBackground: loadInBackground,
|
||||
forceNotRemote: aForceNotRemote});
|
||||
|
@ -4814,9 +4814,12 @@ nsBrowserAccess.prototype = {
|
|||
// will do the job of shuttling off the newly opened browser to run in
|
||||
// the right process once it starts loading a URI.
|
||||
let forceNotRemote = !!aOpener;
|
||||
let userContextId = aOpener && aOpener.document
|
||||
? aOpener.document.nodePrincipal.originAttributes.userContextId
|
||||
: Ci.nsIScriptSecurityManager.DEFAULT_USER_CONTEXT_ID;
|
||||
let browser = this._openURIInNewTab(aURI, referrer, referrerPolicy,
|
||||
isPrivate, isExternal,
|
||||
forceNotRemote);
|
||||
forceNotRemote, userContextId);
|
||||
if (browser)
|
||||
newWindow = browser.contentWindow;
|
||||
break;
|
||||
|
@ -4845,9 +4848,17 @@ nsBrowserAccess.prototype = {
|
|||
}
|
||||
|
||||
var isExternal = (aContext == Ci.nsIBrowserDOMWindow.OPEN_EXTERNAL);
|
||||
|
||||
var userContextId = aParams.openerOriginAttributes &&
|
||||
("userContextId" in aParams.openerOriginAttributes)
|
||||
? aParams.openerOriginAttributes.userContextId
|
||||
: Ci.nsIScriptSecurityManager.DEFAULT_USER_CONTEXT_ID
|
||||
|
||||
let browser = this._openURIInNewTab(aURI, aParams.referrer,
|
||||
aParams.referrerPolicy,
|
||||
aParams.isPrivate, isExternal);
|
||||
aParams.isPrivate,
|
||||
isExternal, false,
|
||||
userContextId);
|
||||
if (browser)
|
||||
return browser.QueryInterface(Ci.nsIFrameLoaderOwner);
|
||||
|
||||
|
|
|
@ -90,10 +90,16 @@ def HostStdCppCompat():
|
|||
|
||||
|
||||
@template
|
||||
def HostProgram(name):
|
||||
def HostProgram(name, c_only=False):
|
||||
'''Template for build tools executables.'''
|
||||
HOST_PROGRAM = name
|
||||
|
||||
# With context-based templates, this won't be needed anymore, and will
|
||||
# work better than relying on the caller setting it, but at the moment,
|
||||
# this is the best we have. And it doesn't matter /that/ much, so there's
|
||||
# really only one place using this, where it does matter to avoid the
|
||||
# extra dependency (because it creates a circular one).
|
||||
if not c_only:
|
||||
HostStdCppCompat()
|
||||
|
||||
|
||||
|
|
|
@ -24,7 +24,10 @@ if CONFIG['HOST_OS_ARCH'] != 'WINNT':
|
|||
'nsinstall.c',
|
||||
'pathsub.c',
|
||||
]
|
||||
HostProgram('nsinstall_real')
|
||||
# stdc++compat depends on config/export, so avoid a circular
|
||||
# dependency added by HostProgram depending on stdc++compat,
|
||||
# while the program here is in C.
|
||||
HostProgram('nsinstall_real', c_only=True)
|
||||
|
||||
if CONFIG['MOZ_SHARED_ICU']:
|
||||
DEFINES['MOZ_SHARED_ICU'] = True
|
||||
|
|
|
@ -152,7 +152,7 @@ widget/android/bindings/export: build/annotationProcessors/export
|
|||
mobile/android/tests/browser/robocop/roboextender/tools: mobile/android/tests/javaaddons/tools
|
||||
|
||||
ifdef ENABLE_CLANG_PLUGIN
|
||||
$(filter-out build/clang-plugin/%,$(compile_targets)): build/clang-plugin/target build/clang-plugin/tests/target
|
||||
$(filter-out config/host build/unix/stdc++compat/% build/clang-plugin/%,$(compile_targets)): build/clang-plugin/target build/clang-plugin/tests/target
|
||||
build/clang-plugin/tests/target: build/clang-plugin/target
|
||||
endif
|
||||
|
||||
|
@ -176,3 +176,6 @@ endif
|
|||
# happen at the same time (bug #1146738)
|
||||
js/src/target: js/src/host
|
||||
endif
|
||||
# Most things are built during compile (target/host), but some things happen during export
|
||||
# Those need to depend on config/export for system wrappers.
|
||||
$(addprefix build/unix/stdc++compat/,target host) build/clang-plugin/target: config/export
|
||||
|
|
|
@ -863,9 +863,6 @@ endif # WINNT && !GCC
|
|||
ifdef ENABLE_STRIP
|
||||
$(STRIP) $(STRIP_FLAGS) $@
|
||||
endif
|
||||
ifdef MOZ_POST_DSO_LIB_COMMAND
|
||||
$(MOZ_POST_DSO_LIB_COMMAND) $@
|
||||
endif
|
||||
|
||||
ifeq ($(SOLARIS_SUNPRO_CC),1)
|
||||
_MDDEPFILE = $(MDDEPDIR)/$(@F).pp
|
||||
|
|
|
@ -8475,7 +8475,6 @@ AC_SUBST(USE_DEPENDENT_LIBS)
|
|||
|
||||
AC_SUBST(MOZ_BUILD_ROOT)
|
||||
|
||||
AC_SUBST(MOZ_POST_DSO_LIB_COMMAND)
|
||||
AC_SUBST(MOZ_POST_PROGRAM_COMMAND)
|
||||
AC_SUBST(MOZ_LINKER_EXTRACT)
|
||||
|
||||
|
|
|
@ -5814,6 +5814,15 @@ nsDocShell::SetPosition(int32_t aX, int32_t aY)
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDocShell::SetPositionDesktopPix(int32_t aX, int32_t aY)
|
||||
{
|
||||
// Added to nsIBaseWindow in bug 1247335;
|
||||
// implement if a use-case is found.
|
||||
NS_ASSERTION(false, "implement me!");
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDocShell::GetPosition(int32_t* aX, int32_t* aY)
|
||||
{
|
||||
|
|
|
@ -1107,7 +1107,7 @@ Animation::PostUpdate()
|
|||
}
|
||||
|
||||
Element* targetElement;
|
||||
nsCSSPseudoElements::Type targetPseudoType;
|
||||
CSSPseudoElementType targetPseudoType;
|
||||
mEffect->GetTarget(targetElement, targetPseudoType);
|
||||
if (!targetElement) {
|
||||
return;
|
||||
|
@ -1204,8 +1204,7 @@ Animation::EffectEnd() const
|
|||
return StickyTimeDuration(0);
|
||||
}
|
||||
|
||||
return mEffect->SpecifiedTiming().mDelay
|
||||
+ mEffect->GetComputedTiming().mActiveDuration;
|
||||
return mEffect->GetComputedTiming().mEndTime;
|
||||
}
|
||||
|
||||
nsIDocument*
|
||||
|
|
|
@ -17,13 +17,13 @@ NS_IMPL_CYCLE_COLLECTION_ROOT_NATIVE(CSSPseudoElement, AddRef)
|
|||
NS_IMPL_CYCLE_COLLECTION_UNROOT_NATIVE(CSSPseudoElement, Release)
|
||||
|
||||
CSSPseudoElement::CSSPseudoElement(Element* aElement,
|
||||
nsCSSPseudoElements::Type aType)
|
||||
CSSPseudoElementType aType)
|
||||
: mParentElement(aElement)
|
||||
, mPseudoType(aType)
|
||||
{
|
||||
MOZ_ASSERT(aElement);
|
||||
MOZ_ASSERT(aType == nsCSSPseudoElements::ePseudo_after ||
|
||||
aType == nsCSSPseudoElements::ePseudo_before,
|
||||
MOZ_ASSERT(aType == CSSPseudoElementType::after ||
|
||||
aType == CSSPseudoElementType::before,
|
||||
"Unexpected Pseudo Type");
|
||||
}
|
||||
|
||||
|
@ -69,7 +69,7 @@ CSSPseudoElement::Animate(
|
|||
|
||||
/* static */ already_AddRefed<CSSPseudoElement>
|
||||
CSSPseudoElement::GetCSSPseudoElement(Element* aElement,
|
||||
nsCSSPseudoElements::Type aType)
|
||||
CSSPseudoElementType aType)
|
||||
{
|
||||
if (!aElement) {
|
||||
return nullptr;
|
||||
|
@ -96,14 +96,13 @@ CSSPseudoElement::GetCSSPseudoElement(Element* aElement,
|
|||
}
|
||||
|
||||
/* static */ nsIAtom*
|
||||
CSSPseudoElement::GetCSSPseudoElementPropertyAtom(
|
||||
nsCSSPseudoElements::Type aType)
|
||||
CSSPseudoElement::GetCSSPseudoElementPropertyAtom(CSSPseudoElementType aType)
|
||||
{
|
||||
switch (aType) {
|
||||
case nsCSSPseudoElements::ePseudo_before:
|
||||
case CSSPseudoElementType::before:
|
||||
return nsGkAtoms::cssPseudoElementBeforeProperty;
|
||||
|
||||
case nsCSSPseudoElements::ePseudo_after:
|
||||
case CSSPseudoElementType::after:
|
||||
return nsGkAtoms::cssPseudoElementAfterProperty;
|
||||
|
||||
default:
|
||||
|
|
|
@ -38,7 +38,7 @@ public:
|
|||
virtual JSObject* WrapObject(JSContext* aCx,
|
||||
JS::Handle<JSObject*> aGivenProto) override;
|
||||
|
||||
nsCSSPseudoElements::Type GetType() const { return mPseudoType; }
|
||||
CSSPseudoElementType GetType() const { return mPseudoType; }
|
||||
void GetType(nsString& aRetVal) const
|
||||
{
|
||||
MOZ_ASSERT(nsCSSPseudoElements::GetPseudoAtom(mPseudoType),
|
||||
|
@ -64,20 +64,19 @@ public:
|
|||
// pseudo-type on element, a new CSSPseudoElement will be created and stored
|
||||
// on the element.
|
||||
static already_AddRefed<CSSPseudoElement>
|
||||
GetCSSPseudoElement(Element* aElement, nsCSSPseudoElements::Type aType);
|
||||
GetCSSPseudoElement(Element* aElement, CSSPseudoElementType aType);
|
||||
|
||||
private:
|
||||
// Only ::before and ::after are supported.
|
||||
CSSPseudoElement(Element* aElement, nsCSSPseudoElements::Type aType);
|
||||
CSSPseudoElement(Element* aElement, CSSPseudoElementType aType);
|
||||
|
||||
static nsIAtom*
|
||||
GetCSSPseudoElementPropertyAtom(nsCSSPseudoElements::Type aType);
|
||||
static nsIAtom* GetCSSPseudoElementPropertyAtom(CSSPseudoElementType aType);
|
||||
|
||||
// mParentElement needs to be an owning reference since if script is holding
|
||||
// on to the pseudo-element, it needs to continue to be able to refer to
|
||||
// the parent element.
|
||||
RefPtr<Element> mParentElement;
|
||||
nsCSSPseudoElements::Type mPseudoType;
|
||||
CSSPseudoElementType mPseudoType;
|
||||
};
|
||||
|
||||
} // namespace dom
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
#include "nsComputedDOMStyle.h" // nsComputedDOMStyle::GetPresShellForContent
|
||||
#include "nsCSSPropertySet.h"
|
||||
#include "nsCSSProps.h"
|
||||
#include "nsCSSPseudoElements.h"
|
||||
#include "nsIPresShell.h"
|
||||
#include "nsLayoutUtils.h"
|
||||
#include "nsRuleNode.h" // For nsRuleNode::ComputePropertiesOverridingAnimation
|
||||
|
@ -80,7 +81,7 @@ FindAnimationsForCompositor(const nsIFrame* aFrame,
|
|||
// Those cases are probably not important but just to be safe, let's make
|
||||
// sure the cascade is up to date since if it *is* up to date, this is
|
||||
// basically a no-op.
|
||||
Maybe<Pair<dom::Element*, nsCSSPseudoElements::Type>> pseudoElement =
|
||||
Maybe<Pair<dom::Element*, CSSPseudoElementType>> pseudoElement =
|
||||
EffectCompositor::GetAnimationElementAndPseudoForFrame(aFrame);
|
||||
if (pseudoElement) {
|
||||
EffectCompositor::MaybeUpdateCascadeResults(pseudoElement->first(),
|
||||
|
@ -131,7 +132,7 @@ FindAnimationsForCompositor(const nsIFrame* aFrame,
|
|||
|
||||
void
|
||||
EffectCompositor::RequestRestyle(dom::Element* aElement,
|
||||
nsCSSPseudoElements::Type aPseudoType,
|
||||
CSSPseudoElementType aPseudoType,
|
||||
RestyleType aRestyleType,
|
||||
CascadeLevel aCascadeLevel)
|
||||
{
|
||||
|
@ -171,7 +172,7 @@ EffectCompositor::RequestRestyle(dom::Element* aElement,
|
|||
|
||||
void
|
||||
EffectCompositor::PostRestyleForAnimation(dom::Element* aElement,
|
||||
nsCSSPseudoElements::Type aPseudoType,
|
||||
CSSPseudoElementType aPseudoType,
|
||||
CascadeLevel aCascadeLevel)
|
||||
{
|
||||
if (!mPresContext) {
|
||||
|
@ -212,8 +213,7 @@ EffectCompositor::PostRestyleForThrottledAnimations()
|
|||
|
||||
void
|
||||
EffectCompositor::MaybeUpdateAnimationRule(dom::Element* aElement,
|
||||
nsCSSPseudoElements::Type
|
||||
aPseudoType,
|
||||
CSSPseudoElementType aPseudoType,
|
||||
CascadeLevel aCascadeLevel)
|
||||
{
|
||||
// First update cascade results since that may cause some elements to
|
||||
|
@ -235,7 +235,7 @@ EffectCompositor::MaybeUpdateAnimationRule(dom::Element* aElement,
|
|||
|
||||
nsIStyleRule*
|
||||
EffectCompositor::GetAnimationRule(dom::Element* aElement,
|
||||
nsCSSPseudoElements::Type aPseudoType,
|
||||
CSSPseudoElementType aPseudoType,
|
||||
CascadeLevel aCascadeLevel)
|
||||
{
|
||||
// NOTE: We need to be careful about early returns in this method where
|
||||
|
@ -281,9 +281,9 @@ EffectCompositor::GetAnimationRule(dom::Element* aElement,
|
|||
|
||||
/* static */ dom::Element*
|
||||
EffectCompositor::GetElementToRestyle(dom::Element* aElement,
|
||||
nsCSSPseudoElements::Type aPseudoType)
|
||||
CSSPseudoElementType aPseudoType)
|
||||
{
|
||||
if (aPseudoType == nsCSSPseudoElements::ePseudo_NotPseudoElement) {
|
||||
if (aPseudoType == CSSPseudoElementType::NotPseudo) {
|
||||
return aElement;
|
||||
}
|
||||
|
||||
|
@ -292,9 +292,9 @@ EffectCompositor::GetElementToRestyle(dom::Element* aElement,
|
|||
return nullptr;
|
||||
}
|
||||
nsIFrame* pseudoFrame;
|
||||
if (aPseudoType == nsCSSPseudoElements::ePseudo_before) {
|
||||
if (aPseudoType == CSSPseudoElementType::before) {
|
||||
pseudoFrame = nsLayoutUtils::GetBeforeFrame(primaryFrame);
|
||||
} else if (aPseudoType == nsCSSPseudoElements::ePseudo_after) {
|
||||
} else if (aPseudoType == CSSPseudoElementType::after) {
|
||||
pseudoFrame = nsLayoutUtils::GetAfterFrame(primaryFrame);
|
||||
} else {
|
||||
NS_NOTREACHED("Should not try to get the element to restyle for a pseudo "
|
||||
|
@ -417,8 +417,7 @@ EffectCompositor::ClearIsRunningOnCompositor(const nsIFrame *aFrame,
|
|||
|
||||
/* static */ void
|
||||
EffectCompositor::MaybeUpdateCascadeResults(Element* aElement,
|
||||
nsCSSPseudoElements::Type
|
||||
aPseudoType,
|
||||
CSSPseudoElementType aPseudoType,
|
||||
nsStyleContext* aStyleContext)
|
||||
{
|
||||
EffectSet* effects = EffectSet::GetEffectSet(aElement, aPseudoType);
|
||||
|
@ -433,8 +432,7 @@ EffectCompositor::MaybeUpdateCascadeResults(Element* aElement,
|
|||
|
||||
/* static */ void
|
||||
EffectCompositor::MaybeUpdateCascadeResults(Element* aElement,
|
||||
nsCSSPseudoElements::Type
|
||||
aPseudoType)
|
||||
CSSPseudoElementType aPseudoType)
|
||||
{
|
||||
nsStyleContext* styleContext = nullptr;
|
||||
{
|
||||
|
@ -474,7 +472,7 @@ namespace {
|
|||
|
||||
/* static */ void
|
||||
EffectCompositor::UpdateCascadeResults(Element* aElement,
|
||||
nsCSSPseudoElements::Type aPseudoType,
|
||||
CSSPseudoElementType aPseudoType,
|
||||
nsStyleContext* aStyleContext)
|
||||
{
|
||||
EffectSet* effects = EffectSet::GetEffectSet(aElement, aPseudoType);
|
||||
|
@ -485,19 +483,18 @@ EffectCompositor::UpdateCascadeResults(Element* aElement,
|
|||
UpdateCascadeResults(*effects, aElement, aPseudoType, aStyleContext);
|
||||
}
|
||||
|
||||
/* static */ Maybe<Pair<Element*, nsCSSPseudoElements::Type>>
|
||||
/* static */ Maybe<Pair<Element*, CSSPseudoElementType>>
|
||||
EffectCompositor::GetAnimationElementAndPseudoForFrame(const nsIFrame* aFrame)
|
||||
{
|
||||
// Always return the same object to benefit from return-value optimization.
|
||||
Maybe<Pair<Element*, nsCSSPseudoElements::Type>> result;
|
||||
Maybe<Pair<Element*, CSSPseudoElementType>> result;
|
||||
|
||||
nsIContent* content = aFrame->GetContent();
|
||||
if (!content) {
|
||||
return result;
|
||||
}
|
||||
|
||||
nsCSSPseudoElements::Type pseudoType =
|
||||
nsCSSPseudoElements::ePseudo_NotPseudoElement;
|
||||
CSSPseudoElementType pseudoType = CSSPseudoElementType::NotPseudo;
|
||||
|
||||
if (aFrame->IsGeneratedContentFrame()) {
|
||||
nsIFrame* parent = aFrame->GetParent();
|
||||
|
@ -506,9 +503,9 @@ EffectCompositor::GetAnimationElementAndPseudoForFrame(const nsIFrame* aFrame)
|
|||
}
|
||||
nsIAtom* name = content->NodeInfo()->NameAtom();
|
||||
if (name == nsGkAtoms::mozgeneratedcontentbefore) {
|
||||
pseudoType = nsCSSPseudoElements::ePseudo_before;
|
||||
pseudoType = CSSPseudoElementType::before;
|
||||
} else if (name == nsGkAtoms::mozgeneratedcontentafter) {
|
||||
pseudoType = nsCSSPseudoElements::ePseudo_after;
|
||||
pseudoType = CSSPseudoElementType::after;
|
||||
} else {
|
||||
return result;
|
||||
}
|
||||
|
@ -534,7 +531,7 @@ EffectCompositor::GetAnimationElementAndPseudoForFrame(const nsIFrame* aFrame)
|
|||
|
||||
/* static */ void
|
||||
EffectCompositor::ComposeAnimationRule(dom::Element* aElement,
|
||||
nsCSSPseudoElements::Type aPseudoType,
|
||||
CSSPseudoElementType aPseudoType,
|
||||
CascadeLevel aCascadeLevel,
|
||||
TimeStamp aRefreshTime)
|
||||
{
|
||||
|
@ -615,7 +612,7 @@ EffectCompositor::GetOverriddenProperties(nsStyleContext* aStyleContext,
|
|||
/* static */ void
|
||||
EffectCompositor::UpdateCascadeResults(EffectSet& aEffectSet,
|
||||
Element* aElement,
|
||||
nsCSSPseudoElements::Type aPseudoType,
|
||||
CSSPseudoElementType aPseudoType,
|
||||
nsStyleContext* aStyleContext)
|
||||
{
|
||||
MOZ_ASSERT(EffectSet::GetEffectSet(aElement, aPseudoType) == &aEffectSet,
|
||||
|
@ -763,7 +760,7 @@ EffectCompositor::AnimationStyleRuleProcessor::RulesMatching(
|
|||
{
|
||||
nsIStyleRule *rule =
|
||||
mCompositor->GetAnimationRule(aData->mElement,
|
||||
nsCSSPseudoElements::ePseudo_NotPseudoElement,
|
||||
CSSPseudoElementType::NotPseudo,
|
||||
mCascadeLevel);
|
||||
if (rule) {
|
||||
aData->mRuleWalker->Forward(rule);
|
||||
|
@ -775,8 +772,8 @@ void
|
|||
EffectCompositor::AnimationStyleRuleProcessor::RulesMatching(
|
||||
PseudoElementRuleProcessorData* aData)
|
||||
{
|
||||
if (aData->mPseudoType != nsCSSPseudoElements::ePseudo_before &&
|
||||
aData->mPseudoType != nsCSSPseudoElements::ePseudo_after) {
|
||||
if (aData->mPseudoType != CSSPseudoElementType::before &&
|
||||
aData->mPseudoType != CSSPseudoElementType::after) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
@ -14,7 +14,6 @@
|
|||
#include "mozilla/PseudoElementHashEntry.h"
|
||||
#include "mozilla/RefPtr.h"
|
||||
#include "nsCSSProperty.h"
|
||||
#include "nsCSSPseudoElements.h"
|
||||
#include "nsCycleCollectionParticipant.h"
|
||||
#include "nsDataHashtable.h"
|
||||
#include "nsIStyleRuleProcessor.h"
|
||||
|
@ -30,6 +29,7 @@ namespace mozilla {
|
|||
|
||||
class EffectSet;
|
||||
class RestyleTracker;
|
||||
enum class CSSPseudoElementType : uint8_t;
|
||||
|
||||
namespace dom {
|
||||
class Animation;
|
||||
|
@ -94,7 +94,7 @@ public:
|
|||
// The specified steps taken to update the animation rule depend on
|
||||
// |aRestyleType| whose values are described above.
|
||||
void RequestRestyle(dom::Element* aElement,
|
||||
nsCSSPseudoElements::Type aPseudoType,
|
||||
CSSPseudoElementType aPseudoType,
|
||||
RestyleType aRestyleType,
|
||||
CascadeLevel aCascadeLevel);
|
||||
|
||||
|
@ -103,7 +103,7 @@ public:
|
|||
// need to perform this step when triggering transitions *without* also
|
||||
// invalidating the animation style rule (which RequestRestyle would do).
|
||||
void PostRestyleForAnimation(dom::Element* aElement,
|
||||
nsCSSPseudoElements::Type aPseudoType,
|
||||
CSSPseudoElementType aPseudoType,
|
||||
CascadeLevel aCascadeLevel);
|
||||
|
||||
// Posts an animation restyle for any elements whose animation style rule
|
||||
|
@ -116,11 +116,11 @@ public:
|
|||
// If the animation rule is not marked as needing an update,
|
||||
// no work is done.
|
||||
void MaybeUpdateAnimationRule(dom::Element* aElement,
|
||||
nsCSSPseudoElements::Type aPseudoType,
|
||||
CSSPseudoElementType aPseudoType,
|
||||
CascadeLevel aCascadeLevel);
|
||||
|
||||
nsIStyleRule* GetAnimationRule(dom::Element* aElement,
|
||||
nsCSSPseudoElements::Type aPseudoType,
|
||||
CSSPseudoElementType aPseudoType,
|
||||
CascadeLevel aCascadeLevel);
|
||||
|
||||
bool HasPendingStyleUpdates() const;
|
||||
|
@ -155,14 +155,14 @@ public:
|
|||
// animation level of the cascade have changed.
|
||||
static void
|
||||
MaybeUpdateCascadeResults(dom::Element* aElement,
|
||||
nsCSSPseudoElements::Type aPseudoType,
|
||||
CSSPseudoElementType aPseudoType,
|
||||
nsStyleContext* aStyleContext);
|
||||
|
||||
// An overload of MaybeUpdateCascadeResults that uses the style context
|
||||
// of the primary frame of the specified (pseudo-)element, when available.
|
||||
static void
|
||||
MaybeUpdateCascadeResults(dom::Element* aElement,
|
||||
nsCSSPseudoElements::Type aPseudoType);
|
||||
CSSPseudoElementType aPseudoType);
|
||||
|
||||
// Update the mWinsInCascade member for each property in effects targetting
|
||||
// the specified (pseudo-)element.
|
||||
|
@ -172,7 +172,7 @@ public:
|
|||
// other cases we should call MaybeUpdateCascadeResults.
|
||||
static void
|
||||
UpdateCascadeResults(dom::Element* aElement,
|
||||
nsCSSPseudoElements::Type aPseudoType,
|
||||
CSSPseudoElementType aPseudoType,
|
||||
nsStyleContext* aStyleContext);
|
||||
|
||||
// Helper to fetch the corresponding element and pseudo-type from a frame.
|
||||
|
@ -184,7 +184,7 @@ public:
|
|||
// Returns an empty result when a suitable element cannot be found including
|
||||
// when the frame represents a pseudo-element on which we do not support
|
||||
// animations.
|
||||
static Maybe<Pair<dom::Element*, nsCSSPseudoElements::Type>>
|
||||
static Maybe<Pair<dom::Element*, CSSPseudoElementType>>
|
||||
GetAnimationElementAndPseudoForFrame(const nsIFrame* aFrame);
|
||||
|
||||
private:
|
||||
|
@ -193,12 +193,12 @@ private:
|
|||
// Rebuilds the animation rule corresponding to |aCascadeLevel| on the
|
||||
// EffectSet associated with the specified (pseudo-)element.
|
||||
static void ComposeAnimationRule(dom::Element* aElement,
|
||||
nsCSSPseudoElements::Type aPseudoType,
|
||||
CSSPseudoElementType aPseudoType,
|
||||
CascadeLevel aCascadeLevel,
|
||||
TimeStamp aRefreshTime);
|
||||
|
||||
static dom::Element* GetElementToRestyle(dom::Element* aElement,
|
||||
nsCSSPseudoElements::Type
|
||||
CSSPseudoElementType
|
||||
aPseudoType);
|
||||
|
||||
// Get the properties in |aEffectSet| that we are able to animate on the
|
||||
|
@ -212,7 +212,7 @@ private:
|
|||
static void
|
||||
UpdateCascadeResults(EffectSet& aEffectSet,
|
||||
dom::Element* aElement,
|
||||
nsCSSPseudoElements::Type aPseudoType,
|
||||
CSSPseudoElementType aPseudoType,
|
||||
nsStyleContext* aStyleContext);
|
||||
|
||||
static nsPresContext* GetPresContext(dom::Element* aElement);
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
#include "EffectSet.h"
|
||||
#include "mozilla/dom/Element.h" // For Element
|
||||
#include "RestyleManager.h"
|
||||
#include "nsCSSPseudoElements.h" // For CSSPseudoElementType
|
||||
#include "nsCycleCollectionNoteChild.h" // For CycleCollectionNoteChild
|
||||
#include "nsPresContext.h"
|
||||
#include "nsLayoutUtils.h"
|
||||
|
@ -38,7 +39,7 @@ EffectSet::Traverse(nsCycleCollectionTraversalCallback& aCallback)
|
|||
|
||||
/* static */ EffectSet*
|
||||
EffectSet::GetEffectSet(dom::Element* aElement,
|
||||
nsCSSPseudoElements::Type aPseudoType)
|
||||
CSSPseudoElementType aPseudoType)
|
||||
{
|
||||
nsIAtom* propName = GetEffectSetPropertyAtom(aPseudoType);
|
||||
return static_cast<EffectSet*>(aElement->GetProperty(propName));
|
||||
|
@ -87,7 +88,7 @@ EffectSet::GetEffectSet(const nsIFrame* aFrame)
|
|||
|
||||
/* static */ EffectSet*
|
||||
EffectSet::GetOrCreateEffectSet(dom::Element* aElement,
|
||||
nsCSSPseudoElements::Type aPseudoType)
|
||||
CSSPseudoElementType aPseudoType)
|
||||
{
|
||||
EffectSet* effectSet = GetEffectSet(aElement, aPseudoType);
|
||||
if (effectSet) {
|
||||
|
@ -114,7 +115,7 @@ EffectSet::GetOrCreateEffectSet(dom::Element* aElement,
|
|||
|
||||
/* static */ void
|
||||
EffectSet::DestroyEffectSet(dom::Element* aElement,
|
||||
nsCSSPseudoElements::Type aPseudoType)
|
||||
CSSPseudoElementType aPseudoType)
|
||||
{
|
||||
nsIAtom* propName = GetEffectSetPropertyAtom(aPseudoType);
|
||||
EffectSet* effectSet =
|
||||
|
@ -152,16 +153,16 @@ EffectSet::GetEffectSetPropertyAtoms()
|
|||
}
|
||||
|
||||
/* static */ nsIAtom*
|
||||
EffectSet::GetEffectSetPropertyAtom(nsCSSPseudoElements::Type aPseudoType)
|
||||
EffectSet::GetEffectSetPropertyAtom(CSSPseudoElementType aPseudoType)
|
||||
{
|
||||
switch (aPseudoType) {
|
||||
case nsCSSPseudoElements::ePseudo_NotPseudoElement:
|
||||
case CSSPseudoElementType::NotPseudo:
|
||||
return nsGkAtoms::animationEffectsProperty;
|
||||
|
||||
case nsCSSPseudoElements::ePseudo_before:
|
||||
case CSSPseudoElementType::before:
|
||||
return nsGkAtoms::animationEffectsForBeforeProperty;
|
||||
|
||||
case nsCSSPseudoElements::ePseudo_after:
|
||||
case CSSPseudoElementType::after:
|
||||
return nsGkAtoms::animationEffectsForAfterProperty;
|
||||
|
||||
default:
|
||||
|
|
|
@ -12,7 +12,6 @@
|
|||
#include "mozilla/EffectCompositor.h"
|
||||
#include "mozilla/EnumeratedArray.h"
|
||||
#include "mozilla/TimeStamp.h"
|
||||
#include "nsCSSPseudoElements.h" // For nsCSSPseudoElements::Type
|
||||
#include "nsHashKeys.h" // For nsPtrHashKey
|
||||
#include "nsTHashtable.h" // For nsTHashtable
|
||||
|
||||
|
@ -25,6 +24,8 @@ class Element;
|
|||
class KeyframeEffectReadOnly;
|
||||
} // namespace dom
|
||||
|
||||
enum class CSSPseudoElementType : uint8_t;
|
||||
|
||||
// A wrapper around a hashset of AnimationEffect objects to handle
|
||||
// storing the set as a property of an element.
|
||||
class EffectSet
|
||||
|
@ -57,12 +58,12 @@ public:
|
|||
void Traverse(nsCycleCollectionTraversalCallback& aCallback);
|
||||
|
||||
static EffectSet* GetEffectSet(dom::Element* aElement,
|
||||
nsCSSPseudoElements::Type aPseudoType);
|
||||
CSSPseudoElementType aPseudoType);
|
||||
static EffectSet* GetEffectSet(const nsIFrame* aFrame);
|
||||
static EffectSet* GetOrCreateEffectSet(dom::Element* aElement,
|
||||
nsCSSPseudoElements::Type aPseudoType);
|
||||
CSSPseudoElementType aPseudoType);
|
||||
static void DestroyEffectSet(dom::Element* aElement,
|
||||
nsCSSPseudoElements::Type aPseudoType);
|
||||
CSSPseudoElementType aPseudoType);
|
||||
|
||||
void AddEffect(dom::KeyframeEffectReadOnly& aEffect);
|
||||
void RemoveEffect(dom::KeyframeEffectReadOnly& aEffect);
|
||||
|
@ -182,8 +183,7 @@ public:
|
|||
static nsIAtom** GetEffectSetPropertyAtoms();
|
||||
|
||||
private:
|
||||
static nsIAtom* GetEffectSetPropertyAtom(nsCSSPseudoElements::Type
|
||||
aPseudoType);
|
||||
static nsIAtom* GetEffectSetPropertyAtom(CSSPseudoElementType aPseudoType);
|
||||
|
||||
OwningEffectSet mEffects;
|
||||
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
#include "nsCSSParser.h"
|
||||
#include "nsCSSPropertySet.h"
|
||||
#include "nsCSSProps.h" // For nsCSSProps::PropHasFlags
|
||||
#include "nsCSSPseudoElements.h"
|
||||
#include "nsCSSValue.h"
|
||||
#include "nsStyleUtil.h"
|
||||
#include <algorithm> // For std::max
|
||||
|
@ -40,8 +41,7 @@ GetComputedTimingDictionary(const ComputedTiming& aComputedTiming,
|
|||
|
||||
// ComputedTimingProperties
|
||||
aRetVal.mActiveDuration = aComputedTiming.mActiveDuration.ToMilliseconds();
|
||||
aRetVal.mEndTime
|
||||
= std::max(aRetVal.mDelay + aRetVal.mActiveDuration + aRetVal.mEndDelay, 0.0);
|
||||
aRetVal.mEndTime = aComputedTiming.mEndTime.ToMilliseconds();
|
||||
aRetVal.mLocalTime = AnimationUtils::TimeDurationToDouble(aLocalTime);
|
||||
aRetVal.mProgress = aComputedTiming.mProgress;
|
||||
if (!aRetVal.mProgress.IsNull()) {
|
||||
|
@ -74,7 +74,7 @@ NS_IMPL_RELEASE_INHERITED(KeyframeEffectReadOnly, AnimationEffectReadOnly)
|
|||
KeyframeEffectReadOnly::KeyframeEffectReadOnly(
|
||||
nsIDocument* aDocument,
|
||||
Element* aTarget,
|
||||
nsCSSPseudoElements::Type aPseudoType,
|
||||
CSSPseudoElementType aPseudoType,
|
||||
const TimingParams& aTiming)
|
||||
: KeyframeEffectReadOnly(aDocument, aTarget, aPseudoType,
|
||||
new AnimationEffectTimingReadOnly(aTiming))
|
||||
|
@ -84,7 +84,7 @@ KeyframeEffectReadOnly::KeyframeEffectReadOnly(
|
|||
KeyframeEffectReadOnly::KeyframeEffectReadOnly(
|
||||
nsIDocument* aDocument,
|
||||
Element* aTarget,
|
||||
nsCSSPseudoElements::Type aPseudoType,
|
||||
CSSPseudoElementType aPseudoType,
|
||||
AnimationEffectTimingReadOnly* aTiming)
|
||||
: AnimationEffectReadOnly(aDocument)
|
||||
, mTarget(aTarget)
|
||||
|
@ -244,6 +244,8 @@ KeyframeEffectReadOnly::GetComputedTimingAt(
|
|||
1.0f :
|
||||
aTiming.mIterations;
|
||||
result.mActiveDuration = ActiveDuration(result.mDuration, result.mIterations);
|
||||
// Bug 1244635: Add endDelay to the end time calculation
|
||||
result.mEndTime = aTiming.mDelay + result.mActiveDuration;
|
||||
result.mFill = aTiming.mFill == dom::FillMode::Auto ?
|
||||
dom::FillMode::None :
|
||||
aTiming.mFill;
|
||||
|
@ -366,18 +368,19 @@ KeyframeEffectReadOnly::GetComputedTimingAt(
|
|||
}
|
||||
|
||||
StickyTimeDuration
|
||||
KeyframeEffectReadOnly::ActiveDuration(const StickyTimeDuration& aIterationDuration,
|
||||
KeyframeEffectReadOnly::ActiveDuration(
|
||||
const StickyTimeDuration& aIterationDuration,
|
||||
double aIterationCount)
|
||||
{
|
||||
if (IsInfinite(aIterationCount)) {
|
||||
// An animation that repeats forever has an infinite active duration
|
||||
// unless its iteration duration is zero, in which case it has a zero
|
||||
// active duration.
|
||||
// If either the iteration duration or iteration count is zero,
|
||||
// Web Animations says that the active duration is zero. This is to
|
||||
// ensure that the result is defined when the other argument is Infinity.
|
||||
const StickyTimeDuration zeroDuration;
|
||||
return aIterationDuration == zeroDuration ?
|
||||
zeroDuration :
|
||||
StickyTimeDuration::Forever();
|
||||
if (aIterationDuration == zeroDuration ||
|
||||
aIterationCount == 0.0) {
|
||||
return zeroDuration;
|
||||
}
|
||||
|
||||
return aIterationDuration.MultDouble(aIterationCount);
|
||||
}
|
||||
|
||||
|
@ -624,8 +627,7 @@ KeyframeEffectReadOnly::ConstructKeyframeEffect(const GlobalObject& aGlobal,
|
|||
"Uninitialized target");
|
||||
|
||||
RefPtr<Element> targetElement;
|
||||
nsCSSPseudoElements::Type pseudoType =
|
||||
nsCSSPseudoElements::ePseudo_NotPseudoElement;
|
||||
CSSPseudoElementType pseudoType = CSSPseudoElementType::NotPseudo;
|
||||
if (target.IsElement()) {
|
||||
targetElement = &target.GetAsElement();
|
||||
} else {
|
||||
|
@ -1230,7 +1232,7 @@ ApplyDistributeSpacing(nsTArray<OffsetIndexedKeyframe>& aKeyframes)
|
|||
*/
|
||||
static void
|
||||
GenerateValueEntries(Element* aTarget,
|
||||
nsCSSPseudoElements::Type aPseudoType,
|
||||
CSSPseudoElementType aPseudoType,
|
||||
nsTArray<OffsetIndexedKeyframe>& aKeyframes,
|
||||
nsTArray<KeyframeValueEntry>& aResult,
|
||||
ErrorResult& aRv)
|
||||
|
@ -1434,7 +1436,7 @@ static void
|
|||
BuildAnimationPropertyListFromKeyframeSequence(
|
||||
JSContext* aCx,
|
||||
Element* aTarget,
|
||||
nsCSSPseudoElements::Type aPseudoType,
|
||||
CSSPseudoElementType aPseudoType,
|
||||
JS::ForOfIterator& aIterator,
|
||||
nsTArray<AnimationProperty>& aResult,
|
||||
ErrorResult& aRv)
|
||||
|
@ -1492,7 +1494,7 @@ static void
|
|||
BuildAnimationPropertyListFromPropertyIndexedKeyframes(
|
||||
JSContext* aCx,
|
||||
Element* aTarget,
|
||||
nsCSSPseudoElements::Type aPseudoType,
|
||||
CSSPseudoElementType aPseudoType,
|
||||
JS::Handle<JS::Value> aValue,
|
||||
InfallibleTArray<AnimationProperty>& aResult,
|
||||
ErrorResult& aRv)
|
||||
|
@ -1667,7 +1669,7 @@ BuildAnimationPropertyListFromPropertyIndexedKeyframes(
|
|||
KeyframeEffectReadOnly::BuildAnimationPropertyList(
|
||||
JSContext* aCx,
|
||||
Element* aTarget,
|
||||
nsCSSPseudoElements::Type aPseudoType,
|
||||
CSSPseudoElementType aPseudoType,
|
||||
JS::Handle<JSObject*> aFrames,
|
||||
InfallibleTArray<AnimationProperty>& aResult,
|
||||
ErrorResult& aRv)
|
||||
|
@ -1721,13 +1723,13 @@ KeyframeEffectReadOnly::GetTarget(
|
|||
}
|
||||
|
||||
switch (mPseudoType) {
|
||||
case nsCSSPseudoElements::ePseudo_before:
|
||||
case nsCSSPseudoElements::ePseudo_after:
|
||||
case CSSPseudoElementType::before:
|
||||
case CSSPseudoElementType::after:
|
||||
aRv.SetValue().SetAsCSSPseudoElement() =
|
||||
CSSPseudoElement::GetCSSPseudoElement(mTarget, mPseudoType);
|
||||
break;
|
||||
|
||||
case nsCSSPseudoElements::ePseudo_NotPseudoElement:
|
||||
case CSSPseudoElementType::NotPseudo:
|
||||
aRv.SetValue().SetAsElement() = mTarget;
|
||||
break;
|
||||
|
||||
|
@ -1975,12 +1977,12 @@ KeyframeEffectReadOnly::GetAnimationFrame() const
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
if (mPseudoType == nsCSSPseudoElements::ePseudo_before) {
|
||||
if (mPseudoType == CSSPseudoElementType::before) {
|
||||
frame = nsLayoutUtils::GetBeforeFrame(frame);
|
||||
} else if (mPseudoType == nsCSSPseudoElements::ePseudo_after) {
|
||||
} else if (mPseudoType == CSSPseudoElementType::after) {
|
||||
frame = nsLayoutUtils::GetAfterFrame(frame);
|
||||
} else {
|
||||
MOZ_ASSERT(mPseudoType == nsCSSPseudoElements::ePseudo_NotPseudoElement,
|
||||
MOZ_ASSERT(mPseudoType == CSSPseudoElementType::NotPseudo,
|
||||
"unknown mPseudoType");
|
||||
}
|
||||
if (!frame) {
|
||||
|
@ -2126,7 +2128,7 @@ KeyframeEffectReadOnly::ShouldBlockCompositorAnimations(const nsIFrame*
|
|||
|
||||
KeyframeEffect::KeyframeEffect(nsIDocument* aDocument,
|
||||
Element* aTarget,
|
||||
nsCSSPseudoElements::Type aPseudoType,
|
||||
CSSPseudoElementType aPseudoType,
|
||||
const TimingParams& aTiming)
|
||||
: KeyframeEffectReadOnly(aDocument, aTarget, aPseudoType,
|
||||
new AnimationEffectTiming(aTiming))
|
||||
|
|
|
@ -9,7 +9,6 @@
|
|||
|
||||
#include "nsAutoPtr.h"
|
||||
#include "nsCycleCollectionParticipant.h"
|
||||
#include "nsCSSPseudoElements.h"
|
||||
#include "nsIDocument.h"
|
||||
#include "nsWrapperCache.h"
|
||||
#include "mozilla/Attributes.h"
|
||||
|
@ -38,6 +37,7 @@ namespace mozilla {
|
|||
|
||||
struct AnimationCollection;
|
||||
class AnimValuesStyleRule;
|
||||
enum class CSSPseudoElementType : uint8_t;
|
||||
|
||||
namespace dom {
|
||||
class ElementOrCSSPseudoElement;
|
||||
|
@ -57,6 +57,10 @@ struct ComputedTiming
|
|||
// Will equal StickyTimeDuration::Forever() if the animation repeats
|
||||
// indefinitely.
|
||||
StickyTimeDuration mActiveDuration;
|
||||
// The effect end time in local time (i.e. an offset from the effect's
|
||||
// start time). Will equal StickyTimeDuration::Forever() if the animation
|
||||
// plays indefinitely.
|
||||
StickyTimeDuration mEndTime;
|
||||
// Progress towards the end of the current iteration. If the effect is
|
||||
// being sampled backwards, this will go from 1.0 to 0.0.
|
||||
// Will be null if the animation is neither animating nor
|
||||
|
@ -172,7 +176,7 @@ class KeyframeEffectReadOnly : public AnimationEffectReadOnly
|
|||
public:
|
||||
KeyframeEffectReadOnly(nsIDocument* aDocument,
|
||||
Element* aTarget,
|
||||
nsCSSPseudoElements::Type aPseudoType,
|
||||
CSSPseudoElementType aPseudoType,
|
||||
const TimingParams& aTiming);
|
||||
|
||||
NS_DECL_ISUPPORTS_INHERITED
|
||||
|
@ -209,7 +213,7 @@ public:
|
|||
// Temporary workaround to return both the target element and pseudo-type
|
||||
// until we implement PseudoElement (bug 1174575).
|
||||
void GetTarget(Element*& aTarget,
|
||||
nsCSSPseudoElements::Type& aPseudoType) const {
|
||||
CSSPseudoElementType& aPseudoType) const {
|
||||
aTarget = mTarget;
|
||||
aPseudoType = mPseudoType;
|
||||
}
|
||||
|
@ -322,7 +326,7 @@ public:
|
|||
protected:
|
||||
KeyframeEffectReadOnly(nsIDocument* aDocument,
|
||||
Element* aTarget,
|
||||
nsCSSPseudoElements::Type aPseudoType,
|
||||
CSSPseudoElementType aPseudoType,
|
||||
AnimationEffectTimingReadOnly* aTiming);
|
||||
|
||||
virtual ~KeyframeEffectReadOnly();
|
||||
|
@ -351,7 +355,7 @@ protected:
|
|||
static void BuildAnimationPropertyList(
|
||||
JSContext* aCx,
|
||||
Element* aTarget,
|
||||
nsCSSPseudoElements::Type aPseudoType,
|
||||
CSSPseudoElementType aPseudoType,
|
||||
JS::Handle<JSObject*> aFrames,
|
||||
InfallibleTArray<AnimationProperty>& aResult,
|
||||
ErrorResult& aRv);
|
||||
|
@ -360,7 +364,7 @@ protected:
|
|||
RefPtr<Animation> mAnimation;
|
||||
|
||||
OwningNonNull<AnimationEffectTimingReadOnly> mTiming;
|
||||
nsCSSPseudoElements::Type mPseudoType;
|
||||
CSSPseudoElementType mPseudoType;
|
||||
|
||||
InfallibleTArray<AnimationProperty> mProperties;
|
||||
|
||||
|
@ -395,7 +399,7 @@ class KeyframeEffect : public KeyframeEffectReadOnly
|
|||
public:
|
||||
KeyframeEffect(nsIDocument* aDocument,
|
||||
Element* aTarget,
|
||||
nsCSSPseudoElements::Type aPseudoType,
|
||||
CSSPseudoElementType aPseudoType,
|
||||
const TimingParams& aTiming);
|
||||
|
||||
JSObject* WrapObject(JSContext* aCx,
|
||||
|
|
|
@ -9,18 +9,19 @@
|
|||
|
||||
#include "mozilla/dom/Element.h"
|
||||
#include "mozilla/HashFunctions.h"
|
||||
#include "nsCSSPseudoElements.h"
|
||||
#include "PLDHashTable.h"
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
enum class CSSPseudoElementType : uint8_t;
|
||||
|
||||
struct PseudoElementHashKey
|
||||
{
|
||||
dom::Element* mElement;
|
||||
nsCSSPseudoElements::Type mPseudoType;
|
||||
CSSPseudoElementType mPseudoType;
|
||||
};
|
||||
|
||||
// A hash entry that uses a RefPtr<dom::Element>, nsCSSPseudoElements::Type pair
|
||||
// A hash entry that uses a RefPtr<dom::Element>, CSSPseudoElementType pair
|
||||
class PseudoElementHashEntry : public PLDHashEntryHdr
|
||||
{
|
||||
public:
|
||||
|
@ -47,12 +48,14 @@ public:
|
|||
if (!aKey)
|
||||
return 0;
|
||||
|
||||
return mozilla::HashGeneric(aKey->mElement, aKey->mPseudoType);
|
||||
// Convert the scoped enum into an integer while adding it to hash.
|
||||
return mozilla::HashGeneric(aKey->mElement,
|
||||
static_cast<uint8_t>(aKey->mPseudoType));
|
||||
}
|
||||
enum { ALLOW_MEMMOVE = true };
|
||||
|
||||
RefPtr<dom::Element> mElement;
|
||||
nsCSSPseudoElements::Type mPseudoType;
|
||||
CSSPseudoElementType mPseudoType;
|
||||
};
|
||||
|
||||
} // namespace mozilla
|
||||
|
|
|
@ -188,11 +188,11 @@ test(function(t) {
|
|||
}, 'endTime of an infinitely repeating zero-duration animation');
|
||||
|
||||
test(function(t) {
|
||||
// Fill forwards so div.getAnimations()[0] wouldn't return
|
||||
// Fill forwards so div.getAnimations()[0] won't return an
|
||||
// undefined value.
|
||||
var div = addDiv(t, {style: 'animation: moveAnimation 10s -100s forwards'});
|
||||
var effect = div.getAnimations()[0].effect;
|
||||
assert_equals(effect.getComputedTiming().endTime, 0,
|
||||
assert_equals(effect.getComputedTiming().endTime, -90000,
|
||||
'Initial value of endTime');
|
||||
}, 'endTime of an animation that finishes before its startTime');
|
||||
|
||||
|
|
|
@ -3368,7 +3368,7 @@ void
|
|||
Element::GetAnimationsUnsorted(nsTArray<RefPtr<Animation>>& aAnimations)
|
||||
{
|
||||
EffectSet* effects = EffectSet::GetEffectSet(this,
|
||||
nsCSSPseudoElements::ePseudo_NotPseudoElement);
|
||||
CSSPseudoElementType::NotPseudo);
|
||||
if (!effects) {
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -2523,6 +2523,9 @@ public:
|
|||
bool
|
||||
PreDispatch(JSContext* aCx, WorkerPrivate* aWorkerPrivate)
|
||||
{
|
||||
// We don't call WorkerRunnable::PreDispatch because it would assert the
|
||||
// wrong thing about which thread we're on.
|
||||
AssertIsOnMainThread();
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -2530,6 +2533,9 @@ public:
|
|||
PostDispatch(JSContext* aCx, WorkerPrivate* aWorkerPrivate,
|
||||
bool aDispatchResult)
|
||||
{
|
||||
// We don't call WorkerRunnable::PostDispatch because it would assert the
|
||||
// wrong thing about which thread we're on.
|
||||
AssertIsOnMainThread();
|
||||
}
|
||||
|
||||
private:
|
||||
|
@ -2696,6 +2702,10 @@ public:
|
|||
bool
|
||||
PreDispatch(JSContext* aCx, WorkerPrivate* aWorkerPrivate)
|
||||
{
|
||||
// We don't call WorkerRunnable::PreDispatch because it would assert the
|
||||
// wrong thing about which thread we're on. We're on whichever thread the
|
||||
// channel implementation is running on (probably the main thread or socket
|
||||
// transport thread).
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -2703,6 +2713,10 @@ public:
|
|||
PostDispatch(JSContext* aCx, WorkerPrivate* aWorkerPrivate,
|
||||
bool aDispatchResult)
|
||||
{
|
||||
// We don't call WorkerRunnable::PreDispatch because it would assert the
|
||||
// wrong thing about which thread we're on. We're on whichever thread the
|
||||
// channel implementation is running on (probably the main thread or socket
|
||||
// transport thread).
|
||||
}
|
||||
|
||||
private:
|
||||
|
|
|
@ -389,7 +389,7 @@ nsAnimationReceiver::RecordAnimationMutation(Animation* aAnimation,
|
|||
}
|
||||
|
||||
mozilla::dom::Element* animationTarget;
|
||||
nsCSSPseudoElements::Type pseudoType;
|
||||
CSSPseudoElementType pseudoType;
|
||||
effect->GetTarget(animationTarget, pseudoType);
|
||||
if (!animationTarget) {
|
||||
return;
|
||||
|
|
|
@ -101,6 +101,7 @@
|
|||
#include "nsIDOMStyleSheet.h"
|
||||
#include "nsIStyleSheetService.h"
|
||||
#include "nsContentPermissionHelper.h"
|
||||
#include "nsCSSPseudoElements.h" // for CSSPseudoElementType
|
||||
#include "nsNetUtil.h"
|
||||
#include "nsDocument.h"
|
||||
#include "HTMLImageElement.h"
|
||||
|
@ -2247,10 +2248,9 @@ ComputeAnimationValue(nsCSSProperty aProperty,
|
|||
StyleAnimationValue& aOutput)
|
||||
{
|
||||
|
||||
if (!StyleAnimationValue::ComputeValue(
|
||||
aProperty,
|
||||
if (!StyleAnimationValue::ComputeValue(aProperty,
|
||||
aElement,
|
||||
nsCSSPseudoElements::ePseudo_NotPseudoElement,
|
||||
CSSPseudoElementType::NotPseudo,
|
||||
aInput,
|
||||
false,
|
||||
aOutput)) {
|
||||
|
|
|
@ -5002,6 +5002,8 @@ nsGlobalWindow::SetOuterSize(int32_t aLengthCSSPixels, bool aIsWidth,
|
|||
height = lengthDevPixels;
|
||||
}
|
||||
aError = treeOwnerAsWin->SetSize(width, height, true);
|
||||
|
||||
CheckForDPIChange();
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -5323,6 +5325,8 @@ nsGlobalWindow::SetScreenXOuter(int32_t aScreenX, ErrorResult& aError, bool aCal
|
|||
x = CSSToDevIntPixels(aScreenX);
|
||||
|
||||
aError = treeOwnerAsWin->SetPosition(x, y);
|
||||
|
||||
CheckForDPIChange();
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -5383,6 +5387,8 @@ nsGlobalWindow::SetScreenYOuter(int32_t aScreenY, ErrorResult& aError, bool aCal
|
|||
y = CSSToDevIntPixels(aScreenY);
|
||||
|
||||
aError = treeOwnerAsWin->SetPosition(x, y);
|
||||
|
||||
CheckForDPIChange();
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -7063,8 +7069,11 @@ nsGlobalWindow::MoveToOuter(int32_t aXPos, int32_t aYPos, ErrorResult& aError, b
|
|||
getter_AddRefs(screen));
|
||||
}
|
||||
|
||||
LayoutDevicePoint devPos;
|
||||
if (screen) {
|
||||
// On secondary displays, the "CSS px" coordinates are offset so that they
|
||||
// share their origin with global desktop pixels, to avoid ambiguities in
|
||||
// the coordinate space when there are displays with different DPIs.
|
||||
// (See the corresponding code in GetScreenXY() above.)
|
||||
int32_t screenLeftDeskPx, screenTopDeskPx, w, h;
|
||||
screen->GetRectDisplayPix(&screenLeftDeskPx, &screenTopDeskPx, &w, &h);
|
||||
CSSIntPoint cssPos(aXPos - screenLeftDeskPx, aYPos - screenTopDeskPx);
|
||||
|
@ -7072,20 +7081,21 @@ nsGlobalWindow::MoveToOuter(int32_t aXPos, int32_t aYPos, ErrorResult& aError, b
|
|||
|
||||
double scale;
|
||||
screen->GetDefaultCSSScaleFactor(&scale);
|
||||
devPos = cssPos * CSSToLayoutDeviceScale(scale);
|
||||
LayoutDevicePoint devPos = cssPos * CSSToLayoutDeviceScale(scale);
|
||||
|
||||
int32_t screenLeftDevPx, screenTopDevPx;
|
||||
screen->GetRect(&screenLeftDevPx, &screenTopDevPx, &w, &h);
|
||||
devPos.x += screenLeftDevPx;
|
||||
devPos.y += screenTopDevPx;
|
||||
screen->GetContentsScaleFactor(&scale);
|
||||
DesktopPoint deskPos = devPos / DesktopToLayoutDeviceScale(scale);
|
||||
aError = treeOwnerAsWin->SetPositionDesktopPix(screenLeftDeskPx + deskPos.x,
|
||||
screenTopDeskPx + deskPos.y);
|
||||
} else {
|
||||
// We couldn't find a screen? Just assume a 1:1 mapping.
|
||||
CSSIntPoint cssPos(aXPos, aXPos);
|
||||
CheckSecurityLeftAndTop(&cssPos.x, &cssPos.y, aCallerIsChrome);
|
||||
devPos = cssPos * CSSToLayoutDeviceScale(1.0);
|
||||
LayoutDevicePoint devPos = cssPos * CSSToLayoutDeviceScale(1.0);
|
||||
aError = treeOwnerAsWin->SetPosition(devPos.x, devPos.y);
|
||||
}
|
||||
|
||||
aError = treeOwnerAsWin->SetPosition(devPos.x, devPos.y);
|
||||
CheckForDPIChange();
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -7135,6 +7145,8 @@ nsGlobalWindow::MoveByOuter(int32_t aXDif, int32_t aYDif, ErrorResult& aError, b
|
|||
nsIntSize newDevPos(CSSToDevIntPixels(cssPos));
|
||||
|
||||
aError = treeOwnerAsWin->SetPosition(newDevPos.width, newDevPos.height);
|
||||
|
||||
CheckForDPIChange();
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -7193,6 +7205,8 @@ nsGlobalWindow::ResizeToOuter(int32_t aWidth, int32_t aHeight, ErrorResult& aErr
|
|||
nsIntSize devSz(CSSToDevIntPixels(cssSize));
|
||||
|
||||
aError = treeOwnerAsWin->SetSize(devSz.width, devSz.height, true);
|
||||
|
||||
CheckForDPIChange();
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -7262,6 +7276,8 @@ nsGlobalWindow::ResizeByOuter(int32_t aWidthDif, int32_t aHeightDif,
|
|||
nsIntSize newDevSize(CSSToDevIntPixels(cssSize));
|
||||
|
||||
aError = treeOwnerAsWin->SetSize(newDevSize.width, newDevSize.height, true);
|
||||
|
||||
CheckForDPIChange();
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -13958,6 +13974,23 @@ nsGlobalWindow::CreateImageBitmap(const ImageBitmapSource& aImage,
|
|||
return ImageBitmap::Create(this, aImage, Some(gfx::IntRect(aSx, aSy, aSw, aSh)), aRv);
|
||||
}
|
||||
|
||||
// Helper called by methods that move/resize the window,
|
||||
// to ensure the presContext (if any) is aware of resolution
|
||||
// change that may happen in multi-monitor configuration.
|
||||
void
|
||||
nsGlobalWindow::CheckForDPIChange()
|
||||
{
|
||||
if (mDocShell) {
|
||||
RefPtr<nsPresContext> presContext;
|
||||
mDocShell->GetPresContext(getter_AddRefs(presContext));
|
||||
if (presContext) {
|
||||
if (presContext->DeviceContext()->CheckDPIChange()) {
|
||||
presContext->UIResolutionChanged();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template class nsPIDOMWindow<mozIDOMWindowProxy>;
|
||||
template class nsPIDOMWindow<mozIDOMWindow>;
|
||||
template class nsPIDOMWindow<nsISupports>;
|
||||
|
|
|
@ -1652,6 +1652,10 @@ protected:
|
|||
// show, in that case we show a separate dialog to ask this question.
|
||||
bool ConfirmDialogIfNeeded();
|
||||
|
||||
// Helper called after moving/resizing, to update docShell's presContext
|
||||
// if we have caused a resolution change by moving across monitors.
|
||||
void CheckForDPIChange();
|
||||
|
||||
private:
|
||||
// Fire the JS engine's onNewGlobalObject hook. Only used on inner windows.
|
||||
void FireOnNewGlobalObject();
|
||||
|
|
|
@ -178,6 +178,7 @@ static uint32_t sForgetSkippableBeforeCC = 0;
|
|||
static uint32_t sPreviousSuspectedCount = 0;
|
||||
static uint32_t sCleanupsSinceLastGC = UINT32_MAX;
|
||||
static bool sNeedsFullCC = false;
|
||||
static bool sNeedsFullGC = false;
|
||||
static bool sNeedsGCAfterCC = false;
|
||||
static bool sIncrementalCC = false;
|
||||
static bool sDidPaintAfterPreviousICCSlice = false;
|
||||
|
@ -1312,7 +1313,14 @@ nsJSContext::GarbageCollectNow(JS::gcreason::Reason aReason,
|
|||
}
|
||||
|
||||
JSGCInvocationKind gckind = aShrinking == ShrinkingGC ? GC_SHRINK : GC_NORMAL;
|
||||
|
||||
if (sNeedsFullGC || aReason != JS::gcreason::CC_WAITING) {
|
||||
sNeedsFullGC = false;
|
||||
JS::PrepareForFullGC(sRuntime);
|
||||
} else {
|
||||
CycleCollectedJSRuntime::Get()->PrepareWaitingZonesForGC();
|
||||
}
|
||||
|
||||
if (aIncremental == IncrementalGC) {
|
||||
JS::StartIncrementalGC(sRuntime, gckind, aReason, aSliceMillis);
|
||||
} else {
|
||||
|
@ -2009,6 +2017,8 @@ nsJSContext::RunNextCollectorTimer()
|
|||
void
|
||||
nsJSContext::PokeGC(JS::gcreason::Reason aReason, int aDelay)
|
||||
{
|
||||
sNeedsFullGC = sNeedsFullGC || aReason != JS::gcreason::CC_WAITING;
|
||||
|
||||
if (sGCTimer || sInterSliceGCTimer || sShuttingDown) {
|
||||
// There's already a timer for GC'ing, just return
|
||||
return;
|
||||
|
@ -2278,14 +2288,11 @@ DOMGCSliceCallback(JSRuntime *aRt, JS::GCProgress aProgress, const JS::GCDescrip
|
|||
}
|
||||
} else {
|
||||
nsJSContext::KillFullGCTimer();
|
||||
}
|
||||
|
||||
// Avoid shrinking during heavy activity, which is suggested by
|
||||
// compartment GC. We don't need to shrink after a shrinking GC as this
|
||||
// happens automatically in this case.
|
||||
if (aDesc.invocationKind_ == GC_NORMAL) {
|
||||
nsJSContext::PokeShrinkGCBuffers();
|
||||
}
|
||||
}
|
||||
|
||||
if (ShouldTriggerCC(nsCycleCollector_suspectedCount())) {
|
||||
nsCycleCollector_dispatchDeferredDeletion();
|
||||
|
@ -2380,6 +2387,7 @@ mozilla::dom::StartupJSEnvironment()
|
|||
sLikelyShortLivingObjectsNeedingGC = 0;
|
||||
sPostGCEventsToConsole = false;
|
||||
sNeedsFullCC = false;
|
||||
sNeedsFullGC = false;
|
||||
sNeedsGCAfterCC = false;
|
||||
gNameSpaceManager = nullptr;
|
||||
sRuntime = nullptr;
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
|
||||
#include "nsNodeUtils.h"
|
||||
#include "nsContentUtils.h"
|
||||
#include "nsCSSPseudoElements.h"
|
||||
#include "nsINode.h"
|
||||
#include "nsIContent.h"
|
||||
#include "mozilla/dom/Element.h"
|
||||
|
@ -235,13 +236,13 @@ nsNodeUtils::GetTargetForAnimation(const Animation* aAnimation)
|
|||
}
|
||||
|
||||
Element* target;
|
||||
nsCSSPseudoElements::Type pseudoType;
|
||||
CSSPseudoElementType pseudoType;
|
||||
effect->GetTarget(target, pseudoType);
|
||||
|
||||
// If the animation targets a pseudo-element, we don't dispatch
|
||||
// notifications for it. (In the future we will have PseudoElement
|
||||
// objects we can use as the target of the notifications.)
|
||||
if (pseudoType != nsCSSPseudoElements::ePseudo_NotPseudoElement) {
|
||||
if (pseudoType != CSSPseudoElementType::NotPseudo) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
|
|
@ -5,11 +5,13 @@
|
|||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "nsOpenURIInFrameParams.h"
|
||||
#include "mozilla/BasePrincipal.h"
|
||||
|
||||
NS_IMPL_ISUPPORTS(nsOpenURIInFrameParams, nsIOpenURIInFrameParams)
|
||||
|
||||
nsOpenURIInFrameParams::nsOpenURIInFrameParams() :
|
||||
mIsPrivate(false)
|
||||
nsOpenURIInFrameParams::nsOpenURIInFrameParams(const mozilla::DocShellOriginAttributes& aOriginAttributes)
|
||||
: mOpenerOriginAttributes(aOriginAttributes)
|
||||
, mIsPrivate(false)
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -22,6 +24,7 @@ nsOpenURIInFrameParams::GetReferrer(nsAString& aReferrer)
|
|||
aReferrer = mReferrer;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsOpenURIInFrameParams::SetReferrer(const nsAString& aReferrer)
|
||||
{
|
||||
|
@ -36,9 +39,19 @@ nsOpenURIInFrameParams::GetIsPrivate(bool* aIsPrivate)
|
|||
*aIsPrivate = mIsPrivate;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsOpenURIInFrameParams::SetIsPrivate(bool aIsPrivate)
|
||||
{
|
||||
mIsPrivate = aIsPrivate;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsOpenURIInFrameParams::GetOpenerOriginAttributes(JSContext* aCx,
|
||||
JS::MutableHandle<JS::Value> aValue)
|
||||
{
|
||||
bool ok = ToJSValue(aCx, mOpenerOriginAttributes, aValue);
|
||||
NS_ENSURE_TRUE(ok, NS_ERROR_FAILURE);
|
||||
return NS_OK;
|
||||
}
|
||||
|
|
|
@ -7,16 +7,22 @@
|
|||
#include "nsIBrowserDOMWindow.h"
|
||||
#include "nsString.h"
|
||||
|
||||
namespace mozilla {
|
||||
class DocShellOriginAttributes;
|
||||
}
|
||||
|
||||
class nsOpenURIInFrameParams final : public nsIOpenURIInFrameParams
|
||||
{
|
||||
public:
|
||||
NS_DECL_ISUPPORTS
|
||||
NS_DECL_NSIOPENURIINFRAMEPARAMS
|
||||
|
||||
nsOpenURIInFrameParams();
|
||||
explicit nsOpenURIInFrameParams(const mozilla::DocShellOriginAttributes& aOriginAttributes);
|
||||
|
||||
private:
|
||||
~nsOpenURIInFrameParams();
|
||||
|
||||
mozilla::DocShellOriginAttributes mOpenerOriginAttributes;
|
||||
nsString mReferrer;
|
||||
bool mIsPrivate;
|
||||
};
|
||||
|
|
|
@ -70,6 +70,10 @@
|
|||
#include "WebGLVertexArray.h"
|
||||
#include "WebGLVertexAttribData.h"
|
||||
|
||||
#ifdef MOZ_WIDGET_COCOA
|
||||
#include "nsCocoaFeatures.h"
|
||||
#endif
|
||||
|
||||
// Generated
|
||||
#include "mozilla/dom/WebGLRenderingContextBinding.h"
|
||||
|
||||
|
@ -109,6 +113,7 @@ WebGLContext::WebGLContext()
|
|||
, mNeedsFakeNoAlpha(false)
|
||||
, mNeedsFakeNoDepth(false)
|
||||
, mNeedsFakeNoStencil(false)
|
||||
, mNeedsEmulatedLoneDepthStencil(false)
|
||||
{
|
||||
mGeneration = 0;
|
||||
mInvalidated = false;
|
||||
|
@ -891,6 +896,14 @@ WebGLContext::SetDimensions(int32_t signedWidth, int32_t signedHeight)
|
|||
|
||||
if (!mOptions.stencil && gl->Caps().stencil)
|
||||
mNeedsFakeNoStencil = true;
|
||||
|
||||
#ifdef MOZ_WIDGET_COCOA
|
||||
if (!nsCocoaFeatures::IsAtLeastVersion(10, 12) &&
|
||||
gl->Vendor() == GLVendor::Intel)
|
||||
{
|
||||
mNeedsEmulatedLoneDepthStencil = true;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
// Update mOptions.
|
||||
|
@ -1847,10 +1860,19 @@ WebGLContext::ScopedMaskWorkaround::~ScopedMaskWorkaround()
|
|||
mWebGL.gl->fEnable(LOCAL_GL_DEPTH_TEST);
|
||||
}
|
||||
if (mFakeNoStencil) {
|
||||
MOZ_ASSERT(mWebGL.mStencilTestEnabled);
|
||||
mWebGL.gl->fEnable(LOCAL_GL_STENCIL_TEST);
|
||||
}
|
||||
}
|
||||
|
||||
/*static*/ bool
|
||||
WebGLContext::ScopedMaskWorkaround::HasDepthButNoStencil(const WebGLFramebuffer* fb)
|
||||
{
|
||||
const auto& depth = fb->DepthAttachment();
|
||||
const auto& stencil = fb->StencilAttachment();
|
||||
return depth.IsDefined() && !stencil.IsDefined();
|
||||
}
|
||||
|
||||
////////////////////////////////////////
|
||||
|
||||
ScopedUnpackReset::ScopedUnpackReset(WebGLContext* webgl)
|
||||
|
|
|
@ -1505,6 +1505,7 @@ protected:
|
|||
bool mNeedsFakeNoAlpha;
|
||||
bool mNeedsFakeNoDepth;
|
||||
bool mNeedsFakeNoStencil;
|
||||
bool mNeedsEmulatedLoneDepthStencil;
|
||||
|
||||
struct ScopedMaskWorkaround {
|
||||
WebGLContext& mWebGL;
|
||||
|
@ -1527,11 +1528,32 @@ protected:
|
|||
webgl.mDepthTestEnabled;
|
||||
}
|
||||
|
||||
static bool HasDepthButNoStencil(const WebGLFramebuffer* fb);
|
||||
|
||||
static bool ShouldFakeNoStencil(WebGLContext& webgl) {
|
||||
// We should only be doing this if we're about to draw to the backbuffer.
|
||||
return !webgl.mBoundDrawFramebuffer &&
|
||||
webgl.mNeedsFakeNoStencil &&
|
||||
webgl.mStencilTestEnabled;
|
||||
if (!webgl.mStencilTestEnabled)
|
||||
return false;
|
||||
|
||||
if (!webgl.mBoundDrawFramebuffer) {
|
||||
if (webgl.mNeedsFakeNoStencil)
|
||||
return true;
|
||||
|
||||
if (webgl.mNeedsEmulatedLoneDepthStencil &&
|
||||
webgl.mOptions.depth && !webgl.mOptions.stencil)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
if (webgl.mNeedsEmulatedLoneDepthStencil &&
|
||||
HasDepthButNoStencil(webgl.mBoundDrawFramebuffer))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
explicit ScopedMaskWorkaround(WebGLContext& webgl);
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
TEST_DIRS += ['compiledtest']
|
||||
|
||||
# Number changes to this file to avoid bug 1081323 (clobber after changing a manifest):
|
||||
# 5
|
||||
# 11
|
||||
|
||||
MOCHITEST_MANIFESTS += [
|
||||
'test/crossorigin/mochitest.ini',
|
||||
|
|
|
@ -117,7 +117,6 @@ function GetExpectedTestFailSet() {
|
|||
failSet['conformance/glsl/functions/glsl-function-sin.html'] = true;
|
||||
failSet['conformance/misc/object-deletion-behaviour.html'] = true;
|
||||
failSet['conformance/textures/tex-image-with-format-and-type.html'] = true;
|
||||
failSet['conformance/textures/texture-mips.html'] = true;
|
||||
failSet['conformance/textures/texture-npot.html'] = true;
|
||||
failSet['conformance/textures/texture-size-cube-maps.html'] = true;
|
||||
} else if (DriverInfo.getOSVersion() >= OS_VERSION_ANDROID_ICS) {
|
||||
|
@ -135,7 +134,6 @@ function GetExpectedTestFailSet() {
|
|||
failSet['conformance/state/gl-get-calls.html'] = true;
|
||||
failSet['conformance/textures/tex-image-with-format-and-type.html'] = true;
|
||||
failSet['conformance/textures/tex-sub-image-2d.html'] = true;
|
||||
failSet['conformance/textures/texture-mips.html'] = true;
|
||||
failSet['conformance/textures/texture-size-cube-maps.html'] = true;
|
||||
} else {
|
||||
// Android 2.3 slaves.
|
||||
|
@ -144,7 +142,6 @@ function GetExpectedTestFailSet() {
|
|||
failSet['conformance/misc/object-deletion-behaviour.html'] = true;
|
||||
failSet['conformance/programs/program-test.html'] = true;
|
||||
failSet['conformance/textures/tex-image-and-sub-image-2d-with-video.html'] = true;
|
||||
failSet['conformance/textures/texture-mips.html'] = true;
|
||||
failSet['conformance/textures/texture-npot.html'] = true;
|
||||
}
|
||||
break;
|
||||
|
@ -158,7 +155,6 @@ function GetExpectedTestFailSet() {
|
|||
failSet['conformance/misc/object-deletion-behaviour.html'] = true;
|
||||
failSet['conformance/programs/get-active-test.html'] = true;
|
||||
failSet['conformance/textures/tex-input-validation.html'] = true;
|
||||
failSet['conformance/textures/texture-mips.html'] = true;
|
||||
failSet['conformance/textures/texture-npot.html'] = true;
|
||||
failSet['conformance/textures/texture-size-cube-maps.html'] = true;
|
||||
failSet['conformance/textures/texture-size.html'] = true;
|
||||
|
|
|
@ -15,11 +15,11 @@ fail-if = (os == 'android')
|
|||
[webgl-mochitest/ensure-exts/test_EXT_color_buffer_half_float.html]
|
||||
fail-if = (os == 'android')
|
||||
[webgl-mochitest/ensure-exts/test_EXT_disjoint_timer_query.html]
|
||||
fail-if = (os == 'android') || (os == 'linux') || (os == 'mac') || (os == 'win')
|
||||
fail-if = (os == 'android') || (os == 'mac') || (os == 'win')
|
||||
[webgl-mochitest/ensure-exts/test_EXT_frag_depth.html]
|
||||
fail-if = (os == 'android')
|
||||
[webgl-mochitest/ensure-exts/test_EXT_sRGB.html]
|
||||
fail-if = (os == 'android') || (os == 'linux') || (os == 'mac' && os_version == '10.6') || (os == 'win')
|
||||
fail-if = (os == 'android') || (os == 'mac' && os_version == '10.6') || (os == 'win')
|
||||
[webgl-mochitest/ensure-exts/test_EXT_shader_texture_lod.html]
|
||||
fail-if = (os == 'android') || (os == 'linux') || (os == 'mac')
|
||||
[webgl-mochitest/ensure-exts/test_EXT_texture_filter_anisotropic.html]
|
||||
|
@ -60,6 +60,8 @@ support-files = captureStream_common.js
|
|||
[webgl-mochitest/test_fb_param_crash.html]
|
||||
[webgl-mochitest/test_hidden_alpha.html]
|
||||
skip-if = (os == 'b2g') || buildapp == 'mulet' # Mulet - bug 1093639 (crashes in libLLVM-3.0.so)
|
||||
[webgl-mochitest/test_hidden_depth_stencil.html]
|
||||
fail-if = (os == 'win' && (os_version == '5.1' || os_version == '6.1'))
|
||||
[webgl-mochitest/test_implicit_color_buffer_float.html]
|
||||
[webgl-mochitest/test_highp_fs.html]
|
||||
[webgl-mochitest/test_no_arr_points.html]
|
||||
|
|
|
@ -0,0 +1,159 @@
|
|||
<!DOCTYPE HTML>
|
||||
<title>WebGL test: Hidden depth/stencil passes without a depth/stencil buffer respectively</title>
|
||||
<script src='/tests/SimpleTest/SimpleTest.js'></script>
|
||||
<link rel='stylesheet' href='/tests/SimpleTest/test.css'>
|
||||
<script src='webgl-util.js'></script>
|
||||
<body>
|
||||
<script id='vs' type='x-shader/x-vertex'>
|
||||
void main(void) {
|
||||
gl_PointSize = 1.0; // Note that this is undefined if we don't write to it!
|
||||
gl_Position = vec4(vec3(0), 1);
|
||||
}
|
||||
</script>
|
||||
|
||||
<script id='fs' type='x-shader/x-fragment'>
|
||||
precision mediump float;
|
||||
|
||||
void main(void) {
|
||||
gl_FragColor = vec4(0, 1, 0, 1);
|
||||
}
|
||||
</script>
|
||||
<script>
|
||||
|
||||
function ColorString(arr) {
|
||||
return '[' + arr[0] + ', ' + arr[1] + ', ' + arr[2] + ', ' + arr[3] + ']';
|
||||
}
|
||||
|
||||
function DrawAndCheck(gl, infoPrefix, refColorStr) {
|
||||
gl.viewport(0, 0, 1, 1);
|
||||
|
||||
gl.clearColor(1, 0, 0, 1);
|
||||
gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT | gl.STENCIL_BUFFER_BIT);
|
||||
gl.drawArrays(gl.POINTS, 0, 1);
|
||||
|
||||
var pixel = new Uint8Array(4);
|
||||
gl.readPixels(0, 0, 1, 1, gl.RGBA, gl.UNSIGNED_BYTE, pixel);
|
||||
var pixelStr = ColorString(pixel);
|
||||
|
||||
ok(pixelStr == refColorStr, infoPrefix + pixelStr + ' should be ' + refColorStr);
|
||||
}
|
||||
|
||||
function TestCurrent(gl, attribs, infoPrefix) {
|
||||
infoPrefix = infoPrefix + JSON.stringify(attribs) + ': ';
|
||||
|
||||
var CLEAR_COLOR = ColorString([255, 0, 0, 255]);
|
||||
var DRAW_COLOR = ColorString([0, 255, 0, 255]);
|
||||
|
||||
gl.disable(gl.DEPTH_TEST);
|
||||
gl.disable(gl.STENCIL_TEST);
|
||||
|
||||
DrawAndCheck(gl, infoPrefix + 'initial: ', DRAW_COLOR);
|
||||
|
||||
if (!attribs.depth) {
|
||||
gl.enable(gl.DEPTH_TEST);
|
||||
gl.depthFunc(gl.NEVER);
|
||||
|
||||
gl.disable(gl.STENCIL_TEST);
|
||||
|
||||
// Depth test is enabled, and should pass NEVER.
|
||||
// Since there is no depth buffer, the depth test is not run.
|
||||
// Stencil test is disabled.
|
||||
DrawAndCheck(gl, infoPrefix + 'no-depth: ', DRAW_COLOR);
|
||||
}
|
||||
|
||||
if (!attribs.stencil) {
|
||||
gl.disable(gl.DEPTH_TEST);
|
||||
|
||||
gl.enable(gl.STENCIL_TEST);
|
||||
gl.stencilFunc(gl.NEVER, 0, 0);
|
||||
|
||||
// Depth test is disabled.
|
||||
// Stencil test is enabled, and should pass NEVER.
|
||||
// Since there is no stencil buffer, the stencil test is not run.
|
||||
DrawAndCheck(gl, infoPrefix + 'no-stencil: ', DRAW_COLOR);
|
||||
}
|
||||
}
|
||||
|
||||
function TestBackbuffer(requestedAttribs) {
|
||||
var canvas = document.createElement('canvas');
|
||||
canvas.width = 1;
|
||||
canvas.height = 1;
|
||||
var gl = canvas.getContext('experimental-webgl', requestedAttribs);
|
||||
if (!gl) {
|
||||
ok(true, 'WebGL doesn\'t work, skipping test.');
|
||||
return;
|
||||
}
|
||||
|
||||
ok(gl.drawingBufferWidth == 1 && gl.drawingBufferHeight == 1,
|
||||
'backbuffer should be 1x1');
|
||||
|
||||
var prog = WebGLUtil.createProgramByIds(gl, 'vs', 'fs');
|
||||
gl.useProgram(prog);
|
||||
|
||||
var attribs = {
|
||||
depth: gl.getContextAttributes().depth,
|
||||
stencil: gl.getContextAttributes().stencil,
|
||||
};
|
||||
TestCurrent(gl, attribs, 'Backbuffer: ');
|
||||
}
|
||||
|
||||
function TestUserFB() {
|
||||
var canvas = document.createElement('canvas');
|
||||
var gl = canvas.getContext('experimental-webgl');
|
||||
if (!gl) {
|
||||
ok(true, 'WebGL doesn\'t work, skipping test.');
|
||||
return;
|
||||
}
|
||||
|
||||
var prog = WebGLUtil.createProgramByIds(gl, 'vs', 'fs');
|
||||
gl.useProgram(prog);
|
||||
|
||||
var rb = gl.createRenderbuffer();
|
||||
gl.bindRenderbuffer(gl.RENDERBUFFER, rb);
|
||||
gl.renderbufferStorage(gl.RENDERBUFFER, gl.RGBA4, 1, 1);
|
||||
|
||||
var fb = gl.createFramebuffer();
|
||||
gl.bindFramebuffer(gl.FRAMEBUFFER, fb);
|
||||
gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.RENDERBUFFER, rb);
|
||||
|
||||
var depthRB = gl.createRenderbuffer();
|
||||
gl.bindRenderbuffer(gl.RENDERBUFFER, depthRB);
|
||||
gl.renderbufferStorage(gl.RENDERBUFFER, gl.DEPTH_COMPONENT16, 1, 1);
|
||||
|
||||
var stencilRB = gl.createRenderbuffer();
|
||||
gl.bindRenderbuffer(gl.RENDERBUFFER, stencilRB);
|
||||
gl.renderbufferStorage(gl.RENDERBUFFER, gl.STENCIL_INDEX8, 1, 1);
|
||||
|
||||
do {
|
||||
gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.DEPTH_ATTACHMENT, gl.RENDERBUFFER, depthRB);
|
||||
gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.STENCIL_ATTACHMENT, gl.RENDERBUFFER, null);
|
||||
var status = gl.checkFramebufferStatus(gl.FRAMEBUFFER);
|
||||
if (status != gl.FRAMEBUFFER_COMPLETE) {
|
||||
ok(true, 'Depth-only user FB is incomplete. This is allowed.');
|
||||
break;
|
||||
}
|
||||
|
||||
TestCurrent(gl, {depth: true, stencil: false}, 'Depth-only user FB');
|
||||
} while (false);
|
||||
|
||||
do {
|
||||
gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.DEPTH_ATTACHMENT, gl.RENDERBUFFER, null);
|
||||
gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.STENCIL_ATTACHMENT, gl.RENDERBUFFER, stencilRB);
|
||||
var status = gl.checkFramebufferStatus(gl.FRAMEBUFFER);
|
||||
if (status != gl.FRAMEBUFFER_COMPLETE) {
|
||||
ok(true, 'Stencil-only user FB is incomplete. This is allowed.');
|
||||
break;
|
||||
}
|
||||
|
||||
TestCurrent(gl, {depth: false, stencil: true}, 'Stencil-only user FB');
|
||||
} while (false);
|
||||
}
|
||||
|
||||
(function(){
|
||||
TestBackbuffer({depth: true, stencil: false});
|
||||
TestBackbuffer({depth: false, stencil: true});
|
||||
TestUserFB();
|
||||
})();
|
||||
|
||||
</script>
|
||||
</body>
|
|
@ -82,6 +82,20 @@ HTMLSourceElement::WouldMatchMediaForDocument(const nsAString& aMedia,
|
|||
return pctx && mediaList->Matches(pctx, nullptr);
|
||||
}
|
||||
|
||||
void
|
||||
HTMLSourceElement::UpdateMediaList(const nsAttrValue* aValue)
|
||||
{
|
||||
mMediaList = nullptr;
|
||||
nsString mediaStr;
|
||||
if (!aValue || (mediaStr = aValue->GetStringValue()).IsEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
nsCSSParser cssParser;
|
||||
mMediaList = new nsMediaList();
|
||||
cssParser.ParseMediaList(mediaStr, nullptr, 0, mMediaList, false);
|
||||
}
|
||||
|
||||
nsresult
|
||||
HTMLSourceElement::AfterSetAttr(int32_t aNameSpaceID, nsIAtom* aName,
|
||||
const nsAttrValue* aValue, bool aNotify)
|
||||
|
@ -105,23 +119,17 @@ HTMLSourceElement::AfterSetAttr(int32_t aNameSpaceID, nsIAtom* aName,
|
|||
img->PictureSourceSrcsetChanged(AsContent(), strVal, aNotify);
|
||||
} else if (aName == nsGkAtoms::sizes) {
|
||||
img->PictureSourceSizesChanged(AsContent(), strVal, aNotify);
|
||||
} else if (aName == nsGkAtoms::media ||
|
||||
aName == nsGkAtoms::type) {
|
||||
} else if (aName == nsGkAtoms::media) {
|
||||
UpdateMediaList(aValue);
|
||||
img->PictureSourceMediaOrTypeChanged(AsContent(), aNotify);
|
||||
} else if (aName == nsGkAtoms::type) {
|
||||
img->PictureSourceMediaOrTypeChanged(AsContent(), aNotify);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} else if (aNameSpaceID == kNameSpaceID_None && aName == nsGkAtoms::media) {
|
||||
mMediaList = nullptr;
|
||||
if (aValue) {
|
||||
nsString mediaStr = aValue->GetStringValue();
|
||||
if (!mediaStr.IsEmpty()) {
|
||||
nsCSSParser cssParser;
|
||||
mMediaList = new nsMediaList();
|
||||
cssParser.ParseMediaList(mediaStr, nullptr, 0, mMediaList, false);
|
||||
}
|
||||
}
|
||||
UpdateMediaList(aValue);
|
||||
} else if (aNameSpaceID == kNameSpaceID_None && aName == nsGkAtoms::src) {
|
||||
mSrcMediaSource = nullptr;
|
||||
if (aValue) {
|
||||
|
|
|
@ -13,6 +13,7 @@
|
|||
#include "mozilla/dom/HTMLMediaElement.h"
|
||||
|
||||
class nsMediaList;
|
||||
class nsAttrValue;
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
|
@ -118,6 +119,9 @@ protected:
|
|||
private:
|
||||
RefPtr<nsMediaList> mMediaList;
|
||||
RefPtr<MediaSource> mSrcMediaSource;
|
||||
|
||||
// Generates a new nsMediaList using the given input
|
||||
void UpdateMediaList(const nsAttrValue* aValue);
|
||||
};
|
||||
|
||||
} // namespace dom
|
||||
|
|
|
@ -127,8 +127,7 @@ skip-if = (buildapp == 'b2g' && toolkit != 'gonk') # Bug 931116
|
|||
[test_blob_archive.html]
|
||||
skip-if = (buildapp == 'b2g' && toolkit != 'gonk') # Bug 931116
|
||||
[test_blob_file_backed.html]
|
||||
# This test can only run in the main process.
|
||||
skip-if = buildapp == 'b2g' || e10s
|
||||
skip-if = buildapp == 'b2g'
|
||||
[test_blob_simple.html]
|
||||
skip-if = (buildapp == 'b2g' && toolkit != 'gonk') # Bug 931116
|
||||
[test_blob_worker_crash.html]
|
||||
|
|
|
@ -9,10 +9,6 @@ var testGenerator = testSteps();
|
|||
|
||||
function testSteps()
|
||||
{
|
||||
const fileIOFlags = 0x02 | // PR_WRONLY
|
||||
0x08 | // PR_CREATEFILE
|
||||
0x20; // PR_TRUNCATE
|
||||
const filePerms = 0o664;
|
||||
const fileData = "abcdefghijklmnopqrstuvwxyz";
|
||||
const fileType = "text/plain";
|
||||
|
||||
|
@ -23,22 +19,12 @@ function testSteps()
|
|||
|
||||
info("Creating temp file");
|
||||
|
||||
let dirSvc =
|
||||
SpecialPowers.Cc["@mozilla.org/file/directory_service;1"]
|
||||
.getService(SpecialPowers.Ci.nsIProperties);
|
||||
let testFile = dirSvc.get("ProfD", SpecialPowers.Ci.nsIFile);
|
||||
testFile.createUnique(SpecialPowers.Ci.nsIFile.NORMAL_FILE_TYPE, filePerms);
|
||||
SpecialPowers.createFiles([{data:fileData, options:{type:fileType}}], function (files) {
|
||||
testGenerator.next(files[0]);
|
||||
});
|
||||
|
||||
info("Writing temp file");
|
||||
let file = yield undefined;
|
||||
|
||||
let outStream =
|
||||
SpecialPowers.Cc["@mozilla.org/network/file-output-stream;1"]
|
||||
.createInstance(SpecialPowers.Ci.nsIFileOutputStream);
|
||||
outStream.init(testFile, fileIOFlags, filePerms, 0);
|
||||
outStream.write(fileData, fileData.length);
|
||||
outStream.close();
|
||||
|
||||
let file = SpecialPowers.createDOMFile(testFile.path, { type: fileType });
|
||||
ok(file instanceof File, "Got a File object");
|
||||
is(file.size, fileData.length, "Correct size");
|
||||
is(file.type, fileType, "Correct type");
|
||||
|
@ -67,7 +53,6 @@ function testSteps()
|
|||
db = event.target.result;
|
||||
|
||||
file = null;
|
||||
testFile.remove(false);
|
||||
|
||||
objectStore = db.transaction(objectStoreName).objectStore(objectStoreName);
|
||||
objectStore.get(objectStoreKey).onsuccess = grabEventAndContinueHandler;
|
||||
|
|
|
@ -69,6 +69,8 @@ function finishTest()
|
|||
"free");
|
||||
}
|
||||
|
||||
SpecialPowers.removeFiles();
|
||||
|
||||
do_execute_soon(function(){
|
||||
testGenerator.close();
|
||||
do_test_finished();
|
||||
|
@ -484,7 +486,46 @@ var SpecialPowers = {
|
|||
return Cu;
|
||||
},
|
||||
|
||||
createDOMFile: function(file, options) {
|
||||
return new File(file, options);
|
||||
// Based on SpecialPowersObserver.prototype.receiveMessage
|
||||
createFiles: function(requests, callback) {
|
||||
let dirSvc = Cc["@mozilla.org/file/directory_service;1"].getService(Ci.nsIProperties);
|
||||
let filePaths = new Array;
|
||||
if (!this._createdFiles) {
|
||||
this._createdFiles = new Array;
|
||||
}
|
||||
let createdFiles = this._createdFiles;
|
||||
requests.forEach(function(request) {
|
||||
const filePerms = 0o666;
|
||||
let testFile = dirSvc.get("ProfD", Ci.nsIFile);
|
||||
if (request.name) {
|
||||
testFile.append(request.name);
|
||||
} else {
|
||||
testFile.createUnique(Ci.nsIFile.NORMAL_FILE_TYPE, filePerms);
|
||||
}
|
||||
let outStream = Cc["@mozilla.org/network/file-output-stream;1"].createInstance(Ci.nsIFileOutputStream);
|
||||
outStream.init(testFile, 0x02 | 0x08 | 0x20, // PR_WRONLY | PR_CREATE_FILE | PR_TRUNCATE
|
||||
filePerms, 0);
|
||||
if (request.data) {
|
||||
outStream.write(request.data, request.data.length);
|
||||
outStream.close();
|
||||
}
|
||||
filePaths.push(new File(testFile.path, request.options));
|
||||
createdFiles.push(testFile);
|
||||
});
|
||||
|
||||
setTimeout(function () {
|
||||
callback(filePaths);
|
||||
}, 0);
|
||||
},
|
||||
|
||||
removeFiles: function() {
|
||||
if (this._createdFiles) {
|
||||
this._createdFiles.forEach(function (testFile) {
|
||||
try {
|
||||
testFile.remove(false);
|
||||
} catch (e) {}
|
||||
});
|
||||
this._createdFiles = null;
|
||||
}
|
||||
},
|
||||
};
|
||||
|
|
|
@ -11,11 +11,13 @@ interface nsIURI;
|
|||
interface nsIFrameLoaderOwner;
|
||||
|
||||
[scriptable, uuid(e774db14-79ac-4156-a7a3-aa3fd0a22c10)]
|
||||
|
||||
interface nsIOpenURIInFrameParams : nsISupports
|
||||
{
|
||||
attribute DOMString referrer;
|
||||
attribute boolean isPrivate;
|
||||
|
||||
[implicit_jscontext]
|
||||
readonly attribute jsval openerOriginAttributes;
|
||||
};
|
||||
|
||||
[scriptable, uuid(9d17f3dd-672b-451e-afd2-b1115df780d5)]
|
||||
|
|
|
@ -73,6 +73,7 @@
|
|||
#include "mozilla/unused.h"
|
||||
|
||||
#include "mozInlineSpellChecker.h"
|
||||
#include "nsDocShell.h"
|
||||
#include "nsIConsoleListener.h"
|
||||
#include "nsICycleCollectorListener.h"
|
||||
#include "nsIDragService.h"
|
||||
|
@ -872,12 +873,22 @@ ContentChild::ProvideWindowCommon(TabChild* aTabOpener,
|
|||
baseURI->GetSpec(baseURIString);
|
||||
}
|
||||
|
||||
auto* opener = nsPIDOMWindowOuter::From(aParent);
|
||||
nsIDocShell* openerShell;
|
||||
RefPtr<nsDocShell> openerDocShell;
|
||||
if (opener && (openerShell = opener->GetDocShell())) {
|
||||
openerDocShell = static_cast<nsDocShell*>(openerShell);
|
||||
}
|
||||
|
||||
nsresult rv;
|
||||
if (!SendCreateWindow(aTabOpener, newChild,
|
||||
aChromeFlags, aCalledFromJS, aPositionSpecified,
|
||||
aSizeSpecified, url,
|
||||
name, features,
|
||||
baseURIString,
|
||||
openerDocShell
|
||||
? openerDocShell->GetOriginAttributes()
|
||||
: DocShellOriginAttributes(),
|
||||
&rv,
|
||||
aWindowIsNew,
|
||||
&frameScripts,
|
||||
|
|
|
@ -5465,6 +5465,7 @@ ContentParent::RecvCreateWindow(PBrowserParent* aThisTab,
|
|||
const nsString& aName,
|
||||
const nsCString& aFeatures,
|
||||
const nsCString& aBaseURI,
|
||||
const DocShellOriginAttributes& aOpenerOriginAttributes,
|
||||
nsresult* aResult,
|
||||
bool* aWindowIsNew,
|
||||
InfallibleTArray<FrameScriptInfo>* aFrameScripts,
|
||||
|
@ -5563,7 +5564,8 @@ ContentParent::RecvCreateWindow(PBrowserParent* aThisTab,
|
|||
loadContext->GetUsePrivateBrowsing(&isPrivate);
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIOpenURIInFrameParams> params = new nsOpenURIInFrameParams();
|
||||
nsCOMPtr<nsIOpenURIInFrameParams> params =
|
||||
new nsOpenURIInFrameParams(aOpenerOriginAttributes);
|
||||
params->SetReferrer(NS_ConvertUTF8toUTF16(aBaseURI));
|
||||
params->SetIsPrivate(isPrivate);
|
||||
|
||||
|
|
|
@ -501,6 +501,7 @@ public:
|
|||
const nsString& aName,
|
||||
const nsCString& aFeatures,
|
||||
const nsCString& aBaseURI,
|
||||
const DocShellOriginAttributes& aOpenerOriginAttributes,
|
||||
nsresult* aResult,
|
||||
bool* aWindowIsNew,
|
||||
InfallibleTArray<FrameScriptInfo>* aFrameScripts,
|
||||
|
|
|
@ -94,6 +94,7 @@ using mozilla::dom::ContentParentId from "mozilla/dom/ipc/IdType.h";
|
|||
using struct LookAndFeelInt from "mozilla/widget/WidgetMessageUtils.h";
|
||||
using class mozilla::dom::ipc::StructuredCloneData from "ipc/IPCMessageUtils.h";
|
||||
using mozilla::DataStorageType from "ipc/DataStorageIPCUtils.h";
|
||||
using mozilla::DocShellOriginAttributes from "mozilla/ipc/BackgroundUtils.h";
|
||||
|
||||
union ChromeRegistryItem
|
||||
{
|
||||
|
@ -1172,7 +1173,8 @@ parent:
|
|||
nsCString aURI,
|
||||
nsString aName,
|
||||
nsCString aFeatures,
|
||||
nsCString aBaseURI)
|
||||
nsCString aBaseURI,
|
||||
DocShellOriginAttributes aOpenerOriginAttributes)
|
||||
returns (nsresult rv,
|
||||
bool windowOpened,
|
||||
FrameScriptInfo[] frameScripts,
|
||||
|
|
|
@ -273,6 +273,25 @@ OpenDumpFile(AudioStream* aStream)
|
|||
return f;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
typename EnableIf<IsSame<T, int16_t>::value, void>::Type
|
||||
WriteDumpFileHelper(T* aInput, size_t aSamples, FILE* aFile) {
|
||||
fwrite(aInput, sizeof(T), aSamples, aFile);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
typename EnableIf<IsSame<T, float>::value, void>::Type
|
||||
WriteDumpFileHelper(T* aInput, size_t aSamples, FILE* aFile) {
|
||||
AutoTArray<uint8_t, 1024*2> buf;
|
||||
buf.SetLength(aSamples*2);
|
||||
uint8_t* output = buf.Elements();
|
||||
for (uint32_t i = 0; i < aSamples; ++i) {
|
||||
SetUint16LE(output + i*2, int16_t(aInput[i]*32767.0f));
|
||||
}
|
||||
fwrite(output, 2, aSamples, aFile);
|
||||
fflush(aFile);
|
||||
}
|
||||
|
||||
static void
|
||||
WriteDumpFile(FILE* aDumpFile, AudioStream* aStream, uint32_t aFrames,
|
||||
void* aBuffer)
|
||||
|
@ -281,22 +300,20 @@ WriteDumpFile(FILE* aDumpFile, AudioStream* aStream, uint32_t aFrames,
|
|||
return;
|
||||
|
||||
uint32_t samples = aStream->GetOutChannels()*aFrames;
|
||||
if (AUDIO_OUTPUT_FORMAT == AUDIO_FORMAT_S16) {
|
||||
fwrite(aBuffer, 2, samples, aDumpFile);
|
||||
return;
|
||||
|
||||
using SampleT = AudioSampleTraits<AUDIO_OUTPUT_FORMAT>::Type;
|
||||
WriteDumpFileHelper(reinterpret_cast<SampleT*>(aBuffer), samples, aDumpFile);
|
||||
}
|
||||
|
||||
NS_ASSERTION(AUDIO_OUTPUT_FORMAT == AUDIO_FORMAT_FLOAT32, "bad format");
|
||||
AutoTArray<uint8_t, 1024*2> buf;
|
||||
buf.SetLength(samples*2);
|
||||
float* input = static_cast<float*>(aBuffer);
|
||||
uint8_t* output = buf.Elements();
|
||||
for (uint32_t i = 0; i < samples; ++i) {
|
||||
SetUint16LE(output + i*2, int16_t(input[i]*32767.0f));
|
||||
}
|
||||
fwrite(output, 2, samples, aDumpFile);
|
||||
fflush(aDumpFile);
|
||||
}
|
||||
template <AudioSampleFormat N>
|
||||
struct ToCubebFormat {
|
||||
static const cubeb_sample_format value = CUBEB_SAMPLE_FLOAT32NE;
|
||||
};
|
||||
|
||||
template <>
|
||||
struct ToCubebFormat<AUDIO_FORMAT_S16> {
|
||||
static const cubeb_sample_format value = CUBEB_SAMPLE_S16NE;
|
||||
};
|
||||
|
||||
nsresult
|
||||
AudioStream::Init(uint32_t aNumChannels, uint32_t aRate,
|
||||
|
@ -333,12 +350,8 @@ AudioStream::Init(uint32_t aNumChannels, uint32_t aRate,
|
|||
return NS_ERROR_INVALID_ARG;
|
||||
}
|
||||
#endif
|
||||
if (AUDIO_OUTPUT_FORMAT == AUDIO_FORMAT_S16) {
|
||||
params.format = CUBEB_SAMPLE_S16NE;
|
||||
} else {
|
||||
params.format = CUBEB_SAMPLE_FLOAT32NE;
|
||||
}
|
||||
|
||||
params.format = ToCubebFormat<AUDIO_OUTPUT_FORMAT>::value;
|
||||
mAudioClock.Init();
|
||||
|
||||
return OpenCubeb(params);
|
||||
|
|
|
@ -134,8 +134,10 @@ static const char* const gWaveTypes[5] = {
|
|||
nullptr
|
||||
};
|
||||
|
||||
static char const *const gWaveCodecs[2] = {
|
||||
static char const *const gWaveCodecs[4] = {
|
||||
"1", // Microsoft PCM Format
|
||||
"6", // aLaw Encoding
|
||||
"7", // uLaw Encoding
|
||||
nullptr
|
||||
};
|
||||
|
||||
|
|
|
@ -104,7 +104,6 @@ TrackBuffersManager::TrackBuffersManager(dom::SourceBufferAttributes* aAttribute
|
|||
, mEvictionOccurred(false)
|
||||
, mMonitor("TrackBuffersManager")
|
||||
, mAppendRunning(false)
|
||||
, mSegmentParserLoopRunning(false)
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread(), "Must be instanciated on the main thread");
|
||||
}
|
||||
|
@ -301,7 +300,6 @@ void
|
|||
TrackBuffersManager::CompleteResetParserState()
|
||||
{
|
||||
MOZ_ASSERT(OnTaskQueue());
|
||||
MOZ_DIAGNOSTIC_ASSERT(!mSegmentParserLoopRunning);
|
||||
MSE_DEBUG("");
|
||||
|
||||
for (auto& track : GetTracksList()) {
|
||||
|
@ -437,7 +435,6 @@ bool
|
|||
TrackBuffersManager::CodedFrameRemoval(TimeInterval aInterval)
|
||||
{
|
||||
MOZ_ASSERT(OnTaskQueue());
|
||||
MOZ_ASSERT(!mSegmentParserLoopRunning, "Logic error: Append in progress");
|
||||
MSE_DEBUG("From %.2fs to %.2f",
|
||||
aInterval.mStart.ToSeconds(), aInterval.mEnd.ToSeconds());
|
||||
|
||||
|
@ -576,8 +573,6 @@ TrackBuffersManager::SegmentParserLoop()
|
|||
{
|
||||
MOZ_ASSERT(OnTaskQueue());
|
||||
|
||||
mSegmentParserLoopRunning = true;
|
||||
|
||||
while (true) {
|
||||
// 1. If the input buffer is empty, then jump to the need more data step below.
|
||||
if (!mInputBuffer || mInputBuffer->IsEmpty()) {
|
||||
|
@ -702,7 +697,6 @@ TrackBuffersManager::NeedMoreData()
|
|||
MSE_DEBUG("");
|
||||
RestoreCachedVariables();
|
||||
mAppendRunning = false;
|
||||
mSegmentParserLoopRunning = false;
|
||||
{
|
||||
// Wake-up any pending Abort()
|
||||
MonitorAutoLock mon(mMonitor);
|
||||
|
@ -716,7 +710,6 @@ TrackBuffersManager::RejectAppend(nsresult aRejectValue, const char* aName)
|
|||
{
|
||||
MSE_DEBUG("rv=%d", aRejectValue);
|
||||
mAppendRunning = false;
|
||||
mSegmentParserLoopRunning = false;
|
||||
{
|
||||
// Wake-up any pending Abort()
|
||||
MonitorAutoLock mon(mMonitor);
|
||||
|
|
|
@ -350,11 +350,8 @@ private:
|
|||
// Monitor to protect following objects accessed across multipple threads.
|
||||
// mMonitor is also notified if the value of mAppendRunning becomes false.
|
||||
mutable Monitor mMonitor;
|
||||
// Set to true while SegmentParserLoop is running.
|
||||
// Set to true while a BufferAppend is running or is pending.
|
||||
Atomic<bool> mAppendRunning;
|
||||
// Set to true while SegmentParserLoop is running.
|
||||
// This is for diagnostic only. Only accessed on the task queue.
|
||||
bool mSegmentParserLoopRunning;
|
||||
// Stable audio and video track time ranges.
|
||||
media::TimeIntervals mVideoBufferedRanges;
|
||||
media::TimeIntervals mAudioBufferedRanges;
|
||||
|
|
|
@ -155,6 +155,11 @@ EXPORTS.mozilla.media.webrtc += [
|
|||
'webrtc/WebrtcGlobal.h',
|
||||
]
|
||||
|
||||
if not CONFIG['MOZ_WEBRTC']:
|
||||
EXPORTS.mtransport += [
|
||||
'../../media/mtransport/runnable_utils.h',
|
||||
]
|
||||
|
||||
IPDL_SOURCES += [
|
||||
'webrtc/PWebrtcGlobal.ipdl'
|
||||
]
|
||||
|
|
|
@ -12,6 +12,39 @@ using mp4_demuxer::ByteReader;
|
|||
|
||||
namespace mozilla {
|
||||
|
||||
int16_t
|
||||
DecodeALawSample(uint8_t aValue)
|
||||
{
|
||||
aValue = aValue ^ 0x55;
|
||||
int8_t sign = (aValue & 0x80) ? -1 : 1;
|
||||
uint8_t exponent = (aValue & 0x70) >> 4;
|
||||
uint8_t mantissa = aValue & 0x0F;
|
||||
int16_t sample = mantissa << 4;
|
||||
switch (exponent) {
|
||||
case 0:
|
||||
sample += 8;
|
||||
break;
|
||||
case 1:
|
||||
sample += 0x108;
|
||||
break;
|
||||
default:
|
||||
sample += 0x108;
|
||||
sample <<= exponent - 1;
|
||||
}
|
||||
return sign * sample;
|
||||
}
|
||||
|
||||
int16_t
|
||||
DecodeULawSample(uint8_t aValue)
|
||||
{
|
||||
aValue = aValue ^ 0xFF;
|
||||
int8_t sign = (aValue & 0x80) ? -1 : 1;
|
||||
uint8_t exponent = (aValue & 0x70) >> 4;
|
||||
uint8_t mantissa = aValue & 0x0F;
|
||||
int16_t sample = (33 + 2 * mantissa) * (2 << (exponent + 1)) - 33;
|
||||
return sign * sample;
|
||||
}
|
||||
|
||||
WaveDataDecoder::WaveDataDecoder(const AudioInfo& aConfig,
|
||||
FlushableTaskQueue* aTaskQueue,
|
||||
MediaDataDecoderCallback* aCallback)
|
||||
|
@ -69,6 +102,17 @@ WaveDataDecoder::DoDecode(MediaRawData* aSample)
|
|||
auto buffer = MakeUnique<AudioDataValue[]>(frames * mInfo.mChannels);
|
||||
for (int i = 0; i < frames; ++i) {
|
||||
for (unsigned int j = 0; j < mInfo.mChannels; ++j) {
|
||||
if (mInfo.mProfile == 6) { //ALAW Data
|
||||
uint8_t v = aReader.ReadU8();
|
||||
int16_t decoded = DecodeALawSample(v);
|
||||
buffer[i * mInfo.mChannels + j] =
|
||||
IntegerToAudioSample<AudioDataValue>(decoded);
|
||||
} else if (mInfo.mProfile == 7) { //ULAW Data
|
||||
uint8_t v = aReader.ReadU8();
|
||||
int16_t decoded = DecodeULawSample(v);
|
||||
buffer[i * mInfo.mChannels + j] =
|
||||
IntegerToAudioSample<AudioDataValue>(decoded);
|
||||
} else { //PCM Data
|
||||
if (mInfo.mBitDepth == 8) {
|
||||
uint8_t v = aReader.ReadU8();
|
||||
buffer[i * mInfo.mChannels + j] =
|
||||
|
@ -84,6 +128,7 @@ WaveDataDecoder::DoDecode(MediaRawData* aSample)
|
|||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
aReader.DiscardRemaining();
|
||||
|
||||
|
@ -132,6 +177,8 @@ WaveDataDecoder::IsWave(const nsACString& aMimeType)
|
|||
// WAVdemuxer uses "audio/wave; codecs=aNum".
|
||||
return aMimeType.EqualsLiteral("audio/x-wav") ||
|
||||
aMimeType.EqualsLiteral("audio/wave; codecs=1") ||
|
||||
aMimeType.EqualsLiteral("audio/wave; codecs=6") ||
|
||||
aMimeType.EqualsLiteral("audio/wave; codecs=7") ||
|
||||
aMimeType.EqualsLiteral("audio/wave; codecs=65534");
|
||||
}
|
||||
|
||||
|
|
|
@ -263,6 +263,8 @@ AndroidDecoderModule::SupportsMimeType(const nsACString& aMimeType) const
|
|||
// To avoid this we check for wav types here.
|
||||
if (aMimeType.EqualsLiteral("audio/x-wav") ||
|
||||
aMimeType.EqualsLiteral("audio/wave; codecs=1") ||
|
||||
aMimeType.EqualsLiteral("audio/wave; codecs=6") ||
|
||||
aMimeType.EqualsLiteral("audio/wave; codecs=7") ||
|
||||
aMimeType.EqualsLiteral("audio/wave; codecs=65534")) {
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -474,13 +474,14 @@ void
|
|||
Shutdown(void)
|
||||
{
|
||||
OffTheBooksMutexAutoLock lock(CamerasSingleton::Mutex());
|
||||
if (!CamerasSingleton::Child()) {
|
||||
CamerasChild* child = CamerasSingleton::Child();
|
||||
if (!child) {
|
||||
// We don't want to cause everything to get fired up if we're
|
||||
// really already shut down.
|
||||
LOG(("Shutdown when already shut down"));
|
||||
return;
|
||||
}
|
||||
GetCamerasChild()->Shutdown();
|
||||
child->ShutdownAll();
|
||||
}
|
||||
|
||||
class ShutdownRunnable : public nsRunnable {
|
||||
|
@ -505,14 +506,22 @@ private:
|
|||
};
|
||||
|
||||
void
|
||||
CamerasChild::Shutdown()
|
||||
CamerasChild::ShutdownAll()
|
||||
{
|
||||
// Called with CamerasSingleton::Mutex() held
|
||||
ShutdownParent();
|
||||
ShutdownChild();
|
||||
}
|
||||
|
||||
void
|
||||
CamerasChild::ShutdownParent()
|
||||
{
|
||||
// Called with CamerasSingleton::Mutex() held
|
||||
{
|
||||
MonitorAutoLock monitor(mReplyMonitor);
|
||||
mIPCIsAlive = false;
|
||||
monitor.NotifyAll();
|
||||
}
|
||||
|
||||
if (CamerasSingleton::Thread()) {
|
||||
LOG(("Dispatching actor deletion"));
|
||||
// Delete the parent actor.
|
||||
|
@ -524,6 +533,16 @@ CamerasChild::Shutdown()
|
|||
return NS_OK;
|
||||
});
|
||||
CamerasSingleton::Thread()->Dispatch(deleteRunnable, NS_DISPATCH_NORMAL);
|
||||
} else {
|
||||
LOG(("ShutdownParent called without PBackground thread"));
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
CamerasChild::ShutdownChild()
|
||||
{
|
||||
// Called with CamerasSingleton::Mutex() held
|
||||
if (CamerasSingleton::Thread()) {
|
||||
LOG(("PBackground thread exists, dispatching close"));
|
||||
// Dispatch closing the IPC thread back to us when the
|
||||
// BackgroundChild is closed.
|
||||
|
@ -607,7 +626,11 @@ CamerasChild::~CamerasChild()
|
|||
|
||||
{
|
||||
OffTheBooksMutexAutoLock lock(CamerasSingleton::Mutex());
|
||||
Shutdown();
|
||||
// In normal circumstances we've already shut down and the
|
||||
// following does nothing. But on fatal IPC errors we will
|
||||
// get destructed immediately, and should not try to reach
|
||||
// the parent.
|
||||
ShutdownChild();
|
||||
}
|
||||
|
||||
MOZ_COUNT_DTOR(CamerasChild);
|
||||
|
|
|
@ -192,13 +192,9 @@ public:
|
|||
const unsigned int device_nameUTF8Length,
|
||||
char* unique_idUTF8,
|
||||
const unsigned int unique_idUTF8Length);
|
||||
void Shutdown();
|
||||
void ShutdownAll();
|
||||
|
||||
webrtc::ExternalRenderer* Callback(CaptureEngine aCapEngine, int capture_id);
|
||||
void AddCallback(const CaptureEngine aCapEngine, const int capture_id,
|
||||
webrtc::ExternalRenderer* render);
|
||||
void RemoveCallback(const CaptureEngine aCapEngine, const int capture_id);
|
||||
|
||||
|
||||
private:
|
||||
CamerasChild();
|
||||
|
@ -207,6 +203,11 @@ private:
|
|||
// decidecated Cameras IPC/PBackground thread.
|
||||
bool DispatchToParent(nsIRunnable* aRunnable,
|
||||
MonitorAutoLock& aMonitor);
|
||||
void AddCallback(const CaptureEngine aCapEngine, const int capture_id,
|
||||
webrtc::ExternalRenderer* render);
|
||||
void RemoveCallback(const CaptureEngine aCapEngine, const int capture_id);
|
||||
void ShutdownParent();
|
||||
void ShutdownChild();
|
||||
|
||||
nsTArray<CapturerElement> mCallbacks;
|
||||
// Protects the callback arrays
|
||||
|
|
|
@ -11,6 +11,8 @@ function check_wave(v, enabled) {
|
|||
|
||||
// Supported Wave codecs
|
||||
check("audio/wave; codecs=1", "probably");
|
||||
check("audio/wave; codecs=6", "probably");
|
||||
check("audio/wave; codecs=7", "probably");
|
||||
// "no codecs" should be supported, I guess
|
||||
check("audio/wave; codecs=", "probably");
|
||||
check("audio/wave; codecs=\"\"", "probably");
|
||||
|
|
|
@ -158,6 +158,10 @@ var gPlayTests = [
|
|||
{ name:"16bit_wave_extrametadata.wav", type:"audio/x-wav", duration:1.108 },
|
||||
// 24-bit samples
|
||||
{ name:"wavedata_s24.wav", type:"audio/x-wav", duration:1.0 },
|
||||
// aLaw compressed wave file
|
||||
{ name:"wavedata_alaw.wav", type:"audio/x-wav", duration:1.0 },
|
||||
// uLaw compressed wave file
|
||||
{ name:"wavedata_ulaw.wav", type:"audio/x-wav", duration:1.0 },
|
||||
|
||||
// Ogg stream without eof marker
|
||||
{ name:"bug461281.ogg", type:"application/ogg", duration:2.208 },
|
||||
|
|
|
@ -557,12 +557,16 @@ support-files =
|
|||
wave_metadata_unknown_tag.wav^headers^
|
||||
wave_metadata_utf8.wav
|
||||
wave_metadata_utf8.wav^headers^
|
||||
wavedata_alaw.wav
|
||||
wavedata_alaw.wav^headers^
|
||||
wavedata_s24.wav
|
||||
wavedata_s24.wav^headers^
|
||||
wavedata_s16.wav
|
||||
wavedata_s16.wav^headers^
|
||||
wavedata_u8.wav
|
||||
wavedata_u8.wav^headers^
|
||||
wavedata_ulaw.wav
|
||||
wavedata_ulaw.wav^headers^
|
||||
|
||||
[test_access_control.html]
|
||||
skip-if = buildapp == 'b2g' && toolkit != 'gonk' # bug 1082984
|
||||
|
|
Двоичный файл не отображается.
|
@ -0,0 +1 @@
|
|||
Cache-Control: no-store
|
Двоичный файл не отображается.
|
@ -0,0 +1 @@
|
|||
Cache-Control: no-store
|
|
@ -74,15 +74,6 @@
|
|||
]);
|
||||
|
||||
test.chain.insertBefore('PC_LOCAL_CREATE_OFFER', [
|
||||
// addTrack will not finish until GMP is initted, but addTrack doesn't
|
||||
// give us a promise to wait on or a callback. We cannot do
|
||||
// setParameters until addTrack is finished. So, we create a dummy
|
||||
// offer, which _does_ give us a promise to wait on, and once that is
|
||||
// done we know that addTrack is done too.
|
||||
// TODO(bug 1241153): Remove the need for this hack.
|
||||
function PC_LOCAL_CREATE_OFFER(test) {
|
||||
return test.createOffer(test.pcLocal);
|
||||
},
|
||||
function PC_LOCAL_SET_RIDS(test) {
|
||||
var senders = test.pcLocal._pc.getSenders();
|
||||
is(senders.length, 1, "We have exactly one RTP sender");
|
||||
|
|
|
@ -52,7 +52,10 @@ WaveDecoder::CanHandleMediaType(const nsACString& aType,
|
|||
{
|
||||
if (aType.EqualsASCII("audio/wave") || aType.EqualsASCII("audio/x-wav") ||
|
||||
aType.EqualsASCII("audio/wav") || aType.EqualsASCII("audio/x-pn-wav")) {
|
||||
return IsEnabled() && (aCodecs.IsEmpty() || aCodecs.EqualsASCII("1"));
|
||||
return IsEnabled() && (aCodecs.IsEmpty() ||
|
||||
aCodecs.EqualsASCII("1") ||
|
||||
aCodecs.EqualsASCII("6") ||
|
||||
aCodecs.EqualsASCII("7"));
|
||||
}
|
||||
|
||||
return false;
|
||||
|
|
|
@ -148,7 +148,8 @@ MediaEngineGonkVideoSource::NumCapabilities()
|
|||
nsresult
|
||||
MediaEngineGonkVideoSource::Allocate(const dom::MediaTrackConstraints& aConstraints,
|
||||
const MediaEnginePrefs& aPrefs,
|
||||
const nsString& aDeviceId)
|
||||
const nsString& aDeviceId,
|
||||
const nsACString& aOrigin)
|
||||
{
|
||||
LOG((__FUNCTION__));
|
||||
|
||||
|
|
|
@ -62,7 +62,8 @@ public:
|
|||
|
||||
nsresult Allocate(const dom::MediaTrackConstraints &aConstraints,
|
||||
const MediaEnginePrefs &aPrefs,
|
||||
const nsString& aDeviceId) override;
|
||||
const nsString& aDeviceId,
|
||||
const nsACString& aOrigin) override;
|
||||
nsresult Deallocate() override;
|
||||
nsresult Start(SourceMediaStream* aStream, TrackID aID) override;
|
||||
nsresult Stop(SourceMediaStream* aSource, TrackID aID) override;
|
||||
|
|
|
@ -41,8 +41,6 @@ if CONFIG['MOZ_WEBSPEECH']:
|
|||
'test/nsFakeSynthServices.cpp'
|
||||
]
|
||||
|
||||
DIRS = []
|
||||
|
||||
if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'windows':
|
||||
DIRS += ['windows']
|
||||
|
||||
|
|
|
@ -375,6 +375,9 @@ protected:
|
|||
bool
|
||||
PreDispatch(JSContext* aCx, WorkerPrivate* aWorkerPrivate) override
|
||||
{
|
||||
// We don't call WorkerRunnable::PreDispatch because it would assert the
|
||||
// wrong thing about which thread we're on.
|
||||
AssertIsOnMainThread();
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -382,6 +385,9 @@ protected:
|
|||
PostDispatch(JSContext* aCx, WorkerPrivate* aWorkerPrivate,
|
||||
bool aDispatchResult) override
|
||||
{
|
||||
// We don't call WorkerRunnable::PostDispatch because it would assert the
|
||||
// wrong thing about which thread we're on.
|
||||
AssertIsOnMainThread();
|
||||
}
|
||||
|
||||
bool
|
||||
|
|
|
@ -90,12 +90,12 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=840388
|
|||
switch(event.data.test) {
|
||||
|
||||
case "insecurePage_navigate_child":
|
||||
ok((event.data.msg == "navigated to insecure iframe on insecure page"), "navigating to insecure iframe blocked on insecure page");
|
||||
is(event.data.msg, "navigated to insecure iframe on insecure page", "navigating to insecure iframe blocked on insecure page");
|
||||
testsToRunInsecure["insecurePage_navigate_child"] = true;
|
||||
break;
|
||||
|
||||
case "insecurePage_navigate_grandchild":
|
||||
ok((event.data.msg == "navigated to insecure grandchild iframe on insecure page"), "navigating to insecure grandchild iframe blocked on insecure page");
|
||||
is(event.data.msg, "navigated to insecure grandchild iframe on insecure page", "navigating to insecure grandchild iframe blocked on insecure page");
|
||||
testsToRunInsecure["insecurePage_navigate_grandchild"] = true;
|
||||
break;
|
||||
|
||||
|
@ -105,7 +105,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=840388
|
|||
break;
|
||||
|
||||
case "blankTarget":
|
||||
ok((event.data.msg == "opened an http link with target=_blank from a secure page"), "couldn't open an http link in a new window from a secure page");
|
||||
is(event.data.msg, "opened an http link with target=_blank from a secure page", "couldn't open an http link in a new window from a secure page");
|
||||
testsToRunSecure["blankTarget"] = true;
|
||||
break;
|
||||
|
||||
|
|
|
@ -360,10 +360,9 @@ ValueFromStringHelper(nsCSSProperty aPropID,
|
|||
}
|
||||
}
|
||||
nsDependentSubstring subString(aString, subStringBegin);
|
||||
if (!StyleAnimationValue::ComputeValue(
|
||||
aPropID,
|
||||
if (!StyleAnimationValue::ComputeValue(aPropID,
|
||||
aTargetElement,
|
||||
nsCSSPseudoElements::ePseudo_NotPseudoElement,
|
||||
CSSPseudoElementType::NotPseudo,
|
||||
subString,
|
||||
true,
|
||||
aStyleAnimValue,
|
||||
|
|
|
@ -168,4 +168,5 @@ skip-if = buildapp == 'mulet' || buildapp == 'b2g' || toolkit == 'android' || e1
|
|||
skip-if = buildapp == 'mulet' || buildapp == 'b2g' || toolkit == 'android' || e10s
|
||||
[test_bug1022869.html]
|
||||
[test_bug1112040.html]
|
||||
[test_bug1160342_marquee.html]
|
||||
[test_bug1171215.html]
|
||||
|
|
|
@ -0,0 +1,228 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<!--
|
||||
https://bugzilla.mozilla.org/show_bug.cgi?id=1160342
|
||||
-->
|
||||
<head>
|
||||
<title>Test for Bug 411103</title>
|
||||
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
|
||||
</head>
|
||||
<body>
|
||||
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1160342">Mozilla Bug 1160342</a>
|
||||
<p id="display"></p>
|
||||
<div id="content">
|
||||
<marquee id="a">marquee</marquee>
|
||||
</div>
|
||||
|
||||
<pre id="test">
|
||||
<script class="testbody" type="text/javascript">
|
||||
var x=document.getElementById('a');
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
|
||||
setTimeout(function() {
|
||||
is(x.behavior, "scroll", "Wrong behavior value");
|
||||
x.setAttribute('behavior', 'alternate');
|
||||
is(x.behavior, "alternate", "Wrong behavior value");
|
||||
x.setAttribute('behavior', 'invalid');
|
||||
todo_is(x.behavior, "scroll", "Wrong behavior value");;
|
||||
x.setAttribute('behavior', 'Scroll');
|
||||
is(x.behavior, "scroll", "Wrong behavior value");
|
||||
x.setAttribute('behavior', 'Slide');
|
||||
is(x.behavior, "slide", "Wrong behavior value");
|
||||
x.removeAttribute('behavior');
|
||||
is(x.behavior, "scroll", "Wrong behavior value");
|
||||
|
||||
x.behavior = 'alternate';
|
||||
is(x.behavior, "alternate", "Wrong behavior value");
|
||||
try {
|
||||
x.behavior = 'invalid';
|
||||
todo_is(false, true, "marquee.behavior = 'invalid' should throw");
|
||||
} catch(e) {
|
||||
ok(true, "Exception was raised");
|
||||
}
|
||||
is(x.behavior, "alternate", "Wrong behavior value");
|
||||
x.behavior = 'Slide';
|
||||
is(x.behavior, "slide", "Wrong behavior value");
|
||||
try {
|
||||
x.behavior = 'invalid';
|
||||
todo_is(false, true, "marquee.behavior = 'invalid' should throw");
|
||||
} catch(e) {
|
||||
ok(true, "Exception was raised");
|
||||
}
|
||||
is(x.behavior, "slide", "Wrong behavior value");
|
||||
|
||||
is(x.loop, -1, "Wrong loop value");
|
||||
x.setAttribute('loop', '1');
|
||||
is(x.loop, 1, "Wrong loop value");
|
||||
x.setAttribute('loop', 'invalid');
|
||||
todo_is(x.loop, -1, "Wrong loop value");
|
||||
x.setAttribute('loop', '1000');
|
||||
is(x.loop, 1000, "Wrong loop value");
|
||||
x.setAttribute('loop', '-1');
|
||||
is(x.loop, -1, "Wrong loop value");
|
||||
x.setAttribute('loop', '1000');
|
||||
is(x.loop, 1000, "Wrong loop value");
|
||||
x.removeAttribute('loop');
|
||||
is(x.loop, -1, "Wrong loop value");
|
||||
|
||||
x.loop = 1;
|
||||
is(x.loop, 1, "Wrong loop value");
|
||||
try {
|
||||
x.loop = -2;
|
||||
todo_is(false, true, "marquee.loop = -2 should throw");
|
||||
} catch(e) {
|
||||
ok(true, "Exception was raised");
|
||||
}
|
||||
todo_is(x.loop, 1, "Wrong loop value");
|
||||
try {
|
||||
x.loop = 'invalid';
|
||||
todo_is(false, true, ".loop = 'invalid' should throw");
|
||||
} catch(e) {
|
||||
ok(true, "Exception was raised");
|
||||
}
|
||||
todo_is(x.loop, 1, "Wrong loop value");
|
||||
try {
|
||||
x.loop = null;
|
||||
todo_is(false, true, "marquee.loop = null should throw");
|
||||
} catch(e) {
|
||||
ok(true, "Exception was raised");
|
||||
}
|
||||
todo_is(x.loop, 1, "Wrong loop value");
|
||||
x.loop = -1;
|
||||
is(x.loop, -1, "Wrong loop value");
|
||||
x.loop = '100';
|
||||
is(x.loop, 100, "Wrong loop value");
|
||||
|
||||
is(x.scrollAmount, 6, "Wrong scrollAmount value");
|
||||
x.setAttribute('scrollAmount', '1');
|
||||
is(x.scrollAmount, 1, "Wrong scrollAmount value");
|
||||
x.setAttribute('scrollAmount', 'invalid');
|
||||
todo_is(x.scrollAmount, 6, "Wrong scrollAmount value");
|
||||
x.setAttribute('scrollAmount', '1000');
|
||||
is(x.scrollAmount, 1000, "Wrong scrollAmount value");
|
||||
x.setAttribute('scrollAmount', '-1');
|
||||
is(x.scrollAmount, 1000, "Wrong scrollAmount value");
|
||||
x.setAttribute('scrollAmount', '999');
|
||||
is(x.scrollAmount, 999, "Wrong scrollAmount value");
|
||||
x.removeAttribute('scrollAmount');
|
||||
is(x.scrollAmount, 6, "Wrong scrollAmount value");
|
||||
|
||||
x.scrollAmount = 1;
|
||||
is(x.scrollAmount, 1, "Wrong scrollAmount value");
|
||||
try {
|
||||
x.scrollAmount = -2;
|
||||
todo_is(false, true, "marquee.scrollAmount = -2 should throw");
|
||||
} catch(e) {
|
||||
ok(true, "Exception was raised");
|
||||
}
|
||||
is(x.scrollAmount, 1, "Wrong scrollAmount value");
|
||||
x.scrollAmount = 'invalid';
|
||||
todo_is(x.scrollAmount, 0, "Wrong scrollAmount value");
|
||||
x.scrollAmount = 1;
|
||||
x.scrollAmount = null;
|
||||
todo_is(x.scrollAmount, 0, "Wrong scrollAmount value");
|
||||
x.scrollAmount = '2';
|
||||
is(x.scrollAmount, 2, "Wrong scrollAmount value");
|
||||
|
||||
|
||||
is(x.scrollDelay, 85, "Wrong scrollDelay value");
|
||||
x.setAttribute('scrollDelay', '1');
|
||||
is(x.scrollDelay, 1, "Wrong scrollDelay value");
|
||||
x.setAttribute('scrollDelay', 'invalid');
|
||||
todo_is(x.scrollDelay, 85, "Wrong scrollDelay value");
|
||||
x.setAttribute('scrollDelay', '70');
|
||||
is(x.scrollDelay, 70, "Wrong scrollDelay value");
|
||||
x.setAttribute('scrollDelay', '59');
|
||||
is(x.scrollDelay, 59, "Wrong scrollDelay value");
|
||||
x.setAttribute('scrollDelay', '1000');
|
||||
is(x.scrollDelay, 1000, "Wrong scrollDelay value");
|
||||
x.setAttribute('scrollDelay', '-1');
|
||||
is(x.scrollDelay, 1000, "Wrong scrollDelay value");
|
||||
x.removeAttribute('scrollDelay');
|
||||
is(x.scrollDelay, 85, "Wrong scrollDelay value");
|
||||
|
||||
x.scrollDelay = 100;
|
||||
is(x.scrollDelay, 100, "Wrong scrollDelay value");
|
||||
try {
|
||||
x.scrollDelay = -2;
|
||||
todo_is(false, true, "marquee.scrollDelay = -2 should throw");
|
||||
} catch(e) {
|
||||
ok(true, "Exception was raised");
|
||||
}
|
||||
is(x.scrollDelay, 100, "Wrong scrollDelay value");
|
||||
try {
|
||||
x.scrollDelay = 'invalid';
|
||||
todo_is(false, true, "marquee.scrollDelay = 'invalid' should throw");
|
||||
} catch(e) {
|
||||
ok(true, "Exception was raised");
|
||||
}
|
||||
is(x.scrollDelay, 100, "Wrong scrollDelay value");
|
||||
try {
|
||||
x.scrollDelay = null;
|
||||
todo_is(false, true, "marquee.scrollDelay = null should throw");
|
||||
} catch(e) {
|
||||
ok(true, "Exception was raised");
|
||||
}
|
||||
is(x.scrollDelay, 100, "Wrong scrollDelay value");
|
||||
try {
|
||||
x.scrollDelay = -1;
|
||||
todo_is(false, true, "marquee.scrollDelay = -1 should throw");
|
||||
} catch(e) {
|
||||
ok(true, "Exception was raised");
|
||||
}
|
||||
is(x.scrollDelay, 100, "Wrong scrollDelay value");
|
||||
x.scrollDelay = '50';
|
||||
is(x.scrollDelay, 50, "Wrong scrollDelay value");
|
||||
|
||||
is(x.trueSpeed, false, "Wrong trueSpeed value");
|
||||
x.setAttribute('trueSpeed', '1');
|
||||
is(x.trueSpeed, true, "Wrong trueSpeed value");
|
||||
x.setAttribute('trueSpeed', 'false');
|
||||
is(x.trueSpeed, true, "Wrong trueSpeed value");
|
||||
x.removeAttribute('trueSpeed');
|
||||
is(x.trueSpeed, false, "Wrong trueSpeed value");
|
||||
|
||||
x.trueSpeed = 1;
|
||||
is(x.trueSpeed, true, "Wrong trueSpeed value");
|
||||
x.trueSpeed = -2;
|
||||
is(x.trueSpeed, true, "Wrong trueSpeed value");
|
||||
x.trueSpeed = null;
|
||||
is(x.trueSpeed, false, "Wrong trueSpeed value");
|
||||
x.trueSpeed = '100';
|
||||
is(x.trueSpeed, true, "Wrong trueSpeed value");
|
||||
|
||||
todo_is(x.direction, "left", "Wrong direction value");
|
||||
x.setAttribute('direction', 'right');
|
||||
is(x.direction, "right", "Wrong direction value");
|
||||
x.setAttribute('direction', 'invalid');
|
||||
todo_is(x.direction, "left", "Wrong direction value");
|
||||
x.setAttribute('direction', 'RIGHT');
|
||||
todo_is(x.direction, "right", "Wrong direction value");
|
||||
x.removeAttribute('direction');
|
||||
todo_is(x.direction, "left", "Wrong direction value");
|
||||
|
||||
x.direction = 'right';
|
||||
is(x.direction, "right", "Wrong direction value");
|
||||
try {
|
||||
x.direction = 1;
|
||||
todo_is(false, true, "marquee.direction = 1 should throw");
|
||||
} catch(e) {
|
||||
ok(true, "Exception was raised");
|
||||
}
|
||||
todo_is(x.direction, "right", "Wrong direction value");
|
||||
try {
|
||||
x.direction = null;
|
||||
todo_is(false, true, "marquee.direction = null should throw");
|
||||
} catch(e) {
|
||||
ok(true, "Exception was raised");
|
||||
}
|
||||
todo_is(x.direction, "right", "Wrong direction value");
|
||||
SimpleTest.finish();
|
||||
}, 0);
|
||||
|
||||
</script>
|
||||
</pre>
|
||||
</body>
|
||||
</html>
|
|
@ -165,7 +165,6 @@
|
|||
|
||||
expectEvents(1, 0, function() {
|
||||
is(img.currentSrc, testPNG50, "Should have switched to testPNG50");
|
||||
Math.sin(90);
|
||||
|
||||
// Now add a source *also* wanting that DPI *just before* the
|
||||
// selected source. Properly re-running the algorithm should
|
||||
|
@ -231,7 +230,7 @@ Math.sin(90);
|
|||
is(img.currentSrc, testPNG100, "Should still have testPNG100");
|
||||
|
||||
// And a valid MQ
|
||||
source1.media = "(min-resolution: 3dppx)";
|
||||
source1.media = "(min-resolution: 1dppx)";
|
||||
expectEvents(1, 0, function() {
|
||||
// And a valid type...
|
||||
source1.type = "image/png";
|
||||
|
|
|
@ -319,6 +319,8 @@ public:
|
|||
nsCOMPtr<nsIRunnable> runnable =
|
||||
new RegistrationUpdateRunnable(mRegistration, true /* time check */);
|
||||
NS_DispatchToMainThread(runnable.forget());
|
||||
|
||||
ExtendableEventWorkerRunnable::PostRun(aCx, aWorkerPrivate, aRunResult);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -182,6 +182,7 @@ ServiceWorkerRegistrar::RegisterServiceWorker(
|
|||
bool found = false;
|
||||
for (uint32_t i = 0, len = mData.Length(); i < len; ++i) {
|
||||
if (Equivalent(aData, mData[i])) {
|
||||
mData[i] = aData;
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -610,9 +610,7 @@ private:
|
|||
WorkerRunnable::PostRun(aCx, aWorkerPrivate, aRunResult);
|
||||
|
||||
// Match the busy count increase from NotifyRunnable.
|
||||
if (!aWorkerPrivate->ModifyBusyCountFromWorker(aCx, false)) {
|
||||
JS_ReportPendingException(aCx);
|
||||
}
|
||||
aWorkerPrivate->ModifyBusyCountFromWorker(aCx, false);
|
||||
|
||||
aWorkerPrivate->CloseHandlerFinished();
|
||||
}
|
||||
|
|
|
@ -223,9 +223,7 @@ WorkerRunnable::PostRun(JSContext* aCx, WorkerPrivate* aWorkerPrivate,
|
|||
#endif
|
||||
|
||||
if (mBehavior == WorkerThreadModifyBusyCount) {
|
||||
if (!aWorkerPrivate->ModifyBusyCountFromWorker(aCx, false)) {
|
||||
aRunResult = false;
|
||||
}
|
||||
aWorkerPrivate->ModifyBusyCountFromWorker(aCx, false);
|
||||
}
|
||||
|
||||
if (!aRunResult) {
|
||||
|
@ -350,10 +348,44 @@ WorkerRunnable::Run()
|
|||
cx = jsapi.cx();
|
||||
}
|
||||
|
||||
// If we're not on the worker thread we'll either be in our parent's
|
||||
// compartment or the null compartment, so we need to enter our own.
|
||||
// Note that we can't assert anything about mWorkerPrivate->GetWrapper()
|
||||
// existing, since it may in fact have been GCed (and we may be one of the
|
||||
// runnables cleaning up the worker as a result).
|
||||
|
||||
// If we are on the parent thread and that thread is not the main thread,
|
||||
// then we must be a dedicated worker (because there are no
|
||||
// Shared/ServiceWorkers whose parent is itself a worker) and then we
|
||||
// definitely have a globalObject. If it _is_ the main thread, globalObject
|
||||
// can be null for workers started from JSMs or other non-window contexts,
|
||||
// sadly.
|
||||
MOZ_ASSERT_IF(!targetIsWorkerThread && !isMainThread,
|
||||
mWorkerPrivate->IsDedicatedWorker() && globalObject);
|
||||
|
||||
// If we're on the parent thread we might be in a null compartment in the
|
||||
// situation described above when globalObject is null. Make sure to enter
|
||||
// the compartment of the worker's reflector if there is one. There might
|
||||
// not be one if we're just starting to compile the script for this worker.
|
||||
Maybe<JSAutoCompartment> ac;
|
||||
if (!targetIsWorkerThread && mWorkerPrivate->GetWrapper()) {
|
||||
// If we're on the parent thread and have a reflector and a globalObject,
|
||||
// then the compartments of cx, globalObject, and the worker's reflector
|
||||
// should all match.
|
||||
MOZ_ASSERT_IF(globalObject,
|
||||
js::GetObjectCompartment(mWorkerPrivate->GetWrapper()) ==
|
||||
js::GetContextCompartment(cx));
|
||||
MOZ_ASSERT_IF(globalObject,
|
||||
js::GetObjectCompartment(mWorkerPrivate->GetWrapper()) ==
|
||||
js::GetObjectCompartment(globalObject->GetGlobalJSObject()));
|
||||
|
||||
// If we're on the parent thread and have a reflector, then our
|
||||
// JSContext had better be either in the null compartment (and hence
|
||||
// have no globalObject) or in the compartment of our reflector.
|
||||
MOZ_ASSERT(!js::GetContextCompartment(cx) ||
|
||||
js::GetObjectCompartment(mWorkerPrivate->GetWrapper()) ==
|
||||
js::GetContextCompartment(cx),
|
||||
"Must either be in the null compartment or in our reflector "
|
||||
"compartment");
|
||||
|
||||
ac.emplace(cx, mWorkerPrivate->GetWrapper());
|
||||
}
|
||||
|
||||
|
@ -610,6 +642,9 @@ bool
|
|||
WorkerSameThreadRunnable::PreDispatch(JSContext* aCx,
|
||||
WorkerPrivate* aWorkerPrivate)
|
||||
{
|
||||
// We don't call WorkerRunnable::PreDispatch, because we're using
|
||||
// WorkerThreadModifyBusyCount for mBehavior, and WorkerRunnable will assert
|
||||
// that PreDispatch is on the parent thread in that case.
|
||||
aWorkerPrivate->AssertIsOnWorkerThread();
|
||||
return true;
|
||||
}
|
||||
|
@ -619,6 +654,9 @@ WorkerSameThreadRunnable::PostDispatch(JSContext* aCx,
|
|||
WorkerPrivate* aWorkerPrivate,
|
||||
bool aDispatchResult)
|
||||
{
|
||||
// We don't call WorkerRunnable::PostDispatch, because we're using
|
||||
// WorkerThreadModifyBusyCount for mBehavior, and WorkerRunnable will assert
|
||||
// that PostDispatch is on the parent thread in that case.
|
||||
aWorkerPrivate->AssertIsOnWorkerThread();
|
||||
if (aDispatchResult) {
|
||||
DebugOnly<bool> willIncrement = aWorkerPrivate->ModifyBusyCountFromWorker(aCx, true);
|
||||
|
@ -627,21 +665,3 @@ WorkerSameThreadRunnable::PostDispatch(JSContext* aCx,
|
|||
MOZ_ASSERT(willIncrement);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
WorkerSameThreadRunnable::PostRun(JSContext* aCx, WorkerPrivate* aWorkerPrivate,
|
||||
bool aRunResult)
|
||||
{
|
||||
MOZ_ASSERT(aCx);
|
||||
MOZ_ASSERT(aWorkerPrivate);
|
||||
|
||||
aWorkerPrivate->AssertIsOnWorkerThread();
|
||||
|
||||
DebugOnly<bool> willDecrement = aWorkerPrivate->ModifyBusyCountFromWorker(aCx, false);
|
||||
MOZ_ASSERT(willDecrement);
|
||||
|
||||
if (!aRunResult) {
|
||||
JS_ReportPendingException(aCx);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -115,26 +115,45 @@ protected:
|
|||
// By default asserts that Dispatch() is being called on the right thread
|
||||
// (ParentThread if |mTarget| is WorkerThread, or WorkerThread otherwise).
|
||||
// Also increments the busy count of |mWorkerPrivate| if targeting the
|
||||
// WorkerThread.
|
||||
// WorkerThread. The JSContext passed in here is the one that was passed to
|
||||
// Dispatch().
|
||||
virtual bool
|
||||
PreDispatch(JSContext* aCx, WorkerPrivate* aWorkerPrivate);
|
||||
|
||||
// By default asserts that Dispatch() is being called on the right thread
|
||||
// (ParentThread if |mTarget| is WorkerThread, or WorkerThread otherwise).
|
||||
// Also reports any Dispatch() failures as an exception on |aCx|, and
|
||||
// busy count if targeting the WorkerThread and Dispatch() failed.
|
||||
// Also reports any Dispatch() failures as an exception on |aCx|, and busy
|
||||
// count if targeting the WorkerThread and Dispatch() failed. The JSContext
|
||||
// passed in here is the one that was passed to Dispatch().
|
||||
virtual void
|
||||
PostDispatch(JSContext* aCx, WorkerPrivate* aWorkerPrivate,
|
||||
bool aDispatchResult);
|
||||
|
||||
// Must be implemented by subclasses. Called on the target thread.
|
||||
// Must be implemented by subclasses. Called on the target thread. The return
|
||||
// value will be passed to PostRun(). The JSContext passed in here comes from
|
||||
// an AutoJSAPI (or AutoEntryScript) that we set up on the stack. If
|
||||
// mBehavior is ParentThreadUnchangedBusyCount, it is in the compartment of
|
||||
// mWorkerPrivate's reflector (i.e. the worker object in the parent thread),
|
||||
// unless that reflector is null, in which case it's in the compartment of the
|
||||
// parent global (which is the compartment reflector would have been in), or
|
||||
// in the null compartment if there is no parent global. For other mBehavior
|
||||
// values, we're running on the worker thread and aCx is in whatever
|
||||
// compartment GetCurrentThreadJSContext() was in when nsIRunnable::Run() got
|
||||
// called (XXXbz: Why is this a sane thing to be doing now that we have
|
||||
// multiple globals per worker???). If it wasn't in a compartment, aCx will
|
||||
// be in either the debugger global's compartment or the worker's global's
|
||||
// compartment depending on whether IsDebuggerRunnable() is true.
|
||||
virtual bool
|
||||
WorkerRun(JSContext* aCx, WorkerPrivate* aWorkerPrivate) = 0;
|
||||
|
||||
// By default asserts that Run() (and WorkerRun()) were called on the correct
|
||||
// thread. Any failures (false return from WorkerRun) are reported on |aCx|.
|
||||
// Also sends an asynchronous message to the ParentThread if the busy
|
||||
// count was previously modified in PreDispatch().
|
||||
// thread. Also sends an asynchronous message to the ParentThread if the
|
||||
// busy count was previously modified in PreDispatch().
|
||||
//
|
||||
// The aCx passed here is the same one as was passed to WorkerRun and is
|
||||
// still in the same compartment. If aRunResult is false, any failures on
|
||||
// aCx are reported. Otherwise failures are left to linger on the JSContext
|
||||
// and maim later code (XXXbz: Aiming to fix that in bug 1072144).
|
||||
virtual void
|
||||
PostRun(JSContext* aCx, WorkerPrivate* aWorkerPrivate, bool aRunResult);
|
||||
|
||||
|
@ -386,9 +405,8 @@ protected:
|
|||
PostDispatch(JSContext* aCx, WorkerPrivate* aWorkerPrivate,
|
||||
bool aDispatchResult) override;
|
||||
|
||||
virtual void
|
||||
PostRun(JSContext* aCx, WorkerPrivate* aWorkerPrivate,
|
||||
bool aRunResult) override;
|
||||
// We just delegate PostRun to WorkerRunnable, since it does exactly
|
||||
// what we want.
|
||||
};
|
||||
|
||||
// Base class for the runnable objects, which makes a synchronous call to
|
||||
|
|
|
@ -294,6 +294,8 @@ SuspendWorkersForWindow(nsPIDOMWindowInner* aWindow);
|
|||
void
|
||||
ResumeWorkersForWindow(nsPIDOMWindowInner* aWindow);
|
||||
|
||||
// A class that can be used with WorkerCrossThreadDispatcher to run a
|
||||
// bit of C++ code on the worker thread.
|
||||
class WorkerTask
|
||||
{
|
||||
protected:
|
||||
|
@ -306,6 +308,8 @@ protected:
|
|||
public:
|
||||
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(WorkerTask)
|
||||
|
||||
// The return value here has the same semantics as the return value
|
||||
// of WorkerRunnable::WorkerRun.
|
||||
virtual bool
|
||||
RunTask(JSContext* aCx) = 0;
|
||||
};
|
||||
|
|
|
@ -570,6 +570,15 @@ nsDocShellTreeOwner::GetDevicePixelsPerDesktopPixel(double* aScale)
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDocShellTreeOwner::SetPositionDesktopPix(int32_t aX, int32_t aY)
|
||||
{
|
||||
// Added to nsIBaseWindow in bug 1247335;
|
||||
// implement if a use-case is found.
|
||||
NS_ASSERTION(false, "implement me!");
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDocShellTreeOwner::SetPosition(int32_t aX, int32_t aY)
|
||||
{
|
||||
|
|
|
@ -1302,6 +1302,15 @@ nsWebBrowser::GetDevicePixelsPerDesktopPixel(double* aScale)
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsWebBrowser::SetPositionDesktopPix(int32_t aX, int32_t aY)
|
||||
{
|
||||
// Added to nsIBaseWindow in bug 1247335;
|
||||
// implement if a use-case is found.
|
||||
NS_ASSERTION(false, "implement me!");
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsWebBrowser::SetPosition(int32_t aX, int32_t aY)
|
||||
{
|
||||
|
|
|
@ -554,6 +554,8 @@ DrawTargetSkia::ShouldLCDRenderText(FontType aFontType, AntialiasMode aAntialias
|
|||
if (aAntialiasMode == AntialiasMode::DEFAULT) {
|
||||
switch (aFontType) {
|
||||
case FontType::MAC:
|
||||
case FontType::GDI:
|
||||
case FontType::DWRITE:
|
||||
return true;
|
||||
default:
|
||||
// TODO: Figure out what to do for the other platforms.
|
||||
|
|
|
@ -31,7 +31,6 @@
|
|||
#include "TextureGarbageBin.h"
|
||||
#include "gfx2DGlue.h"
|
||||
#include "gfxPrefs.h"
|
||||
#include "DriverCrashGuard.h"
|
||||
#include "mozilla/IntegerPrintfMacros.h"
|
||||
|
||||
#include "OGLShaderProgram.h" // for ShaderProgramType
|
||||
|
@ -476,11 +475,6 @@ GLContext::InitWithPrefix(const char *prefix, bool trygl)
|
|||
return true;
|
||||
}
|
||||
|
||||
GLContextCrashGuard crashGuard;
|
||||
if (crashGuard.Crashed()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
mWorkAroundDriverBugs = gfxPrefs::WorkAroundDriverBugs();
|
||||
|
||||
SymLoadStruct symbols[] = {
|
||||
|
|
|
@ -1117,7 +1117,8 @@ ContainerLayer::ContainerLayer(LayerManager* aManager, void* aImplData)
|
|||
mMayHaveReadbackChild(false),
|
||||
mChildrenChanged(false),
|
||||
mEventRegionsOverride(EventRegionsOverride::NoOverride),
|
||||
mVRDeviceID(0)
|
||||
mVRDeviceID(0),
|
||||
mInputFrameID(0)
|
||||
{
|
||||
MOZ_COUNT_CTOR(ContainerLayer);
|
||||
mContentFlags = 0; // Clear NO_TEXT, NO_TEXT_OVER_TRANSPARENT
|
||||
|
@ -1279,7 +1280,8 @@ ContainerLayer::FillSpecificAttributes(SpecificLayerAttributes& aAttrs)
|
|||
mInheritedXScale, mInheritedYScale,
|
||||
mPresShellResolution, mScaleToResolution,
|
||||
mEventRegionsOverride,
|
||||
mVRDeviceID);
|
||||
mVRDeviceID,
|
||||
mInputFrameID);
|
||||
}
|
||||
|
||||
bool
|
||||
|
@ -2146,7 +2148,7 @@ ContainerLayer::PrintInfo(std::stringstream& aStream, const char* aPrefix)
|
|||
aStream << " [force-ehr]";
|
||||
}
|
||||
if (mVRDeviceID) {
|
||||
aStream << nsPrintfCString(" [hmd=%lu]", mVRDeviceID).get();
|
||||
aStream << nsPrintfCString(" [hmd=%lu] [hmdframe=%l]", mVRDeviceID, mInputFrameID).get();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -2143,10 +2143,18 @@ public:
|
|||
*/
|
||||
void SetVRDeviceID(uint32_t aVRDeviceID) {
|
||||
mVRDeviceID = aVRDeviceID;
|
||||
Mutated();
|
||||
}
|
||||
uint32_t GetVRDeviceID() {
|
||||
return mVRDeviceID;
|
||||
}
|
||||
void SetInputFrameID(int32_t aInputFrameID) {
|
||||
mInputFrameID = aInputFrameID;
|
||||
Mutated();
|
||||
}
|
||||
int32_t GetInputFrameID() {
|
||||
return mInputFrameID;
|
||||
}
|
||||
|
||||
/**
|
||||
* Replace the current effective transform with the given one,
|
||||
|
@ -2223,6 +2231,7 @@ protected:
|
|||
bool mChildrenChanged;
|
||||
EventRegionsOverride mEventRegionsOverride;
|
||||
uint32_t mVRDeviceID;
|
||||
int32_t mInputFrameID;
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
|
@ -153,6 +153,32 @@ BasicCompositor::CreateRenderTargetFromSource(const IntRect &aRect,
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
already_AddRefed<CompositingRenderTarget>
|
||||
BasicCompositor::CreateRenderTargetForWindow(const IntRect& aRect, SurfaceInitMode aInit, BufferMode aBufferMode)
|
||||
{
|
||||
if (aBufferMode != BufferMode::BUFFER_NONE) {
|
||||
return CreateRenderTarget(aRect, aInit);
|
||||
}
|
||||
|
||||
MOZ_ASSERT(aRect.width != 0 && aRect.height != 0, "Trying to create a render target of invalid size");
|
||||
|
||||
if (aRect.width * aRect.height == 0) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
MOZ_ASSERT(mDrawTarget);
|
||||
|
||||
// Adjust bounds rect to account for new origin at (0, 0).
|
||||
IntRect rect(0, 0, aRect.XMost(), aRect.YMost());
|
||||
RefPtr<BasicCompositingRenderTarget> rt = new BasicCompositingRenderTarget(mDrawTarget, rect);
|
||||
|
||||
if (aInit == INIT_MODE_CLEAR) {
|
||||
mDrawTarget->ClearRect(gfx::Rect(aRect));
|
||||
}
|
||||
|
||||
return rt.forget();
|
||||
}
|
||||
|
||||
already_AddRefed<DataTextureSource>
|
||||
BasicCompositor::CreateDataTextureSource(TextureFlags aFlags)
|
||||
{
|
||||
|
@ -557,13 +583,14 @@ BasicCompositor::BeginFrame(const nsIntRegion& aInvalidRegion,
|
|||
*aRenderBoundsOut = Rect();
|
||||
}
|
||||
|
||||
BufferMode bufferMode = BufferMode::BUFFERED;
|
||||
if (mTarget) {
|
||||
// If we have a copy target, then we don't have a widget-provided mDrawTarget (currently). Use a dummy
|
||||
// placeholder so that CreateRenderTarget() works.
|
||||
mDrawTarget = gfxPlatform::GetPlatform()->ScreenReferenceDrawTarget();
|
||||
} else {
|
||||
// StartRemoteDrawingInRegion can mutate mInvalidRegion.
|
||||
mDrawTarget = mWidget->StartRemoteDrawingInRegion(mInvalidRegion);
|
||||
mDrawTarget = mWidget->StartRemoteDrawingInRegion(mInvalidRegion, &bufferMode);
|
||||
if (!mDrawTarget) {
|
||||
return;
|
||||
}
|
||||
|
@ -581,7 +608,7 @@ BasicCompositor::BeginFrame(const nsIntRegion& aInvalidRegion,
|
|||
// Setup an intermediate render target to buffer all compositing. We will
|
||||
// copy this into mDrawTarget (the widget), and/or mTarget in EndFrame()
|
||||
RefPtr<CompositingRenderTarget> target =
|
||||
CreateRenderTarget(mInvalidRect.ToUnknownRect(), INIT_MODE_CLEAR);
|
||||
CreateRenderTargetForWindow(mInvalidRect.ToUnknownRect(), INIT_MODE_CLEAR, bufferMode);
|
||||
if (!target) {
|
||||
if (!mTarget) {
|
||||
mWidget->EndRemoteDrawingInRegion(mDrawTarget, mInvalidRegion);
|
||||
|
@ -592,8 +619,7 @@ BasicCompositor::BeginFrame(const nsIntRegion& aInvalidRegion,
|
|||
|
||||
// We only allocate a surface sized to the invalidated region, so we need to
|
||||
// translate future coordinates.
|
||||
mRenderTarget->mDrawTarget->SetTransform(Matrix::Translation(-mInvalidRect.x,
|
||||
-mInvalidRect.y));
|
||||
mRenderTarget->mDrawTarget->SetTransform(Matrix::Translation(-mRenderTarget->GetOrigin()));
|
||||
|
||||
gfxUtils::ClipToRegion(mRenderTarget->mDrawTarget,
|
||||
mInvalidRegion.ToUnknownRegion());
|
||||
|
@ -631,6 +657,7 @@ BasicCompositor::EndFrame()
|
|||
// Pop aInvalidregion
|
||||
mRenderTarget->mDrawTarget->PopClip();
|
||||
|
||||
if (mTarget || mRenderTarget->mDrawTarget != mDrawTarget) {
|
||||
// Note: Most platforms require us to buffer drawing to the widget surface.
|
||||
// That's why we don't draw to mDrawTarget directly.
|
||||
RefPtr<SourceSurface> source = mRenderTarget->mDrawTarget->Snapshot();
|
||||
|
@ -644,9 +671,11 @@ BasicCompositor::EndFrame()
|
|||
for (auto iter = mInvalidRegion.RectIter(); !iter.Done(); iter.Next()) {
|
||||
const LayoutDeviceIntRect& r = iter.Get();
|
||||
dest->CopySurface(source,
|
||||
IntRect(r.x - mInvalidRect.x, r.y - mInvalidRect.y, r.width, r.height),
|
||||
IntPoint(r.x - offset.x, r.y - offset.y));
|
||||
IntRect(r.x, r.y, r.width, r.height) - mRenderTarget->GetOrigin(),
|
||||
IntPoint(r.x, r.y) - offset);
|
||||
}
|
||||
}
|
||||
|
||||
if (!mTarget) {
|
||||
mWidget->EndRemoteDrawingInRegion(mDrawTarget, mInvalidRegion);
|
||||
}
|
||||
|
|
|
@ -62,6 +62,11 @@ public:
|
|||
const CompositingRenderTarget *aSource,
|
||||
const gfx::IntPoint &aSourcePoint) override;
|
||||
|
||||
virtual already_AddRefed<CompositingRenderTarget>
|
||||
CreateRenderTargetForWindow(const gfx::IntRect& aRect,
|
||||
SurfaceInitMode aInit,
|
||||
BufferMode aBufferMode);
|
||||
|
||||
virtual already_AddRefed<DataTextureSource>
|
||||
CreateDataTextureSource(TextureFlags aFlags = TextureFlags::NO_FLAGS) override;
|
||||
|
||||
|
|
|
@ -25,6 +25,7 @@
|
|||
#include "nsDebug.h" // for printf_stderr, NS_ASSERTION
|
||||
#include "nsXULAppAPI.h" // for XRE_GetProcessType, etc
|
||||
#include "TextureClientSharedSurface.h"
|
||||
#include "VRManagerChild.h"
|
||||
|
||||
using namespace mozilla::gfx;
|
||||
using namespace mozilla::gl;
|
||||
|
@ -125,6 +126,7 @@ CanvasClient2D::Update(gfx::IntSize aSize, ClientCanvasLayer* aLayer)
|
|||
t->mTextureClient = mBuffer;
|
||||
t->mPictureRect = nsIntRect(nsIntPoint(0, 0), mBuffer->GetSize());
|
||||
t->mFrameID = mFrameID;
|
||||
t->mInputFrameID = VRManagerChild::Get()->GetInputFrameID();
|
||||
GetForwarder()->UseTextures(this, textures);
|
||||
mBuffer->SyncWithObject(GetForwarder()->GetSyncObject());
|
||||
}
|
||||
|
@ -481,6 +483,11 @@ CanvasClientSharedSurface::Updated()
|
|||
t->mTextureClient = mFront;
|
||||
t->mPictureRect = nsIntRect(nsIntPoint(0, 0), mFront->GetSize());
|
||||
t->mFrameID = mFrameID;
|
||||
// XXX TODO - This reference to VRManagerChild will be moved with the
|
||||
// implementation of the WebVR 1.0 API, which will enable
|
||||
// the inputFrameID to be passed through Javascript with
|
||||
// the new VRDisplay API.
|
||||
t->mInputFrameID = VRManagerChild::Get()->GetInputFrameID();
|
||||
forwarder->UseTextures(this, textures);
|
||||
}
|
||||
|
||||
|
|
|
@ -194,6 +194,7 @@ public:
|
|||
gfx::IntRect mPictureRect;
|
||||
int32_t mFrameID;
|
||||
int32_t mProducerID;
|
||||
int32_t mInputFrameID;
|
||||
};
|
||||
virtual void UseTextureHost(const nsTArray<TimedTexture>& aTextures);
|
||||
virtual void UseComponentAlphaTextures(TextureHost* aTextureOnBlack,
|
||||
|
@ -235,6 +236,8 @@ public:
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
virtual int32_t GetLastInputFrameID() const { return -1; }
|
||||
|
||||
protected:
|
||||
TextureInfo mTextureInfo;
|
||||
uint64_t mAsyncID;
|
||||
|
|
|
@ -139,8 +139,11 @@ template<class ContainerT> void
|
|||
ContainerRenderVR(ContainerT* aContainer,
|
||||
LayerManagerComposite* aManager,
|
||||
const gfx::IntRect& aClipRect,
|
||||
RefPtr<gfx::VRHMDInfo> aHMD)
|
||||
RefPtr<gfx::VRHMDInfo> aHMD,
|
||||
int32_t aInputFrameID)
|
||||
{
|
||||
int32_t inputFrameID = -1;
|
||||
|
||||
RefPtr<CompositingRenderTarget> surface;
|
||||
|
||||
Compositor* compositor = aManager->GetCompositor();
|
||||
|
@ -265,6 +268,14 @@ ContainerRenderVR(ContainerT* aContainer,
|
|||
surfaceRect.width, surfaceRect.height));
|
||||
layerToRender->RenderLayer(surfaceRect);
|
||||
|
||||
CompositableHost *ch = layerToRender->GetCompositableHost();
|
||||
if (ch) {
|
||||
int32_t compositableInputFrameID = ch->GetLastInputFrameID();
|
||||
if (compositableInputFrameID != -1) {
|
||||
inputFrameID = compositableInputFrameID;
|
||||
}
|
||||
}
|
||||
|
||||
if (restoreTransform) {
|
||||
layer->ReplaceEffectiveTransform(childTransform);
|
||||
}
|
||||
|
@ -282,7 +293,7 @@ ContainerRenderVR(ContainerT* aContainer,
|
|||
compositor->SetRenderTarget(previousTarget);
|
||||
|
||||
if (vrRendering) {
|
||||
vrRendering->SubmitFrame(aContainer->mVRRenderTargetSet);
|
||||
vrRendering->SubmitFrame(aContainer->mVRRenderTargetSet, inputFrameID);
|
||||
DUMP("<<< ContainerRenderVR [used vrRendering] [%p]\n", aContainer);
|
||||
if (!gfxPrefs::VRMirrorTextures()) {
|
||||
return;
|
||||
|
@ -696,7 +707,7 @@ ContainerRender(ContainerT* aContainer,
|
|||
|
||||
RefPtr<gfx::VRHMDInfo> hmdInfo = gfx::VRManager::Get()->GetDevice(aContainer->GetVRDeviceID());
|
||||
if (hmdInfo && hmdInfo->GetConfiguration().IsValid()) {
|
||||
ContainerRenderVR(aContainer, aManager, aClipRect, hmdInfo);
|
||||
ContainerRenderVR(aContainer, aManager, aClipRect, hmdInfo, aContainer->GetInputFrameID());
|
||||
aContainer->mPrepared = nullptr;
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -32,6 +32,7 @@ ImageHost::ImageHost(const TextureInfo& aTextureInfo)
|
|||
, mImageContainer(nullptr)
|
||||
, mLastFrameID(-1)
|
||||
, mLastProducerID(-1)
|
||||
, mLastInputFrameID(-1)
|
||||
, mBias(BIAS_NONE)
|
||||
, mLocked(false)
|
||||
{}
|
||||
|
@ -84,6 +85,7 @@ ImageHost::UseTextureHost(const nsTArray<TimedTexture>& aTextures)
|
|||
img.mPictureRect = t.mPictureRect;
|
||||
img.mFrameID = t.mFrameID;
|
||||
img.mProducerID = t.mProducerID;
|
||||
img.mInputFrameID = t.mInputFrameID;
|
||||
}
|
||||
// Recycle any leftover mTextureSources and call PrepareTextureSource on all
|
||||
// images.
|
||||
|
@ -357,6 +359,7 @@ ImageHost::Composite(LayerComposite* aLayer,
|
|||
}
|
||||
mLastFrameID = img->mFrameID;
|
||||
mLastProducerID = img->mProducerID;
|
||||
mLastInputFrameID = img->mInputFrameID;
|
||||
}
|
||||
aEffectChain.mPrimaryEffect = effect;
|
||||
gfx::Rect pictureRect(0, 0, img->mPictureRect.width, img->mPictureRect.height);
|
||||
|
|
|
@ -100,6 +100,7 @@ public:
|
|||
|
||||
int32_t GetLastFrameID() const { return mLastFrameID; }
|
||||
int32_t GetLastProducerID() const { return mLastProducerID; }
|
||||
virtual int32_t GetLastInputFrameID() const override { return mLastInputFrameID; }
|
||||
|
||||
enum Bias {
|
||||
// Don't apply bias to frame times
|
||||
|
@ -118,6 +119,7 @@ protected:
|
|||
gfx::IntRect mPictureRect;
|
||||
int32_t mFrameID;
|
||||
int32_t mProducerID;
|
||||
int32_t mInputFrameID;
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -135,6 +137,7 @@ protected:
|
|||
ImageContainerParent* mImageContainer;
|
||||
int32_t mLastFrameID;
|
||||
int32_t mLastProducerID;
|
||||
int32_t mLastInputFrameID;
|
||||
/**
|
||||
* Bias to apply to the next frame.
|
||||
*/
|
||||
|
|
Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше
Загрузка…
Ссылка в новой задаче