mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Merge b2g-inbound to m-c
This commit is contained in:
commit
bd028a4319
@ -1,4 +1,4 @@
|
||||
{
|
||||
"revision": "00ceae21c52602059b7614b661bc39a3c73c84de",
|
||||
"revision": "e9d3946c6e4c26c60f67b8efac40e14785b634d3",
|
||||
"repo_path": "/integration/gaia-central"
|
||||
}
|
||||
|
@ -61,8 +61,10 @@ NS_IMPL_RELEASE_INHERITED(MediaRecorder, nsDOMEventTargetHelper)
|
||||
* 2) A Session is destroyed in DestroyRunnable after MediaRecorder::Stop being called
|
||||
* _and_ all encoded media data been passed to OnDataAvailable handler.
|
||||
*/
|
||||
class MediaRecorder::Session
|
||||
class MediaRecorder::Session: public nsIObserver
|
||||
{
|
||||
NS_DECL_THREADSAFE_ISUPPORTS
|
||||
|
||||
// Main thread task.
|
||||
// Create a blob event and send back to client.
|
||||
class PushBlobRunnable : public nsRunnable
|
||||
@ -114,7 +116,7 @@ class MediaRecorder::Session
|
||||
class DestroyRunnable : public nsRunnable
|
||||
{
|
||||
public:
|
||||
DestroyRunnable(Session *aSession)
|
||||
DestroyRunnable(const already_AddRefed<Session> &aSession)
|
||||
: mSession(aSession) {}
|
||||
|
||||
NS_IMETHODIMP Run()
|
||||
@ -122,12 +124,16 @@ class MediaRecorder::Session
|
||||
MOZ_ASSERT(NS_IsMainThread() && mSession.get());
|
||||
MediaRecorder *recorder = mSession->mRecorder;
|
||||
|
||||
// If MediaRecoder is not in Inactive mode, call MediaRecoder::Stop
|
||||
// and dispatch DestroyRunnable again.
|
||||
// SourceMediaStream is ended, and send out TRACK_EVENT_END notification.
|
||||
// Read Thread will be terminate soon.
|
||||
// We need to switch MediaRecorder to "Stop" state first to make sure
|
||||
// MediaRecorder is not associated with this Session anymore, then, it's
|
||||
// safe to delete this Session.
|
||||
if (recorder->mState != RecordingState::Inactive) {
|
||||
ErrorResult result;
|
||||
recorder->Stop(result);
|
||||
NS_DispatchToMainThread(new DestroyRunnable(mSession.forget()));
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
@ -135,14 +141,12 @@ class MediaRecorder::Session
|
||||
recorder->DispatchSimpleEvent(NS_LITERAL_STRING("stop"));
|
||||
recorder->SetMimeType(NS_LITERAL_STRING(""));
|
||||
|
||||
// Delete session object.
|
||||
mSession = nullptr;
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
private:
|
||||
nsAutoPtr<Session> mSession;
|
||||
// Call mSession::Release automatically while DestroyRunnable be destroy.
|
||||
nsRefPtr<Session> mSession;
|
||||
};
|
||||
|
||||
friend class PushBlobRunnable;
|
||||
@ -156,21 +160,16 @@ public:
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
||||
AddRef();
|
||||
mEncodedBufferCache = new EncodedBufferCache(MAX_ALLOW_MEMORY_BUFFER);
|
||||
}
|
||||
|
||||
// Only DestroyRunnable is allowed to delete Session object.
|
||||
~Session()
|
||||
virtual ~Session()
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
||||
if (mInputPort.get()) {
|
||||
mInputPort->Destroy();
|
||||
}
|
||||
|
||||
if (mTrackUnionStream.get()) {
|
||||
mTrackUnionStream->Destroy();
|
||||
}
|
||||
CleanupStreams();
|
||||
}
|
||||
|
||||
void Start()
|
||||
@ -183,17 +182,16 @@ public:
|
||||
if (!mReadThread) {
|
||||
nsresult rv = NS_NewNamedThread("Media Encoder", getter_AddRefs(mReadThread));
|
||||
if (NS_FAILED(rv)) {
|
||||
if (mInputPort.get()) {
|
||||
mInputPort->Destroy();
|
||||
}
|
||||
if (mTrackUnionStream.get()) {
|
||||
mTrackUnionStream->Destroy();
|
||||
}
|
||||
CleanupStreams();
|
||||
mRecorder->NotifyError(rv);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// In case source media stream does not notify track end, recieve
|
||||
// shutdown notification and stop Read Thread.
|
||||
nsContentUtils::RegisterShutdownObserver(this);
|
||||
|
||||
mReadThread->Dispatch(new ExtractRunnable(this), NS_DISPATCH_NORMAL);
|
||||
}
|
||||
|
||||
@ -201,18 +199,8 @@ public:
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
||||
// Shutdown mEncoder to stop Session::Extract
|
||||
if (mInputPort.get())
|
||||
{
|
||||
mInputPort->Destroy();
|
||||
mInputPort = nullptr;
|
||||
}
|
||||
|
||||
if (mTrackUnionStream.get())
|
||||
{
|
||||
mTrackUnionStream->Destroy();
|
||||
mTrackUnionStream = nullptr;
|
||||
}
|
||||
CleanupStreams();
|
||||
nsContentUtils::UnregisterShutdownObserver(this);
|
||||
}
|
||||
|
||||
void Pause()
|
||||
@ -233,6 +221,7 @@ public:
|
||||
{
|
||||
nsString mimeType;
|
||||
mRecorder->GetMimeType(mimeType);
|
||||
|
||||
return mEncodedBufferCache->ExtractBlob(mimeType);
|
||||
}
|
||||
|
||||
@ -273,7 +262,7 @@ private:
|
||||
NS_DispatchToMainThread(new PushBlobRunnable(this));
|
||||
|
||||
// Destroy this session object in main thread.
|
||||
NS_DispatchToMainThread(new DestroyRunnable(this));
|
||||
NS_DispatchToMainThread(new DestroyRunnable(already_AddRefed<Session>(this)));
|
||||
}
|
||||
|
||||
// Bind media source with MediaEncoder to receive raw media data.
|
||||
@ -281,15 +270,17 @@ private:
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
||||
// Create a Track Union Stream
|
||||
MediaStreamGraph* gm = mRecorder->mStream->GetStream()->Graph();
|
||||
mTrackUnionStream = gm->CreateTrackUnionStream(nullptr);
|
||||
MOZ_ASSERT(mTrackUnionStream, "CreateTrackUnionStream failed");
|
||||
|
||||
mTrackUnionStream->SetAutofinish(true);
|
||||
|
||||
// Bind this Track Union Stream with Source Media
|
||||
mInputPort = mTrackUnionStream->AllocateInputPort(mRecorder->mStream->GetStream(), MediaInputPort::FLAG_BLOCK_OUTPUT);
|
||||
|
||||
// Allocate encoder and bind with union stream.
|
||||
// Allocate encoder and bind with the Track Union Stream.
|
||||
mEncoder = MediaEncoder::CreateEncoder(NS_LITERAL_STRING(""));
|
||||
MOZ_ASSERT(mEncoder, "CreateEncoder failed");
|
||||
|
||||
@ -298,11 +289,37 @@ private:
|
||||
}
|
||||
}
|
||||
|
||||
void CleanupStreams()
|
||||
{
|
||||
if (mInputPort.get()) {
|
||||
mInputPort->Destroy();
|
||||
mInputPort = nullptr;
|
||||
}
|
||||
|
||||
if (mTrackUnionStream.get()) {
|
||||
mTrackUnionStream->Destroy();
|
||||
mTrackUnionStream = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
NS_IMETHODIMP Observe(nsISupports *aSubject, const char *aTopic, const PRUnichar *aData)
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
||||
if (strcmp(aTopic, NS_XPCOM_SHUTDOWN_OBSERVER_ID) == 0) {
|
||||
// Force stop Session to terminate Read Thread.
|
||||
Stop();
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
private:
|
||||
// Hold a reference to MediaRecoder to make sure MediaRecoder be
|
||||
// destroyed after all session object dead.
|
||||
nsRefPtr<MediaRecorder> mRecorder;
|
||||
|
||||
// Receive track data from source and dispatch to Encoder.
|
||||
// Pause/ Resume controller.
|
||||
nsRefPtr<ProcessedMediaStream> mTrackUnionStream;
|
||||
nsRefPtr<MediaInputPort> mInputPort;
|
||||
@ -320,6 +337,8 @@ private:
|
||||
const int32_t mTimeSlice;
|
||||
};
|
||||
|
||||
NS_IMPL_ISUPPORTS1(MediaRecorder::Session, nsIObserver)
|
||||
|
||||
MediaRecorder::~MediaRecorder()
|
||||
{
|
||||
MOZ_ASSERT(mSession == nullptr);
|
||||
|
@ -2154,16 +2154,17 @@ this.DOMApplicationRegistry = {
|
||||
queuedDownload: {},
|
||||
queuedPackageDownload: {},
|
||||
|
||||
onInstallSuccessAck: function onInstallSuccessAck(aManifestURL) {
|
||||
onInstallSuccessAck: function onInstallSuccessAck(aManifestURL,
|
||||
aDontNeedNetwork) {
|
||||
// If we are offline, register to run when we'll be online.
|
||||
if (Services.io.offline) {
|
||||
if ((Services.io.offline) && !aDontNeedNetwork) {
|
||||
let onlineWrapper = {
|
||||
observe: function(aSubject, aTopic, aData) {
|
||||
Services.obs.removeObserver(onlineWrapper,
|
||||
"network:offline-status-changed");
|
||||
DOMApplicationRegistry.onInstallSuccessAck(aManifestURL);
|
||||
}
|
||||
}
|
||||
};
|
||||
Services.obs.addObserver(onlineWrapper,
|
||||
"network:offline-status-changed", false);
|
||||
return;
|
||||
@ -2368,12 +2369,13 @@ this.DOMApplicationRegistry = {
|
||||
aInstallSuccessCallback(app.manifest);
|
||||
}
|
||||
}
|
||||
|
||||
let dontNeedNetwork = false;
|
||||
if (manifest.package_path) {
|
||||
// If it is a local app then it must been installed from a local file
|
||||
// instead of web.
|
||||
let origPath = jsonManifest.package_path;
|
||||
if (aData.app.localInstallPath) {
|
||||
dontNeedNetwork = true;
|
||||
jsonManifest.package_path = "file://" + aData.app.localInstallPath;
|
||||
}
|
||||
// origin for install apps is meaningless here, since it's app:// and this
|
||||
@ -2390,7 +2392,7 @@ this.DOMApplicationRegistry = {
|
||||
if (aData.forceSuccessAck) {
|
||||
// If it's a local install, there's no content process so just
|
||||
// ack the install.
|
||||
this.onInstallSuccessAck(app.manifestURL);
|
||||
this.onInstallSuccessAck(app.manifestURL, dontNeedNetwork);
|
||||
}
|
||||
},
|
||||
|
||||
|
@ -14,6 +14,10 @@
|
||||
#include "mozilla/dom/PFMRadioChild.h"
|
||||
#include "mozilla/dom/FMRadioService.h"
|
||||
#include "DOMRequest.h"
|
||||
#include "nsDOMClassInfo.h"
|
||||
#include "nsIDocShell.h"
|
||||
#include "nsIInterfaceRequestorUtils.h"
|
||||
#include "nsIAudioManager.h"
|
||||
|
||||
#undef LOG
|
||||
#define LOG(args...) FM_LOG("FMRadio", args)
|
||||
@ -110,6 +114,27 @@ FMRadio::Init(nsPIDOMWindow *aWindow)
|
||||
mHeadphoneState = GetCurrentSwitchState(SWITCH_HEADPHONES);
|
||||
RegisterSwitchObserver(SWITCH_HEADPHONES, this);
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIDOMEventTarget> target = do_QueryInterface(GetOwner());
|
||||
NS_ENSURE_TRUE_VOID(target);
|
||||
target->AddSystemEventListener(NS_LITERAL_STRING("visibilitychange"), this,
|
||||
/* useCapture = */ true,
|
||||
/* wantsUntrusted = */ false);
|
||||
|
||||
mAudioChannelAgent = do_CreateInstance("@mozilla.org/audiochannelagent;1");
|
||||
if (!mAudioChannelAgent) {
|
||||
return;
|
||||
}
|
||||
|
||||
mAudioChannelAgent->InitWithWeakCallback(nsIAudioChannelAgent::AUDIO_AGENT_CHANNEL_CONTENT,
|
||||
this);
|
||||
|
||||
nsCOMPtr<nsIDocShell> docshell = do_GetInterface(GetOwner());
|
||||
if (docshell) {
|
||||
bool isActive = false;
|
||||
docshell->GetIsActive(&isActive);
|
||||
mAudioChannelAgent->SetVisibilityState(isActive);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
@ -121,6 +146,11 @@ FMRadio::Shutdown()
|
||||
UnregisterSwitchObserver(SWITCH_HEADPHONES, this);
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIDOMEventTarget> target = do_QueryInterface(GetOwner());
|
||||
NS_ENSURE_TRUE_VOID(target);
|
||||
target->RemoveSystemEventListener(NS_LITERAL_STRING("visibilitychange"), this,
|
||||
/* useCapture = */ true);
|
||||
|
||||
mIsShutdown = true;
|
||||
}
|
||||
|
||||
@ -151,8 +181,14 @@ FMRadio::Notify(const FMRadioEventType& aType)
|
||||
break;
|
||||
case EnabledChanged:
|
||||
if (Enabled()) {
|
||||
int32_t playingState = 0;
|
||||
mAudioChannelAgent->StartPlaying(&playingState);
|
||||
SetCanPlay(playingState == AudioChannelState::AUDIO_CHANNEL_STATE_NORMAL);
|
||||
|
||||
DispatchTrustedEvent(NS_LITERAL_STRING("enabled"));
|
||||
} else {
|
||||
mAudioChannelAgent->StopPlaying();
|
||||
|
||||
DispatchTrustedEvent(NS_LITERAL_STRING("disabled"));
|
||||
}
|
||||
break;
|
||||
@ -284,8 +320,43 @@ FMRadio::CancelSeek()
|
||||
return r.forget();
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
FMRadio::HandleEvent(nsIDOMEvent* aEvent)
|
||||
{
|
||||
nsAutoString type;
|
||||
aEvent->GetType(type);
|
||||
|
||||
if (!type.EqualsLiteral("visibilitychange")) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIDocShell> docshell = do_GetInterface(GetOwner());
|
||||
NS_ENSURE_TRUE(docshell, NS_ERROR_FAILURE);
|
||||
|
||||
bool isActive = false;
|
||||
docshell->GetIsActive(&isActive);
|
||||
|
||||
mAudioChannelAgent->SetVisibilityState(isActive);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
FMRadio::CanPlayChanged(int32_t aCanPlay)
|
||||
{
|
||||
SetCanPlay(aCanPlay == AudioChannelState::AUDIO_CHANNEL_STATE_NORMAL);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
void
|
||||
FMRadio::SetCanPlay(bool aCanPlay)
|
||||
{
|
||||
IFMRadioService::Singleton()->EnableAudio(aCanPlay);
|
||||
}
|
||||
|
||||
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(FMRadio)
|
||||
NS_INTERFACE_MAP_ENTRY(nsISupportsWeakReference)
|
||||
NS_INTERFACE_MAP_ENTRY(nsIAudioChannelAgentCallback)
|
||||
NS_INTERFACE_MAP_ENTRY(nsIDOMEventListener)
|
||||
NS_INTERFACE_MAP_END_INHERITING(nsDOMEventTargetHelper)
|
||||
|
||||
NS_IMPL_ADDREF_INHERITED(FMRadio, nsDOMEventTargetHelper)
|
||||
|
@ -11,6 +11,7 @@
|
||||
#include "nsCycleCollectionParticipant.h"
|
||||
#include "mozilla/HalTypes.h"
|
||||
#include "nsWeakReference.h"
|
||||
#include "AudioChannelAgent.h"
|
||||
|
||||
class nsPIDOMWindow;
|
||||
class nsIScriptContext;
|
||||
@ -23,6 +24,9 @@ class FMRadio MOZ_FINAL : public nsDOMEventTargetHelper
|
||||
, public hal::SwitchObserver
|
||||
, public FMRadioEventObserver
|
||||
, public nsSupportsWeakReference
|
||||
, public nsIAudioChannelAgentCallback
|
||||
, public nsIDOMEventListener
|
||||
|
||||
{
|
||||
friend class FMRadioRequest;
|
||||
|
||||
@ -30,6 +34,7 @@ public:
|
||||
FMRadio();
|
||||
|
||||
NS_DECL_ISUPPORTS_INHERITED
|
||||
NS_DECL_NSIAUDIOCHANNELAGENTCALLBACK
|
||||
|
||||
NS_REALLY_FORWARD_NSIDOMEVENTTARGET(nsDOMEventTargetHelper)
|
||||
|
||||
@ -78,12 +83,19 @@ public:
|
||||
IMPL_EVENT_HANDLER(antennaavailablechange);
|
||||
IMPL_EVENT_HANDLER(frequencychange);
|
||||
|
||||
// nsIDOMEventListener
|
||||
NS_IMETHOD HandleEvent(nsIDOMEvent* aEvent);
|
||||
|
||||
private:
|
||||
~FMRadio();
|
||||
|
||||
void SetCanPlay(bool aCanPlay);
|
||||
|
||||
hal::SwitchState mHeadphoneState;
|
||||
bool mHasInternalAntenna;
|
||||
bool mIsShutdown;
|
||||
|
||||
nsCOMPtr<nsIAudioChannelAgent> mAudioChannelAgent;
|
||||
};
|
||||
|
||||
END_FMRADIO_NAMESPACE
|
||||
|
@ -123,12 +123,8 @@ public:
|
||||
info.spaceType() = mSpaceType;
|
||||
|
||||
EnableFMRadio(info);
|
||||
IFMRadioService::Singleton()->EnableAudio(true);
|
||||
|
||||
nsCOMPtr<nsIAudioManager> audioManager =
|
||||
do_GetService(NS_AUDIOMANAGER_CONTRACTID);
|
||||
audioManager->SetFmRadioAudioEnabled(true);
|
||||
|
||||
// TODO apply path from bug 862899: AudioChannelAgent per process
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
@ -209,11 +205,7 @@ public:
|
||||
// Fix Bug 796733. DisableFMRadio should be called before
|
||||
// SetFmRadioAudioEnabled to prevent the annoying beep sound.
|
||||
DisableFMRadio();
|
||||
|
||||
nsCOMPtr<nsIAudioManager> audioManager =
|
||||
do_GetService(NS_AUDIOMANAGER_CONTRACTID);
|
||||
|
||||
audioManager->SetFmRadioAudioEnabled(false);
|
||||
IFMRadioService::Singleton()->EnableAudio(false);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
@ -299,6 +291,24 @@ FMRadioService::RemoveObserver(FMRadioEventObserver* aObserver)
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
FMRadioService::EnableAudio(bool aAudioEnabled)
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread(), "Wrong thread!");
|
||||
|
||||
nsCOMPtr<nsIAudioManager> audioManager =
|
||||
do_GetService("@mozilla.org/telephony/audiomanager;1");
|
||||
if (!audioManager) {
|
||||
return;
|
||||
}
|
||||
|
||||
bool AudioEnabled;
|
||||
audioManager->GetFmRadioAudioEnabled(&AudioEnabled);
|
||||
if (AudioEnabled != aAudioEnabled) {
|
||||
audioManager->SetFmRadioAudioEnabled(aAudioEnabled);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Round the frequency to match the range of frequency and the channel width. If
|
||||
* the given frequency is out of range, return 0. For example:
|
||||
|
@ -117,6 +117,9 @@ public:
|
||||
virtual void AddObserver(FMRadioEventObserver* aObserver) = 0;
|
||||
virtual void RemoveObserver(FMRadioEventObserver* aObserver) = 0;
|
||||
|
||||
// Enable/Disable FMRadio
|
||||
virtual void EnableAudio(bool aAudioEnabled) = 0;
|
||||
|
||||
/**
|
||||
* Static method to return the singleton instance. If it's in the child
|
||||
* process, we will get an object of FMRadioChild.
|
||||
@ -164,6 +167,8 @@ public:
|
||||
virtual void AddObserver(FMRadioEventObserver* aObserver) MOZ_OVERRIDE;
|
||||
virtual void RemoveObserver(FMRadioEventObserver* aObserver) MOZ_OVERRIDE;
|
||||
|
||||
virtual void EnableAudio(bool aAudioEnabled) MOZ_OVERRIDE;
|
||||
|
||||
/* FMRadioObserver */
|
||||
void Notify(const hal::FMRadioOperationInformation& aInfo) MOZ_OVERRIDE;
|
||||
|
||||
|
@ -165,6 +165,12 @@ FMRadioChild::DeallocPFMRadioRequestChild(PFMRadioRequestChild* aActor)
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
FMRadioChild::EnableAudio(bool aAudioEnabled)
|
||||
{
|
||||
SendEnableAudio(aAudioEnabled);
|
||||
}
|
||||
|
||||
// static
|
||||
FMRadioChild*
|
||||
FMRadioChild::Singleton()
|
||||
|
@ -51,6 +51,8 @@ public:
|
||||
virtual void AddObserver(FMRadioEventObserver* aObserver) MOZ_OVERRIDE;
|
||||
virtual void RemoveObserver(FMRadioEventObserver* aObserver) MOZ_OVERRIDE;
|
||||
|
||||
virtual void EnableAudio(bool aAudioEnabled) MOZ_OVERRIDE;
|
||||
|
||||
/* PFMRadioChild */
|
||||
virtual bool
|
||||
Recv__delete__() MOZ_OVERRIDE;
|
||||
|
@ -97,5 +97,12 @@ FMRadioParent::Notify(const FMRadioEventType& aType)
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
FMRadioParent::RecvEnableAudio(const bool& aAudioEnabled)
|
||||
{
|
||||
IFMRadioService::Singleton()->EnableAudio(aAudioEnabled);
|
||||
return true;
|
||||
}
|
||||
|
||||
END_FMRADIO_NAMESPACE
|
||||
|
||||
|
@ -33,6 +33,9 @@ public:
|
||||
|
||||
/* FMRadioEventObserver */
|
||||
virtual void Notify(const FMRadioEventType& aType) MOZ_OVERRIDE;
|
||||
|
||||
virtual bool
|
||||
RecvEnableAudio(const bool& aAudioEnabled) MOZ_OVERRIDE;
|
||||
};
|
||||
|
||||
END_FMRADIO_NAMESPACE
|
||||
|
@ -86,6 +86,11 @@ parent:
|
||||
* is more error prone.
|
||||
*/
|
||||
PFMRadioRequest(FMRadioRequestArgs requestType);
|
||||
|
||||
/**
|
||||
* Enable/Disable audio
|
||||
*/
|
||||
EnableAudio(bool audioEnabled);
|
||||
};
|
||||
|
||||
} // namespace dom
|
||||
|
@ -141,7 +141,7 @@ APZCTreeManager::UpdatePanZoomControllerTree(CompositorParent* aCompositor,
|
||||
apzc->NotifyLayersUpdated(container->GetFrameMetrics(),
|
||||
aIsFirstPaint && (aLayersId == aFirstPaintLayersId));
|
||||
|
||||
LayerRect visible = ScreenRect(container->GetFrameMetrics().mCompositionBounds) * ScreenToLayerScale(1.0);
|
||||
ScreenRect visible(container->GetFrameMetrics().mCompositionBounds);
|
||||
apzc->SetLayerHitTestData(visible, aTransform, aLayer->GetTransform());
|
||||
APZC_LOG("Setting rect(%f %f %f %f) as visible region for APZC %p\n", visible.x, visible.y,
|
||||
visible.width, visible.height,
|
||||
@ -233,7 +233,7 @@ APZCTreeManager::ReceiveInputEvent(const InputData& aEvent)
|
||||
{
|
||||
nsEventStatus result = nsEventStatus_eIgnore;
|
||||
gfx3DMatrix transformToApzc;
|
||||
gfx3DMatrix transformToScreen;
|
||||
gfx3DMatrix transformToGecko;
|
||||
switch (aEvent.mInputType) {
|
||||
case MULTITOUCH_INPUT: {
|
||||
const MultiTouchInput& multiTouchInput = aEvent.AsMultiTouchInput();
|
||||
@ -251,7 +251,7 @@ APZCTreeManager::ReceiveInputEvent(const InputData& aEvent)
|
||||
|
||||
// Cache transformToApzc so it can be used for future events in this block.
|
||||
if (mApzcForInputBlock) {
|
||||
GetInputTransforms(mApzcForInputBlock, transformToApzc, transformToScreen);
|
||||
GetInputTransforms(mApzcForInputBlock, transformToApzc, transformToGecko);
|
||||
mCachedTransformToApzcForInputBlock = transformToApzc;
|
||||
}
|
||||
} else if (mApzcForInputBlock) {
|
||||
@ -279,7 +279,7 @@ APZCTreeManager::ReceiveInputEvent(const InputData& aEvent)
|
||||
const PinchGestureInput& pinchInput = aEvent.AsPinchGestureInput();
|
||||
nsRefPtr<AsyncPanZoomController> apzc = GetTargetAPZC(pinchInput.mFocusPoint);
|
||||
if (apzc) {
|
||||
GetInputTransforms(apzc, transformToApzc, transformToScreen);
|
||||
GetInputTransforms(apzc, transformToApzc, transformToGecko);
|
||||
PinchGestureInput inputForApzc(pinchInput);
|
||||
ApplyTransform(&(inputForApzc.mFocusPoint), transformToApzc);
|
||||
result = apzc->ReceiveInputEvent(inputForApzc);
|
||||
@ -289,7 +289,7 @@ APZCTreeManager::ReceiveInputEvent(const InputData& aEvent)
|
||||
const TapGestureInput& tapInput = aEvent.AsTapGestureInput();
|
||||
nsRefPtr<AsyncPanZoomController> apzc = GetTargetAPZC(ScreenPoint(tapInput.mPoint));
|
||||
if (apzc) {
|
||||
GetInputTransforms(apzc, transformToApzc, transformToScreen);
|
||||
GetInputTransforms(apzc, transformToApzc, transformToGecko);
|
||||
TapGestureInput inputForApzc(tapInput);
|
||||
ApplyTransform(&(inputForApzc.mPoint), transformToApzc);
|
||||
result = apzc->ReceiveInputEvent(inputForApzc);
|
||||
@ -305,7 +305,7 @@ APZCTreeManager::GetTouchInputBlockAPZC(const WidgetTouchEvent& aEvent,
|
||||
ScreenPoint aPoint)
|
||||
{
|
||||
nsRefPtr<AsyncPanZoomController> apzc = GetTargetAPZC(aPoint);
|
||||
gfx3DMatrix transformToApzc, transformToScreen;
|
||||
gfx3DMatrix transformToApzc, transformToGecko;
|
||||
// Reset the cached apz transform
|
||||
mCachedTransformToApzcForInputBlock = transformToApzc;
|
||||
if (!apzc) {
|
||||
@ -324,7 +324,7 @@ APZCTreeManager::GetTouchInputBlockAPZC(const WidgetTouchEvent& aEvent,
|
||||
}
|
||||
if (apzc) {
|
||||
// Cache apz transform so it can be used for future events in this block.
|
||||
GetInputTransforms(apzc, mCachedTransformToApzcForInputBlock, transformToScreen);
|
||||
GetInputTransforms(apzc, mCachedTransformToApzcForInputBlock, transformToGecko);
|
||||
}
|
||||
return apzc.get();
|
||||
}
|
||||
@ -344,11 +344,11 @@ APZCTreeManager::ProcessTouchEvent(const WidgetTouchEvent& aEvent,
|
||||
nsEventStatus ret = mApzcForInputBlock->ReceiveInputEvent(inputForApzc);
|
||||
|
||||
// For computing the event to pass back to Gecko, use the up-to-date transforms.
|
||||
// This ensures that transformToApzc and transformToScreen are in sync
|
||||
// (note that transformToScreen isn't cached).
|
||||
gfx3DMatrix transformToScreen;
|
||||
GetInputTransforms(mApzcForInputBlock, transformToApzc, transformToScreen);
|
||||
gfx3DMatrix outTransform = transformToApzc * transformToScreen;
|
||||
// This ensures that transformToApzc and transformToGecko are in sync
|
||||
// (note that transformToGecko isn't cached).
|
||||
gfx3DMatrix transformToGecko;
|
||||
GetInputTransforms(mApzcForInputBlock, transformToApzc, transformToGecko);
|
||||
gfx3DMatrix outTransform = transformToApzc * transformToGecko;
|
||||
for (size_t i = 0; i < aOutEvent->touches.Length(); i++) {
|
||||
ApplyTransform(&(aOutEvent->touches[i]->mRefPoint), outTransform);
|
||||
}
|
||||
@ -371,11 +371,11 @@ APZCTreeManager::ProcessMouseEvent(const WidgetMouseEvent& aEvent,
|
||||
return nsEventStatus_eIgnore;
|
||||
}
|
||||
gfx3DMatrix transformToApzc;
|
||||
gfx3DMatrix transformToScreen;
|
||||
GetInputTransforms(apzc, transformToApzc, transformToScreen);
|
||||
gfx3DMatrix transformToGecko;
|
||||
GetInputTransforms(apzc, transformToApzc, transformToGecko);
|
||||
MultiTouchInput inputForApzc(aEvent);
|
||||
ApplyTransform(&(inputForApzc.mTouches[0].mScreenPoint), transformToApzc);
|
||||
gfx3DMatrix outTransform = transformToApzc * transformToScreen;
|
||||
gfx3DMatrix outTransform = transformToApzc * transformToGecko;
|
||||
ApplyTransform(&aOutEvent->refPoint, outTransform);
|
||||
return apzc->ReceiveInputEvent(inputForApzc);
|
||||
}
|
||||
@ -390,10 +390,10 @@ APZCTreeManager::ProcessEvent(const WidgetInputEvent& aEvent,
|
||||
return nsEventStatus_eIgnore;
|
||||
}
|
||||
gfx3DMatrix transformToApzc;
|
||||
gfx3DMatrix transformToScreen;
|
||||
GetInputTransforms(apzc, transformToApzc, transformToScreen);
|
||||
gfx3DMatrix transformToGecko;
|
||||
GetInputTransforms(apzc, transformToApzc, transformToGecko);
|
||||
ApplyTransform(&(aOutEvent->refPoint), transformToApzc);
|
||||
gfx3DMatrix outTransform = transformToApzc * transformToScreen;
|
||||
gfx3DMatrix outTransform = transformToApzc * transformToGecko;
|
||||
ApplyTransform(&(aOutEvent->refPoint), outTransform);
|
||||
return nsEventStatus_eIgnore;
|
||||
}
|
||||
@ -542,15 +542,15 @@ APZCTreeManager::HandleOverscroll(AsyncPanZoomController* aChild, ScreenPoint aS
|
||||
return;
|
||||
|
||||
gfx3DMatrix transformToApzc;
|
||||
gfx3DMatrix transformToScreen; // ignored
|
||||
gfx3DMatrix transformToGecko; // ignored
|
||||
|
||||
// Convert start and end points to untransformed screen coordinates.
|
||||
GetInputTransforms(aChild, transformToApzc, transformToScreen);
|
||||
GetInputTransforms(aChild, transformToApzc, transformToGecko);
|
||||
ApplyTransform(&aStartPoint, transformToApzc.Inverse());
|
||||
ApplyTransform(&aEndPoint, transformToApzc.Inverse());
|
||||
|
||||
// Convert start and end points to parent's transformed screen coordinates.
|
||||
GetInputTransforms(parent, transformToApzc, transformToScreen);
|
||||
GetInputTransforms(parent, transformToApzc, transformToGecko);
|
||||
ApplyTransform(&aStartPoint, transformToApzc);
|
||||
ApplyTransform(&aEndPoint, transformToApzc);
|
||||
|
||||
@ -629,36 +629,48 @@ APZCTreeManager::GetAPZCAtPoint(AsyncPanZoomController* aApzc, const gfxPoint& a
|
||||
// comments explain what values are stored in the variables at these two levels. All the comments
|
||||
// use standard matrix notation where the leftmost matrix in a multiplication is applied first.
|
||||
|
||||
// ancestorUntransform is OC.Inverse() * NC.Inverse() * MC.Inverse() at recursion level for L,
|
||||
// and RC.Inverse() * QC.Inverse() at recursion level for P.
|
||||
// ancestorUntransform takes points from aApzc's parent APZC's screen coordinates
|
||||
// to aApzc's screen coordinates.
|
||||
// It is OC.Inverse() * NC.Inverse() * MC.Inverse() at recursion level for L,
|
||||
// and RC.Inverse() * QC.Inverse() at recursion level for P.
|
||||
gfx3DMatrix ancestorUntransform = aApzc->GetAncestorTransform().Inverse();
|
||||
// asyncUntransform is LA.Inverse() at recursion level for L,
|
||||
// and PA.Inverse() at recursion level for P.
|
||||
gfx3DMatrix asyncUntransform = gfx3DMatrix(aApzc->GetCurrentAsyncTransform()).Inverse();
|
||||
// untransformSinceLastApzc is OC.Inverse() * NC.Inverse() * MC.Inverse() * LA.Inverse() * LC.Inverse() at L,
|
||||
// and RC.Inverse() * QC.Inverse() * PA.Inverse() * PC.Inverse() at P.
|
||||
gfx3DMatrix untransformSinceLastApzc = ancestorUntransform * asyncUntransform * aApzc->GetCSSTransform().Inverse();
|
||||
// untransformed is the user input in L's layer space at L,
|
||||
// and in P's layer space at P.
|
||||
gfxPoint untransformed = untransformSinceLastApzc.ProjectPoint(aHitTestPoint);
|
||||
APZC_LOG("Untransformed %f %f to %f %f for APZC %p\n", aHitTestPoint.x, aHitTestPoint.y, untransformed.x, untransformed.y, aApzc);
|
||||
|
||||
// Hit testing for this layer is performed in aApzc's screen coordinates.
|
||||
gfxPoint hitTestPointForThisLayer = ancestorUntransform.ProjectPoint(aHitTestPoint);
|
||||
APZC_LOG("Untransformed %f %f to screen coordinates %f %f for hit-testing APZC %p\n",
|
||||
aHitTestPoint.x, aHitTestPoint.y,
|
||||
hitTestPointForThisLayer.x, hitTestPointForThisLayer.y, aApzc);
|
||||
|
||||
// myUntransform takes points from aApzc's screen coordinates
|
||||
// to aApzc's layer coordinates (which are aApzc's children's screen coordinates).
|
||||
// It is LA.Inverse() * LC.Inverse() at L
|
||||
// and PA.Inverse() * PC.Inverse() at P.
|
||||
gfx3DMatrix myUntransform = gfx3DMatrix(aApzc->GetCurrentAsyncTransform()).Inverse()
|
||||
* aApzc->GetCSSTransform().Inverse();
|
||||
|
||||
// Hit testing for child layers is performed in aApzc's layer coordinates.
|
||||
gfxPoint hitTestPointForChildLayers = myUntransform.ProjectPoint(hitTestPointForThisLayer);
|
||||
APZC_LOG("Untransformed %f %f to layer coordinates %f %f for APZC %p\n",
|
||||
aHitTestPoint.x, aHitTestPoint.y,
|
||||
hitTestPointForChildLayers.x, hitTestPointForChildLayers.y, aApzc);
|
||||
|
||||
// This walks the tree in depth-first, reverse order, so that it encounters
|
||||
// APZCs front-to-back on the screen.
|
||||
for (AsyncPanZoomController* child = aApzc->GetLastChild(); child; child = child->GetPrevSibling()) {
|
||||
AsyncPanZoomController* match = GetAPZCAtPoint(child, untransformed);
|
||||
AsyncPanZoomController* match = GetAPZCAtPoint(child, hitTestPointForChildLayers);
|
||||
if (match) {
|
||||
return match;
|
||||
}
|
||||
}
|
||||
if (aApzc->VisibleRegionContains(LayerPoint(untransformed.x, untransformed.y))) {
|
||||
APZC_LOG("Successfully matched untransformed point %f %f to visible region for APZC %p\n", untransformed.x, untransformed.y, aApzc);
|
||||
if (aApzc->VisibleRegionContains(ScreenPoint(hitTestPointForThisLayer.x, hitTestPointForThisLayer.y))) {
|
||||
APZC_LOG("Successfully matched untransformed point %f %f to visible region for APZC %p\n",
|
||||
hitTestPointForThisLayer.x, hitTestPointForThisLayer.y, aApzc);
|
||||
return aApzc;
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
/* This function sets the aTransformToApzcOut and aTransformToScreenOut out-parameters
|
||||
/* This function sets the aTransformToApzcOut and aTransformToGeckoOut out-parameters
|
||||
to some useful transformations that input events may need applied. This is best
|
||||
illustrated with an example. Consider a chain of layers, L, M, N, O, P, Q, R. Layer L
|
||||
is the layer that corresponds to the returned APZC instance, and layer R is the root
|
||||
@ -706,7 +718,7 @@ APZCTreeManager::GetAPZCAtPoint(AsyncPanZoomController* aApzc, const gfxPoint& a
|
||||
MC
|
||||
...
|
||||
RC
|
||||
Since aTransformToApzcOut is already one of the out-parameters, we set aTransformToScreenOut
|
||||
Since aTransformToApzcOut is already one of the out-parameters, we set aTransformToGeckoOut
|
||||
to the remaining transforms (LA.Inverse() * MC * ... * RC), so that the caller code can
|
||||
combine it with aTransformToApzcOut to get the final transform required in this case.
|
||||
|
||||
@ -721,7 +733,7 @@ APZCTreeManager::GetAPZCAtPoint(AsyncPanZoomController* aApzc, const gfxPoint& a
|
||||
*/
|
||||
void
|
||||
APZCTreeManager::GetInputTransforms(AsyncPanZoomController *aApzc, gfx3DMatrix& aTransformToApzcOut,
|
||||
gfx3DMatrix& aTransformToScreenOut)
|
||||
gfx3DMatrix& aTransformToGeckoOut)
|
||||
{
|
||||
// The comments below assume there is a chain of layers L..R with L and P having APZC instances as
|
||||
// explained in the comment above. This function is called with aApzc at L, and the loop
|
||||
@ -736,8 +748,8 @@ APZCTreeManager::GetInputTransforms(AsyncPanZoomController *aApzc, gfx3DMatrix&
|
||||
|
||||
// aTransformToApzcOut is initialized to OC.Inverse() * NC.Inverse() * MC.Inverse()
|
||||
aTransformToApzcOut = ancestorUntransform;
|
||||
// aTransformToScreenOut is initialized to LA.Inverse() * MC * NC * OC
|
||||
aTransformToScreenOut = asyncUntransform * aApzc->GetAncestorTransform();
|
||||
// aTransformToGeckoOut is initialized to LA.Inverse() * MC * NC * OC
|
||||
aTransformToGeckoOut = asyncUntransform * aApzc->GetAncestorTransform();
|
||||
|
||||
for (AsyncPanZoomController* parent = aApzc->GetParent(); parent; parent = parent->GetParent()) {
|
||||
// ancestorUntransform is updated to RC.Inverse() * QC.Inverse() when parent == P
|
||||
@ -749,10 +761,10 @@ APZCTreeManager::GetInputTransforms(AsyncPanZoomController *aApzc, gfx3DMatrix&
|
||||
|
||||
// aTransformToApzcOut is RC.Inverse() * QC.Inverse() * PA.Inverse() * PC.Inverse() * OC.Inverse() * NC.Inverse() * MC.Inverse()
|
||||
aTransformToApzcOut = untransformSinceLastApzc * aTransformToApzcOut;
|
||||
// aTransformToScreenOut is LA.Inverse() * MC * NC * OC * PC * QC * RC
|
||||
aTransformToScreenOut = aTransformToScreenOut * parent->GetCSSTransform() * parent->GetAncestorTransform();
|
||||
// aTransformToGeckoOut is LA.Inverse() * MC * NC * OC * PC * QC * RC
|
||||
aTransformToGeckoOut = aTransformToGeckoOut * parent->GetCSSTransform() * parent->GetAncestorTransform();
|
||||
|
||||
// The above values for aTransformToApzcOut and aTransformToScreenOut when parent == P match
|
||||
// The above values for aTransformToApzcOut and aTransformToGeckoOut when parent == P match
|
||||
// the required output as explained in the comment above GetTargetAPZC. Note that any missing terms
|
||||
// are async transforms that are guaranteed to be identity transforms.
|
||||
}
|
||||
|
@ -277,7 +277,7 @@ public:
|
||||
already_AddRefed<AsyncPanZoomController> GetTargetAPZC(const ScrollableLayerGuid& aGuid);
|
||||
already_AddRefed<AsyncPanZoomController> GetTargetAPZC(const ScreenPoint& aPoint);
|
||||
void GetInputTransforms(AsyncPanZoomController *aApzc, gfx3DMatrix& aTransformToApzcOut,
|
||||
gfx3DMatrix& aTransformToScreenOut);
|
||||
gfx3DMatrix& aTransformToGeckoOut);
|
||||
private:
|
||||
/* Helpers */
|
||||
AsyncPanZoomController* FindTargetAPZC(AsyncPanZoomController* aApzc, const ScrollableLayerGuid& aGuid);
|
||||
|
@ -655,7 +655,7 @@ private:
|
||||
* hit-testing to see which APZC instance should handle touch events.
|
||||
*/
|
||||
public:
|
||||
void SetLayerHitTestData(const LayerRect& aRect, const gfx3DMatrix& aTransformToLayer,
|
||||
void SetLayerHitTestData(const ScreenRect& aRect, const gfx3DMatrix& aTransformToLayer,
|
||||
const gfx3DMatrix& aTransformForLayer) {
|
||||
mVisibleRect = aRect;
|
||||
mAncestorTransform = aTransformToLayer;
|
||||
@ -670,16 +670,15 @@ public:
|
||||
return mCSSTransform;
|
||||
}
|
||||
|
||||
bool VisibleRegionContains(const LayerPoint& aPoint) const {
|
||||
bool VisibleRegionContains(const ScreenPoint& aPoint) const {
|
||||
return mVisibleRect.Contains(aPoint);
|
||||
}
|
||||
|
||||
private:
|
||||
/* This is the viewport of the layer that this APZC corresponds to, in
|
||||
* layer pixels. It position here does not account for any transformations
|
||||
* applied to any layers, whether they are CSS transforms or async
|
||||
* transforms. */
|
||||
LayerRect mVisibleRect;
|
||||
/* This is the visible region of the layer that this APZC corresponds to, in
|
||||
* that layer's screen pixels (the same coordinate system in which this APZC
|
||||
* receives events in ReceiveInputEvent()). */
|
||||
ScreenRect mVisibleRect;
|
||||
/* This is the cumulative CSS transform for all the layers between the parent
|
||||
* APZC and this one (not inclusive) */
|
||||
gfx3DMatrix mAncestorTransform;
|
||||
|
@ -433,19 +433,17 @@ TEST(AsyncPanZoomController, OverScrollPanning) {
|
||||
EXPECT_EQ(pointOut, ScreenPoint(0, 90));
|
||||
}
|
||||
|
||||
// Layer tree for HitTesting1
|
||||
static already_AddRefed<mozilla::layers::Layer>
|
||||
CreateTestLayerTree(nsRefPtr<LayerManager>& aLayerManager, nsTArray<nsRefPtr<Layer> >& aLayers) {
|
||||
const char* layerTreeSyntax = "c(ttccc(c(c)))";
|
||||
// LayerID 0 12345 6 7
|
||||
CreateTestLayerTree1(nsRefPtr<LayerManager>& aLayerManager, nsTArray<nsRefPtr<Layer> >& aLayers) {
|
||||
const char* layerTreeSyntax = "c(ttcc)";
|
||||
// LayerID 0 1234
|
||||
nsIntRegion layerVisibleRegion[] = {
|
||||
nsIntRegion(nsIntRect(0,0,100,100)),
|
||||
nsIntRegion(nsIntRect(0,0,100,100)),
|
||||
nsIntRegion(nsIntRect(10,10,20,20)),
|
||||
nsIntRegion(nsIntRect(10,10,20,20)),
|
||||
nsIntRegion(nsIntRect(5,5,20,20)),
|
||||
nsIntRegion(nsIntRect(10,10,40,40)),
|
||||
nsIntRegion(nsIntRect(10,10,40,40)),
|
||||
nsIntRegion(nsIntRect(10,10,40,40)),
|
||||
};
|
||||
gfx3DMatrix transforms[] = {
|
||||
gfx3DMatrix(),
|
||||
@ -453,15 +451,35 @@ CreateTestLayerTree(nsRefPtr<LayerManager>& aLayerManager, nsTArray<nsRefPtr<Lay
|
||||
gfx3DMatrix(),
|
||||
gfx3DMatrix(),
|
||||
gfx3DMatrix(),
|
||||
gfx3DMatrix(),
|
||||
gfx3DMatrix(),
|
||||
gfx3DMatrix(),
|
||||
};
|
||||
return CreateLayerTree(layerTreeSyntax, layerVisibleRegion, transforms, aLayerManager, aLayers);
|
||||
}
|
||||
|
||||
// Layer Tree for HitTesting2
|
||||
static already_AddRefed<mozilla::layers::Layer>
|
||||
CreateTestLayerTree2(nsRefPtr<LayerManager>& aLayerManager, nsTArray<nsRefPtr<Layer> >& aLayers) {
|
||||
const char* layerTreeSyntax = "c(cc(c))";
|
||||
// LayerID 0 12 3
|
||||
nsIntRegion layerVisibleRegion[] = {
|
||||
nsIntRegion(nsIntRect(0,0,100,100)),
|
||||
nsIntRegion(nsIntRect(10,10,40,40)),
|
||||
nsIntRegion(nsIntRect(10,60,40,40)),
|
||||
nsIntRegion(nsIntRect(10,60,40,40)),
|
||||
};
|
||||
gfx3DMatrix transforms[] = {
|
||||
gfx3DMatrix(),
|
||||
gfx3DMatrix(),
|
||||
gfx3DMatrix(),
|
||||
gfx3DMatrix(),
|
||||
};
|
||||
return CreateLayerTree(layerTreeSyntax, layerVisibleRegion, transforms, aLayerManager, aLayers);
|
||||
}
|
||||
|
||||
static void
|
||||
SetScrollableFrameMetrics(Layer* aLayer, FrameMetrics::ViewID aScrollId, MockContentController* mcc)
|
||||
SetScrollableFrameMetrics(Layer* aLayer, FrameMetrics::ViewID aScrollId,
|
||||
// The scrollable rect is only used in HitTesting2,
|
||||
// HitTesting1 doesn't care about it.
|
||||
CSSRect aScrollableRect = CSSRect(-1, -1, -1, -1))
|
||||
{
|
||||
ContainerLayer* container = aLayer->AsContainerLayer();
|
||||
FrameMetrics metrics;
|
||||
@ -469,8 +487,8 @@ SetScrollableFrameMetrics(Layer* aLayer, FrameMetrics::ViewID aScrollId, MockCon
|
||||
nsIntRect layerBound = aLayer->GetVisibleRegion().GetBounds();
|
||||
metrics.mCompositionBounds = ScreenIntRect(layerBound.x, layerBound.y,
|
||||
layerBound.width, layerBound.height);
|
||||
metrics.mViewport = CSSRect(layerBound.x, layerBound.y,
|
||||
layerBound.width, layerBound.height);
|
||||
metrics.mScrollableRect = aScrollableRect;
|
||||
metrics.mScrollOffset = CSSPoint(0, 0);
|
||||
container->SetFrameMetrics(metrics);
|
||||
}
|
||||
|
||||
@ -490,19 +508,20 @@ NudgeToIntegers(const gfxPoint& aPoint)
|
||||
|
||||
static already_AddRefed<AsyncPanZoomController>
|
||||
GetTargetAPZC(APZCTreeManager* manager, const ScreenPoint& aPoint,
|
||||
gfx3DMatrix& aTransformToApzcOut, gfx3DMatrix& aTransformToScreenOut)
|
||||
gfx3DMatrix& aTransformToApzcOut, gfx3DMatrix& aTransformToGeckoOut)
|
||||
{
|
||||
nsRefPtr<AsyncPanZoomController> hit = manager->GetTargetAPZC(aPoint);
|
||||
if (hit) {
|
||||
manager->GetInputTransforms(hit.get(), aTransformToApzcOut, aTransformToScreenOut);
|
||||
manager->GetInputTransforms(hit.get(), aTransformToApzcOut, aTransformToGeckoOut);
|
||||
}
|
||||
return hit.forget();
|
||||
}
|
||||
|
||||
TEST(APZCTreeManager, GetAPZCAtPoint) {
|
||||
// A simple hit testing test that doesn't involve any transforms on layers.
|
||||
TEST(APZCTreeManager, HitTesting1) {
|
||||
nsTArray<nsRefPtr<Layer> > layers;
|
||||
nsRefPtr<LayerManager> lm;
|
||||
nsRefPtr<Layer> root = CreateTestLayerTree(lm, layers);
|
||||
nsRefPtr<Layer> root = CreateTestLayerTree1(lm, layers);
|
||||
|
||||
TimeStamp testStartTime = TimeStamp::Now();
|
||||
AsyncPanZoomController::SetFrameTime(testStartTime);
|
||||
@ -511,115 +530,171 @@ TEST(APZCTreeManager, GetAPZCAtPoint) {
|
||||
|
||||
nsRefPtr<APZCTreeManager> manager = new TestAPZCTreeManager();
|
||||
gfx3DMatrix transformToApzc;
|
||||
gfx3DMatrix transformToScreen;
|
||||
gfx3DMatrix transformToGecko;
|
||||
|
||||
// No APZC attached so hit testing will return no APZC at (20,20)
|
||||
nsRefPtr<AsyncPanZoomController> hit = GetTargetAPZC(manager, ScreenPoint(20, 20), transformToApzc, transformToScreen);
|
||||
nsRefPtr<AsyncPanZoomController> hit = GetTargetAPZC(manager, ScreenPoint(20, 20), transformToApzc, transformToGecko);
|
||||
AsyncPanZoomController* nullAPZC = nullptr;
|
||||
EXPECT_EQ(nullAPZC, hit.get());
|
||||
EXPECT_EQ(gfx3DMatrix(), transformToApzc);
|
||||
EXPECT_EQ(gfx3DMatrix(), transformToScreen);
|
||||
EXPECT_EQ(gfx3DMatrix(), transformToGecko);
|
||||
|
||||
// Now we have a root APZC that will match the page
|
||||
SetScrollableFrameMetrics(root, FrameMetrics::ROOT_SCROLL_ID, mcc);
|
||||
manager->UpdatePanZoomControllerTree(nullptr, root, 0, false);
|
||||
hit = GetTargetAPZC(manager, ScreenPoint(15, 15), transformToApzc, transformToScreen);
|
||||
SetScrollableFrameMetrics(root, FrameMetrics::ROOT_SCROLL_ID);
|
||||
manager->UpdatePanZoomControllerTree(nullptr, root, false, 0);
|
||||
hit = GetTargetAPZC(manager, ScreenPoint(15, 15), transformToApzc, transformToGecko);
|
||||
EXPECT_EQ(root->AsContainerLayer()->GetAsyncPanZoomController(), hit.get());
|
||||
// expect hit point at LayerIntPoint(15, 15)
|
||||
EXPECT_EQ(gfxPoint(15, 15), transformToApzc.Transform(gfxPoint(15, 15)));
|
||||
EXPECT_EQ(gfxPoint(15, 15), transformToScreen.Transform(gfxPoint(15, 15)));
|
||||
EXPECT_EQ(gfxPoint(15, 15), transformToGecko.Transform(gfxPoint(15, 15)));
|
||||
|
||||
// Now we have a sub APZC with a better fit
|
||||
SetScrollableFrameMetrics(layers[3], FrameMetrics::START_SCROLL_ID, mcc);
|
||||
manager->UpdatePanZoomControllerTree(nullptr, root, 0, false);
|
||||
SetScrollableFrameMetrics(layers[3], FrameMetrics::START_SCROLL_ID);
|
||||
manager->UpdatePanZoomControllerTree(nullptr, root, false, 0);
|
||||
EXPECT_NE(root->AsContainerLayer()->GetAsyncPanZoomController(), layers[3]->AsContainerLayer()->GetAsyncPanZoomController());
|
||||
hit = GetTargetAPZC(manager, ScreenPoint(15, 15), transformToApzc, transformToScreen);
|
||||
hit = GetTargetAPZC(manager, ScreenPoint(15, 15), transformToApzc, transformToGecko);
|
||||
EXPECT_EQ(layers[3]->AsContainerLayer()->GetAsyncPanZoomController(), hit.get());
|
||||
// expect hit point at LayerIntPoint(15, 15)
|
||||
EXPECT_EQ(gfxPoint(15, 15), transformToApzc.Transform(gfxPoint(15, 15)));
|
||||
EXPECT_EQ(gfxPoint(15, 15), transformToScreen.Transform(gfxPoint(15, 15)));
|
||||
EXPECT_EQ(gfxPoint(15, 15), transformToGecko.Transform(gfxPoint(15, 15)));
|
||||
|
||||
// Now test hit testing when we have two scrollable layers
|
||||
hit = GetTargetAPZC(manager, ScreenPoint(15, 15), transformToApzc, transformToScreen);
|
||||
hit = GetTargetAPZC(manager, ScreenPoint(15, 15), transformToApzc, transformToGecko);
|
||||
EXPECT_EQ(layers[3]->AsContainerLayer()->GetAsyncPanZoomController(), hit.get());
|
||||
SetScrollableFrameMetrics(layers[4], FrameMetrics::START_SCROLL_ID + 1, mcc);
|
||||
manager->UpdatePanZoomControllerTree(nullptr, root, 0, false);
|
||||
hit = GetTargetAPZC(manager, ScreenPoint(15, 15), transformToApzc, transformToScreen);
|
||||
SetScrollableFrameMetrics(layers[4], FrameMetrics::START_SCROLL_ID + 1);
|
||||
manager->UpdatePanZoomControllerTree(nullptr, root, false, 0);
|
||||
hit = GetTargetAPZC(manager, ScreenPoint(15, 15), transformToApzc, transformToGecko);
|
||||
EXPECT_EQ(layers[4]->AsContainerLayer()->GetAsyncPanZoomController(), hit.get());
|
||||
// expect hit point at LayerIntPoint(15, 15)
|
||||
EXPECT_EQ(gfxPoint(15, 15), transformToApzc.Transform(gfxPoint(15, 15)));
|
||||
EXPECT_EQ(gfxPoint(15, 15), transformToScreen.Transform(gfxPoint(15, 15)));
|
||||
EXPECT_EQ(gfxPoint(15, 15), transformToGecko.Transform(gfxPoint(15, 15)));
|
||||
|
||||
// Hit test ouside the reach of layer[3,4] but inside root
|
||||
hit = GetTargetAPZC(manager, ScreenPoint(90, 90), transformToApzc, transformToScreen);
|
||||
hit = GetTargetAPZC(manager, ScreenPoint(90, 90), transformToApzc, transformToGecko);
|
||||
EXPECT_EQ(root->AsContainerLayer()->GetAsyncPanZoomController(), hit.get());
|
||||
// expect hit point at LayerIntPoint(90, 90)
|
||||
EXPECT_EQ(gfxPoint(90, 90), transformToApzc.Transform(gfxPoint(90, 90)));
|
||||
EXPECT_EQ(gfxPoint(90, 90), transformToScreen.Transform(gfxPoint(90, 90)));
|
||||
EXPECT_EQ(gfxPoint(90, 90), transformToGecko.Transform(gfxPoint(90, 90)));
|
||||
|
||||
// Hit test ouside the reach of any layer
|
||||
hit = GetTargetAPZC(manager, ScreenPoint(1000, 10), transformToApzc, transformToScreen);
|
||||
hit = GetTargetAPZC(manager, ScreenPoint(1000, 10), transformToApzc, transformToGecko);
|
||||
EXPECT_EQ(nullAPZC, hit.get());
|
||||
EXPECT_EQ(gfx3DMatrix(), transformToApzc);
|
||||
EXPECT_EQ(gfx3DMatrix(), transformToScreen);
|
||||
hit = GetTargetAPZC(manager, ScreenPoint(-1000, 10), transformToApzc, transformToScreen);
|
||||
EXPECT_EQ(gfx3DMatrix(), transformToGecko);
|
||||
hit = GetTargetAPZC(manager, ScreenPoint(-1000, 10), transformToApzc, transformToGecko);
|
||||
EXPECT_EQ(nullAPZC, hit.get());
|
||||
EXPECT_EQ(gfx3DMatrix(), transformToApzc);
|
||||
EXPECT_EQ(gfx3DMatrix(), transformToScreen);
|
||||
|
||||
// Test layer transform
|
||||
gfx3DMatrix transform;
|
||||
transform.ScalePost(0.1, 0.1, 1);
|
||||
root->SetBaseTransform(transform);
|
||||
manager->UpdatePanZoomControllerTree(nullptr, root, 0, false);
|
||||
hit = GetTargetAPZC(manager, ScreenPoint(50, 50), transformToApzc, transformToScreen); // This point is now outside the root layer
|
||||
EXPECT_EQ(nullAPZC, hit.get());
|
||||
EXPECT_EQ(gfx3DMatrix(), transformToApzc);
|
||||
EXPECT_EQ(gfx3DMatrix(), transformToScreen);
|
||||
|
||||
// This hit test will hit both layers[3] and layers[4]; layers[4] is later in the tree so
|
||||
// it is a better match
|
||||
hit = GetTargetAPZC(manager, ScreenPoint(2, 2), transformToApzc, transformToScreen);
|
||||
EXPECT_EQ(layers[4]->AsContainerLayer()->GetAsyncPanZoomController(), hit.get());
|
||||
// expect hit point at LayerPoint(20, 20)
|
||||
EXPECT_EQ(gfxPoint(20, 20), NudgeToIntegers(transformToApzc.Transform(gfxPoint(2, 2))));
|
||||
EXPECT_EQ(gfxPoint(2, 2), NudgeToIntegers(transformToScreen.Transform(gfxPoint(20, 20))));
|
||||
|
||||
// Scale layer[4] outside the range
|
||||
layers[4]->SetBaseTransform(transform);
|
||||
// layer 4 effective visible screenrect: (0.05, 0.05, 0.2, 0.2)
|
||||
// Does not contain (2, 2)
|
||||
manager->UpdatePanZoomControllerTree(nullptr, root, 0, false);
|
||||
hit = GetTargetAPZC(manager, ScreenPoint(2, 2), transformToApzc, transformToScreen);
|
||||
EXPECT_EQ(layers[3]->AsContainerLayer()->GetAsyncPanZoomController(), hit.get());
|
||||
// expect hit point at LayerPoint(20, 20)
|
||||
EXPECT_EQ(gfxPoint(20, 20), NudgeToIntegers(transformToApzc.Transform(gfxPoint(2, 2))));
|
||||
EXPECT_EQ(gfxPoint(2, 2), NudgeToIntegers(transformToScreen.Transform(gfxPoint(20, 20))));
|
||||
|
||||
// Transformation chain to layer 7
|
||||
SetScrollableFrameMetrics(layers[7], FrameMetrics::START_SCROLL_ID + 2, mcc);
|
||||
|
||||
gfx3DMatrix translateTransform;
|
||||
translateTransform.Translate(gfxPoint3D(10, 10, 0));
|
||||
layers[5]->SetBaseTransform(translateTransform);
|
||||
|
||||
gfx3DMatrix translateTransform2;
|
||||
translateTransform2.Translate(gfxPoint3D(-20, 0, 0));
|
||||
layers[6]->SetBaseTransform(translateTransform2);
|
||||
|
||||
gfx3DMatrix translateTransform3;
|
||||
translateTransform3.ScalePost(1,15,1);
|
||||
layers[7]->SetBaseTransform(translateTransform3);
|
||||
|
||||
manager->UpdatePanZoomControllerTree(nullptr, root, 0, false);
|
||||
// layer 7 effective visible screenrect (0,16,4,60) but clipped by parent layers
|
||||
hit = GetTargetAPZC(manager, ScreenPoint(1, 45), transformToApzc, transformToScreen);
|
||||
EXPECT_EQ(layers[7]->AsContainerLayer()->GetAsyncPanZoomController(), hit.get());
|
||||
// expect hit point at LayerPoint(20, 440), which is CSSPoint(20, 29)
|
||||
EXPECT_EQ(gfxPoint(20, 440), NudgeToIntegers(transformToApzc.Transform(gfxPoint(1, 45))));
|
||||
EXPECT_EQ(gfxPoint(1, 45), NudgeToIntegers(transformToScreen.Transform(gfxPoint(20, 440))));
|
||||
EXPECT_EQ(gfx3DMatrix(), transformToGecko);
|
||||
|
||||
manager->ClearTree();
|
||||
}
|
||||
|
||||
// A more involved hit testing test that involves css and async transforms.
|
||||
TEST(APZCTreeManager, HitTesting2) {
|
||||
nsTArray<nsRefPtr<Layer> > layers;
|
||||
nsRefPtr<LayerManager> lm;
|
||||
nsRefPtr<Layer> root = CreateTestLayerTree2(lm, layers);
|
||||
|
||||
TimeStamp testStartTime = TimeStamp::Now();
|
||||
AsyncPanZoomController::SetFrameTime(testStartTime);
|
||||
nsRefPtr<MockContentController> mcc = new MockContentController();
|
||||
ScopedLayerTreeRegistration controller(0, root, mcc);
|
||||
|
||||
nsRefPtr<APZCTreeManager> manager = new TestAPZCTreeManager();
|
||||
nsRefPtr<AsyncPanZoomController> hit;
|
||||
gfx3DMatrix transformToApzc;
|
||||
gfx3DMatrix transformToGecko;
|
||||
|
||||
// Set a CSS transform on one of the layers.
|
||||
gfx3DMatrix transform;
|
||||
transform.ScalePost(2, 1, 1);
|
||||
layers[2]->SetBaseTransform(transform);
|
||||
|
||||
// Make some other layers scrollable.
|
||||
SetScrollableFrameMetrics(root, FrameMetrics::ROOT_SCROLL_ID, CSSRect(0, 0, 200, 200));
|
||||
SetScrollableFrameMetrics(layers[1], FrameMetrics::START_SCROLL_ID, CSSRect(0, 0, 80, 80));
|
||||
SetScrollableFrameMetrics(layers[3], FrameMetrics::START_SCROLL_ID + 1, CSSRect(0, 0, 80, 80));
|
||||
|
||||
manager->UpdatePanZoomControllerTree(nullptr, root, false, 0);
|
||||
|
||||
// At this point, the following holds (all coordinates in screen pixels):
|
||||
// layers[0] has content from (0,0)-(200,200), clipped by composition bounds (0,0)-(100,100)
|
||||
// layers[1] has content from (10,10)-(90,90), clipped by composition bounds (10,10)-(50,50)
|
||||
// layers[2] has content from (20,60)-(100,100). no clipping as it's not a scrollable layer
|
||||
// layers[3] has content from (20,60)-(180,140), clipped by composition bounds (20,60)-(100,100)
|
||||
|
||||
AsyncPanZoomController* apzcroot = root->AsContainerLayer()->GetAsyncPanZoomController();
|
||||
AsyncPanZoomController* apzc1 = layers[1]->AsContainerLayer()->GetAsyncPanZoomController();
|
||||
AsyncPanZoomController* apzc3 = layers[3]->AsContainerLayer()->GetAsyncPanZoomController();
|
||||
|
||||
// Hit an area that's clearly on the root layer but not any of the child layers.
|
||||
hit = GetTargetAPZC(manager, ScreenPoint(75, 25), transformToApzc, transformToGecko);
|
||||
EXPECT_EQ(apzcroot, hit.get());
|
||||
EXPECT_EQ(gfxPoint(75, 25), transformToApzc.Transform(gfxPoint(75, 25)));
|
||||
EXPECT_EQ(gfxPoint(75, 25), transformToGecko.Transform(gfxPoint(75, 25)));
|
||||
|
||||
// Hit an area on the root that would be on layers[3] if layers[2]
|
||||
// weren't transformed.
|
||||
// Note that if layers[2] were scrollable, then this would hit layers[2]
|
||||
// because its composition bounds would be at (10,60)-(50,100) (and the
|
||||
// scale-only transform that we set on layers[2] would be invalid because
|
||||
// it would place the layer into overscroll, as its composition bounds
|
||||
// start at x=10 but its content at x=20).
|
||||
hit = GetTargetAPZC(manager, ScreenPoint(15, 75), transformToApzc, transformToGecko);
|
||||
EXPECT_EQ(apzcroot, hit.get());
|
||||
EXPECT_EQ(gfxPoint(15, 75), transformToApzc.Transform(gfxPoint(15, 75)));
|
||||
EXPECT_EQ(gfxPoint(15, 75), transformToGecko.Transform(gfxPoint(15, 75)));
|
||||
|
||||
// Hit an area on layers[1].
|
||||
hit = GetTargetAPZC(manager, ScreenPoint(25, 25), transformToApzc, transformToGecko);
|
||||
EXPECT_EQ(apzc1, hit.get());
|
||||
EXPECT_EQ(gfxPoint(25, 25), transformToApzc.Transform(gfxPoint(25, 25)));
|
||||
EXPECT_EQ(gfxPoint(25, 25), transformToGecko.Transform(gfxPoint(25, 25)));
|
||||
|
||||
// Hit an area on layers[3].
|
||||
hit = GetTargetAPZC(manager, ScreenPoint(25, 75), transformToApzc, transformToGecko);
|
||||
EXPECT_EQ(apzc3, hit.get());
|
||||
// transformToApzc should unapply layers[2]'s transform
|
||||
EXPECT_EQ(gfxPoint(12.5, 75), transformToApzc.Transform(gfxPoint(25, 75)));
|
||||
// and transformToGecko should reapply it
|
||||
EXPECT_EQ(gfxPoint(25, 75), transformToGecko.Transform(gfxPoint(12.5, 75)));
|
||||
|
||||
// Hit an area on layers[3] that would be on the root if layers[2]
|
||||
// weren't transformed.
|
||||
hit = GetTargetAPZC(manager, ScreenPoint(75, 75), transformToApzc, transformToGecko);
|
||||
EXPECT_EQ(apzc3, hit.get());
|
||||
// transformToApzc should unapply layers[2]'s transform
|
||||
EXPECT_EQ(gfxPoint(37.5, 75), transformToApzc.Transform(gfxPoint(75, 75)));
|
||||
// and transformToGecko should reapply it
|
||||
EXPECT_EQ(gfxPoint(75, 75), transformToGecko.Transform(gfxPoint(37.5, 75)));
|
||||
|
||||
// Pan the root layer upward by 50 pixels.
|
||||
// This causes layers[1] to scroll out of view, and an async transform
|
||||
// of -50 to be set on the root layer.
|
||||
int time = 0;
|
||||
// Silence GMock warnings about "uninteresting mock function calls".
|
||||
EXPECT_CALL(*mcc, PostDelayedTask(_,_)).Times(1);
|
||||
EXPECT_CALL(*mcc, SendAsyncScrollDOMEvent(_,_,_)).Times(2);
|
||||
EXPECT_CALL(*mcc, RequestContentRepaint(_)).Times(1);
|
||||
ApzcPan(apzcroot, time, 100, 50);
|
||||
|
||||
// Hit where layers[3] used to be. It should now hit the root.
|
||||
hit = GetTargetAPZC(manager, ScreenPoint(75, 75), transformToApzc, transformToGecko);
|
||||
EXPECT_EQ(apzcroot, hit.get());
|
||||
// transformToApzc doesn't unapply the root's own async transform
|
||||
EXPECT_EQ(gfxPoint(75, 75), transformToApzc.Transform(gfxPoint(75, 75)));
|
||||
// but transformToGecko does
|
||||
EXPECT_EQ(gfxPoint(75, 125), transformToGecko.Transform(gfxPoint(75, 75)));
|
||||
|
||||
// Hit where layers[1] used to be and where layers[3] should now be.
|
||||
hit = GetTargetAPZC(manager, ScreenPoint(25, 25), transformToApzc, transformToGecko);
|
||||
EXPECT_EQ(apzc3, hit.get());
|
||||
// transformToApzc unapplies both layers[2]'s css transform and the root's
|
||||
// async trasnform
|
||||
EXPECT_EQ(gfxPoint(12.5, 75), transformToApzc.Transform(gfxPoint(25, 25)));
|
||||
// transformToGecko reapplies the css transform only (since Gecko doesn't
|
||||
// know about async transforms)
|
||||
EXPECT_EQ(gfxPoint(25, 75), transformToGecko.Transform(gfxPoint(12.5, 75)));
|
||||
|
||||
manager->ClearTree();
|
||||
}
|
||||
|
@ -49,6 +49,11 @@ pref("general.smoothScroll", true);
|
||||
// WebPayment
|
||||
pref("dom.mozPay.enabled", true);
|
||||
|
||||
// Disable slow script dialog for apps
|
||||
pref("dom.max_script_run_time", 0);
|
||||
pref("dom.max_chrome_script_run_time", 0);
|
||||
|
||||
|
||||
#ifndef RELEASE_BUILD
|
||||
// Enable mozPay default provider
|
||||
pref("dom.payment.provider.0.name", "Firefox Marketplace");
|
||||
|
Loading…
Reference in New Issue
Block a user