mirror of
https://github.com/mozilla/gecko-dev.git
synced 2025-11-13 06:38:48 +02:00
A couple of RemoteContentController methods get called on the controller thread in the GPU process. This is the same as the compositor thread so we could just do compositor-thread stuff here, but we will want to support the controller thread being the main thread instead of the compositor thread. So we detect those cases and bounce the message accordingly.
410 lines
13 KiB
C++
410 lines
13 KiB
C++
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
|
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
|
/* 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::HandleTapOnCompositorThread(TapType aTapType,
|
|
LayoutDevicePoint aPoint,
|
|
Modifiers aModifiers,
|
|
ScrollableLayerGuid aGuid,
|
|
uint64_t aInputBlockId)
|
|
{
|
|
MOZ_ASSERT(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->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) {
|
|
if (MessageLoop::current() == mCompositorThread) {
|
|
HandleTapOnCompositorThread(aTapType, aPoint, aModifiers, aGuid, aInputBlockId);
|
|
} else {
|
|
// We have to send messages from the compositor thread
|
|
mCompositorThread->PostTask(NewRunnableMethod<TapType,
|
|
LayoutDevicePoint,
|
|
Modifiers,
|
|
ScrollableLayerGuid,
|
|
uint64_t>(
|
|
"layers::RemoteContentController::HandleTapOnCompositorThread",
|
|
this,
|
|
&RemoteContentController::HandleTapOnCompositorThread,
|
|
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::NotifyPinchGestureOnCompositorThread(
|
|
PinchGestureInput::PinchGestureType aType,
|
|
const ScrollableLayerGuid& aGuid,
|
|
LayoutDeviceCoord aSpanChange,
|
|
Modifiers aModifiers)
|
|
{
|
|
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);
|
|
}
|
|
}
|
|
|
|
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()) {
|
|
if (MessageLoop::current() == mCompositorThread) {
|
|
NotifyPinchGestureOnCompositorThread(aType, aGuid, aSpanChange, aModifiers);
|
|
} else {
|
|
mCompositorThread->PostTask(NewRunnableMethod<PinchGestureInput::PinchGestureType,
|
|
ScrollableLayerGuid,
|
|
LayoutDeviceCoord,
|
|
Modifiers>(
|
|
"layers::RemoteContentController::NotifyPinchGestureOnCompositorThread",
|
|
this,
|
|
&RemoteContentController::NotifyPinchGestureOnCompositorThread,
|
|
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::NotifyAsyncAutoscrollRejected(const FrameMetrics::ViewID& aScrollId)
|
|
{
|
|
if (MessageLoop::current() != mCompositorThread) {
|
|
// We have to send messages from the compositor thread
|
|
mCompositorThread->PostTask(NewRunnableMethod<FrameMetrics::ViewID>(
|
|
"layers::RemoteContentController::NotifyAsyncAutoscrollRejected",
|
|
this,
|
|
&RemoteContentController::NotifyAsyncAutoscrollRejected,
|
|
aScrollId));
|
|
return;
|
|
}
|
|
|
|
if (mCanSend) {
|
|
Unused << SendNotifyAsyncAutoscrollRejected(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
|