summaryrefslogtreecommitdiffstats
path: root/gfx/layers/apz/src/OverscrollHandoffState.cpp
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-28 14:29:10 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-28 14:29:10 +0000
commit2aa4a82499d4becd2284cdb482213d541b8804dd (patch)
treeb80bf8bf13c3766139fbacc530efd0dd9d54394c /gfx/layers/apz/src/OverscrollHandoffState.cpp
parentInitial commit. (diff)
downloadfirefox-2aa4a82499d4becd2284cdb482213d541b8804dd.tar.xz
firefox-2aa4a82499d4becd2284cdb482213d541b8804dd.zip
Adding upstream version 86.0.1.upstream/86.0.1upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'gfx/layers/apz/src/OverscrollHandoffState.cpp')
-rw-r--r--gfx/layers/apz/src/OverscrollHandoffState.cpp178
1 files changed, 178 insertions, 0 deletions
diff --git a/gfx/layers/apz/src/OverscrollHandoffState.cpp b/gfx/layers/apz/src/OverscrollHandoffState.cpp
new file mode 100644
index 0000000000..c8575ef68b
--- /dev/null
+++ b/gfx/layers/apz/src/OverscrollHandoffState.cpp
@@ -0,0 +1,178 @@
+/* -*- 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 "OverscrollHandoffState.h"
+
+#include <algorithm> // for std::stable_sort
+#include "mozilla/Assertions.h"
+#include "AsyncPanZoomController.h"
+
+namespace mozilla {
+namespace layers {
+
+OverscrollHandoffChain::~OverscrollHandoffChain() = default;
+
+void OverscrollHandoffChain::Add(AsyncPanZoomController* aApzc) {
+ mChain.push_back(aApzc);
+}
+
+struct CompareByScrollPriority {
+ bool operator()(const RefPtr<AsyncPanZoomController>& a,
+ const RefPtr<AsyncPanZoomController>& b) const {
+ return a->HasScrollgrab() && !b->HasScrollgrab();
+ }
+};
+
+void OverscrollHandoffChain::SortByScrollPriority() {
+ // The sorting being stable ensures that the relative order between
+ // non-scrollgrabbing APZCs remains child -> parent.
+ // (The relative order between scrollgrabbing APZCs will also remain
+ // child -> parent, though that's just an artefact of the implementation
+ // and users of 'scrollgrab' should not rely on this.)
+ std::stable_sort(mChain.begin(), mChain.end(), CompareByScrollPriority());
+}
+
+const RefPtr<AsyncPanZoomController>& OverscrollHandoffChain::GetApzcAtIndex(
+ uint32_t aIndex) const {
+ MOZ_ASSERT(aIndex < Length());
+ return mChain[aIndex];
+}
+
+uint32_t OverscrollHandoffChain::IndexOf(
+ const AsyncPanZoomController* aApzc) const {
+ uint32_t i;
+ for (i = 0; i < Length(); ++i) {
+ if (mChain[i] == aApzc) {
+ break;
+ }
+ }
+ return i;
+}
+
+void OverscrollHandoffChain::ForEachApzc(APZCMethod aMethod) const {
+ for (uint32_t i = 0; i < Length(); ++i) {
+ (mChain[i]->*aMethod)();
+ }
+}
+
+bool OverscrollHandoffChain::AnyApzc(APZCPredicate aPredicate) const {
+ MOZ_ASSERT(Length() > 0);
+ for (uint32_t i = 0; i < Length(); ++i) {
+ if ((mChain[i]->*aPredicate)()) {
+ return true;
+ }
+ }
+ return false;
+}
+
+void OverscrollHandoffChain::FlushRepaints() const {
+ ForEachApzc(&AsyncPanZoomController::FlushRepaintForOverscrollHandoff);
+}
+
+void OverscrollHandoffChain::CancelAnimations(
+ CancelAnimationFlags aFlags) const {
+ MOZ_ASSERT(Length() > 0);
+ for (uint32_t i = 0; i < Length(); ++i) {
+ mChain[i]->CancelAnimation(aFlags);
+ }
+}
+
+void OverscrollHandoffChain::ClearOverscroll() const {
+ ForEachApzc(&AsyncPanZoomController::ClearOverscroll);
+}
+
+void OverscrollHandoffChain::SnapBackOverscrolledApzc(
+ const AsyncPanZoomController* aStart) const {
+ uint32_t i = IndexOf(aStart);
+ for (; i < Length(); ++i) {
+ AsyncPanZoomController* apzc = mChain[i];
+ if (!apzc->IsDestroyed()) {
+ apzc->SnapBackIfOverscrolled();
+ }
+ }
+}
+
+bool OverscrollHandoffChain::CanBePanned(
+ const AsyncPanZoomController* aApzc) const {
+ // Find |aApzc| in the handoff chain.
+ uint32_t i = IndexOf(aApzc);
+
+ // See whether any APZC in the handoff chain starting from |aApzc|
+ // has room to be panned.
+ for (uint32_t j = i; j < Length(); ++j) {
+ if (mChain[j]->IsPannable()) {
+ return true;
+ }
+ }
+
+ return false;
+}
+
+bool OverscrollHandoffChain::CanScrollInDirection(
+ const AsyncPanZoomController* aApzc, ScrollDirection aDirection) const {
+ // Find |aApzc| in the handoff chain.
+ uint32_t i = IndexOf(aApzc);
+
+ // See whether any APZC in the handoff chain starting from |aApzc|
+ // has room to scroll in the given direction.
+ for (uint32_t j = i; j < Length(); ++j) {
+ if (mChain[j]->CanScroll(aDirection)) {
+ return true;
+ }
+ }
+
+ return false;
+}
+
+bool OverscrollHandoffChain::HasOverscrolledApzc() const {
+ return AnyApzc(&AsyncPanZoomController::IsOverscrolled);
+}
+
+bool OverscrollHandoffChain::HasFastFlungApzc() const {
+ return AnyApzc(&AsyncPanZoomController::IsFlingingFast);
+}
+
+RefPtr<AsyncPanZoomController> OverscrollHandoffChain::FindFirstScrollable(
+ const InputData& aInput,
+ ScrollDirections* aOutAllowedScrollDirections) const {
+ // Start by allowing scrolling in both directions. As we do handoff
+ // overscroll-behavior may restrict one or both of the directions.
+ *aOutAllowedScrollDirections += ScrollDirection::eVertical;
+ *aOutAllowedScrollDirections += ScrollDirection::eHorizontal;
+
+ for (size_t i = 0; i < Length(); i++) {
+ if (mChain[i]->CanScroll(aInput)) {
+ return mChain[i];
+ }
+
+ *aOutAllowedScrollDirections &= mChain[i]->GetAllowedHandoffDirections();
+ if (aOutAllowedScrollDirections->isEmpty()) {
+ return nullptr;
+ }
+ }
+ return nullptr;
+}
+
+bool OverscrollHandoffChain::ScrollingDownWillMoveDynamicToolbar(
+ const AsyncPanZoomController* aApzc) const {
+ MOZ_ASSERT(aApzc && !aApzc->IsRootContent(),
+ "Should be used for non-root APZC");
+
+ for (uint32_t i = IndexOf(aApzc); i < Length(); i++) {
+ if (mChain[i]->IsRootContent()) {
+ return mChain[i]->CanScrollDownwardsWithDynamicToolbar();
+ }
+
+ if (mChain[i]->CanScrollDownwards()) {
+ return false;
+ }
+ }
+
+ return false;
+}
+
+} // namespace layers
+} // namespace mozilla