Bug 949132 - Use the FrameMetrics flag on the layers update to update APZC scroll offset instead of tracking it in widget code. r=Cwiiis

This commit is contained in:
Kartikaya Gupta 2013-12-16 12:04:46 -05:00
parent 330e915734
commit cede2efb3a
22 changed files with 17 additions and 294 deletions

View File

@ -34,7 +34,6 @@ var APZCObserver = {
window.addEventListener("SizeChanged", this, true);
Elements.tabList.addEventListener("TabSelect", this, true);
Elements.browsers.addEventListener("pageshow", this, true);
messageManager.addMessageListener("Browser:ContentScroll", this);
messageManager.addMessageListener("Content:ZoomToRect", this);
},
@ -49,7 +48,6 @@ var APZCObserver = {
window.removeEventListener("SizeChanged", this, true);
Elements.tabList.removeEventListener("TabSelect", this, true);
Elements.browsers.removeEventListener("pageshow", this, true);
messageManager.removeMessageListener("Browser:ContentScroll", this);
messageManager.removeMessageListener("Content:ZoomToRect", this);
},
@ -85,16 +83,6 @@ var APZCObserver = {
let json = aMessage.json;
let browser = aMessage.target;
switch (aMessage.name) {
// Content notifies us here (syncronously) if it has scrolled
// independent of the apz. This can happen in a lot of
// cases: keyboard shortcuts, scroll wheel, or content script.
// Let the apz know about this change so that it can update
// its scroll offset data.
case "Browser:ContentScroll": {
let data = json.viewId + " " + json.presShellId + " (" + json.scrollOffset.x + ", " + json.scrollOffset.y + ")";
Services.obs.notifyObservers(null, "apzc-scroll-offset-changed", data);
break;
}
case "Content:ZoomToRect": {
let { presShellId, viewId } = json;
let rect = Rect.fromRect(json.rect);

View File

@ -563,9 +563,6 @@ let ContentScroll = {
init: function() {
addMessageListener("Content:SetWindowSize", this);
if (Services.prefs.getBoolPref("layers.async-pan-zoom.enabled")) {
addEventListener("scroll", this, true);
}
addEventListener("pagehide", this, false);
addEventListener("MozScrolledAreaChanged", this, false);
},
@ -601,11 +598,6 @@ let ContentScroll = {
this._scrollOffset = { x: 0, y: 0 };
break;
case "scroll": {
this.notifyChromeAboutContentScroll(aEvent.target);
break;
}
case "MozScrolledAreaChanged": {
let doc = aEvent.originalTarget;
if (content != doc.defaultView) // We are only interested in root scroll pane changes
@ -627,47 +619,6 @@ let ContentScroll = {
break;
}
}
},
/*
* DOM scroll handler - if we receive this, content or the dom scrolled
* content without going through the apz. This can happen in a lot of
* cases, keyboard shortcuts, scroll wheel, or content script. Messages
* chrome via a sync call which messages the apz about the update.
*/
notifyChromeAboutContentScroll: function (target) {
let isRoot = false;
if (target instanceof Ci.nsIDOMDocument) {
var window = target.defaultView;
var scrollOffset = this.getScrollOffset(window);
var element = target.documentElement;
if (target == content.document) {
if (this._scrollOffset.x == scrollOffset.x && this._scrollOffset.y == scrollOffset.y) {
// Don't send a scroll message back to APZC if it's the same as the
// last one.
return;
}
this._scrollOffset = scrollOffset;
isRoot = true;
}
} else {
var window = target.ownerDocument.defaultView;
var scrollOffset = this.getScrollOffsetForElement(target);
var element = target;
}
let utils = window.QueryInterface(Ci.nsIInterfaceRequestor).getInterface(Ci.nsIDOMWindowUtils);
let presShellId = {};
utils.getPresShellId(presShellId);
let viewId = utils.getViewId(element);
// Must be synchronous to prevent redraw getting out of sync from
// composition.
sendSyncMessage("Browser:ContentScroll",
{ presShellId: presShellId.value,
viewId: viewId,
scrollOffset: scrollOffset,
isRoot: isRoot });
}
};

View File

@ -296,13 +296,6 @@ parent:
UpdateZoomConstraints(uint32_t aPresShellId, ViewID aViewId, bool aIsRoot,
bool aAllowZoom, CSSToScreenScale aMinZoom, CSSToScreenScale aMaxZoom);
/**
* Notifies the parent about a scroll event. The pres shell ID and
* view ID identify which scrollable (sub-)frame was scrolled, and
* the new scroll offset for that frame is sent.
*/
UpdateScrollOffset(uint32_t aPresShellId, ViewID aViewId, CSSIntPoint aScrollOffset);
__delete__();
child:

View File

@ -299,53 +299,6 @@ TabChild::HandleEvent(nsIDOMEvent* aEvent)
// This meta data may or may not have been a meta viewport tag. If it was,
// we should handle it immediately.
HandlePossibleViewportChange();
} else if (eventType.EqualsLiteral("scroll")) {
nsCOMPtr<nsIDOMEventTarget> target;
aEvent->GetTarget(getter_AddRefs(target));
ViewID viewId;
uint32_t presShellId;
nsCOMPtr<nsIContent> content;
if (nsCOMPtr<nsIDocument> doc = do_QueryInterface(target))
content = doc->GetDocumentElement();
else
content = do_QueryInterface(target);
nsCOMPtr<nsIDOMWindowUtils> utils = APZCCallbackHelper::GetDOMWindowUtils(content);
utils->GetPresShellId(&presShellId);
if (!nsLayoutUtils::FindIDFor(content, &viewId))
return NS_ERROR_UNEXPECTED;
nsIScrollableFrame* scrollFrame = nsLayoutUtils::FindScrollableFrameFor(viewId);
if (!scrollFrame)
return NS_OK;
CSSIntPoint scrollOffset = scrollFrame->GetScrollPositionCSSPixels();
if (viewId == mLastRootMetrics.mScrollId) {
// We store the last metrics that was sent via the TabParent (This is
// updated in ProcessUpdateFrame and RecvUpdateFrame).
// We use this here to avoid sending APZC back a scroll event that
// originally came from APZC (besides being unnecessary, the event might
// be slightly out of date by the time it reaches APZC).
if (RoundedToInt(mLastRootMetrics.mScrollOffset) == scrollOffset) {
return NS_OK;
}
// Update the last scroll offset now, otherwise RecvUpdateDimensions()
// might trigger a scroll to the old offset before RecvUpdateFrame()
// gets a chance to update it.
mLastRootMetrics.mScrollOffset = scrollOffset;
} else if (viewId == mLastSubFrameMetrics.mScrollId) {
if (RoundedToInt(mLastSubFrameMetrics.mScrollOffset) == scrollOffset) {
return NS_OK;
}
mLastSubFrameMetrics.mScrollOffset = scrollOffset;
}
SendUpdateScrollOffset(presShellId, viewId, scrollOffset);
}
return NS_OK;
@ -1549,7 +1502,6 @@ TabChild::RecvUpdateFrame(const FrameMetrics& aFrameMetrics)
if (content) {
FrameMetrics newSubFrameMetrics(aFrameMetrics);
APZCCallbackHelper::UpdateSubFrame(content, newSubFrameMetrics);
mLastSubFrameMetrics = newSubFrameMetrics;
return true;
}
}
@ -2244,7 +2196,6 @@ TabChild::InitTabChildGlobal(FrameScriptLoading aScriptLoading)
root->SetParentTarget(scope);
chromeHandler->AddEventListener(NS_LITERAL_STRING("DOMMetaAdded"), this, false);
chromeHandler->AddEventListener(NS_LITERAL_STRING("scroll"), this, true);
}
if (aScriptLoading != DONT_LOAD_SCRIPTS && !mTriedBrowserInit) {

View File

@ -469,7 +469,6 @@ private:
nsCOMPtr<nsIWidget> mWidget;
nsCOMPtr<nsIURI> mLastURI;
FrameMetrics mLastRootMetrics;
FrameMetrics mLastSubFrameMetrics;
RenderFrameChild* mRemoteFrame;
nsRefPtr<ContentChild> mManager;
nsRefPtr<TabChildGlobal> mTabChildGlobal;

View File

@ -1721,17 +1721,6 @@ TabParent::RecvUpdateZoomConstraints(const uint32_t& aPresShellId,
return true;
}
bool
TabParent::RecvUpdateScrollOffset(const uint32_t& aPresShellId,
const ViewID& aViewId,
const CSSIntPoint& aScrollOffset)
{
if (RenderFrameParent* rfp = GetRenderFrame()) {
rfp->UpdateScrollOffset(aPresShellId, aViewId, aScrollOffset);
}
return true;
}
bool
TabParent::RecvContentReceivedTouch(const ScrollableLayerGuid& aGuid,
const bool& aPreventDefault)

View File

@ -171,7 +171,6 @@ public:
const bool& aAllowZoom,
const CSSToScreenScale& aMinZoom,
const CSSToScreenScale& aMaxZoom);
virtual bool RecvUpdateScrollOffset(const uint32_t& aPresShellId, const ViewID& aViewId, const CSSIntPoint& aScrollOffset);
virtual bool RecvContentReceivedTouch(const ScrollableLayerGuid& aGuid,
const bool& aPreventDefault);
virtual PContentDialogParent* AllocPContentDialogParent(const uint32_t& aType,

View File

@ -619,16 +619,6 @@ APZCTreeManager::UpdateZoomConstraintsRecursively(AsyncPanZoomController* aApzc,
}
}
void
APZCTreeManager::UpdateScrollOffset(const ScrollableLayerGuid& aGuid,
const CSSPoint& aScrollOffset)
{
nsRefPtr<AsyncPanZoomController> apzc = GetTargetAPZC(aGuid);
if (apzc) {
apzc->UpdateScrollOffset(aScrollOffset);
}
}
void
APZCTreeManager::CancelAnimation(const ScrollableLayerGuid &aGuid)
{

View File

@ -172,14 +172,6 @@ public:
const CSSToScreenScale& aMinScale,
const CSSToScreenScale& aMaxScale);
/**
* Update mFrameMetrics.mScrollOffset to the given offset.
* This is necessary in cases where a scroll is not caused by user
* input (for example, a content scrollTo()).
*/
void UpdateScrollOffset(const ScrollableLayerGuid& aGuid,
const CSSPoint& aScrollOffset);
/**
* Cancels any currently running animation. Note that all this does is set the
* state of the AsyncPanZoomController back to NOTHING, but it is the

View File

@ -61,7 +61,7 @@
#define APZC_LOG_FM(fm, prefix, ...) \
APZC_LOG(prefix ":" \
" i=(%ld %lld) cb=(%d %d %d %d) dp=(%.3f %.3f %.3f %.3f) v=(%.3f %.3f %.3f %.3f) " \
"s=(%.3f %.3f) sr=(%.3f %.3f %.3f %.3f) z=(%.3f %.3f %.3f %.3f)\n", \
"s=(%.3f %.3f) sr=(%.3f %.3f %.3f %.3f) z=(%.3f %.3f %.3f %.3f) %d\n", \
__VA_ARGS__, \
fm.mPresShellId, fm.mScrollId, \
fm.mCompositionBounds.x, fm.mCompositionBounds.y, fm.mCompositionBounds.width, fm.mCompositionBounds.height, \
@ -69,7 +69,8 @@
fm.mViewport.x, fm.mViewport.y, fm.mViewport.width, fm.mViewport.height, \
fm.mScrollOffset.x, fm.mScrollOffset.y, \
fm.mScrollableRect.x, fm.mScrollableRect.y, fm.mScrollableRect.width, fm.mScrollableRect.height, \
fm.mDevPixelsPerCSSPixel.scale, fm.mResolution.scale, fm.mCumulativeResolution.scale, fm.mZoom.scale); \
fm.mDevPixelsPerCSSPixel.scale, fm.mResolution.scale, fm.mCumulativeResolution.scale, fm.mZoom.scale, \
fm.mUpdateScrollOffset); \
// Static helper functions
namespace {
@ -1475,6 +1476,16 @@ void AsyncPanZoomController::NotifyLayersUpdated(const FrameMetrics& aLayerMetri
mFrameMetrics.mZoom.scale *= parentResolutionChange;
mFrameMetrics.mResolution = aLayerMetrics.mResolution;
mFrameMetrics.mCumulativeResolution = aLayerMetrics.mCumulativeResolution;
// If the layers update was not triggered by our own repaint request, then
// we want to take the new scroll offset.
if (aLayerMetrics.mUpdateScrollOffset) {
APZC_LOG("Updating scroll offset from (%f, %f) to (%f, %f)\n",
mFrameMetrics.mScrollOffset.x, mFrameMetrics.mScrollOffset.y,
aLayerMetrics.mScrollOffset.x, aLayerMetrics.mScrollOffset.y);
mFrameMetrics.mScrollOffset = aLayerMetrics.mScrollOffset;
}
}
if (needContentRepaint) {
@ -1717,16 +1728,6 @@ void AsyncPanZoomController::SendAsyncScrollEvent() {
controller->SendAsyncScrollDOMEvent(isRoot, contentRect, scrollableSize);
}
void AsyncPanZoomController::UpdateScrollOffset(const CSSPoint& aScrollOffset)
{
APZC_LOG("Updating scroll offset from (%f, %f) to (%f, %f)\n",
mFrameMetrics.mScrollOffset.x, mFrameMetrics.mScrollOffset.y,
aScrollOffset.x, aScrollOffset.y);
ReentrantMonitorAutoEnter lock(mMonitor);
mFrameMetrics.mScrollOffset = aScrollOffset;
}
bool AsyncPanZoomController::Matches(const ScrollableLayerGuid& aGuid)
{
return aGuid == ScrollableLayerGuid(mLayersId, mFrameMetrics);

View File

@ -260,13 +260,6 @@ public:
*/
static void SetFrameTime(const TimeStamp& aMilliseconds);
/**
* Update mFrameMetrics.mScrollOffset to the given offset.
* This is necessary in cases where a scroll is not caused by user
* input (for example, a content scrollTo()).
*/
void UpdateScrollOffset(const CSSPoint& aScrollOffset);
void StartAnimation(AsyncPanZoomAnimation* aAnimation);
/**

View File

@ -1115,15 +1115,6 @@ RenderFrameParent::UpdateZoomConstraints(uint32_t aPresShellId,
}
}
void
RenderFrameParent::UpdateScrollOffset(uint32_t aPresShellId, ViewID aViewId, const CSSIntPoint& aScrollOffset)
{
if (GetApzcTreeManager()) {
GetApzcTreeManager()->UpdateScrollOffset(ScrollableLayerGuid(mLayersId, aPresShellId, aViewId),
aScrollOffset);
}
}
bool
RenderFrameParent::HitTest(const nsRect& aRect)
{

View File

@ -124,10 +124,6 @@ public:
const CSSToScreenScale& aMinZoom,
const CSSToScreenScale& aMaxZoom);
void UpdateScrollOffset(uint32_t aPresShellId,
ViewID aViewId,
const CSSIntPoint& aScrollOffset);
bool HitTest(const nsRect& aRect);
protected:

View File

@ -383,9 +383,6 @@ public class GeckoLayerClient implements LayerView.Listener, PanZoomTarget
if (!oldMetrics.fuzzyEquals(newMetrics)) {
abortPanZoomAnimation();
}
mPanZoomController.updateScrollOffset(
messageMetrics.viewportRectLeft / messageMetrics.zoomFactor,
messageMetrics.viewportRectTop / messageMetrics.zoomFactor);
break;
case PAGE_SIZE:
// adjust the page dimensions to account for differences in zoom

View File

@ -1457,11 +1457,6 @@ class JavaPanZoomController
return mX.getOverScrollMode();
}
@Override
public void updateScrollOffset(float cssX, float cssY) {
// Nothing to update, this class doesn't store the scroll offset locally.
}
@Override
public void setOverscrollHandler(final Overscroll handler) {
mOverscroll = handler;

View File

@ -103,8 +103,6 @@ class NativePanZoomController implements PanZoomController, GeckoEventListener {
}
}
public native void updateScrollOffset(float cssX, float cssY);
public void setOverscrollHandler(final Overscroll listener) {
}
}

View File

@ -44,7 +44,5 @@ public interface PanZoomController {
public void setOverScrollMode(int overscrollMode);
public int getOverScrollMode();
public void updateScrollOffset(float cssX, float cssY);
public void setOverscrollHandler(final Overscroll controller);
}

View File

@ -533,25 +533,6 @@ Java_org_mozilla_gecko_gfx_NativePanZoomController_getOverScrollMode(JNIEnv * ar
#ifdef JNI_STUBS
typedef void (*Java_org_mozilla_gecko_gfx_NativePanZoomController_updateScrollOffset_t)(JNIEnv *, jobject, jfloat, jfloat);
static Java_org_mozilla_gecko_gfx_NativePanZoomController_updateScrollOffset_t f_Java_org_mozilla_gecko_gfx_NativePanZoomController_updateScrollOffset;
extern "C" NS_EXPORT void JNICALL
Java_org_mozilla_gecko_gfx_NativePanZoomController_updateScrollOffset(JNIEnv * arg0, jobject arg1, jfloat arg2, jfloat arg3) {
if (!f_Java_org_mozilla_gecko_gfx_NativePanZoomController_updateScrollOffset) {
arg0->ThrowNew(arg0->FindClass("java/lang/UnsupportedOperationException"),
"JNI Function called before it was loaded");
return ;
}
f_Java_org_mozilla_gecko_gfx_NativePanZoomController_updateScrollOffset(arg0, arg1, arg2, arg3);
}
#endif
#ifdef JNI_BINDINGS
xul_dlsym("Java_org_mozilla_gecko_gfx_NativePanZoomController_updateScrollOffset", &f_Java_org_mozilla_gecko_gfx_NativePanZoomController_updateScrollOffset);
#endif
#ifdef JNI_STUBS
typedef jboolean (*Java_org_mozilla_gecko_ANRReporter_requestNativeStack_t)(JNIEnv *, jclass);
static Java_org_mozilla_gecko_ANRReporter_requestNativeStack_t f_Java_org_mozilla_gecko_ANRReporter_requestNativeStack;
extern "C" NS_EXPORT jboolean JNICALL

View File

@ -949,16 +949,6 @@ Java_org_mozilla_gecko_gfx_NativePanZoomController_getOverScrollMode(JNIEnv* env
return 0;
}
NS_EXPORT void JNICALL
Java_org_mozilla_gecko_gfx_NativePanZoomController_updateScrollOffset(JNIEnv* env, jobject instance, jfloat cssX, jfloat cssY)
{
APZCTreeManager *controller = nsWindow::GetAPZCTreeManager();
if (controller) {
// TODO: Pass in correct values for presShellId and viewId.
controller->UpdateScrollOffset(ScrollableLayerGuid(nsWindow::RootLayerTreeId(), 0, 0), CSSPoint(cssX, cssY));
}
}
NS_EXPORT jboolean JNICALL
Java_org_mozilla_gecko_ANRReporter_requestNativeStack(JNIEnv*, jclass)
{

View File

@ -83,17 +83,12 @@ GetDOMTargets(uint64_t aScrollId,
class RequestContentRepaintEvent : public nsRunnable
{
typedef mozilla::layers::FrameMetrics FrameMetrics;
typedef mozilla::layers::ScrollableLayerGuid ScrollableLayerGuid;
public:
RequestContentRepaintEvent(const FrameMetrics& aFrameMetrics,
nsIWidgetListener* aListener,
CSSIntPoint* aLastOffsetOut,
ScrollableLayerGuid* aLastScrollId) :
nsIWidgetListener* aListener) :
mFrameMetrics(aFrameMetrics),
mWidgetListener(aListener),
mLastOffsetOut(aLastOffsetOut),
mLastScrollIdOut(aLastScrollId)
mWidgetListener(aListener)
{
}
@ -135,16 +130,6 @@ public:
if (utils) {
APZCCallbackHelper::UpdateRootFrame(utils, mFrameMetrics);
// Return the actual scroll value so we can use it to filter
// out scroll messages triggered by setting the display port.
if (mLastOffsetOut) {
*mLastOffsetOut = mozilla::gfx::RoundedToInt(mFrameMetrics.mScrollOffset);
}
if (mLastScrollIdOut) {
mLastScrollIdOut->mScrollId = mFrameMetrics.mScrollId;
mLastScrollIdOut->mPresShellId = mFrameMetrics.mPresShellId;
}
#ifdef DEBUG_CONTROLLER
WinUtils::Log("APZController: %I64d mDisplayPort: %0.2f %0.2f %0.2f %0.2f",
mFrameMetrics.mScrollId,
@ -160,8 +145,6 @@ public:
protected:
FrameMetrics mFrameMetrics;
nsIWidgetListener* mWidgetListener;
CSSIntPoint* mLastOffsetOut;
ScrollableLayerGuid* mLastScrollIdOut;
};
void
@ -241,9 +224,7 @@ APZController::RequestContentRepaint(const FrameMetrics& aFrameMetrics)
aFrameMetrics.mScrollId);
#endif
nsCOMPtr<nsIRunnable> r1 = new RequestContentRepaintEvent(aFrameMetrics,
mWidgetListener,
&mLastScrollOffset,
&mLastScrollLayerGuid);
mWidgetListener);
if (!NS_IsMainThread()) {
NS_DispatchToMainThread(r1);
} else {
@ -251,33 +232,6 @@ APZController::RequestContentRepaint(const FrameMetrics& aFrameMetrics)
}
}
// Content send us this when it detect content has scrolled via
// a dom scroll event. Note we get these in response to dom scroll
// events and as a result of apzc scrolling which we filter out.
void
APZController::UpdateScrollOffset(const mozilla::layers::ScrollableLayerGuid& aScrollLayerId,
CSSIntPoint& aScrollOffset)
{
#ifdef DEBUG_CONTROLLER
WinUtils::Log("APZController::UpdateScrollOffset: scrollid:%I64d == %I64d offsets: %d,%d == %d,%d",
aScrollLayerId.mScrollId, aScrollLayerId.mScrollId,
aScrollOffset.x, aScrollOffset.y,
mLastScrollOffset.x, mLastScrollOffset.y);
#endif
// Bail if this the same scroll guid the apzc just scrolled and the offsets
// equal the offset the apzc set.
if (!sAPZC || (mLastScrollLayerGuid.mScrollId == aScrollLayerId.mScrollId &&
mLastScrollLayerGuid.mPresShellId == aScrollLayerId.mPresShellId &&
mLastScrollOffset == aScrollOffset)) {
#ifdef DEBUG_CONTROLLER
WinUtils::Log("Skipping UpdateScrollOffset");
#endif
return;
}
sAPZC->UpdateScrollOffset(aScrollLayerId, aScrollOffset);
}
void
APZController::HandleDoubleTap(const CSSIntPoint& aPoint, int32_t aModifiers)
{

View File

@ -42,7 +42,6 @@ public:
virtual void NotifyTransformEnd(const ScrollableLayerGuid& aGuid);
void SetWidgetListener(nsIWidgetListener* aWidgetListener);
void UpdateScrollOffset(const mozilla::layers::ScrollableLayerGuid& aScrollLayerId, CSSIntPoint& aScrollOffset);
bool HitTestAPZC(mozilla::ScreenIntPoint& aPoint);
void TransformCoordinateToGecko(const mozilla::ScreenIntPoint& aPoint,
@ -60,8 +59,6 @@ public:
private:
nsIWidgetListener* mWidgetListener;
ScrollableLayerGuid mLastScrollLayerGuid;
CSSIntPoint mLastScrollOffset;
};
} } }

View File

@ -1589,27 +1589,7 @@ NS_IMETHODIMP
MetroWidget::Observe(nsISupports *subject, const char *topic, const PRUnichar *data)
{
NS_ENSURE_ARG_POINTER(topic);
if (!strcmp(topic, "apzc-scroll-offset-changed")) {
uint64_t scrollId;
int32_t presShellId;
CSSIntPoint scrollOffset;
int matched = sscanf(NS_LossyConvertUTF16toASCII(data).get(),
"%llu %d (%d, %d)",
&scrollId,
&presShellId,
&scrollOffset.x,
&scrollOffset.y);
if (matched != 4) {
NS_WARNING("Malformed scroll-offset-changed message");
return NS_ERROR_UNEXPECTED;
}
if (!mController) {
return NS_ERROR_UNEXPECTED;
}
mController->UpdateScrollOffset(ScrollableLayerGuid(mRootLayerTreeId, presShellId, scrollId),
scrollOffset);
}
else if (!strcmp(topic, "apzc-zoom-to-rect")) {
if (!strcmp(topic, "apzc-zoom-to-rect")) {
CSSRect rect = CSSRect();
uint64_t viewId = 0;
int32_t presShellId = 0;