forked from mirrors/gecko-dev
Rather than using a separate function APZCTreeManager::AddInputBlockCallback(), allow an optional callback argument to be passed to APZInputBridge::ReceiveInputEvent(). This avoids a race condition where the input block is processed before the callback has a chance to be added to the input queue, meaning the callback will never be fired. With the GPU process enabled the added latency of adding the callback cross-process meant this occured frequently, causing intermittent junit test failures. This works similarily to before, with the in-process APZCTreeManager implementation simply calling InputQueue::AddInputBlockCallback() and the InputQueue will fire the callback when the input block has been processed. For the cross-process implementation, APZInputBridgeChild maintains a local map of the callbacks, and APZInputBridgeParent adds an intermediate callback to its local InputQueue. This intermediate callback will call APZInputBridgeParent::SendCallInputBlockCallback(), which tells the APZInputBridgeChild to fire the real callback. Care must be taken in both APZInputBridgeChild and Parent to only add their respective callbacks if we determine that it is required, eg not already handled by the root APZ. Differential Revision: https://phabricator.services.mozilla.com/D138801
213 lines
7.1 KiB
C++
213 lines
7.1 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/APZInputBridgeParent.h"
|
|
|
|
#include "mozilla/ipc/Endpoint.h"
|
|
#include "mozilla/layers/APZInputBridge.h"
|
|
#include "mozilla/layers/CompositorBridgeParent.h"
|
|
#include "mozilla/layers/IAPZCTreeManager.h"
|
|
#include "InputData.h"
|
|
|
|
namespace mozilla {
|
|
namespace layers {
|
|
|
|
/* static */
|
|
RefPtr<APZInputBridgeParent> APZInputBridgeParent::Create(
|
|
const LayersId& aLayersId, Endpoint<PAPZInputBridgeParent>&& aEndpoint) {
|
|
RefPtr<APZInputBridgeParent> parent = new APZInputBridgeParent(aLayersId);
|
|
if (!aEndpoint.Bind(parent)) {
|
|
// We can't recover from this.
|
|
MOZ_CRASH("Failed to bind APZInputBridgeParent to endpoint");
|
|
}
|
|
|
|
return parent;
|
|
}
|
|
|
|
APZInputBridgeParent::APZInputBridgeParent(const LayersId& aLayersId) {
|
|
MOZ_ASSERT(XRE_IsGPUProcess());
|
|
MOZ_ASSERT(NS_IsMainThread());
|
|
|
|
mTreeManager = CompositorBridgeParent::GetAPZCTreeManager(aLayersId);
|
|
MOZ_ASSERT(mTreeManager);
|
|
}
|
|
|
|
APZInputBridgeParent::~APZInputBridgeParent() = default;
|
|
|
|
mozilla::ipc::IPCResult APZInputBridgeParent::RecvReceiveMultiTouchInputEvent(
|
|
const MultiTouchInput& aEvent, bool aWantsCallback,
|
|
APZEventResult* aOutResult, MultiTouchInput* aOutEvent) {
|
|
MultiTouchInput event = aEvent;
|
|
|
|
APZInputBridge::InputBlockCallback callback;
|
|
if (aWantsCallback) {
|
|
callback = [self = RefPtr<APZInputBridgeParent>(this)](
|
|
uint64_t aInputBlockId,
|
|
const APZHandledResult& aHandledResult) {
|
|
Unused << self->SendCallInputBlockCallback(aInputBlockId, aHandledResult);
|
|
};
|
|
}
|
|
|
|
*aOutResult = mTreeManager->InputBridge()->ReceiveInputEvent(
|
|
event, std::move(callback));
|
|
*aOutEvent = event;
|
|
|
|
return IPC_OK();
|
|
}
|
|
|
|
mozilla::ipc::IPCResult APZInputBridgeParent::RecvReceiveMouseInputEvent(
|
|
const MouseInput& aEvent, bool aWantsCallback, APZEventResult* aOutResult,
|
|
MouseInput* aOutEvent) {
|
|
MouseInput event = aEvent;
|
|
|
|
APZInputBridge::InputBlockCallback callback;
|
|
if (aWantsCallback) {
|
|
callback = [self = RefPtr<APZInputBridgeParent>(this)](
|
|
uint64_t aInputBlockId,
|
|
const APZHandledResult& aHandledResult) {
|
|
Unused << self->SendCallInputBlockCallback(aInputBlockId, aHandledResult);
|
|
};
|
|
}
|
|
|
|
*aOutResult = mTreeManager->InputBridge()->ReceiveInputEvent(
|
|
event, std::move(callback));
|
|
*aOutEvent = event;
|
|
|
|
return IPC_OK();
|
|
}
|
|
|
|
mozilla::ipc::IPCResult APZInputBridgeParent::RecvReceivePanGestureInputEvent(
|
|
const PanGestureInput& aEvent, bool aWantsCallback,
|
|
APZEventResult* aOutResult, PanGestureInput* aOutEvent) {
|
|
PanGestureInput event = aEvent;
|
|
|
|
APZInputBridge::InputBlockCallback callback;
|
|
if (aWantsCallback) {
|
|
callback = [self = RefPtr<APZInputBridgeParent>(this)](
|
|
uint64_t aInputBlockId,
|
|
const APZHandledResult& aHandledResult) {
|
|
Unused << self->SendCallInputBlockCallback(aInputBlockId, aHandledResult);
|
|
};
|
|
}
|
|
|
|
*aOutResult = mTreeManager->InputBridge()->ReceiveInputEvent(
|
|
event, std::move(callback));
|
|
*aOutEvent = event;
|
|
|
|
return IPC_OK();
|
|
}
|
|
|
|
mozilla::ipc::IPCResult APZInputBridgeParent::RecvReceivePinchGestureInputEvent(
|
|
const PinchGestureInput& aEvent, bool aWantsCallback,
|
|
APZEventResult* aOutResult, PinchGestureInput* aOutEvent) {
|
|
PinchGestureInput event = aEvent;
|
|
|
|
APZInputBridge::InputBlockCallback callback;
|
|
if (aWantsCallback) {
|
|
callback = [self = RefPtr<APZInputBridgeParent>(this)](
|
|
uint64_t aInputBlockId,
|
|
const APZHandledResult& aHandledResult) {
|
|
Unused << self->SendCallInputBlockCallback(aInputBlockId, aHandledResult);
|
|
};
|
|
}
|
|
|
|
*aOutResult = mTreeManager->InputBridge()->ReceiveInputEvent(
|
|
event, std::move(callback));
|
|
*aOutEvent = event;
|
|
|
|
return IPC_OK();
|
|
}
|
|
|
|
mozilla::ipc::IPCResult APZInputBridgeParent::RecvReceiveTapGestureInputEvent(
|
|
const TapGestureInput& aEvent, bool aWantsCallback,
|
|
APZEventResult* aOutResult, TapGestureInput* aOutEvent) {
|
|
TapGestureInput event = aEvent;
|
|
|
|
APZInputBridge::InputBlockCallback callback;
|
|
if (aWantsCallback) {
|
|
callback = [self = RefPtr<APZInputBridgeParent>(this)](
|
|
uint64_t aInputBlockId,
|
|
const APZHandledResult& aHandledResult) {
|
|
Unused << self->SendCallInputBlockCallback(aInputBlockId, aHandledResult);
|
|
};
|
|
}
|
|
|
|
*aOutResult = mTreeManager->InputBridge()->ReceiveInputEvent(
|
|
event, std::move(callback));
|
|
*aOutEvent = event;
|
|
|
|
return IPC_OK();
|
|
}
|
|
|
|
mozilla::ipc::IPCResult APZInputBridgeParent::RecvReceiveScrollWheelInputEvent(
|
|
const ScrollWheelInput& aEvent, bool aWantsCallback,
|
|
APZEventResult* aOutResult, ScrollWheelInput* aOutEvent) {
|
|
ScrollWheelInput event = aEvent;
|
|
|
|
APZInputBridge::InputBlockCallback callback;
|
|
if (aWantsCallback) {
|
|
callback = [self = RefPtr<APZInputBridgeParent>(this)](
|
|
uint64_t aInputBlockId,
|
|
const APZHandledResult& aHandledResult) {
|
|
Unused << self->SendCallInputBlockCallback(aInputBlockId, aHandledResult);
|
|
};
|
|
}
|
|
|
|
*aOutResult = mTreeManager->InputBridge()->ReceiveInputEvent(
|
|
event, std::move(callback));
|
|
*aOutEvent = event;
|
|
|
|
return IPC_OK();
|
|
}
|
|
|
|
mozilla::ipc::IPCResult APZInputBridgeParent::RecvReceiveKeyboardInputEvent(
|
|
const KeyboardInput& aEvent, bool aWantsCallback,
|
|
APZEventResult* aOutResult, KeyboardInput* aOutEvent) {
|
|
KeyboardInput event = aEvent;
|
|
|
|
APZInputBridge::InputBlockCallback callback;
|
|
if (aWantsCallback) {
|
|
callback = [self = RefPtr<APZInputBridgeParent>(this)](
|
|
uint64_t aInputBlockId,
|
|
const APZHandledResult& aHandledResult) {
|
|
Unused << self->SendCallInputBlockCallback(aInputBlockId, aHandledResult);
|
|
};
|
|
}
|
|
|
|
*aOutResult = mTreeManager->InputBridge()->ReceiveInputEvent(
|
|
event, std::move(callback));
|
|
*aOutEvent = event;
|
|
|
|
return IPC_OK();
|
|
}
|
|
|
|
mozilla::ipc::IPCResult APZInputBridgeParent::RecvUpdateWheelTransaction(
|
|
const LayoutDeviceIntPoint& aRefPoint, const EventMessage& aEventMessage,
|
|
const Maybe<ScrollableLayerGuid>& aTargetGuid) {
|
|
mTreeManager->InputBridge()->UpdateWheelTransaction(aRefPoint, aEventMessage,
|
|
aTargetGuid);
|
|
return IPC_OK();
|
|
}
|
|
|
|
mozilla::ipc::IPCResult APZInputBridgeParent::RecvProcessUnhandledEvent(
|
|
const LayoutDeviceIntPoint& aRefPoint, LayoutDeviceIntPoint* aOutRefPoint,
|
|
ScrollableLayerGuid* aOutTargetGuid, uint64_t* aOutFocusSequenceNumber,
|
|
LayersId* aOutLayersId) {
|
|
LayoutDeviceIntPoint refPoint = aRefPoint;
|
|
mTreeManager->InputBridge()->ProcessUnhandledEvent(
|
|
&refPoint, aOutTargetGuid, aOutFocusSequenceNumber, aOutLayersId);
|
|
*aOutRefPoint = refPoint;
|
|
|
|
return IPC_OK();
|
|
}
|
|
|
|
void APZInputBridgeParent::ActorDestroy(ActorDestroyReason aWhy) {
|
|
// We shouldn't need it after this
|
|
mTreeManager = nullptr;
|
|
}
|
|
|
|
} // namespace layers
|
|
} // namespace mozilla
|