forked from mirrors/gecko-dev
This version of the Dynamic Toolbar moves the animation of the toolbar from the Android UI thread to the compositor thread. All animation for showing and hiding the toolbar are done with the compositor and a static snapshot of the real toolbar. MozReview-Commit-ID: BCe8zpbkWQt
266 lines
8.6 KiB
C++
266 lines
8.6 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"
|
|
|
|
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>
|
|
(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>(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;
|
|
}
|
|
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>(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>(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>(this,
|
|
&RemoteContentController::NotifyAsyncScrollbarDragRejected, aScrollId));
|
|
return;
|
|
}
|
|
|
|
if (mCanSend) {
|
|
Unused << SendNotifyAsyncScrollbarDragRejected(aScrollId);
|
|
}
|
|
}
|
|
|
|
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
|