mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Merge m-c to inbound.
This commit is contained in:
commit
02d1dbe0d8
@ -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 \
|
||||
|
@ -1,4 +1,4 @@
|
||||
{
|
||||
"revision": "10f16f6a15f8a1c4b910548b4d0968baaac21c91",
|
||||
"revision": "7e8284bea36c2d9307f919090922d3885f67eafc",
|
||||
"repo_path": "/integration/gaia-central"
|
||||
}
|
||||
|
@ -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"
|
||||
;;
|
||||
*)
|
||||
|
@ -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));
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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();
|
||||
|
@ -1032,6 +1032,20 @@ TabChild::GetDOMWindowUtils()
|
||||
return utils.forget();
|
||||
}
|
||||
|
||||
already_AddRefed<nsIDOMWindowUtils>
|
||||
TabChild::GetDOMWindowUtils(nsIContent* content)
|
||||
{
|
||||
nsCOMPtr<nsIDOMWindowUtils> utils;
|
||||
nsIDocument* doc = content->GetCurrentDoc();
|
||||
if (doc) {
|
||||
nsCOMPtr<nsIDOMWindow> window = doc->GetDefaultView();
|
||||
if (window) {
|
||||
utils = do_GetInterface(window);
|
||||
}
|
||||
}
|
||||
return utils.forget();
|
||||
}
|
||||
|
||||
static nsInterfaceHashtable<nsPtrHashKey<PContentDialogChild>, 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<nsGlobalWindow*>(aWindow);
|
||||
nsIScrollableFrame* sf = window->GetScrollFrame();
|
||||
|
||||
if (sf) {
|
||||
sf->ScrollToCSSPixelsApproximate(aPoint);
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
TabChild::RecvUpdateFrame(const FrameMetrics& aFrameMetrics)
|
||||
{
|
||||
nsCOMPtr<nsIDOMWindowUtils> utils(GetDOMWindowUtils());
|
||||
MOZ_ASSERT(aFrameMetrics.mScrollId != FrameMetrics::NULL_SCROLL_ID);
|
||||
|
||||
if (aFrameMetrics.mScrollId == FrameMetrics::ROOT_SCROLL_ID) {
|
||||
uint32_t presShellId;
|
||||
nsCOMPtr<nsIDOMWindowUtils> 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<nsIContent> 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<nsIDOMWindowUtils> utils(GetDOMWindowUtils());
|
||||
nsCOMPtr<nsIDOMWindow> 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<nsGlobalWindow*>(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<nsIDOMDocument> domDoc;
|
||||
mWebNav->GetDocument(getter_AddRefs(domDoc));
|
||||
if (domDoc) {
|
||||
nsCOMPtr<nsIDOMElement> 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<nsIDOMDocument> 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<nsIDOMElement> element;
|
||||
if (aFrameMetrics.mScrollId == FrameMetrics::ROOT_SCROLL_ID) {
|
||||
domDoc->GetDocumentElement(getter_AddRefs(element));
|
||||
} else {
|
||||
element = do_QueryInterface(nsLayoutUtils::FindContentFor(
|
||||
aFrameMetrics.mScrollId));
|
||||
}
|
||||
|
||||
if (element) {
|
||||
nsCOMPtr<nsIDOMWindowUtils> utils(GetDOMWindowUtils());
|
||||
nsCOMPtr<nsIDOMWindowUtils> utils(GetDOMWindowUtils(aContent));
|
||||
nsCOMPtr<nsIDOMElement> 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
|
||||
|
@ -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<nsIDOMWindowUtils> 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<nsIDOMWindowUtils> GetDOMWindowUtils(nsIContent* aContent);
|
||||
|
||||
class CachedFileDescriptorInfo;
|
||||
class CachedFileDescriptorCallbackRunnable;
|
||||
|
@ -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]
|
||||
|
@ -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();
|
@ -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;
|
||||
|
@ -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;
|
||||
})();
|
||||
|
@ -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;
|
||||
})();
|
||||
|
@ -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;
|
||||
})();
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
})();
|
||||
|
@ -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 =
|
||||
"<wap-provisioningdoc>" +
|
||||
"<characteristic type=\"BOOTSTRAP\">" +
|
||||
"<parm name=\"NAME\" value=\"CHT_emome\"/>" +
|
||||
"</characteristic>" +
|
||||
"<characteristic type=\"APPLICATION\">" +
|
||||
"<parm name=\"APPID\" value=\"w2\"/>" +
|
||||
"<parm name=\"TO-PROXY\" value=\"WPROXY\"/>" +
|
||||
"<parm name=\"NAME\" value=\"CHT_emome\"/>" +
|
||||
"<characteristic type=\"RESOURCE\">" +
|
||||
"<parm name=\"URI\" value=\"http://wap.emome.net/\"/>" +
|
||||
"<parm name=\"NAME\" value=\"CHT_emome\"/>" +
|
||||
"<parm name=\"STARTPAGE\"/>" +
|
||||
"</characteristic>" +
|
||||
"</characteristic>" +
|
||||
"<characteristic type=\"APPLICATION\">" +
|
||||
"<parm name=\"APPID\" value=\"w4\"/>" +
|
||||
"<parm name=\"TO-PROXY\" value=\"MPROXY\"/>" +
|
||||
"<parm name=\"ADDR\" value=\"http://mms:8002\"/>" +
|
||||
"</characteristic>" +
|
||||
"<characteristic type=\"PXLOGICAL\">" +
|
||||
"<parm name=\"PROXY-ID\" value=\"WPROXY\"/>" +
|
||||
"<parm name=\"NAME\" value=\"CHT_emome\"/>" +
|
||||
"<parm name=\"STARTPAGE\" value=\"http://wap.emome.net/\"/>" +
|
||||
"<characteristic type=\"PXPHYSICAL\">" +
|
||||
"<parm name=\"PHYSICAL-PROXY-ID\" value=\"PROXY1\"/>" +
|
||||
"<parm name=\"PXADDR\" value=\"10.1.1.1\"/>" +
|
||||
"<parm name=\"PXADDRTYPE\" value=\"IPV4\"/>" +
|
||||
"<parm name=\"TO-NAPID\" value=\"CHT_emome\"/>" +
|
||||
"<characteristic type=\"PORT\">" +
|
||||
"<parm name=\"PORTNBR\" value=\"8080\"/>" +
|
||||
"</characteristic>" +
|
||||
"</characteristic>" +
|
||||
"</characteristic>" +
|
||||
"<characteristic type=\"PXLOGICAL\">" +
|
||||
"<parm name=\"PROXY-ID\" value=\"MPROXY\"/>" +
|
||||
"<parm name=\"NAME\" value=\"CHT_MMS\"/>" +
|
||||
"<characteristic type=\"PXPHYSICAL\">" +
|
||||
"<parm name=\"PHYSICAL-PROXY-ID\" value=\"PROXY2\"/>" +
|
||||
"<parm name=\"PXADDR\" value=\"10.1.1.1\"/>" +
|
||||
"<parm name=\"PXADDRTYPE\" value=\"IPV4\"/>" +
|
||||
"<parm name=\"TO-NAPID\" value=\"CHT_MMS\"/>" +
|
||||
"<characteristic type=\"PORT\">" +
|
||||
"<parm name=\"PORTNBR\" value=\"8080\"/>" +
|
||||
"</characteristic>" +
|
||||
"</characteristic>" +
|
||||
"</characteristic>" +
|
||||
"<characteristic type=\"NAPDEF\">" +
|
||||
"<parm name=\"NAPID\" value=\"CHT_emome\"/>" +
|
||||
"<parm name=\"NAME\" value=\"CHT_emome\"/>" +
|
||||
"<parm name=\"BEARER\" value=\"GSM-GPRS\"/>" +
|
||||
"<parm name=\"NAP-ADDRESS\" value=\"emome\"/>" +
|
||||
"<parm name=\"NAP-ADDRTYPE\" value=\"APN\"/>" +
|
||||
"</characteristic>" +
|
||||
"<characteristic type=\"NAPDEF\">" +
|
||||
"<parm name=\"NAPID\" value=\"CHT_MMS\"/>" +
|
||||
"<parm name=\"NAME\" value=\"CHT_MMS\"/>" +
|
||||
"<parm name=\"BEARER\" value=\"GSM-GPRS\"/>" +
|
||||
"<parm name=\"NAP-ADDRESS\" value=\"emome\"/>" +
|
||||
"<parm name=\"NAP-ADDRTYPE\" value=\"APN\"/>" +
|
||||
"</characteristic>" +
|
||||
"</wap-provisioningdoc>";
|
||||
|
||||
test_parser(wbxml_code_page_data_array, "application/vnd.wap.connectivity-wbxml", {
|
||||
contentType: "text/vnd.wap.connectivity-xml",
|
||||
content: wbxml_content
|
||||
});
|
||||
|
||||
run_next_test();
|
||||
});
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
386
gfx/layers/composite/APZCTreeManager.cpp
Normal file
386
gfx/layers/composite/APZCTreeManager.cpp
Normal file
@ -0,0 +1,386 @@
|
||||
/* -*- 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 "AsyncCompositionManager.h" // for ViewTransform
|
||||
#include "LayerManagerComposite.h" // for AsyncCompositionManager.h
|
||||
#include "Compositor.h"
|
||||
|
||||
#define APZC_LOG(...)
|
||||
// #define APZC_LOG(args...) printf_stderr(args)
|
||||
|
||||
namespace mozilla {
|
||||
namespace layers {
|
||||
|
||||
APZCTreeManager::APZCTreeManager()
|
||||
: mTreeLock("APZCTreeLock")
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
AsyncPanZoomController::InitializeGlobalState();
|
||||
}
|
||||
|
||||
void
|
||||
APZCTreeManager::AssertOnCompositorThread()
|
||||
{
|
||||
Compositor::AssertOnCompositorThread();
|
||||
}
|
||||
|
||||
/* Flatten the tree of APZC instances into the given nsTArray */
|
||||
static void
|
||||
Collect(AsyncPanZoomController* aApzc, nsTArray< nsRefPtr<AsyncPanZoomController> >* aCollection)
|
||||
{
|
||||
if (aApzc) {
|
||||
aCollection->AppendElement(aApzc);
|
||||
Collect(aApzc->GetLastChild(), aCollection);
|
||||
Collect(aApzc->GetPrevSibling(), aCollection);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
APZCTreeManager::UpdatePanZoomControllerTree(CompositorParent* aCompositor, Layer* aRoot,
|
||||
bool aIsFirstPaint, uint64_t aFirstPaintLayersId)
|
||||
{
|
||||
AssertOnCompositorThread();
|
||||
|
||||
MonitorAutoLock lock(mTreeLock);
|
||||
|
||||
// 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<AsyncPanZoomController> > apzcsToDestroy;
|
||||
Collect(mRootApzc, &apzcsToDestroy);
|
||||
mRootApzc = nullptr;
|
||||
|
||||
if (aRoot) {
|
||||
UpdatePanZoomControllerTree(aCompositor,
|
||||
aRoot,
|
||||
// aCompositor is null in gtest scenarios
|
||||
aCompositor ? aCompositor->RootLayerTreeId() : 0,
|
||||
nullptr, nullptr,
|
||||
aIsFirstPaint, aFirstPaintLayersId,
|
||||
&apzcsToDestroy);
|
||||
}
|
||||
|
||||
for (int i = apzcsToDestroy.Length() - 1; i >= 0; i--) {
|
||||
APZC_LOG("Destroying APZC at %p\n", apzcsToDestroy[i].get());
|
||||
apzcsToDestroy[i]->Destroy();
|
||||
}
|
||||
}
|
||||
|
||||
AsyncPanZoomController*
|
||||
APZCTreeManager::UpdatePanZoomControllerTree(CompositorParent* aCompositor,
|
||||
Layer* aLayer, uint64_t aLayersId,
|
||||
AsyncPanZoomController* aParent,
|
||||
AsyncPanZoomController* aNextSibling,
|
||||
bool aIsFirstPaint, uint64_t aFirstPaintLayersId,
|
||||
nsTArray< nsRefPtr<AsyncPanZoomController> >* 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);
|
||||
}
|
||||
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);
|
||||
} else if (aParent) {
|
||||
aParent->SetLastChild(controller);
|
||||
} else {
|
||||
mRootApzc = controller;
|
||||
}
|
||||
|
||||
// Let this controller be the parent of other controllers when we recurse downwards
|
||||
aParent = controller;
|
||||
}
|
||||
}
|
||||
|
||||
container->SetAsyncPanZoomController(controller);
|
||||
}
|
||||
|
||||
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) {
|
||||
return controller;
|
||||
}
|
||||
if (next) {
|
||||
return next;
|
||||
}
|
||||
return aNextSibling;
|
||||
}
|
||||
|
||||
nsEventStatus
|
||||
APZCTreeManager::ReceiveInputEvent(const InputData& aEvent)
|
||||
{
|
||||
nsRefPtr<AsyncPanZoomController> 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<AsyncPanZoomController> apzc;
|
||||
switch (aEvent.eventStructType) {
|
||||
case NS_TOUCH_EVENT: {
|
||||
const nsTouchEvent& touchEvent = static_cast<const nsTouchEvent&>(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<const nsMouseEvent&>(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<AsyncPanZoomController> apzc = GetTargetAPZC(aGuid);
|
||||
if (apzc) {
|
||||
apzc->UpdateCompositionBounds(aCompositionBounds);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
APZCTreeManager::CancelDefaultPanZoom(const ScrollableLayerGuid& aGuid)
|
||||
{
|
||||
nsRefPtr<AsyncPanZoomController> apzc = GetTargetAPZC(aGuid);
|
||||
if (apzc) {
|
||||
apzc->CancelDefaultPanZoom();
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
APZCTreeManager::DetectScrollableSubframe(const ScrollableLayerGuid& aGuid)
|
||||
{
|
||||
nsRefPtr<AsyncPanZoomController> apzc = GetTargetAPZC(aGuid);
|
||||
if (apzc) {
|
||||
apzc->DetectScrollableSubframe();
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
APZCTreeManager::ZoomToRect(const ScrollableLayerGuid& aGuid,
|
||||
const CSSRect& aRect)
|
||||
{
|
||||
nsRefPtr<AsyncPanZoomController> apzc = GetTargetAPZC(aGuid);
|
||||
if (apzc) {
|
||||
apzc->ZoomToRect(aRect);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
APZCTreeManager::ContentReceivedTouch(const ScrollableLayerGuid& aGuid,
|
||||
bool aPreventDefault)
|
||||
{
|
||||
nsRefPtr<AsyncPanZoomController> apzc = GetTargetAPZC(aGuid);
|
||||
if (apzc) {
|
||||
apzc->ContentReceivedTouch(aPreventDefault);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
APZCTreeManager::UpdateZoomConstraints(const ScrollableLayerGuid& aGuid,
|
||||
bool aAllowZoom,
|
||||
float aMinScale,
|
||||
float aMaxScale)
|
||||
{
|
||||
nsRefPtr<AsyncPanZoomController> apzc = GetTargetAPZC(aGuid);
|
||||
if (apzc) {
|
||||
apzc->UpdateZoomConstraints(aAllowZoom, aMinScale, aMaxScale);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
APZCTreeManager::UpdateScrollOffset(const ScrollableLayerGuid& aGuid,
|
||||
const CSSPoint& aScrollOffset)
|
||||
{
|
||||
nsRefPtr<AsyncPanZoomController> apzc = GetTargetAPZC(aGuid);
|
||||
if (apzc) {
|
||||
apzc->UpdateScrollOffset(aScrollOffset);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
APZCTreeManager::CancelAnimation(const ScrollableLayerGuid &aGuid)
|
||||
{
|
||||
nsRefPtr<AsyncPanZoomController> apzc = GetTargetAPZC(aGuid);
|
||||
if (apzc) {
|
||||
apzc->CancelAnimation();
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
APZCTreeManager::ClearTree()
|
||||
{
|
||||
MonitorAutoLock lock(mTreeLock);
|
||||
|
||||
// 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<AsyncPanZoomController> > apzcsToDestroy;
|
||||
Collect(mRootApzc, &apzcsToDestroy);
|
||||
for (int i = apzcsToDestroy.Length() - 1; i >= 0; i--) {
|
||||
apzcsToDestroy[i]->Destroy();
|
||||
}
|
||||
mRootApzc = nullptr;
|
||||
}
|
||||
|
||||
already_AddRefed<AsyncPanZoomController>
|
||||
APZCTreeManager::GetTargetAPZC(const ScrollableLayerGuid& aGuid)
|
||||
{
|
||||
MonitorAutoLock lock(mTreeLock);
|
||||
nsRefPtr<AsyncPanZoomController> target;
|
||||
// The root may have siblings, check those too
|
||||
for (AsyncPanZoomController* apzc = mRootApzc; apzc; apzc = apzc->GetPrevSibling()) {
|
||||
target = FindTargetAPZC(apzc, aGuid);
|
||||
if (target) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
return target.forget();
|
||||
}
|
||||
|
||||
already_AddRefed<AsyncPanZoomController>
|
||||
APZCTreeManager::GetTargetAPZC(const ScreenPoint& aPoint)
|
||||
{
|
||||
MonitorAutoLock lock(mTreeLock);
|
||||
nsRefPtr<AsyncPanZoomController> 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*
|
||||
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;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
275
gfx/layers/composite/APZCTreeManager.h
Normal file
275
gfx/layers/composite/APZCTreeManager.h
Normal file
@ -0,0 +1,275 @@
|
||||
/* -*- 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"
|
||||
|
||||
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
|
||||
* 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 {
|
||||
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(APZCTreeManager)
|
||||
|
||||
public:
|
||||
APZCTreeManager();
|
||||
virtual ~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.
|
||||
*
|
||||
* @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,
|
||||
bool aIsFirstPaint, uint64_t aFirstPaintLayersId);
|
||||
|
||||
/**
|
||||
* 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 <meta name="viewport"> 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();
|
||||
|
||||
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. These are public for testing code and generally should not be
|
||||
used by other production code.
|
||||
*/
|
||||
already_AddRefed<AsyncPanZoomController> GetTargetAPZC(const ScrollableLayerGuid& aGuid);
|
||||
already_AddRefed<AsyncPanZoomController> GetTargetAPZC(const ScreenPoint& aPoint);
|
||||
private:
|
||||
/* 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
|
||||
* 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<AsyncPanZoomController> >* aApzcsToDestroy);
|
||||
|
||||
private:
|
||||
/* 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). 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;
|
||||
nsRefPtr<AsyncPanZoomController> mRootApzc;
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
#endif // mozilla_layers_PanZoomController_h
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -437,7 +428,6 @@ AsyncCompositionManager::ApplyAsyncContentTransformToTree(TimeStamp aCurrentFram
|
||||
ScreenPoint scrollOffset;
|
||||
*aWantNextFrame |=
|
||||
controller->SampleContentTransformForFrame(aCurrentFrame,
|
||||
container,
|
||||
&treeTransform,
|
||||
scrollOffset);
|
||||
|
||||
|
@ -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,36 +153,22 @@ 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);
|
||||
|
||||
gComputedTimingFunction = new ComputedTimingFunction();
|
||||
gComputedTimingFunction->Init(
|
||||
nsTimingFunction(NS_STYLE_TRANSITION_TIMING_FUNCTION_EASE));
|
||||
ClearOnShutdown(&gComputedTimingFunction);
|
||||
}
|
||||
|
||||
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());
|
||||
}
|
||||
}
|
||||
|
||||
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),
|
||||
mX(this),
|
||||
mY(this),
|
||||
@ -176,45 +182,48 @@ 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();
|
||||
|
||||
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() {
|
||||
MOZ_COUNT_DTOR(AsyncPanZoomController);
|
||||
}
|
||||
|
||||
already_AddRefed<GeckoContentController>
|
||||
AsyncPanZoomController::GetGeckoContentController() {
|
||||
MonitorAutoLock lock(mRefPtrMonitor);
|
||||
nsRefPtr<GeckoContentController> controller = mGeckoContentController;
|
||||
return controller.forget();
|
||||
}
|
||||
|
||||
already_AddRefed<GestureEventListener>
|
||||
AsyncPanZoomController::GetGestureEventListener() {
|
||||
MonitorAutoLock lock(mRefPtrMonitor);
|
||||
nsRefPtr<GestureEventListener> listener = mGestureEventListener;
|
||||
return listener.forget();
|
||||
}
|
||||
|
||||
void
|
||||
AsyncPanZoomController::Destroy()
|
||||
{
|
||||
// These memebrs can only be used on the controller/UI thread.
|
||||
mGeckoContentController = nullptr;
|
||||
mGestureEventListener = nullptr;
|
||||
{ // scope the lock
|
||||
MonitorAutoLock lock(mRefPtrMonitor);
|
||||
mGeckoContentController = nullptr;
|
||||
mGestureEventListener = nullptr;
|
||||
}
|
||||
mPrevSibling = nullptr;
|
||||
mLastChild = nullptr;
|
||||
}
|
||||
|
||||
/* static */float
|
||||
@ -332,8 +341,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<GestureEventListener> listener = GetGestureEventListener();
|
||||
if (listener && !mDisableNextTouchBatch) {
|
||||
rv = listener->HandleInputEvent(aEvent);
|
||||
if (rv == nsEventStatus_eConsumeNoDefault)
|
||||
return rv;
|
||||
}
|
||||
@ -659,12 +669,13 @@ nsEventStatus AsyncPanZoomController::OnScaleEnd(const PinchGestureInput& aEvent
|
||||
}
|
||||
|
||||
nsEventStatus AsyncPanZoomController::OnLongPress(const TapGestureInput& aEvent) {
|
||||
if (mGeckoContentController) {
|
||||
nsRefPtr<GeckoContentController> 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;
|
||||
@ -675,25 +686,27 @@ nsEventStatus AsyncPanZoomController::OnSingleTapUp(const TapGestureInput& aEven
|
||||
}
|
||||
|
||||
nsEventStatus AsyncPanZoomController::OnSingleTapConfirmed(const TapGestureInput& aEvent) {
|
||||
if (mGeckoContentController) {
|
||||
nsRefPtr<GeckoContentController> 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<GeckoContentController> 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;
|
||||
@ -1019,12 +1032,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<GeckoContentController> controller = GetGeckoContentController();
|
||||
if (controller) {
|
||||
mPaintThrottler.PostTask(
|
||||
FROM_HERE,
|
||||
NewRunnableMethod(controller.get(),
|
||||
&GeckoContentController::RequestContentRepaint,
|
||||
mFrameMetrics),
|
||||
GetFrameTime());
|
||||
}
|
||||
mFrameMetrics.mPresShellId = mLastContentPaintMetrics.mPresShellId;
|
||||
mLastPaintRequestMetrics = mFrameMetrics;
|
||||
|
||||
@ -1043,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
|
||||
@ -1053,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);
|
||||
|
||||
@ -1103,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;
|
||||
}
|
||||
|
||||
@ -1129,7 +1132,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,25 +1144,35 @@ bool AsyncPanZoomController::SampleContentTransformForFrame(const TimeStamp& aSa
|
||||
NewRunnableMethod(this, &AsyncPanZoomController::FireAsyncScrollOnTimeout);
|
||||
MessageLoop::current()->PostDelayedTask(FROM_HERE,
|
||||
mAsyncScrollTimeoutTask,
|
||||
mAsyncScrollTimeout);
|
||||
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;
|
||||
}
|
||||
|
||||
void AsyncPanZoomController::NotifyLayersUpdated(const FrameMetrics& aViewportFrame, bool aIsFirstPaint) {
|
||||
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);
|
||||
|
||||
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.
|
||||
@ -1176,7 +1189,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:
|
||||
@ -1187,12 +1200,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);
|
||||
}
|
||||
@ -1204,11 +1217,15 @@ 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() && !aLayerMetrics.IsDefault());
|
||||
|
||||
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) {
|
||||
@ -1242,8 +1259,9 @@ void AsyncPanZoomController::UpdateCompositionBounds(const ScreenIntRect& aCompo
|
||||
|
||||
void AsyncPanZoomController::CancelDefaultPanZoom() {
|
||||
mDisableNextTouchBatch = true;
|
||||
if (mGestureEventListener) {
|
||||
mGestureEventListener->CancelGesture();
|
||||
nsRefPtr<GestureEventListener> listener = GetGestureEventListener();
|
||||
if (listener) {
|
||||
listener->CancelGesture();
|
||||
}
|
||||
}
|
||||
|
||||
@ -1424,83 +1442,44 @@ void AsyncPanZoomController::UpdateZoomConstraints(bool aAllowZoom,
|
||||
}
|
||||
|
||||
void AsyncPanZoomController::PostDelayedTask(Task* aTask, int aDelayMs) {
|
||||
if (!mGeckoContentController) {
|
||||
return;
|
||||
nsRefPtr<GeckoContentController> controller = GetGeckoContentController();
|
||||
if (controller) {
|
||||
controller->PostDelayedTask(aTask, aDelayMs);
|
||||
}
|
||||
|
||||
mGeckoContentController->PostDelayedTask(aTask, aDelayMs);
|
||||
}
|
||||
|
||||
void AsyncPanZoomController::SendAsyncScrollEvent() {
|
||||
if (!mGeckoContentController) {
|
||||
nsRefPtr<GeckoContentController> controller = GetGeckoContentController();
|
||||
if (!controller) {
|
||||
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);
|
||||
}
|
||||
|
||||
mGeckoContentController->SendAsyncScrollDOMEvent(contentRect, scrollableSize);
|
||||
controller->SendAsyncScrollDOMEvent(scrollId, 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<ContainerLayer&>(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(CSSPoint aScrollOffset)
|
||||
void AsyncPanZoomController::UpdateScrollOffset(const CSSPoint& aScrollOffset)
|
||||
{
|
||||
MonitorAutoLock monitor(mMonitor);
|
||||
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;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
@ -45,7 +47,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;
|
||||
@ -68,19 +70,25 @@ public:
|
||||
*/
|
||||
static float GetTouchStartTolerance();
|
||||
|
||||
AsyncPanZoomController(GeckoContentController* aController,
|
||||
AsyncPanZoomController(uint64_t aLayersId,
|
||||
GeckoContentController* aController,
|
||||
GestureBehavior aGestures = DEFAULT_GESTURES);
|
||||
~AsyncPanZoomController();
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
// These methods must only be called on the controller/UI thread.
|
||||
// These methods must only be called on the gecko thread.
|
||||
//
|
||||
|
||||
/**
|
||||
* Shut down the controller/UI thread state and prepare to be
|
||||
* deleted (which may happen from any 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.
|
||||
*/
|
||||
void Destroy();
|
||||
static void InitializeGlobalState();
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
// These methods must only be called on the controller/UI thread.
|
||||
//
|
||||
|
||||
/**
|
||||
* General handler for incoming input events. Manipulates the frame metrics
|
||||
@ -166,26 +174,25 @@ 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
|
||||
* composite.
|
||||
*/
|
||||
bool SampleContentTransformForFrame(const TimeStamp& aSampleTime,
|
||||
ContainerLayer* aLayer,
|
||||
ViewTransform* aNewTransform,
|
||||
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
|
||||
@ -197,6 +204,24 @@ 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();
|
||||
|
||||
/**
|
||||
* 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
|
||||
@ -234,6 +259,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
|
||||
@ -241,23 +271,12 @@ 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
|
||||
* 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
|
||||
@ -492,16 +511,39 @@ private:
|
||||
*/
|
||||
void SetState(PanZoomState aState);
|
||||
|
||||
uint64_t mLayersId;
|
||||
nsRefPtr<CompositorParent> 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<GeckoContentController> mGeckoContentController;
|
||||
nsRefPtr<GestureEventListener> mGestureEventListener;
|
||||
Monitor mRefPtrMonitor;
|
||||
|
||||
/* Utility functions that return a addrefed pointer to the corresponding fields. */
|
||||
already_AddRefed<GeckoContentController> GetGeckoContentController();
|
||||
already_AddRefed<GestureEventListener> 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|, 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.
|
||||
@ -532,14 +574,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;
|
||||
@ -571,14 +605,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
|
||||
@ -598,6 +624,37 @@ 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<AsyncPanZoomController> mLastChild;
|
||||
nsRefPtr<AsyncPanZoomController> 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;
|
||||
};
|
||||
|
||||
}
|
||||
|
@ -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,10 @@ CompositorParent::CompositorParent(nsIWidget* aWidget,
|
||||
CompositorLoop()->PostTask(FROM_HERE, NewRunnableFunction(&AddCompositor,
|
||||
this, &mCompositorID));
|
||||
|
||||
mRootLayerTreeID = AllocateLayerTreeId();
|
||||
sIndirectLayerTrees[mRootLayerTreeID].mParent = this;
|
||||
|
||||
mApzcTreeManager = new APZCTreeManager();
|
||||
++sCompositorThreadRefCount;
|
||||
}
|
||||
|
||||
@ -170,6 +173,12 @@ CompositorParent::IsInCompositorThread()
|
||||
return CompositorThreadID() == PlatformThread::CurrentId();
|
||||
}
|
||||
|
||||
uint64_t
|
||||
CompositorParent::RootLayerTreeId()
|
||||
{
|
||||
return mRootLayerTreeID;
|
||||
}
|
||||
|
||||
CompositorParent::~CompositorParent()
|
||||
{
|
||||
MOZ_COUNT_DTOR(CompositorParent);
|
||||
@ -186,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
|
||||
@ -404,8 +416,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, mLayerManager->GetRoot(), aIsFirstPaint, aId);
|
||||
}
|
||||
|
||||
if (mLayerManager) {
|
||||
LayerManagerComposite* managerComposite = mLayerManager->AsLayerManagerComposite();
|
||||
if (managerComposite) {
|
||||
@ -559,6 +576,12 @@ CompositorParent::ShadowLayersUpdated(LayerTransactionParent* aLayerTree,
|
||||
mCompositionManager->Updated(isFirstPaint, aTargetConfig);
|
||||
Layer* root = aLayerTree->GetRoot();
|
||||
mLayerManager->SetRoot(root);
|
||||
|
||||
if (mApzcTreeManager) {
|
||||
AutoResolveRefLayers resolve(mCompositionManager);
|
||||
mApzcTreeManager->UpdatePanZoomControllerTree(this, root, isFirstPaint, mRootLayerTreeID);
|
||||
}
|
||||
|
||||
if (root) {
|
||||
SetShadowProperties(root);
|
||||
if (mIsTesting) {
|
||||
@ -704,7 +727,7 @@ CompositorParent::AllocateLayerTreeId()
|
||||
{
|
||||
MOZ_ASSERT(CompositorLoop());
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
static uint64_t ids;
|
||||
static uint64_t ids = 0;
|
||||
return ++ids;
|
||||
}
|
||||
|
||||
@ -724,20 +747,30 @@ 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<AsyncPanZoomController>(aController);
|
||||
already_AddRefed<GeckoContentController>(aController);
|
||||
}
|
||||
|
||||
// Notify the AsyncPanZoomController about the current compositor so that it
|
||||
// can request composites off the compositor thread.
|
||||
aController->SetCompositorParent(sIndirectLayerTrees[aLayersId].mParent);
|
||||
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::SetPanZoomControllerForLayerTree(uint64_t aLayersId,
|
||||
AsyncPanZoomController* aController)
|
||||
CompositorParent::SetControllerForLayerTree(uint64_t aLayersId,
|
||||
GeckoContentController* aController)
|
||||
{
|
||||
// This ref is adopted by UpdateControllerForLayersId().
|
||||
aController->AddRef();
|
||||
@ -747,6 +780,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
|
||||
@ -831,16 +874,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*
|
||||
@ -912,9 +949,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
|
||||
|
@ -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,12 +32,23 @@ class Thread;
|
||||
namespace mozilla {
|
||||
namespace layers {
|
||||
|
||||
class AsyncPanZoomController;
|
||||
class APZCTreeManager;
|
||||
class Layer;
|
||||
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
|
||||
{
|
||||
@ -89,7 +101,13 @@ public:
|
||||
bool ScheduleResumeOnCompositorThread(int width, int height);
|
||||
|
||||
virtual void ScheduleComposition();
|
||||
void NotifyShadowTreeTransaction();
|
||||
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.
|
||||
@ -128,13 +146,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
|
||||
@ -154,7 +178,7 @@ public:
|
||||
|
||||
struct LayerTreeState {
|
||||
nsRefPtr<Layer> mRoot;
|
||||
nsRefPtr<AsyncPanZoomController> mController;
|
||||
nsRefPtr<GeckoContentController> mController;
|
||||
CompositorParent *mParent;
|
||||
TargetConfig mTargetConfig;
|
||||
};
|
||||
@ -264,10 +288,13 @@ private:
|
||||
mozilla::Monitor mResumeCompositionMonitor;
|
||||
|
||||
uint64_t mCompositorID;
|
||||
uint64_t mRootLayerTreeID;
|
||||
|
||||
bool mOverrideComposeReadiness;
|
||||
CancelableTask* mForceCompositionTask;
|
||||
|
||||
nsRefPtr<APZCTreeManager> mApzcTreeManager;
|
||||
|
||||
DISALLOW_EVIL_CONSTRUCTORS(CompositorParent);
|
||||
};
|
||||
|
||||
|
@ -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;
|
||||
|
||||
/**
|
||||
|
@ -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',
|
||||
|
@ -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"
|
||||
|
||||
@ -24,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));
|
||||
};
|
||||
|
||||
@ -39,6 +41,23 @@ class TestAPZCContainerLayer : public ContainerLayer {
|
||||
void RepositionChild(Layer* aChild, Layer* aAfter) {}
|
||||
};
|
||||
|
||||
class TestAsyncPanZoomController : public AsyncPanZoomController {
|
||||
public:
|
||||
TestAsyncPanZoomController(uint64_t aLayersId, MockContentController* mcc)
|
||||
: AsyncPanZoomController(aLayersId, mcc)
|
||||
{}
|
||||
|
||||
void SetFrameMetrics(const FrameMetrics& metrics) {
|
||||
MonitorAutoLock lock(mMonitor);
|
||||
mFrameMetrics = metrics;
|
||||
}
|
||||
};
|
||||
|
||||
class TestAPZCTreeManager : public APZCTreeManager {
|
||||
protected:
|
||||
void AssertOnCompositorThread() MOZ_OVERRIDE { /* no-op */ }
|
||||
};
|
||||
|
||||
static
|
||||
FrameMetrics TestFrameMetrics() {
|
||||
FrameMetrics fm;
|
||||
@ -90,21 +109,20 @@ void ApzcPan(AsyncPanZoomController* apzc, int& aTime, int aTouchStartY, int aTo
|
||||
TEST(AsyncPanZoomController, Constructor) {
|
||||
// RefCounted class can't live in the stack
|
||||
nsRefPtr<MockContentController> mcc = new MockContentController();
|
||||
nsRefPtr<AsyncPanZoomController> apzc = new AsyncPanZoomController(mcc);
|
||||
apzc->NotifyLayersUpdated(TestFrameMetrics(), true);
|
||||
nsRefPtr<TestAsyncPanZoomController> apzc = new TestAsyncPanZoomController(0, mcc);
|
||||
apzc->SetFrameMetrics(TestFrameMetrics());
|
||||
}
|
||||
|
||||
TEST(AsyncPanZoomController, SimpleTransform) {
|
||||
TimeStamp testStartTime = TimeStamp::Now();
|
||||
// RefCounted class can't live in the stack
|
||||
nsRefPtr<MockContentController> mcc = new MockContentController();
|
||||
nsRefPtr<AsyncPanZoomController> apzc = new AsyncPanZoomController(mcc);
|
||||
apzc->NotifyLayersUpdated(TestFrameMetrics(), true);
|
||||
nsRefPtr<TestAsyncPanZoomController> 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());
|
||||
@ -131,7 +149,8 @@ TEST(AsyncPanZoomController, ComplexTransform) {
|
||||
// sides.
|
||||
|
||||
nsRefPtr<MockContentController> mcc = new MockContentController();
|
||||
nsRefPtr<AsyncPanZoomController> apzc = new AsyncPanZoomController(mcc);
|
||||
nsRefPtr<TestAsyncPanZoomController> apzc = new TestAsyncPanZoomController(0, mcc);
|
||||
nsRefPtr<TestAsyncPanZoomController> childApzc = new TestAsyncPanZoomController(0, mcc);
|
||||
|
||||
const char* layerTreeSyntax = "c(c)";
|
||||
// LayerID 0 1
|
||||
@ -174,39 +193,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);
|
||||
apzc->SampleContentTransformForFrame(testStartTime, &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, &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->SampleContentTransformForFrame(testStartTime, layers[0]->AsContainerLayer(), &viewTransformOut, pointOut);
|
||||
apzc->SetFrameMetrics(metrics);
|
||||
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);
|
||||
apzc->NotifyLayersUpdated(childMetrics, true);
|
||||
apzc->SampleContentTransformForFrame(testStartTime, layers[1]->AsContainerLayer(), &viewTransformOut, pointOut);
|
||||
childApzc->SetFrameMetrics(childMetrics);
|
||||
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->NotifyLayersUpdated(metrics, true);
|
||||
apzc->SampleContentTransformForFrame(testStartTime, layers[0]->AsContainerLayer(), &viewTransformOut, pointOut);
|
||||
apzc->SetFrameMetrics(metrics);
|
||||
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;
|
||||
apzc->NotifyLayersUpdated(childMetrics, true);
|
||||
apzc->SampleContentTransformForFrame(testStartTime, layers[0]->AsContainerLayer(), &viewTransformOut, pointOut);
|
||||
childApzc->SetFrameMetrics(childMetrics);
|
||||
childApzc->SampleContentTransformForFrame(testStartTime, &viewTransformOut, pointOut);
|
||||
EXPECT_EQ(ViewTransform(LayerPoint(-30, 0), LayoutDeviceToScreenScale(3)), viewTransformOut);
|
||||
EXPECT_EQ(ScreenPoint(135, 90), pointOut);
|
||||
}
|
||||
@ -216,28 +237,29 @@ TEST(AsyncPanZoomController, Pan) {
|
||||
AsyncPanZoomController::SetFrameTime(testStartTime);
|
||||
|
||||
nsRefPtr<MockContentController> mcc = new MockContentController();
|
||||
nsRefPtr<AsyncPanZoomController> apzc = new AsyncPanZoomController(mcc);
|
||||
nsRefPtr<TestAsyncPanZoomController> apzc = new TestAsyncPanZoomController(0, mcc);
|
||||
|
||||
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;
|
||||
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());
|
||||
}
|
||||
@ -247,16 +269,17 @@ TEST(AsyncPanZoomController, Fling) {
|
||||
AsyncPanZoomController::SetFrameTime(testStartTime);
|
||||
|
||||
nsRefPtr<MockContentController> mcc = new MockContentController();
|
||||
nsRefPtr<AsyncPanZoomController> apzc = new AsyncPanZoomController(mcc);
|
||||
nsRefPtr<TestAsyncPanZoomController> apzc = new TestAsyncPanZoomController(0, mcc);
|
||||
|
||||
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;
|
||||
int touchStart = 50;
|
||||
int touchEnd = 10;
|
||||
TestAPZCContainerLayer layer;
|
||||
ScreenPoint pointOut;
|
||||
ViewTransform viewTransformOut;
|
||||
|
||||
@ -264,7 +287,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;
|
||||
}
|
||||
@ -275,23 +298,24 @@ TEST(AsyncPanZoomController, OverScrollPanning) {
|
||||
AsyncPanZoomController::SetFrameTime(testStartTime);
|
||||
|
||||
nsRefPtr<MockContentController> mcc = new MockContentController();
|
||||
nsRefPtr<AsyncPanZoomController> apzc = new AsyncPanZoomController(mcc);
|
||||
nsRefPtr<TestAsyncPanZoomController> apzc = new TestAsyncPanZoomController(0, mcc);
|
||||
|
||||
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
|
||||
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));
|
||||
}
|
||||
|
||||
@ -322,124 +346,102 @@ CreateTestLayerTree(nsRefPtr<LayerManager>& aLayerManager, nsTArray<nsRefPtr<Lay
|
||||
return CreateLayerTree(layerTreeSyntax, layerVisibleRegion, transforms, aLayerManager, aLayers);
|
||||
}
|
||||
|
||||
TEST(AsyncPanZoomController, GetAPZCAtPoint) {
|
||||
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<nsRefPtr<Layer> > layers;
|
||||
nsRefPtr<LayerManager> lm;
|
||||
nsRefPtr<Layer> root = CreateTestLayerTree(lm, layers);
|
||||
|
||||
TimeStamp testStartTime = TimeStamp::Now();
|
||||
AsyncPanZoomController::SetFrameTime(testStartTime);
|
||||
|
||||
nsRefPtr<MockContentController> mcc = new MockContentController();
|
||||
nsRefPtr<AsyncPanZoomController> apzcMain = new AsyncPanZoomController(mcc);
|
||||
nsRefPtr<AsyncPanZoomController> apzcSub3 = new AsyncPanZoomController(mcc);
|
||||
nsRefPtr<AsyncPanZoomController> apzcSub4 = new AsyncPanZoomController(mcc);
|
||||
nsRefPtr<AsyncPanZoomController> apzcSub7 = new AsyncPanZoomController(mcc);
|
||||
apzcMain->NotifyLayersUpdated(TestFrameMetrics(), true);
|
||||
ScopedLayerTreeRegistration controller(0, root, mcc);
|
||||
|
||||
nsIntRect layerBound;
|
||||
ScreenIntPoint touchPoint(20, 20);
|
||||
AsyncPanZoomController* apzcOut;
|
||||
LayerIntPoint relativePointOut;
|
||||
|
||||
FrameMetrics scrollable;
|
||||
nsRefPtr<APZCTreeManager> manager = new TestAPZCTreeManager();
|
||||
|
||||
// No APZC attached so hit testing will return no APZC at (20,20)
|
||||
AsyncPanZoomController::GetAPZCAtPoint(*root->AsContainerLayer(), touchPoint,
|
||||
&apzcOut, &relativePointOut);
|
||||
|
||||
nsRefPtr<AsyncPanZoomController> hit = manager->GetTargetAPZC(ScreenPoint(20, 20));
|
||||
AsyncPanZoomController* nullAPZC = nullptr;
|
||||
EXPECT_EQ(apzcOut, nullAPZC);
|
||||
EXPECT_EQ(nullAPZC, hit.get());
|
||||
|
||||
// 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);
|
||||
SetScrollableFrameMetrics(root, FrameMetrics::ROOT_SCROLL_ID, mcc);
|
||||
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
|
||||
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);
|
||||
SetScrollableFrameMetrics(layers[3], FrameMetrics::START_SCROLL_ID, mcc);
|
||||
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());
|
||||
// expect hit point at LayerIntPoint(15, 15)
|
||||
|
||||
// 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 = 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, 0, 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 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 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
|
||||
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);
|
||||
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, 0, false);
|
||||
hit = manager->GetTargetAPZC(ScreenPoint(50, 50)); // This point is now outside the root layer
|
||||
EXPECT_EQ(nullAPZC, hit.get());
|
||||
|
||||
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);
|
||||
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)
|
||||
AsyncPanZoomController::GetAPZCAtPoint(*root->AsContainerLayer(), touchPoint,
|
||||
&apzcOut, &relativePointOut);
|
||||
EXPECT_EQ(apzcOut, apzcSub3.get());
|
||||
EXPECT_EQ(LayerIntPoint(20, 20), relativePointOut);
|
||||
root->ComputeEffectiveTransforms(gfx3DMatrix());
|
||||
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)
|
||||
|
||||
// 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);
|
||||
SetScrollableFrameMetrics(layers[7], FrameMetrics::START_SCROLL_ID + 2, mcc);
|
||||
|
||||
gfx3DMatrix translateTransform;
|
||||
translateTransform.Translate(gfxPoint3D(10, 10, 0));
|
||||
@ -453,12 +455,14 @@ TEST(AsyncPanZoomController, GetAPZCAtPoint) {
|
||||
translateTransform3.ScalePost(1,15,1);
|
||||
layers[7]->SetBaseTransform(translateTransform3);
|
||||
|
||||
touchPoint = ScreenIntPoint(1,45);
|
||||
root->ComputeEffectiveTransforms(gfx3DMatrix());
|
||||
manager->UpdatePanZoomControllerTree(nullptr, root, 0, false);
|
||||
// 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);
|
||||
hit = manager->GetTargetAPZC(ScreenPoint(1, 45));
|
||||
EXPECT_EQ(layers[7]->AsContainerLayer()->GetAsyncPanZoomController(), hit.get());
|
||||
// expect hit point at LayerPoint(20, 29)
|
||||
|
||||
manager->ClearTree();
|
||||
}
|
||||
|
||||
|
||||
|
@ -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<Layer> CreateLayerTree(
|
||||
lastLayer = layer;
|
||||
}
|
||||
}
|
||||
if (rootLayer) {
|
||||
rootLayer->ComputeEffectiveTransforms(gfx3DMatrix());
|
||||
}
|
||||
return rootLayer.forget();
|
||||
}
|
||||
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -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.
|
||||
*/
|
||||
|
@ -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"
|
||||
@ -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<TabParent*>(mRenderFrame->Manager());
|
||||
BrowserElementParent::DispatchAsyncScrollEvent(browser, aContentRect,
|
||||
aContentSize);
|
||||
@ -620,14 +621,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 +798,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 +821,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 +847,8 @@ RenderFrameParent::RecvNotifyCompositorTransaction()
|
||||
bool
|
||||
RenderFrameParent::RecvCancelDefaultPanZoom()
|
||||
{
|
||||
if (mPanZoomController) {
|
||||
mPanZoomController->CancelDefaultPanZoom();
|
||||
if (GetApzcTreeManager()) {
|
||||
GetApzcTreeManager()->CancelDefaultPanZoom(ScrollableLayerGuid(mLayersId));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
@ -845,8 +856,8 @@ RenderFrameParent::RecvCancelDefaultPanZoom()
|
||||
bool
|
||||
RenderFrameParent::RecvDetectScrollableSubframe()
|
||||
{
|
||||
if (mPanZoomController) {
|
||||
mPanZoomController->DetectScrollableSubframe();
|
||||
if (GetApzcTreeManager()) {
|
||||
GetApzcTreeManager()->DetectScrollableSubframe(ScrollableLayerGuid(mLayersId));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
@ -972,24 +983,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);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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<nsFrameLoader> mFrameLoader;
|
||||
nsRefPtr<ContainerLayer> 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<layers::AsyncPanZoomController> mPanZoomController;
|
||||
// APZCTreeManager. It's used to manipulate the shadow layer tree
|
||||
// on the compositor thread.
|
||||
nsRefPtr<layers::APZCTreeManager> mApzcTreeManager;
|
||||
nsRefPtr<RemoteContentController> mContentController;
|
||||
|
||||
layers::APZCTreeManager* GetApzcTreeManager();
|
||||
|
||||
// This contains the views for all the scrollable frames currently in the
|
||||
// painted region of our remote content.
|
||||
ViewMap mContentViews;
|
||||
|
@ -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 \
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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();
|
||||
};
|
||||
|
@ -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 = nsWindow::GetAPZCTreeManager();
|
||||
if (controller) {
|
||||
controller->CancelAnimation(ScrollableLayerGuid(nsWindow::RootLayerTreeId()));
|
||||
}
|
||||
}
|
||||
|
||||
NS_EXPORT void JNICALL
|
||||
@ -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);
|
||||
}
|
||||
nsWindow::SetPanZoomController(new AsyncPanZoomController(AndroidBridge::Bridge(), AsyncPanZoomController::USE_GESTURE_DETECTOR));
|
||||
}
|
||||
|
||||
NS_EXPORT void JNICALL
|
||||
Java_org_mozilla_gecko_gfx_NativePanZoomController_handleTouchEvent(JNIEnv* env, jobject instance, jobject event)
|
||||
{
|
||||
AsyncPanZoomController *controller = nsWindow::GetPanZoomController();
|
||||
APZCTreeManager *controller = nsWindow::GetAPZCTreeManager();
|
||||
if (controller) {
|
||||
AndroidGeckoEvent* wrapper = AndroidGeckoEvent::MakeFromJavaObject(env, event);
|
||||
const MultiTouchInput& input = wrapper->MakeMultiTouchInput(nsWindow::TopWindow());
|
||||
@ -905,7 +904,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 +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)
|
||||
{
|
||||
AsyncPanZoomController *controller = nsWindow::GetPanZoomController();
|
||||
APZCTreeManager *controller = nsWindow::GetAPZCTreeManager();
|
||||
if (controller) {
|
||||
controller->ContentReceivedTouch(prevented);
|
||||
controller->ContentReceivedTouch(ScrollableLayerGuid(nsWindow::RootLayerTreeId()), prevented);
|
||||
}
|
||||
}
|
||||
|
||||
@ -946,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)
|
||||
{
|
||||
AsyncPanZoomController* controller = nsWindow::GetPanZoomController();
|
||||
APZCTreeManager *controller = nsWindow::GetAPZCTreeManager();
|
||||
if (controller) {
|
||||
controller->UpdateScrollOffset(CSSPoint(cssX, cssY));
|
||||
controller->UpdateScrollOffset(ScrollableLayerGuid(nsWindow::RootLayerTreeId()), CSSPoint(cssX, cssY));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2417,11 +2417,11 @@ nsWindow::DrawWindowOverlay(LayerManager* aManager, nsIntRect aRect)
|
||||
|
||||
// off-main-thread compositor fields and functions
|
||||
|
||||
nsRefPtr<mozilla::layers::APZCTreeManager> nsWindow::sApzcTreeManager = 0;
|
||||
nsRefPtr<mozilla::layers::LayerManager> nsWindow::sLayerManager = 0;
|
||||
nsRefPtr<mozilla::layers::CompositorParent> nsWindow::sCompositorParent = 0;
|
||||
nsRefPtr<mozilla::layers::CompositorChild> nsWindow::sCompositorChild = 0;
|
||||
bool nsWindow::sCompositorPaused = true;
|
||||
nsRefPtr<mozilla::layers::AsyncPanZoomController> nsWindow::sApzc = 0;
|
||||
|
||||
void
|
||||
nsWindow::SetCompositor(mozilla::layers::LayerManager* aLayerManager,
|
||||
@ -2496,52 +2496,30 @@ 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)
|
||||
mozilla::layers::APZCTreeManager*
|
||||
nsWindow::GetAPZCTreeManager()
|
||||
{
|
||||
if (sApzc) {
|
||||
sApzc->SetCompositorParent(nullptr);
|
||||
sApzc = nullptr;
|
||||
}
|
||||
if (apzc) {
|
||||
sApzc = apzc;
|
||||
sApzc->SetCompositorParent(sCompositorParent);
|
||||
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;
|
||||
}
|
||||
|
||||
AsyncPanZoomController*
|
||||
nsWindow::GetPanZoomController()
|
||||
uint64_t
|
||||
nsWindow::RootLayerTreeId()
|
||||
{
|
||||
return sApzc;
|
||||
MOZ_ASSERT(sCompositorParent);
|
||||
return sCompositorParent->RootLayerTreeId();
|
||||
}
|
||||
|
||||
|
@ -23,7 +23,7 @@ namespace mozilla {
|
||||
class CompositorParent;
|
||||
class CompositorChild;
|
||||
class LayerManager;
|
||||
class AsyncPanZoomController;
|
||||
class APZCTreeManager;
|
||||
}
|
||||
}
|
||||
|
||||
@ -155,8 +155,9 @@ 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();
|
||||
static mozilla::layers::APZCTreeManager* GetAPZCTreeManager();
|
||||
/* RootLayerTreeId() can only be called when GetAPZCTreeManager() returns non-null */
|
||||
static uint64_t RootLayerTreeId();
|
||||
|
||||
virtual bool WidgetPaintsBackground();
|
||||
|
||||
@ -231,11 +232,11 @@ private:
|
||||
|
||||
mozilla::AndroidLayerRendererFrame mLayerRendererFrame;
|
||||
|
||||
static nsRefPtr<mozilla::layers::APZCTreeManager> sApzcTreeManager;
|
||||
static nsRefPtr<mozilla::layers::LayerManager> sLayerManager;
|
||||
static nsRefPtr<mozilla::layers::CompositorParent> sCompositorParent;
|
||||
static nsRefPtr<mozilla::layers::CompositorChild> sCompositorChild;
|
||||
static bool sCompositorPaused;
|
||||
static nsRefPtr<mozilla::layers::AsyncPanZoomController> sApzc;
|
||||
};
|
||||
|
||||
#endif /* NSWINDOW_H_ */
|
||||
|
@ -29,7 +29,6 @@
|
||||
#include <EGL/egl.h>
|
||||
|
||||
#include <hardware/hardware.h>
|
||||
#include <gui/SurfaceTextureClient.h>
|
||||
#include <ui/GraphicBuffer.h>
|
||||
|
||||
#include "FramebufferSurface.h"
|
||||
|
@ -14,7 +14,7 @@
|
||||
*/
|
||||
|
||||
#include "GonkDisplayJB.h"
|
||||
#include <gui/SurfaceTextureClient.h>
|
||||
#include <gui/Surface.h>
|
||||
|
||||
#include <hardware/hardware.h>
|
||||
#include <hardware/hwcomposer.h>
|
||||
@ -99,7 +99,7 @@ GonkDisplayJB::GonkDisplayJB()
|
||||
mAlloc = new GraphicBufferAlloc();
|
||||
mFBSurface = new FramebufferSurface(0, mWidth, mHeight, surfaceformat, mAlloc);
|
||||
|
||||
sp<SurfaceTextureClient> stc = new SurfaceTextureClient(static_cast<sp<ISurfaceTexture> >(mFBSurface->getBufferQueue()));
|
||||
sp<Surface> stc = new Surface(static_cast<sp<IGraphicBufferProducer> >(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);
|
||||
|
@ -20,7 +20,7 @@ CPP_SOURCES += [
|
||||
'BootAnimation.cpp',
|
||||
]
|
||||
|
||||
if CONFIG['ANDROID_VERSION'] == '17':
|
||||
if CONFIG['ANDROID_VERSION'] == '18':
|
||||
CPP_SOURCES += [
|
||||
'FramebufferSurface.cpp',
|
||||
'GraphicBufferAlloc.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();
|
||||
|
@ -140,7 +140,7 @@ namespace {
|
||||
NS_IMPL_ISUPPORTS_INHERITED0(MetroWidget, nsBaseWidget)
|
||||
|
||||
|
||||
nsRefPtr<mozilla::layers::AsyncPanZoomController> MetroWidget::sAPZC;
|
||||
nsRefPtr<mozilla::layers::APZCTreeManager> 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<mozilla::layers::LayerManagerD3D10> 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();
|
||||
}
|
||||
|
@ -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<mozilla::layers::AsyncPanZoomController> sAPZC;
|
||||
static nsRefPtr<mozilla::layers::APZCTreeManager> sAPZC;
|
||||
};
|
||||
|
Loading…
Reference in New Issue
Block a user