From 2cfa0fab9104394c93205e84c6da809db4137ff1 Mon Sep 17 00:00:00 2001 From: Mike Hommey Date: Thu, 13 Nov 2014 09:23:40 +0900 Subject: [PATCH 01/80] Bug 1096651 - Avoid using random bits when determining SSE3/SSE4 availability for the JIT. r=luke --- js/src/jit/shared/Assembler-x86-shared.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/js/src/jit/shared/Assembler-x86-shared.cpp b/js/src/jit/shared/Assembler-x86-shared.cpp index 61811a1ba954..6f4aa1ba6811 100644 --- a/js/src/jit/shared/Assembler-x86-shared.cpp +++ b/js/src/jit/shared/Assembler-x86-shared.cpp @@ -161,7 +161,11 @@ CPUInfo::SetSSEVersion() ); # else // On x86, preserve ebx. The compiler needs it for PIC mode. + // Some older processors don't fill the ecx register with cpuid, so clobber + // it before calling cpuid, so that there's no risk of picking random bits + // indicating SSE3/SSE4 are present. asm ( + "xor %%ecx, %%ecx;" "movl $0x1, %%eax;" "pushl %%ebx;" "cpuid;" From 486629b635c8bf8f744c2e750bbbaabd45783dcb Mon Sep 17 00:00:00 2001 From: Mike Hommey Date: Thu, 13 Nov 2014 09:24:28 +0900 Subject: [PATCH 02/80] Bug 1097506 - Pass a JSONWriteFunc to dmd::AnalyzeReports instead of a JSONWriter. r=njn The interesting feature JSONWriteFunc has, contrary to JSONWriter, is that it only has virtual methods, which makes it a better candidate to be passed around between libraries not linked against each other. This will allow to make dmd and libxul independent from each other. --- memory/replace/dmd/DMD.cpp | 59 ++++++++++++++-------------- memory/replace/dmd/DMD.h | 5 ++- memory/replace/dmd/test/SmokeDMD.cpp | 12 ++---- xpcom/base/nsMemoryInfoDumper.cpp | 3 +- 4 files changed, 38 insertions(+), 41 deletions(-) diff --git a/memory/replace/dmd/DMD.cpp b/memory/replace/dmd/DMD.cpp index 79eaec13cdff..d2539a363b01 100644 --- a/memory/replace/dmd/DMD.cpp +++ b/memory/replace/dmd/DMD.cpp @@ -1549,7 +1549,7 @@ private: }; static void -AnalyzeReportsImpl(JSONWriter& aWriter) +AnalyzeReportsImpl(UniquePtr aWriter) { if (!gIsDMDRunning) { return; @@ -1572,76 +1572,77 @@ AnalyzeReportsImpl(JSONWriter& aWriter) static int analysisCount = 1; StatusMsg("Dump %d {\n", analysisCount++); - aWriter.Start(); + JSONWriter writer(Move(aWriter)); + writer.Start(); { - aWriter.IntProperty("version", kOutputVersionNumber); + writer.IntProperty("version", kOutputVersionNumber); - aWriter.StartObjectProperty("invocation"); + writer.StartObjectProperty("invocation"); { - aWriter.StringProperty("dmdEnvVar", gOptions->DMDEnvVar()); - aWriter.IntProperty("sampleBelowSize", gOptions->SampleBelowSize()); + writer.StringProperty("dmdEnvVar", gOptions->DMDEnvVar()); + writer.IntProperty("sampleBelowSize", gOptions->SampleBelowSize()); } - aWriter.EndObject(); + writer.EndObject(); StatusMsg(" Constructing the heap block list...\n"); ToIdStringConverter isc; - aWriter.StartArrayProperty("blockList"); + writer.StartArrayProperty("blockList"); { for (BlockTable::Range r = gBlockTable->all(); !r.empty(); r.popFront()) { const Block& b = r.front(); b.AddStackTracesToTable(usedStackTraces); - aWriter.StartObjectElement(aWriter.SingleLineStyle); + writer.StartObjectElement(writer.SingleLineStyle); { if (!b.IsSampled()) { - aWriter.IntProperty("req", b.ReqSize()); + writer.IntProperty("req", b.ReqSize()); if (b.SlopSize() > 0) { - aWriter.IntProperty("slop", b.SlopSize()); + writer.IntProperty("slop", b.SlopSize()); } } - aWriter.StringProperty("alloc", isc.ToIdString(b.AllocStackTrace())); + writer.StringProperty("alloc", isc.ToIdString(b.AllocStackTrace())); if (b.NumReports() > 0) { - aWriter.StartArrayProperty("reps"); + writer.StartArrayProperty("reps"); { if (b.ReportStackTrace1()) { - aWriter.StringElement(isc.ToIdString(b.ReportStackTrace1())); + writer.StringElement(isc.ToIdString(b.ReportStackTrace1())); } if (b.ReportStackTrace2()) { - aWriter.StringElement(isc.ToIdString(b.ReportStackTrace2())); + writer.StringElement(isc.ToIdString(b.ReportStackTrace2())); } } - aWriter.EndArray(); + writer.EndArray(); } } - aWriter.EndObject(); + writer.EndObject(); } } - aWriter.EndArray(); + writer.EndArray(); StatusMsg(" Constructing the stack trace table...\n"); - aWriter.StartObjectProperty("traceTable"); + writer.StartObjectProperty("traceTable"); { for (StackTraceSet::Enum e(usedStackTraces); !e.empty(); e.popFront()) { const StackTrace* const st = e.front(); - aWriter.StartArrayProperty(isc.ToIdString(st), aWriter.SingleLineStyle); + writer.StartArrayProperty(isc.ToIdString(st), writer.SingleLineStyle); { for (uint32_t i = 0; i < st->Length(); i++) { const void* pc = st->Pc(i); - aWriter.StringElement(isc.ToIdString(pc)); + writer.StringElement(isc.ToIdString(pc)); usedPcs.put(pc); } } - aWriter.EndArray(); + writer.EndArray(); } } - aWriter.EndObject(); + writer.EndObject(); StatusMsg(" Constructing the stack frame table...\n"); - aWriter.StartObjectProperty("frameTable"); + writer.StartObjectProperty("frameTable"); { static const size_t locBufLen = 1024; char locBuf[locBufLen]; @@ -1652,14 +1653,14 @@ AnalyzeReportsImpl(JSONWriter& aWriter) // Use 0 for the frame number. See the JSON format description comment // in DMD.h to understand why. locService->GetLocation(0, pc, locBuf, locBufLen); - aWriter.StringProperty(isc.ToIdString(pc), locBuf); + writer.StringProperty(isc.ToIdString(pc), locBuf); } } - aWriter.EndObject(); + writer.EndObject(); iscSize = isc.sizeOfExcludingThis(MallocSizeOf); } - aWriter.End(); + writer.End(); if (gOptions->ShowDumpStats()) { Sizes sizes; @@ -1727,9 +1728,9 @@ AnalyzeReportsImpl(JSONWriter& aWriter) } MOZ_EXPORT void -AnalyzeReports(JSONWriter& aWriter) +AnalyzeReports(UniquePtr aWriter) { - AnalyzeReportsImpl(aWriter); + AnalyzeReportsImpl(Move(aWriter)); ClearReports(); } diff --git a/memory/replace/dmd/DMD.h b/memory/replace/dmd/DMD.h index 7a39551a7c65..3c543b96b9ec 100644 --- a/memory/replace/dmd/DMD.h +++ b/memory/replace/dmd/DMD.h @@ -10,10 +10,11 @@ #include #include "mozilla/Types.h" +#include "mozilla/UniquePtr.h" namespace mozilla { -class JSONWriter; +class JSONWriteFunc; namespace dmd { @@ -121,7 +122,7 @@ ClearReports(); // } // } MOZ_EXPORT void -AnalyzeReports(mozilla::JSONWriter& aWriter); +AnalyzeReports(mozilla::UniquePtr); struct Sizes { diff --git a/memory/replace/dmd/test/SmokeDMD.cpp b/memory/replace/dmd/test/SmokeDMD.cpp index 48c51283c987..2aa6efb0e272 100644 --- a/memory/replace/dmd/test/SmokeDMD.cpp +++ b/memory/replace/dmd/test/SmokeDMD.cpp @@ -119,8 +119,7 @@ RunTests() //--------- // AnalyzeReports 1. Zero for everything. - JSONWriter writer1(Move(f1)); - AnalyzeReports(writer1); + AnalyzeReports(Move(f1)); //--------- @@ -246,8 +245,7 @@ RunTests() //UseItOrLoseIt(z, seven); // AnalyzeReports 2. - JSONWriter writer2(Move(f2)); - AnalyzeReports(writer2); + AnalyzeReports(Move(f2)); //--------- @@ -263,8 +261,7 @@ RunTests() //free(z); // AnalyzeReports 3. - JSONWriter writer3(Move(f3)); - AnalyzeReports(writer3); + AnalyzeReports(Move(f3)); //--------- @@ -323,8 +320,7 @@ RunTests() // bytes of allocation overall, which is 64 less than the real value 1,488. // AnalyzeReports 4. - JSONWriter writer4(Move(f4)); - AnalyzeReports(writer4); + AnalyzeReports(Move(f4)); } int main() diff --git a/xpcom/base/nsMemoryInfoDumper.cpp b/xpcom/base/nsMemoryInfoDumper.cpp index 74208bb60021..47c4cd13e4fd 100644 --- a/xpcom/base/nsMemoryInfoDumper.cpp +++ b/xpcom/base/nsMemoryInfoDumper.cpp @@ -811,8 +811,7 @@ nsMemoryInfoDumper::DumpDMDToFile(FILE* aFile) } // Dump DMD's memory reports analysis to the file. - JSONWriter jsonWriter(MakeUnique(gzWriter)); - dmd::AnalyzeReports(jsonWriter); + dmd::AnalyzeReports(MakeUnique(gzWriter)); rv = gzWriter->Finish(); NS_WARN_IF(NS_FAILED(rv)); From 6c50ffddfddf4c82a008c37eebdf140e0b1de172 Mon Sep 17 00:00:00 2001 From: Chris Double Date: Thu, 13 Nov 2014 10:47:31 +1300 Subject: [PATCH 03/80] Bug 1065215 - MSE endOfStream() called within an 'updateend' event can fail with 'object no longer usable' - r=karl Reopens the MediaSource when SourceBuffer::Remove is called on an Ended MediaSource. Only run the Range Removal algorithm when MediaSource duration is changed instead of calling Remove on SourceBuffers. Updates tests for the fact that update{start,end} can now be called more than once due to DurationChange. --HG-- extra : rebase_source : efe01de2f7c6be09b29e2e19d69d9943c9ab5e52 --- dom/media/mediasource/MediaSource.cpp | 8 +--- dom/media/mediasource/SourceBuffer.cpp | 11 ++++- dom/media/mediasource/SourceBuffer.h | 3 ++ dom/media/mediasource/SourceBufferList.cpp | 9 ++-- dom/media/mediasource/SourceBufferList.h | 5 +- dom/media/mediasource/test/mochitest.ini | 1 + .../mediasource/test/test_BufferedSeek.html | 10 +++- .../mediasource/test/test_EndOfStream.html | 47 +++++++++++++++++++ .../mediasource/test/test_FrameSelection.html | 10 ++-- .../mediasource/test/test_MediaSource.html | 14 ++++-- .../test/test_SeekableAfterEndOfStream.html | 10 +++- .../test_SeekableAfterEndOfStreamSplit.html | 2 +- .../mediasource/test/test_SplitAppend.html | 10 ++-- .../test/test_SplitAppendDelay.html | 10 ++-- 14 files changed, 115 insertions(+), 35 deletions(-) create mode 100644 dom/media/mediasource/test/test_EndOfStream.html diff --git a/dom/media/mediasource/MediaSource.cpp b/dom/media/mediasource/MediaSource.cpp index 6a45d1118cbe..a41fe9eb2542 100644 --- a/dom/media/mediasource/MediaSource.cpp +++ b/dom/media/mediasource/MediaSource.cpp @@ -418,14 +418,10 @@ void MediaSource::DurationChange(double aOldDuration, double aNewDuration) { MOZ_ASSERT(NS_IsMainThread()); - MSE_DEBUG("MediaSource(%p)::DurationChange(aNewDuration=%f)", this, aNewDuration); + MSE_DEBUG("MediaSource(%p)::DurationChange(aOldDuration=%f, aNewDuration=%f)", this, aOldDuration, aNewDuration); if (aNewDuration < aOldDuration) { - ErrorResult rv; - mSourceBuffers->Remove(aNewDuration, aOldDuration, rv); - if (rv.Failed()) { - return; - } + mSourceBuffers->RangeRemoval(aNewDuration, aOldDuration); } // TODO: If partial audio frames/text cues exist, clamp duration based on mSourceBuffers. } diff --git a/dom/media/mediasource/SourceBuffer.cpp b/dom/media/mediasource/SourceBuffer.cpp index 320e2a6559e1..838e02c56ba9 100644 --- a/dom/media/mediasource/SourceBuffer.cpp +++ b/dom/media/mediasource/SourceBuffer.cpp @@ -188,10 +188,19 @@ SourceBuffer::Remove(double aStart, double aEnd, ErrorResult& aRv) aRv.Throw(NS_ERROR_DOM_INVALID_ACCESS_ERR); return; } - if (mUpdating || mMediaSource->ReadyState() != MediaSourceReadyState::Open) { + if (mUpdating) { aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR); return; } + if (mMediaSource->ReadyState() == MediaSourceReadyState::Ended) { + mMediaSource->SetReadyState(MediaSourceReadyState::Open); + } + RangeRemoval(aStart, aEnd); +} + +void +SourceBuffer::RangeRemoval(double aStart, double aEnd) +{ StartUpdating(); /// TODO: Run coded frame removal algorithm. diff --git a/dom/media/mediasource/SourceBuffer.h b/dom/media/mediasource/SourceBuffer.h index 5be60b50a219..88a6f892a1db 100644 --- a/dom/media/mediasource/SourceBuffer.h +++ b/dom/media/mediasource/SourceBuffer.h @@ -108,6 +108,9 @@ public: double GetBufferedStart(); double GetBufferedEnd(); + // Runs the range removal algorithm as defined by the MSE spec. + void RangeRemoval(double aStart, double aEnd); + #if defined(DEBUG) void Dump(const char* aPath); #endif diff --git a/dom/media/mediasource/SourceBufferList.cpp b/dom/media/mediasource/SourceBufferList.cpp index d833bc9ddbc9..041fbb80ed96 100644 --- a/dom/media/mediasource/SourceBufferList.cpp +++ b/dom/media/mediasource/SourceBufferList.cpp @@ -108,15 +108,12 @@ SourceBufferList::AnyUpdating() } void -SourceBufferList::Remove(double aStart, double aEnd, ErrorResult& aRv) +SourceBufferList::RangeRemoval(double aStart, double aEnd) { MOZ_ASSERT(NS_IsMainThread()); - MSE_DEBUG("SourceBufferList(%p)::Remove(aStart=%f, aEnd=%f", this, aStart, aEnd); + MSE_DEBUG("SourceBufferList(%p)::RangeRemoval(aStart=%f, aEnd=%f", this, aStart, aEnd); for (uint32_t i = 0; i < mSourceBuffers.Length(); ++i) { - mSourceBuffers[i]->Remove(aStart, aEnd, aRv); - if (aRv.Failed()) { - return; - } + mSourceBuffers[i]->RangeRemoval(aStart, aEnd); } } diff --git a/dom/media/mediasource/SourceBufferList.h b/dom/media/mediasource/SourceBufferList.h index ca5087f2ea22..de02b914a435 100644 --- a/dom/media/mediasource/SourceBufferList.h +++ b/dom/media/mediasource/SourceBufferList.h @@ -66,9 +66,8 @@ public: // Returns true if updating is true on any SourceBuffers in the list. bool AnyUpdating(); - // Calls Remove(aStart, aEnd) on each SourceBuffer in the list. Aborts on - // first error, with result returned in aRv. - void Remove(double aStart, double aEnd, ErrorResult& aRv); + // Runs the range removal steps from the MSE specification on each SourceBuffer. + void RangeRemoval(double aStart, double aEnd); // Mark all SourceBuffers input buffers as ended. void Ended(); diff --git a/dom/media/mediasource/test/mochitest.ini b/dom/media/mediasource/test/mochitest.ini index 9d527391816b..2bb16b2fd8bc 100644 --- a/dom/media/mediasource/test/mochitest.ini +++ b/dom/media/mediasource/test/mochitest.ini @@ -9,6 +9,7 @@ support-files = [test_MediaSource_disabled.html] [test_BufferedSeek.html] [test_BufferingWait.html] +[test_EndOfStream.html] [test_FrameSelection.html] [test_HaveMetadataUnbufferedSeek.html] [test_LoadedMetadataFired.html] diff --git a/dom/media/mediasource/test/test_BufferedSeek.html b/dom/media/mediasource/test/test_BufferedSeek.html index b800a573576f..949fee773b7d 100644 --- a/dom/media/mediasource/test/test_BufferedSeek.html +++ b/dom/media/mediasource/test/test_BufferedSeek.html @@ -12,6 +12,8 @@ SimpleTest.waitForExplicitFinish(); +var updateCount = 0; + runWithMSE(function (ms, v) { ms.addEventListener("sourceopen", function () { var sb = ms.addSourceBuffer("video/webm"); @@ -19,7 +21,13 @@ runWithMSE(function (ms, v) { fetchWithXHR("seek.webm", function (arrayBuffer) { sb.appendBuffer(new Uint8Array(arrayBuffer)); sb.addEventListener("updateend", function () { - ms.endOfStream() + updateCount++; + /* Ensure that we endOfStream on the first update event only as endOfStream can + raise more if the duration of the last buffered range and the intial duration + differ. See bug 1065207 */ + if (updateCount == 1) { + ms.endOfStream(); + }; }); }); diff --git a/dom/media/mediasource/test/test_EndOfStream.html b/dom/media/mediasource/test/test_EndOfStream.html new file mode 100644 index 000000000000..0ab76701dfdf --- /dev/null +++ b/dom/media/mediasource/test/test_EndOfStream.html @@ -0,0 +1,47 @@ + + + + MSE: endOfStream call after an appendBuffer + + + + + +
+
+
+ + diff --git a/dom/media/mediasource/test/test_FrameSelection.html b/dom/media/mediasource/test/test_FrameSelection.html index d75d8f7ddedd..bb2634c706a1 100644 --- a/dom/media/mediasource/test/test_FrameSelection.html +++ b/dom/media/mediasource/test/test_FrameSelection.html @@ -12,6 +12,8 @@ SimpleTest.waitForExplicitFinish(); +var updateCount = 0; + runWithMSE(function (ms, v) { ms.addEventListener("sourceopen", function () { var sb = ms.addSourceBuffer("video/webm"); @@ -34,13 +36,13 @@ runWithMSE(function (ms, v) { fetchWithXHR("seek_lowres.webm", function (arrayBuffer) { // Append initialization segment. sb.appendBuffer(new Uint8Array(arrayBuffer, 0, 438)); - var first = true; sb.addEventListener("updateend", function () { - if (first) { + updateCount++; + if (updateCount == 1) { // Append media segment covering range [2, 4]. sb.appendBuffer(new Uint8Array(arrayBuffer, 51003)); - first = false; - } else { + } + else if (updateCount == 2) { ms.endOfStream(); target = targets.shift(); v.currentTime = target.currentTime; diff --git a/dom/media/mediasource/test/test_MediaSource.html b/dom/media/mediasource/test/test_MediaSource.html index 131d64b1c485..53c03cefa130 100644 --- a/dom/media/mediasource/test/test_MediaSource.html +++ b/dom/media/mediasource/test/test_MediaSource.html @@ -57,7 +57,12 @@ runWithMSE(function () { sb.addEventListener("update", function () { is(sb.updating, false, "SourceBuffer.updating is expected value in update event"); updateCount++; - ms.endOfStream(); + /* Ensure that we endOfStream on the first update event only as endOfStream can + raise more if the duration of the last buffered range and the intial duration + differ. See bug 1065207 */ + if (updateCount == 1) { + ms.endOfStream(); + } }); sb.addEventListener("updatestart", function () { @@ -84,9 +89,10 @@ runWithMSE(function () { // XXX: Duration should be exactly 4.0, see bug 1065207. ok(Math.abs(v.duration - 4) <= 0.002, "Video has correct duration"); ok(Math.abs(v.currentTime - 4) <= 0.002, "Video has played to end"); - is(updateCount, 1, "update event received"); - is(updateendCount, 1, "updateend event received"); - is(updatestartCount, 1, "updatestart event received"); + // XXX: 2 update events can be received dueto duration differences, see bug 1065207. + ok(updateCount == 1 || updateCount == 2, "update event received"); + ok(updateendCount == 1 || updateendCount == 2, "updateend event received"); + ok(updatestartCount == 1 || updatestartCount == 2, "updatestart event received"); is(loadedmetadataCount, 1, "loadedmetadata event received"); v.parentNode.removeChild(v); SimpleTest.finish(); diff --git a/dom/media/mediasource/test/test_SeekableAfterEndOfStream.html b/dom/media/mediasource/test/test_SeekableAfterEndOfStream.html index 7ffe68686685..850434429a24 100644 --- a/dom/media/mediasource/test/test_SeekableAfterEndOfStream.html +++ b/dom/media/mediasource/test/test_SeekableAfterEndOfStream.html @@ -12,6 +12,8 @@ SimpleTest.waitForExplicitFinish(); +var updateCount = 0; + runWithMSE(function (ms, v) { ms.addEventListener("sourceopen", function () { var sb = ms.addSourceBuffer("video/webm"); @@ -19,7 +21,13 @@ runWithMSE(function (ms, v) { fetchWithXHR("seek.webm", function (arrayBuffer) { sb.appendBuffer(new Uint8Array(arrayBuffer)); sb.addEventListener("updateend", function () { - ms.endOfStream() + updateCount++; + /* Ensure that we endOfStream on the first update event only as endOfStream can + raise more if the duration of the last buffered range and the intial duration + differ. See bug 1065207 */ + if (updateCount == 1) { + ms.endOfStream(); + }; }); }); diff --git a/dom/media/mediasource/test/test_SeekableAfterEndOfStreamSplit.html b/dom/media/mediasource/test/test_SeekableAfterEndOfStreamSplit.html index 5f75f11ffec2..771f9b159a60 100644 --- a/dom/media/mediasource/test/test_SeekableAfterEndOfStreamSplit.html +++ b/dom/media/mediasource/test/test_SeekableAfterEndOfStreamSplit.html @@ -24,7 +24,7 @@ runWithMSE(function (ms, v) { if (updateCount == 1) { sb.appendBuffer(new Uint8Array(arrayBuffer, 25223)); } - else { + else if (updateCount == 2) { ms.endOfStream(); } }); diff --git a/dom/media/mediasource/test/test_SplitAppend.html b/dom/media/mediasource/test/test_SplitAppend.html index f743032080d7..e87bd00edca5 100644 --- a/dom/media/mediasource/test/test_SplitAppend.html +++ b/dom/media/mediasource/test/test_SplitAppend.html @@ -12,18 +12,20 @@ SimpleTest.waitForExplicitFinish(); +var updateCount = 0; + runWithMSE(function (ms, v) { ms.addEventListener("sourceopen", function () { var sb = ms.addSourceBuffer("video/webm"); fetchWithXHR("seek.webm", function (arrayBuffer) { sb.appendBuffer(new Uint8Array(arrayBuffer, 0, 318)); - var first = true; sb.addEventListener("updateend", function () { - if (first) { + updateCount++; + if (updateCount == 1) { sb.appendBuffer(new Uint8Array(arrayBuffer, 318)); - first = false; - } else { + } + else if (updateCount == 2) { ms.endOfStream(); } }); diff --git a/dom/media/mediasource/test/test_SplitAppendDelay.html b/dom/media/mediasource/test/test_SplitAppendDelay.html index 10dde8b8156e..f4604b3d0c1c 100644 --- a/dom/media/mediasource/test/test_SplitAppendDelay.html +++ b/dom/media/mediasource/test/test_SplitAppendDelay.html @@ -12,20 +12,22 @@ SimpleTest.waitForExplicitFinish(); +var updateCount = 0; + runWithMSE(function (ms, v) { ms.addEventListener("sourceopen", function () { var sb = ms.addSourceBuffer("video/webm"); fetchWithXHR("seek.webm", function (arrayBuffer) { sb.appendBuffer(new Uint8Array(arrayBuffer, 0, 318)); - var first = true; sb.addEventListener("updateend", function () { - if (first) { + updateCount++; + if (updateCount == 1) { window.setTimeout(function () { sb.appendBuffer(new Uint8Array(arrayBuffer, 318)); - first = false; }, 1000); - } else { + } + else if (updateCount == 2) { ms.endOfStream(); } }); From cfa4228c82924bf9020fbb625edac1a45d989059 Mon Sep 17 00:00:00 2001 From: Chris Double Date: Thu, 13 Nov 2014 10:47:38 +1300 Subject: [PATCH 04/80] Bug 1065215 - Fix EME test for changes to MediaSource::endOfStream - r=cpearce --HG-- extra : rebase_source : 95a4bf916ddbb6a11ef66f3700a9ef0ed39d0d25 --- dom/media/test/eme.js | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/dom/media/test/eme.js b/dom/media/test/eme.js index 3d3a2c3af85f..d46a01c00629 100644 --- a/dom/media/test/eme.js +++ b/dom/media/test/eme.js @@ -121,6 +121,15 @@ function PlayFragmented(test, elem, token) var curFragment = 0; function addNextFragment() { + /* We can get another updateevent as a result of calling ms.endOfStream() if + the highest end time of our source buffers is different from that of the + media source duration. Due to bug 1065207 this can happen because of + inaccuracies in the frame duration calculations. Check if we are already + "ended" and ignore the update event */ + if (ms.readyState == "ended") { + return; + } + if (curFragment >= test.fragments.length) { Log(token, "addNextFragment() end of stream"); ms.endOfStream(); From 9cf2985921fa912f3b642e4de20dacbb7f003ed9 Mon Sep 17 00:00:00 2001 From: Chris Double Date: Thu, 13 Nov 2014 10:47:43 +1300 Subject: [PATCH 05/80] Bug 1065215 - web platform test should expect pass for SourceBuffer.remove reopening MediaSource - r=karl --HG-- extra : rebase_source : 4e301c6e3c22d8e7702ff964f76c596ae00c4ca8 --- .../web-platform/meta/media-source/mediasource-remove.html.ini | 3 --- 1 file changed, 3 deletions(-) diff --git a/testing/web-platform/meta/media-source/mediasource-remove.html.ini b/testing/web-platform/meta/media-source/mediasource-remove.html.ini index e1dfbe1f4562..ff9097294991 100644 --- a/testing/web-platform/meta/media-source/mediasource-remove.html.ini +++ b/testing/web-platform/meta/media-source/mediasource-remove.html.ini @@ -1,9 +1,6 @@ [mediasource-remove.html] type: testharness expected: TIMEOUT - [Test remove transitioning readyState from \'ended\' to \'open\'.] - expected: FAIL - [Test removing all appended data.] expected: FAIL From 512e1cc4ef416566bc983fbccdb296187e710e05 Mon Sep 17 00:00:00 2001 From: Monica Chew Date: Thu, 2 Oct 2014 15:49:26 -0700 Subject: [PATCH 06/80] Bug 1046430: Make cookie behavior the same on beta/release as on aurora/nightly (r=jdm) --- .../components/preferences/in-content/privacy.js | 13 ------------- .../in-content/tests/browser_privacypane_4.js | 8 ++------ browser/components/preferences/privacy.js | 13 ------------- .../preferences/tests/browser_privacypane_4.js | 8 ++------ modules/libpref/init/all.js | 4 ---- .../document-cookie.html.ini | 4 ++++ 6 files changed, 8 insertions(+), 42 deletions(-) create mode 100644 testing/web-platform/meta/html/dom/documents/resource-metadata-management/document-cookie.html.ini diff --git a/browser/components/preferences/in-content/privacy.js b/browser/components/preferences/in-content/privacy.js index c44787c142d5..c3846d5b8da0 100644 --- a/browser/components/preferences/in-content/privacy.js +++ b/browser/components/preferences/in-content/privacy.js @@ -203,13 +203,8 @@ var gPrivacyPane = { // select the remember forms history option document.getElementById("browser.formfill.enable").value = true; -#ifdef RELEASE_BUILD // select the allow cookies option document.getElementById("network.cookie.cookieBehavior").value = 0; -#else - // select the limit cookies option - document.getElementById("network.cookie.cookieBehavior").value = 3; -#endif // select the cookie lifetime policy option document.getElementById("network.cookie.lifetimePolicy").value = 0; @@ -429,19 +424,11 @@ var gPrivacyPane = { var accept = document.getElementById("acceptCookies"); var acceptThirdPartyMenu = document.getElementById("acceptThirdPartyMenu"); -#ifdef RELEASE_BUILD // if we're enabling cookies, automatically select 'accept third party always' if (accept.checked) acceptThirdPartyMenu.selectedIndex = 0; return accept.checked ? 0 : 2; -#else - // if we're enabling cookies, automatically select 'accept third party from visited' - if (accept.checked) - acceptThirdPartyMenu.selectedIndex = 1; - - return accept.checked ? 3 : 2; -#endif }, /** diff --git a/browser/components/preferences/in-content/tests/browser_privacypane_4.js b/browser/components/preferences/in-content/tests/browser_privacypane_4.js index 9dd90291bee7..b09f0e215fc2 100644 --- a/browser/components/preferences/in-content/tests/browser_privacypane_4.js +++ b/browser/components/preferences/in-content/tests/browser_privacypane_4.js @@ -17,14 +17,10 @@ function test() { test_custom_retention("acceptCookies", "remember"), test_custom_retention("acceptCookies", "custom") ], - (runtime.isReleaseBuild ? [ + [ test_custom_retention("acceptThirdPartyMenu", "remember", "visited"), test_custom_retention("acceptThirdPartyMenu", "custom", "always") - ] - : [ - test_custom_retention("acceptThirdPartyMenu", "remember", "always"), - test_custom_retention("acceptThirdPartyMenu", "custom", "visited") - ]), [ + ], [ test_custom_retention("keepCookiesUntil", "remember", 1), test_custom_retention("keepCookiesUntil", "custom", 2), test_custom_retention("keepCookiesUntil", "custom", 0), diff --git a/browser/components/preferences/privacy.js b/browser/components/preferences/privacy.js index 8381be5e724b..c44a38d6b38d 100644 --- a/browser/components/preferences/privacy.js +++ b/browser/components/preferences/privacy.js @@ -165,13 +165,8 @@ var gPrivacyPane = { // select the remember forms history option document.getElementById("browser.formfill.enable").value = true; -#ifdef RELEASE_BUILD // select the accept cookies option document.getElementById("network.cookie.cookieBehavior").value = 0; -#else - // select the limit cookies option - document.getElementById("network.cookie.cookieBehavior").value = 3; -#endif // select the cookie lifetime policy option document.getElementById("network.cookie.lifetimePolicy").value = 0; @@ -392,19 +387,11 @@ var gPrivacyPane = { var accept = document.getElementById("acceptCookies"); var acceptThirdPartyMenu = document.getElementById("acceptThirdPartyMenu"); -#ifdef RELEASE_BUILD // if we're enabling cookies, automatically select 'accept third party always' if (accept.checked) acceptThirdPartyMenu.selectedIndex = 0; return accept.checked ? 0 : 2; -#else - // if we're enabling cookies, automatically select 'accept third party from visited' - if (accept.checked) - acceptThirdPartyMenu.selectedIndex = 1; - - return accept.checked ? 3 : 2; -#endif }, /** diff --git a/browser/components/preferences/tests/browser_privacypane_4.js b/browser/components/preferences/tests/browser_privacypane_4.js index d44af109eaaa..a86252922380 100644 --- a/browser/components/preferences/tests/browser_privacypane_4.js +++ b/browser/components/preferences/tests/browser_privacypane_4.js @@ -18,14 +18,10 @@ function test() { test_custom_retention("acceptCookies", "remember"), test_custom_retention("acceptCookies", "custom") ], - (runtime.isReleaseBuild ? [ + [ test_custom_retention("acceptThirdPartyMenu", "remember", "visited"), test_custom_retention("acceptThirdPartyMenu", "custom", "always") - ] - : [ - test_custom_retention("acceptThirdPartyMenu", "remember", "always"), - test_custom_retention("acceptThirdPartyMenu", "custom", "visited") - ]), [ + ], [ test_custom_retention("keepCookiesUntil", "remember", 1), test_custom_retention("keepCookiesUntil", "custom", 2), test_custom_retention("keepCookiesUntil", "custom", 0), diff --git a/modules/libpref/init/all.js b/modules/libpref/init/all.js index 655334c2529b..050fb925d68b 100644 --- a/modules/libpref/init/all.js +++ b/modules/libpref/init/all.js @@ -1656,11 +1656,7 @@ pref("network.proxy.proxy_over_tls", true); pref("network.proxy.no_proxies_on", "localhost, 127.0.0.1"); pref("network.proxy.failover_timeout", 1800); // 30 minutes pref("network.online", true); //online/offline -#ifdef RELEASE_BUILD pref("network.cookie.cookieBehavior", 0); // 0-Accept, 1-dontAcceptForeign, 2-dontUse, 3-limitForeign -#else -pref("network.cookie.cookieBehavior", 3); // 0-Accept, 1-dontAcceptForeign, 2-dontUse, 3-limitForeign -#endif #ifdef ANDROID pref("network.cookie.cookieBehavior", 0); // Keep the old default of accepting all cookies #endif diff --git a/testing/web-platform/meta/html/dom/documents/resource-metadata-management/document-cookie.html.ini b/testing/web-platform/meta/html/dom/documents/resource-metadata-management/document-cookie.html.ini new file mode 100644 index 000000000000..5c40910e6bbb --- /dev/null +++ b/testing/web-platform/meta/html/dom/documents/resource-metadata-management/document-cookie.html.ini @@ -0,0 +1,4 @@ +[document-cookie.html] + type: testharness + [getting cookie for a cookie-averse document returns empty string, setting does nothing] + expected: FAIL From c076d14da138e7fa26da0fac61c3ae87e4c7ca2d Mon Sep 17 00:00:00 2001 From: Sotaro Ikeda Date: Wed, 12 Nov 2014 17:47:10 -0800 Subject: [PATCH 07/80] Bug 1091777 - Add TextureClient recycling to CairoImag r=nical --- gfx/layers/ImageContainer.cpp | 32 ++- gfx/layers/ImageContainer.h | 2 +- gfx/layers/client/CompositableClient.cpp | 24 ++ gfx/layers/client/CompositableClient.h | 6 +- gfx/layers/client/TextureClient.cpp | 46 ++++ gfx/layers/client/TextureClient.h | 26 +- .../client/TextureClientRecycleAllocator.cpp | 257 ++++++++++++++++++ .../client/TextureClientRecycleAllocator.h | 49 ++++ gfx/layers/client/TiledContentClient.cpp | 1 + gfx/layers/composite/TextureHost.cpp | 21 ++ gfx/layers/composite/TextureHost.h | 2 + gfx/layers/ipc/PTexture.ipdl | 3 + gfx/layers/moz.build | 2 + 13 files changed, 454 insertions(+), 17 deletions(-) create mode 100644 gfx/layers/client/TextureClientRecycleAllocator.cpp create mode 100644 gfx/layers/client/TextureClientRecycleAllocator.h diff --git a/gfx/layers/ImageContainer.cpp b/gfx/layers/ImageContainer.cpp index 75d42fd12573..f0ca6b13bc0e 100644 --- a/gfx/layers/ImageContainer.cpp +++ b/gfx/layers/ImageContainer.cpp @@ -496,11 +496,33 @@ CairoImage::GetTextureClient(CompositableClient *aClient) return nullptr; } - // gfx::BackendType::NONE means default to content backend - textureClient = aClient->CreateTextureClientForDrawing(surface->GetFormat(), - surface->GetSize(), - gfx::BackendType::NONE, - TextureFlags::DEFAULT); + +// XXX windows' TextureClients do not hold ISurfaceAllocator, +// recycler does not work on windows. +#ifndef XP_WIN + +// XXX only gonk ensure when TextureClient is recycled, +// TextureHost is not used by CompositableHost. +#ifdef MOZ_WIDGET_GONK + RefPtr recycler = + aClient->GetTextureClientRecycler(); + if (recycler) { + textureClient = + recycler->CreateOrRecycleForDrawing(surface->GetFormat(), + surface->GetSize(), + gfx::BackendType::NONE, + aClient->GetTextureFlags()); + } +#endif + +#endif + if (!textureClient) { + // gfx::BackendType::NONE means default to content backend + textureClient = aClient->CreateTextureClientForDrawing(surface->GetFormat(), + surface->GetSize(), + gfx::BackendType::NONE, + TextureFlags::DEFAULT); + } if (!textureClient) { return nullptr; } diff --git a/gfx/layers/ImageContainer.h b/gfx/layers/ImageContainer.h index 9d7b41668308..8ca6df4941fc 100644 --- a/gfx/layers/ImageContainer.h +++ b/gfx/layers/ImageContainer.h @@ -811,7 +811,7 @@ public: virtual ISharedImage* AsSharedImage() { return this; } virtual uint8_t* GetBuffer() { return nullptr; } - virtual TextureClient* GetTextureClient(CompositableClient* aClient); + virtual TextureClient* GetTextureClient(CompositableClient* aClient) MOZ_OVERRIDE; gfx::IntSize GetSize() { return mSize; } diff --git a/gfx/layers/client/CompositableClient.cpp b/gfx/layers/client/CompositableClient.cpp index c51329e00168..2b11c597251b 100644 --- a/gfx/layers/client/CompositableClient.cpp +++ b/gfx/layers/client/CompositableClient.cpp @@ -219,6 +219,7 @@ CompositableClient::AddTextureClient(TextureClient* aClient) if(!aClient || !aClient->IsAllocated()) { return false; } + aClient->SetAddedToCompositableClient(); return aClient->InitIPDLActor(mForwarder); } @@ -233,5 +234,28 @@ CompositableClient::RemoveTexture(TextureClient* aTexture) mForwarder->RemoveTextureFromCompositable(this, aTexture); } +CompositableClient::ClearCachedResources() +{ + if (mTextureClientRecycler) { + mTextureClientRecycler = nullptr; + } +} + +TextureClientRecycleAllocator* +CompositableClient::GetTextureClientRecycler() +{ + if (mTextureClientRecycler) { + return mTextureClientRecycler; + } + + if (!mForwarder) { + return nullptr; + } + + mTextureClientRecycler = + new layers::TextureClientRecycleAllocator(mForwarder); + return mTextureClientRecycler; +} + } // namespace layers } // namespace mozilla diff --git a/gfx/layers/client/CompositableClient.h b/gfx/layers/client/CompositableClient.h index 0e0c5cca652b..0c51e3f726b1 100644 --- a/gfx/layers/client/CompositableClient.h +++ b/gfx/layers/client/CompositableClient.h @@ -16,6 +16,7 @@ #include "mozilla/layers/CompositorTypes.h" #include "mozilla/layers/LayersTypes.h" // for LayersBackend #include "mozilla/layers/TextureClient.h" // for TextureClient +#include "mozilla/layers/TextureClientRecycleAllocator.h" // for TextureClientRecycleAllocator #include "nsISupportsImpl.h" // for MOZ_COUNT_CTOR, etc namespace mozilla { @@ -194,7 +195,7 @@ public: * Clear any resources that are not immediately necessary. This may be called * in low-memory conditions. */ - virtual void ClearCachedResources() {} + virtual void ClearCachedResources(); /** * Should be called when deataching a TextureClient from a Compositable, because @@ -229,12 +230,15 @@ public: TextureFlags GetTextureFlags() const { return mTextureFlags; } + TextureClientRecycleAllocator* GetTextureClientRecycler(); + protected: CompositableChild* mCompositableChild; CompositableForwarder* mForwarder; // Some layers may want to enforce some flags to all their textures // (like disallowing tiling) TextureFlags mTextureFlags; + RefPtr mTextureClientRecycler; friend class CompositableChild; }; diff --git a/gfx/layers/client/TextureClient.cpp b/gfx/layers/client/TextureClient.cpp index cb04fc3dc972..ac96d9867360 100644 --- a/gfx/layers/client/TextureClient.cpp +++ b/gfx/layers/client/TextureClient.cpp @@ -176,12 +176,57 @@ TextureClient::AsTextureClient(PTextureChild* actor) return actor ? static_cast(actor)->mTextureClient : nullptr; } +void +TextureClient::AddFlags(TextureFlags aFlags) +{ + MOZ_ASSERT(!IsSharedWithCompositor() || + ((GetFlags() & TextureFlags::RECYCLE) && !IsAddedToCompositableClient())); + mFlags |= aFlags; + if (mValid && mActor && mActor->IPCOpen()) { + mActor->SendRecycleTexture(mFlags); + } +} + +void +TextureClient::RemoveFlags(TextureFlags aFlags) +{ + MOZ_ASSERT(!IsSharedWithCompositor() || + ((GetFlags() & TextureFlags::RECYCLE) && !IsAddedToCompositableClient())); + mFlags &= ~aFlags; + if (mValid && mActor && mActor->IPCOpen()) { + mActor->SendRecycleTexture(mFlags); + } +} + +void +TextureClient::RecycleTexture(TextureFlags aFlags) +{ + MOZ_ASSERT(GetFlags() & TextureFlags::RECYCLE); + MOZ_ASSERT(!HasRecycleCallback()); + + mAddedToCompositableClient = false; + if (mFlags != aFlags) { + mFlags = aFlags; + if (mValid && mActor && mActor->IPCOpen()) { + mActor->SendRecycleTexture(mFlags); + } + } +} + void TextureClient::WaitForCompositorRecycle() { mActor->WaitForCompositorRecycle(); } +void +TextureClient::SetAddedToCompositableClient() +{ + if (!mAddedToCompositableClient) { + mAddedToCompositableClient = true; + } +} + bool TextureClient::InitIPDLActor(CompositableForwarder* aForwarder) { @@ -429,6 +474,7 @@ TextureClient::TextureClient(TextureFlags aFlags) : mFlags(aFlags) , mShared(false) , mValid(true) + , mAddedToCompositableClient(false) {} TextureClient::~TextureClient() diff --git a/gfx/layers/client/TextureClient.h b/gfx/layers/client/TextureClient.h index 290fe456897a..9932e460039a 100644 --- a/gfx/layers/client/TextureClient.h +++ b/gfx/layers/client/TextureClient.h @@ -301,17 +301,11 @@ public: return (mFlags & aFlags) == aFlags; } - void AddFlags(TextureFlags aFlags) - { - MOZ_ASSERT(!IsSharedWithCompositor()); - mFlags |= aFlags; - } + void AddFlags(TextureFlags aFlags); - void RemoveFlags(TextureFlags aFlags) - { - MOZ_ASSERT(!IsSharedWithCompositor()); - mFlags &= ~aFlags; - } + void RemoveFlags(TextureFlags aFlags); + + void RecycleTexture(TextureFlags aFlags); /** * valid only for TextureFlags::RECYCLE TextureClient. @@ -341,6 +335,17 @@ public: */ bool IsValid() const { return mValid; } + /** + * Called when TextureClient is added to CompositableClient. + */ + void SetAddedToCompositableClient(); + + /** + * If this method retuns false, TextureClient is already added to CompositableClient, + * since its creation or recycling. + */ + bool IsAddedToCompositableClient() const { return mAddedToCompositableClient; } + /** * kee the passed object alive until the IPDL actor is destroyed. This can * help avoid race conditions in some cases. @@ -461,6 +466,7 @@ protected: gl::GfxTextureWasteTracker mWasteTracker; bool mShared; bool mValid; + bool mAddedToCompositableClient; RefPtr mReadbackSink; diff --git a/gfx/layers/client/TextureClientRecycleAllocator.cpp b/gfx/layers/client/TextureClientRecycleAllocator.cpp new file mode 100644 index 000000000000..6c9f72e3d9bc --- /dev/null +++ b/gfx/layers/client/TextureClientRecycleAllocator.cpp @@ -0,0 +1,257 @@ +/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*- +* 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 +#include + +#include "gfxPlatform.h" +#include "mozilla/layers/GrallocTextureClient.h" +#include "mozilla/layers/ISurfaceAllocator.h" +#include "mozilla/Mutex.h" + +#include "TextureClientRecycleAllocator.h" + +namespace mozilla { +namespace layers { + +class TextureClientRecycleAllocatorImp : public ISurfaceAllocator +{ + ~TextureClientRecycleAllocatorImp(); + +public: + explicit TextureClientRecycleAllocatorImp(ISurfaceAllocator* aAllocator); + + // Creates and allocates a TextureClient. + TemporaryRef + CreateOrRecycleForDrawing(gfx::SurfaceFormat aFormat, + gfx::IntSize aSize, + gfx::BackendType aMoz2dBackend, + TextureFlags aTextureFlags, + TextureAllocationFlags flags); + + void Destroy(); + + void RecycleCallbackImp(TextureClient* aClient); + + static void RecycleCallback(TextureClient* aClient, void* aClosure); + + // ISurfaceAllocator + virtual LayersBackend GetCompositorBackendType() const MOZ_OVERRIDE + { + return mSurfaceAllocator->GetCompositorBackendType(); + } + + virtual bool AllocShmem(size_t aSize, + mozilla::ipc::SharedMemory::SharedMemoryType aType, + mozilla::ipc::Shmem* aShmem) MOZ_OVERRIDE + { + return mSurfaceAllocator->AllocShmem(aSize, aType, aShmem); + } + + virtual bool AllocUnsafeShmem(size_t aSize, + mozilla::ipc::SharedMemory::SharedMemoryType aType, + mozilla::ipc::Shmem* aShmem) MOZ_OVERRIDE + { + return mSurfaceAllocator->AllocUnsafeShmem(aSize, aType, aShmem); + } + + virtual void DeallocShmem(mozilla::ipc::Shmem& aShmem) MOZ_OVERRIDE + { + mSurfaceAllocator->DeallocShmem(aShmem); + } + + virtual bool IsSameProcess() const MOZ_OVERRIDE + { + return mSurfaceAllocator->IsSameProcess(); + } + +protected: + // ISurfaceAllocator + virtual bool IsOnCompositorSide() const MOZ_OVERRIDE + { + return false; + } + +private: + static const uint32_t kMaxPooledSized = 2; + + // Used to keep TextureClient's reference count stable as not to disrupt recycling. + class TextureClientHolder + { + ~TextureClientHolder() {} + public: + NS_INLINE_DECL_THREADSAFE_REFCOUNTING(TextureClientHolder) + + explicit TextureClientHolder(TextureClient* aClient) + : mTextureClient(aClient) + {} + + TextureClient* GetTextureClient() + { + return mTextureClient; + } + void ClearTextureClient() { mTextureClient = nullptr; } + protected: + RefPtr mTextureClient; + }; + + bool mDestroyed; + uint32_t mMaxPooledSize; + RefPtr mSurfaceAllocator; + std::map > mInUseClients; + + // On b2g gonk, std::queue might be a better choice. + // On ICS, fence wait happens implicitly before drawing. + // Since JB, fence wait happens explicitly when fetching a client from the pool. + // stack is good from Graphics cache usage point of view. + std::stack > mPooledClients; + Mutex mLock; +}; + +TextureClientRecycleAllocatorImp::TextureClientRecycleAllocatorImp(ISurfaceAllocator *aAllocator) + : mDestroyed(false) + , mMaxPooledSize(kMaxPooledSized) + , mSurfaceAllocator(aAllocator) + , mLock("TextureClientRecycleAllocatorImp.mLock") +{ +} + +TextureClientRecycleAllocatorImp::~TextureClientRecycleAllocatorImp() +{ + MOZ_ASSERT(mDestroyed); + MOZ_ASSERT(mPooledClients.empty()); + MOZ_ASSERT(mInUseClients.empty()); +} + + +TemporaryRef +TextureClientRecycleAllocatorImp::CreateOrRecycleForDrawing( + gfx::SurfaceFormat aFormat, + gfx::IntSize aSize, + gfx::BackendType aMoz2DBackend, + TextureFlags aTextureFlags, + TextureAllocationFlags aAllocFlags) +{ + // TextureAllocationFlags is actually used only by ContentClient. + // This class does not handle ConteClient's TextureClient allocation. + MOZ_ASSERT(aAllocFlags == TextureAllocationFlags::ALLOC_DEFAULT); + MOZ_ASSERT(!(aTextureFlags & TextureFlags::RECYCLE)); + aTextureFlags = aTextureFlags | TextureFlags::RECYCLE; // Set recycle flag + + RefPtr textureHolder; + + if (aMoz2DBackend == gfx::BackendType::NONE) { + aMoz2DBackend = gfxPlatform::GetPlatform()->GetContentBackend(); + } + + { + MutexAutoLock lock(mLock); + if (mDestroyed) { + return nullptr; + } else if (!mPooledClients.empty()) { + textureHolder = mPooledClients.top(); + mPooledClients.pop(); + // If a pooled TextureClient is not compatible, release it. + if (textureHolder->GetTextureClient()->GetFormat() != aFormat || + textureHolder->GetTextureClient()->GetSize() != aSize) + { + TextureClientReleaseTask* task = new TextureClientReleaseTask(textureHolder->GetTextureClient()); + textureHolder->ClearTextureClient(); + textureHolder = nullptr; + // Release TextureClient. + mSurfaceAllocator->GetMessageLoop()->PostTask(FROM_HERE, task); + } else { + textureHolder->GetTextureClient()->RecycleTexture(aTextureFlags); + } + } + } + + if (!textureHolder) { + // Allocate new TextureClient + RefPtr texture; + texture = TextureClient::CreateForDrawing(this, aFormat, aSize, aMoz2DBackend, + aTextureFlags, aAllocFlags); + if (!texture) { + return nullptr; + } + textureHolder = new TextureClientHolder(texture); + } + + { + MutexAutoLock lock(mLock); + MOZ_ASSERT(mInUseClients.find(textureHolder->GetTextureClient()) == mInUseClients.end()); + // Register TextureClient + mInUseClients[textureHolder->GetTextureClient()] = textureHolder; + } + textureHolder->GetTextureClient()->SetRecycleCallback(TextureClientRecycleAllocatorImp::RecycleCallback, this); + return textureHolder->GetTextureClient(); +} + +void +TextureClientRecycleAllocatorImp::Destroy() +{ + MutexAutoLock lock(mLock); + if (mDestroyed) { + return; + } + mDestroyed = true; + while (!mPooledClients.empty()) { + mPooledClients.pop(); + } +} + +void +TextureClientRecycleAllocatorImp::RecycleCallbackImp(TextureClient* aClient) +{ + RefPtr textureHolder; + aClient->ClearRecycleCallback(); + { + MutexAutoLock lock(mLock); + if (mInUseClients.find(aClient) != mInUseClients.end()) { + textureHolder = mInUseClients[aClient]; // Keep reference count of TextureClientHolder within lock. + if (!mDestroyed && mPooledClients.size() < mMaxPooledSize) { + mPooledClients.push(textureHolder); + } + mInUseClients.erase(aClient); + } + } +} + +/* static */ void +TextureClientRecycleAllocatorImp::RecycleCallback(TextureClient* aClient, void* aClosure) +{ + TextureClientRecycleAllocatorImp* recycleAllocator = static_cast(aClosure); + recycleAllocator->RecycleCallbackImp(aClient); +} + +TextureClientRecycleAllocator::TextureClientRecycleAllocator(ISurfaceAllocator *aAllocator) +{ + mAllocator = new TextureClientRecycleAllocatorImp(aAllocator); +} + +TextureClientRecycleAllocator::~TextureClientRecycleAllocator() +{ + mAllocator->Destroy(); + mAllocator = nullptr; +} + + +TemporaryRef +TextureClientRecycleAllocator::CreateOrRecycleForDrawing( + gfx::SurfaceFormat aFormat, + gfx::IntSize aSize, + gfx::BackendType aMoz2DBackend, + TextureFlags aTextureFlags, + TextureAllocationFlags aAllocFlags) +{ + return mAllocator->CreateOrRecycleForDrawing(aFormat, + aSize, + aMoz2DBackend, + aTextureFlags, + aAllocFlags); +} + +} +} diff --git a/gfx/layers/client/TextureClientRecycleAllocator.h b/gfx/layers/client/TextureClientRecycleAllocator.h new file mode 100644 index 000000000000..9436c5885d9f --- /dev/null +++ b/gfx/layers/client/TextureClientRecycleAllocator.h @@ -0,0 +1,49 @@ +/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*- +* 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 MOZILLA_GFX_TEXTURECLIENT_RECYCLE_ALLOCATOR_H +#define MOZILLA_GFX_TEXTURECLIENT_RECYCLE_ALLOCATOR_H + +#include "mozilla/gfx/Types.h" +#include "mozilla/RefPtr.h" +#include "TextureClient.h" + +namespace mozilla { +namespace layers { + +class ISurfaceAllocator; +class TextureClientRecycleAllocatorImp; + + +/** + * TextureClientRecycleAllocator provides TextureClients allocation and + * recycling capabilities. It expects allocations of same sizes and + * attributres. If a recycled TextureClient is different from + * requested one, the recycled one is dropped and new TextureClient is allocated. + */ +class TextureClientRecycleAllocator +{ + ~TextureClientRecycleAllocator(); + +public: + NS_INLINE_DECL_THREADSAFE_REFCOUNTING(TextureClientRecycleAllocator) + + explicit TextureClientRecycleAllocator(ISurfaceAllocator* aAllocator); + + // Creates and allocates a TextureClient. + TemporaryRef + CreateOrRecycleForDrawing(gfx::SurfaceFormat aFormat, + gfx::IntSize aSize, + gfx::BackendType aMoz2dBackend, + TextureFlags aTextureFlags, + TextureAllocationFlags flags = ALLOC_DEFAULT); + +private: + RefPtr mAllocator; +}; + +} +} +#endif /* MOZILLA_GFX_TEXTURECLIENT_RECYCLE_ALLOCATOR_H */ diff --git a/gfx/layers/client/TiledContentClient.cpp b/gfx/layers/client/TiledContentClient.cpp index 90fce04e66e5..6cbdfab36ef8 100644 --- a/gfx/layers/client/TiledContentClient.cpp +++ b/gfx/layers/client/TiledContentClient.cpp @@ -106,6 +106,7 @@ TiledContentClient::TiledContentClient(ClientTiledPaintedLayer* aPaintedLayer, void TiledContentClient::ClearCachedResources() { + CompositableClient::ClearCachedResources(); mTiledBuffer.DiscardBuffers(); mLowPrecisionTiledBuffer.DiscardBuffers(); } diff --git a/gfx/layers/composite/TextureHost.cpp b/gfx/layers/composite/TextureHost.cpp index c5fcf2618c53..d91cf47e0b2e 100644 --- a/gfx/layers/composite/TextureHost.cpp +++ b/gfx/layers/composite/TextureHost.cpp @@ -85,6 +85,8 @@ public: virtual bool RecvRemoveTexture() MOZ_OVERRIDE; + virtual bool RecvRecycleTexture(const TextureFlags& aTextureFlags) MOZ_OVERRIDE; + TextureHost* GetTextureHost() { return mTextureHost; } void ActorDestroy(ActorDestroyReason why) MOZ_OVERRIDE; @@ -301,6 +303,15 @@ void TextureHost::Finalize() } } +void +TextureHost::RecycleTexture(TextureFlags aFlags) +{ + MOZ_ASSERT(GetFlags() & TextureFlags::RECYCLE); + MOZ_ASSERT(aFlags & TextureFlags::RECYCLE); + MOZ_ASSERT(!HasRecycleCallback()); + mFlags = aFlags; +} + void TextureHost::PrintInfo(std::stringstream& aStream, const char* aPrefix) { @@ -793,6 +804,16 @@ TextureParent::ClearTextureHost() mTextureHost = nullptr; } +bool +TextureParent::RecvRecycleTexture(const TextureFlags& aTextureFlags) +{ + if (!mTextureHost) { + return true; + } + mTextureHost->RecycleTexture(aTextureFlags); + return true; +} + //////////////////////////////////////////////////////////////////////////////// static RefPtr diff --git a/gfx/layers/composite/TextureHost.h b/gfx/layers/composite/TextureHost.h index f0c2ec38eb9b..dfe8b2bcb6cc 100644 --- a/gfx/layers/composite/TextureHost.h +++ b/gfx/layers/composite/TextureHost.h @@ -506,6 +506,8 @@ public: virtual TextureHostOGL* AsHostOGL() { return nullptr; } protected: + void RecycleTexture(TextureFlags aFlags); + PTextureParent* mActor; TextureFlags mFlags; diff --git a/gfx/layers/ipc/PTexture.ipdl b/gfx/layers/ipc/PTexture.ipdl index 5e5f53cdd454..c654c8d159b9 100644 --- a/gfx/layers/ipc/PTexture.ipdl +++ b/gfx/layers/ipc/PTexture.ipdl @@ -11,6 +11,7 @@ include protocol PImageBridge; include "mozilla/GfxMessageUtils.h"; using struct mozilla::layers::FrameMetrics from "FrameMetrics.h"; +using mozilla::layers::TextureFlags from "mozilla/layers/CompositorTypes.h"; namespace mozilla { namespace layers { @@ -39,6 +40,8 @@ parent: * Asynchronously tell the Compositor side to remove the texture. */ async RemoveTexture(); + + async RecycleTexture(TextureFlags aTextureFlags); }; } // layers diff --git a/gfx/layers/moz.build b/gfx/layers/moz.build index c582bca44ca5..2be45a169cbb 100644 --- a/gfx/layers/moz.build +++ b/gfx/layers/moz.build @@ -125,6 +125,7 @@ EXPORTS.mozilla.layers += [ 'client/ImageClient.h', 'client/TextureClient.h', 'client/TextureClientPool.h', + 'client/TextureClientRecycleAllocator.h', 'client/TiledContentClient.h', 'composite/AsyncCompositionManager.h', 'composite/CanvasLayerComposite.h', @@ -268,6 +269,7 @@ UNIFIED_SOURCES += [ 'client/ImageClient.cpp', 'client/TextureClient.cpp', 'client/TextureClientPool.cpp', + 'client/TextureClientRecycleAllocator.cpp', 'client/TiledContentClient.cpp', 'composite/AsyncCompositionManager.cpp', 'composite/CanvasLayerComposite.cpp', From ecc049922a0b87c85188b9169687ca19acadce8c Mon Sep 17 00:00:00 2001 From: Anthony Jones Date: Thu, 13 Nov 2014 14:48:08 +1300 Subject: [PATCH 08/80] Bug 1097449 - Add locking around libav open/close; r=jya --- dom/media/fmp4/ffmpeg/FFmpegDataDecoder.cpp | 5 +++++ dom/media/fmp4/ffmpeg/FFmpegDataDecoder.h | 1 + 2 files changed, 6 insertions(+) diff --git a/dom/media/fmp4/ffmpeg/FFmpegDataDecoder.cpp b/dom/media/fmp4/ffmpeg/FFmpegDataDecoder.cpp index 89fdc3ec25e6..022302fb2629 100644 --- a/dom/media/fmp4/ffmpeg/FFmpegDataDecoder.cpp +++ b/dom/media/fmp4/ffmpeg/FFmpegDataDecoder.cpp @@ -18,6 +18,7 @@ namespace mozilla { bool FFmpegDataDecoder::sFFmpegInitDone = false; +Monitor FFmpegDataDecoder::sMonitor("FFmpegDataDecoder"); FFmpegDataDecoder::FFmpegDataDecoder(MediaTaskQueue* aTaskQueue, AVCodecID aCodecID) @@ -58,6 +59,8 @@ ChoosePixelFormat(AVCodecContext* aCodecContext, const PixelFormat* aFormats) nsresult FFmpegDataDecoder::Init() { + MonitorAutoLock mon(sMonitor); + FFMPEG_LOG("Initialising FFmpeg decoder."); if (!sFFmpegInitDone) { @@ -130,6 +133,8 @@ FFmpegDataDecoder::Flush() nsresult FFmpegDataDecoder::Shutdown() { + MonitorAutoLock mon(sMonitor); + if (sFFmpegInitDone) { avcodec_close(mCodecContext); av_freep(&mCodecContext); diff --git a/dom/media/fmp4/ffmpeg/FFmpegDataDecoder.h b/dom/media/fmp4/ffmpeg/FFmpegDataDecoder.h index 947898e072c7..5a4571d1b6d7 100644 --- a/dom/media/fmp4/ffmpeg/FFmpegDataDecoder.h +++ b/dom/media/fmp4/ffmpeg/FFmpegDataDecoder.h @@ -44,6 +44,7 @@ protected: private: static bool sFFmpegInitDone; + static Monitor sMonitor; AVCodecID mCodecID; }; From cae555594be44e7fb7b8a5cdaf355de75060d343 Mon Sep 17 00:00:00 2001 From: Ryan VanderMeulen Date: Wed, 12 Nov 2014 21:09:40 -0500 Subject: [PATCH 09/80] Backed out changeset 92295f515d2d (bug 1091777) for bustage. --- gfx/layers/ImageContainer.cpp | 32 +-- gfx/layers/ImageContainer.h | 2 +- gfx/layers/client/CompositableClient.cpp | 24 -- gfx/layers/client/CompositableClient.h | 6 +- gfx/layers/client/TextureClient.cpp | 46 ---- gfx/layers/client/TextureClient.h | 26 +- .../client/TextureClientRecycleAllocator.cpp | 257 ------------------ .../client/TextureClientRecycleAllocator.h | 49 ---- gfx/layers/client/TiledContentClient.cpp | 1 - gfx/layers/composite/TextureHost.cpp | 21 -- gfx/layers/composite/TextureHost.h | 2 - gfx/layers/ipc/PTexture.ipdl | 3 - gfx/layers/moz.build | 2 - 13 files changed, 17 insertions(+), 454 deletions(-) delete mode 100644 gfx/layers/client/TextureClientRecycleAllocator.cpp delete mode 100644 gfx/layers/client/TextureClientRecycleAllocator.h diff --git a/gfx/layers/ImageContainer.cpp b/gfx/layers/ImageContainer.cpp index f0ca6b13bc0e..75d42fd12573 100644 --- a/gfx/layers/ImageContainer.cpp +++ b/gfx/layers/ImageContainer.cpp @@ -496,33 +496,11 @@ CairoImage::GetTextureClient(CompositableClient *aClient) return nullptr; } - -// XXX windows' TextureClients do not hold ISurfaceAllocator, -// recycler does not work on windows. -#ifndef XP_WIN - -// XXX only gonk ensure when TextureClient is recycled, -// TextureHost is not used by CompositableHost. -#ifdef MOZ_WIDGET_GONK - RefPtr recycler = - aClient->GetTextureClientRecycler(); - if (recycler) { - textureClient = - recycler->CreateOrRecycleForDrawing(surface->GetFormat(), - surface->GetSize(), - gfx::BackendType::NONE, - aClient->GetTextureFlags()); - } -#endif - -#endif - if (!textureClient) { - // gfx::BackendType::NONE means default to content backend - textureClient = aClient->CreateTextureClientForDrawing(surface->GetFormat(), - surface->GetSize(), - gfx::BackendType::NONE, - TextureFlags::DEFAULT); - } + // gfx::BackendType::NONE means default to content backend + textureClient = aClient->CreateTextureClientForDrawing(surface->GetFormat(), + surface->GetSize(), + gfx::BackendType::NONE, + TextureFlags::DEFAULT); if (!textureClient) { return nullptr; } diff --git a/gfx/layers/ImageContainer.h b/gfx/layers/ImageContainer.h index 8ca6df4941fc..9d7b41668308 100644 --- a/gfx/layers/ImageContainer.h +++ b/gfx/layers/ImageContainer.h @@ -811,7 +811,7 @@ public: virtual ISharedImage* AsSharedImage() { return this; } virtual uint8_t* GetBuffer() { return nullptr; } - virtual TextureClient* GetTextureClient(CompositableClient* aClient) MOZ_OVERRIDE; + virtual TextureClient* GetTextureClient(CompositableClient* aClient); gfx::IntSize GetSize() { return mSize; } diff --git a/gfx/layers/client/CompositableClient.cpp b/gfx/layers/client/CompositableClient.cpp index 2b11c597251b..c51329e00168 100644 --- a/gfx/layers/client/CompositableClient.cpp +++ b/gfx/layers/client/CompositableClient.cpp @@ -219,7 +219,6 @@ CompositableClient::AddTextureClient(TextureClient* aClient) if(!aClient || !aClient->IsAllocated()) { return false; } - aClient->SetAddedToCompositableClient(); return aClient->InitIPDLActor(mForwarder); } @@ -234,28 +233,5 @@ CompositableClient::RemoveTexture(TextureClient* aTexture) mForwarder->RemoveTextureFromCompositable(this, aTexture); } -CompositableClient::ClearCachedResources() -{ - if (mTextureClientRecycler) { - mTextureClientRecycler = nullptr; - } -} - -TextureClientRecycleAllocator* -CompositableClient::GetTextureClientRecycler() -{ - if (mTextureClientRecycler) { - return mTextureClientRecycler; - } - - if (!mForwarder) { - return nullptr; - } - - mTextureClientRecycler = - new layers::TextureClientRecycleAllocator(mForwarder); - return mTextureClientRecycler; -} - } // namespace layers } // namespace mozilla diff --git a/gfx/layers/client/CompositableClient.h b/gfx/layers/client/CompositableClient.h index 0c51e3f726b1..0e0c5cca652b 100644 --- a/gfx/layers/client/CompositableClient.h +++ b/gfx/layers/client/CompositableClient.h @@ -16,7 +16,6 @@ #include "mozilla/layers/CompositorTypes.h" #include "mozilla/layers/LayersTypes.h" // for LayersBackend #include "mozilla/layers/TextureClient.h" // for TextureClient -#include "mozilla/layers/TextureClientRecycleAllocator.h" // for TextureClientRecycleAllocator #include "nsISupportsImpl.h" // for MOZ_COUNT_CTOR, etc namespace mozilla { @@ -195,7 +194,7 @@ public: * Clear any resources that are not immediately necessary. This may be called * in low-memory conditions. */ - virtual void ClearCachedResources(); + virtual void ClearCachedResources() {} /** * Should be called when deataching a TextureClient from a Compositable, because @@ -230,15 +229,12 @@ public: TextureFlags GetTextureFlags() const { return mTextureFlags; } - TextureClientRecycleAllocator* GetTextureClientRecycler(); - protected: CompositableChild* mCompositableChild; CompositableForwarder* mForwarder; // Some layers may want to enforce some flags to all their textures // (like disallowing tiling) TextureFlags mTextureFlags; - RefPtr mTextureClientRecycler; friend class CompositableChild; }; diff --git a/gfx/layers/client/TextureClient.cpp b/gfx/layers/client/TextureClient.cpp index ac96d9867360..cb04fc3dc972 100644 --- a/gfx/layers/client/TextureClient.cpp +++ b/gfx/layers/client/TextureClient.cpp @@ -176,57 +176,12 @@ TextureClient::AsTextureClient(PTextureChild* actor) return actor ? static_cast(actor)->mTextureClient : nullptr; } -void -TextureClient::AddFlags(TextureFlags aFlags) -{ - MOZ_ASSERT(!IsSharedWithCompositor() || - ((GetFlags() & TextureFlags::RECYCLE) && !IsAddedToCompositableClient())); - mFlags |= aFlags; - if (mValid && mActor && mActor->IPCOpen()) { - mActor->SendRecycleTexture(mFlags); - } -} - -void -TextureClient::RemoveFlags(TextureFlags aFlags) -{ - MOZ_ASSERT(!IsSharedWithCompositor() || - ((GetFlags() & TextureFlags::RECYCLE) && !IsAddedToCompositableClient())); - mFlags &= ~aFlags; - if (mValid && mActor && mActor->IPCOpen()) { - mActor->SendRecycleTexture(mFlags); - } -} - -void -TextureClient::RecycleTexture(TextureFlags aFlags) -{ - MOZ_ASSERT(GetFlags() & TextureFlags::RECYCLE); - MOZ_ASSERT(!HasRecycleCallback()); - - mAddedToCompositableClient = false; - if (mFlags != aFlags) { - mFlags = aFlags; - if (mValid && mActor && mActor->IPCOpen()) { - mActor->SendRecycleTexture(mFlags); - } - } -} - void TextureClient::WaitForCompositorRecycle() { mActor->WaitForCompositorRecycle(); } -void -TextureClient::SetAddedToCompositableClient() -{ - if (!mAddedToCompositableClient) { - mAddedToCompositableClient = true; - } -} - bool TextureClient::InitIPDLActor(CompositableForwarder* aForwarder) { @@ -474,7 +429,6 @@ TextureClient::TextureClient(TextureFlags aFlags) : mFlags(aFlags) , mShared(false) , mValid(true) - , mAddedToCompositableClient(false) {} TextureClient::~TextureClient() diff --git a/gfx/layers/client/TextureClient.h b/gfx/layers/client/TextureClient.h index 9932e460039a..290fe456897a 100644 --- a/gfx/layers/client/TextureClient.h +++ b/gfx/layers/client/TextureClient.h @@ -301,11 +301,17 @@ public: return (mFlags & aFlags) == aFlags; } - void AddFlags(TextureFlags aFlags); + void AddFlags(TextureFlags aFlags) + { + MOZ_ASSERT(!IsSharedWithCompositor()); + mFlags |= aFlags; + } - void RemoveFlags(TextureFlags aFlags); - - void RecycleTexture(TextureFlags aFlags); + void RemoveFlags(TextureFlags aFlags) + { + MOZ_ASSERT(!IsSharedWithCompositor()); + mFlags &= ~aFlags; + } /** * valid only for TextureFlags::RECYCLE TextureClient. @@ -335,17 +341,6 @@ public: */ bool IsValid() const { return mValid; } - /** - * Called when TextureClient is added to CompositableClient. - */ - void SetAddedToCompositableClient(); - - /** - * If this method retuns false, TextureClient is already added to CompositableClient, - * since its creation or recycling. - */ - bool IsAddedToCompositableClient() const { return mAddedToCompositableClient; } - /** * kee the passed object alive until the IPDL actor is destroyed. This can * help avoid race conditions in some cases. @@ -466,7 +461,6 @@ protected: gl::GfxTextureWasteTracker mWasteTracker; bool mShared; bool mValid; - bool mAddedToCompositableClient; RefPtr mReadbackSink; diff --git a/gfx/layers/client/TextureClientRecycleAllocator.cpp b/gfx/layers/client/TextureClientRecycleAllocator.cpp deleted file mode 100644 index 6c9f72e3d9bc..000000000000 --- a/gfx/layers/client/TextureClientRecycleAllocator.cpp +++ /dev/null @@ -1,257 +0,0 @@ -/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*- -* 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 -#include - -#include "gfxPlatform.h" -#include "mozilla/layers/GrallocTextureClient.h" -#include "mozilla/layers/ISurfaceAllocator.h" -#include "mozilla/Mutex.h" - -#include "TextureClientRecycleAllocator.h" - -namespace mozilla { -namespace layers { - -class TextureClientRecycleAllocatorImp : public ISurfaceAllocator -{ - ~TextureClientRecycleAllocatorImp(); - -public: - explicit TextureClientRecycleAllocatorImp(ISurfaceAllocator* aAllocator); - - // Creates and allocates a TextureClient. - TemporaryRef - CreateOrRecycleForDrawing(gfx::SurfaceFormat aFormat, - gfx::IntSize aSize, - gfx::BackendType aMoz2dBackend, - TextureFlags aTextureFlags, - TextureAllocationFlags flags); - - void Destroy(); - - void RecycleCallbackImp(TextureClient* aClient); - - static void RecycleCallback(TextureClient* aClient, void* aClosure); - - // ISurfaceAllocator - virtual LayersBackend GetCompositorBackendType() const MOZ_OVERRIDE - { - return mSurfaceAllocator->GetCompositorBackendType(); - } - - virtual bool AllocShmem(size_t aSize, - mozilla::ipc::SharedMemory::SharedMemoryType aType, - mozilla::ipc::Shmem* aShmem) MOZ_OVERRIDE - { - return mSurfaceAllocator->AllocShmem(aSize, aType, aShmem); - } - - virtual bool AllocUnsafeShmem(size_t aSize, - mozilla::ipc::SharedMemory::SharedMemoryType aType, - mozilla::ipc::Shmem* aShmem) MOZ_OVERRIDE - { - return mSurfaceAllocator->AllocUnsafeShmem(aSize, aType, aShmem); - } - - virtual void DeallocShmem(mozilla::ipc::Shmem& aShmem) MOZ_OVERRIDE - { - mSurfaceAllocator->DeallocShmem(aShmem); - } - - virtual bool IsSameProcess() const MOZ_OVERRIDE - { - return mSurfaceAllocator->IsSameProcess(); - } - -protected: - // ISurfaceAllocator - virtual bool IsOnCompositorSide() const MOZ_OVERRIDE - { - return false; - } - -private: - static const uint32_t kMaxPooledSized = 2; - - // Used to keep TextureClient's reference count stable as not to disrupt recycling. - class TextureClientHolder - { - ~TextureClientHolder() {} - public: - NS_INLINE_DECL_THREADSAFE_REFCOUNTING(TextureClientHolder) - - explicit TextureClientHolder(TextureClient* aClient) - : mTextureClient(aClient) - {} - - TextureClient* GetTextureClient() - { - return mTextureClient; - } - void ClearTextureClient() { mTextureClient = nullptr; } - protected: - RefPtr mTextureClient; - }; - - bool mDestroyed; - uint32_t mMaxPooledSize; - RefPtr mSurfaceAllocator; - std::map > mInUseClients; - - // On b2g gonk, std::queue might be a better choice. - // On ICS, fence wait happens implicitly before drawing. - // Since JB, fence wait happens explicitly when fetching a client from the pool. - // stack is good from Graphics cache usage point of view. - std::stack > mPooledClients; - Mutex mLock; -}; - -TextureClientRecycleAllocatorImp::TextureClientRecycleAllocatorImp(ISurfaceAllocator *aAllocator) - : mDestroyed(false) - , mMaxPooledSize(kMaxPooledSized) - , mSurfaceAllocator(aAllocator) - , mLock("TextureClientRecycleAllocatorImp.mLock") -{ -} - -TextureClientRecycleAllocatorImp::~TextureClientRecycleAllocatorImp() -{ - MOZ_ASSERT(mDestroyed); - MOZ_ASSERT(mPooledClients.empty()); - MOZ_ASSERT(mInUseClients.empty()); -} - - -TemporaryRef -TextureClientRecycleAllocatorImp::CreateOrRecycleForDrawing( - gfx::SurfaceFormat aFormat, - gfx::IntSize aSize, - gfx::BackendType aMoz2DBackend, - TextureFlags aTextureFlags, - TextureAllocationFlags aAllocFlags) -{ - // TextureAllocationFlags is actually used only by ContentClient. - // This class does not handle ConteClient's TextureClient allocation. - MOZ_ASSERT(aAllocFlags == TextureAllocationFlags::ALLOC_DEFAULT); - MOZ_ASSERT(!(aTextureFlags & TextureFlags::RECYCLE)); - aTextureFlags = aTextureFlags | TextureFlags::RECYCLE; // Set recycle flag - - RefPtr textureHolder; - - if (aMoz2DBackend == gfx::BackendType::NONE) { - aMoz2DBackend = gfxPlatform::GetPlatform()->GetContentBackend(); - } - - { - MutexAutoLock lock(mLock); - if (mDestroyed) { - return nullptr; - } else if (!mPooledClients.empty()) { - textureHolder = mPooledClients.top(); - mPooledClients.pop(); - // If a pooled TextureClient is not compatible, release it. - if (textureHolder->GetTextureClient()->GetFormat() != aFormat || - textureHolder->GetTextureClient()->GetSize() != aSize) - { - TextureClientReleaseTask* task = new TextureClientReleaseTask(textureHolder->GetTextureClient()); - textureHolder->ClearTextureClient(); - textureHolder = nullptr; - // Release TextureClient. - mSurfaceAllocator->GetMessageLoop()->PostTask(FROM_HERE, task); - } else { - textureHolder->GetTextureClient()->RecycleTexture(aTextureFlags); - } - } - } - - if (!textureHolder) { - // Allocate new TextureClient - RefPtr texture; - texture = TextureClient::CreateForDrawing(this, aFormat, aSize, aMoz2DBackend, - aTextureFlags, aAllocFlags); - if (!texture) { - return nullptr; - } - textureHolder = new TextureClientHolder(texture); - } - - { - MutexAutoLock lock(mLock); - MOZ_ASSERT(mInUseClients.find(textureHolder->GetTextureClient()) == mInUseClients.end()); - // Register TextureClient - mInUseClients[textureHolder->GetTextureClient()] = textureHolder; - } - textureHolder->GetTextureClient()->SetRecycleCallback(TextureClientRecycleAllocatorImp::RecycleCallback, this); - return textureHolder->GetTextureClient(); -} - -void -TextureClientRecycleAllocatorImp::Destroy() -{ - MutexAutoLock lock(mLock); - if (mDestroyed) { - return; - } - mDestroyed = true; - while (!mPooledClients.empty()) { - mPooledClients.pop(); - } -} - -void -TextureClientRecycleAllocatorImp::RecycleCallbackImp(TextureClient* aClient) -{ - RefPtr textureHolder; - aClient->ClearRecycleCallback(); - { - MutexAutoLock lock(mLock); - if (mInUseClients.find(aClient) != mInUseClients.end()) { - textureHolder = mInUseClients[aClient]; // Keep reference count of TextureClientHolder within lock. - if (!mDestroyed && mPooledClients.size() < mMaxPooledSize) { - mPooledClients.push(textureHolder); - } - mInUseClients.erase(aClient); - } - } -} - -/* static */ void -TextureClientRecycleAllocatorImp::RecycleCallback(TextureClient* aClient, void* aClosure) -{ - TextureClientRecycleAllocatorImp* recycleAllocator = static_cast(aClosure); - recycleAllocator->RecycleCallbackImp(aClient); -} - -TextureClientRecycleAllocator::TextureClientRecycleAllocator(ISurfaceAllocator *aAllocator) -{ - mAllocator = new TextureClientRecycleAllocatorImp(aAllocator); -} - -TextureClientRecycleAllocator::~TextureClientRecycleAllocator() -{ - mAllocator->Destroy(); - mAllocator = nullptr; -} - - -TemporaryRef -TextureClientRecycleAllocator::CreateOrRecycleForDrawing( - gfx::SurfaceFormat aFormat, - gfx::IntSize aSize, - gfx::BackendType aMoz2DBackend, - TextureFlags aTextureFlags, - TextureAllocationFlags aAllocFlags) -{ - return mAllocator->CreateOrRecycleForDrawing(aFormat, - aSize, - aMoz2DBackend, - aTextureFlags, - aAllocFlags); -} - -} -} diff --git a/gfx/layers/client/TextureClientRecycleAllocator.h b/gfx/layers/client/TextureClientRecycleAllocator.h deleted file mode 100644 index 9436c5885d9f..000000000000 --- a/gfx/layers/client/TextureClientRecycleAllocator.h +++ /dev/null @@ -1,49 +0,0 @@ -/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*- -* 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 MOZILLA_GFX_TEXTURECLIENT_RECYCLE_ALLOCATOR_H -#define MOZILLA_GFX_TEXTURECLIENT_RECYCLE_ALLOCATOR_H - -#include "mozilla/gfx/Types.h" -#include "mozilla/RefPtr.h" -#include "TextureClient.h" - -namespace mozilla { -namespace layers { - -class ISurfaceAllocator; -class TextureClientRecycleAllocatorImp; - - -/** - * TextureClientRecycleAllocator provides TextureClients allocation and - * recycling capabilities. It expects allocations of same sizes and - * attributres. If a recycled TextureClient is different from - * requested one, the recycled one is dropped and new TextureClient is allocated. - */ -class TextureClientRecycleAllocator -{ - ~TextureClientRecycleAllocator(); - -public: - NS_INLINE_DECL_THREADSAFE_REFCOUNTING(TextureClientRecycleAllocator) - - explicit TextureClientRecycleAllocator(ISurfaceAllocator* aAllocator); - - // Creates and allocates a TextureClient. - TemporaryRef - CreateOrRecycleForDrawing(gfx::SurfaceFormat aFormat, - gfx::IntSize aSize, - gfx::BackendType aMoz2dBackend, - TextureFlags aTextureFlags, - TextureAllocationFlags flags = ALLOC_DEFAULT); - -private: - RefPtr mAllocator; -}; - -} -} -#endif /* MOZILLA_GFX_TEXTURECLIENT_RECYCLE_ALLOCATOR_H */ diff --git a/gfx/layers/client/TiledContentClient.cpp b/gfx/layers/client/TiledContentClient.cpp index 6cbdfab36ef8..90fce04e66e5 100644 --- a/gfx/layers/client/TiledContentClient.cpp +++ b/gfx/layers/client/TiledContentClient.cpp @@ -106,7 +106,6 @@ TiledContentClient::TiledContentClient(ClientTiledPaintedLayer* aPaintedLayer, void TiledContentClient::ClearCachedResources() { - CompositableClient::ClearCachedResources(); mTiledBuffer.DiscardBuffers(); mLowPrecisionTiledBuffer.DiscardBuffers(); } diff --git a/gfx/layers/composite/TextureHost.cpp b/gfx/layers/composite/TextureHost.cpp index d91cf47e0b2e..c5fcf2618c53 100644 --- a/gfx/layers/composite/TextureHost.cpp +++ b/gfx/layers/composite/TextureHost.cpp @@ -85,8 +85,6 @@ public: virtual bool RecvRemoveTexture() MOZ_OVERRIDE; - virtual bool RecvRecycleTexture(const TextureFlags& aTextureFlags) MOZ_OVERRIDE; - TextureHost* GetTextureHost() { return mTextureHost; } void ActorDestroy(ActorDestroyReason why) MOZ_OVERRIDE; @@ -303,15 +301,6 @@ void TextureHost::Finalize() } } -void -TextureHost::RecycleTexture(TextureFlags aFlags) -{ - MOZ_ASSERT(GetFlags() & TextureFlags::RECYCLE); - MOZ_ASSERT(aFlags & TextureFlags::RECYCLE); - MOZ_ASSERT(!HasRecycleCallback()); - mFlags = aFlags; -} - void TextureHost::PrintInfo(std::stringstream& aStream, const char* aPrefix) { @@ -804,16 +793,6 @@ TextureParent::ClearTextureHost() mTextureHost = nullptr; } -bool -TextureParent::RecvRecycleTexture(const TextureFlags& aTextureFlags) -{ - if (!mTextureHost) { - return true; - } - mTextureHost->RecycleTexture(aTextureFlags); - return true; -} - //////////////////////////////////////////////////////////////////////////////// static RefPtr diff --git a/gfx/layers/composite/TextureHost.h b/gfx/layers/composite/TextureHost.h index dfe8b2bcb6cc..f0c2ec38eb9b 100644 --- a/gfx/layers/composite/TextureHost.h +++ b/gfx/layers/composite/TextureHost.h @@ -506,8 +506,6 @@ public: virtual TextureHostOGL* AsHostOGL() { return nullptr; } protected: - void RecycleTexture(TextureFlags aFlags); - PTextureParent* mActor; TextureFlags mFlags; diff --git a/gfx/layers/ipc/PTexture.ipdl b/gfx/layers/ipc/PTexture.ipdl index c654c8d159b9..5e5f53cdd454 100644 --- a/gfx/layers/ipc/PTexture.ipdl +++ b/gfx/layers/ipc/PTexture.ipdl @@ -11,7 +11,6 @@ include protocol PImageBridge; include "mozilla/GfxMessageUtils.h"; using struct mozilla::layers::FrameMetrics from "FrameMetrics.h"; -using mozilla::layers::TextureFlags from "mozilla/layers/CompositorTypes.h"; namespace mozilla { namespace layers { @@ -40,8 +39,6 @@ parent: * Asynchronously tell the Compositor side to remove the texture. */ async RemoveTexture(); - - async RecycleTexture(TextureFlags aTextureFlags); }; } // layers diff --git a/gfx/layers/moz.build b/gfx/layers/moz.build index 2be45a169cbb..c582bca44ca5 100644 --- a/gfx/layers/moz.build +++ b/gfx/layers/moz.build @@ -125,7 +125,6 @@ EXPORTS.mozilla.layers += [ 'client/ImageClient.h', 'client/TextureClient.h', 'client/TextureClientPool.h', - 'client/TextureClientRecycleAllocator.h', 'client/TiledContentClient.h', 'composite/AsyncCompositionManager.h', 'composite/CanvasLayerComposite.h', @@ -269,7 +268,6 @@ UNIFIED_SOURCES += [ 'client/ImageClient.cpp', 'client/TextureClient.cpp', 'client/TextureClientPool.cpp', - 'client/TextureClientRecycleAllocator.cpp', 'client/TiledContentClient.cpp', 'composite/AsyncCompositionManager.cpp', 'composite/CanvasLayerComposite.cpp', From 9f9a5ddb26448a1ceacd03a90956f4bc37ad3a21 Mon Sep 17 00:00:00 2001 From: Chris Double Date: Thu, 13 Nov 2014 15:38:56 +1300 Subject: [PATCH 10/80] Back out ea9e204bc97a for test failure on Android. --- dom/media/mediasource/MediaSource.cpp | 8 +++- dom/media/mediasource/SourceBuffer.cpp | 11 +---- dom/media/mediasource/SourceBuffer.h | 3 -- dom/media/mediasource/SourceBufferList.cpp | 9 ++-- dom/media/mediasource/SourceBufferList.h | 5 +- dom/media/mediasource/test/mochitest.ini | 1 - .../mediasource/test/test_BufferedSeek.html | 10 +--- .../mediasource/test/test_EndOfStream.html | 47 ------------------- .../mediasource/test/test_FrameSelection.html | 10 ++-- .../mediasource/test/test_MediaSource.html | 14 ++---- .../test/test_SeekableAfterEndOfStream.html | 10 +--- .../test_SeekableAfterEndOfStreamSplit.html | 2 +- .../mediasource/test/test_SplitAppend.html | 10 ++-- .../test/test_SplitAppendDelay.html | 10 ++-- 14 files changed, 35 insertions(+), 115 deletions(-) delete mode 100644 dom/media/mediasource/test/test_EndOfStream.html diff --git a/dom/media/mediasource/MediaSource.cpp b/dom/media/mediasource/MediaSource.cpp index a41fe9eb2542..6a45d1118cbe 100644 --- a/dom/media/mediasource/MediaSource.cpp +++ b/dom/media/mediasource/MediaSource.cpp @@ -418,10 +418,14 @@ void MediaSource::DurationChange(double aOldDuration, double aNewDuration) { MOZ_ASSERT(NS_IsMainThread()); - MSE_DEBUG("MediaSource(%p)::DurationChange(aOldDuration=%f, aNewDuration=%f)", this, aOldDuration, aNewDuration); + MSE_DEBUG("MediaSource(%p)::DurationChange(aNewDuration=%f)", this, aNewDuration); if (aNewDuration < aOldDuration) { - mSourceBuffers->RangeRemoval(aNewDuration, aOldDuration); + ErrorResult rv; + mSourceBuffers->Remove(aNewDuration, aOldDuration, rv); + if (rv.Failed()) { + return; + } } // TODO: If partial audio frames/text cues exist, clamp duration based on mSourceBuffers. } diff --git a/dom/media/mediasource/SourceBuffer.cpp b/dom/media/mediasource/SourceBuffer.cpp index 838e02c56ba9..320e2a6559e1 100644 --- a/dom/media/mediasource/SourceBuffer.cpp +++ b/dom/media/mediasource/SourceBuffer.cpp @@ -188,19 +188,10 @@ SourceBuffer::Remove(double aStart, double aEnd, ErrorResult& aRv) aRv.Throw(NS_ERROR_DOM_INVALID_ACCESS_ERR); return; } - if (mUpdating) { + if (mUpdating || mMediaSource->ReadyState() != MediaSourceReadyState::Open) { aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR); return; } - if (mMediaSource->ReadyState() == MediaSourceReadyState::Ended) { - mMediaSource->SetReadyState(MediaSourceReadyState::Open); - } - RangeRemoval(aStart, aEnd); -} - -void -SourceBuffer::RangeRemoval(double aStart, double aEnd) -{ StartUpdating(); /// TODO: Run coded frame removal algorithm. diff --git a/dom/media/mediasource/SourceBuffer.h b/dom/media/mediasource/SourceBuffer.h index 88a6f892a1db..5be60b50a219 100644 --- a/dom/media/mediasource/SourceBuffer.h +++ b/dom/media/mediasource/SourceBuffer.h @@ -108,9 +108,6 @@ public: double GetBufferedStart(); double GetBufferedEnd(); - // Runs the range removal algorithm as defined by the MSE spec. - void RangeRemoval(double aStart, double aEnd); - #if defined(DEBUG) void Dump(const char* aPath); #endif diff --git a/dom/media/mediasource/SourceBufferList.cpp b/dom/media/mediasource/SourceBufferList.cpp index 041fbb80ed96..d833bc9ddbc9 100644 --- a/dom/media/mediasource/SourceBufferList.cpp +++ b/dom/media/mediasource/SourceBufferList.cpp @@ -108,12 +108,15 @@ SourceBufferList::AnyUpdating() } void -SourceBufferList::RangeRemoval(double aStart, double aEnd) +SourceBufferList::Remove(double aStart, double aEnd, ErrorResult& aRv) { MOZ_ASSERT(NS_IsMainThread()); - MSE_DEBUG("SourceBufferList(%p)::RangeRemoval(aStart=%f, aEnd=%f", this, aStart, aEnd); + MSE_DEBUG("SourceBufferList(%p)::Remove(aStart=%f, aEnd=%f", this, aStart, aEnd); for (uint32_t i = 0; i < mSourceBuffers.Length(); ++i) { - mSourceBuffers[i]->RangeRemoval(aStart, aEnd); + mSourceBuffers[i]->Remove(aStart, aEnd, aRv); + if (aRv.Failed()) { + return; + } } } diff --git a/dom/media/mediasource/SourceBufferList.h b/dom/media/mediasource/SourceBufferList.h index de02b914a435..ca5087f2ea22 100644 --- a/dom/media/mediasource/SourceBufferList.h +++ b/dom/media/mediasource/SourceBufferList.h @@ -66,8 +66,9 @@ public: // Returns true if updating is true on any SourceBuffers in the list. bool AnyUpdating(); - // Runs the range removal steps from the MSE specification on each SourceBuffer. - void RangeRemoval(double aStart, double aEnd); + // Calls Remove(aStart, aEnd) on each SourceBuffer in the list. Aborts on + // first error, with result returned in aRv. + void Remove(double aStart, double aEnd, ErrorResult& aRv); // Mark all SourceBuffers input buffers as ended. void Ended(); diff --git a/dom/media/mediasource/test/mochitest.ini b/dom/media/mediasource/test/mochitest.ini index 2bb16b2fd8bc..9d527391816b 100644 --- a/dom/media/mediasource/test/mochitest.ini +++ b/dom/media/mediasource/test/mochitest.ini @@ -9,7 +9,6 @@ support-files = [test_MediaSource_disabled.html] [test_BufferedSeek.html] [test_BufferingWait.html] -[test_EndOfStream.html] [test_FrameSelection.html] [test_HaveMetadataUnbufferedSeek.html] [test_LoadedMetadataFired.html] diff --git a/dom/media/mediasource/test/test_BufferedSeek.html b/dom/media/mediasource/test/test_BufferedSeek.html index 949fee773b7d..b800a573576f 100644 --- a/dom/media/mediasource/test/test_BufferedSeek.html +++ b/dom/media/mediasource/test/test_BufferedSeek.html @@ -12,8 +12,6 @@ SimpleTest.waitForExplicitFinish(); -var updateCount = 0; - runWithMSE(function (ms, v) { ms.addEventListener("sourceopen", function () { var sb = ms.addSourceBuffer("video/webm"); @@ -21,13 +19,7 @@ runWithMSE(function (ms, v) { fetchWithXHR("seek.webm", function (arrayBuffer) { sb.appendBuffer(new Uint8Array(arrayBuffer)); sb.addEventListener("updateend", function () { - updateCount++; - /* Ensure that we endOfStream on the first update event only as endOfStream can - raise more if the duration of the last buffered range and the intial duration - differ. See bug 1065207 */ - if (updateCount == 1) { - ms.endOfStream(); - }; + ms.endOfStream() }); }); diff --git a/dom/media/mediasource/test/test_EndOfStream.html b/dom/media/mediasource/test/test_EndOfStream.html deleted file mode 100644 index 0ab76701dfdf..000000000000 --- a/dom/media/mediasource/test/test_EndOfStream.html +++ /dev/null @@ -1,47 +0,0 @@ - - - - MSE: endOfStream call after an appendBuffer - - - - - -
-
-
- - diff --git a/dom/media/mediasource/test/test_FrameSelection.html b/dom/media/mediasource/test/test_FrameSelection.html index bb2634c706a1..d75d8f7ddedd 100644 --- a/dom/media/mediasource/test/test_FrameSelection.html +++ b/dom/media/mediasource/test/test_FrameSelection.html @@ -12,8 +12,6 @@ SimpleTest.waitForExplicitFinish(); -var updateCount = 0; - runWithMSE(function (ms, v) { ms.addEventListener("sourceopen", function () { var sb = ms.addSourceBuffer("video/webm"); @@ -36,13 +34,13 @@ runWithMSE(function (ms, v) { fetchWithXHR("seek_lowres.webm", function (arrayBuffer) { // Append initialization segment. sb.appendBuffer(new Uint8Array(arrayBuffer, 0, 438)); + var first = true; sb.addEventListener("updateend", function () { - updateCount++; - if (updateCount == 1) { + if (first) { // Append media segment covering range [2, 4]. sb.appendBuffer(new Uint8Array(arrayBuffer, 51003)); - } - else if (updateCount == 2) { + first = false; + } else { ms.endOfStream(); target = targets.shift(); v.currentTime = target.currentTime; diff --git a/dom/media/mediasource/test/test_MediaSource.html b/dom/media/mediasource/test/test_MediaSource.html index 53c03cefa130..131d64b1c485 100644 --- a/dom/media/mediasource/test/test_MediaSource.html +++ b/dom/media/mediasource/test/test_MediaSource.html @@ -57,12 +57,7 @@ runWithMSE(function () { sb.addEventListener("update", function () { is(sb.updating, false, "SourceBuffer.updating is expected value in update event"); updateCount++; - /* Ensure that we endOfStream on the first update event only as endOfStream can - raise more if the duration of the last buffered range and the intial duration - differ. See bug 1065207 */ - if (updateCount == 1) { - ms.endOfStream(); - } + ms.endOfStream(); }); sb.addEventListener("updatestart", function () { @@ -89,10 +84,9 @@ runWithMSE(function () { // XXX: Duration should be exactly 4.0, see bug 1065207. ok(Math.abs(v.duration - 4) <= 0.002, "Video has correct duration"); ok(Math.abs(v.currentTime - 4) <= 0.002, "Video has played to end"); - // XXX: 2 update events can be received dueto duration differences, see bug 1065207. - ok(updateCount == 1 || updateCount == 2, "update event received"); - ok(updateendCount == 1 || updateendCount == 2, "updateend event received"); - ok(updatestartCount == 1 || updatestartCount == 2, "updatestart event received"); + is(updateCount, 1, "update event received"); + is(updateendCount, 1, "updateend event received"); + is(updatestartCount, 1, "updatestart event received"); is(loadedmetadataCount, 1, "loadedmetadata event received"); v.parentNode.removeChild(v); SimpleTest.finish(); diff --git a/dom/media/mediasource/test/test_SeekableAfterEndOfStream.html b/dom/media/mediasource/test/test_SeekableAfterEndOfStream.html index 850434429a24..7ffe68686685 100644 --- a/dom/media/mediasource/test/test_SeekableAfterEndOfStream.html +++ b/dom/media/mediasource/test/test_SeekableAfterEndOfStream.html @@ -12,8 +12,6 @@ SimpleTest.waitForExplicitFinish(); -var updateCount = 0; - runWithMSE(function (ms, v) { ms.addEventListener("sourceopen", function () { var sb = ms.addSourceBuffer("video/webm"); @@ -21,13 +19,7 @@ runWithMSE(function (ms, v) { fetchWithXHR("seek.webm", function (arrayBuffer) { sb.appendBuffer(new Uint8Array(arrayBuffer)); sb.addEventListener("updateend", function () { - updateCount++; - /* Ensure that we endOfStream on the first update event only as endOfStream can - raise more if the duration of the last buffered range and the intial duration - differ. See bug 1065207 */ - if (updateCount == 1) { - ms.endOfStream(); - }; + ms.endOfStream() }); }); diff --git a/dom/media/mediasource/test/test_SeekableAfterEndOfStreamSplit.html b/dom/media/mediasource/test/test_SeekableAfterEndOfStreamSplit.html index 771f9b159a60..5f75f11ffec2 100644 --- a/dom/media/mediasource/test/test_SeekableAfterEndOfStreamSplit.html +++ b/dom/media/mediasource/test/test_SeekableAfterEndOfStreamSplit.html @@ -24,7 +24,7 @@ runWithMSE(function (ms, v) { if (updateCount == 1) { sb.appendBuffer(new Uint8Array(arrayBuffer, 25223)); } - else if (updateCount == 2) { + else { ms.endOfStream(); } }); diff --git a/dom/media/mediasource/test/test_SplitAppend.html b/dom/media/mediasource/test/test_SplitAppend.html index e87bd00edca5..f743032080d7 100644 --- a/dom/media/mediasource/test/test_SplitAppend.html +++ b/dom/media/mediasource/test/test_SplitAppend.html @@ -12,20 +12,18 @@ SimpleTest.waitForExplicitFinish(); -var updateCount = 0; - runWithMSE(function (ms, v) { ms.addEventListener("sourceopen", function () { var sb = ms.addSourceBuffer("video/webm"); fetchWithXHR("seek.webm", function (arrayBuffer) { sb.appendBuffer(new Uint8Array(arrayBuffer, 0, 318)); + var first = true; sb.addEventListener("updateend", function () { - updateCount++; - if (updateCount == 1) { + if (first) { sb.appendBuffer(new Uint8Array(arrayBuffer, 318)); - } - else if (updateCount == 2) { + first = false; + } else { ms.endOfStream(); } }); diff --git a/dom/media/mediasource/test/test_SplitAppendDelay.html b/dom/media/mediasource/test/test_SplitAppendDelay.html index f4604b3d0c1c..10dde8b8156e 100644 --- a/dom/media/mediasource/test/test_SplitAppendDelay.html +++ b/dom/media/mediasource/test/test_SplitAppendDelay.html @@ -12,22 +12,20 @@ SimpleTest.waitForExplicitFinish(); -var updateCount = 0; - runWithMSE(function (ms, v) { ms.addEventListener("sourceopen", function () { var sb = ms.addSourceBuffer("video/webm"); fetchWithXHR("seek.webm", function (arrayBuffer) { sb.appendBuffer(new Uint8Array(arrayBuffer, 0, 318)); + var first = true; sb.addEventListener("updateend", function () { - updateCount++; - if (updateCount == 1) { + if (first) { window.setTimeout(function () { sb.appendBuffer(new Uint8Array(arrayBuffer, 318)); + first = false; }, 1000); - } - else if (updateCount == 2) { + } else { ms.endOfStream(); } }); From a2c8a9704a0452caab597d34b318ca9953a01d40 Mon Sep 17 00:00:00 2001 From: Chris Double Date: Thu, 13 Nov 2014 15:39:22 +1300 Subject: [PATCH 11/80] Back out 462fde31c880 for test failure on Android --- dom/media/test/eme.js | 9 --------- 1 file changed, 9 deletions(-) diff --git a/dom/media/test/eme.js b/dom/media/test/eme.js index d46a01c00629..3d3a2c3af85f 100644 --- a/dom/media/test/eme.js +++ b/dom/media/test/eme.js @@ -121,15 +121,6 @@ function PlayFragmented(test, elem, token) var curFragment = 0; function addNextFragment() { - /* We can get another updateevent as a result of calling ms.endOfStream() if - the highest end time of our source buffers is different from that of the - media source duration. Due to bug 1065207 this can happen because of - inaccuracies in the frame duration calculations. Check if we are already - "ended" and ignore the update event */ - if (ms.readyState == "ended") { - return; - } - if (curFragment >= test.fragments.length) { Log(token, "addNextFragment() end of stream"); ms.endOfStream(); From 56a5b5235f315b1b3b27f391e521ca926915d2bc Mon Sep 17 00:00:00 2001 From: Chris Double Date: Thu, 13 Nov 2014 15:40:10 +1300 Subject: [PATCH 12/80] Backout f53ad1a63b58 for test failure on Android --- .../web-platform/meta/media-source/mediasource-remove.html.ini | 3 +++ 1 file changed, 3 insertions(+) diff --git a/testing/web-platform/meta/media-source/mediasource-remove.html.ini b/testing/web-platform/meta/media-source/mediasource-remove.html.ini index ff9097294991..e1dfbe1f4562 100644 --- a/testing/web-platform/meta/media-source/mediasource-remove.html.ini +++ b/testing/web-platform/meta/media-source/mediasource-remove.html.ini @@ -1,6 +1,9 @@ [mediasource-remove.html] type: testharness expected: TIMEOUT + [Test remove transitioning readyState from \'ended\' to \'open\'.] + expected: FAIL + [Test removing all appended data.] expected: FAIL From 6d00923374da30e257a805670a03f953d9ad84af Mon Sep 17 00:00:00 2001 From: Ryan VanderMeulen Date: Wed, 12 Nov 2014 22:03:25 -0500 Subject: [PATCH 13/80] Backed out changeset f8ff4c7a978a (bug 1097449) for leaks on a CLOSED TREE. --- dom/media/fmp4/ffmpeg/FFmpegDataDecoder.cpp | 5 ----- dom/media/fmp4/ffmpeg/FFmpegDataDecoder.h | 1 - 2 files changed, 6 deletions(-) diff --git a/dom/media/fmp4/ffmpeg/FFmpegDataDecoder.cpp b/dom/media/fmp4/ffmpeg/FFmpegDataDecoder.cpp index 022302fb2629..89fdc3ec25e6 100644 --- a/dom/media/fmp4/ffmpeg/FFmpegDataDecoder.cpp +++ b/dom/media/fmp4/ffmpeg/FFmpegDataDecoder.cpp @@ -18,7 +18,6 @@ namespace mozilla { bool FFmpegDataDecoder::sFFmpegInitDone = false; -Monitor FFmpegDataDecoder::sMonitor("FFmpegDataDecoder"); FFmpegDataDecoder::FFmpegDataDecoder(MediaTaskQueue* aTaskQueue, AVCodecID aCodecID) @@ -59,8 +58,6 @@ ChoosePixelFormat(AVCodecContext* aCodecContext, const PixelFormat* aFormats) nsresult FFmpegDataDecoder::Init() { - MonitorAutoLock mon(sMonitor); - FFMPEG_LOG("Initialising FFmpeg decoder."); if (!sFFmpegInitDone) { @@ -133,8 +130,6 @@ FFmpegDataDecoder::Flush() nsresult FFmpegDataDecoder::Shutdown() { - MonitorAutoLock mon(sMonitor); - if (sFFmpegInitDone) { avcodec_close(mCodecContext); av_freep(&mCodecContext); diff --git a/dom/media/fmp4/ffmpeg/FFmpegDataDecoder.h b/dom/media/fmp4/ffmpeg/FFmpegDataDecoder.h index 5a4571d1b6d7..947898e072c7 100644 --- a/dom/media/fmp4/ffmpeg/FFmpegDataDecoder.h +++ b/dom/media/fmp4/ffmpeg/FFmpegDataDecoder.h @@ -44,7 +44,6 @@ protected: private: static bool sFFmpegInitDone; - static Monitor sMonitor; AVCodecID mCodecID; }; From ac86a65eb9e6a7decdbe0e23068f7f1df7e873e5 Mon Sep 17 00:00:00 2001 From: Randell Jesup Date: Wed, 12 Nov 2014 22:59:53 -0500 Subject: [PATCH 14/80] Bug 1080312: update iteration code from upstream r=jesup --- netwerk/sctp/src/moz.build | 1 - netwerk/sctp/src/netinet/sctp_callout.c | 85 ++++++++++++--- netwerk/sctp/src/netinet/sctp_callout.h | 6 +- netwerk/sctp/src/netinet/sctp_usrreq.c | 3 + netwerk/sctp/src/user_sctp_timer_iterate.c | 119 --------------------- 5 files changed, 81 insertions(+), 133 deletions(-) delete mode 100755 netwerk/sctp/src/user_sctp_timer_iterate.c diff --git a/netwerk/sctp/src/moz.build b/netwerk/sctp/src/moz.build index de7343356202..fcd8d8fda75b 100644 --- a/netwerk/sctp/src/moz.build +++ b/netwerk/sctp/src/moz.build @@ -31,7 +31,6 @@ SOURCES += [ 'user_environment.c', 'user_mbuf.c', 'user_recv_thread.c', - 'user_sctp_timer_iterate.c', 'user_socket.c', ] diff --git a/netwerk/sctp/src/netinet/sctp_callout.c b/netwerk/sctp/src/netinet/sctp_callout.c index 67b756699a37..e8ac77f59f65 100755 --- a/netwerk/sctp/src/netinet/sctp_callout.c +++ b/netwerk/sctp/src/netinet/sctp_callout.c @@ -30,9 +30,27 @@ * THE POSSIBILITY OF SUCH DAMAGE. */ +#if defined(__Userspace__) +#include +#if !defined (__Userspace_os_Windows) +#include +#include +#include +#endif +#if defined(__Userspace_os_NaCl) +#include +#endif +#include +#include +#include +#include +#include +#include +#else #include #include #include +#endif /* * Callout/Timer routines for OS that doesn't have them @@ -117,24 +135,16 @@ sctp_os_timer_stop(sctp_os_timer_t *c) return (1); } -#if defined(__APPLE__) -/* - * For __APPLE__, use a single main timer at a faster resolution than - * fastim. The timer just calls this existing callout infrastructure. - */ -#endif -void -sctp_timeout(void *arg SCTP_UNUSED) +static void +sctp_handle_tick(int delta) { sctp_os_timer_t *c; void (*c_func)(void *); void *c_arg; SCTP_TIMERQ_LOCK(); -#if defined(__APPLE__) /* update our tick count */ - ticks += SCTP_BASE_VAR(sctp_main_timer_ticks); -#endif + ticks += delta; c = TAILQ_FIRST(&SCTP_BASE_INFO(callqueue)); while (c) { if (c->c_time <= ticks) { @@ -155,9 +165,60 @@ sctp_timeout(void *arg SCTP_UNUSED) } sctp_os_timer_next = NULL; SCTP_TIMERQ_UNLOCK(); +} #if defined(__APPLE__) - /* restart the main timer */ +void +sctp_timeout(void *arg SCTP_UNUSED) +{ + sctp_handle_tick(SCTP_BASE_VAR(sctp_main_timer_ticks)); sctp_start_main_timer(); +} +#endif + +#if defined(__Userspace__) +#define TIMEOUT_INTERVAL 10 + +void * +user_sctp_timer_iterate(void *arg) +{ + for (;;) { +#if defined (__Userspace_os_Windows) + Sleep(TIMEOUT_INTERVAL); +#else + struct timeval timeout; + + timeout.tv_sec = 0; + timeout.tv_usec = 1000 * TIMEOUT_INTERVAL; + select(0, NULL, NULL, NULL, &timeout); +#endif + if (SCTP_BASE_VAR(timer_thread_should_exit)) { + break; + } + sctp_handle_tick(MSEC_TO_TICKS(TIMEOUT_INTERVAL)); + } + return (NULL); +} + +void +sctp_start_timer(void) +{ + /* + * No need to do SCTP_TIMERQ_LOCK_INIT(); + * here, it is being done in sctp_pcb_init() + */ +#if defined (__Userspace_os_Windows) + if ((SCTP_BASE_VAR(timer_thread) = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)user_sctp_timer_iterate, NULL, 0, NULL)) == NULL) { + SCTP_PRINTF("ERROR; Creating ithread failed\n"); + } +#else + int rc; + + rc = pthread_create(&SCTP_BASE_VAR(timer_thread), NULL, user_sctp_timer_iterate, NULL); + if (rc) { + SCTP_PRINTF("ERROR; return code from pthread_create() is %d\n", rc); + } #endif } + +#endif diff --git a/netwerk/sctp/src/netinet/sctp_callout.h b/netwerk/sctp/src/netinet/sctp_callout.h index 278294586b67..c53c5a4fc74f 100755 --- a/netwerk/sctp/src/netinet/sctp_callout.h +++ b/netwerk/sctp/src/netinet/sctp_callout.h @@ -64,7 +64,6 @@ __FBSDID("$FreeBSD$"); #endif extern int ticks; -extern void sctp_start_timer(); #endif TAILQ_HEAD(calloutlist, sctp_callout); @@ -94,6 +93,11 @@ int sctp_os_timer_stop(sctp_os_timer_t *); #define SCTP_OS_TIMER_ACTIVE(tmr) ((tmr)->c_flags & SCTP_CALLOUT_ACTIVE) #define SCTP_OS_TIMER_DEACTIVATE(tmr) ((tmr)->c_flags &= ~SCTP_CALLOUT_ACTIVE) +#if defined(__Userspace__) +void sctp_start_timer(void); +#endif +#if defined(__APPLE__) void sctp_timeout(void *); +#endif #endif diff --git a/netwerk/sctp/src/netinet/sctp_usrreq.c b/netwerk/sctp/src/netinet/sctp_usrreq.c index d4115ad79a91..c17ea0414c72 100755 --- a/netwerk/sctp/src/netinet/sctp_usrreq.c +++ b/netwerk/sctp/src/netinet/sctp_usrreq.c @@ -56,6 +56,9 @@ __FBSDID("$FreeBSD: head/sys/netinet/sctp_usrreq.c 259943 2013-12-27 13:07:00Z t #include #include #include +#if defined(__Userspace__) +#include +#endif #if !defined(__Userspace_os_Windows) #include #endif diff --git a/netwerk/sctp/src/user_sctp_timer_iterate.c b/netwerk/sctp/src/user_sctp_timer_iterate.c deleted file mode 100755 index 0a9dbce6705c..000000000000 --- a/netwerk/sctp/src/user_sctp_timer_iterate.c +++ /dev/null @@ -1,119 +0,0 @@ -/*- - * Copyright (c) 2012 Michael Tuexen - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - */ - -#include -#if !defined (__Userspace_os_Windows) -#include -#include -#include -#endif -#include -#include -#include -#include -#include -#include -#include "netinet/sctp_callout.h" - -/* This is the polling time of callqueue in milliseconds - * 10ms seems to work well. 1ms was giving erratic behavior - */ -#define TIMEOUT_INTERVAL 10 - -extern int ticks; - -void * -user_sctp_timer_iterate(void *arg) -{ - sctp_os_timer_t *c; - void (*c_func)(void *); - void *c_arg; - sctp_os_timer_t *sctp_os_timer_next; - /* - * The MSEC_TO_TICKS conversion depends on hz. The to_ticks in - * sctp_os_timer_start also depends on hz. E.g. if hz=1000 then - * for multiple INIT the to_ticks is 2000, 4000, 8000, 16000, 32000, 60000 - * and further to_ticks level off at 60000 i.e. 60 seconds. - * If hz=100 then for multiple INIT the to_ticks are 200, 400, 800 and so-on. - */ - for (;;) { -#if defined (__Userspace_os_Windows) - Sleep(TIMEOUT_INTERVAL); -#else - struct timeval timeout; - - timeout.tv_sec = 0; - timeout.tv_usec = 1000 * TIMEOUT_INTERVAL; - select(0, NULL, NULL, NULL, &timeout); -#endif - if (SCTP_BASE_VAR(timer_thread_should_exit)) { - break; - } - SCTP_TIMERQ_LOCK(); - /* update our tick count */ - ticks += MSEC_TO_TICKS(TIMEOUT_INTERVAL); - c = TAILQ_FIRST(&SCTP_BASE_INFO(callqueue)); - while (c) { - if (c->c_time <= ticks) { - sctp_os_timer_next = TAILQ_NEXT(c, tqe); - TAILQ_REMOVE(&SCTP_BASE_INFO(callqueue), c, tqe); - c_func = c->c_func; - c_arg = c->c_arg; - c->c_flags &= ~SCTP_CALLOUT_PENDING; - SCTP_TIMERQ_UNLOCK(); - c_func(c_arg); - SCTP_TIMERQ_LOCK(); - c = sctp_os_timer_next; - } else { - c = TAILQ_NEXT(c, tqe); - } - } - SCTP_TIMERQ_UNLOCK(); - } - return (NULL); -} - -void -sctp_start_timer(void) -{ - /* - * No need to do SCTP_TIMERQ_LOCK_INIT(); - * here, it is being done in sctp_pcb_init() - */ -#if defined (__Userspace_os_Windows) - if ((SCTP_BASE_VAR(timer_thread) = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)user_sctp_timer_iterate, NULL, 0, NULL)) == NULL) { - SCTP_PRINTF("ERROR; Creating ithread failed\n"); - } -#else - int rc; - - rc = pthread_create(&SCTP_BASE_VAR(timer_thread), NULL, user_sctp_timer_iterate, NULL); - if (rc) { - SCTP_PRINTF("ERROR; return code from pthread_create() is %d\n", rc); - } -#endif -} From d6f9c2f3a4a6bffa6fd5be5a6dc2bac590489cde Mon Sep 17 00:00:00 2001 From: Anthony Jones Date: Thu, 13 Nov 2014 17:50:26 +1300 Subject: [PATCH 15/80] Bug 1097449 - Add locking around libav open/close; r=jya --- dom/media/fmp4/ffmpeg/FFmpegDataDecoder.cpp | 5 +++++ dom/media/fmp4/ffmpeg/FFmpegDataDecoder.h | 2 ++ 2 files changed, 7 insertions(+) diff --git a/dom/media/fmp4/ffmpeg/FFmpegDataDecoder.cpp b/dom/media/fmp4/ffmpeg/FFmpegDataDecoder.cpp index 89fdc3ec25e6..fbe8b35baaae 100644 --- a/dom/media/fmp4/ffmpeg/FFmpegDataDecoder.cpp +++ b/dom/media/fmp4/ffmpeg/FFmpegDataDecoder.cpp @@ -18,6 +18,7 @@ namespace mozilla { bool FFmpegDataDecoder::sFFmpegInitDone = false; +StaticMutex FFmpegDataDecoder::sMonitor; FFmpegDataDecoder::FFmpegDataDecoder(MediaTaskQueue* aTaskQueue, AVCodecID aCodecID) @@ -58,6 +59,8 @@ ChoosePixelFormat(AVCodecContext* aCodecContext, const PixelFormat* aFormats) nsresult FFmpegDataDecoder::Init() { + StaticMutexAutoLock mon(sMonitor); + FFMPEG_LOG("Initialising FFmpeg decoder."); if (!sFFmpegInitDone) { @@ -130,6 +133,8 @@ FFmpegDataDecoder::Flush() nsresult FFmpegDataDecoder::Shutdown() { + StaticMutexAutoLock mon(sMonitor); + if (sFFmpegInitDone) { avcodec_close(mCodecContext); av_freep(&mCodecContext); diff --git a/dom/media/fmp4/ffmpeg/FFmpegDataDecoder.h b/dom/media/fmp4/ffmpeg/FFmpegDataDecoder.h index 947898e072c7..d0e53ad974ef 100644 --- a/dom/media/fmp4/ffmpeg/FFmpegDataDecoder.h +++ b/dom/media/fmp4/ffmpeg/FFmpegDataDecoder.h @@ -10,6 +10,7 @@ #include "PlatformDecoderModule.h" #include "FFmpegLibs.h" #include "mozilla/Vector.h" +#include "mozilla/StaticMutex.h" namespace mozilla { @@ -44,6 +45,7 @@ protected: private: static bool sFFmpegInitDone; + static StaticMutex sMonitor; AVCodecID mCodecID; }; From 57adf459d45f4322f036b0503aa98a9a72940f4e Mon Sep 17 00:00:00 2001 From: Botond Ballo Date: Fri, 24 Oct 2014 15:49:38 -0400 Subject: [PATCH 16/80] Bug 1076163 - Basic APZ support for css-driven resolution. r=kats,tn This makes APZ behave nicely with most uses of a css transform:scale. Summary of changes: - FrameMetrics::mCumulativeResolution now includes the css-driven resolution in addition to the pres-shell resolution. - Displayports are now stored in Screen pixels rather than Layer pixels. This is what we want anyways (as we'd like the displayport size to remain constant as a fraction of the screen size), but it was necessary to make this change as part of this patch because continuing to store them in Layer pixels in the presence of a css-driven resolution would have required a bunch of infrastructure to implement correctly. Remaining work: - Layout painting a scrollable layer at a resolution different from the scale induced by the css transform causes problems. These will go away with bug 1076192. - Different resolutions on the x and y axes are not supported. This is tracked by bug 1039967. --- dom/base/nsDOMWindowUtils.cpp | 10 +- dom/interfaces/base/nsIDOMWindowUtils.idl | 2 +- gfx/ipc/GfxMessageUtils.h | 2 + gfx/layers/FrameMetrics.h | 44 +++++--- gfx/layers/apz/src/APZCTreeManager.cpp | 2 +- gfx/layers/apz/src/APZCTreeManager.h | 2 +- gfx/layers/apz/src/AsyncPanZoomController.cpp | 14 ++- gfx/layers/apz/src/AsyncPanZoomController.h | 2 +- gfx/layers/apz/util/APZCCallbackHelper.cpp | 12 +-- layout/base/Units.h | 12 +++ layout/base/nsDisplayList.cpp | 23 ++-- layout/base/nsLayoutUtils.cpp | 101 +++++++++++------- layout/base/nsLayoutUtils.h | 14 ++- layout/generic/nsGfxScrollFrame.cpp | 2 +- 14 files changed, 154 insertions(+), 88 deletions(-) diff --git a/dom/base/nsDOMWindowUtils.cpp b/dom/base/nsDOMWindowUtils.cpp index 5f5c3d76e943..9e20e6542b59 100644 --- a/dom/base/nsDOMWindowUtils.cpp +++ b/dom/base/nsDOMWindowUtils.cpp @@ -444,11 +444,11 @@ nsDOMWindowUtils::SetDisplayPortMarginsForElement(float aLeftMargin, } // Note order change of arguments between our function signature and - // LayerMargin constructor. - LayerMargin displayportMargins(aTopMargin, - aRightMargin, - aBottomMargin, - aLeftMargin); + // ScreenMargin constructor. + ScreenMargin displayportMargins(aTopMargin, + aRightMargin, + aBottomMargin, + aLeftMargin); nsLayoutUtils::SetDisplayPortMargins(content, presShell, displayportMargins, aAlignmentX, aAlignmentY, aPriority); diff --git a/dom/interfaces/base/nsIDOMWindowUtils.idl b/dom/interfaces/base/nsIDOMWindowUtils.idl index c42881bfe937..0681ce78cea8 100644 --- a/dom/interfaces/base/nsIDOMWindowUtils.idl +++ b/dom/interfaces/base/nsIDOMWindowUtils.idl @@ -181,7 +181,7 @@ interface nsIDOMWindowUtils : nsISupports { * that each edge is located at a multiple of the "alignment" value. * * Note that both the margin values and alignment are treated as values in - * LayerPixels. Refer to layout/base/Units.h for a description of this unit. + * ScreenPixels. Refer to layout/base/Units.h for a description of this unit. * The base rect values are in app units. */ void setDisplayPortMarginsForElement(in float aLeftMargin, diff --git a/gfx/ipc/GfxMessageUtils.h b/gfx/ipc/GfxMessageUtils.h index 574d70eaa9a3..a62ada5faafc 100644 --- a/gfx/ipc/GfxMessageUtils.h +++ b/gfx/ipc/GfxMessageUtils.h @@ -753,6 +753,7 @@ struct ParamTraits WriteParam(aMsg, aParam.mUpdateScrollOffset); WriteParam(aMsg, aParam.mScrollGeneration); WriteParam(aMsg, aParam.mTransformScale); + WriteParam(aMsg, aParam.mExtraResolution); WriteParam(aMsg, aParam.mBackgroundColor); WriteParam(aMsg, aParam.mDoSmoothScroll); WriteParam(aMsg, aParam.mSmoothScrollOffset); @@ -794,6 +795,7 @@ struct ParamTraits ReadParam(aMsg, aIter, &aResult->mUpdateScrollOffset) && ReadParam(aMsg, aIter, &aResult->mScrollGeneration) && ReadParam(aMsg, aIter, &aResult->mTransformScale) && + ReadParam(aMsg, aIter, &aResult->mExtraResolution) && ReadParam(aMsg, aIter, &aResult->mBackgroundColor) && ReadParam(aMsg, aIter, &aResult->mDoSmoothScroll) && ReadParam(aMsg, aIter, &aResult->mSmoothScrollOffset) && diff --git a/gfx/layers/FrameMetrics.h b/gfx/layers/FrameMetrics.h index 699e4adde674..018e24f6537a 100644 --- a/gfx/layers/FrameMetrics.h +++ b/gfx/layers/FrameMetrics.h @@ -97,6 +97,7 @@ public: , mUseDisplayPortMargins(false) , mPresShellId(-1) , mViewport(0, 0, 0, 0) + , mExtraResolution(1) , mBackgroundColor(0, 0, 0, 0) { } @@ -126,6 +127,7 @@ public: mSmoothScrollOffset == aOther.mSmoothScrollOffset && mHasScrollgrab == aOther.mHasScrollgrab && mUpdateScrollOffset == aOther.mUpdateScrollOffset && + mExtraResolution == aOther.mExtraResolution && mBackgroundColor == aOther.mBackgroundColor && mDoSmoothScroll == aOther.mDoSmoothScroll; } @@ -152,6 +154,18 @@ public: return mScrollId != NULL_SCROLL_ID; } + CSSToScreenScale DisplayportPixelsPerCSSPixel() const + { + // Note: use 'mZoom * ScreenToLayerScale(1.0f)' as the CSS-to-Layer scale + // instead of LayersPixelsPerCSSPixel(), because displayport calculations + // are done in the context of a repaint request, where we ask Layout to + // repaint at a new resolution that includes any async zoom. Until this + // repaint request is processed, LayersPixelsPerCSSPixel() does not yet + // include the async zoom, but it will when the displayport is interpreted + // for the repaint. + return mZoom * ScreenToLayerScale(1.0f) / mExtraResolution; + } + CSSToLayerScale LayersPixelsPerCSSPixel() const { return mCumulativeResolution * mDevPixelsPerCSSPixel; @@ -339,15 +353,7 @@ public: // This information is provided by Gecko at layout/paint time. LayoutDeviceToLayerScale mCumulativeResolution; - // The conversion factor between local screen pixels (the coordinate - // system in which APZCs receive input events) and our parent layer's - // layer pixels (the coordinate system of mCompositionBounds). - // This consists of the scale of the local CSS transform and the - // nontransient async transform. - // TODO: APZ does not currently work well if there is a CSS transform - // on the layer being scrolled that's not just a scale that's - // the same in both directions. When we fix this, mTransformScale - // will probably need to turn into a matrix. + // TODO(botond): This is now always 1 and should be removed (see bug 1055741). ScreenToParentLayerScale mTransformScale; // The conversion factor between CSS pixels and device pixels for this frame. @@ -464,12 +470,12 @@ public: return mRootCompositionSize; } - void SetDisplayPortMargins(const LayerMargin& aDisplayPortMargins) + void SetDisplayPortMargins(const ScreenMargin& aDisplayPortMargins) { mDisplayPortMargins = aDisplayPortMargins; } - const LayerMargin& GetDisplayPortMargins() const + const ScreenMargin& GetDisplayPortMargins() const { return mDisplayPortMargins; } @@ -504,6 +510,16 @@ public: return mViewport; } + void SetExtraResolution(const ScreenToLayerScale& aExtraResolution) + { + mExtraResolution = aExtraResolution; + } + + ScreenToLayerScale GetExtraResolution() const + { + return mExtraResolution; + } + const gfxRGBA& GetBackgroundColor() const { return mBackgroundColor; @@ -605,7 +621,7 @@ private: // A display port expressed as layer margins that apply to the rect of what // is drawn of the scrollable element. - LayerMargin mDisplayPortMargins; + ScreenMargin mDisplayPortMargins; // If this is true then we use the display port margins on this metrics, // otherwise use the display port rect. @@ -624,6 +640,10 @@ private: // meaningless and invalid. CSSRect mViewport; + // The extra resolution at which content in this scroll frame is drawn beyond + // that necessary to draw one Layer pixel per Screen pixel. + ScreenToLayerScale mExtraResolution; + // The background color to use when overscrolling. gfxRGBA mBackgroundColor; diff --git a/gfx/layers/apz/src/APZCTreeManager.cpp b/gfx/layers/apz/src/APZCTreeManager.cpp index 4ce56926f6d0..0184ee30afb7 100644 --- a/gfx/layers/apz/src/APZCTreeManager.cpp +++ b/gfx/layers/apz/src/APZCTreeManager.cpp @@ -61,7 +61,7 @@ struct APZCTreeManager::TreeBuildingState { std::map mApzcMap; }; -/*static*/ const LayerMargin +/*static*/ const ScreenMargin APZCTreeManager::CalculatePendingDisplayPort( const FrameMetrics& aFrameMetrics, const ScreenPoint& aVelocity, diff --git a/gfx/layers/apz/src/APZCTreeManager.h b/gfx/layers/apz/src/APZCTreeManager.h index c24036d1aafb..16c34f4ab84a 100644 --- a/gfx/layers/apz/src/APZCTreeManager.h +++ b/gfx/layers/apz/src/APZCTreeManager.h @@ -245,7 +245,7 @@ public: * function simply delegates to that one, so that non-layers code * never needs to include AsyncPanZoomController.h */ - static const LayerMargin CalculatePendingDisplayPort( + static const ScreenMargin CalculatePendingDisplayPort( const FrameMetrics& aFrameMetrics, const ScreenPoint& aVelocity, double aEstimatedPaintDuration); diff --git a/gfx/layers/apz/src/AsyncPanZoomController.cpp b/gfx/layers/apz/src/AsyncPanZoomController.cpp index e58a3d6081d7..e20a26a1ede1 100644 --- a/gfx/layers/apz/src/AsyncPanZoomController.cpp +++ b/gfx/layers/apz/src/AsyncPanZoomController.cpp @@ -2198,7 +2198,7 @@ RedistributeDisplayPortExcess(CSSSize& aDisplayPortSize, } /* static */ -const LayerMargin AsyncPanZoomController::CalculatePendingDisplayPort( +const ScreenMargin AsyncPanZoomController::CalculatePendingDisplayPort( const FrameMetrics& aFrameMetrics, const ScreenPoint& aVelocity, double aEstimatedPaintDuration) @@ -2240,9 +2240,7 @@ const LayerMargin AsyncPanZoomController::CalculatePendingDisplayPort( cssMargins.right = displayPort.width - compositionSize.width - cssMargins.left; cssMargins.bottom = displayPort.height - compositionSize.height - cssMargins.top; - LayerMargin layerMargins = cssMargins * aFrameMetrics.LayersPixelsPerCSSPixel(); - - return layerMargins; + return cssMargins * aFrameMetrics.DisplayportPixelsPerCSSPixel(); } void AsyncPanZoomController::ScheduleComposite() { @@ -2320,8 +2318,8 @@ void AsyncPanZoomController::RequestContentRepaint(FrameMetrics& aFrameMetrics, // If we're trying to paint what we already think is painted, discard this // request since it's a pointless paint. - LayerMargin marginDelta = mLastPaintRequestMetrics.GetDisplayPortMargins() - - aFrameMetrics.GetDisplayPortMargins(); + ScreenMargin marginDelta = (mLastPaintRequestMetrics.GetDisplayPortMargins() + - aFrameMetrics.GetDisplayPortMargins()); if (fabsf(marginDelta.left) < EPSILON && fabsf(marginDelta.top) < EPSILON && fabsf(marginDelta.right) < EPSILON && @@ -2359,7 +2357,7 @@ GetDisplayPortRect(const FrameMetrics& aFrameMetrics) // changes then this might need to change too CSSRect baseRect(aFrameMetrics.GetScrollOffset(), aFrameMetrics.CalculateBoundedCompositedSizeInCssPixels()); - baseRect.Inflate(aFrameMetrics.GetDisplayPortMargins() / aFrameMetrics.LayersPixelsPerCSSPixel()); + baseRect.Inflate(aFrameMetrics.GetDisplayPortMargins() / aFrameMetrics.DisplayportPixelsPerCSSPixel()); return baseRect; } @@ -2694,7 +2692,7 @@ void AsyncPanZoomController::NotifyLayersUpdated(const FrameMetrics& aLayerMetri mLastDispatchedPaintMetrics = aLayerMetrics; ShareCompositorFrameMetrics(); - if (mFrameMetrics.GetDisplayPortMargins() != LayerMargin()) { + if (mFrameMetrics.GetDisplayPortMargins() != ScreenMargin()) { // A non-zero display port margin here indicates a displayport has // been set by a previous APZC for the content at this guid. The // scrollable rect may have changed since then, making the margins diff --git a/gfx/layers/apz/src/AsyncPanZoomController.h b/gfx/layers/apz/src/AsyncPanZoomController.h index 941f1c01786c..3a00acf6fa57 100644 --- a/gfx/layers/apz/src/AsyncPanZoomController.h +++ b/gfx/layers/apz/src/AsyncPanZoomController.h @@ -245,7 +245,7 @@ public: * checkerboard immediately. This includes a bunch of logic, including * algorithms to bias painting in the direction of the velocity. */ - static const LayerMargin CalculatePendingDisplayPort( + static const ScreenMargin CalculatePendingDisplayPort( const FrameMetrics& aFrameMetrics, const ScreenPoint& aVelocity, double aEstimatedPaintDuration); diff --git a/gfx/layers/apz/util/APZCCallbackHelper.cpp b/gfx/layers/apz/util/APZCCallbackHelper.cpp index 2c998fcc5299..61a2724101ab 100644 --- a/gfx/layers/apz/util/APZCCallbackHelper.cpp +++ b/gfx/layers/apz/util/APZCCallbackHelper.cpp @@ -35,10 +35,10 @@ AdjustDisplayPortForScrollDelta(mozilla::layers::FrameMetrics& aFrameMetrics, { // Correct the display-port by the difference between the requested scroll // offset and the resulting scroll offset after setting the requested value. - LayerPoint shift = + ScreenPoint shift = (aFrameMetrics.GetScrollOffset() - aActualScrollOffset) * - aFrameMetrics.LayersPixelsPerCSSPixel(); - LayerMargin margins = aFrameMetrics.GetDisplayPortMargins(); + aFrameMetrics.DisplayportPixelsPerCSSPixel(); + ScreenMargin margins = aFrameMetrics.GetDisplayPortMargins(); margins.left -= shift.x; margins.right += shift.x; margins.top -= shift.y; @@ -49,7 +49,7 @@ AdjustDisplayPortForScrollDelta(mozilla::layers::FrameMetrics& aFrameMetrics, static void RecenterDisplayPort(mozilla::layers::FrameMetrics& aFrameMetrics) { - LayerMargin margins = aFrameMetrics.GetDisplayPortMargins(); + ScreenMargin margins = aFrameMetrics.GetDisplayPortMargins(); margins.right = margins.left = margins.LeftRight() / 2; margins.top = margins.bottom = margins.TopBottom() / 2; aFrameMetrics.SetDisplayPortMargins(margins); @@ -170,7 +170,7 @@ APZCCallbackHelper::UpdateRootFrame(nsIDOMWindowUtils* aUtils, gfx::IntSize alignment = gfxPlatform::GetPlatform()->UseTiling() ? gfx::IntSize(gfxPrefs::LayersTileWidth(), gfxPrefs::LayersTileHeight()) : gfx::IntSize(0, 0); - LayerMargin margins = aMetrics.GetDisplayPortMargins(); + ScreenMargin margins = aMetrics.GetDisplayPortMargins(); aUtils->SetDisplayPortMarginsForElement(margins.left, margins.top, margins.right, @@ -219,7 +219,7 @@ APZCCallbackHelper::UpdateSubFrame(nsIContent* aContent, gfx::IntSize alignment = gfxPlatform::GetPlatform()->UseTiling() ? gfx::IntSize(gfxPrefs::LayersTileWidth(), gfxPrefs::LayersTileHeight()) : gfx::IntSize(0, 0); - LayerMargin margins = aMetrics.GetDisplayPortMargins(); + ScreenMargin margins = aMetrics.GetDisplayPortMargins(); utils->SetDisplayPortMarginsForElement(margins.left, margins.top, margins.right, diff --git a/layout/base/Units.h b/layout/base/Units.h index e82acc7d60ac..f0cd08c5971f 100644 --- a/layout/base/Units.h +++ b/layout/base/Units.h @@ -198,6 +198,11 @@ struct LayoutDevicePixel { NSAppUnitsToFloatPixels(aRect.height, float(aAppUnitsPerDevPixel))); } + static LayoutDevicePoint FromAppUnits(const nsPoint& aPoint, nscoord aAppUnitsPerDevPixel) { + return LayoutDevicePoint(NSAppUnitsToFloatPixels(aPoint.x, aAppUnitsPerDevPixel), + NSAppUnitsToFloatPixels(aPoint.y, aAppUnitsPerDevPixel)); + } + static LayoutDeviceIntPoint FromAppUnitsRounded(const nsPoint& aPoint, nscoord aAppUnitsPerDevPixel) { return LayoutDeviceIntPoint(NSAppUnitsToIntPixels(aPoint.x, aAppUnitsPerDevPixel), NSAppUnitsToIntPixels(aPoint.y, aAppUnitsPerDevPixel)); @@ -215,6 +220,13 @@ struct LayoutDevicePixel { return nsSize(aSize.width * aAppUnitsPerDevPixel, aSize.height * aAppUnitsPerDevPixel); } + + static nsRect ToAppUnits(const LayoutDeviceRect& aRect, nscoord aAppUnitsPerDevPixel) { + return nsRect(NSFloatPixelsToAppUnits(aRect.x, aAppUnitsPerDevPixel), + NSFloatPixelsToAppUnits(aRect.y, aAppUnitsPerDevPixel), + NSFloatPixelsToAppUnits(aRect.width, aAppUnitsPerDevPixel), + NSFloatPixelsToAppUnits(aRect.height, aAppUnitsPerDevPixel)); + } }; /* diff --git a/layout/base/nsDisplayList.cpp b/layout/base/nsDisplayList.cpp index d6aa96293c82..3045f2c6c9d6 100644 --- a/layout/base/nsDisplayList.cpp +++ b/layout/base/nsDisplayList.cpp @@ -663,7 +663,6 @@ nsDisplayScrollLayer::ComputeFrameMetrics(nsIFrame* aForFrame, { nsPresContext* presContext = aForFrame->PresContext(); int32_t auPerDevPixel = presContext->AppUnitsPerDevPixel(); - LayoutDeviceToLayerScale resolution(aContainerParameters.mXScale, aContainerParameters.mYScale); nsIPresShell* presShell = presContext->GetPresShell(); FrameMetrics metrics; @@ -730,18 +729,18 @@ nsDisplayScrollLayer::ComputeFrameMetrics(nsIFrame* aForFrame, } else { metrics.mResolution = ParentLayerToLayerScale(1.0f); } + // The cumulative resolution is the resolution at which the scroll frame's + // content is actually rendered. It includes the pres shell resolutions of + // all the pres shells from here up to the root, as well as any css-driven + // resolution. We don't need to compute it as it's already stored in the + // container parameters. + metrics.mCumulativeResolution = LayoutDeviceToLayerScale(aContainerParameters.mXScale, + aContainerParameters.mYScale); - // For the cumulateive resolution, multiply the resolutions of all the - // presShells back up to the root - metrics.mCumulativeResolution = LayoutDeviceToLayerScale(1.0f); - nsIPresShell* curPresShell = presShell; - while (curPresShell != nullptr) { - ParentLayerToLayerScale presShellResolution(curPresShell->GetXResolution(), - curPresShell->GetYResolution()); - metrics.mCumulativeResolution.scale *= presShellResolution.scale; - nsPresContext* parentContext = curPresShell->GetPresContext()->GetParentPresContext(); - curPresShell = parentContext ? parentContext->GetPresShell() : nullptr; - } + LayoutDeviceToScreenScale resolutionToScreen( + presShell->GetCumulativeResolution().width + * nsLayoutUtils::GetTransformToAncestorScale(aScrollFrame ? aScrollFrame : aForFrame).width); + metrics.SetExtraResolution(metrics.mCumulativeResolution / resolutionToScreen); metrics.mDevPixelsPerCSSPixel = CSSToLayoutDeviceScale( (float)nsPresContext::AppUnitsPerCSSPixel() / auPerDevPixel); diff --git a/layout/base/nsLayoutUtils.cpp b/layout/base/nsLayoutUtils.cpp index 622548868b48..09cf4e1cb079 100644 --- a/layout/base/nsLayoutUtils.cpp +++ b/layout/base/nsLayoutUtils.cpp @@ -836,32 +836,41 @@ GetDisplayPortFromMarginsData(nsIContent* aContent, nsPresContext* presContext = frame->PresContext(); int32_t auPerDevPixel = presContext->AppUnitsPerDevPixel(); - gfxSize res = presContext->PresShell()->GetCumulativeResolution(); - // First convert the base rect to layer pixels - gfxSize parentRes = res; + LayoutDeviceToScreenScale res(presContext->PresShell()->GetCumulativeResolution().width + * nsLayoutUtils::GetTransformToAncestorScale(frame).width); + + // First convert the base rect to screen pixels + LayoutDeviceToScreenScale parentRes = res; if (isRoot) { // the base rect for root scroll frames is specified in the parent document // coordinate space, so it doesn't include the local resolution. gfxSize localRes = presContext->PresShell()->GetResolution(); - parentRes.width /= localRes.width; - parentRes.height /= localRes.height; + parentRes.scale /= localRes.width; } - LayerRect layerRect(NSAppUnitsToFloatPixels(base.x, auPerDevPixel) * parentRes.width, - NSAppUnitsToFloatPixels(base.y, auPerDevPixel) * parentRes.height, - NSAppUnitsToFloatPixels(base.width, auPerDevPixel) * parentRes.width, - NSAppUnitsToFloatPixels(base.height, auPerDevPixel) * parentRes.height); + ScreenRect screenRect = LayoutDeviceRect::FromAppUnits(base, auPerDevPixel) + * parentRes; // Expand the rect by the margins - layerRect.Inflate(aMarginsData->mMargins); + screenRect.Inflate(aMarginsData->mMargins); - // And then align it to the requested alignment + // And then align it to the requested alignment. + // Note on the correctness of applying the alignment in Screen space: + // The correct space to apply the alignment in would be Layer space, but + // we don't necessarily know the scale to convert to Layer space at this + // point because Layout may not yet have chosen the resolution at which to + // render (it chooses that in FrameLayerBuilder, but this can be called + // during display list building). Therefore, we perform the alignment in + // Screen space, which basically assumes that Layout chose to render at + // screen resolution; since this is what Layout does most of the time, + // this is a good approximation. A proper solution would involve moving the + // choosing of the resolution to display-list building time. if (aMarginsData->mAlignmentX > 0 || aMarginsData->mAlignmentY > 0) { // Inflate the rectangle by 1 so that we always push to the next tile // boundary. This is desirable to stop from having a rectangle with a // moving origin occasionally being smaller when it coincidentally lines // up to tile boundaries. - layerRect.Inflate(1); + screenRect.Inflate(1); // Avoid division by zero. if (aMarginsData->mAlignmentX == 0) { @@ -871,23 +880,20 @@ GetDisplayPortFromMarginsData(nsIContent* aContent, aMarginsData->mAlignmentY = 1; } - LayerPoint scrollPosLayer(NSAppUnitsToFloatPixels(scrollPos.x, auPerDevPixel) * res.width, - NSAppUnitsToFloatPixels(scrollPos.y, auPerDevPixel) * res.height); + ScreenPoint scrollPosScreen = LayoutDevicePoint::FromAppUnits(scrollPos, auPerDevPixel) + * res; - layerRect += scrollPosLayer; - float x = aMarginsData->mAlignmentX * floor(layerRect.x / aMarginsData->mAlignmentX); - float y = aMarginsData->mAlignmentY * floor(layerRect.y / aMarginsData->mAlignmentY); - float w = aMarginsData->mAlignmentX * ceil(layerRect.XMost() / aMarginsData->mAlignmentX) - x; - float h = aMarginsData->mAlignmentY * ceil(layerRect.YMost() / aMarginsData->mAlignmentY) - y; - layerRect = LayerRect(x, y, w, h); - layerRect -= scrollPosLayer; + screenRect += scrollPosScreen; + float x = aMarginsData->mAlignmentX * floor(screenRect.x / aMarginsData->mAlignmentX); + float y = aMarginsData->mAlignmentY * floor(screenRect.y / aMarginsData->mAlignmentY); + float w = aMarginsData->mAlignmentX * ceil(screenRect.XMost() / aMarginsData->mAlignmentX) - x; + float h = aMarginsData->mAlignmentY * ceil(screenRect.YMost() / aMarginsData->mAlignmentY) - y; + screenRect = ScreenRect(x, y, w, h); + screenRect -= scrollPosScreen; } // Convert the aligned rect back into app units - nsRect result(NSFloatPixelsToAppUnits(layerRect.x / res.width, auPerDevPixel), - NSFloatPixelsToAppUnits(layerRect.y / res.height, auPerDevPixel), - NSFloatPixelsToAppUnits(layerRect.width / res.width, auPerDevPixel), - NSFloatPixelsToAppUnits(layerRect.height / res.height, auPerDevPixel)); + nsRect result = LayoutDeviceRect::ToAppUnits(screenRect / res, auPerDevPixel); // Expand it for the low-res buffer if needed result = ApplyRectMultiplier(result, aMultiplier); @@ -950,7 +956,7 @@ nsLayoutUtils::GetDisplayPort(nsIContent* aContent, nsRect *aResult) void nsLayoutUtils::SetDisplayPortMargins(nsIContent* aContent, nsIPresShell* aPresShell, - const LayerMargin& aMargins, + const ScreenMargin& aMargins, uint32_t aAlignmentX, uint32_t aAlignmentY, uint32_t aPriority, @@ -2301,6 +2307,19 @@ nsLayoutUtils::GetTransformToAncestor(nsIFrame *aFrame, const nsIFrame *aAncesto return ctm; } +gfxSize +nsLayoutUtils::GetTransformToAncestorScale(nsIFrame* aFrame) +{ + Matrix4x4 transform = GetTransformToAncestor(aFrame, + nsLayoutUtils::GetDisplayRootFrame(aFrame)); + Matrix transform2D; + if (transform.Is2D(&transform2D)) { + return ThebesMatrix(transform2D).ScaleFactors(true); + } + return gfxSize(1, 1); +} + + static nsIFrame* FindNearestCommonAncestorFrame(nsIFrame* aFrame1, nsIFrame* aFrame2) { @@ -2772,7 +2791,15 @@ CalculateFrameMetricsForDisplayPort(nsIFrame* aScrollFrame, resolution = ParentLayerToLayerScale(presShell->GetXResolution(), presShell->GetYResolution()); } - LayoutDeviceToLayerScale cumulativeResolution(presShell->GetCumulativeResolution().width); + // Note: unlike in ComputeFrameMetrics(), we don't know the full cumulative + // resolution including FrameMetrics::mExtraResolution, because layout hasn't + // chosen a resolution to paint at yet. However, the display port calculation + // divides out mExtraResolution anyways, so we get the correct result by + // setting the mCumulativeResolution to everything except the extra resolution + // and leaving mExtraResolution at 1. + LayoutDeviceToLayerScale cumulativeResolution( + presShell->GetCumulativeResolution().width + * nsLayoutUtils::GetTransformToAncestorScale(aScrollFrame).width); metrics.mDevPixelsPerCSSPixel = deviceScale; metrics.mResolution = resolution; @@ -2841,7 +2868,7 @@ nsLayoutUtils::GetOrMaybeCreateDisplayPort(nsDisplayListBuilder& aBuilder, // If we don't already have a displayport, calculate and set one. if (!haveDisplayPort) { FrameMetrics metrics = CalculateFrameMetricsForDisplayPort(aScrollFrame, scrollableFrame); - LayerMargin displayportMargins = APZCTreeManager::CalculatePendingDisplayPort( + ScreenMargin displayportMargins = APZCTreeManager::CalculatePendingDisplayPort( metrics, ScreenPoint(0.0f, 0.0f), 0.0); nsIPresShell* presShell = aScrollFrame->PresContext()->GetPresShell(); gfx::IntSize alignment = gfxPlatform::GetPlatform()->UseTiling() @@ -7006,10 +7033,11 @@ nsLayoutUtils::CalculateRootCompositionSize(nsIFrame* aFrame, if (aIsRootContentDocRootScrollFrame) { return ViewAs(aMetrics.mCompositionBounds.Size(), PixelCastJustification::ParentLayerToLayerForRootComposition) - / aMetrics.LayersPixelsPerCSSPixel(); + * LayerToScreenScale(1.0f) + / aMetrics.DisplayportPixelsPerCSSPixel(); } nsPresContext* presContext = aFrame->PresContext(); - LayerSize rootCompositionSize; + ScreenSize rootCompositionSize; nsPresContext* rootPresContext = presContext->GetToplevelContentDocumentPresContext(); if (!rootPresContext) { @@ -7023,12 +7051,13 @@ nsLayoutUtils::CalculateRootCompositionSize(nsIFrame* aFrame, nsIPresShell* rootPresShell = rootPresContext->PresShell(); if (nsIFrame* rootFrame = rootPresShell->GetRootFrame()) { LayoutDeviceToLayerScale cumulativeResolution( - rootPresShell->GetCumulativeResolution().width); + rootPresShell->GetCumulativeResolution().width + * nsLayoutUtils::GetTransformToAncestorScale(rootFrame).width); int32_t rootAUPerDevPixel = rootPresContext->AppUnitsPerDevPixel(); LayerSize frameSize = (LayoutDeviceRect::FromAppUnits(rootFrame->GetRect(), rootAUPerDevPixel) * cumulativeResolution).Size(); - rootCompositionSize = frameSize; + rootCompositionSize = frameSize * LayerToScreenScale(1.0f); #ifdef MOZ_WIDGET_ANDROID nsIWidget* widget = rootFrame->GetNearestWidget(); #else @@ -7038,7 +7067,7 @@ nsLayoutUtils::CalculateRootCompositionSize(nsIFrame* aFrame, if (widget) { nsIntRect widgetBounds; widget->GetBounds(widgetBounds); - rootCompositionSize = LayerSize(ViewAs(widgetBounds.Size())); + rootCompositionSize = ScreenSize(ViewAs(widgetBounds.Size())); #ifdef MOZ_WIDGET_ANDROID if (frameSize.height < rootCompositionSize.height) { rootCompositionSize.height = frameSize.height; @@ -7052,7 +7081,7 @@ nsLayoutUtils::CalculateRootCompositionSize(nsIFrame* aFrame, gfxSize res = rootPresContext->GetParentPresContext()->PresShell()->GetCumulativeResolution(); scale = LayoutDeviceToLayerScale(res.width, res.height); } - rootCompositionSize = contentSize * scale; + rootCompositionSize = contentSize * scale * LayerToScreenScale(1.0f); } } } @@ -7060,7 +7089,7 @@ nsLayoutUtils::CalculateRootCompositionSize(nsIFrame* aFrame, nsIWidget* widget = aFrame->GetNearestWidget(); nsIntRect widgetBounds; widget->GetBounds(widgetBounds); - rootCompositionSize = LayerSize(ViewAs(widgetBounds.Size())); + rootCompositionSize = ScreenSize(ViewAs(widgetBounds.Size())); } // Adjust composition size for the size of scroll bars. @@ -7076,7 +7105,7 @@ nsLayoutUtils::CalculateRootCompositionSize(nsIFrame* aFrame, rootCompositionSize.height -= margins.TopBottom(); } - return rootCompositionSize / aMetrics.LayersPixelsPerCSSPixel(); + return rootCompositionSize / aMetrics.DisplayportPixelsPerCSSPixel(); } /* static */ nsRect diff --git a/layout/base/nsLayoutUtils.h b/layout/base/nsLayoutUtils.h index 0f761212df67..b75f2d98f6df 100644 --- a/layout/base/nsLayoutUtils.h +++ b/layout/base/nsLayoutUtils.h @@ -95,7 +95,7 @@ struct DisplayPortPropertyData { }; struct DisplayPortMarginsPropertyData { - DisplayPortMarginsPropertyData(const LayerMargin& aMargins, + DisplayPortMarginsPropertyData(const ScreenMargin& aMargins, uint32_t aAlignmentX, uint32_t aAlignmentY, uint32_t aPriority) : mMargins(aMargins) @@ -103,7 +103,7 @@ struct DisplayPortMarginsPropertyData { , mAlignmentY(aAlignmentY) , mPriority(aPriority) {} - LayerMargin mMargins; + ScreenMargin mMargins; uint32_t mAlignmentX; uint32_t mAlignmentY; uint32_t mPriority; @@ -137,7 +137,7 @@ public: typedef FrameMetrics::ViewID ViewID; typedef mozilla::CSSPoint CSSPoint; typedef mozilla::CSSSize CSSSize; - typedef mozilla::LayerMargin LayerMargin; + typedef mozilla::ScreenMargin ScreenMargin; typedef mozilla::LayoutDeviceIntSize LayoutDeviceIntSize; /** @@ -188,7 +188,7 @@ public: */ static void SetDisplayPortMargins(nsIContent* aContent, nsIPresShell* aPresShell, - const LayerMargin& aMargins, + const ScreenMargin& aMargins, uint32_t aAlignmentX, uint32_t aAlignmentY, uint32_t aPriority = 0, @@ -742,6 +742,12 @@ public: */ static Matrix4x4 GetTransformToAncestor(nsIFrame *aFrame, const nsIFrame *aAncestor); + /** + * Gets the scale factors of the transform for aFrame relative to the root + * frame if this transform is 2D, or the identity scale factors otherwise. + */ + static gfxSize GetTransformToAncestorScale(nsIFrame* aFrame); + /** * Transforms a list of CSSPoints from aFromFrame to aToFrame, taking into * account all relevant transformations on the frames up to (but excluding) diff --git a/layout/generic/nsGfxScrollFrame.cpp b/layout/generic/nsGfxScrollFrame.cpp index 631897f31601..96a3b06187ba 100644 --- a/layout/generic/nsGfxScrollFrame.cpp +++ b/layout/generic/nsGfxScrollFrame.cpp @@ -1876,7 +1876,7 @@ ScrollFrameHelper::ScrollFrameHelper(nsContainerFrame* aOuter, // when scrolling. nsLayoutUtils::SetDisplayPortMargins(mOuter->GetContent(), mOuter->PresContext()->PresShell(), - LayerMargin(), + ScreenMargin(), gfxPrefs::LayersTileWidth(), gfxPrefs::LayersTileHeight(), 0, nsLayoutUtils::RepaintMode::DoNotRepaint); From 98ceb86b05dd6bb5a99efaf6d0419120143ab36c Mon Sep 17 00:00:00 2001 From: Botond Ballo Date: Mon, 20 Oct 2014 17:12:35 -0400 Subject: [PATCH 17/80] Bug 1076163 - Clean up the resolution-related fields and methods in FrameMetrics. r=kats --- dom/ipc/TabChild.cpp | 10 ++--- gfx/ipc/GfxMessageUtils.h | 4 +- gfx/layers/FrameMetrics.h | 29 ++++++------- gfx/layers/LayersLogging.cpp | 2 +- gfx/layers/apz/src/APZCTreeManager.cpp | 13 ++++-- gfx/layers/apz/src/AsyncPanZoomController.cpp | 43 ++++++++++++------- gfx/layers/apz/util/APZCCallbackHelper.cpp | 19 +++----- gfx/layers/client/ClientTiledPaintedLayer.cpp | 4 +- gfx/layers/client/TiledContentClient.cpp | 11 +++-- .../composite/AsyncCompositionManager.cpp | 13 +++--- .../composite/LayerManagerComposite.cpp | 2 +- .../gtest/TestAsyncPanZoomController.cpp | 2 +- layout/base/nsDisplayList.cpp | 4 +- layout/base/nsLayoutUtils.cpp | 2 +- 14 files changed, 83 insertions(+), 75 deletions(-) diff --git a/dom/ipc/TabChild.cpp b/dom/ipc/TabChild.cpp index 382d55aab397..07ac0b840bf6 100644 --- a/dom/ipc/TabChild.cpp +++ b/dom/ipc/TabChild.cpp @@ -250,7 +250,7 @@ TabChildBase::InitializeRootMetrics() mLastRootMetrics.GetZoom() / mLastRootMetrics.mDevPixelsPerCSSPixel * ScreenToLayerScale(1); // This is the root layer, so the cumulative resolution is the same // as the resolution. - mLastRootMetrics.mResolution = mLastRootMetrics.mCumulativeResolution / LayoutDeviceToParentLayerScale(1); + mLastRootMetrics.mPresShellResolution = mLastRootMetrics.mCumulativeResolution / LayoutDeviceToParentLayerScale(1); mLastRootMetrics.SetScrollOffset(CSSPoint(0, 0)); TABC_LOG("After InitializeRootMetrics, mLastRootMetrics is %s\n", @@ -417,8 +417,8 @@ TabChildBase::HandlePossibleViewportChange(const ScreenIntSize& aOldScreenSize) metrics.mCumulativeResolution = metrics.GetZoom() / metrics.mDevPixelsPerCSSPixel * ScreenToLayerScale(1); // This is the root layer, so the cumulative resolution is the same // as the resolution. - metrics.mResolution = metrics.mCumulativeResolution / LayoutDeviceToParentLayerScale(1); - utils->SetResolution(metrics.mResolution.scale, metrics.mResolution.scale); + metrics.mPresShellResolution = metrics.mCumulativeResolution / LayoutDeviceToParentLayerScale(1); + utils->SetResolution(metrics.mPresShellResolution.scale, metrics.mPresShellResolution.scale); CSSSize scrollPort = metrics.CalculateCompositedSizeInCssPixels(); utils->SetScrollPositionClampingScrollPortSize(scrollPort.width, scrollPort.height); @@ -907,8 +907,8 @@ TabChild::Observe(nsISupports *aSubject, // until we we get an inner size. if (HasValidInnerSize()) { InitializeRootMetrics(); - utils->SetResolution(mLastRootMetrics.mResolution.scale, - mLastRootMetrics.mResolution.scale); + utils->SetResolution(mLastRootMetrics.mPresShellResolution.scale, + mLastRootMetrics.mPresShellResolution.scale); HandlePossibleViewportChange(mInnerSize); } } diff --git a/gfx/ipc/GfxMessageUtils.h b/gfx/ipc/GfxMessageUtils.h index a62ada5faafc..b62c2a57839e 100644 --- a/gfx/ipc/GfxMessageUtils.h +++ b/gfx/ipc/GfxMessageUtils.h @@ -741,7 +741,7 @@ struct ParamTraits WriteParam(aMsg, aParam.mRootCompositionSize); WriteParam(aMsg, aParam.mScrollId); WriteParam(aMsg, aParam.mScrollParentId); - WriteParam(aMsg, aParam.mResolution); + WriteParam(aMsg, aParam.mPresShellResolution); WriteParam(aMsg, aParam.mCumulativeResolution); WriteParam(aMsg, aParam.mZoom); WriteParam(aMsg, aParam.mDevPixelsPerCSSPixel); @@ -783,7 +783,7 @@ struct ParamTraits ReadParam(aMsg, aIter, &aResult->mRootCompositionSize) && ReadParam(aMsg, aIter, &aResult->mScrollId) && ReadParam(aMsg, aIter, &aResult->mScrollParentId) && - ReadParam(aMsg, aIter, &aResult->mResolution) && + ReadParam(aMsg, aIter, &aResult->mPresShellResolution) && ReadParam(aMsg, aIter, &aResult->mCumulativeResolution) && ReadParam(aMsg, aIter, &aResult->mZoom) && ReadParam(aMsg, aIter, &aResult->mDevPixelsPerCSSPixel) && diff --git a/gfx/layers/FrameMetrics.h b/gfx/layers/FrameMetrics.h index 018e24f6537a..02bedfbaeb71 100644 --- a/gfx/layers/FrameMetrics.h +++ b/gfx/layers/FrameMetrics.h @@ -76,7 +76,7 @@ public: , mDisplayPort(0, 0, 0, 0) , mCriticalDisplayPort(0, 0, 0, 0) , mScrollableRect(0, 0, 0, 0) - , mResolution(1) + , mPresShellResolution(1) , mCumulativeResolution(1) , mTransformScale(1) , mDevPixelsPerCSSPixel(1) @@ -114,7 +114,7 @@ public: mCriticalDisplayPort.IsEqualEdges(aOther.mCriticalDisplayPort) && mViewport.IsEqualEdges(aOther.mViewport) && mScrollableRect.IsEqualEdges(aOther.mScrollableRect) && - mResolution == aOther.mResolution && + mPresShellResolution == aOther.mPresShellResolution && mCumulativeResolution == aOther.mCumulativeResolution && mDevPixelsPerCSSPixel == aOther.mDevPixelsPerCSSPixel && mMayHaveTouchListeners == aOther.mMayHaveTouchListeners && @@ -171,14 +171,10 @@ public: return mCumulativeResolution * mDevPixelsPerCSSPixel; } - LayerPoint GetScrollOffsetInLayerPixels() const + // Get the amount by which this frame has been zoomed since the last repaint. + LayerToScreenScale GetAsyncZoom() const { - return GetScrollOffset() * LayersPixelsPerCSSPixel(); - } - - LayoutDeviceToParentLayerScale GetParentResolution() const - { - return mCumulativeResolution / mResolution; + return mZoom / LayersPixelsPerCSSPixel(); } // Ensure the scrollableRect is at least as big as the compositionBounds @@ -343,14 +339,17 @@ public: // The following metrics are dimensionless. // - // The incremental resolution that the current frame has been painted at - // relative to the parent frame's resolution. This information is provided - // by Gecko at layout/paint time. - ParentLayerToLayerScale mResolution; + // The pres-shell resolution that has been induced on the document containing + // this scroll frame as a result of zooming this scroll frame (whether via + // user action, or choosing an initial zoom level on page load). This can + // only be different from 1.0 for frames that are zoomable, which currently + // is just the root content document's root scroll frame (mIsRoot = true). + ParentLayerToLayerScale mPresShellResolution; // The cumulative resolution that the current frame has been painted at. - // This is the product of our mResolution and the mResolutions of our parent frames. - // This information is provided by Gecko at layout/paint time. + // This is the product of the pres-shell resolutions of the document + // containing this scroll frame and its ancestors, and any css-driven + // resolution. This information is provided by Gecko at layout/paint time. LayoutDeviceToLayerScale mCumulativeResolution; // TODO(botond): This is now always 1 and should be removed (see bug 1055741). diff --git a/gfx/layers/LayersLogging.cpp b/gfx/layers/LayersLogging.cpp index 8aaf324d3efb..37708bf26d05 100644 --- a/gfx/layers/LayersLogging.cpp +++ b/gfx/layers/LayersLogging.cpp @@ -159,7 +159,7 @@ AppendToString(std::stringstream& aStream, const FrameMetrics& m, AppendToString(aStream, m.GetRootCompositionSize(), " rcs="); AppendToString(aStream, m.GetViewport(), " v="); aStream << nsPrintfCString(" z=(ld=%.3f r=%.3f cr=%.3f z=%.3f ts=%.3f)", - m.mDevPixelsPerCSSPixel.scale, m.mResolution.scale, + m.mDevPixelsPerCSSPixel.scale, m.mPresShellResolution.scale, m.mCumulativeResolution.scale, m.GetZoom().scale, m.mTransformScale.scale).get(); aStream << nsPrintfCString(" u=(%d %d %lu)", diff --git a/gfx/layers/apz/src/APZCTreeManager.cpp b/gfx/layers/apz/src/APZCTreeManager.cpp index 0184ee30afb7..f1373a67ed3c 100644 --- a/gfx/layers/apz/src/APZCTreeManager.cpp +++ b/gfx/layers/apz/src/APZCTreeManager.cpp @@ -197,12 +197,17 @@ ComputeTouchSensitiveRegion(GeckoContentController* aController, ParentLayerRect visible(aMetrics.mCompositionBounds); CSSRect touchSensitiveRegion; if (aController->GetTouchSensitiveRegion(&touchSensitiveRegion)) { - // Note: we assume here that touchSensitiveRegion is in the CSS pixels - // of our parent layer, which makes this coordinate conversion - // correct. + // Here we assume 'touchSensitiveRegion' is in the CSS pixels of the + // parent frame. To convert it to ParentLayer pixels, we therefore need + // the cumulative resolution of the parent frame. We approximate this as + // the quotient of our cumulative resolution and our pres shell resolution; + // this approximation may not be accurate in the presence of a css-driven + // resolution. + LayoutDeviceToParentLayerScale parentCumulativeResolution = + aMetrics.mCumulativeResolution / aMetrics.mPresShellResolution; visible = visible.Intersect(touchSensitiveRegion * aMetrics.mDevPixelsPerCSSPixel - * aMetrics.GetParentResolution()); + * parentCumulativeResolution); } // Not sure what rounding option is the most correct here, but if we ever diff --git a/gfx/layers/apz/src/AsyncPanZoomController.cpp b/gfx/layers/apz/src/AsyncPanZoomController.cpp index e20a26a1ede1..a8f85334b9e0 100644 --- a/gfx/layers/apz/src/AsyncPanZoomController.cpp +++ b/gfx/layers/apz/src/AsyncPanZoomController.cpp @@ -2588,9 +2588,8 @@ ViewTransform AsyncPanZoomController::GetCurrentAsyncTransform() const { } } - ParentLayerToScreenScale scale = mFrameMetrics.GetZoom() - / mLastContentPaintMetrics.mDevPixelsPerCSSPixel - / mFrameMetrics.GetParentResolution(); + ParentLayerToScreenScale scale = mFrameMetrics.mPresShellResolution // non-transient portion + * mFrameMetrics.GetAsyncZoom(); // transient portion ScreenPoint translation = (currentScrollOffset - lastPaintScrollOffset) * mFrameMetrics.GetZoom(); @@ -2599,24 +2598,27 @@ ViewTransform AsyncPanZoomController::GetCurrentAsyncTransform() const { Matrix4x4 AsyncPanZoomController::GetNontransientAsyncTransform() const { ReentrantMonitorAutoEnter lock(mMonitor); - return Matrix4x4::Scaling(mLastContentPaintMetrics.mResolution.scale, - mLastContentPaintMetrics.mResolution.scale, + return Matrix4x4::Scaling(mLastContentPaintMetrics.mPresShellResolution.scale, + mLastContentPaintMetrics.mPresShellResolution.scale, 1.0f); } Matrix4x4 AsyncPanZoomController::GetTransformToLastDispatchedPaint() const { ReentrantMonitorAutoEnter lock(mMonitor); - // Technically we should be taking the scroll delta in the coordinate space - // of transformed layer pixels (i.e. this layer's LayerPixels, with the layer - // transform applied). However in the absence of actual CSS transforms, we - // can use the parent-layer space instead. - // When we fix bug 993525 and properly support CSS transforms we might have - // to revisit this. ParentLayerPoint scrollChange = (mLastContentPaintMetrics.GetScrollOffset() - mLastDispatchedPaintMetrics.GetScrollOffset()) * mLastContentPaintMetrics.mDevPixelsPerCSSPixel - * mLastContentPaintMetrics.GetParentResolution(); + * mLastContentPaintMetrics.mCumulativeResolution + // This transform ("LD" in the terminology of the comment above + // GetScreenToApzcTransform() in APZCTreeManager.h) is applied in a + // coordinate space that includes the APZC's CSS transform ("LC"). + // This CSS transform is the identity unless this APZC sets a pres-shell + // resolution, in which case the transform has a post-scale that cancels + // out the pres-shell resolution. We simulate applying the "LC" transform + // by dividing by the pres-shell resolution. This will go away once + // bug 1076192 is fixed. + / mLastContentPaintMetrics.mPresShellResolution; float zoomChange = mLastContentPaintMetrics.GetZoom().scale / mLastDispatchedPaintMetrics.GetZoom().scale; @@ -2710,9 +2712,18 @@ void AsyncPanZoomController::NotifyLayersUpdated(const FrameMetrics& aLayerMetri if (FuzzyEqualsAdditive(mFrameMetrics.mCompositionBounds.width, aLayerMetrics.mCompositionBounds.width) && mFrameMetrics.mDevPixelsPerCSSPixel == aLayerMetrics.mDevPixelsPerCSSPixel) { - float parentResolutionChange = aLayerMetrics.GetParentResolution().scale - / mFrameMetrics.GetParentResolution().scale; - mFrameMetrics.ZoomBy(parentResolutionChange); + // Any change to the pres shell resolution was requested by APZ and is + // already included in our zoom; however, other components of the + // cumulative resolution (a parent document's pres-shell resolution, or + // the css-driven resolution) may have changed, and we need to update + // our zoom to reflect that. Note that we can't just take + // aLayerMetrics.mZoom because the APZ may have additional async zoom + // since the repaint request. + float totalResolutionChange = aLayerMetrics.mCumulativeResolution.scale + / mFrameMetrics.mCumulativeResolution.scale; + float presShellResolutionChange = aLayerMetrics.mPresShellResolution.scale + / mFrameMetrics.mPresShellResolution.scale; + mFrameMetrics.ZoomBy(totalResolutionChange / presShellResolutionChange); } else { // Take the new zoom as either device scale or composition width or both // got changed (e.g. due to orientation change). @@ -2725,7 +2736,7 @@ void AsyncPanZoomController::NotifyLayersUpdated(const FrameMetrics& aLayerMetri } mFrameMetrics.mCompositionBounds = aLayerMetrics.mCompositionBounds; mFrameMetrics.SetRootCompositionSize(aLayerMetrics.GetRootCompositionSize()); - mFrameMetrics.mResolution = aLayerMetrics.mResolution; + mFrameMetrics.mPresShellResolution = aLayerMetrics.mPresShellResolution; mFrameMetrics.mCumulativeResolution = aLayerMetrics.mCumulativeResolution; mFrameMetrics.SetHasScrollgrab(aLayerMetrics.GetHasScrollgrab()); diff --git a/gfx/layers/apz/util/APZCCallbackHelper.cpp b/gfx/layers/apz/util/APZCCallbackHelper.cpp index 61a2724101ab..8965caa980b3 100644 --- a/gfx/layers/apz/util/APZCCallbackHelper.cpp +++ b/gfx/layers/apz/util/APZCCallbackHelper.cpp @@ -142,19 +142,12 @@ APZCCallbackHelper::UpdateRootFrame(nsIDOMWindowUtils* aUtils, aMetrics.SetScrollOffset(actualScrollOffset); - // The mZoom variable on the frame metrics stores the CSS-to-screen scale for this - // frame. This scale includes all of the (cumulative) resolutions set on the presShells - // from the root down to this frame. However, when setting the resolution, we only - // want the piece of the resolution that corresponds to this presShell, rather than - // all of the cumulative stuff, so we need to divide out the parent resolutions. - // Finally, we multiply by a ScreenToLayerScale of 1.0f because the goal here is to - // take the async zoom calculated by the APZC and tell gecko about it (turning it into - // a "sync" zoom) which will update the resolution at which the layer is painted. - ParentLayerToLayerScale presShellResolution = - aMetrics.GetZoom() - / aMetrics.mDevPixelsPerCSSPixel - / aMetrics.GetParentResolution() - * ScreenToLayerScale(1.0f); + // The pres shell resolution is updated by the the async zoom since the + // last paint. The ScreenToLayerScale(1.0f) reflects this async zoom being + // turned into a "sync" zoom during the repaint. + ParentLayerToLayerScale presShellResolution = aMetrics.mPresShellResolution + * aMetrics.GetAsyncZoom() + * ScreenToLayerScale(1.0f); aUtils->SetResolution(presShellResolution.scale, presShellResolution.scale); // Finally, we set the displayport. diff --git a/gfx/layers/client/ClientTiledPaintedLayer.cpp b/gfx/layers/client/ClientTiledPaintedLayer.cpp index a4005080ad7f..a2691c459ed5 100644 --- a/gfx/layers/client/ClientTiledPaintedLayer.cpp +++ b/gfx/layers/client/ClientTiledPaintedLayer.cpp @@ -75,7 +75,7 @@ GetTransformToAncestorsParentLayer(Layer* aStart, const LayerMetricsWrapper& aAn // If the layer has a non-transient async transform then we need to apply it here // because it will get applied by the APZ in the compositor as well const FrameMetrics& metrics = iter.Metrics(); - transform.PostScale(metrics.mResolution.scale, metrics.mResolution.scale, 1.f); + transform.PostScale(metrics.mPresShellResolution.scale, metrics.mPresShellResolution.scale, 1.f); } return transform; } @@ -167,7 +167,7 @@ ClientTiledPaintedLayer::BeginPaint() // Store the resolution from the displayport ancestor layer. Because this is Gecko-side, // before any async transforms have occurred, we can use the zoom for this. mPaintData.mResolution = displayportMetrics.GetZoomToParent(); - TILING_LOG("TILING %p: Resolution %f\n", this, mPaintData.mResolution.scale); + TILING_LOG("TILING %p: Resolution %f\n", this, mPaintData.mPresShellResolution.scale); // Store the applicable composition bounds in this layer's Layer units. mPaintData.mTransformToCompBounds = diff --git a/gfx/layers/client/TiledContentClient.cpp b/gfx/layers/client/TiledContentClient.cpp index 90fce04e66e5..fb165b30b942 100644 --- a/gfx/layers/client/TiledContentClient.cpp +++ b/gfx/layers/client/TiledContentClient.cpp @@ -150,9 +150,8 @@ ComputeViewTransform(const FrameMetrics& aContentMetrics, const FrameMetrics& aC // but with aContentMetrics used in place of mLastContentPaintMetrics, because they // should be equivalent, modulo race conditions while transactions are inflight. - ParentLayerToScreenScale scale = aCompositorMetrics.GetZoom() - / aContentMetrics.mDevPixelsPerCSSPixel - / aCompositorMetrics.GetParentResolution(); + ParentLayerToScreenScale scale = aCompositorMetrics.mPresShellResolution + * aCompositorMetrics.GetAsyncZoom(); ScreenPoint translation = (aCompositorMetrics.GetScrollOffset() - aContentMetrics.GetScrollOffset()) * aCompositorMetrics.GetZoom(); return ViewTransform(scale, -translation); @@ -1311,7 +1310,7 @@ ClientTiledLayerBuffer::ValidateTile(TileClient aTile, #ifdef GFX_TILEDLAYER_DEBUG_OVERLAY DrawDebugOverlay(drawTarget, aTileOrigin.x * mResolution, - aTileOrigin.y * mResolution, GetTileLength(), GetTileLength()); + aTileOrigin.y * mPresShellResolution, GetTileLength(), GetTileLength()); #endif ctxt = nullptr; @@ -1367,8 +1366,8 @@ GetCompositorSideCompositionBounds(const LayerMetricsWrapper& aScrollAncestor, const ViewTransform& aAPZTransform) { Matrix4x4 nonTransientAPZUntransform = Matrix4x4::Scaling( - aScrollAncestor.Metrics().mResolution.scale, - aScrollAncestor.Metrics().mResolution.scale, + aScrollAncestor.Metrics().mPresShellResolution.scale, + aScrollAncestor.Metrics().mPresShellResolution.scale, 1.f); nonTransientAPZUntransform.Invert(); diff --git a/gfx/layers/composite/AsyncCompositionManager.cpp b/gfx/layers/composite/AsyncCompositionManager.cpp index 22bf15c8c466..f19aded3e80c 100644 --- a/gfx/layers/composite/AsyncCompositionManager.cpp +++ b/gfx/layers/composite/AsyncCompositionManager.cpp @@ -718,7 +718,7 @@ ApplyAsyncTransformToScrollbarForContent(Layer* aScrollbar, // aScrollbarIsDescendant hunk below we unapply the entire async // transform, which includes the nontransientasync transform and would // normally account for the resolution. - scale *= metrics.mResolution.scale; + scale *= metrics.mPresShellResolution.scale; } scrollbarTransform.PostScale(1.f, 1.f / transientTransform._22, 1.f); scrollbarTransform.PostTranslate(0, -transientTransform._42 * scale, 0); @@ -726,7 +726,7 @@ ApplyAsyncTransformToScrollbarForContent(Layer* aScrollbar, if (aScrollbar->GetScrollbarDirection() == Layer::HORIZONTAL) { float scale = metrics.CalculateCompositedSizeInCssPixels().width / metrics.mScrollableRect.width; if (aScrollbarIsDescendant) { - scale *= metrics.mResolution.scale; + scale *= metrics.mPresShellResolution.scale; } scrollbarTransform.PostScale(1.f / transientTransform._11, 1.f, 1.f); scrollbarTransform.PostTranslate(-transientTransform._41 * scale, 0, 0); @@ -888,9 +888,10 @@ AsyncCompositionManager::TransformScrollableLayer(Layer* aLayer) if (metrics.IsScrollable()) { geckoScroll = metrics.GetScrollOffset() * userZoom; } - ParentLayerToScreenScale scale = userZoom - / metrics.mDevPixelsPerCSSPixel - / metrics.GetParentResolution(); + + LayerToScreenScale asyncZoom = userZoom / metrics.LayersPixelsPerCSSPixel(); + ParentLayerToScreenScale scale = metrics.mPresShellResolution + * asyncZoom; ScreenPoint translation = userScroll - geckoScroll; Matrix4x4 treeTransform = ViewTransform(scale, -translation); @@ -900,7 +901,7 @@ AsyncCompositionManager::TransformScrollableLayer(Layer* aLayer) // Apply resolution scaling to the old transform - the layer tree as it is // doesn't have the necessary transform to display correctly. - oldTransform.PreScale(metrics.mResolution.scale, metrics.mResolution.scale, 1); + oldTransform.PreScale(metrics.mPresShellResolution.scale, metrics.mPresShellResolution.scale, 1); // Make sure that overscroll and under-zoom are represented in the old // transform so that fixed position content moves and scales accordingly. diff --git a/gfx/layers/composite/LayerManagerComposite.cpp b/gfx/layers/composite/LayerManagerComposite.cpp index b8622aae064b..dd6c9455160d 100644 --- a/gfx/layers/composite/LayerManagerComposite.cpp +++ b/gfx/layers/composite/LayerManagerComposite.cpp @@ -907,7 +907,7 @@ LayerManagerComposite::ComputeRenderIntegrity() Layer* rootScrollable = rootScrollableLayers[0]; const FrameMetrics& metrics = LayerMetricsWrapper::TopmostScrollableMetrics(rootScrollable); Matrix4x4 transform = rootScrollable->GetEffectiveTransform(); - transform.PostScale(metrics.mResolution.scale, metrics.mResolution.scale, 1); + transform.PostScale(metrics.mPresShellResolution, metrics.mPresShellResolution, 1); // Clip the screen rect to the document bounds Rect documentBounds = diff --git a/gfx/tests/gtest/TestAsyncPanZoomController.cpp b/gfx/tests/gtest/TestAsyncPanZoomController.cpp index 5a4de3027f5a..d47cd48ff914 100644 --- a/gfx/tests/gtest/TestAsyncPanZoomController.cpp +++ b/gfx/tests/gtest/TestAsyncPanZoomController.cpp @@ -778,7 +778,7 @@ TEST_F(APZCBasicTester, ComplexTransform) { metrics.SetScrollOffset(CSSPoint(10, 10)); metrics.mScrollableRect = CSSRect(0, 0, 50, 50); metrics.mCumulativeResolution = LayoutDeviceToLayerScale(2); - metrics.mResolution = ParentLayerToLayerScale(2); + metrics.mPresShellResolution = ParentLayerToLayerScale(2); metrics.SetZoom(CSSToScreenScale(6)); metrics.mDevPixelsPerCSSPixel = CSSToLayoutDeviceScale(3); metrics.SetScrollId(FrameMetrics::START_SCROLL_ID); diff --git a/layout/base/nsDisplayList.cpp b/layout/base/nsDisplayList.cpp index 3045f2c6c9d6..a0f2b71bdec4 100644 --- a/layout/base/nsDisplayList.cpp +++ b/layout/base/nsDisplayList.cpp @@ -724,10 +724,10 @@ nsDisplayScrollLayer::ComputeFrameMetrics(nsIFrame* aForFrame, // Only the root scrollable frame for a given presShell should pick up // the presShell's resolution. All the other frames are 1.0. if (aScrollFrame == presShell->GetRootScrollFrame()) { - metrics.mResolution = ParentLayerToLayerScale(presShell->GetXResolution(), + metrics.mPresShellResolution = ParentLayerToLayerScale(presShell->GetXResolution(), presShell->GetYResolution()); } else { - metrics.mResolution = ParentLayerToLayerScale(1.0f); + metrics.mPresShellResolution = ParentLayerToLayerScale(1.0f); } // The cumulative resolution is the resolution at which the scroll frame's // content is actually rendered. It includes the pres shell resolutions of diff --git a/layout/base/nsLayoutUtils.cpp b/layout/base/nsLayoutUtils.cpp index 09cf4e1cb079..0703995a8d68 100644 --- a/layout/base/nsLayoutUtils.cpp +++ b/layout/base/nsLayoutUtils.cpp @@ -2802,7 +2802,7 @@ CalculateFrameMetricsForDisplayPort(nsIFrame* aScrollFrame, * nsLayoutUtils::GetTransformToAncestorScale(aScrollFrame).width); metrics.mDevPixelsPerCSSPixel = deviceScale; - metrics.mResolution = resolution; + metrics.mPresShellResolution = resolution; metrics.mCumulativeResolution = cumulativeResolution; metrics.SetZoom(deviceScale * cumulativeResolution * LayerToScreenScale(1)); From 979a83daada2a7ddb0d862fedc7ede2a6285ebc4 Mon Sep 17 00:00:00 2001 From: Anthony Jones Date: Thu, 13 Nov 2014 18:34:37 +1300 Subject: [PATCH 18/80] Bug 1097436 - Enable MSE support for MP4 on Windows and disable WebM; r=cajbir --- modules/libpref/init/all.js | 5 +++++ testing/profiles/prefs_general.js | 2 ++ 2 files changed, 7 insertions(+) diff --git a/modules/libpref/init/all.js b/modules/libpref/init/all.js index 050fb925d68b..e160d8c5f4be 100644 --- a/modules/libpref/init/all.js +++ b/modules/libpref/init/all.js @@ -424,9 +424,14 @@ pref("media.mediasource.enabled", true); pref("media.mediasource.mp4.enabled", false); pref("media.mediasource.webm.enabled", false); #else +#ifdef XP_WIN +pref("media.mediasource.mp4.enabled", true); +pref("media.mediasource.webm.enabled", false); +#else pref("media.mediasource.mp4.enabled", false); pref("media.mediasource.webm.enabled", true); #endif +#endif #ifdef MOZ_WEBSPEECH pref("media.webspeech.recognition.enable", false); diff --git a/testing/profiles/prefs_general.js b/testing/profiles/prefs_general.js index 8197a91880bc..bbe0af888ff5 100644 --- a/testing/profiles/prefs_general.js +++ b/testing/profiles/prefs_general.js @@ -156,6 +156,8 @@ user_pref("layout.spammy_warnings.enabled", false); // Enable Media Source Extensions for testing user_pref("media.mediasource.enabled", true); +user_pref("media.mediasource.mp4.enabled", false); +user_pref("media.mediasource.webm.enabled", true); // Enable mozContacts user_pref("dom.mozContacts.enabled", true); From d766d4ca148ce93ada35422c8ce2e0742fec6b0b Mon Sep 17 00:00:00 2001 From: Botond Ballo Date: Mon, 10 Nov 2014 14:35:11 -0500 Subject: [PATCH 19/80] Bug 1055741 - Unify the 'local Screen' and 'ParentLayer' coordinate systems. r=kats --HG-- extra : rebase_source : af7323668fb54079e121755660da2121bec3d76b --- dom/ipc/TabChild.cpp | 50 ++-- gfx/ipc/GfxMessageUtils.h | 2 - gfx/layers/FrameMetrics.h | 78 ++---- gfx/layers/LayersLogging.cpp | 6 +- gfx/layers/apz/src/APZCTreeManager.cpp | 150 +++++------ gfx/layers/apz/src/APZCTreeManager.h | 8 +- gfx/layers/apz/src/AsyncPanZoomController.cpp | 254 ++++++++---------- gfx/layers/apz/src/AsyncPanZoomController.h | 72 +++-- gfx/layers/apz/src/Axis.cpp | 96 +++---- gfx/layers/apz/src/Axis.h | 74 ++--- gfx/layers/apz/src/GestureEventListener.cpp | 77 +++--- gfx/layers/apz/src/GestureEventListener.h | 4 +- gfx/layers/apz/util/APZCCallbackHelper.cpp | 10 +- gfx/layers/client/ClientLayerManager.cpp | 4 +- gfx/layers/client/ClientTiledPaintedLayer.cpp | 14 +- gfx/layers/client/TiledContentClient.cpp | 12 +- .../composite/AsyncCompositionManager.cpp | 30 +-- .../composite/AsyncCompositionManager.h | 14 +- .../gtest/TestAsyncPanZoomController.cpp | 167 +++++++----- layout/base/UnitTransforms.h | 30 ++- layout/base/Units.h | 35 ++- layout/base/nsDisplayList.cpp | 17 +- layout/base/nsLayoutUtils.cpp | 14 +- widget/InputData.h | 72 ++++- widget/android/AndroidBridge.cpp | 8 +- widget/android/AndroidBridge.h | 6 +- widget/windows/winrt/APZController.cpp | 4 +- 27 files changed, 669 insertions(+), 639 deletions(-) diff --git a/dom/ipc/TabChild.cpp b/dom/ipc/TabChild.cpp index 07ac0b840bf6..504bdb0554e9 100644 --- a/dom/ipc/TabChild.cpp +++ b/dom/ipc/TabChild.cpp @@ -241,16 +241,16 @@ TabChildBase::InitializeRootMetrics() mLastRootMetrics.SetViewport(CSSRect(CSSPoint(), kDefaultViewportSize)); mLastRootMetrics.mCompositionBounds = ParentLayerRect( ParentLayerPoint(), - ParentLayerSize(ViewAs(mInnerSize, PixelCastJustification::ScreenToParentLayerForRoot))); + ParentLayerSize(ViewAs(mInnerSize, PixelCastJustification::ScreenIsParentLayerForRoot))); mLastRootMetrics.SetZoom(mLastRootMetrics.CalculateIntrinsicScale()); mLastRootMetrics.mDevPixelsPerCSSPixel = WebWidget()->GetDefaultScale(); - // We use ScreenToLayerScale(1) below in order to turn the + // We use ParentLayerToLayerScale(1) below in order to turn the // async zoom amount into the gecko zoom amount. mLastRootMetrics.mCumulativeResolution = - mLastRootMetrics.GetZoom() / mLastRootMetrics.mDevPixelsPerCSSPixel * ScreenToLayerScale(1); + mLastRootMetrics.GetZoom() / mLastRootMetrics.mDevPixelsPerCSSPixel * ParentLayerToLayerScale(1); // This is the root layer, so the cumulative resolution is the same // as the resolution. - mLastRootMetrics.mPresShellResolution = mLastRootMetrics.mCumulativeResolution / LayoutDeviceToParentLayerScale(1); + mLastRootMetrics.mPresShellResolution = mLastRootMetrics.mCumulativeResolution.scale; mLastRootMetrics.SetScrollOffset(CSSPoint(0, 0)); TABC_LOG("After InitializeRootMetrics, mLastRootMetrics is %s\n", @@ -294,6 +294,20 @@ TabChildBase::GetPageSize(nsCOMPtr aDocument, const CSSSize& aViewp std::max(htmlHeight, bodyHeight)); } +// For the root frame, Screen and ParentLayer pixels are interchangeable. +// nsViewportInfo stores zoom values as CSSToScreenScale (because it's a +// data structure specific to the root frame), while FrameMetrics and +// ZoomConstraints store zoom values as CSSToParentLayerScale (because they +// are not specific to the root frame). We define convenience functions for +// converting between the two. As the name suggests, they should only be used +// when dealing with the root frame! +CSSToScreenScale ConvertScaleForRoot(CSSToParentLayerScale aScale) { + return ViewTargetAs(aScale, PixelCastJustification::ScreenIsParentLayerForRoot); +} +CSSToParentLayerScale ConvertScaleForRoot(CSSToScreenScale aScale) { + return ViewTargetAs(aScale, PixelCastJustification::ScreenIsParentLayerForRoot); +} + bool TabChildBase::HandlePossibleViewportChange(const ScreenIntSize& aOldScreenSize) { @@ -316,8 +330,8 @@ TabChildBase::HandlePossibleViewportChange(const ScreenIntSize& aOldScreenSize) ZoomConstraints constraints( viewportInfo.IsZoomAllowed(), viewportInfo.IsDoubleTapZoomAllowed(), - viewportInfo.GetMinZoom(), - viewportInfo.GetMaxZoom()); + ConvertScaleForRoot(viewportInfo.GetMinZoom()), + ConvertScaleForRoot(viewportInfo.GetMaxZoom())); DoUpdateZoomConstraints(presShellId, viewId, /* isRoot = */ true, @@ -366,7 +380,7 @@ TabChildBase::HandlePossibleViewportChange(const ScreenIntSize& aOldScreenSize) metrics.SetViewport(CSSRect(CSSPoint(), viewport)); metrics.mCompositionBounds = ParentLayerRect( ParentLayerPoint(), - ParentLayerSize(ViewAs(mInnerSize, PixelCastJustification::ScreenToParentLayerForRoot))); + ParentLayerSize(ViewAs(mInnerSize, PixelCastJustification::ScreenIsParentLayerForRoot))); metrics.SetRootCompositionSize( ScreenSize(mInnerSize) * ScreenToLayoutDeviceScale(1.0f) / metrics.mDevPixelsPerCSSPixel); @@ -396,13 +410,13 @@ TabChildBase::HandlePossibleViewportChange(const ScreenIntSize& aOldScreenSize) // 0.0 to mean "did not calculate a zoom". In that case, we default // it to the intrinsic scale. if (viewportInfo.GetDefaultZoom().scale < 0.01f) { - viewportInfo.SetDefaultZoom(metrics.CalculateIntrinsicScale()); + viewportInfo.SetDefaultZoom(ConvertScaleForRoot(metrics.CalculateIntrinsicScale())); } CSSToScreenScale defaultZoom = viewportInfo.GetDefaultZoom(); MOZ_ASSERT(viewportInfo.GetMinZoom() <= defaultZoom && defaultZoom <= viewportInfo.GetMaxZoom()); - metrics.SetZoom(defaultZoom); + metrics.SetZoom(ConvertScaleForRoot(defaultZoom)); metrics.SetScrollId(viewId); } @@ -414,11 +428,13 @@ TabChildBase::HandlePossibleViewportChange(const ScreenIntSize& aOldScreenSize) } } - metrics.mCumulativeResolution = metrics.GetZoom() / metrics.mDevPixelsPerCSSPixel * ScreenToLayerScale(1); + metrics.mCumulativeResolution = metrics.GetZoom() + / metrics.mDevPixelsPerCSSPixel + * ParentLayerToLayerScale(1); // This is the root layer, so the cumulative resolution is the same // as the resolution. - metrics.mPresShellResolution = metrics.mCumulativeResolution / LayoutDeviceToParentLayerScale(1); - utils->SetResolution(metrics.mPresShellResolution.scale, metrics.mPresShellResolution.scale); + metrics.mPresShellResolution = metrics.mCumulativeResolution.scale; + utils->SetResolution(metrics.mPresShellResolution, metrics.mPresShellResolution); CSSSize scrollPort = metrics.CalculateCompositedSizeInCssPixels(); utils->SetScrollPositionClampingScrollPortSize(scrollPort.width, scrollPort.height); @@ -440,7 +456,7 @@ TabChildBase::HandlePossibleViewportChange(const ScreenIntSize& aOldScreenSize) // The page must have been refreshed in some way such as a new document or // new CSS viewport, so we know that there's no velocity, acceleration, and // we have no idea how long painting will take. - metrics, ScreenPoint(0.0f, 0.0f), 0.0)); + metrics, ParentLayerPoint(0.0f, 0.0f), 0.0)); metrics.SetUseDisplayPortMargins(); // Force a repaint with these metrics. This, among other things, sets the @@ -457,8 +473,8 @@ TabChildBase::HandlePossibleViewportChange(const ScreenIntSize& aOldScreenSize) ZoomConstraints constraints( viewportInfo.IsZoomAllowed(), viewportInfo.IsDoubleTapZoomAllowed(), - viewportInfo.GetMinZoom(), - viewportInfo.GetMaxZoom()); + ConvertScaleForRoot(viewportInfo.GetMinZoom()), + ConvertScaleForRoot(viewportInfo.GetMaxZoom())); DoUpdateZoomConstraints(presShellId, viewId, /* isRoot = */ true, @@ -907,8 +923,8 @@ TabChild::Observe(nsISupports *aSubject, // until we we get an inner size. if (HasValidInnerSize()) { InitializeRootMetrics(); - utils->SetResolution(mLastRootMetrics.mPresShellResolution.scale, - mLastRootMetrics.mPresShellResolution.scale); + utils->SetResolution(mLastRootMetrics.mPresShellResolution, + mLastRootMetrics.mPresShellResolution); HandlePossibleViewportChange(mInnerSize); } } diff --git a/gfx/ipc/GfxMessageUtils.h b/gfx/ipc/GfxMessageUtils.h index b62c2a57839e..861252754ae5 100644 --- a/gfx/ipc/GfxMessageUtils.h +++ b/gfx/ipc/GfxMessageUtils.h @@ -752,7 +752,6 @@ struct ParamTraits WriteParam(aMsg, aParam.mHasScrollgrab); WriteParam(aMsg, aParam.mUpdateScrollOffset); WriteParam(aMsg, aParam.mScrollGeneration); - WriteParam(aMsg, aParam.mTransformScale); WriteParam(aMsg, aParam.mExtraResolution); WriteParam(aMsg, aParam.mBackgroundColor); WriteParam(aMsg, aParam.mDoSmoothScroll); @@ -794,7 +793,6 @@ struct ParamTraits ReadParam(aMsg, aIter, &aResult->mHasScrollgrab) && ReadParam(aMsg, aIter, &aResult->mUpdateScrollOffset) && ReadParam(aMsg, aIter, &aResult->mScrollGeneration) && - ReadParam(aMsg, aIter, &aResult->mTransformScale) && ReadParam(aMsg, aIter, &aResult->mExtraResolution) && ReadParam(aMsg, aIter, &aResult->mBackgroundColor) && ReadParam(aMsg, aIter, &aResult->mDoSmoothScroll) && diff --git a/gfx/layers/FrameMetrics.h b/gfx/layers/FrameMetrics.h index 02bedfbaeb71..81fb646035fa 100644 --- a/gfx/layers/FrameMetrics.h +++ b/gfx/layers/FrameMetrics.h @@ -21,38 +21,6 @@ template struct ParamTraits; namespace mozilla { -// The layer coordinates of the parent layer. -// This can be arrived at in two ways: -// - Start with the CSS coordinates of the parent layer (note: NOT the -// CSS coordinates of the current layer, that will give you the wrong -// answer), multiply by the device scale and the resolutions of all -// layers from the root down to and including the parent. -// - Start with global screen coordinates and unapply all CSS and async -// transforms from the root down to and including the parent. -// It's helpful to look at https://wiki.mozilla.org/Platform/GFX/APZ#Coordinate_systems -// to get a picture of how the various coordinate systems relate to each other. -struct ParentLayerPixel {}; - -template<> struct IsPixel : TrueType {}; - -typedef gfx::MarginTyped ParentLayerMargin; -typedef gfx::PointTyped ParentLayerPoint; -typedef gfx::RectTyped ParentLayerRect; -typedef gfx::SizeTyped ParentLayerSize; - -typedef gfx::IntMarginTyped ParentLayerIntMargin; -typedef gfx::IntPointTyped ParentLayerIntPoint; -typedef gfx::IntRectTyped ParentLayerIntRect; -typedef gfx::IntSizeTyped ParentLayerIntSize; - -typedef gfx::ScaleFactor CSSToParentLayerScale; -typedef gfx::ScaleFactor LayoutDeviceToParentLayerScale; -typedef gfx::ScaleFactor ScreenToParentLayerScale; - -typedef gfx::ScaleFactor ParentLayerToLayerScale; -typedef gfx::ScaleFactor ParentLayerToScreenScale; - - namespace layers { /** @@ -78,7 +46,6 @@ public: , mScrollableRect(0, 0, 0, 0) , mPresShellResolution(1) , mCumulativeResolution(1) - , mTransformScale(1) , mDevPixelsPerCSSPixel(1) , mMayHaveTouchListeners(false) , mMayHaveTouchCaret(false) @@ -156,14 +123,14 @@ public: CSSToScreenScale DisplayportPixelsPerCSSPixel() const { - // Note: use 'mZoom * ScreenToLayerScale(1.0f)' as the CSS-to-Layer scale + // Note: use 'mZoom * ParentLayerToLayerScale(1.0f)' as the CSS-to-Layer scale // instead of LayersPixelsPerCSSPixel(), because displayport calculations // are done in the context of a repaint request, where we ask Layout to // repaint at a new resolution that includes any async zoom. Until this // repaint request is processed, LayersPixelsPerCSSPixel() does not yet // include the async zoom, but it will when the displayport is interpreted // for the repaint. - return mZoom * ScreenToLayerScale(1.0f) / mExtraResolution; + return mZoom * ParentLayerToLayerScale(1.0f) / mExtraResolution; } CSSToLayerScale LayersPixelsPerCSSPixel() const @@ -172,7 +139,7 @@ public: } // Get the amount by which this frame has been zoomed since the last repaint. - LayerToScreenScale GetAsyncZoom() const + LayerToParentLayerScale GetAsyncZoom() const { return mZoom / LayersPixelsPerCSSPixel(); } @@ -204,31 +171,21 @@ public: // Return the scale factor needed to fit the viewport // into its composition bounds. - CSSToScreenScale CalculateIntrinsicScale() const + CSSToParentLayerScale CalculateIntrinsicScale() const { - return CSSToScreenScale( + return CSSToParentLayerScale( std::max(mCompositionBounds.width / mViewport.width, mCompositionBounds.height / mViewport.height)); } - // Return the scale factor for converting from CSS pixels (for this layer) - // to layer pixels of our parent layer. Much as mZoom is used to interface - // between inputs we get in screen pixels and quantities in CSS pixels, - // this is used to interface between mCompositionBounds and quantities - // in CSS pixels. - CSSToParentLayerScale GetZoomToParent() const - { - return mZoom * mTransformScale; - } - CSSSize CalculateCompositedSizeInCssPixels() const { - return mCompositionBounds.Size() / GetZoomToParent(); + return mCompositionBounds.Size() / GetZoom(); } CSSRect CalculateCompositedRectInCssPixels() const { - return mCompositionBounds / GetZoomToParent(); + return mCompositionBounds / GetZoom(); } CSSSize CalculateBoundedCompositedSizeInCssPixels() const @@ -344,7 +301,9 @@ public: // user action, or choosing an initial zoom level on page load). This can // only be different from 1.0 for frames that are zoomable, which currently // is just the root content document's root scroll frame (mIsRoot = true). - ParentLayerToLayerScale mPresShellResolution; + // This is a plain float rather than a ScaleFactor because in and of itself + // it does not convert between any coordinate spaces for which we have names. + float mPresShellResolution; // The cumulative resolution that the current frame has been painted at. // This is the product of the pres-shell resolutions of the document @@ -352,9 +311,6 @@ public: // resolution. This information is provided by Gecko at layout/paint time. LayoutDeviceToLayerScale mCumulativeResolution; - // TODO(botond): This is now always 1 and should be removed (see bug 1055741). - ScreenToParentLayerScale mTransformScale; - // The conversion factor between CSS pixels and device pixels for this frame. // This can vary based on a variety of things, such as reflowing-zoom. The // conversion factor for device pixels to layers pixels is just the @@ -402,12 +358,12 @@ public: return mSmoothScrollOffset; } - void SetZoom(const CSSToScreenScale& aZoom) + void SetZoom(const CSSToParentLayerScale& aZoom) { mZoom = aZoom; } - CSSToScreenScale GetZoom() const + CSSToParentLayerScale GetZoom() const { return mZoom; } @@ -602,7 +558,7 @@ private: // but will be drawn to the screen at mZoom. In the steady state, the // two will be the same, but during an async zoom action the two may // diverge. This information is initialized in Gecko but updated in the APZC. - CSSToScreenScale mZoom; + CSSToParentLayerScale mZoom; // Whether mScrollOffset was updated by something other than the APZ code, and // if the APZC receiving this metrics should update its local copy. @@ -740,8 +696,8 @@ gfx::Log& operator<<(gfx::Log& log, const ScrollableLayerGui struct ZoomConstraints { bool mAllowZoom; bool mAllowDoubleTapZoom; - CSSToScreenScale mMinZoom; - CSSToScreenScale mMaxZoom; + CSSToParentLayerScale mMinZoom; + CSSToParentLayerScale mMaxZoom; ZoomConstraints() : mAllowZoom(true) @@ -752,8 +708,8 @@ struct ZoomConstraints { ZoomConstraints(bool aAllowZoom, bool aAllowDoubleTapZoom, - const CSSToScreenScale& aMinZoom, - const CSSToScreenScale& aMaxZoom) + const CSSToParentLayerScale& aMinZoom, + const CSSToParentLayerScale& aMaxZoom) : mAllowZoom(aAllowZoom) , mAllowDoubleTapZoom(aAllowDoubleTapZoom) , mMinZoom(aMinZoom) diff --git a/gfx/layers/LayersLogging.cpp b/gfx/layers/LayersLogging.cpp index 37708bf26d05..321ee54af98f 100644 --- a/gfx/layers/LayersLogging.cpp +++ b/gfx/layers/LayersLogging.cpp @@ -158,10 +158,10 @@ AppendToString(std::stringstream& aStream, const FrameMetrics& m, aStream << nsPrintfCString(" um=%d", m.GetUseDisplayPortMargins()).get(); AppendToString(aStream, m.GetRootCompositionSize(), " rcs="); AppendToString(aStream, m.GetViewport(), " v="); - aStream << nsPrintfCString(" z=(ld=%.3f r=%.3f cr=%.3f z=%.3f ts=%.3f)", - m.mDevPixelsPerCSSPixel.scale, m.mPresShellResolution.scale, + aStream << nsPrintfCString(" z=(ld=%.3f r=%.3f cr=%.3f z=%.3f er=%.3f)", + m.mDevPixelsPerCSSPixel.scale, m.mPresShellResolution, m.mCumulativeResolution.scale, m.GetZoom().scale, - m.mTransformScale.scale).get(); + m.GetExtraResolution().scale).get(); aStream << nsPrintfCString(" u=(%d %d %lu)", m.GetScrollOffsetUpdated(), m.GetDoSmoothScroll(), m.GetScrollGeneration()).get(); diff --git a/gfx/layers/apz/src/APZCTreeManager.cpp b/gfx/layers/apz/src/APZCTreeManager.cpp index f1373a67ed3c..da4b06f25dcd 100644 --- a/gfx/layers/apz/src/APZCTreeManager.cpp +++ b/gfx/layers/apz/src/APZCTreeManager.cpp @@ -64,7 +64,7 @@ struct APZCTreeManager::TreeBuildingState { /*static*/ const ScreenMargin APZCTreeManager::CalculatePendingDisplayPort( const FrameMetrics& aFrameMetrics, - const ScreenPoint& aVelocity, + const ParentLayerPoint& aVelocity, double aEstimatedPaintDuration) { return AsyncPanZoomController::CalculatePendingDisplayPort( @@ -204,7 +204,8 @@ ComputeTouchSensitiveRegion(GeckoContentController* aController, // this approximation may not be accurate in the presence of a css-driven // resolution. LayoutDeviceToParentLayerScale parentCumulativeResolution = - aMetrics.mCumulativeResolution / aMetrics.mPresShellResolution; + aMetrics.mCumulativeResolution + / ParentLayerToLayerScale(aMetrics.mPresShellResolution); visible = visible.Intersect(touchSensitiveRegion * aMetrics.mDevPixelsPerCSSPixel * parentCumulativeResolution); @@ -489,36 +490,6 @@ APZCTreeManager::UpdatePanZoomControllerTree(TreeBuildingState& aState, return aNextSibling; } -/*static*/ template void -ApplyTransform(gfx::PointTyped* aPoint, const Matrix4x4& aMatrix) -{ - Point result = aMatrix * aPoint->ToUnknownPoint(); - *aPoint = ViewAs(result); -} - -/*static*/ template void -ApplyTransform(gfx::IntPointTyped* aPoint, const Matrix4x4& aMatrix) -{ - Point result = aMatrix * aPoint->ToUnknownPoint(); - *aPoint = TruncatedToInt(ViewAs(result)); -} - -/*static*/ void -ApplyTransform(nsIntPoint* aPoint, const Matrix4x4& aMatrix) -{ - Point result = aMatrix * Point(aPoint->x, aPoint->y); - aPoint->x = NS_lround(result.x); - aPoint->y = NS_lround(result.y); -} - -/*static*/ template void -TransformScreenToGecko(T* aPoint, AsyncPanZoomController* aApzc, APZCTreeManager* aApzcTm) -{ - Matrix4x4 transformToApzc = aApzcTm->GetScreenToApzcTransform(aApzc); - Matrix4x4 transformToGecko = aApzcTm->GetApzcToGeckoTransform(aApzc); - ApplyTransform(aPoint, transformToApzc * transformToGecko); -} - nsEventStatus APZCTreeManager::ReceiveInputEvent(InputData& aEvent, ScrollableLayerGuid* aOutTargetGuid, @@ -542,53 +513,53 @@ APZCTreeManager::ReceiveInputEvent(InputData& aEvent, nsRefPtr apzc = GetTargetAPZC(panInput.mPanStartPoint, &inOverscrolledApzc); if (apzc) { - // When passing the event to the APZC, we need to apply a different - // transform than the one in TransformScreenToGecko, so we need to - // make a copy of the event. - PanGestureInput inputForApzc(panInput); transformToApzc = GetScreenToApzcTransform(apzc); - ApplyTransform(&(inputForApzc.mPanStartPoint), transformToApzc); - result = mInputQueue->ReceiveInputEvent(apzc, inputForApzc, aOutInputBlockId); + panInput.mLocalPanStartPoint = TransformTo( + transformToApzc, panInput.mPanStartPoint); + panInput.mLocalPanDisplacement = TransformVector( + transformToApzc, panInput.mPanDisplacement, panInput.mPanStartPoint); + result = mInputQueue->ReceiveInputEvent(apzc, panInput, aOutInputBlockId); // Update the out-parameters so they are what the caller expects. apzc->GetGuid(aOutTargetGuid); - TransformScreenToGecko(&(panInput.mPanStartPoint), apzc, this); + Matrix4x4 transformToGecko = transformToApzc * GetApzcToGeckoTransform(apzc); + panInput.mPanStartPoint = TransformTo( + transformToGecko, panInput.mPanStartPoint); + panInput.mPanDisplacement = TransformVector( + transformToGecko, panInput.mPanDisplacement, panInput.mPanStartPoint); } break; - } case PINCHGESTURE_INPUT: { + } case PINCHGESTURE_INPUT: { // note: no one currently sends these PinchGestureInput& pinchInput = aEvent.AsPinchGestureInput(); nsRefPtr apzc = GetTargetAPZC(pinchInput.mFocusPoint, &inOverscrolledApzc); if (apzc) { - // When passing the event to the APZC, we need to apply a different - // transform than the one in TransformScreenToGecko, so we need to - // make a copy of the event. - PinchGestureInput inputForApzc(pinchInput); transformToApzc = GetScreenToApzcTransform(apzc); - ApplyTransform(&(inputForApzc.mFocusPoint), transformToApzc); - result = mInputQueue->ReceiveInputEvent(apzc, inputForApzc, aOutInputBlockId); + pinchInput.mLocalFocusPoint = TransformTo( + transformToApzc, pinchInput.mFocusPoint); + result = mInputQueue->ReceiveInputEvent(apzc, pinchInput, aOutInputBlockId); // Update the out-parameters so they are what the caller expects. apzc->GetGuid(aOutTargetGuid); - TransformScreenToGecko(&(pinchInput.mFocusPoint), apzc, this); + Matrix4x4 outTransform = transformToApzc * GetApzcToGeckoTransform(apzc); + pinchInput.mFocusPoint = TransformTo( + outTransform, pinchInput.mFocusPoint); } break; - } case TAPGESTURE_INPUT: { + } case TAPGESTURE_INPUT: { // note: no one currently sends these TapGestureInput& tapInput = aEvent.AsTapGestureInput(); - nsRefPtr apzc = GetTargetAPZC(ScreenPoint(tapInput.mPoint), + nsRefPtr apzc = GetTargetAPZC(tapInput.mPoint, &inOverscrolledApzc); if (apzc) { - // When passing the event to the APZC, we need to apply a different - // transform than the one in TransformScreenToGecko, so we need to - // make a copy of the event. - TapGestureInput inputForApzc(tapInput); transformToApzc = GetScreenToApzcTransform(apzc); - ApplyTransform(&(inputForApzc.mPoint), transformToApzc); - result = mInputQueue->ReceiveInputEvent(apzc, inputForApzc, aOutInputBlockId); + tapInput.mLocalPoint = TransformTo( + transformToApzc, tapInput.mPoint); + result = mInputQueue->ReceiveInputEvent(apzc, tapInput, aOutInputBlockId); // Update the out-parameters so they are what the caller expects. apzc->GetGuid(aOutTargetGuid); - TransformScreenToGecko(&(tapInput.mPoint), apzc, this); + Matrix4x4 outTransform = transformToApzc * GetApzcToGeckoTransform(apzc); + tapInput.mPoint = TransformTo(outTransform, tapInput.mPoint); } break; } @@ -709,11 +680,12 @@ APZCTreeManager::ProcessTouchInput(MultiTouchInput& aInput, // This ensures that the sequence of touch points an APZC sees in an // input block are all in the same coordinate space. Matrix4x4 transformToApzc = mCachedTransformToApzcForInputBlock; - MultiTouchInput inputForApzc(aInput); - for (size_t i = 0; i < inputForApzc.mTouches.Length(); i++) { - ApplyTransform(&(inputForApzc.mTouches[i].mScreenPoint), transformToApzc); + for (size_t i = 0; i < aInput.mTouches.Length(); i++) { + SingleTouchData& touchData = aInput.mTouches[i]; + touchData.mLocalScreenPoint = TransformTo( + transformToApzc, ScreenPoint(touchData.mScreenPoint)); } - result = mInputQueue->ReceiveInputEvent(mApzcForInputBlock, inputForApzc, aOutInputBlockId); + result = mInputQueue->ReceiveInputEvent(mApzcForInputBlock, aInput, aOutInputBlockId); // For computing the event to pass back to Gecko, use the up-to-date transforms. // This ensures that transformToApzc and transformToGecko are in sync @@ -722,7 +694,9 @@ APZCTreeManager::ProcessTouchInput(MultiTouchInput& aInput, Matrix4x4 transformToGecko = GetApzcToGeckoTransform(mApzcForInputBlock); Matrix4x4 outTransform = transformToApzc * transformToGecko; for (size_t i = 0; i < aInput.mTouches.Length(); i++) { - ApplyTransform(&(aInput.mTouches[i].mScreenPoint), outTransform); + SingleTouchData& touchData = aInput.mTouches[i]; + touchData.mScreenPoint = TransformTo( + outTransform, touchData.mScreenPoint); } } if (mInOverscrolledApzc) { @@ -784,7 +758,7 @@ APZCTreeManager::ProcessEvent(WidgetInputEvent& aEvent, Matrix4x4 transformToApzc = GetScreenToApzcTransform(apzc); Matrix4x4 transformToGecko = GetApzcToGeckoTransform(apzc); Matrix4x4 outTransform = transformToApzc * transformToGecko; - ApplyTransform(&(aEvent.refPoint), outTransform); + aEvent.refPoint = TransformTo(outTransform, aEvent.refPoint); } if (inOverscrolledApzc) { result = nsEventStatus_eConsumeNoDefault; @@ -913,8 +887,8 @@ APZCTreeManager::ClearTree() } /** - * Transform a displacement from the screen coordinates of a source APZC to - * the screen coordinates of a target APZC. + * Transform a displacement from the ParentLayer coordinates of a source APZC + * to the ParentLayer coordinates of a target APZC. * @param aTreeManager the tree manager for the APZC tree containing |aSource| * and |aTarget| * @param aSource the source APZC @@ -926,23 +900,23 @@ static void TransformDisplacement(APZCTreeManager* aTreeManager, AsyncPanZoomController* aSource, AsyncPanZoomController* aTarget, - ScreenPoint& aStartPoint, - ScreenPoint& aEndPoint) { - // Convert start and end points to untransformed screen coordinates. + ParentLayerPoint& aStartPoint, + ParentLayerPoint& aEndPoint) { + // Convert start and end points to Screen coordinates. Matrix4x4 untransformToApzc = aTreeManager->GetScreenToApzcTransform(aSource).Inverse(); - ApplyTransform(&aStartPoint, untransformToApzc); - ApplyTransform(&aEndPoint, untransformToApzc); + ScreenPoint screenStart = TransformTo(untransformToApzc, aStartPoint); + ScreenPoint screenEnd = TransformTo(untransformToApzc, aEndPoint); - // Convert start and end points to aTarget's transformed screen coordinates. + // Convert start and end points to aTarget's ParentLayer coordinates. Matrix4x4 transformToApzc = aTreeManager->GetScreenToApzcTransform(aTarget); - ApplyTransform(&aStartPoint, transformToApzc); - ApplyTransform(&aEndPoint, transformToApzc); + aStartPoint = TransformTo(transformToApzc, screenStart); + aEndPoint = TransformTo(transformToApzc, screenEnd); } bool APZCTreeManager::DispatchScroll(AsyncPanZoomController* aPrev, - ScreenPoint aStartPoint, - ScreenPoint aEndPoint, + ParentLayerPoint aStartPoint, + ParentLayerPoint aEndPoint, OverscrollHandoffState& aOverscrollHandoffState) { const OverscrollHandoffChain& overscrollHandoffChain = aOverscrollHandoffState.mChain; @@ -977,14 +951,14 @@ APZCTreeManager::DispatchScroll(AsyncPanZoomController* aPrev, bool APZCTreeManager::DispatchFling(AsyncPanZoomController* aPrev, - ScreenPoint aVelocity, + ParentLayerPoint aVelocity, nsRefPtr aOverscrollHandoffChain, bool aHandoff) { nsRefPtr current; uint32_t aOverscrollHandoffChainLength = aOverscrollHandoffChain->Length(); uint32_t startIndex; - + // The fling's velocity needs to be transformed from the screen coordinates // of |aPrev| to the screen coordinates of |next|. To transform a velocity // correctly, we need to convert it to a displacement. For now, we do this @@ -992,13 +966,13 @@ APZCTreeManager::DispatchFling(AsyncPanZoomController* aPrev, // TODO: For this to be correct in the presence of 3D transforms, we should // use the end point of the touch that started the fling as the start point // rather than (0, 0). - ScreenPoint startPoint; // (0, 0) - ScreenPoint endPoint; - ScreenPoint transformedVelocity = aVelocity; - + ParentLayerPoint startPoint; // (0, 0) + ParentLayerPoint endPoint; + ParentLayerPoint transformedVelocity = aVelocity; + if (aHandoff) { startIndex = aOverscrollHandoffChain->IndexOf(aPrev) + 1; - + // IndexOf will return aOverscrollHandoffChain->Length() if // |aPrev| is not found. if (startIndex >= aOverscrollHandoffChainLength) { @@ -1007,17 +981,17 @@ APZCTreeManager::DispatchFling(AsyncPanZoomController* aPrev, } else { startIndex = 0; } - + for (; startIndex < aOverscrollHandoffChainLength; startIndex++) { current = aOverscrollHandoffChain->GetApzcAtIndex(startIndex); - + // Make sure the apcz about to be handled can be handled if (current == nullptr || current->IsDestroyed()) { return false; } - + endPoint = startPoint + transformedVelocity; - + // Only transform when current apcz can be transformed with previous if (startIndex > 0) { TransformDisplacement(this, @@ -1026,9 +1000,9 @@ APZCTreeManager::DispatchFling(AsyncPanZoomController* aPrev, startPoint, endPoint); } - + transformedVelocity = endPoint - startPoint; - + bool handoff = (startIndex < 1) ? aHandoff : true; if (current->AttemptFling(transformedVelocity, aOverscrollHandoffChain, @@ -1036,7 +1010,7 @@ APZCTreeManager::DispatchFling(AsyncPanZoomController* aPrev, return true; } } - + return false; } diff --git a/gfx/layers/apz/src/APZCTreeManager.h b/gfx/layers/apz/src/APZCTreeManager.h index 16c34f4ab84a..d6776267c7f5 100644 --- a/gfx/layers/apz/src/APZCTreeManager.h +++ b/gfx/layers/apz/src/APZCTreeManager.h @@ -247,7 +247,7 @@ public: */ static const ScreenMargin CalculatePendingDisplayPort( const FrameMetrics& aFrameMetrics, - const ScreenPoint& aVelocity, + const ParentLayerPoint& aVelocity, double aEstimatedPaintDuration); /** @@ -327,8 +327,8 @@ public: * a fling, use DispatchFling(). */ bool DispatchScroll(AsyncPanZoomController* aApzc, - ScreenPoint aStartPoint, - ScreenPoint aEndPoint, + ParentLayerPoint aStartPoint, + ParentLayerPoint aEndPoint, OverscrollHandoffState& aOverscrollHandoffState); /** @@ -353,7 +353,7 @@ public: * the excess fling itself by going into an overscroll fling. */ bool DispatchFling(AsyncPanZoomController* aApzc, - ScreenPoint aVelocity, + ParentLayerPoint aVelocity, nsRefPtr aOverscrollHandoffChain, bool aHandoff); diff --git a/gfx/layers/apz/src/AsyncPanZoomController.cpp b/gfx/layers/apz/src/AsyncPanZoomController.cpp index a8f85334b9e0..d9824ac12128 100644 --- a/gfx/layers/apz/src/AsyncPanZoomController.cpp +++ b/gfx/layers/apz/src/AsyncPanZoomController.cpp @@ -135,6 +135,7 @@ typedef mozilla::layers::AllowedTouchBehavior AllowedTouchBehavior; typedef GeckoContentController::APZStateChange APZStateChange; typedef mozilla::gfx::Point Point; typedef mozilla::gfx::Matrix4x4 Matrix4x4; +using mozilla::gfx::PointTyped; /** * \page APZCPrefs APZ preferences @@ -389,12 +390,12 @@ StaticAutoPtr gVelocityCurveFunction; /** * Maximum zoom amount, always used, even if a page asks for higher. */ -static const CSSToScreenScale MAX_ZOOM(8.0f); +static const CSSToParentLayerScale MAX_ZOOM(8.0f); /** * Minimum zoom amount, always used, even if a page asks for lower. */ -static const CSSToScreenScale MIN_ZOOM(0.125f); +static const CSSToParentLayerScale MIN_ZOOM(0.125f); /** * Is aAngle within the given threshold of the horizontal axis? @@ -497,7 +498,7 @@ public: } } - ScreenPoint velocity(mApzc.mX.GetVelocity(), mApzc.mY.GetVelocity()); + ParentLayerPoint velocity = mApzc.GetVelocityVector(); // If the last fling was very recent and in the same direction as this one, // boost the velocity to be the sum of the two. Check separate axes separately @@ -570,18 +571,18 @@ public: // AdjustDisplacement() zeroes out the Axis velocity if we're in overscroll. // Since we need to hand off the velocity to the tree manager in such a case, - // we save it here. Would be ScreenVector instead of ScreenPoint if we had - // vector classes. - ScreenPoint velocity(mApzc.mX.GetVelocity(), mApzc.mY.GetVelocity()); + // we save it here. Would be ParentLayerVector instead of ParentLayerPoint + // if we had vector classes. + ParentLayerPoint velocity = mApzc.GetVelocityVector(); - ScreenPoint offset = velocity * aDelta.ToMilliseconds(); + ParentLayerPoint offset = velocity * aDelta.ToMilliseconds(); // Ordinarily we might need to do a ScheduleComposite if either of // the following AdjustDisplacement calls returns true, but this // is already running as part of a FlingAnimation, so we'll be compositing // per frame of animation anyway. - ScreenPoint overscroll; - ScreenPoint adjustedOffset; + ParentLayerPoint overscroll; + ParentLayerPoint adjustedOffset; mApzc.mX.AdjustDisplacement(offset.x, adjustedOffset.x, overscroll.x); mApzc.mY.AdjustDisplacement(offset.y, adjustedOffset.y, overscroll.y); @@ -645,8 +646,8 @@ private: class ZoomAnimation: public AsyncPanZoomAnimation { public: - ZoomAnimation(CSSPoint aStartOffset, CSSToScreenScale aStartZoom, - CSSPoint aEndOffset, CSSToScreenScale aEndZoom) + ZoomAnimation(CSSPoint aStartOffset, CSSToParentLayerScale aStartZoom, + CSSPoint aEndOffset, CSSToParentLayerScale aEndZoom) : mTotalDuration(TimeDuration::FromMilliseconds(gfxPrefs::APZZoomAnimationDuration())) , mStartOffset(aStartOffset) , mStartZoom(aStartZoom) @@ -672,7 +673,7 @@ public: // We scale the scrollOffset linearly with sampledPosition, so the zoom // needs to scale inversely to match. - aFrameMetrics.SetZoom(CSSToScreenScale(1 / + aFrameMetrics.SetZoom(CSSToParentLayerScale(1 / (sampledPosition / mEndZoom.scale + (1 - sampledPosition) / mStartZoom.scale))); @@ -693,18 +694,18 @@ private: // interpolate between the start and end frames. We only use the // |mViewportScrollOffset| and |mResolution| fields on this. CSSPoint mStartOffset; - CSSToScreenScale mStartZoom; + CSSToParentLayerScale mStartZoom; // Target metrics for a zoom to animation. This is only valid when we are in // the "ANIMATED_ZOOM" state. We only use the |mViewportScrollOffset| and // |mResolution| fields on this. CSSPoint mEndOffset; - CSSToScreenScale mEndZoom; + CSSToParentLayerScale mEndZoom; }; class OverscrollAnimation: public AsyncPanZoomAnimation { public: - explicit OverscrollAnimation(AsyncPanZoomController& aApzc, const ScreenPoint& aVelocity) + explicit OverscrollAnimation(AsyncPanZoomController& aApzc, const ParentLayerPoint& aVelocity) : mApzc(aApzc) { mApzc.mX.SetVelocity(aVelocity.x); @@ -765,7 +766,7 @@ public: mYAxisModel.GetVelocity())); // Convert from points/second to points/ms - ScreenPoint velocity = ScreenPoint(css_velocity.x, css_velocity.y) / 1000.0f; + ParentLayerPoint velocity = ParentLayerPoint(css_velocity.x, css_velocity.y) / 1000.0f; // Keep the velocity updated for the Axis class so that any animations // chained off of the smooth scroll will inherit it. @@ -781,11 +782,11 @@ public: } // If we overscroll, hand off to a fling animation that will complete the // spring back. - CSSToScreenScale zoom = aFrameMetrics.GetZoom(); - ScreenPoint displacement = (position - aFrameMetrics.GetScrollOffset()) * zoom; + CSSToParentLayerScale zoom = aFrameMetrics.GetZoom(); + ParentLayerPoint displacement = (position - aFrameMetrics.GetScrollOffset()) * zoom; - ScreenPoint overscroll; - ScreenPoint adjustedOffset; + ParentLayerPoint overscroll; + ParentLayerPoint adjustedOffset; mApzc.mX.AdjustDisplacement(displacement.x, adjustedOffset.x, overscroll.x); mApzc.mY.AdjustDisplacement(displacement.y, adjustedOffset.y, overscroll.y); @@ -1004,7 +1005,7 @@ AsyncPanZoomController::IsDestroyed() const return mTreeManager == nullptr; } -/* static */float +/* static */ScreenCoord AsyncPanZoomController::GetTouchStartTolerance() { return (gfxPrefs::APZTouchStartTolerance() * APZCTreeManager::GetDPI()); @@ -1131,7 +1132,7 @@ nsEventStatus AsyncPanZoomController::HandleGestureEvent(const InputData& aEvent nsEventStatus AsyncPanZoomController::OnTouchStart(const MultiTouchInput& aEvent) { APZC_LOG("%p got a touch-start in state %d\n", this, mState); mPanDirRestricted = false; - ScreenPoint point = GetFirstTouchScreenPoint(aEvent); + ParentLayerPoint point = GetFirstTouchPoint(aEvent); switch (mState) { case FLING: @@ -1185,7 +1186,7 @@ nsEventStatus AsyncPanZoomController::OnTouchMove(const MultiTouchInput& aEvent) return nsEventStatus_eIgnore; case TOUCHING: { - float panThreshold = GetTouchStartTolerance(); + ScreenCoord panThreshold = GetTouchStartTolerance(); UpdateWithTouchAtDevicePoint(aEvent); if (PanDistance() < panThreshold) { @@ -1270,7 +1271,7 @@ nsEventStatus AsyncPanZoomController::OnTouchEnd(const MultiTouchInput& aEvent) CurrentTouchBlock()->GetOverscrollHandoffChain()->FlushRepaints(); mX.EndTouch(aEvent.mTime); mY.EndTouch(aEvent.mTime); - ScreenPoint flingVelocity(mX.GetVelocity(), mY.GetVelocity()); + ParentLayerPoint flingVelocity = GetVelocityVector(); // Clear our velocities; if DispatchFling() gives the fling to us, // the fling velocity gets *added* to our existing velocity in // AcceptFling(). @@ -1334,7 +1335,7 @@ nsEventStatus AsyncPanZoomController::OnScaleBegin(const PinchGestureInput& aEve } SetState(PINCHING); - mLastZoomFocus = ToParentLayerCoords(aEvent.mFocusPoint) - mFrameMetrics.mCompositionBounds.TopLeft(); + mLastZoomFocus = aEvent.mLocalFocusPoint - mFrameMetrics.mCompositionBounds.TopLeft(); return nsEventStatus_eConsumeNoDefault; } @@ -1361,9 +1362,9 @@ nsEventStatus AsyncPanZoomController::OnScale(const PinchGestureInput& aEvent) { { ReentrantMonitorAutoEnter lock(mMonitor); - CSSToParentLayerScale userZoom = mFrameMetrics.GetZoomToParent(); - ParentLayerPoint focusPoint = ToParentLayerCoords(aEvent.mFocusPoint) - mFrameMetrics.mCompositionBounds.TopLeft(); - CSSPoint cssFocusPoint = focusPoint / mFrameMetrics.GetZoomToParent(); + CSSToParentLayerScale userZoom = mFrameMetrics.GetZoom(); + ParentLayerPoint focusPoint = aEvent.mLocalFocusPoint - mFrameMetrics.mCompositionBounds.TopLeft(); + CSSPoint cssFocusPoint = focusPoint / mFrameMetrics.GetZoom(); CSSPoint focusChange = (mLastZoomFocus - focusPoint) / userZoom; // If displacing by the change in focus point will take us off page bounds, @@ -1377,8 +1378,8 @@ nsEventStatus AsyncPanZoomController::OnScale(const PinchGestureInput& aEvent) { // either axis such that we don't overscroll the boundaries when zooming. CSSPoint neededDisplacement; - CSSToParentLayerScale realMinZoom = mZoomConstraints.mMinZoom * mFrameMetrics.mTransformScale; - CSSToParentLayerScale realMaxZoom = mZoomConstraints.mMaxZoom * mFrameMetrics.mTransformScale; + CSSToParentLayerScale realMinZoom = mZoomConstraints.mMinZoom; + CSSToParentLayerScale realMaxZoom = mZoomConstraints.mMaxZoom; realMinZoom.scale = std::max(realMinZoom.scale, mFrameMetrics.mCompositionBounds.width / mFrameMetrics.mScrollableRect.width); realMinZoom.scale = std::max(realMinZoom.scale, @@ -1453,14 +1454,13 @@ nsEventStatus AsyncPanZoomController::OnScaleEnd(const PinchGestureInput& aEvent } bool -AsyncPanZoomController::ConvertToGecko(const ScreenPoint& aPoint, CSSPoint* aOut) +AsyncPanZoomController::ConvertToGecko(const ParentLayerPoint& aPoint, CSSPoint* aOut) { if (APZCTreeManager* treeManagerLocal = GetApzcTreeManager()) { Matrix4x4 transformToGecko = treeManagerLocal->GetApzcToGeckoTransform(this); - Point result = transformToGecko * Point(aPoint.x, aPoint.y); // NOTE: This isn't *quite* LayoutDevicePoint, we just don't have a name // for this coordinate space and it maps the closest to LayoutDevicePoint. - LayoutDevicePoint layoutPoint = LayoutDevicePoint(result.x, result.y); + LayoutDevicePoint layoutPoint = TransformTo(transformToGecko, aPoint); { // scoped lock to access mFrameMetrics ReentrantMonitorAutoEnter lock(mMonitor); *aOut = layoutPoint / mFrameMetrics.mDevPixelsPerCSSPixel; @@ -1473,8 +1473,8 @@ AsyncPanZoomController::ConvertToGecko(const ScreenPoint& aPoint, CSSPoint* aOut nsEventStatus AsyncPanZoomController::OnPanMayBegin(const PanGestureInput& aEvent) { APZC_LOG("%p got a pan-maybegin in state %d\n", this, mState); - mX.StartTouch(aEvent.mPanStartPoint.x, aEvent.mTime); - mY.StartTouch(aEvent.mPanStartPoint.y, aEvent.mTime); + mX.StartTouch(aEvent.mLocalPanStartPoint.x, aEvent.mTime); + mY.StartTouch(aEvent.mLocalPanStartPoint.y, aEvent.mTime); if (mPanGestureState) { mPanGestureState->GetOverscrollHandoffChain()->CancelAnimations(); } else { @@ -1504,8 +1504,8 @@ nsEventStatus AsyncPanZoomController::OnPanBegin(const PanGestureInput& aEvent) mPanGestureState = MakeUnique(this); - mX.StartTouch(aEvent.mPanStartPoint.x, aEvent.mTime); - mY.StartTouch(aEvent.mPanStartPoint.y, aEvent.mTime); + mX.StartTouch(aEvent.mLocalPanStartPoint.x, aEvent.mTime); + mY.StartTouch(aEvent.mLocalPanStartPoint.y, aEvent.mTime); if (GetAxisLockMode() == FREE) { SetState(PANNING); @@ -1542,19 +1542,18 @@ nsEventStatus AsyncPanZoomController::OnPan(const PanGestureInput& aEvent, bool // size and position. We need to do so even if this is a momentum pan (i.e. // aFingersOnTouchpad == false); in that case the "with touch" part is not // really appropriate, so we may want to rethink this at some point. - mX.UpdateWithTouchAtDevicePoint(aEvent.mPanStartPoint.x, aEvent.mTime); - mY.UpdateWithTouchAtDevicePoint(aEvent.mPanStartPoint.y, aEvent.mTime); + mX.UpdateWithTouchAtDevicePoint(aEvent.mLocalPanStartPoint.x, aEvent.mTime); + mY.UpdateWithTouchAtDevicePoint(aEvent.mLocalPanStartPoint.y, aEvent.mTime); - ScreenPoint panDisplacement = aEvent.mPanDisplacement; - ToGlobalScreenCoordinates(&panDisplacement, aEvent.mPanStartPoint); - HandlePanningUpdate(panDisplacement); + HandlePanningUpdate(aEvent.mPanDisplacement); // TODO: Handle pan events sent without pan begin / pan end events properly. if (mPanGestureState) { - ScreenPoint panDistance(fabs(panDisplacement.x), fabs(panDisplacement.y)); + ScreenPoint panDistance(fabs(aEvent.mPanDisplacement.x), fabs(aEvent.mPanDisplacement.y)); OverscrollHandoffState handoffState( *mPanGestureState->GetOverscrollHandoffChain(), panDistance); - CallDispatchScroll(aEvent.mPanStartPoint, aEvent.mPanStartPoint + aEvent.mPanDisplacement, + CallDispatchScroll(aEvent.mLocalPanStartPoint, + aEvent.mLocalPanStartPoint + aEvent.mLocalPanDisplacement, handoffState); } @@ -1608,7 +1607,7 @@ nsEventStatus AsyncPanZoomController::OnLongPress(const TapGestureInput& aEvent) if (controller) { int32_t modifiers = WidgetModifiersToDOMModifiers(aEvent.modifiers); CSSPoint geckoScreenPoint; - if (ConvertToGecko(aEvent.mPoint, &geckoScreenPoint)) { + if (ConvertToGecko(aEvent.mLocalPoint, &geckoScreenPoint)) { uint64_t blockId = GetInputQueue()->InjectNewTouchBlock(this); controller->HandleLongTap(geckoScreenPoint, modifiers, GetGuid(), blockId); return nsEventStatus_eConsumeNoDefault; @@ -1623,7 +1622,7 @@ nsEventStatus AsyncPanZoomController::OnLongPressUp(const TapGestureInput& aEven if (controller) { int32_t modifiers = WidgetModifiersToDOMModifiers(aEvent.modifiers); CSSPoint geckoScreenPoint; - if (ConvertToGecko(aEvent.mPoint, &geckoScreenPoint)) { + if (ConvertToGecko(aEvent.mLocalPoint, &geckoScreenPoint)) { controller->HandleLongTapUp(geckoScreenPoint, modifiers, GetGuid()); return nsEventStatus_eConsumeNoDefault; } @@ -1631,7 +1630,7 @@ nsEventStatus AsyncPanZoomController::OnLongPressUp(const TapGestureInput& aEven return nsEventStatus_eIgnore; } -nsEventStatus AsyncPanZoomController::GenerateSingleTap(const ScreenIntPoint& aPoint, mozilla::Modifiers aModifiers) { +nsEventStatus AsyncPanZoomController::GenerateSingleTap(const ParentLayerPoint& aPoint, mozilla::Modifiers aModifiers) { nsRefPtr controller = GetGeckoContentController(); if (controller) { CSSPoint geckoScreenPoint; @@ -1667,14 +1666,14 @@ nsEventStatus AsyncPanZoomController::OnSingleTapUp(const TapGestureInput& aEven // If mZoomConstraints.mAllowDoubleTapZoom is true we wait for a call to OnSingleTapConfirmed before // sending event to content if (!(mZoomConstraints.mAllowDoubleTapZoom && CurrentTouchBlock()->TouchActionAllowsDoubleTapZoom())) { - return GenerateSingleTap(aEvent.mPoint, aEvent.modifiers); + return GenerateSingleTap(aEvent.mLocalPoint, aEvent.modifiers); } return nsEventStatus_eIgnore; } nsEventStatus AsyncPanZoomController::OnSingleTapConfirmed(const TapGestureInput& aEvent) { APZC_LOG("%p got a single-tap-confirmed in state %d\n", this, mState); - return GenerateSingleTap(aEvent.mPoint, aEvent.modifiers); + return GenerateSingleTap(aEvent.mLocalPoint, aEvent.modifiers); } nsEventStatus AsyncPanZoomController::OnDoubleTap(const TapGestureInput& aEvent) { @@ -1684,7 +1683,7 @@ nsEventStatus AsyncPanZoomController::OnDoubleTap(const TapGestureInput& aEvent) if (mZoomConstraints.mAllowDoubleTapZoom && CurrentTouchBlock()->TouchActionAllowsDoubleTapZoom()) { int32_t modifiers = WidgetModifiersToDOMModifiers(aEvent.modifiers); CSSPoint geckoScreenPoint; - if (ConvertToGecko(aEvent.mPoint, &geckoScreenPoint)) { + if (ConvertToGecko(aEvent.mLocalPoint, &geckoScreenPoint)) { controller->HandleDoubleTap(geckoScreenPoint, modifiers, GetGuid()); } } @@ -1699,52 +1698,42 @@ nsEventStatus AsyncPanZoomController::OnCancelTap(const TapGestureInput& aEvent) return nsEventStatus_eIgnore; } -// Helper function for To[Global|Local]ScreenCoordinates(). -// TODO(botond): Generalize this into a template function in UnitTransforms.h. -static void TransformVector(const Matrix4x4& aTransform, - ScreenPoint* aVector, - const ScreenPoint& aAnchor) { - ScreenPoint start = aAnchor; - ScreenPoint end = aAnchor + *aVector; - start = TransformTo(aTransform, start); - end = TransformTo(aTransform, end); - *aVector = end - start; -} -void AsyncPanZoomController::ToGlobalScreenCoordinates(ScreenPoint* aVector, - const ScreenPoint& aAnchor) const { +ScreenPoint AsyncPanZoomController::ToScreenCoordinates(const ParentLayerPoint& aVector, + const ParentLayerPoint& aAnchor) const { if (APZCTreeManager* treeManagerLocal = GetApzcTreeManager()) { Matrix4x4 apzcToScreen = treeManagerLocal->GetScreenToApzcTransform(this).Inverse(); - TransformVector(apzcToScreen, aVector, aAnchor); + return TransformVector(apzcToScreen, aVector, aAnchor); } + return ViewAs(aVector, PixelCastJustification::TransformNotAvailable); } -void AsyncPanZoomController::ToLocalScreenCoordinates(ScreenPoint* aVector, - const ScreenPoint& aAnchor) const { +ParentLayerPoint AsyncPanZoomController::ToParentLayerCoordinates(const ScreenPoint& aVector, + const ScreenPoint& aAnchor) const { if (APZCTreeManager* treeManagerLocal = GetApzcTreeManager()) { Matrix4x4 transform = treeManagerLocal->GetScreenToApzcTransform(this); - TransformVector(transform, aVector, aAnchor); + return TransformVector(transform, aVector, aAnchor); } + return ViewAs(aVector, PixelCastJustification::TransformNotAvailable); } -float AsyncPanZoomController::PanDistance() const { - ScreenPoint panVector; - ScreenPoint panStart; +ScreenCoord AsyncPanZoomController::PanDistance() const { + ParentLayerPoint panVector; + ParentLayerPoint panStart; { ReentrantMonitorAutoEnter lock(mMonitor); - panVector = ScreenPoint(mX.PanDistance(), mY.PanDistance()); + panVector = ParentLayerPoint(mX.PanDistance(), mY.PanDistance()); panStart = PanStart(); } - ToGlobalScreenCoordinates(&panVector, panStart); - return NS_hypot(panVector.x, panVector.y); + return ToScreenCoordinates(panVector, panStart).Length(); } -ScreenPoint AsyncPanZoomController::PanStart() const { - return ScreenPoint(mX.PanStart(), mY.PanStart()); +ParentLayerPoint AsyncPanZoomController::PanStart() const { + return ParentLayerPoint(mX.PanStart(), mY.PanStart()); } -const ScreenPoint AsyncPanZoomController::GetVelocityVector() const { - return ScreenPoint(mX.GetVelocity(), mY.GetVelocity()); +const ParentLayerPoint AsyncPanZoomController::GetVelocityVector() const { + return ParentLayerPoint(mX.GetVelocity(), mY.GetVelocity()); } void AsyncPanZoomController::HandlePanningWithTouchAction(double aAngle) { @@ -1844,7 +1833,7 @@ void AsyncPanZoomController::HandlePanningUpdate(const ScreenPoint& aPanDistance nsEventStatus AsyncPanZoomController::StartPanning(const MultiTouchInput& aEvent) { ReentrantMonitorAutoEnter lock(mMonitor); - ScreenPoint point = GetFirstTouchScreenPoint(aEvent); + ParentLayerPoint point = GetFirstTouchPoint(aEvent); float dx = mX.PanDistance(point.x); float dy = mY.PanDistance(point.y); @@ -1877,25 +1866,25 @@ nsEventStatus AsyncPanZoomController::StartPanning(const MultiTouchInput& aEvent } void AsyncPanZoomController::UpdateWithTouchAtDevicePoint(const MultiTouchInput& aEvent) { - ScreenPoint point = GetFirstTouchScreenPoint(aEvent); + ParentLayerPoint point = GetFirstTouchPoint(aEvent); mX.UpdateWithTouchAtDevicePoint(point.x, aEvent.mTime); mY.UpdateWithTouchAtDevicePoint(point.y, aEvent.mTime); } -bool AsyncPanZoomController::AttemptScroll(const ScreenPoint& aStartPoint, - const ScreenPoint& aEndPoint, +bool AsyncPanZoomController::AttemptScroll(const ParentLayerPoint& aStartPoint, + const ParentLayerPoint& aEndPoint, OverscrollHandoffState& aOverscrollHandoffState) { // "start - end" rather than "end - start" because e.g. moving your finger // down (*positive* direction along y axis) causes the vertical scroll offset // to *decrease* as the page follows your finger. - ScreenPoint displacement = aStartPoint - aEndPoint; + ParentLayerPoint displacement = aStartPoint - aEndPoint; - ScreenPoint overscroll; // will be used outside monitor block + ParentLayerPoint overscroll; // will be used outside monitor block { ReentrantMonitorAutoEnter lock(mMonitor); - ScreenPoint adjustedDisplacement; + ParentLayerPoint adjustedDisplacement; bool xChanged = mX.AdjustDisplacement(displacement.x, adjustedDisplacement.x, overscroll.x); bool yChanged = mY.AdjustDisplacement(displacement.y, adjustedDisplacement.y, overscroll.y); if (xChanged || yChanged) { @@ -1932,7 +1921,7 @@ bool AsyncPanZoomController::AttemptScroll(const ScreenPoint& aStartPoint, return OverscrollForPanning(overscroll, aOverscrollHandoffState.mPanDistance); } -bool AsyncPanZoomController::OverscrollForPanning(ScreenPoint aOverscroll, +bool AsyncPanZoomController::OverscrollForPanning(ParentLayerPoint aOverscroll, const ScreenPoint& aPanDistance) { // Only allow entering overscroll along an axis if the pan distance along // that axis is greater than the pan distance along the other axis by a @@ -1949,7 +1938,7 @@ bool AsyncPanZoomController::OverscrollForPanning(ScreenPoint aOverscroll, return OverscrollBy(aOverscroll); } -bool AsyncPanZoomController::OverscrollBy(const ScreenPoint& aOverscroll) { +bool AsyncPanZoomController::OverscrollBy(const ParentLayerPoint& aOverscroll) { if (!gfxPrefs::APZOverscrollEnabled()) { return false; } @@ -1986,7 +1975,7 @@ nsRefPtr AsyncPanZoomController::BuildOverscrollHa return result; } -void AsyncPanZoomController::AcceptFling(const ScreenPoint& aVelocity, +void AsyncPanZoomController::AcceptFling(const ParentLayerPoint& aVelocity, const nsRefPtr& aOverscrollHandoffChain, bool aHandoff) { // We may have a pre-existing velocity for whatever reason (for example, @@ -1999,7 +1988,7 @@ void AsyncPanZoomController::AcceptFling(const ScreenPoint& aVelocity, !aHandoff)); // only apply acceleration if this is an initial fling } -bool AsyncPanZoomController::AttemptFling(ScreenPoint aVelocity, +bool AsyncPanZoomController::AttemptFling(ParentLayerPoint aVelocity, const nsRefPtr& aOverscrollHandoffChain, bool aHandoff) { // If we are pannable, take over the fling ourselves. @@ -2013,7 +2002,7 @@ bool AsyncPanZoomController::AttemptFling(ScreenPoint aVelocity, return false; } -void AsyncPanZoomController::HandleFlingOverscroll(const ScreenPoint& aVelocity, +void AsyncPanZoomController::HandleFlingOverscroll(const ParentLayerPoint& aVelocity, const nsRefPtr& aOverscrollHandoffChain) { APZCTreeManager* treeManagerLocal = GetApzcTreeManager(); if (!(treeManagerLocal && treeManagerLocal->DispatchFling(this, @@ -2028,7 +2017,7 @@ void AsyncPanZoomController::HandleFlingOverscroll(const ScreenPoint& aVelocity, } } -void AsyncPanZoomController::HandleSmoothScrollOverscroll(const ScreenPoint& aVelocity) { +void AsyncPanZoomController::HandleSmoothScrollOverscroll(const ParentLayerPoint& aVelocity) { // We must call BuildOverscrollHandoffChain from this deferred callback // function in order to avoid a deadlock when acquiring the tree lock. HandleFlingOverscroll(aVelocity, BuildOverscrollHandoffChain()); @@ -2037,7 +2026,7 @@ void AsyncPanZoomController::HandleSmoothScrollOverscroll(const ScreenPoint& aVe void AsyncPanZoomController::StartSmoothScroll() { SetState(SMOOTH_SCROLL); nsPoint initialPosition = CSSPoint::ToAppUnits(mFrameMetrics.GetScrollOffset()); - // Cast velocity from ScreenPoints/ms to CSSPoints/ms then convert to + // Cast velocity from ParentLayerPoints/ms to CSSPoints/ms then convert to // appunits/second nsPoint initialVelocity = CSSPoint::ToAppUnits(CSSPoint(mX.GetVelocity(), mY.GetVelocity())) * 1000.0f; @@ -2050,13 +2039,13 @@ void AsyncPanZoomController::StartSmoothScroll() { gfxPrefs::ScrollBehaviorDampingRatio())); } -void AsyncPanZoomController::StartOverscrollAnimation(const ScreenPoint& aVelocity) { +void AsyncPanZoomController::StartOverscrollAnimation(const ParentLayerPoint& aVelocity) { SetState(OVERSCROLL_ANIMATION); StartAnimation(new OverscrollAnimation(*this, aVelocity)); } -bool AsyncPanZoomController::CallDispatchScroll(const ScreenPoint& aStartPoint, - const ScreenPoint& aEndPoint, +bool AsyncPanZoomController::CallDispatchScroll(const ParentLayerPoint& aStartPoint, + const ParentLayerPoint& aEndPoint, OverscrollHandoffState& aOverscrollHandoffState) { // Make a local copy of the tree manager pointer and check if it's not // null before calling DispatchScroll(). This is necessary because @@ -2068,13 +2057,13 @@ bool AsyncPanZoomController::CallDispatchScroll(const ScreenPoint& aStartPoint, } void AsyncPanZoomController::TrackTouch(const MultiTouchInput& aEvent) { - ScreenPoint prevTouchPoint(mX.GetPos(), mY.GetPos()); - ScreenPoint touchPoint = GetFirstTouchScreenPoint(aEvent); + ParentLayerPoint prevTouchPoint(mX.GetPos(), mY.GetPos()); + ParentLayerPoint touchPoint = GetFirstTouchPoint(aEvent); - ScreenPoint panDistance(mX.PanDistance(touchPoint.x), - mY.PanDistance(touchPoint.y)); - const ScreenPoint panStart = PanStart(); - ToGlobalScreenCoordinates(&panDistance, panStart); + ScreenPoint panDistance = ToScreenCoordinates( + ParentLayerPoint(mX.PanDistance(touchPoint.x), + mY.PanDistance(touchPoint.y)), + PanStart()); HandlePanningUpdate(panDistance); UpdateWithTouchAtDevicePoint(aEvent); @@ -2086,8 +2075,8 @@ void AsyncPanZoomController::TrackTouch(const MultiTouchInput& aEvent) { } } -ScreenPoint AsyncPanZoomController::GetFirstTouchScreenPoint(const MultiTouchInput& aEvent) { - return ((SingleTouchData&)aEvent.mTouches[0]).mScreenPoint; +ParentLayerPoint AsyncPanZoomController::GetFirstTouchPoint(const MultiTouchInput& aEvent) { + return ((SingleTouchData&)aEvent.mTouches[0]).mLocalScreenPoint; } void AsyncPanZoomController::StartAnimation(AsyncPanZoomAnimation* aAnimation) @@ -2200,7 +2189,7 @@ RedistributeDisplayPortExcess(CSSSize& aDisplayPortSize, /* static */ const ScreenMargin AsyncPanZoomController::CalculatePendingDisplayPort( const FrameMetrics& aFrameMetrics, - const ScreenPoint& aVelocity, + const ParentLayerPoint& aVelocity, double aEstimatedPaintDuration) { CSSSize compositionSize = aFrameMetrics.CalculateBoundedCompositedSizeInCssPixels(); @@ -2284,7 +2273,7 @@ bool AsyncPanZoomController::SnapBackIfOverscrolled() { ReentrantMonitorAutoEnter lock(mMonitor); if (IsOverscrolled()) { APZC_LOG("%p is overscrolled, starting snap-back\n", this); - StartOverscrollAnimation(ScreenPoint(0, 0)); + StartOverscrollAnimation(ParentLayerPoint(0, 0)); return true; } return false; @@ -2439,7 +2428,7 @@ Matrix4x4 AsyncPanZoomController::GetOverscrollTransform() const { // Compute the amount of the stretch along each axis. The stretch is // proportional to the amount by which we are overscrolled along that axis. - ScreenSize compositionSize(mX.GetCompositionLength(), mY.GetCompositionLength()); + ParentLayerSize compositionSize(mX.GetCompositionLength(), mY.GetCompositionLength()); float scaleX = 1 + kStretchFactor * fabsf(mX.GetOverscroll()) / mX.GetCompositionLength(); float scaleY = 1 + kStretchFactor * fabsf(mY.GetOverscroll()) / mY.GetCompositionLength(); @@ -2457,19 +2446,19 @@ Matrix4x4 AsyncPanZoomController::GetOverscrollTransform() const { // are overscrolling at the top or on the left, but if we are overscrolling // at the bottom or on the right, we want the bottom or right edge of the // content to stay in place instead, so we add a translation to compensate. - ScreenPoint translation; + ParentLayerPoint translation; bool overscrolledOnRight = (mX.GetOverscroll() > 0 && !mX.IsInUnderscroll()) || (mX.GetOverscroll() < 0 && mX.IsInUnderscroll()); if (overscrolledOnRight) { - ScreenCoord overscrolledCompositionWidth = scaleX * compositionSize.width; - ScreenCoord extraCompositionWidth = overscrolledCompositionWidth - compositionSize.width; + ParentLayerCoord overscrolledCompositionWidth = scaleX * compositionSize.width; + ParentLayerCoord extraCompositionWidth = overscrolledCompositionWidth - compositionSize.width; translation.x = -extraCompositionWidth; } bool overscrolledAtBottom = (mY.GetOverscroll() > 0 && !mY.IsInUnderscroll()) || (mY.GetOverscroll() < 0 && mY.IsInUnderscroll()); if (overscrolledAtBottom) { - ScreenCoord overscrolledCompositionHeight = scaleY * compositionSize.height; - ScreenCoord extraCompositionHeight = overscrolledCompositionHeight - compositionSize.height; + ParentLayerCoord overscrolledCompositionHeight = scaleY * compositionSize.height; + ParentLayerCoord extraCompositionHeight = overscrolledCompositionHeight - compositionSize.height; translation.y = -extraCompositionHeight; } @@ -2551,7 +2540,7 @@ bool AsyncPanZoomController::AdvanceAnimations(const TimeStamp& aSampleTime) } void AsyncPanZoomController::SampleContentTransformForFrame(ViewTransform* aOutTransform, - ScreenPoint& aScrollOffset) + ParentLayerPoint& aScrollOffset) { ReentrantMonitorAutoEnter lock(mMonitor); @@ -2588,25 +2577,25 @@ ViewTransform AsyncPanZoomController::GetCurrentAsyncTransform() const { } } - ParentLayerToScreenScale scale = mFrameMetrics.mPresShellResolution // non-transient portion - * mFrameMetrics.GetAsyncZoom(); // transient portion - ScreenPoint translation = (currentScrollOffset - lastPaintScrollOffset) - * mFrameMetrics.GetZoom(); + LayerToParentLayerScale scale(mFrameMetrics.mPresShellResolution // non-transient portion + * mFrameMetrics.GetAsyncZoom().scale); // transient portion + ParentLayerPoint translation = (currentScrollOffset - lastPaintScrollOffset) + * mFrameMetrics.GetZoom(); return ViewTransform(scale, -translation); } Matrix4x4 AsyncPanZoomController::GetNontransientAsyncTransform() const { ReentrantMonitorAutoEnter lock(mMonitor); - return Matrix4x4::Scaling(mLastContentPaintMetrics.mPresShellResolution.scale, - mLastContentPaintMetrics.mPresShellResolution.scale, + return Matrix4x4::Scaling(mLastContentPaintMetrics.mPresShellResolution, + mLastContentPaintMetrics.mPresShellResolution, 1.0f); } Matrix4x4 AsyncPanZoomController::GetTransformToLastDispatchedPaint() const { ReentrantMonitorAutoEnter lock(mMonitor); - ParentLayerPoint scrollChange = + LayerPoint scrollChange = (mLastContentPaintMetrics.GetScrollOffset() - mLastDispatchedPaintMetrics.GetScrollOffset()) * mLastContentPaintMetrics.mDevPixelsPerCSSPixel * mLastContentPaintMetrics.mCumulativeResolution @@ -2647,7 +2636,6 @@ void AsyncPanZoomController::NotifyLayersUpdated(const FrameMetrics& aLayerMetri bool isDefault = mFrameMetrics.IsDefault(); mLastContentPaintMetrics = aLayerMetrics; - UpdateTransformScale(); mFrameMetrics.SetMayHaveTouchListeners(aLayerMetrics.GetMayHaveTouchListeners()); mFrameMetrics.SetMayHaveTouchCaret(aLayerMetrics.GetMayHaveTouchCaret()); @@ -2721,8 +2709,8 @@ void AsyncPanZoomController::NotifyLayersUpdated(const FrameMetrics& aLayerMetri // since the repaint request. float totalResolutionChange = aLayerMetrics.mCumulativeResolution.scale / mFrameMetrics.mCumulativeResolution.scale; - float presShellResolutionChange = aLayerMetrics.mPresShellResolution.scale - / mFrameMetrics.mPresShellResolution.scale; + float presShellResolutionChange = aLayerMetrics.mPresShellResolution + / mFrameMetrics.mPresShellResolution; mFrameMetrics.ZoomBy(totalResolutionChange / presShellResolutionChange); } else { // Take the new zoom as either device scale or composition width or both @@ -2821,7 +2809,7 @@ void AsyncPanZoomController::ZoomToRect(CSSRect aRect) { ParentLayerRect compositionBounds = mFrameMetrics.mCompositionBounds; CSSRect cssPageRect = mFrameMetrics.mScrollableRect; CSSPoint scrollOffset = mFrameMetrics.GetScrollOffset(); - CSSToParentLayerScale currentZoom = mFrameMetrics.GetZoomToParent(); + CSSToParentLayerScale currentZoom = mFrameMetrics.GetZoom(); CSSToParentLayerScale targetZoom; // The minimum zoom to prevent over-zoom-out. @@ -2829,10 +2817,10 @@ void AsyncPanZoomController::ZoomToRect(CSSRect aRect) { // then the CSS content rect, in layers pixels, will be smaller than the // composition bounds. If this happens, we can't fill the target composited // area with this frame. - CSSToParentLayerScale localMinZoom(std::max((mZoomConstraints.mMinZoom * mFrameMetrics.mTransformScale).scale, + CSSToParentLayerScale localMinZoom(std::max(mZoomConstraints.mMinZoom.scale, std::max(compositionBounds.width / cssPageRect.width, compositionBounds.height / cssPageRect.height))); - CSSToParentLayerScale localMaxZoom = mZoomConstraints.mMaxZoom * mFrameMetrics.mTransformScale; + CSSToParentLayerScale localMaxZoom = mZoomConstraints.mMaxZoom; if (!aRect.IsEmpty()) { // Intersect the zoom-to-rect to the CSS rect to make sure it fits. @@ -2864,7 +2852,7 @@ void AsyncPanZoomController::ZoomToRect(CSSRect aRect) { targetZoom.scale = clamped(targetZoom.scale, localMinZoom.scale, localMaxZoom.scale); FrameMetrics endZoomToMetrics = mFrameMetrics; - endZoomToMetrics.SetZoom(targetZoom / mFrameMetrics.mTransformScale); + endZoomToMetrics.SetZoom(targetZoom); // Adjust the zoomToRect to a sensible position to prevent overscrolling. CSSSize sizeAfterZoom = endZoomToMetrics.CalculateCompositedSizeInCssPixels(); @@ -2883,7 +2871,7 @@ void AsyncPanZoomController::ZoomToRect(CSSRect aRect) { endZoomToMetrics.SetScrollOffset(aRect.TopLeft()); endZoomToMetrics.SetDisplayPortMargins( CalculatePendingDisplayPort(endZoomToMetrics, - ScreenPoint(0,0), + ParentLayerPoint(0,0), 0)); endZoomToMetrics.SetUseDisplayPortMargins(); @@ -3108,19 +3096,5 @@ void AsyncPanZoomController::ShareCompositorFrameMetrics() { } } -ParentLayerPoint AsyncPanZoomController::ToParentLayerCoords(const ScreenPoint& aPoint) -{ - // The parent layer pixel space and the screen space for a given layer are the - // same as of bug 1052063. FIXME: Unify these two coordinate systems. - return ParentLayerPoint(aPoint.x, aPoint.y); -} - -void AsyncPanZoomController::UpdateTransformScale() -{ - // The parent layer pixel space and the screen space for a given layer are the - // same as of bug 1052063. FIXME: Unify these two coordinate systems. - mFrameMetrics.mTransformScale.scale = 1; -} - } } diff --git a/gfx/layers/apz/src/AsyncPanZoomController.h b/gfx/layers/apz/src/AsyncPanZoomController.h index 3a00acf6fa57..f6e491c2ac9d 100644 --- a/gfx/layers/apz/src/AsyncPanZoomController.h +++ b/gfx/layers/apz/src/AsyncPanZoomController.h @@ -90,9 +90,10 @@ public: * device DPI, before we start panning the screen. This is to prevent us from * accidentally processing taps as touch moves, and from very short/accidental * touches moving the screen. - * Note: this distance is in global screen coordinates. + * Note: It's an abuse of the 'Coord' class to use it to represent a 2D + * distance, but it's the closest thing we currently have. */ - static float GetTouchStartTolerance(); + static ScreenCoord GetTouchStartTolerance(); AsyncPanZoomController(uint64_t aLayersId, APZCTreeManager* aTreeManager, @@ -162,7 +163,7 @@ public: * out parameter. */ void SampleContentTransformForFrame(ViewTransform* aOutTransform, - ScreenPoint& aScrollOffset); + ParentLayerPoint& aScrollOffset); /** * Return a visual effect that reflects this apzc's @@ -247,7 +248,7 @@ public: */ static const ScreenMargin CalculatePendingDisplayPort( const FrameMetrics& aFrameMetrics, - const ScreenPoint& aVelocity, + const ParentLayerPoint& aVelocity, double aEstimatedPaintDuration); /** @@ -335,25 +336,25 @@ public: /** * Convert the vector |aVector|, rooted at the point |aAnchor|, from - * this APZC's local screen coordinates into global screen coordinates. + * this APZC's ParentLayer coordinates into screen coordinates. * The anchor is necessary because with 3D tranforms, the location of the * vector can affect the result of the transform. * To respect the lock ordering, mMonitor must NOT be held when calling * this function (since this function acquires the tree lock). */ - void ToGlobalScreenCoordinates(ScreenPoint* aVector, - const ScreenPoint& aAnchor) const; + ScreenPoint ToScreenCoordinates(const ParentLayerPoint& aVector, + const ParentLayerPoint& aAnchor) const; /** * Convert the vector |aVector|, rooted at the point |aAnchor|, from - * global screen coordinates into this APZC's local screen coordinates . + * screen coordinates into this APZC's ParentLayer coordinates. * The anchor is necessary because with 3D tranforms, the location of the * vector can affect the result of the transform. * To respect the lock ordering, mMonitor must NOT be held when calling * this function (since this function acquires the tree lock). */ - void ToLocalScreenCoordinates(ScreenPoint* aVector, - const ScreenPoint& aAnchor) const; + ParentLayerPoint ToParentLayerCoordinates(const ScreenPoint& aVector, + const ScreenPoint& aAnchor) const; protected: // Protected destructor, to discourage deletion outside of Release(): @@ -471,31 +472,29 @@ protected: * the distance between the current position and the initial position of the * current touch (this only makes sense if a touch is currently happening and * OnTouchMove() or the equivalent for pan gestures is being invoked). - * Note: This function returns a distance in global screen coordinates, - * not the local screen coordinates of this APZC. + * Note: It's an abuse of the 'Coord' class to use it to represent a 2D + * distance, but it's the closest thing we currently have. */ - float PanDistance() const; + ScreenCoord PanDistance() const; /** * Gets the start point of the current touch. * Like PanDistance(), this only makes sense if a touch is currently * happening and OnTouchMove() or the equivalent for pan gestures is * being invoked. - * Unlikely PanDistance(), this function returns a point in local screen - * coordinates. */ - ScreenPoint PanStart() const; + ParentLayerPoint PanStart() const; /** * Gets a vector of the velocities of each axis. */ - const ScreenPoint GetVelocityVector() const; + const ParentLayerPoint GetVelocityVector() const; /** * Gets the first touch point from a MultiTouchInput. This gets only * the first one and assumes the rest are either missing or not relevant. */ - ScreenPoint GetFirstTouchScreenPoint(const MultiTouchInput& aEvent); + ParentLayerPoint GetFirstTouchPoint(const MultiTouchInput& aEvent); /** * Sets the panning state basing on the pan direction angle and current touch-action value. @@ -509,7 +508,6 @@ protected: /** * Update the panning state and axis locks. - * Note: |aDelta| is expected to be in global screen coordinates. */ void HandlePanningUpdate(const ScreenPoint& aDelta); @@ -586,7 +584,7 @@ protected: * NOTE: This must be converted to CSSPoint relative to the child * document before sending over IPC. */ - bool ConvertToGecko(const ScreenPoint& aPoint, CSSPoint* aOut); + bool ConvertToGecko(const ParentLayerPoint& aPoint, CSSPoint* aOut); enum AxisLockMode { FREE, /* No locking at all */ @@ -596,18 +594,8 @@ protected: static AxisLockMode GetAxisLockMode(); - // Convert a point from local screen coordinates to parent layer coordinates. - // This is a common operation as inputs from the tree manager are in screen - // coordinates but the composition bounds is in parent layer coordinates. - ParentLayerPoint ToParentLayerCoords(const ScreenPoint& aPoint); - - // Update mFrameMetrics.mTransformScale. This should be called whenever - // our CSS transform or the non-transient part of our async transform - // changes, as it corresponds to the scale portion of those transforms. - void UpdateTransformScale(); - // Helper function for OnSingleTapUp() and OnSingleTapConfirmed(). - nsEventStatus GenerateSingleTap(const ScreenIntPoint& aPoint, mozilla::Modifiers aModifiers); + nsEventStatus GenerateSingleTap(const ParentLayerPoint& aPoint, mozilla::Modifiers aModifiers); // Common processing at the end of a touch block. void OnTouchEndOrCancel(); @@ -824,7 +812,7 @@ public: * APZC, and determines whether acceleration is applied to the * fling. */ - bool AttemptFling(ScreenPoint aVelocity, + bool AttemptFling(ParentLayerPoint aVelocity, const nsRefPtr& aOverscrollHandoffChain, bool aHandoff); @@ -833,7 +821,7 @@ private: friend class OverscrollAnimation; friend class SmoothScrollAnimation; // The initial velocity of the most recent fling. - ScreenPoint mLastFlingVelocity; + ParentLayerPoint mLastFlingVelocity; // The time at which the most recent fling started. TimeStamp mLastFlingTime; @@ -842,18 +830,18 @@ private: // The overscroll is handled by trying to hand the fling off to an APZC // later in the handoff chain, or if there are no takers, continuing the // fling and entering an overscrolled state. - void HandleFlingOverscroll(const ScreenPoint& aVelocity, + void HandleFlingOverscroll(const ParentLayerPoint& aVelocity, const nsRefPtr& aOverscrollHandoffChain); - void HandleSmoothScrollOverscroll(const ScreenPoint& aVelocity); + void HandleSmoothScrollOverscroll(const ParentLayerPoint& aVelocity); // Helper function used by TakeOverFling() and HandleFlingOverscroll(). - void AcceptFling(const ScreenPoint& aVelocity, + void AcceptFling(const ParentLayerPoint& aVelocity, const nsRefPtr& aOverscrollHandoffChain, bool aHandoff); // Start an overscroll animation with the given initial velocity. - void StartOverscrollAnimation(const ScreenPoint& aVelocity); + void StartOverscrollAnimation(const ParentLayerPoint& aVelocity); void StartSmoothScroll(); @@ -944,7 +932,7 @@ public: * state). If this returns false, the caller APZC knows that it should enter * an overscrolled state itself if it can. */ - bool AttemptScroll(const ScreenPoint& aStartPoint, const ScreenPoint& aEndPoint, + bool AttemptScroll(const ParentLayerPoint& aStartPoint, const ParentLayerPoint& aEndPoint, OverscrollHandoffState& aOverscrollHandoffState); void FlushRepaintForOverscrollHandoff(); @@ -982,8 +970,8 @@ private: * Guards against the case where the APZC is being concurrently destroyed * (and thus mTreeManager is being nulled out). */ - bool CallDispatchScroll(const ScreenPoint& aStartPoint, - const ScreenPoint& aEndPoint, + bool CallDispatchScroll(const ParentLayerPoint& aStartPoint, + const ParentLayerPoint& aEndPoint, OverscrollHandoffState& aOverscrollHandoffState); /** @@ -991,7 +979,7 @@ private: * around OverscrollBy() that also implements restrictions on entering * overscroll based on the pan angle. */ - bool OverscrollForPanning(ScreenPoint aOverscroll, + bool OverscrollForPanning(ParentLayerPoint aOverscroll, const ScreenPoint& aPanDistance); /** @@ -1000,7 +988,7 @@ private: * and the function returns true. * Otherwise, nothing happens and the function return false. */ - bool OverscrollBy(const ScreenPoint& aOverscroll); + bool OverscrollBy(const ParentLayerPoint& aOverscroll); /* =================================================================== diff --git a/gfx/layers/apz/src/Axis.cpp b/gfx/layers/apz/src/Axis.cpp index a8761c194288..d87680ee0cfc 100644 --- a/gfx/layers/apz/src/Axis.cpp +++ b/gfx/layers/apz/src/Axis.cpp @@ -42,13 +42,19 @@ Axis::Axis(AsyncPanZoomController* aAsyncPanZoomController) { } -float Axis::ToLocalVelocity(float aVelocityInchesPerMs) { - ScreenPoint aVelocityPoint = MakePoint(aVelocityInchesPerMs * APZCTreeManager::GetDPI()); - mAsyncPanZoomController->ToLocalScreenCoordinates(&aVelocityPoint, mAsyncPanZoomController->PanStart()); - return aVelocityPoint.Length(); +float Axis::ToLocalVelocity(float aVelocityInchesPerMs) const { + ScreenPoint velocity = MakePoint(aVelocityInchesPerMs * APZCTreeManager::GetDPI()); + // Use ToScreenCoordinates() to convert a point rather than a vector by + // treating the point as a vector, and using (0, 0) as the anchor. + ScreenPoint panStart = mAsyncPanZoomController->ToScreenCoordinates( + mAsyncPanZoomController->PanStart(), + ParentLayerPoint()); + ParentLayerPoint localVelocity = + mAsyncPanZoomController->ToParentLayerCoordinates(velocity, panStart); + return localVelocity.Length(); } -void Axis::UpdateWithTouchAtDevicePoint(ScreenCoord aPos, uint32_t aTimestampMs) { +void Axis::UpdateWithTouchAtDevicePoint(ParentLayerCoord aPos, uint32_t aTimestampMs) { // mVelocityQueue is controller-thread only AsyncPanZoomController::AssertOnControllerThread(); @@ -98,16 +104,16 @@ void Axis::UpdateWithTouchAtDevicePoint(ScreenCoord aPos, uint32_t aTimestampMs) } } -void Axis::StartTouch(ScreenCoord aPos, uint32_t aTimestampMs) { +void Axis::StartTouch(ParentLayerCoord aPos, uint32_t aTimestampMs) { mStartPos = aPos; mPos = aPos; mPosTimeMs = aTimestampMs; mAxisLocked = false; } -bool Axis::AdjustDisplacement(ScreenCoord aDisplacement, - /* ScreenCoord */ float& aDisplacementOut, - /* ScreenCoord */ float& aOverscrollAmountOut) +bool Axis::AdjustDisplacement(ParentLayerCoord aDisplacement, + /* ParentLayerCoord */ float& aDisplacementOut, + /* ParentLayerCoord */ float& aOverscrollAmountOut) { if (mAxisLocked) { aOverscrollAmountOut = 0; @@ -115,10 +121,10 @@ bool Axis::AdjustDisplacement(ScreenCoord aDisplacement, return false; } - ScreenCoord displacement = aDisplacement; + ParentLayerCoord displacement = aDisplacement; // First consume any overscroll in the opposite direction along this axis. - ScreenCoord consumedOverscroll = 0; + ParentLayerCoord consumedOverscroll = 0; if (mOverscroll > 0 && aDisplacement < 0) { consumedOverscroll = std::min(mOverscroll, -aDisplacement); } else if (mOverscroll < 0 && aDisplacement > 0) { @@ -140,7 +146,7 @@ bool Axis::AdjustDisplacement(ScreenCoord aDisplacement, return fabsf(consumedOverscroll) > EPSILON; } -ScreenCoord Axis::ApplyResistance(ScreenCoord aRequestedOverscroll) const { +ParentLayerCoord Axis::ApplyResistance(ParentLayerCoord aRequestedOverscroll) const { // 'resistanceFactor' is a value between 0 and 1, which: // - tends to 1 as the existing overscroll tends to 0 // - tends to 0 as the existing overscroll tends to the composition length @@ -148,10 +154,10 @@ ScreenCoord Axis::ApplyResistance(ScreenCoord aRequestedOverscroll) const { // factor; this should prevent overscrolling by more than the composition // length. float resistanceFactor = 1 - fabsf(mOverscroll) / GetCompositionLength(); - return resistanceFactor < 0 ? ScreenCoord(0) : aRequestedOverscroll * resistanceFactor; + return resistanceFactor < 0 ? ParentLayerCoord(0) : aRequestedOverscroll * resistanceFactor; } -void Axis::OverscrollBy(ScreenCoord aOverscroll) { +void Axis::OverscrollBy(ParentLayerCoord aOverscroll) { MOZ_ASSERT(CanScroll()); aOverscroll = ApplyResistance(aOverscroll); if (aOverscroll > 0) { @@ -178,7 +184,7 @@ void Axis::OverscrollBy(ScreenCoord aOverscroll) { mOverscroll += aOverscroll; } -ScreenCoord Axis::GetOverscroll() const { +ParentLayerCoord Axis::GetOverscroll() const { return mOverscroll; } @@ -250,15 +256,15 @@ void Axis::ClearOverscroll() { mOverscroll = 0; } -ScreenCoord Axis::PanStart() const { +ParentLayerCoord Axis::PanStart() const { return mStartPos; } -ScreenCoord Axis::PanDistance() const { +ParentLayerCoord Axis::PanDistance() const { return fabs(mPos - mStartPos); } -ScreenCoord Axis::PanDistance(ScreenCoord aPos) const { +ParentLayerCoord Axis::PanDistance(ParentLayerCoord aPos) const { return fabs(aPos - mStartPos); } @@ -314,9 +320,9 @@ bool Axis::FlingApplyFrictionOrCancel(const TimeDuration& aDelta, return true; } -ScreenCoord Axis::DisplacementWillOverscrollAmount(ScreenCoord aDisplacement) const { - ScreenCoord newOrigin = GetOrigin() + aDisplacement; - ScreenCoord newCompositionEnd = GetCompositionEnd() + aDisplacement; +ParentLayerCoord Axis::DisplacementWillOverscrollAmount(ParentLayerCoord aDisplacement) const { + ParentLayerCoord newOrigin = GetOrigin() + aDisplacement; + ParentLayerCoord newCompositionEnd = GetCompositionEnd() + aDisplacement; // If the current pan plus a displacement takes the window to the left of or // above the current page rect. bool minus = newOrigin < GetPageStart(); @@ -338,11 +344,11 @@ ScreenCoord Axis::DisplacementWillOverscrollAmount(ScreenCoord aDisplacement) co } CSSCoord Axis::ScaleWillOverscrollAmount(float aScale, CSSCoord aFocus) const { - // Internally, do computations in Screen coordinates *before* the scale is - // applied. - CSSToScreenScale zoom = GetFrameMetrics().GetZoom(); - ScreenCoord focus = aFocus * zoom; - ScreenCoord originAfterScale = (GetOrigin() + focus) - (focus / aScale); + // Internally, do computations in ParentLayer coordinates *before* the scale + // is applied. + CSSToParentLayerScale zoom = GetFrameMetrics().GetZoom(); + ParentLayerCoord focus = aFocus * zoom; + ParentLayerCoord originAfterScale = (GetOrigin() + focus) - (focus / aScale); bool both = ScaleWillOverscrollBothSides(aScale); bool minus = GetPageStart() - originAfterScale > COORDINATE_EPSILON; @@ -370,39 +376,37 @@ void Axis::SetVelocity(float aVelocity) { mVelocity = aVelocity; } -ScreenCoord Axis::GetCompositionEnd() const { +ParentLayerCoord Axis::GetCompositionEnd() const { return GetOrigin() + GetCompositionLength(); } -ScreenCoord Axis::GetPageEnd() const { +ParentLayerCoord Axis::GetPageEnd() const { return GetPageStart() + GetPageLength(); } -ScreenCoord Axis::GetOrigin() const { - ScreenPoint origin = GetFrameMetrics().GetScrollOffset() * GetFrameMetrics().GetZoom(); +ParentLayerCoord Axis::GetOrigin() const { + ParentLayerPoint origin = GetFrameMetrics().GetScrollOffset() * GetFrameMetrics().GetZoom(); return GetPointOffset(origin); } -ScreenCoord Axis::GetCompositionLength() const { - return GetRectLength(GetFrameMetrics().mCompositionBounds / GetFrameMetrics().mTransformScale); +ParentLayerCoord Axis::GetCompositionLength() const { + return GetRectLength(GetFrameMetrics().mCompositionBounds); } -ScreenCoord Axis::GetPageStart() const { - ScreenRect pageRect = GetFrameMetrics().GetExpandedScrollableRect() * GetFrameMetrics().GetZoom(); +ParentLayerCoord Axis::GetPageStart() const { + ParentLayerRect pageRect = GetFrameMetrics().GetExpandedScrollableRect() * GetFrameMetrics().GetZoom(); return GetRectOffset(pageRect); } -ScreenCoord Axis::GetPageLength() const { - ScreenRect pageRect = GetFrameMetrics().GetExpandedScrollableRect() * GetFrameMetrics().GetZoom(); +ParentLayerCoord Axis::GetPageLength() const { + ParentLayerRect pageRect = GetFrameMetrics().GetExpandedScrollableRect() * GetFrameMetrics().GetZoom(); return GetRectLength(pageRect); } bool Axis::ScaleWillOverscrollBothSides(float aScale) const { const FrameMetrics& metrics = GetFrameMetrics(); - - ScreenToParentLayerScale scale(metrics.mTransformScale.scale * aScale); - ScreenRect screenCompositionBounds = metrics.mCompositionBounds / scale; - + ParentLayerRect screenCompositionBounds = metrics.mCompositionBounds + / ParentLayerToParentLayerScale(aScale); return GetRectLength(screenCompositionBounds) - GetPageLength() > COORDINATE_EPSILON; } @@ -417,17 +421,17 @@ AxisX::AxisX(AsyncPanZoomController* aAsyncPanZoomController) } -ScreenCoord AxisX::GetPointOffset(const ScreenPoint& aPoint) const +ParentLayerCoord AxisX::GetPointOffset(const ParentLayerPoint& aPoint) const { return aPoint.x; } -ScreenCoord AxisX::GetRectLength(const ScreenRect& aRect) const +ParentLayerCoord AxisX::GetRectLength(const ParentLayerRect& aRect) const { return aRect.width; } -ScreenCoord AxisX::GetRectOffset(const ScreenRect& aRect) const +ParentLayerCoord AxisX::GetRectOffset(const ParentLayerRect& aRect) const { return aRect.x; } @@ -443,17 +447,17 @@ AxisY::AxisY(AsyncPanZoomController* aAsyncPanZoomController) } -ScreenCoord AxisY::GetPointOffset(const ScreenPoint& aPoint) const +ParentLayerCoord AxisY::GetPointOffset(const ParentLayerPoint& aPoint) const { return aPoint.y; } -ScreenCoord AxisY::GetRectLength(const ScreenRect& aRect) const +ParentLayerCoord AxisY::GetRectLength(const ParentLayerRect& aRect) const { return aRect.height; } -ScreenCoord AxisY::GetRectOffset(const ScreenRect& aRect) const +ParentLayerCoord AxisY::GetRectOffset(const ParentLayerRect& aRect) const { return aRect.y; } diff --git a/gfx/layers/apz/src/Axis.h b/gfx/layers/apz/src/Axis.h index c8351787426e..4bc5236457c7 100644 --- a/gfx/layers/apz/src/Axis.h +++ b/gfx/layers/apz/src/Axis.h @@ -41,13 +41,13 @@ public: * Notify this Axis that a new touch has been received, including a timestamp * for when the touch was received. This triggers a recalculation of velocity. */ - void UpdateWithTouchAtDevicePoint(ScreenCoord aPos, uint32_t aTimestampMs); + void UpdateWithTouchAtDevicePoint(ParentLayerCoord aPos, uint32_t aTimestampMs); /** * Notify this Axis that a touch has begun, i.e. the user has put their finger * on the screen but has not yet tried to pan. */ - void StartTouch(ScreenCoord aPos, uint32_t aTimestampMs); + void StartTouch(ParentLayerCoord aPos, uint32_t aTimestampMs); /** * Notify this Axis that a touch has ended gracefully. This may perform @@ -73,18 +73,18 @@ public: * displacement, and the function returns true iff internal overscroll amounts * were changed. */ - bool AdjustDisplacement(ScreenCoord aDisplacement, - /* ScreenCoord */ float& aDisplacementOut, - /* ScreenCoord */ float& aOverscrollAmountOut); + bool AdjustDisplacement(ParentLayerCoord aDisplacement, + /* ParentLayerCoord */ float& aDisplacementOut, + /* ParentLayerCoord */ float& aOverscrollAmountOut); /** * Overscrolls this axis by the requested amount in the requested direction. * The axis must be at the end of its scroll range in this direction. */ - void OverscrollBy(ScreenCoord aOverscroll); + void OverscrollBy(ParentLayerCoord aOverscroll); /** - * Return the amount of overscroll on this axis, in Screen pixels. + * Return the amount of overscroll on this axis, in ParentLayer pixels. * * If this amount is nonzero, the relevant component of * mAsyncPanZoomController->mFrameMetrics.mScrollOffset must be at its @@ -94,7 +94,7 @@ public: * Note that if |mInUnderscroll| is true, the interpretation of this field * changes slightly (see below). */ - ScreenCoord GetOverscroll() const; + ParentLayerCoord GetOverscroll() const; /** * Return whether the axis is in underscroll. @@ -138,20 +138,20 @@ public: /** * Gets the starting position of the touch supplied in StartTouch(). */ - ScreenCoord PanStart() const; + ParentLayerCoord PanStart() const; /** * Gets the distance between the starting position of the touch supplied in * StartTouch() and the current touch from the last * UpdateWithTouchAtDevicePoint(). */ - ScreenCoord PanDistance() const; + ParentLayerCoord PanDistance() const; /** * Gets the distance between the starting position of the touch supplied in * StartTouch() and the supplied position. */ - ScreenCoord PanDistance(ScreenCoord aPos) const; + ParentLayerCoord PanDistance(ParentLayerCoord aPos) const; /** * Applies friction during a fling, or cancels the fling if the velocity is @@ -198,7 +198,7 @@ public: * If a displacement will overscroll the axis, this returns the amount and in * what direction. */ - ScreenCoord DisplacementWillOverscrollAmount(ScreenCoord aDisplacement) const; + ParentLayerCoord DisplacementWillOverscrollAmount(ParentLayerCoord aDisplacement) const; /** * If a scale will overscroll the axis, this returns the amount and in what @@ -209,7 +209,7 @@ public: * relative. * * Note: Unlike most other functions in Axis, this functions operates in - * CSS coordinates so there is no confusion as to whether the Screen + * CSS coordinates so there is no confusion as to whether the ParentLayer * coordinates it operates in are before or after the scale is applied. */ CSSCoord ScaleWillOverscrollAmount(float aScale, CSSCoord aFocus) const; @@ -223,30 +223,30 @@ public: */ bool ScaleWillOverscrollBothSides(float aScale) const; - ScreenCoord GetOrigin() const; - ScreenCoord GetCompositionLength() const; - ScreenCoord GetPageStart() const; - ScreenCoord GetPageLength() const; - ScreenCoord GetCompositionEnd() const; - ScreenCoord GetPageEnd() const; + ParentLayerCoord GetOrigin() const; + ParentLayerCoord GetCompositionLength() const; + ParentLayerCoord GetPageStart() const; + ParentLayerCoord GetPageLength() const; + ParentLayerCoord GetCompositionEnd() const; + ParentLayerCoord GetPageEnd() const; - ScreenCoord GetPos() const { return mPos; } + ParentLayerCoord GetPos() const { return mPos; } - virtual ScreenCoord GetPointOffset(const ScreenPoint& aPoint) const = 0; - virtual ScreenCoord GetRectLength(const ScreenRect& aRect) const = 0; - virtual ScreenCoord GetRectOffset(const ScreenRect& aRect) const = 0; + virtual ParentLayerCoord GetPointOffset(const ParentLayerPoint& aPoint) const = 0; + virtual ParentLayerCoord GetRectLength(const ParentLayerRect& aRect) const = 0; + virtual ParentLayerCoord GetRectOffset(const ParentLayerRect& aRect) const = 0; virtual ScreenPoint MakePoint(ScreenCoord aCoord) const = 0; protected: - ScreenCoord mPos; + ParentLayerCoord mPos; uint32_t mPosTimeMs; - ScreenCoord mStartPos; - float mVelocity; // Units: ScreenCoords per millisecond + ParentLayerCoord mStartPos; + float mVelocity; // Units: ParentLayerCoords per millisecond bool mAxisLocked; // Whether movement on this axis is locked. AsyncPanZoomController* mAsyncPanZoomController; - ScreenCoord mOverscroll; // See GetOverscroll(). - bool mInUnderscroll; // See IsInUnderscroll(). + ParentLayerCoord mOverscroll; // See GetOverscroll(). + bool mInUnderscroll; // See IsInUnderscroll(). // A queue of (timestamp, velocity) pairs; these are the historical // velocities at the given timestamps. Timestamps are in milliseconds, // velocities are in screen pixels per ms. This member can only be @@ -257,27 +257,27 @@ protected: // Adjust a requested overscroll amount for resistance, yielding a smaller // actual overscroll amount. - ScreenCoord ApplyResistance(ScreenCoord aOverscroll) const; + ParentLayerCoord ApplyResistance(ParentLayerCoord aOverscroll) const; - // Convert a velocity from global inches/ms into local ScreenCoords per ms - float ToLocalVelocity(float aVelocityInchesPerMs); + // Convert a velocity from global inches/ms into ParentLayerCoords/ms. + float ToLocalVelocity(float aVelocityInchesPerMs) const; }; class AxisX : public Axis { public: explicit AxisX(AsyncPanZoomController* mAsyncPanZoomController); - virtual ScreenCoord GetPointOffset(const ScreenPoint& aPoint) const MOZ_OVERRIDE; - virtual ScreenCoord GetRectLength(const ScreenRect& aRect) const MOZ_OVERRIDE; - virtual ScreenCoord GetRectOffset(const ScreenRect& aRect) const MOZ_OVERRIDE; + virtual ParentLayerCoord GetPointOffset(const ParentLayerPoint& aPoint) const MOZ_OVERRIDE; + virtual ParentLayerCoord GetRectLength(const ParentLayerRect& aRect) const MOZ_OVERRIDE; + virtual ParentLayerCoord GetRectOffset(const ParentLayerRect& aRect) const MOZ_OVERRIDE; virtual ScreenPoint MakePoint(ScreenCoord aCoord) const MOZ_OVERRIDE; }; class AxisY : public Axis { public: explicit AxisY(AsyncPanZoomController* mAsyncPanZoomController); - virtual ScreenCoord GetPointOffset(const ScreenPoint& aPoint) const MOZ_OVERRIDE; - virtual ScreenCoord GetRectLength(const ScreenRect& aRect) const MOZ_OVERRIDE; - virtual ScreenCoord GetRectOffset(const ScreenRect& aRect) const MOZ_OVERRIDE; + virtual ParentLayerCoord GetPointOffset(const ParentLayerPoint& aPoint) const MOZ_OVERRIDE; + virtual ParentLayerCoord GetRectLength(const ParentLayerRect& aRect) const MOZ_OVERRIDE; + virtual ParentLayerCoord GetRectOffset(const ParentLayerRect& aRect) const MOZ_OVERRIDE; virtual ScreenPoint MakePoint(ScreenCoord aCoord) const MOZ_OVERRIDE; }; diff --git a/gfx/layers/apz/src/GestureEventListener.cpp b/gfx/layers/apz/src/GestureEventListener.cpp index d7095eb66fbf..76a8b5d8ec95 100644 --- a/gfx/layers/apz/src/GestureEventListener.cpp +++ b/gfx/layers/apz/src/GestureEventListener.cpp @@ -34,19 +34,30 @@ static const uint32_t MAX_TAP_TIME = 300; */ static const float PINCH_START_THRESHOLD = 35.0f; -ScreenPoint GetCurrentFocus(const MultiTouchInput& aEvent) +ParentLayerPoint GetCurrentFocus(const MultiTouchInput& aEvent) { - const ScreenIntPoint& firstTouch = aEvent.mTouches[0].mScreenPoint, - secondTouch = aEvent.mTouches[1].mScreenPoint; - return ScreenPoint(firstTouch + secondTouch) / 2; + const ParentLayerPoint& firstTouch = aEvent.mTouches[0].mLocalScreenPoint; + const ParentLayerPoint& secondTouch = aEvent.mTouches[1].mLocalScreenPoint; + return (firstTouch + secondTouch) / 2; } float GetCurrentSpan(const MultiTouchInput& aEvent) { - const ScreenIntPoint& firstTouch = aEvent.mTouches[0].mScreenPoint, - secondTouch = aEvent.mTouches[1].mScreenPoint; - ScreenIntPoint delta = secondTouch - firstTouch; - return float(NS_hypot(delta.x, delta.y)); + const ParentLayerPoint& firstTouch = aEvent.mTouches[0].mLocalScreenPoint; + const ParentLayerPoint& secondTouch = aEvent.mTouches[1].mLocalScreenPoint; + ParentLayerPoint delta = secondTouch - firstTouch; + return delta.Length(); +} + +TapGestureInput CreateTapEvent(const MultiTouchInput& aTouch, TapGestureInput::TapGestureType aType) +{ + return TapGestureInput(aType, + aTouch.mTime, + aTouch.mTimeStamp, + // Use mLocalScreenPoint as this goes directly to APZC + // without being transformed in APZCTreeManager. + aTouch.mTouches[0].mLocalScreenPoint, + aTouch.modifiers); } GestureEventListener::GestureEventListener(AsyncPanZoomController* aAsyncPanZoomController) @@ -127,7 +138,7 @@ nsEventStatus GestureEventListener::HandleInputTouchSingleStart() switch (mState) { case GESTURE_NONE: SetState(GESTURE_FIRST_SINGLE_TOUCH_DOWN); - mTouchStartPosition = mLastTouchInput.mTouches[0].mScreenPoint; + mTouchStartPosition = mLastTouchInput.mTouches[0].mLocalScreenPoint; CreateLongTapTimeoutTask(); CreateMaxTapTimeoutTask(); @@ -200,10 +211,10 @@ nsEventStatus GestureEventListener::HandleInputTouchMultiStart() bool GestureEventListener::MoveDistanceIsLarge() { - const ScreenPoint start = mLastTouchInput.mTouches[0].mScreenPoint; - ScreenPoint delta = start - mTouchStartPosition; - mAsyncPanZoomController->ToGlobalScreenCoordinates(&delta, start); - return (delta.Length() > AsyncPanZoomController::GetTouchStartTolerance()); + const ParentLayerPoint start = mLastTouchInput.mTouches[0].mLocalScreenPoint; + ParentLayerPoint delta = start - mTouchStartPosition; + ScreenPoint screenDelta = mAsyncPanZoomController->ToScreenCoordinates(delta, start); + return (screenDelta.Length() > AsyncPanZoomController::GetTouchStartTolerance()); } nsEventStatus GestureEventListener::HandleInputTouchMove() @@ -314,12 +325,8 @@ nsEventStatus GestureEventListener::HandleInputTouchEnd() case GESTURE_FIRST_SINGLE_TOUCH_DOWN: { CancelLongTapTimeoutTask(); CancelMaxTapTimeoutTask(); - TapGestureInput tapEvent(TapGestureInput::TAPGESTURE_UP, - mLastTouchInput.mTime, - mLastTouchInput.mTimeStamp, - mLastTouchInput.mTouches[0].mScreenPoint, - mLastTouchInput.modifiers); - nsEventStatus tapupStatus = mAsyncPanZoomController->HandleGestureEvent(tapEvent); + nsEventStatus tapupStatus = mAsyncPanZoomController->HandleGestureEvent( + CreateTapEvent(mLastTouchInput, TapGestureInput::TAPGESTURE_UP)); if (tapupStatus == nsEventStatus_eIgnore) { SetState(GESTURE_FIRST_SINGLE_TOUCH_UP); CreateMaxTapTimeoutTask(); @@ -333,12 +340,8 @@ nsEventStatus GestureEventListener::HandleInputTouchEnd() case GESTURE_SECOND_SINGLE_TOUCH_DOWN: { CancelMaxTapTimeoutTask(); SetState(GESTURE_NONE); - TapGestureInput tapEvent(TapGestureInput::TAPGESTURE_DOUBLE, - mLastTouchInput.mTime, - mLastTouchInput.mTimeStamp, - mLastTouchInput.mTouches[0].mScreenPoint, - mLastTouchInput.modifiers); - mAsyncPanZoomController->HandleGestureEvent(tapEvent); + mAsyncPanZoomController->HandleGestureEvent( + CreateTapEvent(mLastTouchInput, TapGestureInput::TAPGESTURE_DOUBLE)); break; } @@ -350,12 +353,8 @@ nsEventStatus GestureEventListener::HandleInputTouchEnd() case GESTURE_LONG_TOUCH_DOWN: { SetState(GESTURE_NONE); - TapGestureInput tapEvent(TapGestureInput::TAPGESTURE_LONG_UP, - mLastTouchInput.mTime, - mLastTouchInput.mTimeStamp, - mLastTouchInput.mTouches[0].mScreenPoint, - mLastTouchInput.modifiers); - mAsyncPanZoomController->HandleGestureEvent(tapEvent); + mAsyncPanZoomController->HandleGestureEvent( + CreateTapEvent(mLastTouchInput, TapGestureInput::TAPGESTURE_LONG_UP)); break; } @@ -412,12 +411,8 @@ void GestureEventListener::HandleInputTimeoutLongTap() CancelMaxTapTimeoutTask(); case GESTURE_FIRST_SINGLE_TOUCH_MAX_TAP_DOWN: { SetState(GESTURE_LONG_TOUCH_DOWN); - TapGestureInput tapEvent(TapGestureInput::TAPGESTURE_LONG, - mLastTouchInput.mTime, - mLastTouchInput.mTimeStamp, - mLastTouchInput.mTouches[0].mScreenPoint, - mLastTouchInput.modifiers); - mAsyncPanZoomController->HandleGestureEvent(tapEvent); + mAsyncPanZoomController->HandleGestureEvent( + CreateTapEvent(mLastTouchInput, TapGestureInput::TAPGESTURE_LONG)); break; } default: @@ -447,12 +442,8 @@ void GestureEventListener::HandleInputTimeoutMaxTap() void GestureEventListener::TriggerSingleTapConfirmedEvent() { - TapGestureInput tapEvent(TapGestureInput::TAPGESTURE_CONFIRMED, - mLastTapInput.mTime, - mLastTapInput.mTimeStamp, - mLastTapInput.mTouches[0].mScreenPoint, - mLastTapInput.modifiers); - mAsyncPanZoomController->HandleGestureEvent(tapEvent); + mAsyncPanZoomController->HandleGestureEvent( + CreateTapEvent(mLastTapInput, TapGestureInput::TAPGESTURE_CONFIRMED)); } void GestureEventListener::SetState(GestureState aState) diff --git a/gfx/layers/apz/src/GestureEventListener.h b/gfx/layers/apz/src/GestureEventListener.h index c38ea07d2fe2..51aaddbb0288 100644 --- a/gfx/layers/apz/src/GestureEventListener.h +++ b/gfx/layers/apz/src/GestureEventListener.h @@ -8,7 +8,7 @@ #define mozilla_layers_GestureEventListener_h #include "InputData.h" // for MultiTouchInput, etc -#include "Units.h" // for ScreenIntPoint +#include "Units.h" #include "mozilla/EventForwards.h" // for nsEventStatus #include "nsAutoPtr.h" // for nsRefPtr #include "nsISupportsImpl.h" @@ -193,7 +193,7 @@ private: * or GESTURE_SECOND_SINGLE_TOUCH_DOWN then we're certain the gesture is * not tap. */ - ScreenIntPoint mTouchStartPosition; + ParentLayerPoint mTouchStartPosition; /** * Task used to timeout a long tap. This gets posted to the UI thread such diff --git a/gfx/layers/apz/util/APZCCallbackHelper.cpp b/gfx/layers/apz/util/APZCCallbackHelper.cpp index 8965caa980b3..19a0fd27c4dd 100644 --- a/gfx/layers/apz/util/APZCCallbackHelper.cpp +++ b/gfx/layers/apz/util/APZCCallbackHelper.cpp @@ -143,12 +143,10 @@ APZCCallbackHelper::UpdateRootFrame(nsIDOMWindowUtils* aUtils, aMetrics.SetScrollOffset(actualScrollOffset); // The pres shell resolution is updated by the the async zoom since the - // last paint. The ScreenToLayerScale(1.0f) reflects this async zoom being - // turned into a "sync" zoom during the repaint. - ParentLayerToLayerScale presShellResolution = aMetrics.mPresShellResolution - * aMetrics.GetAsyncZoom() - * ScreenToLayerScale(1.0f); - aUtils->SetResolution(presShellResolution.scale, presShellResolution.scale); + // last paint. + float presShellResolution = aMetrics.mPresShellResolution + * aMetrics.GetAsyncZoom().scale; + aUtils->SetResolution(presShellResolution, presShellResolution); // Finally, we set the displayport. nsCOMPtr content = nsLayoutUtils::FindContentFor(aMetrics.GetScrollId()); diff --git a/gfx/layers/client/ClientLayerManager.cpp b/gfx/layers/client/ClientLayerManager.cpp index f38e5ef6b47c..f7ca782fe96e 100644 --- a/gfx/layers/client/ClientLayerManager.cpp +++ b/gfx/layers/client/ClientLayerManager.cpp @@ -747,8 +747,8 @@ ClientLayerManager::ProgressiveUpdateCallback(bool aHasPendingNewThebesContent, aMetrics.mCriticalDisplayPort : aMetrics.mDisplayPort; LayerRect displayPort = (metricsDisplayPort + aMetrics.GetScrollOffset()) * paintScale; - ScreenPoint scrollOffset; - CSSToScreenScale zoom; + ParentLayerPoint scrollOffset; + CSSToParentLayerScale zoom; bool ret = AndroidBridge::Bridge()->ProgressiveUpdateCallback( aHasPendingNewThebesContent, displayPort, paintScale.scale, aDrawingCritical, scrollOffset, zoom); diff --git a/gfx/layers/client/ClientTiledPaintedLayer.cpp b/gfx/layers/client/ClientTiledPaintedLayer.cpp index a2691c459ed5..7f7ff2ec6581 100644 --- a/gfx/layers/client/ClientTiledPaintedLayer.cpp +++ b/gfx/layers/client/ClientTiledPaintedLayer.cpp @@ -75,7 +75,7 @@ GetTransformToAncestorsParentLayer(Layer* aStart, const LayerMetricsWrapper& aAn // If the layer has a non-transient async transform then we need to apply it here // because it will get applied by the APZ in the compositor as well const FrameMetrics& metrics = iter.Metrics(); - transform.PostScale(metrics.mPresShellResolution.scale, metrics.mPresShellResolution.scale, 1.f); + transform.PostScale(metrics.mPresShellResolution, metrics.mPresShellResolution, 1.f); } return transform; } @@ -149,16 +149,10 @@ ClientTiledPaintedLayer::BeginPaint() GetTransformToAncestorsParentLayer(this, displayPortAncestor); transformDisplayPortToLayer.Invert(); - // Note that below we use GetZoomToParent() in a number of places. Because this - // code runs on the client side, the mTransformScale field of the FrameMetrics - // will not have been set. This can result in incorrect values being returned - // by GetZoomToParent() when we have CSS transforms set on some of these layers. - // This code should be audited and updated as part of fixing bug 993525. - // Compute the critical display port that applies to this layer in the // LayoutDevice space of this layer. ParentLayerRect criticalDisplayPort = - (displayportMetrics.mCriticalDisplayPort * displayportMetrics.GetZoomToParent()) + (displayportMetrics.mCriticalDisplayPort * displayportMetrics.GetZoom()) + displayportMetrics.mCompositionBounds.TopLeft(); mPaintData.mCriticalDisplayPort = RoundedOut( ApplyParentLayerToLayerTransform(transformDisplayPortToLayer, criticalDisplayPort)); @@ -166,7 +160,7 @@ ClientTiledPaintedLayer::BeginPaint() // Store the resolution from the displayport ancestor layer. Because this is Gecko-side, // before any async transforms have occurred, we can use the zoom for this. - mPaintData.mResolution = displayportMetrics.GetZoomToParent(); + mPaintData.mResolution = displayportMetrics.GetZoom(); TILING_LOG("TILING %p: Resolution %f\n", this, mPaintData.mPresShellResolution.scale); // Store the applicable composition bounds in this layer's Layer units. @@ -179,7 +173,7 @@ ClientTiledPaintedLayer::BeginPaint() TILING_LOG("TILING %p: Composition bounds %s\n", this, Stringify(mPaintData.mCompositionBounds).c_str()); // Calculate the scroll offset since the last transaction - mPaintData.mScrollOffset = displayportMetrics.GetScrollOffset() * displayportMetrics.GetZoomToParent(); + mPaintData.mScrollOffset = displayportMetrics.GetScrollOffset() * displayportMetrics.GetZoom(); TILING_LOG("TILING %p: Scroll offset %s\n", this, Stringify(mPaintData.mScrollOffset).c_str()); } diff --git a/gfx/layers/client/TiledContentClient.cpp b/gfx/layers/client/TiledContentClient.cpp index fb165b30b942..f696cdbd6f83 100644 --- a/gfx/layers/client/TiledContentClient.cpp +++ b/gfx/layers/client/TiledContentClient.cpp @@ -150,10 +150,10 @@ ComputeViewTransform(const FrameMetrics& aContentMetrics, const FrameMetrics& aC // but with aContentMetrics used in place of mLastContentPaintMetrics, because they // should be equivalent, modulo race conditions while transactions are inflight. - ParentLayerToScreenScale scale = aCompositorMetrics.mPresShellResolution - * aCompositorMetrics.GetAsyncZoom(); - ScreenPoint translation = (aCompositorMetrics.GetScrollOffset() - aContentMetrics.GetScrollOffset()) - * aCompositorMetrics.GetZoom(); + LayerToParentLayerScale scale(aCompositorMetrics.mPresShellResolution + * aCompositorMetrics.GetAsyncZoom().scale); + ParentLayerPoint translation = (aCompositorMetrics.GetScrollOffset() - aContentMetrics.GetScrollOffset()) + * aCompositorMetrics.GetZoom(); return ViewTransform(scale, -translation); } @@ -1366,8 +1366,8 @@ GetCompositorSideCompositionBounds(const LayerMetricsWrapper& aScrollAncestor, const ViewTransform& aAPZTransform) { Matrix4x4 nonTransientAPZUntransform = Matrix4x4::Scaling( - aScrollAncestor.Metrics().mPresShellResolution.scale, - aScrollAncestor.Metrics().mPresShellResolution.scale, + aScrollAncestor.Metrics().mPresShellResolution, + aScrollAncestor.Metrics().mPresShellResolution, 1.f); nonTransientAPZUntransform.Invert(); diff --git a/gfx/layers/composite/AsyncCompositionManager.cpp b/gfx/layers/composite/AsyncCompositionManager.cpp index f19aded3e80c..e9bbfd941995 100644 --- a/gfx/layers/composite/AsyncCompositionManager.cpp +++ b/gfx/layers/composite/AsyncCompositionManager.cpp @@ -588,7 +588,7 @@ AsyncCompositionManager::ApplyAsyncContentTransformToTree(Layer *aLayer) hasAsyncTransform = true; ViewTransform asyncTransformWithoutOverscroll; - ScreenPoint scrollOffset; + ParentLayerPoint scrollOffset; controller->SampleContentTransformForFrame(&asyncTransformWithoutOverscroll, scrollOffset); Matrix4x4 overscrollTransform = controller->GetOverscrollTransform(); @@ -718,7 +718,7 @@ ApplyAsyncTransformToScrollbarForContent(Layer* aScrollbar, // aScrollbarIsDescendant hunk below we unapply the entire async // transform, which includes the nontransientasync transform and would // normally account for the resolution. - scale *= metrics.mPresShellResolution.scale; + scale *= metrics.mPresShellResolution; } scrollbarTransform.PostScale(1.f, 1.f / transientTransform._22, 1.f); scrollbarTransform.PostTranslate(0, -transientTransform._42 * scale, 0); @@ -726,7 +726,7 @@ ApplyAsyncTransformToScrollbarForContent(Layer* aScrollbar, if (aScrollbar->GetScrollbarDirection() == Layer::HORIZONTAL) { float scale = metrics.CalculateCompositedSizeInCssPixels().width / metrics.mScrollableRect.width; if (aScrollbarIsDescendant) { - scale *= metrics.mPresShellResolution.scale; + scale *= metrics.mPresShellResolution; } scrollbarTransform.PostScale(1.f / transientTransform._11, 1.f, 1.f); scrollbarTransform.PostTranslate(-transientTransform._41 * scale, 0, 0); @@ -868,8 +868,8 @@ AsyncCompositionManager::TransformScrollableLayer(Layer* aLayer) // appears to be that metrics.mZoom is poorly initialized in some scenarios. In these scenarios, // however, we can assume there is no async zooming in progress and so the following statement // works fine. - CSSToScreenScale userZoom(metrics.mDevPixelsPerCSSPixel * metrics.mCumulativeResolution * LayerToScreenScale(1)); - ScreenPoint userScroll = metrics.GetScrollOffset() * userZoom; + CSSToParentLayerScale userZoom(metrics.mDevPixelsPerCSSPixel * metrics.mCumulativeResolution * LayerToParentLayerScale(1)); + ParentLayerPoint userScroll = metrics.GetScrollOffset() * userZoom; SyncViewportInfo(displayPort, geckoZoom, mLayersUpdated, userScroll, userZoom, fixedLayerMargins, offset); @@ -884,15 +884,15 @@ AsyncCompositionManager::TransformScrollableLayer(Layer* aLayer) // primary scrollable layer. We compare this to the user zoom and scroll // offset in the view transform we obtained from Java in order to compute the // transformation we need to apply. - ScreenPoint geckoScroll(0, 0); + ParentLayerPoint geckoScroll(0, 0); if (metrics.IsScrollable()) { geckoScroll = metrics.GetScrollOffset() * userZoom; } - LayerToScreenScale asyncZoom = userZoom / metrics.LayersPixelsPerCSSPixel(); - ParentLayerToScreenScale scale = metrics.mPresShellResolution - * asyncZoom; - ScreenPoint translation = userScroll - geckoScroll; + LayerToParentLayerScale asyncZoom = userZoom / metrics.LayersPixelsPerCSSPixel(); + LayerToParentLayerScale scale(metrics.mPresShellResolution + * asyncZoom.scale); + ParentLayerPoint translation = userScroll - geckoScroll; Matrix4x4 treeTransform = ViewTransform(scale, -translation); SetShadowTransform(aLayer, oldTransform * treeTransform); @@ -901,14 +901,14 @@ AsyncCompositionManager::TransformScrollableLayer(Layer* aLayer) // Apply resolution scaling to the old transform - the layer tree as it is // doesn't have the necessary transform to display correctly. - oldTransform.PreScale(metrics.mPresShellResolution.scale, metrics.mPresShellResolution.scale, 1); + oldTransform.PreScale(metrics.mPresShellResolution, metrics.mPresShellResolution, 1); // Make sure that overscroll and under-zoom are represented in the old // transform so that fixed position content moves and scales accordingly. // These calculations will effectively scale and offset fixed position layers // in screen space when the compensatory transform is performed in // AlignFixedAndStickyLayers. - ScreenRect contentScreenRect = mContentRect * userZoom; + ParentLayerRect contentScreenRect = mContentRect * userZoom; Point3D overscrollTranslation; if (userScroll.x < contentScreenRect.x) { overscrollTranslation.x = contentScreenRect.x - userScroll.x; @@ -1018,8 +1018,8 @@ void AsyncCompositionManager::SyncViewportInfo(const LayerIntRect& aDisplayPort, const CSSToLayerScale& aDisplayResolution, bool aLayersUpdated, - ScreenPoint& aScrollOffset, - CSSToScreenScale& aScale, + ParentLayerPoint& aScrollOffset, + CSSToParentLayerScale& aScale, LayerMargin& aFixedLayerMargins, ScreenPoint& aOffset) { @@ -1035,7 +1035,7 @@ AsyncCompositionManager::SyncViewportInfo(const LayerIntRect& aDisplayPort, } void -AsyncCompositionManager::SyncFrameMetrics(const ScreenPoint& aScrollOffset, +AsyncCompositionManager::SyncFrameMetrics(const ParentLayerPoint& aScrollOffset, float aZoom, const CSSRect& aCssPageRect, bool aLayersUpdated, diff --git a/gfx/layers/composite/AsyncCompositionManager.h b/gfx/layers/composite/AsyncCompositionManager.h index 7e237966c001..73b21700a47d 100644 --- a/gfx/layers/composite/AsyncCompositionManager.h +++ b/gfx/layers/composite/AsyncCompositionManager.h @@ -28,8 +28,8 @@ class AutoResolveRefLayers; // Represents (affine) transforms that are calculated from a content view. struct ViewTransform { - explicit ViewTransform(ParentLayerToScreenScale aScale = ParentLayerToScreenScale(), - ScreenPoint aTranslation = ScreenPoint()) + explicit ViewTransform(LayerToParentLayerScale aScale = LayerToParentLayerScale(), + ParentLayerPoint aTranslation = ParentLayerPoint()) : mScale(aScale) , mTranslation(aTranslation) {} @@ -55,8 +55,8 @@ struct ViewTransform { return !(*this == rhs); } - ParentLayerToScreenScale mScale; - ScreenPoint mTranslation; + LayerToParentLayerScale mScale; + ParentLayerPoint mTranslation; }; /** @@ -139,11 +139,11 @@ private: void SyncViewportInfo(const LayerIntRect& aDisplayPort, const CSSToLayerScale& aDisplayResolution, bool aLayersUpdated, - ScreenPoint& aScrollOffset, - CSSToScreenScale& aScale, + ParentLayerPoint& aScrollOffset, + CSSToParentLayerScale& aScale, LayerMargin& aFixedLayerMargins, ScreenPoint& aOffset); - void SyncFrameMetrics(const ScreenPoint& aScrollOffset, + void SyncFrameMetrics(const ParentLayerPoint& aScrollOffset, float aZoom, const CSSRect& aCssPageRect, bool aLayersUpdated, diff --git a/gfx/tests/gtest/TestAsyncPanZoomController.cpp b/gfx/tests/gtest/TestAsyncPanZoomController.cpp index d47cd48ff914..6c21220b7d87 100644 --- a/gfx/tests/gtest/TestAsyncPanZoomController.cpp +++ b/gfx/tests/gtest/TestAsyncPanZoomController.cpp @@ -188,7 +188,7 @@ public: bool SampleContentTransformForFrame(const TimeStamp& aSampleTime, ViewTransform* aOutTransform, - ScreenPoint& aScrollOffset) { + ParentLayerPoint& aScrollOffset) { bool ret = AdvanceAnimations(aSampleTime); AsyncPanZoomController::SampleContentTransformForFrame( aOutTransform, aScrollOffset); @@ -243,12 +243,12 @@ protected: void MakeApzcZoomable() { - apzc->UpdateZoomConstraints(ZoomConstraints(true, true, CSSToScreenScale(0.25f), CSSToScreenScale(4.0f))); + apzc->UpdateZoomConstraints(ZoomConstraints(true, true, CSSToParentLayerScale(0.25f), CSSToParentLayerScale(4.0f))); } void MakeApzcUnzoomable() { - apzc->UpdateZoomConstraints(ZoomConstraints(false, false, CSSToScreenScale(1.0f), CSSToScreenScale(1.0f))); + apzc->UpdateZoomConstraints(ZoomConstraints(false, false, CSSToParentLayerScale(1.0f), CSSToParentLayerScale(1.0f))); } AsyncPanZoomController::GestureBehavior mGestureBehavior; @@ -277,11 +277,33 @@ public: * code to dispatch input events. */ +// Some helper functions for constructing input event objects suitable to be +// passed either to an APZC (which expects an transformed point), or to an APZTM +// (which expects an untransformed point). We handle both cases by setting both +// the transformed and untransformed fields to the same value. +static SingleTouchData +CreateSingleTouchData(int32_t aIdentifier, int aX, int aY) +{ + SingleTouchData touch(aIdentifier, ScreenIntPoint(aX, aY), ScreenSize(0, 0), 0, 0); + touch.mLocalScreenPoint = ParentLayerPoint(aX, aY); + return touch; +} +static PinchGestureInput +CreatePinchGestureInput(PinchGestureInput::PinchGestureType aType, + int aFocusX, int aFocusY, + float aCurrentSpan, float aPreviousSpan) +{ + PinchGestureInput result(aType, 0, TimeStamp(), ScreenPoint(aFocusX, aFocusY), + aCurrentSpan, aPreviousSpan, 0); + result.mLocalFocusPoint = ParentLayerPoint(aFocusX, aFocusY); + return result; +} + template static nsEventStatus TouchDown(const nsRefPtr& aTarget, int aX, int aY, int aTime, uint64_t* aOutInputBlockId = nullptr) { MultiTouchInput mti = MultiTouchInput(MultiTouchInput::MULTITOUCH_START, aTime, TimeStamp(), 0); - mti.mTouches.AppendElement(SingleTouchData(0, ScreenIntPoint(aX, aY), ScreenSize(0, 0), 0, 0)); + mti.mTouches.AppendElement(CreateSingleTouchData(0, aX, aY)); return aTarget->ReceiveInputEvent(mti, nullptr, aOutInputBlockId); } @@ -289,7 +311,7 @@ template static nsEventStatus TouchMove(const nsRefPtr& aTarget, int aX, int aY, int aTime) { MultiTouchInput mti = MultiTouchInput(MultiTouchInput::MULTITOUCH_MOVE, aTime, TimeStamp(), 0); - mti.mTouches.AppendElement(SingleTouchData(0, ScreenIntPoint(aX, aY), ScreenSize(0, 0), 0, 0)); + mti.mTouches.AppendElement(CreateSingleTouchData(0, aX, aY)); return aTarget->ReceiveInputEvent(mti, nullptr, nullptr); } @@ -297,7 +319,7 @@ template static nsEventStatus TouchUp(const nsRefPtr& aTarget, int aX, int aY, int aTime) { MultiTouchInput mti = MultiTouchInput(MultiTouchInput::MULTITOUCH_END, aTime, TimeStamp(), 0); - mti.mTouches.AppendElement(SingleTouchData(0, ScreenIntPoint(aX, aY), ScreenSize(0, 0), 0, 0)); + mti.mTouches.AppendElement(CreateSingleTouchData(0, aX, aY)); return aTarget->ReceiveInputEvent(mti, nullptr, nullptr); } @@ -435,28 +457,25 @@ PinchWithPinchInput(const nsRefPtr& aTarget, nsEventStatus (*aOutEventStatuses)[3] = nullptr) { nsEventStatus actualStatus = aTarget->ReceiveInputEvent( - PinchGestureInput(PinchGestureInput::PINCHGESTURE_START, - 0, TimeStamp(), ScreenPoint(aFocusX, aFocusY), - 10.0, 10.0, 0), - nullptr); + CreatePinchGestureInput(PinchGestureInput::PINCHGESTURE_START, + aFocusX, aFocusY, 10.0, 10.0), + nullptr); if (aOutEventStatuses) { (*aOutEventStatuses)[0] = actualStatus; } actualStatus = aTarget->ReceiveInputEvent( - PinchGestureInput(PinchGestureInput::PINCHGESTURE_SCALE, - 0, TimeStamp(), ScreenPoint(aFocusX, aFocusY), - 10.0 * aScale, 10.0, 0), - nullptr); + CreatePinchGestureInput(PinchGestureInput::PINCHGESTURE_SCALE, + aFocusX, aFocusY, 10.0 * aScale, 10.0), + nullptr); if (aOutEventStatuses) { (*aOutEventStatuses)[1] = actualStatus; } actualStatus = aTarget->ReceiveInputEvent( - PinchGestureInput(PinchGestureInput::PINCHGESTURE_END, - 0, TimeStamp(), ScreenPoint(aFocusX, aFocusY), - // note: negative values here tell APZC - // not to turn the pinch into a pan - -1.0, -1.0, 0), - nullptr); + CreatePinchGestureInput(PinchGestureInput::PINCHGESTURE_END, + // note: negative values here tell APZC + // not to turn the pinch into a pan + aFocusX, aFocusY, -1.0, -1.0), + nullptr); if (aOutEventStatuses) { (*aOutEventStatuses)[2] = actualStatus; } @@ -498,8 +517,8 @@ PinchWithTouchInput(const nsRefPtr& aTarget, } MultiTouchInput mtiStart = MultiTouchInput(MultiTouchInput::MULTITOUCH_START, 0, TimeStamp(), 0); - mtiStart.mTouches.AppendElement(SingleTouchData(inputId, ScreenIntPoint(aFocusX, aFocusY), ScreenSize(0, 0), 0, 0)); - mtiStart.mTouches.AppendElement(SingleTouchData(inputId + 1, ScreenIntPoint(aFocusX, aFocusY), ScreenSize(0, 0), 0, 0)); + mtiStart.mTouches.AppendElement(CreateSingleTouchData(inputId, aFocusX, aFocusY)); + mtiStart.mTouches.AppendElement(CreateSingleTouchData(inputId + 1, aFocusX, aFocusY)); nsEventStatus status = aTarget->ReceiveInputEvent(mtiStart, aOutInputBlockId); if (aOutEventStatuses) { (*aOutEventStatuses)[0] = status; @@ -510,24 +529,24 @@ PinchWithTouchInput(const nsRefPtr& aTarget, } MultiTouchInput mtiMove1 = MultiTouchInput(MultiTouchInput::MULTITOUCH_MOVE, 0, TimeStamp(), 0); - mtiMove1.mTouches.AppendElement(SingleTouchData(inputId, ScreenIntPoint(aFocusX - pinchLength, aFocusY), ScreenSize(0, 0), 0, 0)); - mtiMove1.mTouches.AppendElement(SingleTouchData(inputId + 1, ScreenIntPoint(aFocusX + pinchLength, aFocusY), ScreenSize(0, 0), 0, 0)); + mtiMove1.mTouches.AppendElement(CreateSingleTouchData(inputId, aFocusX - pinchLength, aFocusY)); + mtiMove1.mTouches.AppendElement(CreateSingleTouchData(inputId + 1, aFocusX + pinchLength, aFocusY)); status = aTarget->ReceiveInputEvent(mtiMove1, nullptr); if (aOutEventStatuses) { (*aOutEventStatuses)[1] = status; } MultiTouchInput mtiMove2 = MultiTouchInput(MultiTouchInput::MULTITOUCH_MOVE, 0, TimeStamp(), 0); - mtiMove2.mTouches.AppendElement(SingleTouchData(inputId, ScreenIntPoint(aFocusX - pinchLengthScaled, aFocusY), ScreenSize(0, 0), 0, 0)); - mtiMove2.mTouches.AppendElement(SingleTouchData(inputId + 1, ScreenIntPoint(aFocusX + pinchLengthScaled, aFocusY), ScreenSize(0, 0), 0, 0)); + mtiMove2.mTouches.AppendElement(CreateSingleTouchData(inputId, aFocusX - pinchLengthScaled, aFocusY)); + mtiMove2.mTouches.AppendElement(CreateSingleTouchData(inputId + 1, aFocusX + pinchLengthScaled, aFocusY)); status = aTarget->ReceiveInputEvent(mtiMove2, nullptr); if (aOutEventStatuses) { (*aOutEventStatuses)[2] = status; } MultiTouchInput mtiEnd = MultiTouchInput(MultiTouchInput::MULTITOUCH_END, 0, TimeStamp(), 0); - mtiEnd.mTouches.AppendElement(SingleTouchData(inputId, ScreenIntPoint(aFocusX - pinchLengthScaled, aFocusY), ScreenSize(0, 0), 0, 0)); - mtiEnd.mTouches.AppendElement(SingleTouchData(inputId + 1, ScreenIntPoint(aFocusX + pinchLengthScaled, aFocusY), ScreenSize(0, 0), 0, 0)); + mtiEnd.mTouches.AppendElement(CreateSingleTouchData(inputId, aFocusX - pinchLengthScaled, aFocusY)); + mtiEnd.mTouches.AppendElement(CreateSingleTouchData(inputId + 1, aFocusX + pinchLengthScaled, aFocusY)); status = aTarget->ReceiveInputEvent(mtiEnd, nullptr); if (aOutEventStatuses) { (*aOutEventStatuses)[3] = status; @@ -567,7 +586,7 @@ protected: fm.mCompositionBounds = ParentLayerRect(200, 200, 100, 200); fm.mScrollableRect = CSSRect(0, 0, 980, 1000); fm.SetScrollOffset(CSSPoint(300, 300)); - fm.SetZoom(CSSToScreenScale(2.0)); + fm.SetZoom(CSSToParentLayerScale(2.0)); // the visible area of the document in CSS pixels is x=300 y=300 w=50 h=100 return fm; } @@ -610,7 +629,7 @@ protected: // part 2 of the test, move to the top-right corner of the page and pinch and // make sure we stay in the correct spot - fm.SetZoom(CSSToScreenScale(2.0)); + fm.SetZoom(CSSToParentLayerScale(2.0)); fm.SetScrollOffset(CSSPoint(930, 5)); apzc->SetFrameMetrics(fm); // the visible area of the document in CSS pixels is x=930 y=5 w=50 h=100 @@ -709,7 +728,7 @@ TEST_F(APZCBasicTester, Overzoom) { fm.mCompositionBounds = ParentLayerRect(0, 0, 100, 100); fm.mScrollableRect = CSSRect(0, 0, 125, 150); fm.SetScrollOffset(CSSPoint(10, 0)); - fm.SetZoom(CSSToScreenScale(1.0)); + fm.SetZoom(CSSToParentLayerScale(1.0)); apzc->SetFrameMetrics(fm); MakeApzcZoomable(); @@ -728,11 +747,11 @@ TEST_F(APZCBasicTester, Overzoom) { } TEST_F(APZCBasicTester, SimpleTransform) { - ScreenPoint pointOut; + ParentLayerPoint pointOut; ViewTransform viewTransformOut; apzc->SampleContentTransformForFrame(testStartTime, &viewTransformOut, pointOut); - EXPECT_EQ(ScreenPoint(), pointOut); + EXPECT_EQ(ParentLayerPoint(), pointOut); EXPECT_EQ(ViewTransform(), viewTransformOut); } @@ -778,8 +797,8 @@ TEST_F(APZCBasicTester, ComplexTransform) { metrics.SetScrollOffset(CSSPoint(10, 10)); metrics.mScrollableRect = CSSRect(0, 0, 50, 50); metrics.mCumulativeResolution = LayoutDeviceToLayerScale(2); - metrics.mPresShellResolution = ParentLayerToLayerScale(2); - metrics.SetZoom(CSSToScreenScale(6)); + metrics.mPresShellResolution = 2.0f; + metrics.SetZoom(CSSToParentLayerScale(6)); metrics.mDevPixelsPerCSSPixel = CSSToLayoutDeviceScale(3); metrics.SetScrollId(FrameMetrics::START_SCROLL_ID); @@ -789,7 +808,7 @@ TEST_F(APZCBasicTester, ComplexTransform) { layers[0]->SetFrameMetrics(metrics); layers[1]->SetFrameMetrics(childMetrics); - ScreenPoint pointOut; + ParentLayerPoint pointOut; ViewTransform viewTransformOut; // Both the parent and child layer should behave exactly the same here, because @@ -799,40 +818,40 @@ TEST_F(APZCBasicTester, ComplexTransform) { apzc->SetFrameMetrics(metrics); apzc->NotifyLayersUpdated(metrics, true); apzc->SampleContentTransformForFrame(testStartTime, &viewTransformOut, pointOut); - EXPECT_EQ(ViewTransform(ParentLayerToScreenScale(2), ScreenPoint()), viewTransformOut); - EXPECT_EQ(ScreenPoint(60, 60), pointOut); + EXPECT_EQ(ViewTransform(LayerToParentLayerScale(2), ParentLayerPoint()), viewTransformOut); + EXPECT_EQ(ParentLayerPoint(60, 60), pointOut); childApzc->SetFrameMetrics(childMetrics); childApzc->NotifyLayersUpdated(childMetrics, true); childApzc->SampleContentTransformForFrame(testStartTime, &viewTransformOut, pointOut); - EXPECT_EQ(ViewTransform(ParentLayerToScreenScale(2), ScreenPoint()), viewTransformOut); - EXPECT_EQ(ScreenPoint(60, 60), pointOut); + EXPECT_EQ(ViewTransform(LayerToParentLayerScale(2), ParentLayerPoint()), viewTransformOut); + EXPECT_EQ(ParentLayerPoint(60, 60), pointOut); // do an async scroll by 5 pixels and check the transform metrics.ScrollBy(CSSPoint(5, 0)); apzc->SetFrameMetrics(metrics); apzc->SampleContentTransformForFrame(testStartTime, &viewTransformOut, pointOut); - EXPECT_EQ(ViewTransform(ParentLayerToScreenScale(2), ScreenPoint(-30, 0)), viewTransformOut); - EXPECT_EQ(ScreenPoint(90, 60), pointOut); + EXPECT_EQ(ViewTransform(LayerToParentLayerScale(2), ParentLayerPoint(-30, 0)), viewTransformOut); + EXPECT_EQ(ParentLayerPoint(90, 60), pointOut); childMetrics.ScrollBy(CSSPoint(5, 0)); childApzc->SetFrameMetrics(childMetrics); childApzc->SampleContentTransformForFrame(testStartTime, &viewTransformOut, pointOut); - EXPECT_EQ(ViewTransform(ParentLayerToScreenScale(2), ScreenPoint(-30, 0)), viewTransformOut); - EXPECT_EQ(ScreenPoint(90, 60), pointOut); + EXPECT_EQ(ViewTransform(LayerToParentLayerScale(2), ParentLayerPoint(-30, 0)), viewTransformOut); + EXPECT_EQ(ParentLayerPoint(90, 60), pointOut); // do an async zoom of 1.5x and check the transform metrics.ZoomBy(1.5f); apzc->SetFrameMetrics(metrics); apzc->SampleContentTransformForFrame(testStartTime, &viewTransformOut, pointOut); - EXPECT_EQ(ViewTransform(ParentLayerToScreenScale(3), ScreenPoint(-45, 0)), viewTransformOut); - EXPECT_EQ(ScreenPoint(135, 90), pointOut); + EXPECT_EQ(ViewTransform(LayerToParentLayerScale(3), ParentLayerPoint(-45, 0)), viewTransformOut); + EXPECT_EQ(ParentLayerPoint(135, 90), pointOut); childMetrics.ZoomBy(1.5f); childApzc->SetFrameMetrics(childMetrics); childApzc->SampleContentTransformForFrame(testStartTime, &viewTransformOut, pointOut); - EXPECT_EQ(ViewTransform(ParentLayerToScreenScale(3), ScreenPoint(-45, 0)), viewTransformOut); - EXPECT_EQ(ScreenPoint(135, 90), pointOut); + EXPECT_EQ(ViewTransform(LayerToParentLayerScale(3), ParentLayerPoint(-45, 0)), viewTransformOut); + EXPECT_EQ(ParentLayerPoint(135, 90), pointOut); } class APZCPanningTester : public APZCBasicTester { @@ -850,7 +869,7 @@ protected: int time = 0; int touchStart = 50; int touchEnd = 10; - ScreenPoint pointOut; + ParentLayerPoint pointOut; ViewTransform viewTransformOut; nsTArray allowedTouchBehaviors; @@ -861,10 +880,10 @@ protected: apzc->SampleContentTransformForFrame(testStartTime, &viewTransformOut, pointOut); if (aShouldTriggerScroll) { - EXPECT_EQ(ScreenPoint(0, -(touchEnd-touchStart)), pointOut); + EXPECT_EQ(ParentLayerPoint(0, -(touchEnd-touchStart)), pointOut); EXPECT_NE(ViewTransform(), viewTransformOut); } else { - EXPECT_EQ(ScreenPoint(), pointOut); + EXPECT_EQ(ParentLayerPoint(), pointOut); EXPECT_EQ(ViewTransform(), viewTransformOut); } @@ -876,7 +895,7 @@ protected: PanAndCheckStatus(apzc, time, touchEnd, touchStart, aShouldBeConsumed, &allowedTouchBehaviors); apzc->SampleContentTransformForFrame(testStartTime, &viewTransformOut, pointOut); - EXPECT_EQ(ScreenPoint(), pointOut); + EXPECT_EQ(ParentLayerPoint(), pointOut); EXPECT_EQ(ViewTransform(), viewTransformOut); } @@ -887,7 +906,7 @@ protected: int time = 0; int touchStart = 50; int touchEnd = 10; - ScreenPoint pointOut; + ParentLayerPoint pointOut; ViewTransform viewTransformOut; uint64_t blockId = 0; @@ -904,7 +923,7 @@ protected: EXPECT_LE(1, mcc->RunThroughDelayedTasks()); apzc->SampleContentTransformForFrame(testStartTime, &viewTransformOut, pointOut); - EXPECT_EQ(ScreenPoint(), pointOut); + EXPECT_EQ(ParentLayerPoint(), pointOut); EXPECT_EQ(ViewTransform(), viewTransformOut); apzc->AssertStateIsReset(); @@ -961,12 +980,12 @@ TEST_F(APZCBasicTester, Fling) { int time = 0; int touchStart = 50; int touchEnd = 10; - ScreenPoint pointOut; + ParentLayerPoint pointOut; ViewTransform viewTransformOut; // Fling down. Each step scroll further down Pan(apzc, time, touchStart, touchEnd); - ScreenPoint lastPoint; + ParentLayerPoint lastPoint; for (int i = 1; i < 50; i+=1) { apzc->SampleContentTransformForFrame(testStartTime+TimeDuration::FromMilliseconds(i), &viewTransformOut, pointOut); EXPECT_GT(pointOut.y, lastPoint.y); @@ -1054,11 +1073,11 @@ TEST_F(APZCBasicTester, OverScrollPanning) { // Check that we recover from overscroll via an animation. const TimeDuration increment = TimeDuration::FromMilliseconds(1); bool recoveredFromOverscroll = false; - ScreenPoint pointOut; + ParentLayerPoint pointOut; ViewTransform viewTransformOut; while (apzc->SampleContentTransformForFrame(testStartTime, &viewTransformOut, pointOut)) { // The reported scroll offset should be the same throughout. - EXPECT_EQ(ScreenPoint(0, 90), pointOut); + EXPECT_EQ(ParentLayerPoint(0, 90), pointOut); if (!apzc->IsOverscrolled()) { recoveredFromOverscroll = true; @@ -1080,7 +1099,7 @@ TEST_F(APZCBasicTester, OverScrollAbort) { Pan(apzc, time, touchStart, touchEnd); EXPECT_TRUE(apzc->IsOverscrolled()); - ScreenPoint pointOut; + ParentLayerPoint pointOut; ViewTransform viewTransformOut; // This sample call will run to the end of the fling animation @@ -1140,7 +1159,7 @@ protected: int tapCallsExpected = aSlow ? 1 : 0; // Advance the fling animation by timeDelta milliseconds. - ScreenPoint pointOut; + ParentLayerPoint pointOut; ViewTransform viewTransformOut; apzc->SampleContentTransformForFrame(testStartTime + TimeDuration::FromMilliseconds(timeDelta), &viewTransformOut, pointOut); @@ -1151,7 +1170,7 @@ protected: while (mcc->RunThroughDelayedTasks()); // Verify that we didn't advance any further after the fling was aborted, in either case. - ScreenPoint finalPointOut; + ParentLayerPoint finalPointOut; apzc->SampleContentTransformForFrame(testStartTime + TimeDuration::FromMilliseconds(timeDelta + 1000), &viewTransformOut, finalPointOut); EXPECT_EQ(pointOut.x, finalPointOut.x); EXPECT_EQ(pointOut.y, finalPointOut.y); @@ -1173,7 +1192,7 @@ protected: while (mcc->RunThroughDelayedTasks()); // Sample the fling a couple of times to ensure it's going. - ScreenPoint point, finalPoint; + ParentLayerPoint point, finalPoint; ViewTransform viewTransform; apzc->SampleContentTransformForFrame(testStartTime + TimeDuration::FromMilliseconds(10), &viewTransform, point); apzc->SampleContentTransformForFrame(testStartTime + TimeDuration::FromMilliseconds(20), &viewTransform, finalPoint); @@ -1385,7 +1404,7 @@ protected: time += 1000; MultiTouchInput mti = MultiTouchInput(MultiTouchInput::MULTITOUCH_MOVE, time, TimeStamp(), 0); - mti.mTouches.AppendElement(SingleTouchData(0, ScreenIntPoint(touchX, touchEndY), ScreenSize(0, 0), 0, 0)); + mti.mTouches.AppendElement(SingleTouchData(0, ParentLayerPoint(touchX, touchEndY), ScreenSize(0, 0), 0, 0)); status = apzc->ReceiveInputEvent(mti, nullptr); EXPECT_EQ(nsEventStatus_eConsumeDoDefault, status); @@ -1393,11 +1412,11 @@ protected: status = TouchUp(apzc, touchX, touchEndY, time); EXPECT_EQ(nsEventStatus_eConsumeDoDefault, status); - ScreenPoint pointOut; + ParentLayerPoint pointOut; ViewTransform viewTransformOut; apzc->SampleContentTransformForFrame(testStartTime, &viewTransformOut, pointOut); - EXPECT_EQ(ScreenPoint(), pointOut); + EXPECT_EQ(ParentLayerPoint(), pointOut); EXPECT_EQ(ViewTransform(), viewTransformOut); apzc->AssertStateIsReset(); @@ -1563,13 +1582,13 @@ TEST_F(APZCGestureDetectorTester, TapFollowedByPinch) { int inputId = 0; MultiTouchInput mti; mti = MultiTouchInput(MultiTouchInput::MULTITOUCH_START, time, TimeStamp(), 0); - mti.mTouches.AppendElement(SingleTouchData(inputId, ScreenIntPoint(20, 20), ScreenSize(0, 0), 0, 0)); - mti.mTouches.AppendElement(SingleTouchData(inputId + 1, ScreenIntPoint(10, 10), ScreenSize(0, 0), 0, 0)); + mti.mTouches.AppendElement(SingleTouchData(inputId, ParentLayerPoint(20, 20), ScreenSize(0, 0), 0, 0)); + mti.mTouches.AppendElement(SingleTouchData(inputId + 1, ParentLayerPoint(10, 10), ScreenSize(0, 0), 0, 0)); apzc->ReceiveInputEvent(mti, nullptr); mti = MultiTouchInput(MultiTouchInput::MULTITOUCH_END, time, TimeStamp(), 0); - mti.mTouches.AppendElement(SingleTouchData(inputId, ScreenIntPoint(20, 20), ScreenSize(0, 0), 0, 0)); - mti.mTouches.AppendElement(SingleTouchData(inputId + 1, ScreenIntPoint(10, 10), ScreenSize(0, 0), 0, 0)); + mti.mTouches.AppendElement(SingleTouchData(inputId, ParentLayerPoint(20, 20), ScreenSize(0, 0), 0, 0)); + mti.mTouches.AppendElement(SingleTouchData(inputId + 1, ParentLayerPoint(10, 10), ScreenSize(0, 0), 0, 0)); apzc->ReceiveInputEvent(mti, nullptr); while (mcc->RunThroughDelayedTasks()); @@ -1588,17 +1607,17 @@ TEST_F(APZCGestureDetectorTester, TapFollowedByMultipleTouches) { int inputId = 0; MultiTouchInput mti; mti = MultiTouchInput(MultiTouchInput::MULTITOUCH_START, time, TimeStamp(), 0); - mti.mTouches.AppendElement(SingleTouchData(inputId, ScreenIntPoint(20, 20), ScreenSize(0, 0), 0, 0)); + mti.mTouches.AppendElement(SingleTouchData(inputId, ParentLayerPoint(20, 20), ScreenSize(0, 0), 0, 0)); apzc->ReceiveInputEvent(mti, nullptr); mti = MultiTouchInput(MultiTouchInput::MULTITOUCH_START, time, TimeStamp(), 0); - mti.mTouches.AppendElement(SingleTouchData(inputId, ScreenIntPoint(20, 20), ScreenSize(0, 0), 0, 0)); - mti.mTouches.AppendElement(SingleTouchData(inputId + 1, ScreenIntPoint(10, 10), ScreenSize(0, 0), 0, 0)); + mti.mTouches.AppendElement(SingleTouchData(inputId, ParentLayerPoint(20, 20), ScreenSize(0, 0), 0, 0)); + mti.mTouches.AppendElement(SingleTouchData(inputId + 1, ParentLayerPoint(10, 10), ScreenSize(0, 0), 0, 0)); apzc->ReceiveInputEvent(mti, nullptr); mti = MultiTouchInput(MultiTouchInput::MULTITOUCH_END, time, TimeStamp(), 0); - mti.mTouches.AppendElement(SingleTouchData(inputId, ScreenIntPoint(20, 20), ScreenSize(0, 0), 0, 0)); - mti.mTouches.AppendElement(SingleTouchData(inputId + 1, ScreenIntPoint(10, 10), ScreenSize(0, 0), 0, 0)); + mti.mTouches.AppendElement(SingleTouchData(inputId, ParentLayerPoint(20, 20), ScreenSize(0, 0), 0, 0)); + mti.mTouches.AppendElement(SingleTouchData(inputId + 1, ParentLayerPoint(10, 10), ScreenSize(0, 0), 0, 0)); apzc->ReceiveInputEvent(mti, nullptr); while (mcc->RunThroughDelayedTasks()); diff --git a/layout/base/UnitTransforms.h b/layout/base/UnitTransforms.h index ce1c4b59210b..c4277851b76b 100644 --- a/layout/base/UnitTransforms.h +++ b/layout/base/UnitTransforms.h @@ -21,9 +21,13 @@ namespace mozilla { MOZ_BEGIN_ENUM_CLASS(PixelCastJustification, uint8_t) // For the root layer, Screen Pixel = Parent Layer Pixel. - ScreenToParentLayerForRoot, + ScreenIsParentLayerForRoot, // For the root composition size we want to view it as layer pixels in any layer - ParentLayerToLayerForRootComposition + ParentLayerToLayerForRootComposition, + // The transform that is usually used to convert between two coordinate + // systems is not available (for example, because the object that stores it + // is being destroyed), so fall back to the identity. + TransformNotAvailable MOZ_END_ENUM_CLASS(PixelCastJustification) template @@ -34,6 +38,16 @@ template gfx::IntSizeTyped ViewAs(const gfx::IntSizeTyped& aSize, PixelCastJustification) { return gfx::IntSizeTyped(aSize.width, aSize.height); } +template +gfx::PointTyped ViewAs(const gfx::PointTyped& aPoint, PixelCastJustification) { + return gfx::PointTyped(aPoint.x, aPoint.y); +} +template +gfx::ScaleFactor ViewTargetAs( + const gfx::ScaleFactor& aScaleFactor, + PixelCastJustification) { + return gfx::ScaleFactor(aScaleFactor.scale); +} // Convenience functions for casting untyped entities to typed entities. // Using these functions does not require a justification, but once we convert @@ -91,6 +105,18 @@ static gfx::IntRectTyped TransformTo(const gfx::Matrix4x4& aTransfo return RoundedToInt(ViewAs(aTransform.TransformBounds(rect))); } +// Transform |aVector|, which is anchored at |aAnchor|, by the given transform +// matrix, yielding a point in |TargetUnits|. +// The anchor is necessary because with 3D tranforms, the location of the +// vector can affect the result of the transform. +template +static gfx::PointTyped TransformVector(const gfx::Matrix4x4& aTransform, + const gfx::PointTyped& aVector, + const gfx::PointTyped& aAnchor) { + gfx::PointTyped transformedStart = TransformTo(aTransform, aAnchor); + gfx::PointTyped transformedEnd = TransformTo(aTransform, aAnchor + aVector); + return transformedEnd - transformedStart; +} } diff --git a/layout/base/Units.h b/layout/base/Units.h index f0cd08c5971f..668acead5a0c 100644 --- a/layout/base/Units.h +++ b/layout/base/Units.h @@ -27,12 +27,25 @@ struct LayoutDevicePixel; struct LayerPixel; struct RenderTargetPixel; struct ScreenPixel; +// The layer coordinates of the parent frame. +// This can be arrived at in three ways: +// - Start with the CSS coordinates of the parent frame, multiply by the +// device scale and the cumulative resolution of the parent frame. +// - Start with the CSS coordinates of current frame, multiply by the device +// scale, the cumulative resolution of the current frame, and the scales +// from the CSS and async transforms of the current frame. +// - Start with global screen coordinates and unapply all CSS and async +// transforms from the root down to and including the parent. +// It's helpful to look at https://wiki.mozilla.org/Platform/GFX/APZ#Coordinate_systems +// to get a picture of how the various coordinate systems relate to each other. +struct ParentLayerPixel {}; template<> struct IsPixel : TrueType {}; template<> struct IsPixel : TrueType {}; template<> struct IsPixel : TrueType {}; template<> struct IsPixel : TrueType {}; template<> struct IsPixel : TrueType {}; +template<> struct IsPixel : TrueType {}; typedef gfx::CoordTyped CSSCoord; typedef gfx::IntCoordTyped CSSIntCoord; @@ -67,8 +80,6 @@ typedef gfx::IntRectTyped LayerIntRect; typedef gfx::MarginTyped LayerMargin; typedef gfx::IntMarginTyped LayerIntMargin; -typedef gfx::CoordTyped ScreenCoord; -typedef gfx::IntCoordTyped ScreenIntCoord; typedef gfx::PointTyped RenderTargetPoint; typedef gfx::IntPointTyped RenderTargetIntPoint; typedef gfx::SizeTyped RenderTargetSize; @@ -78,6 +89,8 @@ typedef gfx::IntRectTyped RenderTargetIntRect; typedef gfx::MarginTyped RenderTargetMargin; typedef gfx::IntMarginTyped RenderTargetIntMargin; +typedef gfx::CoordTyped ScreenCoord; +typedef gfx::IntCoordTyped ScreenIntCoord; typedef gfx::PointTyped ScreenPoint; typedef gfx::IntPointTyped ScreenIntPoint; typedef gfx::SizeTyped ScreenSize; @@ -87,20 +100,38 @@ typedef gfx::IntRectTyped ScreenIntRect; typedef gfx::MarginTyped ScreenMargin; typedef gfx::IntMarginTyped ScreenIntMargin; +typedef gfx::CoordTyped ParentLayerCoord; +typedef gfx::IntCoordTyped ParentLayerIntCoord; +typedef gfx::PointTyped ParentLayerPoint; +typedef gfx::IntPointTyped ParentLayerIntPoint; +typedef gfx::SizeTyped ParentLayerSize; +typedef gfx::IntSizeTyped ParentLayerIntSize; +typedef gfx::RectTyped ParentLayerRect; +typedef gfx::IntRectTyped ParentLayerIntRect; +typedef gfx::MarginTyped ParentLayerMargin; +typedef gfx::IntMarginTyped ParentLayerIntMargin; + typedef gfx::ScaleFactor CSSToLayoutDeviceScale; typedef gfx::ScaleFactor CSSToLayerScale; typedef gfx::ScaleFactor CSSToScreenScale; +typedef gfx::ScaleFactor CSSToParentLayerScale; typedef gfx::ScaleFactor LayoutDeviceToCSSScale; typedef gfx::ScaleFactor LayoutDeviceToLayerScale; typedef gfx::ScaleFactor LayoutDeviceToScreenScale; +typedef gfx::ScaleFactor LayoutDeviceToParentLayerScale; typedef gfx::ScaleFactor LayerToCSSScale; typedef gfx::ScaleFactor LayerToLayoutDeviceScale; typedef gfx::ScaleFactor LayerToRenderTargetScale; typedef gfx::ScaleFactor LayerToScreenScale; +typedef gfx::ScaleFactor LayerToParentLayerScale; typedef gfx::ScaleFactor RenderTargetToScreenScale; typedef gfx::ScaleFactor ScreenToCSSScale; typedef gfx::ScaleFactor ScreenToLayoutDeviceScale; typedef gfx::ScaleFactor ScreenToLayerScale; +typedef gfx::ScaleFactor ScreenToParentLayerScale; +typedef gfx::ScaleFactor ParentLayerToLayerScale; +typedef gfx::ScaleFactor ParentLayerToScreenScale; +typedef gfx::ScaleFactor ParentLayerToParentLayerScale; /* * The pixels that content authors use to specify sizes in. diff --git a/layout/base/nsDisplayList.cpp b/layout/base/nsDisplayList.cpp index a0f2b71bdec4..d8bbd4b2df7d 100644 --- a/layout/base/nsDisplayList.cpp +++ b/layout/base/nsDisplayList.cpp @@ -724,10 +724,9 @@ nsDisplayScrollLayer::ComputeFrameMetrics(nsIFrame* aForFrame, // Only the root scrollable frame for a given presShell should pick up // the presShell's resolution. All the other frames are 1.0. if (aScrollFrame == presShell->GetRootScrollFrame()) { - metrics.mPresShellResolution = ParentLayerToLayerScale(presShell->GetXResolution(), - presShell->GetYResolution()); + metrics.mPresShellResolution = presShell->GetXResolution(); } else { - metrics.mPresShellResolution = ParentLayerToLayerScale(1.0f); + metrics.mPresShellResolution = 1.0f; } // The cumulative resolution is the resolution at which the scroll frame's // content is actually rendered. It includes the pres shell resolutions of @@ -747,9 +746,9 @@ nsDisplayScrollLayer::ComputeFrameMetrics(nsIFrame* aForFrame, // Initially, AsyncPanZoomController should render the content to the screen // at the painted resolution. - const LayerToScreenScale layerToScreenScale(1.0f); + const LayerToParentLayerScale layerToParentLayerScale(1.0f); metrics.SetZoom(metrics.mCumulativeResolution * metrics.mDevPixelsPerCSSPixel - * layerToScreenScale); + * layerToParentLayerScale); if (presShell) { nsIDocument* document = nullptr; @@ -763,11 +762,6 @@ nsDisplayScrollLayer::ComputeFrameMetrics(nsIFrame* aForFrame, metrics.SetMayHaveTouchCaret(presShell->MayHaveTouchCaret()); } - LayoutDeviceToParentLayerScale layoutToParentLayerScale = - // The ScreenToParentLayerScale should be mTransformScale which is not calculated yet, - // but we don't yet handle CSS transforms, so we assume it's 1 here. - metrics.mCumulativeResolution * LayerToScreenScale(1.0) * ScreenToParentLayerScale(1.0); - // Calculate the composition bounds as the size of the scroll frame and // its origin relative to the reference frame. // If aScrollFrame is null, we are in a document without a root scroll frame, @@ -776,7 +770,8 @@ nsDisplayScrollLayer::ComputeFrameMetrics(nsIFrame* aForFrame, nsRect compositionBounds(frameForCompositionBoundsCalculation->GetOffsetToCrossDoc(aReferenceFrame), frameForCompositionBoundsCalculation->GetSize()); ParentLayerRect frameBounds = LayoutDeviceRect::FromAppUnits(compositionBounds, auPerDevPixel) - * layoutToParentLayerScale; + * metrics.mCumulativeResolution + * layerToParentLayerScale; metrics.mCompositionBounds = frameBounds; // For the root scroll frame of the root content document, the above calculation diff --git a/layout/base/nsLayoutUtils.cpp b/layout/base/nsLayoutUtils.cpp index 0703995a8d68..dc63311b0d8e 100644 --- a/layout/base/nsLayoutUtils.cpp +++ b/layout/base/nsLayoutUtils.cpp @@ -2784,12 +2784,11 @@ CalculateFrameMetricsForDisplayPort(nsIFrame* aScrollFrame, nsIPresShell* presShell = presContext->PresShell(); CSSToLayoutDeviceScale deviceScale(float(nsPresContext::AppUnitsPerCSSPixel()) / presContext->AppUnitsPerDevPixel()); - ParentLayerToLayerScale resolution; + float resolution = 1.0f; if (aScrollFrame == presShell->GetRootScrollFrame()) { // Only the root scrollable frame for a given presShell should pick up // the presShell's resolution. All the other frames are 1.0. - resolution = ParentLayerToLayerScale(presShell->GetXResolution(), - presShell->GetYResolution()); + resolution = presShell->GetXResolution(); } // Note: unlike in ComputeFrameMetrics(), we don't know the full cumulative // resolution including FrameMetrics::mExtraResolution, because layout hasn't @@ -2801,10 +2800,11 @@ CalculateFrameMetricsForDisplayPort(nsIFrame* aScrollFrame, presShell->GetCumulativeResolution().width * nsLayoutUtils::GetTransformToAncestorScale(aScrollFrame).width); + LayerToParentLayerScale layerToParentLayerScale(1.0f); metrics.mDevPixelsPerCSSPixel = deviceScale; metrics.mPresShellResolution = resolution; metrics.mCumulativeResolution = cumulativeResolution; - metrics.SetZoom(deviceScale * cumulativeResolution * LayerToScreenScale(1)); + metrics.SetZoom(deviceScale * cumulativeResolution * layerToParentLayerScale); // Only the size of the composition bounds is relevant to the // displayport calculation, not its origin. @@ -2816,9 +2816,7 @@ CalculateFrameMetricsForDisplayPort(nsIFrame* aScrollFrame, compBoundsScale = LayoutDeviceToParentLayerScale(res.width, res.height); } } else { - compBoundsScale = cumulativeResolution - * LayerToScreenScale(1.0f) - * ScreenToParentLayerScale(1.0f); + compBoundsScale = cumulativeResolution * layerToParentLayerScale; } metrics.mCompositionBounds = LayoutDeviceRect::FromAppUnits(nsRect(nsPoint(0, 0), compositionSize), @@ -2869,7 +2867,7 @@ nsLayoutUtils::GetOrMaybeCreateDisplayPort(nsDisplayListBuilder& aBuilder, if (!haveDisplayPort) { FrameMetrics metrics = CalculateFrameMetricsForDisplayPort(aScrollFrame, scrollableFrame); ScreenMargin displayportMargins = APZCTreeManager::CalculatePendingDisplayPort( - metrics, ScreenPoint(0.0f, 0.0f), 0.0); + metrics, ParentLayerPoint(0.0f, 0.0f), 0.0); nsIPresShell* presShell = aScrollFrame->PresContext()->GetPresShell(); gfx::IntSize alignment = gfxPlatform::GetPlatform()->UseTiling() ? gfx::IntSize(gfxPrefs::LayersTileWidth(), gfxPrefs::LayersTileHeight()) : diff --git a/widget/InputData.h b/widget/InputData.h index 6080ba8f6d38..02c3ad320a08 100644 --- a/widget/InputData.h +++ b/widget/InputData.h @@ -108,6 +108,8 @@ protected: class SingleTouchData { public: + // Construct a SingleTouchData from a Screen point. + // mLocalScreenPoint remains (0,0) unless it's set later. SingleTouchData(int32_t aIdentifier, ScreenIntPoint aScreenPoint, ScreenSize aRadius, @@ -121,6 +123,23 @@ public: { } + // Construct a SingleTouchData from a ParentLayer point. + // mScreenPoint remains (0,0) unless it's set later. + // Note: if APZ starts using the radius for anything, we should add a local + // version of that too, and have this constructor take it as a ParentLayerSize. + SingleTouchData(int32_t aIdentifier, + ParentLayerPoint aLocalScreenPoint, + ScreenSize aRadius, + float aRotationAngle, + float aForce) + : mIdentifier(aIdentifier), + mLocalScreenPoint(aLocalScreenPoint), + mRadius(aRadius), + mRotationAngle(aRotationAngle), + mForce(aForce) + { + } + SingleTouchData() { } @@ -135,6 +154,10 @@ public: // coordinates on the screen. ScreenIntPoint mScreenPoint; + // |mScreenPoint| transformed to the local coordinates of the APZC targeted + // by the hit. This is set and used by APZ. + ParentLayerPoint mLocalScreenPoint; + // Radius that the touch covers, i.e. if you're using your thumb it will // probably be larger than using your pinky, even with the same force. // Radius can be different along x and y. For example, if you press down with @@ -274,6 +297,11 @@ public: // Only non-zero if mType is PANGESTURE_PAN or PANGESTURE_MOMENTUMPAN. ScreenPoint mPanDisplacement; + + // Versions of |mPanStartPoint| and |mPanDisplacement| in the local + // coordinates of the APZC receiving the pan. These are set and used by APZ. + ParentLayerPoint mLocalPanStartPoint; + ParentLayerPoint mLocalPanDisplacement; }; /** @@ -291,6 +319,8 @@ public: PINCHGESTURE_END }; + // Construct a tap gesture from a Screen point. + // mLocalFocusPoint remains (0,0) unless it's set later. PinchGestureInput(PinchGestureType aType, uint32_t aTime, TimeStamp aTimeStamp, @@ -304,8 +334,23 @@ public: mCurrentSpan(aCurrentSpan), mPreviousSpan(aPreviousSpan) { + } - + // Construct a tap gesture from a ParentLayer point. + // mFocusPoint remains (0,0) unless it's set later. + PinchGestureInput(PinchGestureType aType, + uint32_t aTime, + TimeStamp aTimeStamp, + const ParentLayerPoint& aLocalFocusPoint, + float aCurrentSpan, + float aPreviousSpan, + Modifiers aModifiers) + : InputData(PINCHGESTURE_INPUT, aTime, aTimeStamp, aModifiers), + mType(aType), + mLocalFocusPoint(aLocalFocusPoint), + mCurrentSpan(aCurrentSpan), + mPreviousSpan(aPreviousSpan) + { } PinchGestureType mType; @@ -317,6 +362,10 @@ public: // are the coordinates on the screen of this midpoint. ScreenPoint mFocusPoint; + // |mFocusPoint| transformed to the local coordinates of the APZC targeted + // by the hit. This is set and used by APZ. + ParentLayerPoint mLocalFocusPoint; + // The distance in device pixels (though as a float for increased precision // and because it is the distance along both the x and y axis) between the // touches responsible for the pinch gesture. @@ -346,6 +395,8 @@ public: TAPGESTURE_CANCEL }; + // Construct a tap gesture from a Screen point. + // mLocalPoint remains (0,0) unless it's set later. TapGestureInput(TapGestureType aType, uint32_t aTime, TimeStamp aTimeStamp, @@ -355,12 +406,29 @@ public: mType(aType), mPoint(aPoint) { + } - + // Construct a tap gesture from a ParentLayer point. + // mPoint remains (0,0) unless it's set later. + TapGestureInput(TapGestureType aType, + uint32_t aTime, + TimeStamp aTimeStamp, + const ParentLayerPoint& aLocalPoint, + Modifiers aModifiers) + : InputData(TAPGESTURE_INPUT, aTime, aTimeStamp, aModifiers), + mType(aType), + mLocalPoint(aLocalPoint) + { } TapGestureType mType; + + // The location of the tap in screen pixels. ScreenIntPoint mPoint; + + // The location of the tap in the local coordinates of the APZC receiving it. + // This is set and used by APZ. + ParentLayerPoint mLocalPoint; }; } diff --git a/widget/android/AndroidBridge.cpp b/widget/android/AndroidBridge.cpp index d713b5db7f1f..339f67c4377b 100644 --- a/widget/android/AndroidBridge.cpp +++ b/widget/android/AndroidBridge.cpp @@ -1493,7 +1493,7 @@ AndroidBridge::SetPageRect(const CSSRect& aCssPageRect) void AndroidBridge::SyncViewportInfo(const LayerIntRect& aDisplayPort, const CSSToLayerScale& aDisplayResolution, - bool aLayersUpdated, ScreenPoint& aScrollOffset, CSSToScreenScale& aScale, + bool aLayersUpdated, ParentLayerPoint& aScrollOffset, CSSToParentLayerScale& aScale, LayerMargin& aFixedLayerMargins, ScreenPoint& aOffset) { mozilla::widget::android::GeckoLayerClient *client = mLayerClient; @@ -1512,7 +1512,7 @@ AndroidBridge::SyncViewportInfo(const LayerIntRect& aDisplayPort, const CSSToLay } ViewTransform* viewTransform = ViewTransform::Wrap(viewTransformJObj); - aScrollOffset = ScreenPoint(viewTransform->getx(), viewTransform->gety()); + aScrollOffset = ParentLayerPoint(viewTransform->getx(), viewTransform->gety()); aScale.scale = viewTransform->getscale(); aFixedLayerMargins.top = viewTransform->getfixedLayerMarginTop(); aFixedLayerMargins.right = viewTransform->getfixedLayerMarginRight(); @@ -1523,7 +1523,7 @@ AndroidBridge::SyncViewportInfo(const LayerIntRect& aDisplayPort, const CSSToLay delete viewTransform; } -void AndroidBridge::SyncFrameMetrics(const ScreenPoint& aScrollOffset, float aZoom, const CSSRect& aCssPageRect, +void AndroidBridge::SyncFrameMetrics(const ParentLayerPoint& aScrollOffset, float aZoom, const CSSRect& aCssPageRect, bool aLayersUpdated, const CSSRect& aDisplayPort, const CSSToLayerScale& aDisplayResolution, bool aIsFirstPaint, LayerMargin& aFixedLayerMargins, ScreenPoint& aOffset) { @@ -1956,7 +1956,7 @@ AndroidBridge::IsContentDocumentDisplayed() bool AndroidBridge::ProgressiveUpdateCallback(bool aHasPendingNewThebesContent, const LayerRect& aDisplayPort, float aDisplayResolution, - bool aDrawingCritical, ScreenPoint& aScrollOffset, CSSToScreenScale& aZoom) + bool aDrawingCritical, ParentLayerPoint& aScrollOffset, CSSToParentLayerScale& aZoom) { mozilla::widget::android::GeckoLayerClient *client = mLayerClient; if (!client) { diff --git a/widget/android/AndroidBridge.h b/widget/android/AndroidBridge.h index 04a3f42d0128..37da66443582 100644 --- a/widget/android/AndroidBridge.h +++ b/widget/android/AndroidBridge.h @@ -208,7 +208,7 @@ public: bool IsContentDocumentDisplayed(); bool ProgressiveUpdateCallback(bool aHasPendingNewThebesContent, const LayerRect& aDisplayPort, float aDisplayResolution, bool aDrawingCritical, - mozilla::ScreenPoint& aScrollOffset, mozilla::CSSToScreenScale& aZoom); + mozilla::ParentLayerPoint& aScrollOffset, mozilla::CSSToParentLayerScale& aZoom); void SetLayerClient(JNIEnv* env, jobject jobj); mozilla::widget::android::GeckoLayerClient* GetLayerClient() { return mLayerClient; } @@ -306,9 +306,9 @@ public: void SetFirstPaintViewport(const LayerIntPoint& aOffset, const CSSToLayerScale& aZoom, const CSSRect& aCssPageRect); void SetPageRect(const CSSRect& aCssPageRect); void SyncViewportInfo(const LayerIntRect& aDisplayPort, const CSSToLayerScale& aDisplayResolution, - bool aLayersUpdated, ScreenPoint& aScrollOffset, CSSToScreenScale& aScale, + bool aLayersUpdated, ParentLayerPoint& aScrollOffset, CSSToParentLayerScale& aScale, LayerMargin& aFixedLayerMargins, ScreenPoint& aOffset); - void SyncFrameMetrics(const ScreenPoint& aScrollOffset, float aZoom, const CSSRect& aCssPageRect, + void SyncFrameMetrics(const ParentLayerPoint& aScrollOffset, float aZoom, const CSSRect& aCssPageRect, bool aLayersUpdated, const CSSRect& aDisplayPort, const CSSToLayerScale& aDisplayResolution, bool aIsFirstPaint, LayerMargin& aFixedLayerMargins, ScreenPoint& aOffset); diff --git a/widget/windows/winrt/APZController.cpp b/widget/windows/winrt/APZController.cpp index 1cad0e91ef79..c88c9b6b35e5 100644 --- a/widget/windows/winrt/APZController.cpp +++ b/widget/windows/winrt/APZController.cpp @@ -253,8 +253,8 @@ APZController::GetRootZoomConstraints(ZoomConstraints* aOutConstraints) // from 1/4 to 4x by default. aOutConstraints->mAllowZoom = true; aOutConstraints->mAllowDoubleTapZoom = false; - aOutConstraints->mMinZoom = CSSToScreenScale(0.25f); - aOutConstraints->mMaxZoom = CSSToScreenScale(4.0f); + aOutConstraints->mMinZoom = CSSToParentLayerScale(0.25f); + aOutConstraints->mMaxZoom = CSSToParentLayerScale(4.0f); return true; } return false; From 46d4b8eac4f62f8ed9ac6854e1d0ee1431074553 Mon Sep 17 00:00:00 2001 From: Randy Lin Date: Thu, 13 Nov 2014 11:52:17 +0800 Subject: [PATCH 20/80] Bug 1082677 - [Music] When unplugging headphones, the music will be muted from the speaker. r=mwu --- dom/system/gonk/AudioManager.cpp | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/dom/system/gonk/AudioManager.cpp b/dom/system/gonk/AudioManager.cpp index dbed18fce279..bf073f160c9e 100644 --- a/dom/system/gonk/AudioManager.cpp +++ b/dom/system/gonk/AudioManager.cpp @@ -227,8 +227,14 @@ InternalSetAudioRoutesICS(SwitchState aState) AUDIO_POLICY_DEVICE_STATE_AVAILABLE, ""); sHeadsetState |= AUDIO_DEVICE_OUT_WIRED_HEADPHONE; } else if (aState == SWITCH_STATE_OFF) { - AudioSystem::setDeviceConnectionState(static_cast(sHeadsetState), - AUDIO_POLICY_DEVICE_STATE_UNAVAILABLE, ""); + if (sHeadsetState & AUDIO_DEVICE_OUT_WIRED_HEADSET) { + AudioSystem::setDeviceConnectionState(AUDIO_DEVICE_OUT_WIRED_HEADSET, + AUDIO_POLICY_DEVICE_STATE_UNAVAILABLE, ""); + } + if (sHeadsetState & AUDIO_DEVICE_OUT_WIRED_HEADPHONE) { + AudioSystem::setDeviceConnectionState(AUDIO_DEVICE_OUT_WIRED_HEADPHONE, + AUDIO_POLICY_DEVICE_STATE_UNAVAILABLE, ""); + } sHeadsetState = 0; } } From fece1d93348070f492480b30f5d9cdca750cf503 Mon Sep 17 00:00:00 2001 From: Garner Lee Date: Tue, 11 Nov 2014 11:20:00 +0100 Subject: [PATCH 21/80] Bug 1075198 - Support code generation for TypedArrays fields in generated events. r=smaug --- dom/bindings/Codegen.py | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/dom/bindings/Codegen.py b/dom/bindings/Codegen.py index 78d7f4909a9b..4e38d41763f9 100644 --- a/dom/bindings/Codegen.py +++ b/dom/bindings/Codegen.py @@ -14768,6 +14768,25 @@ class CGEventMethod(CGNativeMember): target += ".SetValue()" source += ".Value()" members += sequenceCopy % (target, source) + elif m.type.isSpiderMonkeyInterface(): + srcname = "%s.%s" % (self.args[1].name, name) + if m.type.nullable(): + members += fill( + """ + if (${srcname}.IsNull()) { + e->${varname} = nullptr; + } else { + e->${varname} = ${srcname}.Value().Obj(); + } + """, + varname=name, + srcname=srcname); + else: + members += fill( + """ + e->${varname}.set(${srcname}.Obj()); + """, + varname=name, srcname=srcname); else: members += "e->%s = %s.%s;\n" % (name, self.args[1].name, name) if m.type.isAny() or m.type.isObject() or m.type.isSpiderMonkeyInterface(): From c7ca749da66be934c4a8988f98dd3c3455e18b9c Mon Sep 17 00:00:00 2001 From: Jean-Yves Avenard Date: Wed, 12 Nov 2014 15:13:02 +1100 Subject: [PATCH 22/80] Bug 1075332 - Refactor mac audio decoder. Properly calculate timestamps. r=rillian Also, in order to prevent the MediaDecoderStateMachine to stall waiting for audio data, feed back as many decoded audio frame as were first submitted to the decoder in one go. --- dom/media/fmp4/apple/AppleATDecoder.cpp | 135 +++++++++++++++--------- dom/media/fmp4/apple/AppleATDecoder.h | 14 ++- 2 files changed, 99 insertions(+), 50 deletions(-) diff --git a/dom/media/fmp4/apple/AppleATDecoder.cpp b/dom/media/fmp4/apple/AppleATDecoder.cpp index 3ff3e51b859e..025bcd4d4fdd 100644 --- a/dom/media/fmp4/apple/AppleATDecoder.cpp +++ b/dom/media/fmp4/apple/AppleATDecoder.cpp @@ -9,7 +9,6 @@ #include "MP4Reader.h" #include "MP4Decoder.h" #include "mozilla/RefPtr.h" -#include "mozilla/ReentrantMonitor.h" #include "mp4_demuxer/Adts.h" #include "mp4_demuxer/DecoderData.h" #include "nsIThread.h" @@ -33,10 +32,11 @@ AppleATDecoder::AppleATDecoder(const mp4_demuxer::AudioDecoderConfig& aConfig, , mCallback(aCallback) , mConverter(nullptr) , mStream(nullptr) - , mCurrentAudioTimestamp(0) + , mCurrentAudioTimestamp(-1) + , mNextAudioTimestamp(-1) , mSamplePosition(0) - , mHaveOutput(false) - , mFlushed(false) + , mSizeDecoded(0) + , mLastError(noErr) { MOZ_COUNT_CTOR(AppleATDecoder); LOG("Creating Apple AudioToolbox decoder"); @@ -238,8 +238,7 @@ AppleATDecoder::SampleCallback(uint32_t aNumBytes, // Pick a multiple of the frame size close to a power of two // for efficient allocation. const uint32_t MAX_AUDIO_FRAMES = 128; - const uint32_t decodedSize = MAX_AUDIO_FRAMES * mConfig.channel_count * - sizeof(AudioDataValue); + const uint32_t maxDecodedSamples = MAX_AUDIO_FRAMES * mConfig.channel_count; // Descriptions for _decompressed_ audio packets. ignored. nsAutoArrayPtr @@ -251,14 +250,15 @@ AppleATDecoder::SampleCallback(uint32_t aNumBytes, PassthroughUserData userData = { this, aNumPackets, aNumBytes, aData, aPackets, false }; - do { - // Decompressed audio buffer - nsAutoArrayPtr decoded(new uint8_t[decodedSize]); + // Decompressed audio buffer + nsAutoArrayPtr decoded(new AudioDataValue[maxDecodedSamples]); + do { AudioBufferList decBuffer; decBuffer.mNumberBuffers = 1; decBuffer.mBuffers[0].mNumberChannels = mOutputFormat.mChannelsPerFrame; - decBuffer.mBuffers[0].mDataByteSize = decodedSize; + decBuffer.mBuffers[0].mDataByteSize = + maxDecodedSamples * sizeof(AudioDataValue); decBuffer.mBuffers[0].mData = decoded.get(); // in: the max number of packets we can handle from the decoder. @@ -274,50 +274,28 @@ AppleATDecoder::SampleCallback(uint32_t aNumBytes, if (rv && rv != kNeedMoreData) { LOG("Error decoding audio stream: %d\n", rv); - mCallback->Error(); - break; - } - LOG("%d frames decoded", numFrames); - - // If we decoded zero frames then AudioConverterFillComplexBuffer is out - // of data to provide. We drained its internal buffer completely on the - // last pass. - if (numFrames == 0 && rv == kNeedMoreData) { - LOG("FillComplexBuffer out of data exactly\n"); - mCallback->InputExhausted(); + mLastError = rv; break; } - const int rate = mOutputFormat.mSampleRate; - const int channels = mOutputFormat.mChannelsPerFrame; - - int64_t time = mCurrentAudioTimestamp; - int64_t duration = FramesToUsecs(numFrames, rate).value(); - - LOG("pushed audio at time %lfs; duration %lfs\n", - (double)time / USECS_PER_S, (double)duration / USECS_PER_S); - - AudioData* audio = new AudioData(mSamplePosition, - time, duration, numFrames, - reinterpret_cast(decoded.forget()), - channels, rate); - mCallback->Output(audio); - mHaveOutput = true; + mOutputData.AppendElements(decoded.get(), + numFrames * mConfig.channel_count); if (rv == kNeedMoreData) { // No error; we just need more data. LOG("FillComplexBuffer out of data\n"); - mCallback->InputExhausted(); break; } + LOG("%d frames decoded", numFrames); } while (true); + + mSizeDecoded += aNumBytes; } void AppleATDecoder::SetupDecoder() { LOG("Setting up Apple AudioToolbox decoder."); - mHaveOutput = false; AudioStreamBasicDescription inputFormat; nsresult rv = AppleUtils::GetRichestDecodableFormat(mStream, inputFormat); @@ -368,23 +346,84 @@ AppleATDecoder::SubmitSample(nsAutoPtr aSample) return; } } - // Push the sample to the AudioFileStream for parsing. - mSamplePosition = aSample->byte_offset; - mCurrentAudioTimestamp = aSample->composition_timestamp; - uint32_t flags = mFlushed ? kAudioFileStreamParseFlag_Discontinuity : 0; + + const Microseconds fuzz = 5; + CheckedInt upperFuzz = mNextAudioTimestamp + fuzz; + CheckedInt lowerFuzz = mNextAudioTimestamp - fuzz; + bool discontinuity = + !mNextAudioTimestamp.isValid() || mNextAudioTimestamp.value() < 0 || + !upperFuzz.isValid() || lowerFuzz.value() < 0 || + upperFuzz.value() < aSample->composition_timestamp || + lowerFuzz.value() > aSample->composition_timestamp; + + if (discontinuity) { + LOG("Discontinuity detected, expected %lld got %lld\n", + mNextAudioTimestamp.value(), aSample->composition_timestamp); + mCurrentAudioTimestamp = aSample->composition_timestamp; + mSamplePosition = aSample->byte_offset; + } + + uint32_t flags = discontinuity ? kAudioFileStreamParseFlag_Discontinuity : 0; + OSStatus rv = AudioFileStreamParseBytes(mStream, aSample->size, aSample->data, flags); + + if (!mOutputData.IsEmpty()) { + int rate = mOutputFormat.mSampleRate; + int channels = mOutputFormat.mChannelsPerFrame; + size_t numFrames = mOutputData.Length() / channels; + CheckedInt duration = FramesToUsecs(numFrames, rate); + if (!duration.isValid()) { + NS_ERROR("Invalid count of accumulated audio samples"); + mCallback->Error(); + return; + } + + LOG("pushed audio at time %lfs; duration %lfs\n", + (double)mCurrentAudioTimestamp.value() / USECS_PER_S, + (double)duration.value() / USECS_PER_S); + + nsAutoArrayPtr + data(new AudioDataValue[mOutputData.Length()]); + PodCopy(data.get(), &mOutputData[0], mOutputData.Length()); + mOutputData.Clear(); + AudioData* audio = new AudioData(mSamplePosition, + mCurrentAudioTimestamp.value(), + duration.value(), + numFrames, + data.forget(), + channels, + rate); + mCallback->Output(audio); + mCurrentAudioTimestamp += duration.value(); + if (!mCurrentAudioTimestamp.isValid()) { + NS_ERROR("Invalid count of accumulated audio samples"); + mCallback->Error(); + return; + } + mSamplePosition += mSizeDecoded; + mSizeDecoded = 0; + } + + // This is the timestamp of the next sample we should be receiving + mNextAudioTimestamp = + CheckedInt(aSample->composition_timestamp) + aSample->duration; + if (rv != noErr) { LOG("Error %d parsing audio data", rv); mCallback->Error(); + return; + } + if (mLastError != noErr) { + LOG("Error %d during decoding", mLastError); + mCallback->Error(); + mLastError = noErr; + return; } - // Sometimes we need multiple input samples before AudioToolbox - // starts decoding. If we haven't seen any output yet, ask for - // more data here. - if (!mHaveOutput) { + if (mTaskQueue->IsEmpty()) { mCallback->InputExhausted(); } } @@ -392,7 +431,9 @@ AppleATDecoder::SubmitSample(nsAutoPtr aSample) void AppleATDecoder::SignalFlush() { - mFlushed = true; + mOutputData.Clear(); + mNextAudioTimestamp = -1; + mSizeDecoded = 0; } } // namespace mozilla diff --git a/dom/media/fmp4/apple/AppleATDecoder.h b/dom/media/fmp4/apple/AppleATDecoder.h index ba3efcbcead8..f10af7728bc2 100644 --- a/dom/media/fmp4/apple/AppleATDecoder.h +++ b/dom/media/fmp4/apple/AppleATDecoder.h @@ -49,12 +49,20 @@ private: MediaDataDecoderCallback* mCallback; AudioConverterRef mConverter; AudioFileStreamID mStream; - Microseconds mCurrentAudioTimestamp; + // Timestamp of the next audio frame going to be output by the decoder. + CheckedInt mCurrentAudioTimestamp; + // Estimated timestamp of the next compressed audio packet to be supplied by + // the MP4 demuxer. + CheckedInt mNextAudioTimestamp; int64_t mSamplePosition; - bool mHaveOutput; - bool mFlushed; + // Compressed data size that has been processed by the decoder since the last + // output. + int64_t mSizeDecoded; AudioStreamBasicDescription mOutputFormat; AudioFileTypeID mFileType; + // Array containing the queued decoded audio frames, about to be output. + nsTArray mOutputData; + OSStatus mLastError; void SetupDecoder(); void SubmitSample(nsAutoPtr aSample); From 99bec8c69b17e699b0b6a3a57386d967ec36a06e Mon Sep 17 00:00:00 2001 From: Jan-Ivar Bruaroey Date: Wed, 12 Nov 2014 23:30:10 -0500 Subject: [PATCH 23/80] Bug 1097224 - Part1 - make mozCaptureStream work after onloadedmetadata even in opt build. r=jesup --- dom/html/HTMLMediaElement.cpp | 39 +++++++++++++++++++---------------- 1 file changed, 21 insertions(+), 18 deletions(-) diff --git a/dom/html/HTMLMediaElement.cpp b/dom/html/HTMLMediaElement.cpp index 1426a2ff9d06..dba8a0dad253 100644 --- a/dom/html/HTMLMediaElement.cpp +++ b/dom/html/HTMLMediaElement.cpp @@ -1793,28 +1793,31 @@ HTMLMediaElement::CaptureStreamInternal(bool aFinishWhenEnded) } #endif OutputMediaStream* out = mOutputStreams.AppendElement(); -#ifdef DEBUG - // Estimate hints based on the type of the media element - // under the preference media.capturestream_hints for the - // debug builds only. This allows WebRTC Peer Connection - // to behave appropriately when media streams generated - // via mozCaptureStream*() are added to the Peer Connection. - // This functionality is planned to be used as part of Audio - // Quality Performance testing for WebRTC. - // Bug932845: Revisit this once hints mechanism is dealt with - // holistically. uint8_t hints = 0; - if (Preferences::GetBool("media.capturestream_hints.enabled")) { - if (IsVideo() && GetVideoFrameContainer()) { - hints = DOMMediaStream::HINT_CONTENTS_VIDEO | DOMMediaStream::HINT_CONTENTS_AUDIO; - } else { - hints = DOMMediaStream::HINT_CONTENTS_AUDIO; + if (mReadyState >= nsIDOMHTMLMediaElement::HAVE_METADATA) { + hints = (mHasAudio? DOMMediaStream::HINT_CONTENTS_AUDIO : 0) | + (mHasVideo? DOMMediaStream::HINT_CONTENTS_VIDEO : 0); + } else { +#ifdef DEBUG + // Estimate hints based on the type of the media element + // under the preference media.capturestream_hints for the + // debug builds only. This allows WebRTC Peer Connection + // to behave appropriately when media streams generated + // via mozCaptureStream*() are added to the Peer Connection. + // This functionality is planned to be used as part of Audio + // Quality Performance testing for WebRTC. + // Bug932845: Revisit this once hints mechanism is dealt with + // holistically. + if (Preferences::GetBool("media.capturestream_hints.enabled")) { + if (IsVideo() && GetVideoFrameContainer()) { + hints = DOMMediaStream::HINT_CONTENTS_VIDEO | DOMMediaStream::HINT_CONTENTS_AUDIO; + } else { + hints = DOMMediaStream::HINT_CONTENTS_AUDIO; + } } +#endif } out->mStream = DOMMediaStream::CreateTrackUnionStream(window, hints); -#else - out->mStream = DOMMediaStream::CreateTrackUnionStream(window); -#endif nsRefPtr principal = GetCurrentPrincipal(); out->mStream->CombineWithPrincipal(principal); out->mFinishWhenEnded = aFinishWhenEnded; From ccb5a711f493084f10755737fcecd32b20510ebc Mon Sep 17 00:00:00 2001 From: Jan-Ivar Bruaroey Date: Wed, 12 Nov 2014 23:48:30 -0500 Subject: [PATCH 24/80] Bug 1097224 - Part 2 - correct m-line test in verifySdp in test-harness. r=drno --- dom/media/tests/mochitest/pc.js | 27 +++++++++++++------------- dom/media/tests/mochitest/templates.js | 16 +++++++-------- 2 files changed, 22 insertions(+), 21 deletions(-) diff --git a/dom/media/tests/mochitest/pc.js b/dom/media/tests/mochitest/pc.js index fb9c558b794f..83041f5fb115 100644 --- a/dom/media/tests/mochitest/pc.js +++ b/dom/media/tests/mochitest/pc.js @@ -2354,10 +2354,11 @@ PeerConnectionWrapper.prototype = { } }, - verifySdp : function PCW_verifySdp(desc, expectedType, constraints, - offerOptions, trickleIceCallback) { + verifySdp : function PCW_verifySdp(desc, expectedType, offerConstraintsList, + answerConstraintsList, offerOptions, trickleIceCallback) { info("Examining this SessionDescription: " + JSON.stringify(desc)); - info("constraints: " + JSON.stringify(constraints)); + info("offerConstraintsList: " + JSON.stringify(offerConstraintsList)); + info("answerConstraintsList: " + JSON.stringify(answerConstraintsList)); info("offerOptions: " + JSON.stringify(offerOptions)); ok(desc, "SessionDescription is not null"); is(desc.type, expectedType, "SessionDescription type is " + expectedType); @@ -2376,11 +2377,11 @@ PeerConnectionWrapper.prototype = { } //TODO: how can we check for absence/presence of m=application? - //TODO: how to handle media contraints + offer options - var audioTracks = this.countAudioTracksInMediaConstraint(constraints); - if (constraints.length === 0) { - audioTracks = this.audioInOfferOptions(offerOptions); - } + var audioTracks = + Math.max(this.countAudioTracksInMediaConstraint(offerConstraintsList), + this.countAudioTracksInMediaConstraint(answerConstraintsList)) || + this.audioInOfferOptions(offerOptions); + info("expected audio tracks: " + audioTracks); if (audioTracks == 0) { ok(!desc.sdp.contains("m=audio"), "audio m-line is absent from SDP"); @@ -2393,11 +2394,11 @@ PeerConnectionWrapper.prototype = { } - //TODO: how to handle media contraints + offer options - var videoTracks = this.countVideoTracksInMediaConstraint(constraints); - if (constraints.length === 0) { - videoTracks = this.videoInOfferOptions(offerOptions); - } + var videoTracks = + Math.max(this.countVideoTracksInMediaConstraint(offerConstraintsList), + this.countVideoTracksInMediaConstraint(answerConstraintsList)) || + this.videoInOfferOptions(offerOptions); + info("expected video tracks: " + videoTracks); if (videoTracks == 0) { ok(!desc.sdp.contains("m=video"), "video m-line is absent from SDP"); diff --git a/dom/media/tests/mochitest/templates.js b/dom/media/tests/mochitest/templates.js index 1ad52a3248e7..6d3ed12f1901 100644 --- a/dom/media/tests/mochitest/templates.js +++ b/dom/media/tests/mochitest/templates.js @@ -220,7 +220,7 @@ var commandsPeerConnection = [ 'PC_LOCAL_SANE_LOCAL_SDP', function (test) { test.pcLocal.verifySdp(test._local_offer, "offer", - test._offer_constraints, test._offer_options, + test._offer_constraints, test._answer_constraints, test._offer_options, function(trickle) { test.pcLocal.localRequiresTrickleIce = trickle; }); @@ -231,7 +231,7 @@ var commandsPeerConnection = [ 'PC_REMOTE_SANE_REMOTE_SDP', function (test) { test.pcRemote.verifySdp(test._local_offer, "offer", - test._offer_constraints, test._offer_options, + test._offer_constraints, test._answer_constraints, test._offer_options, function (trickle) { test.pcRemote.remoteRequiresTrickleIce = trickle; }); @@ -344,7 +344,7 @@ var commandsPeerConnection = [ 'PC_REMOTE_SANE_LOCAL_SDP', function (test) { test.pcRemote.verifySdp(test._remote_answer, "answer", - test._answer_constraints, test._offer_options, + test._offer_constraints, test._answer_constraints, test._offer_options, function (trickle) { test.pcRemote.localRequiresTrickleIce = trickle; }); @@ -355,7 +355,7 @@ var commandsPeerConnection = [ 'PC_LOCAL_SANE_REMOTE_SDP', function (test) { test.pcLocal.verifySdp(test._remote_answer, "answer", - test._answer_constraints, test._offer_options, + test._offer_constraints, test._answer_constraints, test._offer_options, function (trickle) { test.pcLocal.remoteRequiresTrickleIce = trickle; }); @@ -837,7 +837,7 @@ var commandsDataChannel = [ 'PC_LOCAL_SANE_LOCAL_SDP', function (test) { test.pcLocal.verifySdp(test._local_offer, "offer", - test._offer_constraints, test._offer_options, + test._offer_constraints, test._answer_constraints, test._offer_options, function(trickle) { test.pcLocal.localRequiresTrickleIce = trickle; }); @@ -848,7 +848,7 @@ var commandsDataChannel = [ 'PC_REMOTE_SANE_REMOTE_SDP', function (test) { test.pcRemote.verifySdp(test._local_offer, "offer", - test._offer_constraints, test._offer_options, + test._offer_constraints, test._answer_constraints, test._offer_options, function (trickle) { test.pcRemote.remoteRequiresTrickleIce = trickle; }); @@ -941,7 +941,7 @@ var commandsDataChannel = [ 'PC_REMOTE_SANE_LOCAL_SDP', function (test) { test.pcRemote.verifySdp(test._remote_answer, "answer", - test._answer_constraints, test._offer_options, + test._offer_constraints, test._answer_constraints, test._offer_options, function (trickle) { test.pcRemote.localRequiresTrickleIce = trickle; }); @@ -952,7 +952,7 @@ var commandsDataChannel = [ 'PC_LOCAL_SANE_REMOTE_SDP', function (test) { test.pcLocal.verifySdp(test._remote_answer, "answer", - test._answer_constraints, test._offer_options, + test._offer_constraints, test._answer_constraints, test._offer_options, function (trickle) { test.pcLocal.remoteRequiresTrickleIce = trickle; }); From cfdeb0d0fa208f145972cfb68bfe01c0db8bea86 Mon Sep 17 00:00:00 2001 From: Jan-Ivar Bruaroey Date: Thu, 13 Nov 2014 00:59:22 -0500 Subject: [PATCH 25/80] Bug 1097224 - Part 3 - test mozCaptureStream over peerConnection. r=jesup, r=drno --- dom/media/tests/mochitest/mochitest.ini | 2 + .../test_peerConnection_capturedVideo.html | 55 +++++++++++++++++++ 2 files changed, 57 insertions(+) create mode 100644 dom/media/tests/mochitest/test_peerConnection_capturedVideo.html diff --git a/dom/media/tests/mochitest/mochitest.ini b/dom/media/tests/mochitest/mochitest.ini index 479990d8d0be..d86ca64b8608 100644 --- a/dom/media/tests/mochitest/mochitest.ini +++ b/dom/media/tests/mochitest/mochitest.ini @@ -89,6 +89,8 @@ skip-if = toolkit == 'gonk' # b2g (Bug 1059867) skip-if = toolkit == 'gonk' # b2g emulator seems to be too slow (Bug 1016498 and 1008080) [test_peerConnection_bug1042791.html] skip-if = buildapp == 'b2g' || os == 'android' # bug 1043403 +[test_peerConnection_capturedVideo.html] +skip-if = toolkit == 'gonk' # b2g(Bug 960442, video support for WebRTC is disabled on b2g) [test_peerConnection_close.html] skip-if = toolkit == 'gonk' # b2g (Bug 1059867) [test_peerConnection_errorCallbacks.html] diff --git a/dom/media/tests/mochitest/test_peerConnection_capturedVideo.html b/dom/media/tests/mochitest/test_peerConnection_capturedVideo.html new file mode 100644 index 000000000000..9640b943fa95 --- /dev/null +++ b/dom/media/tests/mochitest/test_peerConnection_capturedVideo.html @@ -0,0 +1,55 @@ + + + + + + + + + + + + + +
+
+
+ + From a40abbc6ebcc55f3c2c0b9f9c1c3c9e517144b98 Mon Sep 17 00:00:00 2001 From: Jean-Yves Avenard Date: Wed, 12 Nov 2014 20:19:29 +1100 Subject: [PATCH 26/80] Bug 1097260 - Ensure video dimensions are known when loadedmetadata is fired. r=cajbir --- dom/media/mediasource/test/test_LoadedMetadataFired.html | 2 ++ 1 file changed, 2 insertions(+) diff --git a/dom/media/mediasource/test/test_LoadedMetadataFired.html b/dom/media/mediasource/test/test_LoadedMetadataFired.html index 7c34886b3278..a26590537a72 100644 --- a/dom/media/mediasource/test/test_LoadedMetadataFired.html +++ b/dom/media/mediasource/test/test_LoadedMetadataFired.html @@ -18,6 +18,8 @@ runWithMSE(function (ms, v) { v.addEventListener("loadedmetadata", function () { ok(true, "Got loadedmetadata event"); + is(v.videoWidth, 320, "videoWidth has correct initial value"); + is(v.videoHeight, 240, "videoHeight has correct initial value"); SimpleTest.finish(); }); From 95437b59b2fe0614b381cbb16e1ad171c5205a17 Mon Sep 17 00:00:00 2001 From: Ralph Giles Date: Wed, 12 Nov 2014 11:03:00 -0800 Subject: [PATCH 27/80] Bug 1097849 - Enforce sane audio sample rates in MediaEncoder. r=derf We believe the rate is constrained by the audio driver in practice, but want to verify this assumption. The valid range 8-192 kHz covers all sample rates in general use for audio data. Note we must use an error return instead of an assertion since these bounds are verified by unit tests, which do not catch MOZ_ASSERT(). --- dom/media/encoder/OpusTrackEncoder.cpp | 4 ++++ dom/media/encoder/VorbisTrackEncoder.cpp | 8 ++++---- dom/media/gtest/TestTrackEncoder.cpp | 9 +++++++++ dom/media/gtest/TestVorbisTrackEncoder.cpp | 5 +++++ 4 files changed, 22 insertions(+), 4 deletions(-) diff --git a/dom/media/encoder/OpusTrackEncoder.cpp b/dom/media/encoder/OpusTrackEncoder.cpp index c3e8e856c8ea..b034e5562dbd 100644 --- a/dom/media/encoder/OpusTrackEncoder.cpp +++ b/dom/media/encoder/OpusTrackEncoder.cpp @@ -158,6 +158,10 @@ OpusTrackEncoder::Init(int aChannels, int aSamplingRate) // let InterleaveTrackData downmix pcm data. mChannels = aChannels > MAX_CHANNELS ? MAX_CHANNELS : aChannels; + // Reject non-audio sample rates. + NS_ENSURE_TRUE(aSamplingRate >= 8000, NS_ERROR_INVALID_ARG); + NS_ENSURE_TRUE(aSamplingRate <= 192000, NS_ERROR_INVALID_ARG); + // According to www.opus-codec.org, creating an opus encoder requires the // sampling rate of source signal be one of 8000, 12000, 16000, 24000, or // 48000. If this constraint is not satisfied, we resample the input to 48kHz. diff --git a/dom/media/encoder/VorbisTrackEncoder.cpp b/dom/media/encoder/VorbisTrackEncoder.cpp index bc993f7f410e..6c50718996c6 100644 --- a/dom/media/encoder/VorbisTrackEncoder.cpp +++ b/dom/media/encoder/VorbisTrackEncoder.cpp @@ -49,10 +49,10 @@ VorbisTrackEncoder::~VorbisTrackEncoder() nsresult VorbisTrackEncoder::Init(int aChannels, int aSamplingRate) { - if (aChannels <= 0 || aChannels > 8) { - VORBISLOG("aChannels <= 0 || aChannels > 8"); - return NS_ERROR_INVALID_ARG; - } + NS_ENSURE_TRUE(aChannels > 0, NS_ERROR_INVALID_ARG); + NS_ENSURE_TRUE(aChannels <= 8, NS_ERROR_INVALID_ARG); + NS_ENSURE_TRUE(aSamplingRate >= 8000, NS_ERROR_INVALID_ARG); + NS_ENSURE_TRUE(aSamplingRate <= 192000, NS_ERROR_INVALID_ARG); // This monitor is used to wake up other methods that are waiting for encoder // to be completely initialized. diff --git a/dom/media/gtest/TestTrackEncoder.cpp b/dom/media/gtest/TestTrackEncoder.cpp index 255d8cdca1a0..01d5c86e93b4 100644 --- a/dom/media/gtest/TestTrackEncoder.cpp +++ b/dom/media/gtest/TestTrackEncoder.cpp @@ -66,6 +66,15 @@ TEST(Media, OpusEncoder_Init) // Expect false with 0 or negative sampling rate of input signal. EXPECT_FALSE(TestOpusInit(1, 0)); EXPECT_FALSE(TestOpusInit(1, -1)); + + // Verify sample rate bounds checking. + EXPECT_FALSE(TestOpusInit(2, 2000)); + EXPECT_FALSE(TestOpusInit(2, 4000)); + EXPECT_FALSE(TestOpusInit(2, 7999)); + EXPECT_TRUE(TestOpusInit(2, 8000)); + EXPECT_TRUE(TestOpusInit(2, 192000)); + EXPECT_FALSE(TestOpusInit(2, 192001)); + EXPECT_FALSE(TestOpusInit(2, 200000)); } TEST(Media, OpusEncoder_Resample) diff --git a/dom/media/gtest/TestVorbisTrackEncoder.cpp b/dom/media/gtest/TestVorbisTrackEncoder.cpp index bf9d2683d04b..22cf3b4914b0 100644 --- a/dom/media/gtest/TestVorbisTrackEncoder.cpp +++ b/dom/media/gtest/TestVorbisTrackEncoder.cpp @@ -130,6 +130,9 @@ TEST(VorbisTrackEncoder, Init) // Sample rate and channel range test. for (int i = 1; i <= 8; i++) { EXPECT_FALSE(TestVorbisInit(i, -1)); + EXPECT_FALSE(TestVorbisInit(i, 2000)); + EXPECT_FALSE(TestVorbisInit(i, 4000)); + EXPECT_FALSE(TestVorbisInit(i, 7999)); EXPECT_TRUE(TestVorbisInit(i, 8000)); EXPECT_TRUE(TestVorbisInit(i, 11000)); EXPECT_TRUE(TestVorbisInit(i, 16000)); @@ -138,6 +141,8 @@ TEST(VorbisTrackEncoder, Init) EXPECT_TRUE(TestVorbisInit(i, 44100)); EXPECT_TRUE(TestVorbisInit(i, 48000)); EXPECT_TRUE(TestVorbisInit(i, 96000)); + EXPECT_TRUE(TestVorbisInit(i, 192000)); + EXPECT_FALSE(TestVorbisInit(i, 192001)); EXPECT_FALSE(TestVorbisInit(i, 200000 + 1)); } } From e9fcf33804c172406fc61f4498cc6c15b835962e Mon Sep 17 00:00:00 2001 From: B2G Bumper Bot Date: Wed, 12 Nov 2014 15:30:55 -0800 Subject: [PATCH 28/80] Bumping gaia.json for 2 gaia revision(s) a=gaia-bump ======== https://hg.mozilla.org/integration/gaia-central/rev/8ca55a9510cd Author: James Burke Desc: Merge pull request #26086 from jrburke/bug1087184-email-contact-query-lowercase-fix Bug 1087184, second part of fix, to allow for undefined emailAddress r=asuth ======== https://hg.mozilla.org/integration/gaia-central/rev/282417be51b0 Author: jrburke Desc: Bug 1087184, second part of fix, to allow for undefined emailAddress, related to 3c1668ad793d4f1a40831c46638acef38e0db230 --- b2g/config/gaia.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/b2g/config/gaia.json b/b2g/config/gaia.json index f88c54a5e6c7..7c385d2448bf 100644 --- a/b2g/config/gaia.json +++ b/b2g/config/gaia.json @@ -4,6 +4,6 @@ "remote": "", "branch": "" }, - "revision": "2e0f2f070a2265b537e6a2ff4e0f2e1f2aca49c6", + "revision": "8ca55a9510cdcaaef742f6695ee12347210aae86", "repo_path": "integration/gaia-central" } From a03addbfdb2f121062000b37dff2245c74019943 Mon Sep 17 00:00:00 2001 From: B2G Bumper Bot Date: Wed, 12 Nov 2014 15:37:20 -0800 Subject: [PATCH 29/80] Bumping manifests a=b2g-bump --- b2g/config/dolphin/sources.xml | 2 +- b2g/config/emulator-ics/sources.xml | 2 +- b2g/config/emulator-jb/sources.xml | 2 +- b2g/config/emulator-kk/sources.xml | 2 +- b2g/config/emulator/sources.xml | 2 +- b2g/config/flame-kk/sources.xml | 2 +- b2g/config/flame/sources.xml | 2 +- b2g/config/hamachi/sources.xml | 2 +- b2g/config/helix/sources.xml | 2 +- b2g/config/nexus-4/sources.xml | 2 +- b2g/config/wasabi/sources.xml | 2 +- 11 files changed, 11 insertions(+), 11 deletions(-) diff --git a/b2g/config/dolphin/sources.xml b/b2g/config/dolphin/sources.xml index ce827928fc39..35d6eab4e24d 100644 --- a/b2g/config/dolphin/sources.xml +++ b/b2g/config/dolphin/sources.xml @@ -15,7 +15,7 @@ - + diff --git a/b2g/config/emulator-ics/sources.xml b/b2g/config/emulator-ics/sources.xml index da92c959722e..282d17ea5b06 100644 --- a/b2g/config/emulator-ics/sources.xml +++ b/b2g/config/emulator-ics/sources.xml @@ -19,7 +19,7 @@ - + diff --git a/b2g/config/emulator-jb/sources.xml b/b2g/config/emulator-jb/sources.xml index e1ae9827bee1..4d59c21dce1f 100644 --- a/b2g/config/emulator-jb/sources.xml +++ b/b2g/config/emulator-jb/sources.xml @@ -17,7 +17,7 @@ - + diff --git a/b2g/config/emulator-kk/sources.xml b/b2g/config/emulator-kk/sources.xml index d7208602a39f..32914388111c 100644 --- a/b2g/config/emulator-kk/sources.xml +++ b/b2g/config/emulator-kk/sources.xml @@ -15,7 +15,7 @@ - + diff --git a/b2g/config/emulator/sources.xml b/b2g/config/emulator/sources.xml index da92c959722e..282d17ea5b06 100644 --- a/b2g/config/emulator/sources.xml +++ b/b2g/config/emulator/sources.xml @@ -19,7 +19,7 @@ - + diff --git a/b2g/config/flame-kk/sources.xml b/b2g/config/flame-kk/sources.xml index daddb498e8d4..64c5e7c86420 100644 --- a/b2g/config/flame-kk/sources.xml +++ b/b2g/config/flame-kk/sources.xml @@ -15,7 +15,7 @@ - + diff --git a/b2g/config/flame/sources.xml b/b2g/config/flame/sources.xml index d40b7a8d6e0d..60f2b5c393cb 100644 --- a/b2g/config/flame/sources.xml +++ b/b2g/config/flame/sources.xml @@ -17,7 +17,7 @@ - + diff --git a/b2g/config/hamachi/sources.xml b/b2g/config/hamachi/sources.xml index 59778837373b..f21a577e44fa 100644 --- a/b2g/config/hamachi/sources.xml +++ b/b2g/config/hamachi/sources.xml @@ -17,7 +17,7 @@ - + diff --git a/b2g/config/helix/sources.xml b/b2g/config/helix/sources.xml index 14fd2ea64e20..5127509928a4 100644 --- a/b2g/config/helix/sources.xml +++ b/b2g/config/helix/sources.xml @@ -15,7 +15,7 @@ - + diff --git a/b2g/config/nexus-4/sources.xml b/b2g/config/nexus-4/sources.xml index 7695c1516d54..63657e0a9b23 100644 --- a/b2g/config/nexus-4/sources.xml +++ b/b2g/config/nexus-4/sources.xml @@ -17,7 +17,7 @@ - + diff --git a/b2g/config/wasabi/sources.xml b/b2g/config/wasabi/sources.xml index e26dacb00122..5df71a40a89a 100644 --- a/b2g/config/wasabi/sources.xml +++ b/b2g/config/wasabi/sources.xml @@ -17,7 +17,7 @@ - + From e91cbd797ead4804dc7bc2e18dea5535c34484a4 Mon Sep 17 00:00:00 2001 From: B2G Bumper Bot Date: Wed, 12 Nov 2014 16:00:55 -0800 Subject: [PATCH 30/80] Bumping gaia.json for 2 gaia revision(s) a=gaia-bump ======== https://hg.mozilla.org/integration/gaia-central/rev/a2d2b614eecc Author: tamarahills Desc: Merge pull request #26083 from tamarahills/bugfix/1068093v3 Bug 1068093 - Remove legacy transition code from the callscreen ======== https://hg.mozilla.org/integration/gaia-central/rev/0f497109a32c Author: Tamara Hills Desc: Bug 1068093 - Remove legacy transition code from the callscreen. r=drs --- b2g/config/gaia.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/b2g/config/gaia.json b/b2g/config/gaia.json index 7c385d2448bf..d1d0a78dd110 100644 --- a/b2g/config/gaia.json +++ b/b2g/config/gaia.json @@ -4,6 +4,6 @@ "remote": "", "branch": "" }, - "revision": "8ca55a9510cdcaaef742f6695ee12347210aae86", + "revision": "a2d2b614eecc8351f6f878f8fa44cafd36eb751f", "repo_path": "integration/gaia-central" } From e0832ded74a34c9bae3913d0c10cff315469a6d9 Mon Sep 17 00:00:00 2001 From: B2G Bumper Bot Date: Wed, 12 Nov 2014 16:07:19 -0800 Subject: [PATCH 31/80] Bumping manifests a=b2g-bump --- b2g/config/dolphin/sources.xml | 2 +- b2g/config/emulator-ics/sources.xml | 2 +- b2g/config/emulator-jb/sources.xml | 2 +- b2g/config/emulator-kk/sources.xml | 2 +- b2g/config/emulator/sources.xml | 2 +- b2g/config/flame-kk/sources.xml | 2 +- b2g/config/flame/sources.xml | 2 +- b2g/config/hamachi/sources.xml | 2 +- b2g/config/helix/sources.xml | 2 +- b2g/config/nexus-4/sources.xml | 2 +- b2g/config/wasabi/sources.xml | 2 +- 11 files changed, 11 insertions(+), 11 deletions(-) diff --git a/b2g/config/dolphin/sources.xml b/b2g/config/dolphin/sources.xml index 35d6eab4e24d..1b9d95863411 100644 --- a/b2g/config/dolphin/sources.xml +++ b/b2g/config/dolphin/sources.xml @@ -15,7 +15,7 @@ - + diff --git a/b2g/config/emulator-ics/sources.xml b/b2g/config/emulator-ics/sources.xml index 282d17ea5b06..255570ed49c6 100644 --- a/b2g/config/emulator-ics/sources.xml +++ b/b2g/config/emulator-ics/sources.xml @@ -19,7 +19,7 @@ - + diff --git a/b2g/config/emulator-jb/sources.xml b/b2g/config/emulator-jb/sources.xml index 4d59c21dce1f..73e3d651963f 100644 --- a/b2g/config/emulator-jb/sources.xml +++ b/b2g/config/emulator-jb/sources.xml @@ -17,7 +17,7 @@ - + diff --git a/b2g/config/emulator-kk/sources.xml b/b2g/config/emulator-kk/sources.xml index 32914388111c..13d556a895bf 100644 --- a/b2g/config/emulator-kk/sources.xml +++ b/b2g/config/emulator-kk/sources.xml @@ -15,7 +15,7 @@ - + diff --git a/b2g/config/emulator/sources.xml b/b2g/config/emulator/sources.xml index 282d17ea5b06..255570ed49c6 100644 --- a/b2g/config/emulator/sources.xml +++ b/b2g/config/emulator/sources.xml @@ -19,7 +19,7 @@ - + diff --git a/b2g/config/flame-kk/sources.xml b/b2g/config/flame-kk/sources.xml index 64c5e7c86420..249cdb7f65c8 100644 --- a/b2g/config/flame-kk/sources.xml +++ b/b2g/config/flame-kk/sources.xml @@ -15,7 +15,7 @@ - + diff --git a/b2g/config/flame/sources.xml b/b2g/config/flame/sources.xml index 60f2b5c393cb..fc1deb30b534 100644 --- a/b2g/config/flame/sources.xml +++ b/b2g/config/flame/sources.xml @@ -17,7 +17,7 @@ - + diff --git a/b2g/config/hamachi/sources.xml b/b2g/config/hamachi/sources.xml index f21a577e44fa..e2247f032cbb 100644 --- a/b2g/config/hamachi/sources.xml +++ b/b2g/config/hamachi/sources.xml @@ -17,7 +17,7 @@ - + diff --git a/b2g/config/helix/sources.xml b/b2g/config/helix/sources.xml index 5127509928a4..acc2ed25640e 100644 --- a/b2g/config/helix/sources.xml +++ b/b2g/config/helix/sources.xml @@ -15,7 +15,7 @@ - + diff --git a/b2g/config/nexus-4/sources.xml b/b2g/config/nexus-4/sources.xml index 63657e0a9b23..09db21b7be25 100644 --- a/b2g/config/nexus-4/sources.xml +++ b/b2g/config/nexus-4/sources.xml @@ -17,7 +17,7 @@ - + diff --git a/b2g/config/wasabi/sources.xml b/b2g/config/wasabi/sources.xml index 5df71a40a89a..9b3614a80ff1 100644 --- a/b2g/config/wasabi/sources.xml +++ b/b2g/config/wasabi/sources.xml @@ -17,7 +17,7 @@ - + From d6726fabdbd0ba7a473c415b5364dc5e5a837af2 Mon Sep 17 00:00:00 2001 From: B2G Bumper Bot Date: Wed, 12 Nov 2014 16:12:53 -0800 Subject: [PATCH 32/80] Bumping manifests a=b2g-bump --- b2g/config/dolphin/sources.xml | 2 +- b2g/config/emulator-ics/sources.xml | 2 +- b2g/config/emulator-jb/sources.xml | 2 +- b2g/config/emulator-kk/sources.xml | 2 +- b2g/config/emulator/sources.xml | 2 +- b2g/config/flame-kk/sources.xml | 2 +- b2g/config/flame/sources.xml | 2 +- b2g/config/hamachi/sources.xml | 2 +- b2g/config/nexus-4/sources.xml | 2 +- b2g/config/wasabi/sources.xml | 2 +- 10 files changed, 10 insertions(+), 10 deletions(-) diff --git a/b2g/config/dolphin/sources.xml b/b2g/config/dolphin/sources.xml index 1b9d95863411..03aec1d3082d 100644 --- a/b2g/config/dolphin/sources.xml +++ b/b2g/config/dolphin/sources.xml @@ -23,7 +23,7 @@ - + diff --git a/b2g/config/emulator-ics/sources.xml b/b2g/config/emulator-ics/sources.xml index 255570ed49c6..f231be98e9fa 100644 --- a/b2g/config/emulator-ics/sources.xml +++ b/b2g/config/emulator-ics/sources.xml @@ -25,7 +25,7 @@ - + diff --git a/b2g/config/emulator-jb/sources.xml b/b2g/config/emulator-jb/sources.xml index 73e3d651963f..1a128868b177 100644 --- a/b2g/config/emulator-jb/sources.xml +++ b/b2g/config/emulator-jb/sources.xml @@ -20,7 +20,7 @@ - + diff --git a/b2g/config/emulator-kk/sources.xml b/b2g/config/emulator-kk/sources.xml index 13d556a895bf..e66395e71c7b 100644 --- a/b2g/config/emulator-kk/sources.xml +++ b/b2g/config/emulator-kk/sources.xml @@ -23,7 +23,7 @@ - + diff --git a/b2g/config/emulator/sources.xml b/b2g/config/emulator/sources.xml index 255570ed49c6..f231be98e9fa 100644 --- a/b2g/config/emulator/sources.xml +++ b/b2g/config/emulator/sources.xml @@ -25,7 +25,7 @@ - + diff --git a/b2g/config/flame-kk/sources.xml b/b2g/config/flame-kk/sources.xml index 249cdb7f65c8..1a7c4ec3164d 100644 --- a/b2g/config/flame-kk/sources.xml +++ b/b2g/config/flame-kk/sources.xml @@ -23,7 +23,7 @@ - + diff --git a/b2g/config/flame/sources.xml b/b2g/config/flame/sources.xml index fc1deb30b534..ee4413fcb299 100644 --- a/b2g/config/flame/sources.xml +++ b/b2g/config/flame/sources.xml @@ -20,7 +20,7 @@ - + diff --git a/b2g/config/hamachi/sources.xml b/b2g/config/hamachi/sources.xml index e2247f032cbb..0b0645e8d072 100644 --- a/b2g/config/hamachi/sources.xml +++ b/b2g/config/hamachi/sources.xml @@ -21,7 +21,7 @@ - + diff --git a/b2g/config/nexus-4/sources.xml b/b2g/config/nexus-4/sources.xml index 09db21b7be25..516f0c5a9f7e 100644 --- a/b2g/config/nexus-4/sources.xml +++ b/b2g/config/nexus-4/sources.xml @@ -20,7 +20,7 @@ - + diff --git a/b2g/config/wasabi/sources.xml b/b2g/config/wasabi/sources.xml index 9b3614a80ff1..8a7b3ee7b67d 100644 --- a/b2g/config/wasabi/sources.xml +++ b/b2g/config/wasabi/sources.xml @@ -22,7 +22,7 @@ - + From dde76d3d0b636dd9caa55be143f722a38ff4b27f Mon Sep 17 00:00:00 2001 From: B2G Bumper Bot Date: Wed, 12 Nov 2014 17:59:56 -0800 Subject: [PATCH 33/80] Bumping gaia.json for 2 gaia revision(s) a=gaia-bump ======== https://hg.mozilla.org/integration/gaia-central/rev/84dc3d8c2e46 Author: Jim Porter Desc: Merge pull request #25856 from jimporter/ringtones-rtl Bug 1094450 - Support RTL for ringtones ======== https://hg.mozilla.org/integration/gaia-central/rev/e219610aa3ce Author: Jim Desc: Bug 1094450 - Support RTL for ringtones --- b2g/config/gaia.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/b2g/config/gaia.json b/b2g/config/gaia.json index d1d0a78dd110..bbf32b334532 100644 --- a/b2g/config/gaia.json +++ b/b2g/config/gaia.json @@ -4,6 +4,6 @@ "remote": "", "branch": "" }, - "revision": "a2d2b614eecc8351f6f878f8fa44cafd36eb751f", + "revision": "84dc3d8c2e468b6bda102921438e5868d53484dd", "repo_path": "integration/gaia-central" } From 93e543466b543e65b6e33668f9c40453123976f3 Mon Sep 17 00:00:00 2001 From: B2G Bumper Bot Date: Wed, 12 Nov 2014 18:00:12 -0800 Subject: [PATCH 34/80] Bumping manifests a=b2g-bump --- b2g/config/dolphin/sources.xml | 2 +- b2g/config/emulator-ics/sources.xml | 2 +- b2g/config/emulator-jb/sources.xml | 2 +- b2g/config/emulator-kk/sources.xml | 2 +- b2g/config/emulator/sources.xml | 2 +- b2g/config/flame-kk/sources.xml | 2 +- b2g/config/flame/sources.xml | 2 +- b2g/config/hamachi/sources.xml | 2 +- b2g/config/helix/sources.xml | 2 +- b2g/config/nexus-4/sources.xml | 2 +- b2g/config/wasabi/sources.xml | 2 +- 11 files changed, 11 insertions(+), 11 deletions(-) diff --git a/b2g/config/dolphin/sources.xml b/b2g/config/dolphin/sources.xml index 03aec1d3082d..efc3d95e939a 100644 --- a/b2g/config/dolphin/sources.xml +++ b/b2g/config/dolphin/sources.xml @@ -15,7 +15,7 @@ - + diff --git a/b2g/config/emulator-ics/sources.xml b/b2g/config/emulator-ics/sources.xml index f231be98e9fa..b63f7de1cf35 100644 --- a/b2g/config/emulator-ics/sources.xml +++ b/b2g/config/emulator-ics/sources.xml @@ -19,7 +19,7 @@ - + diff --git a/b2g/config/emulator-jb/sources.xml b/b2g/config/emulator-jb/sources.xml index 1a128868b177..6040758b5d1f 100644 --- a/b2g/config/emulator-jb/sources.xml +++ b/b2g/config/emulator-jb/sources.xml @@ -17,7 +17,7 @@ - + diff --git a/b2g/config/emulator-kk/sources.xml b/b2g/config/emulator-kk/sources.xml index e66395e71c7b..b3bc1cf70ffb 100644 --- a/b2g/config/emulator-kk/sources.xml +++ b/b2g/config/emulator-kk/sources.xml @@ -15,7 +15,7 @@ - + diff --git a/b2g/config/emulator/sources.xml b/b2g/config/emulator/sources.xml index f231be98e9fa..b63f7de1cf35 100644 --- a/b2g/config/emulator/sources.xml +++ b/b2g/config/emulator/sources.xml @@ -19,7 +19,7 @@ - + diff --git a/b2g/config/flame-kk/sources.xml b/b2g/config/flame-kk/sources.xml index 1a7c4ec3164d..1546b05c9581 100644 --- a/b2g/config/flame-kk/sources.xml +++ b/b2g/config/flame-kk/sources.xml @@ -15,7 +15,7 @@ - + diff --git a/b2g/config/flame/sources.xml b/b2g/config/flame/sources.xml index ee4413fcb299..10fbcb9fa2b6 100644 --- a/b2g/config/flame/sources.xml +++ b/b2g/config/flame/sources.xml @@ -17,7 +17,7 @@ - + diff --git a/b2g/config/hamachi/sources.xml b/b2g/config/hamachi/sources.xml index 0b0645e8d072..d7931fe57e93 100644 --- a/b2g/config/hamachi/sources.xml +++ b/b2g/config/hamachi/sources.xml @@ -17,7 +17,7 @@ - + diff --git a/b2g/config/helix/sources.xml b/b2g/config/helix/sources.xml index acc2ed25640e..0801fb96e797 100644 --- a/b2g/config/helix/sources.xml +++ b/b2g/config/helix/sources.xml @@ -15,7 +15,7 @@ - + diff --git a/b2g/config/nexus-4/sources.xml b/b2g/config/nexus-4/sources.xml index 516f0c5a9f7e..70094a9d0cb0 100644 --- a/b2g/config/nexus-4/sources.xml +++ b/b2g/config/nexus-4/sources.xml @@ -17,7 +17,7 @@ - + diff --git a/b2g/config/wasabi/sources.xml b/b2g/config/wasabi/sources.xml index 8a7b3ee7b67d..7775c9cd5867 100644 --- a/b2g/config/wasabi/sources.xml +++ b/b2g/config/wasabi/sources.xml @@ -17,7 +17,7 @@ - + From 371e647a47611ebcf7f9e67af282f990bad2188d Mon Sep 17 00:00:00 2001 From: "Szu-Yu Chen [:aknow]" Date: Thu, 13 Nov 2014 10:58:45 +0800 Subject: [PATCH 35/80] Bug 1094089 - Part 1: Show reject cause. r=hsinyi --- .../test/marionette/test_audiomanager_phonestate.js | 4 +--- dom/telephony/test/marionette/test_conference_add_error.js | 4 +--- .../test/marionette/test_conference_add_twice_error.js | 4 +--- .../test/marionette/test_conference_remove_error.js | 4 +--- .../test/marionette/test_conference_three_hangup_one.js | 4 +--- .../test/marionette/test_conference_three_remove_one.js | 4 +--- dom/telephony/test/marionette/test_conference_two_calls.js | 4 +--- .../test/marionette/test_conference_two_hangup_all.js | 4 +--- .../test/marionette/test_conference_two_hangup_one.js | 4 +--- .../test/marionette/test_conference_two_hold_resume.js | 4 +--- .../test/marionette/test_conference_two_remove_one.js | 4 +--- .../test/marionette/test_dsds_connection_conflict.js | 4 +--- dom/telephony/test/marionette/test_dsds_normal_call.js | 4 +--- dom/telephony/test/marionette/test_emergency_label.js | 4 +--- dom/telephony/test/marionette/test_mmi.js | 4 +--- dom/telephony/test/marionette/test_mmi_call_forwarding.js | 4 +--- dom/telephony/test/marionette/test_mmi_change_pin.js | 4 +--- .../test/marionette/test_outgoing_answer_radio_off.js | 4 +--- dom/telephony/test/marionette/test_outgoing_auto_hold.js | 4 +--- .../marionette/test_outgoing_emergency_in_airplane_mode.js | 4 +--- .../test/marionette/test_outgoing_when_two_calls_on_line.js | 4 +--- dom/telephony/test/marionette/test_temporary_clir.js | 5 +---- 22 files changed, 22 insertions(+), 67 deletions(-) diff --git a/dom/telephony/test/marionette/test_audiomanager_phonestate.js b/dom/telephony/test/marionette/test_audiomanager_phonestate.js index ce62399df9c5..c59b80d8bfe5 100644 --- a/dom/telephony/test/marionette/test_audiomanager_phonestate.js +++ b/dom/telephony/test/marionette/test_audiomanager_phonestate.js @@ -89,8 +89,6 @@ startTest(function() { .then(() => check(PHONE_STATE_NORMAL)) // End - .then(null, error => { - ok(false, 'promise rejects during test.'); - }) + .catch(error => ok(false, "Promise reject: " + error)) .then(finish); }); diff --git a/dom/telephony/test/marionette/test_conference_add_error.js b/dom/telephony/test/marionette/test_conference_add_error.js index d07b8b31c381..9b77acfb6b3a 100644 --- a/dom/telephony/test/marionette/test_conference_add_error.js +++ b/dom/telephony/test/marionette/test_conference_add_error.js @@ -64,8 +64,6 @@ function testConferenceAddError() { // Start the test startTest(function() { testConferenceAddError() - .then(null, error => { - ok(false, 'promise rejects during test.'); - }) + .catch(error => ok(false, "Promise reject: " + error)) .then(finish); }); diff --git a/dom/telephony/test/marionette/test_conference_add_twice_error.js b/dom/telephony/test/marionette/test_conference_add_twice_error.js index 4c3b743cfa9b..141a85283f15 100644 --- a/dom/telephony/test/marionette/test_conference_add_twice_error.js +++ b/dom/telephony/test/marionette/test_conference_add_twice_error.js @@ -41,8 +41,6 @@ function testConferenceTwoCallsTwice() { // Start the test startTest(function() { testConferenceTwoCallsTwice() - .then(null, error => { - ok(false, 'promise rejects during test.'); - }) + .catch(error => ok(false, "Promise reject: " + error)) .then(finish); }); diff --git a/dom/telephony/test/marionette/test_conference_remove_error.js b/dom/telephony/test/marionette/test_conference_remove_error.js index 3ce85e19280b..6f2ea17b863a 100644 --- a/dom/telephony/test/marionette/test_conference_remove_error.js +++ b/dom/telephony/test/marionette/test_conference_remove_error.js @@ -61,8 +61,6 @@ function testConferenceRemoveError() { // Start the test startTest(function() { testConferenceRemoveError() - .then(null, error => { - ok(false, 'promise rejects during test.'); - }) + .catch(error => ok(false, "Promise reject: " + error)) .then(finish); }); diff --git a/dom/telephony/test/marionette/test_conference_three_hangup_one.js b/dom/telephony/test/marionette/test_conference_three_hangup_one.js index 6ca034c03c15..b262d7ff3c42 100644 --- a/dom/telephony/test/marionette/test_conference_three_hangup_one.js +++ b/dom/telephony/test/marionette/test_conference_three_hangup_one.js @@ -30,8 +30,6 @@ function testConferenceThreeAndHangupOne() { // Start the test startTest(function() { testConferenceThreeAndHangupOne() - .then(null, error => { - ok(false, 'promise rejects during test.'); - }) + .catch(error => ok(false, "Promise reject: " + error)) .then(finish); }); diff --git a/dom/telephony/test/marionette/test_conference_three_remove_one.js b/dom/telephony/test/marionette/test_conference_three_remove_one.js index ca0e056ba486..0f365c58730b 100644 --- a/dom/telephony/test/marionette/test_conference_three_remove_one.js +++ b/dom/telephony/test/marionette/test_conference_three_remove_one.js @@ -34,8 +34,6 @@ function testConferenceThreeAndRemoveOne() { // Start the test startTest(function() { testConferenceThreeAndRemoveOne() - .then(null, error => { - ok(false, 'promise rejects during test.'); - }) + .catch(error => ok(false, "Promise reject: " + error)) .then(finish); }); diff --git a/dom/telephony/test/marionette/test_conference_two_calls.js b/dom/telephony/test/marionette/test_conference_two_calls.js index 87755b527f75..1143624ed260 100644 --- a/dom/telephony/test/marionette/test_conference_two_calls.js +++ b/dom/telephony/test/marionette/test_conference_two_calls.js @@ -23,8 +23,6 @@ function testConferenceTwoCalls() { // Start the test startTest(function() { testConferenceTwoCalls() - .then(null, error => { - ok(false, 'promise rejects during test.'); - }) + .catch(error => ok(false, "Promise reject: " + error)) .then(finish); }); diff --git a/dom/telephony/test/marionette/test_conference_two_hangup_all.js b/dom/telephony/test/marionette/test_conference_two_hangup_all.js index 72c2cad569e2..d957f1968e1a 100644 --- a/dom/telephony/test/marionette/test_conference_two_hangup_all.js +++ b/dom/telephony/test/marionette/test_conference_two_hangup_all.js @@ -49,8 +49,6 @@ function testConferenceHangUpBackground() { startTest(function() { testConferenceHangUpForeground() .then(() => testConferenceHangUpBackground()) - .then(null, error => { - ok(false, 'promise rejects during test.'); - }) + .catch(error => ok(false, "Promise reject: " + error)) .then(finish); }); diff --git a/dom/telephony/test/marionette/test_conference_two_hangup_one.js b/dom/telephony/test/marionette/test_conference_two_hangup_one.js index a1f0f8ab7a8b..1f1d5b505aca 100644 --- a/dom/telephony/test/marionette/test_conference_two_hangup_one.js +++ b/dom/telephony/test/marionette/test_conference_two_hangup_one.js @@ -28,8 +28,6 @@ function testConferenceTwoAndHangupOne() { // Start the test startTest(function() { testConferenceTwoAndHangupOne() - .then(null, error => { - ok(false, 'promise rejects during test.'); - }) + .catch(error => ok(false, "Promise reject: " + error)) .then(finish); }); diff --git a/dom/telephony/test/marionette/test_conference_two_hold_resume.js b/dom/telephony/test/marionette/test_conference_two_hold_resume.js index 230c9ed0de4a..614506df88f2 100644 --- a/dom/telephony/test/marionette/test_conference_two_hold_resume.js +++ b/dom/telephony/test/marionette/test_conference_two_hold_resume.js @@ -35,8 +35,6 @@ function testConferenceHoldAndResume() { // Start the test startTest(function() { testConferenceHoldAndResume() - .then(null, error => { - ok(false, 'promise rejects during test.'); - }) + .catch(error => ok(false, "Promise reject: " + error)) .then(finish); }); diff --git a/dom/telephony/test/marionette/test_conference_two_remove_one.js b/dom/telephony/test/marionette/test_conference_two_remove_one.js index fd5a18797bd9..8bbb3d565f3a 100644 --- a/dom/telephony/test/marionette/test_conference_two_remove_one.js +++ b/dom/telephony/test/marionette/test_conference_two_remove_one.js @@ -30,8 +30,6 @@ function testConferenceTwoAndRemoveOne() { // Start the test startTest(function() { testConferenceTwoAndRemoveOne() - .then(null, error => { - ok(false, 'promise rejects during test.'); - }) + .catch(error => ok(false, "Promise reject: " + error)) .then(finish); }); diff --git a/dom/telephony/test/marionette/test_dsds_connection_conflict.js b/dom/telephony/test/marionette/test_dsds_connection_conflict.js index 5ada8e48d74e..ac0d087fb880 100644 --- a/dom/telephony/test/marionette/test_dsds_connection_conflict.js +++ b/dom/telephony/test/marionette/test_dsds_connection_conflict.js @@ -46,8 +46,6 @@ startDSDSTest(function() { testNewCallWhenOtherConnectionInUse(0, 1) .then(() => testNewCallWhenOtherConnectionInUse(1, 0)) .then(() => muxModem(0)) - .then(null, () => { - ok(false, "promise rejects during test."); - }) + .catch(error => ok(false, "Promise reject: " + error)) .then(finish); }); diff --git a/dom/telephony/test/marionette/test_dsds_normal_call.js b/dom/telephony/test/marionette/test_dsds_normal_call.js index ece526920ae7..ea03ef4576a0 100644 --- a/dom/telephony/test/marionette/test_dsds_normal_call.js +++ b/dom/telephony/test/marionette/test_dsds_normal_call.js @@ -73,8 +73,6 @@ function testIncomingCall() { startDSDSTest(function() { testOutgoingCall() .then(testIncomingCall) - .then(null, () => { - ok(false, "promise rejects during test."); - }) + .catch(error => ok(false, "Promise reject: " + error)) .then(finish); }); diff --git a/dom/telephony/test/marionette/test_emergency_label.js b/dom/telephony/test/marionette/test_emergency_label.js index 41854468acdb..cb8d26d35dba 100644 --- a/dom/telephony/test/marionette/test_emergency_label.js +++ b/dom/telephony/test/marionette/test_emergency_label.js @@ -78,8 +78,6 @@ startTest(function() { .then(() => testEmergencyLabel("119", eccList)) .then(() => testEmergencyLabel("112", eccList)) .then(() => setEccListProperty(origEccList)) - .then(null, error => { - ok(false, 'promise rejects during test: ' + error); - }) + .catch(error => ok(false, "Promise reject: " + error)) .then(finish); }); diff --git a/dom/telephony/test/marionette/test_mmi.js b/dom/telephony/test/marionette/test_mmi.js index 8eca247e6c6a..aa385370851f 100644 --- a/dom/telephony/test/marionette/test_mmi.js +++ b/dom/telephony/test/marionette/test_mmi.js @@ -21,8 +21,6 @@ function testGettingIMEI() { // Start test startTest(function() { testGettingIMEI() - .then(null, cause => { - ok(false, 'promise rejects during test: ' + cause); - }) + .catch(error => ok(false, "Promise reject: " + error)) .then(finish); }); diff --git a/dom/telephony/test/marionette/test_mmi_call_forwarding.js b/dom/telephony/test/marionette/test_mmi_call_forwarding.js index 328bc7154080..dc807abbeaf7 100644 --- a/dom/telephony/test/marionette/test_mmi_call_forwarding.js +++ b/dom/telephony/test/marionette/test_mmi_call_forwarding.js @@ -185,8 +185,6 @@ startTestWithPermissions(['mobileconnection'], function() { // reset call forwarding settings. return promise.then(() => clearAllCallForwardingSettings()) - .then(null, cause => { - ok(false, 'promise rejects during test: ' + cause); - }) + .catch(error => ok(false, "Promise reject: " + error)) .then(finish); }); diff --git a/dom/telephony/test/marionette/test_mmi_change_pin.js b/dom/telephony/test/marionette/test_mmi_change_pin.js index 66b0b6b486ec..81ad3f9dfef1 100644 --- a/dom/telephony/test/marionette/test_mmi_change_pin.js +++ b/dom/telephony/test/marionette/test_mmi_change_pin.js @@ -108,8 +108,6 @@ startTest(function() { } return promise - .then(null, cause => { - ok(false, 'promise rejects during test: ' + cause); - }) + .catch(error => ok(false, "Promise reject: " + error)) .then(finish); }); diff --git a/dom/telephony/test/marionette/test_outgoing_answer_radio_off.js b/dom/telephony/test/marionette/test_outgoing_answer_radio_off.js index 437d30c0f85b..85799588b524 100644 --- a/dom/telephony/test/marionette/test_outgoing_answer_radio_off.js +++ b/dom/telephony/test/marionette/test_outgoing_answer_radio_off.js @@ -98,8 +98,6 @@ function testOutgoingCallRadioOff() { // Start test startTestWithPermissions(['mobileconnection'], function() { testOutgoingCallRadioOff() - .then(null, () => { - ok(false, "promise rejects during test."); - }) + .catch(error => ok(false, "Promise reject: " + error)) .then(finish); }); diff --git a/dom/telephony/test/marionette/test_outgoing_auto_hold.js b/dom/telephony/test/marionette/test_outgoing_auto_hold.js index 68eccf8b0425..352567d5bc0b 100644 --- a/dom/telephony/test/marionette/test_outgoing_auto_hold.js +++ b/dom/telephony/test/marionette/test_outgoing_auto_hold.js @@ -45,8 +45,6 @@ function testAutoHoldConferenceCall() { startTest(function() { testAutoHoldCall() .then(() => testAutoHoldConferenceCall()) - .then(null, () => { - ok(false, 'promise rejects during test.'); - }) + .catch(error => ok(false, "Promise reject: " + error)) .then(finish); }); diff --git a/dom/telephony/test/marionette/test_outgoing_emergency_in_airplane_mode.js b/dom/telephony/test/marionette/test_outgoing_emergency_in_airplane_mode.js index d38654caed2f..25a748e5225f 100644 --- a/dom/telephony/test/marionette/test_outgoing_emergency_in_airplane_mode.js +++ b/dom/telephony/test/marionette/test_outgoing_emergency_in_airplane_mode.js @@ -36,8 +36,6 @@ startTestWithPermissions(['mobileconnection'], function() { .then(() => gRemoteAnswer(outCall)) .then(() => gDelay(1000)) // See Bug 1018051 for the purpose of the delay. .then(() => gRemoteHangUp(outCall)) - .then(null, () => { - ok(false, "promise rejects during test."); - }) + .catch(error => ok(false, "Promise reject: " + error)) .then(finish); }); diff --git a/dom/telephony/test/marionette/test_outgoing_when_two_calls_on_line.js b/dom/telephony/test/marionette/test_outgoing_when_two_calls_on_line.js index 0a9b0fc4f901..ffce822307b5 100644 --- a/dom/telephony/test/marionette/test_outgoing_when_two_calls_on_line.js +++ b/dom/telephony/test/marionette/test_outgoing_when_two_calls_on_line.js @@ -27,8 +27,6 @@ function testReject3rdCall() { startTest(function() { testReject3rdCall() - .then(null, () => { - ok(false, 'promise rejects during test.'); - }) + .catch(error => ok(false, "Promise reject: " + error)) .then(finish); }); diff --git a/dom/telephony/test/marionette/test_temporary_clir.js b/dom/telephony/test/marionette/test_temporary_clir.js index b37d0fa76f98..6d21ed5fe1b2 100644 --- a/dom/telephony/test/marionette/test_temporary_clir.js +++ b/dom/telephony/test/marionette/test_temporary_clir.js @@ -29,9 +29,6 @@ startTest(function() { return deferred.promise; }) .then(() => gRemoteHangUp(outCall)) - // End - .then(null, error => { - ok(false, 'promise rejects during test.'); - }) + .catch(error => ok(false, "Promise reject: " + error)) .then(finish); }); From 00fd7ff8be69b02c3605db4cf7002eb517f8c048 Mon Sep 17 00:00:00 2001 From: "Szu-Yu Chen [:aknow]" Date: Thu, 13 Nov 2014 10:58:46 +0800 Subject: [PATCH 36/80] Bug 1094089 - Part 2: Refactoring the promise usage in head.js. r=hsinyi --- dom/telephony/test/marionette/head.js | 944 +++++++++----------------- 1 file changed, 337 insertions(+), 607 deletions(-) diff --git a/dom/telephony/test/marionette/head.js b/dom/telephony/test/marionette/head.js index d998691e08bb..a9f35f148485 100644 --- a/dom/telephony/test/marionette/head.js +++ b/dom/telephony/test/marionette/head.js @@ -36,25 +36,29 @@ let emulator = (function() { throw "Use emulator.runShellCmd(cmd, callback) instead of runEmulatorShell"; }; + /** + * @return Promise + */ function runCmd(cmd) { - let deferred = Promise.defer(); - - pendingCmdCount++; - originalRunEmulatorCmd(cmd, function(result) { - pendingCmdCount--; - if (result[result.length - 1] === "OK") { - deferred.resolve(result); - } else { - is(result[result.length - 1], "OK", "emulator command result."); - deferred.reject(); - } + return new Promise(function(resolve, reject) { + pendingCmdCount++; + originalRunEmulatorCmd(cmd, function(result) { + pendingCmdCount--; + if (result[result.length - 1] === "OK") { + resolve(result); + } else { + is(result[result.length - 1], "OK", "emulator command result."); + reject(); + } + }); }); - - return deferred.promise; } + /** + * @return Promise + */ function runCmdWithCallback(cmd, callback) { - runCmd(cmd).then(result => { + return runCmd(cmd).then(result => { if (callback && typeof callback === "function") { callback(result); } @@ -65,30 +69,26 @@ let emulator = (function() { * @return Promise */ function runShellCmd(aCommands) { - let deferred = Promise.defer(); - - ++pendingShellCount; - originalRunEmulatorShell(aCommands, function(aResult) { - --pendingShellCount; - deferred.resolve(aResult); + return new Promise(function(resolve, reject) { + ++pendingShellCount; + originalRunEmulatorShell(aCommands, function(aResult) { + --pendingShellCount; + resolve(aResult); + }); }); - - return deferred.promise; } /** * @return Promise */ function waitFinish() { - let deferred = Promise.defer(); - - waitFor(function() { - deferred.resolve(); - }, function() { - return pendingCmdCount === 0 && pendingShellCount === 0; + return new Promise(function(resolve, reject) { + waitFor(function() { + resolve(); + }, function() { + return pendingCmdCount === 0 && pendingShellCount === 0; + }); }); - - return deferred.promise; } return { @@ -107,32 +107,130 @@ let emulator = (function() { * @return Promise */ function delay(ms) { - let deferred = Promise.defer(); - - let startTime = Date.now(); - waitFor(function() { - deferred.resolve(); - },function() { - let duration = Date.now() - startTime; - return (duration >= ms); + return new Promise(function(resolve, reject) { + let startTime = Date.now(); + waitFor(function() { + resolve(); + },function() { + let duration = Date.now() - startTime; + return (duration >= ms); + }); }); + } - return deferred.promise; + /** + * Wait for one named event. + * + * @param aTarget + * A event target. + * @param aEventName + * A string event name. + * @param aPredicate [optional] + * A predicate function, resolve the promise if aPredicate(event) + * return true + * @return Promise + */ + function waitForEvent(aTarget, aEventName, aPredicate) { + return new Promise(function(resolve, reject) { + aTarget.addEventListener(aEventName, function onevent(aEvent) { + if (aPredicate === undefined || aPredicate(aEvent)) { + aTarget.removeEventListener(aEventName, onevent); + + let label = "X"; + if (aTarget instanceof TelephonyCall) { + label = "Call (" + aTarget.id.number + ")"; + } else if (aTarget instanceof TelephonyCallGroup) { + label = "Conference"; + } else if (aTarget instanceof Telephony) { + label = "Telephony"; + } + + log(label + " received event '" + aEventName + "'"); + resolve(aEvent); + } + }); + }); + } + + /** + * Wait for callschanged event with event.call == aExpectedCall + * + * @param aTarget + * A event target. + * @param aExpectedCall + * Expected call for event.call + * @return Promise + */ + function waitForCallsChangedEvent(aTarget, aExpectedCall) { + return waitForEvent(aTarget, "callschanged", + event => event.call == aExpectedCall); + } + + /** + * Wait for call state event, e.g., "connected", "disconnected", ... + * + * @param aTarget + * A event target. + * @param aState + * State name + * @return Promise + */ + function waitForNamedStateEvent(aTarget, aState) { + return waitForEvent(aTarget, aState) + .then(event => { + if (aTarget instanceof TelephonyCall) { + is(aTarget, event.call, "event.call"); + } + is(aTarget.state, aState, "check state"); + return aTarget; + }); + } + + /** + * Wait for groupchange event. + * + * @param aCall + * A TelephonyCall object. + * @param aGroup + * The new group + * @return Promise + */ + function waitForGroupChangeEvent(aCall, aGroup) { + return waitForEvent(aCall, "groupchange") + .then(() => { + is(aCall.group, aGroup, "call group"); + return aCall; + }); + } + + /** + * Wait for statechange event. + * + * @param aTarget + * A event target. + * @param aState + * The desired new state. Check it. + * @return Promise + */ + function waitForStateChangeEvent(aTarget, aState) { + return waitForEvent(aTarget, "statechange") + .then(() => { + is(aTarget.state, aState); + return aTarget; + }); } /** * @return Promise */ function waitForNoCall() { - let deferred = Promise.defer(); - - waitFor(function() { - deferred.resolve(); - }, function() { - return telephony.calls.length === 0; + return new Promise(function(resolve, reject) { + waitFor(function() { + resolve(); + }, function() { + return telephony.calls.length === 0; + }); }); - - return deferred.promise; } /** @@ -214,154 +312,23 @@ let emulator = (function() { function checkInitialState() { log("Verify initial state."); ok(telephony.calls, 'telephony.call'); - checkTelephonyActiveAndCalls(null, []); ok(conference.calls, 'conference.calls'); - checkConferenceStateAndCalls('', []); + checkState(null, [], "", []); } /** - * Convenient helper to compare a TelephonyCall and a received call event. - */ - function checkEventCallState(event, call, state) { - is(call, event.call, "event.call"); - is(call.state, state, "call state"); - } - - /** - * Convenient helper to compare two call lists. Size should be the same and - * order is not important. + * Convenient helper to compare two call lists (order is not important). */ function checkCalls(actualCalls, expectedCalls) { - if (actualCalls.length == expectedCalls.length) { - let expectedSet = new Set(expectedCalls); - for (let i = 0; i < actualCalls.length; ++i) { - ok(expectedSet.has(actualCalls[i]), "should contain the call"); - } + if (actualCalls.length != expectedCalls.length) { + ok(false, "check calls.length"); + return; } - } - /** - * Convenient helper to check mozTelephony.active and mozTelephony.calls. - */ - function checkTelephonyActiveAndCalls(active, calls) { - is(telephony.active, active, "telephony.active"); - is(telephony.calls.length, calls.length, "telephony.calls"); - checkCalls(telephony.calls, calls); - } - - /** - * Convenient helper to check mozTelephony.conferenceGroup.state and - * .conferenceGroup.calls. - */ - function checkConferenceStateAndCalls(state, calls) { - is(conference.state, state, "conference.state"); - is(conference.calls.length, calls.length, "conference.calls"); - checkCalls(conference.calls, calls); - } - - /** - * Convenient helper to handle *.oncallschanged event. - * - * @param container - * Representation of "mozTelephony" or "mozTelephony.conferenceGroup." - * @param containerName - * Name of container. Could be an arbitrary string, used for debug - * messages only. - * @param expectedCalls - * An array of calls. - * @param callback - * A callback function. - */ - function check_oncallschanged(container, containerName, expectedCalls, - callback) { - container.oncallschanged = function(event) { - log("Received 'callschanged' event for the " + containerName); - - ok(event.call); - - let index = expectedCalls.indexOf(event.call); - ok(index != -1); - expectedCalls.splice(index, 1); - - if (expectedCalls.length === 0) { - container.oncallschanged = null; - callback(); - } - }; - } - - /** - * Convenient helper to handle *.ongroupchange event. - * - * @param call - * A TelephonyCall object. - * @param callName - * Name of a call. Could be an arbitrary string, used for debug messages - * only. - * @param group - * Representation of mozTelephony.conferenceGroup. - * @param callback - * A callback function. - */ - function check_ongroupchange(call, callName, group, callback) { - call.ongroupchange = function(event) { - log("Received 'groupchange' event for the " + callName); - call.ongroupchange = null; - - is(call.group, group); - callback(); - }; - } - - /** - * Convenient helper to handle *.onstatechange event. - * - * @param container - * Representation of a TelephonyCall or mozTelephony.conferenceGroup. - * @param containerName - * Name of container. Could be an arbitrary string, used for debug messages - * only. - * @param state - * A string. - * @param callback - * A callback function. - */ - function check_onstatechange(container, containerName, state, callback) { - container.onstatechange = function(event) { - log("Received 'statechange' event for the " + containerName); - container.onstatechange = null; - - is(container.state, state); - callback(); - }; - } - - /** - * Convenient helper to check the sequence of call state and event handlers. - * - * @param state - * A string of the expected call state. - * @param previousEvent - * A string of the event that should come before the expected state. - */ - function StateEventChecker(state, previousEvent) { - let event = 'on' + state; - - return function(call, callName, callback) { - call[event] = function() { - log("Received '" + state + "' event for the " + callName); - call[event] = null; - - if (previousEvent) { - // We always clear the event handler when the event is received. - // Therefore, if the corresponding handler is not existed, the expected - // previous event has been already received. - ok(!call[previousEvent]); - } - is(call.state, state); - callback(); - }; - }; + let expectedSet = new Set(expectedCalls); + for (let i = 0; i < actualCalls.length; ++i) { + ok(expectedSet.has(actualCalls[i]), "should contain the call"); + } } /** @@ -401,7 +368,7 @@ let emulator = (function() { * * @param expectedCallList * An array of call info with the format of "callStrPool()[state]". - * @return A deferred promise. + * @return Promise */ function checkEmulatorCallList(expectedCallList) { return emulator.runCmd("gsm list").then(result => { @@ -428,8 +395,10 @@ let emulator = (function() { * mozTelephony.conferenceGroup.calls. */ function checkState(active, calls, conferenceState, conferenceCalls) { - checkTelephonyActiveAndCalls(active, calls); - checkConferenceStateAndCalls(conferenceState, conferenceCalls); + is(telephony.active, active, "telephony.active"); + checkCalls(telephony.calls, calls); + is(conference.state, conferenceState, "conference.state"); + checkCalls(conference.calls, conferenceCalls); } /** @@ -448,7 +417,7 @@ let emulator = (function() { * mozTelephony.conferenceGroup.calls. * @param callList * An array of call info with the format of "callStrPool()[state]". - * @return A deferred promise. + * @return Promise */ function checkAll(active, calls, conferenceState, conferenceCalls, callList) { checkState(active, calls, conferenceState, conferenceCalls); @@ -459,26 +428,6 @@ let emulator = (function() { * Request utility functions. */ - /** - * Make sure there's no pending event before we jump to the next action. - * - * @param received - * A string of the received event. - * @param pending - * An array of the pending events. - * @param nextAction - * A callback function that is called when there's no pending event. - */ - function receivedPending(received, pending, nextAction) { - let index = pending.indexOf(received); - if (index != -1) { - pending.splice(index, 1); - } - if (pending.length === 0) { - nextAction(); - } - } - /** * Make an outgoing call. * @@ -486,31 +435,21 @@ let emulator = (function() { * A string. * @param serviceId [optional] * Identification of a service. 0 is set as default. - * @return A deferred promise. + * @return Promise */ function dial(number, serviceId) { serviceId = typeof serviceId !== "undefined" ? serviceId : 0; log("Make an outgoing call: " + number + ", serviceId: " + serviceId); - let deferred = Promise.defer(); + return telephony.dial(number, serviceId) + .then(call => { + ok(call); + is(call.id.number, number); + is(call.state, "dialing"); + is(call.serviceId, serviceId); - telephony.dial(number, serviceId).then(call => { - ok(call); - is(call.id.number, number); - is(call.state, "dialing"); - is(call.serviceId, serviceId); - - call.onalerting = function onalerting(event) { - call.onalerting = null; - log("Received 'onalerting' call event."); - checkEventCallState(event, call, "alerting"); - deferred.resolve(call); - }; - }, cause => { - deferred.reject(cause); - }); - - return deferred.promise; + return waitForNamedStateEvent(call, "alerting"); + }); } /** @@ -518,29 +457,19 @@ let emulator = (function() { * * @param number * A string. - * @return A deferred promise. + * @return Promise */ function dialEmergency(number) { log("Make an outgoing emergency call: " + number); - let deferred = Promise.defer(); + return telephony.dialEmergency(number) + .then(call => { + ok(call); + is(call.id.number, number); + is(call.state, "dialing"); - telephony.dialEmergency(number).then(call => { - ok(call); - is(call.id.number, number); - is(call.state, "dialing"); - - call.onalerting = function onalerting(event) { - call.onalerting = null; - log("Received 'onalerting' call event."); - checkEventCallState(event, call, "alerting"); - deferred.resolve(call); - }; - }, cause => { - deferred.reject(cause); - }); - - return deferred.promise; + return waitForNamedStateEvent(call, "alerting"); + }); } /** @@ -551,50 +480,35 @@ let emulator = (function() { * @param conferenceStateChangeCallback [optional] * A callback function which is called if answering an incoming call * triggers conference state change. - * @return A deferred promise. + * @return Promise */ function answer(call, conferenceStateChangeCallback) { log("Answering the incoming call."); - let deferred = Promise.defer(); - let done = function() { - deferred.resolve(call); - }; + let promises = []; - let pending = ["call.onconnected"]; - let receive = function(name) { - receivedPending(name, pending, done); - }; + let promise = waitForNamedStateEvent(call, "connecting") + .then(() => waitForNamedStateEvent(call, "connected")); - // When there's already a connected conference call, answering a new incoming - // call triggers conference state change. We should wait for - // |conference.onstatechange| before checking the state of the conference call. + promises.push(promise); + + // incoming call triggers conference state change. We should wait for + // |conference.onstatechange| before checking the state of the conference + // call. if (conference.state === "connected") { - pending.push("conference.onstatechange"); - check_onstatechange(conference, "conference", "held", function() { - if (typeof conferenceStateChangeCallback === "function") { - conferenceStateChangeCallback(); - } - receive("conference.onstatechange"); - }); + let promise = waitForStateChangeEvent(conference, "held") + .then(() => { + if (typeof conferenceStateChangeCallback === "function") { + conferenceStateChangeCallback(); + } + }); + + promises.push(promise); } - call.onconnecting = function onconnectingIn(event) { - log("Received 'connecting' call event for incoming call."); - call.onconnecting = null; - checkEventCallState(event, call, "connecting"); - }; - - call.onconnected = function onconnectedIn(event) { - log("Received 'connected' call event for incoming call."); - call.onconnected = null; - checkEventCallState(event, call, "connected"); - ok(!call.onconnecting); - receive("call.onconnected"); - }; call.answer(); - return deferred.promise; + return Promise.all(promises).then(() => call); } /** @@ -602,31 +516,17 @@ let emulator = (function() { * * @param call * A TelephonyCall object. - * @return A deferred promise. + * @return Promise */ function hold(call) { log("Putting the call on hold."); - let deferred = Promise.defer(); + let promise = waitForNamedStateEvent(call, "holding") + .then(() => waitForNamedStateEvent(call, "held")); - let gotHolding = false; - call.onholding = function onholding(event) { - log("Received 'holding' call event"); - call.onholding = null; - checkEventCallState(event, call, "holding"); - gotHolding = true; - }; - - call.onheld = function onheld(event) { - log("Received 'held' call event"); - call.onheld = null; - checkEventCallState(event, call, "held"); - ok(gotHolding); - deferred.resolve(call); - }; call.hold(); - return deferred.promise; + return promise; } /** @@ -634,31 +534,17 @@ let emulator = (function() { * * @param call * A TelephonyCall object. - * @return A deferred promise. + * @return Promise */ function resume(call) { log("Resuming the held call."); - let deferred = Promise.defer(); + let promise = waitForNamedStateEvent(call, "resuming") + .then(() => waitForNamedStateEvent(call, "connected")); - let gotResuming = false; - call.onresuming = function onresuming(event) { - log("Received 'resuming' call event"); - call.onresuming = null; - checkEventCallState(event, call, "resuming"); - gotResuming = true; - }; - - call.onconnected = function onconnected(event) { - log("Received 'connected' call event"); - call.onconnected = null; - checkEventCallState(event, call, "connected"); - ok(gotResuming); - deferred.resolve(call); - }; call.resume(); - return deferred.promise; + return promise; } /** @@ -666,20 +552,17 @@ let emulator = (function() { * * @param call * A TelephonyCall object. - * @return A deferred promise. + * @return Promise */ function hangUp(call) { - let deferred = Promise.defer(); + log("Local hanging up the call: " + call.id.number); + + let promise = waitForNamedStateEvent(call, "disconnecting") + .then(() => waitForNamedStateEvent(call, "disconnected")); - call.ondisconnected = function(event) { - log("Received 'disconnected' call event"); - call.ondisconnected = null; - checkEventCallState(event, call, "disconnected"); - deferred.resolve(call); - }; call.hangUp(); - return deferred.promise; + return promise; } /** @@ -693,32 +576,28 @@ let emulator = (function() { * A string. * @param namePresentation [optional] * An unsigned short integer. - * @return A deferred promise. + * @return Promise */ function remoteDial(number, numberPresentation, name, namePresentation) { log("Simulating an incoming call."); - let deferred = Promise.defer(); - - telephony.onincoming = function onincoming(event) { - log("Received 'incoming' call event."); - telephony.onincoming = null; - - let call = event.call; - - ok(call); - is(call.state, "incoming"); - checkCallId(number, numberPresentation, name, namePresentation, - call.id.number, call.id.name); - deferred.resolve(call); - }; - numberPresentation = numberPresentation || ""; name = name || ""; namePresentation = namePresentation || ""; emulator.runCmd("gsm call " + number + "," + numberPresentation + "," + name + "," + namePresentation); - return deferred.promise; + + return waitForEvent(telephony, "incoming") + .then(event => { + let call = event.call; + + ok(call); + is(call.state, "incoming"); + checkCallId(number, numberPresentation, name, namePresentation, + call.id.number, call.id.name); + + return call; + }); } /** @@ -726,22 +605,14 @@ let emulator = (function() { * * @param call * A TelephonyCall object. - * @return A deferred promise. + * @return Promise */ function remoteAnswer(call) { - log("Remote answering the call."); + log("Remote answering the call: " + call.id.number); - let deferred = Promise.defer(); - - call.onconnected = function onconnected(event) { - log("Received 'connected' call event."); - call.onconnected = null; - checkEventCallState(event, call, "connected"); - deferred.resolve(call); - }; emulator.runCmd("gsm accept " + call.id.number); - return deferred.promise; + return waitForNamedStateEvent(call, "connected"); } /** @@ -749,22 +620,14 @@ let emulator = (function() { * * @param call * A TelephonyCall object. - * @return A deferred promise. + * @return Promise */ function remoteHangUp(call) { - log("Remote hanging up the call."); + log("Remote hanging up the call: " + call.id.number); - let deferred = Promise.defer(); - - call.ondisconnected = function ondisconnected(event) { - log("Received 'disconnected' call event."); - call.ondisconnected = null; - checkEventCallState(event, call, "disconnected"); - deferred.resolve(call); - }; emulator.runCmd("gsm cancel " + call.id.number); - return deferred.promise; + return waitForNamedStateEvent(call, "disconnected"); } /** @@ -772,16 +635,11 @@ let emulator = (function() { * * @param calls * An array of TelephonyCall objects. - * @return A deferred promise. + * @return Promise */ function remoteHangUpCalls(calls) { - let promise = Promise.resolve(); - - for (let call of calls) { - promise = promise.then(remoteHangUp.bind(null, call)); - } - - return promise; + let promises = calls.map(remoteHangUp); + return Promise.all(promises); } /** @@ -795,47 +653,27 @@ let emulator = (function() { * connected. * @param twice [optional] * To send conference request twice. It is only used for special test. - * @return A deferred promise. + * @return Promise<[TelephonyCall ...]> */ function addCallsToConference(callsToAdd, connectedCallback, twice) { log("Add " + callsToAdd.length + " calls into conference."); - let deferred = Promise.defer(); - let done = function() { - deferred.resolve(); - }; - - let pending = ["conference.oncallschanged", "conference.onconnected"]; - let receive = function(name) { - receivedPending(name, pending, done); - }; - - let check_onconnected = StateEventChecker('connected', 'onresuming'); + let promises = []; for (let call of callsToAdd) { - let callName = "callToAdd (" + call.id.number + ')'; - - let ongroupchange = callName + ".ongroupchange"; - pending.push(ongroupchange); - check_ongroupchange(call, callName, conference, - receive.bind(null, ongroupchange)); - - let onstatechange = callName + ".onstatechange"; - pending.push(onstatechange); - check_onstatechange(call, callName, 'connected', - receive.bind(null, onstatechange)); + promises.push(waitForCallsChangedEvent(conference, call)); + promises.push(waitForGroupChangeEvent(call, conference)); + promises.push(waitForNamedStateEvent(call, "connected")); + promises.push(waitForStateChangeEvent(call, "connected")); } - check_oncallschanged(conference, 'conference', callsToAdd, - receive.bind(null, "conference.oncallschanged")); - - check_onconnected(conference, "conference", function() { - ok(!conference.oncallschanged); - if (typeof connectedCallback === 'function') { - connectedCallback(); - } - receive("conference.onconnected"); - }); + let promise = waitForNamedStateEvent(conference, "connected") + .then(() => { + if (typeof connectedCallback === "function") { + connectedCallback(); + } + }); + promises.push(promise); // Cannot use apply() through webidl, so just separate the cases to handle. let requestCount = twice ? 2 : 1; @@ -847,113 +685,77 @@ let emulator = (function() { } } - return deferred.promise; + return Promise.all(promises).then(() => conference.calls); } /** * Hold the conference. * - * @param calls + * @param callsInConference * An array of TelephonyCall objects existing in conference. * @param heldCallback [optional] * A callback function which is called when conference state becomes * held. - * @return A deferred promise. + * @return Promise<[TelephonyCall ...]> */ - function holdConference(calls, heldCallback) { + function holdConference(callsInConference, heldCallback) { log("Holding the conference call."); - let deferred = Promise.defer(); - let done = function() { - deferred.resolve(); - }; + let promises = []; - let pending = ["conference.onholding", "conference.onheld"]; - let receive = function(name) { - receivedPending(name, pending, done); - }; - - let check_onholding = StateEventChecker('holding', null); - let check_onheld = StateEventChecker('held', 'onholding'); - - for (let call of calls) { - let callName = "call (" + call.id.number + ')'; - - let onholding = callName + ".onholding"; - pending.push(onholding); - check_onholding(call, callName, receive.bind(null, onholding)); - - let onheld = callName + ".onheld"; - pending.push(onheld); - check_onheld(call, callName, receive.bind(null, onheld)); + for (let call of callsInConference) { + let promise = waitForNamedStateEvent(call, "holding") + .then(() => waitForNamedStateEvent(call, "held")); + promises.push(promise); } - check_onholding(conference, "conference", - receive.bind(null, "conference.onholding")); - - check_onheld(conference, "conference", function() { - if (typeof heldCallback === 'function') { - heldCallback(); - } - receive("conference.onheld"); - }); + let promise = waitForNamedStateEvent(conference, "holding") + .then(() => waitForNamedStateEvent(conference, "held")) + .then(() => { + if (typeof heldCallback === "function") { + heldCallback(); + } + }); + promises.push(promise); conference.hold(); - return deferred.promise; + return Promise.all(promises).then(() => conference.calls); } /** * Resume the conference. * - * @param calls + * @param callsInConference * An array of TelephonyCall objects existing in conference. * @param connectedCallback [optional] * A callback function which is called when conference state becomes * connected. - * @return A deferred promise. + * @return Promise<[TelephonyCall ...]> */ - function resumeConference(calls, connectedCallback) { + function resumeConference(callsInConference, connectedCallback) { log("Resuming the held conference call."); - let deferred = Promise.defer(); - let done = function() { - deferred.resolve(); - }; + let promises = []; - let pending = ["conference.onresuming", "conference.onconnected"]; - let receive = function(name) { - receivedPending(name, pending, done); - }; - - let check_onresuming = StateEventChecker('resuming', null); - let check_onconnected = StateEventChecker('connected', 'onresuming'); - - for (let call of calls) { - let callName = "call (" + call.id.number + ')'; - - let onresuming = callName + ".onresuming"; - pending.push(onresuming); - check_onresuming(call, callName, receive.bind(null, onresuming)); - - let onconnected = callName + ".onconnected"; - pending.push(onconnected); - check_onconnected(call, callName, receive.bind(null, onconnected)); + for (let call of callsInConference) { + let promise = waitForNamedStateEvent(call, "resuming") + .then(() => waitForNamedStateEvent(call, "connected")); + promises.push(promise); } - check_onresuming(conference, "conference", - receive.bind(null, "conference.onresuming")); - - check_onconnected(conference, "conference", function() { - if (typeof connectedCallback === 'function') { - connectedCallback(); - } - receive("conference.onconnected"); - }); + let promise = waitForNamedStateEvent(conference, "resuming") + .then(() => waitForNamedStateEvent(conference, "connected")) + .then(() => { + if (typeof connectedCallback === "function") { + connectedCallback(); + } + }); + promises.push(promise); conference.resume(); - return deferred.promise; + return Promise.all(promises).then(() => conference.calls); } /** @@ -968,7 +770,7 @@ let emulator = (function() { * An array of TelephonyCall objects which remain in conference. * @param stateChangeCallback [optional] * A callback function which is called when conference state changes. - * @return A deferred promise. + * @return Promise<[TelephonyCall ...]> */ function removeCallInConference(callToRemove, autoRemovedCalls, remainedCalls, statechangeCallback) { @@ -976,70 +778,43 @@ let emulator = (function() { is(conference.state, 'connected'); - let deferred = Promise.defer(); - let done = function() { - deferred.resolve(); - }; + let promises = []; - let pending = ["callToRemove.ongroupchange", "telephony.oncallschanged", - "conference.oncallschanged", "conference.onstatechange"]; - let receive = function(name) { - receivedPending(name, pending, done); - }; - - // Remained call in conference will be held. - for (let call of remainedCalls) { - let callName = "remainedCall (" + call.id.number + ')'; - - let onstatechange = callName + ".onstatechange"; - pending.push(onstatechange); - check_onstatechange(call, callName, 'held', - receive.bind(null, onstatechange)); - } + // callToRemove. + promises.push(waitForCallsChangedEvent(telephony, callToRemove)); + promises.push(waitForCallsChangedEvent(conference, callToRemove)); + promises.push(waitForGroupChangeEvent(callToRemove, null).then(() => { + is(callToRemove.state, 'connected'); + })); // When a call is removed from conference with 2 calls, another one will be // automatically removed from group and be put on hold. for (let call of autoRemovedCalls) { - let callName = "autoRemovedCall (" + call.id.number + ')'; - - let ongroupchange = callName + ".ongroupchange"; - pending.push(ongroupchange); - check_ongroupchange(call, callName, null, - receive.bind(null, ongroupchange)); - - let onstatechange = callName + ".onstatechange"; - pending.push(onstatechange); - check_onstatechange(call, callName, 'held', - receive.bind(null, onstatechange)); + promises.push(waitForCallsChangedEvent(telephony, call)); + promises.push(waitForCallsChangedEvent(conference, call)); + promises.push(waitForGroupChangeEvent(call, null)); + promises.push(waitForStateChangeEvent(call, "held")); } - check_ongroupchange(callToRemove, "callToRemove", null, function() { - is(callToRemove.state, 'connected'); - receive("callToRemove.ongroupchange"); - }); + // Remained call in conference will be held. + for (let call of remainedCalls) { + promises.push(waitForStateChangeEvent(call, "held")); + } - check_oncallschanged(telephony, 'telephony', - autoRemovedCalls.concat(callToRemove), - receive.bind(null, "telephony.oncallschanged")); - - check_oncallschanged(conference, 'conference', - autoRemovedCalls.concat(callToRemove), function() { - is(conference.calls.length, remainedCalls.length); - receive("conference.oncallschanged"); - }); - - check_onstatechange(conference, 'conference', - (remainedCalls.length ? 'held' : ''), function() { - ok(!conference.oncallschanged); - if (typeof statechangeCallback === 'function') { - statechangeCallback(); - } - receive("conference.onstatechange"); - }); + let finalConferenceState = remainedCalls.length ? "held" : ""; + let promise = waitForStateChangeEvent(conference, finalConferenceState) + .then(() => { + if (typeof statechangeCallback === 'function') { + statechangeCallback(); + } + }); + promises.push(promise); conference.remove(callToRemove); - return deferred.promise; + return Promise.all(promises) + .then(() => checkCalls(conference.calls, remainedCalls)) + .then(() => conference.calls); } /** @@ -1054,99 +829,61 @@ let emulator = (function() { * An array of TelephonyCall objects which remain in conference. * @param stateChangeCallback [optional] * A callback function which is called when conference state changes. - * @return A deferred promise. + * @return Promise<[TelephonyCall ...]> */ function hangUpCallInConference(callToHangUp, autoRemovedCalls, remainedCalls, statechangeCallback) { log("Release one call in conference."); - let deferred = Promise.defer(); - let done = function() { - deferred.resolve(); - }; + let promises = []; - let pending = ["conference.oncallschanged", "remoteHangUp"]; - let receive = function(name) { - receivedPending(name, pending, done); - }; + // callToHangUp. + promises.push(waitForCallsChangedEvent(conference, callToHangUp)); - // When a call is hang up from conference with 2 calls, another one will be + // When a call is removed from conference with 2 calls, another one will be // automatically removed from group. for (let call of autoRemovedCalls) { - let callName = "autoRemovedCall (" + call.id.number + ')'; - - let ongroupchange = callName + ".ongroupchange"; - pending.push(ongroupchange); - check_ongroupchange(call, callName, null, - receive.bind(null, ongroupchange)); + promises.push(waitForCallsChangedEvent(telephony, call)); + promises.push(waitForCallsChangedEvent(conference, call)); + promises.push(waitForGroupChangeEvent(call, null)); } - if (autoRemovedCalls.length) { - pending.push("telephony.oncallschanged"); - check_oncallschanged(telephony, 'telephony', - autoRemovedCalls, - receive.bind(null, "telephony.oncallschanged")); - } - - check_oncallschanged(conference, 'conference', - autoRemovedCalls.concat(callToHangUp), function() { - is(conference.calls.length, remainedCalls.length); - receive("conference.oncallschanged"); - }); - if (remainedCalls.length === 0) { - pending.push("conference.onstatechange"); - check_onstatechange(conference, 'conference', '', function() { - ok(!conference.oncallschanged); - if (typeof statechangeCallback === 'function') { - statechangeCallback(); - } - receive("conference.onstatechange"); - }); + let promise = waitForStateChangeEvent(conference, "") + .then(() => { + if (typeof statechangeCallback === 'function') { + statechangeCallback(); + } + }); + promises.push(promise); } - remoteHangUp(callToHangUp) - .then(receive.bind(null, "remoteHangUp")); + promises.push(remoteHangUp(callToHangUp)); - return deferred.promise; + return Promise.all(promises) + .then(() => checkCalls(conference.calls, remainedCalls)) + .then(() => conference.calls); } /** * Hangup conference. * - * @return A deferred promise. + * @return Promise */ function hangUpConference() { log("Hangup conference."); - let deferred = Promise.defer(); - let done = function() { - deferred.resolve(); - }; + let promises = []; - let pending = ["conference.hangUp", "conference.onstatechange"]; - let receive = function(name) { - receivedPending(name, pending, done); - }; + promises.push(waitForStateChangeEvent(conference, "")); for (let call of conference.calls) { - let callName = "Call (" + call.id.number + ')'; - - let onstatechange = callName + ".onstatechange"; - pending.push(onstatechange); - check_onstatechange(call, callName, 'disconnected', - receive.bind(null, onstatechange)); + promises.push(waitForNamedStateEvent(call, "disconnected")); } - check_onstatechange(conference, 'conference', '', function() { - receive("conference.onstatechange"); + return conference.hangUp().then(() => { + return Promise.all(promises); }); - - conference.hangUp().then(() => { - receive("conference.hangUp"); - }); - - return deferred.promise; } /** @@ -1287,6 +1024,7 @@ let emulator = (function() { */ this.gDelay = delay; + this.gWaitForEvent = waitForEvent; this.gCheckInitialState = checkInitialState; this.gClearCalls = clearCalls; this.gOutCallStrPool = outCallStrPool; @@ -1311,7 +1049,6 @@ let emulator = (function() { this.gHangUpCallInConference = hangUpCallInConference; this.gHangUpConference = hangUpConference; this.gSetupConference = setupConference; - this.gReceivedPending = receivedPending; }()); function _startTest(permissions, test) { @@ -1371,18 +1108,11 @@ function _startTest(permissions, test) { return tearDown.bind(this); }()); - function mainTest() { - setUp() - .then(function onSuccess() { - log("== Test Start =="); - test(); - }, function onError(error) { - SpecialPowers.Cu.reportError(error); - ok(false, "SetUp error"); - }); - } - - mainTest(); + setUp().then(() => { + log("== Test Start =="); + test(); + }) + .catch(error => ok(false, error)); } function startTest(test) { From d29e4c362728e9bc22a1f73814492cc1dd6d6d7a Mon Sep 17 00:00:00 2001 From: "Szu-Yu Chen [:aknow]" Date: Thu, 13 Nov 2014 10:58:46 +0800 Subject: [PATCH 37/80] Bug 1094089 - Part 3: Rewrite test_outgoing_radio_off.js. r=hsinyi --- .../marionette/test_outgoing_radio_off.js | 68 ++++++------------- 1 file changed, 20 insertions(+), 48 deletions(-) diff --git a/dom/telephony/test/marionette/test_outgoing_radio_off.js b/dom/telephony/test/marionette/test_outgoing_radio_off.js index 92de9015567f..bd2e98b43c76 100644 --- a/dom/telephony/test/marionette/test_outgoing_radio_off.js +++ b/dom/telephony/test/marionette/test_outgoing_radio_off.js @@ -6,57 +6,22 @@ MARIONETTE_HEAD_JS = 'head.js'; let connection; -function setRadioEnabled(enabled, callback) { - let request = connection.setRadioEnabled(enabled); +function setRadioEnabled(enabled) { let desiredRadioState = enabled ? 'enabled' : 'disabled'; + log("Set radio: " + desiredRadioState); - let pending = ['onradiostatechange', 'onsuccess']; - let done = callback; + let promises = []; - connection.onradiostatechange = function() { + let promise = gWaitForEvent(connection, "radiostatechange", event => { let state = connection.radioState; - log("Received 'radiostatechange' event, radioState: " + state); - - if (state == desiredRadioState) { - gReceivedPending('onradiostatechange', pending, done); - } - }; - - request.onsuccess = function onsuccess() { - gReceivedPending('onsuccess', pending, done); - }; - - request.onerror = function onerror() { - ok(false, "setRadioEnabled should be ok"); - }; -} - -function dial(number) { - // Verify initial state before dial. - ok(telephony); - is(telephony.active, null); - ok(telephony.calls); - is(telephony.calls.length, 0); - - log("Make an outgoing call."); - - telephony.dial(number).then(null, cause => { - log("Received promise 'reject'"); - - is(telephony.active, null); - is(telephony.calls.length, 0); - is(cause, "RadioNotAvailable"); - - emulator.runCmdWithCallback("gsm list", function(result) { - log("Initial call list: " + result); - - setRadioEnabled(true, cleanUp); - }); + log("current radioState: " + state); + return state == desiredRadioState; }); -} + promises.push(promise); -function cleanUp() { - finish(); + promises.push(connection.setRadioEnabled(enabled)); + + return Promise.all(promises); } startTestWithPermissions(['mobileconnection'], function() { @@ -64,7 +29,14 @@ startTestWithPermissions(['mobileconnection'], function() { ok(connection instanceof MozMobileConnection, "connection is instanceof " + connection.constructor); - setRadioEnabled(false, function() { - dial("0912345678"); - }); + setRadioEnabled(false) + .then(() => gDial("0912345678")) + .catch(cause => { + is(telephony.active, null); + is(telephony.calls.length, 0); + is(cause, "RadioNotAvailable"); + }) + .then(() => setRadioEnabled(true)) + .catch(error => ok(false, "Promise reject: " + error)) + .then(finish); }); From b5c6ce31e590fdbf523cf63a0f8c9f98aa1b77a0 Mon Sep 17 00:00:00 2001 From: B2G Bumper Bot Date: Wed, 12 Nov 2014 20:30:53 -0800 Subject: [PATCH 38/80] Bumping gaia.json for 2 gaia revision(s) a=gaia-bump ======== https://hg.mozilla.org/integration/gaia-central/rev/d59d24ac9804 Author: Yi-Fan Liao Desc: Merge pull request #26050 from begeeben/1095360_wallpaper_will_display_master Bug 1095369 - [FFOS2.0][Woodduck][Browser]Wallpaper will display when edit bookmark, r=alive ======== https://hg.mozilla.org/integration/gaia-central/rev/86bae88bdad4 Author: Yi-Fan Liao Desc: Bug 1095369 - [FFOS2.0][Woodduck][Browser]Wallpaper will display when edit bookmark When changing orientation from portrait to landscape and resizing with keyboard on, the layout manager in the system app will resize the height of the active app first with the keyboard height in portrait (line 55 in layout_manager.js). When the height of the keyboard in portrait mode is bigger than the height in landscape mode, the calculated height of the active app will be smaller than it should've been. The system wallpaper is visible at the mean time. Subsequent resize events later will immediately correct the active app height using the correct landscape keyboard height. The resizing event sequence is 'resize' --> 'keyboardchange' --> 'keyboardchange'. This patch disables the keyboard height check in the 'resize' event since it'd be incorrect during orientation change, which would display part of the system wallpaper in a flash. --- b2g/config/gaia.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/b2g/config/gaia.json b/b2g/config/gaia.json index bbf32b334532..7821a9a4ab90 100644 --- a/b2g/config/gaia.json +++ b/b2g/config/gaia.json @@ -4,6 +4,6 @@ "remote": "", "branch": "" }, - "revision": "84dc3d8c2e468b6bda102921438e5868d53484dd", + "revision": "d59d24ac98042fad879f9c61e22156ab4c16125b", "repo_path": "integration/gaia-central" } From f8d0afede4a455c0e816b005b7647c09ea5798d9 Mon Sep 17 00:00:00 2001 From: B2G Bumper Bot Date: Wed, 12 Nov 2014 20:37:17 -0800 Subject: [PATCH 39/80] Bumping manifests a=b2g-bump --- b2g/config/dolphin/sources.xml | 2 +- b2g/config/emulator-ics/sources.xml | 2 +- b2g/config/emulator-jb/sources.xml | 2 +- b2g/config/emulator-kk/sources.xml | 2 +- b2g/config/emulator/sources.xml | 2 +- b2g/config/flame-kk/sources.xml | 2 +- b2g/config/flame/sources.xml | 2 +- b2g/config/hamachi/sources.xml | 2 +- b2g/config/helix/sources.xml | 2 +- b2g/config/nexus-4/sources.xml | 2 +- b2g/config/wasabi/sources.xml | 2 +- 11 files changed, 11 insertions(+), 11 deletions(-) diff --git a/b2g/config/dolphin/sources.xml b/b2g/config/dolphin/sources.xml index efc3d95e939a..aee61b412f48 100644 --- a/b2g/config/dolphin/sources.xml +++ b/b2g/config/dolphin/sources.xml @@ -15,7 +15,7 @@ - + diff --git a/b2g/config/emulator-ics/sources.xml b/b2g/config/emulator-ics/sources.xml index b63f7de1cf35..34c26937b1af 100644 --- a/b2g/config/emulator-ics/sources.xml +++ b/b2g/config/emulator-ics/sources.xml @@ -19,7 +19,7 @@ - + diff --git a/b2g/config/emulator-jb/sources.xml b/b2g/config/emulator-jb/sources.xml index 6040758b5d1f..a6977f0e635d 100644 --- a/b2g/config/emulator-jb/sources.xml +++ b/b2g/config/emulator-jb/sources.xml @@ -17,7 +17,7 @@ - + diff --git a/b2g/config/emulator-kk/sources.xml b/b2g/config/emulator-kk/sources.xml index b3bc1cf70ffb..86bcc6bab5be 100644 --- a/b2g/config/emulator-kk/sources.xml +++ b/b2g/config/emulator-kk/sources.xml @@ -15,7 +15,7 @@ - + diff --git a/b2g/config/emulator/sources.xml b/b2g/config/emulator/sources.xml index b63f7de1cf35..34c26937b1af 100644 --- a/b2g/config/emulator/sources.xml +++ b/b2g/config/emulator/sources.xml @@ -19,7 +19,7 @@ - + diff --git a/b2g/config/flame-kk/sources.xml b/b2g/config/flame-kk/sources.xml index 1546b05c9581..d6eeab07dafa 100644 --- a/b2g/config/flame-kk/sources.xml +++ b/b2g/config/flame-kk/sources.xml @@ -15,7 +15,7 @@ - + diff --git a/b2g/config/flame/sources.xml b/b2g/config/flame/sources.xml index 10fbcb9fa2b6..71b05af2cef9 100644 --- a/b2g/config/flame/sources.xml +++ b/b2g/config/flame/sources.xml @@ -17,7 +17,7 @@ - + diff --git a/b2g/config/hamachi/sources.xml b/b2g/config/hamachi/sources.xml index d7931fe57e93..9ab00c5b99ec 100644 --- a/b2g/config/hamachi/sources.xml +++ b/b2g/config/hamachi/sources.xml @@ -17,7 +17,7 @@ - + diff --git a/b2g/config/helix/sources.xml b/b2g/config/helix/sources.xml index 0801fb96e797..674b22889c5c 100644 --- a/b2g/config/helix/sources.xml +++ b/b2g/config/helix/sources.xml @@ -15,7 +15,7 @@ - + diff --git a/b2g/config/nexus-4/sources.xml b/b2g/config/nexus-4/sources.xml index 70094a9d0cb0..57bbb3c8f1a6 100644 --- a/b2g/config/nexus-4/sources.xml +++ b/b2g/config/nexus-4/sources.xml @@ -17,7 +17,7 @@ - + diff --git a/b2g/config/wasabi/sources.xml b/b2g/config/wasabi/sources.xml index 7775c9cd5867..92107839886d 100644 --- a/b2g/config/wasabi/sources.xml +++ b/b2g/config/wasabi/sources.xml @@ -17,7 +17,7 @@ - + From be43a4ea819226987dfc9e0e1eeb1164050d877f Mon Sep 17 00:00:00 2001 From: Michael Wu Date: Thu, 13 Nov 2014 14:11:03 +0800 Subject: [PATCH 40/80] Bug 1085383 - Allow FM radio tuning to be run on a separate thread, r=dhylands --- hal/Hal.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/hal/Hal.cpp b/hal/Hal.cpp index 04b7553b390b..d189888ae251 100644 --- a/hal/Hal.cpp +++ b/hal/Hal.cpp @@ -1072,7 +1072,6 @@ DisableFMRadio() { void FMRadioSeek(const FMRadioSeekDirection& aDirection) { - AssertMainThread(); PROXY_IF_SANDBOXED(FMRadioSeek(aDirection)); } @@ -1084,7 +1083,6 @@ GetFMRadioSettings(FMRadioSettings* aInfo) { void SetFMRadioFrequency(const uint32_t aFrequency) { - AssertMainThread(); PROXY_IF_SANDBOXED(SetFMRadioFrequency(aFrequency)); } From 70fce093ea5084ab6d48ef8c6223eceb63d61231 Mon Sep 17 00:00:00 2001 From: "L. David Baron" Date: Wed, 12 Nov 2014 23:28:52 -0800 Subject: [PATCH 41/80] Bug 1086937 patch 0 - Add missing null check of root element so this patch series doesn't expose a crash in layout/style/crashtests/472237-1.html . r=birtles --- layout/base/RestyleManager.cpp | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/layout/base/RestyleManager.cpp b/layout/base/RestyleManager.cpp index 7a239adfe948..5d0896e9c496 100644 --- a/layout/base/RestyleManager.cpp +++ b/layout/base/RestyleManager.cpp @@ -1495,8 +1495,12 @@ RestyleManager::DoRebuildAllStyleData(RestyleTracker& aRestyleTracker, // different styles). If we use up the hint for one of the // ancestors that we hit first, then we'll fail to do the restyling // we need to do. - aRestyleTracker.AddPendingRestyle(mPresContext->Document()->GetRootElement(), - aRestyleHint, nsChangeHint(0)); + Element* root = mPresContext->Document()->GetRootElement(); + if (root) { + // If the root element is gone, dropping the hint on the floor + // should be fine. + aRestyleTracker.AddPendingRestyle(root, aRestyleHint, nsChangeHint(0)); + } aRestyleHint = nsRestyleHint(0); } From 0c5741e2ef824603830ffa962a9fcc748f2ef2f9 Mon Sep 17 00:00:00 2001 From: "L. David Baron" Date: Wed, 12 Nov 2014 23:28:52 -0800 Subject: [PATCH 42/80] Bug 1086937 patch 1 - Add eRestyle_ChangeAnimationPhaseDescendants restyle hint that is like eRestyle_ChangeAnimationPhase, but for a whole subtree. r=birtles --- layout/base/RestyleManager.cpp | 12 ++++++++---- layout/base/nsChangeHint.h | 8 ++++++-- layout/style/nsStyleSet.cpp | 33 ++++++++++++++++++++++++++------- 3 files changed, 40 insertions(+), 13 deletions(-) diff --git a/layout/base/RestyleManager.cpp b/layout/base/RestyleManager.cpp index 5d0896e9c496..ca7fcbc445fc 100644 --- a/layout/base/RestyleManager.cpp +++ b/layout/base/RestyleManager.cpp @@ -2519,11 +2519,13 @@ ElementRestyler::Restyle(nsRestyleHint aRestyleHint) } } - // If we are restyling this frame with eRestyle_Self, we restyle - // children with nsRestyleHint(0). But we pass the eRestyle_ForceDescendants - // flag down too. + // If we are restyling this frame with eRestyle_Self or weaker hints, + // we restyle children with nsRestyleHint(0). But we pass the + // eRestyle_ChangeAnimationPhaseDescendants and eRestyle_ForceDescendants + // flags down too. nsRestyleHint childRestyleHint = nsRestyleHint(aRestyleHint & (eRestyle_Subtree | + eRestyle_ChangeAnimationPhaseDescendants | eRestyle_ForceDescendants)); nsRefPtr oldContext = mFrame->StyleContext(); @@ -3740,7 +3742,9 @@ RestyleManager::RestyleHintToString(nsRestyleHint aHint) bool any = false; const char* names[] = { "Self", "Subtree", "LaterSiblings", "CSSTransitions", "CSSAnimations", "SVGAttrAnimations", "StyleAttribute", - "ChangeAnimationPhase", "Force", "ForceDescendants" }; + "ChangeAnimationPhase", + "ChangeAnimationPhaseDescendants", + "Force", "ForceDescendants" }; uint32_t hint = aHint & ((1 << ArrayLength(names)) - 1); uint32_t rest = aHint & ~((1 << ArrayLength(names)) - 1); for (uint32_t i = 0; i < ArrayLength(names); i++) { diff --git a/layout/base/nsChangeHint.h b/layout/base/nsChangeHint.h index 9cf0515f798d..fb9b3a36b4ab 100644 --- a/layout/base/nsChangeHint.h +++ b/layout/base/nsChangeHint.h @@ -346,16 +346,20 @@ enum nsRestyleHint { // FIXME: Remove this as part of bug 960465. eRestyle_ChangeAnimationPhase = (1 << 7), + // Same as the previous, except this applies to the entire subtree. + // FIXME: Remove this as part of bug 960465. + eRestyle_ChangeAnimationPhaseDescendants = (1 << 8), + // Continue the restyling process to the current frame's children even // if this frame's restyling resulted in no style changes. - eRestyle_Force = (1<<8), + eRestyle_Force = (1<<9), // Continue the restyling process to all of the current frame's // descendants, even if any frame's restyling resulted in no style // changes. (Implies eRestyle_Force.) Note that this is weaker than // eRestyle_Subtree, which makes us rerun selector matching on all // descendants rather than just continuing the restyling process. - eRestyle_ForceDescendants = (1<<9), + eRestyle_ForceDescendants = (1<<10), }; // The functions below need an integral type to cast to to avoid diff --git a/layout/style/nsStyleSet.cpp b/layout/style/nsStyleSet.cpp index c0d32396ef39..239b4e50ac51 100644 --- a/layout/style/nsStyleSet.cpp +++ b/layout/style/nsStyleSet.cpp @@ -1360,6 +1360,7 @@ nsStyleSet::RuleNodeWithReplacement(Element* aElement, eRestyle_SVGAttrAnimations | eRestyle_StyleAttribute | eRestyle_ChangeAnimationPhase | + eRestyle_ChangeAnimationPhaseDescendants | eRestyle_Force | eRestyle_ForceDescendants)), // FIXME: Once bug 979133 lands we'll have a better @@ -1369,11 +1370,27 @@ nsStyleSet::RuleNodeWithReplacement(Element* aElement, // If we're changing animation phase, we have to reconsider what rules // are in these four levels. - if (aReplacements & eRestyle_ChangeAnimationPhase) { - aReplacements |= eRestyle_CSSTransitions | - eRestyle_CSSAnimations | - eRestyle_SVGAttrAnimations | - eRestyle_StyleAttribute; + if (aReplacements & (eRestyle_ChangeAnimationPhase | + eRestyle_ChangeAnimationPhaseDescendants)) { + // Animations are only on elements and on :before and :after + // pseudo-elements, so those are the only things we need to consider + // when changing animation phase. Furthermore, the :before and + // :after pseudo-elements cannot have style attributes (although + // some other pseudo-elements can). This lets us avoid the problem + // that the eRestyle_StyleAttribute case below can't handle + // pseudo-elements, but not adding that bit to aReplacements for + // pseudo-elements, since we don't need it. + if (aPseudoType == nsCSSPseudoElements::ePseudo_NotPseudoElement) { + aReplacements |= eRestyle_CSSTransitions | + eRestyle_CSSAnimations | + eRestyle_SVGAttrAnimations | + eRestyle_StyleAttribute; + } else if (aPseudoType == nsCSSPseudoElements::ePseudo_before || + aPseudoType == nsCSSPseudoElements::ePseudo_after) { + aReplacements |= eRestyle_CSSTransitions | + eRestyle_CSSAnimations | + eRestyle_SVGAttrAnimations; + } } // FIXME (perf): This should probably not rebuild the whole path, but @@ -1435,7 +1452,8 @@ nsStyleSet::RuleNodeWithReplacement(Element* aElement, break; } case eRestyle_SVGAttrAnimations: { - MOZ_ASSERT(aReplacements & eRestyle_ChangeAnimationPhase, + MOZ_ASSERT(aReplacements & (eRestyle_ChangeAnimationPhase | + eRestyle_ChangeAnimationPhaseDescendants), "don't know how to do this level without phase change"); SVGAttrAnimationRuleProcessor* ruleProcessor = @@ -1448,7 +1466,8 @@ nsStyleSet::RuleNodeWithReplacement(Element* aElement, break; } case eRestyle_StyleAttribute: { - MOZ_ASSERT(aReplacements & eRestyle_ChangeAnimationPhase, + MOZ_ASSERT(aReplacements & (eRestyle_ChangeAnimationPhase | + eRestyle_ChangeAnimationPhaseDescendants), "don't know how to do this level without phase change"); if (!level->mIsImportant) { From 5fc1b3d275b417d68c8c1dd23a215bc3da6b94da Mon Sep 17 00:00:00 2001 From: "L. David Baron" Date: Wed, 12 Nov 2014 23:28:52 -0800 Subject: [PATCH 43/80] Bug 1086937 patch 2 - Use eRestyle_ChangeAnimationPhaseDescendants to get the right style data in RestyleManager::RebuildAllStyleData. r=birtles Until we get rid of animation phases in bug 960465, we need to ensure we're producing style data for the correct animation phase. This makes this optimization slightly less beneficial until then. --- layout/base/RestyleManager.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/layout/base/RestyleManager.cpp b/layout/base/RestyleManager.cpp index ca7fcbc445fc..208b10732335 100644 --- a/layout/base/RestyleManager.cpp +++ b/layout/base/RestyleManager.cpp @@ -1453,9 +1453,12 @@ RestyleManager::RebuildAllStyleData(nsChangeHint aExtraHint, // Until we get rid of these phases in bug 960465, we need to skip // animation restyles during the non-animation phase, and post // animation restyles so that we restyle those elements again in the - // animation phase. + // animation phase. Furthermore, we need to add + // eRestyle_ChangeAnimationPhaseDescendants so that we actually honor + // these booleans in all cases. mSkipAnimationRules = true; mPostAnimationRestyles = true; + aRestyleHint |= eRestyle_ChangeAnimationPhaseDescendants; DoRebuildAllStyleData(mPendingRestyles, aExtraHint, aRestyleHint); From 7cff21024ea3e975e3a925f923aa01d78fb68869 Mon Sep 17 00:00:00 2001 From: "L. David Baron" Date: Wed, 12 Nov 2014 23:28:52 -0800 Subject: [PATCH 44/80] Bug 1086937 patch 3 - Add test for animations continuing across a user font set update. r=birtles I confirmed that without patch 2, the third and fourth tests fail (reporting -1000px), whereas with the patches all 4 tests pass. --- layout/style/test/mochitest.ini | 2 + .../test/test_animations_async_tests.html | 70 +++++++++++++++++++ 2 files changed, 72 insertions(+) create mode 100644 layout/style/test/test_animations_async_tests.html diff --git a/layout/style/test/mochitest.ini b/layout/style/test/mochitest.ini index 8d669e1ed44f..e69c53120062 100644 --- a/layout/style/test/mochitest.ini +++ b/layout/style/test/mochitest.ini @@ -249,3 +249,5 @@ support-files = bug732209-css.sjs [test_counter_style.html] [test_counter_descriptor_storage.html] [test_position_float_display.html] +[test_animations_async_tests.html] +support-files = ../../reftests/fonts/Ahem.ttf diff --git a/layout/style/test/test_animations_async_tests.html b/layout/style/test/test_animations_async_tests.html new file mode 100644 index 000000000000..5516ee63e0d2 --- /dev/null +++ b/layout/style/test/test_animations_async_tests.html @@ -0,0 +1,70 @@ + + + + + Test for Bug 1086937 + + + + + + + +Mozilla Bug 1086937 +
+
+
+ + From 77e97a6efd256cf6aed5e7411cc4a6782f9945d9 Mon Sep 17 00:00:00 2001 From: B2G Bumper Bot Date: Wed, 12 Nov 2014 23:30:53 -0800 Subject: [PATCH 45/80] Bumping gaia.json for 2 gaia revision(s) a=gaia-bump ======== https://hg.mozilla.org/integration/gaia-central/rev/b8c327a878e0 Author: Marina Desc: Merge pull request #25547 from gitmai/bug-1069157-pdfViewer-update-pdf.js Bug 1069157 - [PDF Viewer] update pdf.js in Gaia r=yuri ======== https://hg.mozilla.org/integration/gaia-central/rev/8ad666435350 Author: mai Desc: Bug 1069157 - [PDF Viewer] update pdf.js in Gaia --- b2g/config/gaia.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/b2g/config/gaia.json b/b2g/config/gaia.json index 7821a9a4ab90..50af807dc70b 100644 --- a/b2g/config/gaia.json +++ b/b2g/config/gaia.json @@ -4,6 +4,6 @@ "remote": "", "branch": "" }, - "revision": "d59d24ac98042fad879f9c61e22156ab4c16125b", + "revision": "b8c327a878e0bdb7368dc19f58bcc105ac0859e4", "repo_path": "integration/gaia-central" } From 6309c51ca61f0d63b4d29365648ad31b13eb6f09 Mon Sep 17 00:00:00 2001 From: B2G Bumper Bot Date: Wed, 12 Nov 2014 23:42:18 -0800 Subject: [PATCH 46/80] Bumping manifests a=b2g-bump --- b2g/config/dolphin/sources.xml | 2 +- b2g/config/emulator-ics/sources.xml | 2 +- b2g/config/emulator-jb/sources.xml | 2 +- b2g/config/emulator-kk/sources.xml | 2 +- b2g/config/emulator/sources.xml | 2 +- b2g/config/flame-kk/sources.xml | 2 +- b2g/config/flame/sources.xml | 2 +- b2g/config/hamachi/sources.xml | 2 +- b2g/config/helix/sources.xml | 2 +- b2g/config/nexus-4/sources.xml | 2 +- b2g/config/wasabi/sources.xml | 2 +- 11 files changed, 11 insertions(+), 11 deletions(-) diff --git a/b2g/config/dolphin/sources.xml b/b2g/config/dolphin/sources.xml index aee61b412f48..c9747b5f6c54 100644 --- a/b2g/config/dolphin/sources.xml +++ b/b2g/config/dolphin/sources.xml @@ -15,7 +15,7 @@ - + diff --git a/b2g/config/emulator-ics/sources.xml b/b2g/config/emulator-ics/sources.xml index 34c26937b1af..8a976aaf08bf 100644 --- a/b2g/config/emulator-ics/sources.xml +++ b/b2g/config/emulator-ics/sources.xml @@ -19,7 +19,7 @@ - + diff --git a/b2g/config/emulator-jb/sources.xml b/b2g/config/emulator-jb/sources.xml index a6977f0e635d..f218ab214fce 100644 --- a/b2g/config/emulator-jb/sources.xml +++ b/b2g/config/emulator-jb/sources.xml @@ -17,7 +17,7 @@ - + diff --git a/b2g/config/emulator-kk/sources.xml b/b2g/config/emulator-kk/sources.xml index 86bcc6bab5be..8d5b41ec2f8c 100644 --- a/b2g/config/emulator-kk/sources.xml +++ b/b2g/config/emulator-kk/sources.xml @@ -15,7 +15,7 @@ - + diff --git a/b2g/config/emulator/sources.xml b/b2g/config/emulator/sources.xml index 34c26937b1af..8a976aaf08bf 100644 --- a/b2g/config/emulator/sources.xml +++ b/b2g/config/emulator/sources.xml @@ -19,7 +19,7 @@ - + diff --git a/b2g/config/flame-kk/sources.xml b/b2g/config/flame-kk/sources.xml index d6eeab07dafa..3193c88cf4ad 100644 --- a/b2g/config/flame-kk/sources.xml +++ b/b2g/config/flame-kk/sources.xml @@ -15,7 +15,7 @@ - + diff --git a/b2g/config/flame/sources.xml b/b2g/config/flame/sources.xml index 71b05af2cef9..fa345bd71ecd 100644 --- a/b2g/config/flame/sources.xml +++ b/b2g/config/flame/sources.xml @@ -17,7 +17,7 @@ - + diff --git a/b2g/config/hamachi/sources.xml b/b2g/config/hamachi/sources.xml index 9ab00c5b99ec..ad8b21dde310 100644 --- a/b2g/config/hamachi/sources.xml +++ b/b2g/config/hamachi/sources.xml @@ -17,7 +17,7 @@ - + diff --git a/b2g/config/helix/sources.xml b/b2g/config/helix/sources.xml index 674b22889c5c..3d21c1c49adb 100644 --- a/b2g/config/helix/sources.xml +++ b/b2g/config/helix/sources.xml @@ -15,7 +15,7 @@ - + diff --git a/b2g/config/nexus-4/sources.xml b/b2g/config/nexus-4/sources.xml index 57bbb3c8f1a6..311b189bde6c 100644 --- a/b2g/config/nexus-4/sources.xml +++ b/b2g/config/nexus-4/sources.xml @@ -17,7 +17,7 @@ - + diff --git a/b2g/config/wasabi/sources.xml b/b2g/config/wasabi/sources.xml index 92107839886d..7cbbc572a13d 100644 --- a/b2g/config/wasabi/sources.xml +++ b/b2g/config/wasabi/sources.xml @@ -17,7 +17,7 @@ - + From e95dbcf133c6efa926f0469a47dc4a9caa658480 Mon Sep 17 00:00:00 2001 From: B2G Bumper Bot Date: Wed, 12 Nov 2014 23:45:59 -0800 Subject: [PATCH 47/80] Bumping gaia.json for 2 gaia revision(s) a=gaia-bump ======== https://hg.mozilla.org/integration/gaia-central/rev/c1bed74af46c Author: Carsten Book Desc: Merge pull request #26077 from aosmond/bug1093797 Bug 1093797 - Clear cached picture size when releasing camera. r=jdarcangelo ======== https://hg.mozilla.org/integration/gaia-central/rev/f4ee3dfaac64 Author: Andrew Osmond Desc: Bug 1093797 - Clear cached picture size when releasing camera. --- b2g/config/gaia.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/b2g/config/gaia.json b/b2g/config/gaia.json index 50af807dc70b..c9ecbf4dbb20 100644 --- a/b2g/config/gaia.json +++ b/b2g/config/gaia.json @@ -4,6 +4,6 @@ "remote": "", "branch": "" }, - "revision": "b8c327a878e0bdb7368dc19f58bcc105ac0859e4", + "revision": "c1bed74af46cb81a7092d6e80624134bae5d1bf0", "repo_path": "integration/gaia-central" } From d90b86847860e4515b771e66cdbed8f8a4deaa32 Mon Sep 17 00:00:00 2001 From: B2G Bumper Bot Date: Wed, 12 Nov 2014 23:56:55 -0800 Subject: [PATCH 48/80] Bumping manifests a=b2g-bump --- b2g/config/dolphin/sources.xml | 2 +- b2g/config/emulator-ics/sources.xml | 2 +- b2g/config/emulator-jb/sources.xml | 2 +- b2g/config/emulator-kk/sources.xml | 2 +- b2g/config/emulator/sources.xml | 2 +- b2g/config/flame-kk/sources.xml | 2 +- b2g/config/flame/sources.xml | 2 +- b2g/config/hamachi/sources.xml | 2 +- b2g/config/helix/sources.xml | 2 +- b2g/config/nexus-4/sources.xml | 2 +- b2g/config/wasabi/sources.xml | 2 +- 11 files changed, 11 insertions(+), 11 deletions(-) diff --git a/b2g/config/dolphin/sources.xml b/b2g/config/dolphin/sources.xml index c9747b5f6c54..e0ad4a88b076 100644 --- a/b2g/config/dolphin/sources.xml +++ b/b2g/config/dolphin/sources.xml @@ -15,7 +15,7 @@ - + diff --git a/b2g/config/emulator-ics/sources.xml b/b2g/config/emulator-ics/sources.xml index 8a976aaf08bf..221ae3b10b09 100644 --- a/b2g/config/emulator-ics/sources.xml +++ b/b2g/config/emulator-ics/sources.xml @@ -19,7 +19,7 @@ - + diff --git a/b2g/config/emulator-jb/sources.xml b/b2g/config/emulator-jb/sources.xml index f218ab214fce..3b5b8d460af1 100644 --- a/b2g/config/emulator-jb/sources.xml +++ b/b2g/config/emulator-jb/sources.xml @@ -17,7 +17,7 @@ - + diff --git a/b2g/config/emulator-kk/sources.xml b/b2g/config/emulator-kk/sources.xml index 8d5b41ec2f8c..c40ba1a4d975 100644 --- a/b2g/config/emulator-kk/sources.xml +++ b/b2g/config/emulator-kk/sources.xml @@ -15,7 +15,7 @@ - + diff --git a/b2g/config/emulator/sources.xml b/b2g/config/emulator/sources.xml index 8a976aaf08bf..221ae3b10b09 100644 --- a/b2g/config/emulator/sources.xml +++ b/b2g/config/emulator/sources.xml @@ -19,7 +19,7 @@ - + diff --git a/b2g/config/flame-kk/sources.xml b/b2g/config/flame-kk/sources.xml index 3193c88cf4ad..f4c1cafb8bdb 100644 --- a/b2g/config/flame-kk/sources.xml +++ b/b2g/config/flame-kk/sources.xml @@ -15,7 +15,7 @@ - + diff --git a/b2g/config/flame/sources.xml b/b2g/config/flame/sources.xml index fa345bd71ecd..26ed0b9d16c3 100644 --- a/b2g/config/flame/sources.xml +++ b/b2g/config/flame/sources.xml @@ -17,7 +17,7 @@ - + diff --git a/b2g/config/hamachi/sources.xml b/b2g/config/hamachi/sources.xml index ad8b21dde310..a6ce75148e75 100644 --- a/b2g/config/hamachi/sources.xml +++ b/b2g/config/hamachi/sources.xml @@ -17,7 +17,7 @@ - + diff --git a/b2g/config/helix/sources.xml b/b2g/config/helix/sources.xml index 3d21c1c49adb..8ec990dc991b 100644 --- a/b2g/config/helix/sources.xml +++ b/b2g/config/helix/sources.xml @@ -15,7 +15,7 @@ - + diff --git a/b2g/config/nexus-4/sources.xml b/b2g/config/nexus-4/sources.xml index 311b189bde6c..2167522cc8ad 100644 --- a/b2g/config/nexus-4/sources.xml +++ b/b2g/config/nexus-4/sources.xml @@ -17,7 +17,7 @@ - + diff --git a/b2g/config/wasabi/sources.xml b/b2g/config/wasabi/sources.xml index 7cbbc572a13d..e6856fe789e8 100644 --- a/b2g/config/wasabi/sources.xml +++ b/b2g/config/wasabi/sources.xml @@ -17,7 +17,7 @@ - + From a6f3398faa2bb7cc770471edad389611d5268d12 Mon Sep 17 00:00:00 2001 From: Gabor Krizsanits Date: Thu, 13 Nov 2014 09:50:12 +0100 Subject: [PATCH 49/80] Bug 1081038 - part 1: Microtask in AutoEntryScript. r=bholley --- dom/base/ScriptSettings.cpp | 8 ++++++++ dom/base/ScriptSettings.h | 1 + 2 files changed, 9 insertions(+) diff --git a/dom/base/ScriptSettings.cpp b/dom/base/ScriptSettings.cpp index d7c26096da1c..e02d1fc288fe 100644 --- a/dom/base/ScriptSettings.cpp +++ b/dom/base/ScriptSettings.cpp @@ -463,14 +463,22 @@ AutoEntryScript::AutoEntryScript(nsIGlobalObject* aGlobalObject, aCx ? aCx : FindJSContext(aGlobalObject)) , ScriptSettingsStackEntry(aGlobalObject, /* aCandidate = */ true) , mWebIDLCallerPrincipal(nullptr) + , mIsMainThread(aIsMainThread) { MOZ_ASSERT(aGlobalObject); MOZ_ASSERT_IF(!aCx, aIsMainThread); // cx is mandatory off-main-thread. MOZ_ASSERT_IF(aCx && aIsMainThread, aCx == FindJSContext(aGlobalObject)); + if (aIsMainThread) { + nsContentUtils::EnterMicroTask(); + } } AutoEntryScript::~AutoEntryScript() { + if (mIsMainThread) { + nsContentUtils::LeaveMicroTask(); + } + // GC when we pop a script entry point. This is a useful heuristic that helps // us out on certain (flawed) benchmarks like sunspider, because it lets us // avoid GCing during the timing loop. diff --git a/dom/base/ScriptSettings.h b/dom/base/ScriptSettings.h index f6559a447e00..ffb78ae6f73c 100644 --- a/dom/base/ScriptSettings.h +++ b/dom/base/ScriptSettings.h @@ -330,6 +330,7 @@ private: // bit up the stack, and which will outlive us. So we know the principal // can't go away until then either. nsIPrincipal* mWebIDLCallerPrincipal; + bool mIsMainThread; friend nsIPrincipal* GetWebIDLCallerPrincipal(); }; From beb54125e84d30420280488a8ef9ea260174a1f4 Mon Sep 17 00:00:00 2001 From: Gabor Krizsanits Date: Thu, 13 Nov 2014 09:50:15 +0100 Subject: [PATCH 50/80] Bug 1081038 - part 2: Removing nsAutoMicroTask where we have AutoEntryScript. r=bholley --- dom/base/nsJSUtils.cpp | 1 - dom/bindings/CallbackObject.cpp | 10 ---------- dom/xbl/nsXBLProtoImplField.cpp | 2 -- dom/xbl/nsXBLProtoImplMethod.cpp | 2 -- dom/xul/XULDocument.cpp | 4 +--- 5 files changed, 1 insertion(+), 18 deletions(-) diff --git a/dom/base/nsJSUtils.cpp b/dom/base/nsJSUtils.cpp index de4e73c6901c..15e0617ea588 100644 --- a/dom/base/nsJSUtils.cpp +++ b/dom/base/nsJSUtils.cpp @@ -208,7 +208,6 @@ nsJSUtils::EvaluateString(JSContext* aCx, // set to false. aRetValue.setUndefined(); - nsAutoMicroTask mt; nsresult rv = NS_OK; nsIScriptSecurityManager* ssm = nsContentUtils::GetSecurityManager(); diff --git a/dom/bindings/CallbackObject.cpp b/dom/bindings/CallbackObject.cpp index 40137f93cc9a..76048849a1c2 100644 --- a/dom/bindings/CallbackObject.cpp +++ b/dom/bindings/CallbackObject.cpp @@ -57,10 +57,6 @@ CallbackObject::CallSetup::CallSetup(CallbackObject* aCallback, , mExceptionHandling(aExceptionHandling) , mIsMainThread(NS_IsMainThread()) { - if (mIsMainThread) { - nsContentUtils::EnterMicroTask(); - } - // Compute the caller's subject principal (if necessary) early, before we // do anything that might perturb the relevant state. nsIPrincipal* webIDLCallerPrincipal = nullptr; @@ -274,12 +270,6 @@ CallbackObject::CallSetup::~CallSetup() mAutoIncumbentScript.reset(); mAutoEntryScript.reset(); - - // It is important that this is the last thing we do, after leaving the - // compartment and undoing all our entry/incumbent script changes - if (mIsMainThread) { - nsContentUtils::LeaveMicroTask(); - } } already_AddRefed diff --git a/dom/xbl/nsXBLProtoImplField.cpp b/dom/xbl/nsXBLProtoImplField.cpp index 07ae96bda438..b80da21ae4c9 100644 --- a/dom/xbl/nsXBLProtoImplField.cpp +++ b/dom/xbl/nsXBLProtoImplField.cpp @@ -392,8 +392,6 @@ nsXBLProtoImplField::InstallField(JS::Handle aBoundNode, return NS_OK; } - nsAutoMicroTask mt; - nsAutoCString uriSpec; aBindingDocURI->GetSpec(uriSpec); diff --git a/dom/xbl/nsXBLProtoImplMethod.cpp b/dom/xbl/nsXBLProtoImplMethod.cpp index d28b034e8fd5..965ddcdebaac 100644 --- a/dom/xbl/nsXBLProtoImplMethod.cpp +++ b/dom/xbl/nsXBLProtoImplMethod.cpp @@ -292,8 +292,6 @@ nsXBLProtoImplAnonymousMethod::Execute(nsIContent* aBoundElement, JSAddonId* aAd return NS_OK; } - nsAutoMicroTask mt; - // We are going to run script via JS::Call, so we need a script entry point, // but as this is XBL related it does not appear in the HTML spec. dom::AutoEntryScript aes(global); diff --git a/dom/xul/XULDocument.cpp b/dom/xul/XULDocument.cpp index a31a93385c0d..34ff948df245 100644 --- a/dom/xul/XULDocument.cpp +++ b/dom/xul/XULDocument.cpp @@ -3573,9 +3573,7 @@ XULDocument::ExecuteScript(nsXULPrototypeScript *aScript) JS::HandleScript scriptObject = aScript->GetScriptObject(); NS_ENSURE_TRUE(scriptObject, NS_ERROR_UNEXPECTED); - // Execute the precompiled script with the given version - nsAutoMicroTask mt; - + // Execute the precompiled script with the given version. // We're about to run script via JS::CloneAndExecuteScript, so we need an // AutoEntryScript. This is Gecko specific and not in any spec. AutoEntryScript aes(mScriptGlobalObject); From a2a1b295177f60fa45c6c7963c5d022a31544e56 Mon Sep 17 00:00:00 2001 From: Jonathan Kew Date: Thu, 13 Nov 2014 08:58:02 +0000 Subject: [PATCH 51/80] Bug 1094914 - part 1 - Don't confuse frame and line writing-modes in nsLineLayout. r=smontagu --- layout/generic/nsLineLayout.cpp | 29 ++++++++++++++--------------- 1 file changed, 14 insertions(+), 15 deletions(-) diff --git a/layout/generic/nsLineLayout.cpp b/layout/generic/nsLineLayout.cpp index edcb91937319..ad3552efb7f8 100644 --- a/layout/generic/nsLineLayout.cpp +++ b/layout/generic/nsLineLayout.cpp @@ -1519,7 +1519,7 @@ nsLineLayout::PlaceTopBottomFrames(PerSpanData* psd, } else { pfd->mBounds.BStart(lineWM) = - -aDistanceFromStart + pfd->mMargin.BStart(frameWM); + -aDistanceFromStart + pfd->mMargin.ConvertTo(lineWM, frameWM).BStart(lineWM); } pfd->mFrame->SetRect(lineWM, pfd->mBounds, containerWidth); #ifdef NOISY_BLOCKDIR_ALIGN @@ -1527,7 +1527,7 @@ nsLineLayout::PlaceTopBottomFrames(PerSpanData* psd, nsFrame::ListTag(stdout, pfd->mFrame); printf(": y=%d dTop=%d [bp.top=%d topLeading=%d]\n", pfd->mBounds.BStart(lineWM), aDistanceFromStart, - span ? pfd->mBorderPadding.BStart(frameWM) : 0, + span ? pfd->mBorderPadding.ConvertTo(lineWM, frameWM).BStart(lineWM) : 0, span ? span->mBStartLeading : 0); #endif break; @@ -1539,7 +1539,7 @@ nsLineLayout::PlaceTopBottomFrames(PerSpanData* psd, } else { pfd->mBounds.BStart(lineWM) = -aDistanceFromStart + aLineBSize - - pfd->mMargin.BEnd(frameWM) - pfd->mBounds.BSize(lineWM); + pfd->mMargin.ConvertTo(lineWM, frameWM).BEnd(lineWM) - pfd->mBounds.BSize(lineWM); } pfd->mFrame->SetRect(lineWM, pfd->mBounds, containerWidth); #ifdef NOISY_BLOCKDIR_ALIGN @@ -1725,8 +1725,7 @@ nsLineLayout::VerticalAlignFrames(PerSpanData* psd) mBlockReflowState->ComputedHeight(), inflation); nscoord contentBSize = spanFramePFD->mBounds.BSize(lineWM) - - spanFramePFD->mBorderPadding.BStart(frameWM) - - spanFramePFD->mBorderPadding.BEnd(frameWM); + spanFramePFD->mBorderPadding.ConvertTo(lineWM, frameWM).BStartEnd(lineWM); // Special-case for a ::first-letter frame, set the line height to // the frame block size if the user has left line-height == normal @@ -1759,7 +1758,7 @@ nsLineLayout::VerticalAlignFrames(PerSpanData* psd) // If there are child frames in this span that stick out of this area // then the minBCoord and maxBCoord are updated by the amount of logical // blockSize that is outside this range. - minBCoord = spanFramePFD->mBorderPadding.BStart(frameWM) - + minBCoord = spanFramePFD->mBorderPadding.ConvertTo(lineWM, frameWM).BStart(lineWM) - psd->mBStartLeading; maxBCoord = minBCoord + psd->mLogicalBSize; } @@ -1807,7 +1806,7 @@ nsLineLayout::VerticalAlignFrames(PerSpanData* psd) // For other elements the logical block size is the same as the // frame's block size plus its margins. logicalBSize = pfd->mBounds.BSize(lineWM) + - pfd->mMargin.BStartEnd(frameWM); + pfd->mMargin.ConvertTo(lineWM, frameWM).BStartEnd(lineWM); if (logicalBSize < 0 && mPresContext->CompatibilityMode() == eCompatibility_NavQuirks) { pfd->mAscent -= logicalBSize; @@ -1915,7 +1914,7 @@ nsLineLayout::VerticalAlignFrames(PerSpanData* psd) else { pfd->mBounds.BStart(lineWM) = baselineBCoord - (parentXHeight + logicalBSize)/2 + - pfd->mMargin.BStart(frameWM); + pfd->mMargin.ConvertTo(lineWM, frameWM).BStart(lineWM); } pfd->mBlockDirAlign = VALIGN_OTHER; break; @@ -1930,11 +1929,11 @@ nsLineLayout::VerticalAlignFrames(PerSpanData* psd) nscoord parentAscent = fm->MaxAscent(); if (frameSpan) { pfd->mBounds.BStart(lineWM) = baselineBCoord - parentAscent - - pfd->mBorderPadding.BStart(frameWM) + frameSpan->mBStartLeading; + pfd->mBorderPadding.ConvertTo(lineWM, frameWM).BStart(lineWM) + frameSpan->mBStartLeading; } else { pfd->mBounds.BStart(lineWM) = baselineBCoord - parentAscent + - pfd->mMargin.BStart(frameWM); + pfd->mMargin.ConvertTo(lineWM, frameWM).BStart(lineWM); } pfd->mBlockDirAlign = VALIGN_OTHER; break; @@ -1948,13 +1947,13 @@ nsLineLayout::VerticalAlignFrames(PerSpanData* psd) if (frameSpan) { pfd->mBounds.BStart(lineWM) = baselineBCoord + parentDescent - pfd->mBounds.BSize(lineWM) + - pfd->mBorderPadding.BEnd(frameWM) - + pfd->mBorderPadding.ConvertTo(lineWM, frameWM).BEnd(lineWM) - frameSpan->mBEndLeading; } else { pfd->mBounds.BStart(lineWM) = baselineBCoord + parentDescent - pfd->mBounds.BSize(lineWM) - - pfd->mMargin.BEnd(frameWM); + pfd->mMargin.ConvertTo(lineWM, frameWM).BEnd(lineWM); } pfd->mBlockDirAlign = VALIGN_OTHER; break; @@ -1969,7 +1968,7 @@ nsLineLayout::VerticalAlignFrames(PerSpanData* psd) } else { pfd->mBounds.BStart(lineWM) = baselineBCoord - logicalBSize/2 + - pfd->mMargin.BStart(frameWM); + pfd->mMargin.ConvertTo(lineWM, frameWM).BStart(lineWM); } pfd->mBlockDirAlign = VALIGN_OTHER; break; @@ -2035,7 +2034,7 @@ nsLineLayout::VerticalAlignFrames(PerSpanData* psd) } else { blockStart = pfd->mBounds.BStart(lineWM) - - pfd->mMargin.BStart(frameWM); + pfd->mMargin.ConvertTo(lineWM, frameWM).BStart(lineWM); blockEnd = blockStart + logicalBSize; } if (!preMode && @@ -2146,7 +2145,7 @@ nsLineLayout::VerticalAlignFrames(PerSpanData* psd) spanFramePFD->mAscent, psd->mLogicalBSize, psd->mBStartLeading, psd->mBEndLeading); #endif - nscoord goodMinBCoord = spanFramePFD->mBorderPadding.BStart(frameWM) - + nscoord goodMinBCoord = spanFramePFD->mBorderPadding.ConvertTo(lineWM, frameWM).BStart(lineWM) - psd->mBStartLeading; nscoord goodMaxBCoord = goodMinBCoord + psd->mLogicalBSize; From 6f8bff7661a376063f8f4fc16dbf7ce6b0f05485 Mon Sep 17 00:00:00 2001 From: Jonathan Kew Date: Thu, 13 Nov 2014 08:58:02 +0000 Subject: [PATCH 52/80] Bug 1094914 - part 2 - Store margins and borders using line's writing mode in perFrameData, to avoid writing-mode conversions. r=smontagu --- layout/generic/nsLineLayout.cpp | 87 ++++++++++++++++----------------- layout/generic/nsLineLayout.h | 6 +-- 2 files changed, 44 insertions(+), 49 deletions(-) diff --git a/layout/generic/nsLineLayout.cpp b/layout/generic/nsLineLayout.cpp index ad3552efb7f8..def2786560c4 100644 --- a/layout/generic/nsLineLayout.cpp +++ b/layout/generic/nsLineLayout.cpp @@ -608,8 +608,8 @@ nsLineLayout::NewPerFrameData(nsIFrame* aFrame) WritingMode frameWM = aFrame->GetWritingMode(); WritingMode lineWM = mRootSpan->mWritingMode; pfd->mBounds = LogicalRect(lineWM); - pfd->mMargin = LogicalMargin(frameWM); - pfd->mBorderPadding = LogicalMargin(frameWM); + pfd->mMargin = LogicalMargin(lineWM); + pfd->mBorderPadding = LogicalMargin(lineWM); pfd->mOffsets = LogicalMargin(frameWM); pfd->mJustificationInfo = JustificationInfo(); @@ -809,9 +809,9 @@ nsLineLayout::ReflowFrame(nsIFrame* aFrame, } WritingMode stateWM = reflowState.GetWritingMode(); pfd->mMargin = - reflowState.ComputedLogicalMargin().ConvertTo(frameWM, stateWM); + reflowState.ComputedLogicalMargin().ConvertTo(lineWM, stateWM); pfd->mBorderPadding = - reflowState.ComputedLogicalBorderPadding().ConvertTo(frameWM, stateWM); + reflowState.ComputedLogicalBorderPadding().ConvertTo(lineWM, stateWM); pfd->SetFlag(PFD_RELATIVEPOS, reflowState.mStyleDisplay->IsRelativelyPositionedStyle()); if (pfd->GetFlag(PFD_RELATIVEPOS)) { @@ -1086,7 +1086,7 @@ nsLineLayout::AllowForStartMargin(PerFrameData* pfd, "How'd we get a floated inline frame? " "The frame ctor should've dealt with this."); - WritingMode frameWM = pfd->mFrame->GetWritingMode(); + WritingMode lineWM = mRootSpan->mWritingMode; // Only apply start-margin on the first-in flow for inline frames, // and make sure to not apply it to any inline other than the first @@ -1101,7 +1101,7 @@ nsLineLayout::AllowForStartMargin(PerFrameData* pfd, NS_STYLE_BOX_DECORATION_BREAK_SLICE) { // Zero this out so that when we compute the max-element-width of // the frame we will properly avoid adding in the starting margin. - pfd->mMargin.IStart(frameWM) = 0; + pfd->mMargin.IStart(lineWM) = 0; } else { NS_WARN_IF_FALSE(NS_UNCONSTRAINEDSIZE != aReflowState.AvailableISize(), "have unconstrained inline-size; this should only result " @@ -1112,7 +1112,9 @@ nsLineLayout::AllowForStartMargin(PerFrameData* pfd, // in the reflow state), adjust available inline-size to account for the // start margin. The end margin will be accounted for when we // finish flowing the frame. - aReflowState.AvailableISize() -= pfd->mMargin.IStart(frameWM); + WritingMode wm = aReflowState.GetWritingMode(); + aReflowState.AvailableISize() -= + pfd->mMargin.ConvertTo(wm, lineWM).IStart(wm); } } } @@ -1151,7 +1153,6 @@ nsLineLayout::CanPlaceFrame(PerFrameData* pfd, *aOptionalBreakAfterFits = true; - WritingMode frameWM = pfd->mFrame->GetWritingMode(); WritingMode lineWM = mRootSpan->mWritingMode; /* * We want to only apply the end margin if we're the last continuation and @@ -1176,14 +1177,12 @@ nsLineLayout::CanPlaceFrame(PerFrameData* pfd, !pfd->GetFlag(PFD_ISLETTERFRAME) && pfd->mFrame->StyleBorder()->mBoxDecorationBreak == NS_STYLE_BOX_DECORATION_BREAK_SLICE) { - pfd->mMargin.IEnd(frameWM) = 0; + pfd->mMargin.IEnd(lineWM) = 0; } - // Convert the frame's margins to the line's writing mode and apply - // the start margin to the frame bounds. - LogicalMargin usedMargins = pfd->mMargin.ConvertTo(lineWM, frameWM); - nscoord startMargin = usedMargins.IStart(lineWM); - nscoord endMargin = usedMargins.IEnd(lineWM); + // Apply the start margin to the frame bounds. + nscoord startMargin = pfd->mMargin.IStart(lineWM); + nscoord endMargin = pfd->mMargin.IEnd(lineWM); pfd->mBounds.IStart(lineWM) += startMargin; @@ -1310,7 +1309,6 @@ nsLineLayout::CanPlaceFrame(PerFrameData* pfd, void nsLineLayout::PlaceFrame(PerFrameData* pfd, nsHTMLReflowMetrics& aMetrics) { - WritingMode frameWM = pfd->mFrame->GetWritingMode(); WritingMode lineWM = mRootSpan->mWritingMode; // Record ascent and update max-ascent and max-descent values @@ -1322,7 +1320,7 @@ nsLineLayout::PlaceFrame(PerFrameData* pfd, nsHTMLReflowMetrics& aMetrics) // Advance to next inline coordinate mCurrentSpan->mICoord = pfd->mBounds.IEnd(lineWM) + - pfd->mMargin.ConvertTo(lineWM, frameWM).IEnd(lineWM); + pfd->mMargin.IEnd(lineWM); // Count the number of non-placeholder frames on the line... if (pfd->mFrame->GetType() == nsGkAtoms::placeholderFrame) { @@ -1509,7 +1507,6 @@ nsLineLayout::PlaceTopBottomFrames(PerSpanData* psd, #ifdef DEBUG NS_ASSERTION(0xFF != pfd->mBlockDirAlign, "umr"); #endif - WritingMode frameWM = pfd->mFrame->GetWritingMode(); WritingMode lineWM = mRootSpan->mWritingMode; nscoord containerWidth = ContainerWidthForSpan(psd); switch (pfd->mBlockDirAlign) { @@ -1519,7 +1516,7 @@ nsLineLayout::PlaceTopBottomFrames(PerSpanData* psd, } else { pfd->mBounds.BStart(lineWM) = - -aDistanceFromStart + pfd->mMargin.ConvertTo(lineWM, frameWM).BStart(lineWM); + -aDistanceFromStart + pfd->mMargin.BStart(lineWM); } pfd->mFrame->SetRect(lineWM, pfd->mBounds, containerWidth); #ifdef NOISY_BLOCKDIR_ALIGN @@ -1527,7 +1524,7 @@ nsLineLayout::PlaceTopBottomFrames(PerSpanData* psd, nsFrame::ListTag(stdout, pfd->mFrame); printf(": y=%d dTop=%d [bp.top=%d topLeading=%d]\n", pfd->mBounds.BStart(lineWM), aDistanceFromStart, - span ? pfd->mBorderPadding.ConvertTo(lineWM, frameWM).BStart(lineWM) : 0, + span ? pfd->mBorderPadding.BStart(lineWM) : 0, span ? span->mBStartLeading : 0); #endif break; @@ -1539,7 +1536,7 @@ nsLineLayout::PlaceTopBottomFrames(PerSpanData* psd, } else { pfd->mBounds.BStart(lineWM) = -aDistanceFromStart + aLineBSize - - pfd->mMargin.ConvertTo(lineWM, frameWM).BEnd(lineWM) - pfd->mBounds.BSize(lineWM); + pfd->mMargin.BEnd(lineWM) - pfd->mBounds.BSize(lineWM); } pfd->mFrame->SetRect(lineWM, pfd->mBounds, containerWidth); #ifdef NOISY_BLOCKDIR_ALIGN @@ -1598,7 +1595,6 @@ nsLineLayout::VerticalAlignFrames(PerSpanData* psd) // - it has a prev-in-flow // - it has no next in flow // - it's zero sized - WritingMode frameWM = spanFramePFD->mFrame->GetWritingMode(); WritingMode lineWM = mRootSpan->mWritingMode; bool emptyContinuation = psd != mRootSpan && spanFrame->GetPrevInFlow() && !spanFrame->GetNextInFlow() && @@ -1616,14 +1612,14 @@ nsLineLayout::VerticalAlignFrames(PerSpanData* psd) if (psd != mRootSpan) { WritingMode frameWM = spanFramePFD->mFrame->GetWritingMode(); printf(" bp=%d,%d,%d,%d margin=%d,%d,%d,%d", - spanFramePFD->mBorderPadding.Top(frameWM), - spanFramePFD->mBorderPadding.Right(frameWM), - spanFramePFD->mBorderPadding.Bottom(frameWM), - spanFramePFD->mBorderPadding.Left(frameWM), - spanFramePFD->mMargin.Top(frameWM), - spanFramePFD->mMargin.Right(frameWM), - spanFramePFD->mMargin.Bottom(frameWM), - spanFramePFD->mMargin.Left(frameWM)); + spanFramePFD->mBorderPadding.Top(lineWM), + spanFramePFD->mBorderPadding.Right(lineWM), + spanFramePFD->mBorderPadding.Bottom(lineWM), + spanFramePFD->mBorderPadding.Left(lineWM), + spanFramePFD->mMargin.Top(lineWM), + spanFramePFD->mMargin.Right(lineWM), + spanFramePFD->mMargin.Bottom(lineWM), + spanFramePFD->mMargin.Left(lineWM)); } printf("\n"); #endif @@ -1725,7 +1721,7 @@ nsLineLayout::VerticalAlignFrames(PerSpanData* psd) mBlockReflowState->ComputedHeight(), inflation); nscoord contentBSize = spanFramePFD->mBounds.BSize(lineWM) - - spanFramePFD->mBorderPadding.ConvertTo(lineWM, frameWM).BStartEnd(lineWM); + spanFramePFD->mBorderPadding.BStartEnd(lineWM); // Special-case for a ::first-letter frame, set the line height to // the frame block size if the user has left line-height == normal @@ -1758,7 +1754,7 @@ nsLineLayout::VerticalAlignFrames(PerSpanData* psd) // If there are child frames in this span that stick out of this area // then the minBCoord and maxBCoord are updated by the amount of logical // blockSize that is outside this range. - minBCoord = spanFramePFD->mBorderPadding.ConvertTo(lineWM, frameWM).BStart(lineWM) - + minBCoord = spanFramePFD->mBorderPadding.BStart(lineWM) - psd->mBStartLeading; maxBCoord = minBCoord + psd->mLogicalBSize; } @@ -1775,8 +1771,8 @@ nsLineLayout::VerticalAlignFrames(PerSpanData* psd) printf(": baseLine=%d logicalBSize=%d topLeading=%d h=%d bp=%d,%d zeroEffectiveSpanBox=%s\n", baselineBCoord, psd->mLogicalBSize, psd->mBStartLeading, spanFramePFD->mBounds.BSize(lineWM), - spanFramePFD->mBorderPadding.Top(frameWM), - spanFramePFD->mBorderPadding.Bottom(frameWM), + spanFramePFD->mBorderPadding.Top(lineWM), + spanFramePFD->mBorderPadding.Bottom(lineWM), zeroEffectiveSpanBox ? "yes" : "no"); #endif } @@ -1786,7 +1782,6 @@ nsLineLayout::VerticalAlignFrames(PerSpanData* psd) PerFrameData* pfd = psd->mFirstFrame; while (nullptr != pfd) { nsIFrame* frame = pfd->mFrame; - WritingMode frameWM = frame->GetWritingMode(); // sanity check (see bug 105168, non-reproducible crashes from null frame) NS_ASSERTION(frame, "null frame in PerFrameData - something is very very bad"); @@ -1806,7 +1801,7 @@ nsLineLayout::VerticalAlignFrames(PerSpanData* psd) // For other elements the logical block size is the same as the // frame's block size plus its margins. logicalBSize = pfd->mBounds.BSize(lineWM) + - pfd->mMargin.ConvertTo(lineWM, frameWM).BStartEnd(lineWM); + pfd->mMargin.BStartEnd(lineWM); if (logicalBSize < 0 && mPresContext->CompatibilityMode() == eCompatibility_NavQuirks) { pfd->mAscent -= logicalBSize; @@ -1914,7 +1909,7 @@ nsLineLayout::VerticalAlignFrames(PerSpanData* psd) else { pfd->mBounds.BStart(lineWM) = baselineBCoord - (parentXHeight + logicalBSize)/2 + - pfd->mMargin.ConvertTo(lineWM, frameWM).BStart(lineWM); + pfd->mMargin.BStart(lineWM); } pfd->mBlockDirAlign = VALIGN_OTHER; break; @@ -1929,11 +1924,11 @@ nsLineLayout::VerticalAlignFrames(PerSpanData* psd) nscoord parentAscent = fm->MaxAscent(); if (frameSpan) { pfd->mBounds.BStart(lineWM) = baselineBCoord - parentAscent - - pfd->mBorderPadding.ConvertTo(lineWM, frameWM).BStart(lineWM) + frameSpan->mBStartLeading; + pfd->mBorderPadding.BStart(lineWM) + frameSpan->mBStartLeading; } else { pfd->mBounds.BStart(lineWM) = baselineBCoord - parentAscent + - pfd->mMargin.ConvertTo(lineWM, frameWM).BStart(lineWM); + pfd->mMargin.BStart(lineWM); } pfd->mBlockDirAlign = VALIGN_OTHER; break; @@ -1947,13 +1942,13 @@ nsLineLayout::VerticalAlignFrames(PerSpanData* psd) if (frameSpan) { pfd->mBounds.BStart(lineWM) = baselineBCoord + parentDescent - pfd->mBounds.BSize(lineWM) + - pfd->mBorderPadding.ConvertTo(lineWM, frameWM).BEnd(lineWM) - + pfd->mBorderPadding.BEnd(lineWM) - frameSpan->mBEndLeading; } else { pfd->mBounds.BStart(lineWM) = baselineBCoord + parentDescent - pfd->mBounds.BSize(lineWM) - - pfd->mMargin.ConvertTo(lineWM, frameWM).BEnd(lineWM); + pfd->mMargin.BEnd(lineWM); } pfd->mBlockDirAlign = VALIGN_OTHER; break; @@ -1968,7 +1963,7 @@ nsLineLayout::VerticalAlignFrames(PerSpanData* psd) } else { pfd->mBounds.BStart(lineWM) = baselineBCoord - logicalBSize/2 + - pfd->mMargin.ConvertTo(lineWM, frameWM).BStart(lineWM); + pfd->mMargin.BStart(lineWM); } pfd->mBlockDirAlign = VALIGN_OTHER; break; @@ -2034,7 +2029,7 @@ nsLineLayout::VerticalAlignFrames(PerSpanData* psd) } else { blockStart = pfd->mBounds.BStart(lineWM) - - pfd->mMargin.ConvertTo(lineWM, frameWM).BStart(lineWM); + pfd->mMargin.BStart(lineWM); blockEnd = blockStart + logicalBSize; } if (!preMode && @@ -2053,8 +2048,8 @@ nsLineLayout::VerticalAlignFrames(PerSpanData* psd) #ifdef NOISY_BLOCKDIR_ALIGN printf(" [frame]raw: a=%d h=%d bp=%d,%d logical: h=%d leading=%d y=%d minBCoord=%d maxBCoord=%d\n", pfd->mAscent, pfd->mBounds.BSize(lineWM), - pfd->mBorderPadding.Top(frameWM), - pfd->mBorderPadding.Bottom(frameWM), + pfd->mBorderPadding.Top(lineWM), + pfd->mBorderPadding.Bottom(lineWM), logicalBSize, frameSpan ? frameSpan->mBStartLeading : 0, pfd->mBounds.BStart(lineWM), minBCoord, maxBCoord); @@ -2145,8 +2140,8 @@ nsLineLayout::VerticalAlignFrames(PerSpanData* psd) spanFramePFD->mAscent, psd->mLogicalBSize, psd->mBStartLeading, psd->mBEndLeading); #endif - nscoord goodMinBCoord = spanFramePFD->mBorderPadding.ConvertTo(lineWM, frameWM).BStart(lineWM) - - psd->mBStartLeading; + nscoord goodMinBCoord = + spanFramePFD->mBorderPadding.BStart(lineWM) - psd->mBStartLeading; nscoord goodMaxBCoord = goodMinBCoord + psd->mLogicalBSize; // For cases like the one in bug 714519 (text-decoration placement diff --git a/layout/generic/nsLineLayout.h b/layout/generic/nsLineLayout.h index 4672921576f1..e02931becc7b 100644 --- a/layout/generic/nsLineLayout.h +++ b/layout/generic/nsLineLayout.h @@ -385,9 +385,9 @@ protected: nsOverflowAreas mOverflowAreas; // From reflow-state - mozilla::LogicalMargin mMargin; - mozilla::LogicalMargin mBorderPadding; - mozilla::LogicalMargin mOffsets; + mozilla::LogicalMargin mMargin; // in *line* writing mode + mozilla::LogicalMargin mBorderPadding; // in *line* writing mode + mozilla::LogicalMargin mOffsets; // in *frame* writing mode // state for text justification mozilla::JustificationInfo mJustificationInfo; From 5922ab8a63caa9706c7688243360e3cd9a916f2e Mon Sep 17 00:00:00 2001 From: Jonathan Kew Date: Thu, 13 Nov 2014 08:58:02 +0000 Subject: [PATCH 53/80] Bug 1094914 - Reftest for margins and writing-mode of an inline block. r=smontagu --- .../reftests/writing-mode/1094914-1-ref.html | 43 +++++++++++++++++++ layout/reftests/writing-mode/1094914-1a.html | 43 +++++++++++++++++++ layout/reftests/writing-mode/1094914-1b.html | 43 +++++++++++++++++++ layout/reftests/writing-mode/reftest.list | 2 + 4 files changed, 131 insertions(+) create mode 100644 layout/reftests/writing-mode/1094914-1-ref.html create mode 100644 layout/reftests/writing-mode/1094914-1a.html create mode 100644 layout/reftests/writing-mode/1094914-1b.html diff --git a/layout/reftests/writing-mode/1094914-1-ref.html b/layout/reftests/writing-mode/1094914-1-ref.html new file mode 100644 index 000000000000..28e1efe43f0a --- /dev/null +++ b/layout/reftests/writing-mode/1094914-1-ref.html @@ -0,0 +1,43 @@ + + + + + + + + + +
+
+
+
+ + + diff --git a/layout/reftests/writing-mode/1094914-1a.html b/layout/reftests/writing-mode/1094914-1a.html new file mode 100644 index 000000000000..2234aa1a4a82 --- /dev/null +++ b/layout/reftests/writing-mode/1094914-1a.html @@ -0,0 +1,43 @@ + + + + + + + + + +
+
+
+
+ + + diff --git a/layout/reftests/writing-mode/1094914-1b.html b/layout/reftests/writing-mode/1094914-1b.html new file mode 100644 index 000000000000..e815348adaae --- /dev/null +++ b/layout/reftests/writing-mode/1094914-1b.html @@ -0,0 +1,43 @@ + + + + + + + + + +
+
+
+
+ + + diff --git a/layout/reftests/writing-mode/reftest.list b/layout/reftests/writing-mode/reftest.list index d4504e27d201..973e0b0d0483 100644 --- a/layout/reftests/writing-mode/reftest.list +++ b/layout/reftests/writing-mode/reftest.list @@ -6,3 +6,5 @@ == 1083892-1.html 1083892-1-ref.html == 1086883-1a.html 1086883-1-ref.html == 1086883-1b.html 1086883-1-ref.html +== 1094914-1a.html 1094914-1-ref.html +== 1094914-1b.html 1094914-1-ref.html From 150a68da5c7d5f253cf1452b86a7e6dd8a1dd1af Mon Sep 17 00:00:00 2001 From: Jonathan Kew Date: Thu, 13 Nov 2014 08:58:02 +0000 Subject: [PATCH 54/80] Bug 1089388 - Convert nsBlockFrame::SlideLine to use logical coordinates. r=smontagu --- layout/generic/nsBlockFrame.cpp | 24 ++++++++++++++---------- layout/generic/nsBlockFrame.h | 4 ++-- 2 files changed, 16 insertions(+), 12 deletions(-) diff --git a/layout/generic/nsBlockFrame.cpp b/layout/generic/nsBlockFrame.cpp index 8539001f309e..87c6baaa9077 100644 --- a/layout/generic/nsBlockFrame.cpp +++ b/layout/generic/nsBlockFrame.cpp @@ -2731,12 +2731,12 @@ nsBlockFrame::PullFrameFrom(nsLineBox* aLine, void nsBlockFrame::SlideLine(nsBlockReflowState& aState, - nsLineBox* aLine, nscoord aDY) + nsLineBox* aLine, nscoord aDeltaBCoord) { - NS_PRECONDITION(aDY != 0, "why slide a line nowhere?"); + NS_PRECONDITION(aDeltaBCoord != 0, "why slide a line nowhere?"); // Adjust line state - aLine->SlideBy(aDY, aState.mContainerWidth); + aLine->SlideBy(aDeltaBCoord, aState.mContainerWidth); // Adjust the frames in the line nsIFrame* kid = aLine->mFirstChild; @@ -2744,23 +2744,27 @@ nsBlockFrame::SlideLine(nsBlockReflowState& aState, return; } + WritingMode wm = GetWritingMode(); + nsPoint physicalDelta = + LogicalPoint(wm, 0, aDeltaBCoord).GetPhysicalPoint(wm, 0); + if (aLine->IsBlock()) { - if (aDY) { - kid->MovePositionBy(nsPoint(0, aDY)); + if (aDeltaBCoord) { + kid->MovePositionBy(physicalDelta); } // Make sure the frame's view and any child views are updated nsContainerFrame::PlaceFrameView(kid); } else { - // Adjust the Y coordinate of the frames in the line. - // Note: we need to re-position views even if aDY is 0, because + // Adjust the block-dir coordinate of the frames in the line. + // Note: we need to re-position views even if aDeltaBCoord is 0, because // one of our parent frames may have moved and so the view's position - // relative to its parent may have changed + // relative to its parent may have changed. int32_t n = aLine->GetChildCount(); while (--n >= 0) { - if (aDY) { - kid->MovePositionBy(nsPoint(0, aDY)); + if (aDeltaBCoord) { + kid->MovePositionBy(physicalDelta); } // Make sure the frame's view and any child views are updated nsContainerFrame::PlaceFrameView(kid); diff --git a/layout/generic/nsBlockFrame.h b/layout/generic/nsBlockFrame.h index 72b13783d9f0..f3c5b2d012bb 100644 --- a/layout/generic/nsBlockFrame.h +++ b/layout/generic/nsBlockFrame.h @@ -408,11 +408,11 @@ protected: mState |= aFlags; } - /** move the frames contained by aLine by aDY + /** move the frames contained by aLine by aDeltaBCoord * if aLine is a block, its child floats are added to the state manager */ void SlideLine(nsBlockReflowState& aState, - nsLineBox* aLine, nscoord aDY); + nsLineBox* aLine, nscoord aDeltaBCoord); void ComputeFinalSize(const nsHTMLReflowState& aReflowState, nsBlockReflowState& aState, From c8bcdce921128a9d271b29ce25df1b0f36a1fc2f Mon Sep 17 00:00:00 2001 From: Jonathan Kew Date: Thu, 13 Nov 2014 08:58:03 +0000 Subject: [PATCH 55/80] Bug 1089388 - Followup to add a LogicalPoint version of nsIFrame::MovePositionBy, and use this in SlideLine. r=smontagu --- layout/generic/nsBlockFrame.cpp | 7 +++---- layout/generic/nsIFrame.h | 9 +++++++++ 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/layout/generic/nsBlockFrame.cpp b/layout/generic/nsBlockFrame.cpp index 87c6baaa9077..cf5fbb7c8456 100644 --- a/layout/generic/nsBlockFrame.cpp +++ b/layout/generic/nsBlockFrame.cpp @@ -2745,12 +2745,11 @@ nsBlockFrame::SlideLine(nsBlockReflowState& aState, } WritingMode wm = GetWritingMode(); - nsPoint physicalDelta = - LogicalPoint(wm, 0, aDeltaBCoord).GetPhysicalPoint(wm, 0); + LogicalPoint translation(wm, 0, aDeltaBCoord); if (aLine->IsBlock()) { if (aDeltaBCoord) { - kid->MovePositionBy(physicalDelta); + kid->MovePositionBy(wm, translation); } // Make sure the frame's view and any child views are updated @@ -2764,7 +2763,7 @@ nsBlockFrame::SlideLine(nsBlockReflowState& aState, int32_t n = aLine->GetChildCount(); while (--n >= 0) { if (aDeltaBCoord) { - kid->MovePositionBy(physicalDelta); + kid->MovePositionBy(wm, translation); } // Make sure the frame's view and any child views are updated nsContainerFrame::PlaceFrameView(kid); diff --git a/layout/generic/nsIFrame.h b/layout/generic/nsIFrame.h index f76fc07f141d..c4f8c1f889fd 100644 --- a/layout/generic/nsIFrame.h +++ b/layout/generic/nsIFrame.h @@ -744,6 +744,15 @@ public: */ void MovePositionBy(const nsPoint& aTranslation); + /** + * As above, using a logical-point delta in a given writing mode. + */ + void MovePositionBy(mozilla::WritingMode aWritingMode, + const mozilla::LogicalPoint& aTranslation) + { + MovePositionBy(aTranslation.GetPhysicalPoint(aWritingMode, 0)); + } + /** * Return frame's position without relative positioning */ From c2e1350336913c2d0450472b4660362ebfb8b74e Mon Sep 17 00:00:00 2001 From: Jonathan Kew Date: Thu, 13 Nov 2014 08:58:03 +0000 Subject: [PATCH 56/80] Bug 1089388 - Reftests for nsBlockFrame::SlideLine in vertical writing modes. r=smontagu --- .../reftests/writing-mode/1089388-1-ref.html | 30 ++++++++++++++ layout/reftests/writing-mode/1089388-1.html | 39 +++++++++++++++++++ .../reftests/writing-mode/1089388-2-ref.html | 30 ++++++++++++++ layout/reftests/writing-mode/1089388-2.html | 39 +++++++++++++++++++ layout/reftests/writing-mode/reftest.list | 2 + 5 files changed, 140 insertions(+) create mode 100644 layout/reftests/writing-mode/1089388-1-ref.html create mode 100644 layout/reftests/writing-mode/1089388-1.html create mode 100644 layout/reftests/writing-mode/1089388-2-ref.html create mode 100644 layout/reftests/writing-mode/1089388-2.html diff --git a/layout/reftests/writing-mode/1089388-1-ref.html b/layout/reftests/writing-mode/1089388-1-ref.html new file mode 100644 index 000000000000..ead9d0edaab7 --- /dev/null +++ b/layout/reftests/writing-mode/1089388-1-ref.html @@ -0,0 +1,30 @@ + + + + + + + + + +
+First part of the block. +New text inserted by script, to cause a reflow that slides the following lines. +We will insert enough new content that it wraps onto additional lines. +

+Here is some more text that follows a forced break. +Observe what happens to it when text is added earlier. +
+ + + diff --git a/layout/reftests/writing-mode/1089388-1.html b/layout/reftests/writing-mode/1089388-1.html new file mode 100644 index 000000000000..e5277bae5c6f --- /dev/null +++ b/layout/reftests/writing-mode/1089388-1.html @@ -0,0 +1,39 @@ + + + + + + + + + + + + +
+First part of the block. + +We will insert enough new content that it wraps onto additional lines. +

+Here is some more text that follows a forced break. +Observe what happens to it when text is added earlier. +
+ + + diff --git a/layout/reftests/writing-mode/1089388-2-ref.html b/layout/reftests/writing-mode/1089388-2-ref.html new file mode 100644 index 000000000000..b5b24768101e --- /dev/null +++ b/layout/reftests/writing-mode/1089388-2-ref.html @@ -0,0 +1,30 @@ + + + + + + + + + +
+First part of the block. +New text inserted by script, to cause a reflow that slides the following lines. +We will insert enough new content that it wraps onto additional lines. +

+Here is some more text that follows a forced break. +Observe what happens to it when text is added earlier. +
+ + + diff --git a/layout/reftests/writing-mode/1089388-2.html b/layout/reftests/writing-mode/1089388-2.html new file mode 100644 index 000000000000..69e3ae9fc743 --- /dev/null +++ b/layout/reftests/writing-mode/1089388-2.html @@ -0,0 +1,39 @@ + + + + + + + + + + + + +
+First part of the block. + +We will insert enough new content that it wraps onto additional lines. +

+Here is some more text that follows a forced break. +Observe what happens to it when text is added earlier. +
+ + + diff --git a/layout/reftests/writing-mode/reftest.list b/layout/reftests/writing-mode/reftest.list index 973e0b0d0483..1ba1345307b7 100644 --- a/layout/reftests/writing-mode/reftest.list +++ b/layout/reftests/writing-mode/reftest.list @@ -6,5 +6,7 @@ == 1083892-1.html 1083892-1-ref.html == 1086883-1a.html 1086883-1-ref.html == 1086883-1b.html 1086883-1-ref.html +== 1089388-1.html 1089388-1-ref.html +== 1089388-2.html 1089388-2-ref.html == 1094914-1a.html 1094914-1-ref.html == 1094914-1b.html 1094914-1-ref.html From c02ad81b73e99c9936d69a2b348d1069989fa2f9 Mon Sep 17 00:00:00 2001 From: Jonathan Kew Date: Thu, 13 Nov 2014 08:58:03 +0000 Subject: [PATCH 57/80] Bug 1089581 - Convert nsLineBox::SlideBy to use logical coordinates. r=smontagu --- layout/generic/nsLineBox.h | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/layout/generic/nsLineBox.h b/layout/generic/nsLineBox.h index 9a24549da00f..7618d7738cfc 100644 --- a/layout/generic/nsLineBox.h +++ b/layout/generic/nsLineBox.h @@ -473,8 +473,10 @@ public: mContainerWidth = aContainerWidth; mBounds.BStart(mWritingMode) += aDBCoord; if (mData) { + nsPoint physicalDelta = mozilla::LogicalPoint(mWritingMode, 0, aDBCoord). + GetPhysicalPoint(mWritingMode, 0); NS_FOR_FRAME_OVERFLOW_TYPES(otype) { - mData->mOverflowAreas.Overflow(otype).y += aDBCoord; + mData->mOverflowAreas.Overflow(otype) += physicalDelta; } } } From 1bdefeee1eeee0197057b85bb12615406391876c Mon Sep 17 00:00:00 2001 From: Jonathan Kew Date: Thu, 13 Nov 2014 08:58:03 +0000 Subject: [PATCH 58/80] Bug 1088025 - part 1 - Ensure nsBlockReflowState has a constrained mContainerWidth before we reflow lines into the container. r=dbaron --- layout/generic/nsBlockReflowState.cpp | 15 +++++++++++++-- layout/generic/nsBlockReflowState.h | 2 ++ layout/generic/nsLineBox.h | 4 ++++ layout/generic/nsLineLayout.h | 1 + 4 files changed, 20 insertions(+), 2 deletions(-) diff --git a/layout/generic/nsBlockReflowState.cpp b/layout/generic/nsBlockReflowState.cpp index 4e1658be70cf..33221a98ac0c 100644 --- a/layout/generic/nsBlockReflowState.cpp +++ b/layout/generic/nsBlockReflowState.cpp @@ -54,8 +54,19 @@ nsBlockReflowState::nsBlockReflowState(const nsHTMLReflowState& aReflowState, aFrame->GetLogicalSkipSides(&aReflowState); mBorderPadding.ApplySkipSides(logicalSkipSides); - // Note that mContainerWidth is the physical width! - mContainerWidth = aReflowState.ComputedWidth() + mBorderPadding.LeftRight(wm); + // Note that mContainerWidth is the physical width, needed to convert + // logical block-coordinates in vertical-rl writing mode (measured from a + // RHS origin) to physical coordinates within the containing block. + // If aReflowState doesn't have a constrained ComputedWidth(), we set it to + // zero, which means lines will be positioned (physically) incorrectly; + // we will fix them up at the end of nsBlockFrame::Reflow, after we know + // the total block-size of the frame. + mContainerWidth = aReflowState.ComputedWidth(); + if (mContainerWidth == NS_UNCONSTRAINEDSIZE) { + mContainerWidth = 0; + } + + mContainerWidth += mBorderPadding.LeftRight(wm); if ((aBStartMarginRoot && !logicalSkipSides.BStart()) || 0 != mBorderPadding.BStart(wm)) { diff --git a/layout/generic/nsBlockReflowState.h b/layout/generic/nsBlockReflowState.h index b0b7026ec043..9bb060db1b78 100644 --- a/layout/generic/nsBlockReflowState.h +++ b/layout/generic/nsBlockReflowState.h @@ -203,6 +203,8 @@ public: mozilla::WritingMode wm = mReflowState.GetWritingMode(); return mContentArea.Size(wm).ConvertTo(aWM, wm); } + + // Physical width. Use only for physical <-> logical coordinate conversion. nscoord mContainerWidth; // Continuation out-of-flow float frames that need to move to our diff --git a/layout/generic/nsLineBox.h b/layout/generic/nsLineBox.h index 7618d7738cfc..2f650adb8c38 100644 --- a/layout/generic/nsLineBox.h +++ b/layout/generic/nsLineBox.h @@ -587,9 +587,13 @@ public: nsIFrame* mFirstChild; mozilla::WritingMode mWritingMode; + + // Physical width. Use only for physical <-> logical coordinate conversion. nscoord mContainerWidth; + private: mozilla::LogicalRect mBounds; + public: const mozilla::LogicalRect& GetBounds() { return mBounds; } nsRect GetPhysicalBounds() const diff --git a/layout/generic/nsLineLayout.h b/layout/generic/nsLineLayout.h index e02931becc7b..2828a302ec08 100644 --- a/layout/generic/nsLineLayout.h +++ b/layout/generic/nsLineLayout.h @@ -537,6 +537,7 @@ protected: // frame, if any nscoord mTrimmableISize; + // Physical width. Use only for physical <-> logical coordinate conversion. nscoord mContainerWidth; bool mFirstLetterStyleOK : 1; From 5de4d98d5c5b5c46803f7dda2337127958f61467 Mon Sep 17 00:00:00 2001 From: Jonathan Kew Date: Thu, 13 Nov 2014 08:58:03 +0000 Subject: [PATCH 59/80] Bug 1088025 - part 2 - Fix up block-dir position of lines in a vertical-rl block once we know the final block size (container width) needed to map to physical coordinates. r=dbaron --- layout/generic/nsBlockFrame.cpp | 36 +++++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) diff --git a/layout/generic/nsBlockFrame.cpp b/layout/generic/nsBlockFrame.cpp index cf5fbb7c8456..f092f1e59545 100644 --- a/layout/generic/nsBlockFrame.cpp +++ b/layout/generic/nsBlockFrame.cpp @@ -1231,6 +1231,42 @@ nsBlockFrame::Reflow(nsPresContext* aPresContext, // Compute our final size nscoord blockEndEdgeOfChildren; ComputeFinalSize(*reflowState, state, aMetrics, &blockEndEdgeOfChildren); + + // If the block direction is right-to-left, we need to update the bounds of + // lines that were placed relative to mContainerWidth during reflow, as + // we typically do not know the true container width (block-dir size of the + // finished paragraph/block) until we've reflowed all its children. So we + // use a "fake" mContainerWidth during reflow (see nsBlockReflowState's + // constructor) and then fix up the positions of the lines here, once the + // final block size is known. + // + // Note that writing-mode:vertical-rl is the only case where the block + // logical direction progresses in a negative physical direction, and + // therefore block-dir coordinate conversion depends on knowing the width + // of the coordinate space in order to translate between the logical and + // physical origins. + if (wm.GetBlockDir() == WritingMode::BlockDir::eBlockRL) { + nscoord deltaX = aMetrics.Width() - state.mContainerWidth; + if (deltaX) { + for (line_iterator line = begin_lines(), end = end_lines(); + line != end; line++) { + SlideLine(state, line, -deltaX); + } + for (nsIFrame* f = mFloats.FirstChild(); f; f = f->GetNextSibling()) { + nsPoint physicalDelta(deltaX, 0); + f->MovePositionBy(physicalDelta); + } + nsFrameList* bulletList = GetOutsideBulletList(); + if (bulletList) { + nsPoint physicalDelta(deltaX, 0); + for (nsIFrame* f = bulletList->FirstChild(); f; + f = f->GetNextSibling()) { + f->MovePositionBy(physicalDelta); + } + } + } + } + nsRect areaBounds = nsRect(0, 0, aMetrics.Width(), aMetrics.Height()); ComputeOverflowAreas(areaBounds, reflowState->mStyleDisplay, blockEndEdgeOfChildren, aMetrics.mOverflowAreas); From ae4c472fad7f7f3837b717c078faf7a4dd9775dc Mon Sep 17 00:00:00 2001 From: Jonathan Kew Date: Thu, 13 Nov 2014 08:58:04 +0000 Subject: [PATCH 60/80] Bug 1088025 - Reftest for positioning of lines within paragraphs in a vertical-rl block. r=dbaron --- .../reftests/writing-mode/1088025-1-ref.html | 24 +++++++++++++++++ layout/reftests/writing-mode/1088025-1.html | 27 +++++++++++++++++++ layout/reftests/writing-mode/reftest.list | 1 + 3 files changed, 52 insertions(+) create mode 100644 layout/reftests/writing-mode/1088025-1-ref.html create mode 100644 layout/reftests/writing-mode/1088025-1.html diff --git a/layout/reftests/writing-mode/1088025-1-ref.html b/layout/reftests/writing-mode/1088025-1-ref.html new file mode 100644 index 000000000000..0ed0f34b1da6 --- /dev/null +++ b/layout/reftests/writing-mode/1088025-1-ref.html @@ -0,0 +1,24 @@ + + + +Bug 1083892 + + + + +
+ This is the first paragraph. It's long enough to wrap onto multiple lines.
+ Paragraph two.
+ Third and final paragraph of this simple testcase. That's all, folks! +
+ + + diff --git a/layout/reftests/writing-mode/1088025-1.html b/layout/reftests/writing-mode/1088025-1.html new file mode 100644 index 000000000000..810095844939 --- /dev/null +++ b/layout/reftests/writing-mode/1088025-1.html @@ -0,0 +1,27 @@ + + + +Bug 1083892 + + + + +
+

This is the first paragraph. It's long enough to wrap onto multiple lines. +

Paragraph two. +

Third and final paragraph of this simple testcase. That's all, folks! +

+ + + diff --git a/layout/reftests/writing-mode/reftest.list b/layout/reftests/writing-mode/reftest.list index 1ba1345307b7..8223e7bdcda1 100644 --- a/layout/reftests/writing-mode/reftest.list +++ b/layout/reftests/writing-mode/reftest.list @@ -6,6 +6,7 @@ == 1083892-1.html 1083892-1-ref.html == 1086883-1a.html 1086883-1-ref.html == 1086883-1b.html 1086883-1-ref.html +== 1088025-1.html 1088025-1-ref.html == 1089388-1.html 1089388-1-ref.html == 1089388-2.html 1089388-2-ref.html == 1094914-1a.html 1094914-1-ref.html From f97a6b6a7db0ba2d74515ea3fe96d95315b60949 Mon Sep 17 00:00:00 2001 From: Jonathan Kew Date: Thu, 13 Nov 2014 08:58:04 +0000 Subject: [PATCH 61/80] Bug 1093165 - Include the text-orientation value in WritingMode, and add the IsSideways flag for baseline decisions. r=smontagu --- layout/base/nsLayoutUtils.cpp | 4 +-- layout/generic/WritingModes.h | 54 +++++++++++++++++++++++++++++++---- layout/generic/nsIFrame.h | 2 +- layout/style/nsRuleNode.cpp | 2 +- 4 files changed, 52 insertions(+), 10 deletions(-) diff --git a/layout/base/nsLayoutUtils.cpp b/layout/base/nsLayoutUtils.cpp index dc63311b0d8e..bb6f8e21af41 100644 --- a/layout/base/nsLayoutUtils.cpp +++ b/layout/base/nsLayoutUtils.cpp @@ -3493,7 +3493,7 @@ nsLayoutUtils::GetFontMetricsForStyleContext(nsStyleContext* aStyleContext, if (aInflation != 1.0f) { font.size = NSToCoordRound(font.size * aInflation); } - WritingMode wm(aStyleContext->StyleVisibility()); + WritingMode wm(aStyleContext); return pc->DeviceContext()->GetMetricsFor( font, aStyleContext->StyleFont()->mLanguage, wm.IsVertical() ? gfxFont::eVertical : gfxFont::eHorizontal, @@ -5871,7 +5871,7 @@ nsLayoutUtils::GetTextRunFlagsForStyle(nsStyleContext* aStyleContext, default: break; } - WritingMode wm(aStyleContext->StyleVisibility()); + WritingMode wm(aStyleContext); if (wm.IsVertical()) { switch (aStyleText->mTextOrientation) { case NS_STYLE_TEXT_ORIENTATION_MIXED: diff --git a/layout/generic/WritingModes.h b/layout/generic/WritingModes.h index 19078c023fb7..e95660f83ce4 100644 --- a/layout/generic/WritingModes.h +++ b/layout/generic/WritingModes.h @@ -7,7 +7,7 @@ #define WritingModes_h_ #include "nsRect.h" -#include "nsStyleStruct.h" +#include "nsStyleContext.h" // If WRITING_MODE_VERTICAL_ENABLED is defined, we will attempt to support // the vertical writing-mode values; if it is not defined, then @@ -208,6 +208,20 @@ public: return IsLineInverted() ? -1 : 1; } + /** + * True if the text-orientation will force all text to be rendered sideways + * in vertical lines, in which case we should prefer an alphabetic baseline; + * otherwise, the default is centered. + * Note that some glyph runs may be rendered sideways even if this is false, + * due to text-orientation:mixed resolution, but in that case the dominant + * baseline remains centered. + */ +#ifdef WRITING_MODE_VERTICAL_ENABLED + bool IsSideways() const { return !!(mWritingMode & eSidewaysMask); } +#else + bool IsSideways() const { return false; } +#endif + /** * Default constructor gives us a horizontal, LTR writing mode. * XXX We will probably eliminate this and require explicit initialization @@ -220,25 +234,49 @@ public: /** * Construct writing mode based on a style context */ - explicit WritingMode(const nsStyleVisibility* aStyleVisibility) + explicit WritingMode(nsStyleContext* aStyleContext) { - NS_ASSERTION(aStyleVisibility, "we need an nsStyleVisibility here"); + NS_ASSERTION(aStyleContext, "we need an nsStyleContext here"); + + const nsStyleVisibility* styleVisibility = aStyleContext->StyleVisibility(); #ifdef WRITING_MODE_VERTICAL_ENABLED - switch (aStyleVisibility->mWritingMode) { + switch (styleVisibility->mWritingMode) { case NS_STYLE_WRITING_MODE_HORIZONTAL_TB: mWritingMode = 0; break; case NS_STYLE_WRITING_MODE_VERTICAL_LR: + { mWritingMode = eBlockFlowMask | - eLineOrientMask | //XXX needs update when text-orientation added + eLineOrientMask | eOrientationMask; + uint8_t textOrientation = aStyleContext->StyleText()->mTextOrientation; +#if 0 // not yet implemented + if (textOrientation == NS_STYLE_TEXT_ORIENTATION_SIDEWAYS_LEFT) { + mWritingMode &= ~eLineOrientMask; + } +#endif + if (textOrientation >= NS_STYLE_TEXT_ORIENTATION_SIDEWAYS_RIGHT) { + mWritingMode |= eSidewaysMask; + } break; + } case NS_STYLE_WRITING_MODE_VERTICAL_RL: + { mWritingMode = eOrientationMask; + uint8_t textOrientation = aStyleContext->StyleText()->mTextOrientation; +#if 0 // not yet implemented + if (textOrientation == NS_STYLE_TEXT_ORIENTATION_SIDEWAYS_LEFT) { + mWritingMode |= eLineOrientMask; + } +#endif + if (textOrientation >= NS_STYLE_TEXT_ORIENTATION_SIDEWAYS_RIGHT) { + mWritingMode |= eSidewaysMask; + } break; + } default: NS_NOTREACHED("unknown writing mode!"); @@ -249,7 +287,7 @@ public: mWritingMode = 0; #endif - if (NS_STYLE_DIRECTION_RTL == aStyleVisibility->mDirection) { + if (NS_STYLE_DIRECTION_RTL == styleVisibility->mDirection) { mWritingMode |= eInlineFlowMask | //XXX needs update when text-orientation added eBidiMask; } @@ -325,6 +363,10 @@ private: // Note: We have one excess bit of info; WritingMode can pack into 4 bits. // But since we have space, we're caching interesting things for fast access. + eSidewaysMask = 0x20, // true means text-orientation is sideways-*, + // which means we'll use alphabetic instead of + // centered default baseline for vertical text + // Masks for output enums eInlineMask = 0x03, eBlockMask = 0x05 diff --git a/layout/generic/nsIFrame.h b/layout/generic/nsIFrame.h index c4f8c1f889fd..df4311922cd8 100644 --- a/layout/generic/nsIFrame.h +++ b/layout/generic/nsIFrame.h @@ -608,7 +608,7 @@ public: * The frame's writing-mode, used for logical layout computations. */ mozilla::WritingMode GetWritingMode() const { - return mozilla::WritingMode(StyleVisibility()); + return mozilla::WritingMode(StyleContext()); } /** diff --git a/layout/style/nsRuleNode.cpp b/layout/style/nsRuleNode.cpp index ba8e39da4695..1f6b93c2f54a 100644 --- a/layout/style/nsRuleNode.cpp +++ b/layout/style/nsRuleNode.cpp @@ -288,7 +288,7 @@ GetMetricsFor(nsPresContext* aPresContext, gfxTextPerfMetrics *tp = aPresContext->GetTextPerfMetrics(); gfxFont::Orientation orientation = gfxFont::eHorizontal; if (aStyleContext) { - WritingMode wm(aStyleContext->StyleVisibility()); + WritingMode wm(aStyleContext); if (wm.IsVertical()) { orientation = gfxFont::eVertical; } From 02d6b51ec664c5220ea2203cfc17882dd0b0571b Mon Sep 17 00:00:00 2001 From: Jonathan Kew Date: Thu, 13 Nov 2014 08:58:04 +0000 Subject: [PATCH 62/80] Bug 1090168 - part 1 - Make textBaseline attribute in work for vertical text. r=jdaggett --- dom/canvas/CanvasRenderingContext2D.cpp | 52 ++++++++++++++++--------- gfx/thebes/gfxFont.h | 6 +++ 2 files changed, 39 insertions(+), 19 deletions(-) diff --git a/dom/canvas/CanvasRenderingContext2D.cpp b/dom/canvas/CanvasRenderingContext2D.cpp index 29f7722c4ab4..4941dc72f06f 100644 --- a/dom/canvas/CanvasRenderingContext2D.cpp +++ b/dom/canvas/CanvasRenderingContext2D.cpp @@ -3149,6 +3149,7 @@ struct MOZ_STACK_CLASS CanvasBidiProcessor : public nsBidiPresUtils::BidiProcess gfxPoint point = mPt; bool rtl = mTextRun->IsRightToLeft(); bool verticalRun = mTextRun->IsVertical(); + bool centerBaseline = mTextRun->UseCenterBaseline(); gfxFloat& inlineCoord = verticalRun ? point.y : point.x; inlineCoord += xOffset; @@ -3217,20 +3218,27 @@ struct MOZ_STACK_CLASS CanvasBidiProcessor : public nsBidiPresUtils::BidiProcess if (runs[c].mOrientation == gfxTextRunFactory::TEXT_ORIENT_VERTICAL_SIDEWAYS_RIGHT) { sidewaysRestore.Init(mCtx->mTarget); - // TODO: The baseline adjustment here is kinda ad-hoc; eventually - // perhaps we should check for horizontal and vertical baseline data - // in the font, and adjust accordingly. - // (The same will be true for HTML text layout.) const gfxFont::Metrics& metrics = mTextRun->GetFontGroup()-> GetFirstValidFont()->GetMetrics(gfxFont::eHorizontal); - mCtx->mTarget->SetTransform(mCtx->mTarget->GetTransform().Copy(). + + gfx::Matrix mat = mCtx->mTarget->GetTransform().Copy(). PreTranslate(baselineOrigin). // translate origin for rotation PreRotate(gfx::Float(M_PI / 2.0)). // turn 90deg clockwise - PreTranslate(-baselineOrigin). // undo the translation - PreTranslate(Point(0, (metrics.emAscent - metrics.emDescent) / 2))); - // and offset the (alphabetic) baseline of the + PreTranslate(-baselineOrigin); // undo the translation + + if (centerBaseline) { + // TODO: The baseline adjustment here is kinda ad hoc; eventually + // perhaps we should check for horizontal and vertical baseline data + // in the font, and adjust accordingly. + // (The same will be true for HTML text layout.) + float offset = (metrics.emAscent - metrics.emDescent) / 2; + mat = mat.PreTranslate(Point(0, offset)); + // offset the (alphabetic) baseline of the // horizontally-shaped text from the (centered) // default baseline used for vertical + } + + mCtx->mTarget->SetTransform(mat); } RefPtr renderingOptions = font->GetGlyphRenderingOptions(); @@ -3522,39 +3530,45 @@ CanvasRenderingContext2D::DrawOrMeasureText(const nsAString& aRawText, processor.mPt.x -= anchorX * totalWidth; - // offset pt.y based on text baseline + // offset pt.y (or pt.x, for vertical text) based on text baseline processor.mFontgrp->UpdateUserFonts(); // ensure user font generation is current const gfxFont::Metrics& fontMetrics = - processor.mFontgrp->GetFirstValidFont()->GetMetrics( - ((processor.mTextRunFlags & gfxTextRunFactory::TEXT_ORIENT_MASK) == - gfxTextRunFactory::TEXT_ORIENT_HORIZONTAL) - ? gfxFont::eHorizontal : gfxFont::eVertical); + processor.mFontgrp->GetFirstValidFont()->GetMetrics(gfxFont::eHorizontal); - gfxFloat anchorY; + gfxFloat baselineAnchor; switch (state.textBaseline) { case TextBaseline::HANGING: // fall through; best we can do with the information available case TextBaseline::TOP: - anchorY = fontMetrics.emAscent; + baselineAnchor = fontMetrics.emAscent; break; case TextBaseline::MIDDLE: - anchorY = (fontMetrics.emAscent - fontMetrics.emDescent) * .5f; + baselineAnchor = (fontMetrics.emAscent - fontMetrics.emDescent) * .5f; break; case TextBaseline::IDEOGRAPHIC: // fall through; best we can do with the information available case TextBaseline::ALPHABETIC: - anchorY = 0; + baselineAnchor = 0; break; case TextBaseline::BOTTOM: - anchorY = -fontMetrics.emDescent; + baselineAnchor = -fontMetrics.emDescent; break; default: MOZ_CRASH("unexpected TextBaseline"); } - processor.mPt.y += anchorY; + if (processor.mTextRun->IsVertical()) { + if (processor.mTextRun->UseCenterBaseline()) { + // Adjust to account for mTextRun being shaped using center baseline + // rather than alphabetic. + baselineAnchor -= (fontMetrics.emAscent - fontMetrics.emDescent) * .5f; + } + processor.mPt.x -= baselineAnchor; + } else { + processor.mPt.y += baselineAnchor; + } // correct bounding box to get it to be the correct size/position processor.mBoundingBox.width = totalWidth; diff --git a/gfx/thebes/gfxFont.h b/gfx/thebes/gfxFont.h index 909dbc8ec0d8..f176a4a985e0 100644 --- a/gfx/thebes/gfxFont.h +++ b/gfx/thebes/gfxFont.h @@ -945,6 +945,12 @@ public: gfxTextRunFactory::TEXT_ORIENT_HORIZONTAL; } + bool UseCenterBaseline() const { + uint32_t orient = GetFlags() & gfxTextRunFactory::TEXT_ORIENT_MASK; + return orient == gfxTextRunFactory::TEXT_ORIENT_VERTICAL_MIXED || + orient == gfxTextRunFactory::TEXT_ORIENT_VERTICAL_UPRIGHT; + } + bool IsRightToLeft() const { return (GetFlags() & gfxTextRunFactory::TEXT_IS_RTL) != 0; } From 92a78b6d7665eea3fb6ec13d7e35d415e48d4dd8 Mon Sep 17 00:00:00 2001 From: Jonathan Kew Date: Thu, 13 Nov 2014 08:58:04 +0000 Subject: [PATCH 63/80] Bug 1090168 - part 2 - Adjust initial value of textBaseline depending on writing-mode and text-orientation properties. r=jdaggett --- dom/canvas/CanvasRenderingContext2D.cpp | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/dom/canvas/CanvasRenderingContext2D.cpp b/dom/canvas/CanvasRenderingContext2D.cpp index 4941dc72f06f..58e47164b7b8 100644 --- a/dom/canvas/CanvasRenderingContext2D.cpp +++ b/dom/canvas/CanvasRenderingContext2D.cpp @@ -1357,6 +1357,25 @@ CanvasRenderingContext2D::ClearTarget() state->colorStyles[Style::FILL] = NS_RGB(0,0,0); state->colorStyles[Style::STROKE] = NS_RGB(0,0,0); state->shadowColor = NS_RGBA(0,0,0,0); + + // For vertical writing-mode, unless text-orientation is sideways, + // we'll modify the initial value of textBaseline to 'middle'. + nsRefPtr canvasStyle; + if (mCanvasElement && mCanvasElement->IsInDoc()) { + nsCOMPtr presShell = GetPresShell(); + if (presShell) { + canvasStyle = + nsComputedDOMStyle::GetStyleContextForElement(mCanvasElement, + nullptr, + presShell); + if (canvasStyle) { + WritingMode wm(canvasStyle); + if (wm.IsVertical() && !wm.IsSideways()) { + state->textBaseline = TextBaseline::MIDDLE; + } + } + } + } } NS_IMETHODIMP From 0a0ca18b1f0e351ea33f5dcef36207ca3775f0ec Mon Sep 17 00:00:00 2001 From: Jonathan Kew Date: Thu, 13 Nov 2014 08:58:05 +0000 Subject: [PATCH 64/80] Bug 1090168 - Reftests for textBaseline support in vertical writing-mode text. r=jdaggett --- .../writing-mode/1090168-1-notref.html | 41 ++++++++++++++++ .../reftests/writing-mode/1090168-1-ref.html | 41 ++++++++++++++++ layout/reftests/writing-mode/1090168-1.html | 41 ++++++++++++++++ .../reftests/writing-mode/1090168-2-ref.html | 41 ++++++++++++++++ layout/reftests/writing-mode/1090168-2.html | 41 ++++++++++++++++ .../reftests/writing-mode/1090168-3-ref.html | 47 +++++++++++++++++++ layout/reftests/writing-mode/1090168-3.html | 47 +++++++++++++++++++ layout/reftests/writing-mode/reftest.list | 4 ++ 8 files changed, 303 insertions(+) create mode 100644 layout/reftests/writing-mode/1090168-1-notref.html create mode 100644 layout/reftests/writing-mode/1090168-1-ref.html create mode 100644 layout/reftests/writing-mode/1090168-1.html create mode 100644 layout/reftests/writing-mode/1090168-2-ref.html create mode 100644 layout/reftests/writing-mode/1090168-2.html create mode 100644 layout/reftests/writing-mode/1090168-3-ref.html create mode 100644 layout/reftests/writing-mode/1090168-3.html diff --git a/layout/reftests/writing-mode/1090168-1-notref.html b/layout/reftests/writing-mode/1090168-1-notref.html new file mode 100644 index 000000000000..9480faf73d91 --- /dev/null +++ b/layout/reftests/writing-mode/1090168-1-notref.html @@ -0,0 +1,41 @@ + + + + + + + diff --git a/layout/reftests/writing-mode/1090168-1-ref.html b/layout/reftests/writing-mode/1090168-1-ref.html new file mode 100644 index 000000000000..8f9520cc1b7c --- /dev/null +++ b/layout/reftests/writing-mode/1090168-1-ref.html @@ -0,0 +1,41 @@ + + + + + + + diff --git a/layout/reftests/writing-mode/1090168-1.html b/layout/reftests/writing-mode/1090168-1.html new file mode 100644 index 000000000000..443678678c39 --- /dev/null +++ b/layout/reftests/writing-mode/1090168-1.html @@ -0,0 +1,41 @@ + + + + + + + diff --git a/layout/reftests/writing-mode/1090168-2-ref.html b/layout/reftests/writing-mode/1090168-2-ref.html new file mode 100644 index 000000000000..f12a5156cd8b --- /dev/null +++ b/layout/reftests/writing-mode/1090168-2-ref.html @@ -0,0 +1,41 @@ + + + + + + + diff --git a/layout/reftests/writing-mode/1090168-2.html b/layout/reftests/writing-mode/1090168-2.html new file mode 100644 index 000000000000..631b7a9092db --- /dev/null +++ b/layout/reftests/writing-mode/1090168-2.html @@ -0,0 +1,41 @@ + + + + + + + diff --git a/layout/reftests/writing-mode/1090168-3-ref.html b/layout/reftests/writing-mode/1090168-3-ref.html new file mode 100644 index 000000000000..212c675899c9 --- /dev/null +++ b/layout/reftests/writing-mode/1090168-3-ref.html @@ -0,0 +1,47 @@ + + + + + + + diff --git a/layout/reftests/writing-mode/1090168-3.html b/layout/reftests/writing-mode/1090168-3.html new file mode 100644 index 000000000000..f22a22acd32e --- /dev/null +++ b/layout/reftests/writing-mode/1090168-3.html @@ -0,0 +1,47 @@ + + + + + + + diff --git a/layout/reftests/writing-mode/reftest.list b/layout/reftests/writing-mode/reftest.list index 8223e7bdcda1..6b46dda12704 100644 --- a/layout/reftests/writing-mode/reftest.list +++ b/layout/reftests/writing-mode/reftest.list @@ -9,5 +9,9 @@ == 1088025-1.html 1088025-1-ref.html == 1089388-1.html 1089388-1-ref.html == 1089388-2.html 1089388-2-ref.html +== 1090168-1.html 1090168-1-ref.html +!= 1090168-1.html 1090168-1-notref.html +== 1090168-2.html 1090168-2-ref.html +== 1090168-3.html 1090168-3-ref.html == 1094914-1a.html 1094914-1-ref.html == 1094914-1b.html 1094914-1-ref.html From e1255310b130a9d4a3b5f02f9dcc1f933e2765cf Mon Sep 17 00:00:00 2001 From: Jonathan Kew Date: Thu, 13 Nov 2014 08:58:05 +0000 Subject: [PATCH 65/80] Bug 1091058 - Fix positioning of text-decoration lines in vertical writing mode. r=smontagu --- layout/generic/nsTextFrame.cpp | 44 ++++++++++++++++++++++++---------- 1 file changed, 31 insertions(+), 13 deletions(-) diff --git a/layout/generic/nsTextFrame.cpp b/layout/generic/nsTextFrame.cpp index aac55f276729..275840563fd6 100644 --- a/layout/generic/nsTextFrame.cpp +++ b/layout/generic/nsTextFrame.cpp @@ -4768,15 +4768,16 @@ nsTextFrame::GetTextDecorations( bool useOverride = false; nscolor overrideColor = NS_RGBA(0, 0, 0, 0); - // frameTopOffset represents the offset to f's top from our baseline in our + // frameBStartOffset represents the offset to f's BStart from our baseline in our // coordinate space // baselineOffset represents the offset from our baseline to f's baseline or // the nearest block's baseline, in our coordinate space, whichever is closest // during the particular iteration - nscoord frameTopOffset = mAscent, + nscoord frameBStartOffset = mAscent, baselineOffset = 0; bool nearestBlockFound = false; + bool vertical = GetWritingMode().IsVertical(); for (nsIFrame* f = this, *fChild = nullptr; f; @@ -4819,18 +4820,20 @@ nsTextFrame::GetTextDecorations( const nscoord lineBaselineOffset = LazyGetLineBaselineOffset(fChild, fBlock); - baselineOffset = - frameTopOffset - fChild->GetNormalPosition().y - lineBaselineOffset; + baselineOffset = frameBStartOffset - lineBaselineOffset - + (vertical ? fChild->GetNormalPosition().x + : fChild->GetNormalPosition().y); } } else if (!nearestBlockFound) { // use a dummy WritingMode, because nsTextFrame::GetLogicalBaseLine // doesn't use it anyway - baselineOffset = frameTopOffset - f->GetLogicalBaseline(WritingMode()); + baselineOffset = frameBStartOffset - f->GetLogicalBaseline(WritingMode()); } nearestBlockFound = nearestBlockFound || firstBlock; - frameTopOffset += f->GetNormalPosition().y; + frameBStartOffset += + vertical ? f->GetNormalPosition().x : f->GetNormalPosition().y; const uint8_t style = styleText->GetDecorationStyle(); if (textDecorations) { @@ -6157,13 +6160,28 @@ nsTextFrame::DrawTextRunAndDecorations( // XXX aFramePt is in AppUnits, shouldn't it be nsFloatPoint? nscoord x = NSToCoordRound(aFramePt.x); - nscoord width = vertical ? GetRect().height : GetRect().width; - aClipEdges.Intersect(&x, &width); + nscoord y = NSToCoordRound(aFramePt.y); - gfxPoint decPt(x / app, 0); + // 'width' here is textrun-relative, so for a vertical run it's + // really the height of the decoration + nscoord width = vertical ? GetRect().height : GetRect().width; + + // XXX todo: probably should have a vertical version of this... + if (!vertical) { + aClipEdges.Intersect(&x, &width); + } + + // decPt is the physical point where the decoration is to be drawn, + // relative to the frame; one of its coordinates will be updated below. + gfxPoint decPt(x / app, y / app); + gfxFloat& bCoord = vertical ? decPt.x : decPt.y; + + // ...whereas decSize is a textrun-relative size gfxSize decSize(width / app, 0); const gfxFloat ascent = gfxFloat(mAscent) / app; - const gfxFloat frameTop = aFramePt.y; + + // The starting edge of the frame in block direction + const gfxFloat frameBStart = vertical ? aFramePt.x : aFramePt.y; gfxRect dirtyRect(aDirtyRect.x / app, aDirtyRect.y / app, aDirtyRect.Width() / app, aDirtyRect.Height() / app); @@ -6185,7 +6203,7 @@ nsTextFrame::DrawTextRunAndDecorations( vertical); decSize.height = metrics.underlineSize; - decPt.y = (frameTop - dec.mBaselineOffset) / app; + bCoord = (frameBStart - dec.mBaselineOffset) / app; PaintDecorationLine(this, aCtx, dirtyRect, dec.mColor, aDecorationOverrideColor, decPt, 0.0, decSize, ascent, @@ -6206,7 +6224,7 @@ nsTextFrame::DrawTextRunAndDecorations( vertical); decSize.height = metrics.underlineSize; - decPt.y = (frameTop - dec.mBaselineOffset) / app; + bCoord = (frameBStart - dec.mBaselineOffset) / app; PaintDecorationLine(this, aCtx, dirtyRect, dec.mColor, aDecorationOverrideColor, decPt, 0.0, decSize, ascent, @@ -6233,7 +6251,7 @@ nsTextFrame::DrawTextRunAndDecorations( vertical); decSize.height = metrics.strikeoutSize; - decPt.y = (frameTop - dec.mBaselineOffset) / app; + bCoord = (frameBStart - dec.mBaselineOffset) / app; PaintDecorationLine(this, aCtx, dirtyRect, dec.mColor, aDecorationOverrideColor, decPt, 0.0, decSize, ascent, From 1dc8cfa43b6d46014d563c9b29742b75d563f366 Mon Sep 17 00:00:00 2001 From: Jonathan Kew Date: Thu, 13 Nov 2014 08:58:05 +0000 Subject: [PATCH 66/80] Bug 1091058 - Reftest for underlining of vertical writing-mode spans. r=smontagu --- .../reftests/writing-mode/1091058-1-ref.html | 35 +++++++++++++++++++ layout/reftests/writing-mode/1091058-1.html | 35 +++++++++++++++++++ layout/reftests/writing-mode/reftest.list | 1 + 3 files changed, 71 insertions(+) create mode 100644 layout/reftests/writing-mode/1091058-1-ref.html create mode 100644 layout/reftests/writing-mode/1091058-1.html diff --git a/layout/reftests/writing-mode/1091058-1-ref.html b/layout/reftests/writing-mode/1091058-1-ref.html new file mode 100644 index 000000000000..770dd6868d43 --- /dev/null +++ b/layout/reftests/writing-mode/1091058-1-ref.html @@ -0,0 +1,35 @@ + + + + + + + + + +
+方ABC方方abc方方方xyz +
+ +
+方ABC方方abc方方方xyz +
+ +
+方ABC方方abc方方方xyz +
+ + + diff --git a/layout/reftests/writing-mode/1091058-1.html b/layout/reftests/writing-mode/1091058-1.html new file mode 100644 index 000000000000..14f3725f3c10 --- /dev/null +++ b/layout/reftests/writing-mode/1091058-1.html @@ -0,0 +1,35 @@ + + + + + + + + + +
+方ABC方方abc方方方xyz +
+ +
+方ABC方方abc方方方xyz +
+ +
+方ABC方方abc方方方xyz +
+ + + diff --git a/layout/reftests/writing-mode/reftest.list b/layout/reftests/writing-mode/reftest.list index 6b46dda12704..641648fb5e63 100644 --- a/layout/reftests/writing-mode/reftest.list +++ b/layout/reftests/writing-mode/reftest.list @@ -13,5 +13,6 @@ != 1090168-1.html 1090168-1-notref.html == 1090168-2.html 1090168-2-ref.html == 1090168-3.html 1090168-3-ref.html +== 1091058-1.html 1091058-1-ref.html == 1094914-1a.html 1094914-1-ref.html == 1094914-1b.html 1094914-1-ref.html From 257b729bc8af9530320dc0e4e0fe2f08fa81fa91 Mon Sep 17 00:00:00 2001 From: Jonathan Kew Date: Thu, 13 Nov 2014 08:58:05 +0000 Subject: [PATCH 67/80] Bug 1090159 - Correct baseline alignment in vertical-rl writing mode. r=smontagu --- layout/generic/nsTextFrame.cpp | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/layout/generic/nsTextFrame.cpp b/layout/generic/nsTextFrame.cpp index 275840563fd6..18f2542dd951 100644 --- a/layout/generic/nsTextFrame.cpp +++ b/layout/generic/nsTextFrame.cpp @@ -6018,8 +6018,11 @@ nsTextFrame::PaintText(nsRenderingContext* aRenderingContext, nsPoint aPt, gfxPoint framePt(aPt.x, aPt.y); gfxPoint textBaselinePt; if (vertical) { - textBaselinePt = gfxPoint(aPt.x + mAscent, - rtl ? gfxFloat(aPt.y + GetSize().height) : aPt.y); + WritingMode wm = GetWritingMode(); + textBaselinePt = + gfxPoint(wm.IsVerticalLR() ? aPt.x + mAscent + : aPt.x + frameWidth - mAscent, + rtl ? aPt.y + GetSize().height : aPt.y); } else { textBaselinePt = gfxPoint(rtl ? gfxFloat(aPt.x + frameWidth) : framePt.x, nsLayoutUtils::GetSnappedBaselineY(this, ctx, aPt.y, mAscent)); From e27a2da74cb95dc3dac69ea11b877880cd7a9e07 Mon Sep 17 00:00:00 2001 From: Jonathan Kew Date: Thu, 13 Nov 2014 08:58:05 +0000 Subject: [PATCH 68/80] Bug 1090159 - Reftest for erratic baseline in vertical-rl mode. r=smontagu --- .../reftests/writing-mode/1090159-1-ref.html | 37 +++++++++++++++++++ layout/reftests/writing-mode/1090159-1.html | 37 +++++++++++++++++++ layout/reftests/writing-mode/reftest.list | 1 + 3 files changed, 75 insertions(+) create mode 100644 layout/reftests/writing-mode/1090159-1-ref.html create mode 100644 layout/reftests/writing-mode/1090159-1.html diff --git a/layout/reftests/writing-mode/1090159-1-ref.html b/layout/reftests/writing-mode/1090159-1-ref.html new file mode 100644 index 000000000000..4678efe9ec82 --- /dev/null +++ b/layout/reftests/writing-mode/1090159-1-ref.html @@ -0,0 +1,37 @@ + + + + + + + + + +
+你好吗? hello +
+ +
+你好吗? hello +
+ +
+你好吗? hello +
+ + + diff --git a/layout/reftests/writing-mode/1090159-1.html b/layout/reftests/writing-mode/1090159-1.html new file mode 100644 index 000000000000..eabded9b1177 --- /dev/null +++ b/layout/reftests/writing-mode/1090159-1.html @@ -0,0 +1,37 @@ + + + + + + + + + +
+你好吗? hello +
+ +
+你好吗? hello +
+ +
+你好吗? hello +
+ + + diff --git a/layout/reftests/writing-mode/reftest.list b/layout/reftests/writing-mode/reftest.list index 641648fb5e63..325ed39fab4b 100644 --- a/layout/reftests/writing-mode/reftest.list +++ b/layout/reftests/writing-mode/reftest.list @@ -9,6 +9,7 @@ == 1088025-1.html 1088025-1-ref.html == 1089388-1.html 1089388-1-ref.html == 1089388-2.html 1089388-2-ref.html +== 1090159-1.html 1090159-1-ref.html == 1090168-1.html 1090168-1-ref.html != 1090168-1.html 1090168-1-notref.html == 1090168-2.html 1090168-2-ref.html From 34fea182cdc091780ec7802bfcce7203d00c1e1b Mon Sep 17 00:00:00 2001 From: Jonathan Kew Date: Thu, 13 Nov 2014 08:58:06 +0000 Subject: [PATCH 69/80] Bug 1093553 - Improve handling of line-height metrics, block ascent, etc., in vertical writing mode. r=smontagu --- gfx/thebes/gfxFont.cpp | 62 +++++--- layout/base/nsCSSRendering.cpp | 26 ++-- layout/base/nsLayoutUtils.cpp | 12 +- layout/base/nsLayoutUtils.h | 6 +- layout/forms/nsTextControlFrame.cpp | 3 +- layout/generic/WritingModes.h | 9 +- layout/generic/nsBRFrame.cpp | 3 +- layout/generic/nsBlockFrame.cpp | 7 +- layout/generic/nsFrame.cpp | 7 +- layout/generic/nsLineLayout.cpp | 3 +- layout/generic/nsTextFrame.cpp | 214 ++++++++++++++++++---------- 11 files changed, 240 insertions(+), 112 deletions(-) diff --git a/gfx/thebes/gfxFont.cpp b/gfx/thebes/gfxFont.cpp index 490bee2574ea..188e87af55c6 100644 --- a/gfx/thebes/gfxFont.cpp +++ b/gfx/thebes/gfxFont.cpp @@ -1902,22 +1902,28 @@ gfxFont::Draw(gfxTextRun *aTextRun, uint32_t aStart, uint32_t aEnd, gfxPoint p(aPt->x * aRunParams.devPerApp, aPt->y * aRunParams.devPerApp); const Metrics& metrics = GetMetrics(eHorizontal); - // Adjust the matrix to draw the (horizontally-shaped) textrun with - // 90-degree CW rotation, and adjust position so that the rotated - // horizontal text (which uses a standard alphabetic baseline) will + // Get a matrix we can use to draw the (horizontally-shaped) textrun + // with 90-degree CW rotation. + gfxMatrix mat = aRunParams.context->CurrentMatrix(). + Translate(p). // translate origin for rotation + Rotate(M_PI / 2.0). // turn 90deg clockwise + Translate(-p); // undo the translation + + // If we're drawing rotated horizontal text for an element styled + // text-orientation:mixed, the dominant baseline will be vertical- + // centered. So in this case, we need to adjust the position so that + // the rotated horizontal text (which uses an alphabetic baseline) will // look OK when juxtaposed with upright glyphs (rendered on a centered // vertical baseline). The adjustment here is somewhat ad hoc; we // should eventually look for baseline tables[1] in the fonts and use // those if available. - // [1] http://www.microsoft.com/typography/otspec/base.htm - aRunParams.context->SetMatrix(aRunParams.context->CurrentMatrix(). - Translate(p). // translate origin for rotation - Rotate(M_PI / 2.0). // turn 90deg clockwise - Translate(-p). // undo the translation - Translate(gfxPoint(0, (metrics.emAscent - metrics.emDescent) / 2))); - // and offset the (alphabetic) baseline of the - // horizontally-shaped text from the (centered) - // default baseline used for vertical + // [1] See http://www.microsoft.com/typography/otspec/base.htm + if (aTextRun->UseCenterBaseline()) { + gfxPoint baseAdj(0, (metrics.emAscent - metrics.emDescent) / 2); + mat.Translate(baseAdj); + } + + aRunParams.context->SetMatrix(mat); } nsAutoPtr contextPaint; @@ -2138,15 +2144,33 @@ gfxFont::Measure(gfxTextRun *aTextRun, // Current position in appunits gfxFont::Orientation orientation = aOrientation == gfxTextRunFactory::TEXT_ORIENT_VERTICAL_UPRIGHT - ? gfxFont::eVertical : gfxFont::eHorizontal; + ? eVertical : eHorizontal; const gfxFont::Metrics& fontMetrics = GetMetrics(orientation); + gfxFloat baselineOffset = 0; + if (aTextRun->UseCenterBaseline() && orientation == eHorizontal) { + // For a horizontal font being used in vertical writing mode with + // text-orientation:mixed, the overall metrics we're accumulating + // will be aimed at a center baseline. But this font's metrics were + // based on the alphabetic baseline. So we compute a baseline offset + // that will be applied to ascent/descent values and glyph rects + // to effectively shift them relative to the baseline. + // XXX Eventually we should probably use the BASE table, if present. + // But it usually isn't, so we need an ad hoc adjustment for now. + baselineOffset = appUnitsPerDevUnit * + (fontMetrics.emAscent - fontMetrics.emDescent) / 2; + } + RunMetrics metrics; - metrics.mAscent = fontMetrics.maxAscent*appUnitsPerDevUnit; - metrics.mDescent = fontMetrics.maxDescent*appUnitsPerDevUnit; + metrics.mAscent = fontMetrics.maxAscent * appUnitsPerDevUnit; + metrics.mDescent = fontMetrics.maxDescent * appUnitsPerDevUnit; + if (aStart == aEnd) { // exit now before we look at aSpacing[0], which is undefined - metrics.mBoundingBox = gfxRect(0, -metrics.mAscent, 0, metrics.mAscent + metrics.mDescent); + metrics.mAscent -= baselineOffset; + metrics.mDescent += baselineOffset; + metrics.mBoundingBox = gfxRect(0, -metrics.mAscent, + 0, metrics.mAscent + metrics.mDescent); return metrics; } @@ -2247,6 +2271,12 @@ gfxFont::Measure(gfxTextRun *aTextRun, metrics.mBoundingBox -= gfxPoint(x, 0); } + if (baselineOffset != 0) { + metrics.mAscent -= baselineOffset; + metrics.mDescent += baselineOffset; + metrics.mBoundingBox.y += baselineOffset; + } + metrics.mAdvanceWidth = x*direction; return metrics; } diff --git a/layout/base/nsCSSRendering.cpp b/layout/base/nsCSSRendering.cpp index ca328f61e6a7..f3342e36b760 100644 --- a/layout/base/nsCSSRendering.cpp +++ b/layout/base/nsCSSRendering.cpp @@ -4162,8 +4162,12 @@ nsCSSRendering::PaintDecorationLine(nsIFrame* aFrame, return; } - // The y position should be set to the middle of the line. - rect.y += lineThickness / 2; + // The block-direction position should be set to the middle of the line. + if (aVertical) { + rect.x -= lineThickness / 2; + } else { + rect.y += lineThickness / 2; + } switch (aStyle) { case NS_STYLE_TEXT_DECORATION_STYLE_SOLID: @@ -4360,12 +4364,18 @@ nsCSSRendering::DecorationLineToPath(nsIFrame* aFrame, gfxFloat lineThickness = std::max(NS_round(aLineSize.height), 1.0); - // The y position should be set to the middle of the line. - rect.y += lineThickness / 2; - - aGfxContext->Rectangle - (gfxRect(gfxPoint(rect.TopLeft() - gfxPoint(0.0, lineThickness / 2)), - gfxSize(rect.Width(), lineThickness))); + // The block-direction position should be set to the middle of the line. + if (aVertical) { + rect.x -= lineThickness / 2; + aGfxContext->Rectangle + (gfxRect(gfxPoint(rect.TopLeft() - gfxPoint(lineThickness / 2, 0.0)), + gfxSize(lineThickness, rect.Height()))); + } else { + rect.y += lineThickness / 2; + aGfxContext->Rectangle + (gfxRect(gfxPoint(rect.TopLeft() - gfxPoint(0.0, lineThickness / 2)), + gfxSize(rect.Width(), lineThickness))); + } } nsRect diff --git a/layout/base/nsLayoutUtils.cpp b/layout/base/nsLayoutUtils.cpp index bb6f8e21af41..445b152edab1 100644 --- a/layout/base/nsLayoutUtils.cpp +++ b/layout/base/nsLayoutUtils.cpp @@ -3496,7 +3496,8 @@ nsLayoutUtils::GetFontMetricsForStyleContext(nsStyleContext* aStyleContext, WritingMode wm(aStyleContext); return pc->DeviceContext()->GetMetricsFor( font, aStyleContext->StyleFont()->mLanguage, - wm.IsVertical() ? gfxFont::eVertical : gfxFont::eHorizontal, + wm.IsVertical() && !wm.IsSideways() + ? gfxFont::eVertical : gfxFont::eHorizontal, fs, tp, *aFontMetrics); } @@ -4893,9 +4894,11 @@ nsLayoutUtils::PaintTextShadow(const nsIFrame* aFrame, /* static */ nscoord nsLayoutUtils::GetCenteredFontBaseline(nsFontMetrics* aFontMetrics, - nscoord aLineHeight) + nscoord aLineHeight, + bool aIsInverted) { - nscoord fontAscent = aFontMetrics->MaxAscent(); + nscoord fontAscent = aIsInverted ? aFontMetrics->MaxDescent() + : aFontMetrics->MaxAscent(); nscoord fontHeight = aFontMetrics->MaxHeight(); nscoord leading = aLineHeight - fontHeight; @@ -7350,7 +7353,8 @@ nsLayoutUtils::SetBSizeFromFontMetrics(const nsIFrame* aFrame, // The height of our box is the sum of our font size plus the top // and bottom border and padding. The height of children do not // affect our height. - aMetrics.SetBlockStartAscent(fm->MaxAscent()); + aMetrics.SetBlockStartAscent(aLineWM.IsLineInverted() ? fm->MaxDescent() + : fm->MaxAscent()); aMetrics.BSize(aLineWM) = fm->MaxHeight(); } else { NS_WARNING("Cannot get font metrics - defaulting sizes to 0"); diff --git a/layout/base/nsLayoutUtils.h b/layout/base/nsLayoutUtils.h index b75f2d98f6df..a692e0b4cb98 100644 --- a/layout/base/nsLayoutUtils.h +++ b/layout/base/nsLayoutUtils.h @@ -1397,11 +1397,15 @@ public: /** * Gets the baseline to vertically center text from a font within a * line of specified height. + * aIsInverted: true if the text is inverted relative to the block + * direction, so that the block-dir "ascent" corresponds to font + * descent. (Applies to sideways text in vertical-lr mode.) * * Returns the baseline position relative to the top of the line. */ static nscoord GetCenteredFontBaseline(nsFontMetrics* aFontMetrics, - nscoord aLineHeight); + nscoord aLineHeight, + bool aIsInverted); /** * Derive a baseline of |aFrame| (measured from its top border edge) diff --git a/layout/forms/nsTextControlFrame.cpp b/layout/forms/nsTextControlFrame.cpp index ea69931a390a..9c5daf7850d0 100644 --- a/layout/forms/nsTextControlFrame.cpp +++ b/layout/forms/nsTextControlFrame.cpp @@ -519,7 +519,8 @@ nsTextControlFrame::Reflow(nsPresContext* aPresContext, inflation); // now adjust for our borders and padding aDesiredSize.SetBlockStartAscent( - nsLayoutUtils::GetCenteredFontBaseline(fontMet, lineHeight) + + nsLayoutUtils::GetCenteredFontBaseline(fontMet, lineHeight, + wm.IsLineInverted()) + aReflowState.ComputedLogicalBorderPadding().BStart(wm)); // overflow handling diff --git a/layout/generic/WritingModes.h b/layout/generic/WritingModes.h index e95660f83ce4..1b112aedd94e 100644 --- a/layout/generic/WritingModes.h +++ b/layout/generic/WritingModes.h @@ -168,12 +168,17 @@ public: /** * Return true if LTR. (Convenience method) */ - bool IsBidiLTR() const { return eBidiLTR == (mWritingMode & eBidiMask); } + bool IsBidiLTR() const { return eBidiLTR == GetBidiDir(); } /** * True if vertical-mode block direction is LR (convenience method). */ - bool IsVerticalLR() const { return eBlockLR == (mWritingMode & eBlockMask); } + bool IsVerticalLR() const { return eBlockLR == GetBlockDir(); } + + /** + * True if vertical-mode block direction is RL (convenience method). + */ + bool IsVerticalRL() const { return eBlockRL == GetBlockDir(); } /** * True if vertical writing mode, i.e. when diff --git a/layout/generic/nsBRFrame.cpp b/layout/generic/nsBRFrame.cpp index 0077ee9f52ab..5f6fbd47312a 100644 --- a/layout/generic/nsBRFrame.cpp +++ b/layout/generic/nsBRFrame.cpp @@ -122,7 +122,8 @@ BRFrame::Reflow(nsPresContext* aPresContext, if (fm) { nscoord logicalHeight = aReflowState.CalcLineHeight(); finalSize.BSize(wm) = logicalHeight; - aMetrics.SetBlockStartAscent(nsLayoutUtils::GetCenteredFontBaseline(fm, logicalHeight)); + aMetrics.SetBlockStartAscent(nsLayoutUtils::GetCenteredFontBaseline( + fm, logicalHeight, wm.IsLineInverted())); } else { aMetrics.SetBlockStartAscent(aMetrics.BSize(wm) = 0); diff --git a/layout/generic/nsBlockFrame.cpp b/layout/generic/nsBlockFrame.cpp index f092f1e59545..f62ff951e7e9 100644 --- a/layout/generic/nsBlockFrame.cpp +++ b/layout/generic/nsBlockFrame.cpp @@ -515,7 +515,9 @@ nsBlockFrame::GetCaretBaseline() const nscoord lineHeight = nsHTMLReflowState::CalcLineHeight(GetContent(), StyleContext(), contentRect.height, inflation); - return nsLayoutUtils::GetCenteredFontBaseline(fm, lineHeight) + bp.top; + const WritingMode wm = GetWritingMode(); + return nsLayoutUtils::GetCenteredFontBaseline(fm, lineHeight, + wm.IsLineInverted()) + bp.top; } ///////////////////////////////////////////////////////////////////////////// @@ -2552,7 +2554,8 @@ nsBlockFrame::ReflowDirtyLines(nsBlockReflowState& aState) nsLayoutUtils::FontSizeInflationFor(this)); nscoord minAscent = - nsLayoutUtils::GetCenteredFontBaseline(fm, aState.mMinLineHeight); + nsLayoutUtils::GetCenteredFontBaseline(fm, aState.mMinLineHeight, + wm.IsLineInverted()); nscoord minDescent = aState.mMinLineHeight - minAscent; aState.mBCoord += std::max(minAscent, metrics.BlockStartAscent()) + diff --git a/layout/generic/nsFrame.cpp b/layout/generic/nsFrame.cpp index 9670a0ae808b..bcd09db3f56d 100644 --- a/layout/generic/nsFrame.cpp +++ b/layout/generic/nsFrame.cpp @@ -1339,7 +1339,12 @@ nsFrame::GetLogicalBaseline(WritingMode aWritingMode) const { NS_ASSERTION(!NS_SUBTREE_DIRTY(this), "frame must not be dirty"); - // Default to the bottom margin edge, per CSS2.1's definition of the + // Baseline for inverted line content is the top (block-start) margin edge, + // as the frame is in effect "flipped" for alignment purposes. + if (aWritingMode.IsLineInverted()) { + return -GetLogicalUsedMargin(aWritingMode).BStart(aWritingMode); + } + // Otherwise, the bottom margin edge, per CSS2.1's definition of the // 'baseline' value of 'vertical-align'. return BSize(aWritingMode) + GetLogicalUsedMargin(aWritingMode).BEnd(aWritingMode); diff --git a/layout/generic/nsLineLayout.cpp b/layout/generic/nsLineLayout.cpp index def2786560c4..c5a97137cfd6 100644 --- a/layout/generic/nsLineLayout.cpp +++ b/layout/generic/nsLineLayout.cpp @@ -2098,7 +2098,8 @@ nsLineLayout::VerticalAlignFrames(PerSpanData* psd) #endif nscoord minimumLineBSize = mMinLineBSize; nscoord blockStart = - -nsLayoutUtils::GetCenteredFontBaseline(fm, minimumLineBSize); + -nsLayoutUtils::GetCenteredFontBaseline(fm, minimumLineBSize, + lineWM.IsLineInverted()); nscoord blockEnd = blockStart + minimumLineBSize; if (blockStart < minBCoord) minBCoord = blockStart; diff --git a/layout/generic/nsTextFrame.cpp b/layout/generic/nsTextFrame.cpp index 18f2542dd951..47a196615396 100644 --- a/layout/generic/nsTextFrame.cpp +++ b/layout/generic/nsTextFrame.cpp @@ -1790,13 +1790,13 @@ GetHyphenTextRun(gfxTextRun* aTextRun, gfxContext* aContext, nsTextFrame* aTextF } static gfxFont::Metrics -GetFirstFontMetrics(gfxFontGroup* aFontGroup, bool aVertical) +GetFirstFontMetrics(gfxFontGroup* aFontGroup, bool aVerticalMetrics) { if (!aFontGroup) return gfxFont::Metrics(); gfxFont* font = aFontGroup->GetFirstValidFont(); - return font->GetMetrics(aVertical ? gfxFont::eVertical : - gfxFont::eHorizontal); + return font->GetMetrics(aVerticalMetrics ? gfxFont::eVertical + : gfxFont::eHorizontal); } PR_STATIC_ASSERT(NS_STYLE_WHITESPACE_NORMAL == 0); @@ -3161,7 +3161,7 @@ ComputeTabWidthAppUnits(nsIFrame* aFrame, gfxTextRun* aTextRun) // textruns do gfxFloat spaceWidthAppUnits = NS_round(GetFirstFontMetrics(aTextRun->GetFontGroup(), - aTextRun->IsVertical()).spaceWidth * + aTextRun->UseCenterBaseline()).spaceWidth * aTextRun->GetAppUnitsPerDevUnit()); return textStyle->mTabSize * spaceWidthAppUnits; } @@ -4918,7 +4918,9 @@ nsTextFrame::UnionAdditionalOverflow(nsPresContext* aPresContext, nsRect shadowRect = nsLayoutUtils::GetTextShadowRectsUnion(*aVisualOverflowRect, this); aVisualOverflowRect->UnionRect(*aVisualOverflowRect, shadowRect); - bool vertical = mTextRun->IsVertical(); + bool verticalRun = mTextRun->IsVertical(); + bool useVerticalMetrics = verticalRun && mTextRun->UseCenterBaseline(); + bool inverted = GetWritingMode().IsLineInverted(); if (IsFloatingFirstLetterChild()) { // The underline/overline drawable area must be contained in the overflow @@ -4935,11 +4937,13 @@ nsTextFrame::UnionAdditionalOverflow(nsPresContext* aPresContext, nsFontMetrics* fontMetrics = aProvider.GetFontMetrics(); nscoord underlineOffset, underlineSize; fontMetrics->GetUnderline(underlineOffset, underlineSize); - nscoord maxAscent = fontMetrics->MaxAscent(); + nscoord maxAscent = inverted ? fontMetrics->MaxDescent() + : fontMetrics->MaxAscent(); gfxFloat appUnitsPerDevUnit = aPresContext->AppUnitsPerDevPixel(); gfxFloat gfxWidth = - (vertical ? aVisualOverflowRect->height : aVisualOverflowRect->width) / + (verticalRun ? aVisualOverflowRect->height + : aVisualOverflowRect->width) / appUnitsPerDevUnit; gfxFloat gfxAscent = gfxFloat(mAscent) / appUnitsPerDevUnit; gfxFloat gfxMaxAscent = maxAscent / appUnitsPerDevUnit; @@ -4948,11 +4952,11 @@ nsTextFrame::UnionAdditionalOverflow(nsPresContext* aPresContext, nsRect underlineRect = nsCSSRendering::GetTextDecorationRect(aPresContext, gfxSize(gfxWidth, gfxUnderlineSize), gfxAscent, gfxUnderlineOffset, - NS_STYLE_TEXT_DECORATION_LINE_UNDERLINE, decorationStyle, vertical); + NS_STYLE_TEXT_DECORATION_LINE_UNDERLINE, decorationStyle, verticalRun); nsRect overlineRect = nsCSSRendering::GetTextDecorationRect(aPresContext, gfxSize(gfxWidth, gfxUnderlineSize), gfxAscent, gfxMaxAscent, - NS_STYLE_TEXT_DECORATION_LINE_OVERLINE, decorationStyle, vertical); + NS_STYLE_TEXT_DECORATION_LINE_OVERLINE, decorationStyle, verticalRun); aVisualOverflowRect->UnionRect(*aVisualOverflowRect, underlineRect); aVisualOverflowRect->UnionRect(*aVisualOverflowRect, overlineRect); @@ -4972,11 +4976,16 @@ nsTextFrame::UnionAdditionalOverflow(nsPresContext* aPresContext, nscoord inflationMinFontSize = nsLayoutUtils::InflationMinFontSizeFor(aBlock); - const nscoord measure = vertical ? GetSize().height : GetSize().width; + const nscoord measure = verticalRun ? GetSize().height : GetSize().width; const gfxFloat appUnitsPerDevUnit = aPresContext->AppUnitsPerDevPixel(), - gfxWidth = measure / appUnitsPerDevUnit, - ascent = gfxFloat(mAscent) / appUnitsPerDevUnit; - nscoord top(nscoord_MAX), bottom(nscoord_MIN); + gfxWidth = measure / appUnitsPerDevUnit; + gfxFloat ascent = gfxFloat(mAscent) / appUnitsPerDevUnit; + const WritingMode wm = GetWritingMode(); + if (wm.IsVerticalRL()) { + ascent = -ascent; + } + + nscoord topOrLeft(nscoord_MAX), bottomOrRight(nscoord_MIN); // Below we loop through all text decorations and compute the rectangle // containing all of them, in this frame's coordinate space for (uint32_t i = 0; i < textDecs.mUnderlines.Length(); ++i) { @@ -4993,18 +5002,23 @@ nsTextFrame::UnionAdditionalOverflow(nsPresContext* aPresContext, GetInflationForTextDecorations(dec.mFrame, inflationMinFontSize); const gfxFont::Metrics metrics = GetFirstFontMetrics(GetFontGroupForFrame(dec.mFrame, inflation), - vertical); + useVerticalMetrics); const nsRect decorationRect = nsCSSRendering::GetTextDecorationRect(aPresContext, gfxSize(gfxWidth, metrics.underlineSize), ascent, metrics.underlineOffset, NS_STYLE_TEXT_DECORATION_LINE_UNDERLINE, decorationStyle, - vertical) + + verticalRun) + nsPoint(0, -dec.mBaselineOffset); - top = std::min(decorationRect.y, top); - bottom = std::max(decorationRect.YMost(), bottom); + if (verticalRun) { + topOrLeft = std::min(decorationRect.x, topOrLeft); + bottomOrRight = std::max(decorationRect.XMost(), bottomOrRight); + } else { + topOrLeft = std::min(decorationRect.y, topOrLeft); + bottomOrRight = std::max(decorationRect.YMost(), bottomOrRight); + } } for (uint32_t i = 0; i < textDecs.mOverlines.Length(); ++i) { const LineDecoration& dec = textDecs.mOverlines[i]; @@ -5020,18 +5034,23 @@ nsTextFrame::UnionAdditionalOverflow(nsPresContext* aPresContext, GetInflationForTextDecorations(dec.mFrame, inflationMinFontSize); const gfxFont::Metrics metrics = GetFirstFontMetrics(GetFontGroupForFrame(dec.mFrame, inflation), - vertical); + useVerticalMetrics); const nsRect decorationRect = nsCSSRendering::GetTextDecorationRect(aPresContext, gfxSize(gfxWidth, metrics.underlineSize), ascent, metrics.maxAscent, NS_STYLE_TEXT_DECORATION_LINE_OVERLINE, decorationStyle, - vertical) + + verticalRun) + nsPoint(0, -dec.mBaselineOffset); - top = std::min(decorationRect.y, top); - bottom = std::max(decorationRect.YMost(), bottom); + if (verticalRun) { + topOrLeft = std::min(decorationRect.x, topOrLeft); + bottomOrRight = std::max(decorationRect.XMost(), bottomOrRight); + } else { + topOrLeft = std::min(decorationRect.y, topOrLeft); + bottomOrRight = std::max(decorationRect.YMost(), bottomOrRight); + } } for (uint32_t i = 0; i < textDecs.mStrikes.Length(); ++i) { const LineDecoration& dec = textDecs.mStrikes[i]; @@ -5047,23 +5066,29 @@ nsTextFrame::UnionAdditionalOverflow(nsPresContext* aPresContext, GetInflationForTextDecorations(dec.mFrame, inflationMinFontSize); const gfxFont::Metrics metrics = GetFirstFontMetrics(GetFontGroupForFrame(dec.mFrame, inflation), - vertical); + useVerticalMetrics); const nsRect decorationRect = nsCSSRendering::GetTextDecorationRect(aPresContext, gfxSize(gfxWidth, metrics.strikeoutSize), ascent, metrics.strikeoutOffset, NS_STYLE_TEXT_DECORATION_LINE_LINE_THROUGH, decorationStyle, - vertical) + + verticalRun) + nsPoint(0, -dec.mBaselineOffset); - top = std::min(decorationRect.y, top); - bottom = std::max(decorationRect.YMost(), bottom); + + if (verticalRun) { + topOrLeft = std::min(decorationRect.x, topOrLeft); + bottomOrRight = std::max(decorationRect.XMost(), bottomOrRight); + } else { + topOrLeft = std::min(decorationRect.y, topOrLeft); + bottomOrRight = std::max(decorationRect.YMost(), bottomOrRight); + } } - aVisualOverflowRect->UnionRect(*aVisualOverflowRect, - vertical ? - nsRect(top, 0, bottom - top, measure) : - nsRect(0, top, measure, bottom - top)); + aVisualOverflowRect->UnionRect( + *aVisualOverflowRect, + verticalRun ? nsRect(topOrLeft, 0, bottomOrRight - topOrLeft, measure) + : nsRect(0, topOrLeft, measure, bottomOrRight - topOrLeft)); } } // When this frame is not selected, the text-decoration area must be in @@ -5723,19 +5748,20 @@ nsTextFrame::PaintTextSelectionDecorations(gfxContext* aCtx, } gfxFont* firstFont = aProvider.GetFontGroup()->GetFirstValidFont(); - bool vertical = mTextRun->IsVertical(); + bool verticalRun = mTextRun->IsVertical(); + bool useVerticalMetrics = verticalRun && mTextRun->UseCenterBaseline(); gfxFont::Metrics - decorationMetrics(firstFont->GetMetrics(vertical ? + decorationMetrics(firstFont->GetMetrics(useVerticalMetrics ? gfxFont::eVertical : gfxFont::eHorizontal)); - if (!vertical) { + if (!useVerticalMetrics) { // The potential adjustment from using gfxFontGroup::GetUnderlineOffset - // is only valid for horizontal text. + // is only valid for horizontal font metrics. decorationMetrics.underlineOffset = aProvider.GetFontGroup()->GetUnderlineOffset(); } gfxFloat startIOffset = - vertical ? aTextBaselinePt.y - aFramePt.y : aTextBaselinePt.x - aFramePt.x; + verticalRun ? aTextBaselinePt.y - aFramePt.y : aTextBaselinePt.x - aFramePt.x; SelectionIterator iterator(selectedChars, aContentOffset, aContentLength, aProvider, mTextRun, startIOffset); gfxFloat iOffset, hyphenWidth; @@ -5743,7 +5769,7 @@ nsTextFrame::PaintTextSelectionDecorations(gfxContext* aCtx, int32_t app = aTextPaintStyle.PresContext()->AppUnitsPerDevPixel(); // XXX aTextBaselinePt is in AppUnits, shouldn't it be nsFloatPoint? gfxPoint pt; - if (vertical) { + if (verticalRun) { pt.x = (aTextBaselinePt.x - mAscent) / app; } else { pt.y = (aTextBaselinePt.y - mAscent) / app; @@ -5757,7 +5783,7 @@ nsTextFrame::PaintTextSelectionDecorations(gfxContext* aCtx, gfxFloat advance = hyphenWidth + mTextRun->GetAdvanceWidth(offset, length, &aProvider); if (type == aSelectionType) { - if (vertical) { + if (verticalRun) { pt.y = (aFramePt.y + iOffset - (mTextRun->IsRightToLeft() ? advance : 0)) / app; } else { @@ -5769,7 +5795,7 @@ nsTextFrame::PaintTextSelectionDecorations(gfxContext* aCtx, DrawSelectionDecorations(aCtx, dirtyRect, aSelectionType, this, aTextPaintStyle, selectedStyle, pt, xInFrame, width, mAscent / app, decorationMetrics, - aCallbacks, vertical); + aCallbacks, verticalRun); } iterator.UpdateWithAdvance(advance); } @@ -6013,15 +6039,14 @@ nsTextFrame::PaintText(nsRenderingContext* aRenderingContext, nsPoint aPt, gfxContext* ctx = aRenderingContext->ThebesContext(); const bool rtl = mTextRun->IsRightToLeft(); - const bool vertical = mTextRun->IsVertical(); + const bool verticalRun = mTextRun->IsVertical(); + WritingMode wm = GetWritingMode(); const nscoord frameWidth = GetSize().width; gfxPoint framePt(aPt.x, aPt.y); gfxPoint textBaselinePt; - if (vertical) { - WritingMode wm = GetWritingMode(); - textBaselinePt = - gfxPoint(wm.IsVerticalLR() ? aPt.x + mAscent - : aPt.x + frameWidth - mAscent, + if (verticalRun) { + textBaselinePt = // XXX sideways-left will need different handling here + gfxPoint(aPt.x + (wm.IsVerticalLR() ? mAscent : frameWidth - mAscent), rtl ? aPt.y + GetSize().height : aPt.y); } else { textBaselinePt = gfxPoint(rtl ? gfxFloat(aPt.x + frameWidth) : framePt.x, @@ -6034,7 +6059,7 @@ nsTextFrame::PaintText(nsRenderingContext* aRenderingContext, nsPoint aPt, &startOffset, &maxLength, &snappedLeftEdge, &snappedRightEdge)) { return; } - if (vertical) { + if (verticalRun) { textBaselinePt.y += rtl ? -snappedRightEdge : snappedLeftEdge; } else { textBaselinePt.x += rtl ? -snappedRightEdge : snappedLeftEdge; @@ -6159,32 +6184,43 @@ nsTextFrame::DrawTextRunAndDecorations( nsTextFrame::DrawPathCallbacks* aCallbacks) { const gfxFloat app = aTextStyle.PresContext()->AppUnitsPerDevPixel(); - bool vertical = mTextRun->IsVertical(); + bool verticalRun = mTextRun->IsVertical(); + bool useVerticalMetrics = verticalRun && mTextRun->UseCenterBaseline(); // XXX aFramePt is in AppUnits, shouldn't it be nsFloatPoint? nscoord x = NSToCoordRound(aFramePt.x); nscoord y = NSToCoordRound(aFramePt.y); - // 'width' here is textrun-relative, so for a vertical run it's - // really the height of the decoration - nscoord width = vertical ? GetRect().height : GetRect().width; + // 'measure' here is textrun-relative, so for a horizontal run it's the + // width, while for a vertical run it's the height of the decoration + const nsSize frameSize = GetSize(); + nscoord measure = verticalRun ? frameSize.height : frameSize.width; // XXX todo: probably should have a vertical version of this... - if (!vertical) { - aClipEdges.Intersect(&x, &width); + if (!verticalRun) { + aClipEdges.Intersect(&x, &measure); } // decPt is the physical point where the decoration is to be drawn, // relative to the frame; one of its coordinates will be updated below. gfxPoint decPt(x / app, y / app); - gfxFloat& bCoord = vertical ? decPt.x : decPt.y; + gfxFloat& bCoord = verticalRun ? decPt.x : decPt.y; - // ...whereas decSize is a textrun-relative size - gfxSize decSize(width / app, 0); - const gfxFloat ascent = gfxFloat(mAscent) / app; + // decSize is a textrun-relative size, so its 'width' field is actually + // the run-relative measure, and 'height' will be the line thickness + gfxSize decSize(measure / app, 0); + gfxFloat ascent = gfxFloat(mAscent) / app; // The starting edge of the frame in block direction - const gfxFloat frameBStart = vertical ? aFramePt.x : aFramePt.y; + gfxFloat frameBStart = verticalRun ? aFramePt.x : aFramePt.y; + + // In vertical-rl mode, block coordinates are measured from the right, + // so we need to adjust here. + const WritingMode wm = GetWritingMode(); + if (wm.IsVerticalRL()) { + frameBStart += frameSize.width; + ascent = -ascent; + } gfxRect dirtyRect(aDirtyRect.x / app, aDirtyRect.y / app, aDirtyRect.Width() / app, aDirtyRect.Height() / app); @@ -6203,7 +6239,7 @@ nsTextFrame::DrawTextRunAndDecorations( GetInflationForTextDecorations(dec.mFrame, inflationMinFontSize); const gfxFont::Metrics metrics = GetFirstFontMetrics(GetFontGroupForFrame(dec.mFrame, inflation), - vertical); + useVerticalMetrics); decSize.height = metrics.underlineSize; bCoord = (frameBStart - dec.mBaselineOffset) / app; @@ -6211,7 +6247,7 @@ nsTextFrame::DrawTextRunAndDecorations( PaintDecorationLine(this, aCtx, dirtyRect, dec.mColor, aDecorationOverrideColor, decPt, 0.0, decSize, ascent, metrics.underlineOffset, NS_STYLE_TEXT_DECORATION_LINE_UNDERLINE, - dec.mStyle, eNormalDecoration, aCallbacks, vertical); + dec.mStyle, eNormalDecoration, aCallbacks, verticalRun); } // Overlines for (uint32_t i = aDecorations.mOverlines.Length(); i-- > 0; ) { @@ -6224,7 +6260,7 @@ nsTextFrame::DrawTextRunAndDecorations( GetInflationForTextDecorations(dec.mFrame, inflationMinFontSize); const gfxFont::Metrics metrics = GetFirstFontMetrics(GetFontGroupForFrame(dec.mFrame, inflation), - vertical); + useVerticalMetrics); decSize.height = metrics.underlineSize; bCoord = (frameBStart - dec.mBaselineOffset) / app; @@ -6232,7 +6268,7 @@ nsTextFrame::DrawTextRunAndDecorations( PaintDecorationLine(this, aCtx, dirtyRect, dec.mColor, aDecorationOverrideColor, decPt, 0.0, decSize, ascent, metrics.maxAscent, NS_STYLE_TEXT_DECORATION_LINE_OVERLINE, dec.mStyle, - eNormalDecoration, aCallbacks, vertical); + eNormalDecoration, aCallbacks, verticalRun); } // CSS 2.1 mandates that text be painted after over/underlines, and *then* @@ -6251,7 +6287,7 @@ nsTextFrame::DrawTextRunAndDecorations( GetInflationForTextDecorations(dec.mFrame, inflationMinFontSize); const gfxFont::Metrics metrics = GetFirstFontMetrics(GetFontGroupForFrame(dec.mFrame, inflation), - vertical); + useVerticalMetrics); decSize.height = metrics.strikeoutSize; bCoord = (frameBStart - dec.mBaselineOffset) / app; @@ -6259,7 +6295,7 @@ nsTextFrame::DrawTextRunAndDecorations( PaintDecorationLine(this, aCtx, dirtyRect, dec.mColor, aDecorationOverrideColor, decPt, 0.0, decSize, ascent, metrics.strikeoutOffset, NS_STYLE_TEXT_DECORATION_LINE_LINE_THROUGH, - dec.mStyle, eNormalDecoration, aCallbacks, vertical); + dec.mStyle, eNormalDecoration, aCallbacks, verticalRun); } } @@ -6458,9 +6494,12 @@ nsTextFrame::CombineSelectionUnderlineRect(nsPresContext* aPresContext, GetFontSizeInflation()); gfxFontGroup* fontGroup = fm->GetThebesFontGroup(); gfxFont* firstFont = fontGroup->GetFirstValidFont(); - bool vertical = GetWritingMode().IsVertical(); + WritingMode wm = GetWritingMode(); + bool verticalRun = wm.IsVertical(); + bool useVerticalMetrics = verticalRun && !wm.IsSideways(); const gfxFont::Metrics& metrics = - firstFont->GetMetrics(vertical ? gfxFont::eVertical : gfxFont::eHorizontal); + firstFont->GetMetrics(useVerticalMetrics ? gfxFont::eVertical + : gfxFont::eHorizontal); gfxFloat underlineOffset = fontGroup->GetUnderlineOffset(); gfxFloat ascent = aPresContext->AppUnitsToGfxUnits(mAscent); gfxFloat descentLimit = @@ -6505,7 +6544,7 @@ nsTextFrame::CombineSelectionUnderlineRect(nsPresContext* aPresContext, decorationArea = nsCSSRendering::GetTextDecorationRect(aPresContext, size, ascent, underlineOffset, NS_STYLE_TEXT_DECORATION_LINE_UNDERLINE, - style, vertical, descentLimit); + style, verticalRun, descentLimit); aRect.UnionRect(aRect, decorationArea); } DestroySelectionDetails(details); @@ -7617,7 +7656,11 @@ nsTextFrame::ComputeTightBounds(gfxContext* aContext) const aContext, &provider); // mAscent should be the same as metrics.mAscent, but it's what we use to // paint so that's the one we'll use. - nsRect boundingBox = RoundOut(metrics.mBoundingBox) + nsPoint(0, mAscent); + nsRect boundingBox = RoundOut(metrics.mBoundingBox); + if (GetWritingMode().IsLineInverted()) { + boundingBox.y = -boundingBox.YMost(); + } + boundingBox += nsPoint(0, mAscent); if (mTextRun->IsVertical()) { // Swap line-relative textMetrics dimensions to physical coordinates. Swap(boundingBox.x, boundingBox.y); @@ -8302,9 +8345,15 @@ nsTextFrame::ReflowText(nsLineLayout& aLineLayout, nscoord aAvailableWidth, finalSize.BSize(wm) = 0; } else if (boundingBoxType != gfxFont::LOOSE_INK_EXTENTS) { // Use actual text metrics for floating first letter frame. - aMetrics.SetBlockStartAscent(NSToCoordCeil(textMetrics.mAscent)); - finalSize.BSize(wm) = aMetrics.BlockStartAscent() + - NSToCoordCeil(textMetrics.mDescent); + if (wm.IsLineInverted()) { + aMetrics.SetBlockStartAscent(NSToCoordCeil(textMetrics.mDescent)); + finalSize.BSize(wm) = aMetrics.BlockStartAscent() + + NSToCoordCeil(textMetrics.mAscent); + } else { + aMetrics.SetBlockStartAscent(NSToCoordCeil(textMetrics.mAscent)); + finalSize.BSize(wm) = aMetrics.BlockStartAscent() + + NSToCoordCeil(textMetrics.mDescent); + } } else { // Otherwise, ascent should contain the overline drawable area. // And also descent should contain the underline drawable area. @@ -8312,9 +8361,15 @@ nsTextFrame::ReflowText(nsLineLayout& aLineLayout, nscoord aAvailableWidth, nsFontMetrics* fm = provider.GetFontMetrics(); nscoord fontAscent = fm->MaxAscent(); nscoord fontDescent = fm->MaxDescent(); - aMetrics.SetBlockStartAscent(std::max(NSToCoordCeil(textMetrics.mAscent), fontAscent)); - nscoord descent = std::max(NSToCoordCeil(textMetrics.mDescent), fontDescent); - finalSize.BSize(wm) = aMetrics.BlockStartAscent() + descent; + if (wm.IsLineInverted()) { + aMetrics.SetBlockStartAscent(std::max(NSToCoordCeil(textMetrics.mDescent), fontDescent)); + nscoord descent = std::max(NSToCoordCeil(textMetrics.mAscent), fontAscent); + finalSize.BSize(wm) = aMetrics.BlockStartAscent() + descent; + } else { + aMetrics.SetBlockStartAscent(std::max(NSToCoordCeil(textMetrics.mAscent), fontAscent)); + nscoord descent = std::max(NSToCoordCeil(textMetrics.mDescent), fontDescent); + finalSize.BSize(wm) = aMetrics.BlockStartAscent() + descent; + } } aMetrics.SetSize(wm, finalSize); @@ -8327,13 +8382,17 @@ nsTextFrame::ReflowText(nsLineLayout& aLineLayout, nscoord aAvailableWidth, mAscent = aMetrics.BlockStartAscent(); // Handle text that runs outside its normal bounds. - nsRect boundingBox = RoundOut(textMetrics.mBoundingBox) + nsPoint(0, mAscent); - aMetrics.SetOverflowAreasToDesiredBounds(); + nsRect boundingBox = RoundOut(textMetrics.mBoundingBox); + if (wm.IsLineInverted()) { + boundingBox.y = -boundingBox.YMost(); + } + boundingBox += nsPoint(0, mAscent); if (mTextRun->IsVertical()) { // Swap line-relative textMetrics dimensions to physical coordinates. Swap(boundingBox.x, boundingBox.y); Swap(boundingBox.width, boundingBox.height); } + aMetrics.SetOverflowAreasToDesiredBounds(); aMetrics.VisualOverflow().UnionRect(aMetrics.VisualOverflow(), boundingBox); // When we have text decorations, we don't need to compute their overflow now @@ -8549,18 +8608,23 @@ nsTextFrame::RecomputeOverflow(const nsHTMLReflowState& aBlockReflowState) ComputeTransformedLength(provider), gfxFont::LOOSE_INK_EXTENTS, nullptr, &provider); - nsRect &vis = result.VisualOverflow(); - nsRect boundingBox = RoundOut(textMetrics.mBoundingBox) + nsPoint(0, mAscent); + nsRect boundingBox = RoundOut(textMetrics.mBoundingBox); + if (GetWritingMode().IsLineInverted()) { + boundingBox.y = -boundingBox.YMost(); + } + boundingBox += nsPoint(0, mAscent); if (mTextRun->IsVertical()) { // Swap line-relative textMetrics dimensions to physical coordinates. Swap(boundingBox.x, boundingBox.y); Swap(boundingBox.width, boundingBox.height); } + nsRect &vis = result.VisualOverflow(); vis.UnionRect(vis, boundingBox); UnionAdditionalOverflow(PresContext(), aBlockReflowState.frame, provider, &vis, true); return result; } + static char16_t TransformChar(const nsStyleText* aStyle, gfxTextRun* aTextRun, uint32_t aSkippedOffset, char16_t aChar) { From 5182bb2e02d06e19a82b701d04a5c0cc0275696d Mon Sep 17 00:00:00 2001 From: Jonathan Kew Date: Thu, 13 Nov 2014 08:58:06 +0000 Subject: [PATCH 70/80] Bug 1093553 - Followup to fix positioning of the caret with writing-mode:vertical-lr and text-orientation:sideways-right. r=smontagu --- layout/base/nsCaret.cpp | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/layout/base/nsCaret.cpp b/layout/base/nsCaret.cpp index 1b386ba04ab8..a9783a0aa62c 100644 --- a/layout/base/nsCaret.cpp +++ b/layout/base/nsCaret.cpp @@ -309,9 +309,14 @@ nsCaret::GetGeometryForFrame(nsIFrame* aFrame, descent = fm->MaxDescent(); } nscoord height = ascent + descent; - bool vertical = aFrame->GetWritingMode().IsVertical(); + WritingMode wm = aFrame->GetWritingMode(); + bool vertical = wm.IsVertical(); if (vertical) { - framePos.x = baseline - ascent; + if (wm.IsLineInverted()) { + framePos.x = baseline - descent; + } else { + framePos.x = baseline - ascent; + } } else { framePos.y = baseline - ascent; } From dbeb458ff76cce7f1cfeb3c543bb74d3d3dc136d Mon Sep 17 00:00:00 2001 From: Jonathan Kew Date: Thu, 13 Nov 2014 08:58:06 +0000 Subject: [PATCH 71/80] Bug 1094434 - Render resizer appropriately for vertical-lr and vertical-rl writing modes. r=roc --- layout/xul/nsResizerFrame.cpp | 19 +++++++++++++------ toolkit/content/widgets/resizer.xml | 12 +++++++++--- widget/nsNativeTheme.cpp | 6 +++++- 3 files changed, 27 insertions(+), 10 deletions(-) diff --git a/layout/xul/nsResizerFrame.cpp b/layout/xul/nsResizerFrame.cpp index 84812da89fa6..83477dbba0a5 100644 --- a/layout/xul/nsResizerFrame.cpp +++ b/layout/xul/nsResizerFrame.cpp @@ -502,21 +502,28 @@ nsResizerFrame::GetDirection() {-1, 1}, {1, 1} }; - if (!GetContent()) + if (!GetContent()) { return directions[0]; // default: topleft + } int32_t index = GetContent()->FindAttrValueIn(kNameSpaceID_None, nsGkAtoms::dir, strings, eCaseMatters); - if(index < 0) + if (index < 0) { return directions[0]; // default: topleft - else if (index >= 8 && StyleVisibility()->mDirection == NS_STYLE_DIRECTION_RTL) { + } + + if (index >= 8) { // Directions 8 and higher are RTL-aware directions and should reverse the // horizontal component if RTL. - Direction direction = directions[index]; - direction.mHorizontal *= -1; - return direction; + WritingMode wm = GetWritingMode(); + if (!(wm.IsVertical() ? wm.IsVerticalLR() : wm.IsBidiLTR())) { + Direction direction = directions[index]; + direction.mHorizontal *= -1; + return direction; + } } + return directions[index]; } diff --git a/toolkit/content/widgets/resizer.xml b/toolkit/content/widgets/resizer.xml index 64808df3ffe7..da408e47c5c9 100644 --- a/toolkit/content/widgets/resizer.xml +++ b/toolkit/content/widgets/resizer.xml @@ -21,9 +21,15 @@ // if the direction is rtl, set the rtl attribute so that the // stylesheet can use this to make the cursor appear properly - var direction = window.getComputedStyle(this, "").direction; - if (direction == "rtl") { - this.setAttribute("rtl", "true"); + var cs = window.getComputedStyle(this, ""); + if (cs.writingMode == "horizontal-tb") {; + if (cs.direction == "rtl") { + this.setAttribute("rtl", "true"); + } + } else { + if (cs.writingMode == "vertical-rl") { + this.setAttribute("rtl", "true"); + } } ]]> diff --git a/widget/nsNativeTheme.cpp b/widget/nsNativeTheme.cpp index d647d85c28f0..090c6286b91d 100644 --- a/widget/nsNativeTheme.cpp +++ b/widget/nsNativeTheme.cpp @@ -381,7 +381,11 @@ nsNativeTheme::IsDisabled(nsIFrame* aFrame, EventStates aEventStates) bool nsNativeTheme::IsFrameRTL(nsIFrame* aFrame) { - return aFrame && aFrame->StyleVisibility()->mDirection == NS_STYLE_DIRECTION_RTL; + if (!aFrame) { + return false; + } + WritingMode wm = aFrame->GetWritingMode(); + return !(wm.IsVertical() ? wm.IsVerticalLR() : wm.IsBidiLTR()); } bool From 1b048b43163f5c36c47b5e17e9aec4afcd33f296 Mon Sep 17 00:00:00 2001 From: Jonathan Kew Date: Thu, 13 Nov 2014 09:12:53 +0000 Subject: [PATCH 72/80] Bug 1094434 - Reftests for display of resizer on vertical-lr and vertical-rl textareas. r=roc --- .../reftests/writing-mode/1094434-1-ref.html | 27 +++++++++++++++ layout/reftests/writing-mode/1094434-1.html | 33 ++++++++++++++++++ .../reftests/writing-mode/1094434-2-ref.html | 28 +++++++++++++++ layout/reftests/writing-mode/1094434-2.html | 34 +++++++++++++++++++ layout/reftests/writing-mode/reftest.list | 2 ++ 5 files changed, 124 insertions(+) create mode 100644 layout/reftests/writing-mode/1094434-1-ref.html create mode 100644 layout/reftests/writing-mode/1094434-1.html create mode 100644 layout/reftests/writing-mode/1094434-2-ref.html create mode 100644 layout/reftests/writing-mode/1094434-2.html diff --git a/layout/reftests/writing-mode/1094434-1-ref.html b/layout/reftests/writing-mode/1094434-1-ref.html new file mode 100644 index 000000000000..5929b96df843 --- /dev/null +++ b/layout/reftests/writing-mode/1094434-1-ref.html @@ -0,0 +1,27 @@ + + + + + + + + + + + + + +
+ + + + + + + diff --git a/layout/reftests/writing-mode/1094434-1.html b/layout/reftests/writing-mode/1094434-1.html new file mode 100644 index 000000000000..3fe306c0e8f7 --- /dev/null +++ b/layout/reftests/writing-mode/1094434-1.html @@ -0,0 +1,33 @@ + + + + + + + + + + + + + +
+ + + + + + + diff --git a/layout/reftests/writing-mode/1094434-2-ref.html b/layout/reftests/writing-mode/1094434-2-ref.html new file mode 100644 index 000000000000..bdd59fe485e2 --- /dev/null +++ b/layout/reftests/writing-mode/1094434-2-ref.html @@ -0,0 +1,28 @@ + + + + + + + + + + + + + +
+ + + + + + + diff --git a/layout/reftests/writing-mode/1094434-2.html b/layout/reftests/writing-mode/1094434-2.html new file mode 100644 index 000000000000..3264950e26c2 --- /dev/null +++ b/layout/reftests/writing-mode/1094434-2.html @@ -0,0 +1,34 @@ + + + + + + + + + + + + + +
+ + + + + + + diff --git a/layout/reftests/writing-mode/reftest.list b/layout/reftests/writing-mode/reftest.list index 325ed39fab4b..257064f4346c 100644 --- a/layout/reftests/writing-mode/reftest.list +++ b/layout/reftests/writing-mode/reftest.list @@ -15,5 +15,7 @@ == 1090168-2.html 1090168-2-ref.html == 1090168-3.html 1090168-3-ref.html == 1091058-1.html 1091058-1-ref.html +random-if(gtk2Widget) == 1094434-1.html 1094434-1-ref.html # bug 1094845 +random-if(gtk2Widget) == 1094434-2.html 1094434-2-ref.html # bug 1094845 == 1094914-1a.html 1094914-1-ref.html == 1094914-1b.html 1094914-1-ref.html From ea37e37e959db295ac259d9d6dc3680d5500c699 Mon Sep 17 00:00:00 2001 From: Jan Varga Date: Thu, 13 Nov 2014 10:43:22 +0100 Subject: [PATCH 73/80] Bug 1095474 - Intermittent /indexedDB/test/test_file_replace.html | application terminated with exit code 1; r=bent --- dom/indexedDB/ActorsParent.cpp | 33 +++++++++------------------------ dom/indexedDB/FileInfo.cpp | 29 +++++++++++++++++++++++++---- dom/indexedDB/FileInfo.h | 12 ++++-------- 3 files changed, 38 insertions(+), 36 deletions(-) diff --git a/dom/indexedDB/ActorsParent.cpp b/dom/indexedDB/ActorsParent.cpp index 949010fc74e0..be643df17050 100644 --- a/dom/indexedDB/ActorsParent.cpp +++ b/dom/indexedDB/ActorsParent.cpp @@ -8734,16 +8734,15 @@ FileManager::Invalidate() { public: static PLDHashOperator - CopyToTArray(const uint64_t& aKey, FileInfo* aValue, void* aUserArg) + ClearDBRefs(const uint64_t& aKey, FileInfo*& aValue, void* aUserArg) { MOZ_ASSERT(aValue); - auto* array = static_cast*>(aUserArg); - MOZ_ASSERT(array); + if (aValue->LockedClearDBRefs()) { + return PL_DHASH_NEXT; + } - MOZ_ALWAYS_TRUE(array->AppendElement(aValue)); - - return PL_DHASH_NEXT; + return PL_DHASH_REMOVE; } }; @@ -8752,26 +8751,12 @@ FileManager::Invalidate() return NS_ERROR_UNEXPECTED; } - FallibleTArray fileInfos; - { - MutexAutoLock lock(IndexedDatabaseManager::FileMutex()); + MutexAutoLock lock(IndexedDatabaseManager::FileMutex()); - MOZ_ASSERT(!mInvalidated); - mInvalidated = true; + MOZ_ASSERT(!mInvalidated); + mInvalidated = true; - if (NS_WARN_IF(!fileInfos.SetCapacity(mFileInfos.Count()))) { - return NS_ERROR_OUT_OF_MEMORY; - } - - mFileInfos.EnumerateRead(Helper::CopyToTArray, &fileInfos); - } - - for (uint32_t count = fileInfos.Length(), index = 0; index < count; index++) { - FileInfo* fileInfo = fileInfos[index]; - MOZ_ASSERT(fileInfo); - - fileInfo->ClearDBRefs(); - } + mFileInfos.Enumerate(Helper::ClearDBRefs, nullptr); return NS_OK; } diff --git a/dom/indexedDB/FileInfo.cpp b/dom/indexedDB/FileInfo.cpp index b7ad44f9d2df..2ed25f76edb9 100644 --- a/dom/indexedDB/FileInfo.cpp +++ b/dom/indexedDB/FileInfo.cpp @@ -130,15 +130,13 @@ FileInfo::GetReferences(int32_t* aRefCnt, void FileInfo::UpdateReferences(ThreadSafeAutoRefCnt& aRefCount, - int32_t aDelta, - bool aClear) + int32_t aDelta) { // XXX This can go away once DOM objects no longer hold FileInfo objects... // Looking at you, IDBMutableFile... if (IndexedDatabaseManager::IsClosed()) { MOZ_ASSERT(&aRefCount == &mRefCnt); MOZ_ASSERT(aDelta == 1 || aDelta == -1); - MOZ_ASSERT(!aClear); if (aDelta > 0) { ++aRefCount; @@ -158,7 +156,7 @@ FileInfo::UpdateReferences(ThreadSafeAutoRefCnt& aRefCount, { MutexAutoLock lock(IndexedDatabaseManager::FileMutex()); - aRefCount = aClear ? 0 : aRefCount + aDelta; + aRefCount = aRefCount + aDelta; if (mRefCnt + mDBRefCnt + mSliceRefCnt > 0) { return; @@ -176,6 +174,29 @@ FileInfo::UpdateReferences(ThreadSafeAutoRefCnt& aRefCount, delete this; } +bool +FileInfo::LockedClearDBRefs() +{ + MOZ_ASSERT(!IndexedDatabaseManager::IsClosed()); + + IndexedDatabaseManager::FileMutex().AssertCurrentThreadOwns(); + + mDBRefCnt = 0; + + if (mRefCnt || mSliceRefCnt) { + return true; + } + + // In this case, we are not responsible for removing the file info from the + // hashtable. It's up to FileManager which is the only caller of this method. + + MOZ_ASSERT(mFileManager->Invalidated()); + + delete this; + + return false; +} + void FileInfo::Cleanup() { diff --git a/dom/indexedDB/FileInfo.h b/dom/indexedDB/FileInfo.h index 83d786950362..fb5cfcb8d5ae 100644 --- a/dom/indexedDB/FileInfo.h +++ b/dom/indexedDB/FileInfo.h @@ -50,12 +50,6 @@ public: UpdateReferences(mDBRefCnt, aDelta); } - void - ClearDBRefs() - { - UpdateReferences(mDBRefCnt, 0, true); - } - void UpdateSliceRefs(int32_t aDelta) { @@ -80,8 +74,10 @@ protected: private: void UpdateReferences(ThreadSafeAutoRefCnt& aRefCount, - int32_t aDelta, - bool aClear = false); + int32_t aDelta); + + bool + LockedClearDBRefs(); void Cleanup(); From 4b4108a4a9e89f84dd35eadfbf9762166b27e137 Mon Sep 17 00:00:00 2001 From: "Carsten \"Tomcat\" Book" Date: Thu, 13 Nov 2014 11:47:31 +0100 Subject: [PATCH 74/80] Backed out changeset a96930f1e26b (bug 1055741) --- dom/ipc/TabChild.cpp | 50 ++-- gfx/ipc/GfxMessageUtils.h | 2 + gfx/layers/FrameMetrics.h | 78 ++++-- gfx/layers/LayersLogging.cpp | 6 +- gfx/layers/apz/src/APZCTreeManager.cpp | 150 ++++++----- gfx/layers/apz/src/APZCTreeManager.h | 8 +- gfx/layers/apz/src/AsyncPanZoomController.cpp | 254 ++++++++++-------- gfx/layers/apz/src/AsyncPanZoomController.h | 72 ++--- gfx/layers/apz/src/Axis.cpp | 96 ++++--- gfx/layers/apz/src/Axis.h | 74 ++--- gfx/layers/apz/src/GestureEventListener.cpp | 77 +++--- gfx/layers/apz/src/GestureEventListener.h | 4 +- gfx/layers/apz/util/APZCCallbackHelper.cpp | 10 +- gfx/layers/client/ClientLayerManager.cpp | 4 +- gfx/layers/client/ClientTiledPaintedLayer.cpp | 14 +- gfx/layers/client/TiledContentClient.cpp | 12 +- .../composite/AsyncCompositionManager.cpp | 30 +-- .../composite/AsyncCompositionManager.h | 14 +- .../gtest/TestAsyncPanZoomController.cpp | 167 +++++------- layout/base/UnitTransforms.h | 30 +-- layout/base/Units.h | 35 +-- layout/base/nsDisplayList.cpp | 17 +- layout/base/nsLayoutUtils.cpp | 14 +- widget/InputData.h | 72 +---- widget/android/AndroidBridge.cpp | 8 +- widget/android/AndroidBridge.h | 6 +- widget/windows/winrt/APZController.cpp | 4 +- 27 files changed, 639 insertions(+), 669 deletions(-) diff --git a/dom/ipc/TabChild.cpp b/dom/ipc/TabChild.cpp index 504bdb0554e9..07ac0b840bf6 100644 --- a/dom/ipc/TabChild.cpp +++ b/dom/ipc/TabChild.cpp @@ -241,16 +241,16 @@ TabChildBase::InitializeRootMetrics() mLastRootMetrics.SetViewport(CSSRect(CSSPoint(), kDefaultViewportSize)); mLastRootMetrics.mCompositionBounds = ParentLayerRect( ParentLayerPoint(), - ParentLayerSize(ViewAs(mInnerSize, PixelCastJustification::ScreenIsParentLayerForRoot))); + ParentLayerSize(ViewAs(mInnerSize, PixelCastJustification::ScreenToParentLayerForRoot))); mLastRootMetrics.SetZoom(mLastRootMetrics.CalculateIntrinsicScale()); mLastRootMetrics.mDevPixelsPerCSSPixel = WebWidget()->GetDefaultScale(); - // We use ParentLayerToLayerScale(1) below in order to turn the + // We use ScreenToLayerScale(1) below in order to turn the // async zoom amount into the gecko zoom amount. mLastRootMetrics.mCumulativeResolution = - mLastRootMetrics.GetZoom() / mLastRootMetrics.mDevPixelsPerCSSPixel * ParentLayerToLayerScale(1); + mLastRootMetrics.GetZoom() / mLastRootMetrics.mDevPixelsPerCSSPixel * ScreenToLayerScale(1); // This is the root layer, so the cumulative resolution is the same // as the resolution. - mLastRootMetrics.mPresShellResolution = mLastRootMetrics.mCumulativeResolution.scale; + mLastRootMetrics.mPresShellResolution = mLastRootMetrics.mCumulativeResolution / LayoutDeviceToParentLayerScale(1); mLastRootMetrics.SetScrollOffset(CSSPoint(0, 0)); TABC_LOG("After InitializeRootMetrics, mLastRootMetrics is %s\n", @@ -294,20 +294,6 @@ TabChildBase::GetPageSize(nsCOMPtr aDocument, const CSSSize& aViewp std::max(htmlHeight, bodyHeight)); } -// For the root frame, Screen and ParentLayer pixels are interchangeable. -// nsViewportInfo stores zoom values as CSSToScreenScale (because it's a -// data structure specific to the root frame), while FrameMetrics and -// ZoomConstraints store zoom values as CSSToParentLayerScale (because they -// are not specific to the root frame). We define convenience functions for -// converting between the two. As the name suggests, they should only be used -// when dealing with the root frame! -CSSToScreenScale ConvertScaleForRoot(CSSToParentLayerScale aScale) { - return ViewTargetAs(aScale, PixelCastJustification::ScreenIsParentLayerForRoot); -} -CSSToParentLayerScale ConvertScaleForRoot(CSSToScreenScale aScale) { - return ViewTargetAs(aScale, PixelCastJustification::ScreenIsParentLayerForRoot); -} - bool TabChildBase::HandlePossibleViewportChange(const ScreenIntSize& aOldScreenSize) { @@ -330,8 +316,8 @@ TabChildBase::HandlePossibleViewportChange(const ScreenIntSize& aOldScreenSize) ZoomConstraints constraints( viewportInfo.IsZoomAllowed(), viewportInfo.IsDoubleTapZoomAllowed(), - ConvertScaleForRoot(viewportInfo.GetMinZoom()), - ConvertScaleForRoot(viewportInfo.GetMaxZoom())); + viewportInfo.GetMinZoom(), + viewportInfo.GetMaxZoom()); DoUpdateZoomConstraints(presShellId, viewId, /* isRoot = */ true, @@ -380,7 +366,7 @@ TabChildBase::HandlePossibleViewportChange(const ScreenIntSize& aOldScreenSize) metrics.SetViewport(CSSRect(CSSPoint(), viewport)); metrics.mCompositionBounds = ParentLayerRect( ParentLayerPoint(), - ParentLayerSize(ViewAs(mInnerSize, PixelCastJustification::ScreenIsParentLayerForRoot))); + ParentLayerSize(ViewAs(mInnerSize, PixelCastJustification::ScreenToParentLayerForRoot))); metrics.SetRootCompositionSize( ScreenSize(mInnerSize) * ScreenToLayoutDeviceScale(1.0f) / metrics.mDevPixelsPerCSSPixel); @@ -410,13 +396,13 @@ TabChildBase::HandlePossibleViewportChange(const ScreenIntSize& aOldScreenSize) // 0.0 to mean "did not calculate a zoom". In that case, we default // it to the intrinsic scale. if (viewportInfo.GetDefaultZoom().scale < 0.01f) { - viewportInfo.SetDefaultZoom(ConvertScaleForRoot(metrics.CalculateIntrinsicScale())); + viewportInfo.SetDefaultZoom(metrics.CalculateIntrinsicScale()); } CSSToScreenScale defaultZoom = viewportInfo.GetDefaultZoom(); MOZ_ASSERT(viewportInfo.GetMinZoom() <= defaultZoom && defaultZoom <= viewportInfo.GetMaxZoom()); - metrics.SetZoom(ConvertScaleForRoot(defaultZoom)); + metrics.SetZoom(defaultZoom); metrics.SetScrollId(viewId); } @@ -428,13 +414,11 @@ TabChildBase::HandlePossibleViewportChange(const ScreenIntSize& aOldScreenSize) } } - metrics.mCumulativeResolution = metrics.GetZoom() - / metrics.mDevPixelsPerCSSPixel - * ParentLayerToLayerScale(1); + metrics.mCumulativeResolution = metrics.GetZoom() / metrics.mDevPixelsPerCSSPixel * ScreenToLayerScale(1); // This is the root layer, so the cumulative resolution is the same // as the resolution. - metrics.mPresShellResolution = metrics.mCumulativeResolution.scale; - utils->SetResolution(metrics.mPresShellResolution, metrics.mPresShellResolution); + metrics.mPresShellResolution = metrics.mCumulativeResolution / LayoutDeviceToParentLayerScale(1); + utils->SetResolution(metrics.mPresShellResolution.scale, metrics.mPresShellResolution.scale); CSSSize scrollPort = metrics.CalculateCompositedSizeInCssPixels(); utils->SetScrollPositionClampingScrollPortSize(scrollPort.width, scrollPort.height); @@ -456,7 +440,7 @@ TabChildBase::HandlePossibleViewportChange(const ScreenIntSize& aOldScreenSize) // The page must have been refreshed in some way such as a new document or // new CSS viewport, so we know that there's no velocity, acceleration, and // we have no idea how long painting will take. - metrics, ParentLayerPoint(0.0f, 0.0f), 0.0)); + metrics, ScreenPoint(0.0f, 0.0f), 0.0)); metrics.SetUseDisplayPortMargins(); // Force a repaint with these metrics. This, among other things, sets the @@ -473,8 +457,8 @@ TabChildBase::HandlePossibleViewportChange(const ScreenIntSize& aOldScreenSize) ZoomConstraints constraints( viewportInfo.IsZoomAllowed(), viewportInfo.IsDoubleTapZoomAllowed(), - ConvertScaleForRoot(viewportInfo.GetMinZoom()), - ConvertScaleForRoot(viewportInfo.GetMaxZoom())); + viewportInfo.GetMinZoom(), + viewportInfo.GetMaxZoom()); DoUpdateZoomConstraints(presShellId, viewId, /* isRoot = */ true, @@ -923,8 +907,8 @@ TabChild::Observe(nsISupports *aSubject, // until we we get an inner size. if (HasValidInnerSize()) { InitializeRootMetrics(); - utils->SetResolution(mLastRootMetrics.mPresShellResolution, - mLastRootMetrics.mPresShellResolution); + utils->SetResolution(mLastRootMetrics.mPresShellResolution.scale, + mLastRootMetrics.mPresShellResolution.scale); HandlePossibleViewportChange(mInnerSize); } } diff --git a/gfx/ipc/GfxMessageUtils.h b/gfx/ipc/GfxMessageUtils.h index 861252754ae5..b62c2a57839e 100644 --- a/gfx/ipc/GfxMessageUtils.h +++ b/gfx/ipc/GfxMessageUtils.h @@ -752,6 +752,7 @@ struct ParamTraits WriteParam(aMsg, aParam.mHasScrollgrab); WriteParam(aMsg, aParam.mUpdateScrollOffset); WriteParam(aMsg, aParam.mScrollGeneration); + WriteParam(aMsg, aParam.mTransformScale); WriteParam(aMsg, aParam.mExtraResolution); WriteParam(aMsg, aParam.mBackgroundColor); WriteParam(aMsg, aParam.mDoSmoothScroll); @@ -793,6 +794,7 @@ struct ParamTraits ReadParam(aMsg, aIter, &aResult->mHasScrollgrab) && ReadParam(aMsg, aIter, &aResult->mUpdateScrollOffset) && ReadParam(aMsg, aIter, &aResult->mScrollGeneration) && + ReadParam(aMsg, aIter, &aResult->mTransformScale) && ReadParam(aMsg, aIter, &aResult->mExtraResolution) && ReadParam(aMsg, aIter, &aResult->mBackgroundColor) && ReadParam(aMsg, aIter, &aResult->mDoSmoothScroll) && diff --git a/gfx/layers/FrameMetrics.h b/gfx/layers/FrameMetrics.h index 81fb646035fa..02bedfbaeb71 100644 --- a/gfx/layers/FrameMetrics.h +++ b/gfx/layers/FrameMetrics.h @@ -21,6 +21,38 @@ template struct ParamTraits; namespace mozilla { +// The layer coordinates of the parent layer. +// This can be arrived at in two ways: +// - Start with the CSS coordinates of the parent layer (note: NOT the +// CSS coordinates of the current layer, that will give you the wrong +// answer), multiply by the device scale and the resolutions of all +// layers from the root down to and including the parent. +// - Start with global screen coordinates and unapply all CSS and async +// transforms from the root down to and including the parent. +// It's helpful to look at https://wiki.mozilla.org/Platform/GFX/APZ#Coordinate_systems +// to get a picture of how the various coordinate systems relate to each other. +struct ParentLayerPixel {}; + +template<> struct IsPixel : TrueType {}; + +typedef gfx::MarginTyped ParentLayerMargin; +typedef gfx::PointTyped ParentLayerPoint; +typedef gfx::RectTyped ParentLayerRect; +typedef gfx::SizeTyped ParentLayerSize; + +typedef gfx::IntMarginTyped ParentLayerIntMargin; +typedef gfx::IntPointTyped ParentLayerIntPoint; +typedef gfx::IntRectTyped ParentLayerIntRect; +typedef gfx::IntSizeTyped ParentLayerIntSize; + +typedef gfx::ScaleFactor CSSToParentLayerScale; +typedef gfx::ScaleFactor LayoutDeviceToParentLayerScale; +typedef gfx::ScaleFactor ScreenToParentLayerScale; + +typedef gfx::ScaleFactor ParentLayerToLayerScale; +typedef gfx::ScaleFactor ParentLayerToScreenScale; + + namespace layers { /** @@ -46,6 +78,7 @@ public: , mScrollableRect(0, 0, 0, 0) , mPresShellResolution(1) , mCumulativeResolution(1) + , mTransformScale(1) , mDevPixelsPerCSSPixel(1) , mMayHaveTouchListeners(false) , mMayHaveTouchCaret(false) @@ -123,14 +156,14 @@ public: CSSToScreenScale DisplayportPixelsPerCSSPixel() const { - // Note: use 'mZoom * ParentLayerToLayerScale(1.0f)' as the CSS-to-Layer scale + // Note: use 'mZoom * ScreenToLayerScale(1.0f)' as the CSS-to-Layer scale // instead of LayersPixelsPerCSSPixel(), because displayport calculations // are done in the context of a repaint request, where we ask Layout to // repaint at a new resolution that includes any async zoom. Until this // repaint request is processed, LayersPixelsPerCSSPixel() does not yet // include the async zoom, but it will when the displayport is interpreted // for the repaint. - return mZoom * ParentLayerToLayerScale(1.0f) / mExtraResolution; + return mZoom * ScreenToLayerScale(1.0f) / mExtraResolution; } CSSToLayerScale LayersPixelsPerCSSPixel() const @@ -139,7 +172,7 @@ public: } // Get the amount by which this frame has been zoomed since the last repaint. - LayerToParentLayerScale GetAsyncZoom() const + LayerToScreenScale GetAsyncZoom() const { return mZoom / LayersPixelsPerCSSPixel(); } @@ -171,21 +204,31 @@ public: // Return the scale factor needed to fit the viewport // into its composition bounds. - CSSToParentLayerScale CalculateIntrinsicScale() const + CSSToScreenScale CalculateIntrinsicScale() const { - return CSSToParentLayerScale( + return CSSToScreenScale( std::max(mCompositionBounds.width / mViewport.width, mCompositionBounds.height / mViewport.height)); } + // Return the scale factor for converting from CSS pixels (for this layer) + // to layer pixels of our parent layer. Much as mZoom is used to interface + // between inputs we get in screen pixels and quantities in CSS pixels, + // this is used to interface between mCompositionBounds and quantities + // in CSS pixels. + CSSToParentLayerScale GetZoomToParent() const + { + return mZoom * mTransformScale; + } + CSSSize CalculateCompositedSizeInCssPixels() const { - return mCompositionBounds.Size() / GetZoom(); + return mCompositionBounds.Size() / GetZoomToParent(); } CSSRect CalculateCompositedRectInCssPixels() const { - return mCompositionBounds / GetZoom(); + return mCompositionBounds / GetZoomToParent(); } CSSSize CalculateBoundedCompositedSizeInCssPixels() const @@ -301,9 +344,7 @@ public: // user action, or choosing an initial zoom level on page load). This can // only be different from 1.0 for frames that are zoomable, which currently // is just the root content document's root scroll frame (mIsRoot = true). - // This is a plain float rather than a ScaleFactor because in and of itself - // it does not convert between any coordinate spaces for which we have names. - float mPresShellResolution; + ParentLayerToLayerScale mPresShellResolution; // The cumulative resolution that the current frame has been painted at. // This is the product of the pres-shell resolutions of the document @@ -311,6 +352,9 @@ public: // resolution. This information is provided by Gecko at layout/paint time. LayoutDeviceToLayerScale mCumulativeResolution; + // TODO(botond): This is now always 1 and should be removed (see bug 1055741). + ScreenToParentLayerScale mTransformScale; + // The conversion factor between CSS pixels and device pixels for this frame. // This can vary based on a variety of things, such as reflowing-zoom. The // conversion factor for device pixels to layers pixels is just the @@ -358,12 +402,12 @@ public: return mSmoothScrollOffset; } - void SetZoom(const CSSToParentLayerScale& aZoom) + void SetZoom(const CSSToScreenScale& aZoom) { mZoom = aZoom; } - CSSToParentLayerScale GetZoom() const + CSSToScreenScale GetZoom() const { return mZoom; } @@ -558,7 +602,7 @@ private: // but will be drawn to the screen at mZoom. In the steady state, the // two will be the same, but during an async zoom action the two may // diverge. This information is initialized in Gecko but updated in the APZC. - CSSToParentLayerScale mZoom; + CSSToScreenScale mZoom; // Whether mScrollOffset was updated by something other than the APZ code, and // if the APZC receiving this metrics should update its local copy. @@ -696,8 +740,8 @@ gfx::Log& operator<<(gfx::Log& log, const ScrollableLayerGui struct ZoomConstraints { bool mAllowZoom; bool mAllowDoubleTapZoom; - CSSToParentLayerScale mMinZoom; - CSSToParentLayerScale mMaxZoom; + CSSToScreenScale mMinZoom; + CSSToScreenScale mMaxZoom; ZoomConstraints() : mAllowZoom(true) @@ -708,8 +752,8 @@ struct ZoomConstraints { ZoomConstraints(bool aAllowZoom, bool aAllowDoubleTapZoom, - const CSSToParentLayerScale& aMinZoom, - const CSSToParentLayerScale& aMaxZoom) + const CSSToScreenScale& aMinZoom, + const CSSToScreenScale& aMaxZoom) : mAllowZoom(aAllowZoom) , mAllowDoubleTapZoom(aAllowDoubleTapZoom) , mMinZoom(aMinZoom) diff --git a/gfx/layers/LayersLogging.cpp b/gfx/layers/LayersLogging.cpp index 321ee54af98f..37708bf26d05 100644 --- a/gfx/layers/LayersLogging.cpp +++ b/gfx/layers/LayersLogging.cpp @@ -158,10 +158,10 @@ AppendToString(std::stringstream& aStream, const FrameMetrics& m, aStream << nsPrintfCString(" um=%d", m.GetUseDisplayPortMargins()).get(); AppendToString(aStream, m.GetRootCompositionSize(), " rcs="); AppendToString(aStream, m.GetViewport(), " v="); - aStream << nsPrintfCString(" z=(ld=%.3f r=%.3f cr=%.3f z=%.3f er=%.3f)", - m.mDevPixelsPerCSSPixel.scale, m.mPresShellResolution, + aStream << nsPrintfCString(" z=(ld=%.3f r=%.3f cr=%.3f z=%.3f ts=%.3f)", + m.mDevPixelsPerCSSPixel.scale, m.mPresShellResolution.scale, m.mCumulativeResolution.scale, m.GetZoom().scale, - m.GetExtraResolution().scale).get(); + m.mTransformScale.scale).get(); aStream << nsPrintfCString(" u=(%d %d %lu)", m.GetScrollOffsetUpdated(), m.GetDoSmoothScroll(), m.GetScrollGeneration()).get(); diff --git a/gfx/layers/apz/src/APZCTreeManager.cpp b/gfx/layers/apz/src/APZCTreeManager.cpp index da4b06f25dcd..f1373a67ed3c 100644 --- a/gfx/layers/apz/src/APZCTreeManager.cpp +++ b/gfx/layers/apz/src/APZCTreeManager.cpp @@ -64,7 +64,7 @@ struct APZCTreeManager::TreeBuildingState { /*static*/ const ScreenMargin APZCTreeManager::CalculatePendingDisplayPort( const FrameMetrics& aFrameMetrics, - const ParentLayerPoint& aVelocity, + const ScreenPoint& aVelocity, double aEstimatedPaintDuration) { return AsyncPanZoomController::CalculatePendingDisplayPort( @@ -204,8 +204,7 @@ ComputeTouchSensitiveRegion(GeckoContentController* aController, // this approximation may not be accurate in the presence of a css-driven // resolution. LayoutDeviceToParentLayerScale parentCumulativeResolution = - aMetrics.mCumulativeResolution - / ParentLayerToLayerScale(aMetrics.mPresShellResolution); + aMetrics.mCumulativeResolution / aMetrics.mPresShellResolution; visible = visible.Intersect(touchSensitiveRegion * aMetrics.mDevPixelsPerCSSPixel * parentCumulativeResolution); @@ -490,6 +489,36 @@ APZCTreeManager::UpdatePanZoomControllerTree(TreeBuildingState& aState, return aNextSibling; } +/*static*/ template void +ApplyTransform(gfx::PointTyped* aPoint, const Matrix4x4& aMatrix) +{ + Point result = aMatrix * aPoint->ToUnknownPoint(); + *aPoint = ViewAs(result); +} + +/*static*/ template void +ApplyTransform(gfx::IntPointTyped* aPoint, const Matrix4x4& aMatrix) +{ + Point result = aMatrix * aPoint->ToUnknownPoint(); + *aPoint = TruncatedToInt(ViewAs(result)); +} + +/*static*/ void +ApplyTransform(nsIntPoint* aPoint, const Matrix4x4& aMatrix) +{ + Point result = aMatrix * Point(aPoint->x, aPoint->y); + aPoint->x = NS_lround(result.x); + aPoint->y = NS_lround(result.y); +} + +/*static*/ template void +TransformScreenToGecko(T* aPoint, AsyncPanZoomController* aApzc, APZCTreeManager* aApzcTm) +{ + Matrix4x4 transformToApzc = aApzcTm->GetScreenToApzcTransform(aApzc); + Matrix4x4 transformToGecko = aApzcTm->GetApzcToGeckoTransform(aApzc); + ApplyTransform(aPoint, transformToApzc * transformToGecko); +} + nsEventStatus APZCTreeManager::ReceiveInputEvent(InputData& aEvent, ScrollableLayerGuid* aOutTargetGuid, @@ -513,53 +542,53 @@ APZCTreeManager::ReceiveInputEvent(InputData& aEvent, nsRefPtr apzc = GetTargetAPZC(panInput.mPanStartPoint, &inOverscrolledApzc); if (apzc) { + // When passing the event to the APZC, we need to apply a different + // transform than the one in TransformScreenToGecko, so we need to + // make a copy of the event. + PanGestureInput inputForApzc(panInput); transformToApzc = GetScreenToApzcTransform(apzc); - panInput.mLocalPanStartPoint = TransformTo( - transformToApzc, panInput.mPanStartPoint); - panInput.mLocalPanDisplacement = TransformVector( - transformToApzc, panInput.mPanDisplacement, panInput.mPanStartPoint); - result = mInputQueue->ReceiveInputEvent(apzc, panInput, aOutInputBlockId); + ApplyTransform(&(inputForApzc.mPanStartPoint), transformToApzc); + result = mInputQueue->ReceiveInputEvent(apzc, inputForApzc, aOutInputBlockId); // Update the out-parameters so they are what the caller expects. apzc->GetGuid(aOutTargetGuid); - Matrix4x4 transformToGecko = transformToApzc * GetApzcToGeckoTransform(apzc); - panInput.mPanStartPoint = TransformTo( - transformToGecko, panInput.mPanStartPoint); - panInput.mPanDisplacement = TransformVector( - transformToGecko, panInput.mPanDisplacement, panInput.mPanStartPoint); + TransformScreenToGecko(&(panInput.mPanStartPoint), apzc, this); } break; - } case PINCHGESTURE_INPUT: { // note: no one currently sends these + } case PINCHGESTURE_INPUT: { PinchGestureInput& pinchInput = aEvent.AsPinchGestureInput(); nsRefPtr apzc = GetTargetAPZC(pinchInput.mFocusPoint, &inOverscrolledApzc); if (apzc) { + // When passing the event to the APZC, we need to apply a different + // transform than the one in TransformScreenToGecko, so we need to + // make a copy of the event. + PinchGestureInput inputForApzc(pinchInput); transformToApzc = GetScreenToApzcTransform(apzc); - pinchInput.mLocalFocusPoint = TransformTo( - transformToApzc, pinchInput.mFocusPoint); - result = mInputQueue->ReceiveInputEvent(apzc, pinchInput, aOutInputBlockId); + ApplyTransform(&(inputForApzc.mFocusPoint), transformToApzc); + result = mInputQueue->ReceiveInputEvent(apzc, inputForApzc, aOutInputBlockId); // Update the out-parameters so they are what the caller expects. apzc->GetGuid(aOutTargetGuid); - Matrix4x4 outTransform = transformToApzc * GetApzcToGeckoTransform(apzc); - pinchInput.mFocusPoint = TransformTo( - outTransform, pinchInput.mFocusPoint); + TransformScreenToGecko(&(pinchInput.mFocusPoint), apzc, this); } break; - } case TAPGESTURE_INPUT: { // note: no one currently sends these + } case TAPGESTURE_INPUT: { TapGestureInput& tapInput = aEvent.AsTapGestureInput(); - nsRefPtr apzc = GetTargetAPZC(tapInput.mPoint, + nsRefPtr apzc = GetTargetAPZC(ScreenPoint(tapInput.mPoint), &inOverscrolledApzc); if (apzc) { + // When passing the event to the APZC, we need to apply a different + // transform than the one in TransformScreenToGecko, so we need to + // make a copy of the event. + TapGestureInput inputForApzc(tapInput); transformToApzc = GetScreenToApzcTransform(apzc); - tapInput.mLocalPoint = TransformTo( - transformToApzc, tapInput.mPoint); - result = mInputQueue->ReceiveInputEvent(apzc, tapInput, aOutInputBlockId); + ApplyTransform(&(inputForApzc.mPoint), transformToApzc); + result = mInputQueue->ReceiveInputEvent(apzc, inputForApzc, aOutInputBlockId); // Update the out-parameters so they are what the caller expects. apzc->GetGuid(aOutTargetGuid); - Matrix4x4 outTransform = transformToApzc * GetApzcToGeckoTransform(apzc); - tapInput.mPoint = TransformTo(outTransform, tapInput.mPoint); + TransformScreenToGecko(&(tapInput.mPoint), apzc, this); } break; } @@ -680,12 +709,11 @@ APZCTreeManager::ProcessTouchInput(MultiTouchInput& aInput, // This ensures that the sequence of touch points an APZC sees in an // input block are all in the same coordinate space. Matrix4x4 transformToApzc = mCachedTransformToApzcForInputBlock; - for (size_t i = 0; i < aInput.mTouches.Length(); i++) { - SingleTouchData& touchData = aInput.mTouches[i]; - touchData.mLocalScreenPoint = TransformTo( - transformToApzc, ScreenPoint(touchData.mScreenPoint)); + MultiTouchInput inputForApzc(aInput); + for (size_t i = 0; i < inputForApzc.mTouches.Length(); i++) { + ApplyTransform(&(inputForApzc.mTouches[i].mScreenPoint), transformToApzc); } - result = mInputQueue->ReceiveInputEvent(mApzcForInputBlock, aInput, aOutInputBlockId); + result = mInputQueue->ReceiveInputEvent(mApzcForInputBlock, inputForApzc, aOutInputBlockId); // For computing the event to pass back to Gecko, use the up-to-date transforms. // This ensures that transformToApzc and transformToGecko are in sync @@ -694,9 +722,7 @@ APZCTreeManager::ProcessTouchInput(MultiTouchInput& aInput, Matrix4x4 transformToGecko = GetApzcToGeckoTransform(mApzcForInputBlock); Matrix4x4 outTransform = transformToApzc * transformToGecko; for (size_t i = 0; i < aInput.mTouches.Length(); i++) { - SingleTouchData& touchData = aInput.mTouches[i]; - touchData.mScreenPoint = TransformTo( - outTransform, touchData.mScreenPoint); + ApplyTransform(&(aInput.mTouches[i].mScreenPoint), outTransform); } } if (mInOverscrolledApzc) { @@ -758,7 +784,7 @@ APZCTreeManager::ProcessEvent(WidgetInputEvent& aEvent, Matrix4x4 transformToApzc = GetScreenToApzcTransform(apzc); Matrix4x4 transformToGecko = GetApzcToGeckoTransform(apzc); Matrix4x4 outTransform = transformToApzc * transformToGecko; - aEvent.refPoint = TransformTo(outTransform, aEvent.refPoint); + ApplyTransform(&(aEvent.refPoint), outTransform); } if (inOverscrolledApzc) { result = nsEventStatus_eConsumeNoDefault; @@ -887,8 +913,8 @@ APZCTreeManager::ClearTree() } /** - * Transform a displacement from the ParentLayer coordinates of a source APZC - * to the ParentLayer coordinates of a target APZC. + * Transform a displacement from the screen coordinates of a source APZC to + * the screen coordinates of a target APZC. * @param aTreeManager the tree manager for the APZC tree containing |aSource| * and |aTarget| * @param aSource the source APZC @@ -900,23 +926,23 @@ static void TransformDisplacement(APZCTreeManager* aTreeManager, AsyncPanZoomController* aSource, AsyncPanZoomController* aTarget, - ParentLayerPoint& aStartPoint, - ParentLayerPoint& aEndPoint) { - // Convert start and end points to Screen coordinates. + ScreenPoint& aStartPoint, + ScreenPoint& aEndPoint) { + // Convert start and end points to untransformed screen coordinates. Matrix4x4 untransformToApzc = aTreeManager->GetScreenToApzcTransform(aSource).Inverse(); - ScreenPoint screenStart = TransformTo(untransformToApzc, aStartPoint); - ScreenPoint screenEnd = TransformTo(untransformToApzc, aEndPoint); + ApplyTransform(&aStartPoint, untransformToApzc); + ApplyTransform(&aEndPoint, untransformToApzc); - // Convert start and end points to aTarget's ParentLayer coordinates. + // Convert start and end points to aTarget's transformed screen coordinates. Matrix4x4 transformToApzc = aTreeManager->GetScreenToApzcTransform(aTarget); - aStartPoint = TransformTo(transformToApzc, screenStart); - aEndPoint = TransformTo(transformToApzc, screenEnd); + ApplyTransform(&aStartPoint, transformToApzc); + ApplyTransform(&aEndPoint, transformToApzc); } bool APZCTreeManager::DispatchScroll(AsyncPanZoomController* aPrev, - ParentLayerPoint aStartPoint, - ParentLayerPoint aEndPoint, + ScreenPoint aStartPoint, + ScreenPoint aEndPoint, OverscrollHandoffState& aOverscrollHandoffState) { const OverscrollHandoffChain& overscrollHandoffChain = aOverscrollHandoffState.mChain; @@ -951,14 +977,14 @@ APZCTreeManager::DispatchScroll(AsyncPanZoomController* aPrev, bool APZCTreeManager::DispatchFling(AsyncPanZoomController* aPrev, - ParentLayerPoint aVelocity, + ScreenPoint aVelocity, nsRefPtr aOverscrollHandoffChain, bool aHandoff) { nsRefPtr current; uint32_t aOverscrollHandoffChainLength = aOverscrollHandoffChain->Length(); uint32_t startIndex; - + // The fling's velocity needs to be transformed from the screen coordinates // of |aPrev| to the screen coordinates of |next|. To transform a velocity // correctly, we need to convert it to a displacement. For now, we do this @@ -966,13 +992,13 @@ APZCTreeManager::DispatchFling(AsyncPanZoomController* aPrev, // TODO: For this to be correct in the presence of 3D transforms, we should // use the end point of the touch that started the fling as the start point // rather than (0, 0). - ParentLayerPoint startPoint; // (0, 0) - ParentLayerPoint endPoint; - ParentLayerPoint transformedVelocity = aVelocity; - + ScreenPoint startPoint; // (0, 0) + ScreenPoint endPoint; + ScreenPoint transformedVelocity = aVelocity; + if (aHandoff) { startIndex = aOverscrollHandoffChain->IndexOf(aPrev) + 1; - + // IndexOf will return aOverscrollHandoffChain->Length() if // |aPrev| is not found. if (startIndex >= aOverscrollHandoffChainLength) { @@ -981,17 +1007,17 @@ APZCTreeManager::DispatchFling(AsyncPanZoomController* aPrev, } else { startIndex = 0; } - + for (; startIndex < aOverscrollHandoffChainLength; startIndex++) { current = aOverscrollHandoffChain->GetApzcAtIndex(startIndex); - + // Make sure the apcz about to be handled can be handled if (current == nullptr || current->IsDestroyed()) { return false; } - + endPoint = startPoint + transformedVelocity; - + // Only transform when current apcz can be transformed with previous if (startIndex > 0) { TransformDisplacement(this, @@ -1000,9 +1026,9 @@ APZCTreeManager::DispatchFling(AsyncPanZoomController* aPrev, startPoint, endPoint); } - + transformedVelocity = endPoint - startPoint; - + bool handoff = (startIndex < 1) ? aHandoff : true; if (current->AttemptFling(transformedVelocity, aOverscrollHandoffChain, @@ -1010,7 +1036,7 @@ APZCTreeManager::DispatchFling(AsyncPanZoomController* aPrev, return true; } } - + return false; } diff --git a/gfx/layers/apz/src/APZCTreeManager.h b/gfx/layers/apz/src/APZCTreeManager.h index d6776267c7f5..16c34f4ab84a 100644 --- a/gfx/layers/apz/src/APZCTreeManager.h +++ b/gfx/layers/apz/src/APZCTreeManager.h @@ -247,7 +247,7 @@ public: */ static const ScreenMargin CalculatePendingDisplayPort( const FrameMetrics& aFrameMetrics, - const ParentLayerPoint& aVelocity, + const ScreenPoint& aVelocity, double aEstimatedPaintDuration); /** @@ -327,8 +327,8 @@ public: * a fling, use DispatchFling(). */ bool DispatchScroll(AsyncPanZoomController* aApzc, - ParentLayerPoint aStartPoint, - ParentLayerPoint aEndPoint, + ScreenPoint aStartPoint, + ScreenPoint aEndPoint, OverscrollHandoffState& aOverscrollHandoffState); /** @@ -353,7 +353,7 @@ public: * the excess fling itself by going into an overscroll fling. */ bool DispatchFling(AsyncPanZoomController* aApzc, - ParentLayerPoint aVelocity, + ScreenPoint aVelocity, nsRefPtr aOverscrollHandoffChain, bool aHandoff); diff --git a/gfx/layers/apz/src/AsyncPanZoomController.cpp b/gfx/layers/apz/src/AsyncPanZoomController.cpp index d9824ac12128..a8f85334b9e0 100644 --- a/gfx/layers/apz/src/AsyncPanZoomController.cpp +++ b/gfx/layers/apz/src/AsyncPanZoomController.cpp @@ -135,7 +135,6 @@ typedef mozilla::layers::AllowedTouchBehavior AllowedTouchBehavior; typedef GeckoContentController::APZStateChange APZStateChange; typedef mozilla::gfx::Point Point; typedef mozilla::gfx::Matrix4x4 Matrix4x4; -using mozilla::gfx::PointTyped; /** * \page APZCPrefs APZ preferences @@ -390,12 +389,12 @@ StaticAutoPtr gVelocityCurveFunction; /** * Maximum zoom amount, always used, even if a page asks for higher. */ -static const CSSToParentLayerScale MAX_ZOOM(8.0f); +static const CSSToScreenScale MAX_ZOOM(8.0f); /** * Minimum zoom amount, always used, even if a page asks for lower. */ -static const CSSToParentLayerScale MIN_ZOOM(0.125f); +static const CSSToScreenScale MIN_ZOOM(0.125f); /** * Is aAngle within the given threshold of the horizontal axis? @@ -498,7 +497,7 @@ public: } } - ParentLayerPoint velocity = mApzc.GetVelocityVector(); + ScreenPoint velocity(mApzc.mX.GetVelocity(), mApzc.mY.GetVelocity()); // If the last fling was very recent and in the same direction as this one, // boost the velocity to be the sum of the two. Check separate axes separately @@ -571,18 +570,18 @@ public: // AdjustDisplacement() zeroes out the Axis velocity if we're in overscroll. // Since we need to hand off the velocity to the tree manager in such a case, - // we save it here. Would be ParentLayerVector instead of ParentLayerPoint - // if we had vector classes. - ParentLayerPoint velocity = mApzc.GetVelocityVector(); + // we save it here. Would be ScreenVector instead of ScreenPoint if we had + // vector classes. + ScreenPoint velocity(mApzc.mX.GetVelocity(), mApzc.mY.GetVelocity()); - ParentLayerPoint offset = velocity * aDelta.ToMilliseconds(); + ScreenPoint offset = velocity * aDelta.ToMilliseconds(); // Ordinarily we might need to do a ScheduleComposite if either of // the following AdjustDisplacement calls returns true, but this // is already running as part of a FlingAnimation, so we'll be compositing // per frame of animation anyway. - ParentLayerPoint overscroll; - ParentLayerPoint adjustedOffset; + ScreenPoint overscroll; + ScreenPoint adjustedOffset; mApzc.mX.AdjustDisplacement(offset.x, adjustedOffset.x, overscroll.x); mApzc.mY.AdjustDisplacement(offset.y, adjustedOffset.y, overscroll.y); @@ -646,8 +645,8 @@ private: class ZoomAnimation: public AsyncPanZoomAnimation { public: - ZoomAnimation(CSSPoint aStartOffset, CSSToParentLayerScale aStartZoom, - CSSPoint aEndOffset, CSSToParentLayerScale aEndZoom) + ZoomAnimation(CSSPoint aStartOffset, CSSToScreenScale aStartZoom, + CSSPoint aEndOffset, CSSToScreenScale aEndZoom) : mTotalDuration(TimeDuration::FromMilliseconds(gfxPrefs::APZZoomAnimationDuration())) , mStartOffset(aStartOffset) , mStartZoom(aStartZoom) @@ -673,7 +672,7 @@ public: // We scale the scrollOffset linearly with sampledPosition, so the zoom // needs to scale inversely to match. - aFrameMetrics.SetZoom(CSSToParentLayerScale(1 / + aFrameMetrics.SetZoom(CSSToScreenScale(1 / (sampledPosition / mEndZoom.scale + (1 - sampledPosition) / mStartZoom.scale))); @@ -694,18 +693,18 @@ private: // interpolate between the start and end frames. We only use the // |mViewportScrollOffset| and |mResolution| fields on this. CSSPoint mStartOffset; - CSSToParentLayerScale mStartZoom; + CSSToScreenScale mStartZoom; // Target metrics for a zoom to animation. This is only valid when we are in // the "ANIMATED_ZOOM" state. We only use the |mViewportScrollOffset| and // |mResolution| fields on this. CSSPoint mEndOffset; - CSSToParentLayerScale mEndZoom; + CSSToScreenScale mEndZoom; }; class OverscrollAnimation: public AsyncPanZoomAnimation { public: - explicit OverscrollAnimation(AsyncPanZoomController& aApzc, const ParentLayerPoint& aVelocity) + explicit OverscrollAnimation(AsyncPanZoomController& aApzc, const ScreenPoint& aVelocity) : mApzc(aApzc) { mApzc.mX.SetVelocity(aVelocity.x); @@ -766,7 +765,7 @@ public: mYAxisModel.GetVelocity())); // Convert from points/second to points/ms - ParentLayerPoint velocity = ParentLayerPoint(css_velocity.x, css_velocity.y) / 1000.0f; + ScreenPoint velocity = ScreenPoint(css_velocity.x, css_velocity.y) / 1000.0f; // Keep the velocity updated for the Axis class so that any animations // chained off of the smooth scroll will inherit it. @@ -782,11 +781,11 @@ public: } // If we overscroll, hand off to a fling animation that will complete the // spring back. - CSSToParentLayerScale zoom = aFrameMetrics.GetZoom(); - ParentLayerPoint displacement = (position - aFrameMetrics.GetScrollOffset()) * zoom; + CSSToScreenScale zoom = aFrameMetrics.GetZoom(); + ScreenPoint displacement = (position - aFrameMetrics.GetScrollOffset()) * zoom; - ParentLayerPoint overscroll; - ParentLayerPoint adjustedOffset; + ScreenPoint overscroll; + ScreenPoint adjustedOffset; mApzc.mX.AdjustDisplacement(displacement.x, adjustedOffset.x, overscroll.x); mApzc.mY.AdjustDisplacement(displacement.y, adjustedOffset.y, overscroll.y); @@ -1005,7 +1004,7 @@ AsyncPanZoomController::IsDestroyed() const return mTreeManager == nullptr; } -/* static */ScreenCoord +/* static */float AsyncPanZoomController::GetTouchStartTolerance() { return (gfxPrefs::APZTouchStartTolerance() * APZCTreeManager::GetDPI()); @@ -1132,7 +1131,7 @@ nsEventStatus AsyncPanZoomController::HandleGestureEvent(const InputData& aEvent nsEventStatus AsyncPanZoomController::OnTouchStart(const MultiTouchInput& aEvent) { APZC_LOG("%p got a touch-start in state %d\n", this, mState); mPanDirRestricted = false; - ParentLayerPoint point = GetFirstTouchPoint(aEvent); + ScreenPoint point = GetFirstTouchScreenPoint(aEvent); switch (mState) { case FLING: @@ -1186,7 +1185,7 @@ nsEventStatus AsyncPanZoomController::OnTouchMove(const MultiTouchInput& aEvent) return nsEventStatus_eIgnore; case TOUCHING: { - ScreenCoord panThreshold = GetTouchStartTolerance(); + float panThreshold = GetTouchStartTolerance(); UpdateWithTouchAtDevicePoint(aEvent); if (PanDistance() < panThreshold) { @@ -1271,7 +1270,7 @@ nsEventStatus AsyncPanZoomController::OnTouchEnd(const MultiTouchInput& aEvent) CurrentTouchBlock()->GetOverscrollHandoffChain()->FlushRepaints(); mX.EndTouch(aEvent.mTime); mY.EndTouch(aEvent.mTime); - ParentLayerPoint flingVelocity = GetVelocityVector(); + ScreenPoint flingVelocity(mX.GetVelocity(), mY.GetVelocity()); // Clear our velocities; if DispatchFling() gives the fling to us, // the fling velocity gets *added* to our existing velocity in // AcceptFling(). @@ -1335,7 +1334,7 @@ nsEventStatus AsyncPanZoomController::OnScaleBegin(const PinchGestureInput& aEve } SetState(PINCHING); - mLastZoomFocus = aEvent.mLocalFocusPoint - mFrameMetrics.mCompositionBounds.TopLeft(); + mLastZoomFocus = ToParentLayerCoords(aEvent.mFocusPoint) - mFrameMetrics.mCompositionBounds.TopLeft(); return nsEventStatus_eConsumeNoDefault; } @@ -1362,9 +1361,9 @@ nsEventStatus AsyncPanZoomController::OnScale(const PinchGestureInput& aEvent) { { ReentrantMonitorAutoEnter lock(mMonitor); - CSSToParentLayerScale userZoom = mFrameMetrics.GetZoom(); - ParentLayerPoint focusPoint = aEvent.mLocalFocusPoint - mFrameMetrics.mCompositionBounds.TopLeft(); - CSSPoint cssFocusPoint = focusPoint / mFrameMetrics.GetZoom(); + CSSToParentLayerScale userZoom = mFrameMetrics.GetZoomToParent(); + ParentLayerPoint focusPoint = ToParentLayerCoords(aEvent.mFocusPoint) - mFrameMetrics.mCompositionBounds.TopLeft(); + CSSPoint cssFocusPoint = focusPoint / mFrameMetrics.GetZoomToParent(); CSSPoint focusChange = (mLastZoomFocus - focusPoint) / userZoom; // If displacing by the change in focus point will take us off page bounds, @@ -1378,8 +1377,8 @@ nsEventStatus AsyncPanZoomController::OnScale(const PinchGestureInput& aEvent) { // either axis such that we don't overscroll the boundaries when zooming. CSSPoint neededDisplacement; - CSSToParentLayerScale realMinZoom = mZoomConstraints.mMinZoom; - CSSToParentLayerScale realMaxZoom = mZoomConstraints.mMaxZoom; + CSSToParentLayerScale realMinZoom = mZoomConstraints.mMinZoom * mFrameMetrics.mTransformScale; + CSSToParentLayerScale realMaxZoom = mZoomConstraints.mMaxZoom * mFrameMetrics.mTransformScale; realMinZoom.scale = std::max(realMinZoom.scale, mFrameMetrics.mCompositionBounds.width / mFrameMetrics.mScrollableRect.width); realMinZoom.scale = std::max(realMinZoom.scale, @@ -1454,13 +1453,14 @@ nsEventStatus AsyncPanZoomController::OnScaleEnd(const PinchGestureInput& aEvent } bool -AsyncPanZoomController::ConvertToGecko(const ParentLayerPoint& aPoint, CSSPoint* aOut) +AsyncPanZoomController::ConvertToGecko(const ScreenPoint& aPoint, CSSPoint* aOut) { if (APZCTreeManager* treeManagerLocal = GetApzcTreeManager()) { Matrix4x4 transformToGecko = treeManagerLocal->GetApzcToGeckoTransform(this); + Point result = transformToGecko * Point(aPoint.x, aPoint.y); // NOTE: This isn't *quite* LayoutDevicePoint, we just don't have a name // for this coordinate space and it maps the closest to LayoutDevicePoint. - LayoutDevicePoint layoutPoint = TransformTo(transformToGecko, aPoint); + LayoutDevicePoint layoutPoint = LayoutDevicePoint(result.x, result.y); { // scoped lock to access mFrameMetrics ReentrantMonitorAutoEnter lock(mMonitor); *aOut = layoutPoint / mFrameMetrics.mDevPixelsPerCSSPixel; @@ -1473,8 +1473,8 @@ AsyncPanZoomController::ConvertToGecko(const ParentLayerPoint& aPoint, CSSPoint* nsEventStatus AsyncPanZoomController::OnPanMayBegin(const PanGestureInput& aEvent) { APZC_LOG("%p got a pan-maybegin in state %d\n", this, mState); - mX.StartTouch(aEvent.mLocalPanStartPoint.x, aEvent.mTime); - mY.StartTouch(aEvent.mLocalPanStartPoint.y, aEvent.mTime); + mX.StartTouch(aEvent.mPanStartPoint.x, aEvent.mTime); + mY.StartTouch(aEvent.mPanStartPoint.y, aEvent.mTime); if (mPanGestureState) { mPanGestureState->GetOverscrollHandoffChain()->CancelAnimations(); } else { @@ -1504,8 +1504,8 @@ nsEventStatus AsyncPanZoomController::OnPanBegin(const PanGestureInput& aEvent) mPanGestureState = MakeUnique(this); - mX.StartTouch(aEvent.mLocalPanStartPoint.x, aEvent.mTime); - mY.StartTouch(aEvent.mLocalPanStartPoint.y, aEvent.mTime); + mX.StartTouch(aEvent.mPanStartPoint.x, aEvent.mTime); + mY.StartTouch(aEvent.mPanStartPoint.y, aEvent.mTime); if (GetAxisLockMode() == FREE) { SetState(PANNING); @@ -1542,18 +1542,19 @@ nsEventStatus AsyncPanZoomController::OnPan(const PanGestureInput& aEvent, bool // size and position. We need to do so even if this is a momentum pan (i.e. // aFingersOnTouchpad == false); in that case the "with touch" part is not // really appropriate, so we may want to rethink this at some point. - mX.UpdateWithTouchAtDevicePoint(aEvent.mLocalPanStartPoint.x, aEvent.mTime); - mY.UpdateWithTouchAtDevicePoint(aEvent.mLocalPanStartPoint.y, aEvent.mTime); + mX.UpdateWithTouchAtDevicePoint(aEvent.mPanStartPoint.x, aEvent.mTime); + mY.UpdateWithTouchAtDevicePoint(aEvent.mPanStartPoint.y, aEvent.mTime); - HandlePanningUpdate(aEvent.mPanDisplacement); + ScreenPoint panDisplacement = aEvent.mPanDisplacement; + ToGlobalScreenCoordinates(&panDisplacement, aEvent.mPanStartPoint); + HandlePanningUpdate(panDisplacement); // TODO: Handle pan events sent without pan begin / pan end events properly. if (mPanGestureState) { - ScreenPoint panDistance(fabs(aEvent.mPanDisplacement.x), fabs(aEvent.mPanDisplacement.y)); + ScreenPoint panDistance(fabs(panDisplacement.x), fabs(panDisplacement.y)); OverscrollHandoffState handoffState( *mPanGestureState->GetOverscrollHandoffChain(), panDistance); - CallDispatchScroll(aEvent.mLocalPanStartPoint, - aEvent.mLocalPanStartPoint + aEvent.mLocalPanDisplacement, + CallDispatchScroll(aEvent.mPanStartPoint, aEvent.mPanStartPoint + aEvent.mPanDisplacement, handoffState); } @@ -1607,7 +1608,7 @@ nsEventStatus AsyncPanZoomController::OnLongPress(const TapGestureInput& aEvent) if (controller) { int32_t modifiers = WidgetModifiersToDOMModifiers(aEvent.modifiers); CSSPoint geckoScreenPoint; - if (ConvertToGecko(aEvent.mLocalPoint, &geckoScreenPoint)) { + if (ConvertToGecko(aEvent.mPoint, &geckoScreenPoint)) { uint64_t blockId = GetInputQueue()->InjectNewTouchBlock(this); controller->HandleLongTap(geckoScreenPoint, modifiers, GetGuid(), blockId); return nsEventStatus_eConsumeNoDefault; @@ -1622,7 +1623,7 @@ nsEventStatus AsyncPanZoomController::OnLongPressUp(const TapGestureInput& aEven if (controller) { int32_t modifiers = WidgetModifiersToDOMModifiers(aEvent.modifiers); CSSPoint geckoScreenPoint; - if (ConvertToGecko(aEvent.mLocalPoint, &geckoScreenPoint)) { + if (ConvertToGecko(aEvent.mPoint, &geckoScreenPoint)) { controller->HandleLongTapUp(geckoScreenPoint, modifiers, GetGuid()); return nsEventStatus_eConsumeNoDefault; } @@ -1630,7 +1631,7 @@ nsEventStatus AsyncPanZoomController::OnLongPressUp(const TapGestureInput& aEven return nsEventStatus_eIgnore; } -nsEventStatus AsyncPanZoomController::GenerateSingleTap(const ParentLayerPoint& aPoint, mozilla::Modifiers aModifiers) { +nsEventStatus AsyncPanZoomController::GenerateSingleTap(const ScreenIntPoint& aPoint, mozilla::Modifiers aModifiers) { nsRefPtr controller = GetGeckoContentController(); if (controller) { CSSPoint geckoScreenPoint; @@ -1666,14 +1667,14 @@ nsEventStatus AsyncPanZoomController::OnSingleTapUp(const TapGestureInput& aEven // If mZoomConstraints.mAllowDoubleTapZoom is true we wait for a call to OnSingleTapConfirmed before // sending event to content if (!(mZoomConstraints.mAllowDoubleTapZoom && CurrentTouchBlock()->TouchActionAllowsDoubleTapZoom())) { - return GenerateSingleTap(aEvent.mLocalPoint, aEvent.modifiers); + return GenerateSingleTap(aEvent.mPoint, aEvent.modifiers); } return nsEventStatus_eIgnore; } nsEventStatus AsyncPanZoomController::OnSingleTapConfirmed(const TapGestureInput& aEvent) { APZC_LOG("%p got a single-tap-confirmed in state %d\n", this, mState); - return GenerateSingleTap(aEvent.mLocalPoint, aEvent.modifiers); + return GenerateSingleTap(aEvent.mPoint, aEvent.modifiers); } nsEventStatus AsyncPanZoomController::OnDoubleTap(const TapGestureInput& aEvent) { @@ -1683,7 +1684,7 @@ nsEventStatus AsyncPanZoomController::OnDoubleTap(const TapGestureInput& aEvent) if (mZoomConstraints.mAllowDoubleTapZoom && CurrentTouchBlock()->TouchActionAllowsDoubleTapZoom()) { int32_t modifiers = WidgetModifiersToDOMModifiers(aEvent.modifiers); CSSPoint geckoScreenPoint; - if (ConvertToGecko(aEvent.mLocalPoint, &geckoScreenPoint)) { + if (ConvertToGecko(aEvent.mPoint, &geckoScreenPoint)) { controller->HandleDoubleTap(geckoScreenPoint, modifiers, GetGuid()); } } @@ -1698,42 +1699,52 @@ nsEventStatus AsyncPanZoomController::OnCancelTap(const TapGestureInput& aEvent) return nsEventStatus_eIgnore; } +// Helper function for To[Global|Local]ScreenCoordinates(). +// TODO(botond): Generalize this into a template function in UnitTransforms.h. +static void TransformVector(const Matrix4x4& aTransform, + ScreenPoint* aVector, + const ScreenPoint& aAnchor) { + ScreenPoint start = aAnchor; + ScreenPoint end = aAnchor + *aVector; + start = TransformTo(aTransform, start); + end = TransformTo(aTransform, end); + *aVector = end - start; +} -ScreenPoint AsyncPanZoomController::ToScreenCoordinates(const ParentLayerPoint& aVector, - const ParentLayerPoint& aAnchor) const { +void AsyncPanZoomController::ToGlobalScreenCoordinates(ScreenPoint* aVector, + const ScreenPoint& aAnchor) const { if (APZCTreeManager* treeManagerLocal = GetApzcTreeManager()) { Matrix4x4 apzcToScreen = treeManagerLocal->GetScreenToApzcTransform(this).Inverse(); - return TransformVector(apzcToScreen, aVector, aAnchor); + TransformVector(apzcToScreen, aVector, aAnchor); } - return ViewAs(aVector, PixelCastJustification::TransformNotAvailable); } -ParentLayerPoint AsyncPanZoomController::ToParentLayerCoordinates(const ScreenPoint& aVector, - const ScreenPoint& aAnchor) const { +void AsyncPanZoomController::ToLocalScreenCoordinates(ScreenPoint* aVector, + const ScreenPoint& aAnchor) const { if (APZCTreeManager* treeManagerLocal = GetApzcTreeManager()) { Matrix4x4 transform = treeManagerLocal->GetScreenToApzcTransform(this); - return TransformVector(transform, aVector, aAnchor); + TransformVector(transform, aVector, aAnchor); } - return ViewAs(aVector, PixelCastJustification::TransformNotAvailable); } -ScreenCoord AsyncPanZoomController::PanDistance() const { - ParentLayerPoint panVector; - ParentLayerPoint panStart; +float AsyncPanZoomController::PanDistance() const { + ScreenPoint panVector; + ScreenPoint panStart; { ReentrantMonitorAutoEnter lock(mMonitor); - panVector = ParentLayerPoint(mX.PanDistance(), mY.PanDistance()); + panVector = ScreenPoint(mX.PanDistance(), mY.PanDistance()); panStart = PanStart(); } - return ToScreenCoordinates(panVector, panStart).Length(); + ToGlobalScreenCoordinates(&panVector, panStart); + return NS_hypot(panVector.x, panVector.y); } -ParentLayerPoint AsyncPanZoomController::PanStart() const { - return ParentLayerPoint(mX.PanStart(), mY.PanStart()); +ScreenPoint AsyncPanZoomController::PanStart() const { + return ScreenPoint(mX.PanStart(), mY.PanStart()); } -const ParentLayerPoint AsyncPanZoomController::GetVelocityVector() const { - return ParentLayerPoint(mX.GetVelocity(), mY.GetVelocity()); +const ScreenPoint AsyncPanZoomController::GetVelocityVector() const { + return ScreenPoint(mX.GetVelocity(), mY.GetVelocity()); } void AsyncPanZoomController::HandlePanningWithTouchAction(double aAngle) { @@ -1833,7 +1844,7 @@ void AsyncPanZoomController::HandlePanningUpdate(const ScreenPoint& aPanDistance nsEventStatus AsyncPanZoomController::StartPanning(const MultiTouchInput& aEvent) { ReentrantMonitorAutoEnter lock(mMonitor); - ParentLayerPoint point = GetFirstTouchPoint(aEvent); + ScreenPoint point = GetFirstTouchScreenPoint(aEvent); float dx = mX.PanDistance(point.x); float dy = mY.PanDistance(point.y); @@ -1866,25 +1877,25 @@ nsEventStatus AsyncPanZoomController::StartPanning(const MultiTouchInput& aEvent } void AsyncPanZoomController::UpdateWithTouchAtDevicePoint(const MultiTouchInput& aEvent) { - ParentLayerPoint point = GetFirstTouchPoint(aEvent); + ScreenPoint point = GetFirstTouchScreenPoint(aEvent); mX.UpdateWithTouchAtDevicePoint(point.x, aEvent.mTime); mY.UpdateWithTouchAtDevicePoint(point.y, aEvent.mTime); } -bool AsyncPanZoomController::AttemptScroll(const ParentLayerPoint& aStartPoint, - const ParentLayerPoint& aEndPoint, +bool AsyncPanZoomController::AttemptScroll(const ScreenPoint& aStartPoint, + const ScreenPoint& aEndPoint, OverscrollHandoffState& aOverscrollHandoffState) { // "start - end" rather than "end - start" because e.g. moving your finger // down (*positive* direction along y axis) causes the vertical scroll offset // to *decrease* as the page follows your finger. - ParentLayerPoint displacement = aStartPoint - aEndPoint; + ScreenPoint displacement = aStartPoint - aEndPoint; - ParentLayerPoint overscroll; // will be used outside monitor block + ScreenPoint overscroll; // will be used outside monitor block { ReentrantMonitorAutoEnter lock(mMonitor); - ParentLayerPoint adjustedDisplacement; + ScreenPoint adjustedDisplacement; bool xChanged = mX.AdjustDisplacement(displacement.x, adjustedDisplacement.x, overscroll.x); bool yChanged = mY.AdjustDisplacement(displacement.y, adjustedDisplacement.y, overscroll.y); if (xChanged || yChanged) { @@ -1921,7 +1932,7 @@ bool AsyncPanZoomController::AttemptScroll(const ParentLayerPoint& aStartPoint, return OverscrollForPanning(overscroll, aOverscrollHandoffState.mPanDistance); } -bool AsyncPanZoomController::OverscrollForPanning(ParentLayerPoint aOverscroll, +bool AsyncPanZoomController::OverscrollForPanning(ScreenPoint aOverscroll, const ScreenPoint& aPanDistance) { // Only allow entering overscroll along an axis if the pan distance along // that axis is greater than the pan distance along the other axis by a @@ -1938,7 +1949,7 @@ bool AsyncPanZoomController::OverscrollForPanning(ParentLayerPoint aOverscroll, return OverscrollBy(aOverscroll); } -bool AsyncPanZoomController::OverscrollBy(const ParentLayerPoint& aOverscroll) { +bool AsyncPanZoomController::OverscrollBy(const ScreenPoint& aOverscroll) { if (!gfxPrefs::APZOverscrollEnabled()) { return false; } @@ -1975,7 +1986,7 @@ nsRefPtr AsyncPanZoomController::BuildOverscrollHa return result; } -void AsyncPanZoomController::AcceptFling(const ParentLayerPoint& aVelocity, +void AsyncPanZoomController::AcceptFling(const ScreenPoint& aVelocity, const nsRefPtr& aOverscrollHandoffChain, bool aHandoff) { // We may have a pre-existing velocity for whatever reason (for example, @@ -1988,7 +1999,7 @@ void AsyncPanZoomController::AcceptFling(const ParentLayerPoint& aVelocity, !aHandoff)); // only apply acceleration if this is an initial fling } -bool AsyncPanZoomController::AttemptFling(ParentLayerPoint aVelocity, +bool AsyncPanZoomController::AttemptFling(ScreenPoint aVelocity, const nsRefPtr& aOverscrollHandoffChain, bool aHandoff) { // If we are pannable, take over the fling ourselves. @@ -2002,7 +2013,7 @@ bool AsyncPanZoomController::AttemptFling(ParentLayerPoint aVelocity, return false; } -void AsyncPanZoomController::HandleFlingOverscroll(const ParentLayerPoint& aVelocity, +void AsyncPanZoomController::HandleFlingOverscroll(const ScreenPoint& aVelocity, const nsRefPtr& aOverscrollHandoffChain) { APZCTreeManager* treeManagerLocal = GetApzcTreeManager(); if (!(treeManagerLocal && treeManagerLocal->DispatchFling(this, @@ -2017,7 +2028,7 @@ void AsyncPanZoomController::HandleFlingOverscroll(const ParentLayerPoint& aVelo } } -void AsyncPanZoomController::HandleSmoothScrollOverscroll(const ParentLayerPoint& aVelocity) { +void AsyncPanZoomController::HandleSmoothScrollOverscroll(const ScreenPoint& aVelocity) { // We must call BuildOverscrollHandoffChain from this deferred callback // function in order to avoid a deadlock when acquiring the tree lock. HandleFlingOverscroll(aVelocity, BuildOverscrollHandoffChain()); @@ -2026,7 +2037,7 @@ void AsyncPanZoomController::HandleSmoothScrollOverscroll(const ParentLayerPoint void AsyncPanZoomController::StartSmoothScroll() { SetState(SMOOTH_SCROLL); nsPoint initialPosition = CSSPoint::ToAppUnits(mFrameMetrics.GetScrollOffset()); - // Cast velocity from ParentLayerPoints/ms to CSSPoints/ms then convert to + // Cast velocity from ScreenPoints/ms to CSSPoints/ms then convert to // appunits/second nsPoint initialVelocity = CSSPoint::ToAppUnits(CSSPoint(mX.GetVelocity(), mY.GetVelocity())) * 1000.0f; @@ -2039,13 +2050,13 @@ void AsyncPanZoomController::StartSmoothScroll() { gfxPrefs::ScrollBehaviorDampingRatio())); } -void AsyncPanZoomController::StartOverscrollAnimation(const ParentLayerPoint& aVelocity) { +void AsyncPanZoomController::StartOverscrollAnimation(const ScreenPoint& aVelocity) { SetState(OVERSCROLL_ANIMATION); StartAnimation(new OverscrollAnimation(*this, aVelocity)); } -bool AsyncPanZoomController::CallDispatchScroll(const ParentLayerPoint& aStartPoint, - const ParentLayerPoint& aEndPoint, +bool AsyncPanZoomController::CallDispatchScroll(const ScreenPoint& aStartPoint, + const ScreenPoint& aEndPoint, OverscrollHandoffState& aOverscrollHandoffState) { // Make a local copy of the tree manager pointer and check if it's not // null before calling DispatchScroll(). This is necessary because @@ -2057,13 +2068,13 @@ bool AsyncPanZoomController::CallDispatchScroll(const ParentLayerPoint& aStartPo } void AsyncPanZoomController::TrackTouch(const MultiTouchInput& aEvent) { - ParentLayerPoint prevTouchPoint(mX.GetPos(), mY.GetPos()); - ParentLayerPoint touchPoint = GetFirstTouchPoint(aEvent); + ScreenPoint prevTouchPoint(mX.GetPos(), mY.GetPos()); + ScreenPoint touchPoint = GetFirstTouchScreenPoint(aEvent); - ScreenPoint panDistance = ToScreenCoordinates( - ParentLayerPoint(mX.PanDistance(touchPoint.x), - mY.PanDistance(touchPoint.y)), - PanStart()); + ScreenPoint panDistance(mX.PanDistance(touchPoint.x), + mY.PanDistance(touchPoint.y)); + const ScreenPoint panStart = PanStart(); + ToGlobalScreenCoordinates(&panDistance, panStart); HandlePanningUpdate(panDistance); UpdateWithTouchAtDevicePoint(aEvent); @@ -2075,8 +2086,8 @@ void AsyncPanZoomController::TrackTouch(const MultiTouchInput& aEvent) { } } -ParentLayerPoint AsyncPanZoomController::GetFirstTouchPoint(const MultiTouchInput& aEvent) { - return ((SingleTouchData&)aEvent.mTouches[0]).mLocalScreenPoint; +ScreenPoint AsyncPanZoomController::GetFirstTouchScreenPoint(const MultiTouchInput& aEvent) { + return ((SingleTouchData&)aEvent.mTouches[0]).mScreenPoint; } void AsyncPanZoomController::StartAnimation(AsyncPanZoomAnimation* aAnimation) @@ -2189,7 +2200,7 @@ RedistributeDisplayPortExcess(CSSSize& aDisplayPortSize, /* static */ const ScreenMargin AsyncPanZoomController::CalculatePendingDisplayPort( const FrameMetrics& aFrameMetrics, - const ParentLayerPoint& aVelocity, + const ScreenPoint& aVelocity, double aEstimatedPaintDuration) { CSSSize compositionSize = aFrameMetrics.CalculateBoundedCompositedSizeInCssPixels(); @@ -2273,7 +2284,7 @@ bool AsyncPanZoomController::SnapBackIfOverscrolled() { ReentrantMonitorAutoEnter lock(mMonitor); if (IsOverscrolled()) { APZC_LOG("%p is overscrolled, starting snap-back\n", this); - StartOverscrollAnimation(ParentLayerPoint(0, 0)); + StartOverscrollAnimation(ScreenPoint(0, 0)); return true; } return false; @@ -2428,7 +2439,7 @@ Matrix4x4 AsyncPanZoomController::GetOverscrollTransform() const { // Compute the amount of the stretch along each axis. The stretch is // proportional to the amount by which we are overscrolled along that axis. - ParentLayerSize compositionSize(mX.GetCompositionLength(), mY.GetCompositionLength()); + ScreenSize compositionSize(mX.GetCompositionLength(), mY.GetCompositionLength()); float scaleX = 1 + kStretchFactor * fabsf(mX.GetOverscroll()) / mX.GetCompositionLength(); float scaleY = 1 + kStretchFactor * fabsf(mY.GetOverscroll()) / mY.GetCompositionLength(); @@ -2446,19 +2457,19 @@ Matrix4x4 AsyncPanZoomController::GetOverscrollTransform() const { // are overscrolling at the top or on the left, but if we are overscrolling // at the bottom or on the right, we want the bottom or right edge of the // content to stay in place instead, so we add a translation to compensate. - ParentLayerPoint translation; + ScreenPoint translation; bool overscrolledOnRight = (mX.GetOverscroll() > 0 && !mX.IsInUnderscroll()) || (mX.GetOverscroll() < 0 && mX.IsInUnderscroll()); if (overscrolledOnRight) { - ParentLayerCoord overscrolledCompositionWidth = scaleX * compositionSize.width; - ParentLayerCoord extraCompositionWidth = overscrolledCompositionWidth - compositionSize.width; + ScreenCoord overscrolledCompositionWidth = scaleX * compositionSize.width; + ScreenCoord extraCompositionWidth = overscrolledCompositionWidth - compositionSize.width; translation.x = -extraCompositionWidth; } bool overscrolledAtBottom = (mY.GetOverscroll() > 0 && !mY.IsInUnderscroll()) || (mY.GetOverscroll() < 0 && mY.IsInUnderscroll()); if (overscrolledAtBottom) { - ParentLayerCoord overscrolledCompositionHeight = scaleY * compositionSize.height; - ParentLayerCoord extraCompositionHeight = overscrolledCompositionHeight - compositionSize.height; + ScreenCoord overscrolledCompositionHeight = scaleY * compositionSize.height; + ScreenCoord extraCompositionHeight = overscrolledCompositionHeight - compositionSize.height; translation.y = -extraCompositionHeight; } @@ -2540,7 +2551,7 @@ bool AsyncPanZoomController::AdvanceAnimations(const TimeStamp& aSampleTime) } void AsyncPanZoomController::SampleContentTransformForFrame(ViewTransform* aOutTransform, - ParentLayerPoint& aScrollOffset) + ScreenPoint& aScrollOffset) { ReentrantMonitorAutoEnter lock(mMonitor); @@ -2577,25 +2588,25 @@ ViewTransform AsyncPanZoomController::GetCurrentAsyncTransform() const { } } - LayerToParentLayerScale scale(mFrameMetrics.mPresShellResolution // non-transient portion - * mFrameMetrics.GetAsyncZoom().scale); // transient portion - ParentLayerPoint translation = (currentScrollOffset - lastPaintScrollOffset) - * mFrameMetrics.GetZoom(); + ParentLayerToScreenScale scale = mFrameMetrics.mPresShellResolution // non-transient portion + * mFrameMetrics.GetAsyncZoom(); // transient portion + ScreenPoint translation = (currentScrollOffset - lastPaintScrollOffset) + * mFrameMetrics.GetZoom(); return ViewTransform(scale, -translation); } Matrix4x4 AsyncPanZoomController::GetNontransientAsyncTransform() const { ReentrantMonitorAutoEnter lock(mMonitor); - return Matrix4x4::Scaling(mLastContentPaintMetrics.mPresShellResolution, - mLastContentPaintMetrics.mPresShellResolution, + return Matrix4x4::Scaling(mLastContentPaintMetrics.mPresShellResolution.scale, + mLastContentPaintMetrics.mPresShellResolution.scale, 1.0f); } Matrix4x4 AsyncPanZoomController::GetTransformToLastDispatchedPaint() const { ReentrantMonitorAutoEnter lock(mMonitor); - LayerPoint scrollChange = + ParentLayerPoint scrollChange = (mLastContentPaintMetrics.GetScrollOffset() - mLastDispatchedPaintMetrics.GetScrollOffset()) * mLastContentPaintMetrics.mDevPixelsPerCSSPixel * mLastContentPaintMetrics.mCumulativeResolution @@ -2636,6 +2647,7 @@ void AsyncPanZoomController::NotifyLayersUpdated(const FrameMetrics& aLayerMetri bool isDefault = mFrameMetrics.IsDefault(); mLastContentPaintMetrics = aLayerMetrics; + UpdateTransformScale(); mFrameMetrics.SetMayHaveTouchListeners(aLayerMetrics.GetMayHaveTouchListeners()); mFrameMetrics.SetMayHaveTouchCaret(aLayerMetrics.GetMayHaveTouchCaret()); @@ -2709,8 +2721,8 @@ void AsyncPanZoomController::NotifyLayersUpdated(const FrameMetrics& aLayerMetri // since the repaint request. float totalResolutionChange = aLayerMetrics.mCumulativeResolution.scale / mFrameMetrics.mCumulativeResolution.scale; - float presShellResolutionChange = aLayerMetrics.mPresShellResolution - / mFrameMetrics.mPresShellResolution; + float presShellResolutionChange = aLayerMetrics.mPresShellResolution.scale + / mFrameMetrics.mPresShellResolution.scale; mFrameMetrics.ZoomBy(totalResolutionChange / presShellResolutionChange); } else { // Take the new zoom as either device scale or composition width or both @@ -2809,7 +2821,7 @@ void AsyncPanZoomController::ZoomToRect(CSSRect aRect) { ParentLayerRect compositionBounds = mFrameMetrics.mCompositionBounds; CSSRect cssPageRect = mFrameMetrics.mScrollableRect; CSSPoint scrollOffset = mFrameMetrics.GetScrollOffset(); - CSSToParentLayerScale currentZoom = mFrameMetrics.GetZoom(); + CSSToParentLayerScale currentZoom = mFrameMetrics.GetZoomToParent(); CSSToParentLayerScale targetZoom; // The minimum zoom to prevent over-zoom-out. @@ -2817,10 +2829,10 @@ void AsyncPanZoomController::ZoomToRect(CSSRect aRect) { // then the CSS content rect, in layers pixels, will be smaller than the // composition bounds. If this happens, we can't fill the target composited // area with this frame. - CSSToParentLayerScale localMinZoom(std::max(mZoomConstraints.mMinZoom.scale, + CSSToParentLayerScale localMinZoom(std::max((mZoomConstraints.mMinZoom * mFrameMetrics.mTransformScale).scale, std::max(compositionBounds.width / cssPageRect.width, compositionBounds.height / cssPageRect.height))); - CSSToParentLayerScale localMaxZoom = mZoomConstraints.mMaxZoom; + CSSToParentLayerScale localMaxZoom = mZoomConstraints.mMaxZoom * mFrameMetrics.mTransformScale; if (!aRect.IsEmpty()) { // Intersect the zoom-to-rect to the CSS rect to make sure it fits. @@ -2852,7 +2864,7 @@ void AsyncPanZoomController::ZoomToRect(CSSRect aRect) { targetZoom.scale = clamped(targetZoom.scale, localMinZoom.scale, localMaxZoom.scale); FrameMetrics endZoomToMetrics = mFrameMetrics; - endZoomToMetrics.SetZoom(targetZoom); + endZoomToMetrics.SetZoom(targetZoom / mFrameMetrics.mTransformScale); // Adjust the zoomToRect to a sensible position to prevent overscrolling. CSSSize sizeAfterZoom = endZoomToMetrics.CalculateCompositedSizeInCssPixels(); @@ -2871,7 +2883,7 @@ void AsyncPanZoomController::ZoomToRect(CSSRect aRect) { endZoomToMetrics.SetScrollOffset(aRect.TopLeft()); endZoomToMetrics.SetDisplayPortMargins( CalculatePendingDisplayPort(endZoomToMetrics, - ParentLayerPoint(0,0), + ScreenPoint(0,0), 0)); endZoomToMetrics.SetUseDisplayPortMargins(); @@ -3096,5 +3108,19 @@ void AsyncPanZoomController::ShareCompositorFrameMetrics() { } } +ParentLayerPoint AsyncPanZoomController::ToParentLayerCoords(const ScreenPoint& aPoint) +{ + // The parent layer pixel space and the screen space for a given layer are the + // same as of bug 1052063. FIXME: Unify these two coordinate systems. + return ParentLayerPoint(aPoint.x, aPoint.y); +} + +void AsyncPanZoomController::UpdateTransformScale() +{ + // The parent layer pixel space and the screen space for a given layer are the + // same as of bug 1052063. FIXME: Unify these two coordinate systems. + mFrameMetrics.mTransformScale.scale = 1; +} + } } diff --git a/gfx/layers/apz/src/AsyncPanZoomController.h b/gfx/layers/apz/src/AsyncPanZoomController.h index f6e491c2ac9d..3a00acf6fa57 100644 --- a/gfx/layers/apz/src/AsyncPanZoomController.h +++ b/gfx/layers/apz/src/AsyncPanZoomController.h @@ -90,10 +90,9 @@ public: * device DPI, before we start panning the screen. This is to prevent us from * accidentally processing taps as touch moves, and from very short/accidental * touches moving the screen. - * Note: It's an abuse of the 'Coord' class to use it to represent a 2D - * distance, but it's the closest thing we currently have. + * Note: this distance is in global screen coordinates. */ - static ScreenCoord GetTouchStartTolerance(); + static float GetTouchStartTolerance(); AsyncPanZoomController(uint64_t aLayersId, APZCTreeManager* aTreeManager, @@ -163,7 +162,7 @@ public: * out parameter. */ void SampleContentTransformForFrame(ViewTransform* aOutTransform, - ParentLayerPoint& aScrollOffset); + ScreenPoint& aScrollOffset); /** * Return a visual effect that reflects this apzc's @@ -248,7 +247,7 @@ public: */ static const ScreenMargin CalculatePendingDisplayPort( const FrameMetrics& aFrameMetrics, - const ParentLayerPoint& aVelocity, + const ScreenPoint& aVelocity, double aEstimatedPaintDuration); /** @@ -336,25 +335,25 @@ public: /** * Convert the vector |aVector|, rooted at the point |aAnchor|, from - * this APZC's ParentLayer coordinates into screen coordinates. + * this APZC's local screen coordinates into global screen coordinates. * The anchor is necessary because with 3D tranforms, the location of the * vector can affect the result of the transform. * To respect the lock ordering, mMonitor must NOT be held when calling * this function (since this function acquires the tree lock). */ - ScreenPoint ToScreenCoordinates(const ParentLayerPoint& aVector, - const ParentLayerPoint& aAnchor) const; + void ToGlobalScreenCoordinates(ScreenPoint* aVector, + const ScreenPoint& aAnchor) const; /** * Convert the vector |aVector|, rooted at the point |aAnchor|, from - * screen coordinates into this APZC's ParentLayer coordinates. + * global screen coordinates into this APZC's local screen coordinates . * The anchor is necessary because with 3D tranforms, the location of the * vector can affect the result of the transform. * To respect the lock ordering, mMonitor must NOT be held when calling * this function (since this function acquires the tree lock). */ - ParentLayerPoint ToParentLayerCoordinates(const ScreenPoint& aVector, - const ScreenPoint& aAnchor) const; + void ToLocalScreenCoordinates(ScreenPoint* aVector, + const ScreenPoint& aAnchor) const; protected: // Protected destructor, to discourage deletion outside of Release(): @@ -472,29 +471,31 @@ protected: * the distance between the current position and the initial position of the * current touch (this only makes sense if a touch is currently happening and * OnTouchMove() or the equivalent for pan gestures is being invoked). - * Note: It's an abuse of the 'Coord' class to use it to represent a 2D - * distance, but it's the closest thing we currently have. + * Note: This function returns a distance in global screen coordinates, + * not the local screen coordinates of this APZC. */ - ScreenCoord PanDistance() const; + float PanDistance() const; /** * Gets the start point of the current touch. * Like PanDistance(), this only makes sense if a touch is currently * happening and OnTouchMove() or the equivalent for pan gestures is * being invoked. + * Unlikely PanDistance(), this function returns a point in local screen + * coordinates. */ - ParentLayerPoint PanStart() const; + ScreenPoint PanStart() const; /** * Gets a vector of the velocities of each axis. */ - const ParentLayerPoint GetVelocityVector() const; + const ScreenPoint GetVelocityVector() const; /** * Gets the first touch point from a MultiTouchInput. This gets only * the first one and assumes the rest are either missing or not relevant. */ - ParentLayerPoint GetFirstTouchPoint(const MultiTouchInput& aEvent); + ScreenPoint GetFirstTouchScreenPoint(const MultiTouchInput& aEvent); /** * Sets the panning state basing on the pan direction angle and current touch-action value. @@ -508,6 +509,7 @@ protected: /** * Update the panning state and axis locks. + * Note: |aDelta| is expected to be in global screen coordinates. */ void HandlePanningUpdate(const ScreenPoint& aDelta); @@ -584,7 +586,7 @@ protected: * NOTE: This must be converted to CSSPoint relative to the child * document before sending over IPC. */ - bool ConvertToGecko(const ParentLayerPoint& aPoint, CSSPoint* aOut); + bool ConvertToGecko(const ScreenPoint& aPoint, CSSPoint* aOut); enum AxisLockMode { FREE, /* No locking at all */ @@ -594,8 +596,18 @@ protected: static AxisLockMode GetAxisLockMode(); + // Convert a point from local screen coordinates to parent layer coordinates. + // This is a common operation as inputs from the tree manager are in screen + // coordinates but the composition bounds is in parent layer coordinates. + ParentLayerPoint ToParentLayerCoords(const ScreenPoint& aPoint); + + // Update mFrameMetrics.mTransformScale. This should be called whenever + // our CSS transform or the non-transient part of our async transform + // changes, as it corresponds to the scale portion of those transforms. + void UpdateTransformScale(); + // Helper function for OnSingleTapUp() and OnSingleTapConfirmed(). - nsEventStatus GenerateSingleTap(const ParentLayerPoint& aPoint, mozilla::Modifiers aModifiers); + nsEventStatus GenerateSingleTap(const ScreenIntPoint& aPoint, mozilla::Modifiers aModifiers); // Common processing at the end of a touch block. void OnTouchEndOrCancel(); @@ -812,7 +824,7 @@ public: * APZC, and determines whether acceleration is applied to the * fling. */ - bool AttemptFling(ParentLayerPoint aVelocity, + bool AttemptFling(ScreenPoint aVelocity, const nsRefPtr& aOverscrollHandoffChain, bool aHandoff); @@ -821,7 +833,7 @@ private: friend class OverscrollAnimation; friend class SmoothScrollAnimation; // The initial velocity of the most recent fling. - ParentLayerPoint mLastFlingVelocity; + ScreenPoint mLastFlingVelocity; // The time at which the most recent fling started. TimeStamp mLastFlingTime; @@ -830,18 +842,18 @@ private: // The overscroll is handled by trying to hand the fling off to an APZC // later in the handoff chain, or if there are no takers, continuing the // fling and entering an overscrolled state. - void HandleFlingOverscroll(const ParentLayerPoint& aVelocity, + void HandleFlingOverscroll(const ScreenPoint& aVelocity, const nsRefPtr& aOverscrollHandoffChain); - void HandleSmoothScrollOverscroll(const ParentLayerPoint& aVelocity); + void HandleSmoothScrollOverscroll(const ScreenPoint& aVelocity); // Helper function used by TakeOverFling() and HandleFlingOverscroll(). - void AcceptFling(const ParentLayerPoint& aVelocity, + void AcceptFling(const ScreenPoint& aVelocity, const nsRefPtr& aOverscrollHandoffChain, bool aHandoff); // Start an overscroll animation with the given initial velocity. - void StartOverscrollAnimation(const ParentLayerPoint& aVelocity); + void StartOverscrollAnimation(const ScreenPoint& aVelocity); void StartSmoothScroll(); @@ -932,7 +944,7 @@ public: * state). If this returns false, the caller APZC knows that it should enter * an overscrolled state itself if it can. */ - bool AttemptScroll(const ParentLayerPoint& aStartPoint, const ParentLayerPoint& aEndPoint, + bool AttemptScroll(const ScreenPoint& aStartPoint, const ScreenPoint& aEndPoint, OverscrollHandoffState& aOverscrollHandoffState); void FlushRepaintForOverscrollHandoff(); @@ -970,8 +982,8 @@ private: * Guards against the case where the APZC is being concurrently destroyed * (and thus mTreeManager is being nulled out). */ - bool CallDispatchScroll(const ParentLayerPoint& aStartPoint, - const ParentLayerPoint& aEndPoint, + bool CallDispatchScroll(const ScreenPoint& aStartPoint, + const ScreenPoint& aEndPoint, OverscrollHandoffState& aOverscrollHandoffState); /** @@ -979,7 +991,7 @@ private: * around OverscrollBy() that also implements restrictions on entering * overscroll based on the pan angle. */ - bool OverscrollForPanning(ParentLayerPoint aOverscroll, + bool OverscrollForPanning(ScreenPoint aOverscroll, const ScreenPoint& aPanDistance); /** @@ -988,7 +1000,7 @@ private: * and the function returns true. * Otherwise, nothing happens and the function return false. */ - bool OverscrollBy(const ParentLayerPoint& aOverscroll); + bool OverscrollBy(const ScreenPoint& aOverscroll); /* =================================================================== diff --git a/gfx/layers/apz/src/Axis.cpp b/gfx/layers/apz/src/Axis.cpp index d87680ee0cfc..a8761c194288 100644 --- a/gfx/layers/apz/src/Axis.cpp +++ b/gfx/layers/apz/src/Axis.cpp @@ -42,19 +42,13 @@ Axis::Axis(AsyncPanZoomController* aAsyncPanZoomController) { } -float Axis::ToLocalVelocity(float aVelocityInchesPerMs) const { - ScreenPoint velocity = MakePoint(aVelocityInchesPerMs * APZCTreeManager::GetDPI()); - // Use ToScreenCoordinates() to convert a point rather than a vector by - // treating the point as a vector, and using (0, 0) as the anchor. - ScreenPoint panStart = mAsyncPanZoomController->ToScreenCoordinates( - mAsyncPanZoomController->PanStart(), - ParentLayerPoint()); - ParentLayerPoint localVelocity = - mAsyncPanZoomController->ToParentLayerCoordinates(velocity, panStart); - return localVelocity.Length(); +float Axis::ToLocalVelocity(float aVelocityInchesPerMs) { + ScreenPoint aVelocityPoint = MakePoint(aVelocityInchesPerMs * APZCTreeManager::GetDPI()); + mAsyncPanZoomController->ToLocalScreenCoordinates(&aVelocityPoint, mAsyncPanZoomController->PanStart()); + return aVelocityPoint.Length(); } -void Axis::UpdateWithTouchAtDevicePoint(ParentLayerCoord aPos, uint32_t aTimestampMs) { +void Axis::UpdateWithTouchAtDevicePoint(ScreenCoord aPos, uint32_t aTimestampMs) { // mVelocityQueue is controller-thread only AsyncPanZoomController::AssertOnControllerThread(); @@ -104,16 +98,16 @@ void Axis::UpdateWithTouchAtDevicePoint(ParentLayerCoord aPos, uint32_t aTimesta } } -void Axis::StartTouch(ParentLayerCoord aPos, uint32_t aTimestampMs) { +void Axis::StartTouch(ScreenCoord aPos, uint32_t aTimestampMs) { mStartPos = aPos; mPos = aPos; mPosTimeMs = aTimestampMs; mAxisLocked = false; } -bool Axis::AdjustDisplacement(ParentLayerCoord aDisplacement, - /* ParentLayerCoord */ float& aDisplacementOut, - /* ParentLayerCoord */ float& aOverscrollAmountOut) +bool Axis::AdjustDisplacement(ScreenCoord aDisplacement, + /* ScreenCoord */ float& aDisplacementOut, + /* ScreenCoord */ float& aOverscrollAmountOut) { if (mAxisLocked) { aOverscrollAmountOut = 0; @@ -121,10 +115,10 @@ bool Axis::AdjustDisplacement(ParentLayerCoord aDisplacement, return false; } - ParentLayerCoord displacement = aDisplacement; + ScreenCoord displacement = aDisplacement; // First consume any overscroll in the opposite direction along this axis. - ParentLayerCoord consumedOverscroll = 0; + ScreenCoord consumedOverscroll = 0; if (mOverscroll > 0 && aDisplacement < 0) { consumedOverscroll = std::min(mOverscroll, -aDisplacement); } else if (mOverscroll < 0 && aDisplacement > 0) { @@ -146,7 +140,7 @@ bool Axis::AdjustDisplacement(ParentLayerCoord aDisplacement, return fabsf(consumedOverscroll) > EPSILON; } -ParentLayerCoord Axis::ApplyResistance(ParentLayerCoord aRequestedOverscroll) const { +ScreenCoord Axis::ApplyResistance(ScreenCoord aRequestedOverscroll) const { // 'resistanceFactor' is a value between 0 and 1, which: // - tends to 1 as the existing overscroll tends to 0 // - tends to 0 as the existing overscroll tends to the composition length @@ -154,10 +148,10 @@ ParentLayerCoord Axis::ApplyResistance(ParentLayerCoord aRequestedOverscroll) co // factor; this should prevent overscrolling by more than the composition // length. float resistanceFactor = 1 - fabsf(mOverscroll) / GetCompositionLength(); - return resistanceFactor < 0 ? ParentLayerCoord(0) : aRequestedOverscroll * resistanceFactor; + return resistanceFactor < 0 ? ScreenCoord(0) : aRequestedOverscroll * resistanceFactor; } -void Axis::OverscrollBy(ParentLayerCoord aOverscroll) { +void Axis::OverscrollBy(ScreenCoord aOverscroll) { MOZ_ASSERT(CanScroll()); aOverscroll = ApplyResistance(aOverscroll); if (aOverscroll > 0) { @@ -184,7 +178,7 @@ void Axis::OverscrollBy(ParentLayerCoord aOverscroll) { mOverscroll += aOverscroll; } -ParentLayerCoord Axis::GetOverscroll() const { +ScreenCoord Axis::GetOverscroll() const { return mOverscroll; } @@ -256,15 +250,15 @@ void Axis::ClearOverscroll() { mOverscroll = 0; } -ParentLayerCoord Axis::PanStart() const { +ScreenCoord Axis::PanStart() const { return mStartPos; } -ParentLayerCoord Axis::PanDistance() const { +ScreenCoord Axis::PanDistance() const { return fabs(mPos - mStartPos); } -ParentLayerCoord Axis::PanDistance(ParentLayerCoord aPos) const { +ScreenCoord Axis::PanDistance(ScreenCoord aPos) const { return fabs(aPos - mStartPos); } @@ -320,9 +314,9 @@ bool Axis::FlingApplyFrictionOrCancel(const TimeDuration& aDelta, return true; } -ParentLayerCoord Axis::DisplacementWillOverscrollAmount(ParentLayerCoord aDisplacement) const { - ParentLayerCoord newOrigin = GetOrigin() + aDisplacement; - ParentLayerCoord newCompositionEnd = GetCompositionEnd() + aDisplacement; +ScreenCoord Axis::DisplacementWillOverscrollAmount(ScreenCoord aDisplacement) const { + ScreenCoord newOrigin = GetOrigin() + aDisplacement; + ScreenCoord newCompositionEnd = GetCompositionEnd() + aDisplacement; // If the current pan plus a displacement takes the window to the left of or // above the current page rect. bool minus = newOrigin < GetPageStart(); @@ -344,11 +338,11 @@ ParentLayerCoord Axis::DisplacementWillOverscrollAmount(ParentLayerCoord aDispla } CSSCoord Axis::ScaleWillOverscrollAmount(float aScale, CSSCoord aFocus) const { - // Internally, do computations in ParentLayer coordinates *before* the scale - // is applied. - CSSToParentLayerScale zoom = GetFrameMetrics().GetZoom(); - ParentLayerCoord focus = aFocus * zoom; - ParentLayerCoord originAfterScale = (GetOrigin() + focus) - (focus / aScale); + // Internally, do computations in Screen coordinates *before* the scale is + // applied. + CSSToScreenScale zoom = GetFrameMetrics().GetZoom(); + ScreenCoord focus = aFocus * zoom; + ScreenCoord originAfterScale = (GetOrigin() + focus) - (focus / aScale); bool both = ScaleWillOverscrollBothSides(aScale); bool minus = GetPageStart() - originAfterScale > COORDINATE_EPSILON; @@ -376,37 +370,39 @@ void Axis::SetVelocity(float aVelocity) { mVelocity = aVelocity; } -ParentLayerCoord Axis::GetCompositionEnd() const { +ScreenCoord Axis::GetCompositionEnd() const { return GetOrigin() + GetCompositionLength(); } -ParentLayerCoord Axis::GetPageEnd() const { +ScreenCoord Axis::GetPageEnd() const { return GetPageStart() + GetPageLength(); } -ParentLayerCoord Axis::GetOrigin() const { - ParentLayerPoint origin = GetFrameMetrics().GetScrollOffset() * GetFrameMetrics().GetZoom(); +ScreenCoord Axis::GetOrigin() const { + ScreenPoint origin = GetFrameMetrics().GetScrollOffset() * GetFrameMetrics().GetZoom(); return GetPointOffset(origin); } -ParentLayerCoord Axis::GetCompositionLength() const { - return GetRectLength(GetFrameMetrics().mCompositionBounds); +ScreenCoord Axis::GetCompositionLength() const { + return GetRectLength(GetFrameMetrics().mCompositionBounds / GetFrameMetrics().mTransformScale); } -ParentLayerCoord Axis::GetPageStart() const { - ParentLayerRect pageRect = GetFrameMetrics().GetExpandedScrollableRect() * GetFrameMetrics().GetZoom(); +ScreenCoord Axis::GetPageStart() const { + ScreenRect pageRect = GetFrameMetrics().GetExpandedScrollableRect() * GetFrameMetrics().GetZoom(); return GetRectOffset(pageRect); } -ParentLayerCoord Axis::GetPageLength() const { - ParentLayerRect pageRect = GetFrameMetrics().GetExpandedScrollableRect() * GetFrameMetrics().GetZoom(); +ScreenCoord Axis::GetPageLength() const { + ScreenRect pageRect = GetFrameMetrics().GetExpandedScrollableRect() * GetFrameMetrics().GetZoom(); return GetRectLength(pageRect); } bool Axis::ScaleWillOverscrollBothSides(float aScale) const { const FrameMetrics& metrics = GetFrameMetrics(); - ParentLayerRect screenCompositionBounds = metrics.mCompositionBounds - / ParentLayerToParentLayerScale(aScale); + + ScreenToParentLayerScale scale(metrics.mTransformScale.scale * aScale); + ScreenRect screenCompositionBounds = metrics.mCompositionBounds / scale; + return GetRectLength(screenCompositionBounds) - GetPageLength() > COORDINATE_EPSILON; } @@ -421,17 +417,17 @@ AxisX::AxisX(AsyncPanZoomController* aAsyncPanZoomController) } -ParentLayerCoord AxisX::GetPointOffset(const ParentLayerPoint& aPoint) const +ScreenCoord AxisX::GetPointOffset(const ScreenPoint& aPoint) const { return aPoint.x; } -ParentLayerCoord AxisX::GetRectLength(const ParentLayerRect& aRect) const +ScreenCoord AxisX::GetRectLength(const ScreenRect& aRect) const { return aRect.width; } -ParentLayerCoord AxisX::GetRectOffset(const ParentLayerRect& aRect) const +ScreenCoord AxisX::GetRectOffset(const ScreenRect& aRect) const { return aRect.x; } @@ -447,17 +443,17 @@ AxisY::AxisY(AsyncPanZoomController* aAsyncPanZoomController) } -ParentLayerCoord AxisY::GetPointOffset(const ParentLayerPoint& aPoint) const +ScreenCoord AxisY::GetPointOffset(const ScreenPoint& aPoint) const { return aPoint.y; } -ParentLayerCoord AxisY::GetRectLength(const ParentLayerRect& aRect) const +ScreenCoord AxisY::GetRectLength(const ScreenRect& aRect) const { return aRect.height; } -ParentLayerCoord AxisY::GetRectOffset(const ParentLayerRect& aRect) const +ScreenCoord AxisY::GetRectOffset(const ScreenRect& aRect) const { return aRect.y; } diff --git a/gfx/layers/apz/src/Axis.h b/gfx/layers/apz/src/Axis.h index 4bc5236457c7..c8351787426e 100644 --- a/gfx/layers/apz/src/Axis.h +++ b/gfx/layers/apz/src/Axis.h @@ -41,13 +41,13 @@ public: * Notify this Axis that a new touch has been received, including a timestamp * for when the touch was received. This triggers a recalculation of velocity. */ - void UpdateWithTouchAtDevicePoint(ParentLayerCoord aPos, uint32_t aTimestampMs); + void UpdateWithTouchAtDevicePoint(ScreenCoord aPos, uint32_t aTimestampMs); /** * Notify this Axis that a touch has begun, i.e. the user has put their finger * on the screen but has not yet tried to pan. */ - void StartTouch(ParentLayerCoord aPos, uint32_t aTimestampMs); + void StartTouch(ScreenCoord aPos, uint32_t aTimestampMs); /** * Notify this Axis that a touch has ended gracefully. This may perform @@ -73,18 +73,18 @@ public: * displacement, and the function returns true iff internal overscroll amounts * were changed. */ - bool AdjustDisplacement(ParentLayerCoord aDisplacement, - /* ParentLayerCoord */ float& aDisplacementOut, - /* ParentLayerCoord */ float& aOverscrollAmountOut); + bool AdjustDisplacement(ScreenCoord aDisplacement, + /* ScreenCoord */ float& aDisplacementOut, + /* ScreenCoord */ float& aOverscrollAmountOut); /** * Overscrolls this axis by the requested amount in the requested direction. * The axis must be at the end of its scroll range in this direction. */ - void OverscrollBy(ParentLayerCoord aOverscroll); + void OverscrollBy(ScreenCoord aOverscroll); /** - * Return the amount of overscroll on this axis, in ParentLayer pixels. + * Return the amount of overscroll on this axis, in Screen pixels. * * If this amount is nonzero, the relevant component of * mAsyncPanZoomController->mFrameMetrics.mScrollOffset must be at its @@ -94,7 +94,7 @@ public: * Note that if |mInUnderscroll| is true, the interpretation of this field * changes slightly (see below). */ - ParentLayerCoord GetOverscroll() const; + ScreenCoord GetOverscroll() const; /** * Return whether the axis is in underscroll. @@ -138,20 +138,20 @@ public: /** * Gets the starting position of the touch supplied in StartTouch(). */ - ParentLayerCoord PanStart() const; + ScreenCoord PanStart() const; /** * Gets the distance between the starting position of the touch supplied in * StartTouch() and the current touch from the last * UpdateWithTouchAtDevicePoint(). */ - ParentLayerCoord PanDistance() const; + ScreenCoord PanDistance() const; /** * Gets the distance between the starting position of the touch supplied in * StartTouch() and the supplied position. */ - ParentLayerCoord PanDistance(ParentLayerCoord aPos) const; + ScreenCoord PanDistance(ScreenCoord aPos) const; /** * Applies friction during a fling, or cancels the fling if the velocity is @@ -198,7 +198,7 @@ public: * If a displacement will overscroll the axis, this returns the amount and in * what direction. */ - ParentLayerCoord DisplacementWillOverscrollAmount(ParentLayerCoord aDisplacement) const; + ScreenCoord DisplacementWillOverscrollAmount(ScreenCoord aDisplacement) const; /** * If a scale will overscroll the axis, this returns the amount and in what @@ -209,7 +209,7 @@ public: * relative. * * Note: Unlike most other functions in Axis, this functions operates in - * CSS coordinates so there is no confusion as to whether the ParentLayer + * CSS coordinates so there is no confusion as to whether the Screen * coordinates it operates in are before or after the scale is applied. */ CSSCoord ScaleWillOverscrollAmount(float aScale, CSSCoord aFocus) const; @@ -223,30 +223,30 @@ public: */ bool ScaleWillOverscrollBothSides(float aScale) const; - ParentLayerCoord GetOrigin() const; - ParentLayerCoord GetCompositionLength() const; - ParentLayerCoord GetPageStart() const; - ParentLayerCoord GetPageLength() const; - ParentLayerCoord GetCompositionEnd() const; - ParentLayerCoord GetPageEnd() const; + ScreenCoord GetOrigin() const; + ScreenCoord GetCompositionLength() const; + ScreenCoord GetPageStart() const; + ScreenCoord GetPageLength() const; + ScreenCoord GetCompositionEnd() const; + ScreenCoord GetPageEnd() const; - ParentLayerCoord GetPos() const { return mPos; } + ScreenCoord GetPos() const { return mPos; } - virtual ParentLayerCoord GetPointOffset(const ParentLayerPoint& aPoint) const = 0; - virtual ParentLayerCoord GetRectLength(const ParentLayerRect& aRect) const = 0; - virtual ParentLayerCoord GetRectOffset(const ParentLayerRect& aRect) const = 0; + virtual ScreenCoord GetPointOffset(const ScreenPoint& aPoint) const = 0; + virtual ScreenCoord GetRectLength(const ScreenRect& aRect) const = 0; + virtual ScreenCoord GetRectOffset(const ScreenRect& aRect) const = 0; virtual ScreenPoint MakePoint(ScreenCoord aCoord) const = 0; protected: - ParentLayerCoord mPos; + ScreenCoord mPos; uint32_t mPosTimeMs; - ParentLayerCoord mStartPos; - float mVelocity; // Units: ParentLayerCoords per millisecond + ScreenCoord mStartPos; + float mVelocity; // Units: ScreenCoords per millisecond bool mAxisLocked; // Whether movement on this axis is locked. AsyncPanZoomController* mAsyncPanZoomController; - ParentLayerCoord mOverscroll; // See GetOverscroll(). - bool mInUnderscroll; // See IsInUnderscroll(). + ScreenCoord mOverscroll; // See GetOverscroll(). + bool mInUnderscroll; // See IsInUnderscroll(). // A queue of (timestamp, velocity) pairs; these are the historical // velocities at the given timestamps. Timestamps are in milliseconds, // velocities are in screen pixels per ms. This member can only be @@ -257,27 +257,27 @@ protected: // Adjust a requested overscroll amount for resistance, yielding a smaller // actual overscroll amount. - ParentLayerCoord ApplyResistance(ParentLayerCoord aOverscroll) const; + ScreenCoord ApplyResistance(ScreenCoord aOverscroll) const; - // Convert a velocity from global inches/ms into ParentLayerCoords/ms. - float ToLocalVelocity(float aVelocityInchesPerMs) const; + // Convert a velocity from global inches/ms into local ScreenCoords per ms + float ToLocalVelocity(float aVelocityInchesPerMs); }; class AxisX : public Axis { public: explicit AxisX(AsyncPanZoomController* mAsyncPanZoomController); - virtual ParentLayerCoord GetPointOffset(const ParentLayerPoint& aPoint) const MOZ_OVERRIDE; - virtual ParentLayerCoord GetRectLength(const ParentLayerRect& aRect) const MOZ_OVERRIDE; - virtual ParentLayerCoord GetRectOffset(const ParentLayerRect& aRect) const MOZ_OVERRIDE; + virtual ScreenCoord GetPointOffset(const ScreenPoint& aPoint) const MOZ_OVERRIDE; + virtual ScreenCoord GetRectLength(const ScreenRect& aRect) const MOZ_OVERRIDE; + virtual ScreenCoord GetRectOffset(const ScreenRect& aRect) const MOZ_OVERRIDE; virtual ScreenPoint MakePoint(ScreenCoord aCoord) const MOZ_OVERRIDE; }; class AxisY : public Axis { public: explicit AxisY(AsyncPanZoomController* mAsyncPanZoomController); - virtual ParentLayerCoord GetPointOffset(const ParentLayerPoint& aPoint) const MOZ_OVERRIDE; - virtual ParentLayerCoord GetRectLength(const ParentLayerRect& aRect) const MOZ_OVERRIDE; - virtual ParentLayerCoord GetRectOffset(const ParentLayerRect& aRect) const MOZ_OVERRIDE; + virtual ScreenCoord GetPointOffset(const ScreenPoint& aPoint) const MOZ_OVERRIDE; + virtual ScreenCoord GetRectLength(const ScreenRect& aRect) const MOZ_OVERRIDE; + virtual ScreenCoord GetRectOffset(const ScreenRect& aRect) const MOZ_OVERRIDE; virtual ScreenPoint MakePoint(ScreenCoord aCoord) const MOZ_OVERRIDE; }; diff --git a/gfx/layers/apz/src/GestureEventListener.cpp b/gfx/layers/apz/src/GestureEventListener.cpp index 76a8b5d8ec95..d7095eb66fbf 100644 --- a/gfx/layers/apz/src/GestureEventListener.cpp +++ b/gfx/layers/apz/src/GestureEventListener.cpp @@ -34,30 +34,19 @@ static const uint32_t MAX_TAP_TIME = 300; */ static const float PINCH_START_THRESHOLD = 35.0f; -ParentLayerPoint GetCurrentFocus(const MultiTouchInput& aEvent) +ScreenPoint GetCurrentFocus(const MultiTouchInput& aEvent) { - const ParentLayerPoint& firstTouch = aEvent.mTouches[0].mLocalScreenPoint; - const ParentLayerPoint& secondTouch = aEvent.mTouches[1].mLocalScreenPoint; - return (firstTouch + secondTouch) / 2; + const ScreenIntPoint& firstTouch = aEvent.mTouches[0].mScreenPoint, + secondTouch = aEvent.mTouches[1].mScreenPoint; + return ScreenPoint(firstTouch + secondTouch) / 2; } float GetCurrentSpan(const MultiTouchInput& aEvent) { - const ParentLayerPoint& firstTouch = aEvent.mTouches[0].mLocalScreenPoint; - const ParentLayerPoint& secondTouch = aEvent.mTouches[1].mLocalScreenPoint; - ParentLayerPoint delta = secondTouch - firstTouch; - return delta.Length(); -} - -TapGestureInput CreateTapEvent(const MultiTouchInput& aTouch, TapGestureInput::TapGestureType aType) -{ - return TapGestureInput(aType, - aTouch.mTime, - aTouch.mTimeStamp, - // Use mLocalScreenPoint as this goes directly to APZC - // without being transformed in APZCTreeManager. - aTouch.mTouches[0].mLocalScreenPoint, - aTouch.modifiers); + const ScreenIntPoint& firstTouch = aEvent.mTouches[0].mScreenPoint, + secondTouch = aEvent.mTouches[1].mScreenPoint; + ScreenIntPoint delta = secondTouch - firstTouch; + return float(NS_hypot(delta.x, delta.y)); } GestureEventListener::GestureEventListener(AsyncPanZoomController* aAsyncPanZoomController) @@ -138,7 +127,7 @@ nsEventStatus GestureEventListener::HandleInputTouchSingleStart() switch (mState) { case GESTURE_NONE: SetState(GESTURE_FIRST_SINGLE_TOUCH_DOWN); - mTouchStartPosition = mLastTouchInput.mTouches[0].mLocalScreenPoint; + mTouchStartPosition = mLastTouchInput.mTouches[0].mScreenPoint; CreateLongTapTimeoutTask(); CreateMaxTapTimeoutTask(); @@ -211,10 +200,10 @@ nsEventStatus GestureEventListener::HandleInputTouchMultiStart() bool GestureEventListener::MoveDistanceIsLarge() { - const ParentLayerPoint start = mLastTouchInput.mTouches[0].mLocalScreenPoint; - ParentLayerPoint delta = start - mTouchStartPosition; - ScreenPoint screenDelta = mAsyncPanZoomController->ToScreenCoordinates(delta, start); - return (screenDelta.Length() > AsyncPanZoomController::GetTouchStartTolerance()); + const ScreenPoint start = mLastTouchInput.mTouches[0].mScreenPoint; + ScreenPoint delta = start - mTouchStartPosition; + mAsyncPanZoomController->ToGlobalScreenCoordinates(&delta, start); + return (delta.Length() > AsyncPanZoomController::GetTouchStartTolerance()); } nsEventStatus GestureEventListener::HandleInputTouchMove() @@ -325,8 +314,12 @@ nsEventStatus GestureEventListener::HandleInputTouchEnd() case GESTURE_FIRST_SINGLE_TOUCH_DOWN: { CancelLongTapTimeoutTask(); CancelMaxTapTimeoutTask(); - nsEventStatus tapupStatus = mAsyncPanZoomController->HandleGestureEvent( - CreateTapEvent(mLastTouchInput, TapGestureInput::TAPGESTURE_UP)); + TapGestureInput tapEvent(TapGestureInput::TAPGESTURE_UP, + mLastTouchInput.mTime, + mLastTouchInput.mTimeStamp, + mLastTouchInput.mTouches[0].mScreenPoint, + mLastTouchInput.modifiers); + nsEventStatus tapupStatus = mAsyncPanZoomController->HandleGestureEvent(tapEvent); if (tapupStatus == nsEventStatus_eIgnore) { SetState(GESTURE_FIRST_SINGLE_TOUCH_UP); CreateMaxTapTimeoutTask(); @@ -340,8 +333,12 @@ nsEventStatus GestureEventListener::HandleInputTouchEnd() case GESTURE_SECOND_SINGLE_TOUCH_DOWN: { CancelMaxTapTimeoutTask(); SetState(GESTURE_NONE); - mAsyncPanZoomController->HandleGestureEvent( - CreateTapEvent(mLastTouchInput, TapGestureInput::TAPGESTURE_DOUBLE)); + TapGestureInput tapEvent(TapGestureInput::TAPGESTURE_DOUBLE, + mLastTouchInput.mTime, + mLastTouchInput.mTimeStamp, + mLastTouchInput.mTouches[0].mScreenPoint, + mLastTouchInput.modifiers); + mAsyncPanZoomController->HandleGestureEvent(tapEvent); break; } @@ -353,8 +350,12 @@ nsEventStatus GestureEventListener::HandleInputTouchEnd() case GESTURE_LONG_TOUCH_DOWN: { SetState(GESTURE_NONE); - mAsyncPanZoomController->HandleGestureEvent( - CreateTapEvent(mLastTouchInput, TapGestureInput::TAPGESTURE_LONG_UP)); + TapGestureInput tapEvent(TapGestureInput::TAPGESTURE_LONG_UP, + mLastTouchInput.mTime, + mLastTouchInput.mTimeStamp, + mLastTouchInput.mTouches[0].mScreenPoint, + mLastTouchInput.modifiers); + mAsyncPanZoomController->HandleGestureEvent(tapEvent); break; } @@ -411,8 +412,12 @@ void GestureEventListener::HandleInputTimeoutLongTap() CancelMaxTapTimeoutTask(); case GESTURE_FIRST_SINGLE_TOUCH_MAX_TAP_DOWN: { SetState(GESTURE_LONG_TOUCH_DOWN); - mAsyncPanZoomController->HandleGestureEvent( - CreateTapEvent(mLastTouchInput, TapGestureInput::TAPGESTURE_LONG)); + TapGestureInput tapEvent(TapGestureInput::TAPGESTURE_LONG, + mLastTouchInput.mTime, + mLastTouchInput.mTimeStamp, + mLastTouchInput.mTouches[0].mScreenPoint, + mLastTouchInput.modifiers); + mAsyncPanZoomController->HandleGestureEvent(tapEvent); break; } default: @@ -442,8 +447,12 @@ void GestureEventListener::HandleInputTimeoutMaxTap() void GestureEventListener::TriggerSingleTapConfirmedEvent() { - mAsyncPanZoomController->HandleGestureEvent( - CreateTapEvent(mLastTapInput, TapGestureInput::TAPGESTURE_CONFIRMED)); + TapGestureInput tapEvent(TapGestureInput::TAPGESTURE_CONFIRMED, + mLastTapInput.mTime, + mLastTapInput.mTimeStamp, + mLastTapInput.mTouches[0].mScreenPoint, + mLastTapInput.modifiers); + mAsyncPanZoomController->HandleGestureEvent(tapEvent); } void GestureEventListener::SetState(GestureState aState) diff --git a/gfx/layers/apz/src/GestureEventListener.h b/gfx/layers/apz/src/GestureEventListener.h index 51aaddbb0288..c38ea07d2fe2 100644 --- a/gfx/layers/apz/src/GestureEventListener.h +++ b/gfx/layers/apz/src/GestureEventListener.h @@ -8,7 +8,7 @@ #define mozilla_layers_GestureEventListener_h #include "InputData.h" // for MultiTouchInput, etc -#include "Units.h" +#include "Units.h" // for ScreenIntPoint #include "mozilla/EventForwards.h" // for nsEventStatus #include "nsAutoPtr.h" // for nsRefPtr #include "nsISupportsImpl.h" @@ -193,7 +193,7 @@ private: * or GESTURE_SECOND_SINGLE_TOUCH_DOWN then we're certain the gesture is * not tap. */ - ParentLayerPoint mTouchStartPosition; + ScreenIntPoint mTouchStartPosition; /** * Task used to timeout a long tap. This gets posted to the UI thread such diff --git a/gfx/layers/apz/util/APZCCallbackHelper.cpp b/gfx/layers/apz/util/APZCCallbackHelper.cpp index 19a0fd27c4dd..8965caa980b3 100644 --- a/gfx/layers/apz/util/APZCCallbackHelper.cpp +++ b/gfx/layers/apz/util/APZCCallbackHelper.cpp @@ -143,10 +143,12 @@ APZCCallbackHelper::UpdateRootFrame(nsIDOMWindowUtils* aUtils, aMetrics.SetScrollOffset(actualScrollOffset); // The pres shell resolution is updated by the the async zoom since the - // last paint. - float presShellResolution = aMetrics.mPresShellResolution - * aMetrics.GetAsyncZoom().scale; - aUtils->SetResolution(presShellResolution, presShellResolution); + // last paint. The ScreenToLayerScale(1.0f) reflects this async zoom being + // turned into a "sync" zoom during the repaint. + ParentLayerToLayerScale presShellResolution = aMetrics.mPresShellResolution + * aMetrics.GetAsyncZoom() + * ScreenToLayerScale(1.0f); + aUtils->SetResolution(presShellResolution.scale, presShellResolution.scale); // Finally, we set the displayport. nsCOMPtr content = nsLayoutUtils::FindContentFor(aMetrics.GetScrollId()); diff --git a/gfx/layers/client/ClientLayerManager.cpp b/gfx/layers/client/ClientLayerManager.cpp index f7ca782fe96e..f38e5ef6b47c 100644 --- a/gfx/layers/client/ClientLayerManager.cpp +++ b/gfx/layers/client/ClientLayerManager.cpp @@ -747,8 +747,8 @@ ClientLayerManager::ProgressiveUpdateCallback(bool aHasPendingNewThebesContent, aMetrics.mCriticalDisplayPort : aMetrics.mDisplayPort; LayerRect displayPort = (metricsDisplayPort + aMetrics.GetScrollOffset()) * paintScale; - ParentLayerPoint scrollOffset; - CSSToParentLayerScale zoom; + ScreenPoint scrollOffset; + CSSToScreenScale zoom; bool ret = AndroidBridge::Bridge()->ProgressiveUpdateCallback( aHasPendingNewThebesContent, displayPort, paintScale.scale, aDrawingCritical, scrollOffset, zoom); diff --git a/gfx/layers/client/ClientTiledPaintedLayer.cpp b/gfx/layers/client/ClientTiledPaintedLayer.cpp index 7f7ff2ec6581..a2691c459ed5 100644 --- a/gfx/layers/client/ClientTiledPaintedLayer.cpp +++ b/gfx/layers/client/ClientTiledPaintedLayer.cpp @@ -75,7 +75,7 @@ GetTransformToAncestorsParentLayer(Layer* aStart, const LayerMetricsWrapper& aAn // If the layer has a non-transient async transform then we need to apply it here // because it will get applied by the APZ in the compositor as well const FrameMetrics& metrics = iter.Metrics(); - transform.PostScale(metrics.mPresShellResolution, metrics.mPresShellResolution, 1.f); + transform.PostScale(metrics.mPresShellResolution.scale, metrics.mPresShellResolution.scale, 1.f); } return transform; } @@ -149,10 +149,16 @@ ClientTiledPaintedLayer::BeginPaint() GetTransformToAncestorsParentLayer(this, displayPortAncestor); transformDisplayPortToLayer.Invert(); + // Note that below we use GetZoomToParent() in a number of places. Because this + // code runs on the client side, the mTransformScale field of the FrameMetrics + // will not have been set. This can result in incorrect values being returned + // by GetZoomToParent() when we have CSS transforms set on some of these layers. + // This code should be audited and updated as part of fixing bug 993525. + // Compute the critical display port that applies to this layer in the // LayoutDevice space of this layer. ParentLayerRect criticalDisplayPort = - (displayportMetrics.mCriticalDisplayPort * displayportMetrics.GetZoom()) + (displayportMetrics.mCriticalDisplayPort * displayportMetrics.GetZoomToParent()) + displayportMetrics.mCompositionBounds.TopLeft(); mPaintData.mCriticalDisplayPort = RoundedOut( ApplyParentLayerToLayerTransform(transformDisplayPortToLayer, criticalDisplayPort)); @@ -160,7 +166,7 @@ ClientTiledPaintedLayer::BeginPaint() // Store the resolution from the displayport ancestor layer. Because this is Gecko-side, // before any async transforms have occurred, we can use the zoom for this. - mPaintData.mResolution = displayportMetrics.GetZoom(); + mPaintData.mResolution = displayportMetrics.GetZoomToParent(); TILING_LOG("TILING %p: Resolution %f\n", this, mPaintData.mPresShellResolution.scale); // Store the applicable composition bounds in this layer's Layer units. @@ -173,7 +179,7 @@ ClientTiledPaintedLayer::BeginPaint() TILING_LOG("TILING %p: Composition bounds %s\n", this, Stringify(mPaintData.mCompositionBounds).c_str()); // Calculate the scroll offset since the last transaction - mPaintData.mScrollOffset = displayportMetrics.GetScrollOffset() * displayportMetrics.GetZoom(); + mPaintData.mScrollOffset = displayportMetrics.GetScrollOffset() * displayportMetrics.GetZoomToParent(); TILING_LOG("TILING %p: Scroll offset %s\n", this, Stringify(mPaintData.mScrollOffset).c_str()); } diff --git a/gfx/layers/client/TiledContentClient.cpp b/gfx/layers/client/TiledContentClient.cpp index f696cdbd6f83..fb165b30b942 100644 --- a/gfx/layers/client/TiledContentClient.cpp +++ b/gfx/layers/client/TiledContentClient.cpp @@ -150,10 +150,10 @@ ComputeViewTransform(const FrameMetrics& aContentMetrics, const FrameMetrics& aC // but with aContentMetrics used in place of mLastContentPaintMetrics, because they // should be equivalent, modulo race conditions while transactions are inflight. - LayerToParentLayerScale scale(aCompositorMetrics.mPresShellResolution - * aCompositorMetrics.GetAsyncZoom().scale); - ParentLayerPoint translation = (aCompositorMetrics.GetScrollOffset() - aContentMetrics.GetScrollOffset()) - * aCompositorMetrics.GetZoom(); + ParentLayerToScreenScale scale = aCompositorMetrics.mPresShellResolution + * aCompositorMetrics.GetAsyncZoom(); + ScreenPoint translation = (aCompositorMetrics.GetScrollOffset() - aContentMetrics.GetScrollOffset()) + * aCompositorMetrics.GetZoom(); return ViewTransform(scale, -translation); } @@ -1366,8 +1366,8 @@ GetCompositorSideCompositionBounds(const LayerMetricsWrapper& aScrollAncestor, const ViewTransform& aAPZTransform) { Matrix4x4 nonTransientAPZUntransform = Matrix4x4::Scaling( - aScrollAncestor.Metrics().mPresShellResolution, - aScrollAncestor.Metrics().mPresShellResolution, + aScrollAncestor.Metrics().mPresShellResolution.scale, + aScrollAncestor.Metrics().mPresShellResolution.scale, 1.f); nonTransientAPZUntransform.Invert(); diff --git a/gfx/layers/composite/AsyncCompositionManager.cpp b/gfx/layers/composite/AsyncCompositionManager.cpp index e9bbfd941995..f19aded3e80c 100644 --- a/gfx/layers/composite/AsyncCompositionManager.cpp +++ b/gfx/layers/composite/AsyncCompositionManager.cpp @@ -588,7 +588,7 @@ AsyncCompositionManager::ApplyAsyncContentTransformToTree(Layer *aLayer) hasAsyncTransform = true; ViewTransform asyncTransformWithoutOverscroll; - ParentLayerPoint scrollOffset; + ScreenPoint scrollOffset; controller->SampleContentTransformForFrame(&asyncTransformWithoutOverscroll, scrollOffset); Matrix4x4 overscrollTransform = controller->GetOverscrollTransform(); @@ -718,7 +718,7 @@ ApplyAsyncTransformToScrollbarForContent(Layer* aScrollbar, // aScrollbarIsDescendant hunk below we unapply the entire async // transform, which includes the nontransientasync transform and would // normally account for the resolution. - scale *= metrics.mPresShellResolution; + scale *= metrics.mPresShellResolution.scale; } scrollbarTransform.PostScale(1.f, 1.f / transientTransform._22, 1.f); scrollbarTransform.PostTranslate(0, -transientTransform._42 * scale, 0); @@ -726,7 +726,7 @@ ApplyAsyncTransformToScrollbarForContent(Layer* aScrollbar, if (aScrollbar->GetScrollbarDirection() == Layer::HORIZONTAL) { float scale = metrics.CalculateCompositedSizeInCssPixels().width / metrics.mScrollableRect.width; if (aScrollbarIsDescendant) { - scale *= metrics.mPresShellResolution; + scale *= metrics.mPresShellResolution.scale; } scrollbarTransform.PostScale(1.f / transientTransform._11, 1.f, 1.f); scrollbarTransform.PostTranslate(-transientTransform._41 * scale, 0, 0); @@ -868,8 +868,8 @@ AsyncCompositionManager::TransformScrollableLayer(Layer* aLayer) // appears to be that metrics.mZoom is poorly initialized in some scenarios. In these scenarios, // however, we can assume there is no async zooming in progress and so the following statement // works fine. - CSSToParentLayerScale userZoom(metrics.mDevPixelsPerCSSPixel * metrics.mCumulativeResolution * LayerToParentLayerScale(1)); - ParentLayerPoint userScroll = metrics.GetScrollOffset() * userZoom; + CSSToScreenScale userZoom(metrics.mDevPixelsPerCSSPixel * metrics.mCumulativeResolution * LayerToScreenScale(1)); + ScreenPoint userScroll = metrics.GetScrollOffset() * userZoom; SyncViewportInfo(displayPort, geckoZoom, mLayersUpdated, userScroll, userZoom, fixedLayerMargins, offset); @@ -884,15 +884,15 @@ AsyncCompositionManager::TransformScrollableLayer(Layer* aLayer) // primary scrollable layer. We compare this to the user zoom and scroll // offset in the view transform we obtained from Java in order to compute the // transformation we need to apply. - ParentLayerPoint geckoScroll(0, 0); + ScreenPoint geckoScroll(0, 0); if (metrics.IsScrollable()) { geckoScroll = metrics.GetScrollOffset() * userZoom; } - LayerToParentLayerScale asyncZoom = userZoom / metrics.LayersPixelsPerCSSPixel(); - LayerToParentLayerScale scale(metrics.mPresShellResolution - * asyncZoom.scale); - ParentLayerPoint translation = userScroll - geckoScroll; + LayerToScreenScale asyncZoom = userZoom / metrics.LayersPixelsPerCSSPixel(); + ParentLayerToScreenScale scale = metrics.mPresShellResolution + * asyncZoom; + ScreenPoint translation = userScroll - geckoScroll; Matrix4x4 treeTransform = ViewTransform(scale, -translation); SetShadowTransform(aLayer, oldTransform * treeTransform); @@ -901,14 +901,14 @@ AsyncCompositionManager::TransformScrollableLayer(Layer* aLayer) // Apply resolution scaling to the old transform - the layer tree as it is // doesn't have the necessary transform to display correctly. - oldTransform.PreScale(metrics.mPresShellResolution, metrics.mPresShellResolution, 1); + oldTransform.PreScale(metrics.mPresShellResolution.scale, metrics.mPresShellResolution.scale, 1); // Make sure that overscroll and under-zoom are represented in the old // transform so that fixed position content moves and scales accordingly. // These calculations will effectively scale and offset fixed position layers // in screen space when the compensatory transform is performed in // AlignFixedAndStickyLayers. - ParentLayerRect contentScreenRect = mContentRect * userZoom; + ScreenRect contentScreenRect = mContentRect * userZoom; Point3D overscrollTranslation; if (userScroll.x < contentScreenRect.x) { overscrollTranslation.x = contentScreenRect.x - userScroll.x; @@ -1018,8 +1018,8 @@ void AsyncCompositionManager::SyncViewportInfo(const LayerIntRect& aDisplayPort, const CSSToLayerScale& aDisplayResolution, bool aLayersUpdated, - ParentLayerPoint& aScrollOffset, - CSSToParentLayerScale& aScale, + ScreenPoint& aScrollOffset, + CSSToScreenScale& aScale, LayerMargin& aFixedLayerMargins, ScreenPoint& aOffset) { @@ -1035,7 +1035,7 @@ AsyncCompositionManager::SyncViewportInfo(const LayerIntRect& aDisplayPort, } void -AsyncCompositionManager::SyncFrameMetrics(const ParentLayerPoint& aScrollOffset, +AsyncCompositionManager::SyncFrameMetrics(const ScreenPoint& aScrollOffset, float aZoom, const CSSRect& aCssPageRect, bool aLayersUpdated, diff --git a/gfx/layers/composite/AsyncCompositionManager.h b/gfx/layers/composite/AsyncCompositionManager.h index 73b21700a47d..7e237966c001 100644 --- a/gfx/layers/composite/AsyncCompositionManager.h +++ b/gfx/layers/composite/AsyncCompositionManager.h @@ -28,8 +28,8 @@ class AutoResolveRefLayers; // Represents (affine) transforms that are calculated from a content view. struct ViewTransform { - explicit ViewTransform(LayerToParentLayerScale aScale = LayerToParentLayerScale(), - ParentLayerPoint aTranslation = ParentLayerPoint()) + explicit ViewTransform(ParentLayerToScreenScale aScale = ParentLayerToScreenScale(), + ScreenPoint aTranslation = ScreenPoint()) : mScale(aScale) , mTranslation(aTranslation) {} @@ -55,8 +55,8 @@ struct ViewTransform { return !(*this == rhs); } - LayerToParentLayerScale mScale; - ParentLayerPoint mTranslation; + ParentLayerToScreenScale mScale; + ScreenPoint mTranslation; }; /** @@ -139,11 +139,11 @@ private: void SyncViewportInfo(const LayerIntRect& aDisplayPort, const CSSToLayerScale& aDisplayResolution, bool aLayersUpdated, - ParentLayerPoint& aScrollOffset, - CSSToParentLayerScale& aScale, + ScreenPoint& aScrollOffset, + CSSToScreenScale& aScale, LayerMargin& aFixedLayerMargins, ScreenPoint& aOffset); - void SyncFrameMetrics(const ParentLayerPoint& aScrollOffset, + void SyncFrameMetrics(const ScreenPoint& aScrollOffset, float aZoom, const CSSRect& aCssPageRect, bool aLayersUpdated, diff --git a/gfx/tests/gtest/TestAsyncPanZoomController.cpp b/gfx/tests/gtest/TestAsyncPanZoomController.cpp index 6c21220b7d87..d47cd48ff914 100644 --- a/gfx/tests/gtest/TestAsyncPanZoomController.cpp +++ b/gfx/tests/gtest/TestAsyncPanZoomController.cpp @@ -188,7 +188,7 @@ public: bool SampleContentTransformForFrame(const TimeStamp& aSampleTime, ViewTransform* aOutTransform, - ParentLayerPoint& aScrollOffset) { + ScreenPoint& aScrollOffset) { bool ret = AdvanceAnimations(aSampleTime); AsyncPanZoomController::SampleContentTransformForFrame( aOutTransform, aScrollOffset); @@ -243,12 +243,12 @@ protected: void MakeApzcZoomable() { - apzc->UpdateZoomConstraints(ZoomConstraints(true, true, CSSToParentLayerScale(0.25f), CSSToParentLayerScale(4.0f))); + apzc->UpdateZoomConstraints(ZoomConstraints(true, true, CSSToScreenScale(0.25f), CSSToScreenScale(4.0f))); } void MakeApzcUnzoomable() { - apzc->UpdateZoomConstraints(ZoomConstraints(false, false, CSSToParentLayerScale(1.0f), CSSToParentLayerScale(1.0f))); + apzc->UpdateZoomConstraints(ZoomConstraints(false, false, CSSToScreenScale(1.0f), CSSToScreenScale(1.0f))); } AsyncPanZoomController::GestureBehavior mGestureBehavior; @@ -277,33 +277,11 @@ public: * code to dispatch input events. */ -// Some helper functions for constructing input event objects suitable to be -// passed either to an APZC (which expects an transformed point), or to an APZTM -// (which expects an untransformed point). We handle both cases by setting both -// the transformed and untransformed fields to the same value. -static SingleTouchData -CreateSingleTouchData(int32_t aIdentifier, int aX, int aY) -{ - SingleTouchData touch(aIdentifier, ScreenIntPoint(aX, aY), ScreenSize(0, 0), 0, 0); - touch.mLocalScreenPoint = ParentLayerPoint(aX, aY); - return touch; -} -static PinchGestureInput -CreatePinchGestureInput(PinchGestureInput::PinchGestureType aType, - int aFocusX, int aFocusY, - float aCurrentSpan, float aPreviousSpan) -{ - PinchGestureInput result(aType, 0, TimeStamp(), ScreenPoint(aFocusX, aFocusY), - aCurrentSpan, aPreviousSpan, 0); - result.mLocalFocusPoint = ParentLayerPoint(aFocusX, aFocusY); - return result; -} - template static nsEventStatus TouchDown(const nsRefPtr& aTarget, int aX, int aY, int aTime, uint64_t* aOutInputBlockId = nullptr) { MultiTouchInput mti = MultiTouchInput(MultiTouchInput::MULTITOUCH_START, aTime, TimeStamp(), 0); - mti.mTouches.AppendElement(CreateSingleTouchData(0, aX, aY)); + mti.mTouches.AppendElement(SingleTouchData(0, ScreenIntPoint(aX, aY), ScreenSize(0, 0), 0, 0)); return aTarget->ReceiveInputEvent(mti, nullptr, aOutInputBlockId); } @@ -311,7 +289,7 @@ template static nsEventStatus TouchMove(const nsRefPtr& aTarget, int aX, int aY, int aTime) { MultiTouchInput mti = MultiTouchInput(MultiTouchInput::MULTITOUCH_MOVE, aTime, TimeStamp(), 0); - mti.mTouches.AppendElement(CreateSingleTouchData(0, aX, aY)); + mti.mTouches.AppendElement(SingleTouchData(0, ScreenIntPoint(aX, aY), ScreenSize(0, 0), 0, 0)); return aTarget->ReceiveInputEvent(mti, nullptr, nullptr); } @@ -319,7 +297,7 @@ template static nsEventStatus TouchUp(const nsRefPtr& aTarget, int aX, int aY, int aTime) { MultiTouchInput mti = MultiTouchInput(MultiTouchInput::MULTITOUCH_END, aTime, TimeStamp(), 0); - mti.mTouches.AppendElement(CreateSingleTouchData(0, aX, aY)); + mti.mTouches.AppendElement(SingleTouchData(0, ScreenIntPoint(aX, aY), ScreenSize(0, 0), 0, 0)); return aTarget->ReceiveInputEvent(mti, nullptr, nullptr); } @@ -457,25 +435,28 @@ PinchWithPinchInput(const nsRefPtr& aTarget, nsEventStatus (*aOutEventStatuses)[3] = nullptr) { nsEventStatus actualStatus = aTarget->ReceiveInputEvent( - CreatePinchGestureInput(PinchGestureInput::PINCHGESTURE_START, - aFocusX, aFocusY, 10.0, 10.0), - nullptr); + PinchGestureInput(PinchGestureInput::PINCHGESTURE_START, + 0, TimeStamp(), ScreenPoint(aFocusX, aFocusY), + 10.0, 10.0, 0), + nullptr); if (aOutEventStatuses) { (*aOutEventStatuses)[0] = actualStatus; } actualStatus = aTarget->ReceiveInputEvent( - CreatePinchGestureInput(PinchGestureInput::PINCHGESTURE_SCALE, - aFocusX, aFocusY, 10.0 * aScale, 10.0), - nullptr); + PinchGestureInput(PinchGestureInput::PINCHGESTURE_SCALE, + 0, TimeStamp(), ScreenPoint(aFocusX, aFocusY), + 10.0 * aScale, 10.0, 0), + nullptr); if (aOutEventStatuses) { (*aOutEventStatuses)[1] = actualStatus; } actualStatus = aTarget->ReceiveInputEvent( - CreatePinchGestureInput(PinchGestureInput::PINCHGESTURE_END, - // note: negative values here tell APZC - // not to turn the pinch into a pan - aFocusX, aFocusY, -1.0, -1.0), - nullptr); + PinchGestureInput(PinchGestureInput::PINCHGESTURE_END, + 0, TimeStamp(), ScreenPoint(aFocusX, aFocusY), + // note: negative values here tell APZC + // not to turn the pinch into a pan + -1.0, -1.0, 0), + nullptr); if (aOutEventStatuses) { (*aOutEventStatuses)[2] = actualStatus; } @@ -517,8 +498,8 @@ PinchWithTouchInput(const nsRefPtr& aTarget, } MultiTouchInput mtiStart = MultiTouchInput(MultiTouchInput::MULTITOUCH_START, 0, TimeStamp(), 0); - mtiStart.mTouches.AppendElement(CreateSingleTouchData(inputId, aFocusX, aFocusY)); - mtiStart.mTouches.AppendElement(CreateSingleTouchData(inputId + 1, aFocusX, aFocusY)); + mtiStart.mTouches.AppendElement(SingleTouchData(inputId, ScreenIntPoint(aFocusX, aFocusY), ScreenSize(0, 0), 0, 0)); + mtiStart.mTouches.AppendElement(SingleTouchData(inputId + 1, ScreenIntPoint(aFocusX, aFocusY), ScreenSize(0, 0), 0, 0)); nsEventStatus status = aTarget->ReceiveInputEvent(mtiStart, aOutInputBlockId); if (aOutEventStatuses) { (*aOutEventStatuses)[0] = status; @@ -529,24 +510,24 @@ PinchWithTouchInput(const nsRefPtr& aTarget, } MultiTouchInput mtiMove1 = MultiTouchInput(MultiTouchInput::MULTITOUCH_MOVE, 0, TimeStamp(), 0); - mtiMove1.mTouches.AppendElement(CreateSingleTouchData(inputId, aFocusX - pinchLength, aFocusY)); - mtiMove1.mTouches.AppendElement(CreateSingleTouchData(inputId + 1, aFocusX + pinchLength, aFocusY)); + mtiMove1.mTouches.AppendElement(SingleTouchData(inputId, ScreenIntPoint(aFocusX - pinchLength, aFocusY), ScreenSize(0, 0), 0, 0)); + mtiMove1.mTouches.AppendElement(SingleTouchData(inputId + 1, ScreenIntPoint(aFocusX + pinchLength, aFocusY), ScreenSize(0, 0), 0, 0)); status = aTarget->ReceiveInputEvent(mtiMove1, nullptr); if (aOutEventStatuses) { (*aOutEventStatuses)[1] = status; } MultiTouchInput mtiMove2 = MultiTouchInput(MultiTouchInput::MULTITOUCH_MOVE, 0, TimeStamp(), 0); - mtiMove2.mTouches.AppendElement(CreateSingleTouchData(inputId, aFocusX - pinchLengthScaled, aFocusY)); - mtiMove2.mTouches.AppendElement(CreateSingleTouchData(inputId + 1, aFocusX + pinchLengthScaled, aFocusY)); + mtiMove2.mTouches.AppendElement(SingleTouchData(inputId, ScreenIntPoint(aFocusX - pinchLengthScaled, aFocusY), ScreenSize(0, 0), 0, 0)); + mtiMove2.mTouches.AppendElement(SingleTouchData(inputId + 1, ScreenIntPoint(aFocusX + pinchLengthScaled, aFocusY), ScreenSize(0, 0), 0, 0)); status = aTarget->ReceiveInputEvent(mtiMove2, nullptr); if (aOutEventStatuses) { (*aOutEventStatuses)[2] = status; } MultiTouchInput mtiEnd = MultiTouchInput(MultiTouchInput::MULTITOUCH_END, 0, TimeStamp(), 0); - mtiEnd.mTouches.AppendElement(CreateSingleTouchData(inputId, aFocusX - pinchLengthScaled, aFocusY)); - mtiEnd.mTouches.AppendElement(CreateSingleTouchData(inputId + 1, aFocusX + pinchLengthScaled, aFocusY)); + mtiEnd.mTouches.AppendElement(SingleTouchData(inputId, ScreenIntPoint(aFocusX - pinchLengthScaled, aFocusY), ScreenSize(0, 0), 0, 0)); + mtiEnd.mTouches.AppendElement(SingleTouchData(inputId + 1, ScreenIntPoint(aFocusX + pinchLengthScaled, aFocusY), ScreenSize(0, 0), 0, 0)); status = aTarget->ReceiveInputEvent(mtiEnd, nullptr); if (aOutEventStatuses) { (*aOutEventStatuses)[3] = status; @@ -586,7 +567,7 @@ protected: fm.mCompositionBounds = ParentLayerRect(200, 200, 100, 200); fm.mScrollableRect = CSSRect(0, 0, 980, 1000); fm.SetScrollOffset(CSSPoint(300, 300)); - fm.SetZoom(CSSToParentLayerScale(2.0)); + fm.SetZoom(CSSToScreenScale(2.0)); // the visible area of the document in CSS pixels is x=300 y=300 w=50 h=100 return fm; } @@ -629,7 +610,7 @@ protected: // part 2 of the test, move to the top-right corner of the page and pinch and // make sure we stay in the correct spot - fm.SetZoom(CSSToParentLayerScale(2.0)); + fm.SetZoom(CSSToScreenScale(2.0)); fm.SetScrollOffset(CSSPoint(930, 5)); apzc->SetFrameMetrics(fm); // the visible area of the document in CSS pixels is x=930 y=5 w=50 h=100 @@ -728,7 +709,7 @@ TEST_F(APZCBasicTester, Overzoom) { fm.mCompositionBounds = ParentLayerRect(0, 0, 100, 100); fm.mScrollableRect = CSSRect(0, 0, 125, 150); fm.SetScrollOffset(CSSPoint(10, 0)); - fm.SetZoom(CSSToParentLayerScale(1.0)); + fm.SetZoom(CSSToScreenScale(1.0)); apzc->SetFrameMetrics(fm); MakeApzcZoomable(); @@ -747,11 +728,11 @@ TEST_F(APZCBasicTester, Overzoom) { } TEST_F(APZCBasicTester, SimpleTransform) { - ParentLayerPoint pointOut; + ScreenPoint pointOut; ViewTransform viewTransformOut; apzc->SampleContentTransformForFrame(testStartTime, &viewTransformOut, pointOut); - EXPECT_EQ(ParentLayerPoint(), pointOut); + EXPECT_EQ(ScreenPoint(), pointOut); EXPECT_EQ(ViewTransform(), viewTransformOut); } @@ -797,8 +778,8 @@ TEST_F(APZCBasicTester, ComplexTransform) { metrics.SetScrollOffset(CSSPoint(10, 10)); metrics.mScrollableRect = CSSRect(0, 0, 50, 50); metrics.mCumulativeResolution = LayoutDeviceToLayerScale(2); - metrics.mPresShellResolution = 2.0f; - metrics.SetZoom(CSSToParentLayerScale(6)); + metrics.mPresShellResolution = ParentLayerToLayerScale(2); + metrics.SetZoom(CSSToScreenScale(6)); metrics.mDevPixelsPerCSSPixel = CSSToLayoutDeviceScale(3); metrics.SetScrollId(FrameMetrics::START_SCROLL_ID); @@ -808,7 +789,7 @@ TEST_F(APZCBasicTester, ComplexTransform) { layers[0]->SetFrameMetrics(metrics); layers[1]->SetFrameMetrics(childMetrics); - ParentLayerPoint pointOut; + ScreenPoint pointOut; ViewTransform viewTransformOut; // Both the parent and child layer should behave exactly the same here, because @@ -818,40 +799,40 @@ TEST_F(APZCBasicTester, ComplexTransform) { apzc->SetFrameMetrics(metrics); apzc->NotifyLayersUpdated(metrics, true); apzc->SampleContentTransformForFrame(testStartTime, &viewTransformOut, pointOut); - EXPECT_EQ(ViewTransform(LayerToParentLayerScale(2), ParentLayerPoint()), viewTransformOut); - EXPECT_EQ(ParentLayerPoint(60, 60), pointOut); + EXPECT_EQ(ViewTransform(ParentLayerToScreenScale(2), ScreenPoint()), viewTransformOut); + EXPECT_EQ(ScreenPoint(60, 60), pointOut); childApzc->SetFrameMetrics(childMetrics); childApzc->NotifyLayersUpdated(childMetrics, true); childApzc->SampleContentTransformForFrame(testStartTime, &viewTransformOut, pointOut); - EXPECT_EQ(ViewTransform(LayerToParentLayerScale(2), ParentLayerPoint()), viewTransformOut); - EXPECT_EQ(ParentLayerPoint(60, 60), pointOut); + EXPECT_EQ(ViewTransform(ParentLayerToScreenScale(2), ScreenPoint()), viewTransformOut); + EXPECT_EQ(ScreenPoint(60, 60), pointOut); // do an async scroll by 5 pixels and check the transform metrics.ScrollBy(CSSPoint(5, 0)); apzc->SetFrameMetrics(metrics); apzc->SampleContentTransformForFrame(testStartTime, &viewTransformOut, pointOut); - EXPECT_EQ(ViewTransform(LayerToParentLayerScale(2), ParentLayerPoint(-30, 0)), viewTransformOut); - EXPECT_EQ(ParentLayerPoint(90, 60), pointOut); + EXPECT_EQ(ViewTransform(ParentLayerToScreenScale(2), ScreenPoint(-30, 0)), viewTransformOut); + EXPECT_EQ(ScreenPoint(90, 60), pointOut); childMetrics.ScrollBy(CSSPoint(5, 0)); childApzc->SetFrameMetrics(childMetrics); childApzc->SampleContentTransformForFrame(testStartTime, &viewTransformOut, pointOut); - EXPECT_EQ(ViewTransform(LayerToParentLayerScale(2), ParentLayerPoint(-30, 0)), viewTransformOut); - EXPECT_EQ(ParentLayerPoint(90, 60), pointOut); + EXPECT_EQ(ViewTransform(ParentLayerToScreenScale(2), ScreenPoint(-30, 0)), viewTransformOut); + EXPECT_EQ(ScreenPoint(90, 60), pointOut); // do an async zoom of 1.5x and check the transform metrics.ZoomBy(1.5f); apzc->SetFrameMetrics(metrics); apzc->SampleContentTransformForFrame(testStartTime, &viewTransformOut, pointOut); - EXPECT_EQ(ViewTransform(LayerToParentLayerScale(3), ParentLayerPoint(-45, 0)), viewTransformOut); - EXPECT_EQ(ParentLayerPoint(135, 90), pointOut); + EXPECT_EQ(ViewTransform(ParentLayerToScreenScale(3), ScreenPoint(-45, 0)), viewTransformOut); + EXPECT_EQ(ScreenPoint(135, 90), pointOut); childMetrics.ZoomBy(1.5f); childApzc->SetFrameMetrics(childMetrics); childApzc->SampleContentTransformForFrame(testStartTime, &viewTransformOut, pointOut); - EXPECT_EQ(ViewTransform(LayerToParentLayerScale(3), ParentLayerPoint(-45, 0)), viewTransformOut); - EXPECT_EQ(ParentLayerPoint(135, 90), pointOut); + EXPECT_EQ(ViewTransform(ParentLayerToScreenScale(3), ScreenPoint(-45, 0)), viewTransformOut); + EXPECT_EQ(ScreenPoint(135, 90), pointOut); } class APZCPanningTester : public APZCBasicTester { @@ -869,7 +850,7 @@ protected: int time = 0; int touchStart = 50; int touchEnd = 10; - ParentLayerPoint pointOut; + ScreenPoint pointOut; ViewTransform viewTransformOut; nsTArray allowedTouchBehaviors; @@ -880,10 +861,10 @@ protected: apzc->SampleContentTransformForFrame(testStartTime, &viewTransformOut, pointOut); if (aShouldTriggerScroll) { - EXPECT_EQ(ParentLayerPoint(0, -(touchEnd-touchStart)), pointOut); + EXPECT_EQ(ScreenPoint(0, -(touchEnd-touchStart)), pointOut); EXPECT_NE(ViewTransform(), viewTransformOut); } else { - EXPECT_EQ(ParentLayerPoint(), pointOut); + EXPECT_EQ(ScreenPoint(), pointOut); EXPECT_EQ(ViewTransform(), viewTransformOut); } @@ -895,7 +876,7 @@ protected: PanAndCheckStatus(apzc, time, touchEnd, touchStart, aShouldBeConsumed, &allowedTouchBehaviors); apzc->SampleContentTransformForFrame(testStartTime, &viewTransformOut, pointOut); - EXPECT_EQ(ParentLayerPoint(), pointOut); + EXPECT_EQ(ScreenPoint(), pointOut); EXPECT_EQ(ViewTransform(), viewTransformOut); } @@ -906,7 +887,7 @@ protected: int time = 0; int touchStart = 50; int touchEnd = 10; - ParentLayerPoint pointOut; + ScreenPoint pointOut; ViewTransform viewTransformOut; uint64_t blockId = 0; @@ -923,7 +904,7 @@ protected: EXPECT_LE(1, mcc->RunThroughDelayedTasks()); apzc->SampleContentTransformForFrame(testStartTime, &viewTransformOut, pointOut); - EXPECT_EQ(ParentLayerPoint(), pointOut); + EXPECT_EQ(ScreenPoint(), pointOut); EXPECT_EQ(ViewTransform(), viewTransformOut); apzc->AssertStateIsReset(); @@ -980,12 +961,12 @@ TEST_F(APZCBasicTester, Fling) { int time = 0; int touchStart = 50; int touchEnd = 10; - ParentLayerPoint pointOut; + ScreenPoint pointOut; ViewTransform viewTransformOut; // Fling down. Each step scroll further down Pan(apzc, time, touchStart, touchEnd); - ParentLayerPoint lastPoint; + ScreenPoint lastPoint; for (int i = 1; i < 50; i+=1) { apzc->SampleContentTransformForFrame(testStartTime+TimeDuration::FromMilliseconds(i), &viewTransformOut, pointOut); EXPECT_GT(pointOut.y, lastPoint.y); @@ -1073,11 +1054,11 @@ TEST_F(APZCBasicTester, OverScrollPanning) { // Check that we recover from overscroll via an animation. const TimeDuration increment = TimeDuration::FromMilliseconds(1); bool recoveredFromOverscroll = false; - ParentLayerPoint pointOut; + ScreenPoint pointOut; ViewTransform viewTransformOut; while (apzc->SampleContentTransformForFrame(testStartTime, &viewTransformOut, pointOut)) { // The reported scroll offset should be the same throughout. - EXPECT_EQ(ParentLayerPoint(0, 90), pointOut); + EXPECT_EQ(ScreenPoint(0, 90), pointOut); if (!apzc->IsOverscrolled()) { recoveredFromOverscroll = true; @@ -1099,7 +1080,7 @@ TEST_F(APZCBasicTester, OverScrollAbort) { Pan(apzc, time, touchStart, touchEnd); EXPECT_TRUE(apzc->IsOverscrolled()); - ParentLayerPoint pointOut; + ScreenPoint pointOut; ViewTransform viewTransformOut; // This sample call will run to the end of the fling animation @@ -1159,7 +1140,7 @@ protected: int tapCallsExpected = aSlow ? 1 : 0; // Advance the fling animation by timeDelta milliseconds. - ParentLayerPoint pointOut; + ScreenPoint pointOut; ViewTransform viewTransformOut; apzc->SampleContentTransformForFrame(testStartTime + TimeDuration::FromMilliseconds(timeDelta), &viewTransformOut, pointOut); @@ -1170,7 +1151,7 @@ protected: while (mcc->RunThroughDelayedTasks()); // Verify that we didn't advance any further after the fling was aborted, in either case. - ParentLayerPoint finalPointOut; + ScreenPoint finalPointOut; apzc->SampleContentTransformForFrame(testStartTime + TimeDuration::FromMilliseconds(timeDelta + 1000), &viewTransformOut, finalPointOut); EXPECT_EQ(pointOut.x, finalPointOut.x); EXPECT_EQ(pointOut.y, finalPointOut.y); @@ -1192,7 +1173,7 @@ protected: while (mcc->RunThroughDelayedTasks()); // Sample the fling a couple of times to ensure it's going. - ParentLayerPoint point, finalPoint; + ScreenPoint point, finalPoint; ViewTransform viewTransform; apzc->SampleContentTransformForFrame(testStartTime + TimeDuration::FromMilliseconds(10), &viewTransform, point); apzc->SampleContentTransformForFrame(testStartTime + TimeDuration::FromMilliseconds(20), &viewTransform, finalPoint); @@ -1404,7 +1385,7 @@ protected: time += 1000; MultiTouchInput mti = MultiTouchInput(MultiTouchInput::MULTITOUCH_MOVE, time, TimeStamp(), 0); - mti.mTouches.AppendElement(SingleTouchData(0, ParentLayerPoint(touchX, touchEndY), ScreenSize(0, 0), 0, 0)); + mti.mTouches.AppendElement(SingleTouchData(0, ScreenIntPoint(touchX, touchEndY), ScreenSize(0, 0), 0, 0)); status = apzc->ReceiveInputEvent(mti, nullptr); EXPECT_EQ(nsEventStatus_eConsumeDoDefault, status); @@ -1412,11 +1393,11 @@ protected: status = TouchUp(apzc, touchX, touchEndY, time); EXPECT_EQ(nsEventStatus_eConsumeDoDefault, status); - ParentLayerPoint pointOut; + ScreenPoint pointOut; ViewTransform viewTransformOut; apzc->SampleContentTransformForFrame(testStartTime, &viewTransformOut, pointOut); - EXPECT_EQ(ParentLayerPoint(), pointOut); + EXPECT_EQ(ScreenPoint(), pointOut); EXPECT_EQ(ViewTransform(), viewTransformOut); apzc->AssertStateIsReset(); @@ -1582,13 +1563,13 @@ TEST_F(APZCGestureDetectorTester, TapFollowedByPinch) { int inputId = 0; MultiTouchInput mti; mti = MultiTouchInput(MultiTouchInput::MULTITOUCH_START, time, TimeStamp(), 0); - mti.mTouches.AppendElement(SingleTouchData(inputId, ParentLayerPoint(20, 20), ScreenSize(0, 0), 0, 0)); - mti.mTouches.AppendElement(SingleTouchData(inputId + 1, ParentLayerPoint(10, 10), ScreenSize(0, 0), 0, 0)); + mti.mTouches.AppendElement(SingleTouchData(inputId, ScreenIntPoint(20, 20), ScreenSize(0, 0), 0, 0)); + mti.mTouches.AppendElement(SingleTouchData(inputId + 1, ScreenIntPoint(10, 10), ScreenSize(0, 0), 0, 0)); apzc->ReceiveInputEvent(mti, nullptr); mti = MultiTouchInput(MultiTouchInput::MULTITOUCH_END, time, TimeStamp(), 0); - mti.mTouches.AppendElement(SingleTouchData(inputId, ParentLayerPoint(20, 20), ScreenSize(0, 0), 0, 0)); - mti.mTouches.AppendElement(SingleTouchData(inputId + 1, ParentLayerPoint(10, 10), ScreenSize(0, 0), 0, 0)); + mti.mTouches.AppendElement(SingleTouchData(inputId, ScreenIntPoint(20, 20), ScreenSize(0, 0), 0, 0)); + mti.mTouches.AppendElement(SingleTouchData(inputId + 1, ScreenIntPoint(10, 10), ScreenSize(0, 0), 0, 0)); apzc->ReceiveInputEvent(mti, nullptr); while (mcc->RunThroughDelayedTasks()); @@ -1607,17 +1588,17 @@ TEST_F(APZCGestureDetectorTester, TapFollowedByMultipleTouches) { int inputId = 0; MultiTouchInput mti; mti = MultiTouchInput(MultiTouchInput::MULTITOUCH_START, time, TimeStamp(), 0); - mti.mTouches.AppendElement(SingleTouchData(inputId, ParentLayerPoint(20, 20), ScreenSize(0, 0), 0, 0)); + mti.mTouches.AppendElement(SingleTouchData(inputId, ScreenIntPoint(20, 20), ScreenSize(0, 0), 0, 0)); apzc->ReceiveInputEvent(mti, nullptr); mti = MultiTouchInput(MultiTouchInput::MULTITOUCH_START, time, TimeStamp(), 0); - mti.mTouches.AppendElement(SingleTouchData(inputId, ParentLayerPoint(20, 20), ScreenSize(0, 0), 0, 0)); - mti.mTouches.AppendElement(SingleTouchData(inputId + 1, ParentLayerPoint(10, 10), ScreenSize(0, 0), 0, 0)); + mti.mTouches.AppendElement(SingleTouchData(inputId, ScreenIntPoint(20, 20), ScreenSize(0, 0), 0, 0)); + mti.mTouches.AppendElement(SingleTouchData(inputId + 1, ScreenIntPoint(10, 10), ScreenSize(0, 0), 0, 0)); apzc->ReceiveInputEvent(mti, nullptr); mti = MultiTouchInput(MultiTouchInput::MULTITOUCH_END, time, TimeStamp(), 0); - mti.mTouches.AppendElement(SingleTouchData(inputId, ParentLayerPoint(20, 20), ScreenSize(0, 0), 0, 0)); - mti.mTouches.AppendElement(SingleTouchData(inputId + 1, ParentLayerPoint(10, 10), ScreenSize(0, 0), 0, 0)); + mti.mTouches.AppendElement(SingleTouchData(inputId, ScreenIntPoint(20, 20), ScreenSize(0, 0), 0, 0)); + mti.mTouches.AppendElement(SingleTouchData(inputId + 1, ScreenIntPoint(10, 10), ScreenSize(0, 0), 0, 0)); apzc->ReceiveInputEvent(mti, nullptr); while (mcc->RunThroughDelayedTasks()); diff --git a/layout/base/UnitTransforms.h b/layout/base/UnitTransforms.h index c4277851b76b..ce1c4b59210b 100644 --- a/layout/base/UnitTransforms.h +++ b/layout/base/UnitTransforms.h @@ -21,13 +21,9 @@ namespace mozilla { MOZ_BEGIN_ENUM_CLASS(PixelCastJustification, uint8_t) // For the root layer, Screen Pixel = Parent Layer Pixel. - ScreenIsParentLayerForRoot, + ScreenToParentLayerForRoot, // For the root composition size we want to view it as layer pixels in any layer - ParentLayerToLayerForRootComposition, - // The transform that is usually used to convert between two coordinate - // systems is not available (for example, because the object that stores it - // is being destroyed), so fall back to the identity. - TransformNotAvailable + ParentLayerToLayerForRootComposition MOZ_END_ENUM_CLASS(PixelCastJustification) template @@ -38,16 +34,6 @@ template gfx::IntSizeTyped ViewAs(const gfx::IntSizeTyped& aSize, PixelCastJustification) { return gfx::IntSizeTyped(aSize.width, aSize.height); } -template -gfx::PointTyped ViewAs(const gfx::PointTyped& aPoint, PixelCastJustification) { - return gfx::PointTyped(aPoint.x, aPoint.y); -} -template -gfx::ScaleFactor ViewTargetAs( - const gfx::ScaleFactor& aScaleFactor, - PixelCastJustification) { - return gfx::ScaleFactor(aScaleFactor.scale); -} // Convenience functions for casting untyped entities to typed entities. // Using these functions does not require a justification, but once we convert @@ -105,18 +91,6 @@ static gfx::IntRectTyped TransformTo(const gfx::Matrix4x4& aTransfo return RoundedToInt(ViewAs(aTransform.TransformBounds(rect))); } -// Transform |aVector|, which is anchored at |aAnchor|, by the given transform -// matrix, yielding a point in |TargetUnits|. -// The anchor is necessary because with 3D tranforms, the location of the -// vector can affect the result of the transform. -template -static gfx::PointTyped TransformVector(const gfx::Matrix4x4& aTransform, - const gfx::PointTyped& aVector, - const gfx::PointTyped& aAnchor) { - gfx::PointTyped transformedStart = TransformTo(aTransform, aAnchor); - gfx::PointTyped transformedEnd = TransformTo(aTransform, aAnchor + aVector); - return transformedEnd - transformedStart; -} } diff --git a/layout/base/Units.h b/layout/base/Units.h index 668acead5a0c..f0cd08c5971f 100644 --- a/layout/base/Units.h +++ b/layout/base/Units.h @@ -27,25 +27,12 @@ struct LayoutDevicePixel; struct LayerPixel; struct RenderTargetPixel; struct ScreenPixel; -// The layer coordinates of the parent frame. -// This can be arrived at in three ways: -// - Start with the CSS coordinates of the parent frame, multiply by the -// device scale and the cumulative resolution of the parent frame. -// - Start with the CSS coordinates of current frame, multiply by the device -// scale, the cumulative resolution of the current frame, and the scales -// from the CSS and async transforms of the current frame. -// - Start with global screen coordinates and unapply all CSS and async -// transforms from the root down to and including the parent. -// It's helpful to look at https://wiki.mozilla.org/Platform/GFX/APZ#Coordinate_systems -// to get a picture of how the various coordinate systems relate to each other. -struct ParentLayerPixel {}; template<> struct IsPixel : TrueType {}; template<> struct IsPixel : TrueType {}; template<> struct IsPixel : TrueType {}; template<> struct IsPixel : TrueType {}; template<> struct IsPixel : TrueType {}; -template<> struct IsPixel : TrueType {}; typedef gfx::CoordTyped CSSCoord; typedef gfx::IntCoordTyped CSSIntCoord; @@ -80,6 +67,8 @@ typedef gfx::IntRectTyped LayerIntRect; typedef gfx::MarginTyped LayerMargin; typedef gfx::IntMarginTyped LayerIntMargin; +typedef gfx::CoordTyped ScreenCoord; +typedef gfx::IntCoordTyped ScreenIntCoord; typedef gfx::PointTyped RenderTargetPoint; typedef gfx::IntPointTyped RenderTargetIntPoint; typedef gfx::SizeTyped RenderTargetSize; @@ -89,8 +78,6 @@ typedef gfx::IntRectTyped RenderTargetIntRect; typedef gfx::MarginTyped RenderTargetMargin; typedef gfx::IntMarginTyped RenderTargetIntMargin; -typedef gfx::CoordTyped ScreenCoord; -typedef gfx::IntCoordTyped ScreenIntCoord; typedef gfx::PointTyped ScreenPoint; typedef gfx::IntPointTyped ScreenIntPoint; typedef gfx::SizeTyped ScreenSize; @@ -100,38 +87,20 @@ typedef gfx::IntRectTyped ScreenIntRect; typedef gfx::MarginTyped ScreenMargin; typedef gfx::IntMarginTyped ScreenIntMargin; -typedef gfx::CoordTyped ParentLayerCoord; -typedef gfx::IntCoordTyped ParentLayerIntCoord; -typedef gfx::PointTyped ParentLayerPoint; -typedef gfx::IntPointTyped ParentLayerIntPoint; -typedef gfx::SizeTyped ParentLayerSize; -typedef gfx::IntSizeTyped ParentLayerIntSize; -typedef gfx::RectTyped ParentLayerRect; -typedef gfx::IntRectTyped ParentLayerIntRect; -typedef gfx::MarginTyped ParentLayerMargin; -typedef gfx::IntMarginTyped ParentLayerIntMargin; - typedef gfx::ScaleFactor CSSToLayoutDeviceScale; typedef gfx::ScaleFactor CSSToLayerScale; typedef gfx::ScaleFactor CSSToScreenScale; -typedef gfx::ScaleFactor CSSToParentLayerScale; typedef gfx::ScaleFactor LayoutDeviceToCSSScale; typedef gfx::ScaleFactor LayoutDeviceToLayerScale; typedef gfx::ScaleFactor LayoutDeviceToScreenScale; -typedef gfx::ScaleFactor LayoutDeviceToParentLayerScale; typedef gfx::ScaleFactor LayerToCSSScale; typedef gfx::ScaleFactor LayerToLayoutDeviceScale; typedef gfx::ScaleFactor LayerToRenderTargetScale; typedef gfx::ScaleFactor LayerToScreenScale; -typedef gfx::ScaleFactor LayerToParentLayerScale; typedef gfx::ScaleFactor RenderTargetToScreenScale; typedef gfx::ScaleFactor ScreenToCSSScale; typedef gfx::ScaleFactor ScreenToLayoutDeviceScale; typedef gfx::ScaleFactor ScreenToLayerScale; -typedef gfx::ScaleFactor ScreenToParentLayerScale; -typedef gfx::ScaleFactor ParentLayerToLayerScale; -typedef gfx::ScaleFactor ParentLayerToScreenScale; -typedef gfx::ScaleFactor ParentLayerToParentLayerScale; /* * The pixels that content authors use to specify sizes in. diff --git a/layout/base/nsDisplayList.cpp b/layout/base/nsDisplayList.cpp index d8bbd4b2df7d..a0f2b71bdec4 100644 --- a/layout/base/nsDisplayList.cpp +++ b/layout/base/nsDisplayList.cpp @@ -724,9 +724,10 @@ nsDisplayScrollLayer::ComputeFrameMetrics(nsIFrame* aForFrame, // Only the root scrollable frame for a given presShell should pick up // the presShell's resolution. All the other frames are 1.0. if (aScrollFrame == presShell->GetRootScrollFrame()) { - metrics.mPresShellResolution = presShell->GetXResolution(); + metrics.mPresShellResolution = ParentLayerToLayerScale(presShell->GetXResolution(), + presShell->GetYResolution()); } else { - metrics.mPresShellResolution = 1.0f; + metrics.mPresShellResolution = ParentLayerToLayerScale(1.0f); } // The cumulative resolution is the resolution at which the scroll frame's // content is actually rendered. It includes the pres shell resolutions of @@ -746,9 +747,9 @@ nsDisplayScrollLayer::ComputeFrameMetrics(nsIFrame* aForFrame, // Initially, AsyncPanZoomController should render the content to the screen // at the painted resolution. - const LayerToParentLayerScale layerToParentLayerScale(1.0f); + const LayerToScreenScale layerToScreenScale(1.0f); metrics.SetZoom(metrics.mCumulativeResolution * metrics.mDevPixelsPerCSSPixel - * layerToParentLayerScale); + * layerToScreenScale); if (presShell) { nsIDocument* document = nullptr; @@ -762,6 +763,11 @@ nsDisplayScrollLayer::ComputeFrameMetrics(nsIFrame* aForFrame, metrics.SetMayHaveTouchCaret(presShell->MayHaveTouchCaret()); } + LayoutDeviceToParentLayerScale layoutToParentLayerScale = + // The ScreenToParentLayerScale should be mTransformScale which is not calculated yet, + // but we don't yet handle CSS transforms, so we assume it's 1 here. + metrics.mCumulativeResolution * LayerToScreenScale(1.0) * ScreenToParentLayerScale(1.0); + // Calculate the composition bounds as the size of the scroll frame and // its origin relative to the reference frame. // If aScrollFrame is null, we are in a document without a root scroll frame, @@ -770,8 +776,7 @@ nsDisplayScrollLayer::ComputeFrameMetrics(nsIFrame* aForFrame, nsRect compositionBounds(frameForCompositionBoundsCalculation->GetOffsetToCrossDoc(aReferenceFrame), frameForCompositionBoundsCalculation->GetSize()); ParentLayerRect frameBounds = LayoutDeviceRect::FromAppUnits(compositionBounds, auPerDevPixel) - * metrics.mCumulativeResolution - * layerToParentLayerScale; + * layoutToParentLayerScale; metrics.mCompositionBounds = frameBounds; // For the root scroll frame of the root content document, the above calculation diff --git a/layout/base/nsLayoutUtils.cpp b/layout/base/nsLayoutUtils.cpp index 445b152edab1..490342cc4b0a 100644 --- a/layout/base/nsLayoutUtils.cpp +++ b/layout/base/nsLayoutUtils.cpp @@ -2784,11 +2784,12 @@ CalculateFrameMetricsForDisplayPort(nsIFrame* aScrollFrame, nsIPresShell* presShell = presContext->PresShell(); CSSToLayoutDeviceScale deviceScale(float(nsPresContext::AppUnitsPerCSSPixel()) / presContext->AppUnitsPerDevPixel()); - float resolution = 1.0f; + ParentLayerToLayerScale resolution; if (aScrollFrame == presShell->GetRootScrollFrame()) { // Only the root scrollable frame for a given presShell should pick up // the presShell's resolution. All the other frames are 1.0. - resolution = presShell->GetXResolution(); + resolution = ParentLayerToLayerScale(presShell->GetXResolution(), + presShell->GetYResolution()); } // Note: unlike in ComputeFrameMetrics(), we don't know the full cumulative // resolution including FrameMetrics::mExtraResolution, because layout hasn't @@ -2800,11 +2801,10 @@ CalculateFrameMetricsForDisplayPort(nsIFrame* aScrollFrame, presShell->GetCumulativeResolution().width * nsLayoutUtils::GetTransformToAncestorScale(aScrollFrame).width); - LayerToParentLayerScale layerToParentLayerScale(1.0f); metrics.mDevPixelsPerCSSPixel = deviceScale; metrics.mPresShellResolution = resolution; metrics.mCumulativeResolution = cumulativeResolution; - metrics.SetZoom(deviceScale * cumulativeResolution * layerToParentLayerScale); + metrics.SetZoom(deviceScale * cumulativeResolution * LayerToScreenScale(1)); // Only the size of the composition bounds is relevant to the // displayport calculation, not its origin. @@ -2816,7 +2816,9 @@ CalculateFrameMetricsForDisplayPort(nsIFrame* aScrollFrame, compBoundsScale = LayoutDeviceToParentLayerScale(res.width, res.height); } } else { - compBoundsScale = cumulativeResolution * layerToParentLayerScale; + compBoundsScale = cumulativeResolution + * LayerToScreenScale(1.0f) + * ScreenToParentLayerScale(1.0f); } metrics.mCompositionBounds = LayoutDeviceRect::FromAppUnits(nsRect(nsPoint(0, 0), compositionSize), @@ -2867,7 +2869,7 @@ nsLayoutUtils::GetOrMaybeCreateDisplayPort(nsDisplayListBuilder& aBuilder, if (!haveDisplayPort) { FrameMetrics metrics = CalculateFrameMetricsForDisplayPort(aScrollFrame, scrollableFrame); ScreenMargin displayportMargins = APZCTreeManager::CalculatePendingDisplayPort( - metrics, ParentLayerPoint(0.0f, 0.0f), 0.0); + metrics, ScreenPoint(0.0f, 0.0f), 0.0); nsIPresShell* presShell = aScrollFrame->PresContext()->GetPresShell(); gfx::IntSize alignment = gfxPlatform::GetPlatform()->UseTiling() ? gfx::IntSize(gfxPrefs::LayersTileWidth(), gfxPrefs::LayersTileHeight()) : diff --git a/widget/InputData.h b/widget/InputData.h index 02c3ad320a08..6080ba8f6d38 100644 --- a/widget/InputData.h +++ b/widget/InputData.h @@ -108,8 +108,6 @@ protected: class SingleTouchData { public: - // Construct a SingleTouchData from a Screen point. - // mLocalScreenPoint remains (0,0) unless it's set later. SingleTouchData(int32_t aIdentifier, ScreenIntPoint aScreenPoint, ScreenSize aRadius, @@ -123,23 +121,6 @@ public: { } - // Construct a SingleTouchData from a ParentLayer point. - // mScreenPoint remains (0,0) unless it's set later. - // Note: if APZ starts using the radius for anything, we should add a local - // version of that too, and have this constructor take it as a ParentLayerSize. - SingleTouchData(int32_t aIdentifier, - ParentLayerPoint aLocalScreenPoint, - ScreenSize aRadius, - float aRotationAngle, - float aForce) - : mIdentifier(aIdentifier), - mLocalScreenPoint(aLocalScreenPoint), - mRadius(aRadius), - mRotationAngle(aRotationAngle), - mForce(aForce) - { - } - SingleTouchData() { } @@ -154,10 +135,6 @@ public: // coordinates on the screen. ScreenIntPoint mScreenPoint; - // |mScreenPoint| transformed to the local coordinates of the APZC targeted - // by the hit. This is set and used by APZ. - ParentLayerPoint mLocalScreenPoint; - // Radius that the touch covers, i.e. if you're using your thumb it will // probably be larger than using your pinky, even with the same force. // Radius can be different along x and y. For example, if you press down with @@ -297,11 +274,6 @@ public: // Only non-zero if mType is PANGESTURE_PAN or PANGESTURE_MOMENTUMPAN. ScreenPoint mPanDisplacement; - - // Versions of |mPanStartPoint| and |mPanDisplacement| in the local - // coordinates of the APZC receiving the pan. These are set and used by APZ. - ParentLayerPoint mLocalPanStartPoint; - ParentLayerPoint mLocalPanDisplacement; }; /** @@ -319,8 +291,6 @@ public: PINCHGESTURE_END }; - // Construct a tap gesture from a Screen point. - // mLocalFocusPoint remains (0,0) unless it's set later. PinchGestureInput(PinchGestureType aType, uint32_t aTime, TimeStamp aTimeStamp, @@ -334,23 +304,8 @@ public: mCurrentSpan(aCurrentSpan), mPreviousSpan(aPreviousSpan) { - } - // Construct a tap gesture from a ParentLayer point. - // mFocusPoint remains (0,0) unless it's set later. - PinchGestureInput(PinchGestureType aType, - uint32_t aTime, - TimeStamp aTimeStamp, - const ParentLayerPoint& aLocalFocusPoint, - float aCurrentSpan, - float aPreviousSpan, - Modifiers aModifiers) - : InputData(PINCHGESTURE_INPUT, aTime, aTimeStamp, aModifiers), - mType(aType), - mLocalFocusPoint(aLocalFocusPoint), - mCurrentSpan(aCurrentSpan), - mPreviousSpan(aPreviousSpan) - { + } PinchGestureType mType; @@ -362,10 +317,6 @@ public: // are the coordinates on the screen of this midpoint. ScreenPoint mFocusPoint; - // |mFocusPoint| transformed to the local coordinates of the APZC targeted - // by the hit. This is set and used by APZ. - ParentLayerPoint mLocalFocusPoint; - // The distance in device pixels (though as a float for increased precision // and because it is the distance along both the x and y axis) between the // touches responsible for the pinch gesture. @@ -395,8 +346,6 @@ public: TAPGESTURE_CANCEL }; - // Construct a tap gesture from a Screen point. - // mLocalPoint remains (0,0) unless it's set later. TapGestureInput(TapGestureType aType, uint32_t aTime, TimeStamp aTimeStamp, @@ -406,29 +355,12 @@ public: mType(aType), mPoint(aPoint) { - } - // Construct a tap gesture from a ParentLayer point. - // mPoint remains (0,0) unless it's set later. - TapGestureInput(TapGestureType aType, - uint32_t aTime, - TimeStamp aTimeStamp, - const ParentLayerPoint& aLocalPoint, - Modifiers aModifiers) - : InputData(TAPGESTURE_INPUT, aTime, aTimeStamp, aModifiers), - mType(aType), - mLocalPoint(aLocalPoint) - { + } TapGestureType mType; - - // The location of the tap in screen pixels. ScreenIntPoint mPoint; - - // The location of the tap in the local coordinates of the APZC receiving it. - // This is set and used by APZ. - ParentLayerPoint mLocalPoint; }; } diff --git a/widget/android/AndroidBridge.cpp b/widget/android/AndroidBridge.cpp index 339f67c4377b..d713b5db7f1f 100644 --- a/widget/android/AndroidBridge.cpp +++ b/widget/android/AndroidBridge.cpp @@ -1493,7 +1493,7 @@ AndroidBridge::SetPageRect(const CSSRect& aCssPageRect) void AndroidBridge::SyncViewportInfo(const LayerIntRect& aDisplayPort, const CSSToLayerScale& aDisplayResolution, - bool aLayersUpdated, ParentLayerPoint& aScrollOffset, CSSToParentLayerScale& aScale, + bool aLayersUpdated, ScreenPoint& aScrollOffset, CSSToScreenScale& aScale, LayerMargin& aFixedLayerMargins, ScreenPoint& aOffset) { mozilla::widget::android::GeckoLayerClient *client = mLayerClient; @@ -1512,7 +1512,7 @@ AndroidBridge::SyncViewportInfo(const LayerIntRect& aDisplayPort, const CSSToLay } ViewTransform* viewTransform = ViewTransform::Wrap(viewTransformJObj); - aScrollOffset = ParentLayerPoint(viewTransform->getx(), viewTransform->gety()); + aScrollOffset = ScreenPoint(viewTransform->getx(), viewTransform->gety()); aScale.scale = viewTransform->getscale(); aFixedLayerMargins.top = viewTransform->getfixedLayerMarginTop(); aFixedLayerMargins.right = viewTransform->getfixedLayerMarginRight(); @@ -1523,7 +1523,7 @@ AndroidBridge::SyncViewportInfo(const LayerIntRect& aDisplayPort, const CSSToLay delete viewTransform; } -void AndroidBridge::SyncFrameMetrics(const ParentLayerPoint& aScrollOffset, float aZoom, const CSSRect& aCssPageRect, +void AndroidBridge::SyncFrameMetrics(const ScreenPoint& aScrollOffset, float aZoom, const CSSRect& aCssPageRect, bool aLayersUpdated, const CSSRect& aDisplayPort, const CSSToLayerScale& aDisplayResolution, bool aIsFirstPaint, LayerMargin& aFixedLayerMargins, ScreenPoint& aOffset) { @@ -1956,7 +1956,7 @@ AndroidBridge::IsContentDocumentDisplayed() bool AndroidBridge::ProgressiveUpdateCallback(bool aHasPendingNewThebesContent, const LayerRect& aDisplayPort, float aDisplayResolution, - bool aDrawingCritical, ParentLayerPoint& aScrollOffset, CSSToParentLayerScale& aZoom) + bool aDrawingCritical, ScreenPoint& aScrollOffset, CSSToScreenScale& aZoom) { mozilla::widget::android::GeckoLayerClient *client = mLayerClient; if (!client) { diff --git a/widget/android/AndroidBridge.h b/widget/android/AndroidBridge.h index 37da66443582..04a3f42d0128 100644 --- a/widget/android/AndroidBridge.h +++ b/widget/android/AndroidBridge.h @@ -208,7 +208,7 @@ public: bool IsContentDocumentDisplayed(); bool ProgressiveUpdateCallback(bool aHasPendingNewThebesContent, const LayerRect& aDisplayPort, float aDisplayResolution, bool aDrawingCritical, - mozilla::ParentLayerPoint& aScrollOffset, mozilla::CSSToParentLayerScale& aZoom); + mozilla::ScreenPoint& aScrollOffset, mozilla::CSSToScreenScale& aZoom); void SetLayerClient(JNIEnv* env, jobject jobj); mozilla::widget::android::GeckoLayerClient* GetLayerClient() { return mLayerClient; } @@ -306,9 +306,9 @@ public: void SetFirstPaintViewport(const LayerIntPoint& aOffset, const CSSToLayerScale& aZoom, const CSSRect& aCssPageRect); void SetPageRect(const CSSRect& aCssPageRect); void SyncViewportInfo(const LayerIntRect& aDisplayPort, const CSSToLayerScale& aDisplayResolution, - bool aLayersUpdated, ParentLayerPoint& aScrollOffset, CSSToParentLayerScale& aScale, + bool aLayersUpdated, ScreenPoint& aScrollOffset, CSSToScreenScale& aScale, LayerMargin& aFixedLayerMargins, ScreenPoint& aOffset); - void SyncFrameMetrics(const ParentLayerPoint& aScrollOffset, float aZoom, const CSSRect& aCssPageRect, + void SyncFrameMetrics(const ScreenPoint& aScrollOffset, float aZoom, const CSSRect& aCssPageRect, bool aLayersUpdated, const CSSRect& aDisplayPort, const CSSToLayerScale& aDisplayResolution, bool aIsFirstPaint, LayerMargin& aFixedLayerMargins, ScreenPoint& aOffset); diff --git a/widget/windows/winrt/APZController.cpp b/widget/windows/winrt/APZController.cpp index c88c9b6b35e5..1cad0e91ef79 100644 --- a/widget/windows/winrt/APZController.cpp +++ b/widget/windows/winrt/APZController.cpp @@ -253,8 +253,8 @@ APZController::GetRootZoomConstraints(ZoomConstraints* aOutConstraints) // from 1/4 to 4x by default. aOutConstraints->mAllowZoom = true; aOutConstraints->mAllowDoubleTapZoom = false; - aOutConstraints->mMinZoom = CSSToParentLayerScale(0.25f); - aOutConstraints->mMaxZoom = CSSToParentLayerScale(4.0f); + aOutConstraints->mMinZoom = CSSToScreenScale(0.25f); + aOutConstraints->mMaxZoom = CSSToScreenScale(4.0f); return true; } return false; From c247fdb775e70cc13d439e51d49a7d592e672f69 Mon Sep 17 00:00:00 2001 From: "Carsten \"Tomcat\" Book" Date: Thu, 13 Nov 2014 11:47:35 +0100 Subject: [PATCH 75/80] Backed out changeset 71fe4233208a (bug 1076163) --- dom/ipc/TabChild.cpp | 10 ++--- gfx/ipc/GfxMessageUtils.h | 4 +- gfx/layers/FrameMetrics.h | 29 +++++++------ gfx/layers/LayersLogging.cpp | 2 +- gfx/layers/apz/src/APZCTreeManager.cpp | 13 ++---- gfx/layers/apz/src/AsyncPanZoomController.cpp | 43 +++++++------------ gfx/layers/apz/util/APZCCallbackHelper.cpp | 19 +++++--- gfx/layers/client/ClientTiledPaintedLayer.cpp | 4 +- gfx/layers/client/TiledContentClient.cpp | 11 ++--- .../composite/AsyncCompositionManager.cpp | 13 +++--- .../composite/LayerManagerComposite.cpp | 2 +- .../gtest/TestAsyncPanZoomController.cpp | 2 +- layout/base/nsDisplayList.cpp | 4 +- layout/base/nsLayoutUtils.cpp | 2 +- 14 files changed, 75 insertions(+), 83 deletions(-) diff --git a/dom/ipc/TabChild.cpp b/dom/ipc/TabChild.cpp index 07ac0b840bf6..382d55aab397 100644 --- a/dom/ipc/TabChild.cpp +++ b/dom/ipc/TabChild.cpp @@ -250,7 +250,7 @@ TabChildBase::InitializeRootMetrics() mLastRootMetrics.GetZoom() / mLastRootMetrics.mDevPixelsPerCSSPixel * ScreenToLayerScale(1); // This is the root layer, so the cumulative resolution is the same // as the resolution. - mLastRootMetrics.mPresShellResolution = mLastRootMetrics.mCumulativeResolution / LayoutDeviceToParentLayerScale(1); + mLastRootMetrics.mResolution = mLastRootMetrics.mCumulativeResolution / LayoutDeviceToParentLayerScale(1); mLastRootMetrics.SetScrollOffset(CSSPoint(0, 0)); TABC_LOG("After InitializeRootMetrics, mLastRootMetrics is %s\n", @@ -417,8 +417,8 @@ TabChildBase::HandlePossibleViewportChange(const ScreenIntSize& aOldScreenSize) metrics.mCumulativeResolution = metrics.GetZoom() / metrics.mDevPixelsPerCSSPixel * ScreenToLayerScale(1); // This is the root layer, so the cumulative resolution is the same // as the resolution. - metrics.mPresShellResolution = metrics.mCumulativeResolution / LayoutDeviceToParentLayerScale(1); - utils->SetResolution(metrics.mPresShellResolution.scale, metrics.mPresShellResolution.scale); + metrics.mResolution = metrics.mCumulativeResolution / LayoutDeviceToParentLayerScale(1); + utils->SetResolution(metrics.mResolution.scale, metrics.mResolution.scale); CSSSize scrollPort = metrics.CalculateCompositedSizeInCssPixels(); utils->SetScrollPositionClampingScrollPortSize(scrollPort.width, scrollPort.height); @@ -907,8 +907,8 @@ TabChild::Observe(nsISupports *aSubject, // until we we get an inner size. if (HasValidInnerSize()) { InitializeRootMetrics(); - utils->SetResolution(mLastRootMetrics.mPresShellResolution.scale, - mLastRootMetrics.mPresShellResolution.scale); + utils->SetResolution(mLastRootMetrics.mResolution.scale, + mLastRootMetrics.mResolution.scale); HandlePossibleViewportChange(mInnerSize); } } diff --git a/gfx/ipc/GfxMessageUtils.h b/gfx/ipc/GfxMessageUtils.h index b62c2a57839e..a62ada5faafc 100644 --- a/gfx/ipc/GfxMessageUtils.h +++ b/gfx/ipc/GfxMessageUtils.h @@ -741,7 +741,7 @@ struct ParamTraits WriteParam(aMsg, aParam.mRootCompositionSize); WriteParam(aMsg, aParam.mScrollId); WriteParam(aMsg, aParam.mScrollParentId); - WriteParam(aMsg, aParam.mPresShellResolution); + WriteParam(aMsg, aParam.mResolution); WriteParam(aMsg, aParam.mCumulativeResolution); WriteParam(aMsg, aParam.mZoom); WriteParam(aMsg, aParam.mDevPixelsPerCSSPixel); @@ -783,7 +783,7 @@ struct ParamTraits ReadParam(aMsg, aIter, &aResult->mRootCompositionSize) && ReadParam(aMsg, aIter, &aResult->mScrollId) && ReadParam(aMsg, aIter, &aResult->mScrollParentId) && - ReadParam(aMsg, aIter, &aResult->mPresShellResolution) && + ReadParam(aMsg, aIter, &aResult->mResolution) && ReadParam(aMsg, aIter, &aResult->mCumulativeResolution) && ReadParam(aMsg, aIter, &aResult->mZoom) && ReadParam(aMsg, aIter, &aResult->mDevPixelsPerCSSPixel) && diff --git a/gfx/layers/FrameMetrics.h b/gfx/layers/FrameMetrics.h index 02bedfbaeb71..018e24f6537a 100644 --- a/gfx/layers/FrameMetrics.h +++ b/gfx/layers/FrameMetrics.h @@ -76,7 +76,7 @@ public: , mDisplayPort(0, 0, 0, 0) , mCriticalDisplayPort(0, 0, 0, 0) , mScrollableRect(0, 0, 0, 0) - , mPresShellResolution(1) + , mResolution(1) , mCumulativeResolution(1) , mTransformScale(1) , mDevPixelsPerCSSPixel(1) @@ -114,7 +114,7 @@ public: mCriticalDisplayPort.IsEqualEdges(aOther.mCriticalDisplayPort) && mViewport.IsEqualEdges(aOther.mViewport) && mScrollableRect.IsEqualEdges(aOther.mScrollableRect) && - mPresShellResolution == aOther.mPresShellResolution && + mResolution == aOther.mResolution && mCumulativeResolution == aOther.mCumulativeResolution && mDevPixelsPerCSSPixel == aOther.mDevPixelsPerCSSPixel && mMayHaveTouchListeners == aOther.mMayHaveTouchListeners && @@ -171,10 +171,14 @@ public: return mCumulativeResolution * mDevPixelsPerCSSPixel; } - // Get the amount by which this frame has been zoomed since the last repaint. - LayerToScreenScale GetAsyncZoom() const + LayerPoint GetScrollOffsetInLayerPixels() const { - return mZoom / LayersPixelsPerCSSPixel(); + return GetScrollOffset() * LayersPixelsPerCSSPixel(); + } + + LayoutDeviceToParentLayerScale GetParentResolution() const + { + return mCumulativeResolution / mResolution; } // Ensure the scrollableRect is at least as big as the compositionBounds @@ -339,17 +343,14 @@ public: // The following metrics are dimensionless. // - // The pres-shell resolution that has been induced on the document containing - // this scroll frame as a result of zooming this scroll frame (whether via - // user action, or choosing an initial zoom level on page load). This can - // only be different from 1.0 for frames that are zoomable, which currently - // is just the root content document's root scroll frame (mIsRoot = true). - ParentLayerToLayerScale mPresShellResolution; + // The incremental resolution that the current frame has been painted at + // relative to the parent frame's resolution. This information is provided + // by Gecko at layout/paint time. + ParentLayerToLayerScale mResolution; // The cumulative resolution that the current frame has been painted at. - // This is the product of the pres-shell resolutions of the document - // containing this scroll frame and its ancestors, and any css-driven - // resolution. This information is provided by Gecko at layout/paint time. + // This is the product of our mResolution and the mResolutions of our parent frames. + // This information is provided by Gecko at layout/paint time. LayoutDeviceToLayerScale mCumulativeResolution; // TODO(botond): This is now always 1 and should be removed (see bug 1055741). diff --git a/gfx/layers/LayersLogging.cpp b/gfx/layers/LayersLogging.cpp index 37708bf26d05..8aaf324d3efb 100644 --- a/gfx/layers/LayersLogging.cpp +++ b/gfx/layers/LayersLogging.cpp @@ -159,7 +159,7 @@ AppendToString(std::stringstream& aStream, const FrameMetrics& m, AppendToString(aStream, m.GetRootCompositionSize(), " rcs="); AppendToString(aStream, m.GetViewport(), " v="); aStream << nsPrintfCString(" z=(ld=%.3f r=%.3f cr=%.3f z=%.3f ts=%.3f)", - m.mDevPixelsPerCSSPixel.scale, m.mPresShellResolution.scale, + m.mDevPixelsPerCSSPixel.scale, m.mResolution.scale, m.mCumulativeResolution.scale, m.GetZoom().scale, m.mTransformScale.scale).get(); aStream << nsPrintfCString(" u=(%d %d %lu)", diff --git a/gfx/layers/apz/src/APZCTreeManager.cpp b/gfx/layers/apz/src/APZCTreeManager.cpp index f1373a67ed3c..0184ee30afb7 100644 --- a/gfx/layers/apz/src/APZCTreeManager.cpp +++ b/gfx/layers/apz/src/APZCTreeManager.cpp @@ -197,17 +197,12 @@ ComputeTouchSensitiveRegion(GeckoContentController* aController, ParentLayerRect visible(aMetrics.mCompositionBounds); CSSRect touchSensitiveRegion; if (aController->GetTouchSensitiveRegion(&touchSensitiveRegion)) { - // Here we assume 'touchSensitiveRegion' is in the CSS pixels of the - // parent frame. To convert it to ParentLayer pixels, we therefore need - // the cumulative resolution of the parent frame. We approximate this as - // the quotient of our cumulative resolution and our pres shell resolution; - // this approximation may not be accurate in the presence of a css-driven - // resolution. - LayoutDeviceToParentLayerScale parentCumulativeResolution = - aMetrics.mCumulativeResolution / aMetrics.mPresShellResolution; + // Note: we assume here that touchSensitiveRegion is in the CSS pixels + // of our parent layer, which makes this coordinate conversion + // correct. visible = visible.Intersect(touchSensitiveRegion * aMetrics.mDevPixelsPerCSSPixel - * parentCumulativeResolution); + * aMetrics.GetParentResolution()); } // Not sure what rounding option is the most correct here, but if we ever diff --git a/gfx/layers/apz/src/AsyncPanZoomController.cpp b/gfx/layers/apz/src/AsyncPanZoomController.cpp index a8f85334b9e0..e20a26a1ede1 100644 --- a/gfx/layers/apz/src/AsyncPanZoomController.cpp +++ b/gfx/layers/apz/src/AsyncPanZoomController.cpp @@ -2588,8 +2588,9 @@ ViewTransform AsyncPanZoomController::GetCurrentAsyncTransform() const { } } - ParentLayerToScreenScale scale = mFrameMetrics.mPresShellResolution // non-transient portion - * mFrameMetrics.GetAsyncZoom(); // transient portion + ParentLayerToScreenScale scale = mFrameMetrics.GetZoom() + / mLastContentPaintMetrics.mDevPixelsPerCSSPixel + / mFrameMetrics.GetParentResolution(); ScreenPoint translation = (currentScrollOffset - lastPaintScrollOffset) * mFrameMetrics.GetZoom(); @@ -2598,27 +2599,24 @@ ViewTransform AsyncPanZoomController::GetCurrentAsyncTransform() const { Matrix4x4 AsyncPanZoomController::GetNontransientAsyncTransform() const { ReentrantMonitorAutoEnter lock(mMonitor); - return Matrix4x4::Scaling(mLastContentPaintMetrics.mPresShellResolution.scale, - mLastContentPaintMetrics.mPresShellResolution.scale, + return Matrix4x4::Scaling(mLastContentPaintMetrics.mResolution.scale, + mLastContentPaintMetrics.mResolution.scale, 1.0f); } Matrix4x4 AsyncPanZoomController::GetTransformToLastDispatchedPaint() const { ReentrantMonitorAutoEnter lock(mMonitor); + // Technically we should be taking the scroll delta in the coordinate space + // of transformed layer pixels (i.e. this layer's LayerPixels, with the layer + // transform applied). However in the absence of actual CSS transforms, we + // can use the parent-layer space instead. + // When we fix bug 993525 and properly support CSS transforms we might have + // to revisit this. ParentLayerPoint scrollChange = (mLastContentPaintMetrics.GetScrollOffset() - mLastDispatchedPaintMetrics.GetScrollOffset()) * mLastContentPaintMetrics.mDevPixelsPerCSSPixel - * mLastContentPaintMetrics.mCumulativeResolution - // This transform ("LD" in the terminology of the comment above - // GetScreenToApzcTransform() in APZCTreeManager.h) is applied in a - // coordinate space that includes the APZC's CSS transform ("LC"). - // This CSS transform is the identity unless this APZC sets a pres-shell - // resolution, in which case the transform has a post-scale that cancels - // out the pres-shell resolution. We simulate applying the "LC" transform - // by dividing by the pres-shell resolution. This will go away once - // bug 1076192 is fixed. - / mLastContentPaintMetrics.mPresShellResolution; + * mLastContentPaintMetrics.GetParentResolution(); float zoomChange = mLastContentPaintMetrics.GetZoom().scale / mLastDispatchedPaintMetrics.GetZoom().scale; @@ -2712,18 +2710,9 @@ void AsyncPanZoomController::NotifyLayersUpdated(const FrameMetrics& aLayerMetri if (FuzzyEqualsAdditive(mFrameMetrics.mCompositionBounds.width, aLayerMetrics.mCompositionBounds.width) && mFrameMetrics.mDevPixelsPerCSSPixel == aLayerMetrics.mDevPixelsPerCSSPixel) { - // Any change to the pres shell resolution was requested by APZ and is - // already included in our zoom; however, other components of the - // cumulative resolution (a parent document's pres-shell resolution, or - // the css-driven resolution) may have changed, and we need to update - // our zoom to reflect that. Note that we can't just take - // aLayerMetrics.mZoom because the APZ may have additional async zoom - // since the repaint request. - float totalResolutionChange = aLayerMetrics.mCumulativeResolution.scale - / mFrameMetrics.mCumulativeResolution.scale; - float presShellResolutionChange = aLayerMetrics.mPresShellResolution.scale - / mFrameMetrics.mPresShellResolution.scale; - mFrameMetrics.ZoomBy(totalResolutionChange / presShellResolutionChange); + float parentResolutionChange = aLayerMetrics.GetParentResolution().scale + / mFrameMetrics.GetParentResolution().scale; + mFrameMetrics.ZoomBy(parentResolutionChange); } else { // Take the new zoom as either device scale or composition width or both // got changed (e.g. due to orientation change). @@ -2736,7 +2725,7 @@ void AsyncPanZoomController::NotifyLayersUpdated(const FrameMetrics& aLayerMetri } mFrameMetrics.mCompositionBounds = aLayerMetrics.mCompositionBounds; mFrameMetrics.SetRootCompositionSize(aLayerMetrics.GetRootCompositionSize()); - mFrameMetrics.mPresShellResolution = aLayerMetrics.mPresShellResolution; + mFrameMetrics.mResolution = aLayerMetrics.mResolution; mFrameMetrics.mCumulativeResolution = aLayerMetrics.mCumulativeResolution; mFrameMetrics.SetHasScrollgrab(aLayerMetrics.GetHasScrollgrab()); diff --git a/gfx/layers/apz/util/APZCCallbackHelper.cpp b/gfx/layers/apz/util/APZCCallbackHelper.cpp index 8965caa980b3..61a2724101ab 100644 --- a/gfx/layers/apz/util/APZCCallbackHelper.cpp +++ b/gfx/layers/apz/util/APZCCallbackHelper.cpp @@ -142,12 +142,19 @@ APZCCallbackHelper::UpdateRootFrame(nsIDOMWindowUtils* aUtils, aMetrics.SetScrollOffset(actualScrollOffset); - // The pres shell resolution is updated by the the async zoom since the - // last paint. The ScreenToLayerScale(1.0f) reflects this async zoom being - // turned into a "sync" zoom during the repaint. - ParentLayerToLayerScale presShellResolution = aMetrics.mPresShellResolution - * aMetrics.GetAsyncZoom() - * ScreenToLayerScale(1.0f); + // The mZoom variable on the frame metrics stores the CSS-to-screen scale for this + // frame. This scale includes all of the (cumulative) resolutions set on the presShells + // from the root down to this frame. However, when setting the resolution, we only + // want the piece of the resolution that corresponds to this presShell, rather than + // all of the cumulative stuff, so we need to divide out the parent resolutions. + // Finally, we multiply by a ScreenToLayerScale of 1.0f because the goal here is to + // take the async zoom calculated by the APZC and tell gecko about it (turning it into + // a "sync" zoom) which will update the resolution at which the layer is painted. + ParentLayerToLayerScale presShellResolution = + aMetrics.GetZoom() + / aMetrics.mDevPixelsPerCSSPixel + / aMetrics.GetParentResolution() + * ScreenToLayerScale(1.0f); aUtils->SetResolution(presShellResolution.scale, presShellResolution.scale); // Finally, we set the displayport. diff --git a/gfx/layers/client/ClientTiledPaintedLayer.cpp b/gfx/layers/client/ClientTiledPaintedLayer.cpp index a2691c459ed5..a4005080ad7f 100644 --- a/gfx/layers/client/ClientTiledPaintedLayer.cpp +++ b/gfx/layers/client/ClientTiledPaintedLayer.cpp @@ -75,7 +75,7 @@ GetTransformToAncestorsParentLayer(Layer* aStart, const LayerMetricsWrapper& aAn // If the layer has a non-transient async transform then we need to apply it here // because it will get applied by the APZ in the compositor as well const FrameMetrics& metrics = iter.Metrics(); - transform.PostScale(metrics.mPresShellResolution.scale, metrics.mPresShellResolution.scale, 1.f); + transform.PostScale(metrics.mResolution.scale, metrics.mResolution.scale, 1.f); } return transform; } @@ -167,7 +167,7 @@ ClientTiledPaintedLayer::BeginPaint() // Store the resolution from the displayport ancestor layer. Because this is Gecko-side, // before any async transforms have occurred, we can use the zoom for this. mPaintData.mResolution = displayportMetrics.GetZoomToParent(); - TILING_LOG("TILING %p: Resolution %f\n", this, mPaintData.mPresShellResolution.scale); + TILING_LOG("TILING %p: Resolution %f\n", this, mPaintData.mResolution.scale); // Store the applicable composition bounds in this layer's Layer units. mPaintData.mTransformToCompBounds = diff --git a/gfx/layers/client/TiledContentClient.cpp b/gfx/layers/client/TiledContentClient.cpp index fb165b30b942..90fce04e66e5 100644 --- a/gfx/layers/client/TiledContentClient.cpp +++ b/gfx/layers/client/TiledContentClient.cpp @@ -150,8 +150,9 @@ ComputeViewTransform(const FrameMetrics& aContentMetrics, const FrameMetrics& aC // but with aContentMetrics used in place of mLastContentPaintMetrics, because they // should be equivalent, modulo race conditions while transactions are inflight. - ParentLayerToScreenScale scale = aCompositorMetrics.mPresShellResolution - * aCompositorMetrics.GetAsyncZoom(); + ParentLayerToScreenScale scale = aCompositorMetrics.GetZoom() + / aContentMetrics.mDevPixelsPerCSSPixel + / aCompositorMetrics.GetParentResolution(); ScreenPoint translation = (aCompositorMetrics.GetScrollOffset() - aContentMetrics.GetScrollOffset()) * aCompositorMetrics.GetZoom(); return ViewTransform(scale, -translation); @@ -1310,7 +1311,7 @@ ClientTiledLayerBuffer::ValidateTile(TileClient aTile, #ifdef GFX_TILEDLAYER_DEBUG_OVERLAY DrawDebugOverlay(drawTarget, aTileOrigin.x * mResolution, - aTileOrigin.y * mPresShellResolution, GetTileLength(), GetTileLength()); + aTileOrigin.y * mResolution, GetTileLength(), GetTileLength()); #endif ctxt = nullptr; @@ -1366,8 +1367,8 @@ GetCompositorSideCompositionBounds(const LayerMetricsWrapper& aScrollAncestor, const ViewTransform& aAPZTransform) { Matrix4x4 nonTransientAPZUntransform = Matrix4x4::Scaling( - aScrollAncestor.Metrics().mPresShellResolution.scale, - aScrollAncestor.Metrics().mPresShellResolution.scale, + aScrollAncestor.Metrics().mResolution.scale, + aScrollAncestor.Metrics().mResolution.scale, 1.f); nonTransientAPZUntransform.Invert(); diff --git a/gfx/layers/composite/AsyncCompositionManager.cpp b/gfx/layers/composite/AsyncCompositionManager.cpp index f19aded3e80c..22bf15c8c466 100644 --- a/gfx/layers/composite/AsyncCompositionManager.cpp +++ b/gfx/layers/composite/AsyncCompositionManager.cpp @@ -718,7 +718,7 @@ ApplyAsyncTransformToScrollbarForContent(Layer* aScrollbar, // aScrollbarIsDescendant hunk below we unapply the entire async // transform, which includes the nontransientasync transform and would // normally account for the resolution. - scale *= metrics.mPresShellResolution.scale; + scale *= metrics.mResolution.scale; } scrollbarTransform.PostScale(1.f, 1.f / transientTransform._22, 1.f); scrollbarTransform.PostTranslate(0, -transientTransform._42 * scale, 0); @@ -726,7 +726,7 @@ ApplyAsyncTransformToScrollbarForContent(Layer* aScrollbar, if (aScrollbar->GetScrollbarDirection() == Layer::HORIZONTAL) { float scale = metrics.CalculateCompositedSizeInCssPixels().width / metrics.mScrollableRect.width; if (aScrollbarIsDescendant) { - scale *= metrics.mPresShellResolution.scale; + scale *= metrics.mResolution.scale; } scrollbarTransform.PostScale(1.f / transientTransform._11, 1.f, 1.f); scrollbarTransform.PostTranslate(-transientTransform._41 * scale, 0, 0); @@ -888,10 +888,9 @@ AsyncCompositionManager::TransformScrollableLayer(Layer* aLayer) if (metrics.IsScrollable()) { geckoScroll = metrics.GetScrollOffset() * userZoom; } - - LayerToScreenScale asyncZoom = userZoom / metrics.LayersPixelsPerCSSPixel(); - ParentLayerToScreenScale scale = metrics.mPresShellResolution - * asyncZoom; + ParentLayerToScreenScale scale = userZoom + / metrics.mDevPixelsPerCSSPixel + / metrics.GetParentResolution(); ScreenPoint translation = userScroll - geckoScroll; Matrix4x4 treeTransform = ViewTransform(scale, -translation); @@ -901,7 +900,7 @@ AsyncCompositionManager::TransformScrollableLayer(Layer* aLayer) // Apply resolution scaling to the old transform - the layer tree as it is // doesn't have the necessary transform to display correctly. - oldTransform.PreScale(metrics.mPresShellResolution.scale, metrics.mPresShellResolution.scale, 1); + oldTransform.PreScale(metrics.mResolution.scale, metrics.mResolution.scale, 1); // Make sure that overscroll and under-zoom are represented in the old // transform so that fixed position content moves and scales accordingly. diff --git a/gfx/layers/composite/LayerManagerComposite.cpp b/gfx/layers/composite/LayerManagerComposite.cpp index dd6c9455160d..b8622aae064b 100644 --- a/gfx/layers/composite/LayerManagerComposite.cpp +++ b/gfx/layers/composite/LayerManagerComposite.cpp @@ -907,7 +907,7 @@ LayerManagerComposite::ComputeRenderIntegrity() Layer* rootScrollable = rootScrollableLayers[0]; const FrameMetrics& metrics = LayerMetricsWrapper::TopmostScrollableMetrics(rootScrollable); Matrix4x4 transform = rootScrollable->GetEffectiveTransform(); - transform.PostScale(metrics.mPresShellResolution, metrics.mPresShellResolution, 1); + transform.PostScale(metrics.mResolution.scale, metrics.mResolution.scale, 1); // Clip the screen rect to the document bounds Rect documentBounds = diff --git a/gfx/tests/gtest/TestAsyncPanZoomController.cpp b/gfx/tests/gtest/TestAsyncPanZoomController.cpp index d47cd48ff914..5a4de3027f5a 100644 --- a/gfx/tests/gtest/TestAsyncPanZoomController.cpp +++ b/gfx/tests/gtest/TestAsyncPanZoomController.cpp @@ -778,7 +778,7 @@ TEST_F(APZCBasicTester, ComplexTransform) { metrics.SetScrollOffset(CSSPoint(10, 10)); metrics.mScrollableRect = CSSRect(0, 0, 50, 50); metrics.mCumulativeResolution = LayoutDeviceToLayerScale(2); - metrics.mPresShellResolution = ParentLayerToLayerScale(2); + metrics.mResolution = ParentLayerToLayerScale(2); metrics.SetZoom(CSSToScreenScale(6)); metrics.mDevPixelsPerCSSPixel = CSSToLayoutDeviceScale(3); metrics.SetScrollId(FrameMetrics::START_SCROLL_ID); diff --git a/layout/base/nsDisplayList.cpp b/layout/base/nsDisplayList.cpp index a0f2b71bdec4..3045f2c6c9d6 100644 --- a/layout/base/nsDisplayList.cpp +++ b/layout/base/nsDisplayList.cpp @@ -724,10 +724,10 @@ nsDisplayScrollLayer::ComputeFrameMetrics(nsIFrame* aForFrame, // Only the root scrollable frame for a given presShell should pick up // the presShell's resolution. All the other frames are 1.0. if (aScrollFrame == presShell->GetRootScrollFrame()) { - metrics.mPresShellResolution = ParentLayerToLayerScale(presShell->GetXResolution(), + metrics.mResolution = ParentLayerToLayerScale(presShell->GetXResolution(), presShell->GetYResolution()); } else { - metrics.mPresShellResolution = ParentLayerToLayerScale(1.0f); + metrics.mResolution = ParentLayerToLayerScale(1.0f); } // The cumulative resolution is the resolution at which the scroll frame's // content is actually rendered. It includes the pres shell resolutions of diff --git a/layout/base/nsLayoutUtils.cpp b/layout/base/nsLayoutUtils.cpp index 490342cc4b0a..6ccf662a16b4 100644 --- a/layout/base/nsLayoutUtils.cpp +++ b/layout/base/nsLayoutUtils.cpp @@ -2802,7 +2802,7 @@ CalculateFrameMetricsForDisplayPort(nsIFrame* aScrollFrame, * nsLayoutUtils::GetTransformToAncestorScale(aScrollFrame).width); metrics.mDevPixelsPerCSSPixel = deviceScale; - metrics.mPresShellResolution = resolution; + metrics.mResolution = resolution; metrics.mCumulativeResolution = cumulativeResolution; metrics.SetZoom(deviceScale * cumulativeResolution * LayerToScreenScale(1)); From 8894f4319e14d4345c083fe7dda78a11f267088c Mon Sep 17 00:00:00 2001 From: "Carsten \"Tomcat\" Book" Date: Thu, 13 Nov 2014 11:47:57 +0100 Subject: [PATCH 76/80] Backed out changeset fbb9dc943109 (bug 1076163) for Android 4.0 Crashes on a CLOSED TREE --- dom/base/nsDOMWindowUtils.cpp | 10 +- dom/interfaces/base/nsIDOMWindowUtils.idl | 2 +- gfx/ipc/GfxMessageUtils.h | 2 - gfx/layers/FrameMetrics.h | 44 +++----- gfx/layers/apz/src/APZCTreeManager.cpp | 2 +- gfx/layers/apz/src/APZCTreeManager.h | 2 +- gfx/layers/apz/src/AsyncPanZoomController.cpp | 14 +-- gfx/layers/apz/src/AsyncPanZoomController.h | 2 +- gfx/layers/apz/util/APZCCallbackHelper.cpp | 12 +-- layout/base/Units.h | 12 --- layout/base/nsDisplayList.cpp | 23 ++-- layout/base/nsLayoutUtils.cpp | 101 +++++++----------- layout/base/nsLayoutUtils.h | 14 +-- layout/generic/nsGfxScrollFrame.cpp | 2 +- 14 files changed, 88 insertions(+), 154 deletions(-) diff --git a/dom/base/nsDOMWindowUtils.cpp b/dom/base/nsDOMWindowUtils.cpp index 9e20e6542b59..5f5c3d76e943 100644 --- a/dom/base/nsDOMWindowUtils.cpp +++ b/dom/base/nsDOMWindowUtils.cpp @@ -444,11 +444,11 @@ nsDOMWindowUtils::SetDisplayPortMarginsForElement(float aLeftMargin, } // Note order change of arguments between our function signature and - // ScreenMargin constructor. - ScreenMargin displayportMargins(aTopMargin, - aRightMargin, - aBottomMargin, - aLeftMargin); + // LayerMargin constructor. + LayerMargin displayportMargins(aTopMargin, + aRightMargin, + aBottomMargin, + aLeftMargin); nsLayoutUtils::SetDisplayPortMargins(content, presShell, displayportMargins, aAlignmentX, aAlignmentY, aPriority); diff --git a/dom/interfaces/base/nsIDOMWindowUtils.idl b/dom/interfaces/base/nsIDOMWindowUtils.idl index 0681ce78cea8..c42881bfe937 100644 --- a/dom/interfaces/base/nsIDOMWindowUtils.idl +++ b/dom/interfaces/base/nsIDOMWindowUtils.idl @@ -181,7 +181,7 @@ interface nsIDOMWindowUtils : nsISupports { * that each edge is located at a multiple of the "alignment" value. * * Note that both the margin values and alignment are treated as values in - * ScreenPixels. Refer to layout/base/Units.h for a description of this unit. + * LayerPixels. Refer to layout/base/Units.h for a description of this unit. * The base rect values are in app units. */ void setDisplayPortMarginsForElement(in float aLeftMargin, diff --git a/gfx/ipc/GfxMessageUtils.h b/gfx/ipc/GfxMessageUtils.h index a62ada5faafc..574d70eaa9a3 100644 --- a/gfx/ipc/GfxMessageUtils.h +++ b/gfx/ipc/GfxMessageUtils.h @@ -753,7 +753,6 @@ struct ParamTraits WriteParam(aMsg, aParam.mUpdateScrollOffset); WriteParam(aMsg, aParam.mScrollGeneration); WriteParam(aMsg, aParam.mTransformScale); - WriteParam(aMsg, aParam.mExtraResolution); WriteParam(aMsg, aParam.mBackgroundColor); WriteParam(aMsg, aParam.mDoSmoothScroll); WriteParam(aMsg, aParam.mSmoothScrollOffset); @@ -795,7 +794,6 @@ struct ParamTraits ReadParam(aMsg, aIter, &aResult->mUpdateScrollOffset) && ReadParam(aMsg, aIter, &aResult->mScrollGeneration) && ReadParam(aMsg, aIter, &aResult->mTransformScale) && - ReadParam(aMsg, aIter, &aResult->mExtraResolution) && ReadParam(aMsg, aIter, &aResult->mBackgroundColor) && ReadParam(aMsg, aIter, &aResult->mDoSmoothScroll) && ReadParam(aMsg, aIter, &aResult->mSmoothScrollOffset) && diff --git a/gfx/layers/FrameMetrics.h b/gfx/layers/FrameMetrics.h index 018e24f6537a..699e4adde674 100644 --- a/gfx/layers/FrameMetrics.h +++ b/gfx/layers/FrameMetrics.h @@ -97,7 +97,6 @@ public: , mUseDisplayPortMargins(false) , mPresShellId(-1) , mViewport(0, 0, 0, 0) - , mExtraResolution(1) , mBackgroundColor(0, 0, 0, 0) { } @@ -127,7 +126,6 @@ public: mSmoothScrollOffset == aOther.mSmoothScrollOffset && mHasScrollgrab == aOther.mHasScrollgrab && mUpdateScrollOffset == aOther.mUpdateScrollOffset && - mExtraResolution == aOther.mExtraResolution && mBackgroundColor == aOther.mBackgroundColor && mDoSmoothScroll == aOther.mDoSmoothScroll; } @@ -154,18 +152,6 @@ public: return mScrollId != NULL_SCROLL_ID; } - CSSToScreenScale DisplayportPixelsPerCSSPixel() const - { - // Note: use 'mZoom * ScreenToLayerScale(1.0f)' as the CSS-to-Layer scale - // instead of LayersPixelsPerCSSPixel(), because displayport calculations - // are done in the context of a repaint request, where we ask Layout to - // repaint at a new resolution that includes any async zoom. Until this - // repaint request is processed, LayersPixelsPerCSSPixel() does not yet - // include the async zoom, but it will when the displayport is interpreted - // for the repaint. - return mZoom * ScreenToLayerScale(1.0f) / mExtraResolution; - } - CSSToLayerScale LayersPixelsPerCSSPixel() const { return mCumulativeResolution * mDevPixelsPerCSSPixel; @@ -353,7 +339,15 @@ public: // This information is provided by Gecko at layout/paint time. LayoutDeviceToLayerScale mCumulativeResolution; - // TODO(botond): This is now always 1 and should be removed (see bug 1055741). + // The conversion factor between local screen pixels (the coordinate + // system in which APZCs receive input events) and our parent layer's + // layer pixels (the coordinate system of mCompositionBounds). + // This consists of the scale of the local CSS transform and the + // nontransient async transform. + // TODO: APZ does not currently work well if there is a CSS transform + // on the layer being scrolled that's not just a scale that's + // the same in both directions. When we fix this, mTransformScale + // will probably need to turn into a matrix. ScreenToParentLayerScale mTransformScale; // The conversion factor between CSS pixels and device pixels for this frame. @@ -470,12 +464,12 @@ public: return mRootCompositionSize; } - void SetDisplayPortMargins(const ScreenMargin& aDisplayPortMargins) + void SetDisplayPortMargins(const LayerMargin& aDisplayPortMargins) { mDisplayPortMargins = aDisplayPortMargins; } - const ScreenMargin& GetDisplayPortMargins() const + const LayerMargin& GetDisplayPortMargins() const { return mDisplayPortMargins; } @@ -510,16 +504,6 @@ public: return mViewport; } - void SetExtraResolution(const ScreenToLayerScale& aExtraResolution) - { - mExtraResolution = aExtraResolution; - } - - ScreenToLayerScale GetExtraResolution() const - { - return mExtraResolution; - } - const gfxRGBA& GetBackgroundColor() const { return mBackgroundColor; @@ -621,7 +605,7 @@ private: // A display port expressed as layer margins that apply to the rect of what // is drawn of the scrollable element. - ScreenMargin mDisplayPortMargins; + LayerMargin mDisplayPortMargins; // If this is true then we use the display port margins on this metrics, // otherwise use the display port rect. @@ -640,10 +624,6 @@ private: // meaningless and invalid. CSSRect mViewport; - // The extra resolution at which content in this scroll frame is drawn beyond - // that necessary to draw one Layer pixel per Screen pixel. - ScreenToLayerScale mExtraResolution; - // The background color to use when overscrolling. gfxRGBA mBackgroundColor; diff --git a/gfx/layers/apz/src/APZCTreeManager.cpp b/gfx/layers/apz/src/APZCTreeManager.cpp index 0184ee30afb7..4ce56926f6d0 100644 --- a/gfx/layers/apz/src/APZCTreeManager.cpp +++ b/gfx/layers/apz/src/APZCTreeManager.cpp @@ -61,7 +61,7 @@ struct APZCTreeManager::TreeBuildingState { std::map mApzcMap; }; -/*static*/ const ScreenMargin +/*static*/ const LayerMargin APZCTreeManager::CalculatePendingDisplayPort( const FrameMetrics& aFrameMetrics, const ScreenPoint& aVelocity, diff --git a/gfx/layers/apz/src/APZCTreeManager.h b/gfx/layers/apz/src/APZCTreeManager.h index 16c34f4ab84a..c24036d1aafb 100644 --- a/gfx/layers/apz/src/APZCTreeManager.h +++ b/gfx/layers/apz/src/APZCTreeManager.h @@ -245,7 +245,7 @@ public: * function simply delegates to that one, so that non-layers code * never needs to include AsyncPanZoomController.h */ - static const ScreenMargin CalculatePendingDisplayPort( + static const LayerMargin CalculatePendingDisplayPort( const FrameMetrics& aFrameMetrics, const ScreenPoint& aVelocity, double aEstimatedPaintDuration); diff --git a/gfx/layers/apz/src/AsyncPanZoomController.cpp b/gfx/layers/apz/src/AsyncPanZoomController.cpp index e20a26a1ede1..e58a3d6081d7 100644 --- a/gfx/layers/apz/src/AsyncPanZoomController.cpp +++ b/gfx/layers/apz/src/AsyncPanZoomController.cpp @@ -2198,7 +2198,7 @@ RedistributeDisplayPortExcess(CSSSize& aDisplayPortSize, } /* static */ -const ScreenMargin AsyncPanZoomController::CalculatePendingDisplayPort( +const LayerMargin AsyncPanZoomController::CalculatePendingDisplayPort( const FrameMetrics& aFrameMetrics, const ScreenPoint& aVelocity, double aEstimatedPaintDuration) @@ -2240,7 +2240,9 @@ const ScreenMargin AsyncPanZoomController::CalculatePendingDisplayPort( cssMargins.right = displayPort.width - compositionSize.width - cssMargins.left; cssMargins.bottom = displayPort.height - compositionSize.height - cssMargins.top; - return cssMargins * aFrameMetrics.DisplayportPixelsPerCSSPixel(); + LayerMargin layerMargins = cssMargins * aFrameMetrics.LayersPixelsPerCSSPixel(); + + return layerMargins; } void AsyncPanZoomController::ScheduleComposite() { @@ -2318,8 +2320,8 @@ void AsyncPanZoomController::RequestContentRepaint(FrameMetrics& aFrameMetrics, // If we're trying to paint what we already think is painted, discard this // request since it's a pointless paint. - ScreenMargin marginDelta = (mLastPaintRequestMetrics.GetDisplayPortMargins() - - aFrameMetrics.GetDisplayPortMargins()); + LayerMargin marginDelta = mLastPaintRequestMetrics.GetDisplayPortMargins() + - aFrameMetrics.GetDisplayPortMargins(); if (fabsf(marginDelta.left) < EPSILON && fabsf(marginDelta.top) < EPSILON && fabsf(marginDelta.right) < EPSILON && @@ -2357,7 +2359,7 @@ GetDisplayPortRect(const FrameMetrics& aFrameMetrics) // changes then this might need to change too CSSRect baseRect(aFrameMetrics.GetScrollOffset(), aFrameMetrics.CalculateBoundedCompositedSizeInCssPixels()); - baseRect.Inflate(aFrameMetrics.GetDisplayPortMargins() / aFrameMetrics.DisplayportPixelsPerCSSPixel()); + baseRect.Inflate(aFrameMetrics.GetDisplayPortMargins() / aFrameMetrics.LayersPixelsPerCSSPixel()); return baseRect; } @@ -2692,7 +2694,7 @@ void AsyncPanZoomController::NotifyLayersUpdated(const FrameMetrics& aLayerMetri mLastDispatchedPaintMetrics = aLayerMetrics; ShareCompositorFrameMetrics(); - if (mFrameMetrics.GetDisplayPortMargins() != ScreenMargin()) { + if (mFrameMetrics.GetDisplayPortMargins() != LayerMargin()) { // A non-zero display port margin here indicates a displayport has // been set by a previous APZC for the content at this guid. The // scrollable rect may have changed since then, making the margins diff --git a/gfx/layers/apz/src/AsyncPanZoomController.h b/gfx/layers/apz/src/AsyncPanZoomController.h index 3a00acf6fa57..941f1c01786c 100644 --- a/gfx/layers/apz/src/AsyncPanZoomController.h +++ b/gfx/layers/apz/src/AsyncPanZoomController.h @@ -245,7 +245,7 @@ public: * checkerboard immediately. This includes a bunch of logic, including * algorithms to bias painting in the direction of the velocity. */ - static const ScreenMargin CalculatePendingDisplayPort( + static const LayerMargin CalculatePendingDisplayPort( const FrameMetrics& aFrameMetrics, const ScreenPoint& aVelocity, double aEstimatedPaintDuration); diff --git a/gfx/layers/apz/util/APZCCallbackHelper.cpp b/gfx/layers/apz/util/APZCCallbackHelper.cpp index 61a2724101ab..2c998fcc5299 100644 --- a/gfx/layers/apz/util/APZCCallbackHelper.cpp +++ b/gfx/layers/apz/util/APZCCallbackHelper.cpp @@ -35,10 +35,10 @@ AdjustDisplayPortForScrollDelta(mozilla::layers::FrameMetrics& aFrameMetrics, { // Correct the display-port by the difference between the requested scroll // offset and the resulting scroll offset after setting the requested value. - ScreenPoint shift = + LayerPoint shift = (aFrameMetrics.GetScrollOffset() - aActualScrollOffset) * - aFrameMetrics.DisplayportPixelsPerCSSPixel(); - ScreenMargin margins = aFrameMetrics.GetDisplayPortMargins(); + aFrameMetrics.LayersPixelsPerCSSPixel(); + LayerMargin margins = aFrameMetrics.GetDisplayPortMargins(); margins.left -= shift.x; margins.right += shift.x; margins.top -= shift.y; @@ -49,7 +49,7 @@ AdjustDisplayPortForScrollDelta(mozilla::layers::FrameMetrics& aFrameMetrics, static void RecenterDisplayPort(mozilla::layers::FrameMetrics& aFrameMetrics) { - ScreenMargin margins = aFrameMetrics.GetDisplayPortMargins(); + LayerMargin margins = aFrameMetrics.GetDisplayPortMargins(); margins.right = margins.left = margins.LeftRight() / 2; margins.top = margins.bottom = margins.TopBottom() / 2; aFrameMetrics.SetDisplayPortMargins(margins); @@ -170,7 +170,7 @@ APZCCallbackHelper::UpdateRootFrame(nsIDOMWindowUtils* aUtils, gfx::IntSize alignment = gfxPlatform::GetPlatform()->UseTiling() ? gfx::IntSize(gfxPrefs::LayersTileWidth(), gfxPrefs::LayersTileHeight()) : gfx::IntSize(0, 0); - ScreenMargin margins = aMetrics.GetDisplayPortMargins(); + LayerMargin margins = aMetrics.GetDisplayPortMargins(); aUtils->SetDisplayPortMarginsForElement(margins.left, margins.top, margins.right, @@ -219,7 +219,7 @@ APZCCallbackHelper::UpdateSubFrame(nsIContent* aContent, gfx::IntSize alignment = gfxPlatform::GetPlatform()->UseTiling() ? gfx::IntSize(gfxPrefs::LayersTileWidth(), gfxPrefs::LayersTileHeight()) : gfx::IntSize(0, 0); - ScreenMargin margins = aMetrics.GetDisplayPortMargins(); + LayerMargin margins = aMetrics.GetDisplayPortMargins(); utils->SetDisplayPortMarginsForElement(margins.left, margins.top, margins.right, diff --git a/layout/base/Units.h b/layout/base/Units.h index f0cd08c5971f..e82acc7d60ac 100644 --- a/layout/base/Units.h +++ b/layout/base/Units.h @@ -198,11 +198,6 @@ struct LayoutDevicePixel { NSAppUnitsToFloatPixels(aRect.height, float(aAppUnitsPerDevPixel))); } - static LayoutDevicePoint FromAppUnits(const nsPoint& aPoint, nscoord aAppUnitsPerDevPixel) { - return LayoutDevicePoint(NSAppUnitsToFloatPixels(aPoint.x, aAppUnitsPerDevPixel), - NSAppUnitsToFloatPixels(aPoint.y, aAppUnitsPerDevPixel)); - } - static LayoutDeviceIntPoint FromAppUnitsRounded(const nsPoint& aPoint, nscoord aAppUnitsPerDevPixel) { return LayoutDeviceIntPoint(NSAppUnitsToIntPixels(aPoint.x, aAppUnitsPerDevPixel), NSAppUnitsToIntPixels(aPoint.y, aAppUnitsPerDevPixel)); @@ -220,13 +215,6 @@ struct LayoutDevicePixel { return nsSize(aSize.width * aAppUnitsPerDevPixel, aSize.height * aAppUnitsPerDevPixel); } - - static nsRect ToAppUnits(const LayoutDeviceRect& aRect, nscoord aAppUnitsPerDevPixel) { - return nsRect(NSFloatPixelsToAppUnits(aRect.x, aAppUnitsPerDevPixel), - NSFloatPixelsToAppUnits(aRect.y, aAppUnitsPerDevPixel), - NSFloatPixelsToAppUnits(aRect.width, aAppUnitsPerDevPixel), - NSFloatPixelsToAppUnits(aRect.height, aAppUnitsPerDevPixel)); - } }; /* diff --git a/layout/base/nsDisplayList.cpp b/layout/base/nsDisplayList.cpp index 3045f2c6c9d6..d6aa96293c82 100644 --- a/layout/base/nsDisplayList.cpp +++ b/layout/base/nsDisplayList.cpp @@ -663,6 +663,7 @@ nsDisplayScrollLayer::ComputeFrameMetrics(nsIFrame* aForFrame, { nsPresContext* presContext = aForFrame->PresContext(); int32_t auPerDevPixel = presContext->AppUnitsPerDevPixel(); + LayoutDeviceToLayerScale resolution(aContainerParameters.mXScale, aContainerParameters.mYScale); nsIPresShell* presShell = presContext->GetPresShell(); FrameMetrics metrics; @@ -729,18 +730,18 @@ nsDisplayScrollLayer::ComputeFrameMetrics(nsIFrame* aForFrame, } else { metrics.mResolution = ParentLayerToLayerScale(1.0f); } - // The cumulative resolution is the resolution at which the scroll frame's - // content is actually rendered. It includes the pres shell resolutions of - // all the pres shells from here up to the root, as well as any css-driven - // resolution. We don't need to compute it as it's already stored in the - // container parameters. - metrics.mCumulativeResolution = LayoutDeviceToLayerScale(aContainerParameters.mXScale, - aContainerParameters.mYScale); - LayoutDeviceToScreenScale resolutionToScreen( - presShell->GetCumulativeResolution().width - * nsLayoutUtils::GetTransformToAncestorScale(aScrollFrame ? aScrollFrame : aForFrame).width); - metrics.SetExtraResolution(metrics.mCumulativeResolution / resolutionToScreen); + // For the cumulateive resolution, multiply the resolutions of all the + // presShells back up to the root + metrics.mCumulativeResolution = LayoutDeviceToLayerScale(1.0f); + nsIPresShell* curPresShell = presShell; + while (curPresShell != nullptr) { + ParentLayerToLayerScale presShellResolution(curPresShell->GetXResolution(), + curPresShell->GetYResolution()); + metrics.mCumulativeResolution.scale *= presShellResolution.scale; + nsPresContext* parentContext = curPresShell->GetPresContext()->GetParentPresContext(); + curPresShell = parentContext ? parentContext->GetPresShell() : nullptr; + } metrics.mDevPixelsPerCSSPixel = CSSToLayoutDeviceScale( (float)nsPresContext::AppUnitsPerCSSPixel() / auPerDevPixel); diff --git a/layout/base/nsLayoutUtils.cpp b/layout/base/nsLayoutUtils.cpp index 6ccf662a16b4..deb5e6881012 100644 --- a/layout/base/nsLayoutUtils.cpp +++ b/layout/base/nsLayoutUtils.cpp @@ -836,41 +836,32 @@ GetDisplayPortFromMarginsData(nsIContent* aContent, nsPresContext* presContext = frame->PresContext(); int32_t auPerDevPixel = presContext->AppUnitsPerDevPixel(); + gfxSize res = presContext->PresShell()->GetCumulativeResolution(); - LayoutDeviceToScreenScale res(presContext->PresShell()->GetCumulativeResolution().width - * nsLayoutUtils::GetTransformToAncestorScale(frame).width); - - // First convert the base rect to screen pixels - LayoutDeviceToScreenScale parentRes = res; + // First convert the base rect to layer pixels + gfxSize parentRes = res; if (isRoot) { // the base rect for root scroll frames is specified in the parent document // coordinate space, so it doesn't include the local resolution. gfxSize localRes = presContext->PresShell()->GetResolution(); - parentRes.scale /= localRes.width; + parentRes.width /= localRes.width; + parentRes.height /= localRes.height; } - ScreenRect screenRect = LayoutDeviceRect::FromAppUnits(base, auPerDevPixel) - * parentRes; + LayerRect layerRect(NSAppUnitsToFloatPixels(base.x, auPerDevPixel) * parentRes.width, + NSAppUnitsToFloatPixels(base.y, auPerDevPixel) * parentRes.height, + NSAppUnitsToFloatPixels(base.width, auPerDevPixel) * parentRes.width, + NSAppUnitsToFloatPixels(base.height, auPerDevPixel) * parentRes.height); // Expand the rect by the margins - screenRect.Inflate(aMarginsData->mMargins); + layerRect.Inflate(aMarginsData->mMargins); - // And then align it to the requested alignment. - // Note on the correctness of applying the alignment in Screen space: - // The correct space to apply the alignment in would be Layer space, but - // we don't necessarily know the scale to convert to Layer space at this - // point because Layout may not yet have chosen the resolution at which to - // render (it chooses that in FrameLayerBuilder, but this can be called - // during display list building). Therefore, we perform the alignment in - // Screen space, which basically assumes that Layout chose to render at - // screen resolution; since this is what Layout does most of the time, - // this is a good approximation. A proper solution would involve moving the - // choosing of the resolution to display-list building time. + // And then align it to the requested alignment if (aMarginsData->mAlignmentX > 0 || aMarginsData->mAlignmentY > 0) { // Inflate the rectangle by 1 so that we always push to the next tile // boundary. This is desirable to stop from having a rectangle with a // moving origin occasionally being smaller when it coincidentally lines // up to tile boundaries. - screenRect.Inflate(1); + layerRect.Inflate(1); // Avoid division by zero. if (aMarginsData->mAlignmentX == 0) { @@ -880,20 +871,23 @@ GetDisplayPortFromMarginsData(nsIContent* aContent, aMarginsData->mAlignmentY = 1; } - ScreenPoint scrollPosScreen = LayoutDevicePoint::FromAppUnits(scrollPos, auPerDevPixel) - * res; + LayerPoint scrollPosLayer(NSAppUnitsToFloatPixels(scrollPos.x, auPerDevPixel) * res.width, + NSAppUnitsToFloatPixels(scrollPos.y, auPerDevPixel) * res.height); - screenRect += scrollPosScreen; - float x = aMarginsData->mAlignmentX * floor(screenRect.x / aMarginsData->mAlignmentX); - float y = aMarginsData->mAlignmentY * floor(screenRect.y / aMarginsData->mAlignmentY); - float w = aMarginsData->mAlignmentX * ceil(screenRect.XMost() / aMarginsData->mAlignmentX) - x; - float h = aMarginsData->mAlignmentY * ceil(screenRect.YMost() / aMarginsData->mAlignmentY) - y; - screenRect = ScreenRect(x, y, w, h); - screenRect -= scrollPosScreen; + layerRect += scrollPosLayer; + float x = aMarginsData->mAlignmentX * floor(layerRect.x / aMarginsData->mAlignmentX); + float y = aMarginsData->mAlignmentY * floor(layerRect.y / aMarginsData->mAlignmentY); + float w = aMarginsData->mAlignmentX * ceil(layerRect.XMost() / aMarginsData->mAlignmentX) - x; + float h = aMarginsData->mAlignmentY * ceil(layerRect.YMost() / aMarginsData->mAlignmentY) - y; + layerRect = LayerRect(x, y, w, h); + layerRect -= scrollPosLayer; } // Convert the aligned rect back into app units - nsRect result = LayoutDeviceRect::ToAppUnits(screenRect / res, auPerDevPixel); + nsRect result(NSFloatPixelsToAppUnits(layerRect.x / res.width, auPerDevPixel), + NSFloatPixelsToAppUnits(layerRect.y / res.height, auPerDevPixel), + NSFloatPixelsToAppUnits(layerRect.width / res.width, auPerDevPixel), + NSFloatPixelsToAppUnits(layerRect.height / res.height, auPerDevPixel)); // Expand it for the low-res buffer if needed result = ApplyRectMultiplier(result, aMultiplier); @@ -956,7 +950,7 @@ nsLayoutUtils::GetDisplayPort(nsIContent* aContent, nsRect *aResult) void nsLayoutUtils::SetDisplayPortMargins(nsIContent* aContent, nsIPresShell* aPresShell, - const ScreenMargin& aMargins, + const LayerMargin& aMargins, uint32_t aAlignmentX, uint32_t aAlignmentY, uint32_t aPriority, @@ -2307,19 +2301,6 @@ nsLayoutUtils::GetTransformToAncestor(nsIFrame *aFrame, const nsIFrame *aAncesto return ctm; } -gfxSize -nsLayoutUtils::GetTransformToAncestorScale(nsIFrame* aFrame) -{ - Matrix4x4 transform = GetTransformToAncestor(aFrame, - nsLayoutUtils::GetDisplayRootFrame(aFrame)); - Matrix transform2D; - if (transform.Is2D(&transform2D)) { - return ThebesMatrix(transform2D).ScaleFactors(true); - } - return gfxSize(1, 1); -} - - static nsIFrame* FindNearestCommonAncestorFrame(nsIFrame* aFrame1, nsIFrame* aFrame2) { @@ -2791,15 +2772,7 @@ CalculateFrameMetricsForDisplayPort(nsIFrame* aScrollFrame, resolution = ParentLayerToLayerScale(presShell->GetXResolution(), presShell->GetYResolution()); } - // Note: unlike in ComputeFrameMetrics(), we don't know the full cumulative - // resolution including FrameMetrics::mExtraResolution, because layout hasn't - // chosen a resolution to paint at yet. However, the display port calculation - // divides out mExtraResolution anyways, so we get the correct result by - // setting the mCumulativeResolution to everything except the extra resolution - // and leaving mExtraResolution at 1. - LayoutDeviceToLayerScale cumulativeResolution( - presShell->GetCumulativeResolution().width - * nsLayoutUtils::GetTransformToAncestorScale(aScrollFrame).width); + LayoutDeviceToLayerScale cumulativeResolution(presShell->GetCumulativeResolution().width); metrics.mDevPixelsPerCSSPixel = deviceScale; metrics.mResolution = resolution; @@ -2868,7 +2841,7 @@ nsLayoutUtils::GetOrMaybeCreateDisplayPort(nsDisplayListBuilder& aBuilder, // If we don't already have a displayport, calculate and set one. if (!haveDisplayPort) { FrameMetrics metrics = CalculateFrameMetricsForDisplayPort(aScrollFrame, scrollableFrame); - ScreenMargin displayportMargins = APZCTreeManager::CalculatePendingDisplayPort( + LayerMargin displayportMargins = APZCTreeManager::CalculatePendingDisplayPort( metrics, ScreenPoint(0.0f, 0.0f), 0.0); nsIPresShell* presShell = aScrollFrame->PresContext()->GetPresShell(); gfx::IntSize alignment = gfxPlatform::GetPlatform()->UseTiling() @@ -7036,11 +7009,10 @@ nsLayoutUtils::CalculateRootCompositionSize(nsIFrame* aFrame, if (aIsRootContentDocRootScrollFrame) { return ViewAs(aMetrics.mCompositionBounds.Size(), PixelCastJustification::ParentLayerToLayerForRootComposition) - * LayerToScreenScale(1.0f) - / aMetrics.DisplayportPixelsPerCSSPixel(); + / aMetrics.LayersPixelsPerCSSPixel(); } nsPresContext* presContext = aFrame->PresContext(); - ScreenSize rootCompositionSize; + LayerSize rootCompositionSize; nsPresContext* rootPresContext = presContext->GetToplevelContentDocumentPresContext(); if (!rootPresContext) { @@ -7054,13 +7026,12 @@ nsLayoutUtils::CalculateRootCompositionSize(nsIFrame* aFrame, nsIPresShell* rootPresShell = rootPresContext->PresShell(); if (nsIFrame* rootFrame = rootPresShell->GetRootFrame()) { LayoutDeviceToLayerScale cumulativeResolution( - rootPresShell->GetCumulativeResolution().width - * nsLayoutUtils::GetTransformToAncestorScale(rootFrame).width); + rootPresShell->GetCumulativeResolution().width); int32_t rootAUPerDevPixel = rootPresContext->AppUnitsPerDevPixel(); LayerSize frameSize = (LayoutDeviceRect::FromAppUnits(rootFrame->GetRect(), rootAUPerDevPixel) * cumulativeResolution).Size(); - rootCompositionSize = frameSize * LayerToScreenScale(1.0f); + rootCompositionSize = frameSize; #ifdef MOZ_WIDGET_ANDROID nsIWidget* widget = rootFrame->GetNearestWidget(); #else @@ -7070,7 +7041,7 @@ nsLayoutUtils::CalculateRootCompositionSize(nsIFrame* aFrame, if (widget) { nsIntRect widgetBounds; widget->GetBounds(widgetBounds); - rootCompositionSize = ScreenSize(ViewAs(widgetBounds.Size())); + rootCompositionSize = LayerSize(ViewAs(widgetBounds.Size())); #ifdef MOZ_WIDGET_ANDROID if (frameSize.height < rootCompositionSize.height) { rootCompositionSize.height = frameSize.height; @@ -7084,7 +7055,7 @@ nsLayoutUtils::CalculateRootCompositionSize(nsIFrame* aFrame, gfxSize res = rootPresContext->GetParentPresContext()->PresShell()->GetCumulativeResolution(); scale = LayoutDeviceToLayerScale(res.width, res.height); } - rootCompositionSize = contentSize * scale * LayerToScreenScale(1.0f); + rootCompositionSize = contentSize * scale; } } } @@ -7092,7 +7063,7 @@ nsLayoutUtils::CalculateRootCompositionSize(nsIFrame* aFrame, nsIWidget* widget = aFrame->GetNearestWidget(); nsIntRect widgetBounds; widget->GetBounds(widgetBounds); - rootCompositionSize = ScreenSize(ViewAs(widgetBounds.Size())); + rootCompositionSize = LayerSize(ViewAs(widgetBounds.Size())); } // Adjust composition size for the size of scroll bars. @@ -7108,7 +7079,7 @@ nsLayoutUtils::CalculateRootCompositionSize(nsIFrame* aFrame, rootCompositionSize.height -= margins.TopBottom(); } - return rootCompositionSize / aMetrics.DisplayportPixelsPerCSSPixel(); + return rootCompositionSize / aMetrics.LayersPixelsPerCSSPixel(); } /* static */ nsRect diff --git a/layout/base/nsLayoutUtils.h b/layout/base/nsLayoutUtils.h index a692e0b4cb98..5573e0a78ffb 100644 --- a/layout/base/nsLayoutUtils.h +++ b/layout/base/nsLayoutUtils.h @@ -95,7 +95,7 @@ struct DisplayPortPropertyData { }; struct DisplayPortMarginsPropertyData { - DisplayPortMarginsPropertyData(const ScreenMargin& aMargins, + DisplayPortMarginsPropertyData(const LayerMargin& aMargins, uint32_t aAlignmentX, uint32_t aAlignmentY, uint32_t aPriority) : mMargins(aMargins) @@ -103,7 +103,7 @@ struct DisplayPortMarginsPropertyData { , mAlignmentY(aAlignmentY) , mPriority(aPriority) {} - ScreenMargin mMargins; + LayerMargin mMargins; uint32_t mAlignmentX; uint32_t mAlignmentY; uint32_t mPriority; @@ -137,7 +137,7 @@ public: typedef FrameMetrics::ViewID ViewID; typedef mozilla::CSSPoint CSSPoint; typedef mozilla::CSSSize CSSSize; - typedef mozilla::ScreenMargin ScreenMargin; + typedef mozilla::LayerMargin LayerMargin; typedef mozilla::LayoutDeviceIntSize LayoutDeviceIntSize; /** @@ -188,7 +188,7 @@ public: */ static void SetDisplayPortMargins(nsIContent* aContent, nsIPresShell* aPresShell, - const ScreenMargin& aMargins, + const LayerMargin& aMargins, uint32_t aAlignmentX, uint32_t aAlignmentY, uint32_t aPriority = 0, @@ -742,12 +742,6 @@ public: */ static Matrix4x4 GetTransformToAncestor(nsIFrame *aFrame, const nsIFrame *aAncestor); - /** - * Gets the scale factors of the transform for aFrame relative to the root - * frame if this transform is 2D, or the identity scale factors otherwise. - */ - static gfxSize GetTransformToAncestorScale(nsIFrame* aFrame); - /** * Transforms a list of CSSPoints from aFromFrame to aToFrame, taking into * account all relevant transformations on the frames up to (but excluding) diff --git a/layout/generic/nsGfxScrollFrame.cpp b/layout/generic/nsGfxScrollFrame.cpp index 96a3b06187ba..631897f31601 100644 --- a/layout/generic/nsGfxScrollFrame.cpp +++ b/layout/generic/nsGfxScrollFrame.cpp @@ -1876,7 +1876,7 @@ ScrollFrameHelper::ScrollFrameHelper(nsContainerFrame* aOuter, // when scrolling. nsLayoutUtils::SetDisplayPortMargins(mOuter->GetContent(), mOuter->PresContext()->PresShell(), - ScreenMargin(), + LayerMargin(), gfxPrefs::LayersTileWidth(), gfxPrefs::LayersTileHeight(), 0, nsLayoutUtils::RepaintMode::DoNotRepaint); From c969ca264797ab99e1e433652dbd1ea19ea0b490 Mon Sep 17 00:00:00 2001 From: "Carsten \"Tomcat\" Book" Date: Thu, 13 Nov 2014 11:48:00 +0100 Subject: [PATCH 77/80] Backed out changeset 9243c59c3e56 (bug 1081038) --- dom/base/nsJSUtils.cpp | 1 + dom/bindings/CallbackObject.cpp | 10 ++++++++++ dom/xbl/nsXBLProtoImplField.cpp | 2 ++ dom/xbl/nsXBLProtoImplMethod.cpp | 2 ++ dom/xul/XULDocument.cpp | 4 +++- 5 files changed, 18 insertions(+), 1 deletion(-) diff --git a/dom/base/nsJSUtils.cpp b/dom/base/nsJSUtils.cpp index 15e0617ea588..de4e73c6901c 100644 --- a/dom/base/nsJSUtils.cpp +++ b/dom/base/nsJSUtils.cpp @@ -208,6 +208,7 @@ nsJSUtils::EvaluateString(JSContext* aCx, // set to false. aRetValue.setUndefined(); + nsAutoMicroTask mt; nsresult rv = NS_OK; nsIScriptSecurityManager* ssm = nsContentUtils::GetSecurityManager(); diff --git a/dom/bindings/CallbackObject.cpp b/dom/bindings/CallbackObject.cpp index 76048849a1c2..40137f93cc9a 100644 --- a/dom/bindings/CallbackObject.cpp +++ b/dom/bindings/CallbackObject.cpp @@ -57,6 +57,10 @@ CallbackObject::CallSetup::CallSetup(CallbackObject* aCallback, , mExceptionHandling(aExceptionHandling) , mIsMainThread(NS_IsMainThread()) { + if (mIsMainThread) { + nsContentUtils::EnterMicroTask(); + } + // Compute the caller's subject principal (if necessary) early, before we // do anything that might perturb the relevant state. nsIPrincipal* webIDLCallerPrincipal = nullptr; @@ -270,6 +274,12 @@ CallbackObject::CallSetup::~CallSetup() mAutoIncumbentScript.reset(); mAutoEntryScript.reset(); + + // It is important that this is the last thing we do, after leaving the + // compartment and undoing all our entry/incumbent script changes + if (mIsMainThread) { + nsContentUtils::LeaveMicroTask(); + } } already_AddRefed diff --git a/dom/xbl/nsXBLProtoImplField.cpp b/dom/xbl/nsXBLProtoImplField.cpp index b80da21ae4c9..07ae96bda438 100644 --- a/dom/xbl/nsXBLProtoImplField.cpp +++ b/dom/xbl/nsXBLProtoImplField.cpp @@ -392,6 +392,8 @@ nsXBLProtoImplField::InstallField(JS::Handle aBoundNode, return NS_OK; } + nsAutoMicroTask mt; + nsAutoCString uriSpec; aBindingDocURI->GetSpec(uriSpec); diff --git a/dom/xbl/nsXBLProtoImplMethod.cpp b/dom/xbl/nsXBLProtoImplMethod.cpp index 965ddcdebaac..d28b034e8fd5 100644 --- a/dom/xbl/nsXBLProtoImplMethod.cpp +++ b/dom/xbl/nsXBLProtoImplMethod.cpp @@ -292,6 +292,8 @@ nsXBLProtoImplAnonymousMethod::Execute(nsIContent* aBoundElement, JSAddonId* aAd return NS_OK; } + nsAutoMicroTask mt; + // We are going to run script via JS::Call, so we need a script entry point, // but as this is XBL related it does not appear in the HTML spec. dom::AutoEntryScript aes(global); diff --git a/dom/xul/XULDocument.cpp b/dom/xul/XULDocument.cpp index 34ff948df245..a31a93385c0d 100644 --- a/dom/xul/XULDocument.cpp +++ b/dom/xul/XULDocument.cpp @@ -3573,7 +3573,9 @@ XULDocument::ExecuteScript(nsXULPrototypeScript *aScript) JS::HandleScript scriptObject = aScript->GetScriptObject(); NS_ENSURE_TRUE(scriptObject, NS_ERROR_UNEXPECTED); - // Execute the precompiled script with the given version. + // Execute the precompiled script with the given version + nsAutoMicroTask mt; + // We're about to run script via JS::CloneAndExecuteScript, so we need an // AutoEntryScript. This is Gecko specific and not in any spec. AutoEntryScript aes(mScriptGlobalObject); From b7f71a3e33d3c656d3faeb45e0a9e4a5748f4ba5 Mon Sep 17 00:00:00 2001 From: "Carsten \"Tomcat\" Book" Date: Thu, 13 Nov 2014 11:48:21 +0100 Subject: [PATCH 78/80] Backed out changeset b1f8365b8a92 (bug 1081038) for dt Test Failures on a CLOSED TREE --- dom/base/ScriptSettings.cpp | 8 -------- dom/base/ScriptSettings.h | 1 - 2 files changed, 9 deletions(-) diff --git a/dom/base/ScriptSettings.cpp b/dom/base/ScriptSettings.cpp index e02d1fc288fe..d7c26096da1c 100644 --- a/dom/base/ScriptSettings.cpp +++ b/dom/base/ScriptSettings.cpp @@ -463,22 +463,14 @@ AutoEntryScript::AutoEntryScript(nsIGlobalObject* aGlobalObject, aCx ? aCx : FindJSContext(aGlobalObject)) , ScriptSettingsStackEntry(aGlobalObject, /* aCandidate = */ true) , mWebIDLCallerPrincipal(nullptr) - , mIsMainThread(aIsMainThread) { MOZ_ASSERT(aGlobalObject); MOZ_ASSERT_IF(!aCx, aIsMainThread); // cx is mandatory off-main-thread. MOZ_ASSERT_IF(aCx && aIsMainThread, aCx == FindJSContext(aGlobalObject)); - if (aIsMainThread) { - nsContentUtils::EnterMicroTask(); - } } AutoEntryScript::~AutoEntryScript() { - if (mIsMainThread) { - nsContentUtils::LeaveMicroTask(); - } - // GC when we pop a script entry point. This is a useful heuristic that helps // us out on certain (flawed) benchmarks like sunspider, because it lets us // avoid GCing during the timing loop. diff --git a/dom/base/ScriptSettings.h b/dom/base/ScriptSettings.h index ffb78ae6f73c..f6559a447e00 100644 --- a/dom/base/ScriptSettings.h +++ b/dom/base/ScriptSettings.h @@ -330,7 +330,6 @@ private: // bit up the stack, and which will outlive us. So we know the principal // can't go away until then either. nsIPrincipal* mWebIDLCallerPrincipal; - bool mIsMainThread; friend nsIPrincipal* GetWebIDLCallerPrincipal(); }; From 3649cb2cd1e5228fdd1f00300bf546d7c715b470 Mon Sep 17 00:00:00 2001 From: "Carsten \"Tomcat\" Book" Date: Thu, 13 Nov 2014 12:03:23 +0100 Subject: [PATCH 79/80] Backed out changeset 13167bb74be0 (bug 1094434) --- .../reftests/writing-mode/1094434-1-ref.html | 27 --------------- layout/reftests/writing-mode/1094434-1.html | 33 ------------------ .../reftests/writing-mode/1094434-2-ref.html | 28 --------------- layout/reftests/writing-mode/1094434-2.html | 34 ------------------- layout/reftests/writing-mode/reftest.list | 2 -- 5 files changed, 124 deletions(-) delete mode 100644 layout/reftests/writing-mode/1094434-1-ref.html delete mode 100644 layout/reftests/writing-mode/1094434-1.html delete mode 100644 layout/reftests/writing-mode/1094434-2-ref.html delete mode 100644 layout/reftests/writing-mode/1094434-2.html diff --git a/layout/reftests/writing-mode/1094434-1-ref.html b/layout/reftests/writing-mode/1094434-1-ref.html deleted file mode 100644 index 5929b96df843..000000000000 --- a/layout/reftests/writing-mode/1094434-1-ref.html +++ /dev/null @@ -1,27 +0,0 @@ - - - - - - - - - - - - - -
- - - - - - - diff --git a/layout/reftests/writing-mode/1094434-1.html b/layout/reftests/writing-mode/1094434-1.html deleted file mode 100644 index 3fe306c0e8f7..000000000000 --- a/layout/reftests/writing-mode/1094434-1.html +++ /dev/null @@ -1,33 +0,0 @@ - - - - - - - - - - - - - -
- - - - - - - diff --git a/layout/reftests/writing-mode/1094434-2-ref.html b/layout/reftests/writing-mode/1094434-2-ref.html deleted file mode 100644 index bdd59fe485e2..000000000000 --- a/layout/reftests/writing-mode/1094434-2-ref.html +++ /dev/null @@ -1,28 +0,0 @@ - - - - - - - - - - - - - -
- - - - - - - diff --git a/layout/reftests/writing-mode/1094434-2.html b/layout/reftests/writing-mode/1094434-2.html deleted file mode 100644 index 3264950e26c2..000000000000 --- a/layout/reftests/writing-mode/1094434-2.html +++ /dev/null @@ -1,34 +0,0 @@ - - - - - - - - - - - - - -
- - - - - - - diff --git a/layout/reftests/writing-mode/reftest.list b/layout/reftests/writing-mode/reftest.list index 257064f4346c..325ed39fab4b 100644 --- a/layout/reftests/writing-mode/reftest.list +++ b/layout/reftests/writing-mode/reftest.list @@ -15,7 +15,5 @@ == 1090168-2.html 1090168-2-ref.html == 1090168-3.html 1090168-3-ref.html == 1091058-1.html 1091058-1-ref.html -random-if(gtk2Widget) == 1094434-1.html 1094434-1-ref.html # bug 1094845 -random-if(gtk2Widget) == 1094434-2.html 1094434-2-ref.html # bug 1094845 == 1094914-1a.html 1094914-1-ref.html == 1094914-1b.html 1094914-1-ref.html From 4916e71e91edeccb56bb1afd89190f15e5bf7142 Mon Sep 17 00:00:00 2001 From: "Carsten \"Tomcat\" Book" Date: Thu, 13 Nov 2014 12:04:06 +0100 Subject: [PATCH 80/80] Backed out changeset e36492ae23a6 (bug 1094434) for Android Reftest Failures on a CLOSED TREE --- layout/xul/nsResizerFrame.cpp | 19 ++++++------------- toolkit/content/widgets/resizer.xml | 12 +++--------- widget/nsNativeTheme.cpp | 6 +----- 3 files changed, 10 insertions(+), 27 deletions(-) diff --git a/layout/xul/nsResizerFrame.cpp b/layout/xul/nsResizerFrame.cpp index 83477dbba0a5..84812da89fa6 100644 --- a/layout/xul/nsResizerFrame.cpp +++ b/layout/xul/nsResizerFrame.cpp @@ -502,28 +502,21 @@ nsResizerFrame::GetDirection() {-1, 1}, {1, 1} }; - if (!GetContent()) { + if (!GetContent()) return directions[0]; // default: topleft - } int32_t index = GetContent()->FindAttrValueIn(kNameSpaceID_None, nsGkAtoms::dir, strings, eCaseMatters); - if (index < 0) { + if(index < 0) return directions[0]; // default: topleft - } - - if (index >= 8) { + else if (index >= 8 && StyleVisibility()->mDirection == NS_STYLE_DIRECTION_RTL) { // Directions 8 and higher are RTL-aware directions and should reverse the // horizontal component if RTL. - WritingMode wm = GetWritingMode(); - if (!(wm.IsVertical() ? wm.IsVerticalLR() : wm.IsBidiLTR())) { - Direction direction = directions[index]; - direction.mHorizontal *= -1; - return direction; - } + Direction direction = directions[index]; + direction.mHorizontal *= -1; + return direction; } - return directions[index]; } diff --git a/toolkit/content/widgets/resizer.xml b/toolkit/content/widgets/resizer.xml index da408e47c5c9..64808df3ffe7 100644 --- a/toolkit/content/widgets/resizer.xml +++ b/toolkit/content/widgets/resizer.xml @@ -21,15 +21,9 @@ // if the direction is rtl, set the rtl attribute so that the // stylesheet can use this to make the cursor appear properly - var cs = window.getComputedStyle(this, ""); - if (cs.writingMode == "horizontal-tb") {; - if (cs.direction == "rtl") { - this.setAttribute("rtl", "true"); - } - } else { - if (cs.writingMode == "vertical-rl") { - this.setAttribute("rtl", "true"); - } + var direction = window.getComputedStyle(this, "").direction; + if (direction == "rtl") { + this.setAttribute("rtl", "true"); } ]]> diff --git a/widget/nsNativeTheme.cpp b/widget/nsNativeTheme.cpp index 090c6286b91d..d647d85c28f0 100644 --- a/widget/nsNativeTheme.cpp +++ b/widget/nsNativeTheme.cpp @@ -381,11 +381,7 @@ nsNativeTheme::IsDisabled(nsIFrame* aFrame, EventStates aEventStates) bool nsNativeTheme::IsFrameRTL(nsIFrame* aFrame) { - if (!aFrame) { - return false; - } - WritingMode wm = aFrame->GetWritingMode(); - return !(wm.IsVertical() ? wm.IsVerticalLR() : wm.IsBidiLTR()); + return aFrame && aFrame->StyleVisibility()->mDirection == NS_STYLE_DIRECTION_RTL; } bool