gecko-dev/gfx/layers/ipc/RemoteContentController.cpp
Kartikaya Gupta 6d057a3060 Bug 1298173 - Push HandleTap from the GPU process back to the parent process before passing it on to the child process. r=dvander
Sending it back via the parent process ensures that it will take the same path
that regular touch events do, and so guarantees that the Tap event won't overtake
the touch events and get dispatched to content first.

MozReview-Commit-ID: 8TiHY2PFPvE
2016-09-21 10:26:33 -04:00

234 lines
7.1 KiB
C++

/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
* vim: sw=2 ts=8 et :
*/
/* 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 "mozilla/layers/RemoteContentController.h"
#include "base/message_loop.h"
#include "base/task.h"
#include "MainThreadUtils.h"
#include "mozilla/dom/ContentParent.h"
#include "mozilla/dom/TabParent.h"
#include "mozilla/layers/APZCTreeManagerParent.h" // for APZCTreeManagerParent
#include "mozilla/layers/APZThreadUtils.h"
#include "mozilla/layout/RenderFrameParent.h"
#include "mozilla/gfx/GPUProcessManager.h"
#include "mozilla/Unused.h"
#include "Units.h"
#ifdef MOZ_WIDGET_ANDROID
#include "AndroidBridge.h"
#endif
namespace mozilla {
namespace layers {
using namespace mozilla::gfx;
RemoteContentController::RemoteContentController()
: mCompositorThread(MessageLoop::current())
, mCanSend(true)
, mMutex("RemoteContentController")
{
}
RemoteContentController::~RemoteContentController()
{
}
void
RemoteContentController::RequestContentRepaint(const FrameMetrics& aFrameMetrics)
{
MOZ_ASSERT(IsRepaintThread());
if (mCanSend) {
Unused << SendRequestContentRepaint(aFrameMetrics);
}
}
void
RemoteContentController::HandleTap(TapType aTapType,
const LayoutDevicePoint& aPoint,
Modifiers aModifiers,
const ScrollableLayerGuid& aGuid,
uint64_t aInputBlockId)
{
APZThreadUtils::AssertOnControllerThread();
if (XRE_GetProcessType() == GeckoProcessType_GPU) {
MOZ_ASSERT(MessageLoop::current() == mCompositorThread);
// The raw pointer to APZCTreeManagerParent is ok here because we are on the
// compositor thread.
APZCTreeManagerParent* apzctmp =
CompositorBridgeParent::GetApzcTreeManagerParentForRoot(aGuid.mLayersId);
if (apzctmp) {
Unused << apzctmp->SendHandleTap(aTapType, aPoint, aModifiers, aGuid, aInputBlockId);
return;
}
}
// If we get here we're probably in the parent process, but we might be in
// the GPU process in some shutdown phase where the LayerTreeState or
// APZCTreeManagerParent structures are torn down. In that case we'll just get
// a null TabParent.
dom::TabParent* tab = dom::TabParent::GetTabParentFromLayersId(aGuid.mLayersId);
if (tab) {
// If we got a TabParent we're definitely in the parent process, and the
// message is going to a child process. That means we're in an e10s
// environment, so we must be on the main thread.
MOZ_ASSERT(XRE_IsParentProcess());
MOZ_ASSERT(NS_IsMainThread());
tab->SendHandleTap(aTapType, aPoint, aModifiers, aGuid, aInputBlockId);
}
}
void
RemoteContentController::PostDelayedTask(already_AddRefed<Runnable> aTask, int aDelayMs)
{
#ifdef MOZ_WIDGET_ANDROID
AndroidBridge::Bridge()->PostTaskToUiThread(Move(aTask), aDelayMs);
#else
(MessageLoop::current() ? MessageLoop::current() : mCompositorThread)->
PostDelayedTask(Move(aTask), aDelayMs);
#endif
}
bool
RemoteContentController::IsRepaintThread()
{
return MessageLoop::current() == mCompositorThread;
}
void
RemoteContentController::DispatchToRepaintThread(already_AddRefed<Runnable> aTask)
{
mCompositorThread->PostTask(Move(aTask));
}
bool
RemoteContentController::GetTouchSensitiveRegion(CSSRect* aOutRegion)
{
MutexAutoLock lock(mMutex);
if (mTouchSensitiveRegion.IsEmpty()) {
return false;
}
*aOutRegion = CSSRect::FromAppUnits(mTouchSensitiveRegion.GetBounds());
return true;
}
void
RemoteContentController::NotifyAPZStateChange(const ScrollableLayerGuid& aGuid,
APZStateChange aChange,
int aArg)
{
if (MessageLoop::current() != mCompositorThread) {
// We have to send messages from the compositor thread
mCompositorThread->PostTask(NewRunnableMethod<ScrollableLayerGuid,
APZStateChange,
int>(this,
&RemoteContentController::NotifyAPZStateChange,
aGuid, aChange, aArg));
return;
}
if (mCanSend) {
Unused << SendNotifyAPZStateChange(aGuid, aChange, aArg);
}
}
void
RemoteContentController::UpdateOverscrollVelocity(float aX, float aY, bool aIsRootContent)
{
if (MessageLoop::current() != mCompositorThread) {
mCompositorThread->PostTask(NewRunnableMethod<float,
float, bool>(this,
&RemoteContentController::UpdateOverscrollVelocity,
aX, aY, aIsRootContent));
return;
}
Unused << SendUpdateOverscrollVelocity(aX, aY, aIsRootContent);
}
void
RemoteContentController::UpdateOverscrollOffset(float aX, float aY, bool aIsRootContent)
{
if (MessageLoop::current() != mCompositorThread) {
mCompositorThread->PostTask(NewRunnableMethod<float,
float, bool>(this,
&RemoteContentController::UpdateOverscrollOffset,
aX, aY, aIsRootContent));
return;
}
Unused << SendUpdateOverscrollOffset(aX, aY, aIsRootContent);
}
void
RemoteContentController::SetScrollingRootContent(bool aIsRootContent)
{
if (MessageLoop::current() != mCompositorThread) {
mCompositorThread->PostTask(NewRunnableMethod<bool>(this,
&RemoteContentController::SetScrollingRootContent,
aIsRootContent));
return;
}
Unused << SendSetScrollingRootContent(aIsRootContent);
}
void
RemoteContentController::NotifyMozMouseScrollEvent(const FrameMetrics::ViewID& aScrollId,
const nsString& aEvent)
{
if (MessageLoop::current() != mCompositorThread) {
// We have to send messages from the compositor thread
mCompositorThread->PostTask(NewRunnableMethod<FrameMetrics::ViewID,
nsString>(this,
&RemoteContentController::NotifyMozMouseScrollEvent,
aScrollId, aEvent));
return;
}
if (mCanSend) {
Unused << SendNotifyMozMouseScrollEvent(aScrollId, aEvent);
}
}
void
RemoteContentController::NotifyFlushComplete()
{
MOZ_ASSERT(IsRepaintThread());
if (mCanSend) {
Unused << SendNotifyFlushComplete();
}
}
bool
RemoteContentController::RecvUpdateHitRegion(const nsRegion& aRegion)
{
MutexAutoLock lock(mMutex);
mTouchSensitiveRegion = aRegion;
return true;
}
void
RemoteContentController::ActorDestroy(ActorDestroyReason aWhy)
{
// This controller could possibly be kept alive longer after this
// by a RefPtr, but it is no longer valid to send messages.
mCanSend = false;
}
void
RemoteContentController::Destroy()
{
if (mCanSend) {
Unused << SendDestroy();
}
}
} // namespace layers
} // namespace mozilla