mirror of
https://github.com/roytam1/palemoon27.git
synced 2026-05-26 14:18:48 +00:00
import changes from `dev' branch of rmottola/Arctic-Fox:
- Bug 1262361 - Use gfxCriticalError to collect useful info when device reset. r=milan (a565047753)
- Bug 1265282 - Annotate reports instead of crashing when setting an incompatible compositor (D3D11). r=dvander (ed04e9e8eb)
- Bug 1235407 - Part 3: Force a reset when OpenSharedHandle fails. r=milan (a2f5c656eb)
- Bug 1264142 - Add ImageLayerComposite::GetFullyRenderedRegion() r=mattwoodrow (3a5f479820)
- Bug 1224199 - Remove some unused code in TiledLayerBufferComposite - r=nical (b3c60126ce)
- Bug 1262328 - Add Add ClientLayer::HandleMemoryPressure() r=nical (31bb89613d)
- Bug 1224833 - Check explicitly if image has TextureClient r=nical (34044dc195)
- Bug 1240867 - Add missing include. r=nical (abd9a8876e)
- Bug 1240800: When we've reallocated our buffer client side and fail to track the proper invalid region always upload the bounds of the visible region. r=mattwoodrow (7a7cc1928c)
- Bug 1253386 - Double buffer in CanvasClient2D - r=nical (a0fe10f1a6)
- Bug 1266380 - fix offset of untransformed surface when 3d transforming in BasicLayerManager. r=jrmuizel (3d3931346f)
- Bug 1257288 - Fix a bug in APZCTM logging code. r=kats (3c73c99077)
- Bug 1265424 - Record if the target was confirmed via a timeout or not. r=botond (e25c0c016d)
- Bug 1265424 - Ensure that HasReceivedAllContentNotifications doesn't start returning true if the target APZC was confirmed by timeout. r=botond (6c4e57cb8f)
- Bug 1229039 - If a PanGesture input block gets interrupted, just start a new block instead of not sending the rest of the events through the APZ. r=mstange (534b6691f7)
- Bug 1056356 - Remove the hand-rolled mechanism used to get nsRefPtr<const OverscrollHandoffChaiin> to work. r=kats (9d692fa32f)
- Bug 1253617 - Fix non-unified build bustage in OverscrollHandoffStat.cpp r=BenWa (38a53f7521)
- Bug 1262432 - Remove assertion that may be legitimately false sometimes. r=tnikkel (36bbb36476)
- Bug 1169802 - Temporary workaround for a deeper bug, to prevent an assertion from firing. r=botond (b1edd69e49)
- bits of Bug 1223296 (182a1ee34e)
- move around (bug 1014691) and align some more tests (19db30010c)
- Bug 944164 - Update jorendb to current function names, and much else: (b96a636c60)
- Bug 1244222 - Tests. r=bz (9cfbe54859)
- Bug 888969 - Make XPCJSID instanceof comparisons work correctly when [[GetPrototypeOf]] on the [[Prototype]] chain of the instance being tested throws an exception. r=bz (ff450de2ef)
- Bug 1256306 - Bump the Windows stack limit. r=bholley (5f4f0c3b1c)
- Bug 1257234 - Detect main thread's stack size at runtime, on Windows. r=ted (108608ce73)
- bug 1264651 - remove dom.max_child_script_run_time pref r=billm (443bc36d84)
- Bug 1266630 - Make fallible the orphan node table used during memory reporting. r=mccr8. (b7c6da934c)
- Bug 1259699 - Adjust Windows stack limits to account for large PGO stack frames. r=bholley (87ff9dbef9)
- bug 1250486 - get rid of the static ctor for XPCShellImpl.cpp r=bz (748def73ea)
- Bug 1231309 - guard sz with assert. r=bobbyholley (34080a1022)
- Bug 1255817 part 5. Remove the now-unused xpc::SystemErrorReporter. r=bholley (c014f7fa7f)
- Bug 1257888 - Link chromium mutex-based atomics implementation to webrtc signaling tests. r=froydnj (fadb9764b2)
- Bug 1253123 - Remove ipc_sync_message (r=jld) a=kwierso (7cc8a8fe0e)
- Bug 1253123 - Remove ipc_channel_proxy (r=jld) (4000ea80f3)
- Bug 1253123 - Remove message_router (r=jld) a=kwierso (8b41859a17)
- Bug 1235633 - IPC OOM mitigation by eliminating buffer copying (r=jld) (ecd6c12bec)
- Bug 1263314: Remove NonThreadSafe. r=jld (06a6331dee)
- Bug 1261567 - Include compat dir in libevent include path. r=billm (b496d2ad1f)
- Bug 1258312 - Add crash annotation to EnumSerializer r=jld (7face45d63)
- Bug 1262463 - part 1 - turn NS_RUNTIMEABORTs in protocols into FatalErrors; r=jld (731b35dc68)
- Bug 1262463 - part 2 - don't pass the other process pid into FatalError; r=jld (6f54c58494)
- Bug 1262463 - part 3 - out-of-line NS_RUNTIMEABORT calls in IPDL-generated code; r=jld (0728f61a5f)
- Bug 1259428 - part 1 - don't call Log methods of generated method classes; r=jld (938c6ff705)
- Bug 1259428 - part 2 - remove dodgy static_cast downcasts from logging statements; r=jld (4fa0a5228d)
- Bug 1259428 - part 3 - remove Log() methods from generated message subclasses; r=jld (964a0c2487)
- Bug 1259428 - part 4 - remove prtime.h from generated protocol headers; r=jld (8548b37b91)
- Bug 1259428 - part 5 - convert Message subclasses to constructor functions; r=jld (63f195ffce)
- Bug 1259428 - part 6 - remove unneeded MessageDecl methods; r=jld (fc8cd72bd7)
- Bug 1262458 - rename {msg,reply}Class-related things to reflect new functional reality; r=jld (8122887df4)
- Bug 1258663 - Crash annotate system call failures in the IPC transport. r=gabor (5f483a17a5)
- Bug 1258317 - Part 1: Annotate the crash report with process information on failure to transfer an IPC transport to another process. r=krizsa (107947c7c3)
- Bug 1258317 - cross compilation fixup. (534c214182)
- Bug 1258317 - Part 2: Remove unused privilege in mozilla::ipc::TransferHandleTorProcess(). r=krizsa (82fc8ca4cc)
- Bug 1252246 - Try to use PTHREAD_PROCESS_SHARED for CrossProcessMutex on more Unices. r=glandium f=kats (195742a508)
- now we can add crashreporter (2cbb6f2d1a)
- Bug 1251226 - Avoid passing a std::wstring through the variadic method; r=bobowen (80b2dd8034)
- Bug 1260736 - Let the client to filter out its interested messages to lower the number of times entering the monitor in PeekMessages(). r=dvander (3aea1ed77a)
- Bug 1264662 - Record IPC message capacity instead of size. r=billm (fbfff4e5b8)
- Bug 1261099 - Avoid two Message copies in MaybeUndeferIncall. r=billm (ebb7fe2b47)
This commit is contained in:
@@ -496,76 +496,6 @@ bool ScriptErrorEvent::sHandlingScriptError = false;
|
||||
// soon.
|
||||
namespace xpc {
|
||||
|
||||
void
|
||||
SystemErrorReporter(JSContext *cx, const char *message, JSErrorReport *report)
|
||||
{
|
||||
JS::Rooted<JS::Value> exception(cx);
|
||||
::JS_GetPendingException(cx, &exception);
|
||||
|
||||
// Note: we must do this before running any more code on cx.
|
||||
::JS_ClearPendingException(cx);
|
||||
|
||||
MOZ_ASSERT(cx == nsContentUtils::GetCurrentJSContext());
|
||||
nsCOMPtr<nsIGlobalObject> globalObject;
|
||||
|
||||
// The eventual plan is for error reporting to happen in the AutoJSAPI
|
||||
// destructor using the global with which the AutoJSAPI was initialized. We
|
||||
// can't _quite_ do that yet, so we take a sloppy stab at those semantics. If
|
||||
// we have an nsIScriptContext, we'll get the right answer modulo
|
||||
// non-current-inners.
|
||||
//
|
||||
// Otherwise, we just use the privileged junk scope. This has the effect of
|
||||
// causing us to report the error as "chrome javascript" rather than "content
|
||||
// javascript", and not invoking any error reporters. This is exactly what we
|
||||
// want here.
|
||||
if (nsIScriptContext* scx = GetScriptContextFromJSContext(cx)) {
|
||||
nsCOMPtr<nsPIDOMWindow> outer = do_QueryInterface(scx->GetGlobalObject());
|
||||
if (outer) {
|
||||
globalObject = static_cast<nsGlobalWindow*>(outer->GetCurrentInnerWindow());
|
||||
}
|
||||
}
|
||||
|
||||
// We run addons in a separate privileged compartment, but they still expect
|
||||
// to trigger the onerror handler of their associated DOMWindow.
|
||||
//
|
||||
// Note that the way we do this right now is sloppy. Error reporters can
|
||||
// theoretically be triggered at arbitrary times (not just immediately before
|
||||
// an AutoJSAPI comes off the stack), so we don't really have a way of knowing
|
||||
// that the global of the current compartment is the correct global with which
|
||||
// to report the error. But in practice this is probably fine for the time
|
||||
// being, and will get cleaned up soon when we fix bug 981187.
|
||||
if (!globalObject && JS::CurrentGlobalOrNull(cx)) {
|
||||
globalObject = xpc::AddonWindowOrNull(JS::CurrentGlobalOrNull(cx));
|
||||
}
|
||||
|
||||
if (!globalObject) {
|
||||
globalObject = xpc::NativeGlobal(xpc::PrivilegedJunkScope());
|
||||
}
|
||||
|
||||
if (globalObject) {
|
||||
RefPtr<xpc::ErrorReport> xpcReport = new xpc::ErrorReport();
|
||||
bool isChrome = nsContentUtils::IsSystemPrincipal(globalObject->PrincipalOrNull());
|
||||
nsCOMPtr<nsPIDOMWindow> win = do_QueryInterface(globalObject);
|
||||
xpcReport->Init(report, message, isChrome, win ? win->WindowID() : 0);
|
||||
|
||||
// If we can't dispatch an event to a window, report it to the console
|
||||
// directly. This includes the case where the error was an OOM, because
|
||||
// triggering a scripted event handler is likely to generate further OOMs.
|
||||
if (!win || JSREPORT_IS_WARNING(xpcReport->mFlags) ||
|
||||
report->errorNumber == JSMSG_OUT_OF_MEMORY)
|
||||
{
|
||||
JS::Rooted<JSObject*> stack(cx,
|
||||
xpc::FindExceptionStackForConsoleReport(win, exception));
|
||||
xpcReport->LogToConsoleWithStack(stack);
|
||||
return;
|
||||
}
|
||||
|
||||
// Otherwise, we need to asynchronously invoke onerror before we can decide
|
||||
// whether or not to report the error to the console.
|
||||
DispatchScriptErrorEvent(win, JS_GetRuntime(cx), xpcReport, exception);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
DispatchScriptErrorEvent(nsPIDOMWindow *win, JSRuntime *rt, xpc::ErrorReport *xpcReport,
|
||||
JS::Handle<JS::Value> exception)
|
||||
|
||||
@@ -1,14 +0,0 @@
|
||||
# The following tests test the async positioning of the scrollbars.
|
||||
# Basic root-frame scrollbar with async scrolling
|
||||
chaos-mode skip-if(!asyncPan) == async-scrollbar-1-v.html async-scrollbar-1-v-ref.html
|
||||
chaos-mode skip-if(!asyncPan) == async-scrollbar-1-h.html async-scrollbar-1-h-ref.html
|
||||
chaos-mode skip-if(!asyncPan) == async-scrollbar-1-vh.html async-scrollbar-1-vh-ref.html
|
||||
chaos-mode skip-if(!asyncPan) == async-scrollbar-1-v-rtl.html async-scrollbar-1-v-rtl-ref.html
|
||||
chaos-mode skip-if(!asyncPan) == async-scrollbar-1-h-rtl.html async-scrollbar-1-h-rtl-ref.html
|
||||
chaos-mode skip-if(!asyncPan) == async-scrollbar-1-vh-rtl.html async-scrollbar-1-vh-rtl-ref.html
|
||||
|
||||
# Different async zoom levels. Since the scrollthumb gets async-scaled in the
|
||||
# compositor, the border-radius ends of the scrollthumb are going to be a little
|
||||
# off, hence the fuzzy-if clauses.
|
||||
chaos-mode skip-if(!asyncZoom) fuzzy-if(B2G,98,82) == async-scrollbar-zoom-1.html async-scrollbar-zoom-1-ref.html
|
||||
chaos-mode skip-if(!asyncZoom) fuzzy-if(B2G,94,146) == async-scrollbar-zoom-2.html async-scrollbar-zoom-2-ref.html
|
||||
@@ -1770,7 +1770,7 @@ APZCTreeManager::GetAPZCAtPoint(HitTestingTreeNode* aNode,
|
||||
MOZ_ASSERT(result);
|
||||
}
|
||||
APZCTM_LOG("Successfully matched APZC %p via node %p (hit result %d)\n",
|
||||
result, aNode, *aOutHitResult);
|
||||
result, resultNode, *aOutHitResult);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
@@ -25,7 +25,8 @@ static uint64_t sBlockCounter = InputBlockState::NO_BLOCK_ID + 1;
|
||||
InputBlockState::InputBlockState(const RefPtr<AsyncPanZoomController>& aTargetApzc,
|
||||
bool aTargetConfirmed)
|
||||
: mTargetApzc(aTargetApzc)
|
||||
, mTargetConfirmed(aTargetConfirmed)
|
||||
, mTargetConfirmed(aTargetConfirmed ? TargetConfirmationState::eConfirmed
|
||||
: TargetConfirmationState::eUnconfirmed)
|
||||
, mBlockId(sBlockCounter++)
|
||||
, mTransformToApzc(aTargetApzc->GetTransformToThis())
|
||||
{
|
||||
@@ -35,12 +36,23 @@ InputBlockState::InputBlockState(const RefPtr<AsyncPanZoomController>& aTargetAp
|
||||
}
|
||||
|
||||
bool
|
||||
InputBlockState::SetConfirmedTargetApzc(const RefPtr<AsyncPanZoomController>& aTargetApzc)
|
||||
InputBlockState::SetConfirmedTargetApzc(const RefPtr<AsyncPanZoomController>& aTargetApzc,
|
||||
TargetConfirmationState aState)
|
||||
{
|
||||
if (mTargetConfirmed) {
|
||||
MOZ_ASSERT(aState == TargetConfirmationState::eConfirmed
|
||||
|| aState == TargetConfirmationState::eTimedOut);
|
||||
|
||||
if (mTargetConfirmed == TargetConfirmationState::eTimedOut &&
|
||||
aState == TargetConfirmationState::eConfirmed) {
|
||||
// The main thread finally responded. We had already timed out the
|
||||
// confirmation, but we want to update the state internally so that we
|
||||
// can record the time for telemetry purposes.
|
||||
mTargetConfirmed = TargetConfirmationState::eTimedOutAndMainThreadResponded;
|
||||
}
|
||||
if (mTargetConfirmed != TargetConfirmationState::eUnconfirmed) {
|
||||
return false;
|
||||
}
|
||||
mTargetConfirmed = true;
|
||||
mTargetConfirmed = aState;
|
||||
|
||||
TBS_LOG("%p got confirmed target APZC %p\n", this, mTargetApzc.get());
|
||||
if (mTargetApzc == aTargetApzc) {
|
||||
@@ -85,7 +97,14 @@ InputBlockState::GetBlockId() const
|
||||
bool
|
||||
InputBlockState::IsTargetConfirmed() const
|
||||
{
|
||||
return mTargetConfirmed;
|
||||
return mTargetConfirmed != TargetConfirmationState::eUnconfirmed;
|
||||
}
|
||||
|
||||
bool
|
||||
InputBlockState::HasReceivedRealConfirmedTarget() const
|
||||
{
|
||||
return mTargetConfirmed == TargetConfirmationState::eConfirmed ||
|
||||
mTargetConfirmed == TargetConfirmationState::eTimedOutAndMainThreadResponded;
|
||||
}
|
||||
|
||||
bool
|
||||
@@ -192,7 +211,7 @@ CancelableBlockState::IsDefaultPrevented() const
|
||||
bool
|
||||
CancelableBlockState::HasReceivedAllContentNotifications() const
|
||||
{
|
||||
return IsTargetConfirmed() && mContentResponded;
|
||||
return HasReceivedRealConfirmedTarget() && mContentResponded;
|
||||
}
|
||||
|
||||
bool
|
||||
@@ -359,7 +378,8 @@ WheelBlockState::SetContentResponse(bool aPreventDefault)
|
||||
}
|
||||
|
||||
bool
|
||||
WheelBlockState::SetConfirmedTargetApzc(const RefPtr<AsyncPanZoomController>& aTargetApzc)
|
||||
WheelBlockState::SetConfirmedTargetApzc(const RefPtr<AsyncPanZoomController>& aTargetApzc,
|
||||
TargetConfirmationState aState)
|
||||
{
|
||||
// The APZC that we find via APZCCallbackHelpers may not be the same APZC
|
||||
// ESM or OverscrollHandoff would have computed. Make sure we get the right
|
||||
@@ -370,7 +390,7 @@ WheelBlockState::SetConfirmedTargetApzc(const RefPtr<AsyncPanZoomController>& aT
|
||||
apzc = apzc->BuildOverscrollHandoffChain()->FindFirstScrollable(event);
|
||||
}
|
||||
|
||||
InputBlockState::SetConfirmedTargetApzc(apzc);
|
||||
InputBlockState::SetConfirmedTargetApzc(apzc, aState);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -603,7 +623,8 @@ PanGestureBlockState::PanGestureBlockState(const RefPtr<AsyncPanZoomController>&
|
||||
}
|
||||
|
||||
bool
|
||||
PanGestureBlockState::SetConfirmedTargetApzc(const RefPtr<AsyncPanZoomController>& aTargetApzc)
|
||||
PanGestureBlockState::SetConfirmedTargetApzc(const RefPtr<AsyncPanZoomController>& aTargetApzc,
|
||||
TargetConfirmationState aState)
|
||||
{
|
||||
// The APZC that we find via APZCCallbackHelpers may not be the same APZC
|
||||
// ESM or OverscrollHandoff would have computed. Make sure we get the right
|
||||
@@ -618,7 +639,7 @@ PanGestureBlockState::SetConfirmedTargetApzc(const RefPtr<AsyncPanZoomController
|
||||
}
|
||||
}
|
||||
|
||||
InputBlockState::SetConfirmedTargetApzc(apzc);
|
||||
InputBlockState::SetConfirmedTargetApzc(apzc, aState);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -39,17 +39,26 @@ class InputBlockState
|
||||
public:
|
||||
static const uint64_t NO_BLOCK_ID = 0;
|
||||
|
||||
enum class TargetConfirmationState {
|
||||
eUnconfirmed,
|
||||
eTimedOut,
|
||||
eTimedOutAndMainThreadResponded,
|
||||
eConfirmed
|
||||
};
|
||||
|
||||
explicit InputBlockState(const RefPtr<AsyncPanZoomController>& aTargetApzc,
|
||||
bool aTargetConfirmed);
|
||||
virtual ~InputBlockState()
|
||||
{}
|
||||
|
||||
virtual bool SetConfirmedTargetApzc(const RefPtr<AsyncPanZoomController>& aTargetApzc);
|
||||
virtual bool SetConfirmedTargetApzc(const RefPtr<AsyncPanZoomController>& aTargetApzc,
|
||||
TargetConfirmationState aState);
|
||||
const RefPtr<AsyncPanZoomController>& GetTargetApzc() const;
|
||||
const RefPtr<const OverscrollHandoffChain>& GetOverscrollHandoffChain() const;
|
||||
uint64_t GetBlockId() const;
|
||||
|
||||
bool IsTargetConfirmed() const;
|
||||
bool HasReceivedRealConfirmedTarget() const;
|
||||
|
||||
void SetScrolledApzc(AsyncPanZoomController* aApzc);
|
||||
AsyncPanZoomController* GetScrolledApzc() const;
|
||||
@@ -65,7 +74,7 @@ private:
|
||||
|
||||
private:
|
||||
RefPtr<AsyncPanZoomController> mTargetApzc;
|
||||
bool mTargetConfirmed;
|
||||
TargetConfirmationState mTargetConfirmed;
|
||||
const uint64_t mBlockId;
|
||||
|
||||
// The APZC that was actually scrolled by events in this input block.
|
||||
@@ -227,7 +236,8 @@ public:
|
||||
void HandleEvents() override;
|
||||
bool MustStayActive() override;
|
||||
const char* Type() override;
|
||||
bool SetConfirmedTargetApzc(const RefPtr<AsyncPanZoomController>& aTargetApzc) override;
|
||||
bool SetConfirmedTargetApzc(const RefPtr<AsyncPanZoomController>& aTargetApzc,
|
||||
TargetConfirmationState aState) override;
|
||||
|
||||
void AddEvent(const ScrollWheelInput& aEvent);
|
||||
|
||||
@@ -348,7 +358,8 @@ public:
|
||||
void HandleEvents() override;
|
||||
bool MustStayActive() override;
|
||||
const char* Type() override;
|
||||
bool SetConfirmedTargetApzc(const RefPtr<AsyncPanZoomController>& aTargetApzc) override;
|
||||
bool SetConfirmedTargetApzc(const RefPtr<AsyncPanZoomController>& aTargetApzc,
|
||||
TargetConfirmationState aState) override;
|
||||
|
||||
void AddEvent(const PanGestureInput& aEvent);
|
||||
|
||||
|
||||
@@ -118,7 +118,8 @@ InputQueue::ReceiveTouchInput(const RefPtr<AsyncPanZoomController>& aTarget,
|
||||
// from a fast fling to a pinch state (i.e. second finger goes down while
|
||||
// the first finger is moving).
|
||||
block->SetDuringFastFling();
|
||||
block->SetConfirmedTargetApzc(aTarget);
|
||||
block->SetConfirmedTargetApzc(aTarget,
|
||||
InputBlockState::TargetConfirmationState::eConfirmed);
|
||||
if (gfxPrefs::TouchActionEnabled()) {
|
||||
block->SetAllowedTouchBehaviors(currentBehaviors);
|
||||
}
|
||||
@@ -334,22 +335,25 @@ InputQueue::ReceivePanGestureInput(const RefPtr<AsyncPanZoomController>& aTarget
|
||||
block = mInputBlockQueue.LastElement()->AsPanGestureBlock();
|
||||
}
|
||||
|
||||
PanGestureInput event = aEvent;
|
||||
nsEventStatus result = nsEventStatus_eConsumeDoDefault;
|
||||
|
||||
if (!block || block->WasInterrupted()) {
|
||||
if (aEvent.mType != PanGestureInput::PANGESTURE_START) {
|
||||
// Only PANGESTURE_START events are allowed to start a new pan gesture block.
|
||||
INPQ_LOG("pangesture block %p was interrupted %d\n", block,
|
||||
block ? block->WasInterrupted() : 0);
|
||||
return nsEventStatus_eConsumeDoDefault;
|
||||
if (event.mType != PanGestureInput::PANGESTURE_START) {
|
||||
// Only PANGESTURE_START events are allowed to start a new pan gesture
|
||||
// block, but we really want to start a new block here, so we magically
|
||||
// turn this input into a PANGESTURE_START.
|
||||
INPQ_LOG("transmogrifying pan input %d to PANGESTURE_START for new block\n",
|
||||
event.mType);
|
||||
event.mType = PanGestureInput::PANGESTURE_START;
|
||||
}
|
||||
block = new PanGestureBlockState(aTarget, aTargetConfirmed, aEvent);
|
||||
block = new PanGestureBlockState(aTarget, aTargetConfirmed, event);
|
||||
INPQ_LOG("started new pan gesture block %p id %" PRIu64 " for target %p\n",
|
||||
block, block->GetBlockId(), aTarget.get());
|
||||
|
||||
if (aTargetConfirmed &&
|
||||
aEvent.mRequiresContentResponseIfCannotScrollHorizontallyInStartDirection &&
|
||||
!CanScrollTargetHorizontally(aEvent, block)) {
|
||||
event.mRequiresContentResponseIfCannotScrollHorizontallyInStartDirection &&
|
||||
!CanScrollTargetHorizontally(event, block)) {
|
||||
// This event may trigger a swipe gesture, depending on what our caller
|
||||
// wants to do it. We need to suspend handling of this block until we get
|
||||
// a content response which will tell us whether to proceed or abort the
|
||||
@@ -379,8 +383,8 @@ InputQueue::ReceivePanGestureInput(const RefPtr<AsyncPanZoomController>& aTarget
|
||||
// null) should take priority. This is equivalent to just always using the
|
||||
// target (confirmed or not) from the block, which is what
|
||||
// MaybeHandleCurrentBlock() does.
|
||||
if (!MaybeHandleCurrentBlock(block, aEvent)) {
|
||||
block->AddEvent(aEvent.AsPanGestureInput());
|
||||
if (!MaybeHandleCurrentBlock(block, event)) {
|
||||
block->AddEvent(event.AsPanGestureInput());
|
||||
}
|
||||
|
||||
return result;
|
||||
@@ -583,7 +587,9 @@ InputQueue::MainThreadTimeout(const uint64_t& aInputBlockId) {
|
||||
// target apzc in the case where the main thread doesn't get back to us
|
||||
// fast enough.
|
||||
success = mInputBlockQueue[i]->TimeoutContentResponse();
|
||||
success |= mInputBlockQueue[i]->SetConfirmedTargetApzc(mInputBlockQueue[i]->GetTargetApzc());
|
||||
success |= mInputBlockQueue[i]->SetConfirmedTargetApzc(
|
||||
mInputBlockQueue[i]->GetTargetApzc(),
|
||||
InputBlockState::TargetConfirmationState::eTimedOut);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -621,7 +627,8 @@ InputQueue::SetConfirmedTargetApzc(uint64_t aInputBlockId, const RefPtr<AsyncPan
|
||||
for (size_t i = 0; i < mInputBlockQueue.Length(); i++) {
|
||||
CancelableBlockState* block = mInputBlockQueue[i].get();
|
||||
if (block->GetBlockId() == aInputBlockId) {
|
||||
success = block->SetConfirmedTargetApzc(aTargetApzc);
|
||||
success = block->SetConfirmedTargetApzc(aTargetApzc,
|
||||
InputBlockState::TargetConfirmationState::eConfirmed);
|
||||
block->RecordContentResponseTime();
|
||||
break;
|
||||
}
|
||||
@@ -644,7 +651,8 @@ InputQueue::ConfirmDragBlock(uint64_t aInputBlockId, const RefPtr<AsyncPanZoomCo
|
||||
DragBlockState* block = mInputBlockQueue[i]->AsDragBlock();
|
||||
if (block && block->GetBlockId() == aInputBlockId) {
|
||||
block->SetDragMetrics(aDragMetrics);
|
||||
success = block->SetConfirmedTargetApzc(aTargetApzc);
|
||||
success = block->SetConfirmedTargetApzc(aTargetApzc,
|
||||
InputBlockState::TargetConfirmationState::eConfirmed);
|
||||
block->RecordContentResponseTime();
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -16,43 +16,13 @@
|
||||
#include "Units.h" // for ScreenPoint
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
class InputData;
|
||||
|
||||
namespace layers {
|
||||
|
||||
class AsyncPanZoomController;
|
||||
|
||||
/**
|
||||
* A variant of NS_INLINE_DECL_THREADSAFE_REFCOUNTING which makes the refcount
|
||||
* variable |mutable|, and the AddRef and Release methods |const|, to allow
|
||||
* using an |RefPtr<const T>|, and thereby enforcing better const-correctness.
|
||||
* This is currently here because OverscrollHandoffChain is the only thing
|
||||
* currently using it. As a follow-up, we can move this to xpcom/glue, write
|
||||
* a corresponding version for non-threadsafe refcounting, and perhaps
|
||||
* transition other clients of NS_INLINE_DECL_[THREADSAFE_]REFCOUNTING to the
|
||||
* mutable versions.
|
||||
*/
|
||||
#define NS_INLINE_DECL_THREADSAFE_MUTABLE_REFCOUNTING(_class) \
|
||||
public: \
|
||||
NS_METHOD_(MozExternalRefCountType) AddRef(void) const { \
|
||||
MOZ_ASSERT_TYPE_OK_FOR_REFCOUNTING(_class) \
|
||||
MOZ_ASSERT(int32_t(mRefCnt) >= 0, "illegal refcnt"); \
|
||||
nsrefcnt count = ++mRefCnt; \
|
||||
NS_LOG_ADDREF(const_cast<_class*>(this), count, #_class, sizeof(*this)); \
|
||||
return (nsrefcnt) count; \
|
||||
} \
|
||||
NS_METHOD_(MozExternalRefCountType) Release(void) const { \
|
||||
MOZ_ASSERT(int32_t(mRefCnt) > 0, "dup release"); \
|
||||
nsrefcnt count = --mRefCnt; \
|
||||
NS_LOG_RELEASE(const_cast<_class*>(this), count, #_class); \
|
||||
if (count == 0) { \
|
||||
delete (this); \
|
||||
return 0; \
|
||||
} \
|
||||
return count; \
|
||||
} \
|
||||
protected: \
|
||||
mutable ::mozilla::ThreadSafeAutoRefCnt mRefCnt; \
|
||||
public:
|
||||
|
||||
/**
|
||||
* This class represents the chain of APZCs along which overscroll is handed off.
|
||||
* It is created by APZCTreeManager by starting from an initial APZC which is
|
||||
@@ -71,7 +41,7 @@ public:
|
||||
// Mutable so that we can pass around the class by
|
||||
// RefPtr<const OverscrollHandoffChain> and thus enforce that, once built,
|
||||
// the chain is not modified.
|
||||
NS_INLINE_DECL_THREADSAFE_MUTABLE_REFCOUNTING(OverscrollHandoffChain)
|
||||
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(OverscrollHandoffChain)
|
||||
|
||||
/*
|
||||
* Methods for building the handoff chain.
|
||||
|
||||
@@ -1,140 +0,0 @@
|
||||
// Utilities for synthesizing of native events.
|
||||
|
||||
function getPlatform() {
|
||||
if (navigator.platform.indexOf("Win") == 0) {
|
||||
return "windows";
|
||||
}
|
||||
if (navigator.platform.indexOf("Mac") == 0) {
|
||||
return "mac";
|
||||
}
|
||||
if (navigator.platform.indexOf("Linux") == 0) {
|
||||
return "linux";
|
||||
}
|
||||
return "unknown";
|
||||
}
|
||||
|
||||
function nativeVerticalWheelEventMsg() {
|
||||
switch (getPlatform()) {
|
||||
case "windows": return 0x020A; // WM_MOUSEWHEEL
|
||||
case "mac": return 0; // value is unused, can be anything
|
||||
case "linux": return 4; // value is unused, pass GDK_SCROLL_SMOOTH anyway
|
||||
}
|
||||
throw "Native wheel events not supported on platform " + getPlatform();
|
||||
}
|
||||
|
||||
function nativeHorizontalWheelEventMsg() {
|
||||
switch (getPlatform()) {
|
||||
case "windows": return 0x020E; // WM_MOUSEHWHEEL
|
||||
case "mac": return 0; // value is unused, can be anything
|
||||
case "linux": return 4; // value is unused, pass GDK_SCROLL_SMOOTH anyway
|
||||
}
|
||||
throw "Native wheel events not supported on platform " + getPlatform();
|
||||
}
|
||||
|
||||
// Convert (aX, aY), in CSS pixels relative to aElement's bounding rect,
|
||||
// to device pixels relative to aElement's containing window.
|
||||
function coordinatesRelativeToWindow(aX, aY, aElement) {
|
||||
var targetWindow = aElement.ownerDocument.defaultView;
|
||||
var scale = targetWindow.devicePixelRatio;
|
||||
var rect = aElement.getBoundingClientRect();
|
||||
return {
|
||||
x: targetWindow.mozInnerScreenX + ((rect.left + aX) * scale),
|
||||
y: targetWindow.mozInnerScreenY + ((rect.top + aY) * scale)
|
||||
};
|
||||
}
|
||||
|
||||
// Synthesizes a native mousewheel event and returns immediately. This does not
|
||||
// guarantee anything; you probably want to use one of the other functions below
|
||||
// which actually wait for results.
|
||||
// aX and aY are relative to |window|'s top-left. aDeltaX and aDeltaY
|
||||
// are pixel deltas, and aObserver can be left undefined if not needed.
|
||||
function synthesizeNativeWheel(aElement, aX, aY, aDeltaX, aDeltaY, aObserver) {
|
||||
var pt = coordinatesRelativeToWindow(aX, aY, aElement);
|
||||
if (aDeltaX && aDeltaY) {
|
||||
throw "Simultaneous wheeling of horizontal and vertical is not supported on all platforms.";
|
||||
}
|
||||
var msg = aDeltaX ? nativeHorizontalWheelEventMsg() : nativeVerticalWheelEventMsg();
|
||||
_getDOMWindowUtils().sendNativeMouseScrollEvent(pt.x, pt.y, msg, aDeltaX, aDeltaY, 0, 0, 0, aElement, aObserver);
|
||||
return true;
|
||||
}
|
||||
|
||||
// Synthesizes a native mousewheel event and invokes the callback once the
|
||||
// request has been successfully made to the OS. This does not necessarily
|
||||
// guarantee that the OS generates the event we requested. See
|
||||
// synthesizeNativeWheel for details on the parameters.
|
||||
function synthesizeNativeWheelAndWaitForObserver(aElement, aX, aY, aDeltaX, aDeltaY, aCallback) {
|
||||
var observer = {
|
||||
observe: function(aSubject, aTopic, aData) {
|
||||
if (aCallback && aTopic == "mousescrollevent") {
|
||||
setTimeout(aCallback, 0);
|
||||
}
|
||||
}
|
||||
};
|
||||
return synthesizeNativeWheel(aElement, aX, aY, aDeltaX, aDeltaY, observer);
|
||||
}
|
||||
|
||||
// Synthesizes a native mousewheel event and invokes the callback once the
|
||||
// wheel event is dispatched to the window. See synthesizeNativeWheel for
|
||||
// details on the parameters.
|
||||
function synthesizeNativeWheelAndWaitForWheelEvent(aElement, aX, aY, aDeltaX, aDeltaY, aCallback) {
|
||||
window.addEventListener("wheel", function wheelWaiter(e) {
|
||||
window.removeEventListener("wheel", wheelWaiter);
|
||||
setTimeout(aCallback, 0);
|
||||
});
|
||||
return synthesizeNativeWheel(aElement, aX, aY, aDeltaX, aDeltaY);
|
||||
}
|
||||
|
||||
// Synthesizes a native mousewheel event and invokes the callback once the
|
||||
// first resulting scroll event is dispatched to the window.
|
||||
// See synthesizeNativeWheel for details on the parameters.
|
||||
function synthesizeNativeWheelAndWaitForScrollEvent(aElement, aX, aY, aDeltaX, aDeltaY, aCallback) {
|
||||
var useCapture = true; // scroll events don't always bubble
|
||||
window.addEventListener("scroll", function scrollWaiter(e) {
|
||||
window.removeEventListener("scroll", scrollWaiter, useCapture);
|
||||
setTimeout(aCallback, 0);
|
||||
}, useCapture);
|
||||
return synthesizeNativeWheel(aElement, aX, aY, aDeltaX, aDeltaY);
|
||||
}
|
||||
|
||||
// Synthesizes a native mouse move event and returns immediately.
|
||||
// aX and aY are relative to the top-left of |aElement|'s containing window.
|
||||
function synthesizeNativeMouseMove(aElement, aX, aY) {
|
||||
var pt = coordinatesRelativeToWindow(aX, aY, aElement);
|
||||
_getDOMWindowUtils().sendNativeMouseEvent(pt.x, pt.y, nativeMouseMoveEventMsg(), 0, aElement);
|
||||
return true;
|
||||
}
|
||||
|
||||
// Synthesizes a native mouse move event and invokes the callback once the
|
||||
// mouse move event is dispatched to |aElement|'s containing window. If the event
|
||||
// targets content in a subdocument, |aElement| should be inside the
|
||||
// subdocument. See synthesizeNativeMouseMove for details on the other
|
||||
// parameters.
|
||||
function synthesizeNativeMouseMoveAndWaitForMoveEvent(aElement, aX, aY, aCallback) {
|
||||
var targetWindow = aElement.ownerDocument.defaultView;
|
||||
targetWindow.addEventListener("mousemove", function mousemoveWaiter(e) {
|
||||
targetWindow.removeEventListener("mousemove", mousemoveWaiter);
|
||||
setTimeout(aCallback, 0);
|
||||
});
|
||||
return synthesizeNativeMouseMove(aElement, aX, aY);
|
||||
}
|
||||
|
||||
// Synthesizes a native touch event and dispatches it. aX and aY in CSS pixels
|
||||
// relative to the top-left of |aElement|'s bounding rect.
|
||||
function synthesizeNativeTouch(aElement, aX, aY, aType, aObserver = null, aTouchId = 0) {
|
||||
var pt = coordinatesRelativeToWindow(aX, aY, aElement);
|
||||
var utils = SpecialPowers.getDOMWindowUtils(aElement.ownerDocument.defaultView);
|
||||
utils.sendNativeTouchPoint(aTouchId, aType, pt.x, pt.y, 1, 90, aObserver);
|
||||
return true;
|
||||
}
|
||||
|
||||
function synthesizeNativeDrag(aElement, aX, aY, aDeltaX, aDeltaY, aObserver = null, aTouchId = 0) {
|
||||
synthesizeNativeTouch(aElement, aX, aY, SpecialPowers.DOMWindowUtils.TOUCH_CONTACT, null, aTouchId);
|
||||
var steps = Math.max(Math.abs(aDeltaX), Math.abs(aDeltaY));
|
||||
for (var i = 1; i < steps; i++) {
|
||||
var dx = i * (aDeltaX / steps);
|
||||
var dy = i * (aDeltaY / steps);
|
||||
synthesizeNativeTouch(aElement, aX + dx, aY + dy, SpecialPowers.DOMWindowUtils.TOUCH_CONTACT, null, aTouchId);
|
||||
}
|
||||
synthesizeNativeTouch(aElement, aX + aDeltaX, aY + aDeltaY, SpecialPowers.DOMWindowUtils.TOUCH_CONTACT, null, aTouchId);
|
||||
return synthesizeNativeTouch(aElement, aX + aDeltaX, aY + aDeltaY, SpecialPowers.DOMWindowUtils.TOUCH_REMOVE, aObserver, aTouchId);
|
||||
}
|
||||
@@ -1,118 +0,0 @@
|
||||
// Utilities for writing APZ tests using the framework added in bug 961289
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
// Functions that convert the APZ test data into a more usable form.
|
||||
// Every place we have a WebIDL sequence whose elements are dictionaries
|
||||
// with two elements, a key, and a value, we convert this into a JS
|
||||
// object with a property for each key/value pair. (This is the structure
|
||||
// we really want, but we can't express in directly in WebIDL.)
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
function convertEntries(entries) {
|
||||
var result = {};
|
||||
for (var i = 0; i < entries.length; ++i) {
|
||||
result[entries[i].key] = entries[i].value;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
function convertScrollFrameData(scrollFrames) {
|
||||
var result = {};
|
||||
for (var i = 0; i < scrollFrames.length; ++i) {
|
||||
result[scrollFrames[i].scrollId] = convertEntries(scrollFrames[i].entries);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
function convertBuckets(buckets) {
|
||||
var result = {};
|
||||
for (var i = 0; i < buckets.length; ++i) {
|
||||
result[buckets[i].sequenceNumber] = convertScrollFrameData(buckets[i].scrollFrames);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
function convertTestData(testData) {
|
||||
var result = {};
|
||||
result.paints = convertBuckets(testData.paints);
|
||||
result.repaintRequests = convertBuckets(testData.repaintRequests);
|
||||
return result;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
// Utilities for reconstructing the structure of the APZC tree from
|
||||
// 'parentScrollId' entries in the APZ test data.
|
||||
// ----------------------------------------------------------------
|
||||
|
||||
// Create a node with scroll id 'id' in the APZC tree.
|
||||
function makeNode(id) {
|
||||
return {scrollId: id, children: []};
|
||||
}
|
||||
|
||||
// Find a node with scroll id 'id' in the APZC tree rooted at 'root'.
|
||||
function findNode(root, id) {
|
||||
if (root.scrollId == id) {
|
||||
return root;
|
||||
}
|
||||
for (var i = 0; i < root.children.length; ++i) {
|
||||
var subtreeResult = findNode(root.children[i], id);
|
||||
if (subtreeResult != null) {
|
||||
return subtreeResult;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
// Add a child -> parent link to the APZC tree rooted at 'root'.
|
||||
function addLink(root, child, parent) {
|
||||
var parentNode = findNode(root, parent);
|
||||
if (parentNode == null) {
|
||||
parentNode = makeNode(parent);
|
||||
root.children.push(parentNode);
|
||||
}
|
||||
parentNode.children.push(makeNode(child));
|
||||
}
|
||||
|
||||
// Add a root node to the APZC tree. It will become a direct
|
||||
// child of 'root'.
|
||||
function addRoot(root, id) {
|
||||
root.children.push(makeNode(id));
|
||||
}
|
||||
|
||||
// Given APZ test data for a single paint on the compositor side,
|
||||
// reconstruct the APZC tree structure from the 'parentScrollId'
|
||||
// entries that were logged. More specifically, the subset of the
|
||||
// APZC tree structure corresponding to the layer subtree for the
|
||||
// content process that triggered the paint, is reconstructed (as
|
||||
// the APZ test data only contains information abot this subtree).
|
||||
function buildApzcTree(paint) {
|
||||
// The APZC tree can potentially have multiple root nodes,
|
||||
// so we invent a node that is the parent of all roots.
|
||||
// This 'root' does not correspond to an APZC.
|
||||
var root = makeNode(-1);
|
||||
for (var scrollId in paint) {
|
||||
if ("isRootForLayersId" in paint[scrollId]) {
|
||||
addRoot(root, scrollId);
|
||||
} else if ("parentScrollId" in paint[scrollId]) {
|
||||
addLink(root, scrollId, paint[scrollId]["parentScrollId"]);
|
||||
}
|
||||
}
|
||||
return root;
|
||||
}
|
||||
|
||||
function flushApzRepaints(aCallback, aWindow = window) {
|
||||
if (!aCallback) {
|
||||
throw "A callback must be provided!";
|
||||
}
|
||||
var repaintDone = function() {
|
||||
SpecialPowers.Services.obs.removeObserver(repaintDone, "apz-repaints-flushed", false);
|
||||
setTimeout(aCallback, 0);
|
||||
};
|
||||
SpecialPowers.Services.obs.addObserver(repaintDone, "apz-repaints-flushed", false);
|
||||
if (SpecialPowers.getDOMWindowUtils(aWindow).flushApzRepaints()) {
|
||||
dump("Flushed APZ repaints, waiting for callback...\n");
|
||||
} else {
|
||||
dump("Flushing APZ repaints was a no-op, triggering callback directly...\n");
|
||||
repaintDone();
|
||||
}
|
||||
}
|
||||
@@ -1,38 +0,0 @@
|
||||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width; initial-scale=1.0">
|
||||
<title>Sanity panning test</title>
|
||||
<script type="application/javascript" src="apz_test_native_event_utils.js"></script>
|
||||
<script type="application/javascript" src="apz_test_utils.js"></script>
|
||||
<script type="application/javascript">
|
||||
|
||||
function scrollPage() {
|
||||
SpecialPowers._addMessageListener("APZ:TransformEnd", function() {
|
||||
dump("Transform complete; flushing repaints...\n");
|
||||
flushApzRepaints(checkScroll);
|
||||
});
|
||||
|
||||
const TOUCH_SLOP = 1;
|
||||
synthesizeNativeDrag(document.body, 10, 100, 0, -(50 + TOUCH_SLOP));
|
||||
dump("Finished native drag, waiting for transform-end observer...\n");
|
||||
}
|
||||
|
||||
function checkScroll() {
|
||||
window.opener.is(window.scrollY, 50, "check that the window scrolled");
|
||||
window.opener.testDone();
|
||||
}
|
||||
|
||||
window.onload = function() {
|
||||
setTimeout(scrollPage, 0);
|
||||
}
|
||||
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
<div style="height: 5000px; background-color: lightgreen;">
|
||||
This div makes the page scrollable.
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,147 +0,0 @@
|
||||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<!--
|
||||
https://bugzilla.mozilla.org/show_bug.cgi?id=982141
|
||||
-->
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="user-scalable=no">
|
||||
<title>Test for Bug 982141, helper page</title>
|
||||
<script type="application/javascript" src="apz_test_utils.js"></script>
|
||||
<script type="application/javascript">
|
||||
|
||||
// -------------------------------------------------------------------
|
||||
// Infrastructure to get the test assertions to run at the right time.
|
||||
// -------------------------------------------------------------------
|
||||
var SimpleTest = window.opener.SimpleTest;
|
||||
|
||||
window.onload = function() {
|
||||
window.addEventListener("MozAfterPaint", afterPaint, false);
|
||||
};
|
||||
var utils = SpecialPowers.getDOMWindowUtils(window);
|
||||
function afterPaint(e) {
|
||||
// If there is another paint pending, wait for it.
|
||||
if (utils.isMozAfterPaintPending) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Once there are no more paints pending, remove the
|
||||
// MozAfterPaint listener and run the test logic.
|
||||
window.removeEventListener("MozAfterPaint", afterPaint, false);
|
||||
testBug982141();
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
// The actual logic for testing bug 982141.
|
||||
//
|
||||
// In this test we have a simple page with a scrollable <div> which has
|
||||
// enough content to make it scrollable. We test that this <div> got
|
||||
// a displayport.
|
||||
// --------------------------------------------------------------------
|
||||
|
||||
function testBug982141() {
|
||||
// Get the content- and compositor-side test data from nsIDOMWindowUtils.
|
||||
var contentTestData = utils.getContentAPZTestData();
|
||||
var compositorTestData = utils.getCompositorAPZTestData();
|
||||
|
||||
// Get the sequence number of the last paint on the compositor side.
|
||||
// We do this before converting the APZ test data because the conversion
|
||||
// loses the order of the paints.
|
||||
SimpleTest.ok(compositorTestData.paints.length > 0,
|
||||
"expected at least one paint in compositor test data");
|
||||
var lastCompositorPaint = compositorTestData.paints[compositorTestData.paints.length - 1];
|
||||
var lastCompositorPaintSeqNo = lastCompositorPaint.sequenceNumber;
|
||||
|
||||
// Convert the test data into a representation that's easier to navigate.
|
||||
contentTestData = convertTestData(contentTestData);
|
||||
compositorTestData = convertTestData(compositorTestData);
|
||||
|
||||
// Reconstruct the APZC tree structure in the last paint.
|
||||
var apzcTree = buildApzcTree(compositorTestData.paints[lastCompositorPaintSeqNo]);
|
||||
|
||||
// The apzc tree for this page should consist of a single root APZC
|
||||
// and a child APZC for the scrollable <div>.
|
||||
SimpleTest.is(apzcTree.children.length, 1, "expected a single root APZC");
|
||||
var rootApzc = apzcTree.children[0];
|
||||
SimpleTest.is(rootApzc.children.length, 1, "expected a single child APZC");
|
||||
var childScrollId = rootApzc.children[0].scrollId;
|
||||
|
||||
// We should have content-side data for the same paint.
|
||||
SimpleTest.ok(lastCompositorPaintSeqNo in contentTestData.paints,
|
||||
"expected a content paint with sequence number" + lastCompositorPaintSeqNo);
|
||||
var correspondingContentPaint = contentTestData.paints[lastCompositorPaintSeqNo];
|
||||
|
||||
// This content-side data should have a displayport for our scrollable <div>.
|
||||
SimpleTest.ok(childScrollId in correspondingContentPaint,
|
||||
"expected scroll frame data for scroll id " + childScrollId);
|
||||
SimpleTest.ok("displayport" in correspondingContentPaint[childScrollId],
|
||||
"expected a displayport for scroll id " + childScrollId);
|
||||
var childDisplayport = correspondingContentPaint[childScrollId]["displayport"];
|
||||
var dpFields = childDisplayport.replace(/[()\s]+/g, '').split(',');
|
||||
SimpleTest.is(dpFields.length, 4, "expected displayport string of form (x,y,w,h)");
|
||||
var dpWidth = dpFields[2];
|
||||
var dpHeight = dpFields[3];
|
||||
SimpleTest.ok(dpWidth >= 50 && dpHeight >= 50,
|
||||
"expected a displayport at least as large as the scrollable element");
|
||||
|
||||
window.opener.finishTest();
|
||||
}
|
||||
</script>
|
||||
</head>
|
||||
<body style="overflow: hidden;"><!-- This combined with the user-scalable=no ensures the root frame is not scrollable -->
|
||||
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=982141">Mozilla Bug 982141</a>
|
||||
<!-- A scrollable subframe, with enough content to make it have a nonzero scroll range -->
|
||||
<div style="height: 50px; width: 50px; overflow: scroll">
|
||||
Line 1<br>
|
||||
Line 2<br>
|
||||
Line 3<br>
|
||||
Line 4<br>
|
||||
Line 5<br>
|
||||
Line 6<br>
|
||||
Line 7<br>
|
||||
Line 8<br>
|
||||
Line 9<br>
|
||||
Line 10<br>
|
||||
Line 11<br>
|
||||
Line 12<br>
|
||||
Line 13<br>
|
||||
Line 14<br>
|
||||
Line 15<br>
|
||||
Line 16<br>
|
||||
Line 17<br>
|
||||
Line 18<br>
|
||||
Line 19<br>
|
||||
Line 20<br>
|
||||
Line 21<br>
|
||||
Line 22<br>
|
||||
Line 23<br>
|
||||
Line 24<br>
|
||||
Line 25<br>
|
||||
Line 26<br>
|
||||
Line 27<br>
|
||||
Line 28<br>
|
||||
Line 29<br>
|
||||
Line 30<br>
|
||||
Line 31<br>
|
||||
Line 32<br>
|
||||
Line 33<br>
|
||||
Line 34<br>
|
||||
Line 35<br>
|
||||
Line 36<br>
|
||||
Line 37<br>
|
||||
Line 38<br>
|
||||
Line 39<br>
|
||||
Line 40<br>
|
||||
Line 41<br>
|
||||
Line 42<br>
|
||||
Line 43<br>
|
||||
Line 44<br>
|
||||
Line 45<br>
|
||||
Line 46<br>
|
||||
Line 40<br>
|
||||
Line 48<br>
|
||||
Line 49<br>
|
||||
Line 50<br>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,44 +0,0 @@
|
||||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width; initial-scale=1.0">
|
||||
<title>Sanity panning test for scrollable div</title>
|
||||
<script type="application/javascript" src="apz_test_native_event_utils.js"></script>
|
||||
<script type="application/javascript" src="apz_test_utils.js"></script>
|
||||
<script type="application/javascript">
|
||||
|
||||
function scrollOuter() {
|
||||
SpecialPowers._addMessageListener("APZ:TransformEnd", function() {
|
||||
dump("Transform complete; flushing repaints...\n");
|
||||
flushApzRepaints(checkScroll);
|
||||
});
|
||||
|
||||
const TOUCH_SLOP = 1;
|
||||
synthesizeNativeDrag(document.getElementById('outer'), 10, 100, 0, -(50 + TOUCH_SLOP));
|
||||
dump("Finished native drag, waiting for transform-end observer...\n");
|
||||
}
|
||||
|
||||
function checkScroll() {
|
||||
var outerScroll = document.getElementById('outer').scrollTop;
|
||||
window.opener.is(outerScroll, 50, "check that the div scrolled");
|
||||
window.opener.testDone();
|
||||
}
|
||||
|
||||
window.onload = function() {
|
||||
setTimeout(scrollOuter, 0);
|
||||
}
|
||||
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
<div id="outer" style="height: 250px; border: solid 1px black; overflow:scroll">
|
||||
<div style="height: 5000px; background-color: lightblue">
|
||||
This div makes the |outer| div scrollable.
|
||||
</div>
|
||||
</div>
|
||||
<div style="height: 5000px; background-color: lightgreen;">
|
||||
This div makes the top-level page scrollable.
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,14 +0,0 @@
|
||||
<!DOCTYPE HTML>
|
||||
<!-- The purpose of the 'id' on the HTML element is to get something
|
||||
identifiable to show up in the root scroll frame's content description,
|
||||
so we can check it for layerization. -->
|
||||
<html id="outer3">
|
||||
<head>
|
||||
<link rel="stylesheet" type="text/css" href="helper_subframe_style.css"/>
|
||||
</head>
|
||||
<body>
|
||||
<div id="inner3" class="inner-frame">
|
||||
<div class="inner-content"></div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,14 +0,0 @@
|
||||
<!DOCTYPE HTML>
|
||||
<!-- The purpose of the 'id' on the HTML element is to get something
|
||||
identifiable to show up in the root scroll frame's content description,
|
||||
so we can check it for layerization. -->
|
||||
<html id="outer4">
|
||||
<head>
|
||||
<link rel="stylesheet" type="text/css" href="helper_subframe_style.css"/>
|
||||
</head>
|
||||
<body>
|
||||
<div id="inner4" class="inner-frame">
|
||||
<div class="inner-content"></div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,41 +0,0 @@
|
||||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width; initial-scale=1.0">
|
||||
<title>Sanity panning test for scrollable div</title>
|
||||
<script type="application/javascript" src="apz_test_native_event_utils.js"></script>
|
||||
<script type="application/javascript" src="apz_test_utils.js"></script>
|
||||
<script type="application/javascript">
|
||||
|
||||
function scrollOuter() {
|
||||
var outer = document.getElementById('outer');
|
||||
SpecialPowers._addMessageListener("APZ:TransformEnd", function() {
|
||||
dump("Transform complete; flushing repaints...\n");
|
||||
flushApzRepaints(checkScroll, outer.contentWindow);
|
||||
});
|
||||
|
||||
const TOUCH_SLOP = 1;
|
||||
synthesizeNativeDrag(outer.contentDocument.body, 10, 100, 0, -(50 + TOUCH_SLOP));
|
||||
dump("Finished native drag, waiting for transform-end observer...\n");
|
||||
}
|
||||
|
||||
function checkScroll() {
|
||||
var outerScroll = document.getElementById('outer').contentWindow.scrollY;
|
||||
window.opener.is(outerScroll, 50, "check that the iframe scrolled");
|
||||
window.opener.testDone();
|
||||
}
|
||||
|
||||
window.onload = function() {
|
||||
setTimeout(scrollOuter, 0);
|
||||
}
|
||||
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
<iframe id="outer" style="height: 250px; border: solid 1px black" src="data:text/html,<body style='height:5000px'>"></iframe>
|
||||
<div style="height: 5000px; background-color: lightgreen;">
|
||||
This div makes the top-level page scrollable.
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,15 +0,0 @@
|
||||
body {
|
||||
height: 500px;
|
||||
}
|
||||
|
||||
.inner-frame {
|
||||
margin-top: 25%;
|
||||
height: 200%;
|
||||
width: 75%;
|
||||
overflow: scroll;
|
||||
}
|
||||
.inner-content {
|
||||
height: 200%;
|
||||
width: 200%;
|
||||
background: repeating-linear-gradient(#EEE, #EEE 100px, #DDD 100px, #DDD 200px);
|
||||
}
|
||||
@@ -1,8 +0,0 @@
|
||||
[DEFAULT]
|
||||
support-files = apz_test_utils.js
|
||||
[test_bug982141.html]
|
||||
skip-if = toolkit != 'gonk' # bug 991198
|
||||
support-files = helper_bug982141.html
|
||||
[test_bug1151663.html]
|
||||
skip-if = toolkit != 'gonk' # bug 991198
|
||||
support-files = helper_bug1151663.html
|
||||
@@ -31,19 +31,56 @@ function nativeHorizontalWheelEventMsg() {
|
||||
throw "Native wheel events not supported on platform " + getPlatform();
|
||||
}
|
||||
|
||||
// Given a pixel scrolling delta, converts it to the platform's native units.
|
||||
function nativeScrollUnits(aElement, aDimen) {
|
||||
switch (getPlatform()) {
|
||||
case "linux": {
|
||||
// GTK deltas are treated as line height divided by 3 by gecko.
|
||||
var targetWindow = aElement.ownerDocument.defaultView;
|
||||
var lineHeight = targetWindow.getComputedStyle(aElement)["font-size"];
|
||||
return aDimen / (parseInt(lineHeight) * 3);
|
||||
}
|
||||
}
|
||||
return aDimen;
|
||||
}
|
||||
|
||||
function nativeMouseMoveEventMsg() {
|
||||
switch (getPlatform()) {
|
||||
case "windows": return 1; // MOUSEEVENTF_MOVE
|
||||
case "mac": return 5; // NSMouseMoved
|
||||
case "linux": return 3; // GDK_MOTION_NOTIFY
|
||||
}
|
||||
throw "Native wheel events not supported on platform " + getPlatform();
|
||||
}
|
||||
|
||||
// Convert (aX, aY), in CSS pixels relative to aElement's bounding rect,
|
||||
// to device pixels relative to aElement's containing window.
|
||||
function coordinatesRelativeToWindow(aX, aY, aElement) {
|
||||
var targetWindow = aElement.ownerDocument.defaultView;
|
||||
var scale = targetWindow.devicePixelRatio;
|
||||
var rect = aElement.getBoundingClientRect();
|
||||
return {
|
||||
x: (targetWindow.mozInnerScreenX + rect.left + aX) * scale,
|
||||
y: (targetWindow.mozInnerScreenY + rect.top + aY) * scale
|
||||
};
|
||||
}
|
||||
|
||||
// Synthesizes a native mousewheel event and returns immediately. This does not
|
||||
// guarantee anything; you probably want to use one of the other functions below
|
||||
// which actually wait for results.
|
||||
// aX and aY are relative to |window|'s top-left. aDeltaX and aDeltaY
|
||||
// are pixel deltas, and aObserver can be left undefined if not needed.
|
||||
// aX and aY are relative to the top-left of |aElement|'s containing window.
|
||||
// aDeltaX and aDeltaY are pixel deltas, and aObserver can be left undefined
|
||||
// if not needed.
|
||||
function synthesizeNativeWheel(aElement, aX, aY, aDeltaX, aDeltaY, aObserver) {
|
||||
aX += window.mozInnerScreenX;
|
||||
aY += window.mozInnerScreenY;
|
||||
var pt = coordinatesRelativeToWindow(aX, aY, aElement);
|
||||
if (aDeltaX && aDeltaY) {
|
||||
throw "Simultaneous wheeling of horizontal and vertical is not supported on all platforms.";
|
||||
}
|
||||
aDeltaX = nativeScrollUnits(aElement, aDeltaX);
|
||||
aDeltaY = nativeScrollUnits(aElement, aDeltaY);
|
||||
var msg = aDeltaX ? nativeHorizontalWheelEventMsg() : nativeVerticalWheelEventMsg();
|
||||
_getDOMWindowUtils().sendNativeMouseScrollEvent(aX, aY, msg, aDeltaX, aDeltaY, 0, 0, 0, aElement, aObserver);
|
||||
var utils = SpecialPowers.getDOMWindowUtils(aElement.ownerDocument.defaultView);
|
||||
utils.sendNativeMouseScrollEvent(pt.x, pt.y, msg, aDeltaX, aDeltaY, 0, 0, 0, aElement, aObserver);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -63,13 +100,80 @@ function synthesizeNativeWheelAndWaitForObserver(aElement, aX, aY, aDeltaX, aDel
|
||||
}
|
||||
|
||||
// Synthesizes a native mousewheel event and invokes the callback once the
|
||||
// wheel event is dispatched to the window. See synthesizeNativeWheel for
|
||||
// details on the parameters.
|
||||
function synthesizeNativeWheelAndWaitForEvent(aElement, aX, aY, aDeltaX, aDeltaY, aCallback) {
|
||||
window.addEventListener("wheel", function wheelWaiter(e) {
|
||||
window.removeEventListener("wheel", wheelWaiter);
|
||||
// wheel event is dispatched to |aElement|'s containing window. If the event
|
||||
// targets content in a subdocument, |aElement| should be inside the
|
||||
// subdocument. See synthesizeNativeWheel for details on the other parameters.
|
||||
function synthesizeNativeWheelAndWaitForWheelEvent(aElement, aX, aY, aDeltaX, aDeltaY, aCallback) {
|
||||
var targetWindow = aElement.ownerDocument.defaultView;
|
||||
targetWindow.addEventListener("wheel", function wheelWaiter(e) {
|
||||
targetWindow.removeEventListener("wheel", wheelWaiter);
|
||||
setTimeout(aCallback, 0);
|
||||
});
|
||||
return synthesizeNativeWheel(aElement, aX, aY, aDeltaX, aDeltaY);
|
||||
}
|
||||
|
||||
// Synthesizes a native mousewheel event and invokes the callback once the
|
||||
// first resulting scroll event is dispatched to |aElement|'s containing window.
|
||||
// If the event targets content in a subdocument, |aElement| should be inside
|
||||
// the subdocument. See synthesizeNativeWheel for details on the other
|
||||
// parameters.
|
||||
function synthesizeNativeWheelAndWaitForScrollEvent(aElement, aX, aY, aDeltaX, aDeltaY, aCallback) {
|
||||
var targetWindow = aElement.ownerDocument.defaultView;
|
||||
var useCapture = true; // scroll events don't always bubble
|
||||
targetWindow.addEventListener("scroll", function scrollWaiter(e) {
|
||||
targetWindow.removeEventListener("scroll", scrollWaiter, useCapture);
|
||||
setTimeout(aCallback, 0);
|
||||
}, useCapture);
|
||||
return synthesizeNativeWheel(aElement, aX, aY, aDeltaX, aDeltaY);
|
||||
}
|
||||
|
||||
// Synthesizes a native mouse move event and returns immediately.
|
||||
// aX and aY are relative to the top-left of |aElement|'s containing window.
|
||||
function synthesizeNativeMouseMove(aElement, aX, aY) {
|
||||
var pt = coordinatesRelativeToWindow(aX, aY, aElement);
|
||||
var utils = SpecialPowers.getDOMWindowUtils(aElement.ownerDocument.defaultView);
|
||||
utils.sendNativeMouseEvent(pt.x, pt.y, nativeMouseMoveEventMsg(), 0, aElement);
|
||||
return true;
|
||||
}
|
||||
|
||||
// Synthesizes a native mouse move event and invokes the callback once the
|
||||
// mouse move event is dispatched to |aElement|'s containing window. If the event
|
||||
// targets content in a subdocument, |aElement| should be inside the
|
||||
// subdocument. See synthesizeNativeMouseMove for details on the other
|
||||
// parameters.
|
||||
function synthesizeNativeMouseMoveAndWaitForMoveEvent(aElement, aX, aY, aCallback) {
|
||||
var targetWindow = aElement.ownerDocument.defaultView;
|
||||
targetWindow.addEventListener("mousemove", function mousemoveWaiter(e) {
|
||||
targetWindow.removeEventListener("mousemove", mousemoveWaiter);
|
||||
setTimeout(aCallback, 0);
|
||||
});
|
||||
return synthesizeNativeMouseMove(aElement, aX, aY);
|
||||
}
|
||||
|
||||
// Synthesizes a native touch event and dispatches it. aX and aY in CSS pixels
|
||||
// relative to the top-left of |aElement|'s bounding rect.
|
||||
function synthesizeNativeTouch(aElement, aX, aY, aType, aObserver = null, aTouchId = 0) {
|
||||
var pt = coordinatesRelativeToWindow(aX, aY, aElement);
|
||||
var utils = SpecialPowers.getDOMWindowUtils(aElement.ownerDocument.defaultView);
|
||||
utils.sendNativeTouchPoint(aTouchId, aType, pt.x, pt.y, 1, 90, aObserver);
|
||||
return true;
|
||||
}
|
||||
|
||||
function synthesizeNativeDrag(aElement, aX, aY, aDeltaX, aDeltaY, aObserver = null, aTouchId = 0) {
|
||||
synthesizeNativeTouch(aElement, aX, aY, SpecialPowers.DOMWindowUtils.TOUCH_CONTACT, null, aTouchId);
|
||||
var steps = Math.max(Math.abs(aDeltaX), Math.abs(aDeltaY));
|
||||
for (var i = 1; i < steps; i++) {
|
||||
var dx = i * (aDeltaX / steps);
|
||||
var dy = i * (aDeltaY / steps);
|
||||
synthesizeNativeTouch(aElement, aX + dx, aY + dy, SpecialPowers.DOMWindowUtils.TOUCH_CONTACT, null, aTouchId);
|
||||
}
|
||||
synthesizeNativeTouch(aElement, aX + aDeltaX, aY + aDeltaY, SpecialPowers.DOMWindowUtils.TOUCH_CONTACT, null, aTouchId);
|
||||
return synthesizeNativeTouch(aElement, aX + aDeltaX, aY + aDeltaY, SpecialPowers.DOMWindowUtils.TOUCH_REMOVE, aObserver, aTouchId);
|
||||
}
|
||||
|
||||
function synthesizeNativeTap(aElement, aX, aY, aObserver = null) {
|
||||
var pt = coordinatesRelativeToWindow(aX, aY, aElement);
|
||||
var utils = SpecialPowers.getDOMWindowUtils(aElement.ownerDocument.defaultView);
|
||||
utils.sendNativeTouchTap(pt.x, pt.y, false, aObserver);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -97,3 +97,26 @@ function flushApzRepaints(aCallback, aWindow = window) {
|
||||
repaintDone();
|
||||
}
|
||||
}
|
||||
|
||||
// Flush repaints, APZ pending repaints, and any repaints resulting from that
|
||||
// flush. This is particularly useful if the test needs to reach some sort of
|
||||
// "idle" state in terms of repaints. Usually just doing waitForAllPaints
|
||||
// followed by flushApzRepaints is sufficient to flush all APZ state back to
|
||||
// the main thread, but it can leave a paint scheduled which will get triggered
|
||||
// at some later time. For tests that specifically test for painting at
|
||||
// specific times, this method is the way to go. Even if in doubt, this is the
|
||||
// preferred method as the extra step is "safe" and shouldn't interfere with
|
||||
// most tests.
|
||||
function waitForApzFlushedRepaints(aCallback) {
|
||||
// First flush the main-thread paints and send transactions to the APZ
|
||||
waitForAllPaints(function() {
|
||||
// Then flush the APZ to make sure any repaint requests have been sent
|
||||
// back to the main thread
|
||||
flushApzRepaints(function() {
|
||||
// Then flush the main-thread again to process the repaint requests.
|
||||
// Once this is done, we should be in a stable state with nothing
|
||||
// pending, so we can trigger the callback.
|
||||
waitForAllPaints(aCallback);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
+7
-5
@@ -55,15 +55,17 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=1151663
|
||||
// Convert the test data into a representation that's easier to navigate.
|
||||
contentTestData = convertTestData(contentTestData);
|
||||
compositorTestData = convertTestData(compositorTestData);
|
||||
var paint = compositorTestData.paints[lastCompositorPaintSeqNo];
|
||||
|
||||
// Reconstruct the APZC tree structure in the last paint.
|
||||
var apzcTree = buildApzcTree(compositorTestData.paints[lastCompositorPaintSeqNo]);
|
||||
var apzcTree = buildApzcTree(paint);
|
||||
|
||||
// The apzc tree for this page should consist of a single root APZC,
|
||||
// and no child APZCs.
|
||||
SimpleTest.is(apzcTree.children.length, 1, "expected a single root APZC");
|
||||
var rootApzc = apzcTree.children[0];
|
||||
SimpleTest.is(rootApzc.children.length, 0, "expected no child APZCs");
|
||||
// which either is the RCD with no child APZCs (e10s/B2G case) or has a
|
||||
// single child APZC which is for the RCD (fennec case).
|
||||
var rcd = findRcdNode(apzcTree);
|
||||
SimpleTest.ok(rcd != null, "found the RCD node");
|
||||
SimpleTest.is(rcd.children.length, 0, "expected no children on the RCD");
|
||||
|
||||
window.opener.finishTest();
|
||||
}
|
||||
@@ -5,6 +5,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=982141
|
||||
-->
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="user-scalable=no">
|
||||
<title>Test for Bug 982141, helper page</title>
|
||||
<script type="application/javascript" src="apz_test_utils.js"></script>
|
||||
<script type="application/javascript">
|
||||
@@ -58,12 +59,13 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=982141
|
||||
// Reconstruct the APZC tree structure in the last paint.
|
||||
var apzcTree = buildApzcTree(compositorTestData.paints[lastCompositorPaintSeqNo]);
|
||||
|
||||
// The apzc tree for this page should consist of a single root APZC
|
||||
// and a child APZC for the scrollable <div>.
|
||||
SimpleTest.is(apzcTree.children.length, 1, "expected a single root APZC");
|
||||
var rootApzc = apzcTree.children[0];
|
||||
SimpleTest.is(rootApzc.children.length, 1, "expected a single child APZC");
|
||||
var childScrollId = rootApzc.children[0].scrollId;
|
||||
// The apzc tree for this page should consist of a single child APZC on
|
||||
// the RCD node (the child is for scrollable <div>). Note that in e10s/B2G
|
||||
// cases the RCD will be the root of the tree but on Fennec it will not.
|
||||
var rcd = findRcdNode(apzcTree);
|
||||
SimpleTest.ok(rcd != null, "found the RCD node");
|
||||
SimpleTest.is(rcd.children.length, 1, "expected a single child APZC");
|
||||
var childScrollId = rcd.children[0].scrollId;
|
||||
|
||||
// We should have content-side data for the same paint.
|
||||
SimpleTest.ok(lastCompositorPaintSeqNo in contentTestData.paints,
|
||||
@@ -80,17 +82,27 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=982141
|
||||
SimpleTest.is(dpFields.length, 4, "expected displayport string of form (x,y,w,h)");
|
||||
var dpWidth = dpFields[2];
|
||||
var dpHeight = dpFields[3];
|
||||
SimpleTest.ok(dpWidth >= 50 && dpHeight >= 50,
|
||||
"expected a displayport at least as large as the scrollable element");
|
||||
var subframe = document.getElementById('subframe');
|
||||
// The clientWidth and clientHeight may be less than 50 if there are scrollbars showing.
|
||||
// In general they will be (50 - <scrollbarwidth>, 50 - <scrollbarheight>).
|
||||
SimpleTest.ok(subframe.clientWidth > 0, "Expected a non-zero clientWidth, got: " + subframe.clientWidth);
|
||||
SimpleTest.ok(subframe.clientHeight > 0, "Expected a non-zero clientHeight, got: " + subframe.clientHeight);
|
||||
SimpleTest.ok(dpWidth >= subframe.clientWidth && dpHeight >= subframe.clientHeight,
|
||||
"expected a displayport at least as large as the scrollable element, got " + childDisplayport);
|
||||
|
||||
window.opener.finishTest();
|
||||
}
|
||||
</script>
|
||||
</head>
|
||||
<body style="overflow: hidden;"><!-- Make sure the root frame is not scrollable -->
|
||||
<body style="overflow: hidden;"><!-- This combined with the user-scalable=no ensures the root frame is not scrollable -->
|
||||
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=982141">Mozilla Bug 982141</a>
|
||||
<!-- A scrollable subframe, with enough content to make it have a nonzero scroll range -->
|
||||
<div style="height: 50px; width: 50px; overflow: scroll">
|
||||
<div id="subframe" style="height: 50px; width: 50px; overflow: scroll">
|
||||
<div style="width: 100px">
|
||||
Wide content so that the vertical scrollbar for the parent div
|
||||
doesn't eat into the 50px width and reduce the width of the
|
||||
displayport.
|
||||
</div>
|
||||
Line 1<br>
|
||||
Line 2<br>
|
||||
Line 3<br>
|
||||
|
||||
@@ -0,0 +1,70 @@
|
||||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width; initial-scale=1.0">
|
||||
<title>Sanity touch-tapping test</title>
|
||||
<script type="application/javascript" src="apz_test_native_event_utils.js"></script>
|
||||
<script type="application/javascript" src="apz_test_utils.js"></script>
|
||||
<script type="application/javascript" src="/tests/SimpleTest/paint_listener.js"></script>
|
||||
<script type="application/javascript">
|
||||
|
||||
function startTest() {
|
||||
if (window.scrollY == 0) {
|
||||
// the scrollframe is not yet marked as APZ-scrollable. Mark it so and
|
||||
// start over.
|
||||
window.scrollTo(0, 1);
|
||||
waitForApzFlushedRepaints(startTest);
|
||||
return;
|
||||
}
|
||||
|
||||
// This is a scroll by 20px that should use paint-skipping if possible.
|
||||
// If paint-skipping is enabled, this should not trigger a paint, but go
|
||||
// directly to the compositor using an empty transaction. We check for this
|
||||
// by ensuring the document element did not get painted.
|
||||
var utils = window.opener.SpecialPowers.getDOMWindowUtils(window);
|
||||
var elem = document.documentElement;
|
||||
var skipping = location.search == '?true';
|
||||
utils.checkAndClearPaintedState(elem);
|
||||
window.scrollTo(0, 20);
|
||||
waitForAllPaints(function() {
|
||||
if (skipping) {
|
||||
window.opener.is(utils.checkAndClearPaintedState(elem), false, "Document element didn't get painted");
|
||||
}
|
||||
// After that's done, we click on the button to make sure the
|
||||
// skipped-paint codepath still has working APZ event transformations.
|
||||
clickButton();
|
||||
});
|
||||
}
|
||||
|
||||
function clickButton() {
|
||||
if (!window.TouchEvent) {
|
||||
window.opener.ok(true, "Touch events are not supported on this platform, sorry!\n");
|
||||
window.opener.testDone();
|
||||
return;
|
||||
}
|
||||
|
||||
document.addEventListener('click', clicked, false);
|
||||
|
||||
synthesizeNativeTap(document.getElementById('b'), 5, 5, function() {
|
||||
dump("Finished synthesizing tap, waiting for button to be clicked...\n");
|
||||
});
|
||||
}
|
||||
|
||||
function clicked(e) {
|
||||
window.opener.is(e.target, document.getElementById('b'), "Clicked on button, yay! (at " + e.clientX + "," + e.clientY + ")");
|
||||
window.opener.testDone();
|
||||
}
|
||||
|
||||
window.onload = function() {
|
||||
waitForAllPaints(function() {
|
||||
flushApzRepaints(startTest);
|
||||
});
|
||||
}
|
||||
</script>
|
||||
</head>
|
||||
<body style="height: 5000px">
|
||||
<div style="height: 50px">spacer</div>
|
||||
<button id="b" style="width: 10px; height: 10px"></button>
|
||||
</body>
|
||||
</html>
|
||||
@@ -3,7 +3,7 @@ body {
|
||||
}
|
||||
|
||||
.inner-frame {
|
||||
margin-top: 25%;
|
||||
margin-top: 50px; /* this should be at least 30px */
|
||||
height: 200%;
|
||||
width: 75%;
|
||||
overflow: scroll;
|
||||
|
||||
@@ -0,0 +1,42 @@
|
||||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width; initial-scale=1.0">
|
||||
<title>Sanity touch-tapping test</title>
|
||||
<script type="application/javascript" src="apz_test_native_event_utils.js"></script>
|
||||
<script type="application/javascript" src="apz_test_utils.js"></script>
|
||||
<script type="application/javascript" src="/tests/SimpleTest/paint_listener.js"></script>
|
||||
<script type="application/javascript">
|
||||
|
||||
function clickButton() {
|
||||
if (!window.TouchEvent) {
|
||||
window.opener.ok(true, "Touch events are not supported on this platform, sorry!\n");
|
||||
window.opener.testDone();
|
||||
return;
|
||||
}
|
||||
|
||||
document.addEventListener('click', clicked, false);
|
||||
|
||||
synthesizeNativeTap(document.getElementById('b'), 5, 5, function() {
|
||||
dump("Finished synthesizing tap, waiting for button to be clicked...\n");
|
||||
});
|
||||
}
|
||||
|
||||
function clicked(e) {
|
||||
window.opener.is(e.target, document.getElementById('b'), "Clicked on button, yay! (at " + e.clientX + "," + e.clientY + ")");
|
||||
window.opener.testDone();
|
||||
}
|
||||
|
||||
window.onload = function() {
|
||||
waitForAllPaints(function() {
|
||||
flushApzRepaints(clickButton);
|
||||
});
|
||||
}
|
||||
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
<button id="b" style="width: 10px; height: 10px"></button>
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,17 +1,22 @@
|
||||
[test_bug982141.html]
|
||||
skip-if = toolkit != 'gonk' # bug 991198
|
||||
[DEFAULT]
|
||||
support-files =
|
||||
apz_test_utils.js
|
||||
apz_test_native_event_utils.js
|
||||
helper_bug982141.html
|
||||
helper_bug1151663.html
|
||||
helper_iframe1.html
|
||||
helper_iframe2.html
|
||||
helper_subframe_style.css
|
||||
helper_basic_pan.html
|
||||
helper_div_pan.html
|
||||
helper_iframe_pan.html
|
||||
helper_scrollto_tap.html
|
||||
helper_tap.html
|
||||
tags = apz
|
||||
[test_bug982141.html]
|
||||
[test_bug1151663.html]
|
||||
[test_wheel_scroll.html]
|
||||
skip-if = (os == 'android') || (os == 'b2g') # wheel events not supported
|
||||
skip-if = (os == 'android') || (os == 'b2g') || (buildapp == 'mulet') # wheel events not supported on mobile; see bug 1164274 for mulet
|
||||
[test_wheel_transactions.html]
|
||||
skip-if = (os == 'android') || (os == 'b2g') || (buildapp == 'mulet') # wheel events not supported on mobile; see bug 1164274 for mulet
|
||||
[test_bug1151667.html]
|
||||
@@ -28,3 +33,8 @@ skip-if = (os == 'android') || (os == 'b2g') || (buildapp == 'mulet') # wheel ev
|
||||
skip-if = (os == 'android') || (os == 'b2g') || (buildapp == 'mulet') # wheel events not supported on mobile; see bug 1164274 for mulet
|
||||
[test_scroll_subframe_scrollbar.html]
|
||||
skip-if = (os == 'android') || (os == 'b2g') || (buildapp == 'mulet') # wheel events not supported on mobile; see bug 1164274 for mulet
|
||||
[test_frame_reconstruction.html]
|
||||
[test_tap.html]
|
||||
# Windows touch injection doesn't work in automation, but this test can be run locally on a windows touch device.
|
||||
# On OS X we don't support touch events at all.
|
||||
skip-if = (toolkit == 'windows') || (toolkit == 'cocoa')
|
||||
|
||||
@@ -8,7 +8,6 @@
|
||||
<script type="application/javascript">
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
SimpleTest.testInChaosMode();
|
||||
|
||||
// this page just serially loads each one of the following test helper pages in
|
||||
// a new window and waits for it to call testDone()
|
||||
@@ -53,12 +52,19 @@ window.onload = function() {
|
||||
["apz.touch_start_tolerance", "0.0"],
|
||||
// The touchstart from the drag can turn into a long-tap if the touch-move
|
||||
// events get held up. Try to prevent that by making long-taps require
|
||||
// a 10 second hold.
|
||||
["ui.click_hold_context_menus.delay", "10000"],
|
||||
// a 10 second hold. Note that we also cannot enable chaos mode on this
|
||||
// test for this reason, since chaos mode can cause the long-press timer
|
||||
// to fire sooner than the pref dictates.
|
||||
["ui.click_hold_context_menus.delay", 10000],
|
||||
// The subtests in this test do touch-drags to pan the page, but we don't
|
||||
// want those pans to turn into fling animations, so we increase the
|
||||
// fling-stop threshold velocity to absurdly high.
|
||||
["apz.fling_stopped_threshold", "10000"],
|
||||
// The helper_div_pan's div gets a displayport on scroll, but if the
|
||||
// test takes too long the displayport can expire before the new scroll
|
||||
// position is synced back to the main thread. So we disable displayport
|
||||
// expiry for these tests.
|
||||
["apz.displayport_expiry_ms", 0],
|
||||
]
|
||||
}, testDone);
|
||||
};
|
||||
|
||||
+5
@@ -17,6 +17,11 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=1151663
|
||||
// inside an iframe which means we have no control over the root APZC.
|
||||
var w = null;
|
||||
window.onload = function() {
|
||||
if (!SpecialPowers.getDOMWindowUtils(window).asyncPanZoomEnabled) {
|
||||
ok(true, "APZ is not enabled, this test is not relevant, sorry!\n");
|
||||
SimpleTest.finish();
|
||||
return;
|
||||
}
|
||||
SpecialPowers.pushPrefEnv({"set": [["apz.test.logging_enabled", true]]}, function() {
|
||||
w = window.open("helper_bug1151663.html", "_blank");
|
||||
});
|
||||
@@ -17,7 +17,14 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=982141
|
||||
// inside an iframe which means we have no control over the root APZC.
|
||||
var w = null;
|
||||
window.onload = function() {
|
||||
w = window.open("helper_bug982141.html", "_blank");
|
||||
if (!SpecialPowers.getDOMWindowUtils(window).asyncPanZoomEnabled) {
|
||||
ok(true, "APZ is not enabled, this test is not relevant, sorry!\n");
|
||||
SimpleTest.finish();
|
||||
return;
|
||||
}
|
||||
SpecialPowers.pushPrefEnv({"set": [["apz.test.logging_enabled", true]]}, function() {
|
||||
w = window.open("helper_bug982141.html", "_blank");
|
||||
});
|
||||
};
|
||||
|
||||
function finishTest() {
|
||||
|
||||
@@ -0,0 +1,231 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<!--
|
||||
https://bugzilla.mozilla.org/show_bug.cgi?id=1235899
|
||||
-->
|
||||
<head>
|
||||
<title>Test for bug 1235899</title>
|
||||
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<script type="application/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
|
||||
<script type="application/javascript" src="/tests/SimpleTest/paint_listener.js"></script>
|
||||
<script type="application/javascript" src="apz_test_utils.js"></script>
|
||||
<script type="application/javascript" src="apz_test_native_event_utils.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
|
||||
<style>
|
||||
.outer {
|
||||
height: 400px;
|
||||
width: 415px;
|
||||
overflow: hidden;
|
||||
position: relative;
|
||||
}
|
||||
.inner {
|
||||
height: 100%;
|
||||
outline: none;
|
||||
overflow-x: hidden;
|
||||
overflow-y: scroll;
|
||||
position: relative;
|
||||
scroll-behavior: smooth;
|
||||
}
|
||||
.outer.contentBefore::before {
|
||||
top: 0;
|
||||
content: '';
|
||||
display: block;
|
||||
height: 2px;
|
||||
position: absolute;
|
||||
width: 100%;
|
||||
z-index: 99;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1235899">Mozilla Bug 1235899</a>
|
||||
<p id="display"></p>
|
||||
<div id="content">
|
||||
<p>You should be able to fling this list without it stopping abruptly</p>
|
||||
<div class="outer">
|
||||
<div class="inner">
|
||||
<ol>
|
||||
<li>Some text</li>
|
||||
<li>Some text</li>
|
||||
<li>Some text</li>
|
||||
<li>Some text</li>
|
||||
<li>Some text</li>
|
||||
<li>Some text</li>
|
||||
<li>Some text</li>
|
||||
<li>Some text</li>
|
||||
<li>Some text</li>
|
||||
<li>Some text</li>
|
||||
<li>Some text</li>
|
||||
<li>Some text</li>
|
||||
<li>Some text</li>
|
||||
<li>Some text</li>
|
||||
<li>Some text</li>
|
||||
<li>Some text</li>
|
||||
<li>Some text</li>
|
||||
<li>Some text</li>
|
||||
<li>Some text</li>
|
||||
<li>Some text</li>
|
||||
<li>Some text</li>
|
||||
<li>Some text</li>
|
||||
<li>Some text</li>
|
||||
<li>Some text</li>
|
||||
<li>Some text</li>
|
||||
<li>Some text</li>
|
||||
<li>Some text</li>
|
||||
<li>Some text</li>
|
||||
<li>Some text</li>
|
||||
<li>Some text</li>
|
||||
<li>Some text</li>
|
||||
<li>Some text</li>
|
||||
<li>Some text</li>
|
||||
<li>Some text</li>
|
||||
<li>Some text</li>
|
||||
<li>Some text</li>
|
||||
<li>Some text</li>
|
||||
<li>Some text</li>
|
||||
<li>Some text</li>
|
||||
<li>Some text</li>
|
||||
<li>Some text</li>
|
||||
<li>Some text</li>
|
||||
<li>Some text</li>
|
||||
<li>Some text</li>
|
||||
<li>Some text</li>
|
||||
<li>Some text</li>
|
||||
<li>Some text</li>
|
||||
<li>Some text</li>
|
||||
<li>Some text</li>
|
||||
<li>Some text</li>
|
||||
<li>Some text</li>
|
||||
<li>Some text</li>
|
||||
<li>Some text</li>
|
||||
<li>Some text</li>
|
||||
<li>Some text</li>
|
||||
<li>Some text</li>
|
||||
<li>Some text</li>
|
||||
<li>Some text</li>
|
||||
<li>Some text</li>
|
||||
<li>Some text</li>
|
||||
<li>Some text</li>
|
||||
<li>Some text</li>
|
||||
<li>Some text</li>
|
||||
<li>Some text</li>
|
||||
<li>Some text</li>
|
||||
<li>Some text</li>
|
||||
<li>Some text</li>
|
||||
<li>Some text</li>
|
||||
<li>Some text</li>
|
||||
<li>Some text</li>
|
||||
<li>Some text</li>
|
||||
<li>Some text</li>
|
||||
<li>Some text</li>
|
||||
<li>Some text</li>
|
||||
<li>Some text</li>
|
||||
<li>Some text</li>
|
||||
<li>Some text</li>
|
||||
<li>Some text</li>
|
||||
<li>Some text</li>
|
||||
<li>Some text</li>
|
||||
<li>Some text</li>
|
||||
<li>Some text</li>
|
||||
<li>Some text</li>
|
||||
<li>Some text</li>
|
||||
<li>Some text</li>
|
||||
<li>Some text</li>
|
||||
<li>Some text</li>
|
||||
<li>Some text</li>
|
||||
<li>Some text</li>
|
||||
<li>Some text</li>
|
||||
<li>Some text</li>
|
||||
<li>Some text</li>
|
||||
<li>Some text</li>
|
||||
<li>Some text</li>
|
||||
<li>Some text</li>
|
||||
<li>Some text</li>
|
||||
<li>Some text</li>
|
||||
<li>Some text</li>
|
||||
<li>Some text</li>
|
||||
<li>Some text</li>
|
||||
<li>Some text</li>
|
||||
<li>Some text</li>
|
||||
</ol>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<pre id="test">
|
||||
<script type="application/javascript;version=1.7">
|
||||
function* runTest() {
|
||||
var elm = document.getElementsByClassName('inner')[0];
|
||||
elm.scrollTop = 0;
|
||||
yield flushApzRepaints(driveTest);
|
||||
|
||||
// Take over control of the refresh driver and compositor
|
||||
var utils = SpecialPowers.DOMWindowUtils;
|
||||
utils.advanceTimeAndRefresh(0);
|
||||
|
||||
// Kick off an APZ smooth-scroll to 0,200
|
||||
elm.scrollTo(0, 200);
|
||||
yield waitForAllPaints(function() { setTimeout(driveTest, 0); });
|
||||
|
||||
// Let's do a couple of frames of the animation, and make sure it's going
|
||||
utils.advanceTimeAndRefresh(16);
|
||||
utils.advanceTimeAndRefresh(16);
|
||||
yield flushApzRepaints(driveTest);
|
||||
ok(elm.scrollTop > 0, "APZ animation in progress", "scrollTop is now " + elm.scrollTop);
|
||||
ok(elm.scrollTop < 200, "APZ animation not yet completed", "scrollTop is now " + elm.scrollTop);
|
||||
|
||||
var frameReconstructionTriggered = 0;
|
||||
// Register the listener that triggers the frame reconstruction
|
||||
elm.onscroll = function() {
|
||||
// Do the reconstruction
|
||||
elm.parentNode.classList.add('contentBefore');
|
||||
frameReconstructionTriggered++;
|
||||
// schedule a thing to undo the changes above
|
||||
setTimeout(function() {
|
||||
elm.parentNode.classList.remove('contentBefore');
|
||||
}, 0);
|
||||
}
|
||||
|
||||
// and do a few more frames of the animation, this should trigger the listener
|
||||
// and the frame reconstruction
|
||||
utils.advanceTimeAndRefresh(16);
|
||||
utils.advanceTimeAndRefresh(16);
|
||||
yield flushApzRepaints(driveTest);
|
||||
ok(elm.scrollTop < 200, "APZ animation not yet completed", "scrollTop is now " + elm.scrollTop);
|
||||
ok(frameReconstructionTriggered > 0, "Frame reconstruction triggered", "reconstruction triggered " + frameReconstructionTriggered + " times");
|
||||
|
||||
// and now run to completion
|
||||
for (var i = 0; i < 100; i++) {
|
||||
utils.advanceTimeAndRefresh(16);
|
||||
}
|
||||
utils.restoreNormalRefresh();
|
||||
yield waitForAllPaints(function() { setTimeout(driveTest, 0); });
|
||||
yield flushApzRepaints(driveTest);
|
||||
|
||||
is(elm.scrollTop, 200, "Element should have scrolled by 200px");
|
||||
}
|
||||
|
||||
var gTestContinuation = null;
|
||||
function driveTest() {
|
||||
if (!gTestContinuation) {
|
||||
gTestContinuation = runTest();
|
||||
}
|
||||
var ret = gTestContinuation.next();
|
||||
if (ret.done) {
|
||||
SimpleTest.finish();
|
||||
}
|
||||
}
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
var apzEnabled = SpecialPowers.getDOMWindowUtils(window).asyncPanZoomEnabled;
|
||||
if (!apzEnabled) {
|
||||
ok(true, "APZ not enabled, skipping test");
|
||||
SimpleTest.finish();
|
||||
} else {
|
||||
SimpleTest.expectAssertions(0, 1); // this test triggers an assertion, see bug 1247050
|
||||
SimpleTest.waitForFocus(driveTest, window);
|
||||
}
|
||||
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -54,7 +54,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=1173580
|
||||
<script type="application/javascript;version=1.7">
|
||||
|
||||
// Scroll the mouse wheel over |element|.
|
||||
function scrollWheelOver(element) {
|
||||
function scrollWheelOver(element, waitForScroll = true) {
|
||||
var x = 10;
|
||||
var y = 10;
|
||||
// Move the mouse to the desired wheel location.
|
||||
@@ -65,13 +65,19 @@ function scrollWheelOver(element) {
|
||||
// wheel event, otherwise there is a chance they might get reordered, and
|
||||
// we have the transaction problem again.
|
||||
synthesizeNativeMouseMoveAndWaitForMoveEvent(element, x, y, function() {
|
||||
synthesizeNativeWheelAndWaitForScrollEvent(element, x, y, 0, -10, driveTest);
|
||||
if (waitForScroll) {
|
||||
synthesizeNativeWheelAndWaitForScrollEvent(element, x, y, 0, -10, driveTest);
|
||||
} else {
|
||||
synthesizeNativeWheelAndWaitForWheelEvent(element, x, y, 0, -10, driveTest);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
var gTestContinuation = null;
|
||||
var utils;
|
||||
|
||||
const DISPLAYPORT_EXPIRY = 100;
|
||||
|
||||
// Return whether the element with id |elementId| has been layerized.
|
||||
// Assumes |elementId| will be present in the content description for the
|
||||
// element, and not in the content descriptions of other elements.
|
||||
@@ -91,6 +97,14 @@ function isLayerized(elementId) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Helper function to pass to waitForAllPaints rather than passing driveTest
|
||||
// directly. If there are no paints pending waitForAllPaints will invoke the
|
||||
// callback synchronously, and if we did waitForAllPaints(driveTest) that might
|
||||
// cause reentrancy into driveTest which is bad.
|
||||
function callDriveTestAsync() {
|
||||
setTimeout(driveTest, 0);
|
||||
}
|
||||
|
||||
function* runTest() {
|
||||
utils = SpecialPowers.getDOMWindowUtils(window);
|
||||
|
||||
@@ -126,6 +140,74 @@ function* runTest() {
|
||||
yield scrollWheelOver(document.getElementById('outer4').contentDocument.getElementById('inner4'));
|
||||
ok(isLayerized('inner4'), "scrolling 'inner4' should cause it to be layerized");
|
||||
ok(isLayerized('outer4'), "scrolling 'inner4' should also cause 'outer4' to be layerized");
|
||||
|
||||
// Now we enable displayport expiry, and verify that things are still
|
||||
// layerized as they were before.
|
||||
yield SpecialPowers.pushPrefEnv({"set": [["apz.displayport_expiry_ms", DISPLAYPORT_EXPIRY]]}, driveTest);
|
||||
ok(isLayerized('outer1'), "outer1 is still layerized after enabling expiry");
|
||||
ok(!isLayerized('inner1'), "inner1 is still not layerized after enabling expiry");
|
||||
ok(isLayerized('outer2'), "outer2 is still layerized after enabling expiry");
|
||||
ok(isLayerized('inner2'), "inner2 is still layerized after enabling expiry");
|
||||
ok(isLayerized('outer3'), "outer3 is still layerized after enabling expiry");
|
||||
ok(!isLayerized('inner3'), "inner3 is still not layerized after enabling expiry");
|
||||
ok(isLayerized('outer4'), "outer4 is still layerized after enabling expiry");
|
||||
ok(isLayerized('inner4'), "inner4 is still layerized after enabling expiry");
|
||||
|
||||
// Now we trigger a scroll on some of the things still layerized, so that
|
||||
// the displayport expiry gets triggered.
|
||||
|
||||
// Expire displayport with scrolling on outer1
|
||||
yield scrollWheelOver(document.getElementById('outer1'));
|
||||
yield waitForAllPaints(function() {
|
||||
flushApzRepaints(driveTest);
|
||||
});
|
||||
yield setTimeout(driveTest, DISPLAYPORT_EXPIRY);
|
||||
yield waitForAllPaints(callDriveTestAsync);
|
||||
ok(!isLayerized('outer1'), "outer1 is no longer layerized after displayport expiry");
|
||||
ok(!isLayerized('inner1'), "inner1 is still not layerized after displayport expiry");
|
||||
|
||||
// Expire displayport with scrolling on inner2
|
||||
yield scrollWheelOver(document.getElementById('inner2'));
|
||||
yield waitForAllPaints(function() {
|
||||
flushApzRepaints(driveTest);
|
||||
});
|
||||
// Once the expiry elapses, it will trigger expiry on outer2, so we check
|
||||
// both, one at a time.
|
||||
yield setTimeout(driveTest, DISPLAYPORT_EXPIRY);
|
||||
yield waitForAllPaints(callDriveTestAsync);
|
||||
ok(!isLayerized('inner2'), "inner2 is no longer layerized after displayport expiry");
|
||||
yield setTimeout(driveTest, DISPLAYPORT_EXPIRY);
|
||||
yield waitForAllPaints(callDriveTestAsync);
|
||||
ok(!isLayerized('outer2'), "outer2 got de-layerized with inner2");
|
||||
|
||||
// Scroll on inner3. inner3 isn't layerized, and this will cause it to
|
||||
// get layerized, but it will also trigger displayport expiration for inner3
|
||||
// which will eventually trigger displayport expiration on inner3 and outer3.
|
||||
// Note that the displayport expiration might actually happen before the wheel
|
||||
// input is processed in the compositor (see bug 1246480 comment 3), and so
|
||||
// we make sure not to wait for a scroll event here, since it may never fire.
|
||||
yield scrollWheelOver(document.getElementById('outer3').contentDocument.getElementById('inner3'), false);
|
||||
yield waitForAllPaints(function() {
|
||||
flushApzRepaints(driveTest);
|
||||
});
|
||||
yield setTimeout(driveTest, DISPLAYPORT_EXPIRY);
|
||||
yield waitForAllPaints(callDriveTestAsync);
|
||||
ok(!isLayerized('inner3'), "inner3 becomes unlayerized after expiry");
|
||||
yield setTimeout(driveTest, DISPLAYPORT_EXPIRY);
|
||||
yield waitForAllPaints(callDriveTestAsync);
|
||||
ok(!isLayerized('outer3'), "outer3 is no longer layerized after inner3 triggered expiry");
|
||||
|
||||
// Scroll outer4 and wait for the expiry. It should NOT get expired because
|
||||
// inner4 is still layerized
|
||||
yield scrollWheelOver(document.getElementById('outer4').contentDocument.documentElement);
|
||||
yield waitForAllPaints(function() {
|
||||
flushApzRepaints(driveTest);
|
||||
});
|
||||
// Wait for the expiry to elapse
|
||||
yield setTimeout(driveTest, DISPLAYPORT_EXPIRY);
|
||||
yield waitForAllPaints(callDriveTestAsync);
|
||||
ok(isLayerized('inner4'), "inner4 is still layerized because it never expired");
|
||||
ok(isLayerized('outer4'), "outer4 is still layerized because inner4 is still layerized");
|
||||
}
|
||||
|
||||
function driveTest() {
|
||||
@@ -153,7 +235,8 @@ function startTest() {
|
||||
}
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
SimpleTest.testInChaosMode();
|
||||
SimpleTest.requestFlakyTimeout("we are testing code that measures an actual timeout");
|
||||
SimpleTest.expectAssertions(0, 8); // we get a bunch of "ASSERTION: Bounds computation mismatch" sometimes (bug 1232856)
|
||||
|
||||
// Disable smooth scrolling, because it results in long-running scroll
|
||||
// animations that can result in a 'scroll' event triggered by an earlier
|
||||
@@ -161,6 +244,7 @@ SimpleTest.testInChaosMode();
|
||||
// Also enable APZ test logging, since we use that data to determine whether
|
||||
// a scroll frame was layerized.
|
||||
SpecialPowers.pushPrefEnv({"set": [["general.smoothScroll", false],
|
||||
["apz.displayport_expiry_ms", 0],
|
||||
["apz.test.logging_enabled", true]]},
|
||||
function() {
|
||||
SimpleTest.waitForFocus(startTest, window);
|
||||
|
||||
@@ -536,6 +536,7 @@ window.onload = function() {
|
||||
});
|
||||
}
|
||||
|
||||
SimpleTest.testInChaosMode();
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
</script>
|
||||
</body>
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<script type="application/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
|
||||
<script type="application/javascript" src="/tests/SimpleTest/paint_listener.js"></script>
|
||||
<script type="application/javascript" src="apz_test_utils.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
|
||||
</head>
|
||||
<body>
|
||||
@@ -35,15 +36,22 @@ function test() {
|
||||
});
|
||||
}
|
||||
|
||||
function startTest() {
|
||||
waitForAllPaints(function() {
|
||||
flushApzRepaints(test);
|
||||
});
|
||||
}
|
||||
|
||||
window.onload = function() {
|
||||
SpecialPowers.pushPrefEnv({
|
||||
'set': [['general.smoothScroll', false],
|
||||
['mousewheel.transaction.timeout', 1000000]],
|
||||
}, function () {
|
||||
SimpleTest.waitForFocus(test);
|
||||
SimpleTest.waitForFocus(startTest);
|
||||
});
|
||||
}
|
||||
|
||||
SimpleTest.testInChaosMode();
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
</script>
|
||||
</body>
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<script type="application/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
|
||||
<script type="application/javascript" src="/tests/SimpleTest/paint_listener.js"></script>
|
||||
<script type="application/javascript" src="apz_test_utils.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
|
||||
<style>
|
||||
p {
|
||||
@@ -103,13 +104,19 @@ function testScrolling(subframe) {
|
||||
});
|
||||
}
|
||||
|
||||
function startTest() {
|
||||
waitForAllPaints(function() {
|
||||
flushApzRepaints(test);
|
||||
});
|
||||
}
|
||||
|
||||
window.onload = function() {
|
||||
SpecialPowers.pushPrefEnv({
|
||||
'set': [['general.smoothScroll', false],
|
||||
['mousewheel.transaction.timeout', 0],
|
||||
['mousewheel.transaction.ignoremovedelay', 0]]
|
||||
}, function () {
|
||||
SimpleTest.waitForFocus(test);
|
||||
SimpleTest.waitForFocus(startTest);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -32,7 +32,7 @@
|
||||
// Scroll diff
|
||||
var dx = 0;
|
||||
var dy = -10; // Negative to scroll down
|
||||
synthesizeNativeWheelAndWaitForEvent(scrollDiv, x, y, dx, dy);
|
||||
synthesizeNativeWheelAndWaitForWheelEvent(scrollDiv, x, y, dx, dy);
|
||||
window.requestAnimationFrame(sendScrollEvent);
|
||||
} else {
|
||||
// Locally, with silk and apz + e10s, retina 15" mbp usually get ~1.0 - 1.5
|
||||
@@ -61,12 +61,6 @@
|
||||
SimpleTest.finish();
|
||||
}
|
||||
|
||||
var hwVsyncEnabled = SpecialPowers.getBoolPref("gfx.vsync.hw-vsync.enabled");
|
||||
if (!hwVsyncEnabled) {
|
||||
SimpleTest.ok(true, "Hardware vsync not enabled, skipping test");
|
||||
SimpleTest.finish();
|
||||
}
|
||||
|
||||
SpecialPowers.pushPrefEnv({
|
||||
"set" : [
|
||||
[testPref, true]
|
||||
|
||||
@@ -0,0 +1,84 @@
|
||||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Sanity panning test</title>
|
||||
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
|
||||
<script type="application/javascript">
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
|
||||
// this page just serially loads each one of the following test helper pages in
|
||||
// a new window and waits for it to call testDone()
|
||||
var tests = [
|
||||
{'file': 'helper_tap.html'},
|
||||
// For the following two tests, disable displayport suppression to make sure it
|
||||
// doesn't interfere with the test by scheduling paints non-deterministically.
|
||||
{'file': 'helper_scrollto_tap.html?true', 'prefs': [["apz.paint_skipping.enabled", true]], 'dp_suppression': false},
|
||||
{'file': 'helper_scrollto_tap.html?false', 'prefs': [["apz.paint_skipping.enabled", false]], 'dp_suppression': false}
|
||||
];
|
||||
|
||||
var testIndex = -1;
|
||||
var w = null;
|
||||
|
||||
function testDone() {
|
||||
var test = tests[testIndex];
|
||||
if (w) {
|
||||
if (typeof test.dp_suppression != 'undefined') {
|
||||
// We modified the suppression when starting the test, so now undo that.
|
||||
SpecialPowers.getDOMWindowUtils(window).respectDisplayPortSuppression(!test.dp_suppression);
|
||||
}
|
||||
if (!!test.prefs) {
|
||||
// We pushed some prefs for this test, pop them, and re-invoke
|
||||
// testDone() after that's been processed
|
||||
SpecialPowers.popPrefEnv(function() {
|
||||
w.close();
|
||||
w = null;
|
||||
testDone();
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
w.close();
|
||||
}
|
||||
|
||||
testIndex++;
|
||||
if (testIndex >= tests.length) {
|
||||
SimpleTest.finish();
|
||||
return;
|
||||
}
|
||||
|
||||
test = tests[testIndex];
|
||||
if (typeof test.dp_suppression != 'undefined') {
|
||||
// Normally during a test, the displayport will get suppressed during page
|
||||
// load, and unsuppressed at a non-deterministic time during the test. The
|
||||
// unsuppression can trigger a repaint which interferes with the test, so
|
||||
// to avoid that we can force the displayport to be unsuppressed for the
|
||||
// entire test which is more deterministic.
|
||||
SpecialPowers.getDOMWindowUtils(window).respectDisplayPortSuppression(test.dp_suppression);
|
||||
}
|
||||
if (!!test.prefs) {
|
||||
// Got some prefs for this subtest, push them
|
||||
SpecialPowers.pushPrefEnv({"set": test.prefs}, function() {
|
||||
w = window.open(test.file, "_blank");
|
||||
});
|
||||
} else {
|
||||
w = window.open(test.file, "_blank");
|
||||
}
|
||||
}
|
||||
|
||||
window.onload = function() {
|
||||
if (!SpecialPowers.getDOMWindowUtils(window).asyncPanZoomEnabled) {
|
||||
ok(true, "APZ is not enabled, this test is not relevant, sorry!\n");
|
||||
SimpleTest.finish();
|
||||
return;
|
||||
}
|
||||
testDone();
|
||||
};
|
||||
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
</body>
|
||||
</html>
|
||||
@@ -78,7 +78,7 @@ document.getElementById("scrollbox").addEventListener("wheel", function (e) {
|
||||
function* runTest() {
|
||||
var content = document.getElementById('content');
|
||||
for (i = 0; i < 300; i++) { // enough iterations that we would scroll to the bottom of 'content'
|
||||
yield synthesizeNativeWheelAndWaitForEvent(content, 100, 150, 0, -5, continueTest);
|
||||
yield synthesizeNativeWheelAndWaitForWheelEvent(content, 100, 150, 0, -5, continueTest);
|
||||
}
|
||||
var scrollbox = document.getElementById('scrollbox');
|
||||
is(content.scrollTop > 0, true, "We should have scrolled down somewhat");
|
||||
@@ -106,6 +106,7 @@ function startTest() {
|
||||
SpecialPowers.pushPrefEnv({"set": [["general.smoothScroll", false]]}, continueTest);
|
||||
}
|
||||
|
||||
SimpleTest.testInChaosMode();
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
SimpleTest.waitForFocus(startTest, window);
|
||||
|
||||
@@ -114,4 +115,3 @@ SimpleTest.waitForFocus(startTest, window);
|
||||
|
||||
</body>
|
||||
</html>
|
||||
|
||||
|
||||
@@ -7,7 +7,9 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=1175585
|
||||
<title>Test for Bug 1175585</title>
|
||||
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
|
||||
<script type="application/javascript" src="/tests/SimpleTest/paint_listener.js"></script>
|
||||
<script type="application/javascript" src="apz_test_native_event_utils.js"></script>
|
||||
<script type="application/javascript" src="apz_test_utils.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
|
||||
<style>
|
||||
#outer-frame {
|
||||
@@ -131,13 +133,19 @@ function driveTest() {
|
||||
}
|
||||
|
||||
function startTest() {
|
||||
// Disable smooth scrolling because it makes the test flaky (we don't have a good
|
||||
// way of detecting when the scrolling is finished).
|
||||
SpecialPowers.pushPrefEnv({"set": [["general.smoothScroll", false]]}, driveTest);
|
||||
waitForAllPaints(function() {
|
||||
flushApzRepaints(driveTest);
|
||||
});
|
||||
}
|
||||
|
||||
// Disable smooth scrolling because it makes the test flaky (we don't have a good
|
||||
// way of detecting when the scrolling is finished).
|
||||
SpecialPowers.pushPrefEnv({"set": [["general.smoothScroll", false]]},
|
||||
function() {
|
||||
SimpleTest.waitForFocus(startTest, window);
|
||||
});
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
SimpleTest.waitForFocus(startTest, window);
|
||||
|
||||
</script>
|
||||
</pre>
|
||||
|
||||
+1
-1
@@ -2,7 +2,7 @@
|
||||
<html class="reftest-wait"><head>
|
||||
<meta name="viewport" content="width=device-width">
|
||||
</head>
|
||||
<body onload="scrollTo(450,10000); document.documentElement.classList.remove('reftest-wait')">
|
||||
<body onload="scrollTo(450,8000); document.documentElement.classList.remove('reftest-wait')">
|
||||
<div style="width: 9000px; height: 20000px; background: white;"></div>
|
||||
</body>
|
||||
</html>
|
||||
+1
-1
@@ -3,7 +3,7 @@
|
||||
<meta name="viewport" content="width=device-width">
|
||||
<style> html { direction: rtl; } </style>
|
||||
</head>
|
||||
<body onload="scrollTo(-450,10000); document.documentElement.classList.remove('reftest-wait')">
|
||||
<body onload="scrollTo(-450,8000); document.documentElement.classList.remove('reftest-wait')">
|
||||
<div style="width: 9000px; height: 20000px; background: white;"></div>
|
||||
</body>
|
||||
</html>
|
||||
+1
-1
@@ -1,7 +1,7 @@
|
||||
<!DOCTYPE html>
|
||||
<html class="reftest-wait"
|
||||
reftest-async-scroll
|
||||
reftest-async-scroll-x="-440" reftest-async-scroll-y="9999"><head>
|
||||
reftest-async-scroll-x="-440" reftest-async-scroll-y="7999"><head>
|
||||
<meta name="viewport" content="width=device-width">
|
||||
<style> html { direction: rtl; } </style>
|
||||
</head>
|
||||
+1
-1
@@ -1,7 +1,7 @@
|
||||
<!DOCTYPE html>
|
||||
<html class="reftest-wait"
|
||||
reftest-async-scroll
|
||||
reftest-async-scroll-x="449" reftest-async-scroll-y="9999"><head>
|
||||
reftest-async-scroll-x="449" reftest-async-scroll-y="7999"><head>
|
||||
<meta name="viewport" content="width=device-width">
|
||||
</head>
|
||||
<!-- Doing scrollTo(1,1) is to activate the left/up arrows in the scrollbars
|
||||
@@ -0,0 +1,10 @@
|
||||
<!DOCTYPE html>
|
||||
<html><head>
|
||||
<meta name="viewport" content="width=device-width">
|
||||
</head>
|
||||
<body>
|
||||
This tests that an initial-scale of 0 (i.e. garbage) is overridden<br/>
|
||||
with something a little more sane.
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -0,0 +1,10 @@
|
||||
<!DOCTYPE html>
|
||||
<html><head>
|
||||
<meta name="viewport" content="initial-scale=0; width=device-width">
|
||||
</head>
|
||||
<body>
|
||||
This tests that an initial-scale of 0 (i.e. garbage) is overridden<br/>
|
||||
with something a little more sane.
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -0,0 +1,17 @@
|
||||
# The following tests test the async positioning of the scrollbars.
|
||||
# Basic root-frame scrollbar with async scrolling
|
||||
skip-if(!asyncPan) fuzzy-if(Android,6,8) == async-scrollbar-1-v.html async-scrollbar-1-v-ref.html
|
||||
skip-if(!asyncPan) fuzzy-if(Android,6,8) == async-scrollbar-1-h.html async-scrollbar-1-h-ref.html
|
||||
skip-if(!asyncPan) fuzzy-if(Android,6,8) == async-scrollbar-1-vh.html async-scrollbar-1-vh-ref.html
|
||||
skip-if(!asyncPan) fuzzy-if(Android,6,8) == async-scrollbar-1-v-rtl.html async-scrollbar-1-v-rtl-ref.html
|
||||
skip-if(!asyncPan) fuzzy-if(Android,13,8) == async-scrollbar-1-h-rtl.html async-scrollbar-1-h-rtl-ref.html
|
||||
skip-if(!asyncPan) fuzzy-if(Android,8,10) == async-scrollbar-1-vh-rtl.html async-scrollbar-1-vh-rtl-ref.html
|
||||
|
||||
# Different async zoom levels. Since the scrollthumb gets async-scaled in the
|
||||
# compositor, the border-radius ends of the scrollthumb are going to be a little
|
||||
# off, hence the fuzzy-if clauses.
|
||||
skip-if(!asyncZoom) fuzzy-if(B2G,98,82) == async-scrollbar-zoom-1.html async-scrollbar-zoom-1-ref.html
|
||||
skip-if(!asyncZoom) fuzzy-if(B2G,94,146) == async-scrollbar-zoom-2.html async-scrollbar-zoom-2-ref.html
|
||||
|
||||
# Meta-viewport tag support
|
||||
skip-if(!asyncZoom) == initial-scale-1.html initial-scale-1-ref.html
|
||||
@@ -1,57 +0,0 @@
|
||||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Sanity panning test</title>
|
||||
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
|
||||
<script type="application/javascript">
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
SimpleTest.testInChaosMode();
|
||||
|
||||
// this page just serially loads each one of the following test helper pages in
|
||||
// a new window and waits for it to call testDone()
|
||||
var tests = [
|
||||
'helper_basic_pan.html',
|
||||
'helper_div_pan.html',
|
||||
'helper_iframe_pan.html',
|
||||
];
|
||||
|
||||
var testIndex = -1;
|
||||
var w = null;
|
||||
|
||||
function testDone() {
|
||||
if (w) {
|
||||
w.close();
|
||||
}
|
||||
testIndex++;
|
||||
if (testIndex < tests.length) {
|
||||
w = window.open(tests[testIndex], "_blank");
|
||||
} else {
|
||||
SimpleTest.finish();
|
||||
}
|
||||
}
|
||||
|
||||
window.onload = function() {
|
||||
SpecialPowers.pushPrefEnv(
|
||||
{ "set":
|
||||
[
|
||||
// Dropping the touch slop to 0 makes the tests easier to write because
|
||||
// we can just do a one-pixel drag to get over the pan threshold rather
|
||||
// than having to hard-code some larger value.
|
||||
["apz.touch_start_tolerance", "0.0"],
|
||||
|
||||
// The B2G emulator is hella slow, and needs more than 300ms to run the
|
||||
// main-thread code that deals with layerizing subframes and running
|
||||
// touch listeners. In my local runs this needs to be at least 1000.
|
||||
["apz.content_response_timeout", "5000"]
|
||||
]
|
||||
}, testDone);
|
||||
};
|
||||
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,63 +0,0 @@
|
||||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<!--
|
||||
https://bugzilla.mozilla.org/show_bug.cgi?id=1151667
|
||||
-->
|
||||
<head>
|
||||
<title>Test for Bug 1151667</title>
|
||||
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
|
||||
<script type="application/javascript" src="apz_test_native_event_utils.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
|
||||
<style>
|
||||
#subframe {
|
||||
margin-top: 100px;
|
||||
height: 500px;
|
||||
width: 500px;
|
||||
overflow: scroll;
|
||||
}
|
||||
#subframe-content {
|
||||
height: 1000px;
|
||||
width: 500px;
|
||||
/* the background is so that we can see it scroll*/
|
||||
background: repeating-linear-gradient(#EEE, #EEE 100px, #DDD 100px, #DDD 200px);
|
||||
}
|
||||
#page-content {
|
||||
height: 5000px;
|
||||
width: 500px;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1151667">Mozilla Bug 1151667</a>
|
||||
<p id="display"></p>
|
||||
<div id="subframe">
|
||||
<!-- This makes sure the subframe is scrollable -->
|
||||
<div id="subframe-content"></div>
|
||||
</div>
|
||||
<!-- This makes sure the page is also scrollable, so it (rather than the subframe)
|
||||
is considered the primary async-scrollable frame, and so the subframe isn't
|
||||
layerized upon page load. -->
|
||||
<div id="page-content"></div>
|
||||
<pre id="test">
|
||||
<script type="application/javascript;version=1.7">
|
||||
|
||||
function startTest() {
|
||||
var subframe = document.getElementById('subframe');
|
||||
synthesizeNativeWheelAndWaitForScrollEvent(subframe, 100, 150, 0, -10, continueTest);
|
||||
}
|
||||
|
||||
function continueTest() {
|
||||
var subframe = document.getElementById('subframe');
|
||||
is(subframe.scrollTop > 0, true, "We should have scrolled the subframe down");
|
||||
is(document.documentElement.scrollTop, 0, "We should not have scrolled the page");
|
||||
SimpleTest.finish();
|
||||
}
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
SimpleTest.waitForFocus(startTest, window);
|
||||
|
||||
</script>
|
||||
</pre>
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,35 +0,0 @@
|
||||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<!--
|
||||
https://bugzilla.mozilla.org/show_bug.cgi?id=982141
|
||||
-->
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Test for Bug 982141</title>
|
||||
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
|
||||
<script type="application/javascript">
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
|
||||
// Run the actual test in its own window, because it requires that the
|
||||
// root APZC not be scrollable. Mochitest pages themselves often run
|
||||
// inside an iframe which means we have no control over the root APZC.
|
||||
var w = null;
|
||||
window.onload = function() {
|
||||
SpecialPowers.pushPrefEnv({"set": [["apz.test.logging_enabled", true]]}, function() {
|
||||
w = window.open("helper_bug982141.html", "_blank");
|
||||
});
|
||||
};
|
||||
|
||||
function finishTest() {
|
||||
w.close();
|
||||
SimpleTest.finish();
|
||||
};
|
||||
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=982141">Mozilla Bug 982141</a>
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,168 +0,0 @@
|
||||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<!--
|
||||
https://bugzilla.mozilla.org/show_bug.cgi?id=1173580
|
||||
-->
|
||||
<head>
|
||||
<title>Test for layerization</title>
|
||||
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
|
||||
<script type="application/javascript" src="apz_test_native_event_utils.js"></script>
|
||||
<script type="application/javascript" src="apz_test_utils.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
|
||||
<link rel="stylesheet" type="text/css" href="helper_subframe_style.css"/>
|
||||
<style>
|
||||
#container {
|
||||
display: flex;
|
||||
overflow: scroll;
|
||||
height: 500px;
|
||||
}
|
||||
.outer-frame {
|
||||
height: 500px;
|
||||
overflow: scroll;
|
||||
flex-basis: 100%;
|
||||
background: repeating-linear-gradient(#CCC, #CCC 100px, #BBB 100px, #BBB 200px);
|
||||
}
|
||||
#container-content {
|
||||
height: 200%;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1173580">APZ layerization tests</a>
|
||||
<p id="display"></p>
|
||||
<div id="container">
|
||||
<div id="outer1" class="outer-frame">
|
||||
<div id="inner1" class="inner-frame">
|
||||
<div class="inner-content"></div>
|
||||
</div>
|
||||
</div>
|
||||
<div id="outer2" class="outer-frame">
|
||||
<div id="inner2" class="inner-frame">
|
||||
<div class="inner-content"></div>
|
||||
</div>
|
||||
</div>
|
||||
<iframe id="outer3" class="outer-frame" src="helper_iframe1.html"></iframe>
|
||||
<iframe id="outer4" class="outer-frame" src="helper_iframe2.html"></iframe>
|
||||
<!-- The container-content div ensures 'container' is scrollable, so the
|
||||
optimization that layerizes the primary async-scrollable frame on page
|
||||
load layerizes it rather than its child subframes. -->
|
||||
<div id="container-content"></div>
|
||||
</div>
|
||||
<pre id="test">
|
||||
<script type="application/javascript;version=1.7">
|
||||
|
||||
// Scroll the mouse wheel over |element|.
|
||||
function scrollWheelOver(element) {
|
||||
var x = 10;
|
||||
var y = 10;
|
||||
// Move the mouse to the desired wheel location.
|
||||
// Not doing so can result in the wheel events from two consecutive
|
||||
// scrollWheelOver() calls on different elements being incorrectly considered
|
||||
// as part of the same wheel transaction.
|
||||
// We also wait for the mouse move event to be processed before sending the
|
||||
// wheel event, otherwise there is a chance they might get reordered, and
|
||||
// we have the transaction problem again.
|
||||
synthesizeNativeMouseMoveAndWaitForMoveEvent(element, x, y, function() {
|
||||
synthesizeNativeWheelAndWaitForScrollEvent(element, x, y, 0, -10, driveTest);
|
||||
});
|
||||
}
|
||||
|
||||
var gTestContinuation = null;
|
||||
var utils;
|
||||
|
||||
// Return whether the element with id |elementId| has been layerized.
|
||||
// Assumes |elementId| will be present in the content description for the
|
||||
// element, and not in the content descriptions of other elements.
|
||||
function isLayerized(elementId) {
|
||||
var contentTestData = utils.getContentAPZTestData();
|
||||
ok(contentTestData.paints.length > 0, "expected at least one paint");
|
||||
var seqno = contentTestData.paints[contentTestData.paints.length - 1].sequenceNumber;
|
||||
contentTestData = convertTestData(contentTestData);
|
||||
var paint = contentTestData.paints[seqno];
|
||||
for (var scrollId in paint) {
|
||||
if ("contentDescription" in paint[scrollId]) {
|
||||
if (paint[scrollId]["contentDescription"].includes(elementId)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
function* runTest() {
|
||||
utils = SpecialPowers.getDOMWindowUtils(window);
|
||||
|
||||
// Initially, nothing should be layerized.
|
||||
ok(!isLayerized('outer1'), "initially 'outer1' should not be layerized");
|
||||
ok(!isLayerized('inner1'), "initially 'inner1' should not be layerized");
|
||||
ok(!isLayerized('outer2'), "initially 'outer2' should not be layerized");
|
||||
ok(!isLayerized('inner2'), "initially 'inner2' should not be layerized");
|
||||
ok(!isLayerized('outer3'), "initially 'outer3' should not be layerized");
|
||||
ok(!isLayerized('inner3'), "initially 'inner3' should not be layerized");
|
||||
ok(!isLayerized('outer4'), "initially 'outer4' should not be layerized");
|
||||
ok(!isLayerized('inner4'), "initially 'inner4' should not be layerized");
|
||||
|
||||
// Scrolling over outer1 should layerize outer1, but not inner1.
|
||||
yield scrollWheelOver(document.getElementById('outer1'));
|
||||
ok(isLayerized('outer1'), "scrolling 'outer1' should cause it to be layerized");
|
||||
ok(!isLayerized('inner1'), "scrolling 'outer1' should not cause 'inner1' to be layerized");
|
||||
|
||||
// Scrolling over inner2 should layerize both outer2 and inner2.
|
||||
yield scrollWheelOver(document.getElementById('inner2'));
|
||||
ok(isLayerized('inner2'), "scrolling 'inner2' should cause it to be layerized");
|
||||
ok(isLayerized('outer2'), "scrolling 'inner2' should also cause 'outer2' to be layerized");
|
||||
|
||||
// The second half of the test repeats the same checks as the first half,
|
||||
// but with an iframe as the outer scrollable frame.
|
||||
|
||||
// Scrolling over outer3 should layerize outer3, but not inner3.
|
||||
yield scrollWheelOver(document.getElementById('outer3').contentDocument.documentElement);
|
||||
ok(isLayerized('outer3'), "scrolling 'outer3' should cause it to be layerized");
|
||||
ok(!isLayerized('inner3'), "scrolling 'outer3' should not cause 'inner3' to be layerized");
|
||||
|
||||
// Scrolling over outer4 should layerize both outer4 and inner4.
|
||||
yield scrollWheelOver(document.getElementById('outer4').contentDocument.getElementById('inner4'));
|
||||
ok(isLayerized('inner4'), "scrolling 'inner4' should cause it to be layerized");
|
||||
ok(isLayerized('outer4'), "scrolling 'inner4' should also cause 'outer4' to be layerized");
|
||||
}
|
||||
|
||||
function driveTest() {
|
||||
if (!gTestContinuation) {
|
||||
gTestContinuation = runTest();
|
||||
}
|
||||
var ret = gTestContinuation.next();
|
||||
if (ret.done) {
|
||||
SimpleTest.finish();
|
||||
}
|
||||
}
|
||||
|
||||
function startTest() {
|
||||
// This test requires APZ - if it's not enabled, skip it.
|
||||
var apzEnabled = SpecialPowers.getDOMWindowUtils(window).asyncPanZoomEnabled;
|
||||
if (!apzEnabled) {
|
||||
ok(true, "APZ not enabled, skipping test");
|
||||
SimpleTest.finish();
|
||||
return;
|
||||
}
|
||||
|
||||
driveTest();
|
||||
}
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
SimpleTest.testInChaosMode();
|
||||
|
||||
// Disable smooth scrolling, because it results in long-running scroll
|
||||
// animations that can result in a 'scroll' event triggered by an earlier
|
||||
// wheel event as corresponding to a later wheel event.
|
||||
// Also enable APZ test logging, since we use that data to determine whether
|
||||
// a scroll frame was layerized.
|
||||
SpecialPowers.pushPrefEnv({"set": [["general.smoothScroll", false],
|
||||
["apz.test.logging_enabled", true]]},
|
||||
function() {
|
||||
SimpleTest.waitForFocus(startTest, window);
|
||||
});
|
||||
</script>
|
||||
</pre>
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,50 +0,0 @@
|
||||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<head>
|
||||
<title>Test scrolling flattened inactive frames</title>
|
||||
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<script type="application/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
|
||||
<script type="application/javascript" src="/tests/SimpleTest/paint_listener.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
|
||||
</head>
|
||||
<body>
|
||||
<div id="container" style="height: 300px; width: 600px; overflow: auto; background: yellow">
|
||||
<div id="outer" style="height: 400px; width: 500px; overflow: auto; background: black">
|
||||
<div id="inner" style="mix-blend-mode: screen; height: 800px; overflow: auto; background: purple">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<script class="testbody" type="text/javascript;version=1.7">
|
||||
function test() {
|
||||
var container = document.getElementById('container');
|
||||
var outer = document.getElementById('outer');
|
||||
var inner = document.getElementById('inner');
|
||||
var outerScrollTop = outer.scrollTop;
|
||||
var containerScrollTop = container.scrollTop;
|
||||
var event = {
|
||||
deltaMode: WheelEvent.DOM_DELTA_LINE,
|
||||
deltaX: 0,
|
||||
deltaY: 10,
|
||||
lineOrPageDeltaX: 0,
|
||||
lineOrPageDeltaY: 10,
|
||||
};
|
||||
sendWheelAndPaint(inner, 20, 30, event, function () {
|
||||
ok(container.scrollTop == containerScrollTop, "container scrollframe should not have scrolled");
|
||||
ok(outer.scrollTop > outerScrollTop, "nested scrollframe should have scrolled");
|
||||
SimpleTest.finish();
|
||||
});
|
||||
}
|
||||
|
||||
window.onload = function() {
|
||||
SpecialPowers.pushPrefEnv({
|
||||
'set': [['general.smoothScroll', false],
|
||||
['mousewheel.transaction.timeout', 1000000]],
|
||||
}, function () {
|
||||
SimpleTest.waitForFocus(test);
|
||||
});
|
||||
}
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,117 +0,0 @@
|
||||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<!--
|
||||
https://bugzilla.mozilla.org/show_bug.cgi?id=1013412
|
||||
-->
|
||||
<head>
|
||||
<title>Test for Bug 1013412</title>
|
||||
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
|
||||
<script type="application/javascript" src="apz_test_native_event_utils.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
|
||||
<style>
|
||||
#content {
|
||||
height: 800px;
|
||||
overflow: scroll;
|
||||
}
|
||||
|
||||
#scroller {
|
||||
height: 2000px;
|
||||
background: repeating-linear-gradient(#EEE, #EEE 100px, #DDD 100px, #DDD 200px);
|
||||
}
|
||||
|
||||
#scrollbox {
|
||||
margin-top: 200px;
|
||||
width: 500px;
|
||||
height: 500px;
|
||||
border-radius: 250px;
|
||||
box-shadow: inset 0 0 0 60px #555;
|
||||
background: #777;
|
||||
}
|
||||
|
||||
#circle {
|
||||
position: relative;
|
||||
left: 240px;
|
||||
top: 20px;
|
||||
border: 10px solid white;
|
||||
border-radius: 10px;
|
||||
width: 0px;
|
||||
height: 0px;
|
||||
transform-origin: 10px 230px;
|
||||
will-change: transform;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1161206">Mozilla Bug 1161206</a>
|
||||
<p id="display"></p>
|
||||
<div id="content">
|
||||
<p>Scrolling the page should be async, but scrolling over the dark circle should not scroll the page and instead rotate the white ball.</p>
|
||||
<div id="scroller">
|
||||
<div id="scrollbox">
|
||||
<div id="circle"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<pre id="test">
|
||||
<script type="application/javascript;version=1.7">
|
||||
|
||||
var rotation = 0;
|
||||
var rotationAdjusted = false;
|
||||
|
||||
var incrementForMode = function (mode) {
|
||||
switch (mode) {
|
||||
case WheelEvent.DOM_DELTA_PIXEL: return 1;
|
||||
case WheelEvent.DOM_DELTA_LINE: return 15;
|
||||
case WheelEvent.DOM_DELTA_PAGE: return 400;
|
||||
}
|
||||
return 0;
|
||||
};
|
||||
|
||||
document.getElementById("scrollbox").addEventListener("wheel", function (e) {
|
||||
rotation += e.deltaY * incrementForMode(e.deltaMode) * 0.2;
|
||||
document.getElementById("circle").style.transform = "rotate(" + rotation + "deg)";
|
||||
rotationAdjusted = true;
|
||||
e.preventDefault();
|
||||
});
|
||||
|
||||
function* runTest() {
|
||||
var content = document.getElementById('content');
|
||||
for (i = 0; i < 300; i++) { // enough iterations that we would scroll to the bottom of 'content'
|
||||
yield synthesizeNativeWheelAndWaitForWheelEvent(content, 100, 150, 0, -5, continueTest);
|
||||
}
|
||||
var scrollbox = document.getElementById('scrollbox');
|
||||
is(content.scrollTop > 0, true, "We should have scrolled down somewhat");
|
||||
is(content.scrollTop < content.scrollTopMax, true, "We should not have scrolled to the bottom of the scrollframe");
|
||||
is(rotationAdjusted, true, "The rotation should have been adjusted");
|
||||
}
|
||||
|
||||
var gTestContinuation = null;
|
||||
function continueTest() {
|
||||
if (!gTestContinuation) {
|
||||
gTestContinuation = runTest();
|
||||
}
|
||||
var ret = gTestContinuation.next();
|
||||
if (ret.done) {
|
||||
SimpleTest.finish();
|
||||
} else {
|
||||
is(ret.value, true, "Wheel event successfully synthesized");
|
||||
}
|
||||
}
|
||||
|
||||
function startTest() {
|
||||
// If we allow smooth scrolling the "smooth" scrolling may cause the page to
|
||||
// glide past the scrollbox (which is supposed to stop the scrolling) and so
|
||||
// we might end up at the bottom of the page.
|
||||
SpecialPowers.pushPrefEnv({"set": [["general.smoothScroll", false]]}, continueTest);
|
||||
}
|
||||
|
||||
SimpleTest.testInChaosMode();
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
SimpleTest.waitForFocus(startTest, window);
|
||||
|
||||
</script>
|
||||
</pre>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,142 +0,0 @@
|
||||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<!--
|
||||
https://bugzilla.mozilla.org/show_bug.cgi?id=1175585
|
||||
-->
|
||||
<head>
|
||||
<title>Test for Bug 1175585</title>
|
||||
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<script type="text/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
|
||||
<script type="application/javascript" src="apz_test_native_event_utils.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
|
||||
<style>
|
||||
#outer-frame {
|
||||
height: 500px;
|
||||
overflow: scroll;
|
||||
background: repeating-linear-gradient(#CCC, #CCC 100px, #BBB 100px, #BBB 200px);
|
||||
}
|
||||
#inner-frame {
|
||||
margin-top: 25%;
|
||||
height: 200%;
|
||||
width: 75%;
|
||||
overflow: scroll;
|
||||
}
|
||||
#inner-content {
|
||||
height: 200%;
|
||||
width: 200%;
|
||||
background: repeating-linear-gradient(#EEE, #EEE 100px, #DDD 100px, #DDD 200px);
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1175585">APZ wheel transactions test</a>
|
||||
<p id="display"></p>
|
||||
<div id="outer-frame">
|
||||
<div id="inner-frame">
|
||||
<div id="inner-content"></div>
|
||||
</div>
|
||||
</div>
|
||||
<pre id="test">
|
||||
<script type="application/javascript;version=1.7">
|
||||
|
||||
function scrollWheelOver(element, deltaY) {
|
||||
synthesizeNativeWheelAndWaitForScrollEvent(element, 10, 10, 0, deltaY, driveTest);
|
||||
}
|
||||
|
||||
function* runTest() {
|
||||
var outer = document.getElementById('outer-frame');
|
||||
var inner = document.getElementById('inner-frame');
|
||||
var innerContent = document.getElementById('inner-content');
|
||||
|
||||
// Register a wheel event listener that records the target of
|
||||
// the last wheel event, so that we can make assertions about it.
|
||||
var lastWheelTarget;
|
||||
var wheelTargetRecorder = function(e) { lastWheelTarget = e.target; };
|
||||
window.addEventListener("wheel", wheelTargetRecorder);
|
||||
|
||||
// Scroll |outer| to the bottom.
|
||||
while (outer.scrollTop < outer.scrollTopMax) {
|
||||
yield scrollWheelOver(outer, -10);
|
||||
}
|
||||
|
||||
// Verify that this has brought |inner| under the wheel.
|
||||
is(lastWheelTarget, innerContent, "'inner-content' should have been brought under the wheel");
|
||||
window.removeEventListener("wheel", wheelTargetRecorder);
|
||||
|
||||
// Immediately after, scroll it back up a bit.
|
||||
yield scrollWheelOver(outer, 10);
|
||||
|
||||
// Check that it was |outer| that scrolled back, and |inner| didn't
|
||||
// scroll at all, as all the above scrolls should be in the same
|
||||
// transaction.
|
||||
ok(outer.scrollTop < outer.scrollTopMax, "'outer' should have scrolled back a bit");
|
||||
is(inner.scrollTop, 0, "'inner' should not have scrolled");
|
||||
|
||||
// The next part of the test is related to the transaction timeout.
|
||||
// Turn it down a bit so waiting for the timeout to elapse doesn't
|
||||
// slow down the test harness too much.
|
||||
var timeout = 5;
|
||||
yield SpecialPowers.pushPrefEnv({"set": [["mousewheel.transaction.timeout", timeout]]}, driveTest);
|
||||
SimpleTest.requestFlakyTimeout("we are testing code that measures actual elapsed time between two events");
|
||||
|
||||
// Scroll up a bit more. It's still |outer| scrolling because
|
||||
// |inner| is still scrolled all the way to the top.
|
||||
yield scrollWheelOver(outer, 10);
|
||||
|
||||
// Wait for the transaction timeout to elapse.
|
||||
yield window.setTimeout(driveTest, timeout);
|
||||
|
||||
// Now scroll down. The transaction having timed out, the event
|
||||
// should pick up a new target, and that should be |inner|.
|
||||
yield scrollWheelOver(outer, -10);
|
||||
ok(inner.scrollTop > 0, "'inner' should have been scrolled");
|
||||
|
||||
// Finally, test scroll handoff after a timeout.
|
||||
|
||||
// Continue scrolling |inner| down to the bottom.
|
||||
var prevScrollTop = inner.scrollTop;
|
||||
while (inner.scrollTop < inner.scrollTopMax) {
|
||||
yield scrollWheelOver(outer, -10);
|
||||
// Avoid a failure getting us into an infinite loop.
|
||||
ok(inner.scrollTop > prevScrollTop, "scrolling down should increase scrollTop");
|
||||
prevScrollTop = inner.scrollTop;
|
||||
}
|
||||
|
||||
// Wait for the transaction timeout to elapse.
|
||||
yield window.setTimeout(driveTest, timeout);
|
||||
|
||||
// Continued downward scrolling should scroll |outer| to the bottom.
|
||||
prevScrollTop = outer.scrollTop;
|
||||
while (outer.scrollTop < outer.scrollTopMax) {
|
||||
yield scrollWheelOver(outer, -10);
|
||||
// Avoid a failure getting us into an infinite loop.
|
||||
ok(outer.scrollTop > prevScrollTop, "scrolling down should increase scrollTop");
|
||||
prevScrollTop = outer.scrollTop;
|
||||
}
|
||||
}
|
||||
|
||||
var gTestContinuation = null;
|
||||
function driveTest() {
|
||||
if (!gTestContinuation) {
|
||||
gTestContinuation = runTest();
|
||||
}
|
||||
var ret = gTestContinuation.next();
|
||||
if (ret.done) {
|
||||
SimpleTest.finish();
|
||||
}
|
||||
}
|
||||
|
||||
function startTest() {
|
||||
// Disable smooth scrolling because it makes the test flaky (we don't have a good
|
||||
// way of detecting when the scrolling is finished).
|
||||
SpecialPowers.pushPrefEnv({"set": [["general.smoothScroll", false]]}, driveTest);
|
||||
}
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
SimpleTest.waitForFocus(startTest, window);
|
||||
|
||||
</script>
|
||||
</pre>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
@@ -258,7 +258,6 @@ APZCCallbackHelper::UpdateRootFrame(FrameMetrics& aMetrics)
|
||||
// adjusts the display port margins, so do it before we set those.
|
||||
ScrollFrame(content, aMetrics);
|
||||
|
||||
MOZ_ASSERT(nsLayoutUtils::HasDisplayPort(content));
|
||||
SetDisplayPortMargins(shell, content, aMetrics);
|
||||
SetPaintRequestTime(content, aMetrics.GetPaintRequestTime());
|
||||
}
|
||||
|
||||
@@ -90,7 +90,10 @@ ActiveElementManager::TriggerElementActivation()
|
||||
if (!mCanBePan) {
|
||||
SetActive(mTarget);
|
||||
} else {
|
||||
CancelTask(); // this is only needed because of bug 1169802. Fixing that
|
||||
// bug properly should make this unnecessary.
|
||||
MOZ_ASSERT(mSetActiveTask == nullptr);
|
||||
|
||||
mSetActiveTask = NewRunnableMethod(
|
||||
this, &ActiveElementManager::SetActiveTask, mTarget);
|
||||
MessageLoop::current()->PostDelayedTask(
|
||||
|
||||
@@ -28,6 +28,7 @@ class APZEventState;
|
||||
// tree.
|
||||
class ChromeProcessController : public mozilla::layers::GeckoContentController
|
||||
{
|
||||
protected:
|
||||
typedef mozilla::layers::FrameMetrics FrameMetrics;
|
||||
typedef mozilla::layers::ScrollableLayerGuid ScrollableLayerGuid;
|
||||
|
||||
|
||||
@@ -864,7 +864,7 @@ BasicLayerManager::PaintLayer(gfxContext* aTarget,
|
||||
|
||||
paintLayerContext.Apply2DTransform();
|
||||
|
||||
const nsIntRegion visibleRegion = aLayer->GetLocalVisibleRegion().ToUnknownRegion();
|
||||
nsIntRegion visibleRegion = aLayer->GetLocalVisibleRegion().ToUnknownRegion();
|
||||
// If needsGroup is true, we'll clip to the visible region after we've popped the group
|
||||
if (needsClipToVisibleRegion && !needsGroup) {
|
||||
gfxUtils::ClipToRegion(aTarget, visibleRegion);
|
||||
@@ -897,7 +897,7 @@ BasicLayerManager::PaintLayer(gfxContext* aTarget,
|
||||
return;
|
||||
}
|
||||
|
||||
const IntRect& bounds = visibleRegion.GetBounds();
|
||||
IntRect bounds = visibleRegion.GetBounds();
|
||||
RefPtr<DrawTarget> untransformedDT =
|
||||
gfxPlatform::GetPlatform()->CreateOffscreenContentDrawTarget(IntSize(bounds.width, bounds.height),
|
||||
SurfaceFormat::B8G8R8A8);
|
||||
@@ -934,6 +934,7 @@ BasicLayerManager::PaintLayer(gfxContext* aTarget,
|
||||
ToRect(aTarget->GetClipExtents()));
|
||||
xformBounds.RoundOut();
|
||||
effectiveTransform.PostTranslate(-xformBounds.x, -xformBounds.y, 0);
|
||||
effectiveTransform.PreTranslate(bounds.x, bounds.y, 0);
|
||||
|
||||
RefPtr<SourceSurface> untransformedSurf = untransformedDT->Snapshot();
|
||||
RefPtr<DrawTarget> xformDT =
|
||||
|
||||
@@ -71,14 +71,14 @@ void
|
||||
CanvasClient2D::Update(gfx::IntSize aSize, ClientCanvasLayer* aLayer)
|
||||
{
|
||||
AutoRemoveTexture autoRemove(this);
|
||||
if (mBuffer &&
|
||||
(mBuffer->IsImmutable() || mBuffer->GetSize() != aSize)) {
|
||||
autoRemove.mTexture = mBuffer;
|
||||
mBuffer = nullptr;
|
||||
if (mBackBuffer &&
|
||||
(mBackBuffer->IsImmutable() || mBackBuffer->GetSize() != aSize)) {
|
||||
autoRemove.mTexture = mBackBuffer;
|
||||
mBackBuffer = nullptr;
|
||||
}
|
||||
|
||||
bool bufferCreated = false;
|
||||
if (!mBuffer) {
|
||||
if (!mBackBuffer) {
|
||||
bool isOpaque = (aLayer->GetContentFlags() & Layer::CONTENT_OPAQUE);
|
||||
gfxContentType contentType = isOpaque
|
||||
? gfxContentType::COLOR
|
||||
@@ -90,46 +90,48 @@ CanvasClient2D::Update(gfx::IntSize aSize, ClientCanvasLayer* aLayer)
|
||||
flags |= TextureFlags::ORIGIN_BOTTOM_LEFT;
|
||||
}
|
||||
|
||||
mBuffer = CreateTextureClientForCanvas(surfaceFormat, aSize, flags, aLayer);
|
||||
if (!mBuffer) {
|
||||
mBackBuffer = CreateTextureClientForCanvas(surfaceFormat, aSize, flags, aLayer);
|
||||
if (!mBackBuffer) {
|
||||
NS_WARNING("Failed to allocate the TextureClient");
|
||||
return;
|
||||
}
|
||||
MOZ_ASSERT(mBuffer->CanExposeDrawTarget());
|
||||
MOZ_ASSERT(mBackBuffer->CanExposeDrawTarget());
|
||||
|
||||
bufferCreated = true;
|
||||
}
|
||||
|
||||
bool updated = false;
|
||||
{
|
||||
TextureClientAutoLock autoLock(mBuffer, OpenMode::OPEN_WRITE_ONLY);
|
||||
TextureClientAutoLock autoLock(mBackBuffer, OpenMode::OPEN_WRITE_ONLY);
|
||||
if (!autoLock.Succeeded()) {
|
||||
mBuffer = nullptr;
|
||||
mBackBuffer = nullptr;
|
||||
return;
|
||||
}
|
||||
|
||||
RefPtr<DrawTarget> target = mBuffer->BorrowDrawTarget();
|
||||
RefPtr<DrawTarget> target = mBackBuffer->BorrowDrawTarget();
|
||||
if (target) {
|
||||
aLayer->UpdateTarget(target);
|
||||
updated = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (bufferCreated && !AddTextureClient(mBuffer)) {
|
||||
mBuffer = nullptr;
|
||||
if (bufferCreated && !AddTextureClient(mBackBuffer)) {
|
||||
mBackBuffer = nullptr;
|
||||
return;
|
||||
}
|
||||
|
||||
if (updated) {
|
||||
AutoTArray<CompositableForwarder::TimedTextureClient,1> textures;
|
||||
CompositableForwarder::TimedTextureClient* t = textures.AppendElement();
|
||||
t->mTextureClient = mBuffer;
|
||||
t->mPictureRect = nsIntRect(nsIntPoint(0, 0), mBuffer->GetSize());
|
||||
t->mTextureClient = mBackBuffer;
|
||||
t->mPictureRect = nsIntRect(nsIntPoint(0, 0), mBackBuffer->GetSize());
|
||||
t->mFrameID = mFrameID;
|
||||
t->mInputFrameID = VRManagerChild::Get()->GetInputFrameID();
|
||||
GetForwarder()->UseTextures(this, textures);
|
||||
mBuffer->SyncWithObject(GetForwarder()->GetSyncObject());
|
||||
mBackBuffer->SyncWithObject(GetForwarder()->GetSyncObject());
|
||||
}
|
||||
|
||||
mBackBuffer.swap(mFrontBuffer);
|
||||
}
|
||||
|
||||
already_AddRefed<TextureClient>
|
||||
|
||||
@@ -99,7 +99,7 @@ public:
|
||||
|
||||
virtual void Clear() override
|
||||
{
|
||||
mBuffer = nullptr;
|
||||
mBackBuffer = mFrontBuffer = nullptr;
|
||||
}
|
||||
|
||||
virtual void Update(gfx::IntSize aSize, ClientCanvasLayer* aLayer) override;
|
||||
@@ -112,7 +112,7 @@ public:
|
||||
|
||||
virtual void OnDetach() override
|
||||
{
|
||||
mBuffer = nullptr;
|
||||
mBackBuffer = mFrontBuffer = nullptr;
|
||||
}
|
||||
|
||||
private:
|
||||
@@ -122,7 +122,8 @@ private:
|
||||
TextureFlags aFlags,
|
||||
ClientCanvasLayer* aLayer);
|
||||
|
||||
RefPtr<TextureClient> mBuffer;
|
||||
RefPtr<TextureClient> mBackBuffer;
|
||||
RefPtr<TextureClient> mFrontBuffer;
|
||||
};
|
||||
|
||||
// Used for GL canvases where we don't need to do any readback, i.e., with a
|
||||
|
||||
@@ -62,6 +62,13 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
virtual void HandleMemoryPressure() override
|
||||
{
|
||||
if (mCanvasClient) {
|
||||
mCanvasClient->HandleMemoryPressure();
|
||||
}
|
||||
}
|
||||
|
||||
virtual void FillSpecificAttributes(SpecificLayerAttributes& aAttrs) override
|
||||
{
|
||||
aAttrs = CanvasLayerAttributes(mFilter, mBounds);
|
||||
|
||||
@@ -60,6 +60,13 @@ protected:
|
||||
DestroyBackBuffer();
|
||||
}
|
||||
|
||||
virtual void HandleMemoryPressure() override
|
||||
{
|
||||
if (mImageClient) {
|
||||
mImageClient->HandleMemoryPressure();
|
||||
}
|
||||
}
|
||||
|
||||
virtual void FillSpecificAttributes(SpecificLayerAttributes& aAttrs) override
|
||||
{
|
||||
aAttrs = ImageLayerAttributes(mFilter, mScaleToSize, mScaleMode);
|
||||
|
||||
@@ -762,6 +762,10 @@ ClientLayerManager::ClearCachedResources(Layer* aSubtree)
|
||||
void
|
||||
ClientLayerManager::HandleMemoryPressure()
|
||||
{
|
||||
if (mRoot) {
|
||||
HandleMemoryPressureLayer(mRoot);
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < mTexturePools.Length(); i++) {
|
||||
mTexturePools[i]->ShrinkToMinimumSize();
|
||||
}
|
||||
@@ -777,6 +781,16 @@ ClientLayerManager::ClearLayer(Layer* aLayer)
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
ClientLayerManager::HandleMemoryPressureLayer(Layer* aLayer)
|
||||
{
|
||||
ClientLayer::ToClientLayer(aLayer)->HandleMemoryPressure();
|
||||
for (Layer* child = aLayer->GetFirstChild(); child;
|
||||
child = child->GetNextSibling()) {
|
||||
HandleMemoryPressureLayer(child);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
ClientLayerManager::GetBackendName(nsAString& aName)
|
||||
{
|
||||
|
||||
@@ -293,6 +293,8 @@ private:
|
||||
|
||||
void ClearLayer(Layer* aLayer);
|
||||
|
||||
void HandleMemoryPressureLayer(Layer* aLayer);
|
||||
|
||||
bool EndTransactionInternal(DrawPaintedLayerCallback aCallback,
|
||||
void* aCallbackData,
|
||||
EndTransactionFlags);
|
||||
@@ -380,6 +382,10 @@ public:
|
||||
|
||||
virtual void ClearCachedResources() { }
|
||||
|
||||
// Shrink memory usage.
|
||||
// Called when "memory-pressure" is observed.
|
||||
virtual void HandleMemoryPressure() { }
|
||||
|
||||
virtual void RenderLayer() = 0;
|
||||
virtual void RenderLayerWithReadback(ReadbackProcessor *aReadback) { RenderLayer(); }
|
||||
|
||||
|
||||
@@ -76,7 +76,14 @@ public:
|
||||
mValidRegion.SetEmpty();
|
||||
DestroyBackBuffer();
|
||||
}
|
||||
|
||||
|
||||
virtual void HandleMemoryPressure() override
|
||||
{
|
||||
if (mContentClient) {
|
||||
mContentClient->HandleMemoryPressure();
|
||||
}
|
||||
}
|
||||
|
||||
virtual void FillSpecificAttributes(SpecificLayerAttributes& aAttrs) override
|
||||
{
|
||||
aAttrs = PaintedLayerAttributes(GetValidRegion());
|
||||
|
||||
@@ -73,6 +73,13 @@ public:
|
||||
|
||||
virtual void ClearCachedResources() override;
|
||||
|
||||
virtual void HandleMemoryPressure() override
|
||||
{
|
||||
if (mContentClient) {
|
||||
mContentClient->HandleMemoryPressure();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper method to find the nearest ancestor layers which
|
||||
* scroll and have a displayport. The parameters are out-params
|
||||
|
||||
@@ -243,7 +243,15 @@ void
|
||||
CompositableClient::ClearCachedResources()
|
||||
{
|
||||
if (mTextureClientRecycler) {
|
||||
mTextureClientRecycler = nullptr;
|
||||
mTextureClientRecycler->ShrinkToMinimumSize();
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
CompositableClient::HandleMemoryPressure()
|
||||
{
|
||||
if (mTextureClientRecycler) {
|
||||
mTextureClientRecycler->ShrinkToMinimumSize();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -195,6 +195,12 @@ public:
|
||||
*/
|
||||
virtual void ClearCachedResources();
|
||||
|
||||
/**
|
||||
* Shrink memory usage.
|
||||
* Called when "memory-pressure" is observed.
|
||||
*/
|
||||
virtual void HandleMemoryPressure();
|
||||
|
||||
/**
|
||||
* Should be called when deataching a TextureClient from a Compositable, because
|
||||
* some platforms need to do some extra book keeping when this happens (for
|
||||
|
||||
@@ -357,7 +357,7 @@ ContentClientRemoteBuffer::GetUpdatedRegion(const nsIntRegion& aRegionToDraw,
|
||||
// changes and some changed buffer content isn't reflected in the
|
||||
// draw or invalidate region (on purpose!). When this happens, we
|
||||
// need to read back the entire buffer too.
|
||||
updatedRegion = aVisibleRegion;
|
||||
updatedRegion = aVisibleRegion.GetBounds();
|
||||
mIsNewBuffer = false;
|
||||
} else {
|
||||
updatedRegion = aRegionToDraw;
|
||||
|
||||
@@ -4,7 +4,10 @@
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "ImageClient.h"
|
||||
|
||||
#include <stdint.h> // for uint32_t
|
||||
|
||||
#include "ClientLayerManager.h" // for ClientLayer
|
||||
#include "ImageContainer.h" // for Image, PlanarYCbCrImage, etc
|
||||
#include "ImageTypes.h" // for ImageFormat::PLANAR_YCBCR, etc
|
||||
#include "GLImages.h" // for SurfaceTextureImage::Data, etc
|
||||
@@ -12,6 +15,7 @@
|
||||
#include "gfxPlatform.h" // for gfxPlatform
|
||||
#include "mozilla/Assertions.h" // for MOZ_ASSERT, etc
|
||||
#include "mozilla/RefPtr.h" // for RefPtr, already_AddRefed
|
||||
#include "mozilla/gfx/2D.h"
|
||||
#include "mozilla/gfx/BaseSize.h" // for BaseSize
|
||||
#include "mozilla/gfx/Point.h" // for IntSize
|
||||
#include "mozilla/gfx/Types.h" // for SurfaceFormat, etc
|
||||
@@ -29,8 +33,7 @@
|
||||
#include "nsDebug.h" // for NS_WARNING, NS_ASSERTION
|
||||
#include "nsISupportsImpl.h" // for Image::Release, etc
|
||||
#include "nsRect.h" // for mozilla::gfx::IntRect
|
||||
#include "mozilla/gfx/2D.h"
|
||||
#include "ClientLayerManager.h"
|
||||
|
||||
#ifdef MOZ_WIDGET_GONK
|
||||
#include "GrallocImages.h"
|
||||
#endif
|
||||
@@ -174,11 +177,12 @@ ImageClientSingle::UpdateImage(ImageContainer* aContainer, uint32_t aContentFlag
|
||||
#endif
|
||||
|
||||
RefPtr<TextureClient> texture = image->GetTextureClient(this);
|
||||
const bool hasTextureClient = !!texture;
|
||||
|
||||
for (int32_t i = mBuffers.Length() - 1; i >= 0; --i) {
|
||||
if (mBuffers[i].mImageSerial == image->GetSerial()) {
|
||||
if (texture) {
|
||||
MOZ_ASSERT(texture == mBuffers[i].mTextureClient);
|
||||
if (hasTextureClient) {
|
||||
MOZ_ASSERT(image->GetTextureClient(this) == mBuffers[i].mTextureClient);
|
||||
} else {
|
||||
texture = mBuffers[i].mTextureClient;
|
||||
}
|
||||
|
||||
@@ -144,6 +144,15 @@ TextureClientRecycleAllocator::Allocate(gfx::SurfaceFormat aFormat,
|
||||
aTextureFlags, aAllocFlags);
|
||||
}
|
||||
|
||||
void
|
||||
TextureClientRecycleAllocator::ShrinkToMinimumSize()
|
||||
{
|
||||
MutexAutoLock lock(mLock);
|
||||
while (!mPooledClients.empty()) {
|
||||
mPooledClients.pop();
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
TextureClientRecycleAllocator::RecycleTextureClient(TextureClient* aClient)
|
||||
{
|
||||
|
||||
@@ -49,6 +49,8 @@ public:
|
||||
TextureFlags aTextureFlags,
|
||||
TextureAllocationFlags flags = ALLOC_DEFAULT);
|
||||
|
||||
void ShrinkToMinimumSize();
|
||||
|
||||
protected:
|
||||
virtual already_AddRefed<TextureClient>
|
||||
Allocate(gfx::SurfaceFormat aFormat,
|
||||
|
||||
@@ -168,6 +168,23 @@ ImageLayerComposite::IsOpaque()
|
||||
return false;
|
||||
}
|
||||
|
||||
nsIntRegion
|
||||
ImageLayerComposite::GetFullyRenderedRegion()
|
||||
{
|
||||
if (!mImageHost ||
|
||||
!mImageHost->IsAttached()) {
|
||||
return GetShadowVisibleRegion().ToUnknownRegion();
|
||||
}
|
||||
|
||||
if (mScaleMode == ScaleMode::STRETCH) {
|
||||
nsIntRegion shadowVisibleRegion;
|
||||
shadowVisibleRegion.And(GetShadowVisibleRegion().ToUnknownRegion(), nsIntRegion(gfx::IntRect(0, 0, mScaleToSize.width, mScaleToSize.height)));
|
||||
return shadowVisibleRegion;
|
||||
}
|
||||
|
||||
return GetShadowVisibleRegion().ToUnknownRegion();
|
||||
}
|
||||
|
||||
CompositableHost*
|
||||
ImageLayerComposite::GetCompositableHost()
|
||||
{
|
||||
|
||||
@@ -61,6 +61,8 @@ public:
|
||||
|
||||
virtual bool IsOpaque() override;
|
||||
|
||||
virtual nsIntRegion GetFullyRenderedRegion() override;
|
||||
|
||||
protected:
|
||||
virtual void PrintInfo(std::stringstream& aStream, const char* aPrefix) override;
|
||||
|
||||
|
||||
@@ -553,7 +553,7 @@ public:
|
||||
* While progressive drawing is in progress this region will be
|
||||
* a subset of the shadow visible region.
|
||||
*/
|
||||
nsIntRegion GetFullyRenderedRegion();
|
||||
virtual nsIntRegion GetFullyRenderedRegion();
|
||||
|
||||
protected:
|
||||
gfx::Matrix4x4 mShadowTransform;
|
||||
|
||||
@@ -36,12 +36,6 @@ TiledLayerBufferComposite::~TiledLayerBufferComposite()
|
||||
Clear();
|
||||
}
|
||||
|
||||
/* static */ void
|
||||
TiledLayerBufferComposite::RecycleCallback(TextureHost* textureHost, void* aClosure)
|
||||
{
|
||||
textureHost->CompositorRecycle();
|
||||
}
|
||||
|
||||
void
|
||||
TiledLayerBufferComposite::SetCompositor(Compositor* aCompositor)
|
||||
{
|
||||
|
||||
@@ -146,10 +146,6 @@ public:
|
||||
|
||||
void SetCompositor(Compositor* aCompositor);
|
||||
|
||||
// Recycle callback for TextureHost.
|
||||
// Used when TiledContentClient is present in client side.
|
||||
static void RecycleCallback(TextureHost* textureHost, void* aClosure);
|
||||
|
||||
protected:
|
||||
|
||||
CSSToParentLayerScale2D mFrameResolution;
|
||||
|
||||
@@ -642,7 +642,9 @@ static CompositorD3D11* AssertD3D11Compositor(Compositor* aCompositor)
|
||||
{
|
||||
CompositorD3D11* compositor = aCompositor ? aCompositor->AsCompositorD3D11()
|
||||
: nullptr;
|
||||
MOZ_DIAGNOSTIC_ASSERT(!!compositor);
|
||||
if (!compositor) {
|
||||
gfxCriticalNote << "[D3D11] Attempt to set an incompatible compositor";
|
||||
}
|
||||
return compositor;
|
||||
}
|
||||
|
||||
@@ -670,6 +672,7 @@ DXGITextureHostD3D11::Lock()
|
||||
}
|
||||
if (!mTextureSource) {
|
||||
if (!mTexture && !OpenSharedHandle()) {
|
||||
gfxWindowsPlatform::GetPlatform()->ForceDeviceReset(ForcedDeviceResetReason::OPENSHAREDHANDLE);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@@ -672,7 +672,7 @@ CompositorD3D9::FailedToResetDevice() {
|
||||
if (mFailedResetAttempts > 10) {
|
||||
mFailedResetAttempts = 0;
|
||||
gfxWindowsPlatform::GetPlatform()->D3D9DeviceReset();
|
||||
gfxWarning() << "[D3D9] Unable to get a working D3D9 Compositor";
|
||||
gfxCriticalNote << "[D3D9] Unable to get a working D3D9 Compositor";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -905,7 +905,7 @@ TextureHostD3D9::UpdatedInternal(const nsIntRegion* aRegion)
|
||||
}
|
||||
|
||||
if (!mTextureSource->UpdateFromTexture(mTexture, regionToUpdate)) {
|
||||
gfxWarning() << "[D3D9] DataTextureSourceD3D9::UpdateFromTexture failed";
|
||||
gfxCriticalNote << "[D3D9] DataTextureSourceD3D9::UpdateFromTexture failed";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,17 @@
|
||||
# -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*-
|
||||
# vim: set filetype=python:
|
||||
# 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('/ipc/chromium/chromium-config.mozbuild')
|
||||
|
||||
Library('chromium_atomics')
|
||||
|
||||
# This test is copied from ../moz.build for atomicops_internals_mutex.cc
|
||||
ost = CONFIG['OS_TEST']
|
||||
if '86' not in ost and 'arm' not in ost and 'aarch64' != ost and 'mips' not in ost:
|
||||
SOURCES += [
|
||||
'../src/base/atomicops_internals_mutex.cc',
|
||||
'../src/base/lock_impl_posix.cc',
|
||||
]
|
||||
@@ -9,6 +9,7 @@ include(libevent_path_prefix + '/libeventcommon.mozbuild')
|
||||
|
||||
UNIFIED_SOURCES += [
|
||||
'src/base/at_exit.cc',
|
||||
'src/base/buffer.cc',
|
||||
'src/base/command_line.cc',
|
||||
'src/base/file_path.cc',
|
||||
'src/base/file_util.cc',
|
||||
@@ -17,7 +18,6 @@ UNIFIED_SOURCES += [
|
||||
'src/base/logging.cc',
|
||||
'src/base/message_loop.cc',
|
||||
'src/base/message_pump_default.cc',
|
||||
'src/base/non_thread_safe.cc',
|
||||
'src/base/pickle.cc',
|
||||
'src/base/rand_util.cc',
|
||||
'src/base/revocable_store.cc',
|
||||
@@ -34,11 +34,7 @@ UNIFIED_SOURCES += [
|
||||
'src/chrome/common/child_thread.cc',
|
||||
'src/chrome/common/chrome_switches.cc',
|
||||
'src/chrome/common/ipc_channel.cc',
|
||||
'src/chrome/common/ipc_channel_proxy.cc',
|
||||
'src/chrome/common/ipc_message.cc',
|
||||
'src/chrome/common/ipc_sync_channel.cc',
|
||||
'src/chrome/common/ipc_sync_message.cc',
|
||||
'src/chrome/common/message_router.cc',
|
||||
'src/chrome/common/notification_service.cc',
|
||||
]
|
||||
|
||||
@@ -165,3 +161,7 @@ CXXFLAGS += CONFIG['TK_CFLAGS']
|
||||
include('/ipc/chromium/chromium-config.mozbuild')
|
||||
|
||||
FINAL_LIBRARY = 'xul'
|
||||
|
||||
DIRS += [
|
||||
'atomics',
|
||||
]
|
||||
|
||||
@@ -0,0 +1,125 @@
|
||||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "buffer.h"
|
||||
|
||||
Buffer::Buffer()
|
||||
: mBuffer(nullptr),
|
||||
mSize(0),
|
||||
mReserved(0)
|
||||
{
|
||||
}
|
||||
|
||||
Buffer::~Buffer()
|
||||
{
|
||||
if (mBuffer) {
|
||||
free(mBuffer);
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
Buffer::empty() const
|
||||
{
|
||||
return mSize == 0;
|
||||
}
|
||||
|
||||
size_t
|
||||
Buffer::size() const
|
||||
{
|
||||
return mSize;
|
||||
}
|
||||
|
||||
const char*
|
||||
Buffer::data() const
|
||||
{
|
||||
return mBuffer;
|
||||
}
|
||||
|
||||
void
|
||||
Buffer::clear()
|
||||
{
|
||||
free(mBuffer);
|
||||
mBuffer = nullptr;
|
||||
mSize = 0;
|
||||
mReserved = 0;
|
||||
}
|
||||
|
||||
void
|
||||
Buffer::try_realloc(size_t newlength)
|
||||
{
|
||||
char* buffer = (char*)realloc(mBuffer, newlength);
|
||||
if (buffer) {
|
||||
mBuffer = buffer;
|
||||
mReserved = newlength;
|
||||
return;
|
||||
}
|
||||
|
||||
// If we're growing the buffer, crash. If we're shrinking, then we continue to
|
||||
// use the old (larger) buffer.
|
||||
MOZ_RELEASE_ASSERT(newlength <= mReserved);
|
||||
}
|
||||
|
||||
void
|
||||
Buffer::append(const char* bytes, size_t length)
|
||||
{
|
||||
if (mSize + length > mReserved) {
|
||||
try_realloc(mSize + length);
|
||||
}
|
||||
|
||||
memcpy(mBuffer + mSize, bytes, length);
|
||||
mSize += length;
|
||||
}
|
||||
|
||||
void
|
||||
Buffer::assign(const char* bytes, size_t length)
|
||||
{
|
||||
if (bytes >= mBuffer && bytes < mBuffer + mReserved) {
|
||||
MOZ_RELEASE_ASSERT(bytes + length <= mBuffer + mSize);
|
||||
memmove(mBuffer, bytes, length);
|
||||
mSize = length;
|
||||
try_realloc(length);
|
||||
} else {
|
||||
try_realloc(length);
|
||||
mSize = length;
|
||||
memcpy(mBuffer, bytes, length);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
Buffer::erase(size_t start, size_t count)
|
||||
{
|
||||
mSize -= count;
|
||||
memmove(mBuffer + start, mBuffer + start + count, mSize - start);
|
||||
try_realloc(mSize);
|
||||
}
|
||||
|
||||
void
|
||||
Buffer::reserve(size_t size)
|
||||
{
|
||||
if (mReserved < size) {
|
||||
try_realloc(size);
|
||||
}
|
||||
}
|
||||
|
||||
char*
|
||||
Buffer::trade_bytes(size_t count)
|
||||
{
|
||||
char* result = mBuffer;
|
||||
mSize = mReserved = mSize - count;
|
||||
mBuffer = mReserved ? (char*)malloc(mReserved) : nullptr;
|
||||
MOZ_RELEASE_ASSERT(!mReserved || mBuffer);
|
||||
if (mSize) {
|
||||
memcpy(mBuffer, result + count, mSize);
|
||||
}
|
||||
|
||||
// Try to resize the buffer down, but ignore failure. This can cause extra
|
||||
// copies, but so be it.
|
||||
char* resized = (char*)realloc(result, count);
|
||||
if (resized) {
|
||||
return resized;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#ifndef CHROME_BASE_BUFFER_H_
|
||||
#define CHROME_BASE_BUFFER_H_
|
||||
|
||||
// Buffer is a simple std::string-like class for buffering up IPC messages. Its
|
||||
// main distinguishing characteristic is the trade_bytes function.
|
||||
class Buffer {
|
||||
public:
|
||||
Buffer();
|
||||
~Buffer();
|
||||
|
||||
bool empty() const;
|
||||
const char* data() const;
|
||||
size_t size() const;
|
||||
|
||||
void clear();
|
||||
void append(const char* bytes, size_t length);
|
||||
void assign(const char* bytes, size_t length);
|
||||
void erase(size_t start, size_t count);
|
||||
|
||||
void reserve(size_t size);
|
||||
|
||||
// This function should be used by a caller who wants to extract the first
|
||||
// |count| bytes from the buffer. Rather than copying the bytes out, this
|
||||
// function returns the entire buffer. The bytes in range [count, size()) are
|
||||
// copied out to a new buffer which becomes the current buffer. The
|
||||
// presumption is that |count| is very large and approximately equal to size()
|
||||
// so not much needs to be copied.
|
||||
char* trade_bytes(size_t count);
|
||||
|
||||
private:
|
||||
void try_realloc(size_t newlength);
|
||||
|
||||
char* mBuffer;
|
||||
size_t mSize;
|
||||
size_t mReserved;
|
||||
};
|
||||
|
||||
#endif // CHROME_BASE_BUFFER_H_
|
||||
@@ -1,24 +0,0 @@
|
||||
// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#include "base/non_thread_safe.h"
|
||||
|
||||
// These checks are only done in debug builds.
|
||||
#ifndef NDEBUG
|
||||
|
||||
#include "base/logging.h"
|
||||
|
||||
NonThreadSafe::NonThreadSafe()
|
||||
: valid_thread_id_(PlatformThread::CurrentId()) {
|
||||
}
|
||||
|
||||
bool NonThreadSafe::CalledOnValidThread() const {
|
||||
return valid_thread_id_ == PlatformThread::CurrentId();
|
||||
}
|
||||
|
||||
NonThreadSafe::~NonThreadSafe() {
|
||||
DCHECK(CalledOnValidThread());
|
||||
}
|
||||
|
||||
#endif // NDEBUG
|
||||
@@ -1,52 +0,0 @@
|
||||
// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#ifndef BASE_NON_THREAD_SAFE_H__
|
||||
#define BASE_NON_THREAD_SAFE_H__
|
||||
|
||||
#include "base/platform_thread.h"
|
||||
|
||||
// A helper class used to help verify that methods of a class are
|
||||
// called from the same thread. One can inherit from this class and use
|
||||
// CalledOnValidThread() to verify.
|
||||
//
|
||||
// This is intended to be used with classes that appear to be thread safe, but
|
||||
// aren't. For example, a service or a singleton like the preferences system.
|
||||
//
|
||||
// Example:
|
||||
// class MyClass : public NonThreadSafe {
|
||||
// public:
|
||||
// void Foo() {
|
||||
// DCHECK(CalledOnValidThread());
|
||||
// ... (do stuff) ...
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// In Release mode, CalledOnValidThread will always return true.
|
||||
//
|
||||
#ifndef NDEBUG
|
||||
class NonThreadSafe {
|
||||
public:
|
||||
NonThreadSafe();
|
||||
~NonThreadSafe();
|
||||
|
||||
bool CalledOnValidThread() const;
|
||||
|
||||
private:
|
||||
PlatformThreadId valid_thread_id_;
|
||||
};
|
||||
#else
|
||||
// Do nothing in release mode.
|
||||
class NonThreadSafe {
|
||||
public:
|
||||
NonThreadSafe() {}
|
||||
~NonThreadSafe() {}
|
||||
|
||||
bool CalledOnValidThread() const {
|
||||
return true;
|
||||
}
|
||||
};
|
||||
#endif // NDEBUG
|
||||
|
||||
#endif // BASE_NON_THREAD_SAFE_H__
|
||||
@@ -122,10 +122,10 @@ Pickle::Pickle(int header_size)
|
||||
header_->payload_size = 0;
|
||||
}
|
||||
|
||||
Pickle::Pickle(const char* data, int data_len)
|
||||
Pickle::Pickle(const char* data, int data_len, Ownership ownership)
|
||||
: header_(reinterpret_cast<Header*>(const_cast<char*>(data))),
|
||||
header_size_(0),
|
||||
capacity_(kCapacityReadOnly),
|
||||
capacity_(ownership == BORROWS ? kCapacityReadOnly : data_len),
|
||||
variable_buffer_offset_(0) {
|
||||
if (data_len >= static_cast<int>(sizeof(Header)))
|
||||
header_size_ = data_len - header_->payload_size;
|
||||
@@ -670,3 +670,23 @@ const char* Pickle::FindNext(uint32_t header_size,
|
||||
|
||||
return start + header_size + hdr->payload_size;
|
||||
}
|
||||
|
||||
// static
|
||||
uint32_t Pickle::GetLength(uint32_t header_size,
|
||||
const char* start,
|
||||
const char* end) {
|
||||
DCHECK(header_size == AlignInt(header_size));
|
||||
DCHECK(header_size <= static_cast<memberAlignmentType>(kPayloadUnit));
|
||||
|
||||
if (end < start)
|
||||
return 0;
|
||||
size_t length = static_cast<size_t>(end - start);
|
||||
if (length < sizeof(Header))
|
||||
return 0;
|
||||
|
||||
const Header* hdr = reinterpret_cast<const Header*>(start);
|
||||
if (length < header_size)
|
||||
return 0;
|
||||
|
||||
return header_size + hdr->payload_size;
|
||||
}
|
||||
|
||||
@@ -32,6 +32,11 @@
|
||||
//
|
||||
class Pickle {
|
||||
public:
|
||||
enum Ownership {
|
||||
BORROWS,
|
||||
OWNS,
|
||||
};
|
||||
|
||||
~Pickle();
|
||||
|
||||
// Initialize a Pickle object using the default header size.
|
||||
@@ -42,11 +47,13 @@ class Pickle {
|
||||
// will be rounded up to ensure that the header size is 32bit-aligned.
|
||||
explicit Pickle(int header_size);
|
||||
|
||||
// Initializes a Pickle from a const block of data. The data is not copied;
|
||||
// instead the data is merely referenced by this Pickle. Only const methods
|
||||
// should be used on the Pickle when initialized this way. The header
|
||||
// padding size is deduced from the data length.
|
||||
Pickle(const char* data, int data_len);
|
||||
// Initializes a Pickle from a const block of data. If ownership == BORROWS,
|
||||
// the data is not copied; instead the data is merely referenced by this
|
||||
// Pickle. Only const methods should be used on the Pickle when initialized
|
||||
// this way. The header padding size is deduced from the data length. If
|
||||
// ownership == OWNS, then again no copying takes place. However, the buffer
|
||||
// is writable and will be freed when this Pickle is destroyed.
|
||||
Pickle(const char* data, int data_len, Ownership ownership = BORROWS);
|
||||
|
||||
// Initializes a Pickle as a deep copy of another Pickle.
|
||||
Pickle(const Pickle& other);
|
||||
@@ -62,6 +69,11 @@ class Pickle {
|
||||
int size() const { return static_cast<int>(header_size_ +
|
||||
header_->payload_size); }
|
||||
|
||||
// Return the full size of the memory allocated for this Pickle's data.
|
||||
uint32_t capacity() const {
|
||||
return capacity_;
|
||||
}
|
||||
|
||||
// Returns the data for this Pickle.
|
||||
const void* data() const { return header_; }
|
||||
|
||||
@@ -234,10 +246,6 @@ class Pickle {
|
||||
return header_ ? payload() + payload_size() : nullptr;
|
||||
}
|
||||
|
||||
uint32_t capacity() const {
|
||||
return capacity_;
|
||||
}
|
||||
|
||||
// Resizes the buffer for use when writing the specified amount of data. The
|
||||
// location that the data should be written at is returned, or NULL if there
|
||||
// was an error. Call EndWrite with the returned offset and the given length
|
||||
@@ -282,6 +290,12 @@ class Pickle {
|
||||
const char* range_start,
|
||||
const char* range_end);
|
||||
|
||||
// If the given range contains at least header_size bytes, return the length
|
||||
// of the pickled data including the header.
|
||||
static uint32_t GetLength(uint32_t header_size,
|
||||
const char* range_start,
|
||||
const char* range_end);
|
||||
|
||||
// The allocation granularity of the payload.
|
||||
static const int kPayloadUnit;
|
||||
|
||||
|
||||
@@ -6,12 +6,12 @@
|
||||
#ifndef BASE_TASK_H_
|
||||
#define BASE_TASK_H_
|
||||
|
||||
#include "base/non_thread_safe.h"
|
||||
#include "base/revocable_store.h"
|
||||
#include "base/tracked.h"
|
||||
#include "base/tuple.h"
|
||||
#include "mozilla/IndexSequence.h"
|
||||
#include "mozilla/Tuple.h"
|
||||
#include "nsISupportsImpl.h"
|
||||
|
||||
// Helper functions so that we can call a function a pass it arguments that come
|
||||
// from a Tuple.
|
||||
@@ -128,7 +128,7 @@ class ScopedTaskFactory : public RevocableStore {
|
||||
return new TaskWrapper(this);
|
||||
}
|
||||
|
||||
class TaskWrapper : public TaskType, public NonThreadSafe {
|
||||
class TaskWrapper : public TaskType {
|
||||
public:
|
||||
explicit TaskWrapper(RevocableStore* store) : revocable_(store) { }
|
||||
|
||||
@@ -137,9 +137,15 @@ class ScopedTaskFactory : public RevocableStore {
|
||||
TaskType::Run();
|
||||
}
|
||||
|
||||
~TaskWrapper() {
|
||||
NS_ASSERT_OWNINGTHREAD(TaskWrapper);
|
||||
}
|
||||
|
||||
private:
|
||||
Revocable revocable_;
|
||||
|
||||
NS_DECL_OWNINGTHREAD
|
||||
|
||||
DISALLOW_EVIL_CONSTRUCTORS(TaskWrapper);
|
||||
};
|
||||
|
||||
|
||||
@@ -154,13 +154,13 @@ ChildProcessHost::ListenerHook::ListenerHook(ChildProcessHost* host)
|
||||
}
|
||||
|
||||
void ChildProcessHost::ListenerHook::OnMessageReceived(
|
||||
const IPC::Message& msg) {
|
||||
IPC::Message&& msg) {
|
||||
|
||||
bool msg_is_ok = true;
|
||||
bool handled = false;
|
||||
|
||||
if (!handled) {
|
||||
host_->OnMessageReceived(msg);
|
||||
host_->OnMessageReceived(mozilla::Move(msg));
|
||||
}
|
||||
|
||||
if (!msg_is_ok)
|
||||
|
||||
@@ -75,7 +75,7 @@ class ChildProcessHost :
|
||||
void InstanceCreated();
|
||||
|
||||
// IPC::Channel::Listener implementation:
|
||||
virtual void OnMessageReceived(const IPC::Message& msg) { }
|
||||
virtual void OnMessageReceived(IPC::Message&& msg) { }
|
||||
virtual void OnChannelConnected(int32_t peer_pid) { }
|
||||
virtual void OnChannelError() { }
|
||||
|
||||
@@ -102,7 +102,7 @@ class ChildProcessHost :
|
||||
class ListenerHook : public IPC::Channel::Listener {
|
||||
public:
|
||||
explicit ListenerHook(ChildProcessHost* host);
|
||||
virtual void OnMessageReceived(const IPC::Message& msg);
|
||||
virtual void OnMessageReceived(IPC::Message&& msg);
|
||||
virtual void OnChannelConnected(int32_t peer_pid);
|
||||
virtual void OnChannelError();
|
||||
virtual void GetQueuedMessages(std::queue<IPC::Message>& queue);
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user