Bug 1435788 - Allow handling focus-changing events prior to the first update on GPU process restart. r=rhunt

If the GPU process restarts, the mLastAPZProcessedEvent gets reset to 1.
The code in Update() checks for this special case and resets the value
to the incoming content process sequence number. However, we before that
first call to Update() on the sampler thread, the FocusState might get calls
to ReceiveFocusChangingEvent(), which would be triggered by input events on
the controller thread. These input events would advance
mLastAPZProcessedEvent which would bypass the special case handling in
Update(). This can leave mLastAPZProcessedEvent at a lower value than
mLastContentProcessedEvent which triggers assertion failures.

This patch ensures that calls to ReceiveFocusChangingEvent() during this
initial state doesn't increment mLastAPZProcessedEvent, and so allows
the special case handling in Update() to work as expected. It also adds
the special case handling to the branch where the first Update() call
results in no focus target being selected.

MozReview-Commit-ID: 7P2O2qg0mXj

--HG--
extra : rebase_source : eb0655225eba55a7b1ad9bf16c7c8ecab3c0cc7b
This commit is contained in:
Kartikaya Gupta 2018-03-14 08:43:56 -04:00
parent fb715e3c6d
commit b91f33e3d1
2 changed files with 24 additions and 1 deletions

View File

@ -19,6 +19,7 @@ FocusState::FocusState()
, mLastAPZProcessedEvent(1)
, mLastContentProcessedEvent(0)
, mFocusHasKeyEventListeners(false)
, mReceivedUpdate(false)
, mFocusLayersId(0)
, mFocusHorizontalTarget(FrameMetrics::NULL_SCROLL_ID)
, mFocusVerticalTarget(FrameMetrics::NULL_SCROLL_ID)
@ -51,7 +52,17 @@ FocusState::ReceiveFocusChangingEvent()
APZThreadUtils::AssertOnControllerThread();
MutexAutoLock lock(mMutex);
if (!mReceivedUpdate) {
// In the initial state don't advance mLastAPZProcessedEvent because we
// might blow away the information that we're in a freshly-restarted GPU
// process. This information (i.e. that mLastAPZProcessedEvent == 1) needs
// to be preserved until the first call to Update() which will then advance
// mLastAPZProcessedEvent to match the content-side sequence number.
return;
}
mLastAPZProcessedEvent += 1;
FS_LOG("Focus changing event incremented aseq to %" PRIu64 "\n",
mLastAPZProcessedEvent);
}
void
@ -67,6 +78,7 @@ FocusState::Update(uint64_t aRootLayerTreeId,
aOriginatingLayersId,
aState.Type(),
aState.mSequenceNumber);
mReceivedUpdate = true;
// Update the focus tree with the latest target
mFocusTree[aOriginatingLayersId] = aState;
@ -103,11 +115,20 @@ FocusState::Update(uint64_t aRootLayerTreeId,
const uint64_t mSequenceNumber;
bool match(const FocusTarget::NoFocusTarget& aNoFocusTarget) {
FS_LOG("Setting target to nil (reached a nil target)\n");
FS_LOG("Setting target to nil (reached a nil target) with seq=%" PRIu64 "\n",
mSequenceNumber);
// Mark what sequence number this target has for debugging purposes so
// we can always accurately report on whether we are stale or not
mFocusState.mLastContentProcessedEvent = mSequenceNumber;
// If this focus state was just created and content has experienced more
// events then us, then assume we were recreated and sync focus sequence
// numbers.
if (mFocusState.mLastAPZProcessedEvent == 1 &&
mFocusState.mLastContentProcessedEvent > mFocusState.mLastAPZProcessedEvent) {
mFocusState.mLastAPZProcessedEvent = mFocusState.mLastContentProcessedEvent;
}
return true;
}

View File

@ -157,6 +157,8 @@ private:
// A flag whether there is a key listener on the event target chain for the
// focused element
bool mFocusHasKeyEventListeners;
// A flag that is false until the first call to Update().
bool mReceivedUpdate;
// The layer tree ID which contains the scrollable frame of the focused element
uint64_t mFocusLayersId;