From ea5435834ed9356a19fb9d083d092b28f5e0c626 Mon Sep 17 00:00:00 2001 From: Gaia Pushbot Date: Tue, 30 Jul 2013 06:15:24 -0700 Subject: [PATCH 01/36] Bumping gaia.json for 2 gaia-central revision(s) ======== https://hg.mozilla.org/integration/gaia-central/rev/cc6529f11643 Author: Ben Kelly Desc: Merge pull request #11233 from wanderview/contacts-update-tel-type Bug 898241: Use l10n type for tel update activity. r=jmcf ======== https://hg.mozilla.org/integration/gaia-central/rev/07314a1896fa Author: Ben Kelly Desc: Bug 898241: Use l10n type for tel update activity. --- 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 e3a497cbd87..37dee69e0f0 100644 --- a/b2g/config/gaia.json +++ b/b2g/config/gaia.json @@ -1,4 +1,4 @@ { - "revision": "10f16f6a15f8a1c4b910548b4d0968baaac21c91", + "revision": "cc6529f11643ec1c43130d47f732ec8091f3134e", "repo_path": "/integration/gaia-central" } From 5bb32a98d9bc878c169c873a933281b969671466 Mon Sep 17 00:00:00 2001 From: Gaia Pushbot Date: Tue, 30 Jul 2013 06:25:23 -0700 Subject: [PATCH 02/36] Bumping gaia.json for 2 gaia-central revision(s) ======== https://hg.mozilla.org/integration/gaia-central/rev/a2800243e083 Author: Ben Francis Desc: Merge pull request #11237 from gasolin/issue-897920 Bug 897920 - [Browser] remove redundant resource r=benfrancis ======== https://hg.mozilla.org/integration/gaia-central/rev/cce5d8812de4 Author: gasolin Desc: Bug 897920 - [Browser] remove redundant resource --- 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 37dee69e0f0..e3fbad706d8 100644 --- a/b2g/config/gaia.json +++ b/b2g/config/gaia.json @@ -1,4 +1,4 @@ { - "revision": "cc6529f11643ec1c43130d47f732ec8091f3134e", + "revision": "a2800243e083f43fad4ffce4d52e3bb5bfc1d0ee", "repo_path": "/integration/gaia-central" } From c223d3d7fa80faff2d7d936e26e2f2388c8297fe Mon Sep 17 00:00:00 2001 From: Kay Lee Date: Tue, 30 Jul 2013 09:44:16 -0400 Subject: [PATCH 03/36] Bug 851440 - Sort same contacts by published-order. r=gwagner --- dom/contacts/fallback/ContactDB.jsm | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/dom/contacts/fallback/ContactDB.jsm b/dom/contacts/fallback/ContactDB.jsm index 9821f6b33ed..495a913e5e7 100644 --- a/dom/contacts/fallback/ContactDB.jsm +++ b/dom/contacts/fallback/ContactDB.jsm @@ -905,9 +905,6 @@ ContactDB.prototype = { } xIndex++; } - if (!x) { - return sortOrder == "descending" ? 1 : -1; - } while (yIndex < sortBy.length && !y) { y = b.properties[sortBy[yIndex]]; if (y) { @@ -915,6 +912,18 @@ ContactDB.prototype = { } yIndex++; } + if (!x) { + if (!y) { + let px, py; + px = JSON.stringify(a.published); + py = JSON.stringify(b.published); + if (px && py) { + return px.localeCompare(py); + } + } else { + return sortOrder == 'descending' ? 1 : -1; + } + } if (!y) { return sortOrder == "ascending" ? 1 : -1; } From 88699bb48bd607713953cbea52c88accab96bff3 Mon Sep 17 00:00:00 2001 From: Kay Lee Date: Tue, 30 Jul 2013 09:46:44 -0400 Subject: [PATCH 04/36] Bug 851440 - Add more tests for contacts sorting. r=gwagner --- dom/contacts/tests/test_contacts_basics.html | 76 ++++++++++++++++++++ 1 file changed, 76 insertions(+) diff --git a/dom/contacts/tests/test_contacts_basics.html b/dom/contacts/tests/test_contacts_basics.html index 63566f29bea..fffbb9a369d 100644 --- a/dom/contacts/tests/test_contacts_basics.html +++ b/dom/contacts/tests/test_contacts_basics.html @@ -61,6 +61,24 @@ var c5 = { nickname: "empty" }; +var c6 = { + name: "e", + familyName: ["e","e","e"], + givenName: ["e","e","e"], +}; + +var c7 = { + name: "e", + familyName: ["e","e","e"], + givenName: ["e","e","e"], +}; + +var c8 = { + name: "e", + familyName: ["e","e","e"], + givenName: ["e","e","e"], +}; + var adr1 = { type: "work", streetAddress: "street 1", @@ -1338,6 +1356,64 @@ var steps = [ } req.onerror = onFailure; }, + function () { + ok(true, "Test sorting"); + createResult1 = new mozContact(); + createResult1.init(c7); + req = navigator.mozContacts.save(createResult1); + req.onsuccess = function () { + ok(createResult1.id, "The contact now has an ID."); + checkContacts(c7, createResult1); + next(); + }; + req.onerror = onFailure; + }, + function () { + ok(true, "Test sorting"); + createResult1 = new mozContact(); + createResult1.init(c6); + req = navigator.mozContacts.save(createResult1); + req.onsuccess = function () { + ok(createResult1.id, "The contact now has an ID."); + checkContacts(c6, createResult1); + next(); + }; + req.onerror = onFailure; + }, + function () { + ok(true, "Test sorting"); + createResult1 = new mozContact(); + createResult1.init(c8); + req = navigator.mozContacts.save(createResult1); + req.onsuccess = function () { + ok(createResult1.id, "The contact now has an ID."); + checkContacts(c8, createResult1); + next(); + }; + req.onerror = onFailure; + }, + function () { + ok(true, "Test sorting with published"); + var options = {sortBy: "familyName", + sortOrder: "descending"}; + req = navigator.mozContacts.find(options); + req.onsuccess = function () { + is(req.result.length, 3, "3 results"); + ok(req.result[0].published < req.result[1].published, "Right sorting order"); + ok(req.result[1].published < req.result[2].published, "Right sorting order"); + next(); + }; + req.onerror = onFailure; + }, + function () { + ok(true, "Deleting database"); + req = mozContacts.clear() + req.onsuccess = function () { + ok(true, "Deleted the database"); + next(); + } + req.onerror = onFailure; + }, function () { ok(true, "Adding a new contact with properties2"); createResult2 = new mozContact(); From e40523d01b4925c5f492c28f02cc6c16f89455e9 Mon Sep 17 00:00:00 2001 From: Michael Vines Date: Mon, 29 Jul 2013 21:27:48 -0700 Subject: [PATCH 05/36] Bug 895665 - Gonk support for dev input audio jack events. r=mwu --- widget/gonk/nsAppShell.cpp | 64 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 64 insertions(+) diff --git a/widget/gonk/nsAppShell.cpp b/widget/gonk/nsAppShell.cpp index 4f68d5bb1d1..1b182a5b0aa 100644 --- a/widget/gonk/nsAppShell.cpp +++ b/widget/gonk/nsAppShell.cpp @@ -52,6 +52,7 @@ #include "libui/EventHub.h" #include "libui/InputReader.h" #include "libui/InputDispatcher.h" +#include "cutils/properties.h" #include "GeckoProfiler.h" @@ -78,6 +79,9 @@ bool gDrawRequest = false; static nsAppShell *gAppShell = NULL; static int epollfd = 0; static int signalfds[2] = {0}; +static bool sDevInputAudioJack; +static int32_t sHeadphoneState; +static int32_t sMicrophoneState; NS_IMPL_ISUPPORTS_INHERITED1(nsAppShell, nsBaseAppShell, nsIObserver) @@ -245,6 +249,41 @@ maybeSendKeyEvent(int keyCode, bool pressed, uint64_t timeMs) } } +class SwitchEventRunnable : public nsRunnable { +public: + SwitchEventRunnable(hal::SwitchEvent& aEvent) : mEvent(aEvent) + {} + + NS_IMETHOD Run() + { + hal::NotifySwitchChange(mEvent); + return NS_OK; + } +private: + hal::SwitchEvent mEvent; +}; + +static void +updateHeadphoneSwitch() +{ + hal::SwitchEvent event; + + switch (sHeadphoneState) { + case AKEY_STATE_UP: + event.status() = hal::SWITCH_STATE_OFF; + break; + case AKEY_STATE_DOWN: + event.status() = sMicrophoneState == AKEY_STATE_DOWN ? + hal::SWITCH_STATE_HEADPHONE : hal::SWITCH_STATE_HEADSET; + break; + default: + return; + } + + event.device() = hal::SWITCH_HEADPHONES; + NS_DispatchToMainThread(new SwitchEventRunnable(event)); +} + class GeckoPointerController : public PointerControllerInterface { float mX; float mY; @@ -553,6 +592,19 @@ GeckoInputDispatcher::notifyMotion(const NotifyMotionArgs* args) void GeckoInputDispatcher::notifySwitch(const NotifySwitchArgs* args) { + if (!sDevInputAudioJack) + return; + + switch (args->switchCode) { + case SW_HEADPHONE_INSERT: + sHeadphoneState = args->switchValue; + updateHeadphoneSwitch(); + break; + case SW_MICROPHONE_INSERT: + sMicrophoneState = args->switchValue; + updateHeadphoneSwitch(); + break; + } } void GeckoInputDispatcher::notifyDeviceReset(const NotifyDeviceResetArgs* args) @@ -661,6 +713,12 @@ nsAppShell::Observe(nsISupports* aSubject, return nsBaseAppShell::Observe(aSubject, aTopic, aData); } + if (sDevInputAudioJack) { + sHeadphoneState = mReader->getSwitchState(-1, AINPUT_SOURCE_SWITCH, SW_HEADPHONE_INSERT); + sMicrophoneState = mReader->getSwitchState(-1, AINPUT_SOURCE_SWITCH, SW_MICROPHONE_INSERT); + updateHeadphoneSwitch(); + } + mEnableDraw = true; NotifyEvent(); return NS_OK; @@ -680,6 +738,12 @@ nsAppShell::Exit() void nsAppShell::InitInputDevices() { + char value[PROPERTY_VALUE_MAX]; + property_get("ro.moz.devinputjack", value, "0"); + sDevInputAudioJack = !strcmp(value, "1"); + sHeadphoneState = AKEY_STATE_UNKNOWN; + sMicrophoneState = AKEY_STATE_UNKNOWN; + mEventHub = new EventHub(); mReaderPolicy = new GeckoInputReaderPolicy(); mReaderPolicy->setDisplayInfo(); From 691280eb5dff7f119f88517fa1f2daec411fae57 Mon Sep 17 00:00:00 2001 From: Chuck Lee Date: Mon, 29 Jul 2013 15:08:37 +0800 Subject: [PATCH 06/36] Bug 897368 - 0001. Handle code page switch token. r=vicamo --- dom/wappush/src/gonk/WapPushManager.js | 2 +- dom/wappush/src/gonk/WbxmlPduHelper.jsm | 87 +++++++++++++++++++++---- 2 files changed, 76 insertions(+), 13 deletions(-) diff --git a/dom/wappush/src/gonk/WapPushManager.js b/dom/wappush/src/gonk/WapPushManager.js index 96e87b0a442..217bb989b60 100644 --- a/dom/wappush/src/gonk/WapPushManager.js +++ b/dom/wappush/src/gonk/WapPushManager.js @@ -62,8 +62,8 @@ this.WapPushManager = { let appid = options.headers["x-wap-application-id"]; if (!appid) { + // Assume message without applicatioin ID is WAP Push debug("Push message doesn't contains X-Wap-Application-Id."); - return; } // MMS diff --git a/dom/wappush/src/gonk/WbxmlPduHelper.jsm b/dom/wappush/src/gonk/WbxmlPduHelper.jsm index 67d231881aa..f58577b2e9b 100644 --- a/dom/wappush/src/gonk/WbxmlPduHelper.jsm +++ b/dom/wappush/src/gonk/WbxmlPduHelper.jsm @@ -23,6 +23,7 @@ const TAG_TOKEN_VALUE_MASK = 0x3F; * * @see WAP-192-WBXML-20010725-A, clause 7.1 */ +const CODE_PAGE_SWITCH_TOKEN = 0x00; const TAG_END_TOKEN = 0x01; const INLINE_STRING_TOKEN = 0x03; const STRING_TABLE_TOKEN = 0x83; @@ -34,11 +35,53 @@ this.DEBUG_ALL = false; // Enable debug message for WBXML decoder core. this.DEBUG = DEBUG_ALL | false; +/** + * Handle WBXML code page switch. + * + * @param data + * A wrapped object containing raw PDU data. + * @param decodeInfo + * Internal information for decode process. + * + * @see WAP-192-WBXML-20010725-A, clause 5.8.4.7.2 and 5.8.1 + */ +this.WbxmlCodePageSwitch = { + decode: function decode_wbxml_code_page_switch(data, decodeInfo) { + let codePage = WSP.Octet.decode(data); + + if (decodeInfo.currentState === "tag") { + decodeInfo.currentTokenList.tag = decodeInfo.tokenList.tag[codePage]; + + if (!decodeInfo.currentTokenList.tag) { + throw new Error("Invalid tag code page: " + codePage + "."); + } + + return ""; + } + + if (decodeInfo.currentState === "attr") { + decodeInfo.currentTokenList.attr = decodeInfo.tokenList.attr[codePage]; + decodeInfo.currentTokenList.value = decodeInfo.tokenList.value[codePage]; + + if (!decodeInfo.currentTokenList.attr || + !decodeInfo.currentTokenList.value) { + throw new Error("Invalid attr code page: " + codePage + "."); + } + + return ""; + } + + throw new Error("Invalid decoder state: " + decodeInfo.currentState + "."); + }, +}; + /** * Parse end WBXML encoded message. * * @param data * A wrapped object containing raw PDU data. + * @param decodeInfo + * Internal information for decode process. * * @see WAP-192-WBXML-20010725-A, clause 5.8.4.7.1 * @@ -84,6 +127,8 @@ this.WbxmlStringTable = { * * @param data * A wrapped object containing raw PDU data. + * @param decodeInfo + * Internal information for decode process. * * @see WAP-192-WBXML-20010725-A, clause 5.8.4.1 * @@ -106,6 +151,8 @@ this.WbxmlInlineString = { * * @param data * A wrapped object containing raw PDU data. + * @param decodeInfo + * Internal information for decode process. * * @see WAP-192-WBXML-20010725-A, clause 5.8.4.6 * @@ -135,11 +182,20 @@ this.PduHelper = { parseWbxml: function parseWbxml_wbxml(data, decodeInfo, appToken) { // Parse token definition to my structure. - let tagTokenList = appToken.tagTokenList; - let attrTokenList = appToken.attrTokenList; - let valueTokenList = appToken.valueTokenList; - - decodeInfo.tagStack = []; // tag decode stack + decodeInfo.tokenList = { + tag: appToken.tagTokenList, + attr: appToken.attrTokenList, + value: appToken.valueTokenList + }; + decodeInfo.tagStack = []; // tag decode stack + decodeInfo.currentTokenList = { + tag: decodeInfo.tokenList.tag[0], + attr: decodeInfo.tokenList.attr[0], + value: decodeInfo.tokenList.value[0] + }; + decodeInfo.currentState = "tag"; // Current decoding state, "tag" or "attr" + // Used to read corresponding code page + // initial state : "tag" // Merge global tag tokens into single list, so we don't have // to search two lists every time. @@ -156,6 +212,9 @@ this.PduHelper = { // Decode content, might be a new tag token, an end of tag token, or an // inline string. + // Switch to tag domain + decodeInfo.currentState = "tag"; + let tagToken = WSP.Octet.decode(data); let tagTokenValue = tagToken & TAG_TOKEN_VALUE_MASK; @@ -170,7 +229,7 @@ this.PduHelper = { } // Check if application tag token is valid - tagInfo = tagTokenList[tagTokenValue]; + tagInfo = decodeInfo.currentTokenList.tag[tagTokenValue]; if (!tagInfo) { throw new Error("Unsupported WBXML token: " + tagTokenValue + "."); } @@ -181,6 +240,9 @@ this.PduHelper = { // Decode attributes, might be a new attribute token, a value token, // or an inline string + // Switch to attr/value domain + decodeInfo.currentState = "attr"; + let attrSeperator = ""; while (data.offset < data.array.length) { let attrToken = WSP.Octet.decode(data); @@ -195,14 +257,14 @@ this.PduHelper = { } // Check if attribute token is valid - attrInfo = attrTokenList[attrToken]; + attrInfo = decodeInfo.currentTokenList.attr[attrToken]; if (attrInfo) { content += attrSeperator + " " + attrInfo.name + "=\"" + attrInfo.value; attrSeperator = "\""; continue; } - attrInfo = valueTokenList[attrToken]; + attrInfo = decodeInfo.currentTokenList.value[attrToken]; if (attrInfo) { content += attrInfo.value; continue; @@ -325,10 +387,11 @@ const WBXML_GLOBAL_TOKENS = (function () { names[number] = entry; } - add(TAG_END_TOKEN, WbxmlEnd); - add(INLINE_STRING_TOKEN, WbxmlInlineString); - add(STRING_TABLE_TOKEN, WbxmlStringTable); - add(OPAQUE_TOKEN, WbxmlOpaque); + add(CODE_PAGE_SWITCH_TOKEN, WbxmlCodePageSwitch); + add(TAG_END_TOKEN, WbxmlEnd); + add(INLINE_STRING_TOKEN, WbxmlInlineString); + add(STRING_TABLE_TOKEN, WbxmlStringTable); + add(OPAQUE_TOKEN, WbxmlOpaque); return names; })(); From 7491da88971d226030a35a04949fab9e9294a9a2 Mon Sep 17 00:00:00 2001 From: Chuck Lee Date: Mon, 29 Jul 2013 15:08:38 +0800 Subject: [PATCH 07/36] Bug 897368 - 0002. Support code page in token list. r=vicamo --- dom/wappush/src/gonk/CpPduHelper.jsm | 332 ++++++++++++++++----------- dom/wappush/src/gonk/SiPduHelper.jsm | 65 +++--- dom/wappush/src/gonk/SlPduHelper.jsm | 47 ++-- 3 files changed, 268 insertions(+), 176 deletions(-) diff --git a/dom/wappush/src/gonk/CpPduHelper.jsm b/dom/wappush/src/gonk/CpPduHelper.jsm index 0c68a03740e..0172e51c56a 100644 --- a/dom/wappush/src/gonk/CpPduHelper.jsm +++ b/dom/wappush/src/gonk/CpPduHelper.jsm @@ -86,21 +86,29 @@ this.PduHelper = { /** * Tag tokens * - * @see WAP-183-ProvCont-20010724-A, clause 8.1 + * @see WAP-183-ProvCont-20010724-A, clause 8.1 for code page 0 + * @see OMA-WAP-TS-ProvCont-V1_1-20090421-C, clause 7.1 for code page 1 */ const CP_TAG_FIELDS = (function () { let names = {}; - function add(name, number) { + function add(name, codepage, number) { let entry = { name: name, number: number, }; - names[number] = entry; + if (!names[codepage]) { + names[codepage] = {}; + } + names[codepage][number] = entry; } - add("wap-provisioningdoc", 0x05); - add("characteristic", 0x06); - add("parm", 0x07); + // Code page 0 + add("wap-provisioningdoc", 0, 0x05); + add("characteristic", 0, 0x06); + add("parm", 0, 0x07); + // Code page 1 + add("characteristic", 1, 0x06); + add("parm", 1, 0x07); return names; })(); @@ -108,155 +116,221 @@ const CP_TAG_FIELDS = (function () { /** * Attribute Tokens * - * @see WAP-183-ProvCont-20010724-A, clause 8.2 + * @see WAP-183-ProvCont-20010724-A, clause 8.2 for code page 0 + * @see OMA-WAP-TS-ProvCont-V1_1-20090421-C, clause 7.2 for code page 1 */ const CP_ATTRIBUTE_FIELDS = (function () { let names = {}; - function add(name, value, number) { + function add(name, value, codepage, number) { let entry = { name: name, value: value, number: number, }; - names[number] = entry; + if (!names[codepage]) { + names[codepage] = {}; + } + names[codepage][number] = entry; } - add("name", "", 0x05); - add("value", "", 0x06); - add("name", "NAME", 0x07); - add("name", "NAP-ADDRESS", 0x08); - add("name", "NAP-ADDRTYPE", 0x09); - add("name", "CALLTYPE", 0x0A); - add("name", "VALIDUNTIL", 0x0B); - add("name", "AUTHTYPE", 0x0C); - add("name", "AUTHNAME", 0x0D); - add("name", "AUTHSECRET", 0x0E); - add("name", "LINGER", 0x0F); - add("name", "BEARER", 0x10); - add("name", "NAPID", 0x11); - add("name", "COUNTRY", 0x12); - add("name", "NETWORK", 0x13); - add("name", "INTERNET", 0x14); - add("name", "PROXY-ID", 0x15); - add("name", "PROXY-PROVIDER-ID", 0x16); - add("name", "DOMAIN", 0x17); - add("name", "PROVURL", 0x18); - add("name", "PXAUTH-TYPE", 0x19); - add("name", "PXAUTH-ID", 0x1A); - add("name", "PXAUTH-PW", 0x1B); - add("name", "STARTPAGE", 0x1C); - add("name", "BASAUTH-ID", 0x1D); - add("name", "BASAUTH-PW", 0x1E); - add("name", "PUSHENABLED", 0x1F); - add("name", "PXADDR", 0x20); - add("name", "PXADDRTYPE", 0x21); - add("name", "TO-NAPID", 0x22); - add("name", "PORTNBR", 0x23); - add("name", "SERVICE", 0x24); - add("name", "LINKSPEED", 0x25); - add("name", "DNLINKSPEED", 0x26); - add("name", "LOCAL-ADDR", 0x27); - add("name", "LOCAL-ADDRTYPE", 0x28); - add("name", "CONTEXT-ALLOW", 0x29); - add("name", "TRUST", 0x2A); - add("name", "MASTER", 0x2B); - add("name", "SID", 0x2C); - add("name", "SOC", 0x2D); - add("name", "WSP-VERSION", 0x2E); - add("name", "PHYSICAL-PROXY-ID", 0x2F); - add("name", "CLIENT-ID", 0x30); - add("name", "DELIVERY-ERR-PDU", 0x31); - add("name", "DELIVERY-ORDER", 0x32); - add("name", "TRAFFIC-CLASS", 0x33); - add("name", "MAX-SDU-SIZE", 0x34); - add("name", "MAX-BITRATE-UPLINK", 0x35); - add("name", "MAX-BITRATE-DNLINK", 0x36); - add("name", "RESIDUAL-BER", 0x37); - add("name", "SDU-ERROR-RATIO", 0x38); - add("name", "TRAFFIC-HANDL-PRIO", 0x39); - add("name", "TRANSFER-DELAY", 0x3A); - add("name", "GUARANTEED-BITRATE-UPLINK", 0x3B); - add("name", "GUARANTEED-BITRATE-DNLINK", 0x3C); - add("version", "", 0x45); - add("version", "1.0", 0x46); - add("type", "", 0x50); - add("type", "PXLOGICAL", 0x51); - add("type", "PXPHYSICAL", 0x52); - add("type", "PORT", 0x53); - add("type", "VALIDITY", 0x54); - add("type", "NAPDEF", 0x55); - add("type", "BOOTSTRAP", 0x56); + // Code page 0 + add("name", "", 0, 0x05); + add("value", "", 0, 0x06); + add("name", "NAME", 0, 0x07); + add("name", "NAP-ADDRESS", 0, 0x08); + add("name", "NAP-ADDRTYPE", 0, 0x09); + add("name", "CALLTYPE", 0, 0x0A); + add("name", "VALIDUNTIL", 0, 0x0B); + add("name", "AUTHTYPE", 0, 0x0C); + add("name", "AUTHNAME", 0, 0x0D); + add("name", "AUTHSECRET", 0, 0x0E); + add("name", "LINGER", 0, 0x0F); + add("name", "BEARER", 0, 0x10); + add("name", "NAPID", 0, 0x11); + add("name", "COUNTRY", 0, 0x12); + add("name", "NETWORK", 0, 0x13); + add("name", "INTERNET", 0, 0x14); + add("name", "PROXY-ID", 0, 0x15); + add("name", "PROXY-PROVIDER-ID", 0, 0x16); + add("name", "DOMAIN", 0, 0x17); + add("name", "PROVURL", 0, 0x18); + add("name", "PXAUTH-TYPE", 0, 0x19); + add("name", "PXAUTH-ID", 0, 0x1A); + add("name", "PXAUTH-PW", 0, 0x1B); + add("name", "STARTPAGE", 0, 0x1C); + add("name", "BASAUTH-ID", 0, 0x1D); + add("name", "BASAUTH-PW", 0, 0x1E); + add("name", "PUSHENABLED", 0, 0x1F); + add("name", "PXADDR", 0, 0x20); + add("name", "PXADDRTYPE", 0, 0x21); + add("name", "TO-NAPID", 0, 0x22); + add("name", "PORTNBR", 0, 0x23); + add("name", "SERVICE", 0, 0x24); + add("name", "LINKSPEED", 0, 0x25); + add("name", "DNLINKSPEED", 0, 0x26); + add("name", "LOCAL-ADDR", 0, 0x27); + add("name", "LOCAL-ADDRTYPE", 0, 0x28); + add("name", "CONTEXT-ALLOW", 0, 0x29); + add("name", "TRUST", 0, 0x2A); + add("name", "MASTER", 0, 0x2B); + add("name", "SID", 0, 0x2C); + add("name", "SOC", 0, 0x2D); + add("name", "WSP-VERSION", 0, 0x2E); + add("name", "PHYSICAL-PROXY-ID", 0, 0x2F); + add("name", "CLIENT-ID", 0, 0x30); + add("name", "DELIVERY-ERR-PDU", 0, 0x31); + add("name", "DELIVERY-ORDER", 0, 0x32); + add("name", "TRAFFIC-CLASS", 0, 0x33); + add("name", "MAX-SDU-SIZE", 0, 0x34); + add("name", "MAX-BITRATE-UPLINK", 0, 0x35); + add("name", "MAX-BITRATE-DNLINK", 0, 0x36); + add("name", "RESIDUAL-BER", 0, 0x37); + add("name", "SDU-ERROR-RATIO", 0, 0x38); + add("name", "TRAFFIC-HANDL-PRIO", 0, 0x39); + add("name", "TRANSFER-DELAY", 0, 0x3A); + add("name", "GUARANTEED-BITRATE-UPLINK", 0, 0x3B); + add("name", "GUARANTEED-BITRATE-DNLINK", 0, 0x3C); + add("version", "", 0, 0x45); + add("version", "1.0", 0, 0x46); + add("type", "", 0, 0x50); + add("type", "PXLOGICAL", 0, 0x51); + add("type", "PXPHYSICAL", 0, 0x52); + add("type", "PORT", 0, 0x53); + add("type", "VALIDITY", 0, 0x54); + add("type", "NAPDEF", 0, 0x55); + add("type", "BOOTSTRAP", 0, 0x56); /* * Mark out VENDORCONFIG so if it is contained in message, parse * will failed and raw data is returned. */ -// add("type", "VENDORCONFIG", 0x57); - add("type", "CLIENTIDENTITY", 0x58); - add("type", "PXAUTHINFO", 0x59); - add("type", "NAPAUTHINFO", 0x5A); +// add("type", "VENDORCONFIG", 0, 0x57); + add("type", "CLIENTIDENTITY", 0, 0x58); + add("type", "PXAUTHINFO", 0, 0x59); + add("type", "NAPAUTHINFO", 0, 0x5A); + + // Code page 1 + add("name", "", 1, 0x05); + add("value", "", 1, 0x06); + add("name", "NAME", 1, 0x07); + add("name", "INTERNET", 1, 0x14); + add("name", "STARTPAGE", 1, 0x1C); + add("name", "TO-NAPID", 1, 0x22); + add("name", "PORTNBR", 1, 0x23); + add("name", "SERVICE", 1, 0x24); + add("name", "AACCEPT", 1, 0x2E); + add("name", "AAUTHDATA", 1, 0x2F); + add("name", "AAUTHLEVEL", 1, 0x30); + add("name", "AAUTHNAME", 1, 0x31); + add("name", "AAUTHSECRET", 1, 0x32); + add("name", "AAUTHTYPE", 1, 0x33); + add("name", "ADDR", 1, 0x34); + add("name", "ADDRTYPE", 1, 0x35); + add("name", "APPID", 1, 0x36); + add("name", "APROTOCOL", 1, 0x37); + add("name", "PROVIDER-ID", 1, 0x38); + add("name", "TO-PROXY", 1, 0x39); + add("name", "URI", 1, 0x3A); + add("name", "RULE", 1, 0x3B); + add("type", "", 1, 0x50); + add("type", "PORT", 1, 0x53); + add("type", "APPLICATION", 1, 0x55); + add("type", "APPADDR", 1, 0x56); + add("type", "APPAUTH", 1, 0x57); + add("type", "CLIENTIDENTITY", 1, 0x58); + add("type", "RESOURCE", 1, 0x59); return names; })(); +/** + * Value Tokens + * + * @see WAP-183-ProvCont-20010724-A, clause 8.3 for code page 0 + * @see OMA-WAP-TS-ProvCont-V1_1-20090421-C, clause 7.3 for code page 1 + */ const CP_VALUE_FIELDS = (function () { let names = {}; - function add(value, number) { + function add(value, codepage, number) { let entry = { value: value, number: number, }; - names[number] = entry; + if (!names[codepage]) { + names[codepage] = {}; + } + names[codepage][number] = entry; } - add("IPV4", 0x85); - add("IPV6", 0x86); - add("E164", 0x87); - add("ALPHA", 0x88); - add("APN", 0x89); - add("SCODE", 0x8A); - add("TETRA-ITSI", 0x8B); - add("MAN", 0x8C); - add("ANALOG-MODEM", 0x90); - add("V.120", 0x91); - add("V.110", 0x92); - add("X.31", 0x93); - add("BIT-TRANSPARENT", 0x94); - add("DIRECT-ASYNCHRONOUS-DATA-SERVICE", 0x95); - add("PAP", 0x9A); - add("CHAP", 0x9B); - add("HTTP-BASIC", 0x9C); - add("HTTP-DIGEST", 0x9D); - add("WTLS-SS", 0x9E); - add("GSM-USSD", 0xA2); - add("GSM-SMS", 0xA3); - add("ANSI-136-GUTS", 0xA4); - add("IS-95-CDMA-SMS", 0xA5); - add("IS-95-CDMA-CSD", 0xA6); - add("IS-95-CDMA-PAC", 0xA7); - add("ANSI-136-CSD", 0xA8); - add("ANSI-136-GPRS", 0xA9); - add("GSM-CSD", 0xAA); - add("GSM-GPRS", 0xAB); - add("AMPS-CDPD", 0xAC); - add("PDC-CSD", 0xAD); - add("PDC-PACKET", 0xAE); - add("IDEN-SMS", 0xAF); - add("IDEN-CSD", 0xB0); - add("IDEN-PACKET", 0xB1); - add("FLEX/REFLEX", 0xB2); - add("PHS-SMS", 0xB3); - add("PHS-CSD", 0xB4); - add("TETRA-SDS", 0xB5); - add("TETRA-PACKET", 0xB6); - add("ANSI-136-GHOST", 0xB7); - add("MOBITEX-MPAK", 0xB8); - add("AUTOBOUDING", 0xC5); - add("CL-WSP", 0xCA); - add("CO-WSP", 0xCB); - add("CL-SEC-WSP", 0xCC); - add("CO-SEC-WSP", 0xCD); - add("CL-SEC-WTA", 0xCE); - add("CO-SEC-WTA", 0xCF); + // Code page 0 + add("IPV4", 0, 0x85); + add("IPV6", 0, 0x86); + add("E164", 0, 0x87); + add("ALPHA", 0, 0x88); + add("APN", 0, 0x89); + add("SCODE", 0, 0x8A); + add("TETRA-ITSI", 0, 0x8B); + add("MAN", 0, 0x8C); + add("ANALOG-MODEM", 0, 0x90); + add("V.120", 0, 0x91); + add("V.110", 0, 0x92); + add("X.31", 0, 0x93); + add("BIT-TRANSPARENT", 0, 0x94); + add("DIRECT-ASYNCHRONOUS-DATA-SERVICE", 0, 0x95); + add("PAP", 0, 0x9A); + add("CHAP", 0, 0x9B); + add("HTTP-BASIC", 0, 0x9C); + add("HTTP-DIGEST", 0, 0x9D); + add("WTLS-SS", 0, 0x9E); + add("MD5", 0, 0x9F); // Added in OMA, 7.3.3 + add("GSM-USSD", 0, 0xA2); + add("GSM-SMS", 0, 0xA3); + add("ANSI-136-GUTS", 0, 0xA4); + add("IS-95-CDMA-SMS", 0, 0xA5); + add("IS-95-CDMA-CSD", 0, 0xA6); + add("IS-95-CDMA-PAC", 0, 0xA7); + add("ANSI-136-CSD", 0, 0xA8); + add("ANSI-136-GPRS", 0, 0xA9); + add("GSM-CSD", 0, 0xAA); + add("GSM-GPRS", 0, 0xAB); + add("AMPS-CDPD", 0, 0xAC); + add("PDC-CSD", 0, 0xAD); + add("PDC-PACKET", 0, 0xAE); + add("IDEN-SMS", 0, 0xAF); + add("IDEN-CSD", 0, 0xB0); + add("IDEN-PACKET", 0, 0xB1); + add("FLEX/REFLEX", 0, 0xB2); + add("PHS-SMS", 0, 0xB3); + add("PHS-CSD", 0, 0xB4); + add("TETRA-SDS", 0, 0xB5); + add("TETRA-PACKET", 0, 0xB6); + add("ANSI-136-GHOST", 0, 0xB7); + add("MOBITEX-MPAK", 0, 0xB8); + add("CDMA2000-1X-SIMPLE-IP", 0, 0xB9); // Added in OMA, 7.3.4 + add("CDMA2000-1X-MOBILE-IP", 0, 0xBA); // Added in OMA, 7.3.4 + add("AUTOBOUDING", 0, 0xC5); + add("CL-WSP", 0, 0xCA); + add("CO-WSP", 0, 0xCB); + add("CL-SEC-WSP", 0, 0xCC); + add("CO-SEC-WSP", 0, 0xCD); + add("CL-SEC-WTA", 0, 0xCE); + add("CO-SEC-WTA", 0, 0xCF); + add("OTA-HTTP-TO", 0, 0xD0); // Added in OMA, 7.3.6 + add("OTA-HTTP-TLS-TO", 0, 0xD1); // Added in OMA, 7.3.6 + add("OTA-HTTP-PO", 0, 0xD2); // Added in OMA, 7.3.6 + add("OTA-HTTP-TLS-PO", 0, 0xD3); // Added in OMA, 7.3.6 + add("AAA", 0, 0xE0); // Added in OMA, 7.3.8 + add("HA", 0, 0xE1); // Added in OMA, 7.3.8 + + // Code page 1 + add("IPV6", 1, 0x86); + add("E164", 1, 0x87); + add("ALPHA", 1, 0x88); + add("APPSRV", 1, 0x8D); + add("OBEX", 1, 0x8E); + add(",", 1, 0x90); + add("HTTP-", 1, 0x91); + add("BASIC", 1, 0x92); + add("DIGEST", 1, 0x93); return names; })(); diff --git a/dom/wappush/src/gonk/SiPduHelper.jsm b/dom/wappush/src/gonk/SiPduHelper.jsm index dc8bd5b3c8e..69367d0c229 100644 --- a/dom/wappush/src/gonk/SiPduHelper.jsm +++ b/dom/wappush/src/gonk/SiPduHelper.jsm @@ -134,18 +134,21 @@ this.PduHelper = { */ const SI_TAG_FIELDS = (function () { let names = {}; - function add(name, number) { + function add(name, codepage, number) { let entry = { name: name, number: number, }; - names[number] = entry; + if (!names[codepage]) { + names[codepage] = {}; + } + names[codepage][number] = entry; } - add("si", 0x05); - add("indication", 0x06); - add("info", 0x07); - add("item", 0x08); + add("si", 0, 0x05); + add("indication", 0, 0x06); + add("info", 0, 0x07); + add("item", 0, 0x08); return names; })(); @@ -157,47 +160,53 @@ const SI_TAG_FIELDS = (function () { */ const SI_ATTRIBUTE_FIELDS = (function () { let names = {}; - function add(name, value, number) { + function add(name, value, codepage, number) { let entry = { name: name, value: value, number: number, }; - names[number] = entry; + if (!names[codepage]) { + names[codepage] = {}; + } + names[codepage][number] = entry; } - add("action", "signal-none", 0x05); - add("action", "signal-low", 0x06); - add("action", "signal-medium", 0x07); - add("action", "signal-high", 0x08); - add("action", "delete", 0x09); - add("created", "", 0x0A); - add("href", "", 0x0B); - add("href", "http://", 0x0C); - add("href", "http://www.", 0x0D); - add("href", "https://", 0x0E); - add("href", "https://www.", 0x0F); - add("si-expires", "", 0x10); - add("si-id", "", 0x11); - add("class", "", 0x12); + add("action", "signal-none", 0, 0x05); + add("action", "signal-low", 0, 0x06); + add("action", "signal-medium", 0, 0x07); + add("action", "signal-high", 0, 0x08); + add("action", "delete", 0, 0x09); + add("created", "", 0, 0x0A); + add("href", "", 0, 0x0B); + add("href", "http://", 0, 0x0C); + add("href", "http://www.", 0, 0x0D); + add("href", "https://", 0, 0x0E); + add("href", "https://www.", 0, 0x0F); + add("si-expires", "", 0, 0x10); + add("si-id", "", 0, 0x11); + add("class", "", 0, 0x12); return names; })(); const SI_VALUE_FIELDS = (function () { let names = {}; - function add(value, number) { + function add(value, codepage, number) { let entry = { value: value, number: number, }; - names[number] = entry; + if (!names[codepage]) { + names[codepage] = {}; + } + names[codepage][number] = entry; } - add(".com/", 0x85); - add(".edu/", 0x86); - add(".net/", 0x87); - add(".org/", 0x88); + add(".com/", 0, 0x85); + add(".edu/", 0, 0x86); + add(".net/", 0, 0x87); + add(".org/", 0, 0x88); return names; })(); diff --git a/dom/wappush/src/gonk/SlPduHelper.jsm b/dom/wappush/src/gonk/SlPduHelper.jsm index eba29431819..1973b9cb4ef 100644 --- a/dom/wappush/src/gonk/SlPduHelper.jsm +++ b/dom/wappush/src/gonk/SlPduHelper.jsm @@ -90,15 +90,18 @@ this.PduHelper = { */ const SL_TAG_FIELDS = (function () { let names = {}; - function add(name, number) { + function add(name, codepage, number) { let entry = { name: name, number: number, }; - names[number] = entry; + if (!names[codepage]) { + names[codepage] = {}; + } + names[codepage][number] = entry; } - add("sl", 0x05); + add("sl", 0, 0x05); return names; })(); @@ -110,41 +113,47 @@ const SL_TAG_FIELDS = (function () { */ const SL_ATTRIBUTE_FIELDS = (function () { let names = {}; - function add(name, value, number) { + function add(name, value, codepage, number) { let entry = { name: name, value: value, number: number, }; - names[number] = entry; + if (!names[codepage]) { + names[codepage] = {}; + } + names[codepage][number] = entry; } - add("action", "execute-low", 0x05); - add("action", "execute-high", 0x06); - add("action", "cache", 0x07); - add("href", "", 0x08); - add("href", "http://", 0x09); - add("href", "http://www.", 0x0A); - add("href", "https://", 0x0B); - add("href", "https://www.", 0x0C); + add("action", "execute-low", 0, 0x05); + add("action", "execute-high", 0, 0x06); + add("action", "cache", 0, 0x07); + add("href", "", 0, 0x08); + add("href", "http://", 0, 0x09); + add("href", "http://www.", 0, 0x0A); + add("href", "https://", 0, 0x0B); + add("href", "https://www.", 0, 0x0C); return names; })(); const SL_VALUE_FIELDS = (function () { let names = {}; - function add(value, number) { + function add(value, codepage, number) { let entry = { value: value, number: number, }; - names[number] = entry; + if (!names[codepage]) { + names[codepage] = {}; + } + names[codepage][number] = entry; } - add(".com/", 0x85); - add(".edu/", 0x86); - add(".net/", 0x87); - add(".org/", 0x88); + add(".com/", 0, 0x85); + add(".edu/", 0, 0x86); + add(".net/", 0, 0x87); + add(".org/", 0, 0x88); return names; })(); From d0b61ea8e6bd4f232589d739701f55563d3c50cb Mon Sep 17 00:00:00 2001 From: Chuck Lee Date: Mon, 29 Jul 2013 15:08:40 +0800 Subject: [PATCH 08/36] Bug 897368 - 0003. Test case for code page switch. r=vicamo --- dom/wappush/tests/test_cp_pdu_helper.js | 140 ++++++++++++++++++++++++ 1 file changed, 140 insertions(+) diff --git a/dom/wappush/tests/test_cp_pdu_helper.js b/dom/wappush/tests/test_cp_pdu_helper.js index c43f280eb73..f98ddaffaad 100644 --- a/dom/wappush/tests/test_cp_pdu_helper.js +++ b/dom/wappush/tests/test_cp_pdu_helper.js @@ -357,3 +357,143 @@ add_test(function test_cp_parse_wbxml() { run_next_test(); }); + +/** + * CP compressed by WBXML with code page switch + */ +add_test(function test_cp_parse_wbxml_code_page() { + let wbxml_code_page_data_array = new Uint8Array([ + 0x03, 0x0B, 0x6A, 0x00, 0x45, 0xC6, 0x56, 0x01, + 0x87, 0x07, 0x06, 0x03, 0x43, 0x48, 0x54, 0x5F, + 0x65, 0x6D, 0x6F, 0x6D, 0x65, 0x00, 0x01, 0x01, + 0xC6, 0x00, 0x01, 0x55, 0x01, 0x87, 0x36, 0x00, + 0x00, 0x06, 0x03, 0x77, 0x32, 0x00, 0x01, 0x87, + 0x00, 0x01, 0x39, 0x00, 0x00, 0x06, 0x03, 0x57, + 0x50, 0x52, 0x4F, 0x58, 0x59, 0x00, 0x01, 0x87, + 0x07, 0x06, 0x03, 0x43, 0x48, 0x54, 0x5F, 0x65, + 0x6D, 0x6F, 0x6D, 0x65, 0x00, 0x01, 0xC6, 0x00, + 0x01, 0x59, 0x01, 0x87, 0x3A, 0x00, 0x00, 0x06, + 0x03, 0x68, 0x74, 0x74, 0x70, 0x3A, 0x2F, 0x2F, + 0x77, 0x61, 0x70, 0x2E, 0x65, 0x6D, 0x6F, 0x6D, + 0x65, 0x2E, 0x6E, 0x65, 0x74, 0x2F, 0x00, 0x01, + 0x87, 0x07, 0x06, 0x03, 0x43, 0x48, 0x54, 0x5F, + 0x65, 0x6D, 0x6F, 0x6D, 0x65, 0x00, 0x01, 0x87, + 0x1C, 0x01, 0x01, 0x01, 0xC6, 0x00, 0x01, 0x55, + 0x01, 0x87, 0x36, 0x00, 0x00, 0x06, 0x03, 0x77, + 0x34, 0x00, 0x01, 0x87, 0x00, 0x01, 0x39, 0x00, + 0x00, 0x06, 0x03, 0x4D, 0x50, 0x52, 0x4F, 0x58, + 0x59, 0x00, 0x01, 0x87, 0x00, 0x01, 0x34, 0x00, + 0x00, 0x06, 0x03, 0x68, 0x74, 0x74, 0x70, 0x3A, + 0x2F, 0x2F, 0x6D, 0x6D, 0x73, 0x3A, 0x38, 0x30, + 0x30, 0x32, 0x00, 0x01, 0x01, 0xC6, 0x51, 0x01, + 0x87, 0x15, 0x06, 0x03, 0x57, 0x50, 0x52, 0x4F, + 0x58, 0x59, 0x00, 0x01, 0x87, 0x07, 0x06, 0x03, + 0x43, 0x48, 0x54, 0x5F, 0x65, 0x6D, 0x6F, 0x6D, + 0x65, 0x00, 0x01, 0x87, 0x1C, 0x06, 0x03, 0x68, + 0x74, 0x74, 0x70, 0x3A, 0x2F, 0x2F, 0x77, 0x61, + 0x70, 0x2E, 0x65, 0x6D, 0x6F, 0x6D, 0x65, 0x2E, + 0x6E, 0x65, 0x74, 0x2F, 0x00, 0x01, 0xC6, 0x52, + 0x01, 0x87, 0x2F, 0x06, 0x03, 0x50, 0x52, 0x4F, + 0x58, 0x59, 0x31, 0x00, 0x01, 0x87, 0x20, 0x06, + 0x03, 0x31, 0x30, 0x2E, 0x31, 0x2E, 0x31, 0x2E, + 0x31, 0x00, 0x01, 0x87, 0x21, 0x06, 0x85, 0x01, + 0x87, 0x22, 0x06, 0x03, 0x43, 0x48, 0x54, 0x5F, + 0x65, 0x6D, 0x6F, 0x6D, 0x65, 0x00, 0x01, 0xC6, + 0x53, 0x01, 0x87, 0x23, 0x06, 0x03, 0x38, 0x30, + 0x38, 0x30, 0x00, 0x01, 0x01, 0x01, 0x01, 0xC6, + 0x51, 0x01, 0x87, 0x15, 0x06, 0x03, 0x4D, 0x50, + 0x52, 0x4F, 0x58, 0x59, 0x00, 0x01, 0x87, 0x07, + 0x06, 0x03, 0x43, 0x48, 0x54, 0x5F, 0x4D, 0x4D, + 0x53, 0x00, 0x01, 0xC6, 0x52, 0x01, 0x87, 0x2F, + 0x06, 0x03, 0x50, 0x52, 0x4F, 0x58, 0x59, 0x32, + 0x00, 0x01, 0x87, 0x20, 0x06, 0x03, 0x31, 0x30, + 0x2E, 0x31, 0x2E, 0x31, 0x2E, 0x31, 0x00, 0x01, + 0x87, 0x21, 0x06, 0x85, 0x01, 0x87, 0x22, 0x06, + 0x03, 0x43, 0x48, 0x54, 0x5F, 0x4D, 0x4D, 0x53, + 0x00, 0x01, 0xC6, 0x53, 0x01, 0x87, 0x23, 0x06, + 0x03, 0x38, 0x30, 0x38, 0x30, 0x00, 0x01, 0x01, + 0x01, 0x01, 0xC6, 0x55, 0x01, 0x87, 0x11, 0x06, + 0x03, 0x43, 0x48, 0x54, 0x5F, 0x65, 0x6D, 0x6F, + 0x6D, 0x65, 0x00, 0x01, 0x87, 0x07, 0x06, 0x03, + 0x43, 0x48, 0x54, 0x5F, 0x65, 0x6D, 0x6F, 0x6D, + 0x65, 0x00, 0x01, 0x87, 0x10, 0x06, 0xAB, 0x01, + 0x87, 0x08, 0x06, 0x03, 0x65, 0x6D, 0x6F, 0x6D, + 0x65, 0x00, 0x01, 0x87, 0x09, 0x06, 0x89, 0x01, + 0x01, 0xC6, 0x55, 0x01, 0x87, 0x11, 0x06, 0x03, + 0x43, 0x48, 0x54, 0x5F, 0x4D, 0x4D, 0x53, 0x00, + 0x01, 0x87, 0x07, 0x06, 0x03, 0x43, 0x48, 0x54, + 0x5F, 0x4D, 0x4D, 0x53, 0x00, 0x01, 0x87, 0x10, + 0x06, 0xAB, 0x01, 0x87, 0x08, 0x06, 0x03, 0x65, + 0x6D, 0x6F, 0x6D, 0x65, 0x00, 0x01, 0x87, 0x09, + 0x06, 0x89, 0x01, 0x01, 0x01 + ]); + let wbxml_content = + "" + + "" + + "" + + "" + + "" + + "" + + "" + + "" + + "" + + "" + + "" + + "" + + "" + + "" + + "" + + "" + + "" + + "" + + "" + + "" + + "" + + "" + + "" + + "" + + "" + + "" + + "" + + "" + + "" + + "" + + "" + + "" + + "" + + "" + + "" + + "" + + "" + + "" + + "" + + "" + + "" + + "" + + "" + + "" + + "" + + "" + + "" + + "" + + "" + + "" + + "" + + "" + + "" + + "" + + "" + + "" + + "" + + "" + + "" + + "" + + ""; + + test_parser(wbxml_code_page_data_array, "application/vnd.wap.connectivity-wbxml", { + contentType: "text/vnd.wap.connectivity-xml", + content: wbxml_content + }); + + run_next_test(); +}); From 16228b70980a1c12ba9047002fb7941dbf962fe6 Mon Sep 17 00:00:00 2001 From: Gaia Pushbot Date: Tue, 30 Jul 2013 07:00:24 -0700 Subject: [PATCH 09/36] Bumping gaia.json for 2 gaia-central revision(s) ======== https://hg.mozilla.org/integration/gaia-central/rev/8e61d48cd62b Author: Andrew Sutherland Desc: Merge pull request #11246 from ian-liu/email/Bug887700_cannot_load_email_in_Inbox_after_OTA_updated Bug 887700 - [OTA] [Data Migration] [Email] Cannot load email in Inbox after update from v1.0.1 to v1.1.0. r=asuth ======== https://hg.mozilla.org/integration/gaia-central/rev/de3ad2b843b8 Author: ian-liu Desc: Bug 887700 - [OTA] [Data Migration] [Email] Cannot load email in Inbox after update from v1.0.1 to v1.1.0 --- 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 e3fbad706d8..4fc236d8f26 100644 --- a/b2g/config/gaia.json +++ b/b2g/config/gaia.json @@ -1,4 +1,4 @@ { - "revision": "a2800243e083f43fad4ffce4d52e3bb5bfc1d0ee", + "revision": "8e61d48cd62b88dc614a7513d4b1c2e47097419d", "repo_path": "/integration/gaia-central" } From aef3e6d5a712e1363d53d953eac5806d0221e75b Mon Sep 17 00:00:00 2001 From: Edgar Chen Date: Tue, 30 Jul 2013 17:11:03 +0800 Subject: [PATCH 10/36] Bug 899484 - Part 1: Use sendChromeMessage to send message instead of using sendDOMMessage. r=hsinyi --- dom/system/gonk/ril_worker.js | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/dom/system/gonk/ril_worker.js b/dom/system/gonk/ril_worker.js index c251bd7b107..78112560986 100644 --- a/dom/system/gonk/ril_worker.js +++ b/dom/system/gonk/ril_worker.js @@ -1616,7 +1616,7 @@ let RIL = { if (roamingMode === -1) { options.errorMsg = GECKO_ERROR_INVALID_PARAMETER; - this.sendDOMMessage(options); + this.sendChromeMessage(options); return; } @@ -5649,22 +5649,22 @@ RIL[REQUEST_CDMA_SET_SUBSCRIPTION_SOURCE] = null; RIL[REQUEST_CDMA_SET_ROAMING_PREFERENCE] = function REQUEST_CDMA_SET_ROAMING_PREFERENCE(length, options) { if (options.rilRequestError) { options.errorMsg = RIL_ERROR_TO_GECKO_ERROR[options.rilRequestError]; - this.sendDOMMessage(options); + this.sendChromeMessage(options); return; } - this.sendDOMMessage(options); + this.sendChromeMessage(options); }; RIL[REQUEST_CDMA_QUERY_ROAMING_PREFERENCE] = function REQUEST_CDMA_QUERY_ROAMING_PREFERENCE(length, options) { if (options.rilRequestError) { options.errorMsg = RIL_ERROR_TO_GECKO_ERROR[options.rilRequestError]; - this.sendDOMMessage(options); + this.sendChromeMessage(options); return; } let mode = Buf.readUint32List(); options.mode = CDMA_ROAMING_PREFERENCE_TO_GECKO[mode[0]]; - this.sendDOMMessage(options); + this.sendChromeMessage(options); }; RIL[REQUEST_SET_TTY_MODE] = null; RIL[REQUEST_QUERY_TTY_MODE] = null; From 44fa6c804e0a4ec3a84661b51d15036b69a4c5a7 Mon Sep 17 00:00:00 2001 From: Edgar Chen Date: Tue, 30 Jul 2013 17:18:24 +0800 Subject: [PATCH 11/36] Bug 899484 - Part 2: Add marionette tests for roaming preference. r=hsinyi --- dom/network/tests/marionette/manifest.ini | 1 + .../test_mobile_roaming_preference.js | 98 +++++++++++++++++++ 2 files changed, 99 insertions(+) create mode 100644 dom/network/tests/marionette/test_mobile_roaming_preference.js diff --git a/dom/network/tests/marionette/manifest.ini b/dom/network/tests/marionette/manifest.ini index d61be3dc847..a8adccf5f0e 100644 --- a/dom/network/tests/marionette/manifest.ini +++ b/dom/network/tests/marionette/manifest.ini @@ -13,5 +13,6 @@ disabled = Bug 808783 [test_mobile_data_location.js] [test_mobile_data_state.js] [test_mobile_mmi.js] +[test_mobile_roaming_preference.js] [test_call_barring_get_option.js] [test_call_barring_set_error.js] diff --git a/dom/network/tests/marionette/test_mobile_roaming_preference.js b/dom/network/tests/marionette/test_mobile_roaming_preference.js new file mode 100644 index 00000000000..96c8ce4888e --- /dev/null +++ b/dom/network/tests/marionette/test_mobile_roaming_preference.js @@ -0,0 +1,98 @@ +/* Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ */ + +MARIONETTE_TIMEOUT = 60000; + +SpecialPowers.addPermission("mobileconnection", true, document); + +let connection = navigator.mozMobileConnection; +ok(connection instanceof MozMobileConnection, + "connection is instanceof " + connection.constructor); + +function failedToSetRoamingPreference(mode, expectedErrorMessage, callback) { + let request = connection.setRoamingPreference(mode); + + ok(request instanceof DOMRequest, + "request instanceof " + request.constructor); + + request.onsuccess = function onsuccess() { + ok(false, "Should not be here !!"); + + callback(); + } + + request.onerror = function onerror() { + is(request.error.name, expectedErrorMessage); + + callback(); + } +} + +function testSetRoamingPreferenceWithNullValue() { + log("test setRoamingPreference(null)"); + + failedToSetRoamingPreference(null, "InvalidParameter", runNextTest); +} + +function testSetRoamingPreferenceWithInvalidValue() { + log("test setRoamingPreference(\"InvalidValue\")"); + + failedToSetRoamingPreference("InvalidValue", "InvalidParameter", runNextTest); +} + +function testSetRoamingPreferenceToHome() { + log("test setRoamingPreference(\"home\")"); + + // TODO: Bug 896394. + // Currently emulator run as GSM mode by default. So we expect to get a + // 'RequestNotSupported' error here. + failedToSetRoamingPreference("home", "RequestNotSupported", runNextTest); +} + +function testGetRoamingPreference() { + log("test getRoamingPreference()"); + + // TODO: Bug 896394. + // Currently emulator run as GSM mode by default. So we expect to get a + // 'RequestNotSupported' error here. + let request = connection.getRoamingPreference(); + + ok(request instanceof DOMRequest, + "request instanceof " + request.constructor); + + request.onsuccess = function onsuccess() { + ok(false, "Should not be here !!"); + + runNextTest(); + } + + request.onerror = function onerror() { + is(request.error.name, "RequestNotSupported"); + + runNextTest(); + } +} + +let tests = [ + testSetRoamingPreferenceWithNullValue, + testSetRoamingPreferenceWithInvalidValue, + testSetRoamingPreferenceToHome, + testGetRoamingPreference +]; + +function runNextTest() { + let test = tests.shift(); + if (!test) { + cleanUp(); + return; + } + + test(); +} + +function cleanUp() { + SpecialPowers.removePermission("mobileconnection", document); + finish(); +} + +runNextTest(); \ No newline at end of file From d3e986ac0f4f715bf8b6a3e1e2ca0efed0a92857 Mon Sep 17 00:00:00 2001 From: Gaia Pushbot Date: Tue, 30 Jul 2013 08:05:23 -0700 Subject: [PATCH 12/36] Bumping gaia.json for 2 gaia-central revision(s) ======== https://hg.mozilla.org/integration/gaia-central/rev/c16a68a6edd5 Author: Dale Harvey Desc: Merge pull request #11216 from mpizza/Bug_898358_turnOff_flashLight_frontFacingMode Bug 898372 - [Camera][Helix][V1.1.0 HD] FxOS doesn't turn off the light r=daleharvey ======== https://hg.mozilla.org/integration/gaia-central/rev/0d12748b4ec0 Author: mpizza Desc: Bug 898372 - [Camera][Helix][V1.1.0 HD] FxOS doesn't turn off the light after user switched to front-facing 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 4fc236d8f26..351b6c89cc2 100644 --- a/b2g/config/gaia.json +++ b/b2g/config/gaia.json @@ -1,4 +1,4 @@ { - "revision": "8e61d48cd62b88dc614a7513d4b1c2e47097419d", + "revision": "c16a68a6edd54064791557a65f2a76064fc1ec12", "repo_path": "/integration/gaia-central" } From 826e54b82eb35fdb30b9b6d1f885e1711a6c0c33 Mon Sep 17 00:00:00 2001 From: Gaia Pushbot Date: Tue, 30 Jul 2013 08:30:22 -0700 Subject: [PATCH 13/36] Bumping gaia.json for 2 gaia-central revision(s) ======== https://hg.mozilla.org/integration/gaia-central/rev/fd0e7d9b0435 Author: Dale Harvey Desc: Merge pull request #11214 from mpizza/Bug_898358_video_recording_disable_switchBTN Bug 898358 - [Camera][Helix][V1.1.0 HD] The switching icon is still disp r=daleharvey ======== https://hg.mozilla.org/integration/gaia-central/rev/b711390d891a Author: mpizza Desc: Bug 898358 - [Camera][Helix][V1.1.0 HD] The switching icon is still displayed here while user is recording a video --- 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 351b6c89cc2..709517aaf02 100644 --- a/b2g/config/gaia.json +++ b/b2g/config/gaia.json @@ -1,4 +1,4 @@ { - "revision": "c16a68a6edd54064791557a65f2a76064fc1ec12", + "revision": "fd0e7d9b0435e27284b58bd616db78b71e5e711a", "repo_path": "/integration/gaia-central" } From b028ba60232180df9f36c88fe7d395cc0324b28e Mon Sep 17 00:00:00 2001 From: Gaia Pushbot Date: Tue, 30 Jul 2013 08:40:28 -0700 Subject: [PATCH 14/36] Bumping gaia.json for 2 gaia-central revision(s) ======== https://hg.mozilla.org/integration/gaia-central/rev/b716117c0391 Author: Kevin Grandon Desc: Merge pull request #11235 from KevinGrandon/bug_872500_update_manifests Bug 872500 - Update manifests r=baku ======== https://hg.mozilla.org/integration/gaia-central/rev/3e12b71f13f5 Author: Kevin Grandon Desc: Bug 872500 - Update manifests --- 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 709517aaf02..141ddfe0b70 100644 --- a/b2g/config/gaia.json +++ b/b2g/config/gaia.json @@ -1,4 +1,4 @@ { - "revision": "fd0e7d9b0435e27284b58bd616db78b71e5e711a", + "revision": "b716117c0391bccc601c3714ff57b12052f4a53d", "repo_path": "/integration/gaia-central" } From 7229dec7e12a3d856ea669840c1b8fa6748c6cf7 Mon Sep 17 00:00:00 2001 From: Michael Wu Date: Tue, 30 Jul 2013 13:36:53 -0400 Subject: [PATCH 15/36] Bug 898897 - Update GonkDisplayJB to support JB MR2, r=vlad --- widget/gonk/libdisplay/FramebufferSurface.cpp | 1 - widget/gonk/libdisplay/GonkDisplayJB.cpp | 16 ++++++++++------ widget/gonk/libdisplay/moz.build | 2 +- 3 files changed, 11 insertions(+), 8 deletions(-) diff --git a/widget/gonk/libdisplay/FramebufferSurface.cpp b/widget/gonk/libdisplay/FramebufferSurface.cpp index ea0ec72b413..b41c46f487e 100644 --- a/widget/gonk/libdisplay/FramebufferSurface.cpp +++ b/widget/gonk/libdisplay/FramebufferSurface.cpp @@ -29,7 +29,6 @@ #include #include -#include #include #include "FramebufferSurface.h" diff --git a/widget/gonk/libdisplay/GonkDisplayJB.cpp b/widget/gonk/libdisplay/GonkDisplayJB.cpp index ce826e92f55..11fb231587b 100644 --- a/widget/gonk/libdisplay/GonkDisplayJB.cpp +++ b/widget/gonk/libdisplay/GonkDisplayJB.cpp @@ -14,7 +14,7 @@ */ #include "GonkDisplayJB.h" -#include +#include #include #include @@ -99,7 +99,7 @@ GonkDisplayJB::GonkDisplayJB() mAlloc = new GraphicBufferAlloc(); mFBSurface = new FramebufferSurface(0, mWidth, mHeight, surfaceformat, mAlloc); - sp stc = new SurfaceTextureClient(static_cast >(mFBSurface->getBufferQueue())); + sp stc = new Surface(static_cast >(mFBSurface->getBufferQueue())); mSTClient = stc; mList = (hwc_display_contents_1_t *)malloc(sizeof(*mList) + (sizeof(hwc_layer_1_t)*2)); @@ -166,8 +166,8 @@ GonkDisplayJB::SwapBuffers(EGLDisplay dpy, EGLSurface sur) StopBootAnimation(); mBootAnimBuffer = nullptr; - mList->dpy = dpy; - mList->sur = sur; + mList->outbuf = nullptr; + mList->outbufAcquireFenceFd = -1; eglSwapBuffers(dpy, sur); return Post(mFBSurface->lastHandle, mFBSurface->lastFenceFD); } @@ -189,8 +189,11 @@ GonkDisplayJB::Post(buffer_handle_t buf, int fence) mList->flags = HWC_GEOMETRY_CHANGED; mList->hwLayers[0].compositionType = HWC_BACKGROUND; mList->hwLayers[0].hints = 0; - mList->hwLayers[0].flags = 0; + /* Skip this layer so the hwc module doesn't complain about null handles */ + mList->hwLayers[0].flags = HWC_SKIP_LAYER; mList->hwLayers[0].backgroundColor = {0}; + /* hwc module checks displayFrame even though it shouldn't */ + mList->hwLayers[0].displayFrame = r; mList->hwLayers[1].compositionType = HWC_FRAMEBUFFER_TARGET; mList->hwLayers[1].hints = 0; mList->hwLayers[1].flags = 0; @@ -200,9 +203,10 @@ GonkDisplayJB::Post(buffer_handle_t buf, int fence) mList->hwLayers[1].sourceCrop = r; mList->hwLayers[1].displayFrame = r; mList->hwLayers[1].visibleRegionScreen.numRects = 1; - mList->hwLayers[1].visibleRegionScreen.rects = &mList->hwLayers[0].sourceCrop; + mList->hwLayers[1].visibleRegionScreen.rects = &mList->hwLayers[1].sourceCrop; mList->hwLayers[1].acquireFenceFd = fence; mList->hwLayers[1].releaseFenceFd = -1; + mList->hwLayers[1].planeAlpha = 0xFF; mHwc->prepare(mHwc, HWC_NUM_DISPLAY_TYPES, displays); int err = mHwc->set(mHwc, HWC_NUM_DISPLAY_TYPES, displays); mFBSurface->setReleaseFenceFd(mList->hwLayers[1].releaseFenceFd); diff --git a/widget/gonk/libdisplay/moz.build b/widget/gonk/libdisplay/moz.build index 960c3d26adc..ea186b6d655 100644 --- a/widget/gonk/libdisplay/moz.build +++ b/widget/gonk/libdisplay/moz.build @@ -20,7 +20,7 @@ CPP_SOURCES += [ 'BootAnimation.cpp', ] -if CONFIG['ANDROID_VERSION'] == '17': +if CONFIG['ANDROID_VERSION'] == '18': CPP_SOURCES += [ 'FramebufferSurface.cpp', 'GraphicBufferAlloc.cpp', From 8e55a995e408f351add560a52e2ad08b2e13ecea Mon Sep 17 00:00:00 2001 From: Michael Wu Date: Tue, 30 Jul 2013 13:36:54 -0400 Subject: [PATCH 16/36] Bug 898898 - Add support for building on gonk-JB MR2, r=glandium --- b2g/app/Makefile.in | 2 +- configure.in | 2 +- toolkit/library/Makefile.in | 4 +++- 3 files changed, 5 insertions(+), 3 deletions(-) diff --git a/b2g/app/Makefile.in b/b2g/app/Makefile.in index 3bfbe1df17c..7fe9ef55e22 100644 --- a/b2g/app/Makefile.in +++ b/b2g/app/Makefile.in @@ -30,7 +30,7 @@ LIBS += \ $(DEPTH)/widget/gonk/libdisplay/$(LIB_PREFIX)display.$(LIB_SUFFIX) \ $(MOZ_ZLIB_LIBS) \ $(NULL) -ifeq (17,$(ANDROID_VERSION)) +ifeq (18,$(ANDROID_VERSION)) LIBS += \ -lgui \ -lsuspend \ diff --git a/configure.in b/configure.in index cf800ea9c4b..62da95e6987 100644 --- a/configure.in +++ b/configure.in @@ -214,7 +214,7 @@ if test -n "$gonkdir" ; then AC_DEFINE(MOZ_OMX_DECODER) AC_SUBST(MOZ_OMX_DECODER) ;; - 17) + 18) GONK_INCLUDES="-I$gonkdir/frameworks/native/include" ;; *) diff --git a/toolkit/library/Makefile.in b/toolkit/library/Makefile.in index e5ac009f49e..1f082d4a361 100644 --- a/toolkit/library/Makefile.in +++ b/toolkit/library/Makefile.in @@ -96,6 +96,9 @@ endif #} ifdef MOZ_B2G_BT #{ STATIC_LIBS += mozdbus_s +ifeq (gonk,$(MOZ_WIDGET_TOOLKIT)) +OS_LIBS += -ldbus +endif endif #} ifneq ($(strip $(MOZ_B2G_RIL)$(MOZ_B2G_BT)),) #{ @@ -446,7 +449,6 @@ OS_LIBS += \ -lsysutils \ -lcamera_client \ -lsensorservice \ - -ldbus \ -lstagefright \ -lstagefright_foundation \ -lstagefright_omx \ From 3c6d12f1bf2ce42d8de153d1b3d8166516279f52 Mon Sep 17 00:00:00 2001 From: Gaia Pushbot Date: Tue, 30 Jul 2013 10:45:24 -0700 Subject: [PATCH 17/36] Bumping gaia.json for 2 gaia-central revision(s) ======== https://hg.mozilla.org/integration/gaia-central/rev/1e3fa6fe4ab9 Author: Justin Lebar Desc: Merge pull request #11236 from jlebar/apploaded-listener Bug 899328 - Register only one listener for mozbrowserloadend and appload... ======== https://hg.mozilla.org/integration/gaia-central/rev/836f32732fee Author: Justin Lebar Desc: Bug 899328 - Register only one listener for mozbrowserloadend and appopen on a given app iframe. This prevents us from leaking listeners. --- 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 141ddfe0b70..77bb45fff9b 100644 --- a/b2g/config/gaia.json +++ b/b2g/config/gaia.json @@ -1,4 +1,4 @@ { - "revision": "b716117c0391bccc601c3714ff57b12052f4a53d", + "revision": "1e3fa6fe4ab933fd3ebea869679bbba7a11fa71f", "repo_path": "/integration/gaia-central" } From b91095aea20fdc9d86254ca15da89a69efd4758a Mon Sep 17 00:00:00 2001 From: Kartikaya Gupta Date: Tue, 30 Jul 2013 14:03:38 -0400 Subject: [PATCH 18/36] Bug 866232 - Reserve a layer tree id for the root layer tree. r=BenWa --- gfx/layers/ipc/CompositorParent.cpp | 7 ++++++- gfx/layers/ipc/CompositorParent.h | 5 +++++ 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/gfx/layers/ipc/CompositorParent.cpp b/gfx/layers/ipc/CompositorParent.cpp index 3f8d6a21bf6..bfd4a0361a8 100644 --- a/gfx/layers/ipc/CompositorParent.cpp +++ b/gfx/layers/ipc/CompositorParent.cpp @@ -697,12 +697,17 @@ CompositorParent::NotifyChildCreated(uint64_t aChild) sIndirectLayerTrees[aChild].mParent = this; } +// Ensure all layer tree IDs are greater than zero, so if we +// ever see a zero-valued layer tree id we know it's actually +// uninitialized and/or garbage. +uint64_t CompositorParent::ROOT_LAYER_TREE_ID = 1; + /*static*/ uint64_t CompositorParent::AllocateLayerTreeId() { MOZ_ASSERT(CompositorLoop()); MOZ_ASSERT(NS_IsMainThread()); - static uint64_t ids; + static uint64_t ids = ROOT_LAYER_TREE_ID; return ++ids; } diff --git a/gfx/layers/ipc/CompositorParent.h b/gfx/layers/ipc/CompositorParent.h index 3b8612639d9..70ba9362428 100644 --- a/gfx/layers/ipc/CompositorParent.h +++ b/gfx/layers/ipc/CompositorParent.h @@ -113,6 +113,11 @@ public: */ static void ShutDown(); + /** + * The reserved layer tree ID for the root of the layer tree. + */ + static uint64_t ROOT_LAYER_TREE_ID; + /** * Allocate an ID that can be used to refer to a layer tree and * associated resources that live only on the compositor thread. From 56b257378e7eead6083e25358dea446802191464 Mon Sep 17 00:00:00 2001 From: Kartikaya Gupta Date: Tue, 30 Jul 2013 14:03:39 -0400 Subject: [PATCH 19/36] Bug 866232 - Move around code in APZC to more easily allow creating it on the compositor thread. r=BenWa --- gfx/layers/ipc/AsyncPanZoomController.cpp | 70 ++++++++++------------- gfx/layers/ipc/AsyncPanZoomController.h | 19 +++--- 2 files changed, 41 insertions(+), 48 deletions(-) diff --git a/gfx/layers/ipc/AsyncPanZoomController.cpp b/gfx/layers/ipc/AsyncPanZoomController.cpp index 50776b667cf..95c69b1abbb 100644 --- a/gfx/layers/ipc/AsyncPanZoomController.cpp +++ b/gfx/layers/ipc/AsyncPanZoomController.cpp @@ -106,6 +106,18 @@ static float gYSkateSizeMultiplier = 3.5f; static float gXStationarySizeMultiplier = 1.5f; static float gYStationarySizeMultiplier = 2.5f; +/** + * The time period in ms that throttles mozbrowserasyncscroll event. + * Default is 100ms if there is no "apzc.asyncscroll.throttle" in preference. + */ + +static int gAsyncScrollThrottleTime = 100; +/** + * The timeout in ms for mAsyncScrollTimeoutTask delay task. + * Default is 300ms if there is no "apzc.asyncscroll.timeout" in preference. + */ +static int gAsyncScrollTimeout = 300; + static TimeStamp sFrameTime; static TimeStamp @@ -121,8 +133,16 @@ AsyncPanZoomController::SetFrameTime(const TimeStamp& aTime) { sFrameTime = aTime; } -static void ReadAZPCPrefs() +/*static*/ void +AsyncPanZoomController::InitializeGlobalState() { + MOZ_ASSERT(NS_IsMainThread()); + + static bool sInitialized = false; + if (sInitialized) + return; + sInitialized = true; + Preferences::AddIntVarCache(&gPanRepaintInterval, "gfx.azpc.pan_repaint_interval", gPanRepaintInterval); Preferences::AddIntVarCache(&gFlingRepaintInterval, "gfx.azpc.fling_repaint_interval", gFlingRepaintInterval); Preferences::AddFloatVarCache(&gMinSkateSpeed, "gfx.azpc.min_skate_speed", gMinSkateSpeed); @@ -133,30 +153,13 @@ static void ReadAZPCPrefs() Preferences::AddFloatVarCache(&gYSkateSizeMultiplier, "gfx.azpc.y_skate_size_multiplier", gYSkateSizeMultiplier); Preferences::AddFloatVarCache(&gXStationarySizeMultiplier, "gfx.azpc.x_stationary_size_multiplier", gXStationarySizeMultiplier); Preferences::AddFloatVarCache(&gYStationarySizeMultiplier, "gfx.azpc.y_stationary_size_multiplier", gYStationarySizeMultiplier); -} + Preferences::AddIntVarCache(&gAsyncScrollThrottleTime, "apzc.asyncscroll.throttle", gAsyncScrollThrottleTime); + Preferences::AddIntVarCache(&gAsyncScrollTimeout, "apzc.asyncscroll.timeout", gAsyncScrollTimeout); -class ReadAZPCPref MOZ_FINAL : public nsRunnable { -public: - NS_IMETHOD Run() - { - ReadAZPCPrefs(); - return NS_OK; - } -}; - -static void InitAZPCPrefs() -{ - static bool sInitialized = false; - if (sInitialized) - return; - - sInitialized = true; - if (NS_IsMainThread()) { - ReadAZPCPrefs(); - } else { - // We have to dispatch an event to the main thread to read the pref. - NS_DispatchToMainThread(new ReadAZPCPref()); - } + gComputedTimingFunction = new ComputedTimingFunction(); + gComputedTimingFunction->Init( + nsTimingFunction(NS_STYLE_TRANSITION_TIMING_FUNCTION_EASE)); + ClearOnShutdown(&gComputedTimingFunction); } AsyncPanZoomController::AsyncPanZoomController(GeckoContentController* aGeckoContentController, @@ -176,33 +179,20 @@ AsyncPanZoomController::AsyncPanZoomController(GeckoContentController* aGeckoCon mLastAsyncScrollOffset(0, 0), mCurrentAsyncScrollOffset(0, 0), mAsyncScrollTimeoutTask(nullptr), - mAsyncScrollThrottleTime(100), - mAsyncScrollTimeout(300), mDPI(72), mDisableNextTouchBatch(false), mHandlingTouchQueue(false), mDelayPanning(false) { - MOZ_ASSERT(NS_IsMainThread()); MOZ_COUNT_CTOR(AsyncPanZoomController); - InitAZPCPrefs(); + InitializeGlobalState(); if (aGestures == USE_GESTURE_DETECTOR) { mGestureEventListener = new GestureEventListener(this); } SetDPI(mDPI); - - if (!gComputedTimingFunction) { - gComputedTimingFunction = new ComputedTimingFunction(); - gComputedTimingFunction->Init( - nsTimingFunction(NS_STYLE_TRANSITION_TIMING_FUNCTION_EASE)); - ClearOnShutdown(&gComputedTimingFunction); - } - - Preferences::GetUint("apzc.asyncscroll.throttle", &mAsyncScrollThrottleTime); - Preferences::GetUint("apzc.asyncscroll.timeout", &mAsyncScrollTimeout); } AsyncPanZoomController::~AsyncPanZoomController() { @@ -1129,7 +1119,7 @@ bool AsyncPanZoomController::SampleContentTransformForFrame(const TimeStamp& aSa // with the last event. // Otherwise, start a timer to fire the event sAsyncScrollTimeout ms from now. TimeDuration delta = aSampleTime - mLastAsyncScrollTime; - if (delta.ToMilliseconds() > mAsyncScrollThrottleTime && + if (delta.ToMilliseconds() > gAsyncScrollThrottleTime && mCurrentAsyncScrollOffset != mLastAsyncScrollOffset) { MonitorAutoLock monitor(mMonitor); mLastAsyncScrollTime = aSampleTime; @@ -1141,7 +1131,7 @@ bool AsyncPanZoomController::SampleContentTransformForFrame(const TimeStamp& aSa NewRunnableMethod(this, &AsyncPanZoomController::FireAsyncScrollOnTimeout); MessageLoop::current()->PostDelayedTask(FROM_HERE, mAsyncScrollTimeoutTask, - mAsyncScrollTimeout); + gAsyncScrollTimeout); } CSSToLayerScale paintedScale = frame.mDevPixelsPerCSSPixel * frame.mResolution; diff --git a/gfx/layers/ipc/AsyncPanZoomController.h b/gfx/layers/ipc/AsyncPanZoomController.h index be28064c797..d1fc839d375 100644 --- a/gfx/layers/ipc/AsyncPanZoomController.h +++ b/gfx/layers/ipc/AsyncPanZoomController.h @@ -72,6 +72,17 @@ public: GestureBehavior aGestures = DEFAULT_GESTURES); ~AsyncPanZoomController(); + // -------------------------------------------------------------------------- + // These methods must only be called on the gecko thread. + // + + /** + * Read the various prefs and do any global initialization for all APZC instances. + * This must be run on the gecko thread before any APZC instances are actually + * used for anything meaningful. + */ + static void InitializeGlobalState(); + // -------------------------------------------------------------------------- // These methods must only be called on the controller/UI thread. // @@ -571,14 +582,6 @@ private: // ensures the last mozbrowserasyncscroll event is always been fired. CancelableTask* mAsyncScrollTimeoutTask; - // The time period in ms that throttles mozbrowserasyncscroll event. - // Default is 100ms if there is no "apzc.asyncscroll.throttle" in preference. - uint32_t mAsyncScrollThrottleTime; - - // The timeout in ms for mAsyncScrollTimeoutTask delay task. - // Default is 300ms if there is no "apzc.asyncscroll.timeout" in preference. - uint32_t mAsyncScrollTimeout; - int mDPI; // Flag used to determine whether or not we should disable handling of the From d87852c13337208b505682fe321b6ec36e520b93 Mon Sep 17 00:00:00 2001 From: Kartikaya Gupta Date: Tue, 30 Jul 2013 14:03:39 -0400 Subject: [PATCH 20/36] Bug 866232 - Guard some APZC fields by a lock so they can be nulled out from the compositor thread. r=BenWa --- gfx/layers/ipc/AsyncPanZoomController.cpp | 69 +++++++++++++++-------- gfx/layers/ipc/AsyncPanZoomController.h | 21 +++++-- 2 files changed, 61 insertions(+), 29 deletions(-) diff --git a/gfx/layers/ipc/AsyncPanZoomController.cpp b/gfx/layers/ipc/AsyncPanZoomController.cpp index 95c69b1abbb..5d8be3918ab 100644 --- a/gfx/layers/ipc/AsyncPanZoomController.cpp +++ b/gfx/layers/ipc/AsyncPanZoomController.cpp @@ -166,6 +166,7 @@ AsyncPanZoomController::AsyncPanZoomController(GeckoContentController* aGeckoCon GestureBehavior aGestures) : mPaintThrottler(GetFrameTime()), mGeckoContentController(aGeckoContentController), + mRefPtrMonitor("RefPtrMonitor"), mTouchListenerTimeoutTask(nullptr), mX(this), mY(this), @@ -199,10 +200,24 @@ AsyncPanZoomController::~AsyncPanZoomController() { MOZ_COUNT_DTOR(AsyncPanZoomController); } +already_AddRefed +AsyncPanZoomController::GetGeckoContentController() { + MonitorAutoLock lock(mRefPtrMonitor); + nsRefPtr controller = mGeckoContentController; + return controller.forget(); +} + +already_AddRefed +AsyncPanZoomController::GetGestureEventListener() { + MonitorAutoLock lock(mRefPtrMonitor); + nsRefPtr listener = mGestureEventListener; + return listener.forget(); +} + void AsyncPanZoomController::Destroy() { - // These memebrs can only be used on the controller/UI thread. + MonitorAutoLock lock(mRefPtrMonitor); mGeckoContentController = nullptr; mGestureEventListener = nullptr; } @@ -322,8 +337,9 @@ nsEventStatus AsyncPanZoomController::ReceiveInputEvent(const InputData& aEvent) nsEventStatus AsyncPanZoomController::HandleInputEvent(const InputData& aEvent) { nsEventStatus rv = nsEventStatus_eIgnore; - if (mGestureEventListener && !mDisableNextTouchBatch) { - rv = mGestureEventListener->HandleInputEvent(aEvent); + nsRefPtr listener = GetGestureEventListener(); + if (listener && !mDisableNextTouchBatch) { + rv = listener->HandleInputEvent(aEvent); if (rv == nsEventStatus_eConsumeNoDefault) return rv; } @@ -649,12 +665,13 @@ nsEventStatus AsyncPanZoomController::OnScaleEnd(const PinchGestureInput& aEvent } nsEventStatus AsyncPanZoomController::OnLongPress(const TapGestureInput& aEvent) { - if (mGeckoContentController) { + nsRefPtr controller = GetGeckoContentController(); + if (controller) { MonitorAutoLock monitor(mMonitor); CSSToScreenScale resolution = mFrameMetrics.CalculateResolution(); CSSPoint point = WidgetSpaceToCompensatedViewportSpace(aEvent.mPoint, resolution); - mGeckoContentController->HandleLongTap(gfx::RoundedToInt(point)); + controller->HandleLongTap(gfx::RoundedToInt(point)); return nsEventStatus_eConsumeNoDefault; } return nsEventStatus_eIgnore; @@ -665,25 +682,27 @@ nsEventStatus AsyncPanZoomController::OnSingleTapUp(const TapGestureInput& aEven } nsEventStatus AsyncPanZoomController::OnSingleTapConfirmed(const TapGestureInput& aEvent) { - if (mGeckoContentController) { + nsRefPtr controller = GetGeckoContentController(); + if (controller) { MonitorAutoLock monitor(mMonitor); CSSToScreenScale resolution = mFrameMetrics.CalculateResolution(); CSSPoint point = WidgetSpaceToCompensatedViewportSpace(aEvent.mPoint, resolution); - mGeckoContentController->HandleSingleTap(gfx::RoundedToInt(point)); + controller->HandleSingleTap(gfx::RoundedToInt(point)); return nsEventStatus_eConsumeNoDefault; } return nsEventStatus_eIgnore; } nsEventStatus AsyncPanZoomController::OnDoubleTap(const TapGestureInput& aEvent) { - if (mGeckoContentController) { + nsRefPtr controller = GetGeckoContentController(); + if (controller) { MonitorAutoLock monitor(mMonitor); if (mAllowZoom) { CSSToScreenScale resolution = mFrameMetrics.CalculateResolution(); CSSPoint point = WidgetSpaceToCompensatedViewportSpace(aEvent.mPoint, resolution); - mGeckoContentController->HandleDoubleTap(gfx::RoundedToInt(point)); + controller->HandleDoubleTap(gfx::RoundedToInt(point)); } return nsEventStatus_eConsumeNoDefault; @@ -1009,12 +1028,15 @@ void AsyncPanZoomController::RequestContentRepaint() { // This message is compressed, so fire whether or not we already have a paint // queued up. We need to know whether or not a paint was requested anyways, // for the purposes of content calling window.scrollTo(). - mPaintThrottler.PostTask( - FROM_HERE, - NewRunnableMethod(mGeckoContentController.get(), - &GeckoContentController::RequestContentRepaint, - mFrameMetrics), - GetFrameTime()); + nsRefPtr controller = GetGeckoContentController(); + if (controller) { + mPaintThrottler.PostTask( + FROM_HERE, + NewRunnableMethod(controller.get(), + &GeckoContentController::RequestContentRepaint, + mFrameMetrics), + GetFrameTime()); + } mFrameMetrics.mPresShellId = mLastContentPaintMetrics.mPresShellId; mLastPaintRequestMetrics = mFrameMetrics; @@ -1232,8 +1254,9 @@ void AsyncPanZoomController::UpdateCompositionBounds(const ScreenIntRect& aCompo void AsyncPanZoomController::CancelDefaultPanZoom() { mDisableNextTouchBatch = true; - if (mGestureEventListener) { - mGestureEventListener->CancelGesture(); + nsRefPtr listener = GetGestureEventListener(); + if (listener) { + listener->CancelGesture(); } } @@ -1414,15 +1437,15 @@ void AsyncPanZoomController::UpdateZoomConstraints(bool aAllowZoom, } void AsyncPanZoomController::PostDelayedTask(Task* aTask, int aDelayMs) { - if (!mGeckoContentController) { - return; + nsRefPtr controller = GetGeckoContentController(); + if (controller) { + controller->PostDelayedTask(aTask, aDelayMs); } - - mGeckoContentController->PostDelayedTask(aTask, aDelayMs); } void AsyncPanZoomController::SendAsyncScrollEvent() { - if (!mGeckoContentController) { + nsRefPtr controller = GetGeckoContentController(); + if (!controller) { return; } @@ -1434,7 +1457,7 @@ void AsyncPanZoomController::SendAsyncScrollEvent() { contentRect.MoveTo(mCurrentAsyncScrollOffset); } - mGeckoContentController->SendAsyncScrollDOMEvent(contentRect, scrollableSize); + controller->SendAsyncScrollDOMEvent(contentRect, scrollableSize); } static void GetAPZCAtPointOnSubtree(const ContainerLayer& aLayerIn, diff --git a/gfx/layers/ipc/AsyncPanZoomController.h b/gfx/layers/ipc/AsyncPanZoomController.h index d1fc839d375..d954420f898 100644 --- a/gfx/layers/ipc/AsyncPanZoomController.h +++ b/gfx/layers/ipc/AsyncPanZoomController.h @@ -87,12 +87,6 @@ public: // These methods must only be called on the controller/UI thread. // - /** - * Shut down the controller/UI thread state and prepare to be - * deleted (which may happen from any thread). - */ - void Destroy(); - /** * General handler for incoming input events. Manipulates the frame metrics * based on what type of input it is. For example, a PinchGestureEvent will @@ -208,6 +202,12 @@ public: // These methods can be called from any thread. // + /** + * Shut down the controller/UI thread state and prepare to be + * deleted (which may happen from any thread). + */ + void Destroy(); + /** * Sets the DPI of the device for use within panning and zooming logic. It is * a platform responsibility to set this on initialization of this class and @@ -505,8 +505,17 @@ private: nsRefPtr mCompositorParent; TaskThrottler mPaintThrottler; + + /* Access to the following two fields is protected by the mRefPtrMonitor, + since they are accessed on the UI thread but can be cleared on the + compositor thread. */ nsRefPtr mGeckoContentController; nsRefPtr mGestureEventListener; + Monitor mRefPtrMonitor; + + /* Utility functions that return a addrefed pointer to the corresponding fields. */ + already_AddRefed GetGeckoContentController(); + already_AddRefed GetGestureEventListener(); // Both |mFrameMetrics| and |mLastContentPaintMetrics| are protected by the // monitor. Do not read from or modify either of them without locking. From 3a19367421c5e0cd6e19a8fe0a3e0e701cd805d4 Mon Sep 17 00:00:00 2001 From: Kartikaya Gupta Date: Tue, 30 Jul 2013 14:03:40 -0400 Subject: [PATCH 21/36] Bug 866232 - Add support for delaying APZC creation until the layer update. r=BenWa --- gfx/layers/ipc/AsyncPanZoomController.cpp | 6 ++- gfx/layers/ipc/AsyncPanZoomController.h | 21 ++++---- .../gtest/TestAsyncPanZoomController.cpp | 53 +++++++++++++------ 3 files changed, 54 insertions(+), 26 deletions(-) diff --git a/gfx/layers/ipc/AsyncPanZoomController.cpp b/gfx/layers/ipc/AsyncPanZoomController.cpp index 5d8be3918ab..1fdadddde12 100644 --- a/gfx/layers/ipc/AsyncPanZoomController.cpp +++ b/gfx/layers/ipc/AsyncPanZoomController.cpp @@ -1216,8 +1216,12 @@ void AsyncPanZoomController::NotifyLayersUpdated(const FrameMetrics& aViewportFr mX.CancelTouch(); mY.CancelTouch(); - mFrameMetrics = aViewportFrame; + // XXX If this is the very first time we're getting a layers update we need to + // trigger another repaint, or the B2G browser shows stale content. This needs + // to be investigated and fixed. + needContentRepaint |= (mFrameMetrics.IsDefault() && !aViewportFrame.IsDefault()); + mFrameMetrics = aViewportFrame; mState = NOTHING; } else if (!mFrameMetrics.mScrollableRect.IsEqualEdges(aViewportFrame.mScrollableRect)) { mFrameMetrics.mScrollableRect = aViewportFrame.mScrollableRect; diff --git a/gfx/layers/ipc/AsyncPanZoomController.h b/gfx/layers/ipc/AsyncPanZoomController.h index d954420f898..22418530308 100644 --- a/gfx/layers/ipc/AsyncPanZoomController.h +++ b/gfx/layers/ipc/AsyncPanZoomController.h @@ -45,7 +45,7 @@ class ViewTransform; * asynchronously scrolled subframes, we want to have one AsyncPanZoomController * per frame. */ -class AsyncPanZoomController MOZ_FINAL { +class AsyncPanZoomController { NS_INLINE_DECL_THREADSAFE_REFCOUNTING(AsyncPanZoomController) typedef mozilla::MonitorAutoLock MonitorAutoLock; @@ -517,9 +517,20 @@ private: already_AddRefed GetGeckoContentController(); already_AddRefed GetGestureEventListener(); +protected: // Both |mFrameMetrics| and |mLastContentPaintMetrics| are protected by the // monitor. Do not read from or modify either of them without locking. FrameMetrics mFrameMetrics; + + // Protects |mFrameMetrics|, |mLastContentPaintMetrics|, |mState| and + // |mMetaViewportInfo|. Before manipulating |mFrameMetrics| or + // |mLastContentPaintMetrics|, the monitor should be held. When setting + // |mState|, either the SetState() function can be used, or the monitor can be + // held and then |mState| updated. |mMetaViewportInfo| should be updated + // using UpdateMetaViewport(). + Monitor mMonitor; + +private: // These are the metrics at last content paint, the most recent // values we were notified of in NotifyLayersUpdate(). FrameMetrics mLastContentPaintMetrics; @@ -552,14 +563,6 @@ private: float mMinZoom; float mMaxZoom; - // Protects |mFrameMetrics|, |mLastContentPaintMetrics|, |mState| and - // |mMetaViewportInfo|. Before manipulating |mFrameMetrics| or - // |mLastContentPaintMetrics|, the monitor should be held. When setting - // |mState|, either the SetState() function can be used, or the monitor can be - // held and then |mState| updated. |mMetaViewportInfo| should be updated - // using UpdateMetaViewport(). - Monitor mMonitor; - // The last time the compositor has sampled the content transform for this // frame. TimeStamp mLastSampleTime; diff --git a/gfx/tests/gtest/TestAsyncPanZoomController.cpp b/gfx/tests/gtest/TestAsyncPanZoomController.cpp index 9a8ac51bab7..4199ebc7b80 100644 --- a/gfx/tests/gtest/TestAsyncPanZoomController.cpp +++ b/gfx/tests/gtest/TestAsyncPanZoomController.cpp @@ -39,6 +39,18 @@ class TestAPZCContainerLayer : public ContainerLayer { void RepositionChild(Layer* aChild, Layer* aAfter) {} }; +class TestAsyncPanZoomController : public AsyncPanZoomController { +public: + TestAsyncPanZoomController(MockContentController* mcc) + : AsyncPanZoomController(mcc) + {} + + void SetFrameMetrics(const FrameMetrics& metrics) { + MonitorAutoLock lock(mMonitor); + mFrameMetrics = metrics; + } +}; + static FrameMetrics TestFrameMetrics() { FrameMetrics fm; @@ -90,16 +102,16 @@ void ApzcPan(AsyncPanZoomController* apzc, int& aTime, int aTouchStartY, int aTo TEST(AsyncPanZoomController, Constructor) { // RefCounted class can't live in the stack nsRefPtr mcc = new MockContentController(); - nsRefPtr apzc = new AsyncPanZoomController(mcc); - apzc->NotifyLayersUpdated(TestFrameMetrics(), true); + nsRefPtr apzc = new TestAsyncPanZoomController(mcc); + apzc->SetFrameMetrics(TestFrameMetrics()); } TEST(AsyncPanZoomController, SimpleTransform) { TimeStamp testStartTime = TimeStamp::Now(); // RefCounted class can't live in the stack nsRefPtr mcc = new MockContentController(); - nsRefPtr apzc = new AsyncPanZoomController(mcc); - apzc->NotifyLayersUpdated(TestFrameMetrics(), true); + nsRefPtr apzc = new TestAsyncPanZoomController(mcc); + apzc->SetFrameMetrics(TestFrameMetrics()); TestAPZCContainerLayer layer; ScreenPoint pointOut; @@ -131,7 +143,8 @@ TEST(AsyncPanZoomController, ComplexTransform) { // sides. nsRefPtr mcc = new MockContentController(); - nsRefPtr apzc = new AsyncPanZoomController(mcc); + nsRefPtr apzc = new TestAsyncPanZoomController(mcc); + nsRefPtr childApzc = new TestAsyncPanZoomController(mcc); const char* layerTreeSyntax = "c(c)"; // LayerID 0 1 @@ -174,39 +187,41 @@ TEST(AsyncPanZoomController, ComplexTransform) { // the CSS transform on the child layer does not affect the SampleContentTransformForFrame code // initial transform + apzc->SetFrameMetrics(metrics); apzc->NotifyLayersUpdated(metrics, true); apzc->SampleContentTransformForFrame(testStartTime, layers[0]->AsContainerLayer(), &viewTransformOut, pointOut); EXPECT_EQ(ViewTransform(LayerPoint(), LayoutDeviceToScreenScale(2)), viewTransformOut); EXPECT_EQ(ScreenPoint(60, 60), pointOut); - apzc->NotifyLayersUpdated(childMetrics, true); - apzc->SampleContentTransformForFrame(testStartTime, layers[1]->AsContainerLayer(), &viewTransformOut, pointOut); + childApzc->SetFrameMetrics(childMetrics); + childApzc->NotifyLayersUpdated(childMetrics, true); + childApzc->SampleContentTransformForFrame(testStartTime, layers[1]->AsContainerLayer(), &viewTransformOut, pointOut); EXPECT_EQ(ViewTransform(LayerPoint(), LayoutDeviceToScreenScale(2)), viewTransformOut); EXPECT_EQ(ScreenPoint(60, 60), pointOut); // do an async scroll by 5 pixels and check the transform metrics.mScrollOffset += CSSPoint(5, 0); - apzc->NotifyLayersUpdated(metrics, true); + apzc->SetFrameMetrics(metrics); apzc->SampleContentTransformForFrame(testStartTime, layers[0]->AsContainerLayer(), &viewTransformOut, pointOut); EXPECT_EQ(ViewTransform(LayerPoint(-30, 0), LayoutDeviceToScreenScale(2)), viewTransformOut); EXPECT_EQ(ScreenPoint(90, 60), pointOut); childMetrics.mScrollOffset += CSSPoint(5, 0); - apzc->NotifyLayersUpdated(childMetrics, true); - apzc->SampleContentTransformForFrame(testStartTime, layers[1]->AsContainerLayer(), &viewTransformOut, pointOut); + childApzc->SetFrameMetrics(childMetrics); + childApzc->SampleContentTransformForFrame(testStartTime, layers[1]->AsContainerLayer(), &viewTransformOut, pointOut); EXPECT_EQ(ViewTransform(LayerPoint(-30, 0), LayoutDeviceToScreenScale(2)), viewTransformOut); EXPECT_EQ(ScreenPoint(90, 60), pointOut); // do an async zoom of 1.5x and check the transform metrics.mZoom.scale *= 1.5f; - apzc->NotifyLayersUpdated(metrics, true); + apzc->SetFrameMetrics(metrics); apzc->SampleContentTransformForFrame(testStartTime, layers[0]->AsContainerLayer(), &viewTransformOut, pointOut); EXPECT_EQ(ViewTransform(LayerPoint(-30, 0), LayoutDeviceToScreenScale(3)), viewTransformOut); EXPECT_EQ(ScreenPoint(135, 90), pointOut); childMetrics.mZoom.scale *= 1.5f; - apzc->NotifyLayersUpdated(childMetrics, true); - apzc->SampleContentTransformForFrame(testStartTime, layers[0]->AsContainerLayer(), &viewTransformOut, pointOut); + childApzc->SetFrameMetrics(childMetrics); + childApzc->SampleContentTransformForFrame(testStartTime, layers[0]->AsContainerLayer(), &viewTransformOut, pointOut); EXPECT_EQ(ViewTransform(LayerPoint(-30, 0), LayoutDeviceToScreenScale(3)), viewTransformOut); EXPECT_EQ(ScreenPoint(135, 90), pointOut); } @@ -216,7 +231,9 @@ TEST(AsyncPanZoomController, Pan) { AsyncPanZoomController::SetFrameTime(testStartTime); nsRefPtr mcc = new MockContentController(); - nsRefPtr apzc = new AsyncPanZoomController(mcc); + nsRefPtr apzc = new TestAsyncPanZoomController(mcc); + + apzc->SetFrameMetrics(TestFrameMetrics()); apzc->NotifyLayersUpdated(TestFrameMetrics(), true); EXPECT_CALL(*mcc, SendAsyncScrollDOMEvent(_,_)).Times(4); @@ -247,7 +264,9 @@ TEST(AsyncPanZoomController, Fling) { AsyncPanZoomController::SetFrameTime(testStartTime); nsRefPtr mcc = new MockContentController(); - nsRefPtr apzc = new AsyncPanZoomController(mcc); + nsRefPtr apzc = new TestAsyncPanZoomController(mcc); + + apzc->SetFrameMetrics(TestFrameMetrics()); apzc->NotifyLayersUpdated(TestFrameMetrics(), true); EXPECT_CALL(*mcc, SendAsyncScrollDOMEvent(_,_)).Times(2); @@ -275,7 +294,9 @@ TEST(AsyncPanZoomController, OverScrollPanning) { AsyncPanZoomController::SetFrameTime(testStartTime); nsRefPtr mcc = new MockContentController(); - nsRefPtr apzc = new AsyncPanZoomController(mcc); + nsRefPtr apzc = new TestAsyncPanZoomController(mcc); + + apzc->SetFrameMetrics(TestFrameMetrics()); apzc->NotifyLayersUpdated(TestFrameMetrics(), true); EXPECT_CALL(*mcc, SendAsyncScrollDOMEvent(_,_)).Times(3); From 047677d3e36978b31b1cdeb320402a2c05cd21b9 Mon Sep 17 00:00:00 2001 From: Kartikaya Gupta Date: Tue, 30 Jul 2013 14:03:40 -0400 Subject: [PATCH 22/36] Bug 866232 - Add an APZCTreeManager to encapsulate the multiple APZCs corresponding to a given layer tree. r=BenWa, mattwoodrow --- gfx/layers/Compositor.cpp | 8 +- gfx/layers/Compositor.h | 6 + gfx/layers/composite/APZCTreeManager.cpp | 237 ++++++++++++++++++ gfx/layers/composite/APZCTreeManager.h | 231 +++++++++++++++++ .../composite/AsyncCompositionManager.cpp | 9 - gfx/layers/ipc/AsyncPanZoomController.cpp | 4 +- gfx/layers/ipc/AsyncPanZoomController.h | 2 +- gfx/layers/ipc/CompositorParent.cpp | 57 +++-- gfx/layers/ipc/CompositorParent.h | 21 +- gfx/layers/moz.build | 2 + layout/ipc/RenderFrameParent.cpp | 55 ++-- layout/ipc/RenderFrameParent.h | 10 +- widget/android/AndroidJNI.cpp | 23 +- widget/android/nsWindow.cpp | 47 +--- widget/android/nsWindow.h | 5 +- 15 files changed, 590 insertions(+), 127 deletions(-) create mode 100644 gfx/layers/composite/APZCTreeManager.cpp create mode 100644 gfx/layers/composite/APZCTreeManager.h diff --git a/gfx/layers/Compositor.cpp b/gfx/layers/Compositor.cpp index faaad0d34e1..4b67f947ff1 100644 --- a/gfx/layers/Compositor.cpp +++ b/gfx/layers/Compositor.cpp @@ -13,11 +13,17 @@ namespace layers { /* static */ LayersBackend Compositor::sBackend = LAYERS_NONE; /* static */ LayersBackend Compositor::GetBackend() +{ + AssertOnCompositorThread(); + return sBackend; +} + +/* static */ void +Compositor::AssertOnCompositorThread() { MOZ_ASSERT(CompositorParent::CompositorLoop() == MessageLoop::current(), "Can only call this from the compositor thread!"); - return sBackend; } void diff --git a/gfx/layers/Compositor.h b/gfx/layers/Compositor.h index 03fc0979c4c..f7d6bfbf136 100644 --- a/gfx/layers/Compositor.h +++ b/gfx/layers/Compositor.h @@ -398,6 +398,12 @@ public: virtual nsIWidget* GetWidget() const { return nullptr; } virtual const nsIntSize& GetWidgetSize() = 0; + /** + * Debug-build assertion that can be called to ensure code is running on the + * compositor thread. + */ + static void AssertOnCompositorThread(); + /** * We enforce that there can only be one Compositor backend type off the main * thread at the same time. The backend type in use can be checked with this diff --git a/gfx/layers/composite/APZCTreeManager.cpp b/gfx/layers/composite/APZCTreeManager.cpp new file mode 100644 index 00000000000..e34feaa7605 --- /dev/null +++ b/gfx/layers/composite/APZCTreeManager.cpp @@ -0,0 +1,237 @@ +/* -*- Mode: C++; tab-width: 8; 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 "APZCTreeManager.h" +#include "Compositor.h" + +namespace mozilla { +namespace layers { + +APZCTreeManager::APZCTreeManager() + : mTreeLock("APZCTreeLock") +{ + MOZ_ASSERT(NS_IsMainThread()); + AsyncPanZoomController::InitializeGlobalState(); +} + +void +APZCTreeManager::UpdatePanZoomControllerTree(CompositorParent* aCompositor, Layer* aRoot, + uint64_t aLayersId, bool aIsFirstPaint) +{ + Compositor::AssertOnCompositorThread(); + + MonitorAutoLock lock(mTreeLock); + AsyncPanZoomController* controller = nullptr; + if (aRoot && aRoot->AsContainerLayer()) { + ContainerLayer* container = aRoot->AsContainerLayer(); + + // If the layer is scrollable, it needs an APZC. If there is already an APZC on it, use that, + // otherwise create one if we can. We might not be able to create one if we don't have a + // GeckoContentController for it, in which case we just leave it as null. + controller = container->GetAsyncPanZoomController(); + const FrameMetrics& metrics = container->GetFrameMetrics(); + if (metrics.IsScrollable()) { + // Scrollable, create an APZC if it doesn't have one and we can create it + if (!controller) { + const CompositorParent::LayerTreeState* state = CompositorParent::GetIndirectShadowTree(aLayersId); + if (state && state->mController.get()) { + controller = new AsyncPanZoomController(state->mController, + AsyncPanZoomController::USE_GESTURE_DETECTOR); + controller->SetCompositorParent(aCompositor); + } + } + } else if (controller) { + // Not scrollable, so clear the APZC instance + controller = nullptr; + } + container->SetAsyncPanZoomController(controller); + + if (controller) { + controller->NotifyLayersUpdated(container->GetFrameMetrics(), aIsFirstPaint); + } + } + + if (controller) { + mApzcs[aLayersId] = controller; + } else { + mApzcs.erase(aLayersId); + } +} + +nsEventStatus +APZCTreeManager::ReceiveInputEvent(const InputData& aEvent) +{ + nsRefPtr apzc; + switch (aEvent.mInputType) { + case MULTITOUCH_INPUT: { + const MultiTouchInput& multiTouchInput = aEvent.AsMultiTouchInput(); + apzc = GetTargetAPZC(ScreenPoint(multiTouchInput.mTouches[0].mScreenPoint)); + break; + } case PINCHGESTURE_INPUT: { + const PinchGestureInput& pinchInput = aEvent.AsPinchGestureInput(); + apzc = GetTargetAPZC(pinchInput.mFocusPoint); + break; + } case TAPGESTURE_INPUT: { + const TapGestureInput& tapInput = aEvent.AsTapGestureInput(); + apzc = GetTargetAPZC(ScreenPoint(tapInput.mPoint)); + break; + } default: { + // leave apzc as nullptr + break; + } + } + if (apzc) { + return apzc->ReceiveInputEvent(aEvent); + } + return nsEventStatus_eIgnore; +} + +nsEventStatus +APZCTreeManager::ReceiveInputEvent(const nsInputEvent& aEvent, + nsInputEvent* aOutEvent) +{ + MOZ_ASSERT(NS_IsMainThread()); + + nsRefPtr apzc; + switch (aEvent.eventStructType) { + case NS_TOUCH_EVENT: { + const nsTouchEvent& touchEvent = static_cast(aEvent); + if (touchEvent.touches.Length() > 0) { + nsIntPoint point = touchEvent.touches[0]->mRefPoint; + apzc = GetTargetAPZC(ScreenPoint::FromUnknownPoint(gfx::Point(point.x, point.y))); + } + break; + } case NS_MOUSE_EVENT: { + const nsMouseEvent& mouseEvent = static_cast(aEvent); + apzc = GetTargetAPZC(ScreenPoint::FromUnknownPoint(gfx::Point(mouseEvent.refPoint.x, + mouseEvent.refPoint.y))); + break; + } default: { + // leave apzc as nullptr + break; + } + } + if (apzc) { + return apzc->ReceiveInputEvent(aEvent, aOutEvent); + } + return nsEventStatus_eIgnore; +} + +void +APZCTreeManager::UpdateCompositionBounds(const ScrollableLayerGuid& aGuid, + const ScreenIntRect& aCompositionBounds) +{ + nsRefPtr apzc = GetTargetAPZC(aGuid); + if (apzc) { + apzc->UpdateCompositionBounds(aCompositionBounds); + } +} + +void +APZCTreeManager::CancelDefaultPanZoom(const ScrollableLayerGuid& aGuid) +{ + nsRefPtr apzc = GetTargetAPZC(aGuid); + if (apzc) { + apzc->CancelDefaultPanZoom(); + } +} + +void +APZCTreeManager::DetectScrollableSubframe(const ScrollableLayerGuid& aGuid) +{ + nsRefPtr apzc = GetTargetAPZC(aGuid); + if (apzc) { + apzc->DetectScrollableSubframe(); + } +} + +void +APZCTreeManager::ZoomToRect(const ScrollableLayerGuid& aGuid, + const CSSRect& aRect) +{ + nsRefPtr apzc = GetTargetAPZC(aGuid); + if (apzc) { + apzc->ZoomToRect(aRect); + } +} + +void +APZCTreeManager::ContentReceivedTouch(const ScrollableLayerGuid& aGuid, + bool aPreventDefault) +{ + nsRefPtr apzc = GetTargetAPZC(aGuid); + if (apzc) { + apzc->ContentReceivedTouch(aPreventDefault); + } +} + +void +APZCTreeManager::UpdateZoomConstraints(const ScrollableLayerGuid& aGuid, + bool aAllowZoom, + float aMinScale, + float aMaxScale) +{ + nsRefPtr apzc = GetTargetAPZC(aGuid); + if (apzc) { + apzc->UpdateZoomConstraints(aAllowZoom, aMinScale, aMaxScale); + } +} + +void +APZCTreeManager::UpdateScrollOffset(const ScrollableLayerGuid& aGuid, + const CSSPoint& aScrollOffset) +{ + nsRefPtr apzc = GetTargetAPZC(aGuid); + if (apzc) { + apzc->UpdateScrollOffset(aScrollOffset); + } +} + +void +APZCTreeManager::CancelAnimation(const ScrollableLayerGuid &aGuid) +{ + nsRefPtr apzc = GetTargetAPZC(aGuid); + if (apzc) { + apzc->CancelAnimation(); + } +} + +void +APZCTreeManager::ClearTree() +{ + MonitorAutoLock lock(mTreeLock); + + std::map< uint64_t, nsRefPtr >::iterator it = mApzcs.begin(); + while (it != mApzcs.end()) { + nsRefPtr apzc = it->second; + apzc->Destroy(); + it++; + } + mApzcs.clear(); +} + +already_AddRefed +APZCTreeManager::GetTargetAPZC(const ScrollableLayerGuid& aGuid) +{ + MonitorAutoLock lock(mTreeLock); + std::map< uint64_t, nsRefPtr >::iterator it = mApzcs.find(aGuid.mLayersId); + if (it == mApzcs.end()) { + return nullptr; + } + nsRefPtr target = it->second; + return target.forget(); +} + +already_AddRefed +APZCTreeManager::GetTargetAPZC(const ScreenPoint& aPoint) +{ + MonitorAutoLock lock(mTreeLock); + // TODO: Do a hit test on the tree of + // APZC instances and return the right one. + return nullptr; +} + +} +} diff --git a/gfx/layers/composite/APZCTreeManager.h b/gfx/layers/composite/APZCTreeManager.h new file mode 100644 index 00000000000..99ac5ec0b5b --- /dev/null +++ b/gfx/layers/composite/APZCTreeManager.h @@ -0,0 +1,231 @@ +/* -*- Mode: C++; tab-width: 8; 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_layers_APZCTreeManager_h +#define mozilla_layers_APZCTreeManager_h + +#include "mozilla/layers/AsyncPanZoomController.h" +#include "Layers.h" +#include "CompositorParent.h" +#include + +namespace mozilla { +namespace layers { + +/** + * This class allows us to uniquely identify a scrollable layer. The + * mLayersId identifies the layer tree (corresponding to a child process + * and/or tab) that the scrollable layer belongs to. The mPresShellId + * is a temporal identifier (corresponding to the document loaded that + * contains the scrollable layer, which may change over time). The + * mScrollId corresponds to the actual frame that is scrollable. + */ +struct ScrollableLayerGuid { + uint64_t mLayersId; + uint32_t mPresShellId; + FrameMetrics::ViewID mScrollId; + + ScrollableLayerGuid(uint64_t aLayersId, uint32_t aPresShellId, + FrameMetrics::ViewID aScrollId) + : mLayersId(aLayersId) + , mPresShellId(aPresShellId) + , mScrollId(aScrollId) + { + MOZ_COUNT_CTOR(ScrollableLayerGuid); + } + + ScrollableLayerGuid(uint64_t aLayersId, const FrameMetrics& aMetrics) + : mLayersId(aLayersId) + , mPresShellId(aMetrics.mPresShellId) + , mScrollId(aMetrics.mScrollId) + { + MOZ_COUNT_CTOR(ScrollableLayerGuid); + } + + ScrollableLayerGuid(uint64_t aLayersId) + : mLayersId(aLayersId) + , mPresShellId(0) + , mScrollId(FrameMetrics::ROOT_SCROLL_ID) + { + MOZ_COUNT_CTOR(ScrollableLayerGuid); + // TODO: get rid of this constructor once all callers know their + // presShellId and scrollId + } + + ~ScrollableLayerGuid() + { + MOZ_COUNT_DTOR(ScrollableLayerGuid); + } + + bool operator==(const ScrollableLayerGuid& other) const + { + return mLayersId == other.mLayersId + && mPresShellId == other.mPresShellId + && mScrollId == other.mScrollId; + } + + bool operator!=(const ScrollableLayerGuid& other) const + { + return !(*this == other); + } +}; + +/** + * This class manages the tree of AsyncPanZoomController instances. There is one + * instance of this class owned by each CompositorParent, and it contains as + * many AsyncPanZoomController instances as there are scrollable container layers. + * This class generally lives on the compositor thread, although some functions + * may be called from other threads as noted; thread safety is ensured internally. + * + * The bulk of the work of this class happens as part of the UpdatePanZoomControllerTree + * function, which is when a layer tree update is received by the compositor. + * This function walks through the layer tree and creates a tree of APZC instances + * to match the scrollable container layers. APZC instances may be preserved across + * calls to this function if the corresponding layers are still present in the layer + * tree. + * + * The other functions on this class are used by various pieces of client code to + * notify the APZC instances of events relevant to them. This includes, for example, + * user input events that drive panning and zooming, changes to the scroll viewport + * area, and changes to pan/zoom constraints. + * + * Note that the ClearTree function MUST be called when this class is no longer needed; + * see the method documentation for details. + */ +class APZCTreeManager MOZ_FINAL { + NS_INLINE_DECL_THREADSAFE_REFCOUNTING(APZCTreeManager) + +public: + APZCTreeManager(); + + /** + * Rebuild the APZC tree based on the layer update that just came up. Preserve + * APZC instances where possible, but retire those whose layers are no longer + * in the layer tree. + * + * This must be called on the compositor thread as it walks the layer tree. + */ + void UpdatePanZoomControllerTree(CompositorParent* aCompositor, Layer* aRoot, + uint64_t aLayersId, bool aIsFirstPaint); + + /** + * General handler for incoming input events. Manipulates the frame metrics + * based on what type of input it is. For example, a PinchGestureEvent will + * cause scaling. This should only be called externally to this class. + * HandleInputEvent() should be used internally. + */ + nsEventStatus ReceiveInputEvent(const InputData& aEvent); + + /** + * Special handler for nsInputEvents. Also sets |aOutEvent| (which is assumed + * to be an already-existing instance of an nsInputEvent which may be an + * nsTouchEvent) to have its touch points in DOM space. This is so that the + * touches can be passed through the DOM and content can handle them. + * + * NOTE: Be careful of invoking the nsInputEvent variant. This can only be + * called on the main thread. See widget/InputData.h for more information on + * why we have InputData and nsInputEvent separated. + */ + nsEventStatus ReceiveInputEvent(const nsInputEvent& aEvent, + nsInputEvent* aOutEvent); + + /** + * Updates the composition bounds, i.e. the dimensions of the final size of + * the frame this is tied to during composition onto, in device pixels. In + * general, this will just be: + * { x = 0, y = 0, width = surface.width, height = surface.height }, however + * there is no hard requirement for this. + */ + void UpdateCompositionBounds(const ScrollableLayerGuid& aGuid, + const ScreenIntRect& aCompositionBounds); + + /** + * We are scrolling a subframe, so disable our machinery until we hit + * a touch end or a new touch start. This prevents us from accidentally + * panning both the subframe and the parent frame. + * + * XXX/bug 775452: We should eventually be supporting async scrollable + * subframes. + */ + void CancelDefaultPanZoom(const ScrollableLayerGuid& aGuid); + + /** + * We have found a scrollable subframe, so we need to delay the scrolling + * gesture executed and let subframe do the scrolling first. + */ + void DetectScrollableSubframe(const ScrollableLayerGuid& aGuid); + + /** + * Kicks an animation to zoom to a rect. This may be either a zoom out or zoom + * in. The actual animation is done on the compositor thread after being set + * up. |aRect| must be given in CSS pixels, relative to the document. + */ + void ZoomToRect(const ScrollableLayerGuid& aGuid, + const CSSRect& aRect); + + /** + * If we have touch listeners, this should always be called when we know + * definitively whether or not content has preventDefaulted any touch events + * that have come in. If |aPreventDefault| is true, any touch events in the + * queue will be discarded. + */ + void ContentReceivedTouch(const ScrollableLayerGuid& aGuid, + bool aPreventDefault); + + /** + * Updates any zoom constraints contained in the tag. + * We try to obey everything it asks us elsewhere, but here we only handle + * minimum-scale, maximum-scale, and user-scalable. + */ + void UpdateZoomConstraints(const ScrollableLayerGuid& aGuid, + bool aAllowZoom, + float aMinScale, + float aMaxScale); + + /** + * Update mFrameMetrics.mScrollOffset to the given offset. + * This is necessary in cases where a scroll is not caused by user + * input (for example, a content scrollTo()). + */ + void UpdateScrollOffset(const ScrollableLayerGuid& aGuid, + const CSSPoint& aScrollOffset); + + /** + * Cancels any currently running animation. Note that all this does is set the + * state of the AsyncPanZoomController back to NOTHING, but it is the + * animation's responsibility to check this before advancing. + */ + void CancelAnimation(const ScrollableLayerGuid &aGuid); + + /** + * Calls Destroy() on all APZC instances attached to the tree, and resets the + * tree back to empty. This function may be called multiple times during the + * lifetime of this APZCTreeManager, but it must always be called at least once + * when this APZCTreeManager is no longer needed. Failing to call this function + * may prevent objects from being freed properly. + */ + void ClearTree(); + +private: + /* Some helper functions to find an APZC given some identifying input. These functions + lock the tree of APZCs while they find the right one, and then return an addref'd + pointer to it. This allows caller code to just use the target APZC without worrying + about it going away. + */ + already_AddRefed GetTargetAPZC(const ScrollableLayerGuid& aGuid); + already_AddRefed GetTargetAPZC(const ScreenPoint& aPoint); + +private: + /* Whenever walking or mutating the map of APZC instances, mTreeLock must be held. + * This lock does not need to be held while manipulating a single APZC instance in + * isolation (that is, if its tree pointers are not being accessed or mutated). */ + mozilla::Monitor mTreeLock; + std::map< uint64_t, nsRefPtr > mApzcs; +}; + +} +} + +#endif // mozilla_layers_PanZoomController_h diff --git a/gfx/layers/composite/AsyncCompositionManager.cpp b/gfx/layers/composite/AsyncCompositionManager.cpp index 05ad9b18efc..4426bbfaabf 100644 --- a/gfx/layers/composite/AsyncCompositionManager.cpp +++ b/gfx/layers/composite/AsyncCompositionManager.cpp @@ -51,7 +51,6 @@ WalkTheTree(Layer* aLayer, if (RefLayer* ref = aLayer->AsRefLayer()) { if (const CompositorParent::LayerTreeState* state = CompositorParent::GetIndirectShadowTree(ref->GetReferentId())) { if (Layer* referent = state->mRoot) { - ContainerLayer *referentAsContainer = referent->AsContainerLayer(); if (!ref->GetVisibleRegion().IsEmpty()) { ScreenOrientation chromeOrientation = aTargetConfig.orientation(); ScreenOrientation contentOrientation = state->mTargetConfig.orientation(); @@ -63,16 +62,8 @@ WalkTheTree(Layer* aLayer, if (OP == Resolve) { ref->ConnectReferentLayer(referent); - if (referentAsContainer) { - if (AsyncPanZoomController* apzc = state->mController) { - referentAsContainer->SetAsyncPanZoomController(apzc); - } - } } else { ref->DetachReferentLayer(referent); - if (referentAsContainer) { - referentAsContainer->SetAsyncPanZoomController(nullptr); - } } } } diff --git a/gfx/layers/ipc/AsyncPanZoomController.cpp b/gfx/layers/ipc/AsyncPanZoomController.cpp index 1fdadddde12..8e2cf1f511d 100644 --- a/gfx/layers/ipc/AsyncPanZoomController.cpp +++ b/gfx/layers/ipc/AsyncPanZoomController.cpp @@ -187,8 +187,6 @@ AsyncPanZoomController::AsyncPanZoomController(GeckoContentController* aGeckoCon { MOZ_COUNT_CTOR(AsyncPanZoomController); - InitializeGlobalState(); - if (aGestures == USE_GESTURE_DETECTOR) { mGestureEventListener = new GestureEventListener(this); } @@ -1513,7 +1511,7 @@ void AsyncPanZoomController::GetAPZCAtPoint(const ContainerLayer& aLayerTree, GetAPZCAtPointOnSubtree(aLayerTree, point, aApzcOut, aRelativePointOut); } -void AsyncPanZoomController::UpdateScrollOffset(CSSPoint aScrollOffset) +void AsyncPanZoomController::UpdateScrollOffset(const CSSPoint& aScrollOffset) { MonitorAutoLock monitor(mMonitor); mFrameMetrics.mScrollOffset = aScrollOffset; diff --git a/gfx/layers/ipc/AsyncPanZoomController.h b/gfx/layers/ipc/AsyncPanZoomController.h index 22418530308..d718908ba7b 100644 --- a/gfx/layers/ipc/AsyncPanZoomController.h +++ b/gfx/layers/ipc/AsyncPanZoomController.h @@ -268,7 +268,7 @@ public: * This is necessary in cases where a scroll is not caused by user * input (for example, a content scrollTo()). */ - void UpdateScrollOffset(CSSPoint aScrollOffset); + void UpdateScrollOffset(const CSSPoint& aScrollOffset); /** * Cancels any currently running animation. Note that all this does is set the diff --git a/gfx/layers/ipc/CompositorParent.cpp b/gfx/layers/ipc/CompositorParent.cpp index bfd4a0361a8..6bd8f49bf9b 100644 --- a/gfx/layers/ipc/CompositorParent.cpp +++ b/gfx/layers/ipc/CompositorParent.cpp @@ -8,7 +8,6 @@ #include "mozilla/DebugOnly.h" -#include "AsyncPanZoomController.h" #include "AutoOpenSurface.h" #include "CompositorParent.h" #include "mozilla/layers/CompositorOGL.h" @@ -155,6 +154,7 @@ CompositorParent::CompositorParent(nsIWidget* aWidget, CompositorLoop()->PostTask(FROM_HERE, NewRunnableFunction(&AddCompositor, this, &mCompositorID)); + mApzcTreeManager = new APZCTreeManager(); ++sCompositorThreadRefCount; } @@ -174,6 +174,7 @@ CompositorParent::~CompositorParent() { MOZ_COUNT_DTOR(CompositorParent); + mApzcTreeManager->ClearTree(); ReleaseCompositorThread(); } @@ -404,8 +405,13 @@ CompositorParent::ScheduleTask(CancelableTask* task, int time) } void -CompositorParent::NotifyShadowTreeTransaction() +CompositorParent::NotifyShadowTreeTransaction(uint64_t aId, bool aIsFirstPaint) { + if (mApzcTreeManager) { + AutoResolveRefLayers resolve(mCompositionManager); + mApzcTreeManager->UpdatePanZoomControllerTree(this, GetIndirectShadowTree(aId)->mRoot, aId, aIsFirstPaint); + } + if (mLayerManager) { LayerManagerComposite* managerComposite = mLayerManager->AsLayerManagerComposite(); if (managerComposite) { @@ -559,6 +565,17 @@ CompositorParent::ShadowLayersUpdated(LayerTransactionParent* aLayerTree, mCompositionManager->Updated(isFirstPaint, aTargetConfig); Layer* root = aLayerTree->GetRoot(); mLayerManager->SetRoot(root); + +#ifdef MOZ_WIDGET_ANDROID + // Temporary hack for Fennec. This will be removed once UpdatePanZoomControllerTree actually + // does a full tree walk. + if (mApzcTreeManager) { + AutoResolveRefLayers resolve(mCompositionManager); + Layer* pzcRoot = mLayerManager->GetPrimaryScrollableLayer(); + mApzcTreeManager->UpdatePanZoomControllerTree(this, pzcRoot, ROOT_LAYER_TREE_ID, isFirstPaint); + } +#endif + if (root) { SetShadowProperties(root); if (mIsTesting) { @@ -727,20 +744,16 @@ CompositorParent::DeallocateLayerTreeId(uint64_t aId) static void UpdateControllerForLayersId(uint64_t aLayersId, - AsyncPanZoomController* aController) + GeckoContentController* aController) { - // Adopt ref given to us by SetPanZoomControllerForLayerTree() + // Adopt ref given to us by SetControllerForLayerTree() sIndirectLayerTrees[aLayersId].mController = - already_AddRefed(aController); - - // Notify the AsyncPanZoomController about the current compositor so that it - // can request composites off the compositor thread. - aController->SetCompositorParent(sIndirectLayerTrees[aLayersId].mParent); + already_AddRefed(aController); } /*static*/ void -CompositorParent::SetPanZoomControllerForLayerTree(uint64_t aLayersId, - AsyncPanZoomController* aController) +CompositorParent::SetControllerForLayerTree(uint64_t aLayersId, + GeckoContentController* aController) { // This ref is adopted by UpdateControllerForLayersId(). aController->AddRef(); @@ -750,6 +763,16 @@ CompositorParent::SetPanZoomControllerForLayerTree(uint64_t aLayersId, aController)); } +/*static*/ APZCTreeManager* +CompositorParent::GetAPZCTreeManager(uint64_t aLayersId) +{ + const CompositorParent::LayerTreeState* state = CompositorParent::GetIndirectShadowTree(aLayersId); + if (state && state->mParent) { + return state->mParent->mApzcTreeManager; + } + return nullptr; +} + /** * This class handles layer updates pushed directly from child * processes to the compositor thread. It's associated with a @@ -834,16 +857,10 @@ CompositorParent::Create(Transport* aTransport, ProcessId aOtherProcess) } static void -UpdateIndirectTree(uint64_t aId, Layer* aRoot, const TargetConfig& aTargetConfig, bool isFirstPaint) +UpdateIndirectTree(uint64_t aId, Layer* aRoot, const TargetConfig& aTargetConfig) { sIndirectLayerTrees[aId].mRoot = aRoot; sIndirectLayerTrees[aId].mTargetConfig = aTargetConfig; - ContainerLayer* rootContainer = aRoot->AsContainerLayer(); - if (rootContainer) { - if (AsyncPanZoomController* apzc = sIndirectLayerTrees[aId].mController) { - apzc->NotifyLayersUpdated(rootContainer->GetFrameMetrics(), isFirstPaint); - } - } } /* static */ const CompositorParent::LayerTreeState* @@ -915,9 +932,9 @@ CrossProcessCompositorParent::ShadowLayersUpdated( if (shadowRoot) { SetShadowProperties(shadowRoot); } - UpdateIndirectTree(id, shadowRoot, aTargetConfig, isFirstPaint); + UpdateIndirectTree(id, shadowRoot, aTargetConfig); - sIndirectLayerTrees[id].mParent->NotifyShadowTreeTransaction(); + sIndirectLayerTrees[id].mParent->NotifyShadowTreeTransaction(id, isFirstPaint); } void diff --git a/gfx/layers/ipc/CompositorParent.h b/gfx/layers/ipc/CompositorParent.h index 70ba9362428..4959f24dc5f 100644 --- a/gfx/layers/ipc/CompositorParent.h +++ b/gfx/layers/ipc/CompositorParent.h @@ -17,6 +17,7 @@ #include "mozilla/layers/PCompositorParent.h" #include "mozilla/layers/PLayerTransactionParent.h" +#include "mozilla/layers/APZCTreeManager.h" #include "base/thread.h" #include "mozilla/Monitor.h" #include "mozilla/TimeStamp.h" @@ -31,7 +32,7 @@ class Thread; namespace mozilla { namespace layers { -class AsyncPanZoomController; +class APZCTreeManager; class Layer; class LayerManagerComposite; class AsyncCompositionManager; @@ -89,7 +90,7 @@ public: bool ScheduleResumeOnCompositorThread(int width, int height); virtual void ScheduleComposition(); - void NotifyShadowTreeTransaction(); + void NotifyShadowTreeTransaction(uint64_t aId, bool aIsFirstPaint); /** * Returns a pointer to the compositor corresponding to the given ID. @@ -133,13 +134,19 @@ public: static void DeallocateLayerTreeId(uint64_t aId); /** - * Set aController as the pan/zoom controller for the tree referred + * Set aController as the pan/zoom callback for the subtree referred * to by aLayersId. * * Must run on content main thread. */ - static void SetPanZoomControllerForLayerTree(uint64_t aLayersId, - AsyncPanZoomController* aController); + static void SetControllerForLayerTree(uint64_t aLayersId, + GeckoContentController* aController); + + /** + * This returns a reference to the APZCTreeManager to which + * pan/zoom-related events can be sent. + */ + static APZCTreeManager* GetAPZCTreeManager(uint64_t aLayersId); /** * A new child process has been configured to push transactions @@ -159,7 +166,7 @@ public: struct LayerTreeState { nsRefPtr mRoot; - nsRefPtr mController; + nsRefPtr mController; CompositorParent *mParent; TargetConfig mTargetConfig; }; @@ -273,6 +280,8 @@ private: bool mOverrideComposeReadiness; CancelableTask* mForceCompositionTask; + nsRefPtr mApzcTreeManager; + DISALLOW_EVIL_CONSTRUCTORS(CompositorParent); }; diff --git a/gfx/layers/moz.build b/gfx/layers/moz.build index 09d6a214d26..6fb002493f8 100644 --- a/gfx/layers/moz.build +++ b/gfx/layers/moz.build @@ -105,6 +105,7 @@ EXPORTS.mozilla.layers += [ 'client/ImageClient.h', 'client/TextureClient.h', 'client/TiledContentClient.h', + 'composite/APZCTreeManager.h', 'composite/AsyncCompositionManager.h', 'composite/CanvasLayerComposite.h', 'composite/ColorLayerComposite.h', @@ -170,6 +171,7 @@ if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'gonk': ] CPP_SOURCES += [ + 'APZCTreeManager.cpp', 'AsyncCompositionManager.cpp', 'AsyncPanZoomController.cpp', 'Axis.cpp', diff --git a/layout/ipc/RenderFrameParent.cpp b/layout/ipc/RenderFrameParent.cpp index dd1183fb4a8..96ed70df203 100644 --- a/layout/ipc/RenderFrameParent.cpp +++ b/layout/ipc/RenderFrameParent.cpp @@ -15,7 +15,7 @@ #endif //MOZ_ENABLE_D3D9_LAYER #include "mozilla/BrowserElementParent.h" #include "mozilla/dom/TabParent.h" -#include "mozilla/layers/AsyncPanZoomController.h" +#include "mozilla/layers/APZCTreeManager.h" #include "mozilla/layers/CompositorParent.h" #include "mozilla/layers/LayerTransactionParent.h" #include "nsContentUtils.h" @@ -620,14 +620,24 @@ RenderFrameParent::RenderFrameParent(nsFrameLoader* aFrameLoader, } if (aScrollingBehavior == ASYNC_PAN_ZOOM) { mContentController = new RemoteContentController(this); - mPanZoomController = new AsyncPanZoomController( - mContentController, AsyncPanZoomController::USE_GESTURE_DETECTOR); - CompositorParent::SetPanZoomControllerForLayerTree(mLayersId, - mPanZoomController); + CompositorParent::SetControllerForLayerTree(mLayersId, mContentController); } } } +APZCTreeManager* +RenderFrameParent::GetApzcTreeManager() +{ + // We can't get a ref to the APZCTreeManager until after the child is + // created and the static getter knows which CompositorParent is + // instantiated with this layers ID. That's why try to fetch it when + // we first need it and cache the result. + if (!mApzcTreeManager) { + mApzcTreeManager = CompositorParent::GetAPZCTreeManager(mLayersId); + } + return mApzcTreeManager.get(); +} + RenderFrameParent::~RenderFrameParent() {} @@ -787,17 +797,17 @@ void RenderFrameParent::NotifyInputEvent(const nsInputEvent& aEvent, nsInputEvent* aOutEvent) { - if (mPanZoomController) { - mPanZoomController->ReceiveInputEvent(aEvent, aOutEvent); + if (GetApzcTreeManager()) { + GetApzcTreeManager()->ReceiveInputEvent(aEvent, aOutEvent); } } void RenderFrameParent::NotifyDimensionsChanged(ScreenIntSize size) { - if (mPanZoomController) { - mPanZoomController->UpdateCompositionBounds( - ScreenIntRect(ScreenIntPoint(), size)); + if (GetApzcTreeManager()) { + GetApzcTreeManager()->UpdateCompositionBounds(ScrollableLayerGuid(mLayersId), + ScreenIntRect(ScreenIntPoint(), size)); } } @@ -810,7 +820,7 @@ RenderFrameParent::ActorDestroy(ActorDestroyReason why) // Stop our content controller from requesting repaints of our // content. mContentController->ClearRenderFrame(); - mPanZoomController->Destroy(); + // TODO: notify the compositor? } } @@ -836,8 +846,8 @@ RenderFrameParent::RecvNotifyCompositorTransaction() bool RenderFrameParent::RecvCancelDefaultPanZoom() { - if (mPanZoomController) { - mPanZoomController->CancelDefaultPanZoom(); + if (GetApzcTreeManager()) { + GetApzcTreeManager()->CancelDefaultPanZoom(ScrollableLayerGuid(mLayersId)); } return true; } @@ -845,8 +855,8 @@ RenderFrameParent::RecvCancelDefaultPanZoom() bool RenderFrameParent::RecvDetectScrollableSubframe() { - if (mPanZoomController) { - mPanZoomController->DetectScrollableSubframe(); + if (GetApzcTreeManager()) { + GetApzcTreeManager()->DetectScrollableSubframe(ScrollableLayerGuid(mLayersId)); } return true; } @@ -972,24 +982,27 @@ RenderFrameParent::BuildDisplayList(nsDisplayListBuilder* aBuilder, void RenderFrameParent::ZoomToRect(const CSSRect& aRect) { - if (mPanZoomController) { - mPanZoomController->ZoomToRect(aRect); + if (GetApzcTreeManager()) { + GetApzcTreeManager()->ZoomToRect(ScrollableLayerGuid(mLayersId), + aRect); } } void RenderFrameParent::ContentReceivedTouch(bool aPreventDefault) { - if (mPanZoomController) { - mPanZoomController->ContentReceivedTouch(aPreventDefault); + if (GetApzcTreeManager()) { + GetApzcTreeManager()->ContentReceivedTouch(ScrollableLayerGuid(mLayersId), + aPreventDefault); } } void RenderFrameParent::UpdateZoomConstraints(bool aAllowZoom, float aMinZoom, float aMaxZoom) { - if (mPanZoomController) { - mPanZoomController->UpdateZoomConstraints(aAllowZoom, aMinZoom, aMaxZoom); + if (GetApzcTreeManager()) { + GetApzcTreeManager()->UpdateZoomConstraints(ScrollableLayerGuid(mLayersId), + aAllowZoom, aMinZoom, aMaxZoom); } } diff --git a/layout/ipc/RenderFrameParent.h b/layout/ipc/RenderFrameParent.h index 161bec159b5..04e7b88feec 100644 --- a/layout/ipc/RenderFrameParent.h +++ b/layout/ipc/RenderFrameParent.h @@ -25,7 +25,7 @@ namespace mozilla { class InputEvent; namespace layers { -class AsyncPanZoomController; +class APZCTreeManager; class GestureEventListener; class TargetConfig; class LayerTransactionParent; @@ -132,11 +132,13 @@ private: nsRefPtr mFrameLoader; nsRefPtr mContainer; // When our scrolling behavior is ASYNC_PAN_ZOOM, we have a nonnull - // AsyncPanZoomController. It's associated with the shadow layer - // tree on the compositor thread. - nsRefPtr mPanZoomController; + // APZCTreeManager. It's used to manipulate the shadow layer tree + // on the compositor thread. + nsRefPtr mApzcTreeManager; nsRefPtr mContentController; + layers::APZCTreeManager* GetApzcTreeManager(); + // This contains the views for all the scrollable frames currently in the // painted region of our remote content. ViewMap mContentViews; diff --git a/widget/android/AndroidJNI.cpp b/widget/android/AndroidJNI.cpp index 30756098406..737f441896b 100644 --- a/widget/android/AndroidJNI.cpp +++ b/widget/android/AndroidJNI.cpp @@ -35,7 +35,7 @@ #include "mozilla/dom/mobilemessage/Types.h" #include "mozilla/dom/mobilemessage/PSms.h" #include "mozilla/dom/mobilemessage/SmsParent.h" -#include "mozilla/layers/AsyncPanZoomController.h" +#include "mozilla/layers/APZCTreeManager.h" #include "nsIMobileMessageDatabaseService.h" #include "nsPluginInstanceOwner.h" #include "nsSurfaceTexture.h" @@ -847,10 +847,10 @@ Java_org_mozilla_gecko_GeckoJavaSampler_getProfilerTime(JNIEnv *jenv, jclass jc) NS_EXPORT void JNICALL Java_org_mozilla_gecko_gfx_NativePanZoomController_abortAnimation(JNIEnv* env, jobject instance) { - AsyncPanZoomController* controller = nsWindow::GetPanZoomController(); - if (controller) { - controller->CancelAnimation(); - } + APZCTreeManager *controller = CompositorParent::GetAPZCTreeManager(CompositorParent::ROOT_LAYER_TREE_ID); + if (controller) { + controller->CancelAnimation(ScrollableLayerGuid(CompositorParent::ROOT_LAYER_TREE_ID)); + } } NS_EXPORT void JNICALL @@ -865,13 +865,13 @@ Java_org_mozilla_gecko_gfx_NativePanZoomController_init(JNIEnv* env, jobject ins MOZ_ASSERT(false, "Registering a new NPZC when we already have one"); env->DeleteGlobalRef(oldRef); } - nsWindow::SetPanZoomController(new AsyncPanZoomController(AndroidBridge::Bridge(), AsyncPanZoomController::USE_GESTURE_DETECTOR)); + CompositorParent::SetControllerForLayerTree(CompositorParent::ROOT_LAYER_TREE_ID, AndroidBridge::Bridge()); } NS_EXPORT void JNICALL Java_org_mozilla_gecko_gfx_NativePanZoomController_handleTouchEvent(JNIEnv* env, jobject instance, jobject event) { - AsyncPanZoomController *controller = nsWindow::GetPanZoomController(); + APZCTreeManager *controller = CompositorParent::GetAPZCTreeManager(CompositorParent::ROOT_LAYER_TREE_ID); if (controller) { AndroidGeckoEvent* wrapper = AndroidGeckoEvent::MakeFromJavaObject(env, event); const MultiTouchInput& input = wrapper->MakeMultiTouchInput(nsWindow::TopWindow()); @@ -905,7 +905,6 @@ Java_org_mozilla_gecko_gfx_NativePanZoomController_destroy(JNIEnv* env, jobject return; } - nsWindow::SetPanZoomController(nullptr); jobject oldRef = AndroidBridge::Bridge()->SetNativePanZoomController(NULL); if (!oldRef) { MOZ_ASSERT(false, "Clearing a non-existent NPZC"); @@ -917,9 +916,9 @@ Java_org_mozilla_gecko_gfx_NativePanZoomController_destroy(JNIEnv* env, jobject NS_EXPORT void JNICALL Java_org_mozilla_gecko_gfx_NativePanZoomController_notifyDefaultActionPrevented(JNIEnv* env, jobject instance, jboolean prevented) { - AsyncPanZoomController *controller = nsWindow::GetPanZoomController(); + APZCTreeManager *controller = CompositorParent::GetAPZCTreeManager(CompositorParent::ROOT_LAYER_TREE_ID); if (controller) { - controller->ContentReceivedTouch(prevented); + controller->ContentReceivedTouch(ScrollableLayerGuid(CompositorParent::ROOT_LAYER_TREE_ID), prevented); } } @@ -946,9 +945,9 @@ Java_org_mozilla_gecko_gfx_NativePanZoomController_getOverScrollMode(JNIEnv* env NS_EXPORT void JNICALL Java_org_mozilla_gecko_gfx_NativePanZoomController_updateScrollOffset(JNIEnv* env, jobject instance, jfloat cssX, jfloat cssY) { - AsyncPanZoomController* controller = nsWindow::GetPanZoomController(); + APZCTreeManager *controller = CompositorParent::GetAPZCTreeManager(CompositorParent::ROOT_LAYER_TREE_ID); if (controller) { - controller->UpdateScrollOffset(CSSPoint(cssX, cssY)); + controller->UpdateScrollOffset(ScrollableLayerGuid(CompositorParent::ROOT_LAYER_TREE_ID), CSSPoint(cssX, cssY)); } } diff --git a/widget/android/nsWindow.cpp b/widget/android/nsWindow.cpp index e6c4d7a4c38..4b97f75d49a 100644 --- a/widget/android/nsWindow.cpp +++ b/widget/android/nsWindow.cpp @@ -2421,7 +2421,6 @@ nsRefPtr nsWindow::sLayerManager = 0; nsRefPtr nsWindow::sCompositorParent = 0; nsRefPtr nsWindow::sCompositorChild = 0; bool nsWindow::sCompositorPaused = true; -nsRefPtr nsWindow::sApzc = 0; void nsWindow::SetCompositor(mozilla::layers::LayerManager* aLayerManager, @@ -2496,52 +2495,8 @@ nsWindow::NeedsPaint() return nsIWidget::NeedsPaint(); } -class AndroidCompositorParent : public CompositorParent { -public: - AndroidCompositorParent(nsIWidget* aWidget, bool aRenderToEGLSurface, - int aSurfaceWidth, int aSurfaceHeight) - : CompositorParent(aWidget, aRenderToEGLSurface, aSurfaceWidth, aSurfaceHeight) - { - if (nsWindow::GetPanZoomController()) { - nsWindow::GetPanZoomController()->SetCompositorParent(this); - } - } - - virtual void ShadowLayersUpdated(LayerTransactionParent* aLayerTree, const TargetConfig& aTargetConfig, - bool isFirstPaint) MOZ_OVERRIDE - { - CompositorParent::ShadowLayersUpdated(aLayerTree, aTargetConfig, isFirstPaint); - Layer* targetLayer = GetLayerManager()->GetPrimaryScrollableLayer(); - AsyncPanZoomController* controller = nsWindow::GetPanZoomController(); - if (targetLayer && targetLayer->AsContainerLayer() && controller) { - targetLayer->AsContainerLayer()->SetAsyncPanZoomController(controller); - controller->NotifyLayersUpdated(targetLayer->AsContainerLayer()->GetFrameMetrics(), isFirstPaint); - } - } -}; - CompositorParent* nsWindow::NewCompositorParent(int aSurfaceWidth, int aSurfaceHeight) { - return new AndroidCompositorParent(this, true, aSurfaceWidth, aSurfaceHeight); + return new CompositorParent(this, true, aSurfaceWidth, aSurfaceHeight); } - -void -nsWindow::SetPanZoomController(AsyncPanZoomController* apzc) -{ - if (sApzc) { - sApzc->SetCompositorParent(nullptr); - sApzc = nullptr; - } - if (apzc) { - sApzc = apzc; - sApzc->SetCompositorParent(sCompositorParent); - } -} - -AsyncPanZoomController* -nsWindow::GetPanZoomController() -{ - return sApzc; -} - diff --git a/widget/android/nsWindow.h b/widget/android/nsWindow.h index 8979655ad21..cf444372bb7 100644 --- a/widget/android/nsWindow.h +++ b/widget/android/nsWindow.h @@ -23,7 +23,7 @@ namespace mozilla { class CompositorParent; class CompositorChild; class LayerManager; - class AsyncPanZoomController; + class APZCTreeManager; } } @@ -155,8 +155,6 @@ public: static void ScheduleResumeComposition(int width, int height); static void ForceIsFirstPaint(); static float ComputeRenderIntegrity(); - static void SetPanZoomController(mozilla::layers::AsyncPanZoomController* apzc); - static mozilla::layers::AsyncPanZoomController* GetPanZoomController(); virtual bool WidgetPaintsBackground(); @@ -235,7 +233,6 @@ private: static nsRefPtr sCompositorParent; static nsRefPtr sCompositorChild; static bool sCompositorPaused; - static nsRefPtr sApzc; }; #endif /* NSWINDOW_H_ */ From 81eb2a5995e901fd5f30a51366a597e7710b14a2 Mon Sep 17 00:00:00 2001 From: Kartikaya Gupta Date: Tue, 30 Jul 2013 14:03:40 -0400 Subject: [PATCH 23/36] Bug 866232 - Add code to build the APZC tree on layer updates. r=BenWa, mattwoodrow --- gfx/layers/composite/APZCTreeManager.cpp | 170 ++++++++++++++---- gfx/layers/composite/APZCTreeManager.h | 43 ++++- gfx/layers/ipc/AsyncPanZoomController.cpp | 23 ++- gfx/layers/ipc/AsyncPanZoomController.h | 25 ++- gfx/layers/ipc/CompositorParent.cpp | 9 +- .../gtest/TestAsyncPanZoomController.cpp | 18 +- 6 files changed, 226 insertions(+), 62 deletions(-) diff --git a/gfx/layers/composite/APZCTreeManager.cpp b/gfx/layers/composite/APZCTreeManager.cpp index e34feaa7605..a85f204be8e 100644 --- a/gfx/layers/composite/APZCTreeManager.cpp +++ b/gfx/layers/composite/APZCTreeManager.cpp @@ -16,48 +16,126 @@ APZCTreeManager::APZCTreeManager() AsyncPanZoomController::InitializeGlobalState(); } +/* Flatten the tree of APZC instances into the given nsTArray */ +static void +Collect(AsyncPanZoomController* aApzc, nsTArray< nsRefPtr >* aCollection) +{ + if (aApzc) { + aCollection->AppendElement(aApzc); + Collect(aApzc->GetLastChild(), aCollection); + Collect(aApzc->GetPrevSibling(), aCollection); + } +} + void APZCTreeManager::UpdatePanZoomControllerTree(CompositorParent* aCompositor, Layer* aRoot, - uint64_t aLayersId, bool aIsFirstPaint) + bool aIsFirstPaint, uint64_t aFirstPaintLayersId) { Compositor::AssertOnCompositorThread(); MonitorAutoLock lock(mTreeLock); - AsyncPanZoomController* controller = nullptr; - if (aRoot && aRoot->AsContainerLayer()) { - ContainerLayer* container = aRoot->AsContainerLayer(); - // If the layer is scrollable, it needs an APZC. If there is already an APZC on it, use that, - // otherwise create one if we can. We might not be able to create one if we don't have a - // GeckoContentController for it, in which case we just leave it as null. - controller = container->GetAsyncPanZoomController(); - const FrameMetrics& metrics = container->GetFrameMetrics(); - if (metrics.IsScrollable()) { - // Scrollable, create an APZC if it doesn't have one and we can create it - if (!controller) { - const CompositorParent::LayerTreeState* state = CompositorParent::GetIndirectShadowTree(aLayersId); - if (state && state->mController.get()) { - controller = new AsyncPanZoomController(state->mController, + // We do this business with collecting the entire tree into an array because otherwise + // it's very hard to determine which APZC instances need to be destroyed. In the worst + // case, there are two scenarios: (a) a layer with an APZC is removed from the layer + // tree and (b) a layer with an APZC is moved in the layer tree from one place to a + // completely different place. In scenario (a) we would want to destroy the APZC while + // walking the layer tree and noticing that the layer/APZC is no longer there. But if + // we do that then we run into a problem in scenario (b) because we might encounter that + // layer later during the walk. To handle both of these we have to 'remember' that the + // layer was not found, and then do the destroy only at the end of the tree walk after + // we are sure that the layer was removed and not just transplanted elsewhere. Doing that + // as part of a recursive tree walk is hard and so maintaining a list and removing + // APZCs that are still alive is much simpler. + nsTArray< nsRefPtr > apzcsToDestroy; + Collect(mRootApzc, &apzcsToDestroy); + mRootApzc = nullptr; + + if (aRoot) { + UpdatePanZoomControllerTree(aCompositor, + aRoot, CompositorParent::ROOT_LAYER_TREE_ID, + nullptr, nullptr, + aIsFirstPaint, aFirstPaintLayersId, + &apzcsToDestroy); + } + + for (int i = apzcsToDestroy.Length() - 1; i >= 0; i--) { + apzcsToDestroy[i]->Destroy(); + } +} + +AsyncPanZoomController* +APZCTreeManager::UpdatePanZoomControllerTree(CompositorParent* aCompositor, + Layer* aLayer, uint64_t aLayersId, + AsyncPanZoomController* aParent, + AsyncPanZoomController* aNextSibling, + bool aIsFirstPaint, uint64_t aFirstPaintLayersId, + nsTArray< nsRefPtr >* aApzcsToDestroy) +{ + ContainerLayer* container = aLayer->AsContainerLayer(); + AsyncPanZoomController* controller = nullptr; + if (container) { + if (container->GetFrameMetrics().IsScrollable()) { + const CompositorParent::LayerTreeState* state = CompositorParent::GetIndirectShadowTree(aLayersId); + if (state && state->mController.get()) { + // If we get here, aLayer is a scrollable container layer and somebody + // has registered a GeckoContentController for it, so we need to ensure + // it has an APZC instance to manage its scrolling. + + controller = container->GetAsyncPanZoomController(); + if (!controller) { + controller = new AsyncPanZoomController(aLayersId, state->mController, AsyncPanZoomController::USE_GESTURE_DETECTOR); controller->SetCompositorParent(aCompositor); + } else { + // If there was already an APZC for the layer clear the tree pointers + // so that it doesn't continue pointing to APZCs that should no longer + // be in the tree. These pointers will get reset properly as we continue + // building the tree. Also remove it from the set of APZCs that are going + // to be destroyed, because it's going to remain active. + aApzcsToDestroy->RemoveElement(controller); + controller->SetPrevSibling(nullptr); + controller->SetLastChild(nullptr); } + + controller->NotifyLayersUpdated(container->GetFrameMetrics(), + aIsFirstPaint && (aLayersId == aFirstPaintLayersId)); + + // Bind the APZC instance into the tree of APZCs + if (aNextSibling) { + aNextSibling->SetPrevSibling(controller); + } else if (aParent) { + aParent->SetLastChild(controller); + } else { + mRootApzc = controller; + } + + // Let this controller be the parent of other controllers when we recurse downwards + aParent = controller; } - } else if (controller) { - // Not scrollable, so clear the APZC instance - controller = nullptr; } + container->SetAsyncPanZoomController(controller); - - if (controller) { - controller->NotifyLayersUpdated(container->GetFrameMetrics(), aIsFirstPaint); - } } + uint64_t childLayersId = (aLayer->AsRefLayer() ? aLayer->AsRefLayer()->GetReferentId() : aLayersId); + AsyncPanZoomController* next = nullptr; + for (Layer* child = aLayer->GetLastChild(); child; child = child->GetPrevSibling()) { + next = UpdatePanZoomControllerTree(aCompositor, child, childLayersId, aParent, next, + aIsFirstPaint, aFirstPaintLayersId, aApzcsToDestroy); + } + + // Return the APZC that should be the sibling of other APZCs as we continue + // moving towards the first child at this depth in the layer tree. + // If this layer doesn't have a controller, we promote any APZCs in the subtree + // upwards. Otherwise we fall back to the aNextSibling that was passed in. if (controller) { - mApzcs[aLayersId] = controller; - } else { - mApzcs.erase(aLayersId); + return controller; } + if (next) { + return next; + } + return aNextSibling; } nsEventStatus @@ -203,24 +281,29 @@ APZCTreeManager::ClearTree() { MonitorAutoLock lock(mTreeLock); - std::map< uint64_t, nsRefPtr >::iterator it = mApzcs.begin(); - while (it != mApzcs.end()) { - nsRefPtr apzc = it->second; - apzc->Destroy(); - it++; + // This can be done as part of a tree walk but it's easier to + // just re-use the Collect method that we need in other places. + // If this is too slow feel free to change it to a recursive walk. + nsTArray< nsRefPtr > apzcsToDestroy; + Collect(mRootApzc, &apzcsToDestroy); + for (int i = apzcsToDestroy.Length() - 1; i >= 0; i--) { + apzcsToDestroy[i]->Destroy(); } - mApzcs.clear(); + mRootApzc = nullptr; } already_AddRefed APZCTreeManager::GetTargetAPZC(const ScrollableLayerGuid& aGuid) { MonitorAutoLock lock(mTreeLock); - std::map< uint64_t, nsRefPtr >::iterator it = mApzcs.find(aGuid.mLayersId); - if (it == mApzcs.end()) { - return nullptr; + nsRefPtr target; + // The root may have siblings, check those too + for (AsyncPanZoomController* apzc = mRootApzc; apzc; apzc = apzc->GetPrevSibling()) { + target = FindTargetAPZC(apzc, aGuid); + if (target) { + break; + } } - nsRefPtr target = it->second; return target.forget(); } @@ -233,5 +316,22 @@ APZCTreeManager::GetTargetAPZC(const ScreenPoint& aPoint) return nullptr; } +AsyncPanZoomController* +APZCTreeManager::FindTargetAPZC(AsyncPanZoomController* aApzc, const ScrollableLayerGuid& aGuid) { + // This walks the tree in depth-first, reverse order, so that it encounters + // APZCs front-to-back on the screen. + for (AsyncPanZoomController* child = aApzc->GetLastChild(); child; child = child->GetPrevSibling()) { + AsyncPanZoomController* match = FindTargetAPZC(child, aGuid); + if (match) { + return match; + } + } + + if (aApzc->Matches(aGuid)) { + return aApzc; + } + return nullptr; +} + } } diff --git a/gfx/layers/composite/APZCTreeManager.h b/gfx/layers/composite/APZCTreeManager.h index 99ac5ec0b5b..278b9ddc54c 100644 --- a/gfx/layers/composite/APZCTreeManager.h +++ b/gfx/layers/composite/APZCTreeManager.h @@ -9,11 +9,13 @@ #include "mozilla/layers/AsyncPanZoomController.h" #include "Layers.h" #include "CompositorParent.h" -#include namespace mozilla { namespace layers { +class AsyncPanZoomController; +class CompositorParent; + /** * This class allows us to uniquely identify a scrollable layer. The * mLayersId identifies the layer tree (corresponding to a child process @@ -106,9 +108,19 @@ public: * in the layer tree. * * This must be called on the compositor thread as it walks the layer tree. + * + * @param aCompositor A pointer to the compositor parent instance that owns + * this APZCTreeManager + * @param aRoot The root of the (full) layer tree + * @param aFirstPaintLayersId The layers id of the subtree to which aIsFirstPaint + * applies. + * @param aIsFirstPaint True if the layers update that this is called in response + * to included a first-paint. If this is true, the part of + * the tree that is affected by the first-paint flag is + * indicated by the aFirstPaintLayersId parameter. */ void UpdatePanZoomControllerTree(CompositorParent* aCompositor, Layer* aRoot, - uint64_t aLayersId, bool aIsFirstPaint); + bool aIsFirstPaint, uint64_t aFirstPaintLayersId); /** * General handler for incoming input events. Manipulates the frame metrics @@ -216,13 +228,34 @@ private: */ already_AddRefed GetTargetAPZC(const ScrollableLayerGuid& aGuid); already_AddRefed GetTargetAPZC(const ScreenPoint& aPoint); + /* Recursive helper */ + AsyncPanZoomController* FindTargetAPZC(AsyncPanZoomController* aApzc, const ScrollableLayerGuid& aGuid); + + /** + * Recursive helper function to build the APZC tree. The tree of APZC instances has + * the same shape as the layer tree, but excludes all the layers that are not scrollable. + * Note that this means APZCs corresponding to layers at different depths in the tree + * may end up becoming siblings. It also means that the "root" APZC may have siblings. + * This function walks the layer tree backwards through siblings and constructs the APZC + * tree also as a last-child-prev-sibling tree because that simplifies the hit detection + * code. + */ + AsyncPanZoomController* UpdatePanZoomControllerTree(CompositorParent* aCompositor, + Layer* aLayer, uint64_t aLayersId, + AsyncPanZoomController* aParent, + AsyncPanZoomController* aNextSibling, + bool aIsFirstPaint, + uint64_t aFirstPaintLayersId, + nsTArray< nsRefPtr >* aApzcsToDestroy); private: - /* Whenever walking or mutating the map of APZC instances, mTreeLock must be held. + /* Whenever walking or mutating the tree rooted at mRootApzc, mTreeLock must be held. * This lock does not need to be held while manipulating a single APZC instance in - * isolation (that is, if its tree pointers are not being accessed or mutated). */ + * isolation (that is, if its tree pointers are not being accessed or mutated). The + * lock also needs to be held when accessing the mRootApzc instance variable, as that + * is considered part of the APZC tree management state. */ mozilla::Monitor mTreeLock; - std::map< uint64_t, nsRefPtr > mApzcs; + nsRefPtr mRootApzc; }; } diff --git a/gfx/layers/ipc/AsyncPanZoomController.cpp b/gfx/layers/ipc/AsyncPanZoomController.cpp index 8e2cf1f511d..0f03c7bc9e2 100644 --- a/gfx/layers/ipc/AsyncPanZoomController.cpp +++ b/gfx/layers/ipc/AsyncPanZoomController.cpp @@ -162,9 +162,11 @@ AsyncPanZoomController::InitializeGlobalState() ClearOnShutdown(&gComputedTimingFunction); } -AsyncPanZoomController::AsyncPanZoomController(GeckoContentController* aGeckoContentController, +AsyncPanZoomController::AsyncPanZoomController(uint64_t aLayersId, + GeckoContentController* aGeckoContentController, GestureBehavior aGestures) - : mPaintThrottler(GetFrameTime()), + : mLayersId(aLayersId), + mPaintThrottler(GetFrameTime()), mGeckoContentController(aGeckoContentController), mRefPtrMonitor("RefPtrMonitor"), mTouchListenerTimeoutTask(nullptr), @@ -215,9 +217,13 @@ AsyncPanZoomController::GetGestureEventListener() { void AsyncPanZoomController::Destroy() { - MonitorAutoLock lock(mRefPtrMonitor); - mGeckoContentController = nullptr; - mGestureEventListener = nullptr; + { // scope the lock + MonitorAutoLock lock(mRefPtrMonitor); + mGeckoContentController = nullptr; + mGestureEventListener = nullptr; + } + mPrevSibling = nullptr; + mLastChild = nullptr; } /* static */float @@ -1517,5 +1523,12 @@ void AsyncPanZoomController::UpdateScrollOffset(const CSSPoint& aScrollOffset) mFrameMetrics.mScrollOffset = aScrollOffset; } +bool AsyncPanZoomController::Matches(const ScrollableLayerGuid& aGuid) +{ + // TODO: also check the presShellId and mScrollId, once those are + // fully propagated everywhere in RenderFrameParent and AndroidJNI. + return aGuid.mLayersId == mLayersId; +} + } } diff --git a/gfx/layers/ipc/AsyncPanZoomController.h b/gfx/layers/ipc/AsyncPanZoomController.h index d718908ba7b..81a55171243 100644 --- a/gfx/layers/ipc/AsyncPanZoomController.h +++ b/gfx/layers/ipc/AsyncPanZoomController.h @@ -14,12 +14,14 @@ #include "InputData.h" #include "Axis.h" #include "TaskThrottler.h" +#include "mozilla/layers/APZCTreeManager.h" #include "base/message_loop.h" namespace mozilla { namespace layers { +struct ScrollableLayerGuid; class CompositorParent; class GestureEventListener; class ContainerLayer; @@ -68,7 +70,8 @@ public: */ static float GetTouchStartTolerance(); - AsyncPanZoomController(GeckoContentController* aController, + AsyncPanZoomController(uint64_t aLayersId, + GeckoContentController* aController, GestureBehavior aGestures = DEFAULT_GESTURES); ~AsyncPanZoomController(); @@ -245,6 +248,11 @@ public: */ nsEventStatus HandleInputEvent(const InputData& aEvent); + /** + * Returns true if this APZC instance is for the layer identified by the guid. + */ + bool Matches(const ScrollableLayerGuid& aGuid); + /** * Sync panning and zooming animation using a fixed frame time. * This will ensure that we animate the APZC correctly with other external @@ -503,6 +511,7 @@ private: */ void SetState(PanZoomState aState); + uint64_t mLayersId; nsRefPtr mCompositorParent; TaskThrottler mPaintThrottler; @@ -613,6 +622,20 @@ private: bool mDelayPanning; friend class Axis; + + /* The functions and members in this section are used to build a tree + * structure out of APZC instances. This tree can only be walked or + * manipulated while holding the lock in the associated APZCTreeManager + * instance. + */ +public: + void SetLastChild(AsyncPanZoomController* child) { mLastChild = child; } + void SetPrevSibling(AsyncPanZoomController* sibling) { mPrevSibling = sibling; } + AsyncPanZoomController* GetLastChild() const { return mLastChild; } + AsyncPanZoomController* GetPrevSibling() const { return mPrevSibling; } +private: + nsRefPtr mLastChild; + nsRefPtr mPrevSibling; }; } diff --git a/gfx/layers/ipc/CompositorParent.cpp b/gfx/layers/ipc/CompositorParent.cpp index 6bd8f49bf9b..04d5552f150 100644 --- a/gfx/layers/ipc/CompositorParent.cpp +++ b/gfx/layers/ipc/CompositorParent.cpp @@ -409,7 +409,7 @@ CompositorParent::NotifyShadowTreeTransaction(uint64_t aId, bool aIsFirstPaint) { if (mApzcTreeManager) { AutoResolveRefLayers resolve(mCompositionManager); - mApzcTreeManager->UpdatePanZoomControllerTree(this, GetIndirectShadowTree(aId)->mRoot, aId, aIsFirstPaint); + mApzcTreeManager->UpdatePanZoomControllerTree(this, mLayerManager->GetRoot(), aIsFirstPaint, aId); } if (mLayerManager) { @@ -566,15 +566,10 @@ CompositorParent::ShadowLayersUpdated(LayerTransactionParent* aLayerTree, Layer* root = aLayerTree->GetRoot(); mLayerManager->SetRoot(root); -#ifdef MOZ_WIDGET_ANDROID - // Temporary hack for Fennec. This will be removed once UpdatePanZoomControllerTree actually - // does a full tree walk. if (mApzcTreeManager) { AutoResolveRefLayers resolve(mCompositionManager); - Layer* pzcRoot = mLayerManager->GetPrimaryScrollableLayer(); - mApzcTreeManager->UpdatePanZoomControllerTree(this, pzcRoot, ROOT_LAYER_TREE_ID, isFirstPaint); + mApzcTreeManager->UpdatePanZoomControllerTree(this, root, isFirstPaint, ROOT_LAYER_TREE_ID); } -#endif if (root) { SetShadowProperties(root); diff --git a/gfx/tests/gtest/TestAsyncPanZoomController.cpp b/gfx/tests/gtest/TestAsyncPanZoomController.cpp index 4199ebc7b80..db8421e87f7 100644 --- a/gfx/tests/gtest/TestAsyncPanZoomController.cpp +++ b/gfx/tests/gtest/TestAsyncPanZoomController.cpp @@ -41,8 +41,8 @@ class TestAPZCContainerLayer : public ContainerLayer { class TestAsyncPanZoomController : public AsyncPanZoomController { public: - TestAsyncPanZoomController(MockContentController* mcc) - : AsyncPanZoomController(mcc) + TestAsyncPanZoomController(uint64_t aLayersId, MockContentController* mcc) + : AsyncPanZoomController(aLayersId, mcc) {} void SetFrameMetrics(const FrameMetrics& metrics) { @@ -102,7 +102,7 @@ void ApzcPan(AsyncPanZoomController* apzc, int& aTime, int aTouchStartY, int aTo TEST(AsyncPanZoomController, Constructor) { // RefCounted class can't live in the stack nsRefPtr mcc = new MockContentController(); - nsRefPtr apzc = new TestAsyncPanZoomController(mcc); + nsRefPtr apzc = new TestAsyncPanZoomController(0, mcc); apzc->SetFrameMetrics(TestFrameMetrics()); } @@ -110,7 +110,7 @@ TEST(AsyncPanZoomController, SimpleTransform) { TimeStamp testStartTime = TimeStamp::Now(); // RefCounted class can't live in the stack nsRefPtr mcc = new MockContentController(); - nsRefPtr apzc = new TestAsyncPanZoomController(mcc); + nsRefPtr apzc = new TestAsyncPanZoomController(0, mcc); apzc->SetFrameMetrics(TestFrameMetrics()); TestAPZCContainerLayer layer; @@ -143,8 +143,8 @@ TEST(AsyncPanZoomController, ComplexTransform) { // sides. nsRefPtr mcc = new MockContentController(); - nsRefPtr apzc = new TestAsyncPanZoomController(mcc); - nsRefPtr childApzc = new TestAsyncPanZoomController(mcc); + nsRefPtr apzc = new TestAsyncPanZoomController(0, mcc); + nsRefPtr childApzc = new TestAsyncPanZoomController(0, mcc); const char* layerTreeSyntax = "c(c)"; // LayerID 0 1 @@ -231,7 +231,7 @@ TEST(AsyncPanZoomController, Pan) { AsyncPanZoomController::SetFrameTime(testStartTime); nsRefPtr mcc = new MockContentController(); - nsRefPtr apzc = new TestAsyncPanZoomController(mcc); + nsRefPtr apzc = new TestAsyncPanZoomController(0, mcc); apzc->SetFrameMetrics(TestFrameMetrics()); apzc->NotifyLayersUpdated(TestFrameMetrics(), true); @@ -264,7 +264,7 @@ TEST(AsyncPanZoomController, Fling) { AsyncPanZoomController::SetFrameTime(testStartTime); nsRefPtr mcc = new MockContentController(); - nsRefPtr apzc = new TestAsyncPanZoomController(mcc); + nsRefPtr apzc = new TestAsyncPanZoomController(0, mcc); apzc->SetFrameMetrics(TestFrameMetrics()); apzc->NotifyLayersUpdated(TestFrameMetrics(), true); @@ -294,7 +294,7 @@ TEST(AsyncPanZoomController, OverScrollPanning) { AsyncPanZoomController::SetFrameTime(testStartTime); nsRefPtr mcc = new MockContentController(); - nsRefPtr apzc = new TestAsyncPanZoomController(mcc); + nsRefPtr apzc = new TestAsyncPanZoomController(0, mcc); apzc->SetFrameMetrics(TestFrameMetrics()); apzc->NotifyLayersUpdated(TestFrameMetrics(), true); From d725e5e6a19b60d649f9efc7e976a416414f208b Mon Sep 17 00:00:00 2001 From: Kartikaya Gupta Date: Tue, 30 Jul 2013 14:03:40 -0400 Subject: [PATCH 24/36] Bug 866232 - Some documentation/variable renaming cleanup. r=BenWa --- gfx/layers/ipc/AsyncPanZoomController.cpp | 22 +++++++++--------- gfx/layers/ipc/AsyncPanZoomController.h | 28 ++++++++++++----------- 2 files changed, 26 insertions(+), 24 deletions(-) diff --git a/gfx/layers/ipc/AsyncPanZoomController.cpp b/gfx/layers/ipc/AsyncPanZoomController.cpp index 0f03c7bc9e2..b621af9ee5d 100644 --- a/gfx/layers/ipc/AsyncPanZoomController.cpp +++ b/gfx/layers/ipc/AsyncPanZoomController.cpp @@ -1170,12 +1170,12 @@ bool AsyncPanZoomController::SampleContentTransformForFrame(const TimeStamp& aSa return requestAnimationFrame; } -void AsyncPanZoomController::NotifyLayersUpdated(const FrameMetrics& aViewportFrame, bool aIsFirstPaint) { +void AsyncPanZoomController::NotifyLayersUpdated(const FrameMetrics& aLayerMetrics, bool aIsFirstPaint) { MonitorAutoLock monitor(mMonitor); - mLastContentPaintMetrics = aViewportFrame; + mLastContentPaintMetrics = aLayerMetrics; - mFrameMetrics.mMayHaveTouchListeners = aViewportFrame.mMayHaveTouchListeners; + mFrameMetrics.mMayHaveTouchListeners = aLayerMetrics.mMayHaveTouchListeners; // TODO: Once a mechanism for calling UpdateScrollOffset() when content does // a scrollTo() is implemented for B2G (bug 895905), this block can be removed. @@ -1192,7 +1192,7 @@ void AsyncPanZoomController::NotifyLayersUpdated(const FrameMetrics& aViewportFr case FLING: case TOUCHING: case WAITING_LISTENERS: - mFrameMetrics.mScrollOffset = aViewportFrame.mScrollOffset; + mFrameMetrics.mScrollOffset = aLayerMetrics.mScrollOffset; break; // Don't clobber if we're in other states. default: @@ -1203,12 +1203,12 @@ void AsyncPanZoomController::NotifyLayersUpdated(const FrameMetrics& aViewportFr mPaintThrottler.TaskComplete(GetFrameTime()); bool needContentRepaint = false; - if (aViewportFrame.mCompositionBounds.width == mFrameMetrics.mCompositionBounds.width && - aViewportFrame.mCompositionBounds.height == mFrameMetrics.mCompositionBounds.height) { + if (aLayerMetrics.mCompositionBounds.width == mFrameMetrics.mCompositionBounds.width && + aLayerMetrics.mCompositionBounds.height == mFrameMetrics.mCompositionBounds.height) { // Remote content has sync'd up to the composition geometry // change, so we can accept the viewport it's calculated. CSSToScreenScale previousResolution = mFrameMetrics.CalculateResolution(); - mFrameMetrics.mViewport = aViewportFrame.mViewport; + mFrameMetrics.mViewport = aLayerMetrics.mViewport; CSSToScreenScale newResolution = mFrameMetrics.CalculateResolution(); needContentRepaint |= (previousResolution != newResolution); } @@ -1223,12 +1223,12 @@ void AsyncPanZoomController::NotifyLayersUpdated(const FrameMetrics& aViewportFr // XXX If this is the very first time we're getting a layers update we need to // trigger another repaint, or the B2G browser shows stale content. This needs // to be investigated and fixed. - needContentRepaint |= (mFrameMetrics.IsDefault() && !aViewportFrame.IsDefault()); + needContentRepaint |= (mFrameMetrics.IsDefault() && !aLayerMetrics.IsDefault()); - mFrameMetrics = aViewportFrame; + mFrameMetrics = aLayerMetrics; mState = NOTHING; - } else if (!mFrameMetrics.mScrollableRect.IsEqualEdges(aViewportFrame.mScrollableRect)) { - mFrameMetrics.mScrollableRect = aViewportFrame.mScrollableRect; + } else if (!mFrameMetrics.mScrollableRect.IsEqualEdges(aLayerMetrics.mScrollableRect)) { + mFrameMetrics.mScrollableRect = aLayerMetrics.mScrollableRect; } if (needContentRepaint) { diff --git a/gfx/layers/ipc/AsyncPanZoomController.h b/gfx/layers/ipc/AsyncPanZoomController.h index 81a55171243..c8afb154d65 100644 --- a/gfx/layers/ipc/AsyncPanZoomController.h +++ b/gfx/layers/ipc/AsyncPanZoomController.h @@ -174,9 +174,8 @@ public: * idempotent. For example, a fling transform can be applied each time this is * called (though not necessarily). |aSampleTime| is the time that this is * sampled at; this is used for interpolating animations. Calling this sets a - * new transform in |aNewTransform| which should be applied directly to the - * shadow layer of the frame (do not multiply it in as the code already does - * this internally with |aLayer|'s transform). + * new transform in |aNewTransform| which should be multiplied to the transform + * in the shadow layer corresponding to this APZC. * * Return value indicates whether or not any currently running animation * should continue. That is, if true, the compositor should schedule another @@ -188,12 +187,13 @@ public: ScreenPoint& aScrollOffset); /** - * A shadow layer update has arrived. |aViewportFrame| is the new FrameMetrics - * for the top-level frame. |aIsFirstPaint| is a flag passed from the shadow + * A shadow layer update has arrived. |aLayerMetrics| is the new FrameMetrics + * for the container layer corresponding to this APZC. + * |aIsFirstPaint| is a flag passed from the shadow * layers code indicating that the frame metrics being sent with this call are * the initial metrics and the initial paint of the frame has just happened. */ - void NotifyLayersUpdated(const FrameMetrics& aViewportFrame, bool aIsFirstPaint); + void NotifyLayersUpdated(const FrameMetrics& aLayerMetrics, bool aIsFirstPaint); /** * The platform implementation must set the compositor parent so that we can @@ -531,17 +531,19 @@ protected: // monitor. Do not read from or modify either of them without locking. FrameMetrics mFrameMetrics; - // Protects |mFrameMetrics|, |mLastContentPaintMetrics|, |mState| and - // |mMetaViewportInfo|. Before manipulating |mFrameMetrics| or - // |mLastContentPaintMetrics|, the monitor should be held. When setting - // |mState|, either the SetState() function can be used, or the monitor can be - // held and then |mState| updated. |mMetaViewportInfo| should be updated - // using UpdateMetaViewport(). + // Protects |mFrameMetrics|, |mLastContentPaintMetrics|, and |mState|. + // Before manipulating |mFrameMetrics| or |mLastContentPaintMetrics|, the + // monitor should be held. When setting |mState|, either the SetState() + // function can be used, or the monitor can be held and then |mState| updated. Monitor mMonitor; private: + // Metrics of the container layer corresponding to this APZC. This is + // stored here so that it is accessible from the UI/controller thread. // These are the metrics at last content paint, the most recent - // values we were notified of in NotifyLayersUpdate(). + // values we were notified of in NotifyLayersUpdate(). Since it represents + // the Gecko state, it should be used as a basis for untransformation when + // sending messages back to Gecko. FrameMetrics mLastContentPaintMetrics; // The last metrics that we requested a paint for. These are used to make sure // that we're not requesting a paint of the same thing that's already drawn. From ef737ecf30c58f98316dac68774278568cc8f98b Mon Sep 17 00:00:00 2001 From: Kartikaya Gupta Date: Tue, 30 Jul 2013 14:03:41 -0400 Subject: [PATCH 25/36] Bug 866232 - Extract a GetCurrentAsyncTransform method in APZC. r=BenWa --- .../composite/AsyncCompositionManager.cpp | 1 - gfx/layers/ipc/AsyncPanZoomController.cpp | 37 +++++++++---------- gfx/layers/ipc/AsyncPanZoomController.h | 13 ++++++- .../gtest/TestAsyncPanZoomController.cpp | 26 ++++++------- 4 files changed, 40 insertions(+), 37 deletions(-) diff --git a/gfx/layers/composite/AsyncCompositionManager.cpp b/gfx/layers/composite/AsyncCompositionManager.cpp index 4426bbfaabf..9e816b10a55 100644 --- a/gfx/layers/composite/AsyncCompositionManager.cpp +++ b/gfx/layers/composite/AsyncCompositionManager.cpp @@ -428,7 +428,6 @@ AsyncCompositionManager::ApplyAsyncContentTransformToTree(TimeStamp aCurrentFram ScreenPoint scrollOffset; *aWantNextFrame |= controller->SampleContentTransformForFrame(aCurrentFrame, - container, &treeTransform, scrollOffset); diff --git a/gfx/layers/ipc/AsyncPanZoomController.cpp b/gfx/layers/ipc/AsyncPanZoomController.cpp index b621af9ee5d..cfa3280be20 100644 --- a/gfx/layers/ipc/AsyncPanZoomController.cpp +++ b/gfx/layers/ipc/AsyncPanZoomController.cpp @@ -1059,7 +1059,6 @@ AsyncPanZoomController::FireAsyncScrollOnTimeout() } bool AsyncPanZoomController::SampleContentTransformForFrame(const TimeStamp& aSampleTime, - ContainerLayer* aLayer, ViewTransform* aNewTransform, ScreenPoint& aScrollOffset) { // The eventual return value of this function. The compositor needs to know @@ -1069,10 +1068,6 @@ bool AsyncPanZoomController::SampleContentTransformForFrame(const TimeStamp& aSa // responsibility to schedule a composite. bool requestAnimationFrame = false; - LayerPoint metricsScrollOffset; - CSSPoint scrollOffset; - CSSToScreenScale localScale; - const FrameMetrics& frame = aLayer->GetFrameMetrics(); { MonitorAutoLock mon(mMonitor); @@ -1119,17 +1114,9 @@ bool AsyncPanZoomController::SampleContentTransformForFrame(const TimeStamp& aSa break; } - // Current local transform; this is not what's painted but rather - // what PZC has transformed due to touches like panning or - // pinching. Eventually, the root layer transform will become this - // during runtime, but we must wait for Gecko to repaint. - localScale = mFrameMetrics.CalculateResolution(); + aScrollOffset = mFrameMetrics.mScrollOffset * mFrameMetrics.CalculateResolution(); + *aNewTransform = GetCurrentAsyncTransformInternal(); - if (frame.IsScrollable()) { - metricsScrollOffset = frame.GetScrollOffsetInLayerPixels(); - } - - scrollOffset = mFrameMetrics.mScrollOffset; mCurrentAsyncScrollOffset = mFrameMetrics.mScrollOffset; } @@ -1160,16 +1147,26 @@ bool AsyncPanZoomController::SampleContentTransformForFrame(const TimeStamp& aSa gAsyncScrollTimeout); } - CSSToLayerScale paintedScale = frame.mDevPixelsPerCSSPixel * frame.mResolution; - LayerPoint translation = (scrollOffset * paintedScale) - metricsScrollOffset; - *aNewTransform = ViewTransform(-translation, localScale / frame.mDevPixelsPerCSSPixel); - aScrollOffset = scrollOffset * localScale; - mLastSampleTime = aSampleTime; return requestAnimationFrame; } +ViewTransform AsyncPanZoomController::GetCurrentAsyncTransform() { + MonitorAutoLock mon(mMonitor); + return GetCurrentAsyncTransformInternal(); +} + +ViewTransform AsyncPanZoomController::GetCurrentAsyncTransformInternal() { + LayerPoint metricsScrollOffset; + if (mLastContentPaintMetrics.IsScrollable()) { + metricsScrollOffset = mLastContentPaintMetrics.GetScrollOffsetInLayerPixels(); + } + CSSToScreenScale localScale = mFrameMetrics.CalculateResolution(); + LayerPoint translation = mFrameMetrics.GetScrollOffsetInLayerPixels() - metricsScrollOffset; + return ViewTransform(-translation, localScale / mLastContentPaintMetrics.mDevPixelsPerCSSPixel); +} + void AsyncPanZoomController::NotifyLayersUpdated(const FrameMetrics& aLayerMetrics, bool aIsFirstPaint) { MonitorAutoLock monitor(mMonitor); diff --git a/gfx/layers/ipc/AsyncPanZoomController.h b/gfx/layers/ipc/AsyncPanZoomController.h index c8afb154d65..02b25bbce8e 100644 --- a/gfx/layers/ipc/AsyncPanZoomController.h +++ b/gfx/layers/ipc/AsyncPanZoomController.h @@ -182,7 +182,6 @@ public: * composite. */ bool SampleContentTransformForFrame(const TimeStamp& aSampleTime, - ContainerLayer* aLayer, ViewTransform* aNewTransform, ScreenPoint& aScrollOffset); @@ -211,6 +210,18 @@ public: */ void Destroy(); + /** + * Returns the incremental transformation corresponding to the async pan/zoom + * in progress. That is, when this transform is multiplied with the layer's + * existing transform, it will make the layer appear with the desired pan/zoom + * amount. + */ + ViewTransform GetCurrentAsyncTransform(); +private: + /* Internal method of above. Callers to this MUST hold the monitor. */ + ViewTransform GetCurrentAsyncTransformInternal(); +public: + /** * Sets the DPI of the device for use within panning and zooming logic. It is * a platform responsibility to set this on initialization of this class and diff --git a/gfx/tests/gtest/TestAsyncPanZoomController.cpp b/gfx/tests/gtest/TestAsyncPanZoomController.cpp index db8421e87f7..50096af62e0 100644 --- a/gfx/tests/gtest/TestAsyncPanZoomController.cpp +++ b/gfx/tests/gtest/TestAsyncPanZoomController.cpp @@ -113,10 +113,9 @@ TEST(AsyncPanZoomController, SimpleTransform) { nsRefPtr apzc = new TestAsyncPanZoomController(0, mcc); apzc->SetFrameMetrics(TestFrameMetrics()); - TestAPZCContainerLayer layer; ScreenPoint pointOut; ViewTransform viewTransformOut; - apzc->SampleContentTransformForFrame(testStartTime, &layer, &viewTransformOut, pointOut); + apzc->SampleContentTransformForFrame(testStartTime, &viewTransformOut, pointOut); EXPECT_EQ(pointOut, ScreenPoint()); EXPECT_EQ(viewTransformOut, ViewTransform()); @@ -189,39 +188,39 @@ TEST(AsyncPanZoomController, ComplexTransform) { // initial transform apzc->SetFrameMetrics(metrics); apzc->NotifyLayersUpdated(metrics, true); - apzc->SampleContentTransformForFrame(testStartTime, layers[0]->AsContainerLayer(), &viewTransformOut, pointOut); + apzc->SampleContentTransformForFrame(testStartTime, &viewTransformOut, pointOut); EXPECT_EQ(ViewTransform(LayerPoint(), LayoutDeviceToScreenScale(2)), viewTransformOut); EXPECT_EQ(ScreenPoint(60, 60), pointOut); childApzc->SetFrameMetrics(childMetrics); childApzc->NotifyLayersUpdated(childMetrics, true); - childApzc->SampleContentTransformForFrame(testStartTime, layers[1]->AsContainerLayer(), &viewTransformOut, pointOut); + childApzc->SampleContentTransformForFrame(testStartTime, &viewTransformOut, pointOut); EXPECT_EQ(ViewTransform(LayerPoint(), LayoutDeviceToScreenScale(2)), viewTransformOut); EXPECT_EQ(ScreenPoint(60, 60), pointOut); // do an async scroll by 5 pixels and check the transform metrics.mScrollOffset += CSSPoint(5, 0); apzc->SetFrameMetrics(metrics); - apzc->SampleContentTransformForFrame(testStartTime, layers[0]->AsContainerLayer(), &viewTransformOut, pointOut); + apzc->SampleContentTransformForFrame(testStartTime, &viewTransformOut, pointOut); EXPECT_EQ(ViewTransform(LayerPoint(-30, 0), LayoutDeviceToScreenScale(2)), viewTransformOut); EXPECT_EQ(ScreenPoint(90, 60), pointOut); childMetrics.mScrollOffset += CSSPoint(5, 0); childApzc->SetFrameMetrics(childMetrics); - childApzc->SampleContentTransformForFrame(testStartTime, layers[1]->AsContainerLayer(), &viewTransformOut, pointOut); + childApzc->SampleContentTransformForFrame(testStartTime, &viewTransformOut, pointOut); EXPECT_EQ(ViewTransform(LayerPoint(-30, 0), LayoutDeviceToScreenScale(2)), viewTransformOut); EXPECT_EQ(ScreenPoint(90, 60), pointOut); // do an async zoom of 1.5x and check the transform metrics.mZoom.scale *= 1.5f; apzc->SetFrameMetrics(metrics); - apzc->SampleContentTransformForFrame(testStartTime, layers[0]->AsContainerLayer(), &viewTransformOut, pointOut); + apzc->SampleContentTransformForFrame(testStartTime, &viewTransformOut, pointOut); EXPECT_EQ(ViewTransform(LayerPoint(-30, 0), LayoutDeviceToScreenScale(3)), viewTransformOut); EXPECT_EQ(ScreenPoint(135, 90), pointOut); childMetrics.mZoom.scale *= 1.5f; childApzc->SetFrameMetrics(childMetrics); - childApzc->SampleContentTransformForFrame(testStartTime, layers[0]->AsContainerLayer(), &viewTransformOut, pointOut); + childApzc->SampleContentTransformForFrame(testStartTime, &viewTransformOut, pointOut); EXPECT_EQ(ViewTransform(LayerPoint(-30, 0), LayoutDeviceToScreenScale(3)), viewTransformOut); EXPECT_EQ(ScreenPoint(135, 90), pointOut); } @@ -242,19 +241,18 @@ TEST(AsyncPanZoomController, Pan) { int time = 0; int touchStart = 50; int touchEnd = 10; - TestAPZCContainerLayer layer; ScreenPoint pointOut; ViewTransform viewTransformOut; // Pan down ApzcPan(apzc, time, touchStart, touchEnd); - apzc->SampleContentTransformForFrame(testStartTime, &layer, &viewTransformOut, pointOut); + apzc->SampleContentTransformForFrame(testStartTime, &viewTransformOut, pointOut); EXPECT_EQ(pointOut, ScreenPoint(0, -(touchEnd-touchStart))); EXPECT_NE(viewTransformOut, ViewTransform()); // Pan back ApzcPan(apzc, time, touchEnd, touchStart); - apzc->SampleContentTransformForFrame(testStartTime, &layer, &viewTransformOut, pointOut); + apzc->SampleContentTransformForFrame(testStartTime, &viewTransformOut, pointOut); EXPECT_EQ(pointOut, ScreenPoint()); EXPECT_EQ(viewTransformOut, ViewTransform()); } @@ -275,7 +273,6 @@ TEST(AsyncPanZoomController, Fling) { int time = 0; int touchStart = 50; int touchEnd = 10; - TestAPZCContainerLayer layer; ScreenPoint pointOut; ViewTransform viewTransformOut; @@ -283,7 +280,7 @@ TEST(AsyncPanZoomController, Fling) { ApzcPan(apzc, time, touchStart, touchEnd); ScreenPoint lastPoint; for (int i = 1; i < 50; i+=1) { - apzc->SampleContentTransformForFrame(testStartTime+TimeDuration::FromMilliseconds(i), &layer, &viewTransformOut, pointOut); + apzc->SampleContentTransformForFrame(testStartTime+TimeDuration::FromMilliseconds(i), &viewTransformOut, pointOut); EXPECT_GT(pointOut.y, lastPoint.y); lastPoint = pointOut; } @@ -306,13 +303,12 @@ TEST(AsyncPanZoomController, OverScrollPanning) { int time = 0; int touchStart = 500; int touchEnd = 10; - TestAPZCContainerLayer layer; ScreenPoint pointOut; ViewTransform viewTransformOut; // Pan down ApzcPan(apzc, time, touchStart, touchEnd); - apzc->SampleContentTransformForFrame(testStartTime+TimeDuration::FromMilliseconds(1000), &layer, &viewTransformOut, pointOut); + apzc->SampleContentTransformForFrame(testStartTime+TimeDuration::FromMilliseconds(1000), &viewTransformOut, pointOut); EXPECT_EQ(pointOut, ScreenPoint(0, 90)); } From 288b98292eedbac586c76e425a13a773b57e94a7 Mon Sep 17 00:00:00 2001 From: Kartikaya Gupta Date: Tue, 30 Jul 2013 14:03:41 -0400 Subject: [PATCH 26/36] Bug 866232 - Add visible region tracking and hit-testing code for APZCTreeManager. r=BenWa, mattwoodrow --- gfx/layers/composite/APZCTreeManager.cpp | 47 ++- gfx/layers/composite/APZCTreeManager.h | 3 +- gfx/layers/ipc/AsyncPanZoomController.cpp | 49 ---- gfx/layers/ipc/AsyncPanZoomController.h | 28 +- .../gtest/TestAsyncPanZoomController.cpp | 276 +++++++++--------- 5 files changed, 201 insertions(+), 202 deletions(-) diff --git a/gfx/layers/composite/APZCTreeManager.cpp b/gfx/layers/composite/APZCTreeManager.cpp index a85f204be8e..32845502580 100644 --- a/gfx/layers/composite/APZCTreeManager.cpp +++ b/gfx/layers/composite/APZCTreeManager.cpp @@ -4,8 +4,13 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #include "APZCTreeManager.h" +#include "AsyncCompositionManager.h" // for ViewTransform +#include "LayerManagerComposite.h" // for AsyncCompositionManager.h #include "Compositor.h" +#define APZC_LOG(args...) +// #define APZC_LOG(args...) printf_stderr(args) + namespace mozilla { namespace layers { @@ -60,6 +65,7 @@ APZCTreeManager::UpdatePanZoomControllerTree(CompositorParent* aCompositor, Laye } for (int i = apzcsToDestroy.Length() - 1; i >= 0; i--) { + APZC_LOG("Destroying APZC at %p\n", apzcsToDestroy[i].get()); apzcsToDestroy[i]->Destroy(); } } @@ -97,10 +103,19 @@ APZCTreeManager::UpdatePanZoomControllerTree(CompositorParent* aCompositor, controller->SetPrevSibling(nullptr); controller->SetLastChild(nullptr); } + APZC_LOG("Using APZC %p for layer %p with identifiers %lld %lld\n", controller, aLayer, aLayersId, container->GetFrameMetrics().mScrollId); controller->NotifyLayersUpdated(container->GetFrameMetrics(), aIsFirstPaint && (aLayersId == aFirstPaintLayersId)); + gfx3DMatrix transform = container->GetEffectiveTransform(); + LayerRect visible = container->GetFrameMetrics().mViewport * container->GetFrameMetrics().LayersPixelsPerCSSPixel(); + gfxRect transformed = transform.TransformBounds(gfxRect(visible.x, visible.y, visible.width, visible.height)); + controller->SetVisibleRegion(transformed); + APZC_LOG("Setting rect(%f %f %f %f) as visible region for %p\n", transformed.x, transformed.y, + transformed.width, transformed.height, + controller); + // Bind the APZC instance into the tree of APZCs if (aNextSibling) { aNextSibling->SetPrevSibling(controller); @@ -311,9 +326,16 @@ already_AddRefed APZCTreeManager::GetTargetAPZC(const ScreenPoint& aPoint) { MonitorAutoLock lock(mTreeLock); - // TODO: Do a hit test on the tree of - // APZC instances and return the right one. - return nullptr; + nsRefPtr target; + // The root may have siblings, so check those too + gfxPoint point(aPoint.x, aPoint.y); + for (AsyncPanZoomController* apzc = mRootApzc; apzc; apzc = apzc->GetPrevSibling()) { + target = GetAPZCAtPoint(apzc, point); + if (target) { + break; + } + } + return target.forget(); } AsyncPanZoomController* @@ -333,5 +355,24 @@ APZCTreeManager::FindTargetAPZC(AsyncPanZoomController* aApzc, const ScrollableL return nullptr; } +AsyncPanZoomController* +APZCTreeManager::GetAPZCAtPoint(AsyncPanZoomController* aApzc, gfxPoint aHitTestPoint) +{ + // This walks the tree in depth-first, reverse order, so that it encounters + // APZCs front-to-back on the screen. + ViewTransform apzcTransform = aApzc->GetCurrentAsyncTransform(); + gfxPoint untransformed = gfx3DMatrix(apzcTransform).Inverse().ProjectPoint(aHitTestPoint); + for (AsyncPanZoomController* child = aApzc->GetLastChild(); child; child = child->GetPrevSibling()) { + AsyncPanZoomController* match = GetAPZCAtPoint(child, untransformed); + if (match) { + return match; + } + } + if (aApzc->VisibleRegionContains(untransformed)) { + return aApzc; + } + return nullptr; +} + } } diff --git a/gfx/layers/composite/APZCTreeManager.h b/gfx/layers/composite/APZCTreeManager.h index 278b9ddc54c..32540ee1b87 100644 --- a/gfx/layers/composite/APZCTreeManager.h +++ b/gfx/layers/composite/APZCTreeManager.h @@ -228,8 +228,9 @@ private: */ already_AddRefed GetTargetAPZC(const ScrollableLayerGuid& aGuid); already_AddRefed GetTargetAPZC(const ScreenPoint& aPoint); - /* Recursive helper */ + /* Recursive helpers */ AsyncPanZoomController* FindTargetAPZC(AsyncPanZoomController* aApzc, const ScrollableLayerGuid& aGuid); + AsyncPanZoomController* GetAPZCAtPoint(AsyncPanZoomController* aApzc, gfxPoint aHitTestPoint); /** * Recursive helper function to build the APZC tree. The tree of APZC instances has diff --git a/gfx/layers/ipc/AsyncPanZoomController.cpp b/gfx/layers/ipc/AsyncPanZoomController.cpp index cfa3280be20..a28e1cc60c6 100644 --- a/gfx/layers/ipc/AsyncPanZoomController.cpp +++ b/gfx/layers/ipc/AsyncPanZoomController.cpp @@ -1465,55 +1465,6 @@ void AsyncPanZoomController::SendAsyncScrollEvent() { controller->SendAsyncScrollDOMEvent(contentRect, scrollableSize); } -static void GetAPZCAtPointOnSubtree(const ContainerLayer& aLayerIn, - const gfxPoint& aPoint, - AsyncPanZoomController** aApzcOut, - LayerIntPoint* aRelativePointOut) -{ - // Making layers const correct is very slow because it requires - // a near clobber of the tree. Once const correct is further along - // remove this cast. - ContainerLayer& aLayer = const_cast(aLayerIn); - gfx3DMatrix transform = aLayer.GetLocalTransform().Inverse(); - gfxPoint layerPoint = transform.Transform(aPoint); - - // iterate over the children first. They are better match then the parent - Layer* currLayer = aLayer.GetLastChild(); - while (currLayer) { - if (currLayer->AsContainerLayer()) { - GetAPZCAtPointOnSubtree(*currLayer->AsContainerLayer(), layerPoint, aApzcOut, aRelativePointOut); - } - if (*aApzcOut) { - return; - } - currLayer = currLayer->GetPrevSibling(); - } - - if (aLayer.GetFrameMetrics().IsScrollable()) { - const FrameMetrics& frame = aLayer.GetFrameMetrics(); - LayerRect layerViewport = frame.mViewport * frame.LayersPixelsPerCSSPixel(); - bool intersect = layerViewport.Contains(layerPoint.x, layerPoint.y); - - if (intersect) { - *aApzcOut = aLayer.GetAsyncPanZoomController(); - *aRelativePointOut = LayerIntPoint(NS_lround(layerPoint.x), NS_lround(layerPoint.y)); - } - } - -} - -void AsyncPanZoomController::GetAPZCAtPoint(const ContainerLayer& aLayerTree, - const ScreenIntPoint& aPoint, - AsyncPanZoomController** aApzcOut, - LayerIntPoint* aRelativePointOut) -{ - *aApzcOut = nullptr; - - gfxPoint point(aPoint.x, aPoint.y); - - GetAPZCAtPointOnSubtree(aLayerTree, point, aApzcOut, aRelativePointOut); -} - void AsyncPanZoomController::UpdateScrollOffset(const CSSPoint& aScrollOffset) { MonitorAutoLock monitor(mMonitor); diff --git a/gfx/layers/ipc/AsyncPanZoomController.h b/gfx/layers/ipc/AsyncPanZoomController.h index 02b25bbce8e..183e6643511 100644 --- a/gfx/layers/ipc/AsyncPanZoomController.h +++ b/gfx/layers/ipc/AsyncPanZoomController.h @@ -271,17 +271,6 @@ public: */ static void SetFrameTime(const TimeStamp& aMilliseconds); - /** - * Transform and intersect aPoint with the layer tree returning the appropriate - * AsyncPanZoomController for this point. - * aRelativePointOut Return the point transformed into the layer coordinates - * relative to the scroll origin for this layer. - */ - static void GetAPZCAtPoint(const ContainerLayer& aLayerTree, - const ScreenIntPoint& aPoint, - AsyncPanZoomController** aApzcOut, - LayerIntPoint* aRelativePointOut); - /** * Update mFrameMetrics.mScrollOffset to the given offset. * This is necessary in cases where a scroll is not caused by user @@ -649,6 +638,23 @@ public: private: nsRefPtr mLastChild; nsRefPtr mPrevSibling; + + /* The functions and members in this section are used to maintain the + * area that this APZC instance is responsible for. This is used when + * hit-testing to see which APZC instance should handle touch events. + */ +public: + void SetVisibleRegion(gfxRect rect) { mVisibleRegion = rect; } + + bool VisibleRegionContains(const gfxPoint& aPoint) const { + return mVisibleRegion.Contains(aPoint.x, aPoint.y); + } + +private: + /* This is the viewport of the layer that this APZC corresponds to, but + * post-transform. In other words, it is in the coordinate space of its + * parent layer. */ + gfxRect mVisibleRegion; }; } diff --git a/gfx/tests/gtest/TestAsyncPanZoomController.cpp b/gfx/tests/gtest/TestAsyncPanZoomController.cpp index 50096af62e0..0451682822a 100644 --- a/gfx/tests/gtest/TestAsyncPanZoomController.cpp +++ b/gfx/tests/gtest/TestAsyncPanZoomController.cpp @@ -339,143 +339,143 @@ CreateTestLayerTree(nsRefPtr& aLayerManager, nsTArray > layers; - nsRefPtr lm; - nsRefPtr root = CreateTestLayerTree(lm, layers); - - TimeStamp testStartTime = TimeStamp::Now(); - AsyncPanZoomController::SetFrameTime(testStartTime); - - nsRefPtr mcc = new MockContentController(); - nsRefPtr apzcMain = new AsyncPanZoomController(mcc); - nsRefPtr apzcSub3 = new AsyncPanZoomController(mcc); - nsRefPtr apzcSub4 = new AsyncPanZoomController(mcc); - nsRefPtr apzcSub7 = new AsyncPanZoomController(mcc); - apzcMain->NotifyLayersUpdated(TestFrameMetrics(), true); - - nsIntRect layerBound; - ScreenIntPoint touchPoint(20, 20); - AsyncPanZoomController* apzcOut; - LayerIntPoint relativePointOut; - - FrameMetrics scrollable; - - // No APZC attached so hit testing will return no APZC at (20,20) - AsyncPanZoomController::GetAPZCAtPoint(*root->AsContainerLayer(), touchPoint, - &apzcOut, &relativePointOut); - - AsyncPanZoomController* nullAPZC = nullptr; - EXPECT_EQ(apzcOut, nullAPZC); - - // Now we have a root APZC that will match the page - scrollable.mScrollId = FrameMetrics::ROOT_SCROLL_ID; - layerBound = root->GetVisibleRegion().GetBounds(); - scrollable.mViewport = CSSRect(layerBound.x, layerBound.y, - layerBound.width, layerBound.height); - root->AsContainerLayer()->SetFrameMetrics(scrollable); - root->AsContainerLayer()->SetAsyncPanZoomController(apzcMain); - AsyncPanZoomController::GetAPZCAtPoint(*root->AsContainerLayer(), touchPoint, - &apzcOut, &relativePointOut); - EXPECT_EQ(apzcOut, apzcMain.get()); - EXPECT_EQ(LayerIntPoint(20, 20), relativePointOut); - - // Now we have a sub APZC with a better fit - scrollable.mScrollId = FrameMetrics::START_SCROLL_ID; - layerBound = layers[3]->GetVisibleRegion().GetBounds(); - scrollable.mViewport = CSSRect(layerBound.x, layerBound.y, - layerBound.width, layerBound.height); - layers[3]->AsContainerLayer()->SetFrameMetrics(scrollable); - layers[3]->AsContainerLayer()->SetAsyncPanZoomController(apzcSub3); - AsyncPanZoomController::GetAPZCAtPoint(*root->AsContainerLayer(), touchPoint, - &apzcOut, &relativePointOut); - EXPECT_EQ(apzcOut, apzcSub3.get()); - EXPECT_EQ(LayerIntPoint(20, 20), relativePointOut); - - // Now test hit testing when we have two scrollable layers - touchPoint = ScreenIntPoint(15,15); - AsyncPanZoomController::GetAPZCAtPoint(*root->AsContainerLayer(), touchPoint, - &apzcOut, &relativePointOut); - EXPECT_EQ(apzcOut, apzcSub3.get()); // We haven't bound apzcSub4 yet - scrollable.mScrollId++; - layerBound = layers[4]->GetVisibleRegion().GetBounds(); - scrollable.mViewport = CSSRect(layerBound.x, layerBound.y, - layerBound.width, layerBound.height); - layers[4]->AsContainerLayer()->SetFrameMetrics(scrollable); - layers[4]->AsContainerLayer()->SetAsyncPanZoomController(apzcSub4); - AsyncPanZoomController::GetAPZCAtPoint(*root->AsContainerLayer(), touchPoint, - &apzcOut, &relativePointOut); - EXPECT_EQ(apzcOut, apzcSub4.get()); - EXPECT_EQ(LayerIntPoint(15, 15), relativePointOut); - - // Hit test ouside the reach of apzc3/4 but inside apzcMain - touchPoint = ScreenIntPoint(90,90); - AsyncPanZoomController::GetAPZCAtPoint(*root->AsContainerLayer(), touchPoint, - &apzcOut, &relativePointOut); - EXPECT_EQ(apzcOut, apzcMain.get()); - EXPECT_EQ(LayerIntPoint(90, 90), relativePointOut); - - // Hit test ouside the reach of any layer - touchPoint = ScreenIntPoint(1000,10); - AsyncPanZoomController::GetAPZCAtPoint(*root->AsContainerLayer(), touchPoint, - &apzcOut, &relativePointOut); - EXPECT_EQ(apzcOut, nullAPZC); - touchPoint = ScreenIntPoint(-1000,10); - AsyncPanZoomController::GetAPZCAtPoint(*root->AsContainerLayer(), touchPoint, - &apzcOut, &relativePointOut); - EXPECT_EQ(apzcOut, nullAPZC); - - // Test layer transform - gfx3DMatrix transform; - transform.ScalePost(0.1, 0.1, 1); - root->SetBaseTransform(transform); - - touchPoint = ScreenIntPoint(50,50); // This point is now outside the root layer - AsyncPanZoomController::GetAPZCAtPoint(*root->AsContainerLayer(), touchPoint, - &apzcOut, &relativePointOut); - EXPECT_EQ(apzcOut, nullAPZC); - - touchPoint = ScreenIntPoint(2,2); - AsyncPanZoomController::GetAPZCAtPoint(*root->AsContainerLayer(), touchPoint, - &apzcOut, &relativePointOut); - EXPECT_EQ(apzcOut, apzcSub4.get()); - EXPECT_EQ(LayerIntPoint(20, 20), relativePointOut); - - // Scale layer[4] outside the range - layers[4]->SetBaseTransform(transform); - // layer 4 effective visible screenrect: (0.05, 0.05, 0.2, 0.2) - // Does not contain (2, 2) - AsyncPanZoomController::GetAPZCAtPoint(*root->AsContainerLayer(), touchPoint, - &apzcOut, &relativePointOut); - EXPECT_EQ(apzcOut, apzcSub3.get()); - EXPECT_EQ(LayerIntPoint(20, 20), relativePointOut); - - // Transformation chain to layer 7 - scrollable.mScrollId++; - layerBound = layers[7]->GetVisibleRegion().GetBounds(); - scrollable.mViewport = CSSRect(layerBound.x, layerBound.y, - layerBound.width, layerBound.height); - layers[7]->AsContainerLayer()->SetFrameMetrics(scrollable); - layers[7]->AsContainerLayer()->SetAsyncPanZoomController(apzcSub7); - - gfx3DMatrix translateTransform; - translateTransform.Translate(gfxPoint3D(10, 10, 0)); - layers[5]->SetBaseTransform(translateTransform); - - gfx3DMatrix translateTransform2; - translateTransform2.Translate(gfxPoint3D(-20, 0, 0)); - layers[6]->SetBaseTransform(translateTransform2); - - gfx3DMatrix translateTransform3; - translateTransform3.ScalePost(1,15,1); - layers[7]->SetBaseTransform(translateTransform3); - - touchPoint = ScreenIntPoint(1,45); - // layer 7 effective visible screenrect (0,16,4,60) but clipped by parent layers - AsyncPanZoomController::GetAPZCAtPoint(*root->AsContainerLayer(), touchPoint, - &apzcOut, &relativePointOut); - EXPECT_EQ(apzcOut, apzcSub7.get()); - EXPECT_EQ(LayerIntPoint(20, 29), relativePointOut); -} +//TEST(AsyncPanZoomController, GetAPZCAtPoint) { +// nsTArray > layers; +// nsRefPtr lm; +// nsRefPtr root = CreateTestLayerTree(lm, layers); +// +// TimeStamp testStartTime = TimeStamp::Now(); +// AsyncPanZoomController::SetFrameTime(testStartTime); +// +// nsRefPtr mcc = new MockContentController(); +// nsRefPtr apzcMain = new AsyncPanZoomController(mcc); +// nsRefPtr apzcSub3 = new AsyncPanZoomController(mcc); +// nsRefPtr apzcSub4 = new AsyncPanZoomController(mcc); +// nsRefPtr apzcSub7 = new AsyncPanZoomController(mcc); +// apzcMain->NotifyLayersUpdated(TestFrameMetrics(), true); +// +// nsIntRect layerBound; +// ScreenIntPoint touchPoint(20, 20); +// AsyncPanZoomController* apzcOut; +// LayerIntPoint relativePointOut; +// +// FrameMetrics scrollable; +// +// // No APZC attached so hit testing will return no APZC at (20,20) +// AsyncPanZoomController::GetAPZCAtPoint(*root->AsContainerLayer(), touchPoint, +// &apzcOut, &relativePointOut); +// +// AsyncPanZoomController* nullAPZC = nullptr; +// EXPECT_EQ(apzcOut, nullAPZC); +// +// // Now we have a root APZC that will match the page +// scrollable.mScrollId = FrameMetrics::ROOT_SCROLL_ID; +// layerBound = root->GetVisibleRegion().GetBounds(); +// scrollable.mViewport = CSSRect(layerBound.x, layerBound.y, +// layerBound.width, layerBound.height); +// root->AsContainerLayer()->SetFrameMetrics(scrollable); +// root->AsContainerLayer()->SetAsyncPanZoomController(apzcMain); +// AsyncPanZoomController::GetAPZCAtPoint(*root->AsContainerLayer(), touchPoint, +// &apzcOut, &relativePointOut); +// EXPECT_EQ(apzcOut, apzcMain.get()); +// EXPECT_EQ(LayerIntPoint(20, 20), relativePointOut); +// +// // Now we have a sub APZC with a better fit +// scrollable.mScrollId = FrameMetrics::START_SCROLL_ID; +// layerBound = layers[3]->GetVisibleRegion().GetBounds(); +// scrollable.mViewport = CSSRect(layerBound.x, layerBound.y, +// layerBound.width, layerBound.height); +// layers[3]->AsContainerLayer()->SetFrameMetrics(scrollable); +// layers[3]->AsContainerLayer()->SetAsyncPanZoomController(apzcSub3); +// AsyncPanZoomController::GetAPZCAtPoint(*root->AsContainerLayer(), touchPoint, +// &apzcOut, &relativePointOut); +// EXPECT_EQ(apzcOut, apzcSub3.get()); +// EXPECT_EQ(LayerIntPoint(20, 20), relativePointOut); +// +// // Now test hit testing when we have two scrollable layers +// touchPoint = ScreenIntPoint(15,15); +// AsyncPanZoomController::GetAPZCAtPoint(*root->AsContainerLayer(), touchPoint, +// &apzcOut, &relativePointOut); +// EXPECT_EQ(apzcOut, apzcSub3.get()); // We haven't bound apzcSub4 yet +// scrollable.mScrollId++; +// layerBound = layers[4]->GetVisibleRegion().GetBounds(); +// scrollable.mViewport = CSSRect(layerBound.x, layerBound.y, +// layerBound.width, layerBound.height); +// layers[4]->AsContainerLayer()->SetFrameMetrics(scrollable); +// layers[4]->AsContainerLayer()->SetAsyncPanZoomController(apzcSub4); +// AsyncPanZoomController::GetAPZCAtPoint(*root->AsContainerLayer(), touchPoint, +// &apzcOut, &relativePointOut); +// EXPECT_EQ(apzcOut, apzcSub4.get()); +// EXPECT_EQ(LayerIntPoint(15, 15), relativePointOut); +// +// // Hit test ouside the reach of apzc3/4 but inside apzcMain +// touchPoint = ScreenIntPoint(90,90); +// AsyncPanZoomController::GetAPZCAtPoint(*root->AsContainerLayer(), touchPoint, +// &apzcOut, &relativePointOut); +// EXPECT_EQ(apzcOut, apzcMain.get()); +// EXPECT_EQ(LayerIntPoint(90, 90), relativePointOut); +// +// // Hit test ouside the reach of any layer +// touchPoint = ScreenIntPoint(1000,10); +// AsyncPanZoomController::GetAPZCAtPoint(*root->AsContainerLayer(), touchPoint, +// &apzcOut, &relativePointOut); +// EXPECT_EQ(apzcOut, nullAPZC); +// touchPoint = ScreenIntPoint(-1000,10); +// AsyncPanZoomController::GetAPZCAtPoint(*root->AsContainerLayer(), touchPoint, +// &apzcOut, &relativePointOut); +// EXPECT_EQ(apzcOut, nullAPZC); +// +// // Test layer transform +// gfx3DMatrix transform; +// transform.ScalePost(0.1, 0.1, 1); +// root->SetBaseTransform(transform); +// +// touchPoint = ScreenIntPoint(50,50); // This point is now outside the root layer +// AsyncPanZoomController::GetAPZCAtPoint(*root->AsContainerLayer(), touchPoint, +// &apzcOut, &relativePointOut); +// EXPECT_EQ(apzcOut, nullAPZC); +// +// touchPoint = ScreenIntPoint(2,2); +// AsyncPanZoomController::GetAPZCAtPoint(*root->AsContainerLayer(), touchPoint, +// &apzcOut, &relativePointOut); +// EXPECT_EQ(apzcOut, apzcSub4.get()); +// EXPECT_EQ(LayerIntPoint(20, 20), relativePointOut); +// +// // Scale layer[4] outside the range +// layers[4]->SetBaseTransform(transform); +// // layer 4 effective visible screenrect: (0.05, 0.05, 0.2, 0.2) +// // Does not contain (2, 2) +// AsyncPanZoomController::GetAPZCAtPoint(*root->AsContainerLayer(), touchPoint, +// &apzcOut, &relativePointOut); +// EXPECT_EQ(apzcOut, apzcSub3.get()); +// EXPECT_EQ(LayerIntPoint(20, 20), relativePointOut); +// +// // Transformation chain to layer 7 +// scrollable.mScrollId++; +// layerBound = layers[7]->GetVisibleRegion().GetBounds(); +// scrollable.mViewport = CSSRect(layerBound.x, layerBound.y, +// layerBound.width, layerBound.height); +// layers[7]->AsContainerLayer()->SetFrameMetrics(scrollable); +// layers[7]->AsContainerLayer()->SetAsyncPanZoomController(apzcSub7); +// +// gfx3DMatrix translateTransform; +// translateTransform.Translate(gfxPoint3D(10, 10, 0)); +// layers[5]->SetBaseTransform(translateTransform); +// +// gfx3DMatrix translateTransform2; +// translateTransform2.Translate(gfxPoint3D(-20, 0, 0)); +// layers[6]->SetBaseTransform(translateTransform2); +// +// gfx3DMatrix translateTransform3; +// translateTransform3.ScalePost(1,15,1); +// layers[7]->SetBaseTransform(translateTransform3); +// +// touchPoint = ScreenIntPoint(1,45); +// // layer 7 effective visible screenrect (0,16,4,60) but clipped by parent layers +// AsyncPanZoomController::GetAPZCAtPoint(*root->AsContainerLayer(), touchPoint, +// &apzcOut, &relativePointOut); +// EXPECT_EQ(apzcOut, apzcSub7.get()); +// EXPECT_EQ(LayerIntPoint(20, 29), relativePointOut); +//} From c27169836eaf3c2271e501eab4af1fd5768d95ef Mon Sep 17 00:00:00 2001 From: Kartikaya Gupta Date: Tue, 30 Jul 2013 14:03:41 -0400 Subject: [PATCH 27/36] Bug 866232 - Update and re-enable the test for hit detection in the APZC tree. r=BenWa --- gfx/layers/composite/APZCTreeManager.cpp | 8 +- gfx/layers/composite/APZCTreeManager.h | 16 +- gfx/layers/ipc/CompositorParent.cpp | 14 + gfx/layers/ipc/CompositorParent.h | 11 + .../gtest/TestAsyncPanZoomController.cpp | 263 +++++++++--------- gfx/tests/gtest/TestLayers.cpp | 8 +- 6 files changed, 174 insertions(+), 146 deletions(-) diff --git a/gfx/layers/composite/APZCTreeManager.cpp b/gfx/layers/composite/APZCTreeManager.cpp index 32845502580..6d18f0b5a44 100644 --- a/gfx/layers/composite/APZCTreeManager.cpp +++ b/gfx/layers/composite/APZCTreeManager.cpp @@ -21,6 +21,12 @@ APZCTreeManager::APZCTreeManager() AsyncPanZoomController::InitializeGlobalState(); } +void +APZCTreeManager::AssertOnCompositorThread() +{ + Compositor::AssertOnCompositorThread(); +} + /* Flatten the tree of APZC instances into the given nsTArray */ static void Collect(AsyncPanZoomController* aApzc, nsTArray< nsRefPtr >* aCollection) @@ -36,7 +42,7 @@ void APZCTreeManager::UpdatePanZoomControllerTree(CompositorParent* aCompositor, Layer* aRoot, bool aIsFirstPaint, uint64_t aFirstPaintLayersId) { - Compositor::AssertOnCompositorThread(); + AssertOnCompositorThread(); MonitorAutoLock lock(mTreeLock); diff --git a/gfx/layers/composite/APZCTreeManager.h b/gfx/layers/composite/APZCTreeManager.h index 32540ee1b87..de8c55b4221 100644 --- a/gfx/layers/composite/APZCTreeManager.h +++ b/gfx/layers/composite/APZCTreeManager.h @@ -96,11 +96,12 @@ struct ScrollableLayerGuid { * Note that the ClearTree function MUST be called when this class is no longer needed; * see the method documentation for details. */ -class APZCTreeManager MOZ_FINAL { +class APZCTreeManager { NS_INLINE_DECL_THREADSAFE_REFCOUNTING(APZCTreeManager) public: APZCTreeManager(); + virtual ~APZCTreeManager() {} /** * Rebuild the APZC tree based on the layer update that just came up. Preserve @@ -220,14 +221,23 @@ public: */ void ClearTree(); -private: +protected: + /** + * Debug-build assertion that can be called to ensure code is running on the + * compositor thread. + */ + virtual void AssertOnCompositorThread(); + +public: /* Some helper functions to find an APZC given some identifying input. These functions lock the tree of APZCs while they find the right one, and then return an addref'd pointer to it. This allows caller code to just use the target APZC without worrying - about it going away. + about it going away. These are public for testing code and generally should not be + used by other production code. */ already_AddRefed GetTargetAPZC(const ScrollableLayerGuid& aGuid); already_AddRefed GetTargetAPZC(const ScreenPoint& aPoint); +private: /* Recursive helpers */ AsyncPanZoomController* FindTargetAPZC(AsyncPanZoomController* aApzc, const ScrollableLayerGuid& aGuid); AsyncPanZoomController* GetAPZCAtPoint(AsyncPanZoomController* aApzc, gfxPoint aHitTestPoint); diff --git a/gfx/layers/ipc/CompositorParent.cpp b/gfx/layers/ipc/CompositorParent.cpp index 04d5552f150..05a7eb207c9 100644 --- a/gfx/layers/ipc/CompositorParent.cpp +++ b/gfx/layers/ipc/CompositorParent.cpp @@ -746,6 +746,20 @@ UpdateControllerForLayersId(uint64_t aLayersId, already_AddRefed(aController); } +ScopedLayerTreeRegistration::ScopedLayerTreeRegistration(uint64_t aLayersId, + Layer* aRoot, + GeckoContentController* aController) + : mLayersId(aLayersId) +{ + sIndirectLayerTrees[aLayersId].mRoot = aRoot; + sIndirectLayerTrees[aLayersId].mController = aController; +} + +ScopedLayerTreeRegistration::~ScopedLayerTreeRegistration() +{ + sIndirectLayerTrees.erase(mLayersId); +} + /*static*/ void CompositorParent::SetControllerForLayerTree(uint64_t aLayersId, GeckoContentController* aController) diff --git a/gfx/layers/ipc/CompositorParent.h b/gfx/layers/ipc/CompositorParent.h index 4959f24dc5f..0522fbe4414 100644 --- a/gfx/layers/ipc/CompositorParent.h +++ b/gfx/layers/ipc/CompositorParent.h @@ -38,6 +38,17 @@ class LayerManagerComposite; class AsyncCompositionManager; struct TextureFactoryIdentifier; +struct ScopedLayerTreeRegistration +{ + ScopedLayerTreeRegistration(uint64_t aLayersId, + Layer* aRoot, + GeckoContentController* aController); + ~ScopedLayerTreeRegistration(); + +private: + uint64_t mLayersId; +}; + class CompositorParent : public PCompositorParent, public ShadowLayersManager { diff --git a/gfx/tests/gtest/TestAsyncPanZoomController.cpp b/gfx/tests/gtest/TestAsyncPanZoomController.cpp index 0451682822a..9fed66b0175 100644 --- a/gfx/tests/gtest/TestAsyncPanZoomController.cpp +++ b/gfx/tests/gtest/TestAsyncPanZoomController.cpp @@ -10,6 +10,8 @@ #include "mozilla/layers/AsyncPanZoomController.h" #include "mozilla/layers/LayerManagerComposite.h" #include "mozilla/layers/GeckoContentController.h" +#include "mozilla/layers/CompositorParent.h" +#include "mozilla/layers/APZCTreeManager.h" #include "Layers.h" #include "TestLayers.h" @@ -51,6 +53,11 @@ public: } }; +class TestAPZCTreeManager : public APZCTreeManager { +protected: + void AssertOnCompositorThread() MOZ_OVERRIDE { /* no-op */ } +}; + static FrameMetrics TestFrameMetrics() { FrameMetrics fm; @@ -339,143 +346,123 @@ CreateTestLayerTree(nsRefPtr& aLayerManager, nsTArray > layers; -// nsRefPtr lm; -// nsRefPtr root = CreateTestLayerTree(lm, layers); -// -// TimeStamp testStartTime = TimeStamp::Now(); -// AsyncPanZoomController::SetFrameTime(testStartTime); -// -// nsRefPtr mcc = new MockContentController(); -// nsRefPtr apzcMain = new AsyncPanZoomController(mcc); -// nsRefPtr apzcSub3 = new AsyncPanZoomController(mcc); -// nsRefPtr apzcSub4 = new AsyncPanZoomController(mcc); -// nsRefPtr apzcSub7 = new AsyncPanZoomController(mcc); -// apzcMain->NotifyLayersUpdated(TestFrameMetrics(), true); -// -// nsIntRect layerBound; -// ScreenIntPoint touchPoint(20, 20); -// AsyncPanZoomController* apzcOut; -// LayerIntPoint relativePointOut; -// -// FrameMetrics scrollable; -// -// // No APZC attached so hit testing will return no APZC at (20,20) -// AsyncPanZoomController::GetAPZCAtPoint(*root->AsContainerLayer(), touchPoint, -// &apzcOut, &relativePointOut); -// -// AsyncPanZoomController* nullAPZC = nullptr; -// EXPECT_EQ(apzcOut, nullAPZC); -// -// // Now we have a root APZC that will match the page -// scrollable.mScrollId = FrameMetrics::ROOT_SCROLL_ID; -// layerBound = root->GetVisibleRegion().GetBounds(); -// scrollable.mViewport = CSSRect(layerBound.x, layerBound.y, -// layerBound.width, layerBound.height); -// root->AsContainerLayer()->SetFrameMetrics(scrollable); -// root->AsContainerLayer()->SetAsyncPanZoomController(apzcMain); -// AsyncPanZoomController::GetAPZCAtPoint(*root->AsContainerLayer(), touchPoint, -// &apzcOut, &relativePointOut); -// EXPECT_EQ(apzcOut, apzcMain.get()); -// EXPECT_EQ(LayerIntPoint(20, 20), relativePointOut); -// -// // Now we have a sub APZC with a better fit -// scrollable.mScrollId = FrameMetrics::START_SCROLL_ID; -// layerBound = layers[3]->GetVisibleRegion().GetBounds(); -// scrollable.mViewport = CSSRect(layerBound.x, layerBound.y, -// layerBound.width, layerBound.height); -// layers[3]->AsContainerLayer()->SetFrameMetrics(scrollable); -// layers[3]->AsContainerLayer()->SetAsyncPanZoomController(apzcSub3); -// AsyncPanZoomController::GetAPZCAtPoint(*root->AsContainerLayer(), touchPoint, -// &apzcOut, &relativePointOut); -// EXPECT_EQ(apzcOut, apzcSub3.get()); -// EXPECT_EQ(LayerIntPoint(20, 20), relativePointOut); -// -// // Now test hit testing when we have two scrollable layers -// touchPoint = ScreenIntPoint(15,15); -// AsyncPanZoomController::GetAPZCAtPoint(*root->AsContainerLayer(), touchPoint, -// &apzcOut, &relativePointOut); -// EXPECT_EQ(apzcOut, apzcSub3.get()); // We haven't bound apzcSub4 yet -// scrollable.mScrollId++; -// layerBound = layers[4]->GetVisibleRegion().GetBounds(); -// scrollable.mViewport = CSSRect(layerBound.x, layerBound.y, -// layerBound.width, layerBound.height); -// layers[4]->AsContainerLayer()->SetFrameMetrics(scrollable); -// layers[4]->AsContainerLayer()->SetAsyncPanZoomController(apzcSub4); -// AsyncPanZoomController::GetAPZCAtPoint(*root->AsContainerLayer(), touchPoint, -// &apzcOut, &relativePointOut); -// EXPECT_EQ(apzcOut, apzcSub4.get()); -// EXPECT_EQ(LayerIntPoint(15, 15), relativePointOut); -// -// // Hit test ouside the reach of apzc3/4 but inside apzcMain -// touchPoint = ScreenIntPoint(90,90); -// AsyncPanZoomController::GetAPZCAtPoint(*root->AsContainerLayer(), touchPoint, -// &apzcOut, &relativePointOut); -// EXPECT_EQ(apzcOut, apzcMain.get()); -// EXPECT_EQ(LayerIntPoint(90, 90), relativePointOut); -// -// // Hit test ouside the reach of any layer -// touchPoint = ScreenIntPoint(1000,10); -// AsyncPanZoomController::GetAPZCAtPoint(*root->AsContainerLayer(), touchPoint, -// &apzcOut, &relativePointOut); -// EXPECT_EQ(apzcOut, nullAPZC); -// touchPoint = ScreenIntPoint(-1000,10); -// AsyncPanZoomController::GetAPZCAtPoint(*root->AsContainerLayer(), touchPoint, -// &apzcOut, &relativePointOut); -// EXPECT_EQ(apzcOut, nullAPZC); -// -// // Test layer transform -// gfx3DMatrix transform; -// transform.ScalePost(0.1, 0.1, 1); -// root->SetBaseTransform(transform); -// -// touchPoint = ScreenIntPoint(50,50); // This point is now outside the root layer -// AsyncPanZoomController::GetAPZCAtPoint(*root->AsContainerLayer(), touchPoint, -// &apzcOut, &relativePointOut); -// EXPECT_EQ(apzcOut, nullAPZC); -// -// touchPoint = ScreenIntPoint(2,2); -// AsyncPanZoomController::GetAPZCAtPoint(*root->AsContainerLayer(), touchPoint, -// &apzcOut, &relativePointOut); -// EXPECT_EQ(apzcOut, apzcSub4.get()); -// EXPECT_EQ(LayerIntPoint(20, 20), relativePointOut); -// -// // Scale layer[4] outside the range -// layers[4]->SetBaseTransform(transform); -// // layer 4 effective visible screenrect: (0.05, 0.05, 0.2, 0.2) -// // Does not contain (2, 2) -// AsyncPanZoomController::GetAPZCAtPoint(*root->AsContainerLayer(), touchPoint, -// &apzcOut, &relativePointOut); -// EXPECT_EQ(apzcOut, apzcSub3.get()); -// EXPECT_EQ(LayerIntPoint(20, 20), relativePointOut); -// -// // Transformation chain to layer 7 -// scrollable.mScrollId++; -// layerBound = layers[7]->GetVisibleRegion().GetBounds(); -// scrollable.mViewport = CSSRect(layerBound.x, layerBound.y, -// layerBound.width, layerBound.height); -// layers[7]->AsContainerLayer()->SetFrameMetrics(scrollable); -// layers[7]->AsContainerLayer()->SetAsyncPanZoomController(apzcSub7); -// -// gfx3DMatrix translateTransform; -// translateTransform.Translate(gfxPoint3D(10, 10, 0)); -// layers[5]->SetBaseTransform(translateTransform); -// -// gfx3DMatrix translateTransform2; -// translateTransform2.Translate(gfxPoint3D(-20, 0, 0)); -// layers[6]->SetBaseTransform(translateTransform2); -// -// gfx3DMatrix translateTransform3; -// translateTransform3.ScalePost(1,15,1); -// layers[7]->SetBaseTransform(translateTransform3); -// -// touchPoint = ScreenIntPoint(1,45); -// // layer 7 effective visible screenrect (0,16,4,60) but clipped by parent layers -// AsyncPanZoomController::GetAPZCAtPoint(*root->AsContainerLayer(), touchPoint, -// &apzcOut, &relativePointOut); -// EXPECT_EQ(apzcOut, apzcSub7.get()); -// EXPECT_EQ(LayerIntPoint(20, 29), relativePointOut); -//} +static void +SetScrollableFrameMetrics(Layer* aLayer, FrameMetrics::ViewID aScrollId, MockContentController* mcc) +{ + ContainerLayer* container = aLayer->AsContainerLayer(); + FrameMetrics metrics; + metrics.mScrollId = aScrollId; + nsIntRect layerBound = aLayer->GetVisibleRegion().GetBounds(); + metrics.mCompositionBounds = ScreenIntRect(layerBound.x, layerBound.y, + layerBound.width, layerBound.height); + metrics.mViewport = CSSRect(layerBound.x, layerBound.y, + layerBound.width, layerBound.height); + container->SetFrameMetrics(metrics); + + // when we do the next tree update, a new APZC will be created for this layer, + // and that will invoke these functions once. + EXPECT_CALL(*mcc, SendAsyncScrollDOMEvent(_,_)).Times(1); + EXPECT_CALL(*mcc, RequestContentRepaint(_)).Times(1); +} + +TEST(APZCTreeManager, GetAPZCAtPoint) { + nsTArray > layers; + nsRefPtr lm; + nsRefPtr root = CreateTestLayerTree(lm, layers); + + TimeStamp testStartTime = TimeStamp::Now(); + AsyncPanZoomController::SetFrameTime(testStartTime); + nsRefPtr mcc = new MockContentController(); + ScopedLayerTreeRegistration controller(CompositorParent::ROOT_LAYER_TREE_ID, root, mcc); + + nsRefPtr manager = new TestAPZCTreeManager(); + + // No APZC attached so hit testing will return no APZC at (20,20) + nsRefPtr hit = manager->GetTargetAPZC(ScreenPoint(20, 20)); + AsyncPanZoomController* nullAPZC = nullptr; + EXPECT_EQ(nullAPZC, hit.get()); + + // Now we have a root APZC that will match the page + SetScrollableFrameMetrics(root, FrameMetrics::ROOT_SCROLL_ID, mcc); + manager->UpdatePanZoomControllerTree(nullptr, root, CompositorParent::ROOT_LAYER_TREE_ID, false); + hit = manager->GetTargetAPZC(ScreenPoint(15, 15)); + EXPECT_EQ(root->AsContainerLayer()->GetAsyncPanZoomController(), hit.get()); + // expect hit point at LayerIntPoint(15, 15) + + // Now we have a sub APZC with a better fit + SetScrollableFrameMetrics(layers[3], FrameMetrics::START_SCROLL_ID, mcc); + manager->UpdatePanZoomControllerTree(nullptr, root, CompositorParent::ROOT_LAYER_TREE_ID, false); + EXPECT_NE(root->AsContainerLayer()->GetAsyncPanZoomController(), layers[3]->AsContainerLayer()->GetAsyncPanZoomController()); + hit = manager->GetTargetAPZC(ScreenPoint(15, 15)); + EXPECT_EQ(layers[3]->AsContainerLayer()->GetAsyncPanZoomController(), hit.get()); + // expect hit point at LayerIntPoint(15, 15) + + // Now test hit testing when we have two scrollable layers + hit = manager->GetTargetAPZC(ScreenPoint(15, 15)); + EXPECT_EQ(layers[3]->AsContainerLayer()->GetAsyncPanZoomController(), hit.get()); + SetScrollableFrameMetrics(layers[4], FrameMetrics::START_SCROLL_ID + 1, mcc); + manager->UpdatePanZoomControllerTree(nullptr, root, CompositorParent::ROOT_LAYER_TREE_ID, false); + hit = manager->GetTargetAPZC(ScreenPoint(15, 15)); + EXPECT_EQ(layers[4]->AsContainerLayer()->GetAsyncPanZoomController(), hit.get()); + // expect hit point at LayerIntPoint(15, 15) + + // Hit test ouside the reach of layer[3,4] but inside root + hit = manager->GetTargetAPZC(ScreenPoint(90, 90)); + EXPECT_EQ(root->AsContainerLayer()->GetAsyncPanZoomController(), hit.get()); + // expect hit point at LayerIntPoint(90, 90) + + // Hit test ouside the reach of any layer + hit = manager->GetTargetAPZC(ScreenPoint(1000, 10)); + EXPECT_EQ(nullAPZC, hit.get()); + hit = manager->GetTargetAPZC(ScreenPoint(-1000, 10)); + EXPECT_EQ(nullAPZC, hit.get()); + + // Test layer transform + gfx3DMatrix transform; + transform.ScalePost(0.1, 0.1, 1); + root->SetBaseTransform(transform); + root->ComputeEffectiveTransforms(gfx3DMatrix()); + manager->UpdatePanZoomControllerTree(nullptr, root, CompositorParent::ROOT_LAYER_TREE_ID, false); + hit = manager->GetTargetAPZC(ScreenPoint(50, 50)); // This point is now outside the root layer + EXPECT_EQ(nullAPZC, hit.get()); + + hit = manager->GetTargetAPZC(ScreenPoint(2, 2)); + EXPECT_EQ(layers[3]->AsContainerLayer()->GetAsyncPanZoomController(), hit.get()); + // expect hit point at LayerPoint(20, 20) + + // Scale layer[4] outside the range + layers[4]->SetBaseTransform(transform); + // layer 4 effective visible screenrect: (0.05, 0.05, 0.2, 0.2) + // Does not contain (2, 2) + root->ComputeEffectiveTransforms(gfx3DMatrix()); + manager->UpdatePanZoomControllerTree(nullptr, root, CompositorParent::ROOT_LAYER_TREE_ID, false); + hit = manager->GetTargetAPZC(ScreenPoint(2, 2)); + EXPECT_EQ(layers[3]->AsContainerLayer()->GetAsyncPanZoomController(), hit.get()); + // expect hit point at LayerPoint(20, 20) + + // Transformation chain to layer 7 + SetScrollableFrameMetrics(layers[7], FrameMetrics::START_SCROLL_ID + 2, mcc); + + gfx3DMatrix translateTransform; + translateTransform.Translate(gfxPoint3D(10, 10, 0)); + layers[5]->SetBaseTransform(translateTransform); + + gfx3DMatrix translateTransform2; + translateTransform2.Translate(gfxPoint3D(-20, 0, 0)); + layers[6]->SetBaseTransform(translateTransform2); + + gfx3DMatrix translateTransform3; + translateTransform3.ScalePost(1,15,1); + layers[7]->SetBaseTransform(translateTransform3); + + root->ComputeEffectiveTransforms(gfx3DMatrix()); + manager->UpdatePanZoomControllerTree(nullptr, root, CompositorParent::ROOT_LAYER_TREE_ID, false); + // layer 7 effective visible screenrect (0,16,4,60) but clipped by parent layers + hit = manager->GetTargetAPZC(ScreenPoint(1, 45)); + EXPECT_EQ(layers[7]->AsContainerLayer()->GetAsyncPanZoomController(), hit.get()); + // expect hit point at LayerPoint(20, 29) + + manager->ClearTree(); +} diff --git a/gfx/tests/gtest/TestLayers.cpp b/gfx/tests/gtest/TestLayers.cpp index bd1c5cb327c..c1364f06935 100644 --- a/gfx/tests/gtest/TestLayers.cpp +++ b/gfx/tests/gtest/TestLayers.cpp @@ -48,6 +48,7 @@ public: } virtual void ComputeEffectiveTransforms(const gfx3DMatrix& aTransformToSurface) { + DefaultComputeEffectiveTransforms(aTransformToSurface); } virtual void RepositionChild(Layer* aChild, Layer* aAfter) { @@ -92,10 +93,6 @@ public: return TYPE_THEBES; } - virtual void ComputeEffectiveTransforms(const gfx3DMatrix& aTransformToSurface) { - MOZ_CRASH(); - } - virtual void InvalidateRegion(const nsIntRegion& aRegion) { MOZ_CRASH(); } @@ -236,6 +233,9 @@ already_AddRefed CreateLayerTree( lastLayer = layer; } } + if (rootLayer) { + rootLayer->ComputeEffectiveTransforms(gfx3DMatrix()); + } return rootLayer.forget(); } From 80fc21967b439c15ffac3e0dc1891dc2bf1ef825 Mon Sep 17 00:00:00 2001 From: Kartikaya Gupta Date: Tue, 30 Jul 2013 14:03:42 -0400 Subject: [PATCH 28/36] Bug 866232 - Update TabChild to better handle scrolling subframes. r=BenWa, mattwoodrow --- dom/ipc/TabChild.cpp | 119 ++++++++++++++++++++-------------- dom/ipc/TabChild.h | 9 +-- layout/base/nsLayoutUtils.cpp | 17 +++++ layout/base/nsLayoutUtils.h | 5 ++ 4 files changed, 99 insertions(+), 51 deletions(-) diff --git a/dom/ipc/TabChild.cpp b/dom/ipc/TabChild.cpp index 4359b386004..2a658ba4fe7 100644 --- a/dom/ipc/TabChild.cpp +++ b/dom/ipc/TabChild.cpp @@ -1032,6 +1032,20 @@ TabChild::GetDOMWindowUtils() return utils.forget(); } +already_AddRefed +TabChild::GetDOMWindowUtils(nsIContent* content) +{ + nsCOMPtr utils; + nsIDocument* doc = content->GetCurrentDoc(); + if (doc) { + nsCOMPtr window = doc->GetDefaultView(); + if (window) { + utils = do_GetInterface(window); + } + } + return utils.forget(); +} + static nsInterfaceHashtable, nsIDialogParamBlock> gActiveDialogs; NS_IMETHODIMP @@ -1459,32 +1473,34 @@ TabChild::DispatchMessageManagerMessage(const nsAString& aMessageName, aMessageName, false, &cloneData, nullptr, nullptr); } -static void -ScrollWindowTo(nsIDOMWindow* aWindow, const CSSPoint& aPoint) -{ - nsGlobalWindow* window = static_cast(aWindow); - nsIScrollableFrame* sf = window->GetScrollFrame(); - - if (sf) { - sf->ScrollToCSSPixelsApproximate(aPoint); - } -} - bool TabChild::RecvUpdateFrame(const FrameMetrics& aFrameMetrics) { - nsCOMPtr utils(GetDOMWindowUtils()); + MOZ_ASSERT(aFrameMetrics.mScrollId != FrameMetrics::NULL_SCROLL_ID); + if (aFrameMetrics.mScrollId == FrameMetrics::ROOT_SCROLL_ID) { uint32_t presShellId; + nsCOMPtr utils(GetDOMWindowUtils()); nsresult rv = utils->GetPresShellId(&presShellId); MOZ_ASSERT(NS_SUCCEEDED(rv)); - if (NS_SUCCEEDED(rv) && aFrameMetrics.mPresShellId != presShellId) { - // We've recieved a message that is out of date and we want to ignore. - // However we can't reply without painting so we reply by painting the - // exact same thing as we did before. - return ProcessUpdateFrame(mLastMetrics); + + if (NS_SUCCEEDED(rv) && aFrameMetrics.mPresShellId == presShellId) { + return ProcessUpdateFrame(aFrameMetrics); } - return ProcessUpdateFrame(aFrameMetrics); + } else { + // aFrameMetrics.mScrollId is not FrameMetrics::ROOT_SCROLL_ID, + // so we are trying to update a subframe. This requires special handling. + nsCOMPtr content = nsLayoutUtils::FindContentFor( + aFrameMetrics.mScrollId); + if (content) { + return ProcessUpdateSubframe(content, aFrameMetrics); + } + } + + // We've recieved a message that is out of date and we want to ignore. + // However we can't reply without painting so we reply by painting the + // exact same thing as we did before. + return ProcessUpdateFrame(mLastMetrics); } bool @@ -1533,51 +1549,60 @@ TabChild::ProcessUpdateFrame(const FrameMetrics& aFrameMetrics) nsCOMPtr utils(GetDOMWindowUtils()); nsCOMPtr window = do_GetInterface(mWebNav); + // set the scroll port size, which determines the scroll range utils->SetScrollPositionClampingScrollPortSize( cssCompositedRect.width, cssCompositedRect.height); - ScrollWindowTo(window, aFrameMetrics.mScrollOffset); - LayoutDeviceToLayerScale resolution = - aFrameMetrics.CalculateResolution() - / aFrameMetrics.mDevPixelsPerCSSPixel - * ScreenToLayerScale(1); + + // scroll the window to the desired spot + nsIScrollableFrame* sf = static_cast(window.get())->GetScrollFrame(); + if (sf) { + sf->ScrollToCSSPixelsApproximate(aFrameMetrics.mScrollOffset); + } + + // set the resolution + LayoutDeviceToLayerScale resolution = aFrameMetrics.CalculateResolution() + / aFrameMetrics.mDevPixelsPerCSSPixel * ScreenToLayerScale(1); utils->SetResolution(resolution.scale, resolution.scale); - if (aFrameMetrics.mScrollId != FrameMetrics::NULL_SCROLL_ID) { - SetDisplayPort(aFrameMetrics); + // and set the display port + nsCOMPtr domDoc; + mWebNav->GetDocument(getter_AddRefs(domDoc)); + if (domDoc) { + nsCOMPtr element; + domDoc->GetDocumentElement(getter_AddRefs(element)); + if (element) { + utils->SetDisplayPortForElement( + aFrameMetrics.mDisplayPort.x, aFrameMetrics.mDisplayPort.y, + aFrameMetrics.mDisplayPort.width, aFrameMetrics.mDisplayPort.height, + element); + } } mLastMetrics = aFrameMetrics; - return true; } -void -TabChild::SetDisplayPort(const FrameMetrics& aFrameMetrics) +bool +TabChild::ProcessUpdateSubframe(nsIContent* aContent, + const FrameMetrics& aMetrics) { - nsCOMPtr domDoc; - mWebNav->GetDocument(getter_AddRefs(domDoc)); - if (!domDoc) { - return; + // scroll the frame to the desired spot + nsIScrollableFrame* scrollFrame = nsLayoutUtils::FindScrollableFrameFor(aMetrics.mScrollId); + if (scrollFrame) { + scrollFrame->ScrollToCSSPixelsApproximate(aMetrics.mScrollOffset); } - // nsLayoutUtils::FindContentFor() doesn't provide a look-up for the root - // scroll idea. This is because the root scroll ID could refer to a different - // element in the DOM when navigating to a new document. - nsCOMPtr element; - if (aFrameMetrics.mScrollId == FrameMetrics::ROOT_SCROLL_ID) { - domDoc->GetDocumentElement(getter_AddRefs(element)); - } else { - element = do_QueryInterface(nsLayoutUtils::FindContentFor( - aFrameMetrics.mScrollId)); - } - - if (element) { - nsCOMPtr utils(GetDOMWindowUtils()); + nsCOMPtr utils(GetDOMWindowUtils(aContent)); + nsCOMPtr element = do_QueryInterface(aContent); + if (utils && element) { + // and set the display port utils->SetDisplayPortForElement( - aFrameMetrics.mDisplayPort.x, aFrameMetrics.mDisplayPort.y, - aFrameMetrics.mDisplayPort.width, aFrameMetrics.mDisplayPort.height, + aMetrics.mDisplayPort.x, aMetrics.mDisplayPort.y, + aMetrics.mDisplayPort.width, aMetrics.mDisplayPort.height, element); } + + return true; } bool diff --git a/dom/ipc/TabChild.h b/dom/ipc/TabChild.h index eca8af55bb7..e982da01546 100644 --- a/dom/ipc/TabChild.h +++ b/dom/ipc/TabChild.h @@ -378,10 +378,7 @@ private: void DestroyWindow(); void SetProcessNameToAppName(); bool ProcessUpdateFrame(const mozilla::layers::FrameMetrics& aFrameMetrics); - - // Update the DOM with the given display port. Finds the element based on - // the aFrameMetrics.mScrollId. - void SetDisplayPort(const FrameMetrics& aFrameMetrics); + bool ProcessUpdateSubframe(nsIContent* aContent, const FrameMetrics& aMetrics); // Call RecvShow(nsIntSize(0, 0)) and block future calls to RecvShow(). void DoFakeShow(); @@ -426,7 +423,11 @@ private: bool* aWindowIsNew, nsIDOMWindow** aReturn); + // Get the DOMWindowUtils for the top-level window in this tab. already_AddRefed GetDOMWindowUtils(); + // Get the DOMWindowUtils for the window corresponding to the givent content + // element. This might be an iframe inside the tab, for instance. + already_AddRefed GetDOMWindowUtils(nsIContent* aContent); class CachedFileDescriptorInfo; class CachedFileDescriptorCallbackRunnable; diff --git a/layout/base/nsLayoutUtils.cpp b/layout/base/nsLayoutUtils.cpp index 8162ea3da6e..63cfd3a4319 100644 --- a/layout/base/nsLayoutUtils.cpp +++ b/layout/base/nsLayoutUtils.cpp @@ -469,6 +469,23 @@ nsLayoutUtils::FindContentFor(ViewID aId) } } +nsIScrollableFrame* +nsLayoutUtils::FindScrollableFrameFor(ViewID aId) +{ + nsIContent* content = FindContentFor(aId); + if (!content) { + return nullptr; + } + + nsIFrame* scrolledFrame = content->GetPrimaryFrame(); + if (scrolledFrame && content->OwnerDoc()->GetRootElement() == content) { + // The content is the root element of a subdocument, so return the root scrollable + // for the subdocument. + scrolledFrame = scrolledFrame->PresContext()->PresShell()->GetRootScrollFrame(); + } + return scrolledFrame ? scrolledFrame->GetScrollTargetFrame() : nullptr; +} + bool nsLayoutUtils::GetDisplayPort(nsIContent* aContent, nsRect *aResult) { diff --git a/layout/base/nsLayoutUtils.h b/layout/base/nsLayoutUtils.h index 263292c2e92..c5fab518119 100644 --- a/layout/base/nsLayoutUtils.h +++ b/layout/base/nsLayoutUtils.h @@ -76,6 +76,11 @@ public: */ static nsIContent* FindContentFor(ViewID aId); + /** + * Find the scrollable frame for a given ID. + */ + static nsIScrollableFrame* FindScrollableFrameFor(ViewID aId); + /** * Get display port for the given element. */ From 221f9754272ebf6f78f5e2faf4396ccb86bfcfee Mon Sep 17 00:00:00 2001 From: Kartikaya Gupta Date: Tue, 30 Jul 2013 14:03:42 -0400 Subject: [PATCH 29/36] Bug 866232 - Disable BrowserElementPanning.js from panning subframes and interfering with multi-apzc. r=BenWa, vingtetun --- dom/browser-element/BrowserElementPanning.js | 23 ++++++++++++-------- 1 file changed, 14 insertions(+), 9 deletions(-) diff --git a/dom/browser-element/BrowserElementPanning.js b/dom/browser-element/BrowserElementPanning.js index abe8ced256b..cf7cf7e371d 100644 --- a/dom/browser-element/BrowserElementPanning.js +++ b/dom/browser-element/BrowserElementPanning.js @@ -45,16 +45,21 @@ const ContentPanning = { this.watchedEventsType = 'mouse'; } - let els = Cc["@mozilla.org/eventlistenerservice;1"] - .getService(Ci.nsIEventListenerService); + // If we are using an AsyncPanZoomController for the parent frame, + // it will handle subframe scrolling too. We don't need to listen for + // these events. + if (!this._asyncPanZoomForViewportFrame) { + let els = Cc["@mozilla.org/eventlistenerservice;1"] + .getService(Ci.nsIEventListenerService); - events.forEach(function(type) { - // Using the system group for mouse/touch events to avoid - // missing events if .stopPropagation() has been called. - els.addSystemEventListener(global, type, - this.handleEvent.bind(this), - /* useCapture = */ false); - }.bind(this)); + events.forEach(function(type) { + // Using the system group for mouse/touch events to avoid + // missing events if .stopPropagation() has been called. + els.addSystemEventListener(global, type, + this.handleEvent.bind(this), + /* useCapture = */ false); + }.bind(this)); + } addMessageListener("Viewport:Change", this._recvViewportChange.bind(this)); addMessageListener("Gesture:DoubleTap", this._recvDoubleTap.bind(this)); From 0ab038a3d20a9af809161ec58a39a681c3718460 Mon Sep 17 00:00:00 2001 From: Kartikaya Gupta Date: Tue, 30 Jul 2013 14:03:42 -0400 Subject: [PATCH 30/36] Bug 866232 - Only fire mozbrowserasyncscroll events on the top-level scrollable for backwards compatibility. r=BenWa --- gfx/layers/ipc/AsyncPanZoomController.cpp | 5 ++++- gfx/layers/ipc/GeckoContentController.h | 3 ++- gfx/tests/gtest/TestAsyncPanZoomController.cpp | 10 +++++----- layout/ipc/RenderFrameParent.cpp | 7 ++++--- widget/android/AndroidBridge.cpp | 4 +++- widget/android/AndroidBridge.h | 4 +++- 6 files changed, 21 insertions(+), 12 deletions(-) diff --git a/gfx/layers/ipc/AsyncPanZoomController.cpp b/gfx/layers/ipc/AsyncPanZoomController.cpp index a28e1cc60c6..80037626ab6 100644 --- a/gfx/layers/ipc/AsyncPanZoomController.cpp +++ b/gfx/layers/ipc/AsyncPanZoomController.cpp @@ -1454,15 +1454,18 @@ void AsyncPanZoomController::SendAsyncScrollEvent() { return; } + FrameMetrics::ViewID scrollId; CSSRect contentRect; CSSSize scrollableSize; { + // XXX bug 890932 - there should be a lock here. but it causes a deadlock. + scrollId = mFrameMetrics.mScrollId; scrollableSize = mFrameMetrics.mScrollableRect.Size(); contentRect = mFrameMetrics.CalculateCompositedRectInCssPixels(); contentRect.MoveTo(mCurrentAsyncScrollOffset); } - controller->SendAsyncScrollDOMEvent(contentRect, scrollableSize); + controller->SendAsyncScrollDOMEvent(scrollId, contentRect, scrollableSize); } void AsyncPanZoomController::UpdateScrollOffset(const CSSPoint& aScrollOffset) diff --git a/gfx/layers/ipc/GeckoContentController.h b/gfx/layers/ipc/GeckoContentController.h index eeaa97919ad..718a83c9bca 100644 --- a/gfx/layers/ipc/GeckoContentController.h +++ b/gfx/layers/ipc/GeckoContentController.h @@ -51,7 +51,8 @@ public: * |aContentRect| is in CSS pixels, relative to the current cssPage. * |aScrollableSize| is the current content width/height in CSS pixels. */ - virtual void SendAsyncScrollDOMEvent(const CSSRect &aContentRect, + virtual void SendAsyncScrollDOMEvent(FrameMetrics::ViewID aScrollId, + const CSSRect &aContentRect, const CSSSize &aScrollableSize) = 0; /** diff --git a/gfx/tests/gtest/TestAsyncPanZoomController.cpp b/gfx/tests/gtest/TestAsyncPanZoomController.cpp index 9fed66b0175..f8283bb0f24 100644 --- a/gfx/tests/gtest/TestAsyncPanZoomController.cpp +++ b/gfx/tests/gtest/TestAsyncPanZoomController.cpp @@ -26,7 +26,7 @@ public: MOCK_METHOD1(HandleDoubleTap, void(const CSSIntPoint&)); MOCK_METHOD1(HandleSingleTap, void(const CSSIntPoint&)); MOCK_METHOD1(HandleLongTap, void(const CSSIntPoint&)); - MOCK_METHOD2(SendAsyncScrollDOMEvent, void(const CSSRect &aContentRect, const CSSSize &aScrollableSize)); + MOCK_METHOD3(SendAsyncScrollDOMEvent, void(FrameMetrics::ViewID aScrollId, const CSSRect &aContentRect, const CSSSize &aScrollableSize)); MOCK_METHOD2(PostDelayedTask, void(Task* aTask, int aDelayMs)); }; @@ -242,7 +242,7 @@ TEST(AsyncPanZoomController, Pan) { apzc->SetFrameMetrics(TestFrameMetrics()); apzc->NotifyLayersUpdated(TestFrameMetrics(), true); - EXPECT_CALL(*mcc, SendAsyncScrollDOMEvent(_,_)).Times(4); + EXPECT_CALL(*mcc, SendAsyncScrollDOMEvent(_,_,_)).Times(4); EXPECT_CALL(*mcc, RequestContentRepaint(_)).Times(1); int time = 0; @@ -274,7 +274,7 @@ TEST(AsyncPanZoomController, Fling) { apzc->SetFrameMetrics(TestFrameMetrics()); apzc->NotifyLayersUpdated(TestFrameMetrics(), true); - EXPECT_CALL(*mcc, SendAsyncScrollDOMEvent(_,_)).Times(2); + EXPECT_CALL(*mcc, SendAsyncScrollDOMEvent(_,_,_)).Times(2); EXPECT_CALL(*mcc, RequestContentRepaint(_)).Times(1); int time = 0; @@ -303,7 +303,7 @@ TEST(AsyncPanZoomController, OverScrollPanning) { apzc->SetFrameMetrics(TestFrameMetrics()); apzc->NotifyLayersUpdated(TestFrameMetrics(), true); - EXPECT_CALL(*mcc, SendAsyncScrollDOMEvent(_,_)).Times(3); + EXPECT_CALL(*mcc, SendAsyncScrollDOMEvent(_,_,_)).Times(3); EXPECT_CALL(*mcc, RequestContentRepaint(_)).Times(1); // Pan sufficiently to hit overscroll behavior @@ -361,7 +361,7 @@ SetScrollableFrameMetrics(Layer* aLayer, FrameMetrics::ViewID aScrollId, MockCon // when we do the next tree update, a new APZC will be created for this layer, // and that will invoke these functions once. - EXPECT_CALL(*mcc, SendAsyncScrollDOMEvent(_,_)).Times(1); + EXPECT_CALL(*mcc, SendAsyncScrollDOMEvent(_,_,_)).Times(1); EXPECT_CALL(*mcc, RequestContentRepaint(_)).Times(1); } diff --git a/layout/ipc/RenderFrameParent.cpp b/layout/ipc/RenderFrameParent.cpp index 96ed70df203..b44eaa286cd 100644 --- a/layout/ipc/RenderFrameParent.cpp +++ b/layout/ipc/RenderFrameParent.cpp @@ -552,7 +552,8 @@ public: void ClearRenderFrame() { mRenderFrame = nullptr; } - virtual void SendAsyncScrollDOMEvent(const CSSRect& aContentRect, + virtual void SendAsyncScrollDOMEvent(FrameMetrics::ViewID aScrollId, + const CSSRect& aContentRect, const CSSSize& aContentSize) MOZ_OVERRIDE { if (MessageLoop::current() != mUILoop) { @@ -560,10 +561,10 @@ public: FROM_HERE, NewRunnableMethod(this, &RemoteContentController::SendAsyncScrollDOMEvent, - aContentRect, aContentSize)); + aScrollId, aContentRect, aContentSize)); return; } - if (mRenderFrame) { + if (mRenderFrame && aScrollId == FrameMetrics::ROOT_SCROLL_ID) { TabParent* browser = static_cast(mRenderFrame->Manager()); BrowserElementParent::DispatchAsyncScrollEvent(browser, aContentRect, aContentSize); diff --git a/widget/android/AndroidBridge.cpp b/widget/android/AndroidBridge.cpp index c530b8c3195..35bda9e9f29 100644 --- a/widget/android/AndroidBridge.cpp +++ b/widget/android/AndroidBridge.cpp @@ -2850,7 +2850,9 @@ AndroidBridge::HandleLongTap(const CSSIntPoint& aPoint) } void -AndroidBridge::SendAsyncScrollDOMEvent(const CSSRect& aContentRect, const CSSSize& aScrollableSize) +AndroidBridge::SendAsyncScrollDOMEvent(mozilla::layers::FrameMetrics::ViewID aScrollId, + const CSSRect& aContentRect, + const CSSSize& aScrollableSize) { // FIXME implement this } diff --git a/widget/android/AndroidBridge.h b/widget/android/AndroidBridge.h index b200cd04d63..25e931ce296 100644 --- a/widget/android/AndroidBridge.h +++ b/widget/android/AndroidBridge.h @@ -601,7 +601,9 @@ public: void HandleDoubleTap(const CSSIntPoint& aPoint) MOZ_OVERRIDE; void HandleSingleTap(const CSSIntPoint& aPoint) MOZ_OVERRIDE; void HandleLongTap(const CSSIntPoint& aPoint) MOZ_OVERRIDE; - void SendAsyncScrollDOMEvent(const CSSRect& aContentRect, const CSSSize& aScrollableSize) MOZ_OVERRIDE; + void SendAsyncScrollDOMEvent(mozilla::layers::FrameMetrics::ViewID aScrollId, + const CSSRect& aContentRect, + const CSSSize& aScrollableSize) MOZ_OVERRIDE; void PostDelayedTask(Task* aTask, int aDelayMs) MOZ_OVERRIDE; int64_t RunDelayedTasks(); }; From 40271aeb0cb6d524727f01662aee21a23850ca94 Mon Sep 17 00:00:00 2001 From: Kartikaya Gupta Date: Tue, 30 Jul 2013 14:03:43 -0400 Subject: [PATCH 31/36] Bug 866232 - Break assumption of a single global root layer tree. r=BenWa, mattwoodrow --- gfx/layers/composite/APZCTreeManager.cpp | 4 +++- gfx/layers/ipc/CompositorParent.cpp | 22 +++++++++++------- gfx/layers/ipc/CompositorParent.h | 12 ++++++---- .../gtest/TestAsyncPanZoomController.cpp | 14 +++++------ widget/android/AndroidJNI.cpp | 15 ++++++------ widget/android/nsWindow.cpp | 23 +++++++++++++++++++ widget/android/nsWindow.h | 4 ++++ 7 files changed, 65 insertions(+), 29 deletions(-) diff --git a/gfx/layers/composite/APZCTreeManager.cpp b/gfx/layers/composite/APZCTreeManager.cpp index 6d18f0b5a44..5e31c4e6b16 100644 --- a/gfx/layers/composite/APZCTreeManager.cpp +++ b/gfx/layers/composite/APZCTreeManager.cpp @@ -64,7 +64,9 @@ APZCTreeManager::UpdatePanZoomControllerTree(CompositorParent* aCompositor, Laye if (aRoot) { UpdatePanZoomControllerTree(aCompositor, - aRoot, CompositorParent::ROOT_LAYER_TREE_ID, + aRoot, + // aCompositor is null in gtest scenarios + aCompositor ? aCompositor->RootLayerTreeId() : 0, nullptr, nullptr, aIsFirstPaint, aFirstPaintLayersId, &apzcsToDestroy); diff --git a/gfx/layers/ipc/CompositorParent.cpp b/gfx/layers/ipc/CompositorParent.cpp index 05a7eb207c9..c3ce7bfb5fb 100644 --- a/gfx/layers/ipc/CompositorParent.cpp +++ b/gfx/layers/ipc/CompositorParent.cpp @@ -154,6 +154,9 @@ CompositorParent::CompositorParent(nsIWidget* aWidget, CompositorLoop()->PostTask(FROM_HERE, NewRunnableFunction(&AddCompositor, this, &mCompositorID)); + mRootLayerTreeID = AllocateLayerTreeId(); + sIndirectLayerTrees[mRootLayerTreeID].mParent = this; + mApzcTreeManager = new APZCTreeManager(); ++sCompositorThreadRefCount; } @@ -170,11 +173,16 @@ CompositorParent::IsInCompositorThread() return CompositorThreadID() == PlatformThread::CurrentId(); } +uint64_t +CompositorParent::RootLayerTreeId() +{ + return mRootLayerTreeID; +} + CompositorParent::~CompositorParent() { MOZ_COUNT_DTOR(CompositorParent); - mApzcTreeManager->ClearTree(); ReleaseCompositorThread(); } @@ -187,6 +195,9 @@ CompositorParent::Destroy() // Ensure that the layer manager is destructed on the compositor thread. mLayerManager = nullptr; mCompositionManager = nullptr; + mApzcTreeManager->ClearTree(); + mApzcTreeManager = nullptr; + sIndirectLayerTrees.erase(mRootLayerTreeID); } void @@ -568,7 +579,7 @@ CompositorParent::ShadowLayersUpdated(LayerTransactionParent* aLayerTree, if (mApzcTreeManager) { AutoResolveRefLayers resolve(mCompositionManager); - mApzcTreeManager->UpdatePanZoomControllerTree(this, root, isFirstPaint, ROOT_LAYER_TREE_ID); + mApzcTreeManager->UpdatePanZoomControllerTree(this, root, isFirstPaint, mRootLayerTreeID); } if (root) { @@ -709,17 +720,12 @@ CompositorParent::NotifyChildCreated(uint64_t aChild) sIndirectLayerTrees[aChild].mParent = this; } -// Ensure all layer tree IDs are greater than zero, so if we -// ever see a zero-valued layer tree id we know it's actually -// uninitialized and/or garbage. -uint64_t CompositorParent::ROOT_LAYER_TREE_ID = 1; - /*static*/ uint64_t CompositorParent::AllocateLayerTreeId() { MOZ_ASSERT(CompositorLoop()); MOZ_ASSERT(NS_IsMainThread()); - static uint64_t ids = ROOT_LAYER_TREE_ID; + static uint64_t ids = 0; return ++ids; } diff --git a/gfx/layers/ipc/CompositorParent.h b/gfx/layers/ipc/CompositorParent.h index 0522fbe4414..392687f4276 100644 --- a/gfx/layers/ipc/CompositorParent.h +++ b/gfx/layers/ipc/CompositorParent.h @@ -103,6 +103,12 @@ public: virtual void ScheduleComposition(); void NotifyShadowTreeTransaction(uint64_t aId, bool aIsFirstPaint); + /** + * Returns the unique layer tree identifier that corresponds to the root + * tree of this compositor. + */ + uint64_t RootLayerTreeId(); + /** * Returns a pointer to the compositor corresponding to the given ID. */ @@ -125,11 +131,6 @@ public: */ static void ShutDown(); - /** - * The reserved layer tree ID for the root of the layer tree. - */ - static uint64_t ROOT_LAYER_TREE_ID; - /** * Allocate an ID that can be used to refer to a layer tree and * associated resources that live only on the compositor thread. @@ -287,6 +288,7 @@ private: mozilla::Monitor mResumeCompositionMonitor; uint64_t mCompositorID; + uint64_t mRootLayerTreeID; bool mOverrideComposeReadiness; CancelableTask* mForceCompositionTask; diff --git a/gfx/tests/gtest/TestAsyncPanZoomController.cpp b/gfx/tests/gtest/TestAsyncPanZoomController.cpp index f8283bb0f24..885a79e5ee4 100644 --- a/gfx/tests/gtest/TestAsyncPanZoomController.cpp +++ b/gfx/tests/gtest/TestAsyncPanZoomController.cpp @@ -373,7 +373,7 @@ TEST(APZCTreeManager, GetAPZCAtPoint) { TimeStamp testStartTime = TimeStamp::Now(); AsyncPanZoomController::SetFrameTime(testStartTime); nsRefPtr mcc = new MockContentController(); - ScopedLayerTreeRegistration controller(CompositorParent::ROOT_LAYER_TREE_ID, root, mcc); + ScopedLayerTreeRegistration controller(0, root, mcc); nsRefPtr manager = new TestAPZCTreeManager(); @@ -384,14 +384,14 @@ TEST(APZCTreeManager, GetAPZCAtPoint) { // Now we have a root APZC that will match the page SetScrollableFrameMetrics(root, FrameMetrics::ROOT_SCROLL_ID, mcc); - manager->UpdatePanZoomControllerTree(nullptr, root, CompositorParent::ROOT_LAYER_TREE_ID, false); + manager->UpdatePanZoomControllerTree(nullptr, root, 0, false); hit = manager->GetTargetAPZC(ScreenPoint(15, 15)); EXPECT_EQ(root->AsContainerLayer()->GetAsyncPanZoomController(), hit.get()); // expect hit point at LayerIntPoint(15, 15) // Now we have a sub APZC with a better fit SetScrollableFrameMetrics(layers[3], FrameMetrics::START_SCROLL_ID, mcc); - manager->UpdatePanZoomControllerTree(nullptr, root, CompositorParent::ROOT_LAYER_TREE_ID, false); + manager->UpdatePanZoomControllerTree(nullptr, root, 0, false); EXPECT_NE(root->AsContainerLayer()->GetAsyncPanZoomController(), layers[3]->AsContainerLayer()->GetAsyncPanZoomController()); hit = manager->GetTargetAPZC(ScreenPoint(15, 15)); EXPECT_EQ(layers[3]->AsContainerLayer()->GetAsyncPanZoomController(), hit.get()); @@ -401,7 +401,7 @@ TEST(APZCTreeManager, GetAPZCAtPoint) { hit = manager->GetTargetAPZC(ScreenPoint(15, 15)); EXPECT_EQ(layers[3]->AsContainerLayer()->GetAsyncPanZoomController(), hit.get()); SetScrollableFrameMetrics(layers[4], FrameMetrics::START_SCROLL_ID + 1, mcc); - manager->UpdatePanZoomControllerTree(nullptr, root, CompositorParent::ROOT_LAYER_TREE_ID, false); + manager->UpdatePanZoomControllerTree(nullptr, root, 0, false); hit = manager->GetTargetAPZC(ScreenPoint(15, 15)); EXPECT_EQ(layers[4]->AsContainerLayer()->GetAsyncPanZoomController(), hit.get()); // expect hit point at LayerIntPoint(15, 15) @@ -422,7 +422,7 @@ TEST(APZCTreeManager, GetAPZCAtPoint) { transform.ScalePost(0.1, 0.1, 1); root->SetBaseTransform(transform); root->ComputeEffectiveTransforms(gfx3DMatrix()); - manager->UpdatePanZoomControllerTree(nullptr, root, CompositorParent::ROOT_LAYER_TREE_ID, false); + manager->UpdatePanZoomControllerTree(nullptr, root, 0, false); hit = manager->GetTargetAPZC(ScreenPoint(50, 50)); // This point is now outside the root layer EXPECT_EQ(nullAPZC, hit.get()); @@ -435,7 +435,7 @@ TEST(APZCTreeManager, GetAPZCAtPoint) { // layer 4 effective visible screenrect: (0.05, 0.05, 0.2, 0.2) // Does not contain (2, 2) root->ComputeEffectiveTransforms(gfx3DMatrix()); - manager->UpdatePanZoomControllerTree(nullptr, root, CompositorParent::ROOT_LAYER_TREE_ID, false); + manager->UpdatePanZoomControllerTree(nullptr, root, 0, false); hit = manager->GetTargetAPZC(ScreenPoint(2, 2)); EXPECT_EQ(layers[3]->AsContainerLayer()->GetAsyncPanZoomController(), hit.get()); // expect hit point at LayerPoint(20, 20) @@ -456,7 +456,7 @@ TEST(APZCTreeManager, GetAPZCAtPoint) { layers[7]->SetBaseTransform(translateTransform3); root->ComputeEffectiveTransforms(gfx3DMatrix()); - manager->UpdatePanZoomControllerTree(nullptr, root, CompositorParent::ROOT_LAYER_TREE_ID, false); + manager->UpdatePanZoomControllerTree(nullptr, root, 0, false); // layer 7 effective visible screenrect (0,16,4,60) but clipped by parent layers hit = manager->GetTargetAPZC(ScreenPoint(1, 45)); EXPECT_EQ(layers[7]->AsContainerLayer()->GetAsyncPanZoomController(), hit.get()); diff --git a/widget/android/AndroidJNI.cpp b/widget/android/AndroidJNI.cpp index 737f441896b..e7a5c91f412 100644 --- a/widget/android/AndroidJNI.cpp +++ b/widget/android/AndroidJNI.cpp @@ -847,9 +847,9 @@ Java_org_mozilla_gecko_GeckoJavaSampler_getProfilerTime(JNIEnv *jenv, jclass jc) NS_EXPORT void JNICALL Java_org_mozilla_gecko_gfx_NativePanZoomController_abortAnimation(JNIEnv* env, jobject instance) { - APZCTreeManager *controller = CompositorParent::GetAPZCTreeManager(CompositorParent::ROOT_LAYER_TREE_ID); + APZCTreeManager *controller = nsWindow::GetAPZCTreeManager(); if (controller) { - controller->CancelAnimation(ScrollableLayerGuid(CompositorParent::ROOT_LAYER_TREE_ID)); + controller->CancelAnimation(ScrollableLayerGuid(nsWindow::RootLayerTreeId())); } } @@ -865,13 +865,12 @@ Java_org_mozilla_gecko_gfx_NativePanZoomController_init(JNIEnv* env, jobject ins MOZ_ASSERT(false, "Registering a new NPZC when we already have one"); env->DeleteGlobalRef(oldRef); } - CompositorParent::SetControllerForLayerTree(CompositorParent::ROOT_LAYER_TREE_ID, AndroidBridge::Bridge()); } NS_EXPORT void JNICALL Java_org_mozilla_gecko_gfx_NativePanZoomController_handleTouchEvent(JNIEnv* env, jobject instance, jobject event) { - APZCTreeManager *controller = CompositorParent::GetAPZCTreeManager(CompositorParent::ROOT_LAYER_TREE_ID); + APZCTreeManager *controller = nsWindow::GetAPZCTreeManager(); if (controller) { AndroidGeckoEvent* wrapper = AndroidGeckoEvent::MakeFromJavaObject(env, event); const MultiTouchInput& input = wrapper->MakeMultiTouchInput(nsWindow::TopWindow()); @@ -916,9 +915,9 @@ Java_org_mozilla_gecko_gfx_NativePanZoomController_destroy(JNIEnv* env, jobject NS_EXPORT void JNICALL Java_org_mozilla_gecko_gfx_NativePanZoomController_notifyDefaultActionPrevented(JNIEnv* env, jobject instance, jboolean prevented) { - APZCTreeManager *controller = CompositorParent::GetAPZCTreeManager(CompositorParent::ROOT_LAYER_TREE_ID); + APZCTreeManager *controller = nsWindow::GetAPZCTreeManager(); if (controller) { - controller->ContentReceivedTouch(ScrollableLayerGuid(CompositorParent::ROOT_LAYER_TREE_ID), prevented); + controller->ContentReceivedTouch(ScrollableLayerGuid(nsWindow::RootLayerTreeId()), prevented); } } @@ -945,9 +944,9 @@ Java_org_mozilla_gecko_gfx_NativePanZoomController_getOverScrollMode(JNIEnv* env NS_EXPORT void JNICALL Java_org_mozilla_gecko_gfx_NativePanZoomController_updateScrollOffset(JNIEnv* env, jobject instance, jfloat cssX, jfloat cssY) { - APZCTreeManager *controller = CompositorParent::GetAPZCTreeManager(CompositorParent::ROOT_LAYER_TREE_ID); + APZCTreeManager *controller = nsWindow::GetAPZCTreeManager(); if (controller) { - controller->UpdateScrollOffset(ScrollableLayerGuid(CompositorParent::ROOT_LAYER_TREE_ID), CSSPoint(cssX, cssY)); + controller->UpdateScrollOffset(ScrollableLayerGuid(nsWindow::RootLayerTreeId()), CSSPoint(cssX, cssY)); } } diff --git a/widget/android/nsWindow.cpp b/widget/android/nsWindow.cpp index 4b97f75d49a..4a688296d35 100644 --- a/widget/android/nsWindow.cpp +++ b/widget/android/nsWindow.cpp @@ -2417,6 +2417,7 @@ nsWindow::DrawWindowOverlay(LayerManager* aManager, nsIntRect aRect) // off-main-thread compositor fields and functions +nsRefPtr nsWindow::sApzcTreeManager = 0; nsRefPtr nsWindow::sLayerManager = 0; nsRefPtr nsWindow::sCompositorParent = 0; nsRefPtr nsWindow::sCompositorChild = 0; @@ -2500,3 +2501,25 @@ nsWindow::NewCompositorParent(int aSurfaceWidth, int aSurfaceHeight) { return new CompositorParent(this, true, aSurfaceWidth, aSurfaceHeight); } + +mozilla::layers::APZCTreeManager* +nsWindow::GetAPZCTreeManager() +{ + if (!sApzcTreeManager) { + CompositorParent* compositor = sCompositorParent; + if (!compositor) { + return nullptr; + } + uint64_t rootLayerTreeId = compositor->RootLayerTreeId(); + CompositorParent::SetControllerForLayerTree(rootLayerTreeId, AndroidBridge::Bridge()); + sApzcTreeManager = CompositorParent::GetAPZCTreeManager(rootLayerTreeId); + } + return sApzcTreeManager; +} + +uint64_t +nsWindow::RootLayerTreeId() +{ + MOZ_ASSERT(sCompositorParent); + return sCompositorParent->RootLayerTreeId(); +} diff --git a/widget/android/nsWindow.h b/widget/android/nsWindow.h index cf444372bb7..bce79a77299 100644 --- a/widget/android/nsWindow.h +++ b/widget/android/nsWindow.h @@ -155,6 +155,9 @@ public: static void ScheduleResumeComposition(int width, int height); static void ForceIsFirstPaint(); static float ComputeRenderIntegrity(); + static mozilla::layers::APZCTreeManager* GetAPZCTreeManager(); + /* RootLayerTreeId() can only be called when GetAPZCTreeManager() returns non-null */ + static uint64_t RootLayerTreeId(); virtual bool WidgetPaintsBackground(); @@ -229,6 +232,7 @@ private: mozilla::AndroidLayerRendererFrame mLayerRendererFrame; + static nsRefPtr sApzcTreeManager; static nsRefPtr sLayerManager; static nsRefPtr sCompositorParent; static nsRefPtr sCompositorChild; From d334e608dad110beb9d63e5ef8358225932286d3 Mon Sep 17 00:00:00 2001 From: Kartikaya Gupta Date: Tue, 30 Jul 2013 14:03:43 -0400 Subject: [PATCH 32/36] Bug 866232 - Update the Windows Metro code to handle APZCTreeManager. r=BenWa, bbondy --- widget/windows/winrt/MetroWidget.cpp | 28 ++++------------------------ widget/windows/winrt/MetroWidget.h | 6 +++--- 2 files changed, 7 insertions(+), 27 deletions(-) diff --git a/widget/windows/winrt/MetroWidget.cpp b/widget/windows/winrt/MetroWidget.cpp index db362f58f4c..bd6dabf4e7d 100644 --- a/widget/windows/winrt/MetroWidget.cpp +++ b/widget/windows/winrt/MetroWidget.cpp @@ -140,7 +140,7 @@ namespace { NS_IMPL_ISUPPORTS_INHERITED0(MetroWidget, nsBaseWidget) -nsRefPtr MetroWidget::sAPZC; +nsRefPtr MetroWidget::sAPZC; MetroWidget::MetroWidget() : mTransparencyMode(eTransparencyOpaque), @@ -166,7 +166,6 @@ MetroWidget::~MetroWidget() // Global shutdown if (!gInstanceCount) { - MetroWidget::sAPZC->Destroy(); MetroWidget::sAPZC = nullptr; nsTextStore::Terminate(); } // !gInstanceCount @@ -813,22 +812,8 @@ public: observerService->AddObserver(this, "viewport-needs-updating", false); } - if (MetroWidget::sAPZC) { - MetroWidget::sAPZC->SetCompositorParent(this); - } - } - - virtual void ShadowLayersUpdated(LayerTransactionParent* aLayerTree, const TargetConfig& aTargetConfig, - bool isFirstPaint) MOZ_OVERRIDE - { - CompositorParent::ShadowLayersUpdated(aLayerTree, aTargetConfig, isFirstPaint); - Layer* targetLayer = GetLayerManager()->GetPrimaryScrollableLayer(); - if (targetLayer && targetLayer->AsContainerLayer() && MetroWidget::sAPZC && - targetLayer->AsContainerLayer()->GetFrameMetrics().IsScrollable()) { - targetLayer->AsContainerLayer()->SetAsyncPanZoomController(MetroWidget::sAPZC); - MetroWidget::sAPZC->NotifyLayersUpdated(targetLayer->AsContainerLayer()->GetFrameMetrics(), - isFirstPaint); - } + CompositorParent::SetControllerForLayerTree(RootLayerTreeId(), aMetroWidget); + MetroWidget::sAPZC = CompositorParent::GetAPZCTreeManager(RootLayerTreeId()); } NS_IMETHODIMP Observe(nsISupports *subject, const char *topic, const PRUnichar *data) @@ -846,7 +831,6 @@ public: mozilla::gfx::Point(0.0f, 0.0f), mozilla::gfx::Point(0.0f, 0.0f), 0.0); - MetroWidget::sAPZC->NotifyLayersUpdated(frameMetrics, true); mMetroWidget->RequestContentRepaint(frameMetrics); } } @@ -910,10 +894,6 @@ MetroWidget::GetLayerManager(PLayerTransactionChild* aShadowManager, if (ShouldUseOffMainThreadCompositing()) { NS_ASSERTION(aShadowManager == nullptr, "Async Compositor not supported with e10s"); CreateCompositor(); - if (ShouldUseAPZC()) { - sAPZC = new AsyncPanZoomController(this, AsyncPanZoomController::USE_GESTURE_DETECTOR); - sAPZC->SetCompositorParent(mCompositorParent); - } } else if (ShouldUseMainThreadD3D10Manager()) { nsRefPtr layerManager = new mozilla::layers::LayerManagerD3D10(this); @@ -1457,7 +1437,7 @@ MetroWidget::HandleLongTap(const CSSIntPoint& aPoint) } void -MetroWidget::SendAsyncScrollDOMEvent(const CSSRect &aContentRect, const CSSSize &aScrollableSize) +MetroWidget::SendAsyncScrollDOMEvent(FrameMetrics::ViewID aScrollId, const CSSRect &aContentRect, const CSSSize &aScrollableSize) { LogFunction(); } diff --git a/widget/windows/winrt/MetroWidget.h b/widget/windows/winrt/MetroWidget.h index 163df024dc4..e008a05250c 100644 --- a/widget/windows/winrt/MetroWidget.h +++ b/widget/windows/winrt/MetroWidget.h @@ -23,7 +23,7 @@ #endif #include "mozilla/layers/CompositorParent.h" #include "mozilla/layers/GeckoContentController.h" -#include "mozilla/layers/AsyncPanZoomController.h" +#include "mozilla/layers/APZCTreeManager.h" #include "mozilla/layers/LayerManagerComposite.h" #include "Units.h" #include "MetroInput.h" @@ -191,7 +191,7 @@ public: virtual void HandleDoubleTap(const mozilla::CSSIntPoint& aPoint); virtual void HandleSingleTap(const mozilla::CSSIntPoint& aPoint); virtual void HandleLongTap(const mozilla::CSSIntPoint& aPoint); - virtual void SendAsyncScrollDOMEvent(const mozilla::CSSRect &aContentRect, const mozilla::CSSSize &aScrollableSize); + virtual void SendAsyncScrollDOMEvent(mozilla::layers::FrameMetrics::ViewID aScrollId, const mozilla::CSSRect &aContentRect, const mozilla::CSSSize &aScrollableSize); virtual void PostDelayedTask(Task* aTask, int aDelayMs); virtual void HandlePanBegin(); virtual void HandlePanEnd(); @@ -237,5 +237,5 @@ protected: mozilla::layers::FrameMetrics mFrameMetrics; public: - static nsRefPtr sAPZC; + static nsRefPtr sAPZC; }; From bf26e2b1dd6a8514ba69f9ada02edbfc5f0a00f7 Mon Sep 17 00:00:00 2001 From: Gaia Pushbot Date: Tue, 30 Jul 2013 11:40:24 -0700 Subject: [PATCH 33/36] Bumping gaia.json for 1 gaia-central revision(s) ======== https://hg.mozilla.org/integration/gaia-central/rev/775b20c42b52 Author: Julien Wajsberg Desc: Bug 890443 - [SMS] the "fixed header" style and transitions should be adjusted so that it's not jumping when changing header r=schung Important changes * changes how the fixed header is found. Now we're iterating starting with the top instead of the bottom. In the SMS app, the most common cases is when the list is not scrolled so much, and therefore starting at the top will likely be way faster once the list is long. * we don't position the header in the same loop, now we position the header depending on the next header, if it exists. * we use a specific hiding class instead of specifying the 100% transform translation in the js code. Also, using a 100% transform translation is used instead of display none, so that we can get some necessary measurements in the init method. Most notably, we need to take into account the view's padding top. Less important changes: * changed the desktop mock so that we have more headers when loading in Firefox * check that we have mozSetMessageHandler before using it so that we can launch the app in main Firefox * moved the first header's margin top to the view's padding top. This makes it easier to calculate the exact location to trigger the fixed header switch effect. --- 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 77bb45fff9b..13dad9eb958 100644 --- a/b2g/config/gaia.json +++ b/b2g/config/gaia.json @@ -1,4 +1,4 @@ { - "revision": "1e3fa6fe4ab933fd3ebea869679bbba7a11fa71f", + "revision": "775b20c42b5220f79af35fb94ad53925eb6b7aea", "repo_path": "/integration/gaia-central" } From f5ec94d1ab037f4db5754eaf44d91c736a3140e9 Mon Sep 17 00:00:00 2001 From: Gaia Pushbot Date: Tue, 30 Jul 2013 11:50:24 -0700 Subject: [PATCH 34/36] Bumping gaia.json for 1 gaia-central revision(s) ======== https://hg.mozilla.org/integration/gaia-central/rev/d2343a615807 Author: William Chen Desc: Bug 782211 - Update Gaia with additional functionality to support Notification API. --- 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 13dad9eb958..fe951761cb8 100644 --- a/b2g/config/gaia.json +++ b/b2g/config/gaia.json @@ -1,4 +1,4 @@ { - "revision": "775b20c42b5220f79af35fb94ad53925eb6b7aea", + "revision": "d2343a61580787083ca39707e97f43d0f25a300f", "repo_path": "/integration/gaia-central" } From 795301b9979ab490ab10f243f4c8007e5e6c5f94 Mon Sep 17 00:00:00 2001 From: Kartikaya Gupta Date: Tue, 30 Jul 2013 14:55:57 -0400 Subject: [PATCH 35/36] Bug 866232 - Fix build breakage introduced in f69d34718660. r=me --- gfx/layers/composite/APZCTreeManager.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gfx/layers/composite/APZCTreeManager.cpp b/gfx/layers/composite/APZCTreeManager.cpp index 5e31c4e6b16..d00d44a00c0 100644 --- a/gfx/layers/composite/APZCTreeManager.cpp +++ b/gfx/layers/composite/APZCTreeManager.cpp @@ -8,7 +8,7 @@ #include "LayerManagerComposite.h" // for AsyncCompositionManager.h #include "Compositor.h" -#define APZC_LOG(args...) +#define APZC_LOG(...) // #define APZC_LOG(args...) printf_stderr(args) namespace mozilla { From 90e46a99a84c8aa76b454e2be20f4d0b02c8d97e Mon Sep 17 00:00:00 2001 From: Gaia Pushbot Date: Tue, 30 Jul 2013 13:45:23 -0700 Subject: [PATCH 36/36] Bumping gaia.json for 1 gaia-central revision(s) ======== https://hg.mozilla.org/integration/gaia-central/rev/7e8284bea36c Author: Rick Waldron Desc: Bug 899003 - [Buri][Buri][SMS] Long press on number in message: menu includes "Call" option r=gnarf https://bugzilla.mozilla.org/show_bug.cgi?id=899003 Signed-off-by: Rick Waldron --- 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 fe951761cb8..01a9409af9c 100644 --- a/b2g/config/gaia.json +++ b/b2g/config/gaia.json @@ -1,4 +1,4 @@ { - "revision": "d2343a61580787083ca39707e97f43d0f25a300f", + "revision": "7e8284bea36c2d9307f919090922d3885f67eafc", "repo_path": "/integration/gaia-central" }