mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-24 21:31:04 +00:00
Bug 805746 - Send CustomScroll domevent to browser.js. r=cjones
This commit is contained in:
parent
95f613b3e2
commit
f016ff4111
@ -496,6 +496,7 @@ using mozilla::dom::indexedDB::IDBWrapperCache;
|
||||
#include "DOMError.h"
|
||||
#include "DOMRequest.h"
|
||||
#include "nsIOpenWindowEventDetail.h"
|
||||
#include "nsIAsyncScrollEventDetail.h"
|
||||
#include "nsIDOMGlobalObjectConstructor.h"
|
||||
#include "nsIDOMCanvasRenderingContext2D.h"
|
||||
#include "DOMFileHandle.h"
|
||||
@ -1544,6 +1545,8 @@ static nsDOMClassInfoData sClassInfoData[] = {
|
||||
EVENTTARGET_SCRIPTABLE_FLAGS)
|
||||
NS_DEFINE_CLASSINFO_DATA(OpenWindowEventDetail, nsDOMGenericSH,
|
||||
DOM_DEFAULT_SCRIPTABLE_FLAGS)
|
||||
NS_DEFINE_CLASSINFO_DATA(AsyncScrollEventDetail, nsDOMGenericSH,
|
||||
DOM_DEFAULT_SCRIPTABLE_FLAGS)
|
||||
|
||||
NS_DEFINE_CLASSINFO_DATA_WITH_NAME(DOMFileHandle, FileHandle, nsEventTargetSH,
|
||||
EVENTTARGET_SCRIPTABLE_FLAGS)
|
||||
@ -4016,6 +4019,10 @@ nsDOMClassInfo::Init()
|
||||
DOM_CLASSINFO_MAP_ENTRY(nsIOpenWindowEventDetail)
|
||||
DOM_CLASSINFO_MAP_END
|
||||
|
||||
DOM_CLASSINFO_MAP_BEGIN(AsyncScrollEventDetail, nsIAsyncScrollEventDetail)
|
||||
DOM_CLASSINFO_MAP_ENTRY(nsIAsyncScrollEventDetail)
|
||||
DOM_CLASSINFO_MAP_END
|
||||
|
||||
DOM_CLASSINFO_MAP_BEGIN(DOMFileHandle, nsIDOMFileHandle)
|
||||
DOM_CLASSINFO_MAP_ENTRY(nsIDOMFileHandle)
|
||||
DOM_CLASSINFO_MAP_END
|
||||
|
@ -453,6 +453,7 @@ DOMCI_CLASS(CameraCapabilities)
|
||||
DOMCI_CLASS(DOMError)
|
||||
DOMCI_CLASS(DOMRequest)
|
||||
DOMCI_CLASS(OpenWindowEventDetail)
|
||||
DOMCI_CLASS(AsyncScrollEventDetail)
|
||||
|
||||
DOMCI_CLASS(DOMFileHandle)
|
||||
DOMCI_CLASS(FileRequest)
|
||||
|
@ -19,6 +19,7 @@
|
||||
#include "nsIDOMCustomEvent.h"
|
||||
#include "nsIInterfaceRequestorUtils.h"
|
||||
#include "nsVariant.h"
|
||||
#include "nsAsyncScrollEventDetail.h"
|
||||
|
||||
using mozilla::dom::Element;
|
||||
using mozilla::dom::TabParent;
|
||||
@ -68,6 +69,40 @@ CreateIframe(Element* aOpenerFrameElement, const nsAString& aName, bool aRemote)
|
||||
return popupFrameElement.forget();
|
||||
}
|
||||
|
||||
bool
|
||||
DispatchCustomDOMEvent(Element* aFrameElement, const nsAString& aEventName,
|
||||
nsISupports *aDetailValue)
|
||||
{
|
||||
NS_ENSURE_TRUE(aFrameElement, false);
|
||||
nsIPresShell *shell = aFrameElement->OwnerDoc()->GetShell();
|
||||
nsRefPtr<nsPresContext> presContext;
|
||||
if (shell) {
|
||||
presContext = shell->GetPresContext();
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIDOMEvent> domEvent;
|
||||
nsEventDispatcher::CreateEvent(presContext, nullptr,
|
||||
NS_LITERAL_STRING("customevent"),
|
||||
getter_AddRefs(domEvent));
|
||||
NS_ENSURE_TRUE(domEvent, false);
|
||||
|
||||
nsCOMPtr<nsIWritableVariant> detailVariant = new nsVariant();
|
||||
nsresult rv = detailVariant->SetAsISupports(aDetailValue);
|
||||
NS_ENSURE_SUCCESS(rv, false);
|
||||
nsCOMPtr<nsIDOMCustomEvent> customEvent = do_QueryInterface(domEvent);
|
||||
NS_ENSURE_TRUE(customEvent, false);
|
||||
customEvent->InitCustomEvent(aEventName,
|
||||
/* bubbles = */ true,
|
||||
/* cancelable = */ false,
|
||||
detailVariant);
|
||||
customEvent->SetTrusted(true);
|
||||
// Dispatch the event.
|
||||
nsEventStatus status = nsEventStatus_eIgnore;
|
||||
rv = nsEventDispatcher::DispatchDOMEvent(aFrameElement, nullptr,
|
||||
domEvent, presContext, &status);
|
||||
return NS_SUCCEEDED(rv);
|
||||
}
|
||||
|
||||
/**
|
||||
* Dispatch a mozbrowseropenwindow event to the given opener frame element.
|
||||
* The "popup iframe" (event.detail.frameElement) will be |aPopupFrameElement|.
|
||||
@ -90,40 +125,15 @@ DispatchOpenWindowEvent(Element* aOpenerFrameElement,
|
||||
nsRefPtr<nsOpenWindowEventDetail> detail =
|
||||
new nsOpenWindowEventDetail(aURL, aName, aFeatures,
|
||||
aPopupFrameElement->AsDOMNode());
|
||||
nsCOMPtr<nsIWritableVariant> detailVariant = new nsVariant();
|
||||
nsresult rv = detailVariant->SetAsISupports(detail);
|
||||
NS_ENSURE_SUCCESS(rv, false);
|
||||
|
||||
// Create the CustomEvent.
|
||||
nsIPresShell *shell = aOpenerFrameElement->OwnerDoc()->GetShell();
|
||||
nsRefPtr<nsPresContext> presContext;
|
||||
if (shell) {
|
||||
presContext = shell->GetPresContext();
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIDOMEvent> domEvent;
|
||||
nsEventDispatcher::CreateEvent(presContext, nullptr,
|
||||
NS_LITERAL_STRING("customevent"),
|
||||
getter_AddRefs(domEvent));
|
||||
NS_ENSURE_TRUE(domEvent, false);
|
||||
|
||||
nsCOMPtr<nsIDOMCustomEvent> customEvent = do_QueryInterface(domEvent);
|
||||
NS_ENSURE_TRUE(customEvent, false);
|
||||
customEvent->InitCustomEvent(NS_LITERAL_STRING("mozbrowseropenwindow"),
|
||||
/* bubbles = */ true,
|
||||
/* cancelable = */ false,
|
||||
detailVariant);
|
||||
customEvent->SetTrusted(true);
|
||||
|
||||
// Dispatch the event.
|
||||
nsEventStatus status = nsEventStatus_eIgnore;
|
||||
rv = nsEventDispatcher::DispatchDOMEvent(aOpenerFrameElement, nullptr,
|
||||
domEvent, presContext, &status);
|
||||
NS_ENSURE_SUCCESS(rv, false);
|
||||
bool dispatchSucceeded =
|
||||
DispatchCustomDOMEvent(aOpenerFrameElement,
|
||||
NS_LITERAL_STRING("mozbrowseropenwindow"),
|
||||
detail);
|
||||
|
||||
// If the iframe is not in some document's DOM at this point, the embedder
|
||||
// has "blocked" the popup.
|
||||
return aPopupFrameElement->IsInDoc();
|
||||
return (dispatchSucceeded && aPopupFrameElement->IsInDoc());
|
||||
}
|
||||
|
||||
} // anonymous namespace
|
||||
@ -131,8 +141,8 @@ DispatchOpenWindowEvent(Element* aOpenerFrameElement,
|
||||
namespace mozilla {
|
||||
|
||||
/*static*/ bool
|
||||
BrowserElementParent::OpenWindowOOP(mozilla::dom::TabParent* aOpenerTabParent,
|
||||
mozilla::dom::TabParent* aPopupTabParent,
|
||||
BrowserElementParent::OpenWindowOOP(TabParent* aOpenerTabParent,
|
||||
TabParent* aPopupTabParent,
|
||||
const nsAString& aURL,
|
||||
const nsAString& aName,
|
||||
const nsAString& aFeatures)
|
||||
@ -230,4 +240,21 @@ BrowserElementParent::OpenWindowInProcess(nsIDOMWindow* aOpenerWindow,
|
||||
return !!*aReturnWindow;
|
||||
}
|
||||
|
||||
bool
|
||||
BrowserElementParent::DispatchAsyncScrollEvent(TabParent* aTabParent,
|
||||
const gfx::Rect& aContentRect,
|
||||
const gfx::Size& aContentSize)
|
||||
{
|
||||
nsIDOMElement* element = aTabParent->GetOwnerElement();
|
||||
nsCOMPtr<Element> frameElement = do_QueryInterface(element);
|
||||
// Create the event's detail object.
|
||||
nsRefPtr<nsAsyncScrollEventDetail> detail =
|
||||
new nsAsyncScrollEventDetail(aContentRect.x, aContentRect.y,
|
||||
aContentRect.width, aContentRect.height,
|
||||
aContentSize.width, aContentSize.height);
|
||||
return DispatchCustomDOMEvent(frameElement,
|
||||
NS_LITERAL_STRING("mozbrowserasyncscroll"),
|
||||
detail);
|
||||
}
|
||||
|
||||
} // namespace mozilla
|
||||
|
@ -16,6 +16,11 @@ namespace dom {
|
||||
class TabParent;
|
||||
}
|
||||
|
||||
namespace gfx{
|
||||
struct Rect;
|
||||
struct Size;
|
||||
}
|
||||
|
||||
/**
|
||||
* BrowserElementParent implements a portion of the parent-process side of
|
||||
* <iframe mozbrowser>.
|
||||
@ -63,8 +68,8 @@ public:
|
||||
* window.open request.
|
||||
*/
|
||||
static bool
|
||||
OpenWindowOOP(mozilla::dom::TabParent* aOpenerTabParent,
|
||||
mozilla::dom::TabParent* aPopupTabParent,
|
||||
OpenWindowOOP(dom::TabParent* aOpenerTabParent,
|
||||
dom::TabParent* aPopupTabParent,
|
||||
const nsAString& aURL,
|
||||
const nsAString& aName,
|
||||
const nsAString& aFeatures);
|
||||
@ -86,6 +91,26 @@ public:
|
||||
const nsAString& aName,
|
||||
const nsACString& aFeatures,
|
||||
nsIDOMWindow** aReturnWindow);
|
||||
|
||||
/**
|
||||
* Fire a mozbrowserasyncscroll CustomEvent on the given TabParent's frame element.
|
||||
* This event's detail is an instance of nsIAsyncScrollEventDetail.
|
||||
*
|
||||
* @param aContentRect: The portion of the page which is currently visible
|
||||
* onscreen in CSS pixels.
|
||||
*
|
||||
* @param aContentSize: The content width/height in CSS pixels.
|
||||
*
|
||||
* aContentRect.top + aContentRect.height may be larger than aContentSize.height.
|
||||
* This indicates that the content is over-scrolled, which occurs when the
|
||||
* page "rubber-bands" after being scrolled all the way to the bottom.
|
||||
* Similarly, aContentRect.left + aContentRect.width may be greater than
|
||||
* contentSize.width, and both left and top may be negative.
|
||||
*/
|
||||
static bool
|
||||
DispatchAsyncScrollEvent(dom::TabParent* aTabParent,
|
||||
const gfx::Rect& aContentRect,
|
||||
const gfx::Size& aContentSize);
|
||||
};
|
||||
|
||||
} // namespace mozilla
|
||||
|
@ -22,10 +22,12 @@ TEST_DIRS += mochitest
|
||||
|
||||
XPIDLSRCS = \
|
||||
nsIOpenWindowEventDetail.idl \
|
||||
nsIAsyncScrollEventDetail.idl \
|
||||
$(NULL)
|
||||
|
||||
EXPORTS = \
|
||||
nsOpenWindowEventDetail.h \
|
||||
nsAsyncScrollEventDetail.h \
|
||||
$(NULL)
|
||||
|
||||
EXPORTS_NAMESPACES = mozilla
|
||||
@ -35,6 +37,7 @@ EXPORTS_mozilla = \
|
||||
|
||||
CPPSRCS = \
|
||||
nsOpenWindowEventDetail.cpp \
|
||||
nsAsyncScrollEventDetail.cpp \
|
||||
BrowserElementParent.cpp \
|
||||
$(NULL)
|
||||
|
||||
|
62
dom/browser-element/nsAsyncScrollEventDetail.cpp
Normal file
62
dom/browser-element/nsAsyncScrollEventDetail.cpp
Normal file
@ -0,0 +1,62 @@
|
||||
/* 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 "nsAsyncScrollEventDetail.h"
|
||||
#include "nsDOMClassInfoID.h"
|
||||
#include "nsIDOMClassInfo.h"
|
||||
#include "nsIClassInfo.h"
|
||||
#include "nsDOMClassInfo.h"
|
||||
|
||||
NS_IMPL_ADDREF(nsAsyncScrollEventDetail)
|
||||
NS_IMPL_RELEASE(nsAsyncScrollEventDetail)
|
||||
NS_INTERFACE_MAP_BEGIN(nsAsyncScrollEventDetail)
|
||||
NS_INTERFACE_MAP_ENTRY(nsISupports)
|
||||
NS_INTERFACE_MAP_ENTRY(nsIAsyncScrollEventDetail)
|
||||
NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(AsyncScrollEventDetail)
|
||||
NS_INTERFACE_MAP_END
|
||||
|
||||
DOMCI_DATA(AsyncScrollEventDetail, nsAsyncScrollEventDetail)
|
||||
|
||||
/* readonly attribute float top; */
|
||||
NS_IMETHODIMP nsAsyncScrollEventDetail::GetTop(float *aTop)
|
||||
{
|
||||
*aTop = mTop;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
/* readonly attribute float left; */
|
||||
NS_IMETHODIMP nsAsyncScrollEventDetail::GetLeft(float *aLeft)
|
||||
{
|
||||
*aLeft = mLeft;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
/* readonly attribute float width; */
|
||||
NS_IMETHODIMP nsAsyncScrollEventDetail::GetWidth(float *aWidth)
|
||||
{
|
||||
*aWidth = mWidth;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
/* readonly attribute float height; */
|
||||
NS_IMETHODIMP nsAsyncScrollEventDetail::GetHeight(float *aHeight)
|
||||
{
|
||||
*aHeight = mHeight;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
/* readonly attribute float scrollWidth; */
|
||||
NS_IMETHODIMP nsAsyncScrollEventDetail::GetScrollWidth(float *aScrollWidth)
|
||||
{
|
||||
*aScrollWidth = mScrollWidth;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
/* readonly attribute float scrollHeight; */
|
||||
NS_IMETHODIMP nsAsyncScrollEventDetail::GetScrollHeight(float *aScrollHeight)
|
||||
{
|
||||
*aScrollHeight = mScrollHeight;
|
||||
return NS_OK;
|
||||
}
|
||||
|
36
dom/browser-element/nsAsyncScrollEventDetail.h
Normal file
36
dom/browser-element/nsAsyncScrollEventDetail.h
Normal file
@ -0,0 +1,36 @@
|
||||
/* 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 "nsIAsyncScrollEventDetail.h"
|
||||
|
||||
/**
|
||||
* When we send a mozbrowserasyncscroll event (an instance of CustomEvent), we
|
||||
* use an instance of this class as the event's detail.
|
||||
*/
|
||||
class nsAsyncScrollEventDetail : public nsIAsyncScrollEventDetail
|
||||
{
|
||||
public:
|
||||
nsAsyncScrollEventDetail(const float left, const float top,
|
||||
const float width, const float height,
|
||||
const float contentWidth, const float contentHeigh)
|
||||
: mTop(top)
|
||||
, mLeft(left)
|
||||
, mWidth(width)
|
||||
, mHeight(height)
|
||||
, mScrollWidth(contentWidth)
|
||||
, mScrollHeight(contentHeigh)
|
||||
{}
|
||||
|
||||
NS_DECL_ISUPPORTS
|
||||
NS_DECL_NSIASYNCSCROLLEVENTDETAIL
|
||||
|
||||
private:
|
||||
virtual ~nsAsyncScrollEventDetail() {}
|
||||
const float mTop;
|
||||
const float mLeft;
|
||||
const float mWidth;
|
||||
const float mHeight;
|
||||
const float mScrollWidth;
|
||||
const float mScrollHeight;
|
||||
};
|
29
dom/browser-element/nsIAsyncScrollEventDetail.idl
Normal file
29
dom/browser-element/nsIAsyncScrollEventDetail.idl
Normal file
@ -0,0 +1,29 @@
|
||||
/* 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 "nsISupports.idl"
|
||||
|
||||
/**
|
||||
* When we send a mozbrowserasyncscroll event (an instance of CustomEvent), we
|
||||
* use an instance of this interface as the event's detail.
|
||||
* [left, top, width, height]: The portion of the page which is currently
|
||||
* visible onscreen in CSS pixels.
|
||||
* [scrollWidth, scrollHeight]: The content width/height in CSS pixels.
|
||||
*
|
||||
* top + height may be larger than scrollHeight.
|
||||
* This indicates that the content is over-scrolled, which occurs when the
|
||||
* page "rubber-bands" after being scrolled all the way to the bottom.
|
||||
* Similarly, left + width may be greater than scrollWidth,
|
||||
* and both left and top may be negative.
|
||||
*/
|
||||
[scriptable, uuid(d0c13577-31e6-4701-b9b7-3535bbe19fe6)]
|
||||
interface nsIAsyncScrollEventDetail : nsISupports
|
||||
{
|
||||
readonly attribute float top;
|
||||
readonly attribute float left;
|
||||
readonly attribute float width;
|
||||
readonly attribute float height;
|
||||
readonly attribute float scrollWidth;
|
||||
readonly attribute float scrollHeight;
|
||||
};
|
@ -528,7 +528,8 @@ var interfaceNamesInGlobalScope =
|
||||
"RTCPeerConnection",
|
||||
"LocalMediaStream",
|
||||
"CSSConditionRule",
|
||||
"CSSGroupingRule"
|
||||
"CSSGroupingRule",
|
||||
"AsyncScrollEventDetail"
|
||||
]
|
||||
|
||||
for (var i in SpecialPowers.Components.interfaces) {
|
||||
|
@ -92,11 +92,18 @@ AsyncPanZoomController::AsyncPanZoomController(GeckoContentController* aGeckoCon
|
||||
mMonitor("AsyncPanZoomController"),
|
||||
mLastSampleTime(TimeStamp::Now()),
|
||||
mState(NOTHING),
|
||||
mLastAsyncScrollTime(TimeStamp::Now()),
|
||||
mLastAsyncScrollOffset(0, 0),
|
||||
mCurrentAsyncScrollOffset(0, 0),
|
||||
mAsyncScrollTimeoutTask(nullptr),
|
||||
mAsyncScrollThrottleTime(100),
|
||||
mAsyncScrollTimeout(300),
|
||||
mDPI(72),
|
||||
mWaitingForContentToPaint(false),
|
||||
mDisableNextTouchBatch(false),
|
||||
mHandlingTouchQueue(false)
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
if (aGestures == USE_GESTURE_DETECTOR) {
|
||||
mGestureEventListener = new GestureEventListener(this);
|
||||
}
|
||||
@ -109,6 +116,9 @@ AsyncPanZoomController::AsyncPanZoomController(GeckoContentController* aGeckoCon
|
||||
nsTimingFunction(NS_STYLE_TRANSITION_TIMING_FUNCTION_EASE));
|
||||
ClearOnShutdown(&gComputedTimingFunction);
|
||||
}
|
||||
|
||||
Preferences::GetUint("apzc.asyncscroll.throttle", &mAsyncScrollThrottleTime);
|
||||
Preferences::GetUint("apzc.asyncscroll.timeout", &mAsyncScrollTimeout);
|
||||
}
|
||||
|
||||
AsyncPanZoomController::~AsyncPanZoomController() {
|
||||
@ -367,6 +377,11 @@ nsEventStatus AsyncPanZoomController::OnTouchEnd(const MultiTouchInput& aEvent)
|
||||
return nsEventStatus_eIgnore;
|
||||
}
|
||||
|
||||
{
|
||||
MonitorAutoLock monitor(mMonitor);
|
||||
SendAsyncScrollEvent();
|
||||
}
|
||||
|
||||
switch (mState) {
|
||||
case FLING:
|
||||
// Should never happen.
|
||||
@ -679,6 +694,7 @@ bool AsyncPanZoomController::DoFling(const TimeDuration& aDelta) {
|
||||
// Bring the resolution back in sync with the zoom, in case we scaled down
|
||||
// the zoom while accelerating.
|
||||
SetZoomAndResolution(mFrameMetrics.mZoom.width);
|
||||
SendAsyncScrollEvent();
|
||||
RequestContentRepaint();
|
||||
mState = NOTHING;
|
||||
return false;
|
||||
@ -953,6 +969,8 @@ void AsyncPanZoomController::RequestContentRepaint() {
|
||||
return;
|
||||
}
|
||||
|
||||
SendAsyncScrollEvent();
|
||||
|
||||
// Cache the zoom since we're temporarily changing it for
|
||||
// acceleration-scaled painting.
|
||||
gfxFloat actualZoom = mFrameMetrics.mZoom.width;
|
||||
@ -979,6 +997,16 @@ void AsyncPanZoomController::RequestContentRepaint() {
|
||||
mFrameMetrics.mZoom = gfxSize(actualZoom, actualZoom);
|
||||
}
|
||||
|
||||
void
|
||||
AsyncPanZoomController::FireAsyncScrollOnTimeout()
|
||||
{
|
||||
if (mCurrentAsyncScrollOffset != mLastAsyncScrollOffset) {
|
||||
MonitorAutoLock monitor(mMonitor);
|
||||
SendAsyncScrollEvent();
|
||||
}
|
||||
mAsyncScrollTimeoutTask = nullptr;
|
||||
}
|
||||
|
||||
bool AsyncPanZoomController::SampleContentTransformForFrame(const TimeStamp& aSampleTime,
|
||||
ContainerLayer* aLayer,
|
||||
ViewTransform* aNewTransform) {
|
||||
@ -1036,6 +1064,7 @@ bool AsyncPanZoomController::SampleContentTransformForFrame(const TimeStamp& aSa
|
||||
// Bring the resolution in sync with the zoom.
|
||||
SetZoomAndResolution(mFrameMetrics.mZoom.width);
|
||||
mState = NOTHING;
|
||||
SendAsyncScrollEvent();
|
||||
RequestContentRepaint();
|
||||
}
|
||||
|
||||
@ -1056,6 +1085,34 @@ bool AsyncPanZoomController::SampleContentTransformForFrame(const TimeStamp& aSa
|
||||
}
|
||||
|
||||
scrollOffset = gfxPoint(mFrameMetrics.mScrollOffset.x, mFrameMetrics.mScrollOffset.y);
|
||||
mCurrentAsyncScrollOffset = mFrameMetrics.mScrollOffset;
|
||||
}
|
||||
|
||||
// Cancel the mAsyncScrollTimeoutTask because we will fire a
|
||||
// mozbrowserasyncscroll event or renew the mAsyncScrollTimeoutTask again.
|
||||
if (mAsyncScrollTimeoutTask) {
|
||||
mAsyncScrollTimeoutTask->Cancel();
|
||||
mAsyncScrollTimeoutTask = nullptr;
|
||||
}
|
||||
// Fire the mozbrowserasyncscroll event immediately if it's been
|
||||
// sAsyncScrollThrottleTime ms since the last time we fired the event and the
|
||||
// current scroll offset is different than the mLastAsyncScrollOffset we sent
|
||||
// with the last event.
|
||||
// Otherwise, start a timer to fire the event sAsyncScrollTimeout ms from now.
|
||||
TimeDuration delta = aSampleTime - mLastAsyncScrollTime;
|
||||
if (delta.ToMilliseconds() > mAsyncScrollThrottleTime &&
|
||||
mCurrentAsyncScrollOffset != mLastAsyncScrollOffset) {
|
||||
MonitorAutoLock monitor(mMonitor);
|
||||
mLastAsyncScrollTime = aSampleTime;
|
||||
mLastAsyncScrollOffset = mCurrentAsyncScrollOffset;
|
||||
SendAsyncScrollEvent();
|
||||
}
|
||||
else {
|
||||
mAsyncScrollTimeoutTask =
|
||||
NewRunnableMethod(this, &AsyncPanZoomController::FireAsyncScrollOnTimeout);
|
||||
MessageLoop::current()->PostDelayedTask(FROM_HERE,
|
||||
mAsyncScrollTimeoutTask,
|
||||
mAsyncScrollTimeout);
|
||||
}
|
||||
|
||||
nsIntPoint scrollCompensation(
|
||||
@ -1312,5 +1369,22 @@ void AsyncPanZoomController::UpdateZoomConstraints(bool aAllowZoom,
|
||||
mMaxZoom = aMaxZoom;
|
||||
}
|
||||
|
||||
void AsyncPanZoomController::SendAsyncScrollEvent() {
|
||||
if (!mGeckoContentController) {
|
||||
return;
|
||||
}
|
||||
|
||||
gfx::Rect contentRect;
|
||||
gfx::Size scrollableSize;
|
||||
{
|
||||
scrollableSize = gfx::Size(mFrameMetrics.mScrollableRect.width,
|
||||
mFrameMetrics.mScrollableRect.height);
|
||||
contentRect =
|
||||
AsyncPanZoomController::CalculateCompositedRectInCssPixels(mFrameMetrics);
|
||||
contentRect.MoveTo(mCurrentAsyncScrollOffset);
|
||||
}
|
||||
|
||||
mGeckoContentController->SendAsyncScrollDOMEvent(contentRect, scrollableSize);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -227,6 +227,12 @@ public:
|
||||
|
||||
static gfx::Rect CalculateCompositedRectInCssPixels(const FrameMetrics& aMetrics);
|
||||
|
||||
/**
|
||||
* Send an mozbrowserasyncscroll event.
|
||||
* *** The monitor must be held while calling this.
|
||||
*/
|
||||
void SendAsyncScrollEvent();
|
||||
|
||||
protected:
|
||||
/**
|
||||
* Internal handler for ReceiveInputEvent(). Does all the actual work.
|
||||
@ -439,6 +445,14 @@ protected:
|
||||
*/
|
||||
void SetZoomAndResolution(float aScale);
|
||||
|
||||
/**
|
||||
* Timeout function for mozbrowserasyncscroll event. Because we throttle
|
||||
* mozbrowserasyncscroll events in some conditions, this function ensures
|
||||
* that the last mozbrowserasyncscroll event will be fired after a period of
|
||||
* time.
|
||||
*/
|
||||
void FireAsyncScrollOnTimeout();
|
||||
|
||||
private:
|
||||
enum PanZoomState {
|
||||
NOTHING, /* no touch-start events received */
|
||||
@ -532,6 +546,27 @@ private:
|
||||
// previous paints.
|
||||
TimeStamp mPreviousPaintStartTime;
|
||||
|
||||
// The last time and offset we fire the mozbrowserasyncscroll event when
|
||||
// compositor has sampled the content transform for this frame.
|
||||
TimeStamp mLastAsyncScrollTime;
|
||||
gfx::Point mLastAsyncScrollOffset;
|
||||
|
||||
// The current offset drawn on the screen, it may not be sent since we have
|
||||
// throttling policy for mozbrowserasyncscroll event.
|
||||
gfx::Point mCurrentAsyncScrollOffset;
|
||||
|
||||
// The delay task triggered by the throttling mozbrowserasyncscroll event
|
||||
// ensures the last mozbrowserasyncscroll event is always been fired.
|
||||
CancelableTask* mAsyncScrollTimeoutTask;
|
||||
|
||||
// The time period in ms that throttles mozbrowserasyncscroll event.
|
||||
// Default is 100ms if there is no "apzc.asyncscroll.throttle" in preference.
|
||||
uint32_t mAsyncScrollThrottleTime;
|
||||
|
||||
// The timeout in ms for mAsyncScrollTimeoutTask delay task.
|
||||
// Default is 300ms if there is no "apzc.asyncscroll.timeout" in preference.
|
||||
uint32_t mAsyncScrollTimeout;
|
||||
|
||||
int mDPI;
|
||||
|
||||
// Stores the current paint status of the frame that we're managing. Repaints
|
||||
|
@ -44,6 +44,14 @@ public:
|
||||
*/
|
||||
virtual void HandleLongTap(const nsIntPoint& aPoint) = 0;
|
||||
|
||||
/**
|
||||
* Requests sending a mozbrowserasyncscroll domevent to embedder.
|
||||
* |aContentRect| is in CSS pixels, relative to the current cssPage.
|
||||
* |aScrollableSize| is the current content width/height in CSS pixels.
|
||||
*/
|
||||
virtual void SendAsyncScrollDOMEvent(const gfx::Rect &aContentRect,
|
||||
const gfx::Size &aScrollableSize) = 0;
|
||||
|
||||
GeckoContentController() {}
|
||||
virtual ~GeckoContentController() {}
|
||||
};
|
||||
|
@ -13,6 +13,7 @@
|
||||
#ifdef MOZ_ENABLE_D3D9_LAYER
|
||||
# include "LayerManagerD3D9.h"
|
||||
#endif //MOZ_ENABLE_D3D9_LAYER
|
||||
#include "mozilla/BrowserElementParent.h"
|
||||
#include "mozilla/dom/TabParent.h"
|
||||
#include "mozilla/layers/AsyncPanZoomController.h"
|
||||
#include "mozilla/layers/CompositorParent.h"
|
||||
@ -550,6 +551,24 @@ public:
|
||||
|
||||
void ClearRenderFrame() { mRenderFrame = nullptr; }
|
||||
|
||||
virtual void SendAsyncScrollDOMEvent(const gfx::Rect& aContentRect,
|
||||
const gfx::Size& aContentSize) MOZ_OVERRIDE
|
||||
{
|
||||
if (MessageLoop::current() != mUILoop) {
|
||||
mUILoop->PostTask(
|
||||
FROM_HERE,
|
||||
NewRunnableMethod(this,
|
||||
&RemoteContentController::SendAsyncScrollDOMEvent,
|
||||
aContentRect, aContentSize));
|
||||
return;
|
||||
}
|
||||
if (mRenderFrame) {
|
||||
TabParent* browser = static_cast<TabParent*>(mRenderFrame->Manager());
|
||||
BrowserElementParent::DispatchAsyncScrollEvent(browser, aContentRect,
|
||||
aContentSize);
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
void DoRequestContentRepaint(const FrameMetrics& aFrameMetrics)
|
||||
{
|
||||
|
Loading…
Reference in New Issue
Block a user