LCOV - code coverage report
Current view: top level - gfx/layers/apz/util - APZCCallbackHelper.cpp (source / functions) Hit Total Coverage
Test: output.info Lines: 131 397 33.0 %
Date: 2017-07-14 16:53:18 Functions: 17 41 41.5 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
       2             : /* This Source Code Form is subject to the terms of the Mozilla Public
       3             :  * License, v. 2.0. If a copy of the MPL was not distributed with this
       4             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
       5             : 
       6             : #include "APZCCallbackHelper.h"
       7             : 
       8             : #include "TouchActionHelper.h"
       9             : #include "gfxPlatform.h" // For gfxPlatform::UseTiling
      10             : #include "gfxPrefs.h"
      11             : #include "LayersLogging.h"  // For Stringify
      12             : #include "mozilla/dom/Element.h"
      13             : #include "mozilla/dom/TabParent.h"
      14             : #include "mozilla/IntegerPrintfMacros.h"
      15             : #include "mozilla/layers/LayerTransactionChild.h"
      16             : #include "mozilla/layers/ShadowLayers.h"
      17             : #include "mozilla/layers/WebRenderLayerManager.h"
      18             : #include "mozilla/layers/WebRenderBridgeChild.h"
      19             : #include "mozilla/TouchEvents.h"
      20             : #include "nsContentUtils.h"
      21             : #include "nsContainerFrame.h"
      22             : #include "nsIScrollableFrame.h"
      23             : #include "nsLayoutUtils.h"
      24             : #include "nsIInterfaceRequestorUtils.h"
      25             : #include "nsIContent.h"
      26             : #include "nsIDocument.h"
      27             : #include "nsIDOMWindow.h"
      28             : #include "nsIDOMWindowUtils.h"
      29             : #include "nsRefreshDriver.h"
      30             : #include "nsString.h"
      31             : #include "nsView.h"
      32             : #include "Layers.h"
      33             : 
      34             : // #define APZCCH_LOGGING 1
      35             : #ifdef APZCCH_LOGGING
      36             : #define APZCCH_LOG(...) printf_stderr("APZCCH: " __VA_ARGS__)
      37             : #else
      38             : #define APZCCH_LOG(...)
      39             : #endif
      40             : 
      41             : namespace mozilla {
      42             : namespace layers {
      43             : 
      44             : using dom::TabParent;
      45             : 
      46             : uint64_t APZCCallbackHelper::sLastTargetAPZCNotificationInputBlock = uint64_t(-1);
      47             : 
      48             : void
      49           0 : APZCCallbackHelper::AdjustDisplayPortForScrollDelta(
      50             :     mozilla::layers::FrameMetrics& aFrameMetrics,
      51             :     const CSSPoint& aActualScrollOffset)
      52             : {
      53             :   // Correct the display-port by the difference between the requested scroll
      54             :   // offset and the resulting scroll offset after setting the requested value.
      55             :   ScreenPoint shift =
      56           0 :       (aFrameMetrics.GetScrollOffset() - aActualScrollOffset) *
      57           0 :       aFrameMetrics.DisplayportPixelsPerCSSPixel();
      58           0 :   ScreenMargin margins = aFrameMetrics.GetDisplayPortMargins();
      59           0 :   margins.left -= shift.x;
      60           0 :   margins.right += shift.x;
      61           0 :   margins.top -= shift.y;
      62           0 :   margins.bottom += shift.y;
      63           0 :   aFrameMetrics.SetDisplayPortMargins(margins);
      64           0 : }
      65             : 
      66             : static void
      67           2 : RecenterDisplayPort(mozilla::layers::FrameMetrics& aFrameMetrics)
      68             : {
      69           2 :   ScreenMargin margins = aFrameMetrics.GetDisplayPortMargins();
      70           2 :   margins.right = margins.left = margins.LeftRight() / 2;
      71           2 :   margins.top = margins.bottom = margins.TopBottom() / 2;
      72           2 :   aFrameMetrics.SetDisplayPortMargins(margins);
      73           2 : }
      74             : 
      75             : static CSSPoint
      76           2 : ScrollFrameTo(nsIScrollableFrame* aFrame, const FrameMetrics& aMetrics, bool& aSuccessOut)
      77             : {
      78           2 :   aSuccessOut = false;
      79           2 :   CSSPoint targetScrollPosition = aMetrics.GetScrollOffset();
      80             : 
      81           2 :   if (!aFrame) {
      82           2 :     return targetScrollPosition;
      83             :   }
      84             : 
      85           0 :   CSSPoint geckoScrollPosition = CSSPoint::FromAppUnits(aFrame->GetScrollPosition());
      86             : 
      87             :   // If the repaint request was triggered due to a previous main-thread scroll
      88             :   // offset update sent to the APZ, then we don't need to do another scroll here
      89             :   // and we can just return.
      90           0 :   if (!aMetrics.GetScrollOffsetUpdated()) {
      91           0 :     return geckoScrollPosition;
      92             :   }
      93             : 
      94             :   // If the frame is overflow:hidden on a particular axis, we don't want to allow
      95             :   // user-driven scroll on that axis. Simply set the scroll position on that axis
      96             :   // to whatever it already is. Note that this will leave the APZ's async scroll
      97             :   // position out of sync with the gecko scroll position, but APZ can deal with that
      98             :   // (by design). Note also that when we run into this case, even if both axes
      99             :   // have overflow:hidden, we want to set aSuccessOut to true, so that the displayport
     100             :   // follows the async scroll position rather than the gecko scroll position.
     101           0 :   if (aFrame->GetScrollbarStyles().mVertical == NS_STYLE_OVERFLOW_HIDDEN) {
     102           0 :     targetScrollPosition.y = geckoScrollPosition.y;
     103             :   }
     104           0 :   if (aFrame->GetScrollbarStyles().mHorizontal == NS_STYLE_OVERFLOW_HIDDEN) {
     105           0 :     targetScrollPosition.x = geckoScrollPosition.x;
     106             :   }
     107             : 
     108             :   // If the scrollable frame is currently in the middle of an async or smooth
     109             :   // scroll then we don't want to interrupt it (see bug 961280).
     110             :   // Also if the scrollable frame got a scroll request from a higher priority origin
     111             :   // since the last layers update, then we don't want to push our scroll request
     112             :   // because we'll clobber that one, which is bad.
     113           0 :   bool scrollInProgress = APZCCallbackHelper::IsScrollInProgress(aFrame);
     114           0 :   if (!scrollInProgress) {
     115           0 :     aFrame->ScrollToCSSPixelsApproximate(targetScrollPosition, nsGkAtoms::apz);
     116           0 :     geckoScrollPosition = CSSPoint::FromAppUnits(aFrame->GetScrollPosition());
     117           0 :     aSuccessOut = true;
     118             :   }
     119             :   // Return the final scroll position after setting it so that anything that relies
     120             :   // on it can have an accurate value. Note that even if we set it above re-querying it
     121             :   // is a good idea because it may have gotten clamped or rounded.
     122           0 :   return geckoScrollPosition;
     123             : }
     124             : 
     125             : /**
     126             :  * Scroll the scroll frame associated with |aContent| to the scroll position
     127             :  * requested in |aMetrics|.
     128             :  * The scroll offset in |aMetrics| is updated to reflect the actual scroll
     129             :  * position.
     130             :  * The displayport stored in |aMetrics| and the callback-transform stored on
     131             :  * the content are updated to reflect any difference between the requested
     132             :  * and actual scroll positions.
     133             :  */
     134             : static void
     135           2 : ScrollFrame(nsIContent* aContent,
     136             :             FrameMetrics& aMetrics)
     137             : {
     138             :   // Scroll the window to the desired spot
     139           2 :   nsIScrollableFrame* sf = nsLayoutUtils::FindScrollableFrameFor(aMetrics.GetScrollId());
     140           2 :   if (sf) {
     141           0 :     sf->ResetScrollInfoIfGeneration(aMetrics.GetScrollGeneration());
     142           0 :     sf->SetScrollableByAPZ(!aMetrics.IsScrollInfoLayer());
     143             :   }
     144           2 :   bool scrollUpdated = false;
     145           2 :   CSSPoint apzScrollOffset = aMetrics.GetScrollOffset();
     146           2 :   CSSPoint actualScrollOffset = ScrollFrameTo(sf, aMetrics, scrollUpdated);
     147             : 
     148           2 :   if (scrollUpdated) {
     149           0 :     if (aMetrics.IsScrollInfoLayer()) {
     150             :       // In cases where the APZ scroll offset is different from the content scroll
     151             :       // offset, we want to interpret the margins as relative to the APZ scroll
     152             :       // offset except when the frame is not scrollable by APZ. Therefore, if the
     153             :       // layer is a scroll info layer, we leave the margins as-is and they will
     154             :       // be interpreted as relative to the content scroll offset.
     155           0 :       if (nsIFrame* frame = aContent->GetPrimaryFrame()) {
     156           0 :         frame->SchedulePaint();
     157             :       }
     158             :     } else {
     159             :       // Correct the display port due to the difference between mScrollOffset and the
     160             :       // actual scroll offset.
     161           0 :       APZCCallbackHelper::AdjustDisplayPortForScrollDelta(aMetrics, actualScrollOffset);
     162             :     }
     163             :   } else {
     164             :     // For whatever reason we couldn't update the scroll offset on the scroll frame,
     165             :     // which means the data APZ used for its displayport calculation is stale. Fall
     166             :     // back to a sane default behaviour. Note that we don't tile-align the recentered
     167             :     // displayport because tile-alignment depends on the scroll position, and the
     168             :     // scroll position here is out of our control. See bug 966507 comment 21 for a
     169             :     // more detailed explanation.
     170           2 :     RecenterDisplayPort(aMetrics);
     171             :   }
     172             : 
     173           2 :   aMetrics.SetScrollOffset(actualScrollOffset);
     174             : 
     175             :   // APZ transforms inputs assuming we applied the exact scroll offset it
     176             :   // requested (|apzScrollOffset|). Since we may not have, record the difference
     177             :   // between what APZ asked for and what we actually applied, and apply it to
     178             :   // input events to compensate.
     179             :   // Note that if the main-thread had a change in its scroll position, we don't
     180             :   // want to record that difference here, because it can be large and throw off
     181             :   // input events by a large amount. It is also going to be transient, because
     182             :   // any main-thread scroll position change will be synced to APZ and we will
     183             :   // get another repaint request when APZ confirms. In the interval while this
     184             :   // is happening we can just leave the callback transform as it was.
     185             :   bool mainThreadScrollChanged =
     186           2 :     sf && sf->CurrentScrollGeneration() != aMetrics.GetScrollGeneration() && nsLayoutUtils::CanScrollOriginClobberApz(sf->LastScrollOrigin());
     187           2 :   if (aContent && !mainThreadScrollChanged) {
     188           2 :     CSSPoint scrollDelta = apzScrollOffset - actualScrollOffset;
     189           4 :     aContent->SetProperty(nsGkAtoms::apzCallbackTransform, new CSSPoint(scrollDelta),
     190           4 :                           nsINode::DeleteProperty<CSSPoint>);
     191             :   }
     192           2 : }
     193             : 
     194             : static void
     195           2 : SetDisplayPortMargins(nsIPresShell* aPresShell,
     196             :                       nsIContent* aContent,
     197             :                       const FrameMetrics& aMetrics)
     198             : {
     199           2 :   if (!aContent) {
     200           0 :     return;
     201             :   }
     202             : 
     203           2 :   bool hadDisplayPort = nsLayoutUtils::HasDisplayPort(aContent);
     204           2 :   ScreenMargin margins = aMetrics.GetDisplayPortMargins();
     205           2 :   nsLayoutUtils::SetDisplayPortMargins(aContent, aPresShell, margins, 0);
     206           2 :   if (!hadDisplayPort) {
     207           0 :     nsLayoutUtils::SetZeroMarginDisplayPortOnAsyncScrollableAncestors(
     208           0 :         aContent->GetPrimaryFrame(), nsLayoutUtils::RepaintMode::Repaint);
     209             :   }
     210             : 
     211           2 :   CSSRect baseCSS = aMetrics.CalculateCompositedRectInCssPixels();
     212             :   nsRect base(0, 0,
     213           2 :               baseCSS.width * nsPresContext::AppUnitsPerCSSPixel(),
     214           6 :               baseCSS.height * nsPresContext::AppUnitsPerCSSPixel());
     215           2 :   nsLayoutUtils::SetDisplayPortBaseIfNotSet(aContent, base);
     216             : }
     217             : 
     218             : static already_AddRefed<nsIPresShell>
     219           5 : GetPresShell(const nsIContent* aContent)
     220             : {
     221          10 :   nsCOMPtr<nsIPresShell> result;
     222           5 :   if (nsIDocument* doc = aContent->GetComposedDoc()) {
     223           5 :     result = doc->GetShell();
     224             :   }
     225          10 :   return result.forget();
     226             : }
     227             : 
     228             : static void
     229           2 : SetPaintRequestTime(nsIContent* aContent, const TimeStamp& aPaintRequestTime)
     230             : {
     231           4 :   aContent->SetProperty(nsGkAtoms::paintRequestTime,
     232           2 :                         new TimeStamp(aPaintRequestTime),
     233           4 :                         nsINode::DeleteProperty<TimeStamp>);
     234           2 : }
     235             : 
     236             : void
     237           0 : APZCCallbackHelper::UpdateRootFrame(FrameMetrics& aMetrics)
     238             : {
     239           0 :   if (aMetrics.GetScrollId() == FrameMetrics::NULL_SCROLL_ID) {
     240           0 :     return;
     241             :   }
     242           0 :   nsIContent* content = nsLayoutUtils::FindContentFor(aMetrics.GetScrollId());
     243           0 :   if (!content) {
     244           0 :     return;
     245             :   }
     246             : 
     247           0 :   nsCOMPtr<nsIPresShell> shell = GetPresShell(content);
     248           0 :   if (!shell || aMetrics.GetPresShellId() != shell->GetPresShellId()) {
     249           0 :     return;
     250             :   }
     251             : 
     252           0 :   MOZ_ASSERT(aMetrics.GetUseDisplayPortMargins());
     253             : 
     254           0 :   if (gfxPrefs::APZAllowZooming()) {
     255             :     // If zooming is disabled then we don't really want to let APZ fiddle
     256             :     // with these things. In theory setting the resolution here should be a
     257             :     // no-op, but setting the SPCSPS is bad because it can cause a stale value
     258             :     // to be returned by window.innerWidth/innerHeight (see bug 1187792).
     259             : 
     260           0 :     float presShellResolution = shell->GetResolution();
     261             : 
     262             :     // If the pres shell resolution has changed on the content side side
     263             :     // the time this repaint request was fired, consider this request out of date
     264             :     // and drop it; setting a zoom based on the out-of-date resolution can have
     265             :     // the effect of getting us stuck with the stale resolution.
     266           0 :     if (!FuzzyEqualsMultiplicative(presShellResolution, aMetrics.GetPresShellResolution())) {
     267           0 :       return;
     268             :     }
     269             : 
     270             :     // The pres shell resolution is updated by the the async zoom since the
     271             :     // last paint.
     272           0 :     presShellResolution = aMetrics.GetPresShellResolution()
     273           0 :                         * aMetrics.GetAsyncZoom().scale;
     274           0 :     shell->SetResolutionAndScaleTo(presShellResolution);
     275             :   }
     276             : 
     277             :   // Do this as late as possible since scrolling can flush layout. It also
     278             :   // adjusts the display port margins, so do it before we set those.
     279           0 :   ScrollFrame(content, aMetrics);
     280             : 
     281           0 :   SetDisplayPortMargins(shell, content, aMetrics);
     282           0 :   SetPaintRequestTime(content, aMetrics.GetPaintRequestTime());
     283             : }
     284             : 
     285             : void
     286           2 : APZCCallbackHelper::UpdateSubFrame(FrameMetrics& aMetrics)
     287             : {
     288           2 :   if (aMetrics.GetScrollId() == FrameMetrics::NULL_SCROLL_ID) {
     289           0 :     return;
     290             :   }
     291           2 :   nsIContent* content = nsLayoutUtils::FindContentFor(aMetrics.GetScrollId());
     292           2 :   if (!content) {
     293           0 :     return;
     294             :   }
     295             : 
     296           2 :   MOZ_ASSERT(aMetrics.GetUseDisplayPortMargins());
     297             : 
     298             :   // We don't currently support zooming for subframes, so nothing extra
     299             :   // needs to be done beyond the tasks common to this and UpdateRootFrame.
     300           2 :   ScrollFrame(content, aMetrics);
     301           4 :   if (nsCOMPtr<nsIPresShell> shell = GetPresShell(content)) {
     302           2 :     SetDisplayPortMargins(shell, content, aMetrics);
     303             :   }
     304           2 :   SetPaintRequestTime(content, aMetrics.GetPaintRequestTime());
     305             : }
     306             : 
     307             : bool
     308           3 : APZCCallbackHelper::GetOrCreateScrollIdentifiers(nsIContent* aContent,
     309             :                                                  uint32_t* aPresShellIdOut,
     310             :                                                  FrameMetrics::ViewID* aViewIdOut)
     311             : {
     312           3 :     if (!aContent) {
     313           0 :       return false;
     314             :     }
     315           3 :     *aViewIdOut = nsLayoutUtils::FindOrCreateIDFor(aContent);
     316           3 :     if (nsCOMPtr<nsIPresShell> shell = GetPresShell(aContent)) {
     317           3 :       *aPresShellIdOut = shell->GetPresShellId();
     318           3 :       return true;
     319             :     }
     320           0 :     return false;
     321             : }
     322             : 
     323             : void
     324           2 : APZCCallbackHelper::InitializeRootDisplayport(nsIPresShell* aPresShell)
     325             : {
     326             :   // Create a view-id and set a zero-margin displayport for the root element
     327             :   // of the root document in the chrome process. This ensures that the scroll
     328             :   // frame for this element gets an APZC, which in turn ensures that all content
     329             :   // in the chrome processes is covered by an APZC.
     330             :   // The displayport is zero-margin because this element is generally not
     331             :   // actually scrollable (if it is, APZC will set proper margins when it's
     332             :   // scrolled).
     333           2 :   if (!aPresShell) {
     334           0 :     return;
     335             :   }
     336             : 
     337           2 :   MOZ_ASSERT(aPresShell->GetDocument());
     338           2 :   nsIContent* content = aPresShell->GetDocument()->GetDocumentElement();
     339           2 :   if (!content) {
     340           0 :     return;
     341             :   }
     342             : 
     343             :   uint32_t presShellId;
     344             :   FrameMetrics::ViewID viewId;
     345           2 :   if (APZCCallbackHelper::GetOrCreateScrollIdentifiers(content, &presShellId, &viewId)) {
     346           2 :     nsPresContext* pc = aPresShell->GetPresContext();
     347             :     // This code is only correct for root content or toplevel documents.
     348           2 :     MOZ_ASSERT(!pc || pc->IsRootContentDocument() || !pc->GetParentPresContext());
     349           2 :     nsIFrame* frame = aPresShell->GetRootScrollFrame();
     350           2 :     if (!frame) {
     351           1 :       frame = aPresShell->GetRootFrame();
     352             :     }
     353           4 :     nsRect baseRect;
     354           2 :     if (frame) {
     355           2 :       baseRect =
     356           4 :         nsRect(nsPoint(0, 0), nsLayoutUtils::CalculateCompositionSizeForFrame(frame));
     357           0 :     } else if (pc) {
     358           0 :       baseRect = nsRect(nsPoint(0, 0), pc->GetVisibleArea().Size());
     359             :     }
     360           2 :     nsLayoutUtils::SetDisplayPortBaseIfNotSet(content, baseRect);
     361             :     // Note that we also set the base rect that goes with these margins in
     362             :     // nsRootBoxFrame::BuildDisplayList.
     363           4 :     nsLayoutUtils::SetDisplayPortMargins(content, aPresShell, ScreenMargin(), 0,
     364           2 :         nsLayoutUtils::RepaintMode::DoNotRepaint);
     365           2 :     nsLayoutUtils::SetZeroMarginDisplayPortOnAsyncScrollableAncestors(
     366           2 :         content->GetPrimaryFrame(), nsLayoutUtils::RepaintMode::DoNotRepaint);
     367             :   }
     368             : }
     369             : 
     370             : nsPresContext*
     371          71 : APZCCallbackHelper::GetPresContextForContent(nsIContent* aContent)
     372             : {
     373          71 :   nsIDocument* doc = aContent->GetComposedDoc();
     374          71 :   if (!doc) {
     375           0 :       return nullptr;
     376             :   }
     377          71 :   nsIPresShell* shell = doc->GetShell();
     378          71 :   if (!shell) {
     379           0 :       return nullptr;
     380             :   }
     381          71 :   return shell->GetPresContext();
     382             : }
     383             : 
     384             : nsIPresShell*
     385          71 : APZCCallbackHelper::GetRootContentDocumentPresShellForContent(nsIContent* aContent)
     386             : {
     387          71 :     nsPresContext* context = GetPresContextForContent(aContent);
     388          71 :     if (!context) {
     389           0 :         return nullptr;
     390             :     }
     391          71 :     context = context->GetToplevelContentDocumentPresContext();
     392          71 :     if (!context) {
     393          58 :         return nullptr;
     394             :     }
     395          13 :     return context->PresShell();
     396             : }
     397             : 
     398             : static nsIPresShell*
     399           5 : GetRootDocumentPresShell(nsIContent* aContent)
     400             : {
     401           5 :     nsIDocument* doc = aContent->GetComposedDoc();
     402           5 :     if (!doc) {
     403           0 :         return nullptr;
     404             :     }
     405           5 :     nsIPresShell* shell = doc->GetShell();
     406           5 :     if (!shell) {
     407           0 :         return nullptr;
     408             :     }
     409           5 :     nsPresContext* context = shell->GetPresContext();
     410           5 :     if (!context) {
     411           0 :         return nullptr;
     412             :     }
     413           5 :     context = context->GetRootPresContext();
     414           5 :     if (!context) {
     415           0 :         return nullptr;
     416             :     }
     417           5 :     return context->PresShell();
     418             : }
     419             : 
     420             : CSSPoint
     421          11 : APZCCallbackHelper::ApplyCallbackTransform(const CSSPoint& aInput,
     422             :                                            const ScrollableLayerGuid& aGuid)
     423             : {
     424          11 :     CSSPoint input = aInput;
     425          11 :     if (aGuid.mScrollId == FrameMetrics::NULL_SCROLL_ID) {
     426           6 :         return input;
     427             :     }
     428          10 :     nsCOMPtr<nsIContent> content = nsLayoutUtils::FindContentFor(aGuid.mScrollId);
     429           5 :     if (!content) {
     430           0 :         return input;
     431             :     }
     432             : 
     433             :     // First, scale inversely by the root content document's pres shell
     434             :     // resolution to cancel the scale-to-resolution transform that the
     435             :     // compositor adds to the layer with the pres shell resolution. The points
     436             :     // sent to Gecko by APZ don't have this transform unapplied (unlike other
     437             :     // compositor-side transforms) because APZ doesn't know about it.
     438           5 :     if (nsIPresShell* shell = GetRootDocumentPresShell(content)) {
     439           5 :         input = input / shell->GetResolution();
     440             :     }
     441             : 
     442             :     // This represents any resolution on the Root Content Document (RCD)
     443             :     // that's not on the Root Document (RD). That is, on platforms where
     444             :     // RCD == RD, it's 1, and on platforms where RCD != RD, it's the RCD
     445             :     // resolution. 'input' has this resolution applied, but the scroll
     446             :     // delta retrieved below do not, so we need to apply them to the
     447             :     // delta before adding the delta to 'input'. (Technically, deltas
     448             :     // from scroll frames outside the RCD would already have this
     449             :     // resolution applied, but we don't have such scroll frames in
     450             :     // practice.)
     451           5 :     float nonRootResolution = 1.0f;
     452           5 :     if (nsIPresShell* shell = GetRootContentDocumentPresShellForContent(content)) {
     453           0 :       nonRootResolution = shell->GetCumulativeNonRootScaleResolution();
     454             :     }
     455             :     // Now apply the callback-transform. This is only approximately correct,
     456             :     // see the comment on GetCumulativeApzCallbackTransform for details.
     457           5 :     CSSPoint transform = nsLayoutUtils::GetCumulativeApzCallbackTransform(content->GetPrimaryFrame());
     458           5 :     return input + transform * nonRootResolution;
     459             : }
     460             : 
     461             : LayoutDeviceIntPoint
     462          11 : APZCCallbackHelper::ApplyCallbackTransform(const LayoutDeviceIntPoint& aPoint,
     463             :                                            const ScrollableLayerGuid& aGuid,
     464             :                                            const CSSToLayoutDeviceScale& aScale)
     465             : {
     466          11 :     LayoutDevicePoint point = LayoutDevicePoint(aPoint.x, aPoint.y);
     467          11 :     point = ApplyCallbackTransform(point / aScale, aGuid) * aScale;
     468          11 :     return LayoutDeviceIntPoint::Round(point);
     469             : }
     470             : 
     471             : void
     472          11 : APZCCallbackHelper::ApplyCallbackTransform(WidgetEvent& aEvent,
     473             :                                            const ScrollableLayerGuid& aGuid,
     474             :                                            const CSSToLayoutDeviceScale& aScale)
     475             : {
     476          11 :   if (aEvent.AsTouchEvent()) {
     477           0 :     WidgetTouchEvent& event = *(aEvent.AsTouchEvent());
     478           0 :     for (size_t i = 0; i < event.mTouches.Length(); i++) {
     479           0 :       event.mTouches[i]->mRefPoint = ApplyCallbackTransform(
     480           0 :           event.mTouches[i]->mRefPoint, aGuid, aScale);
     481             :     }
     482             :   } else {
     483          11 :     aEvent.mRefPoint = ApplyCallbackTransform(aEvent.mRefPoint, aGuid, aScale);
     484             :   }
     485          11 : }
     486             : 
     487             : nsEventStatus
     488           6 : APZCCallbackHelper::DispatchWidgetEvent(WidgetGUIEvent& aEvent)
     489             : {
     490           6 :   nsEventStatus status = nsEventStatus_eConsumeNoDefault;
     491           6 :   if (aEvent.mWidget) {
     492           6 :     aEvent.mWidget->DispatchEvent(&aEvent, status);
     493             :   }
     494           6 :   return status;
     495             : }
     496             : 
     497             : nsEventStatus
     498           0 : APZCCallbackHelper::DispatchSynthesizedMouseEvent(EventMessage aMsg,
     499             :                                                   uint64_t aTime,
     500             :                                                   const LayoutDevicePoint& aRefPoint,
     501             :                                                   Modifiers aModifiers,
     502             :                                                   int32_t aClickCount,
     503             :                                                   nsIWidget* aWidget)
     504             : {
     505           0 :   MOZ_ASSERT(aMsg == eMouseMove || aMsg == eMouseDown ||
     506             :              aMsg == eMouseUp || aMsg == eMouseLongTap);
     507             : 
     508             :   WidgetMouseEvent event(true, aMsg, aWidget,
     509           0 :                          WidgetMouseEvent::eReal, WidgetMouseEvent::eNormal);
     510           0 :   event.mRefPoint = LayoutDeviceIntPoint::Truncate(aRefPoint.x, aRefPoint.y);
     511           0 :   event.mTime = aTime;
     512           0 :   event.button = WidgetMouseEvent::eLeftButton;
     513           0 :   event.inputSource = nsIDOMMouseEvent::MOZ_SOURCE_TOUCH;
     514           0 :   if (aMsg == eMouseLongTap) {
     515           0 :     event.mFlags.mOnlyChromeDispatch = true;
     516             :   }
     517           0 :   event.mIgnoreRootScrollFrame = true;
     518           0 :   if (aMsg != eMouseMove) {
     519           0 :     event.mClickCount = aClickCount;
     520             :   }
     521           0 :   event.mModifiers = aModifiers;
     522             :   // Real touch events will generate corresponding pointer events. We set
     523             :   // convertToPointer to false to prevent the synthesized mouse events generate
     524             :   // pointer events again.
     525           0 :   event.convertToPointer = false;
     526           0 :   return DispatchWidgetEvent(event);
     527             : }
     528             : 
     529             : bool
     530           0 : APZCCallbackHelper::DispatchMouseEvent(const nsCOMPtr<nsIPresShell>& aPresShell,
     531             :                                        const nsString& aType,
     532             :                                        const CSSPoint& aPoint,
     533             :                                        int32_t aButton,
     534             :                                        int32_t aClickCount,
     535             :                                        int32_t aModifiers,
     536             :                                        bool aIgnoreRootScrollFrame,
     537             :                                        unsigned short aInputSourceArg,
     538             :                                        uint32_t aPointerId)
     539             : {
     540           0 :   NS_ENSURE_TRUE(aPresShell, true);
     541             : 
     542           0 :   bool defaultPrevented = false;
     543           0 :   nsContentUtils::SendMouseEvent(aPresShell, aType, aPoint.x, aPoint.y,
     544             :       aButton, nsIDOMWindowUtils::MOUSE_BUTTONS_NOT_SPECIFIED, aClickCount,
     545             :       aModifiers, aIgnoreRootScrollFrame, 0, aInputSourceArg, aPointerId, false,
     546           0 :       &defaultPrevented, false, /* aIsWidgetEventSynthesized = */ false);
     547           0 :   return defaultPrevented;
     548             : }
     549             : 
     550             : 
     551             : void
     552           0 : APZCCallbackHelper::FireSingleTapEvent(const LayoutDevicePoint& aPoint,
     553             :                                        Modifiers aModifiers,
     554             :                                        int32_t aClickCount,
     555             :                                        nsIWidget* aWidget)
     556             : {
     557           0 :   if (aWidget->Destroyed()) {
     558           0 :     return;
     559             :   }
     560             :   APZCCH_LOG("Dispatching single-tap component events to %s\n",
     561             :     Stringify(aPoint).c_str());
     562           0 :   int time = 0;
     563           0 :   DispatchSynthesizedMouseEvent(eMouseMove, time, aPoint, aModifiers, aClickCount, aWidget);
     564           0 :   DispatchSynthesizedMouseEvent(eMouseDown, time, aPoint, aModifiers, aClickCount, aWidget);
     565           0 :   DispatchSynthesizedMouseEvent(eMouseUp, time, aPoint, aModifiers, aClickCount, aWidget);
     566             : }
     567             : 
     568             : static dom::Element*
     569           0 : GetDisplayportElementFor(nsIScrollableFrame* aScrollableFrame)
     570             : {
     571           0 :   if (!aScrollableFrame) {
     572           0 :     return nullptr;
     573             :   }
     574           0 :   nsIFrame* scrolledFrame = aScrollableFrame->GetScrolledFrame();
     575           0 :   if (!scrolledFrame) {
     576           0 :     return nullptr;
     577             :   }
     578             :   // |scrolledFrame| should at this point be the root content frame of the
     579             :   // nearest ancestor scrollable frame. The element corresponding to this
     580             :   // frame should be the one with the displayport set on it, so find that
     581             :   // element and return it.
     582           0 :   nsIContent* content = scrolledFrame->GetContent();
     583           0 :   MOZ_ASSERT(content->IsElement()); // roc says this must be true
     584           0 :   return content->AsElement();
     585             : }
     586             : 
     587             : 
     588             : static dom::Element*
     589           0 : GetRootDocumentElementFor(nsIWidget* aWidget)
     590             : {
     591             :   // This returns the root element that ChromeProcessController sets the
     592             :   // displayport on during initialization.
     593           0 :   if (nsView* view = nsView::GetViewFor(aWidget)) {
     594           0 :     if (nsIPresShell* shell = view->GetPresShell()) {
     595           0 :       MOZ_ASSERT(shell->GetDocument());
     596           0 :       return shell->GetDocument()->GetDocumentElement();
     597             :     }
     598             :   }
     599           0 :   return nullptr;
     600             : }
     601             : 
     602             : static nsIFrame*
     603           0 : UpdateRootFrameForTouchTargetDocument(nsIFrame* aRootFrame)
     604             : {
     605             : #if defined(MOZ_WIDGET_ANDROID)
     606             :   // Re-target so that the hit test is performed relative to the frame for the
     607             :   // Root Content Document instead of the Root Document which are different in
     608             :   // Android. See bug 1229752 comment 16 for an explanation of why this is necessary.
     609             :   if (nsIDocument* doc = aRootFrame->PresContext()->PresShell()->GetPrimaryContentDocument()) {
     610             :     if (nsIPresShell* shell = doc->GetShell()) {
     611             :       if (nsIFrame* frame = shell->GetRootFrame()) {
     612             :         return frame;
     613             :       }
     614             :     }
     615             :   }
     616             : #endif
     617           0 :   return aRootFrame;
     618             : }
     619             : 
     620             : // Determine the scrollable target frame for the given point and add it to
     621             : // the target list. If the frame doesn't have a displayport, set one.
     622             : // Return whether or not a displayport was set.
     623             : static bool
     624           0 : PrepareForSetTargetAPZCNotification(nsIWidget* aWidget,
     625             :                                     const ScrollableLayerGuid& aGuid,
     626             :                                     nsIFrame* aRootFrame,
     627             :                                     const LayoutDeviceIntPoint& aRefPoint,
     628             :                                     nsTArray<ScrollableLayerGuid>* aTargets)
     629             : {
     630           0 :   ScrollableLayerGuid guid(aGuid.mLayersId, 0, FrameMetrics::NULL_SCROLL_ID);
     631             :   nsPoint point =
     632           0 :     nsLayoutUtils::GetEventCoordinatesRelativeTo(aWidget, aRefPoint, aRootFrame);
     633           0 :   uint32_t flags = 0;
     634             : #ifdef MOZ_WIDGET_ANDROID
     635             :   // On Android, we need IGNORE_ROOT_SCROLL_FRAME for correct hit testing
     636             :   // when zoomed out. On desktop, don't use it because it interferes with
     637             :   // hit testing for some purposes such as scrollbar dragging.
     638             :   flags = nsLayoutUtils::IGNORE_ROOT_SCROLL_FRAME;
     639             : #endif
     640             :   nsIFrame* target =
     641           0 :     nsLayoutUtils::GetFrameForPoint(aRootFrame, point, flags);
     642             :   nsIScrollableFrame* scrollAncestor = target
     643           0 :     ? nsLayoutUtils::GetAsyncScrollableAncestorFrame(target)
     644           0 :     : aRootFrame->PresContext()->PresShell()->GetRootScrollFrameAsScrollable();
     645             : 
     646             :   // Assuming that if there's no scrollAncestor, there's already a displayPort.
     647             :   nsCOMPtr<dom::Element> dpElement = scrollAncestor
     648             :     ? GetDisplayportElementFor(scrollAncestor)
     649           0 :     : GetRootDocumentElementFor(aWidget);
     650             : 
     651             : #ifdef APZCCH_LOGGING
     652             :   nsAutoString dpElementDesc;
     653             :   if (dpElement) {
     654             :     dpElement->Describe(dpElementDesc);
     655             :   }
     656             :   APZCCH_LOG("For event at %s found scrollable element %p (%s)\n",
     657             :       Stringify(aRefPoint).c_str(), dpElement.get(),
     658             :       NS_LossyConvertUTF16toASCII(dpElementDesc).get());
     659             : #endif
     660             : 
     661             :   bool guidIsValid = APZCCallbackHelper::GetOrCreateScrollIdentifiers(
     662           0 :     dpElement, &(guid.mPresShellId), &(guid.mScrollId));
     663           0 :   aTargets->AppendElement(guid);
     664             : 
     665           0 :   if (!guidIsValid || nsLayoutUtils::HasDisplayPort(dpElement)) {
     666           0 :     return false;
     667             :   }
     668             : 
     669           0 :   if (!scrollAncestor) {
     670           0 :     MOZ_ASSERT(false);  // If you hit this, please file a bug with STR.
     671             : 
     672             :     // Attempt some sort of graceful handling based on a theory as to why we
     673             :     // reach this point...
     674             :     // If we get here, the document element is non-null, valid, but doesn't have
     675             :     // a displayport. It's possible that the init code in ChromeProcessController
     676             :     // failed for some reason, or the document element got swapped out at some
     677             :     // later time. In this case let's try to set a displayport on the document
     678             :     // element again and bail out on this operation.
     679             :     APZCCH_LOG("Widget %p's document element %p didn't have a displayport\n",
     680             :         aWidget, dpElement.get());
     681             :     APZCCallbackHelper::InitializeRootDisplayport(aRootFrame->PresContext()->PresShell());
     682             :     return false;
     683             :   }
     684             : 
     685             :   APZCCH_LOG("%p didn't have a displayport, so setting one...\n", dpElement.get());
     686             :   bool activated = nsLayoutUtils::CalculateAndSetDisplayPortMargins(
     687           0 :       scrollAncestor, nsLayoutUtils::RepaintMode::Repaint);
     688           0 :   if (!activated) {
     689           0 :     return false;
     690             :   }
     691             : 
     692           0 :   nsIFrame* frame = do_QueryFrame(scrollAncestor);
     693             :   nsLayoutUtils::SetZeroMarginDisplayPortOnAsyncScrollableAncestors(frame,
     694           0 :     nsLayoutUtils::RepaintMode::Repaint);
     695             : 
     696           0 :   return true;
     697             : }
     698             : 
     699             : static void
     700           0 : SendLayersDependentApzcTargetConfirmation(nsIPresShell* aShell, uint64_t aInputBlockId,
     701             :                                           const nsTArray<ScrollableLayerGuid>& aTargets)
     702             : {
     703           0 :   LayerManager* lm = aShell->GetLayerManager();
     704           0 :   if (!lm) {
     705           0 :     return;
     706             :   }
     707             : 
     708           0 :   if (WebRenderLayerManager* wrlm = lm->AsWebRenderLayerManager()) {
     709           0 :     if (WebRenderBridgeChild* wrbc = wrlm->WrBridge()) {
     710           0 :       wrbc->SendSetConfirmedTargetAPZC(aInputBlockId, aTargets);
     711             :     }
     712           0 :     return;
     713             :   }
     714             : 
     715           0 :   LayerTransactionChild* shadow = lm->AsShadowForwarder()->GetShadowManager();
     716           0 :   if (!shadow) {
     717           0 :     return;
     718             :   }
     719             : 
     720           0 :   shadow->SendSetConfirmedTargetAPZC(aInputBlockId, aTargets);
     721             : }
     722             : 
     723             : class DisplayportSetListener : public nsAPostRefreshObserver {
     724             : public:
     725           0 :   DisplayportSetListener(nsIPresShell* aPresShell,
     726             :                          const uint64_t& aInputBlockId,
     727             :                          const nsTArray<ScrollableLayerGuid>& aTargets)
     728           0 :     : mPresShell(aPresShell)
     729           0 :     , mInputBlockId(aInputBlockId)
     730           0 :     , mTargets(aTargets)
     731             :   {
     732           0 :   }
     733             : 
     734           0 :   virtual ~DisplayportSetListener()
     735           0 :   {
     736           0 :   }
     737             : 
     738           0 :   void DidRefresh() override {
     739           0 :     if (!mPresShell) {
     740           0 :       MOZ_ASSERT_UNREACHABLE("Post-refresh observer fired again after failed attempt at unregistering it");
     741             :       return;
     742             :     }
     743             : 
     744             :     APZCCH_LOG("Got refresh, sending target APZCs for input block %" PRIu64 "\n", mInputBlockId);
     745           0 :     SendLayersDependentApzcTargetConfirmation(mPresShell, mInputBlockId, Move(mTargets));
     746             : 
     747           0 :     if (!mPresShell->RemovePostRefreshObserver(this)) {
     748           0 :       MOZ_ASSERT_UNREACHABLE("Unable to unregister post-refresh observer! Leaking it instead of leaving garbage registered");
     749             :       // Graceful handling, just in case...
     750             :       mPresShell = nullptr;
     751             :       return;
     752             :     }
     753             : 
     754           0 :     delete this;
     755             :   }
     756             : 
     757             : private:
     758             :   RefPtr<nsIPresShell> mPresShell;
     759             :   uint64_t mInputBlockId;
     760             :   nsTArray<ScrollableLayerGuid> mTargets;
     761             : };
     762             : 
     763             : // Sends a SetTarget notification for APZC, given one or more previous
     764             : // calls to PrepareForAPZCSetTargetNotification().
     765             : static void
     766           0 : SendSetTargetAPZCNotificationHelper(nsIWidget* aWidget,
     767             :                                     nsIPresShell* aShell,
     768             :                                     const uint64_t& aInputBlockId,
     769             :                                     const nsTArray<ScrollableLayerGuid>& aTargets,
     770             :                                     bool aWaitForRefresh)
     771             : {
     772           0 :   bool waitForRefresh = aWaitForRefresh;
     773           0 :   if (waitForRefresh) {
     774             :     APZCCH_LOG("At least one target got a new displayport, need to wait for refresh\n");
     775           0 :     waitForRefresh = aShell->AddPostRefreshObserver(
     776           0 :       new DisplayportSetListener(aShell, aInputBlockId, Move(aTargets)));
     777             :   }
     778           0 :   if (!waitForRefresh) {
     779             :     APZCCH_LOG("Sending target APZCs for input block %" PRIu64 "\n", aInputBlockId);
     780           0 :     aWidget->SetConfirmedTargetAPZC(aInputBlockId, aTargets);
     781             :   } else {
     782             :     APZCCH_LOG("Successfully registered post-refresh observer\n");
     783             :   }
     784           0 : }
     785             : 
     786             : bool
     787           0 : APZCCallbackHelper::SendSetTargetAPZCNotification(nsIWidget* aWidget,
     788             :                                                   nsIDocument* aDocument,
     789             :                                                   const WidgetGUIEvent& aEvent,
     790             :                                                   const ScrollableLayerGuid& aGuid,
     791             :                                                   uint64_t aInputBlockId)
     792             : {
     793           0 :   if (!aWidget || !aDocument) {
     794           0 :     return false;
     795             :   }
     796           0 :   if (aInputBlockId == sLastTargetAPZCNotificationInputBlock) {
     797             :     // We have already confirmed the target APZC for a previous event of this
     798             :     // input block. If we activated a scroll frame for this input block,
     799             :     // sending another target APZC confirmation would be harmful, as it might
     800             :     // race the original confirmation (which needs to go through a layers
     801             :     // transaction).
     802             :     APZCCH_LOG("Not resending target APZC confirmation for input block %" PRIu64 "\n", aInputBlockId);
     803           0 :     return false;
     804             :   }
     805           0 :   sLastTargetAPZCNotificationInputBlock = aInputBlockId;
     806           0 :   if (nsIPresShell* shell = aDocument->GetShell()) {
     807           0 :     if (nsIFrame* rootFrame = shell->GetRootFrame()) {
     808           0 :       rootFrame = UpdateRootFrameForTouchTargetDocument(rootFrame);
     809             : 
     810           0 :       bool waitForRefresh = false;
     811           0 :       nsTArray<ScrollableLayerGuid> targets;
     812             : 
     813           0 :       if (const WidgetTouchEvent* touchEvent = aEvent.AsTouchEvent()) {
     814           0 :         for (size_t i = 0; i < touchEvent->mTouches.Length(); i++) {
     815           0 :           waitForRefresh |= PrepareForSetTargetAPZCNotification(aWidget, aGuid,
     816           0 :               rootFrame, touchEvent->mTouches[i]->mRefPoint, &targets);
     817             :         }
     818           0 :       } else if (const WidgetWheelEvent* wheelEvent = aEvent.AsWheelEvent()) {
     819           0 :         waitForRefresh = PrepareForSetTargetAPZCNotification(aWidget, aGuid,
     820           0 :             rootFrame, wheelEvent->mRefPoint, &targets);
     821           0 :       } else if (const WidgetMouseEvent* mouseEvent = aEvent.AsMouseEvent()) {
     822           0 :         waitForRefresh = PrepareForSetTargetAPZCNotification(aWidget, aGuid,
     823           0 :             rootFrame, mouseEvent->mRefPoint, &targets);
     824             :       }
     825             :       // TODO: Do other types of events need to be handled?
     826             : 
     827           0 :       if (!targets.IsEmpty()) {
     828           0 :         SendSetTargetAPZCNotificationHelper(
     829             :           aWidget,
     830             :           shell,
     831             :           aInputBlockId,
     832           0 :           Move(targets),
     833           0 :           waitForRefresh);
     834             :       }
     835             : 
     836           0 :       return waitForRefresh;
     837             :     }
     838             :   }
     839           0 :   return false;
     840             : }
     841             : 
     842             : void
     843           0 : APZCCallbackHelper::SendSetAllowedTouchBehaviorNotification(
     844             :         nsIWidget* aWidget,
     845             :         nsIDocument* aDocument,
     846             :         const WidgetTouchEvent& aEvent,
     847             :         uint64_t aInputBlockId,
     848             :         const SetAllowedTouchBehaviorCallback& aCallback)
     849             : {
     850           0 :   if (nsIPresShell* shell = aDocument->GetShell()) {
     851           0 :     if (nsIFrame* rootFrame = shell->GetRootFrame()) {
     852           0 :       rootFrame = UpdateRootFrameForTouchTargetDocument(rootFrame);
     853             : 
     854           0 :       nsTArray<TouchBehaviorFlags> flags;
     855           0 :       for (uint32_t i = 0; i < aEvent.mTouches.Length(); i++) {
     856             :         flags.AppendElement(
     857           0 :           TouchActionHelper::GetAllowedTouchBehavior(aWidget,
     858           0 :                 rootFrame, aEvent.mTouches[i]->mRefPoint));
     859             :       }
     860           0 :       aCallback(aInputBlockId, Move(flags));
     861             :     }
     862             :   }
     863           0 : }
     864             : 
     865             : void
     866           0 : APZCCallbackHelper::NotifyMozMouseScrollEvent(const FrameMetrics::ViewID& aScrollId, const nsString& aEvent)
     867             : {
     868           0 :   nsCOMPtr<nsIContent> targetContent = nsLayoutUtils::FindContentFor(aScrollId);
     869           0 :   if (!targetContent) {
     870           0 :     return;
     871             :   }
     872           0 :   nsCOMPtr<nsIDocument> ownerDoc = targetContent->OwnerDoc();
     873           0 :   if (!ownerDoc) {
     874           0 :     return;
     875             :   }
     876             : 
     877           0 :   nsContentUtils::DispatchTrustedEvent(
     878             :     ownerDoc, targetContent,
     879             :     aEvent,
     880           0 :     true, true);
     881             : }
     882             : 
     883             : void
     884           0 : APZCCallbackHelper::NotifyFlushComplete(nsIPresShell* aShell)
     885             : {
     886           0 :   MOZ_ASSERT(NS_IsMainThread());
     887             :   // In some cases, flushing the APZ state to the main thread doesn't actually
     888             :   // trigger a flush and repaint (this is an intentional optimization - the stuff
     889             :   // visible to the user is still correct). However, reftests update their
     890             :   // snapshot based on invalidation events that are emitted during paints,
     891             :   // so we ensure that we kick off a paint when an APZ flush is done. Note that
     892             :   // only chrome/testing code can trigger this behaviour.
     893           0 :   if (aShell && aShell->GetRootFrame()) {
     894           0 :     aShell->GetRootFrame()->SchedulePaint();
     895             :   }
     896             : 
     897           0 :   nsCOMPtr<nsIObserverService> observerService = mozilla::services::GetObserverService();
     898           0 :   MOZ_ASSERT(observerService);
     899           0 :   observerService->NotifyObservers(nullptr, "apz-repaints-flushed", nullptr);
     900           0 : }
     901             : 
     902             : static int32_t sActiveSuppressDisplayport = 0;
     903             : static bool sDisplayPortSuppressionRespected = true;
     904             : 
     905             : void
     906           0 : APZCCallbackHelper::SuppressDisplayport(const bool& aEnabled,
     907             :                                         const nsCOMPtr<nsIPresShell>& aShell)
     908             : {
     909           0 :   if (aEnabled) {
     910           0 :     sActiveSuppressDisplayport++;
     911             :   } else {
     912           0 :     bool isSuppressed = IsDisplayportSuppressed();
     913           0 :     sActiveSuppressDisplayport--;
     914           0 :     if (isSuppressed && !IsDisplayportSuppressed() &&
     915           0 :         aShell && aShell->GetRootFrame()) {
     916             :       // We unsuppressed the displayport, trigger a paint
     917           0 :       aShell->GetRootFrame()->SchedulePaint();
     918             :     }
     919             :   }
     920             : 
     921           0 :   MOZ_ASSERT(sActiveSuppressDisplayport >= 0);
     922           0 : }
     923             : 
     924             : void
     925           0 : APZCCallbackHelper::RespectDisplayPortSuppression(bool aEnabled,
     926             :                                                   const nsCOMPtr<nsIPresShell>& aShell)
     927             : {
     928           0 :   bool isSuppressed = IsDisplayportSuppressed();
     929           0 :   sDisplayPortSuppressionRespected = aEnabled;
     930           0 :   if (isSuppressed && !IsDisplayportSuppressed() &&
     931           0 :       aShell && aShell->GetRootFrame()) {
     932             :     // We unsuppressed the displayport, trigger a paint
     933           0 :     aShell->GetRootFrame()->SchedulePaint();
     934             :   }
     935           0 : }
     936             : 
     937             : bool
     938          78 : APZCCallbackHelper::IsDisplayportSuppressed()
     939             : {
     940             :   return sDisplayPortSuppressionRespected
     941          78 :       && sActiveSuppressDisplayport > 0;
     942             : }
     943             : 
     944             : /* static */ bool
     945           0 : APZCCallbackHelper::IsScrollInProgress(nsIScrollableFrame* aFrame)
     946             : {
     947           0 :   return aFrame->IsProcessingAsyncScroll()
     948           0 :          || nsLayoutUtils::CanScrollOriginClobberApz(aFrame->LastScrollOrigin())
     949           0 :          || aFrame->LastSmoothScrollOrigin();
     950             : }
     951             : 
     952             : /* static */ void
     953           0 : APZCCallbackHelper::NotifyAsyncScrollbarDragRejected(const FrameMetrics::ViewID& aScrollId)
     954             : {
     955           0 :   MOZ_ASSERT(NS_IsMainThread());
     956           0 :   if (nsIScrollableFrame* scrollFrame = nsLayoutUtils::FindScrollableFrameFor(aScrollId)) {
     957           0 :     scrollFrame->AsyncScrollbarDragRejected();
     958             :   }
     959           0 : }
     960             : 
     961             : /* static */ void
     962           0 : APZCCallbackHelper::NotifyPinchGesture(PinchGestureInput::PinchGestureType aType,
     963             :                                        LayoutDeviceCoord aSpanChange,
     964             :                                        Modifiers aModifiers,
     965             :                                        nsIWidget* aWidget)
     966             : {
     967             :   EventMessage msg;
     968           0 :   switch (aType) {
     969             :     case PinchGestureInput::PINCHGESTURE_START:
     970           0 :       msg = eMagnifyGestureStart;
     971           0 :       break;
     972             :     case PinchGestureInput::PINCHGESTURE_SCALE:
     973           0 :       msg = eMagnifyGestureUpdate;
     974           0 :       break;
     975             :     case PinchGestureInput::PINCHGESTURE_END:
     976           0 :       msg = eMagnifyGesture;
     977           0 :       break;
     978             :   }
     979             : 
     980           0 :   WidgetSimpleGestureEvent event(true, msg, aWidget);
     981           0 :   event.mDelta = aSpanChange;
     982           0 :   event.mModifiers = aModifiers;
     983           0 :   DispatchWidgetEvent(event);
     984           0 : }
     985             : 
     986             : } // namespace layers
     987             : } // namespace mozilla
     988             : 

Generated by: LCOV version 1.13