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:
Ryan Hunt
2017-06-05 19:45:31 -05:00
parent 3eb832e2a9
commit 03a67c3376
21 changed files with 188 additions and 37 deletions

View File

@@ -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;
}

View File

@@ -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,

View File

@@ -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

View File

@@ -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,

View File

@@ -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);
}

View File

@@ -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;

View File

@@ -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;
}

View File

@@ -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;

View File

@@ -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

View File

@@ -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(

View File

@@ -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();

View File

@@ -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 { }

View File

@@ -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;
}

View File

@@ -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__();

View File

@@ -967,7 +967,7 @@ description =
description =
[PAPZCTreeManager::ReceiveScrollWheelInputEvent]
description =
[PAPZCTreeManager::TransformEventRefPoint]
[PAPZCTreeManager::ProcessUnhandledEvent]
description =
[PCompositorBridge::Initialize]
description =

View File

@@ -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;

View File

@@ -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;

View File

@@ -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;

View File

@@ -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;
}

View File

@@ -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;

View File

@@ -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);
}
};