Bug 1351783 part 12 - Create and sync focus sequence numbers. r=kats,botond,dvander
Focus can change at any moment in a document. This causes non-determinism and correctness problems for doing keyboard apz scrolling. To get around this, we will maintain deterministic behavior for focus changes initiated by input events and see if we can get away with more non-determinism for things like `setTimeout` In order to do this, we disable async keyboard scrolling when an input event is processed that could have a event listener. We then attach a sequence number to that input event and dispatch it to content. In content, we record the highest sequence number that we have processed from an event, and send that on each focus update. Using this, we can determine in APZ if we have a current focus target or if we are still waiting for an input event to be processed and focus to be reconfirmed. MozReview-Commit-ID: CWcu8YEFQz4
This commit is contained in:
@@ -69,11 +69,12 @@ IAPZCTreeManager::ReceiveInputEvent(
|
||||
mouseEvent.mRefPoint.x = input.mOrigin.x;
|
||||
mouseEvent.mRefPoint.y = input.mOrigin.y;
|
||||
mouseEvent.mFlags.mHandledByAPZ = input.mHandledByAPZ;
|
||||
mouseEvent.mFocusSequenceNumber = input.mFocusSequenceNumber;
|
||||
return status;
|
||||
|
||||
}
|
||||
|
||||
TransformEventRefPoint(&mouseEvent.mRefPoint, aOutTargetGuid);
|
||||
ProcessUnhandledEvent(&mouseEvent.mRefPoint, aOutTargetGuid, &aEvent.mFocusSequenceNumber);
|
||||
return nsEventStatus_eIgnore;
|
||||
}
|
||||
case eTouchEventClass: {
|
||||
@@ -92,6 +93,7 @@ IAPZCTreeManager::ReceiveInputEvent(
|
||||
touchInput.mTouches[i].ToNewDOMTouch();
|
||||
}
|
||||
touchEvent.mFlags.mHandledByAPZ = touchInput.mHandledByAPZ;
|
||||
touchEvent.mFocusSequenceNumber = touchInput.mFocusSequenceNumber;
|
||||
return result;
|
||||
|
||||
}
|
||||
@@ -133,18 +135,19 @@ IAPZCTreeManager::ReceiveInputEvent(
|
||||
wheelEvent.mRefPoint.x = input.mOrigin.x;
|
||||
wheelEvent.mRefPoint.y = input.mOrigin.y;
|
||||
wheelEvent.mFlags.mHandledByAPZ = input.mHandledByAPZ;
|
||||
wheelEvent.mFocusSequenceNumber = input.mFocusSequenceNumber;
|
||||
return status;
|
||||
}
|
||||
|
||||
UpdateWheelTransaction(aEvent.mRefPoint, aEvent.mMessage);
|
||||
TransformEventRefPoint(&aEvent.mRefPoint, aOutTargetGuid);
|
||||
ProcessUnhandledEvent(&aEvent.mRefPoint, aOutTargetGuid, &aEvent.mFocusSequenceNumber);
|
||||
return nsEventStatus_eIgnore;
|
||||
|
||||
}
|
||||
default: {
|
||||
|
||||
UpdateWheelTransaction(aEvent.mRefPoint, aEvent.mMessage);
|
||||
TransformEventRefPoint(&aEvent.mRefPoint, aOutTargetGuid);
|
||||
ProcessUnhandledEvent(&aEvent.mRefPoint, aOutTargetGuid, &aEvent.mFocusSequenceNumber);
|
||||
return nsEventStatus_eIgnore;
|
||||
|
||||
}
|
||||
|
||||
@@ -211,9 +211,10 @@ protected:
|
||||
|
||||
// Methods to help process WidgetInputEvents (or manage conversion to/from InputData)
|
||||
|
||||
virtual void TransformEventRefPoint(
|
||||
virtual void ProcessUnhandledEvent(
|
||||
LayoutDeviceIntPoint* aRefPoint,
|
||||
ScrollableLayerGuid* aOutTargetGuid) = 0;
|
||||
ScrollableLayerGuid* aOutTargetGuid,
|
||||
uint64_t* aOutFocusSequenceNumber) = 0;
|
||||
|
||||
virtual void UpdateWheelTransaction(
|
||||
LayoutDeviceIntPoint aRefPoint,
|
||||
|
||||
@@ -165,6 +165,35 @@ APZCTreeManager::CheckerboardFlushObserver::Observe(nsISupports* aSubject,
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* A RAII class used for setting the focus sequence number on input events
|
||||
* as they are being processed. Any input event is assumed to be potentially
|
||||
* focus changing unless explicitly marked otherwise.
|
||||
*/
|
||||
class MOZ_RAII AutoFocusSequenceNumberSetter
|
||||
{
|
||||
public:
|
||||
AutoFocusSequenceNumberSetter(FocusState& aFocusState, InputData& aEvent)
|
||||
: mFocusState(aFocusState)
|
||||
, mEvent(aEvent)
|
||||
, mMayChangeFocus(true)
|
||||
{ }
|
||||
|
||||
void MarkAsNonFocusChanging() { mMayChangeFocus = false; }
|
||||
|
||||
~AutoFocusSequenceNumberSetter()
|
||||
{
|
||||
if (mMayChangeFocus) {
|
||||
mFocusState.ReceiveFocusChangingEvent();
|
||||
}
|
||||
mEvent.mFocusSequenceNumber = mFocusState.LastAPZProcessedEvent();
|
||||
}
|
||||
|
||||
private:
|
||||
FocusState& mFocusState;
|
||||
InputData& mEvent;
|
||||
bool mMayChangeFocus;
|
||||
};
|
||||
|
||||
/*static*/ const ScreenMargin
|
||||
APZCTreeManager::CalculatePendingDisplayPort(
|
||||
@@ -281,6 +310,8 @@ APZCTreeManager::UpdateHitTestingTreeImpl(uint64_t aRootLayerTreeId,
|
||||
uint64_t layersId = aRootLayerTreeId;
|
||||
ancestorTransforms.push(Matrix4x4());
|
||||
|
||||
state.mLayersIdsToDestroy.erase(aRootLayerTreeId);
|
||||
|
||||
mApzcTreeLog << "[start]\n";
|
||||
mTreeLock.AssertCurrentThreadOwns();
|
||||
|
||||
@@ -298,9 +329,6 @@ APZCTreeManager::UpdateHitTestingTreeImpl(uint64_t aRootLayerTreeId,
|
||||
|
||||
mApzcTreeLog << '\n';
|
||||
|
||||
// Mark that this layer tree is being used
|
||||
state.mLayersIdsToDestroy.erase(layersId);
|
||||
|
||||
// Accumulate the CSS transform between layers that have an APZC.
|
||||
// In the terminology of the big comment above APZCTreeManager::GetScreenToApzcTransform, if
|
||||
// we are at layer M, then aAncestorTransform is NC * OC * PC, and we left-multiply MC and
|
||||
@@ -321,7 +349,15 @@ APZCTreeManager::UpdateHitTestingTreeImpl(uint64_t aRootLayerTreeId,
|
||||
MOZ_ASSERT(!node->GetFirstChild());
|
||||
parent = node;
|
||||
next = nullptr;
|
||||
layersId = aLayerMetrics.GetReferentId().valueOr(layersId);
|
||||
|
||||
// Update the layersId if we have a new one
|
||||
if (Maybe<uint64_t> newLayersId = aLayerMetrics.GetReferentId()) {
|
||||
layersId = *newLayersId;
|
||||
|
||||
// Mark that this layer tree is being used
|
||||
state.mLayersIdsToDestroy.erase(layersId);
|
||||
}
|
||||
|
||||
indents.push(gfx::TreeAutoIndent(mApzcTreeLog));
|
||||
},
|
||||
[&](ScrollNode aLayerMetrics)
|
||||
@@ -894,6 +930,9 @@ APZCTreeManager::ReceiveInputEvent(InputData& aEvent,
|
||||
{
|
||||
APZThreadUtils::AssertOnControllerThread();
|
||||
|
||||
// Use a RAII class for updating the focus sequence number of this event
|
||||
AutoFocusSequenceNumberSetter focusSetter(mFocusState, aEvent);
|
||||
|
||||
#if defined(MOZ_WIDGET_ANDROID)
|
||||
MOZ_ASSERT(mToolbarAnimator);
|
||||
ScreenPoint scrollOffset;
|
||||
@@ -1061,7 +1100,6 @@ APZCTreeManager::ReceiveInputEvent(InputData& aEvent,
|
||||
FlushRepaintsToClearScreenToGeckoTransform();
|
||||
|
||||
ScrollWheelInput& wheelInput = aEvent.AsScrollWheelInput();
|
||||
|
||||
wheelInput.mHandledByAPZ = WillHandleInput(wheelInput);
|
||||
if (!wheelInput.mHandledByAPZ) {
|
||||
return result;
|
||||
@@ -1430,8 +1468,9 @@ APZCTreeManager::UpdateWheelTransaction(LayoutDeviceIntPoint aRefPoint,
|
||||
}
|
||||
|
||||
void
|
||||
APZCTreeManager::TransformEventRefPoint(LayoutDeviceIntPoint* aRefPoint,
|
||||
ScrollableLayerGuid* aOutTargetGuid)
|
||||
APZCTreeManager::ProcessUnhandledEvent(LayoutDeviceIntPoint* aRefPoint,
|
||||
ScrollableLayerGuid* aOutTargetGuid,
|
||||
uint64_t* aOutFocusSequenceNumber)
|
||||
{
|
||||
// Transform the aRefPoint.
|
||||
// If the event hits an overscrolled APZC, instruct the caller to ignore it.
|
||||
@@ -1453,6 +1492,10 @@ APZCTreeManager::TransformEventRefPoint(LayoutDeviceIntPoint* aRefPoint,
|
||||
ViewAs<LayoutDevicePixel>(*untransformedRefPoint, LDIsScreen);
|
||||
}
|
||||
}
|
||||
|
||||
// Update the focus sequence number and attach it to the event
|
||||
mFocusState.ReceiveFocusChangingEvent();
|
||||
*aOutFocusSequenceNumber = mFocusState.LastAPZProcessedEvent();
|
||||
}
|
||||
|
||||
void
|
||||
|
||||
@@ -451,9 +451,10 @@ public:
|
||||
|
||||
// Methods to help process WidgetInputEvents (or manage conversion to/from InputData)
|
||||
|
||||
void TransformEventRefPoint(
|
||||
void ProcessUnhandledEvent(
|
||||
LayoutDeviceIntPoint* aRefPoint,
|
||||
ScrollableLayerGuid* aOutTargetGuid) override;
|
||||
ScrollableLayerGuid* aOutTargetGuid,
|
||||
uint64_t* aOutFocusSequenceNumber) override;
|
||||
|
||||
void UpdateWheelTransaction(
|
||||
LayoutDeviceIntPoint aRefPoint,
|
||||
|
||||
@@ -9,13 +9,28 @@ namespace mozilla {
|
||||
namespace layers {
|
||||
|
||||
FocusState::FocusState()
|
||||
: mFocusHasKeyEventListeners(false)
|
||||
: mLastAPZProcessedEvent(1)
|
||||
, mLastContentProcessedEvent(0)
|
||||
, mFocusHasKeyEventListeners(false)
|
||||
, mFocusLayersId(0)
|
||||
, mFocusHorizontalTarget(FrameMetrics::NULL_SCROLL_ID)
|
||||
, mFocusVerticalTarget(FrameMetrics::NULL_SCROLL_ID)
|
||||
{
|
||||
}
|
||||
|
||||
bool
|
||||
FocusState::IsCurrent() const
|
||||
{
|
||||
MOZ_ASSERT(mLastContentProcessedEvent <= mLastAPZProcessedEvent);
|
||||
return mLastContentProcessedEvent == mLastAPZProcessedEvent;
|
||||
}
|
||||
|
||||
void
|
||||
FocusState::ReceiveFocusChangingEvent()
|
||||
{
|
||||
mLastAPZProcessedEvent += 1;
|
||||
}
|
||||
|
||||
void
|
||||
FocusState::Update(uint64_t aRootLayerTreeId,
|
||||
uint64_t aOriginatingLayersId,
|
||||
@@ -60,9 +75,16 @@ FocusState::Update(uint64_t aRootLayerTreeId,
|
||||
// This is the global focus target
|
||||
mFocusHorizontalTarget = target.mData.mScrollTargets.mHorizontal;
|
||||
mFocusVerticalTarget = target.mData.mScrollTargets.mVertical;
|
||||
|
||||
// Mark what sequence number this target has so we can determine whether
|
||||
// it is stale or not
|
||||
mLastContentProcessedEvent = target.mSequenceNumber;
|
||||
return;
|
||||
}
|
||||
case FocusTarget::eNone: {
|
||||
// Mark what sequence number this target has for debugging purposes so
|
||||
// we can always accurately report on whether we are stale or not
|
||||
mLastContentProcessedEvent = target.mSequenceNumber;
|
||||
return;
|
||||
}
|
||||
case FocusTarget::eSentinel: {
|
||||
@@ -78,7 +100,7 @@ FocusState::GetFocusTargetLayerIds() const
|
||||
std::unordered_set<uint64_t> layersIds;
|
||||
layersIds.reserve(mFocusTree.size());
|
||||
|
||||
for (auto focusNode : mFocusTree) {
|
||||
for (const auto& focusNode : mFocusTree) {
|
||||
layersIds.insert(focusNode.first);
|
||||
}
|
||||
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
#include <unordered_set> // for std::unordered_set
|
||||
|
||||
#include "FrameMetrics.h" // for FrameMetrics::ViewID
|
||||
|
||||
#include "mozilla/layers/FocusTarget.h" // for FocusTarget
|
||||
|
||||
namespace mozilla {
|
||||
@@ -69,6 +70,28 @@ class FocusState final
|
||||
public:
|
||||
FocusState();
|
||||
|
||||
/**
|
||||
* The sequence number of the last potentially focus changing event processed
|
||||
* by APZ. This number starts at one and increases monotonically. This number
|
||||
* will never be zero as that is used to catch uninitialized focus sequence
|
||||
* numbers on input events.
|
||||
*/
|
||||
uint64_t LastAPZProcessedEvent() const { return mLastAPZProcessedEvent; }
|
||||
|
||||
/**
|
||||
* Whether the current focus state is known to be current or else if an event
|
||||
* has been processed that could change the focus but we have not received an
|
||||
* update with a new confirmed target.
|
||||
*/
|
||||
bool IsCurrent() const;
|
||||
|
||||
/**
|
||||
* Notify focus state of a potentially focus changing event. This will
|
||||
* increment the current focus sequence number. The new value can be gotten
|
||||
* from LastAPZProcessedEvent().
|
||||
*/
|
||||
void ReceiveFocusChangingEvent();
|
||||
|
||||
/**
|
||||
* Update the internal focus tree and recalculate the global focus target for
|
||||
* a focus target update received from chrome or content.
|
||||
@@ -96,6 +119,16 @@ private:
|
||||
// The set of focus targets received indexed by their layer tree ID
|
||||
std::unordered_map<uint64_t, FocusTarget> mFocusTree;
|
||||
|
||||
// The focus sequence number of the last potentially focus changing event
|
||||
// processed by APZ. This number starts at one and increases monotonically.
|
||||
// We don't worry about wrap around here because at a pace of 100 increments/sec,
|
||||
// it would take 5.85*10^9 years before we would wrap around. This number will
|
||||
// never be zero as that is used to catch uninitialized focus sequence numbers
|
||||
// on input events.
|
||||
uint64_t mLastAPZProcessedEvent;
|
||||
// The focus sequence number last received in a focus update.
|
||||
uint64_t mLastContentProcessedEvent;
|
||||
|
||||
// A flag whether there is a key listener on the event target chain for the
|
||||
// focused element
|
||||
bool mFocusHasKeyEventListeners;
|
||||
|
||||
@@ -67,13 +67,16 @@ IsEditableNode(nsINode* aNode)
|
||||
}
|
||||
|
||||
FocusTarget::FocusTarget()
|
||||
: mFocusHasKeyEventListeners(false)
|
||||
: mSequenceNumber(0)
|
||||
, mFocusHasKeyEventListeners(false)
|
||||
, mType(FocusTarget::eNone)
|
||||
{
|
||||
}
|
||||
|
||||
FocusTarget::FocusTarget(nsIPresShell* aRootPresShell)
|
||||
: mFocusHasKeyEventListeners(false)
|
||||
FocusTarget::FocusTarget(nsIPresShell* aRootPresShell,
|
||||
uint64_t aFocusSequenceNumber)
|
||||
: mSequenceNumber(aFocusSequenceNumber)
|
||||
, mFocusHasKeyEventListeners(false)
|
||||
{
|
||||
MOZ_ASSERT(aRootPresShell);
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
@@ -132,7 +135,8 @@ FocusTarget::FocusTarget(nsIPresShell* aRootPresShell)
|
||||
bool
|
||||
FocusTarget::operator==(const FocusTarget& aRhs) const
|
||||
{
|
||||
if (mFocusHasKeyEventListeners != aRhs.mFocusHasKeyEventListeners ||
|
||||
if (mSequenceNumber != aRhs.mSequenceNumber ||
|
||||
mFocusHasKeyEventListeners != aRhs.mFocusHasKeyEventListeners ||
|
||||
mType != aRhs.mType) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -50,11 +50,15 @@ public:
|
||||
/**
|
||||
* Construct a focus target for the specified top level PresShell
|
||||
*/
|
||||
FocusTarget(nsIPresShell* aRootPresShell);
|
||||
FocusTarget(nsIPresShell* aRootPresShell,
|
||||
uint64_t aFocusSequenceNumber);
|
||||
|
||||
bool operator==(const FocusTarget& aRhs) const;
|
||||
|
||||
public:
|
||||
// The content sequence number recorded at the time of this class's creation
|
||||
uint64_t mSequenceNumber;
|
||||
|
||||
// Whether there are keydown, keypress, or keyup event listeners
|
||||
// in the event target chain of the focused element
|
||||
bool mFocusHasKeyEventListeners;
|
||||
|
||||
@@ -213,11 +213,15 @@ APZCTreeManagerChild::UpdateWheelTransaction(
|
||||
SendUpdateWheelTransaction(aRefPoint, aEventMessage);
|
||||
}
|
||||
|
||||
void APZCTreeManagerChild::TransformEventRefPoint(
|
||||
void APZCTreeManagerChild::ProcessUnhandledEvent(
|
||||
LayoutDeviceIntPoint* aRefPoint,
|
||||
ScrollableLayerGuid* aOutTargetGuid)
|
||||
ScrollableLayerGuid* aOutTargetGuid,
|
||||
uint64_t* aOutFocusSequenceNumber)
|
||||
{
|
||||
SendTransformEventRefPoint(*aRefPoint, aRefPoint, aOutTargetGuid);
|
||||
SendProcessUnhandledEvent(*aRefPoint,
|
||||
aRefPoint,
|
||||
aOutTargetGuid,
|
||||
aOutFocusSequenceNumber);
|
||||
}
|
||||
|
||||
mozilla::ipc::IPCResult
|
||||
|
||||
@@ -77,9 +77,10 @@ public:
|
||||
ProcessTouchVelocity(uint32_t aTimestampMs, float aSpeedY) override;
|
||||
|
||||
void
|
||||
TransformEventRefPoint(
|
||||
ProcessUnhandledEvent(
|
||||
LayoutDeviceIntPoint* aRefPoint,
|
||||
ScrollableLayerGuid* aOutTargetGuid) override;
|
||||
ScrollableLayerGuid* aOutTargetGuid,
|
||||
uint64_t* aOutFocusSequenceNumber) override;
|
||||
|
||||
void
|
||||
UpdateWheelTransaction(
|
||||
|
||||
@@ -307,13 +307,14 @@ APZCTreeManagerParent::RecvUpdateWheelTransaction(
|
||||
}
|
||||
|
||||
mozilla::ipc::IPCResult
|
||||
APZCTreeManagerParent::RecvTransformEventRefPoint(
|
||||
APZCTreeManagerParent::RecvProcessUnhandledEvent(
|
||||
const LayoutDeviceIntPoint& aRefPoint,
|
||||
LayoutDeviceIntPoint* aOutRefPoint,
|
||||
ScrollableLayerGuid* aOutTargetGuid)
|
||||
ScrollableLayerGuid* aOutTargetGuid,
|
||||
uint64_t* aOutFocusSequenceNumber)
|
||||
{
|
||||
LayoutDeviceIntPoint refPoint = aRefPoint;
|
||||
mTreeManager->TransformEventRefPoint(&refPoint, aOutTargetGuid);
|
||||
mTreeManager->ProcessUnhandledEvent(&refPoint, aOutTargetGuid, aOutFocusSequenceNumber);
|
||||
*aOutRefPoint = refPoint;
|
||||
|
||||
return IPC_OK();
|
||||
|
||||
@@ -132,10 +132,11 @@ public:
|
||||
const EventMessage& aEventMessage) override;
|
||||
|
||||
mozilla::ipc::IPCResult
|
||||
RecvTransformEventRefPoint(
|
||||
RecvProcessUnhandledEvent(
|
||||
const LayoutDeviceIntPoint& aRefPoint,
|
||||
LayoutDeviceIntPoint* aOutRefPoint,
|
||||
ScrollableLayerGuid* aOutTargetGuid) override;
|
||||
ScrollableLayerGuid* aOutTargetGuid,
|
||||
uint64_t* aOutFocusSequenceNumber) override;
|
||||
|
||||
void
|
||||
ActorDestroy(ActorDestroyReason aWhy) override { }
|
||||
|
||||
@@ -454,6 +454,7 @@ struct ParamTraits<mozilla::layers::FocusTarget>
|
||||
|
||||
static void Write(Message* aMsg, const paramType& aParam)
|
||||
{
|
||||
WriteParam(aMsg, aParam.mSequenceNumber);
|
||||
WriteParam(aMsg, aParam.mFocusHasKeyEventListeners);
|
||||
WriteParam(aMsg, aParam.mType);
|
||||
if (aParam.mType == mozilla::layers::FocusTarget::eRefLayer) {
|
||||
@@ -465,7 +466,8 @@ struct ParamTraits<mozilla::layers::FocusTarget>
|
||||
|
||||
static bool Read(const Message* aMsg, PickleIterator* aIter, paramType* aResult)
|
||||
{
|
||||
if (!ReadParam(aMsg, aIter, &aResult->mFocusHasKeyEventListeners) ||
|
||||
if (!ReadParam(aMsg, aIter, &aResult->mSequenceNumber) ||
|
||||
!ReadParam(aMsg, aIter, &aResult->mFocusHasKeyEventListeners) ||
|
||||
!ReadParam(aMsg, aIter, &aResult->mType)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -123,9 +123,10 @@ parent:
|
||||
|
||||
async UpdateWheelTransaction(LayoutDeviceIntPoint aRefPoint, EventMessage aEventMessage);
|
||||
|
||||
sync TransformEventRefPoint(LayoutDeviceIntPoint aRefPoint)
|
||||
sync ProcessUnhandledEvent(LayoutDeviceIntPoint aRefPoint)
|
||||
returns (LayoutDeviceIntPoint aOutRefPoint,
|
||||
ScrollableLayerGuid aOutTargetGuid);
|
||||
ScrollableLayerGuid aOutTargetGuid,
|
||||
uint64_t aOutFocusSequenceNumber);
|
||||
|
||||
async __delete__();
|
||||
|
||||
|
||||
@@ -967,7 +967,7 @@ description =
|
||||
description =
|
||||
[PAPZCTreeManager::ReceiveScrollWheelInputEvent]
|
||||
description =
|
||||
[PAPZCTreeManager::TransformEventRefPoint]
|
||||
[PAPZCTreeManager::ProcessUnhandledEvent]
|
||||
description =
|
||||
[PCompositorBridge::Initialize]
|
||||
description =
|
||||
|
||||
@@ -802,6 +802,7 @@ nsIPresShell::nsIPresShell()
|
||||
, mObservingLayoutFlushes(false)
|
||||
, mNeedThrottledAnimationFlush(true)
|
||||
, mPresShellId(0)
|
||||
, mAPZFocusSequenceNumber(0)
|
||||
, mFontSizeInflationEmPerLine(0)
|
||||
, mFontSizeInflationMinTwips(0)
|
||||
, mFontSizeInflationLineThreshold(0)
|
||||
@@ -6340,7 +6341,7 @@ PresShell::Paint(nsView* aViewToPaint,
|
||||
// Update the focus target for async keyboard scrolling. This will be forwarded
|
||||
// to APZ by nsDisplayList::PaintRoot. We need to to do this before we enter
|
||||
// the paint phase because dispatching eVoid events can cause layout to happen.
|
||||
mAPZFocusTarget = FocusTarget(this);
|
||||
mAPZFocusTarget = FocusTarget(this, mAPZFocusSequenceNumber);
|
||||
|
||||
nsPresContext* presContext = GetPresContext();
|
||||
AUTO_LAYOUT_PHASE_ENTRY_POINT(presContext, Paint);
|
||||
@@ -7154,6 +7155,12 @@ PresShell::HandleEvent(nsIFrame* aFrame,
|
||||
|
||||
NS_ASSERTION(aFrame, "aFrame should be not null");
|
||||
|
||||
// Update the latest focus sequence number with this new sequence number
|
||||
if (mAPZFocusSequenceNumber < aEvent->mFocusSequenceNumber) {
|
||||
// XXX should we push a new FocusTarget to APZ here
|
||||
mAPZFocusSequenceNumber = aEvent->mFocusSequenceNumber;
|
||||
}
|
||||
|
||||
if (sPointerEventEnabled) {
|
||||
AutoWeakFrame weakFrame(aFrame);
|
||||
nsCOMPtr<nsIContent> targetContent;
|
||||
|
||||
@@ -1905,6 +1905,8 @@ protected:
|
||||
|
||||
uint32_t mPresShellId;
|
||||
|
||||
// The focus sequence number of the last processed input event
|
||||
uint64_t mAPZFocusSequenceNumber;
|
||||
// The focus information needed for async keyboard scrolling
|
||||
FocusTarget mAPZFocusTarget;
|
||||
|
||||
|
||||
@@ -354,6 +354,7 @@ protected:
|
||||
, mMessage(aMessage)
|
||||
, mRefPoint(0, 0)
|
||||
, mLastRefPoint(0, 0)
|
||||
, mFocusSequenceNumber(0)
|
||||
, mSpecifiedEventType(nullptr)
|
||||
{
|
||||
MOZ_COUNT_CTOR(WidgetEvent);
|
||||
@@ -405,6 +406,10 @@ public:
|
||||
LayoutDeviceIntPoint mRefPoint;
|
||||
// The previous mRefPoint, if known, used to calculate mouse movement deltas.
|
||||
LayoutDeviceIntPoint mLastRefPoint;
|
||||
// The sequence number of the last potentially focus changing event handled
|
||||
// by APZ. This is used to track when that event has been processed by content,
|
||||
// and focus can be reconfirmed for async keyboard scrolling.
|
||||
uint64_t mFocusSequenceNumber;
|
||||
// See BaseEventFlags definition for the detail.
|
||||
BaseEventFlags mFlags;
|
||||
|
||||
@@ -435,6 +440,7 @@ public:
|
||||
// mMessage should be initialized with the constructor.
|
||||
mRefPoint = aEvent.mRefPoint;
|
||||
// mLastRefPoint doesn't need to be copied.
|
||||
mFocusSequenceNumber = aEvent.mFocusSequenceNumber;
|
||||
AssignEventTime(aEvent);
|
||||
// mFlags should be copied manually if it's necessary.
|
||||
mSpecifiedEventType = aEvent.mSpecifiedEventType;
|
||||
|
||||
@@ -23,6 +23,7 @@ InputData::~InputData()
|
||||
InputData::InputData(InputType aInputType)
|
||||
: mInputType(aInputType)
|
||||
, mTime(0)
|
||||
, mFocusSequenceNumber(0)
|
||||
, modifiers(0)
|
||||
{
|
||||
}
|
||||
@@ -32,6 +33,7 @@ InputData::InputData(InputType aInputType, uint32_t aTime, TimeStamp aTimeStamp,
|
||||
: mInputType(aInputType)
|
||||
, mTime(aTime)
|
||||
, mTimeStamp(aTimeStamp)
|
||||
, mFocusSequenceNumber(0)
|
||||
, modifiers(aModifiers)
|
||||
{
|
||||
}
|
||||
@@ -226,6 +228,7 @@ MultiTouchInput::ToWidgetTouchEvent(nsIWidget* aWidget) const
|
||||
event.mTime = this->mTime;
|
||||
event.mTimeStamp = this->mTimeStamp;
|
||||
event.mFlags.mHandledByAPZ = mHandledByAPZ;
|
||||
event.mFocusSequenceNumber = mFocusSequenceNumber;
|
||||
|
||||
for (size_t i = 0; i < mTouches.Length(); i++) {
|
||||
*event.mTouches.AppendElement() = mTouches[i].ToNewDOMTouch();
|
||||
@@ -269,6 +272,7 @@ MultiTouchInput::ToWidgetMouseEvent(nsIWidget* aWidget) const
|
||||
event.inputSource = nsIDOMMouseEvent::MOZ_SOURCE_TOUCH;
|
||||
event.mModifiers = modifiers;
|
||||
event.mFlags.mHandledByAPZ = mHandledByAPZ;
|
||||
event.mFocusSequenceNumber = mFocusSequenceNumber;
|
||||
|
||||
if (mouseEventMessage != eMouseMove) {
|
||||
event.mClickCount = 1;
|
||||
@@ -470,6 +474,7 @@ MouseInput::ToWidgetMouseEvent(nsIWidget* aWidget) const
|
||||
event.mClickCount = clickCount;
|
||||
event.inputSource = mInputSource;
|
||||
event.mIgnoreRootScrollFrame = true;
|
||||
event.mFocusSequenceNumber = mFocusSequenceNumber;
|
||||
|
||||
return event;
|
||||
}
|
||||
@@ -537,6 +542,7 @@ PanGestureInput::ToWidgetWheelEvent(nsIWidget* aWidget) const
|
||||
wheelEvent.mDeltaX = mPanDisplacement.x;
|
||||
wheelEvent.mDeltaY = mPanDisplacement.y;
|
||||
wheelEvent.mFlags.mHandledByAPZ = mHandledByAPZ;
|
||||
wheelEvent.mFocusSequenceNumber = mFocusSequenceNumber;
|
||||
return wheelEvent;
|
||||
}
|
||||
|
||||
@@ -764,6 +770,7 @@ ScrollWheelInput::ToWidgetWheelEvent(nsIWidget* aWidget) const
|
||||
wheelEvent.mAllowToOverrideSystemScrollSpeed =
|
||||
mAllowToOverrideSystemScrollSpeed;
|
||||
wheelEvent.mFlags.mHandledByAPZ = mHandledByAPZ;
|
||||
wheelEvent.mFocusSequenceNumber = mFocusSequenceNumber;
|
||||
return wheelEvent;
|
||||
}
|
||||
|
||||
|
||||
@@ -86,6 +86,10 @@ public:
|
||||
// Set in parallel to mTime until we determine it is safe to drop
|
||||
// platform-specific event times (see bug 77992).
|
||||
TimeStamp mTimeStamp;
|
||||
// The sequence number of the last potentially focus changing event handled
|
||||
// by APZ. This is used to track when that event has been processed by content,
|
||||
// and focus can be reconfirmed for async keyboard scrolling.
|
||||
uint64_t mFocusSequenceNumber;
|
||||
|
||||
Modifiers modifiers;
|
||||
|
||||
|
||||
@@ -65,6 +65,7 @@ struct ParamTraits<mozilla::WidgetEvent>
|
||||
static_cast<mozilla::EventClassIDType>(aParam.mClass));
|
||||
WriteParam(aMsg, aParam.mMessage);
|
||||
WriteParam(aMsg, aParam.mRefPoint);
|
||||
WriteParam(aMsg, aParam.mFocusSequenceNumber);
|
||||
WriteParam(aMsg, aParam.mTime);
|
||||
WriteParam(aMsg, aParam.mTimeStamp);
|
||||
WriteParam(aMsg, aParam.mFlags);
|
||||
@@ -76,6 +77,7 @@ struct ParamTraits<mozilla::WidgetEvent>
|
||||
bool ret = ReadParam(aMsg, aIter, &eventClassID) &&
|
||||
ReadParam(aMsg, aIter, &aResult->mMessage) &&
|
||||
ReadParam(aMsg, aIter, &aResult->mRefPoint) &&
|
||||
ReadParam(aMsg, aIter, &aResult->mFocusSequenceNumber) &&
|
||||
ReadParam(aMsg, aIter, &aResult->mTime) &&
|
||||
ReadParam(aMsg, aIter, &aResult->mTimeStamp) &&
|
||||
ReadParam(aMsg, aIter, &aResult->mFlags);
|
||||
@@ -1080,6 +1082,7 @@ struct ParamTraits<mozilla::InputData>
|
||||
WriteParam(aMsg, aParam.mTime);
|
||||
WriteParam(aMsg, aParam.mTimeStamp);
|
||||
WriteParam(aMsg, aParam.modifiers);
|
||||
WriteParam(aMsg, aParam.mFocusSequenceNumber);
|
||||
}
|
||||
|
||||
static bool Read(const Message* aMsg, PickleIterator* aIter, paramType* aResult)
|
||||
@@ -1087,7 +1090,8 @@ struct ParamTraits<mozilla::InputData>
|
||||
return ReadParam(aMsg, aIter, &aResult->mInputType) &&
|
||||
ReadParam(aMsg, aIter, &aResult->mTime) &&
|
||||
ReadParam(aMsg, aIter, &aResult->mTimeStamp) &&
|
||||
ReadParam(aMsg, aIter, &aResult->modifiers);
|
||||
ReadParam(aMsg, aIter, &aResult->modifiers) &&
|
||||
ReadParam(aMsg, aIter, &aResult->mFocusSequenceNumber);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user