зеркало из https://github.com/mozilla/gecko-dev.git
Merge inbound to central, a=merge
MozReview-Commit-ID: ADcSE67n1t8
This commit is contained in:
Коммит
0a2f84202b
|
@ -2082,7 +2082,7 @@ Element::DispatchClickEvent(nsPresContext* aPresContext,
|
|||
NS_PRECONDITION(aStatus, "Null out param?");
|
||||
|
||||
WidgetMouseEvent event(aSourceEvent->IsTrusted(), eMouseClick,
|
||||
aSourceEvent->widget, WidgetMouseEvent::eReal);
|
||||
aSourceEvent->mWidget, WidgetMouseEvent::eReal);
|
||||
event.refPoint = aSourceEvent->refPoint;
|
||||
uint32_t clickCount = 1;
|
||||
float pressure = 0;
|
||||
|
|
|
@ -707,8 +707,7 @@ WriteBlob(JSStructuredCloneWriter* aWriter,
|
|||
}
|
||||
|
||||
// A directory is serialized as:
|
||||
// - pair of ints: SCTAG_DOM_DIRECTORY, 0
|
||||
// - pair of ints: type (eDOMRootDirectory/eDOMNotRootDirectory) - path length
|
||||
// - pair of ints: SCTAG_DOM_DIRECTORY, path length
|
||||
// - path as string
|
||||
bool
|
||||
WriteDirectory(JSStructuredCloneWriter* aWriter,
|
||||
|
@ -721,36 +720,25 @@ WriteDirectory(JSStructuredCloneWriter* aWriter,
|
|||
aDirectory->GetFullRealPath(path);
|
||||
|
||||
size_t charSize = sizeof(nsString::char_type);
|
||||
return JS_WriteUint32Pair(aWriter, SCTAG_DOM_DIRECTORY, 0) &&
|
||||
JS_WriteUint32Pair(aWriter, (uint32_t)aDirectory->Type(),
|
||||
path.Length()) &&
|
||||
return JS_WriteUint32Pair(aWriter, SCTAG_DOM_DIRECTORY, path.Length()) &&
|
||||
JS_WriteBytes(aWriter, path.get(), path.Length() * charSize);
|
||||
}
|
||||
|
||||
JSObject*
|
||||
ReadDirectory(JSContext* aCx,
|
||||
JSStructuredCloneReader* aReader,
|
||||
uint32_t aZero,
|
||||
uint32_t aPathLength,
|
||||
StructuredCloneHolder* aHolder)
|
||||
{
|
||||
MOZ_ASSERT(aCx);
|
||||
MOZ_ASSERT(aReader);
|
||||
MOZ_ASSERT(aHolder);
|
||||
MOZ_ASSERT(aZero == 0);
|
||||
|
||||
uint32_t directoryType, lengthOfString;
|
||||
if (!JS_ReadUint32Pair(aReader, &directoryType, &lengthOfString)) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
MOZ_ASSERT(directoryType == Directory::eDOMRootDirectory ||
|
||||
directoryType == Directory::eNotDOMRootDirectory);
|
||||
|
||||
nsAutoString path;
|
||||
path.SetLength(lengthOfString);
|
||||
path.SetLength(aPathLength);
|
||||
size_t charSize = sizeof(nsString::char_type);
|
||||
if (!JS_ReadBytes(aReader, (void*) path.BeginWriting(),
|
||||
lengthOfString * charSize)) {
|
||||
aPathLength * charSize)) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
@ -769,8 +757,7 @@ ReadDirectory(JSContext* aCx,
|
|||
JS::Rooted<JS::Value> val(aCx);
|
||||
{
|
||||
RefPtr<Directory> directory =
|
||||
Directory::Create(aHolder->ParentDuringRead(), file,
|
||||
(Directory::DirectoryType) directoryType);
|
||||
Directory::Create(aHolder->ParentDuringRead(), file);
|
||||
|
||||
if (!ToJSValue(aCx, directory, &val)) {
|
||||
return nullptr;
|
||||
|
|
|
@ -7798,7 +7798,6 @@ nsContentUtils::SendMouseEvent(nsCOMPtr<nsIPresShell> aPresShell,
|
|||
event.mModifiers = GetWidgetModifiers(aModifiers);
|
||||
event.button = aButton;
|
||||
event.buttons = GetButtonsFlagForButton(aButton);
|
||||
event.widget = widget;
|
||||
event.pressure = aPressure;
|
||||
event.inputSource = aInputSourceArg;
|
||||
event.clickCount = aClickCount;
|
||||
|
|
|
@ -672,7 +672,6 @@ nsDOMWindowUtils::SendPointerEventCommon(const nsAString& aType,
|
|||
event.mModifiers = nsContentUtils::GetWidgetModifiers(aModifiers);
|
||||
event.button = aButton;
|
||||
event.buttons = nsContentUtils::GetButtonsFlagForButton(aButton);
|
||||
event.widget = widget;
|
||||
event.pressure = aPressure;
|
||||
event.inputSource = aInputSourceArg;
|
||||
event.pointerId = aPointerId;
|
||||
|
@ -805,7 +804,6 @@ nsDOMWindowUtils::SendWheelEvent(float aX,
|
|||
(aOptions & WHEEL_EVENT_CUSTOMIZED_BY_USER_PREFS) != 0;
|
||||
wheelEvent.mLineOrPageDeltaX = aLineOrPageDeltaX;
|
||||
wheelEvent.mLineOrPageDeltaY = aLineOrPageDeltaY;
|
||||
wheelEvent.widget = widget;
|
||||
|
||||
wheelEvent.mTime = PR_Now() / 1000;
|
||||
|
||||
|
@ -938,7 +936,6 @@ nsDOMWindowUtils::SendTouchEventCommon(const nsAString& aType,
|
|||
}
|
||||
WidgetTouchEvent event(true, msg, widget);
|
||||
event.mModifiers = nsContentUtils::GetWidgetModifiers(aModifiers);
|
||||
event.widget = widget;
|
||||
event.mTime = PR_Now();
|
||||
|
||||
nsPresContext* presContext = GetPresContext();
|
||||
|
|
|
@ -1534,9 +1534,9 @@ ContentEventHandler::OnQueryCharacterAtPoint(WidgetQueryContentEvent* aEvent)
|
|||
|
||||
// The root frame's widget might be different, e.g., the event was fired on
|
||||
// a popup but the rootFrame is the document root.
|
||||
if (rootWidget != aEvent->widget) {
|
||||
NS_PRECONDITION(aEvent->widget, "The event must have the widget");
|
||||
nsView* view = nsView::GetViewFor(aEvent->widget);
|
||||
if (rootWidget != aEvent->mWidget) {
|
||||
NS_PRECONDITION(aEvent->mWidget, "The event must have the widget");
|
||||
nsView* view = nsView::GetViewFor(aEvent->mWidget);
|
||||
NS_ENSURE_TRUE(view, NS_ERROR_FAILURE);
|
||||
rootFrame = view->GetFrame();
|
||||
NS_ENSURE_TRUE(rootFrame, NS_ERROR_FAILURE);
|
||||
|
@ -1548,8 +1548,8 @@ ContentEventHandler::OnQueryCharacterAtPoint(WidgetQueryContentEvent* aEvent)
|
|||
rootWidget);
|
||||
eventOnRoot.mUseNativeLineBreak = aEvent->mUseNativeLineBreak;
|
||||
eventOnRoot.refPoint = aEvent->refPoint;
|
||||
if (rootWidget != aEvent->widget) {
|
||||
eventOnRoot.refPoint += aEvent->widget->WidgetToScreenOffset() -
|
||||
if (rootWidget != aEvent->mWidget) {
|
||||
eventOnRoot.refPoint += aEvent->mWidget->WidgetToScreenOffset() -
|
||||
rootWidget->WidgetToScreenOffset();
|
||||
}
|
||||
nsPoint ptInRoot =
|
||||
|
@ -1611,7 +1611,7 @@ ContentEventHandler::OnQueryCharacterAtPoint(WidgetQueryContentEvent* aEvent)
|
|||
return rv;
|
||||
}
|
||||
|
||||
WidgetQueryContentEvent textRect(true, eQueryTextRect, aEvent->widget);
|
||||
WidgetQueryContentEvent textRect(true, eQueryTextRect, aEvent->mWidget);
|
||||
textRect.InitForQueryTextRect(offset, 1, aEvent->mUseNativeLineBreak);
|
||||
rv = OnQueryTextRect(&textRect);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
@ -1637,14 +1637,15 @@ ContentEventHandler::OnQueryDOMWidgetHittest(WidgetQueryContentEvent* aEvent)
|
|||
aEvent->mSucceeded = false;
|
||||
aEvent->mReply.mWidgetIsHit = false;
|
||||
|
||||
NS_ENSURE_TRUE(aEvent->widget, NS_ERROR_FAILURE);
|
||||
NS_ENSURE_TRUE(aEvent->mWidget, NS_ERROR_FAILURE);
|
||||
|
||||
nsIDocument* doc = mPresShell->GetDocument();
|
||||
NS_ENSURE_TRUE(doc, NS_ERROR_FAILURE);
|
||||
nsIFrame* docFrame = mPresShell->GetRootFrame();
|
||||
NS_ENSURE_TRUE(docFrame, NS_ERROR_FAILURE);
|
||||
|
||||
LayoutDeviceIntPoint eventLoc = aEvent->refPoint + aEvent->widget->WidgetToScreenOffset();
|
||||
LayoutDeviceIntPoint eventLoc =
|
||||
aEvent->refPoint + aEvent->mWidget->WidgetToScreenOffset();
|
||||
nsIntRect docFrameRect = docFrame->GetScreenRect(); // Returns CSS pixels
|
||||
CSSIntPoint eventLocCSS(
|
||||
mPresContext->DevPixelsToIntCSSPixels(eventLoc.x) - docFrameRect.x,
|
||||
|
@ -1661,7 +1662,7 @@ ContentEventHandler::OnQueryDOMWidgetHittest(WidgetQueryContentEvent* aEvent)
|
|||
} else if (targetFrame) {
|
||||
targetWidget = targetFrame->GetNearestWidget();
|
||||
}
|
||||
if (aEvent->widget == targetWidget) {
|
||||
if (aEvent->mWidget == targetWidget) {
|
||||
aEvent->mReply.mWidgetIsHit = true;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -905,7 +905,7 @@ Event::GetScreenCoords(nsPresContext* aPresContext,
|
|||
// Doing a straight conversion from LayoutDeviceIntPoint to CSSIntPoint
|
||||
// seem incorrect, but it is needed to maintain legacy functionality.
|
||||
WidgetGUIEvent* guiEvent = aEvent->AsGUIEvent();
|
||||
if (!aPresContext || !(guiEvent && guiEvent->widget)) {
|
||||
if (!aPresContext || !(guiEvent && guiEvent->mWidget)) {
|
||||
return CSSIntPoint(aPoint.x, aPoint.y);
|
||||
}
|
||||
|
||||
|
@ -916,7 +916,7 @@ Event::GetScreenCoords(nsPresContext* aPresContext,
|
|||
pt = pt.RemoveResolution(nsLayoutUtils::GetCurrentAPZResolutionScale(ps));
|
||||
}
|
||||
|
||||
pt += LayoutDevicePixel::ToAppUnits(guiEvent->widget->WidgetToScreenOffset(),
|
||||
pt += LayoutDevicePixel::ToAppUnits(guiEvent->mWidget->WidgetToScreenOffset(),
|
||||
aPresContext->DeviceContext()->AppUnitsPerDevPixelAtUnitFullZoom());
|
||||
|
||||
return CSSPixel::FromAppUnitsRounded(pt);
|
||||
|
@ -964,7 +964,7 @@ Event::GetClientCoords(nsPresContext* aPresContext,
|
|||
aEvent->mClass != ePointerEventClass &&
|
||||
aEvent->mClass != eSimpleGestureEventClass) ||
|
||||
!aPresContext ||
|
||||
!aEvent->AsGUIEvent()->widget) {
|
||||
!aEvent->AsGUIEvent()->mWidget) {
|
||||
return aDefaultPoint;
|
||||
}
|
||||
|
||||
|
|
|
@ -822,7 +822,7 @@ EventStateManager::PreHandleEvent(nsPresContext* aPresContext,
|
|||
// composition event.
|
||||
WidgetCompositionEvent* compositionEvent = aEvent->AsCompositionEvent();
|
||||
WidgetQueryContentEvent selectedText(true, eQuerySelectedText,
|
||||
compositionEvent->widget);
|
||||
compositionEvent->mWidget);
|
||||
HandleQueryContentEvent(&selectedText);
|
||||
NS_ASSERTION(selectedText.mSucceeded, "Failed to get selected text");
|
||||
compositionEvent->mData = selectedText.mReply.mString;
|
||||
|
@ -1584,12 +1584,14 @@ EventStateManager::BeginTrackingDragGesture(nsPresContext* aPresContext,
|
|||
WidgetMouseEvent* inDownEvent,
|
||||
nsIFrame* inDownFrame)
|
||||
{
|
||||
if (!inDownEvent->widget)
|
||||
if (!inDownEvent->mWidget) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Note that |inDownEvent| could be either a mouse down event or a
|
||||
// synthesized mouse move event.
|
||||
mGestureDownPoint = inDownEvent->refPoint + inDownEvent->widget->WidgetToScreenOffset();
|
||||
mGestureDownPoint =
|
||||
inDownEvent->refPoint + inDownEvent->mWidget->WidgetToScreenOffset();
|
||||
|
||||
if (inDownFrame) {
|
||||
inDownFrame->GetContentForEvent(inDownEvent,
|
||||
|
@ -1632,13 +1634,14 @@ EventStateManager::StopTrackingDragGesture()
|
|||
void
|
||||
EventStateManager::FillInEventFromGestureDown(WidgetMouseEvent* aEvent)
|
||||
{
|
||||
NS_ASSERTION(aEvent->widget == mCurrentTarget->GetNearestWidget(),
|
||||
NS_ASSERTION(aEvent->mWidget == mCurrentTarget->GetNearestWidget(),
|
||||
"Incorrect widget in event");
|
||||
|
||||
// Set the coordinates in the new event to the coordinates of
|
||||
// the old event, adjusted for the fact that the widget might be
|
||||
// different
|
||||
aEvent->refPoint = mGestureDownPoint - aEvent->widget->WidgetToScreenOffset();
|
||||
aEvent->refPoint =
|
||||
mGestureDownPoint - aEvent->mWidget->WidgetToScreenOffset();
|
||||
aEvent->mModifiers = mGestureModifiers;
|
||||
aEvent->buttons = mGestureDownButtons;
|
||||
}
|
||||
|
@ -1694,7 +1697,8 @@ EventStateManager::GenerateDragGesture(nsPresContext* aPresContext,
|
|||
}
|
||||
|
||||
// fire drag gesture if mouse has moved enough
|
||||
LayoutDeviceIntPoint pt = aEvent->refPoint + aEvent->widget->WidgetToScreenOffset();
|
||||
LayoutDeviceIntPoint pt =
|
||||
aEvent->refPoint + aEvent->mWidget->WidgetToScreenOffset();
|
||||
LayoutDeviceIntPoint distance = pt - mGestureDownPoint;
|
||||
if (Abs(distance.x) > AssertedCast<uint32_t>(pixelThresholdX) ||
|
||||
Abs(distance.y) > AssertedCast<uint32_t>(pixelThresholdY)) {
|
||||
|
@ -2294,11 +2298,10 @@ EventStateManager::SendLineScrollEvent(nsIFrame* aTargetFrame,
|
|||
}
|
||||
|
||||
WidgetMouseScrollEvent event(aEvent->IsTrusted(),
|
||||
eLegacyMouseLineOrPageScroll, aEvent->widget);
|
||||
eLegacyMouseLineOrPageScroll, aEvent->mWidget);
|
||||
event.mFlags.mDefaultPrevented = aState.mDefaultPrevented;
|
||||
event.mFlags.mDefaultPreventedByContent = aState.mDefaultPreventedByContent;
|
||||
event.refPoint = aEvent->refPoint;
|
||||
event.widget = aEvent->widget;
|
||||
event.mTime = aEvent->mTime;
|
||||
event.mTimeStamp = aEvent->mTimeStamp;
|
||||
event.mModifiers = aEvent->mModifiers;
|
||||
|
@ -2334,11 +2337,10 @@ EventStateManager::SendPixelScrollEvent(nsIFrame* aTargetFrame,
|
|||
}
|
||||
|
||||
WidgetMouseScrollEvent event(aEvent->IsTrusted(),
|
||||
eLegacyMousePixelScroll, aEvent->widget);
|
||||
eLegacyMousePixelScroll, aEvent->mWidget);
|
||||
event.mFlags.mDefaultPrevented = aState.mDefaultPrevented;
|
||||
event.mFlags.mDefaultPreventedByContent = aState.mDefaultPreventedByContent;
|
||||
event.refPoint = aEvent->refPoint;
|
||||
event.widget = aEvent->widget;
|
||||
event.mTime = aEvent->mTime;
|
||||
event.mTimeStamp = aEvent->mTimeStamp;
|
||||
event.mModifiers = aEvent->mModifiers;
|
||||
|
@ -3423,8 +3425,8 @@ EventStateManager::PostHandleEvent(nsPresContext* aPresContext,
|
|||
|
||||
WidgetMouseEvent* mouseEvent = aEvent->AsMouseEvent();
|
||||
event.refPoint = mouseEvent->refPoint;
|
||||
if (mouseEvent->widget) {
|
||||
event.refPoint += mouseEvent->widget->WidgetToScreenOffset();
|
||||
if (mouseEvent->mWidget) {
|
||||
event.refPoint += mouseEvent->mWidget->WidgetToScreenOffset();
|
||||
}
|
||||
event.refPoint -= widget->WidgetToScreenOffset();
|
||||
event.mModifiers = mouseEvent->mModifiers;
|
||||
|
@ -3846,7 +3848,7 @@ CreateMouseOrPointerWidgetEvent(WidgetMouseEvent* aMouseEvent,
|
|||
nsAutoPtr<WidgetPointerEvent> newPointerEvent;
|
||||
newPointerEvent =
|
||||
new WidgetPointerEvent(aMouseEvent->IsTrusted(), aMessage,
|
||||
aMouseEvent->widget);
|
||||
aMouseEvent->mWidget);
|
||||
newPointerEvent->isPrimary = sourcePointer->isPrimary;
|
||||
newPointerEvent->pointerId = sourcePointer->pointerId;
|
||||
newPointerEvent->width = sourcePointer->width;
|
||||
|
@ -3860,7 +3862,7 @@ CreateMouseOrPointerWidgetEvent(WidgetMouseEvent* aMouseEvent,
|
|||
} else {
|
||||
aNewEvent =
|
||||
new WidgetMouseEvent(aMouseEvent->IsTrusted(), aMessage,
|
||||
aMouseEvent->widget, WidgetMouseEvent::eReal);
|
||||
aMouseEvent->mWidget, WidgetMouseEvent::eReal);
|
||||
aNewEvent->relatedTarget = aRelatedContent;
|
||||
}
|
||||
aNewEvent->refPoint = aMouseEvent->refPoint;
|
||||
|
@ -4205,7 +4207,7 @@ EventStateManager::GenerateMouseEnterExit(WidgetMouseEvent* aMouseEvent)
|
|||
// Mouse movement is reported on the MouseEvent.movement{X,Y} fields.
|
||||
// Movement is calculated in UIEvent::GetMovementPoint() as:
|
||||
// previous_mousemove_refPoint - current_mousemove_refPoint.
|
||||
if (sIsPointerLocked && aMouseEvent->widget) {
|
||||
if (sIsPointerLocked && aMouseEvent->mWidget) {
|
||||
// The pointer is locked. If the pointer is not located at the center of
|
||||
// the window, dispatch a synthetic mousemove to return the pointer there.
|
||||
// Doing this between "real" pointer moves gives the impression that the
|
||||
|
@ -4213,7 +4215,7 @@ EventStateManager::GenerateMouseEnterExit(WidgetMouseEvent* aMouseEvent)
|
|||
// boundary. We cancel the synthetic event so that we don't end up
|
||||
// dispatching the centering move event to content.
|
||||
LayoutDeviceIntPoint center =
|
||||
GetWindowClientRectCenter(aMouseEvent->widget);
|
||||
GetWindowClientRectCenter(aMouseEvent->mWidget);
|
||||
aMouseEvent->lastRefPoint = center;
|
||||
if (aMouseEvent->refPoint != center) {
|
||||
// Mouse move doesn't finish at the center of the window. Dispatch a
|
||||
|
@ -4222,8 +4224,8 @@ EventStateManager::GenerateMouseEnterExit(WidgetMouseEvent* aMouseEvent)
|
|||
// we've dispatched a synthetic mouse movement, so we can cancel it
|
||||
// in the other branch here.
|
||||
sSynthCenteringPoint = center;
|
||||
aMouseEvent->widget->SynthesizeNativeMouseMove(
|
||||
center + aMouseEvent->widget->WidgetToScreenOffset(), nullptr);
|
||||
aMouseEvent->mWidget->SynthesizeNativeMouseMove(
|
||||
center + aMouseEvent->mWidget->WidgetToScreenOffset(), nullptr);
|
||||
} else if (aMouseEvent->refPoint == sSynthCenteringPoint) {
|
||||
// This is the "synthetic native" event we dispatched to re-center the
|
||||
// pointer. Cancel it so we don't expose the centering move to content.
|
||||
|
@ -4290,7 +4292,7 @@ EventStateManager::GenerateMouseEnterExit(WidgetMouseEvent* aMouseEvent)
|
|||
|
||||
OverOutElementsWrapper* helper = GetWrapperByEventID(aMouseEvent);
|
||||
if (helper->mLastOverFrame &&
|
||||
nsContentUtils::GetTopLevelWidget(aMouseEvent->widget) !=
|
||||
nsContentUtils::GetTopLevelWidget(aMouseEvent->mWidget) !=
|
||||
nsContentUtils::GetTopLevelWidget(helper->mLastOverFrame->GetNearestWidget())) {
|
||||
// the Mouse/PointerOut event widget doesn't have same top widget with
|
||||
// mLastOverFrame, it's a spurious event for mLastOverFrame
|
||||
|
@ -4471,7 +4473,7 @@ EventStateManager::FireDragEnterOrExit(nsPresContext* aPresContext,
|
|||
nsWeakFrame& aTargetFrame)
|
||||
{
|
||||
nsEventStatus status = nsEventStatus_eIgnore;
|
||||
WidgetDragEvent event(aDragEvent->IsTrusted(), aMessage, aDragEvent->widget);
|
||||
WidgetDragEvent event(aDragEvent->IsTrusted(), aMessage, aDragEvent->mWidget);
|
||||
event.refPoint = aDragEvent->refPoint;
|
||||
event.mModifiers = aDragEvent->mModifiers;
|
||||
event.buttons = aDragEvent->buttons;
|
||||
|
@ -4507,7 +4509,8 @@ EventStateManager::FireDragEnterOrExit(nsPresContext* aPresContext,
|
|||
|
||||
if (aMessage == eDragExit && IsRemoteTarget(aTargetContent)) {
|
||||
nsEventStatus status = nsEventStatus_eIgnore;
|
||||
WidgetDragEvent remoteEvent(aDragEvent->IsTrusted(), aMessage, aDragEvent->widget);
|
||||
WidgetDragEvent remoteEvent(aDragEvent->IsTrusted(), aMessage,
|
||||
aDragEvent->mWidget);
|
||||
remoteEvent.AssignDragEventData(*aDragEvent, true);
|
||||
HandleCrossProcessEvent(&remoteEvent, &status);
|
||||
}
|
||||
|
@ -4625,7 +4628,7 @@ EventStateManager::CheckForAndDispatchClick(WidgetMouseEvent* aEvent,
|
|||
if (0 != aEvent->clickCount) {
|
||||
//Check that the window isn't disabled before firing a click
|
||||
//(see bug 366544).
|
||||
if (aEvent->widget && !aEvent->widget->IsEnabled()) {
|
||||
if (aEvent->mWidget && !aEvent->mWidget->IsEnabled()) {
|
||||
return ret;
|
||||
}
|
||||
//fire click
|
||||
|
@ -4634,7 +4637,7 @@ EventStateManager::CheckForAndDispatchClick(WidgetMouseEvent* aEvent,
|
|||
aEvent->button == WidgetMouseEvent::eRightButton);
|
||||
|
||||
WidgetMouseEvent event(aEvent->IsTrusted(), eMouseClick,
|
||||
aEvent->widget, WidgetMouseEvent::eReal);
|
||||
aEvent->mWidget, WidgetMouseEvent::eReal);
|
||||
event.refPoint = aEvent->refPoint;
|
||||
event.clickCount = aEvent->clickCount;
|
||||
event.mModifiers = aEvent->mModifiers;
|
||||
|
@ -4668,7 +4671,7 @@ EventStateManager::CheckForAndDispatchClick(WidgetMouseEvent* aEvent,
|
|||
mouseContent && mouseContent->IsInComposedDoc()) {
|
||||
//fire double click
|
||||
WidgetMouseEvent event2(aEvent->IsTrusted(), eMouseDoubleClick,
|
||||
aEvent->widget, WidgetMouseEvent::eReal);
|
||||
aEvent->mWidget, WidgetMouseEvent::eReal);
|
||||
event2.refPoint = aEvent->refPoint;
|
||||
event2.clickCount = aEvent->clickCount;
|
||||
event2.mModifiers = aEvent->mModifiers;
|
||||
|
|
|
@ -870,7 +870,7 @@ protected:
|
|||
/**
|
||||
* Set the fields of aEvent to reflect the mouse position and modifier keys
|
||||
* that were set when the user first pressed the mouse button (stored by
|
||||
* BeginTrackingDragGesture). aEvent->widget must be
|
||||
* BeginTrackingDragGesture). aEvent->mWidget must be
|
||||
* mCurrentTarget->GetNearestWidget().
|
||||
*/
|
||||
void FillInEventFromGestureDown(WidgetMouseEvent* aEvent);
|
||||
|
|
|
@ -758,7 +758,7 @@ IMEContentObserver::OnMouseButtonEvent(nsPresContext* aPresContext,
|
|||
}
|
||||
if (!aMouseEvent->IsTrusted() ||
|
||||
aMouseEvent->DefaultPrevented() ||
|
||||
!aMouseEvent->widget) {
|
||||
!aMouseEvent->mWidget) {
|
||||
return false;
|
||||
}
|
||||
// Now, we need to notify only mouse down and mouse up event.
|
||||
|
@ -776,7 +776,7 @@ IMEContentObserver::OnMouseButtonEvent(nsPresContext* aPresContext,
|
|||
RefPtr<IMEContentObserver> kungFuDeathGrip(this);
|
||||
|
||||
WidgetQueryContentEvent charAtPt(true, eQueryCharacterAtPoint,
|
||||
aMouseEvent->widget);
|
||||
aMouseEvent->mWidget);
|
||||
charAtPt.refPoint = aMouseEvent->refPoint;
|
||||
ContentEventHandler handler(aPresContext);
|
||||
handler.OnQueryCharacterAtPoint(&charAtPt);
|
||||
|
@ -801,8 +801,8 @@ IMEContentObserver::OnMouseButtonEvent(nsPresContext* aPresContext,
|
|||
}
|
||||
// The refPt is relative to its widget.
|
||||
// We should notify it with offset in the widget.
|
||||
if (aMouseEvent->widget != mWidget) {
|
||||
charAtPt.refPoint += aMouseEvent->widget->WidgetToScreenOffset() -
|
||||
if (aMouseEvent->mWidget != mWidget) {
|
||||
charAtPt.refPoint += aMouseEvent->mWidget->WidgetToScreenOffset() -
|
||||
mWidget->WidgetToScreenOffset();
|
||||
}
|
||||
|
||||
|
|
|
@ -1147,7 +1147,7 @@ IMEStateManager::DispatchCompositionEvent(
|
|||
("ISM: IMEStateManager::DispatchCompositionEvent(aNode=0x%p, "
|
||||
"aPresContext=0x%p, aCompositionEvent={ mMessage=%s, "
|
||||
"mNativeIMEContext={ mRawNativeIMEContext=0x%X, "
|
||||
"mOriginProcessID=0x%X }, widget(0x%p)={ "
|
||||
"mOriginProcessID=0x%X }, mWidget(0x%p)={ "
|
||||
"GetNativeIMEContext()={ mRawNativeIMEContext=0x%X, "
|
||||
"mOriginProcessID=0x%X }, Destroyed()=%s }, "
|
||||
"mFlags={ mIsTrusted=%s, mPropagationStopped=%s } }, "
|
||||
|
@ -1156,10 +1156,10 @@ IMEStateManager::DispatchCompositionEvent(
|
|||
ToChar(aCompositionEvent->mMessage),
|
||||
aCompositionEvent->mNativeIMEContext.mRawNativeIMEContext,
|
||||
aCompositionEvent->mNativeIMEContext.mOriginProcessID,
|
||||
aCompositionEvent->widget.get(),
|
||||
aCompositionEvent->widget->GetNativeIMEContext().mRawNativeIMEContext,
|
||||
aCompositionEvent->widget->GetNativeIMEContext().mOriginProcessID,
|
||||
GetBoolName(aCompositionEvent->widget->Destroyed()),
|
||||
aCompositionEvent->mWidget.get(),
|
||||
aCompositionEvent->mWidget->GetNativeIMEContext().mRawNativeIMEContext,
|
||||
aCompositionEvent->mWidget->GetNativeIMEContext().mOriginProcessID,
|
||||
GetBoolName(aCompositionEvent->mWidget->Destroyed()),
|
||||
GetBoolName(aCompositionEvent->mFlags.mIsTrusted),
|
||||
GetBoolName(aCompositionEvent->mFlags.mPropagationStopped),
|
||||
GetBoolName(aIsSynthesized), tabParent.get()));
|
||||
|
@ -1217,7 +1217,7 @@ IMEStateManager::DispatchCompositionEvent(
|
|||
composition->WasNativeCompositionEndEventDiscarded()) &&
|
||||
aCompositionEvent->CausesDOMCompositionEndEvent()) {
|
||||
TextCompositionArray::index_type i =
|
||||
sTextCompositions->IndexOf(aCompositionEvent->widget);
|
||||
sTextCompositions->IndexOf(aCompositionEvent->mWidget);
|
||||
if (i != TextCompositionArray::NoIndex) {
|
||||
MOZ_LOG(sISMLog, LogLevel::Debug,
|
||||
("ISM: IMEStateManager::DispatchCompositionEvent(), "
|
||||
|
@ -1266,7 +1266,7 @@ IMEStateManager::HandleSelectionEvent(nsPresContext* aPresContext,
|
|||
}
|
||||
|
||||
RefPtr<TextComposition> composition = sTextCompositions ?
|
||||
sTextCompositions->GetCompositionFor(aSelectionEvent->widget) : nullptr;
|
||||
sTextCompositions->GetCompositionFor(aSelectionEvent->mWidget) : nullptr;
|
||||
if (composition) {
|
||||
// When there is a composition, TextComposition should guarantee that the
|
||||
// selection event will be handled in same target as composition events.
|
||||
|
@ -1290,17 +1290,17 @@ IMEStateManager::OnCompositionEventDiscarded(
|
|||
MOZ_LOG(sISMLog, LogLevel::Info,
|
||||
("ISM: IMEStateManager::OnCompositionEventDiscarded(aCompositionEvent={ "
|
||||
"mMessage=%s, mNativeIMEContext={ mRawNativeIMEContext=0x%X, "
|
||||
"mOriginProcessID=0x%X }, widget(0x%p)={ "
|
||||
"mOriginProcessID=0x%X }, mWidget(0x%p)={ "
|
||||
"GetNativeIMEContext()={ mRawNativeIMEContext=0x%X, "
|
||||
"mOriginProcessID=0x%X }, Destroyed()=%s }, "
|
||||
"mFlags={ mIsTrusted=%s } })",
|
||||
ToChar(aCompositionEvent->mMessage),
|
||||
aCompositionEvent->mNativeIMEContext.mRawNativeIMEContext,
|
||||
aCompositionEvent->mNativeIMEContext.mOriginProcessID,
|
||||
aCompositionEvent->widget.get(),
|
||||
aCompositionEvent->widget->GetNativeIMEContext().mRawNativeIMEContext,
|
||||
aCompositionEvent->widget->GetNativeIMEContext().mOriginProcessID,
|
||||
GetBoolName(aCompositionEvent->widget->Destroyed()),
|
||||
aCompositionEvent->mWidget.get(),
|
||||
aCompositionEvent->mWidget->GetNativeIMEContext().mRawNativeIMEContext,
|
||||
aCompositionEvent->mWidget->GetNativeIMEContext().mOriginProcessID,
|
||||
GetBoolName(aCompositionEvent->mWidget->Destroyed()),
|
||||
GetBoolName(aCompositionEvent->mFlags.mIsTrusted)));
|
||||
|
||||
if (!aCompositionEvent->IsTrusted()) {
|
||||
|
@ -1314,7 +1314,7 @@ IMEStateManager::OnCompositionEventDiscarded(
|
|||
}
|
||||
|
||||
RefPtr<TextComposition> composition =
|
||||
sTextCompositions->GetCompositionFor(aCompositionEvent->widget);
|
||||
sTextCompositions->GetCompositionFor(aCompositionEvent->mWidget);
|
||||
if (!composition) {
|
||||
// If the PresShell has been being destroyed during composition,
|
||||
// a TextComposition instance for the composition was already removed from
|
||||
|
|
|
@ -95,7 +95,7 @@ TextComposition::MaybeDispatchCompositionUpdate(
|
|||
{
|
||||
MOZ_RELEASE_ASSERT(!mTabParent);
|
||||
|
||||
if (!IsValidStateForComposition(aCompositionEvent->widget)) {
|
||||
if (!IsValidStateForComposition(aCompositionEvent->mWidget)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -103,7 +103,7 @@ TextComposition::MaybeDispatchCompositionUpdate(
|
|||
return true;
|
||||
}
|
||||
CloneAndDispatchAs(aCompositionEvent, eCompositionUpdate);
|
||||
return IsValidStateForComposition(aCompositionEvent->widget);
|
||||
return IsValidStateForComposition(aCompositionEvent->mWidget);
|
||||
}
|
||||
|
||||
BaseEventFlags
|
||||
|
@ -115,11 +115,11 @@ TextComposition::CloneAndDispatchAs(
|
|||
{
|
||||
MOZ_RELEASE_ASSERT(!mTabParent);
|
||||
|
||||
MOZ_ASSERT(IsValidStateForComposition(aCompositionEvent->widget),
|
||||
MOZ_ASSERT(IsValidStateForComposition(aCompositionEvent->mWidget),
|
||||
"Should be called only when it's safe to dispatch an event");
|
||||
|
||||
WidgetCompositionEvent compositionEvent(aCompositionEvent->IsTrusted(),
|
||||
aMessage, aCompositionEvent->widget);
|
||||
aMessage, aCompositionEvent->mWidget);
|
||||
compositionEvent.mTime = aCompositionEvent->mTime;
|
||||
compositionEvent.mTimeStamp = aCompositionEvent->mTimeStamp;
|
||||
compositionEvent.mData = aCompositionEvent->mData;
|
||||
|
@ -279,7 +279,7 @@ TextComposition::DispatchCompositionEvent(
|
|||
aCompositionEvent->mRanges = nullptr;
|
||||
}
|
||||
|
||||
if (!IsValidStateForComposition(aCompositionEvent->widget)) {
|
||||
if (!IsValidStateForComposition(aCompositionEvent->mWidget)) {
|
||||
*aStatus = nsEventStatus_eConsumeNoDefault;
|
||||
return;
|
||||
}
|
||||
|
@ -377,7 +377,7 @@ TextComposition::DispatchCompositionEvent(
|
|||
*aStatus = nsEventStatus_eConsumeNoDefault;
|
||||
}
|
||||
|
||||
if (!IsValidStateForComposition(aCompositionEvent->widget)) {
|
||||
if (!IsValidStateForComposition(aCompositionEvent->mWidget)) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
@ -125,7 +125,7 @@ UIEvent::GetMovementPoint()
|
|||
mEvent->mClass != eDragEventClass &&
|
||||
mEvent->mClass != ePointerEventClass &&
|
||||
mEvent->mClass != eSimpleGestureEventClass) ||
|
||||
!mEvent->AsGUIEvent()->widget) {
|
||||
!mEvent->AsGUIEvent()->mWidget) {
|
||||
return nsIntPoint(0, 0);
|
||||
}
|
||||
|
||||
|
|
|
@ -338,8 +338,8 @@ WheelTransaction::SetTimeout()
|
|||
WheelTransaction::GetScreenPoint(WidgetGUIEvent* aEvent)
|
||||
{
|
||||
NS_ASSERTION(aEvent, "aEvent is null");
|
||||
NS_ASSERTION(aEvent->widget, "aEvent-widget is null");
|
||||
return (aEvent->refPoint + aEvent->widget->WidgetToScreenOffset())
|
||||
NS_ASSERTION(aEvent->mWidget, "aEvent-mWidget is null");
|
||||
return (aEvent->refPoint + aEvent->mWidget->WidgetToScreenOffset())
|
||||
.ToUnknownPoint();
|
||||
}
|
||||
|
||||
|
|
|
@ -119,9 +119,7 @@ CreateDirectoryTaskChild::HandlerCallback()
|
|||
}
|
||||
|
||||
RefPtr<Directory> dir = Directory::Create(mFileSystem->GetParentObject(),
|
||||
mTargetPath,
|
||||
Directory::eNotDOMRootDirectory,
|
||||
mFileSystem);
|
||||
mTargetPath, mFileSystem);
|
||||
MOZ_ASSERT(dir);
|
||||
|
||||
mPromise->MaybeResolve(dir);
|
||||
|
|
|
@ -115,10 +115,32 @@ DeviceStorageFileSystem::GetParentObject() const
|
|||
}
|
||||
|
||||
void
|
||||
DeviceStorageFileSystem::GetRootName(nsAString& aRetval) const
|
||||
DeviceStorageFileSystem::GetDirectoryName(nsIFile* aFile, nsAString& aRetval,
|
||||
ErrorResult& aRv) const
|
||||
{
|
||||
AssertIsOnOwningThread();
|
||||
aRetval = mStorageName;
|
||||
MOZ_ASSERT(aFile);
|
||||
|
||||
nsCOMPtr<nsIFile> rootPath;
|
||||
aRv = NS_NewLocalFile(LocalOrDeviceStorageRootPath(), false,
|
||||
getter_AddRefs(rootPath));
|
||||
if (NS_WARN_IF(aRv.Failed())) {
|
||||
return;
|
||||
}
|
||||
|
||||
bool equal = false;
|
||||
aRv = aFile->Equals(rootPath, &equal);
|
||||
if (NS_WARN_IF(aRv.Failed())) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (equal) {
|
||||
aRetval = mStorageName;
|
||||
return;
|
||||
}
|
||||
|
||||
FileSystemBase::GetDirectoryName(aFile, aRetval, aRv);
|
||||
NS_WARN_IF(aRv.Failed());
|
||||
}
|
||||
|
||||
bool
|
||||
|
|
|
@ -30,6 +30,9 @@ public:
|
|||
virtual already_AddRefed<FileSystemBase>
|
||||
Clone() override;
|
||||
|
||||
virtual bool
|
||||
ShouldCreateDirectory() override { return true; }
|
||||
|
||||
virtual void
|
||||
Shutdown() override;
|
||||
|
||||
|
@ -37,7 +40,8 @@ public:
|
|||
GetParentObject() const override;
|
||||
|
||||
virtual void
|
||||
GetRootName(nsAString& aRetval) const override;
|
||||
GetDirectoryName(nsIFile* aFile, nsAString& aRetval,
|
||||
ErrorResult& aRv) const override;
|
||||
|
||||
virtual bool
|
||||
IsSafeFile(nsIFile* aFile) const override;
|
||||
|
|
|
@ -137,8 +137,7 @@ Directory::GetRoot(FileSystemBase* aFileSystem, ErrorResult& aRv)
|
|||
}
|
||||
|
||||
RefPtr<GetFileOrDirectoryTaskChild> task =
|
||||
GetFileOrDirectoryTaskChild::Create(aFileSystem, path, eDOMRootDirectory,
|
||||
true, aRv);
|
||||
GetFileOrDirectoryTaskChild::Create(aFileSystem, path, true, aRv);
|
||||
if (NS_WARN_IF(aRv.Failed())) {
|
||||
return nullptr;
|
||||
}
|
||||
|
@ -149,7 +148,7 @@ Directory::GetRoot(FileSystemBase* aFileSystem, ErrorResult& aRv)
|
|||
|
||||
/* static */ already_AddRefed<Directory>
|
||||
Directory::Create(nsISupports* aParent, nsIFile* aFile,
|
||||
DirectoryType aType, FileSystemBase* aFileSystem)
|
||||
FileSystemBase* aFileSystem)
|
||||
{
|
||||
MOZ_ASSERT(aParent);
|
||||
MOZ_ASSERT(aFile);
|
||||
|
@ -158,27 +157,17 @@ Directory::Create(nsISupports* aParent, nsIFile* aFile,
|
|||
bool isDir;
|
||||
nsresult rv = aFile->IsDirectory(&isDir);
|
||||
MOZ_ASSERT(NS_SUCCEEDED(rv) && isDir);
|
||||
|
||||
if (aType == eNotDOMRootDirectory) {
|
||||
RefPtr<nsIFile> parent;
|
||||
rv = aFile->GetParent(getter_AddRefs(parent));
|
||||
// We must have a parent if this is not the root directory.
|
||||
MOZ_ASSERT(NS_SUCCEEDED(rv) && parent);
|
||||
}
|
||||
#endif
|
||||
|
||||
RefPtr<Directory> directory =
|
||||
new Directory(aParent, aFile, aType, aFileSystem);
|
||||
RefPtr<Directory> directory = new Directory(aParent, aFile, aFileSystem);
|
||||
return directory.forget();
|
||||
}
|
||||
|
||||
Directory::Directory(nsISupports* aParent,
|
||||
nsIFile* aFile,
|
||||
DirectoryType aType,
|
||||
FileSystemBase* aFileSystem)
|
||||
: mParent(aParent)
|
||||
, mFile(aFile)
|
||||
, mType(aType)
|
||||
{
|
||||
MOZ_ASSERT(aFile);
|
||||
|
||||
|
@ -213,18 +202,12 @@ Directory::GetName(nsAString& aRetval, ErrorResult& aRv)
|
|||
{
|
||||
aRetval.Truncate();
|
||||
|
||||
if (mType == eDOMRootDirectory) {
|
||||
RefPtr<FileSystemBase> fs = GetFileSystem(aRv);
|
||||
if (NS_WARN_IF(aRv.Failed())) {
|
||||
return;
|
||||
}
|
||||
|
||||
fs->GetRootName(aRetval);
|
||||
RefPtr<FileSystemBase> fs = GetFileSystem(aRv);
|
||||
if (NS_WARN_IF(aRv.Failed())) {
|
||||
return;
|
||||
}
|
||||
|
||||
aRv = mFile->GetLeafName(aRetval);
|
||||
NS_WARN_IF(aRv.Failed());
|
||||
fs->GetDirectoryName(mFile, aRetval, aRv);
|
||||
}
|
||||
|
||||
already_AddRefed<Promise>
|
||||
|
@ -318,8 +301,7 @@ Directory::Get(const nsAString& aPath, ErrorResult& aRv)
|
|||
}
|
||||
|
||||
RefPtr<GetFileOrDirectoryTaskChild> task =
|
||||
GetFileOrDirectoryTaskChild::Create(fs, realPath, eNotDOMRootDirectory,
|
||||
false, aRv);
|
||||
GetFileOrDirectoryTaskChild::Create(fs, realPath, false, aRv);
|
||||
if (NS_WARN_IF(aRv.Failed())) {
|
||||
return nullptr;
|
||||
}
|
||||
|
@ -409,7 +391,7 @@ Directory::GetPath(nsAString& aRetval, ErrorResult& aRv)
|
|||
return;
|
||||
}
|
||||
|
||||
fs->GetDOMPath(mFile, mType, mPath, aRv);
|
||||
fs->GetDOMPath(mFile, mPath, aRv);
|
||||
if (NS_WARN_IF(aRv.Failed())) {
|
||||
return;
|
||||
}
|
||||
|
@ -438,7 +420,7 @@ Directory::GetFilesAndDirectories(ErrorResult& aRv)
|
|||
}
|
||||
|
||||
RefPtr<GetDirectoryListingTaskChild> task =
|
||||
GetDirectoryListingTaskChild::Create(fs, mFile, mType, mFilters, aRv);
|
||||
GetDirectoryListingTaskChild::Create(fs, mFile, mFilters, aRv);
|
||||
if (NS_WARN_IF(aRv.Failed())) {
|
||||
return nullptr;
|
||||
}
|
||||
|
@ -478,10 +460,6 @@ FileSystemBase*
|
|||
Directory::GetFileSystem(ErrorResult& aRv)
|
||||
{
|
||||
if (!mFileSystem) {
|
||||
// Any subdir inherits the FileSystem of the parent Directory. If we are
|
||||
// here it's because we are dealing with the DOM root.
|
||||
MOZ_ASSERT(mType == eDOMRootDirectory);
|
||||
|
||||
nsAutoString path;
|
||||
aRv = mFile->GetPath(path);
|
||||
if (NS_WARN_IF(aRv.Failed())) {
|
||||
|
|
|
@ -59,20 +59,9 @@ public:
|
|||
static already_AddRefed<Promise>
|
||||
GetRoot(FileSystemBase* aFileSystem, ErrorResult& aRv);
|
||||
|
||||
enum DirectoryType {
|
||||
// When a directory is selected using a HTMLInputElement, that will be the
|
||||
// DOM root directory and its name will be '/'. All the sub directory will
|
||||
// be called with they real name. We use this enum to mark what we must
|
||||
// consider the '/' of this DOM filesystem.
|
||||
eDOMRootDirectory,
|
||||
|
||||
// All the sub directories of the '/' will be marked using this other value.
|
||||
eNotDOMRootDirectory
|
||||
};
|
||||
|
||||
static already_AddRefed<Directory>
|
||||
Create(nsISupports* aParent, nsIFile* aDirectory,
|
||||
DirectoryType aType, FileSystemBase* aFileSystem = 0);
|
||||
FileSystemBase* aFileSystem = 0);
|
||||
|
||||
// ========= Begin WebIDL bindings. ===========
|
||||
|
||||
|
@ -145,17 +134,12 @@ public:
|
|||
FileSystemBase*
|
||||
GetFileSystem(ErrorResult& aRv);
|
||||
|
||||
DirectoryType Type() const
|
||||
{
|
||||
return mType;
|
||||
}
|
||||
|
||||
bool
|
||||
ClonableToDifferentThreadOrProcess() const;
|
||||
|
||||
private:
|
||||
Directory(nsISupports* aParent,
|
||||
nsIFile* aFile, DirectoryType aType,
|
||||
nsIFile* aFile,
|
||||
FileSystemBase* aFileSystem = nullptr);
|
||||
~Directory();
|
||||
|
||||
|
@ -172,7 +156,6 @@ private:
|
|||
nsCOMPtr<nsISupports> mParent;
|
||||
RefPtr<FileSystemBase> mFileSystem;
|
||||
nsCOMPtr<nsIFile> mFile;
|
||||
DirectoryType mType;
|
||||
|
||||
nsString mFilters;
|
||||
nsString mPath;
|
||||
|
|
|
@ -110,19 +110,26 @@ FileSystemBase::IsSafeDirectory(Directory* aDir) const
|
|||
return false;
|
||||
}
|
||||
|
||||
void
|
||||
FileSystemBase::GetDirectoryName(nsIFile* aFile, nsAString& aRetval,
|
||||
ErrorResult& aRv) const
|
||||
{
|
||||
AssertIsOnOwningThread();
|
||||
MOZ_ASSERT(aFile);
|
||||
|
||||
aRv = aFile->GetLeafName(aRetval);
|
||||
NS_WARN_IF(aRv.Failed());
|
||||
}
|
||||
|
||||
void
|
||||
FileSystemBase::GetDOMPath(nsIFile* aFile,
|
||||
Directory::DirectoryType aType,
|
||||
nsAString& aRetval,
|
||||
ErrorResult& aRv) const
|
||||
{
|
||||
AssertIsOnOwningThread();
|
||||
MOZ_ASSERT(aFile);
|
||||
|
||||
if (aType == Directory::eDOMRootDirectory) {
|
||||
aRetval.AssignLiteral(FILESYSTEM_DOM_PATH_SEPARATOR_LITERAL);
|
||||
return;
|
||||
}
|
||||
aRetval.Truncate();
|
||||
|
||||
nsCOMPtr<nsIFile> fileSystemPath;
|
||||
aRv = NS_NewNativeLocalFile(NS_ConvertUTF16toUTF8(LocalOrDeviceStorageRootPath()),
|
||||
|
@ -131,8 +138,6 @@ FileSystemBase::GetDOMPath(nsIFile* aFile,
|
|||
return;
|
||||
}
|
||||
|
||||
MOZ_ASSERT(FileSystemUtils::IsDescendantPath(fileSystemPath, aFile));
|
||||
|
||||
nsCOMPtr<nsIFile> path;
|
||||
aRv = aFile->Clone(getter_AddRefs(path));
|
||||
if (NS_WARN_IF(aRv.Failed())) {
|
||||
|
@ -142,6 +147,14 @@ FileSystemBase::GetDOMPath(nsIFile* aFile,
|
|||
nsTArray<nsString> parts;
|
||||
|
||||
while (true) {
|
||||
nsAutoString leafName;
|
||||
aRv = path->GetLeafName(leafName);
|
||||
if (NS_WARN_IF(aRv.Failed())) {
|
||||
return;
|
||||
}
|
||||
|
||||
parts.AppendElement(leafName);
|
||||
|
||||
bool equal = false;
|
||||
aRv = fileSystemPath->Equals(path, &equal);
|
||||
if (NS_WARN_IF(aRv.Failed())) {
|
||||
|
@ -152,14 +165,6 @@ FileSystemBase::GetDOMPath(nsIFile* aFile,
|
|||
break;
|
||||
}
|
||||
|
||||
nsAutoString leafName;
|
||||
aRv = path->GetLeafName(leafName);
|
||||
if (NS_WARN_IF(aRv.Failed())) {
|
||||
return;
|
||||
}
|
||||
|
||||
parts.AppendElement(leafName);
|
||||
|
||||
nsCOMPtr<nsIFile> parentPath;
|
||||
aRv = path->GetParent(getter_AddRefs(parentPath));
|
||||
if (NS_WARN_IF(aRv.Failed())) {
|
||||
|
@ -176,8 +181,6 @@ FileSystemBase::GetDOMPath(nsIFile* aFile,
|
|||
|
||||
MOZ_ASSERT(!parts.IsEmpty());
|
||||
|
||||
aRetval.Truncate();
|
||||
|
||||
for (int32_t i = parts.Length() - 1; i >= 0; --i) {
|
||||
aRetval.AppendLiteral(FILESYSTEM_DOM_PATH_SEPARATOR_LITERAL);
|
||||
aRetval.Append(parts[i]);
|
||||
|
|
|
@ -37,19 +37,18 @@ public:
|
|||
virtual already_AddRefed<FileSystemBase>
|
||||
Clone() = 0;
|
||||
|
||||
virtual bool
|
||||
ShouldCreateDirectory() = 0;
|
||||
|
||||
virtual nsISupports*
|
||||
GetParentObject() const;
|
||||
|
||||
/*
|
||||
* Get the virtual name of the root directory. This name will be exposed to
|
||||
* the content page.
|
||||
*/
|
||||
virtual void
|
||||
GetRootName(nsAString& aRetval) const = 0;
|
||||
GetDirectoryName(nsIFile* aFile, nsAString& aRetval,
|
||||
ErrorResult& aRv) const;
|
||||
|
||||
void
|
||||
GetDOMPath(nsIFile* aFile, Directory::DirectoryType aType,
|
||||
nsAString& aRetval, ErrorResult& aRv) const;
|
||||
GetDOMPath(nsIFile* aFile, nsAString& aRetval, ErrorResult& aRv) const;
|
||||
|
||||
/*
|
||||
* Return the local root path of the FileSystem implementation.
|
||||
|
|
|
@ -28,7 +28,6 @@ namespace dom {
|
|||
/* static */ already_AddRefed<GetDirectoryListingTaskChild>
|
||||
GetDirectoryListingTaskChild::Create(FileSystemBase* aFileSystem,
|
||||
nsIFile* aTargetPath,
|
||||
Directory::DirectoryType aType,
|
||||
const nsAString& aFilters,
|
||||
ErrorResult& aRv)
|
||||
{
|
||||
|
@ -36,7 +35,7 @@ GetDirectoryListingTaskChild::Create(FileSystemBase* aFileSystem,
|
|||
aFileSystem->AssertIsOnOwningThread();
|
||||
|
||||
RefPtr<GetDirectoryListingTaskChild> task =
|
||||
new GetDirectoryListingTaskChild(aFileSystem, aTargetPath, aType, aFilters);
|
||||
new GetDirectoryListingTaskChild(aFileSystem, aTargetPath, aFilters);
|
||||
|
||||
// aTargetPath can be null. In this case SetError will be called.
|
||||
|
||||
|
@ -57,12 +56,10 @@ GetDirectoryListingTaskChild::Create(FileSystemBase* aFileSystem,
|
|||
|
||||
GetDirectoryListingTaskChild::GetDirectoryListingTaskChild(FileSystemBase* aFileSystem,
|
||||
nsIFile* aTargetPath,
|
||||
Directory::DirectoryType aType,
|
||||
const nsAString& aFilters)
|
||||
: FileSystemTaskChildBase(aFileSystem)
|
||||
, mTargetPath(aTargetPath)
|
||||
, mFilters(aFilters)
|
||||
, mType(aType)
|
||||
{
|
||||
MOZ_ASSERT(aFileSystem);
|
||||
aFileSystem->AssertIsOnOwningThread();
|
||||
|
@ -93,7 +90,6 @@ GetDirectoryListingTaskChild::GetRequestParams(const nsString& aSerializedDOMPat
|
|||
}
|
||||
|
||||
return FileSystemGetDirectoryListingParams(aSerializedDOMPath, path,
|
||||
mType == Directory::eDOMRootDirectory,
|
||||
mFilters);
|
||||
}
|
||||
|
||||
|
@ -179,8 +175,7 @@ GetDirectoryListingTaskChild::HandlerCallback()
|
|||
|
||||
if (mTargetData[i].mType == Directory::FileOrDirectoryPath::eDirectoryPath) {
|
||||
RefPtr<Directory> directory =
|
||||
Directory::Create(mFileSystem->GetParentObject(), path,
|
||||
Directory::eNotDOMRootDirectory, mFileSystem);
|
||||
Directory::Create(mFileSystem->GetParentObject(), path, mFileSystem);
|
||||
MOZ_ASSERT(directory);
|
||||
|
||||
// Propogate mFilter onto sub-Directory object:
|
||||
|
@ -230,8 +225,6 @@ GetDirectoryListingTaskParent::Create(FileSystemBase* aFileSystem,
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
task->mType = aParam.isRoot()
|
||||
? Directory::eDOMRootDirectory : Directory::eNotDOMRootDirectory;
|
||||
return task.forget();
|
||||
}
|
||||
|
||||
|
@ -291,11 +284,10 @@ GetDirectoryListingTaskParent::IOWork()
|
|||
}
|
||||
|
||||
if (!exists) {
|
||||
if (mType == Directory::eNotDOMRootDirectory) {
|
||||
if (!mFileSystem->ShouldCreateDirectory()) {
|
||||
return NS_ERROR_DOM_FILE_NOT_FOUND_ERR;
|
||||
}
|
||||
|
||||
// If the root directory doesn't exit, create it.
|
||||
rv = mTargetPath->Create(nsIFile::DIRECTORY_TYPE, 0777);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return rv;
|
||||
|
|
|
@ -23,7 +23,6 @@ public:
|
|||
static already_AddRefed<GetDirectoryListingTaskChild>
|
||||
Create(FileSystemBase* aFileSystem,
|
||||
nsIFile* aTargetPath,
|
||||
Directory::DirectoryType aType,
|
||||
const nsAString& aFilters,
|
||||
ErrorResult& aRv);
|
||||
|
||||
|
@ -40,7 +39,6 @@ private:
|
|||
// If aDirectoryOnly is set, we should ensure that the target is a directory.
|
||||
GetDirectoryListingTaskChild(FileSystemBase* aFileSystem,
|
||||
nsIFile* aTargetPath,
|
||||
Directory::DirectoryType aType,
|
||||
const nsAString& aFilters);
|
||||
|
||||
virtual FileSystemParams
|
||||
|
@ -57,7 +55,6 @@ private:
|
|||
RefPtr<Promise> mPromise;
|
||||
nsCOMPtr<nsIFile> mTargetPath;
|
||||
nsString mFilters;
|
||||
Directory::DirectoryType mType;
|
||||
|
||||
// We cannot store File or Directory objects bacause this object is created
|
||||
// on a different thread and File and Directory are not thread-safe.
|
||||
|
@ -89,7 +86,6 @@ private:
|
|||
|
||||
nsCOMPtr<nsIFile> mTargetPath;
|
||||
nsString mFilters;
|
||||
Directory::DirectoryType mType;
|
||||
|
||||
// We cannot store File or Directory objects bacause this object is created
|
||||
// on a different thread and File and Directory are not thread-safe.
|
||||
|
|
|
@ -27,7 +27,6 @@ namespace dom {
|
|||
/* static */ already_AddRefed<GetFileOrDirectoryTaskChild>
|
||||
GetFileOrDirectoryTaskChild::Create(FileSystemBase* aFileSystem,
|
||||
nsIFile* aTargetPath,
|
||||
Directory::DirectoryType aType,
|
||||
bool aDirectoryOnly,
|
||||
ErrorResult& aRv)
|
||||
{
|
||||
|
@ -35,8 +34,7 @@ GetFileOrDirectoryTaskChild::Create(FileSystemBase* aFileSystem,
|
|||
MOZ_ASSERT(aFileSystem);
|
||||
|
||||
RefPtr<GetFileOrDirectoryTaskChild> task =
|
||||
new GetFileOrDirectoryTaskChild(aFileSystem, aTargetPath, aType,
|
||||
aDirectoryOnly);
|
||||
new GetFileOrDirectoryTaskChild(aFileSystem, aTargetPath, aDirectoryOnly);
|
||||
|
||||
// aTargetPath can be null. In this case SetError will be called.
|
||||
|
||||
|
@ -57,12 +55,10 @@ GetFileOrDirectoryTaskChild::Create(FileSystemBase* aFileSystem,
|
|||
|
||||
GetFileOrDirectoryTaskChild::GetFileOrDirectoryTaskChild(FileSystemBase* aFileSystem,
|
||||
nsIFile* aTargetPath,
|
||||
Directory::DirectoryType aType,
|
||||
bool aDirectoryOnly)
|
||||
: FileSystemTaskChildBase(aFileSystem)
|
||||
, mTargetPath(aTargetPath)
|
||||
, mIsDirectory(aDirectoryOnly)
|
||||
, mType(aType)
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread(), "Only call on main thread!");
|
||||
MOZ_ASSERT(aFileSystem);
|
||||
|
@ -92,8 +88,7 @@ GetFileOrDirectoryTaskChild::GetRequestParams(const nsString& aSerializedDOMPath
|
|||
return FileSystemGetFileOrDirectoryParams();
|
||||
}
|
||||
|
||||
return FileSystemGetFileOrDirectoryParams(aSerializedDOMPath, path,
|
||||
mType == Directory::eDOMRootDirectory);
|
||||
return FileSystemGetFileOrDirectoryParams(aSerializedDOMPath, path);
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -151,7 +146,6 @@ GetFileOrDirectoryTaskChild::HandlerCallback()
|
|||
if (mIsDirectory) {
|
||||
RefPtr<Directory> dir = Directory::Create(mFileSystem->GetParentObject(),
|
||||
mTargetPath,
|
||||
mType,
|
||||
mFileSystem);
|
||||
MOZ_ASSERT(dir);
|
||||
|
||||
|
@ -195,8 +189,6 @@ GetFileOrDirectoryTaskParent::Create(FileSystemBase* aFileSystem,
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
task->mType = aParam.isRoot()
|
||||
? Directory::eDOMRootDirectory : Directory::eNotDOMRootDirectory;
|
||||
return task.forget();
|
||||
}
|
||||
|
||||
|
@ -248,11 +240,10 @@ GetFileOrDirectoryTaskParent::IOWork()
|
|||
}
|
||||
|
||||
if (!exists) {
|
||||
if (mType == Directory::eNotDOMRootDirectory) {
|
||||
if (!mFileSystem->ShouldCreateDirectory()) {
|
||||
return NS_ERROR_DOM_FILE_NOT_FOUND_ERR;
|
||||
}
|
||||
|
||||
// If the root directory doesn't exit, create it.
|
||||
rv = mTargetPath->Create(nsIFile::DIRECTORY_TYPE, 0777);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return rv;
|
||||
|
@ -269,11 +260,6 @@ GetFileOrDirectoryTaskParent::IOWork()
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
// Check if the root is a directory.
|
||||
if (mType == Directory::eDOMRootDirectory) {
|
||||
return NS_ERROR_DOM_FILESYSTEM_TYPE_MISMATCH_ERR;
|
||||
}
|
||||
|
||||
bool isFile;
|
||||
// Get isFile
|
||||
rv = mTargetPath->IsFile(&isFile);
|
||||
|
|
|
@ -23,7 +23,6 @@ public:
|
|||
static already_AddRefed<GetFileOrDirectoryTaskChild>
|
||||
Create(FileSystemBase* aFileSystem,
|
||||
nsIFile* aTargetPath,
|
||||
Directory::DirectoryType aType,
|
||||
bool aDirectoryOnly,
|
||||
ErrorResult& aRv);
|
||||
|
||||
|
@ -51,7 +50,6 @@ private:
|
|||
// If aDirectoryOnly is set, we should ensure that the target is a directory.
|
||||
GetFileOrDirectoryTaskChild(FileSystemBase* aFileSystem,
|
||||
nsIFile* aTargetPath,
|
||||
Directory::DirectoryType aType,
|
||||
bool aDirectoryOnly);
|
||||
|
||||
RefPtr<Promise> mPromise;
|
||||
|
@ -59,7 +57,6 @@ private:
|
|||
|
||||
// Whether we get a directory.
|
||||
bool mIsDirectory;
|
||||
Directory::DirectoryType mType;
|
||||
};
|
||||
|
||||
class GetFileOrDirectoryTaskParent final : public FileSystemTaskParentBase
|
||||
|
@ -90,7 +87,6 @@ private:
|
|||
|
||||
// Whether we get a directory.
|
||||
bool mIsDirectory;
|
||||
Directory::DirectoryType mType;
|
||||
};
|
||||
|
||||
} // namespace dom
|
||||
|
|
|
@ -62,13 +62,6 @@ OSFileSystem::GetParentObject() const
|
|||
return mParent;
|
||||
}
|
||||
|
||||
void
|
||||
OSFileSystem::GetRootName(nsAString& aRetval) const
|
||||
{
|
||||
AssertIsOnOwningThread();
|
||||
aRetval.AssignLiteral(FILESYSTEM_DOM_PATH_SEPARATOR_LITERAL);
|
||||
}
|
||||
|
||||
bool
|
||||
OSFileSystem::IsSafeFile(nsIFile* aFile) const
|
||||
{
|
||||
|
|
|
@ -25,12 +25,18 @@ public:
|
|||
virtual already_AddRefed<FileSystemBase>
|
||||
Clone() override;
|
||||
|
||||
virtual bool
|
||||
ShouldCreateDirectory() override
|
||||
{
|
||||
MOZ_CRASH("This should not be called.");
|
||||
// Because OSFileSystem should not be used when the creation of directories
|
||||
// is needed. For that we have OSFileSystemParent.
|
||||
return false;
|
||||
}
|
||||
|
||||
virtual nsISupports*
|
||||
GetParentObject() const override;
|
||||
|
||||
virtual void
|
||||
GetRootName(nsAString& aRetval) const override;
|
||||
|
||||
virtual bool
|
||||
IsSafeFile(nsIFile* aFile) const override;
|
||||
|
||||
|
@ -67,6 +73,9 @@ public:
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
virtual bool
|
||||
ShouldCreateDirectory() override { return false; }
|
||||
|
||||
virtual nsISupports*
|
||||
GetParentObject() const override
|
||||
{
|
||||
|
@ -75,7 +84,8 @@ public:
|
|||
}
|
||||
|
||||
virtual void
|
||||
GetRootName(nsAString& aRetval) const override
|
||||
GetDirectoryName(nsIFile* aFile, nsAString& aRetval,
|
||||
ErrorResult& aRv) const override
|
||||
{
|
||||
MOZ_CRASH("This should not be called on the PBackground thread.");
|
||||
}
|
||||
|
|
|
@ -31,7 +31,7 @@ struct FileSystemGetDirectoryListingParams
|
|||
{
|
||||
nsString filesystem;
|
||||
nsString realPath;
|
||||
bool isRoot;
|
||||
|
||||
// 'filters' could be an array rather than a semicolon separated string
|
||||
// (we'd then use InfallibleTArray<nsString> internally), but that is
|
||||
// wasteful. E10s requires us to pass the filters over as a string anyway,
|
||||
|
@ -55,7 +55,6 @@ struct FileSystemGetFileOrDirectoryParams
|
|||
{
|
||||
nsString filesystem;
|
||||
nsString realPath;
|
||||
bool isRoot;
|
||||
};
|
||||
|
||||
struct FileSystemRemoveParams
|
||||
|
|
|
@ -1,8 +1,7 @@
|
|||
function test_basic(aDirectory, aNext) {
|
||||
ok(aDirectory, "Directory exists.");
|
||||
ok(aDirectory instanceof Directory, "We have a directory.");
|
||||
is(aDirectory.name, '/', "directory.name must be '/'");
|
||||
is(aDirectory.path, '/', "directory.path must be '/'");
|
||||
is(aDirectory.path, '/' + aDirectory.name, "directory.path must be '/'+name");
|
||||
aNext();
|
||||
}
|
||||
|
||||
|
@ -16,7 +15,7 @@ function test_getFilesAndDirectories(aDirectory, aRecursive, aNext) {
|
|||
isnot(data[i].name, '/', "Subdirectory should be called with the leafname");
|
||||
isnot(data[i].path, '/', "Subdirectory path should be called with the leafname");
|
||||
isnot(data[i].path, dir.path, "Subdirectory path should contain the parent path.");
|
||||
is(data[i].path,dir.path + '/' + data[i].name, "Subdirectory path should be called parentdir.path + '/' + leafname");
|
||||
is(data[i].path, dir.path + '/' + data[i].name, "Subdirectory path should be called parentdir.path + '/' + leafname");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -31,7 +30,7 @@ function test_getFilesAndDirectories(aDirectory, aRecursive, aNext) {
|
|||
ok (data[i] instanceof File || data[i] instanceof Directory, "Just Files or Directories: " + data[i].name);
|
||||
if (data[i] instanceof Directory) {
|
||||
isnot(data[i].name, '/', "Subdirectory should be called with the leafname");
|
||||
is(data[i].path, '/' + data[i].name, "Subdirectory path should be called '/' + leafname");
|
||||
is(data[i].path, aDirectory.path + '/' + data[i].name, "Subdirectory path should be called parentdir.path + '/' + leafname");
|
||||
if (aRecursive) {
|
||||
promises.push(checkSubDir(data[i]));
|
||||
}
|
||||
|
|
|
@ -272,8 +272,7 @@ class HTMLInputElementState final : public nsISupports
|
|||
continue;
|
||||
}
|
||||
|
||||
RefPtr<Directory> directory = Directory::Create(aWindow, file,
|
||||
Directory::eDOMRootDirectory);
|
||||
RefPtr<Directory> directory = Directory::Create(aWindow, file);
|
||||
MOZ_ASSERT(directory);
|
||||
|
||||
OwningFileOrDirectory* element = aResult.AppendElement();
|
||||
|
@ -2311,8 +2310,7 @@ HTMLInputElement::MozSetDirectory(const nsAString& aDirectoryPath,
|
|||
return;
|
||||
}
|
||||
|
||||
RefPtr<Directory> directory = Directory::Create(window, file,
|
||||
Directory::eDOMRootDirectory);
|
||||
RefPtr<Directory> directory = Directory::Create(window, file);
|
||||
MOZ_ASSERT(directory);
|
||||
|
||||
nsTArray<OwningFileOrDirectory> array;
|
||||
|
|
|
@ -902,7 +902,7 @@ nsTextInputListener::HandleEvent(nsIDOMEvent* aEvent)
|
|||
mTxtCtrlElement->IsTextArea() ?
|
||||
nsIWidget::NativeKeyBindingsForMultiLineEditor :
|
||||
nsIWidget::NativeKeyBindingsForSingleLineEditor;
|
||||
nsIWidget* widget = keyEvent->widget;
|
||||
nsIWidget* widget = keyEvent->mWidget;
|
||||
// If the event is created by chrome script, the widget is nullptr.
|
||||
if (!widget) {
|
||||
widget = mFrame->GetNearestWidget();
|
||||
|
|
|
@ -425,6 +425,19 @@ private:
|
|||
|
||||
NS_IMPL_ISUPPORTS(ConsoleListener, nsIConsoleListener)
|
||||
|
||||
// Before we send the error to the parent process (which
|
||||
// involves copying the memory), truncate any long lines. CSS
|
||||
// errors in particular share the memory for long lines with
|
||||
// repeated errors, but the IPC communication we're about to do
|
||||
// will break that sharing, so we better truncate now.
|
||||
static void
|
||||
TruncateString(nsAString& aString)
|
||||
{
|
||||
if (aString.Length() > 1000) {
|
||||
aString.Truncate(1000);
|
||||
}
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
ConsoleListener::Observe(nsIConsoleMessage* aMessage)
|
||||
{
|
||||
|
@ -440,22 +453,13 @@ ConsoleListener::Observe(nsIConsoleMessage* aMessage)
|
|||
|
||||
nsresult rv = scriptError->GetErrorMessage(msg);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
TruncateString(msg);
|
||||
rv = scriptError->GetSourceName(sourceName);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
TruncateString(sourceName);
|
||||
rv = scriptError->GetSourceLine(sourceLine);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
// Before we send the error to the parent process (which
|
||||
// involves copying the memory), truncate any long lines. CSS
|
||||
// errors in particular share the memory for long lines with
|
||||
// repeated errors, but the IPC communication we're about to do
|
||||
// will break that sharing, so we better truncate now.
|
||||
if (sourceName.Length() > 1000) {
|
||||
sourceName.Truncate(1000);
|
||||
}
|
||||
if (sourceLine.Length() > 1000) {
|
||||
sourceLine.Truncate(1000);
|
||||
}
|
||||
TruncateString(sourceLine);
|
||||
|
||||
rv = scriptError->GetCategory(getter_Copies(category));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
@ -465,6 +469,7 @@ ConsoleListener::Observe(nsIConsoleMessage* aMessage)
|
|||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
rv = scriptError->GetFlags(&flags);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
mChild->SendScriptError(msg, sourceName, sourceLine,
|
||||
lineNum, colNum, flags, category);
|
||||
return NS_OK;
|
||||
|
|
|
@ -1856,7 +1856,7 @@ TabChild::RecvRealMouseButtonEvent(const WidgetMouseEvent& aEvent,
|
|||
InputAPZContext context(aGuid, aInputBlockId, unused);
|
||||
|
||||
WidgetMouseEvent localEvent(aEvent);
|
||||
localEvent.widget = mPuppetWidget;
|
||||
localEvent.mWidget = mPuppetWidget;
|
||||
APZCCallbackHelper::ApplyCallbackTransform(localEvent, aGuid,
|
||||
mPuppetWidget->GetDefaultScale());
|
||||
APZCCallbackHelper::DispatchWidgetEvent(localEvent);
|
||||
|
@ -1879,7 +1879,7 @@ TabChild::RecvMouseWheelEvent(const WidgetWheelEvent& aEvent,
|
|||
}
|
||||
|
||||
WidgetWheelEvent localEvent(aEvent);
|
||||
localEvent.widget = mPuppetWidget;
|
||||
localEvent.mWidget = mPuppetWidget;
|
||||
APZCCallbackHelper::ApplyCallbackTransform(localEvent, aGuid,
|
||||
mPuppetWidget->GetDefaultScale());
|
||||
APZCCallbackHelper::DispatchWidgetEvent(localEvent);
|
||||
|
@ -1923,7 +1923,7 @@ TabChild::RecvRealTouchEvent(const WidgetTouchEvent& aEvent,
|
|||
TABC_LOG("Receiving touch event of type %d\n", aEvent.mMessage);
|
||||
|
||||
WidgetTouchEvent localEvent(aEvent);
|
||||
localEvent.widget = mPuppetWidget;
|
||||
localEvent.mWidget = mPuppetWidget;
|
||||
|
||||
APZCCallbackHelper::ApplyCallbackTransform(localEvent, aGuid,
|
||||
mPuppetWidget->GetDefaultScale());
|
||||
|
@ -1968,7 +1968,7 @@ TabChild::RecvRealDragEvent(const WidgetDragEvent& aEvent,
|
|||
const uint32_t& aDropEffect)
|
||||
{
|
||||
WidgetDragEvent localEvent(aEvent);
|
||||
localEvent.widget = mPuppetWidget;
|
||||
localEvent.mWidget = mPuppetWidget;
|
||||
|
||||
nsCOMPtr<nsIDragSession> dragSession = nsContentUtils::GetDragSession();
|
||||
if (dragSession) {
|
||||
|
@ -2004,7 +2004,7 @@ bool
|
|||
TabChild::RecvPluginEvent(const WidgetPluginEvent& aEvent)
|
||||
{
|
||||
WidgetPluginEvent localEvent(aEvent);
|
||||
localEvent.widget = mPuppetWidget;
|
||||
localEvent.mWidget = mPuppetWidget;
|
||||
nsEventStatus status = APZCCallbackHelper::DispatchWidgetEvent(localEvent);
|
||||
if (status != nsEventStatus_eConsumeNoDefault) {
|
||||
// If not consumed, we should call default action
|
||||
|
@ -2063,7 +2063,7 @@ TabChild::RecvRealKeyEvent(const WidgetKeyboardEvent& event,
|
|||
}
|
||||
|
||||
WidgetKeyboardEvent localEvent(event);
|
||||
localEvent.widget = mPuppetWidget;
|
||||
localEvent.mWidget = mPuppetWidget;
|
||||
nsEventStatus status = APZCCallbackHelper::DispatchWidgetEvent(localEvent);
|
||||
|
||||
if (event.mMessage == eKeyDown) {
|
||||
|
@ -2098,7 +2098,7 @@ bool
|
|||
TabChild::RecvCompositionEvent(const WidgetCompositionEvent& event)
|
||||
{
|
||||
WidgetCompositionEvent localEvent(event);
|
||||
localEvent.widget = mPuppetWidget;
|
||||
localEvent.mWidget = mPuppetWidget;
|
||||
APZCCallbackHelper::DispatchWidgetEvent(localEvent);
|
||||
Unused << SendOnEventNeedingAckHandled(event.mMessage);
|
||||
return true;
|
||||
|
@ -2108,7 +2108,7 @@ bool
|
|||
TabChild::RecvSelectionEvent(const WidgetSelectionEvent& event)
|
||||
{
|
||||
WidgetSelectionEvent localEvent(event);
|
||||
localEvent.widget = mPuppetWidget;
|
||||
localEvent.mWidget = mPuppetWidget;
|
||||
APZCCallbackHelper::DispatchWidgetEvent(localEvent);
|
||||
Unused << SendOnEventNeedingAckHandled(event.mMessage);
|
||||
return true;
|
||||
|
|
|
@ -1250,7 +1250,7 @@ bool TabParent::RecvDispatchWheelEvent(const mozilla::WidgetWheelEvent& aEvent)
|
|||
}
|
||||
|
||||
WidgetWheelEvent localEvent(aEvent);
|
||||
localEvent.widget = widget;
|
||||
localEvent.mWidget = widget;
|
||||
localEvent.refPoint -= GetChildProcessOffset();
|
||||
|
||||
widget->DispatchInputEvent(&localEvent);
|
||||
|
@ -1266,7 +1266,7 @@ TabParent::RecvDispatchMouseEvent(const mozilla::WidgetMouseEvent& aEvent)
|
|||
}
|
||||
|
||||
WidgetMouseEvent localEvent(aEvent);
|
||||
localEvent.widget = widget;
|
||||
localEvent.mWidget = widget;
|
||||
localEvent.refPoint -= GetChildProcessOffset();
|
||||
|
||||
widget->DispatchInputEvent(&localEvent);
|
||||
|
@ -1282,7 +1282,7 @@ TabParent::RecvDispatchKeyboardEvent(const mozilla::WidgetKeyboardEvent& aEvent)
|
|||
}
|
||||
|
||||
WidgetKeyboardEvent localEvent(aEvent);
|
||||
localEvent.widget = widget;
|
||||
localEvent.mWidget = widget;
|
||||
localEvent.refPoint -= GetChildProcessOffset();
|
||||
|
||||
widget->DispatchInputEvent(&localEvent);
|
||||
|
@ -2020,7 +2020,7 @@ TabParent::RecvDispatchAfterKeyboardEvent(const WidgetKeyboardEvent& aEvent)
|
|||
NS_ENSURE_TRUE(mFrameElement, true);
|
||||
|
||||
WidgetKeyboardEvent localEvent(aEvent);
|
||||
localEvent.widget = GetWidget();
|
||||
localEvent.mWidget = GetWidget();
|
||||
|
||||
nsIDocument* doc = mFrameElement->OwnerDoc();
|
||||
nsCOMPtr<nsIPresShell> presShell = doc->GetShell();
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
|
||||
#include "AudioConverter.h"
|
||||
#include <string.h>
|
||||
#include <speex/speex_resampler.h>
|
||||
|
||||
/*
|
||||
* Parts derived from MythTV AudioConvert Class
|
||||
|
@ -20,9 +21,9 @@ namespace mozilla {
|
|||
AudioConverter::AudioConverter(const AudioConfig& aIn, const AudioConfig& aOut)
|
||||
: mIn(aIn)
|
||||
, mOut(aOut)
|
||||
, mResampler(nullptr)
|
||||
{
|
||||
MOZ_DIAGNOSTIC_ASSERT(aIn.Rate() == aOut.Rate() &&
|
||||
aIn.Format() == aOut.Format() &&
|
||||
MOZ_DIAGNOSTIC_ASSERT(aIn.Format() == aOut.Format() &&
|
||||
aIn.Interleaved() == aOut.Interleaved(),
|
||||
"No format or rate conversion is supported at this stage");
|
||||
MOZ_DIAGNOSTIC_ASSERT((aIn.Channels() > aOut.Channels() && aOut.Channels() <= 2) ||
|
||||
|
@ -30,28 +31,59 @@ AudioConverter::AudioConverter(const AudioConfig& aIn, const AudioConfig& aOut)
|
|||
"Only downmixing to mono or stereo is supported at this stage");
|
||||
MOZ_DIAGNOSTIC_ASSERT(aOut.Interleaved(), "planar audio format not supported");
|
||||
mIn.Layout().MappingTable(mOut.Layout(), mChannelOrderMap);
|
||||
if (aIn.Rate() != aOut.Rate()) {
|
||||
int error;
|
||||
mResampler = speex_resampler_init(aOut.Channels(),
|
||||
aIn.Rate(),
|
||||
aOut.Rate(),
|
||||
SPEEX_RESAMPLER_QUALITY_DEFAULT,
|
||||
&error);
|
||||
|
||||
if (error == RESAMPLER_ERR_SUCCESS) {
|
||||
speex_resampler_skip_zeros(mResampler);
|
||||
} else {
|
||||
NS_WARNING("Failed to initialize resampler.");
|
||||
mResampler = nullptr;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
AudioConverter::~AudioConverter()
|
||||
{
|
||||
if (mResampler) {
|
||||
speex_resampler_destroy(mResampler);
|
||||
mResampler = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
AudioConverter::CanWorkInPlace() const
|
||||
{
|
||||
return mIn.Channels() * mIn.Rate() * AudioConfig::SampleSize(mIn.Format()) >=
|
||||
mOut.Channels() * mOut.Rate() * AudioConfig::SampleSize(mOut.Format());
|
||||
bool needDownmix = mIn.Channels() > mOut.Channels();
|
||||
bool canDownmixInPlace =
|
||||
mIn.Channels() * AudioConfig::SampleSize(mIn.Format()) >=
|
||||
mOut.Channels() * AudioConfig::SampleSize(mOut.Format());
|
||||
bool needResample = mIn.Rate() != mOut.Rate();
|
||||
bool canResampleInPlace = mIn.Rate() >= mOut.Rate();
|
||||
// We should be able to work in place if 1s of audio input takes less space
|
||||
// than 1s of audio output. However, as we downmix before resampling we can't
|
||||
// perform any upsampling in place (e.g. if incoming rate >= outgoing rate)
|
||||
return (!needDownmix || canDownmixInPlace) &&
|
||||
(!needResample || canResampleInPlace);
|
||||
}
|
||||
|
||||
size_t
|
||||
AudioConverter::Process(void* aOut, const void* aIn, size_t aBytes)
|
||||
AudioConverter::ProcessInternal(void* aOut, const void* aIn, size_t aFrames)
|
||||
{
|
||||
if (!CanWorkInPlace()) {
|
||||
return 0;
|
||||
}
|
||||
if (mIn.Channels() > mOut.Channels()) {
|
||||
return DownmixAudio(aOut, aIn, aBytes);
|
||||
return DownmixAudio(aOut, aIn, aFrames);
|
||||
} else if (mIn.Layout() != mOut.Layout() &&
|
||||
CanReorderAudio()) {
|
||||
ReOrderInterleavedChannels(aOut, aIn, aBytes);
|
||||
ReOrderInterleavedChannels(aOut, aIn, aFrames);
|
||||
} else if (aIn != aOut) {
|
||||
memmove(aOut, aIn, FramesOutToBytes(aFrames));
|
||||
}
|
||||
return aBytes;
|
||||
return aFrames;
|
||||
}
|
||||
|
||||
// Reorder interleaved channels.
|
||||
|
@ -78,7 +110,7 @@ _ReOrderInterleavedChannels(AudioDataType* aOut, const AudioDataType* aIn,
|
|||
|
||||
void
|
||||
AudioConverter::ReOrderInterleavedChannels(void* aOut, const void* aIn,
|
||||
size_t aDataSize) const
|
||||
size_t aFrames) const
|
||||
{
|
||||
MOZ_DIAGNOSTIC_ASSERT(mIn.Channels() == mOut.Channels());
|
||||
|
||||
|
@ -89,7 +121,7 @@ AudioConverter::ReOrderInterleavedChannels(void* aOut, const void* aIn,
|
|||
// If channel count is 1, planar and non-planar formats are the same and
|
||||
// there's nothing to reorder.
|
||||
if (aOut != aIn) {
|
||||
memmove(aOut, aIn, aDataSize);
|
||||
memmove(aOut, aIn, FramesOutToBytes(aFrames));
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
@ -98,19 +130,16 @@ AudioConverter::ReOrderInterleavedChannels(void* aOut, const void* aIn,
|
|||
switch (bits) {
|
||||
case 8:
|
||||
_ReOrderInterleavedChannels((uint8_t*)aOut, (const uint8_t*)aIn,
|
||||
aDataSize/sizeof(uint8_t)/mIn.Channels(),
|
||||
mIn.Channels(), mChannelOrderMap);
|
||||
aFrames, mIn.Channels(), mChannelOrderMap);
|
||||
break;
|
||||
case 16:
|
||||
_ReOrderInterleavedChannels((int16_t*)aOut,(const int16_t*)aIn,
|
||||
aDataSize/sizeof(int16_t)/mIn.Channels(),
|
||||
mIn.Channels(), mChannelOrderMap);
|
||||
aFrames, mIn.Channels(), mChannelOrderMap);
|
||||
break;
|
||||
default:
|
||||
MOZ_DIAGNOSTIC_ASSERT(AudioConfig::SampleSize(mOut.Format()) == 4);
|
||||
_ReOrderInterleavedChannels((int32_t*)aOut,(const int32_t*)aIn,
|
||||
aDataSize/sizeof(int32_t)/mIn.Channels(),
|
||||
mIn.Channels(), mChannelOrderMap);
|
||||
aFrames, mIn.Channels(), mChannelOrderMap);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -121,7 +150,7 @@ static inline int16_t clipTo15(int32_t aX)
|
|||
}
|
||||
|
||||
size_t
|
||||
AudioConverter::DownmixAudio(void* aOut, const void* aIn, size_t aDataSize) const
|
||||
AudioConverter::DownmixAudio(void* aOut, const void* aIn, size_t aFrames) const
|
||||
{
|
||||
MOZ_ASSERT(mIn.Format() == AudioConfig::FORMAT_S16 ||
|
||||
mIn.Format() == AudioConfig::FORMAT_FLT);
|
||||
|
@ -132,14 +161,12 @@ AudioConverter::DownmixAudio(void* aOut, const void* aIn, size_t aDataSize) cons
|
|||
mOut.Layout() == AudioConfig::ChannelLayout(1));
|
||||
|
||||
uint32_t channels = mIn.Channels();
|
||||
uint32_t frames =
|
||||
aDataSize / AudioConfig::SampleSize(mOut.Format()) / channels;
|
||||
|
||||
if (channels == 1 && mOut.Channels() == 1) {
|
||||
if (aOut != aIn) {
|
||||
memmove(aOut, aIn, aDataSize);
|
||||
memmove(aOut, aIn, FramesOutToBytes(aFrames));
|
||||
}
|
||||
return aDataSize;
|
||||
return aFrames;
|
||||
}
|
||||
|
||||
if (channels > 2) {
|
||||
|
@ -156,7 +183,7 @@ AudioConverter::DownmixAudio(void* aOut, const void* aIn, size_t aDataSize) cons
|
|||
// Re-write the buffer with downmixed data
|
||||
const float* in = static_cast<const float*>(aIn);
|
||||
float* out = static_cast<float*>(aOut);
|
||||
for (uint32_t i = 0; i < frames; i++) {
|
||||
for (uint32_t i = 0; i < aFrames; i++) {
|
||||
float sampL = 0.0;
|
||||
float sampR = 0.0;
|
||||
for (uint32_t j = 0; j < channels; j++) {
|
||||
|
@ -180,7 +207,7 @@ AudioConverter::DownmixAudio(void* aOut, const void* aIn, size_t aDataSize) cons
|
|||
// Re-write the buffer with downmixed data
|
||||
const int16_t* in = static_cast<const int16_t*>(aIn);
|
||||
int16_t* out = static_cast<int16_t*>(aOut);
|
||||
for (uint32_t i = 0; i < frames; i++) {
|
||||
for (uint32_t i = 0; i < aFrames; i++) {
|
||||
int32_t sampL = 0;
|
||||
int32_t sampR = 0;
|
||||
for (uint32_t j = 0; j < channels; j++) {
|
||||
|
@ -204,7 +231,7 @@ AudioConverter::DownmixAudio(void* aOut, const void* aIn, size_t aDataSize) cons
|
|||
if (mIn.Format() == AudioConfig::FORMAT_FLT) {
|
||||
const float* in = static_cast<const float*>(aIn);
|
||||
float* out = static_cast<float*>(aOut);
|
||||
for (uint32_t fIdx = 0; fIdx < frames; ++fIdx) {
|
||||
for (uint32_t fIdx = 0; fIdx < aFrames; ++fIdx) {
|
||||
float sample = 0.0;
|
||||
// The sample of the buffer would be interleaved.
|
||||
sample = (in[fIdx*channels] + in[fIdx*channels + 1]) * 0.5;
|
||||
|
@ -213,7 +240,7 @@ AudioConverter::DownmixAudio(void* aOut, const void* aIn, size_t aDataSize) cons
|
|||
} else if (mIn.Format() == AudioConfig::FORMAT_S16) {
|
||||
const int16_t* in = static_cast<const int16_t*>(aIn);
|
||||
int16_t* out = static_cast<int16_t*>(aOut);
|
||||
for (uint32_t fIdx = 0; fIdx < frames; ++fIdx) {
|
||||
for (uint32_t fIdx = 0; fIdx < aFrames; ++fIdx) {
|
||||
int32_t sample = 0.0;
|
||||
// The sample of the buffer would be interleaved.
|
||||
sample = (in[fIdx*channels] + in[fIdx*channels + 1]) * 0.5;
|
||||
|
@ -223,7 +250,56 @@ AudioConverter::DownmixAudio(void* aOut, const void* aIn, size_t aDataSize) cons
|
|||
MOZ_DIAGNOSTIC_ASSERT(false, "Unsupported data type");
|
||||
}
|
||||
}
|
||||
return frames * AudioConfig::SampleSize(mOut.Format()) * mOut.Channels();
|
||||
return aFrames;
|
||||
}
|
||||
|
||||
} // namespace mozilla
|
||||
size_t
|
||||
AudioConverter::ResampleAudio(void* aOut, const void* aIn, size_t aFrames)
|
||||
{
|
||||
if (!mResampler) {
|
||||
return 0;
|
||||
}
|
||||
uint32_t outframes = ResampleRecipientFrames(aFrames);
|
||||
uint32_t inframes = aFrames;
|
||||
|
||||
if (mOut.Format() == AudioConfig::FORMAT_FLT) {
|
||||
const float* in = reinterpret_cast<const float*>(aIn);
|
||||
float* out = reinterpret_cast<float*>(aOut);
|
||||
speex_resampler_process_interleaved_float(mResampler, in, &inframes,
|
||||
out, &outframes);
|
||||
} else if (mOut.Format() == AudioConfig::FORMAT_S16) {
|
||||
const int16_t* in = reinterpret_cast<const int16_t*>(aIn);
|
||||
int16_t* out = reinterpret_cast<int16_t*>(aOut);
|
||||
speex_resampler_process_interleaved_int(mResampler, in, &inframes,
|
||||
out, &outframes);
|
||||
} else {
|
||||
MOZ_DIAGNOSTIC_ASSERT(false, "Unsupported data type");
|
||||
}
|
||||
MOZ_ASSERT(inframes == aFrames, "Some frames will be dropped");
|
||||
return outframes;
|
||||
}
|
||||
|
||||
size_t
|
||||
AudioConverter::ResampleRecipientFrames(size_t aFrames) const
|
||||
{
|
||||
return (uint64_t)aFrames * mOut.Rate() / mIn.Rate() + 1;
|
||||
}
|
||||
|
||||
size_t
|
||||
AudioConverter::FramesOutToSamples(size_t aFrames) const
|
||||
{
|
||||
return aFrames * mOut.Channels();
|
||||
}
|
||||
|
||||
size_t
|
||||
AudioConverter::SamplesInToFrames(size_t aSamples) const
|
||||
{
|
||||
return aSamples / mIn.Channels();
|
||||
}
|
||||
|
||||
size_t
|
||||
AudioConverter::FramesOutToBytes(size_t aFrames) const
|
||||
{
|
||||
return FramesOutToSamples(aFrames) * AudioConfig::SampleSize(mOut.Format());
|
||||
}
|
||||
} // namespace mozilla
|
||||
|
|
|
@ -9,6 +9,9 @@
|
|||
|
||||
#include "MediaInfo.h"
|
||||
|
||||
// Forward declaration
|
||||
typedef struct SpeexResamplerState_ SpeexResamplerState;
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
template <AudioConfig::SampleFormat T> struct AudioDataBufferTypeChooser;
|
||||
|
@ -87,6 +90,16 @@ public:
|
|||
static_assert(Format == AudioConfig::FORMAT_FLT,
|
||||
"Conversion not implemented yet");
|
||||
}
|
||||
AudioDataBuffer& operator=(AudioDataBuffer&& aOther)
|
||||
{
|
||||
mBuffer = Move(aOther.mBuffer);
|
||||
return *this;
|
||||
}
|
||||
AudioDataBuffer& operator=(const AudioDataBuffer& aOther)
|
||||
{
|
||||
mBuffer = aOther.mBuffer;
|
||||
return *this;
|
||||
}
|
||||
|
||||
Value* Data() const { return mBuffer.Data(); }
|
||||
size_t Length() const { return mBuffer.Length(); }
|
||||
|
@ -105,45 +118,110 @@ typedef AudioDataBuffer<AudioConfig::FORMAT_DEFAULT> AudioSampleBuffer;
|
|||
class AudioConverter {
|
||||
public:
|
||||
AudioConverter(const AudioConfig& aIn, const AudioConfig& aOut);
|
||||
~AudioConverter();
|
||||
|
||||
// Convert the AudioDataBuffer.
|
||||
// Conversion will be done in place if possible. Otherwise a new buffer will
|
||||
// be returned.
|
||||
template <AudioConfig::SampleFormat Format, typename Value>
|
||||
AudioDataBuffer<Format, Value> Process(AudioDataBuffer<Format, Value>&& aBuffer)
|
||||
{
|
||||
MOZ_DIAGNOSTIC_ASSERT(mIn.Format() == mOut.Format() && mIn.Format() == Format);
|
||||
AudioDataBuffer<Format, Value> buffer = Move(aBuffer);
|
||||
if (CanWorkInPlace()) {
|
||||
size_t frames = SamplesInToFrames(buffer.Length());
|
||||
frames = ProcessInternal(buffer.Data(), buffer.Data(), frames);
|
||||
if (frames && mIn.Rate() != mOut.Rate()) {
|
||||
frames = ResampleAudio(buffer.Data(), buffer.Data(), frames);
|
||||
}
|
||||
AlignedBuffer<Value> temp = buffer.Forget();
|
||||
temp.SetLength(FramesOutToSamples(frames));
|
||||
return AudioDataBuffer<Format, Value>(Move(temp));;
|
||||
}
|
||||
return Process(buffer);
|
||||
}
|
||||
|
||||
template <AudioConfig::SampleFormat Format, typename Value>
|
||||
AudioDataBuffer<Format, Value> Process(const AudioDataBuffer<Format, Value>& aBuffer)
|
||||
{
|
||||
MOZ_DIAGNOSTIC_ASSERT(mIn.Format() == mOut.Format() && mIn.Format() == Format);
|
||||
// Perform the downmixing / reordering in temporary buffer.
|
||||
size_t frames = SamplesInToFrames(aBuffer.Length());
|
||||
AlignedBuffer<Value> temp1;
|
||||
if (!temp1.SetLength(FramesOutToSamples(frames))) {
|
||||
return AudioDataBuffer<Format, Value>(Move(temp1));
|
||||
}
|
||||
frames = ProcessInternal(temp1.Data(), aBuffer.Data(), frames);
|
||||
if (!frames || mIn.Rate() == mOut.Rate()) {
|
||||
temp1.SetLength(FramesOutToSamples(frames));
|
||||
return AudioDataBuffer<Format, Value>(Move(temp1));
|
||||
}
|
||||
|
||||
// At this point, temp1 contains the buffer reordered and downmixed.
|
||||
// If we are downsampling we can re-use it.
|
||||
AlignedBuffer<Value>* outputBuffer = &temp1;
|
||||
AlignedBuffer<Value> temp2;
|
||||
if (mOut.Rate() > mIn.Rate()) {
|
||||
// We are upsampling, we can't work in place. Allocate another temporary
|
||||
// buffer where the upsampling will occur.
|
||||
temp2.SetLength(FramesOutToSamples(ResampleRecipientFrames(frames)));
|
||||
outputBuffer = &temp2;
|
||||
}
|
||||
frames = ResampleAudio(outputBuffer->Data(), temp1.Data(), frames);
|
||||
outputBuffer->SetLength(FramesOutToSamples(frames));
|
||||
return AudioDataBuffer<Format, Value>(Move(*outputBuffer));
|
||||
}
|
||||
|
||||
// Attempt to convert the AudioDataBuffer in place.
|
||||
// Will return 0 if the conversion wasn't possible.
|
||||
// Process may allocate memory internally should intermediary steps be
|
||||
// required.
|
||||
template <AudioConfig::SampleFormat Type, typename Value>
|
||||
size_t Process(AudioDataBuffer<Type, Value>& aBuffer)
|
||||
{
|
||||
MOZ_DIAGNOSTIC_ASSERT(mIn.Format() == mOut.Format() && mIn.Format() == Type);
|
||||
return Process(aBuffer.Data(), aBuffer.Data(), aBuffer.Size());
|
||||
}
|
||||
template <typename Value>
|
||||
size_t Process(Value* aBuffer, size_t aSamples)
|
||||
size_t Process(Value* aBuffer, size_t aFrames)
|
||||
{
|
||||
MOZ_DIAGNOSTIC_ASSERT(mIn.Format() == mOut.Format());
|
||||
return Process(aBuffer, aBuffer, aSamples * AudioConfig::SampleSize(mIn.Format()));
|
||||
if (!CanWorkInPlace()) {
|
||||
return 0;
|
||||
}
|
||||
size_t frames = ProcessInternal(aBuffer, aBuffer, aFrames);
|
||||
if (frames && mIn.Rate() != mOut.Rate()) {
|
||||
frames = ResampleAudio(aBuffer, aBuffer, aFrames);
|
||||
}
|
||||
return frames;
|
||||
}
|
||||
|
||||
bool CanWorkInPlace() const;
|
||||
bool CanReorderAudio() const
|
||||
{
|
||||
return mIn.Layout().MappingTable(mOut.Layout());
|
||||
}
|
||||
|
||||
const AudioConfig& InputConfig() const { return mIn; }
|
||||
const AudioConfig& OutputConfig() const { return mOut; }
|
||||
|
||||
private:
|
||||
const AudioConfig mIn;
|
||||
const AudioConfig mOut;
|
||||
uint8_t mChannelOrderMap[MAX_AUDIO_CHANNELS];
|
||||
/**
|
||||
* Process
|
||||
* ProcessInternal
|
||||
* Parameters:
|
||||
* aOut : destination buffer where converted samples will be copied
|
||||
* aIn : source buffer
|
||||
* aBytes: size in bytes of source buffer
|
||||
* aSamples: number of frames in source buffer
|
||||
*
|
||||
* Return Value: size in bytes of samples converted or 0 if error
|
||||
* Return Value: number of frames converted or 0 if error
|
||||
*/
|
||||
size_t Process(void* aOut, const void* aIn, size_t aBytes);
|
||||
void ReOrderInterleavedChannels(void* aOut, const void* aIn, size_t aDataSize) const;
|
||||
size_t DownmixAudio(void* aOut, const void* aIn, size_t aDataSize) const;
|
||||
size_t ProcessInternal(void* aOut, const void* aIn, size_t aFrames);
|
||||
void ReOrderInterleavedChannels(void* aOut, const void* aIn, size_t aFrames) const;
|
||||
size_t DownmixAudio(void* aOut, const void* aIn, size_t aFrames) const;
|
||||
|
||||
size_t FramesOutToSamples(size_t aFrames) const;
|
||||
size_t SamplesInToFrames(size_t aSamples) const;
|
||||
size_t FramesOutToBytes(size_t aFrames) const;
|
||||
|
||||
// Resampler context.
|
||||
SpeexResamplerState* mResampler;
|
||||
size_t ResampleAudio(void* aOut, const void* aIn, size_t aFrames);
|
||||
size_t ResampleRecipientFrames(size_t aFrames) const;
|
||||
};
|
||||
|
||||
} // namespace mozilla
|
||||
|
|
|
@ -331,7 +331,7 @@ AudioStream::Init(uint32_t aNumChannels, uint32_t aRate,
|
|||
("%s channels: %d, rate: %d for %p", __FUNCTION__, aNumChannels, aRate, this));
|
||||
mInRate = mOutRate = aRate;
|
||||
mChannels = aNumChannels;
|
||||
mOutChannels = (aNumChannels > 2) ? 2 : aNumChannels;
|
||||
mOutChannels = mIsMonoAudioEnabled ? 1 : aNumChannels;
|
||||
|
||||
mDumpFile = OpenDumpFile(this);
|
||||
|
||||
|
@ -353,9 +353,11 @@ AudioStream::Init(uint32_t aNumChannels, uint32_t aRate,
|
|||
params.format = ToCubebFormat<AUDIO_OUTPUT_FORMAT>::value;
|
||||
mAudioClock.Init();
|
||||
|
||||
AudioConfig inConfig(mChannels, mInRate);
|
||||
AudioConfig outConfig(mOutChannels, mOutRate);
|
||||
mAudioConverter = MakeUnique<AudioConverter>(inConfig, outConfig);
|
||||
if (mIsMonoAudioEnabled) {
|
||||
AudioConfig inConfig(mChannels, mInRate);
|
||||
AudioConfig outConfig(mOutChannels, mOutRate);
|
||||
mAudioConverter = MakeUnique<AudioConverter>(inConfig, outConfig);
|
||||
}
|
||||
return OpenCubeb(params);
|
||||
}
|
||||
|
||||
|
@ -561,14 +563,8 @@ AudioStream::Downmix(Chunk* aChunk)
|
|||
return false;
|
||||
}
|
||||
|
||||
if (aChunk->Channels() > 2) {
|
||||
MOZ_ASSERT(mAudioConverter);
|
||||
mAudioConverter->Process(aChunk->GetWritable(),
|
||||
aChunk->Channels() * aChunk->Frames());
|
||||
}
|
||||
|
||||
if (aChunk->Channels() >= 2 && mIsMonoAudioEnabled) {
|
||||
DownmixStereoToMono(aChunk->GetWritable(), aChunk->Frames());
|
||||
if (mAudioConverter) {
|
||||
mAudioConverter->Process(aChunk->GetWritable(), aChunk->Frames());
|
||||
}
|
||||
|
||||
return true;
|
||||
|
|
|
@ -604,6 +604,16 @@ public:
|
|||
{
|
||||
return mInterleaved;
|
||||
}
|
||||
bool operator==(const AudioConfig& aOther) const
|
||||
{
|
||||
return mChannelLayout == aOther.mChannelLayout &&
|
||||
mRate == aOther.mRate && mFormat == aOther.mFormat &&
|
||||
mInterleaved == aOther.mInterleaved;
|
||||
}
|
||||
bool operator!=(const AudioConfig& aOther) const
|
||||
{
|
||||
return !(*this == aOther);
|
||||
}
|
||||
|
||||
static const char* FormatToString(SampleFormat aFormat);
|
||||
static uint32_t SampleSize(SampleFormat aFormat);
|
||||
|
|
|
@ -34,10 +34,6 @@
|
|||
#include "gmp-audio-decode.h"
|
||||
#include "gmp-video-decode.h"
|
||||
|
||||
#if defined(XP_WIN) || defined(XP_MACOSX)
|
||||
#define PRIMETIME_EME_SUPPORTED 1
|
||||
#endif
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
|
||||
|
@ -280,7 +276,7 @@ MediaKeySystemAccess::GetKeySystemStatus(const nsAString& aKeySystem,
|
|||
return EnsureMinCDMVersion(mps, aKeySystem, aMinCdmVersion, aOutMessage, aOutCdmVersion);
|
||||
}
|
||||
|
||||
#ifdef PRIMETIME_EME_SUPPORTED
|
||||
#ifdef MOZ_ADOBE_EME
|
||||
if (aKeySystem.EqualsLiteral("com.adobe.primetime")) {
|
||||
if (!Preferences::GetBool("media.gmp-eme-adobe.enabled", false)) {
|
||||
aOutMessage = NS_LITERAL_CSTRING("Adobe EME disabled");
|
||||
|
|
|
@ -8,9 +8,11 @@
|
|||
#include "MediaQueue.h"
|
||||
#include "DecodedAudioDataSink.h"
|
||||
#include "VideoUtils.h"
|
||||
#include "AudioConverter.h"
|
||||
|
||||
#include "mozilla/CheckedInt.h"
|
||||
#include "mozilla/DebugOnly.h"
|
||||
#include "gfxPrefs.h"
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
|
@ -40,6 +42,14 @@ DecodedAudioDataSink::DecodedAudioDataSink(MediaQueue<MediaData>& aAudioQueue,
|
|||
, mPlaying(true)
|
||||
, mPlaybackComplete(false)
|
||||
{
|
||||
bool resampling = gfxPrefs::AudioSinkResampling();
|
||||
uint32_t resamplingRate = gfxPrefs::AudioSinkResampleRate();
|
||||
mConverter =
|
||||
MakeUnique<AudioConverter>(
|
||||
AudioConfig(mInfo.mChannels, mInfo.mRate),
|
||||
AudioConfig(mInfo.mChannels > 2 && gfxPrefs::AudioSinkForceStereo()
|
||||
? 2 : mInfo.mChannels,
|
||||
resampling ? resamplingRate : mInfo.mRate));
|
||||
}
|
||||
|
||||
DecodedAudioDataSink::~DecodedAudioDataSink()
|
||||
|
@ -136,7 +146,9 @@ nsresult
|
|||
DecodedAudioDataSink::InitializeAudioStream(const PlaybackParams& aParams)
|
||||
{
|
||||
mAudioStream = new AudioStream(*this);
|
||||
nsresult rv = mAudioStream->Init(mInfo.mChannels, mInfo.mRate, mChannel);
|
||||
nsresult rv = mAudioStream->Init(mConverter->OutputConfig().Channels(),
|
||||
mConverter->OutputConfig().Rate(),
|
||||
mChannel);
|
||||
if (NS_FAILED(rv)) {
|
||||
mAudioStream->Shutdown();
|
||||
mAudioStream = nullptr;
|
||||
|
@ -156,7 +168,8 @@ DecodedAudioDataSink::InitializeAudioStream(const PlaybackParams& aParams)
|
|||
int64_t
|
||||
DecodedAudioDataSink::GetEndTime() const
|
||||
{
|
||||
CheckedInt64 playedUsecs = FramesToUsecs(mWritten, mInfo.mRate) + mStartTime;
|
||||
CheckedInt64 playedUsecs =
|
||||
FramesToUsecs(mWritten, mConverter->OutputConfig().Rate()) + mStartTime;
|
||||
if (!playedUsecs.isValid()) {
|
||||
NS_WARNING("Int overflow calculating audio end time");
|
||||
return -1;
|
||||
|
@ -231,9 +244,11 @@ DecodedAudioDataSink::PopFrames(uint32_t aFrames)
|
|||
// audio hardware, so we can play across the gap.
|
||||
// Calculate the timestamp of the next chunk of audio in numbers of
|
||||
// samples.
|
||||
CheckedInt64 sampleTime = UsecsToFrames(AudioQueue().PeekFront()->mTime, mInfo.mRate);
|
||||
CheckedInt64 sampleTime = UsecsToFrames(AudioQueue().PeekFront()->mTime,
|
||||
mConverter->OutputConfig().Rate());
|
||||
// Calculate the number of frames that have been pushed onto the audio hardware.
|
||||
CheckedInt64 playedFrames = UsecsToFrames(mStartTime, mInfo.mRate) +
|
||||
CheckedInt64 playedFrames = UsecsToFrames(mStartTime,
|
||||
mConverter->OutputConfig().Rate()) +
|
||||
static_cast<int64_t>(mWritten);
|
||||
CheckedInt64 missingFrames = sampleTime - playedFrames;
|
||||
|
||||
|
@ -243,6 +258,9 @@ DecodedAudioDataSink::PopFrames(uint32_t aFrames)
|
|||
return MakeUnique<Chunk>();
|
||||
}
|
||||
|
||||
const uint32_t rate = mConverter->OutputConfig().Rate();
|
||||
const uint32_t channels = mConverter->OutputConfig().Channels();
|
||||
|
||||
if (missingFrames.value() > AUDIO_FUZZ_FRAMES) {
|
||||
// The next audio chunk begins some time after the end of the last chunk
|
||||
// we pushed to the audio hardware. We must push silence into the audio
|
||||
|
@ -251,10 +269,26 @@ DecodedAudioDataSink::PopFrames(uint32_t aFrames)
|
|||
missingFrames = std::min<int64_t>(UINT32_MAX, missingFrames.value());
|
||||
auto framesToPop = std::min<uint32_t>(missingFrames.value(), aFrames);
|
||||
mWritten += framesToPop;
|
||||
return MakeUnique<SilentChunk>(framesToPop, mInfo.mChannels, mInfo.mRate);
|
||||
return MakeUnique<SilentChunk>(framesToPop, channels, rate);
|
||||
}
|
||||
|
||||
RefPtr<AudioData> data =
|
||||
dont_AddRef(AudioQueue().PopFront().take()->As<AudioData>());
|
||||
if (mConverter->InputConfig() != mConverter->OutputConfig()) {
|
||||
AlignedAudioBuffer convertedData =
|
||||
mConverter->Process(AudioSampleBuffer(Move(data->mAudioData))).Forget();
|
||||
mCurrentData =
|
||||
new AudioData(data->mOffset,
|
||||
data->mTime,
|
||||
data->mDuration,
|
||||
convertedData.Length() / channels,
|
||||
Move(convertedData),
|
||||
channels,
|
||||
rate);
|
||||
} else {
|
||||
mCurrentData = Move(data);
|
||||
}
|
||||
|
||||
mCurrentData = dont_AddRef(AudioQueue().PopFront().take()->As<AudioData>());
|
||||
mCursor = MakeUnique<AudioBufferCursor>(mCurrentData->mAudioData.get(),
|
||||
mCurrentData->mChannels,
|
||||
mCurrentData->mFrames);
|
||||
|
|
|
@ -21,6 +21,8 @@
|
|||
|
||||
namespace mozilla {
|
||||
|
||||
class AudioConverter;
|
||||
|
||||
namespace media {
|
||||
|
||||
class DecodedAudioDataSink : public AudioSink,
|
||||
|
@ -97,13 +99,15 @@ private:
|
|||
*/
|
||||
// The AudioData at which AudioStream::DataSource is reading.
|
||||
RefPtr<AudioData> mCurrentData;
|
||||
// Keep track of the read positoin of mCurrentData.
|
||||
// Keep track of the read position of mCurrentData.
|
||||
UniquePtr<AudioBufferCursor> mCursor;
|
||||
// True if there is any error in processing audio data like overflow.
|
||||
bool mErrored = false;
|
||||
|
||||
// Set on the callback thread of cubeb once the stream has drained.
|
||||
Atomic<bool> mPlaybackComplete;
|
||||
|
||||
UniquePtr<AudioConverter> mConverter;
|
||||
};
|
||||
|
||||
} // namespace media
|
||||
|
|
|
@ -227,7 +227,7 @@ VorbisDataDecoder::DoDecode(MediaRawData* aSample)
|
|||
}
|
||||
MOZ_ASSERT(mAudioConverter->CanWorkInPlace());
|
||||
AudioSampleBuffer data(Move(buffer));
|
||||
mAudioConverter->Process(data);
|
||||
data = mAudioConverter->Process(Move(data));
|
||||
|
||||
aTotalFrames += frames;
|
||||
mCallback->Output(new AudioData(aOffset,
|
||||
|
|
|
@ -287,7 +287,7 @@ AppleATDecoder::DecodeSample(MediaRawData* aSample)
|
|||
}
|
||||
if (mAudioConverter) {
|
||||
MOZ_ASSERT(mAudioConverter->CanWorkInPlace());
|
||||
mAudioConverter->Process(data);
|
||||
data = mAudioConverter->Process(Move(data));
|
||||
}
|
||||
|
||||
RefPtr<AudioData> audio = new AudioData(aSample->mOffset,
|
||||
|
|
|
@ -765,6 +765,7 @@ skip-if = toolkit == 'gonk' # bug 1128845
|
|||
[test_preload_actions.html]
|
||||
[test_preload_attribute.html]
|
||||
[test_preload_suspend.html]
|
||||
[test_preserve_playbackrate_after_ui_play.html]
|
||||
[test_progress.html]
|
||||
[test_reactivate.html]
|
||||
skip-if = toolkit == 'gonk' # bug 1128845 on gonk
|
||||
|
|
|
@ -0,0 +1,60 @@
|
|||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<head>
|
||||
<title> Bug 1013933 - preserve playbackRate after clicking play button </title>
|
||||
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<script type="application/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
|
||||
<script type="application/javascript" src="browserElementTestHelpers.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<div id="content">
|
||||
<video width="320" height="240" id="video" controls mozNoDynamicControls preload="auto"></video>
|
||||
</div>
|
||||
|
||||
<script type="text/javascript">
|
||||
/*
|
||||
* Positions of the UI elements, relative to the upper-left corner of the
|
||||
* <video> box.
|
||||
*/
|
||||
const videoHeight = 240;
|
||||
const playButtonWidth = 28;
|
||||
const playButtonHeight = 28;
|
||||
const playButtonCenterX = 0 + Math.round(playButtonWidth / 2);
|
||||
const playButtonCenterY = videoHeight - Math.round(playButtonHeight / 2);
|
||||
|
||||
var expectedPlaybackRate = 0.5
|
||||
|
||||
function runTest() {
|
||||
var video = document.getElementById("video");
|
||||
video.src = "audio.wav";
|
||||
video.loop = true;
|
||||
video.playbackRate = expectedPlaybackRate;
|
||||
|
||||
video.oncanplaythrough = function() {
|
||||
video.oncanplaythrough = null;
|
||||
is(video.paused, true, "video is not playing yet.");
|
||||
is(video.playbackRate, expectedPlaybackRate,
|
||||
"playbackRate is correct before clicking play button.");
|
||||
|
||||
// Click the play button
|
||||
synthesizeMouse(video, playButtonCenterX, playButtonCenterY, { });
|
||||
};
|
||||
|
||||
video.onplay = function() {
|
||||
video.onplay = null;
|
||||
is(video.paused, false, "video starts playing.");
|
||||
is(video.playbackRate, expectedPlaybackRate,
|
||||
"playbackRate is correct after clicking play button.");
|
||||
video.pause();
|
||||
SimpleTest.finish();
|
||||
};
|
||||
}
|
||||
|
||||
window.addEventListener("load", runTest, false);
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
</script>
|
||||
</pre>
|
||||
</body>
|
||||
</html>
|
|
@ -628,8 +628,6 @@ WAVTrackDemuxer::Read(uint8_t* aBuffer, int64_t aOffset, int32_t aSize)
|
|||
uint32_t
|
||||
RIFFParser::Parse(ByteReader& aReader)
|
||||
{
|
||||
MOZ_ASSERT(&aReader);
|
||||
|
||||
while (aReader.CanRead8() && !mRiffHeader.ParseNext(aReader.ReadU8())) { }
|
||||
|
||||
if (mRiffHeader.IsValid()) {
|
||||
|
@ -784,8 +782,6 @@ HeaderParser::ChunkHeader::Update(uint8_t c)
|
|||
uint32_t
|
||||
FormatParser::Parse(ByteReader& aReader)
|
||||
{
|
||||
MOZ_ASSERT(&aReader);
|
||||
|
||||
while (aReader.CanRead8() && !mFmtChunk.ParseNext(aReader.ReadU8())) { }
|
||||
|
||||
if (mFmtChunk.IsValid()) {
|
||||
|
|
|
@ -0,0 +1,29 @@
|
|||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim:set ts=2 sw=2 sts=2 et cindent: */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#ifndef AlignmentUtils_h__
|
||||
#define AlignmentUtils_h__
|
||||
|
||||
#define IS_ALIGNED16(ptr) ((((uintptr_t)ptr + 15) & ~0x0F) == (uintptr_t)ptr)
|
||||
|
||||
#ifdef DEBUG
|
||||
#define ASSERT_ALIGNED16(ptr) \
|
||||
MOZ_ASSERT(IS_ALIGNED16(ptr), \
|
||||
#ptr " has to be aligned to a 16 byte boundary");
|
||||
#else
|
||||
#define ASSERT_ALIGNED16(ptr)
|
||||
#endif
|
||||
|
||||
#ifdef DEBUG
|
||||
#define ASSERT_MULTIPLE16(v) \
|
||||
MOZ_ASSERT(v % 16 == 0, #v " has to be a a multiple of 16");
|
||||
#else
|
||||
#define ASSERT_MULTIPLE16(v)
|
||||
#endif
|
||||
|
||||
#define ALIGNED16(ptr) (float*)(((uintptr_t)ptr + 15) & ~0x0F);
|
||||
|
||||
#endif
|
|
@ -5,6 +5,7 @@
|
|||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "AudioBlock.h"
|
||||
#include "AlignmentUtils.h"
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
|
@ -17,9 +18,7 @@ namespace mozilla {
|
|||
* buffer can reuse and modify its contents next iteration if other references
|
||||
* are all downstream temporary references held by AudioBlock.
|
||||
*
|
||||
* This only guarantees 4-byte alignment of the data. For alignment we simply
|
||||
* assume that the memory from malloc is at least 4-byte aligned and that
|
||||
* AudioBlockBuffer's size is divisible by 4.
|
||||
* We guarantee 16 byte alignment of the channel data.
|
||||
*/
|
||||
class AudioBlockBuffer final : public ThreadSharedObject {
|
||||
public:
|
||||
|
@ -28,7 +27,9 @@ public:
|
|||
|
||||
float* ChannelData(uint32_t aChannel)
|
||||
{
|
||||
return reinterpret_cast<float*>(this + 1) + aChannel * WEBAUDIO_BLOCK_SIZE;
|
||||
float* base = reinterpret_cast<float*>(((uintptr_t)(this + 1) + 15) & ~0x0F);
|
||||
ASSERT_ALIGNED16(base);
|
||||
return base + aChannel * WEBAUDIO_BLOCK_SIZE;
|
||||
}
|
||||
|
||||
static already_AddRefed<AudioBlockBuffer> Create(uint32_t aChannelCount)
|
||||
|
@ -37,9 +38,11 @@ public:
|
|||
size *= aChannelCount;
|
||||
size *= sizeof(float);
|
||||
size += sizeof(AudioBlockBuffer);
|
||||
size += 15; //padding for alignment
|
||||
if (!size.isValid()) {
|
||||
MOZ_CRASH();
|
||||
}
|
||||
|
||||
void* m = moz_xmalloc(size.value());
|
||||
RefPtr<AudioBlockBuffer> p = new (m) AudioBlockBuffer();
|
||||
NS_ASSERTION((reinterpret_cast<char*>(p.get() + 1) - reinterpret_cast<char*>(p.get())) % 4 == 0,
|
||||
|
@ -150,8 +153,6 @@ AudioBlock::AllocateChannels(uint32_t aChannelCount)
|
|||
}
|
||||
}
|
||||
|
||||
// XXX for SIMD purposes we should do something here to make sure the
|
||||
// channel buffers are 16-byte aligned.
|
||||
RefPtr<AudioBlockBuffer> buffer = AudioBlockBuffer::Create(aChannelCount);
|
||||
mChannelData.SetLength(aChannelCount);
|
||||
for (uint32_t i = 0; i < aChannelCount; ++i) {
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "AudioDestinationNode.h"
|
||||
#include "AlignmentUtils.h"
|
||||
#include "AudioContext.h"
|
||||
#include "mozilla/dom/AudioDestinationNodeBinding.h"
|
||||
#include "mozilla/dom/ScriptSettings.h"
|
||||
|
@ -87,7 +88,7 @@ public:
|
|||
PodZero(outputData, duration);
|
||||
} else {
|
||||
const float* inputBuffer = static_cast<const float*>(aInput.mChannelData[i]);
|
||||
if (duration == WEBAUDIO_BLOCK_SIZE) {
|
||||
if (duration == WEBAUDIO_BLOCK_SIZE && IS_ALIGNED16(inputBuffer)) {
|
||||
// Use the optimized version of the copy with scale operation
|
||||
AudioBlockCopyChannelWithScale(inputBuffer, aInput.mVolume,
|
||||
outputData);
|
||||
|
|
|
@ -9,6 +9,9 @@
|
|||
#include "mozilla/arm.h"
|
||||
#include "AudioNodeEngineNEON.h"
|
||||
#endif
|
||||
#ifdef USE_SSE2
|
||||
#include "AudioNodeEngineSSE2.h"
|
||||
#endif
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
|
@ -71,6 +74,14 @@ void AudioBufferAddWithScale(const float* aInput,
|
|||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef USE_SSE2
|
||||
if (mozilla::supports_sse2()) {
|
||||
AudioBufferAddWithScale_SSE(aInput, aScale, aOutput, aSize);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (aScale == 1.0f) {
|
||||
for (uint32_t i = 0; i < aSize; ++i) {
|
||||
aOutput[i] += aInput[i];
|
||||
|
@ -104,6 +115,14 @@ AudioBlockCopyChannelWithScale(const float* aInput,
|
|||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef USE_SSE2
|
||||
if (mozilla::supports_sse2()) {
|
||||
AudioBlockCopyChannelWithScale_SSE(aInput, aScale, aOutput);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
for (uint32_t i = 0; i < WEBAUDIO_BLOCK_SIZE; ++i) {
|
||||
aOutput[i] = aInput[i]*aScale;
|
||||
}
|
||||
|
@ -116,6 +135,14 @@ BufferComplexMultiply(const float* aInput,
|
|||
float* aOutput,
|
||||
uint32_t aSize)
|
||||
{
|
||||
|
||||
#ifdef USE_SSE2
|
||||
if (mozilla::supports_sse()) {
|
||||
BufferComplexMultiply_SSE(aInput, aScale, aOutput, aSize);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
for (uint32_t i = 0; i < aSize * 2; i += 2) {
|
||||
float real1 = aInput[i];
|
||||
float imag1 = aInput[i + 1];
|
||||
|
@ -152,6 +179,14 @@ AudioBlockCopyChannelWithScale(const float aInput[WEBAUDIO_BLOCK_SIZE],
|
|||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef USE_SSE2
|
||||
if (mozilla::supports_sse2()) {
|
||||
AudioBlockCopyChannelWithScale_SSE(aInput, aScale, aOutput);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
for (uint32_t i = 0; i < WEBAUDIO_BLOCK_SIZE; ++i) {
|
||||
aOutput[i] = aInput[i]*aScale[i];
|
||||
}
|
||||
|
@ -178,6 +213,14 @@ AudioBufferInPlaceScale(float* aBlock,
|
|||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef USE_SSE2
|
||||
if (mozilla::supports_sse2()) {
|
||||
AudioBufferInPlaceScale_SSE(aBlock, aScale, aSize);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
for (uint32_t i = 0; i < aSize; ++i) {
|
||||
*aBlock++ *= aScale;
|
||||
}
|
||||
|
@ -220,6 +263,15 @@ AudioBlockPanStereoToStereo(const float aInputL[WEBAUDIO_BLOCK_SIZE],
|
|||
}
|
||||
#endif
|
||||
|
||||
#ifdef USE_SSE2
|
||||
if (mozilla::supports_sse2()) {
|
||||
AudioBlockPanStereoToStereo_SSE(aInputL, aInputR,
|
||||
aGainL, aGainR, aIsOnTheLeft,
|
||||
aOutputL, aOutputR);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
uint32_t i;
|
||||
|
||||
if (aIsOnTheLeft) {
|
||||
|
@ -269,6 +321,27 @@ float
|
|||
AudioBufferSumOfSquares(const float* aInput, uint32_t aLength)
|
||||
{
|
||||
float sum = 0.0f;
|
||||
|
||||
#ifdef USE_SSE2
|
||||
if (mozilla::supports_sse()) {
|
||||
const float* alignedInput = ALIGNED16(aInput);
|
||||
float vLength = (aLength >> 4) << 4;
|
||||
|
||||
// use scalar operations for any unaligned data at the beginning
|
||||
while (aInput != alignedInput) {
|
||||
sum += *aInput * *aInput;
|
||||
++aInput;
|
||||
}
|
||||
|
||||
sum += AudioBufferSumOfSquares_SSE(alignedInput, vLength);
|
||||
|
||||
// adjust aInput and aLength to use scalar operations for any
|
||||
// remaining values
|
||||
aInput = alignedInput + 1;
|
||||
aLength -= vLength;
|
||||
}
|
||||
#endif
|
||||
|
||||
while (aLength--) {
|
||||
sum += *aInput * *aInput;
|
||||
++aInput;
|
||||
|
|
|
@ -0,0 +1,315 @@
|
|||
/* -*- mode: c++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* this source code form is subject to the terms of the mozilla public
|
||||
* license, v. 2.0. if a copy of the mpl was not distributed with this file,
|
||||
* You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "AlignmentUtils.h"
|
||||
#include "AudioNodeEngineSSE2.h"
|
||||
#include <emmintrin.h>
|
||||
|
||||
|
||||
namespace mozilla {
|
||||
void
|
||||
AudioBufferAddWithScale_SSE(const float* aInput,
|
||||
float aScale,
|
||||
float* aOutput,
|
||||
uint32_t aSize)
|
||||
{
|
||||
__m128 vin0, vin1, vin2, vin3,
|
||||
vscaled0, vscaled1, vscaled2, vscaled3,
|
||||
vout0, vout1, vout2, vout3,
|
||||
vgain;
|
||||
|
||||
ASSERT_ALIGNED16(aInput);
|
||||
ASSERT_ALIGNED16(aOutput);
|
||||
ASSERT_MULTIPLE16(aSize);
|
||||
|
||||
vgain = _mm_load1_ps(&aScale);
|
||||
|
||||
for (unsigned i = 0; i < aSize; i+=16) {
|
||||
vin0 = _mm_load_ps(&aInput[i]);
|
||||
vin1 = _mm_load_ps(&aInput[i + 4]);
|
||||
vin2 = _mm_load_ps(&aInput[i + 8]);
|
||||
vin3 = _mm_load_ps(&aInput[i + 12]);
|
||||
|
||||
vscaled0 = _mm_mul_ps(vin0, vgain);
|
||||
vscaled1 = _mm_mul_ps(vin1, vgain);
|
||||
vscaled2 = _mm_mul_ps(vin2, vgain);
|
||||
vscaled3 = _mm_mul_ps(vin3, vgain);
|
||||
|
||||
vin0 = _mm_load_ps(&aOutput[i]);
|
||||
vin1 = _mm_load_ps(&aOutput[i + 4]);
|
||||
vin2 = _mm_load_ps(&aOutput[i + 8]);
|
||||
vin3 = _mm_load_ps(&aOutput[i + 12]);
|
||||
|
||||
vout0 = _mm_add_ps(vin0, vscaled0);
|
||||
vout1 = _mm_add_ps(vin1, vscaled1);
|
||||
vout2 = _mm_add_ps(vin2, vscaled2);
|
||||
vout3 = _mm_add_ps(vin3, vscaled3);
|
||||
|
||||
_mm_store_ps(&aOutput[i], vout0);
|
||||
_mm_store_ps(&aOutput[i + 4], vout1);
|
||||
_mm_store_ps(&aOutput[i + 8], vout2);
|
||||
_mm_store_ps(&aOutput[i + 12], vout3);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
AudioBlockCopyChannelWithScale_SSE(const float* aInput,
|
||||
float aScale,
|
||||
float* aOutput)
|
||||
{
|
||||
__m128 vin0, vin1, vin2, vin3,
|
||||
vout0, vout1, vout2, vout3;
|
||||
|
||||
ASSERT_ALIGNED16(aInput);
|
||||
ASSERT_ALIGNED16(aOutput);
|
||||
|
||||
__m128 vgain = _mm_load1_ps(&aScale);
|
||||
|
||||
for (unsigned i = 0 ; i < WEBAUDIO_BLOCK_SIZE; i+=16) {
|
||||
vin0 = _mm_load_ps(&aInput[i]);
|
||||
vin1 = _mm_load_ps(&aInput[i + 4]);
|
||||
vin2 = _mm_load_ps(&aInput[i + 8]);
|
||||
vin3 = _mm_load_ps(&aInput[i + 12]);
|
||||
vout0 = _mm_mul_ps(vin0, vgain);
|
||||
vout1 = _mm_mul_ps(vin1, vgain);
|
||||
vout2 = _mm_mul_ps(vin2, vgain);
|
||||
vout3 = _mm_mul_ps(vin3, vgain);
|
||||
_mm_store_ps(&aOutput[i], vout0);
|
||||
_mm_store_ps(&aOutput[i + 4], vout1);
|
||||
_mm_store_ps(&aOutput[i + 8], vout2);
|
||||
_mm_store_ps(&aOutput[i + 12], vout3);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
AudioBlockCopyChannelWithScale_SSE(const float aInput[WEBAUDIO_BLOCK_SIZE],
|
||||
const float aScale[WEBAUDIO_BLOCK_SIZE],
|
||||
float aOutput[WEBAUDIO_BLOCK_SIZE])
|
||||
{
|
||||
__m128 vin0, vin1, vin2, vin3,
|
||||
vscaled0, vscaled1, vscaled2, vscaled3,
|
||||
vout0, vout1, vout2, vout3;
|
||||
|
||||
ASSERT_ALIGNED16(aInput);
|
||||
ASSERT_ALIGNED16(aScale);
|
||||
ASSERT_ALIGNED16(aOutput);
|
||||
|
||||
for (unsigned i = 0 ; i < WEBAUDIO_BLOCK_SIZE; i+=16) {
|
||||
vscaled0 = _mm_load_ps(&aScale[i]);
|
||||
vscaled1 = _mm_load_ps(&aScale[i+4]);
|
||||
vscaled2 = _mm_load_ps(&aScale[i+8]);
|
||||
vscaled3 = _mm_load_ps(&aScale[i+12]);
|
||||
|
||||
vin0 = _mm_load_ps(&aInput[i]);
|
||||
vin1 = _mm_load_ps(&aInput[i + 4]);
|
||||
vin2 = _mm_load_ps(&aInput[i + 8]);
|
||||
vin3 = _mm_load_ps(&aInput[i + 12]);
|
||||
|
||||
vout0 = _mm_mul_ps(vin0, vscaled0);
|
||||
vout1 = _mm_mul_ps(vin1, vscaled1);
|
||||
vout2 = _mm_mul_ps(vin2, vscaled2);
|
||||
vout3 = _mm_mul_ps(vin3, vscaled3);
|
||||
|
||||
_mm_store_ps(&aOutput[i], vout0);
|
||||
_mm_store_ps(&aOutput[i + 4], vout1);
|
||||
_mm_store_ps(&aOutput[i + 8], vout2);
|
||||
_mm_store_ps(&aOutput[i + 12], vout3);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
AudioBufferInPlaceScale_SSE(float* aBlock,
|
||||
float aScale,
|
||||
uint32_t aSize)
|
||||
{
|
||||
__m128 vout0, vout1, vout2, vout3,
|
||||
vin0, vin1, vin2, vin3;
|
||||
|
||||
ASSERT_ALIGNED16(aBlock);
|
||||
ASSERT_MULTIPLE16(aSize);
|
||||
|
||||
__m128 vgain = _mm_load1_ps(&aScale);
|
||||
|
||||
for (unsigned i = 0; i < aSize; i+=16) {
|
||||
vin0 = _mm_load_ps(&aBlock[i]);
|
||||
vin1 = _mm_load_ps(&aBlock[i + 4]);
|
||||
vin2 = _mm_load_ps(&aBlock[i + 8]);
|
||||
vin3 = _mm_load_ps(&aBlock[i + 12]);
|
||||
vout0 = _mm_mul_ps(vin0, vgain);
|
||||
vout1 = _mm_mul_ps(vin1, vgain);
|
||||
vout2 = _mm_mul_ps(vin2, vgain);
|
||||
vout3 = _mm_mul_ps(vin3, vgain);
|
||||
_mm_store_ps(&aBlock[i], vout0);
|
||||
_mm_store_ps(&aBlock[i + 4], vout1);
|
||||
_mm_store_ps(&aBlock[i + 8], vout2);
|
||||
_mm_store_ps(&aBlock[i + 12], vout3);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
AudioBlockPanStereoToStereo_SSE(const float aInputL[WEBAUDIO_BLOCK_SIZE],
|
||||
const float aInputR[WEBAUDIO_BLOCK_SIZE],
|
||||
float aGainL, float aGainR, bool aIsOnTheLeft,
|
||||
float aOutputL[WEBAUDIO_BLOCK_SIZE],
|
||||
float aOutputR[WEBAUDIO_BLOCK_SIZE])
|
||||
{
|
||||
__m128 vinl0, vinr0, vinl1, vinr1,
|
||||
vout0, vout1,
|
||||
vscaled0, vscaled1,
|
||||
vgainl, vgainr;
|
||||
|
||||
ASSERT_ALIGNED16(aInputL);
|
||||
ASSERT_ALIGNED16(aInputR);
|
||||
ASSERT_ALIGNED16(aOutputL);
|
||||
ASSERT_ALIGNED16(aOutputR);
|
||||
|
||||
vgainl = _mm_load1_ps(&aGainL);
|
||||
vgainr = _mm_load1_ps(&aGainR);
|
||||
|
||||
if (aIsOnTheLeft) {
|
||||
for (unsigned i = 0; i < WEBAUDIO_BLOCK_SIZE; i+=8) {
|
||||
vinl0 = _mm_load_ps(&aInputL[i]);
|
||||
vinr0 = _mm_load_ps(&aInputR[i]);
|
||||
vinl1 = _mm_load_ps(&aInputL[i+4]);
|
||||
vinr1 = _mm_load_ps(&aInputR[i+4]);
|
||||
|
||||
/* left channel : aOutputL = aInputL + aInputR * gainL */
|
||||
vscaled0 = _mm_mul_ps(vinr0, vgainl);
|
||||
vscaled1 = _mm_mul_ps(vinr1, vgainl);
|
||||
vout0 = _mm_add_ps(vscaled0, vinl0);
|
||||
vout1 = _mm_add_ps(vscaled1, vinl1);
|
||||
_mm_store_ps(&aOutputL[i], vout0);
|
||||
_mm_store_ps(&aOutputL[i+4], vout1);
|
||||
|
||||
/* right channel : aOutputR = aInputR * gainR */
|
||||
vscaled0 = _mm_mul_ps(vinr0, vgainr);
|
||||
vscaled1 = _mm_mul_ps(vinr1, vgainr);
|
||||
_mm_store_ps(&aOutputR[i], vscaled0);
|
||||
_mm_store_ps(&aOutputR[i+4], vscaled1);
|
||||
}
|
||||
} else {
|
||||
for (unsigned i = 0; i < WEBAUDIO_BLOCK_SIZE; i+=8) {
|
||||
vinl0 = _mm_load_ps(&aInputL[i]);
|
||||
vinr0 = _mm_load_ps(&aInputR[i]);
|
||||
vinl1 = _mm_load_ps(&aInputL[i+4]);
|
||||
vinr1 = _mm_load_ps(&aInputR[i+4]);
|
||||
|
||||
/* left channel : aInputL * gainL */
|
||||
vscaled0 = _mm_mul_ps(vinl0, vgainl);
|
||||
vscaled1 = _mm_mul_ps(vinl1, vgainl);
|
||||
_mm_store_ps(&aOutputL[i], vscaled0);
|
||||
_mm_store_ps(&aOutputL[i+4], vscaled1);
|
||||
|
||||
/* right channel: aOutputR = aInputR + aInputL * gainR */
|
||||
vscaled0 = _mm_mul_ps(vinl0, vgainr);
|
||||
vscaled1 = _mm_mul_ps(vinl1, vgainr);
|
||||
vout0 = _mm_add_ps(vscaled0, vinr0);
|
||||
vout1 = _mm_add_ps(vscaled1, vinr1);
|
||||
_mm_store_ps(&aOutputR[i], vout0);
|
||||
_mm_store_ps(&aOutputR[i+4], vout1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void BufferComplexMultiply_SSE(const float* aInput,
|
||||
const float* aScale,
|
||||
float* aOutput,
|
||||
uint32_t aSize)
|
||||
{
|
||||
unsigned i;
|
||||
__m128 in0, in1, in2, in3,
|
||||
outreal0, outreal1, outreal2, outreal3,
|
||||
outimag0, outimag1, outimag2, outimag3;
|
||||
|
||||
ASSERT_ALIGNED16(aInput);
|
||||
ASSERT_ALIGNED16(aScale);
|
||||
ASSERT_ALIGNED16(aOutput);
|
||||
ASSERT_MULTIPLE16(aSize);
|
||||
|
||||
for (i = 0; i < aSize * 2; i += 16) {
|
||||
in0 = _mm_load_ps(&aInput[i]);
|
||||
in1 = _mm_load_ps(&aInput[i + 4]);
|
||||
in2 = _mm_load_ps(&aInput[i + 8]);
|
||||
in3 = _mm_load_ps(&aInput[i + 12]);
|
||||
|
||||
outreal0 = _mm_shuffle_ps(in0, in1, _MM_SHUFFLE(2, 0, 2, 0));
|
||||
outimag0 = _mm_shuffle_ps(in0, in1, _MM_SHUFFLE(3, 1, 3, 1));
|
||||
outreal2 = _mm_shuffle_ps(in2, in3, _MM_SHUFFLE(2, 0, 2, 0));
|
||||
outimag2 = _mm_shuffle_ps(in2, in3, _MM_SHUFFLE(3, 1, 3, 1));
|
||||
|
||||
in0 = _mm_load_ps(&aScale[i]);
|
||||
in1 = _mm_load_ps(&aScale[i + 4]);
|
||||
in2 = _mm_load_ps(&aScale[i + 8]);
|
||||
in3 = _mm_load_ps(&aScale[i + 12]);
|
||||
|
||||
outreal1 = _mm_shuffle_ps(in0, in1, _MM_SHUFFLE(2, 0, 2, 0));
|
||||
outimag1 = _mm_shuffle_ps(in0, in1, _MM_SHUFFLE(3, 1, 3, 1));
|
||||
outreal3 = _mm_shuffle_ps(in2, in3, _MM_SHUFFLE(2, 0, 2, 0));
|
||||
outimag3 = _mm_shuffle_ps(in2, in3, _MM_SHUFFLE(3, 1, 3, 1));
|
||||
|
||||
in0 = _mm_sub_ps(_mm_mul_ps(outreal0, outreal1),
|
||||
_mm_mul_ps(outimag0, outimag1));
|
||||
in1 = _mm_add_ps(_mm_mul_ps(outreal0, outimag1),
|
||||
_mm_mul_ps(outimag0, outreal1));
|
||||
in2 = _mm_sub_ps(_mm_mul_ps(outreal2, outreal3),
|
||||
_mm_mul_ps(outimag2, outimag3));
|
||||
in3 = _mm_add_ps(_mm_mul_ps(outreal2, outimag3),
|
||||
_mm_mul_ps(outimag2, outreal3));
|
||||
|
||||
outreal0 = _mm_unpacklo_ps(in0, in1);
|
||||
outreal1 = _mm_unpackhi_ps(in0, in1);
|
||||
outreal2 = _mm_unpacklo_ps(in2, in3);
|
||||
outreal3 = _mm_unpackhi_ps(in2, in3);
|
||||
|
||||
_mm_store_ps(&aOutput[i], outreal0);
|
||||
_mm_store_ps(&aOutput[i + 4], outreal1);
|
||||
_mm_store_ps(&aOutput[i + 8], outreal2);
|
||||
_mm_store_ps(&aOutput[i + 12], outreal3);
|
||||
}
|
||||
}
|
||||
|
||||
float
|
||||
AudioBufferSumOfSquares_SSE(const float* aInput, uint32_t aLength)
|
||||
{
|
||||
unsigned i;
|
||||
__m128 in0, in1, in2, in3,
|
||||
acc0, acc1, acc2, acc3;
|
||||
float out[4];
|
||||
|
||||
ASSERT_ALIGNED16(aInput);
|
||||
ASSERT_MULTIPLE16(aLength);
|
||||
|
||||
acc0 = _mm_setzero_ps();
|
||||
acc1 = _mm_setzero_ps();
|
||||
acc2 = _mm_setzero_ps();
|
||||
acc3 = _mm_setzero_ps();
|
||||
|
||||
for (i = 0; i < aLength; i+=16) {
|
||||
in0 = _mm_load_ps(&aInput[i]);
|
||||
in1 = _mm_load_ps(&aInput[i + 4]);
|
||||
in2 = _mm_load_ps(&aInput[i + 8]);
|
||||
in3 = _mm_load_ps(&aInput[i + 12]);
|
||||
|
||||
in0 = _mm_mul_ps(in0, in0);
|
||||
in1 = _mm_mul_ps(in1, in1);
|
||||
in2 = _mm_mul_ps(in2, in2);
|
||||
in3 = _mm_mul_ps(in3, in3);
|
||||
|
||||
acc0 = _mm_add_ps(acc0, in0);
|
||||
acc1 = _mm_add_ps(acc1, in1);
|
||||
acc2 = _mm_add_ps(acc2, in2);
|
||||
acc3 = _mm_add_ps(acc3, in3);
|
||||
}
|
||||
|
||||
acc0 = _mm_add_ps(acc0, acc1);
|
||||
acc0 = _mm_add_ps(acc0, acc2);
|
||||
acc0 = _mm_add_ps(acc0, acc3);
|
||||
|
||||
_mm_store_ps(out, acc0);
|
||||
|
||||
return out[0] + out[1] + out[2] + out[3];
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,45 @@
|
|||
/* -*- mode: c++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* this source code form is subject to the terms of the mozilla public
|
||||
* license, v. 2.0. if a copy of the mpl was not distributed with this file,
|
||||
* You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "AudioNodeEngine.h"
|
||||
|
||||
namespace mozilla {
|
||||
void
|
||||
AudioBufferAddWithScale_SSE(const float* aInput,
|
||||
float aScale,
|
||||
float* aOutput,
|
||||
uint32_t aSize);
|
||||
|
||||
void
|
||||
AudioBlockCopyChannelWithScale_SSE(const float* aInput,
|
||||
float aScale,
|
||||
float* aOutput);
|
||||
|
||||
void
|
||||
AudioBlockCopyChannelWithScale_SSE(const float aInput[WEBAUDIO_BLOCK_SIZE],
|
||||
const float aScale[WEBAUDIO_BLOCK_SIZE],
|
||||
float aOutput[WEBAUDIO_BLOCK_SIZE]);
|
||||
|
||||
void
|
||||
AudioBufferInPlaceScale_SSE(float* aBlock,
|
||||
float aScale,
|
||||
uint32_t aSize);
|
||||
|
||||
void
|
||||
AudioBlockPanStereoToStereo_SSE(const float aInputL[WEBAUDIO_BLOCK_SIZE],
|
||||
const float aInputR[WEBAUDIO_BLOCK_SIZE],
|
||||
float aGainL, float aGainR, bool aIsOnTheLeft,
|
||||
float aOutputL[WEBAUDIO_BLOCK_SIZE],
|
||||
float aOutputR[WEBAUDIO_BLOCK_SIZE]);
|
||||
|
||||
float
|
||||
AudioBufferSumOfSquares_SSE(const float* aInput, uint32_t aLength);
|
||||
|
||||
void
|
||||
BufferComplexMultiply_SSE(const float* aInput,
|
||||
const float* aScale,
|
||||
float* aOutput,
|
||||
uint32_t aSize);
|
||||
}
|
|
@ -3,6 +3,8 @@
|
|||
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||
* You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "AlignedTArray.h"
|
||||
#include "AlignmentUtils.h"
|
||||
#include "AudioNodeEngine.h"
|
||||
#include "AudioNodeExternalInputStream.h"
|
||||
#include "AudioChannelFormat.h"
|
||||
|
@ -90,9 +92,20 @@ static void ConvertSegmentToAudioBlock(AudioSegment* aSegment,
|
|||
NS_ASSERTION(!ci.IsEnded(), "Should be at least one chunk!");
|
||||
if (ci->GetDuration() == WEBAUDIO_BLOCK_SIZE &&
|
||||
(ci->IsNull() || ci->mBufferFormat == AUDIO_FORMAT_FLOAT32)) {
|
||||
|
||||
bool aligned = true;
|
||||
for (size_t i = 0; i < ci->mChannelData.Length(); ++i) {
|
||||
if (!IS_ALIGNED16(ci->mChannelData[i])) {
|
||||
aligned = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Return this chunk directly to avoid copying data.
|
||||
*aBlock = *ci;
|
||||
return;
|
||||
if (aligned) {
|
||||
*aBlock = *ci;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -192,7 +205,10 @@ AudioNodeExternalInputStream::ProcessInput(GraphTime aFrom, GraphTime aTo,
|
|||
|
||||
uint32_t accumulateIndex = 0;
|
||||
if (inputChannels) {
|
||||
AutoTArray<float,GUESS_AUDIO_CHANNELS*WEBAUDIO_BLOCK_SIZE> downmixBuffer;
|
||||
// TODO: See Bug 1261168. Ideally we would use an aligned version of
|
||||
// AutoTArray (of size GUESS_AUDIO_CHANNELS*WEBAUDIO_BLOCK_SIZE) here.
|
||||
AlignedTArray<float,16> downmixBuffer;
|
||||
downmixBuffer.SetLength(GUESS_AUDIO_CHANNELS*WEBAUDIO_BLOCK_SIZE);
|
||||
for (uint32_t i = 0; i < audioSegments.Length(); ++i) {
|
||||
AudioBlock tmpChunk;
|
||||
ConvertSegmentToAudioBlock(&audioSegments[i], &tmpChunk, inputChannels);
|
||||
|
|
|
@ -453,8 +453,10 @@ AudioNodeStream::ObtainInputBlock(AudioBlock& aTmpChunk,
|
|||
}
|
||||
|
||||
aTmpChunk.AllocateChannels(outputChannelCount);
|
||||
// The static storage here should be 1KB, so it's fine
|
||||
AutoTArray<float, GUESS_AUDIO_CHANNELS*WEBAUDIO_BLOCK_SIZE> downmixBuffer;
|
||||
// TODO: See Bug 1261168. Ideally we would use an aligned version of
|
||||
// AutoTArray (of size GUESS_AUDIO_CHANNELS*WEBAUDIO_BLOCK_SIZE) here.
|
||||
AlignedTArray<float, 16> downmixBuffer;
|
||||
downmixBuffer.SetLength(GUESS_AUDIO_CHANNELS*WEBAUDIO_BLOCK_SIZE);
|
||||
|
||||
for (uint32_t i = 0; i < inputChunkCount; ++i) {
|
||||
AccumulateInputChunk(i, *inputChunks[i], &aTmpChunk, &downmixBuffer);
|
||||
|
@ -465,7 +467,7 @@ void
|
|||
AudioNodeStream::AccumulateInputChunk(uint32_t aInputIndex,
|
||||
const AudioBlock& aChunk,
|
||||
AudioBlock* aBlock,
|
||||
nsTArray<float>* aDownmixBuffer)
|
||||
AlignedTArray<float, 16>* aDownmixBuffer)
|
||||
{
|
||||
AutoTArray<const float*,GUESS_AUDIO_CHANNELS> channels;
|
||||
UpMixDownMixChunk(&aChunk, aBlock->ChannelCount(), channels, *aDownmixBuffer);
|
||||
|
@ -491,7 +493,7 @@ void
|
|||
AudioNodeStream::UpMixDownMixChunk(const AudioBlock* aChunk,
|
||||
uint32_t aOutputChannelCount,
|
||||
nsTArray<const float*>& aOutputChannels,
|
||||
nsTArray<float>& aDownmixBuffer)
|
||||
AlignedTArray<float, 16>& aDownmixBuffer)
|
||||
{
|
||||
for (uint32_t i = 0; i < aChunk->ChannelCount(); i++) {
|
||||
aOutputChannels.AppendElement(static_cast<const float*>(aChunk->mChannelData[i]));
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
|
||||
#include "MediaStreamGraph.h"
|
||||
#include "mozilla/dom/AudioNodeBinding.h"
|
||||
#include "AlignedTArray.h"
|
||||
#include "AudioBlock.h"
|
||||
|
||||
namespace mozilla {
|
||||
|
@ -190,10 +191,10 @@ protected:
|
|||
void FinishOutput();
|
||||
void AccumulateInputChunk(uint32_t aInputIndex, const AudioBlock& aChunk,
|
||||
AudioBlock* aBlock,
|
||||
nsTArray<float>* aDownmixBuffer);
|
||||
AlignedTArray<float, 16>* aDownmixBuffer);
|
||||
void UpMixDownMixChunk(const AudioBlock* aChunk, uint32_t aOutputChannelCount,
|
||||
nsTArray<const float*>& aOutputChannels,
|
||||
nsTArray<float>& aDownmixBuffer);
|
||||
AlignedTArray<float, 16>& aDownmixBuffer);
|
||||
|
||||
uint32_t ComputedNumberOfChannels(uint32_t aInputChannelCount);
|
||||
void ObtainInputBlock(AudioBlock& aTmpChunk, uint32_t aPortIndex);
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "BiquadFilterNode.h"
|
||||
#include "AlignmentUtils.h"
|
||||
#include "AudioNodeEngine.h"
|
||||
#include "AudioNodeStream.h"
|
||||
#include "AudioDestinationNode.h"
|
||||
|
@ -137,7 +138,9 @@ public:
|
|||
AudioBlock* aOutput,
|
||||
bool* aFinished) override
|
||||
{
|
||||
float inputBuffer[WEBAUDIO_BLOCK_SIZE];
|
||||
float inputBuffer[WEBAUDIO_BLOCK_SIZE + 4];
|
||||
float* alignedInputBuffer = ALIGNED16(inputBuffer);
|
||||
ASSERT_ALIGNED16(alignedInputBuffer);
|
||||
|
||||
if (aInput.IsNull()) {
|
||||
bool hasTail = false;
|
||||
|
@ -191,12 +194,12 @@ public:
|
|||
for (uint32_t i = 0; i < numberOfChannels; ++i) {
|
||||
const float* input;
|
||||
if (aInput.IsNull()) {
|
||||
input = inputBuffer;
|
||||
input = alignedInputBuffer;
|
||||
} else {
|
||||
input = static_cast<const float*>(aInput.mChannelData[i]);
|
||||
if (aInput.mVolume != 1.0) {
|
||||
AudioBlockCopyChannelWithScale(input, aInput.mVolume, inputBuffer);
|
||||
input = inputBuffer;
|
||||
AudioBlockCopyChannelWithScale(input, aInput.mVolume, alignedInputBuffer);
|
||||
input = alignedInputBuffer;
|
||||
}
|
||||
}
|
||||
SetParamsOnBiquad(mBiquads[i], aStream->SampleRate(), mType, freq, q, gain, detune);
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
|
||||
#include "ConvolverNode.h"
|
||||
#include "mozilla/dom/ConvolverNodeBinding.h"
|
||||
#include "AlignmentUtils.h"
|
||||
#include "AudioNodeEngine.h"
|
||||
#include "AudioNodeStream.h"
|
||||
#include "blink/Reverb.h"
|
||||
|
@ -261,11 +262,13 @@ ConvolverNode::SetBuffer(JSContext* aCx, AudioBuffer* aBuffer, ErrorResult& aRv)
|
|||
length = WEBAUDIO_BLOCK_SIZE;
|
||||
RefPtr<ThreadSharedFloatArrayBufferList> paddedBuffer =
|
||||
new ThreadSharedFloatArrayBufferList(data->GetChannels());
|
||||
float* channelData = (float*) malloc(sizeof(float) * length * data->GetChannels());
|
||||
void* channelData = malloc(sizeof(float) * length * data->GetChannels() + 15);
|
||||
float* alignedChannelData = ALIGNED16(channelData);
|
||||
ASSERT_ALIGNED16(alignedChannelData);
|
||||
for (uint32_t i = 0; i < data->GetChannels(); ++i) {
|
||||
PodCopy(channelData + length * i, data->GetData(i), mBuffer->Length());
|
||||
PodZero(channelData + length * i + mBuffer->Length(), WEBAUDIO_BLOCK_SIZE - mBuffer->Length());
|
||||
paddedBuffer->SetData(i, (i == 0) ? channelData : nullptr, free, channelData);
|
||||
PodCopy(alignedChannelData + length * i, data->GetData(i), mBuffer->Length());
|
||||
PodZero(alignedChannelData + length * i + mBuffer->Length(), WEBAUDIO_BLOCK_SIZE - mBuffer->Length());
|
||||
paddedBuffer->SetData(i, (i == 0) ? channelData : nullptr, free, alignedChannelData);
|
||||
}
|
||||
data = paddedBuffer;
|
||||
}
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
|
||||
#include "GainNode.h"
|
||||
#include "mozilla/dom/GainNodeBinding.h"
|
||||
#include "AlignmentUtils.h"
|
||||
#include "AudioNodeEngine.h"
|
||||
#include "AudioNodeStream.h"
|
||||
#include "AudioDestinationNode.h"
|
||||
|
@ -79,18 +80,20 @@ public:
|
|||
|
||||
// Compute the gain values for the duration of the input AudioChunk
|
||||
StreamTime tick = mDestination->GraphTimeToStreamTime(aFrom);
|
||||
float computedGain[WEBAUDIO_BLOCK_SIZE];
|
||||
mGain.GetValuesAtTime(tick, computedGain, WEBAUDIO_BLOCK_SIZE);
|
||||
float computedGain[WEBAUDIO_BLOCK_SIZE + 4];
|
||||
float* alignedComputedGain = ALIGNED16(computedGain);
|
||||
ASSERT_ALIGNED16(alignedComputedGain);
|
||||
mGain.GetValuesAtTime(tick, alignedComputedGain, WEBAUDIO_BLOCK_SIZE);
|
||||
|
||||
for (size_t counter = 0; counter < WEBAUDIO_BLOCK_SIZE; ++counter) {
|
||||
computedGain[counter] *= aInput.mVolume;
|
||||
alignedComputedGain[counter] *= aInput.mVolume;
|
||||
}
|
||||
|
||||
// Apply the gain to the output buffer
|
||||
for (size_t channel = 0; channel < aOutput->ChannelCount(); ++channel) {
|
||||
const float* inputBuffer = static_cast<const float*> (aInput.mChannelData[channel]);
|
||||
float* buffer = aOutput->ChannelFloatsForWrite(channel);
|
||||
AudioBlockCopyChannelWithScale(inputBuffer, computedGain, buffer);
|
||||
AudioBlockCopyChannelWithScale(inputBuffer, alignedComputedGain, buffer);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
#include "AudioNodeEngine.h"
|
||||
#include "AudioNodeStream.h"
|
||||
#include "AudioDestinationNode.h"
|
||||
#include "AlignmentUtils.h"
|
||||
#include "WebAudioUtils.h"
|
||||
#include "PanningUtils.h"
|
||||
#include "AudioParamTimeline.h"
|
||||
|
@ -137,24 +138,26 @@ public:
|
|||
panning <= 0);
|
||||
}
|
||||
} else {
|
||||
float computedGain[2][WEBAUDIO_BLOCK_SIZE];
|
||||
float computedGain[2*WEBAUDIO_BLOCK_SIZE + 4];
|
||||
bool onLeft[WEBAUDIO_BLOCK_SIZE];
|
||||
|
||||
float values[WEBAUDIO_BLOCK_SIZE];
|
||||
StreamTime tick = mDestination->GraphTimeToStreamTime(aFrom);
|
||||
mPan.GetValuesAtTime(tick, values, WEBAUDIO_BLOCK_SIZE);
|
||||
|
||||
float* alignedComputedGain = ALIGNED16(computedGain);
|
||||
ASSERT_ALIGNED16(alignedComputedGain);
|
||||
for (size_t counter = 0; counter < WEBAUDIO_BLOCK_SIZE; ++counter) {
|
||||
float left, right;
|
||||
GetGainValuesForPanning(values[counter], monoToStereo, left, right);
|
||||
|
||||
computedGain[0][counter] = left * aInput.mVolume;
|
||||
computedGain[1][counter] = right * aInput.mVolume;
|
||||
alignedComputedGain[counter] = left * aInput.mVolume;
|
||||
alignedComputedGain[WEBAUDIO_BLOCK_SIZE + counter] = right * aInput.mVolume;
|
||||
onLeft[counter] = values[counter] <= 0;
|
||||
}
|
||||
|
||||
// Apply the gain to the output buffer
|
||||
ApplyStereoPanning(aInput, aOutput, computedGain[0], computedGain[1], onLeft);
|
||||
ApplyStereoPanning(aInput, aOutput, alignedComputedGain, &alignedComputedGain[WEBAUDIO_BLOCK_SIZE], onLeft);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
|
||||
#include "WaveShaperNode.h"
|
||||
#include "mozilla/dom/WaveShaperNodeBinding.h"
|
||||
#include "AlignmentUtils.h"
|
||||
#include "AudioNode.h"
|
||||
#include "AudioNodeEngine.h"
|
||||
#include "AudioNodeStream.h"
|
||||
|
@ -231,13 +232,15 @@ public:
|
|||
aOutput->AllocateChannels(channelCount);
|
||||
for (uint32_t i = 0; i < channelCount; ++i) {
|
||||
const float* inputSamples;
|
||||
float scaledInput[WEBAUDIO_BLOCK_SIZE];
|
||||
float scaledInput[WEBAUDIO_BLOCK_SIZE + 4];
|
||||
float* alignedScaledInput = ALIGNED16(scaledInput);
|
||||
ASSERT_ALIGNED16(alignedScaledInput);
|
||||
if (aInput.mVolume != 1.0f) {
|
||||
AudioBlockCopyChannelWithScale(
|
||||
static_cast<const float*>(aInput.mChannelData[i]),
|
||||
aInput.mVolume,
|
||||
scaledInput);
|
||||
inputSamples = scaledInput;
|
||||
alignedScaledInput);
|
||||
inputSamples = alignedScaledInput;
|
||||
} else {
|
||||
inputSamples = static_cast<const float*>(aInput.mChannelData[i]);
|
||||
}
|
||||
|
|
|
@ -96,12 +96,30 @@ int ReverbAccumulationBuffer::accumulate(const float* source, size_t numberOfFra
|
|||
if (!isSafe)
|
||||
return 0;
|
||||
|
||||
AudioBufferAddWithScale(source, 1.0f, destination + writeIndex, numberOfFrames1);
|
||||
#ifdef USE_SSE2
|
||||
// It is unlikely either the source is aligned or the number of values
|
||||
// is a multiple of 16, so we just add them here rather than calling
|
||||
// AudioBufferAddWithScale.
|
||||
//
|
||||
// TODO: Ideally we would use scalar calls when necessary and switch
|
||||
// to vector calls when we have aligned sources and destinations.
|
||||
// See Bug 1263910.
|
||||
for (uint32_t i = 0; i < numberOfFrames1; ++i) {
|
||||
destination[writeIndex + i] += source[i];
|
||||
}
|
||||
|
||||
// Handle wrap-around if necessary
|
||||
// Handle wrap-around if necessary.
|
||||
if (numberOfFrames2 > 0) {
|
||||
for (uint32_t i = 0; i < numberOfFrames2; ++i) {
|
||||
destination[i] += source[numberOfFrames1 + i];
|
||||
}
|
||||
}
|
||||
#else
|
||||
AudioBufferAddWithScale(source, 1.0f, destination + writeIndex, numberOfFrames1);
|
||||
if (numberOfFrames2 > 0) {
|
||||
AudioBufferAddWithScale(source + numberOfFrames1, 1.0f, destination, numberOfFrames2);
|
||||
}
|
||||
#endif
|
||||
|
||||
return writeIndex;
|
||||
}
|
||||
|
|
|
@ -29,13 +29,11 @@
|
|||
#ifndef ReverbAccumulationBuffer_h
|
||||
#define ReverbAccumulationBuffer_h
|
||||
|
||||
#include "nsTArray.h"
|
||||
#include "AlignedTArray.h"
|
||||
#include "mozilla/MemoryReporting.h"
|
||||
|
||||
namespace WebCore {
|
||||
|
||||
typedef nsTArray<float> AudioFloatArray;
|
||||
|
||||
// ReverbAccumulationBuffer is a circular delay buffer with one client reading from it and multiple clients
|
||||
// writing/accumulating to it at different delay offsets from the read position. The read operation will zero the memory
|
||||
// just read from the buffer, so it will be ready for accumulation the next time around.
|
||||
|
@ -65,7 +63,7 @@ public:
|
|||
}
|
||||
|
||||
private:
|
||||
AudioFloatArray m_buffer;
|
||||
AlignedTArray<float, 16> m_buffer;
|
||||
size_t m_readIndex;
|
||||
size_t m_readTimeFrame; // for debugging (frame on continuous timeline)
|
||||
};
|
||||
|
|
|
@ -23,6 +23,10 @@ UNIFIED_SOURCES += [
|
|||
'ZeroPole.cpp',
|
||||
]
|
||||
|
||||
# Are we targeting x86 or x64? If so, build SSE2 files.
|
||||
if CONFIG['INTEL_ARCHITECTURE']:
|
||||
DEFINES['USE_SSE2'] = True
|
||||
|
||||
include('/ipc/chromium/chromium-config.mozbuild')
|
||||
|
||||
FINAL_LIBRARY = 'xul'
|
||||
|
|
|
@ -114,6 +114,13 @@ if CONFIG['CPU_ARCH'] == 'arm' and CONFIG['BUILD_ARM_NEON']:
|
|||
'/media/openmax_dl/dl/api/'
|
||||
]
|
||||
|
||||
# Are we targeting x86 or x64? If so, build SSE2 files.
|
||||
if CONFIG['INTEL_ARCHITECTURE']:
|
||||
SOURCES += ['AudioNodeEngineSSE2.cpp']
|
||||
DEFINES['USE_SSE2'] = True
|
||||
SOURCES['AudioNodeEngineSSE2.cpp'].flags += CONFIG['SSE2_FLAGS']
|
||||
|
||||
|
||||
include('/ipc/chromium/chromium-config.mozbuild')
|
||||
|
||||
FINAL_LIBRARY = 'xul'
|
||||
|
|
|
@ -2539,7 +2539,7 @@ nsEventStatus nsPluginInstanceOwner::ProcessEvent(const WidgetGUIEvent& anEvent)
|
|||
|
||||
#ifdef MOZ_X11
|
||||
// this code supports windowless plugins
|
||||
nsIWidget* widget = anEvent.widget;
|
||||
nsIWidget* widget = anEvent.mWidget;
|
||||
XEvent pluginEvent = XEvent();
|
||||
pluginEvent.type = 0;
|
||||
|
||||
|
|
|
@ -1,8 +0,0 @@
|
|||
#
|
||||
# This Source Code Form is subject to the terms of the Mozilla Public
|
||||
# License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
RELATIVE_PATH=.
|
||||
COCOA_NAME=Test
|
||||
include @srcdir@/testplugin.mk
|
|
@ -1,9 +0,0 @@
|
|||
#
|
||||
# This Source Code Form is subject to the terms of the Mozilla Public
|
||||
# License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||
# You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
RELATIVE_PATH=..
|
||||
COCOA_NAME=npswftest
|
||||
include @srcdir@/../testplugin.mk
|
||||
|
|
@ -7,4 +7,5 @@
|
|||
SharedLibrary('npswftest')
|
||||
|
||||
relative_path = 'flashplugin'
|
||||
cocoa_name = 'npswftest'
|
||||
include('../testplugin.mozbuild')
|
||||
|
|
|
@ -1,8 +0,0 @@
|
|||
#
|
||||
# This Source Code Form is subject to the terms of the Mozilla Public
|
||||
# License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||
# You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
RELATIVE_PATH=..
|
||||
COCOA_NAME=JavaTest
|
||||
include @srcdir@/../testplugin.mk
|
|
@ -7,4 +7,5 @@
|
|||
SharedLibrary('nptestjava')
|
||||
|
||||
relative_path = 'javaplugin'
|
||||
cocoa_name = 'JavaTest'
|
||||
include('../testplugin.mozbuild')
|
||||
|
|
|
@ -9,4 +9,5 @@ DIRS += ['secondplugin', 'javaplugin', 'thirdplugin', 'flashplugin', 'silverligh
|
|||
SharedLibrary('nptest')
|
||||
|
||||
relative_path = '.'
|
||||
cocoa_name = 'Test'
|
||||
include('testplugin.mozbuild')
|
||||
|
|
|
@ -1,8 +0,0 @@
|
|||
#
|
||||
# This Source Code Form is subject to the terms of the Mozilla Public
|
||||
# License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||
# You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
RELATIVE_PATH=..
|
||||
COCOA_NAME=SecondTest
|
||||
include @srcdir@/../testplugin.mk
|
|
@ -7,4 +7,5 @@
|
|||
SharedLibrary('npsecondtest')
|
||||
|
||||
relative_path = 'secondplugin'
|
||||
cocoa_name = 'SecondTest'
|
||||
include('../testplugin.mozbuild')
|
||||
|
|
|
@ -1,9 +0,0 @@
|
|||
#
|
||||
# This Source Code Form is subject to the terms of the Mozilla Public
|
||||
# License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||
# You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
RELATIVE_PATH=..
|
||||
COCOA_NAME=npctrltest
|
||||
include @srcdir@/../testplugin.mk
|
||||
|
|
@ -7,4 +7,5 @@
|
|||
SharedLibrary('npctrltest')
|
||||
|
||||
relative_path = 'silverlightplugin'
|
||||
cocoa_name = 'npctrltest'
|
||||
include('../testplugin.mozbuild')
|
||||
|
|
|
@ -1,19 +0,0 @@
|
|||
#
|
||||
# This Source Code Form is subject to the terms of the Mozilla Public
|
||||
# License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||
# You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
TEST_PLUGIN_FILES = $(SHARED_LIBRARY)
|
||||
|
||||
ifeq ($(MOZ_WIDGET_TOOLKIT),cocoa)
|
||||
MAC_PLIST_FILES += $(srcdir)/Info.plist
|
||||
MAC_PLIST_DEST = $(DIST)/plugins/$(COCOA_NAME).plugin/Contents
|
||||
TEST_PLUGIN_DEST = $(DIST)/plugins/$(COCOA_NAME).plugin/Contents/MacOS
|
||||
INSTALL_TARGETS += \
|
||||
TEST_PLUGIN \
|
||||
MAC_PLIST \
|
||||
$(NULL)
|
||||
else
|
||||
TEST_PLUGIN_DEST = $(DIST)/plugins
|
||||
INSTALL_TARGETS += TEST_PLUGIN
|
||||
endif
|
|
@ -4,8 +4,6 @@
|
|||
# License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
DIST_INSTALL = False
|
||||
|
||||
UNIFIED_SOURCES += [
|
||||
'nptest.cpp',
|
||||
'nptest_utils.cpp',
|
||||
|
@ -74,3 +72,9 @@ if CONFIG['_MSC_VER']:
|
|||
# This is intended as a temporary hack to support building with VS2015.
|
||||
# conversion from 'X' to 'Y' requires a narrowing conversion
|
||||
CXXFLAGS += ['-wd4838']
|
||||
|
||||
if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'cocoa':
|
||||
FINAL_TARGET = 'dist/plugins/%s.plugin/Contents/MacOS' % cocoa_name
|
||||
OBJDIR_FILES.dist.plugins['%s.plugin' % cocoa_name].Contents += ['Info.plist']
|
||||
else:
|
||||
FINAL_TARGET = 'dist/plugins'
|
||||
|
|
|
@ -1,8 +0,0 @@
|
|||
#
|
||||
# This Source Code Form is subject to the terms of the Mozilla Public
|
||||
# License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||
# You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
RELATIVE_PATH=..
|
||||
COCOA_NAME=ThirdTest
|
||||
include @srcdir@/../testplugin.mk
|
|
@ -7,4 +7,5 @@
|
|||
SharedLibrary('npthirdtest')
|
||||
|
||||
relative_path = 'thirdplugin'
|
||||
cocoa_name = 'ThirdTest'
|
||||
include('../testplugin.mozbuild')
|
||||
|
|
|
@ -706,13 +706,15 @@ StripURIForReporting(nsIURI* aURI,
|
|||
// 1) If the origin of uri is a globally unique identifier (for example,
|
||||
// aURI has a scheme of data, blob, or filesystem), then return the
|
||||
// ASCII serialization of uri’s scheme.
|
||||
bool isHttp =
|
||||
(NS_SUCCEEDED(aURI->SchemeIs("http", &isHttp)) && isHttp) ||
|
||||
(NS_SUCCEEDED(aURI->SchemeIs("https", &isHttp)) && isHttp);
|
||||
if (!isHttp) {
|
||||
bool isHttpOrFtp =
|
||||
(NS_SUCCEEDED(aURI->SchemeIs("http", &isHttpOrFtp)) && isHttpOrFtp) ||
|
||||
(NS_SUCCEEDED(aURI->SchemeIs("https", &isHttpOrFtp)) && isHttpOrFtp) ||
|
||||
(NS_SUCCEEDED(aURI->SchemeIs("ftp", &isHttpOrFtp)) && isHttpOrFtp);
|
||||
|
||||
if (!isHttpOrFtp) {
|
||||
// not strictly spec compliant, but what we really care about is
|
||||
// http/https. If it's not http/https, then treat aURI as if
|
||||
// it's a globally unique identifier and just return the scheme.
|
||||
// http/https and also ftp. If it's not http/https or ftp, then treat aURI
|
||||
// as if it's a globally unique identifier and just return the scheme.
|
||||
aURI->GetScheme(outStrippedURI);
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -212,4 +212,13 @@ function run_test() {
|
|||
NetUtil.newURI(selfSpec + "#bar"),
|
||||
null, null, null, null);
|
||||
});
|
||||
|
||||
// test scheme of ftp:
|
||||
makeTest(8, {"blocked-uri": "ftp://blocked.test"}, false,
|
||||
function(csp) {
|
||||
// shouldLoad creates and sends out the report here.
|
||||
csp.shouldLoad(Ci.nsIContentPolicy.TYPE_SCRIPT,
|
||||
NetUtil.newURI("ftp://blocked.test/profile.png"),
|
||||
null, null, null, null);
|
||||
});
|
||||
}
|
||||
|
|
|
@ -5092,7 +5092,7 @@ nsEditor::IsAcceptableInputEvent(nsIDOMEvent* aEvent)
|
|||
break;
|
||||
}
|
||||
if (needsWidget &&
|
||||
(!widgetGUIEvent || !widgetGUIEvent->widget)) {
|
||||
(!widgetGUIEvent || !widgetGUIEvent->mWidget)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
|
@ -644,7 +644,7 @@ nsEditorEventListener::KeyPress(nsIDOMKeyEvent* aKeyEvent)
|
|||
aKeyEvent->AsEvent()->WidgetEventPtr()->AsKeyboardEvent();
|
||||
MOZ_ASSERT(keyEvent,
|
||||
"DOM key event's internal event must be WidgetKeyboardEvent");
|
||||
nsIWidget* widget = keyEvent->widget;
|
||||
nsIWidget* widget = keyEvent->mWidget;
|
||||
// If the event is created by chrome script, the widget is always nullptr.
|
||||
if (!widget) {
|
||||
nsCOMPtr<nsIPresShell> ps = GetPresShell();
|
||||
|
|
|
@ -55,6 +55,8 @@ WIN_LIBS= \
|
|||
// This is for extending the dialog
|
||||
#include <dlgs.h>
|
||||
|
||||
#include "nsWindowsHelpers.h"
|
||||
|
||||
// Default labels for the radio buttons
|
||||
static const char* kAsLaidOutOnScreenStr = "As &laid out on the screen";
|
||||
static const char* kTheSelectedFrameStr = "The selected &frame";
|
||||
|
@ -462,79 +464,71 @@ static UINT CALLBACK PrintHookProc(HWND hdlg, UINT uiMsg, WPARAM wParam, LPARAM
|
|||
// This function assumes that aPrintName has already been converted from
|
||||
// unicode
|
||||
//
|
||||
HGLOBAL CreateGlobalDevModeAndInit(const nsXPIDLString& aPrintName, nsIPrintSettings* aPS)
|
||||
static nsReturnRef<nsHGLOBAL>
|
||||
CreateGlobalDevModeAndInit(const nsXPIDLString& aPrintName,
|
||||
nsIPrintSettings* aPS)
|
||||
{
|
||||
HGLOBAL hGlobalDevMode = nullptr;
|
||||
|
||||
HANDLE hPrinter = nullptr;
|
||||
nsHPRINTER hPrinter = nullptr;
|
||||
// const cast kludge for silly Win32 api's
|
||||
LPWSTR printName = const_cast<wchar_t*>(static_cast<const wchar_t*>(aPrintName.get()));
|
||||
BOOL status = ::OpenPrinterW(printName, &hPrinter, nullptr);
|
||||
if (status) {
|
||||
|
||||
LPDEVMODEW pNewDevMode;
|
||||
DWORD dwNeeded, dwRet;
|
||||
|
||||
// Get the buffer size
|
||||
dwNeeded = ::DocumentPropertiesW(gParentWnd, hPrinter, printName, nullptr, nullptr, 0);
|
||||
if (dwNeeded == 0) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// Allocate a buffer of the correct size.
|
||||
pNewDevMode = (LPDEVMODEW)::HeapAlloc (::GetProcessHeap(), HEAP_ZERO_MEMORY, dwNeeded);
|
||||
if (!pNewDevMode) return nullptr;
|
||||
|
||||
hGlobalDevMode = (HGLOBAL)::GlobalAlloc(GHND, dwNeeded);
|
||||
if (!hGlobalDevMode) {
|
||||
::HeapFree(::GetProcessHeap(), 0, pNewDevMode);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
dwRet = ::DocumentPropertiesW(gParentWnd, hPrinter, printName, pNewDevMode, nullptr, DM_OUT_BUFFER);
|
||||
|
||||
if (dwRet != IDOK) {
|
||||
::HeapFree(::GetProcessHeap(), 0, pNewDevMode);
|
||||
::GlobalFree(hGlobalDevMode);
|
||||
::ClosePrinter(hPrinter);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// Lock memory and copy contents from DEVMODE (current printer)
|
||||
// to Global Memory DEVMODE
|
||||
LPDEVMODEW devMode = (DEVMODEW *)::GlobalLock(hGlobalDevMode);
|
||||
if (devMode) {
|
||||
memcpy(devMode, pNewDevMode, dwNeeded);
|
||||
// Initialize values from the PrintSettings
|
||||
nsCOMPtr<nsIPrintSettingsWin> psWin = do_QueryInterface(aPS);
|
||||
MOZ_ASSERT(psWin);
|
||||
psWin->CopyToNative(devMode);
|
||||
|
||||
// Sets back the changes we made to the DevMode into the Printer Driver
|
||||
dwRet = ::DocumentPropertiesW(gParentWnd, hPrinter, printName, devMode, devMode, DM_IN_BUFFER | DM_OUT_BUFFER);
|
||||
if (dwRet != IDOK) {
|
||||
::GlobalUnlock(hGlobalDevMode);
|
||||
::GlobalFree(hGlobalDevMode);
|
||||
::HeapFree(::GetProcessHeap(), 0, pNewDevMode);
|
||||
::ClosePrinter(hPrinter);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
::GlobalUnlock(hGlobalDevMode);
|
||||
} else {
|
||||
::GlobalFree(hGlobalDevMode);
|
||||
hGlobalDevMode = nullptr;
|
||||
}
|
||||
|
||||
::HeapFree(::GetProcessHeap(), 0, pNewDevMode);
|
||||
|
||||
::ClosePrinter(hPrinter);
|
||||
|
||||
} else {
|
||||
return nullptr;
|
||||
if (!status) {
|
||||
return nsReturnRef<nsHGLOBAL>();
|
||||
}
|
||||
|
||||
return hGlobalDevMode;
|
||||
// Make sure hPrinter is closed on all paths
|
||||
nsAutoPrinter autoPrinter(hPrinter);
|
||||
|
||||
// Get the buffer size
|
||||
DWORD dwNeeded = ::DocumentPropertiesW(gParentWnd, hPrinter, printName, nullptr,
|
||||
nullptr, 0);
|
||||
if (dwNeeded == 0) {
|
||||
return nsReturnRef<nsHGLOBAL>();
|
||||
}
|
||||
|
||||
// Allocate a buffer of the correct size.
|
||||
nsAutoDevMode newDevMode((LPDEVMODEW)::HeapAlloc(::GetProcessHeap(), HEAP_ZERO_MEMORY,
|
||||
dwNeeded));
|
||||
if (!newDevMode) {
|
||||
return nsReturnRef<nsHGLOBAL>();
|
||||
}
|
||||
|
||||
nsHGLOBAL hDevMode = ::GlobalAlloc(GHND, dwNeeded);
|
||||
nsAutoGlobalMem globalDevMode(hDevMode);
|
||||
if (!hDevMode) {
|
||||
return nsReturnRef<nsHGLOBAL>();
|
||||
}
|
||||
|
||||
DWORD dwRet = ::DocumentPropertiesW(gParentWnd, hPrinter, printName, newDevMode,
|
||||
nullptr, DM_OUT_BUFFER);
|
||||
if (dwRet != IDOK) {
|
||||
return nsReturnRef<nsHGLOBAL>();
|
||||
}
|
||||
|
||||
// Lock memory and copy contents from DEVMODE (current printer)
|
||||
// to Global Memory DEVMODE
|
||||
LPDEVMODEW devMode = (DEVMODEW *)::GlobalLock(hDevMode);
|
||||
if (!devMode) {
|
||||
return nsReturnRef<nsHGLOBAL>();
|
||||
}
|
||||
|
||||
memcpy(devMode, newDevMode.get(), dwNeeded);
|
||||
// Initialize values from the PrintSettings
|
||||
nsCOMPtr<nsIPrintSettingsWin> psWin = do_QueryInterface(aPS);
|
||||
MOZ_ASSERT(psWin);
|
||||
psWin->CopyToNative(devMode);
|
||||
|
||||
// Sets back the changes we made to the DevMode into the Printer Driver
|
||||
dwRet = ::DocumentPropertiesW(gParentWnd, hPrinter, printName, devMode, devMode,
|
||||
DM_IN_BUFFER | DM_OUT_BUFFER);
|
||||
if (dwRet != IDOK) {
|
||||
::GlobalUnlock(hDevMode);
|
||||
return nsReturnRef<nsHGLOBAL>();
|
||||
}
|
||||
|
||||
::GlobalUnlock(hDevMode);
|
||||
|
||||
return globalDevMode.out();
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------
|
||||
|
@ -576,9 +570,6 @@ ShowNativePrintDialog(HWND aHWnd,
|
|||
|
||||
gDialogWasExtended = false;
|
||||
|
||||
HGLOBAL hGlobalDevMode = nullptr;
|
||||
HGLOBAL hDevNames = nullptr;
|
||||
|
||||
// Get the Print Name to be used
|
||||
nsXPIDLString printerName;
|
||||
aPrintSettings->GetPrinterName(getter_Copies(printerName));
|
||||
|
@ -588,7 +579,8 @@ ShowNativePrintDialog(HWND aHWnd,
|
|||
GetDefaultPrinterNameFromGlobalPrinters(printerName);
|
||||
} else {
|
||||
HANDLE hPrinter = nullptr;
|
||||
if(!::OpenPrinterW(const_cast<wchar_t*>(static_cast<const wchar_t*>(printerName.get())), &hPrinter, nullptr)) {
|
||||
if(!::OpenPrinterW(const_cast<wchar_t*>(static_cast<const wchar_t*>(printerName.get())),
|
||||
&hPrinter, nullptr)) {
|
||||
// If the last used printer is not found, we should use default printer.
|
||||
GetDefaultPrinterNameFromGlobalPrinters(printerName);
|
||||
} else {
|
||||
|
@ -599,15 +591,15 @@ ShowNativePrintDialog(HWND aHWnd,
|
|||
// Now create a DEVNAMES struct so the the dialog is initialized correctly.
|
||||
|
||||
uint32_t len = printerName.Length();
|
||||
hDevNames = (HGLOBAL)::GlobalAlloc(GHND, sizeof(wchar_t) * (len + 1) +
|
||||
sizeof(DEVNAMES));
|
||||
nsHGLOBAL hDevNames = ::GlobalAlloc(GHND, sizeof(wchar_t) * (len + 1)
|
||||
+ sizeof(DEVNAMES));
|
||||
nsAutoGlobalMem autoDevNames(hDevNames);
|
||||
if (!hDevNames) {
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
|
||||
DEVNAMES* pDevNames = (DEVNAMES*)::GlobalLock(hDevNames);
|
||||
if (!pDevNames) {
|
||||
::GlobalFree(hDevNames);
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
pDevNames->wDriverOffset = sizeof(DEVNAMES)/sizeof(wchar_t);
|
||||
|
@ -621,10 +613,8 @@ ShowNativePrintDialog(HWND aHWnd,
|
|||
// Create a Moveable Memory Object that holds a new DevMode
|
||||
// from the Printer Name
|
||||
// The PRINTDLG.hDevMode requires that it be a moveable memory object
|
||||
// NOTE: We only need to free hGlobalDevMode when the dialog is cancelled
|
||||
// When the user prints, it comes back in the printdlg struct and
|
||||
// is used and cleaned up later
|
||||
hGlobalDevMode = CreateGlobalDevModeAndInit(printerName, aPrintSettings);
|
||||
// NOTE: autoDevMode is automatically freed when any error occurred
|
||||
nsAutoGlobalMem autoDevMode(CreateGlobalDevModeAndInit(printerName, aPrintSettings));
|
||||
|
||||
// Prepare to Display the Print Dialog
|
||||
PRINTDLGW prntdlg;
|
||||
|
@ -632,7 +622,7 @@ ShowNativePrintDialog(HWND aHWnd,
|
|||
|
||||
prntdlg.lStructSize = sizeof(prntdlg);
|
||||
prntdlg.hwndOwner = aHWnd;
|
||||
prntdlg.hDevMode = hGlobalDevMode;
|
||||
prntdlg.hDevMode = autoDevMode.get();
|
||||
prntdlg.hDevNames = hDevNames;
|
||||
prntdlg.hDC = nullptr;
|
||||
prntdlg.Flags = PD_ALLPAGES | PD_RETURNIC |
|
||||
|
@ -682,13 +672,11 @@ ShowNativePrintDialog(HWND aHWnd,
|
|||
NS_ENSURE_TRUE(aPrintSettings && prntdlg.hDevMode, NS_ERROR_FAILURE);
|
||||
|
||||
if (prntdlg.hDevNames == nullptr) {
|
||||
::GlobalFree(hGlobalDevMode);
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
// Lock the deviceNames and check for nullptr
|
||||
DEVNAMES *devnames = (DEVNAMES *)::GlobalLock(prntdlg.hDevNames);
|
||||
if (devnames == nullptr) {
|
||||
::GlobalFree(hGlobalDevMode);
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
|
@ -716,7 +704,6 @@ ShowNativePrintDialog(HWND aHWnd,
|
|||
|
||||
nsCOMPtr<nsIPrintSettingsWin> psWin(do_QueryInterface(aPrintSettings));
|
||||
if (!psWin) {
|
||||
::GlobalFree(hGlobalDevMode);
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
|
@ -772,7 +759,6 @@ ShowNativePrintDialog(HWND aHWnd,
|
|||
// Transfer the settings from the native data to the PrintSettings
|
||||
LPDEVMODEW devMode = (LPDEVMODEW)::GlobalLock(prntdlg.hDevMode);
|
||||
if (!devMode || !prntdlg.hDC) {
|
||||
::GlobalFree(hGlobalDevMode);
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
psWin->SetDevMode(devMode); // copies DevMode
|
||||
|
@ -805,7 +791,6 @@ ShowNativePrintDialog(HWND aHWnd,
|
|||
} else {
|
||||
::SetFocus(aHWnd);
|
||||
aPrintSettings->SetIsCancelled(true);
|
||||
if (hGlobalDevMode) ::GlobalFree(hGlobalDevMode);
|
||||
return NS_ERROR_ABORT;
|
||||
}
|
||||
|
||||
|
|
|
@ -9,6 +9,4 @@ nsresult NativeShowPrintDialog(HWND aHWnd,
|
|||
nsIWebBrowserPrint* aWebBrowserPrint,
|
||||
nsIPrintSettings* aPrintSettings);
|
||||
|
||||
HGLOBAL CreateGlobalDevModeAndInit(const nsXPIDLString& aPrintName, nsIPrintSettings* aPS);
|
||||
|
||||
#endif /* nsFlyOwnDialog_h___ */
|
||||
|
|
|
@ -36,14 +36,6 @@ public:
|
|||
*/
|
||||
virtual void RequestContentRepaint(const FrameMetrics& aFrameMetrics) = 0;
|
||||
|
||||
/**
|
||||
* Acknowledges the recipt of a scroll offset update for the scrollable
|
||||
* frame with the given scroll id. This is used to maintain consistency
|
||||
* between APZ and other sources of scroll changes.
|
||||
*/
|
||||
virtual void AcknowledgeScrollUpdate(const FrameMetrics::ViewID& aScrollId,
|
||||
const uint32_t& aScrollGeneration) = 0;
|
||||
|
||||
/**
|
||||
* Requests handling of a double tap. |aPoint| is in CSS pixels, relative to
|
||||
* the current scroll offset. This should eventually round-trip back to
|
||||
|
|
|
@ -3457,7 +3457,7 @@ void AsyncPanZoomController::NotifyLayersUpdated(const ScrollMetadata& aScrollMe
|
|||
|
||||
mScrollMetadata = aScrollMetadata;
|
||||
if (scrollOffsetUpdated) {
|
||||
AcknowledgeScrollUpdate();
|
||||
needContentRepaint = true;
|
||||
}
|
||||
mExpectedGeckoMetrics = aLayerMetrics;
|
||||
ShareCompositorFrameMetrics();
|
||||
|
@ -3532,7 +3532,6 @@ void AsyncPanZoomController::NotifyLayersUpdated(const ScrollMetadata& aScrollMe
|
|||
// correct this we need to update mExpectedGeckoMetrics to be the
|
||||
// last thing we know was painted by Gecko.
|
||||
mFrameMetrics.CopyScrollInfoFrom(aLayerMetrics);
|
||||
AcknowledgeScrollUpdate();
|
||||
mExpectedGeckoMetrics = aLayerMetrics;
|
||||
|
||||
// Cancel the animation (which might also trigger a repaint request)
|
||||
|
@ -3564,7 +3563,7 @@ void AsyncPanZoomController::NotifyLayersUpdated(const ScrollMetadata& aScrollMe
|
|||
// See comment on the similar code in the |if (scrollOffsetUpdated)| block
|
||||
// above.
|
||||
mFrameMetrics.CopySmoothScrollInfoFrom(aLayerMetrics);
|
||||
AcknowledgeScrollUpdate();
|
||||
needContentRepaint = true;
|
||||
mExpectedGeckoMetrics = aLayerMetrics;
|
||||
|
||||
SmoothScrollTo(mFrameMetrics.GetSmoothScrollOffset());
|
||||
|
@ -3576,21 +3575,6 @@ void AsyncPanZoomController::NotifyLayersUpdated(const ScrollMetadata& aScrollMe
|
|||
UpdateSharedCompositorFrameMetrics();
|
||||
}
|
||||
|
||||
void
|
||||
AsyncPanZoomController::AcknowledgeScrollUpdate() const
|
||||
{
|
||||
// Once layout issues a scroll offset update, it becomes impervious to
|
||||
// scroll offset updates from APZ until we acknowledge the update it sent.
|
||||
// This prevents APZ updates from clobbering scroll updates from other
|
||||
// more "legitimate" sources like content scripts.
|
||||
RefPtr<GeckoContentController> controller = GetGeckoContentController();
|
||||
if (controller) {
|
||||
APZC_LOG("%p sending scroll update acknowledgement with gen %u\n", this, mFrameMetrics.GetScrollGeneration());
|
||||
controller->AcknowledgeScrollUpdate(mFrameMetrics.GetScrollId(),
|
||||
mFrameMetrics.GetScrollGeneration());
|
||||
}
|
||||
}
|
||||
|
||||
const FrameMetrics& AsyncPanZoomController::GetFrameMetrics() const {
|
||||
mMonitor.AssertCurrentThreadIn();
|
||||
return mFrameMetrics;
|
||||
|
|
|
@ -896,8 +896,6 @@ private:
|
|||
// Returns whether overscroll is allowed during an event.
|
||||
bool AllowScrollHandoffInCurrentBlock() const;
|
||||
|
||||
void AcknowledgeScrollUpdate() const;
|
||||
|
||||
/* ===================================================================
|
||||
* The functions and members in this section are used to make ancestor chains
|
||||
* out of APZC instances. These chains can only be walked or manipulated
|
||||
|
|
|
@ -124,9 +124,9 @@ ScrollFrame(nsIContent* aContent,
|
|||
// Scroll the window to the desired spot
|
||||
nsIScrollableFrame* sf = nsLayoutUtils::FindScrollableFrameFor(aMetrics.GetScrollId());
|
||||
if (sf) {
|
||||
sf->ResetScrollInfoIfGeneration(aMetrics.GetScrollGeneration());
|
||||
sf->SetScrollableByAPZ(!aMetrics.IsScrollInfoLayer());
|
||||
}
|
||||
|
||||
bool scrollUpdated = false;
|
||||
CSSPoint apzScrollOffset = aMetrics.GetScrollOffset();
|
||||
CSSPoint actualScrollOffset = ScrollFrameTo(sf, apzScrollOffset, scrollUpdated);
|
||||
|
@ -330,54 +330,6 @@ APZCCallbackHelper::InitializeRootDisplayport(nsIPresShell* aPresShell)
|
|||
}
|
||||
}
|
||||
|
||||
class AcknowledgeScrollUpdateEvent : public nsRunnable
|
||||
{
|
||||
typedef mozilla::layers::FrameMetrics::ViewID ViewID;
|
||||
|
||||
public:
|
||||
AcknowledgeScrollUpdateEvent(const ViewID& aScrollId, const uint32_t& aScrollGeneration)
|
||||
: mScrollId(aScrollId)
|
||||
, mScrollGeneration(aScrollGeneration)
|
||||
{
|
||||
}
|
||||
|
||||
NS_IMETHOD Run() {
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
||||
nsIScrollableFrame* sf = nsLayoutUtils::FindScrollableFrameFor(mScrollId);
|
||||
if (sf) {
|
||||
sf->ResetScrollInfoIfGeneration(mScrollGeneration);
|
||||
}
|
||||
|
||||
// Since the APZ and content are in sync, we need to clear any callback transform
|
||||
// that might have been set on the last repaint request (which might have failed
|
||||
// due to the inflight scroll update that this message is acknowledging).
|
||||
nsCOMPtr<nsIContent> content = nsLayoutUtils::FindContentFor(mScrollId);
|
||||
if (content) {
|
||||
content->SetProperty(nsGkAtoms::apzCallbackTransform, new CSSPoint(),
|
||||
nsINode::DeleteProperty<CSSPoint>);
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
protected:
|
||||
ViewID mScrollId;
|
||||
uint32_t mScrollGeneration;
|
||||
};
|
||||
|
||||
void
|
||||
APZCCallbackHelper::AcknowledgeScrollUpdate(const FrameMetrics::ViewID& aScrollId,
|
||||
const uint32_t& aScrollGeneration)
|
||||
{
|
||||
nsCOMPtr<nsIRunnable> r1 = new AcknowledgeScrollUpdateEvent(aScrollId, aScrollGeneration);
|
||||
if (!NS_IsMainThread()) {
|
||||
NS_DispatchToMainThread(r1);
|
||||
} else {
|
||||
r1->Run();
|
||||
}
|
||||
}
|
||||
|
||||
nsIPresShell*
|
||||
APZCCallbackHelper::GetRootContentDocumentPresShellForContent(nsIContent* aContent)
|
||||
{
|
||||
|
@ -514,8 +466,8 @@ nsEventStatus
|
|||
APZCCallbackHelper::DispatchWidgetEvent(WidgetGUIEvent& aEvent)
|
||||
{
|
||||
nsEventStatus status = nsEventStatus_eConsumeNoDefault;
|
||||
if (aEvent.widget) {
|
||||
aEvent.widget->DispatchEvent(&aEvent, status);
|
||||
if (aEvent.mWidget) {
|
||||
aEvent.mWidget->DispatchEvent(&aEvent, status);
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
@ -530,7 +482,7 @@ APZCCallbackHelper::DispatchSynthesizedMouseEvent(EventMessage aMsg,
|
|||
MOZ_ASSERT(aMsg == eMouseMove || aMsg == eMouseDown ||
|
||||
aMsg == eMouseUp || aMsg == eMouseLongTap);
|
||||
|
||||
WidgetMouseEvent event(true, aMsg, nullptr,
|
||||
WidgetMouseEvent event(true, aMsg, aWidget,
|
||||
WidgetMouseEvent::eReal, WidgetMouseEvent::eNormal);
|
||||
event.refPoint = LayoutDeviceIntPoint(aRefPoint.x, aRefPoint.y);
|
||||
event.mTime = aTime;
|
||||
|
@ -541,7 +493,6 @@ APZCCallbackHelper::DispatchSynthesizedMouseEvent(EventMessage aMsg,
|
|||
event.clickCount = 1;
|
||||
}
|
||||
event.mModifiers = aModifiers;
|
||||
event.widget = aWidget;
|
||||
|
||||
return DispatchWidgetEvent(event);
|
||||
}
|
||||
|
|
|
@ -66,11 +66,6 @@ public:
|
|||
given presShell. */
|
||||
static void InitializeRootDisplayport(nsIPresShell* aPresShell);
|
||||
|
||||
/* Tell layout that we received the scroll offset update for the given view ID, so
|
||||
that it accepts future scroll offset updates from APZ. */
|
||||
static void AcknowledgeScrollUpdate(const FrameMetrics::ViewID& aScrollId,
|
||||
const uint32_t& aScrollGeneration);
|
||||
|
||||
/* Get the pres shell associated with the root content document enclosing |aContent|. */
|
||||
static nsIPresShell* GetRootContentDocumentPresShellForContent(nsIContent* aContent);
|
||||
|
||||
|
|
|
@ -328,7 +328,7 @@ APZEventState::ProcessTouchEvent(const WidgetTouchEvent& aEvent,
|
|||
}
|
||||
}
|
||||
nsEventStatus status;
|
||||
cancelEvent.widget->DispatchEvent(&cancelEvent, status);
|
||||
cancelEvent.mWidget->DispatchEvent(&cancelEvent, status);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -68,13 +68,6 @@ ChromeProcessController::PostDelayedTask(Task* aTask, int aDelayMs)
|
|||
MessageLoop::current()->PostDelayedTask(FROM_HERE, aTask, aDelayMs);
|
||||
}
|
||||
|
||||
void
|
||||
ChromeProcessController::AcknowledgeScrollUpdate(const FrameMetrics::ViewID& aScrollId,
|
||||
const uint32_t& aScrollGeneration)
|
||||
{
|
||||
APZCCallbackHelper::AcknowledgeScrollUpdate(aScrollId, aScrollGeneration);
|
||||
}
|
||||
|
||||
void
|
||||
ChromeProcessController::Destroy()
|
||||
{
|
||||
|
|
|
@ -40,9 +40,6 @@ public:
|
|||
// GeckoContentController interface
|
||||
virtual void RequestContentRepaint(const FrameMetrics& aFrameMetrics) override;
|
||||
virtual void PostDelayedTask(Task* aTask, int aDelayMs) override;
|
||||
virtual void AcknowledgeScrollUpdate(const FrameMetrics::ViewID& aScrollId,
|
||||
const uint32_t& aScrollGeneration) override;
|
||||
|
||||
virtual void HandleDoubleTap(const mozilla::CSSPoint& aPoint, Modifiers aModifiers,
|
||||
const ScrollableLayerGuid& aGuid) override;
|
||||
virtual void HandleSingleTap(const mozilla::CSSPoint& aPoint, Modifiers aModifiers,
|
||||
|
|
|
@ -94,14 +94,6 @@ APZChild::RecvUpdateFrame(const FrameMetrics& aFrameMetrics)
|
|||
return mBrowser->UpdateFrame(aFrameMetrics);
|
||||
}
|
||||
|
||||
bool
|
||||
APZChild::RecvAcknowledgeScrollUpdate(const ViewID& aScrollId,
|
||||
const uint32_t& aScrollGeneration)
|
||||
{
|
||||
APZCCallbackHelper::AcknowledgeScrollUpdate(aScrollId, aScrollGeneration);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
APZChild::RecvHandleDoubleTap(const CSSPoint& aPoint,
|
||||
const Modifiers& aModifiers,
|
||||
|
|
|
@ -28,9 +28,6 @@ public:
|
|||
|
||||
virtual bool RecvUpdateFrame(const FrameMetrics& frame) override;
|
||||
|
||||
virtual bool RecvAcknowledgeScrollUpdate(const ViewID& aScrollId,
|
||||
const uint32_t& aScrollGeneration) override;
|
||||
|
||||
virtual bool RecvHandleDoubleTap(const CSSPoint& aPoint,
|
||||
const Modifiers& aModifiers,
|
||||
const ScrollableLayerGuid& aGuid) override;
|
||||
|
|
|
@ -89,7 +89,6 @@ child:
|
|||
// The following methods correspond to functions on the GeckoContentController
|
||||
// interface in gfx/layers/apz/public/GeckoContentController.h. Refer to documentation
|
||||
// in that file for these functions.
|
||||
async AcknowledgeScrollUpdate(ViewID aScrollId, uint32_t aScrollGeneration);
|
||||
async HandleDoubleTap(CSSPoint aPoint, Modifiers aModifiers, ScrollableLayerGuid aGuid);
|
||||
async HandleSingleTap(CSSPoint aPoint, Modifiers aModifiers, ScrollableLayerGuid aGuid, bool aCallTakeFocusForClickFromTap);
|
||||
async HandleLongTap(CSSPoint point, Modifiers aModifiers, ScrollableLayerGuid aGuid, uint64_t aInputBlockId);
|
||||
|
|
|
@ -51,24 +51,6 @@ RemoteContentController::RequestContentRepaint(const FrameMetrics& aFrameMetrics
|
|||
}
|
||||
}
|
||||
|
||||
void
|
||||
RemoteContentController::AcknowledgeScrollUpdate(const FrameMetrics::ViewID& aScrollId,
|
||||
const uint32_t& aScrollGeneration)
|
||||
{
|
||||
if (MessageLoop::current() != mUILoop) {
|
||||
// We have to send this message from the "UI thread" (main
|
||||
// thread).
|
||||
mUILoop->PostTask(
|
||||
FROM_HERE,
|
||||
NewRunnableMethod(this, &RemoteContentController::AcknowledgeScrollUpdate,
|
||||
aScrollId, aScrollGeneration));
|
||||
return;
|
||||
}
|
||||
if (CanSend()) {
|
||||
Unused << SendAcknowledgeScrollUpdate(aScrollId, aScrollGeneration);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
RemoteContentController::HandleDoubleTap(const CSSPoint& aPoint,
|
||||
Modifiers aModifiers,
|
||||
|
|
|
@ -42,9 +42,6 @@ public:
|
|||
// Needs to be called on the main thread.
|
||||
virtual void RequestContentRepaint(const FrameMetrics& aFrameMetrics) override;
|
||||
|
||||
virtual void AcknowledgeScrollUpdate(const FrameMetrics::ViewID& aScrollId,
|
||||
const uint32_t& aScrollGeneration) override;
|
||||
|
||||
virtual void HandleDoubleTap(const CSSPoint& aPoint,
|
||||
Modifiers aModifiers,
|
||||
const ScrollableLayerGuid& aGuid) override;
|
||||
|
|
|
@ -135,6 +135,9 @@ private:
|
|||
|
||||
// It's a short time fix, and will be removed after landing bug 1206637.
|
||||
DECL_GFX_PREF(Live, "accessibility.monoaudio.enable", MonoAudio, bool, false);
|
||||
DECL_GFX_PREF(Live, "media.resampling.enabled", AudioSinkResampling, bool, false);
|
||||
DECL_GFX_PREF(Live, "media.resampling.rate", AudioSinkResampleRate, uint32_t, 48000);
|
||||
DECL_GFX_PREF(Live, "media.forcestereo.enabled", AudioSinkForceStereo, bool, true);
|
||||
|
||||
// The apz prefs are explained in AsyncPanZoomController.cpp
|
||||
DECL_GFX_PREF(Live, "apz.allow_checkerboarding", APZAllowCheckerboarding, bool, true);
|
||||
|
|
|
@ -81,6 +81,16 @@ Unify(ExprType one, ExprType two)
|
|||
return ExprType::Void;
|
||||
}
|
||||
|
||||
static bool
|
||||
IsI64Implemented()
|
||||
{
|
||||
#ifdef JS_CPU_X64
|
||||
return true;
|
||||
#else
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
class FunctionDecoder
|
||||
{
|
||||
JSContext* cx_;
|
||||
|
@ -108,11 +118,9 @@ class FunctionDecoder
|
|||
return Fail(cx_, d_, str);
|
||||
}
|
||||
bool checkI64Support() {
|
||||
#ifdef JS_CPU_X64
|
||||
if (!IsI64Implemented())
|
||||
return fail("i64 NYI on this platform");
|
||||
return true;
|
||||
#else
|
||||
return fail("i64 NYI on this platform");
|
||||
#endif
|
||||
}
|
||||
|
||||
MOZ_WARN_UNUSED_RESULT bool pushBlock() {
|
||||
|
@ -1073,14 +1081,16 @@ DecodeFunctionTable(JSContext* cx, Decoder& d, ModuleGeneratorData* init)
|
|||
static bool
|
||||
CheckTypeForJS(JSContext* cx, Decoder& d, const Sig& sig)
|
||||
{
|
||||
bool allowI64 = IsI64Implemented() && JitOptions.wasmTestMode;
|
||||
|
||||
for (ValType argType : sig.args()) {
|
||||
if (argType == ValType::I64)
|
||||
if (argType == ValType::I64 && !allowI64)
|
||||
return Fail(cx, d, "cannot import/export i64 argument");
|
||||
if (IsSimdType(argType))
|
||||
return Fail(cx, d, "cannot import/export SIMD argument");
|
||||
}
|
||||
|
||||
if (sig.ret() == ExprType::I64)
|
||||
if (sig.ret() == ExprType::I64 && !allowI64)
|
||||
return Fail(cx, d, "cannot import/export i64 return type");
|
||||
if (IsSimdType(sig.ret()))
|
||||
return Fail(cx, d, "cannot import/export SIMD return type");
|
||||
|
|
|
@ -958,6 +958,12 @@ class FunctionCompiler
|
|||
return numPushed;
|
||||
}
|
||||
|
||||
static MDefinition* peekPushedDef(MBasicBlock* block)
|
||||
{
|
||||
MOZ_ASSERT(hasPushed(block));
|
||||
return block->getSlot(block->stackDepth() - 1);
|
||||
}
|
||||
|
||||
public:
|
||||
void pushDef(MDefinition* def)
|
||||
{
|
||||
|
@ -968,21 +974,39 @@ class FunctionCompiler
|
|||
curBlock_->push(def);
|
||||
}
|
||||
|
||||
MDefinition* popDefIfPushed()
|
||||
{
|
||||
if (!hasPushed(curBlock_))
|
||||
return nullptr;
|
||||
MDefinition* def = curBlock_->pop();
|
||||
MOZ_ASSERT(def->type() != MIRType_Value);
|
||||
return def;
|
||||
}
|
||||
|
||||
template <typename GetBlock>
|
||||
void ensurePushInvariants(const GetBlock& getBlock, size_t numBlocks)
|
||||
{
|
||||
// Preserve the invariant that, for every iterated MBasicBlock,
|
||||
// either: every MBasicBlock has a non-void pushed expression OR no
|
||||
// MBasicBlock has any pushed expression. This is required by
|
||||
// MBasicBlock::addPredecessor.
|
||||
bool allPushed = true;
|
||||
// Preserve the invariant that, for every iterated MBasicBlock, either:
|
||||
// every MBasicBlock has a pushed expression with the same type (to
|
||||
// prevent creating phis with type Value) OR no MBasicBlock has any
|
||||
// pushed expression. This is required by MBasicBlock::addPredecessor.
|
||||
if (numBlocks < 2)
|
||||
return;
|
||||
|
||||
for (size_t i = 0; allPushed && i < numBlocks; i++)
|
||||
allPushed = hasPushed(getBlock(i));
|
||||
MBasicBlock* block = getBlock(0);
|
||||
|
||||
bool allPushed = hasPushed(block);
|
||||
if (allPushed) {
|
||||
MIRType type = peekPushedDef(block)->type();
|
||||
for (size_t i = 1; allPushed && i < numBlocks; i++) {
|
||||
block = getBlock(i);
|
||||
allPushed = hasPushed(block) && peekPushedDef(block)->type() == type;
|
||||
}
|
||||
}
|
||||
|
||||
if (!allPushed) {
|
||||
for (size_t i = 0; i < numBlocks; i++) {
|
||||
MBasicBlock* block = getBlock(i);
|
||||
block = getBlock(i);
|
||||
if (hasPushed(block))
|
||||
block->pop();
|
||||
}
|
||||
|
@ -1034,10 +1058,7 @@ class FunctionCompiler
|
|||
}
|
||||
|
||||
curBlock_ = join;
|
||||
if (hasPushed(curBlock_))
|
||||
*def = curBlock_->pop();
|
||||
else
|
||||
*def = nullptr;
|
||||
*def = popDefIfPushed();
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -1357,7 +1378,7 @@ class FunctionCompiler
|
|||
bool bindBranches(uint32_t absolute, MDefinition** def)
|
||||
{
|
||||
if (absolute >= blockPatches_.length() || blockPatches_[absolute].empty()) {
|
||||
*def = !inDeadCode() && hasPushed(curBlock_) ? curBlock_->pop() : nullptr;
|
||||
*def = inDeadCode() ? nullptr : popDefIfPushed();
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -1400,7 +1421,7 @@ class FunctionCompiler
|
|||
return false;
|
||||
curBlock_ = join;
|
||||
|
||||
*def = hasPushed(curBlock_) ? curBlock_->pop() : nullptr;
|
||||
*def = popDefIfPushed();
|
||||
|
||||
patches.clear();
|
||||
return true;
|
||||
|
|
Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше
Загрузка…
Ссылка в новой задаче