Bug 1669588 - Factor out a OneShotPostRefreshObserver utility class. r=kats

Differential Revision: https://phabricator.services.mozilla.com/D93897
This commit is contained in:
Botond Ballo 2020-10-21 23:09:50 +00:00
Родитель 63198ca57a
Коммит 944a3748f5
6 изменённых файлов: 91 добавлений и 69 удалений

Просмотреть файл

@ -649,7 +649,7 @@ static bool PrepareForSetTargetAPZCNotification(
static void SendLayersDependentApzcTargetConfirmation(
PresShell* aPresShell, uint64_t aInputBlockId,
const nsTArray<ScrollableLayerGuid>& aTargets) {
nsTArray<ScrollableLayerGuid>&& aTargets) {
LayerManager* lm = aPresShell->GetLayerManager();
if (!lm) {
return;
@ -679,11 +679,13 @@ static void SendLayersDependentApzcTargetConfirmation(
DisplayportSetListener::DisplayportSetListener(
nsIWidget* aWidget, PresShell* aPresShell, const uint64_t& aInputBlockId,
const nsTArray<ScrollableLayerGuid>& aTargets)
: mWidget(aWidget),
mPresShell(aPresShell),
nsTArray<ScrollableLayerGuid>&& aTargets)
: OneShotPostRefreshObserver(
aPresShell,
[this](PresShell* aPresShell) { OnPostRefresh(this, aPresShell); }),
mWidget(aWidget),
mInputBlockId(aInputBlockId),
mTargets(aTargets.Clone()) {}
mTargets(std::move(aTargets)) {}
DisplayportSetListener::~DisplayportSetListener() = default;
@ -699,29 +701,13 @@ bool DisplayportSetListener::Register() {
return false;
}
void DisplayportSetListener::DidRefresh() {
if (!mPresShell) {
MOZ_ASSERT_UNREACHABLE(
"Post-refresh observer fired again after failed attempt at "
"unregistering it");
return;
}
/* static */
void DisplayportSetListener::OnPostRefresh(DisplayportSetListener* aListener,
PresShell* aPresShell) {
APZCCH_LOG("Got refresh, sending target APZCs for input block %" PRIu64 "\n",
mInputBlockId);
SendLayersDependentApzcTargetConfirmation(mPresShell, mInputBlockId,
std::move(mTargets));
if (!mPresShell->RemovePostRefreshObserver(this)) {
MOZ_ASSERT_UNREACHABLE(
"Unable to unregister post-refresh observer! Leaking it instead of "
"leaving garbage registered");
// Graceful handling, just in case...
mPresShell = nullptr;
return;
}
delete this;
aListener->mInputBlockId);
SendLayersDependentApzcTargetConfirmation(
aPresShell, aListener->mInputBlockId, std::move(aListener->mTargets));
}
UniquePtr<DisplayportSetListener>

Просмотреть файл

@ -35,20 +35,21 @@ typedef std::function<void(uint64_t, const nsTArray<TouchBehaviorFlags>&)>
SetAllowedTouchBehaviorCallback;
/* Refer to documentation on SendSetTargetAPZCNotification for this class */
class DisplayportSetListener : public nsAPostRefreshObserver {
class DisplayportSetListener : public OneShotPostRefreshObserver {
public:
DisplayportSetListener(nsIWidget* aWidget, PresShell* aPresShell,
const uint64_t& aInputBlockId,
const nsTArray<ScrollableLayerGuid>& aTargets);
nsTArray<ScrollableLayerGuid>&& aTargets);
virtual ~DisplayportSetListener();
bool Register();
void DidRefresh() override;
private:
RefPtr<nsIWidget> mWidget;
RefPtr<PresShell> mPresShell;
uint64_t mInputBlockId;
nsTArray<ScrollableLayerGuid> mTargets;
static void OnPostRefresh(DisplayportSetListener* aListener,
PresShell* aPresShell);
};
/* This class contains some helper methods that facilitate implementing the

Просмотреть файл

@ -125,6 +125,7 @@ UNIFIED_SOURCES += [
"nsPresArena.cpp",
"nsPresContext.cpp",
"nsQuoteList.cpp",
"nsRefreshObservers.cpp",
"nsStyleChangeList.cpp",
"nsStyleSheetService.cpp",
"PositionedEventTargeting.cpp",

Просмотреть файл

@ -0,0 +1,41 @@
/* -*- 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 "nsRefreshObservers.h"
#include "PresShell.h"
namespace mozilla {
OneShotPostRefreshObserver::OneShotPostRefreshObserver(PresShell* aPresShell,
Action&& aAction)
: mPresShell(aPresShell), mAction(std::move(aAction)) {}
OneShotPostRefreshObserver::~OneShotPostRefreshObserver() = default;
void OneShotPostRefreshObserver::DidRefresh() {
if (!mPresShell) {
MOZ_ASSERT_UNREACHABLE(
"Post-refresh observer fired again after failed attempt at "
"unregistering it");
return;
}
mAction(mPresShell);
if (!mPresShell->RemovePostRefreshObserver(this)) {
MOZ_ASSERT_UNREACHABLE(
"Unable to unregister post-refresh observer! Leaking it instead of "
"leaving garbage registered");
// Graceful handling, just in case...
mPresShell = nullptr;
mAction = Action();
return;
}
delete this;
}
} // namespace mozilla

Просмотреть файл

@ -19,6 +19,7 @@
namespace mozilla {
class AnimationEventDispatcher;
class PendingFullscreenEvent;
class PresShell;
class RefreshDriverTimer;
namespace layout {
class VsyncChild;
@ -64,4 +65,28 @@ class nsAPostRefreshObserver {
virtual void DidRefresh() = 0;
};
namespace mozilla {
/**
* A wrapper for nsAPostRefreshObserver that's one-shot (unregisters itself
* after firing once) and can be used without writing a derived class by passing
* in the action in the form of a lambda (or other function object).
*
* Note, while the observer unregisters itself, the registering still needs to
* be done by the caller.
*/
class OneShotPostRefreshObserver : public nsAPostRefreshObserver {
public:
using Action = std::function<void(mozilla::PresShell*)>;
OneShotPostRefreshObserver(mozilla::PresShell* aPresShell, Action&& aAction);
virtual ~OneShotPostRefreshObserver();
void DidRefresh() override;
protected:
RefPtr<mozilla::PresShell> mPresShell;
Action mAction;
};
} // namespace mozilla
#endif

Просмотреть файл

@ -894,42 +894,6 @@ nsresult nsSliderMediator::HandleEvent(dom::Event* aEvent) {
return NS_OK;
}
class AsyncScrollbarDragStarter final : public nsAPostRefreshObserver {
public:
AsyncScrollbarDragStarter(mozilla::PresShell* aPresShell, nsIWidget* aWidget,
const AsyncDragMetrics& aDragMetrics)
: mPresShell(aPresShell), mWidget(aWidget), mDragMetrics(aDragMetrics) {}
virtual ~AsyncScrollbarDragStarter() = default;
void DidRefresh() override {
if (!mPresShell) {
MOZ_ASSERT_UNREACHABLE(
"Post-refresh observer fired again after failed attempt at "
"unregistering it");
return;
}
mWidget->StartAsyncScrollbarDrag(mDragMetrics);
if (!mPresShell->RemovePostRefreshObserver(this)) {
MOZ_ASSERT_UNREACHABLE(
"Unable to unregister post-refresh observer! Leaking it instead of "
"leaving garbage registered");
// Graceful handling, just in case...
mPresShell = nullptr;
mWidget = nullptr;
return;
}
delete this;
}
private:
RefPtr<mozilla::PresShell> mPresShell;
RefPtr<nsIWidget> mWidget;
AsyncDragMetrics mDragMetrics;
};
static bool ScrollFrameWillBuildScrollInfoLayer(nsIFrame* aScrollFrame) {
/*
* Note: if changing the conditions in this function, make a corresponding
@ -1026,8 +990,12 @@ void nsSliderFrame::StartAPZDrag(WidgetGUIEvent* aEvent) {
bool waitForRefresh = InputAPZContext::HavePendingLayerization();
nsIWidget* widget = this->GetNearestWidget();
if (waitForRefresh) {
waitForRefresh = presShell->AddPostRefreshObserver(
new AsyncScrollbarDragStarter(presShell, widget, dragMetrics));
waitForRefresh =
presShell->AddPostRefreshObserver(new OneShotPostRefreshObserver(
presShell, [widget = RefPtr<nsIWidget>(widget),
dragMetrics](mozilla::PresShell*) {
widget->StartAsyncScrollbarDrag(dragMetrics);
}));
}
if (!waitForRefresh) {
widget->StartAsyncScrollbarDrag(dragMetrics);