gecko-dev/gfx/layers/ipc/RemoteContentController.cpp

361 строка
11 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/APZCCallbackHelper.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"
namespace mozilla {
namespace layers {
using namespace mozilla::gfx;
RemoteContentController::RemoteContentController()
: mCompositorThread(MessageLoop::current())
, mCanSend(true)
{
}
RemoteContentController::~RemoteContentController()
{
}
void
RemoteContentController::RequestContentRepaint(const FrameMetrics& aFrameMetrics)
{
MOZ_ASSERT(IsRepaintThread());
if (mCanSend) {
Unused << SendRequestContentRepaint(aFrameMetrics);
}
}
void
RemoteContentController::HandleTapOnMainThread(TapType aTapType,
LayoutDevicePoint aPoint,
Modifiers aModifiers,
ScrollableLayerGuid aGuid,
uint64_t aInputBlockId)
{
MOZ_ASSERT(NS_IsMainThread());
dom::TabParent* tab = dom::TabParent::GetTabParentFromLayersId(aGuid.mLayersId);
if (tab) {
tab->SendHandleTap(aTapType, aPoint, aModifiers, aGuid, aInputBlockId);
}
}
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;
}
MOZ_ASSERT(XRE_IsParentProcess());
if (NS_IsMainThread()) {
HandleTapOnMainThread(aTapType, aPoint, aModifiers, aGuid, aInputBlockId);
} else {
// We don't want to get the TabParent or call TabParent::SendHandleTap() from a non-main thread (this might happen
// on Android, where this is called from the Java UI thread)
NS_DispatchToMainThread(NewRunnableMethod<TapType,
LayoutDevicePoint,
Modifiers,
ScrollableLayerGuid,
uint64_t>(
"layers::RemoteContentController::HandleTapOnMainThread",
this,
&RemoteContentController::HandleTapOnMainThread,
aTapType,
aPoint,
aModifiers,
aGuid,
aInputBlockId));
}
}
void
RemoteContentController::NotifyPinchGesture(PinchGestureInput::PinchGestureType aType,
const ScrollableLayerGuid& aGuid,
LayoutDeviceCoord aSpanChange,
Modifiers aModifiers)
{
APZThreadUtils::AssertOnControllerThread();
// For now we only ever want to handle this NotifyPinchGesture message in
// the parent process, even if the APZ is sending it to a content process.
// If we're in the GPU process, try to find a handle to the parent process
// and send it there.
if (XRE_IsGPUProcess()) {
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->SendNotifyPinchGesture(aType, aGuid, aSpanChange, aModifiers);
return;
}
}
// If we're in the parent process, handle it directly. We don't have a handle
// to the widget though, so we fish out the ChromeProcessController and
// delegate to that instead.
if (XRE_IsParentProcess()) {
MOZ_ASSERT(NS_IsMainThread());
RefPtr<GeckoContentController> rootController =
CompositorBridgeParent::GetGeckoContentControllerForRoot(aGuid.mLayersId);
if (rootController) {
rootController->NotifyPinchGesture(aType, aGuid, aSpanChange, aModifiers);
}
}
}
void
RemoteContentController::PostDelayedTask(already_AddRefed<Runnable> aTask, int aDelayMs)
{
(MessageLoop::current() ? MessageLoop::current() : mCompositorThread)->
PostDelayedTask(Move(aTask), aDelayMs);
}
bool
RemoteContentController::IsRepaintThread()
{
return MessageLoop::current() == mCompositorThread;
}
void
RemoteContentController::DispatchToRepaintThread(already_AddRefed<Runnable> aTask)
{
mCompositorThread->PostTask(Move(aTask));
}
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>(
"layers::RemoteContentController::NotifyAPZStateChange",
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>(
"layers::RemoteContentController::UpdateOverscrollVelocity",
this,
&RemoteContentController::UpdateOverscrollVelocity,
aX,
aY,
aIsRootContent));
return;
}
if (mCanSend) {
Unused << SendUpdateOverscrollVelocity(aX, aY, aIsRootContent);
}
}
void
RemoteContentController::UpdateOverscrollOffset(float aX, float aY, bool aIsRootContent)
{
if (MessageLoop::current() != mCompositorThread) {
mCompositorThread->PostTask(NewRunnableMethod<float, float, bool>(
"layers::RemoteContentController::UpdateOverscrollOffset",
this,
&RemoteContentController::UpdateOverscrollOffset,
aX,
aY,
aIsRootContent));
return;
}
if (mCanSend) {
Unused << SendUpdateOverscrollOffset(aX, aY, 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>(
"layers::RemoteContentController::NotifyMozMouseScrollEvent",
this,
&RemoteContentController::NotifyMozMouseScrollEvent,
aScrollId,
aEvent));
return;
}
if (mCanSend) {
Unused << SendNotifyMozMouseScrollEvent(aScrollId, aEvent);
}
}
void
RemoteContentController::NotifyFlushComplete()
{
MOZ_ASSERT(IsRepaintThread());
if (mCanSend) {
Unused << SendNotifyFlushComplete();
}
}
void
RemoteContentController::NotifyAsyncScrollbarDragRejected(const FrameMetrics::ViewID& aScrollId)
{
if (MessageLoop::current() != mCompositorThread) {
// We have to send messages from the compositor thread
mCompositorThread->PostTask(NewRunnableMethod<FrameMetrics::ViewID>(
"layers::RemoteContentController::NotifyAsyncScrollbarDragRejected",
this,
&RemoteContentController::NotifyAsyncScrollbarDragRejected,
aScrollId));
return;
}
if (mCanSend) {
Unused << SendNotifyAsyncScrollbarDragRejected(aScrollId);
}
}
void
RemoteContentController::NotifyAutoscrollHandledByAPZ(const FrameMetrics::ViewID& aScrollId)
{
if (MessageLoop::current() != mCompositorThread) {
// We have to send messages from the compositor thread
mCompositorThread->PostTask(NewRunnableMethod<FrameMetrics::ViewID>(
"layers::RemoteContentController::NotifyAutoscrollHandledByAPZ",
this,
&RemoteContentController::NotifyAutoscrollHandledByAPZ,
aScrollId));
return;
}
if (mCanSend) {
Unused << SendNotifyAutoscrollHandledByAPZ(aScrollId);
}
}
void
RemoteContentController::CancelAutoscroll(const ScrollableLayerGuid& aGuid)
{
if (XRE_GetProcessType() == GeckoProcessType_GPU) {
CancelAutoscrollCrossProcess(aGuid);
} else {
CancelAutoscrollInProcess(aGuid);
}
}
void
RemoteContentController::CancelAutoscrollInProcess(const ScrollableLayerGuid& aGuid)
{
MOZ_ASSERT(XRE_IsParentProcess());
if (!NS_IsMainThread()) {
NS_DispatchToMainThread(NewRunnableMethod<ScrollableLayerGuid>(
"layers::RemoteContentController::CancelAutoscrollInProcess",
this,
&RemoteContentController::CancelAutoscrollInProcess,
aGuid));
return;
}
APZCCallbackHelper::CancelAutoscroll(aGuid.mScrollId);
}
void
RemoteContentController::CancelAutoscrollCrossProcess(const ScrollableLayerGuid& aGuid)
{
MOZ_ASSERT(XRE_IsGPUProcess());
if (MessageLoop::current() != mCompositorThread) {
mCompositorThread->PostTask(NewRunnableMethod<ScrollableLayerGuid>(
"layers::RemoteContentController::CancelAutoscrollCrossProcess",
this,
&RemoteContentController::CancelAutoscrollCrossProcess,
aGuid));
return;
}
// The raw pointer to APZCTreeManagerParent is ok here because we are on the
// compositor thread.
if (APZCTreeManagerParent* parent =
CompositorBridgeParent::GetApzcTreeManagerParentForRoot(aGuid.mLayersId)) {
Unused << parent->SendCancelAutoscroll(aGuid.mScrollId);
}
}
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) {
mCanSend = false;
Unused << SendDestroy();
}
}
} // namespace layers
} // namespace mozilla