зеркало из https://github.com/mozilla/gecko-dev.git
Merge m-c to inbound.
This commit is contained in:
Коммит
fd758076bd
|
@ -30,7 +30,7 @@ LIBS += \
|
||||||
$(DEPTH)/widget/gonk/libdisplay/$(LIB_PREFIX)display.$(LIB_SUFFIX) \
|
$(DEPTH)/widget/gonk/libdisplay/$(LIB_PREFIX)display.$(LIB_SUFFIX) \
|
||||||
$(MOZ_ZLIB_LIBS) \
|
$(MOZ_ZLIB_LIBS) \
|
||||||
$(NULL)
|
$(NULL)
|
||||||
ifeq (17,$(ANDROID_VERSION))
|
ifeq (18,$(ANDROID_VERSION))
|
||||||
LIBS += \
|
LIBS += \
|
||||||
-lgui \
|
-lgui \
|
||||||
-lsuspend \
|
-lsuspend \
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
{
|
{
|
||||||
"revision": "10f16f6a15f8a1c4b910548b4d0968baaac21c91",
|
"revision": "7e8284bea36c2d9307f919090922d3885f67eafc",
|
||||||
"repo_path": "/integration/gaia-central"
|
"repo_path": "/integration/gaia-central"
|
||||||
}
|
}
|
||||||
|
|
|
@ -214,7 +214,7 @@ if test -n "$gonkdir" ; then
|
||||||
AC_DEFINE(MOZ_OMX_DECODER)
|
AC_DEFINE(MOZ_OMX_DECODER)
|
||||||
AC_SUBST(MOZ_OMX_DECODER)
|
AC_SUBST(MOZ_OMX_DECODER)
|
||||||
;;
|
;;
|
||||||
17)
|
18)
|
||||||
GONK_INCLUDES="-I$gonkdir/frameworks/native/include"
|
GONK_INCLUDES="-I$gonkdir/frameworks/native/include"
|
||||||
;;
|
;;
|
||||||
*)
|
*)
|
||||||
|
|
|
@ -45,16 +45,21 @@ const ContentPanning = {
|
||||||
this.watchedEventsType = 'mouse';
|
this.watchedEventsType = 'mouse';
|
||||||
}
|
}
|
||||||
|
|
||||||
let els = Cc["@mozilla.org/eventlistenerservice;1"]
|
// If we are using an AsyncPanZoomController for the parent frame,
|
||||||
.getService(Ci.nsIEventListenerService);
|
// 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) {
|
events.forEach(function(type) {
|
||||||
// Using the system group for mouse/touch events to avoid
|
// Using the system group for mouse/touch events to avoid
|
||||||
// missing events if .stopPropagation() has been called.
|
// missing events if .stopPropagation() has been called.
|
||||||
els.addSystemEventListener(global, type,
|
els.addSystemEventListener(global, type,
|
||||||
this.handleEvent.bind(this),
|
this.handleEvent.bind(this),
|
||||||
/* useCapture = */ false);
|
/* useCapture = */ false);
|
||||||
}.bind(this));
|
}.bind(this));
|
||||||
|
}
|
||||||
|
|
||||||
addMessageListener("Viewport:Change", this._recvViewportChange.bind(this));
|
addMessageListener("Viewport:Change", this._recvViewportChange.bind(this));
|
||||||
addMessageListener("Gesture:DoubleTap", this._recvDoubleTap.bind(this));
|
addMessageListener("Gesture:DoubleTap", this._recvDoubleTap.bind(this));
|
||||||
|
|
|
@ -905,9 +905,6 @@ ContactDB.prototype = {
|
||||||
}
|
}
|
||||||
xIndex++;
|
xIndex++;
|
||||||
}
|
}
|
||||||
if (!x) {
|
|
||||||
return sortOrder == "descending" ? 1 : -1;
|
|
||||||
}
|
|
||||||
while (yIndex < sortBy.length && !y) {
|
while (yIndex < sortBy.length && !y) {
|
||||||
y = b.properties[sortBy[yIndex]];
|
y = b.properties[sortBy[yIndex]];
|
||||||
if (y) {
|
if (y) {
|
||||||
|
@ -915,6 +912,18 @@ ContactDB.prototype = {
|
||||||
}
|
}
|
||||||
yIndex++;
|
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) {
|
if (!y) {
|
||||||
return sortOrder == "ascending" ? 1 : -1;
|
return sortOrder == "ascending" ? 1 : -1;
|
||||||
}
|
}
|
||||||
|
|
|
@ -61,6 +61,24 @@ var c5 = {
|
||||||
nickname: "empty"
|
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 = {
|
var adr1 = {
|
||||||
type: "work",
|
type: "work",
|
||||||
streetAddress: "street 1",
|
streetAddress: "street 1",
|
||||||
|
@ -1338,6 +1356,64 @@ var steps = [
|
||||||
}
|
}
|
||||||
req.onerror = onFailure;
|
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 () {
|
function () {
|
||||||
ok(true, "Adding a new contact with properties2");
|
ok(true, "Adding a new contact with properties2");
|
||||||
createResult2 = new mozContact();
|
createResult2 = new mozContact();
|
||||||
|
|
|
@ -1032,6 +1032,20 @@ TabChild::GetDOMWindowUtils()
|
||||||
return utils.forget();
|
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;
|
static nsInterfaceHashtable<nsPtrHashKey<PContentDialogChild>, nsIDialogParamBlock> gActiveDialogs;
|
||||||
|
|
||||||
NS_IMETHODIMP
|
NS_IMETHODIMP
|
||||||
|
@ -1459,32 +1473,34 @@ TabChild::DispatchMessageManagerMessage(const nsAString& aMessageName,
|
||||||
aMessageName, false, &cloneData, nullptr, nullptr);
|
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
|
bool
|
||||||
TabChild::RecvUpdateFrame(const FrameMetrics& aFrameMetrics)
|
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;
|
uint32_t presShellId;
|
||||||
|
nsCOMPtr<nsIDOMWindowUtils> utils(GetDOMWindowUtils());
|
||||||
nsresult rv = utils->GetPresShellId(&presShellId);
|
nsresult rv = utils->GetPresShellId(&presShellId);
|
||||||
MOZ_ASSERT(NS_SUCCEEDED(rv));
|
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.
|
if (NS_SUCCEEDED(rv) && aFrameMetrics.mPresShellId == presShellId) {
|
||||||
// However we can't reply without painting so we reply by painting the
|
return ProcessUpdateFrame(aFrameMetrics);
|
||||||
// exact same thing as we did before.
|
|
||||||
return ProcessUpdateFrame(mLastMetrics);
|
|
||||||
}
|
}
|
||||||
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
|
bool
|
||||||
|
@ -1533,51 +1549,60 @@ TabChild::ProcessUpdateFrame(const FrameMetrics& aFrameMetrics)
|
||||||
nsCOMPtr<nsIDOMWindowUtils> utils(GetDOMWindowUtils());
|
nsCOMPtr<nsIDOMWindowUtils> utils(GetDOMWindowUtils());
|
||||||
nsCOMPtr<nsIDOMWindow> window = do_GetInterface(mWebNav);
|
nsCOMPtr<nsIDOMWindow> window = do_GetInterface(mWebNav);
|
||||||
|
|
||||||
|
// set the scroll port size, which determines the scroll range
|
||||||
utils->SetScrollPositionClampingScrollPortSize(
|
utils->SetScrollPositionClampingScrollPortSize(
|
||||||
cssCompositedRect.width, cssCompositedRect.height);
|
cssCompositedRect.width, cssCompositedRect.height);
|
||||||
ScrollWindowTo(window, aFrameMetrics.mScrollOffset);
|
|
||||||
LayoutDeviceToLayerScale resolution =
|
// scroll the window to the desired spot
|
||||||
aFrameMetrics.CalculateResolution()
|
nsIScrollableFrame* sf = static_cast<nsGlobalWindow*>(window.get())->GetScrollFrame();
|
||||||
/ aFrameMetrics.mDevPixelsPerCSSPixel
|
if (sf) {
|
||||||
* ScreenToLayerScale(1);
|
sf->ScrollToCSSPixelsApproximate(aFrameMetrics.mScrollOffset);
|
||||||
|
}
|
||||||
|
|
||||||
|
// set the resolution
|
||||||
|
LayoutDeviceToLayerScale resolution = aFrameMetrics.CalculateResolution()
|
||||||
|
/ aFrameMetrics.mDevPixelsPerCSSPixel * ScreenToLayerScale(1);
|
||||||
utils->SetResolution(resolution.scale, resolution.scale);
|
utils->SetResolution(resolution.scale, resolution.scale);
|
||||||
|
|
||||||
if (aFrameMetrics.mScrollId != FrameMetrics::NULL_SCROLL_ID) {
|
// and set the display port
|
||||||
SetDisplayPort(aFrameMetrics);
|
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;
|
mLastMetrics = aFrameMetrics;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
bool
|
||||||
TabChild::SetDisplayPort(const FrameMetrics& aFrameMetrics)
|
TabChild::ProcessUpdateSubframe(nsIContent* aContent,
|
||||||
|
const FrameMetrics& aMetrics)
|
||||||
{
|
{
|
||||||
nsCOMPtr<nsIDOMDocument> domDoc;
|
// scroll the frame to the desired spot
|
||||||
mWebNav->GetDocument(getter_AddRefs(domDoc));
|
nsIScrollableFrame* scrollFrame = nsLayoutUtils::FindScrollableFrameFor(aMetrics.mScrollId);
|
||||||
if (!domDoc) {
|
if (scrollFrame) {
|
||||||
return;
|
scrollFrame->ScrollToCSSPixelsApproximate(aMetrics.mScrollOffset);
|
||||||
}
|
}
|
||||||
|
|
||||||
// nsLayoutUtils::FindContentFor() doesn't provide a look-up for the root
|
nsCOMPtr<nsIDOMWindowUtils> utils(GetDOMWindowUtils(aContent));
|
||||||
// scroll idea. This is because the root scroll ID could refer to a different
|
nsCOMPtr<nsIDOMElement> element = do_QueryInterface(aContent);
|
||||||
// element in the DOM when navigating to a new document.
|
if (utils && element) {
|
||||||
nsCOMPtr<nsIDOMElement> element;
|
// and set the display port
|
||||||
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());
|
|
||||||
utils->SetDisplayPortForElement(
|
utils->SetDisplayPortForElement(
|
||||||
aFrameMetrics.mDisplayPort.x, aFrameMetrics.mDisplayPort.y,
|
aMetrics.mDisplayPort.x, aMetrics.mDisplayPort.y,
|
||||||
aFrameMetrics.mDisplayPort.width, aFrameMetrics.mDisplayPort.height,
|
aMetrics.mDisplayPort.width, aMetrics.mDisplayPort.height,
|
||||||
element);
|
element);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
|
|
|
@ -378,10 +378,7 @@ private:
|
||||||
void DestroyWindow();
|
void DestroyWindow();
|
||||||
void SetProcessNameToAppName();
|
void SetProcessNameToAppName();
|
||||||
bool ProcessUpdateFrame(const mozilla::layers::FrameMetrics& aFrameMetrics);
|
bool ProcessUpdateFrame(const mozilla::layers::FrameMetrics& aFrameMetrics);
|
||||||
|
bool ProcessUpdateSubframe(nsIContent* aContent, const FrameMetrics& aMetrics);
|
||||||
// Update the DOM with the given display port. Finds the element based on
|
|
||||||
// the aFrameMetrics.mScrollId.
|
|
||||||
void SetDisplayPort(const FrameMetrics& aFrameMetrics);
|
|
||||||
|
|
||||||
// Call RecvShow(nsIntSize(0, 0)) and block future calls to RecvShow().
|
// Call RecvShow(nsIntSize(0, 0)) and block future calls to RecvShow().
|
||||||
void DoFakeShow();
|
void DoFakeShow();
|
||||||
|
@ -426,7 +423,11 @@ private:
|
||||||
bool* aWindowIsNew,
|
bool* aWindowIsNew,
|
||||||
nsIDOMWindow** aReturn);
|
nsIDOMWindow** aReturn);
|
||||||
|
|
||||||
|
// Get the DOMWindowUtils for the top-level window in this tab.
|
||||||
already_AddRefed<nsIDOMWindowUtils> GetDOMWindowUtils();
|
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 CachedFileDescriptorInfo;
|
||||||
class CachedFileDescriptorCallbackRunnable;
|
class CachedFileDescriptorCallbackRunnable;
|
||||||
|
|
|
@ -13,5 +13,6 @@ disabled = Bug 808783
|
||||||
[test_mobile_data_location.js]
|
[test_mobile_data_location.js]
|
||||||
[test_mobile_data_state.js]
|
[test_mobile_data_state.js]
|
||||||
[test_mobile_mmi.js]
|
[test_mobile_mmi.js]
|
||||||
|
[test_mobile_roaming_preference.js]
|
||||||
[test_call_barring_get_option.js]
|
[test_call_barring_get_option.js]
|
||||||
[test_call_barring_set_error.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) {
|
if (roamingMode === -1) {
|
||||||
options.errorMsg = GECKO_ERROR_INVALID_PARAMETER;
|
options.errorMsg = GECKO_ERROR_INVALID_PARAMETER;
|
||||||
this.sendDOMMessage(options);
|
this.sendChromeMessage(options);
|
||||||
return;
|
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) {
|
RIL[REQUEST_CDMA_SET_ROAMING_PREFERENCE] = function REQUEST_CDMA_SET_ROAMING_PREFERENCE(length, options) {
|
||||||
if (options.rilRequestError) {
|
if (options.rilRequestError) {
|
||||||
options.errorMsg = RIL_ERROR_TO_GECKO_ERROR[options.rilRequestError];
|
options.errorMsg = RIL_ERROR_TO_GECKO_ERROR[options.rilRequestError];
|
||||||
this.sendDOMMessage(options);
|
this.sendChromeMessage(options);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
this.sendDOMMessage(options);
|
this.sendChromeMessage(options);
|
||||||
};
|
};
|
||||||
RIL[REQUEST_CDMA_QUERY_ROAMING_PREFERENCE] = function REQUEST_CDMA_QUERY_ROAMING_PREFERENCE(length, options) {
|
RIL[REQUEST_CDMA_QUERY_ROAMING_PREFERENCE] = function REQUEST_CDMA_QUERY_ROAMING_PREFERENCE(length, options) {
|
||||||
if (options.rilRequestError) {
|
if (options.rilRequestError) {
|
||||||
options.errorMsg = RIL_ERROR_TO_GECKO_ERROR[options.rilRequestError];
|
options.errorMsg = RIL_ERROR_TO_GECKO_ERROR[options.rilRequestError];
|
||||||
this.sendDOMMessage(options);
|
this.sendChromeMessage(options);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
let mode = Buf.readUint32List();
|
let mode = Buf.readUint32List();
|
||||||
options.mode = CDMA_ROAMING_PREFERENCE_TO_GECKO[mode[0]];
|
options.mode = CDMA_ROAMING_PREFERENCE_TO_GECKO[mode[0]];
|
||||||
this.sendDOMMessage(options);
|
this.sendChromeMessage(options);
|
||||||
};
|
};
|
||||||
RIL[REQUEST_SET_TTY_MODE] = null;
|
RIL[REQUEST_SET_TTY_MODE] = null;
|
||||||
RIL[REQUEST_QUERY_TTY_MODE] = null;
|
RIL[REQUEST_QUERY_TTY_MODE] = null;
|
||||||
|
|
|
@ -86,21 +86,29 @@ this.PduHelper = {
|
||||||
/**
|
/**
|
||||||
* Tag tokens
|
* 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 () {
|
const CP_TAG_FIELDS = (function () {
|
||||||
let names = {};
|
let names = {};
|
||||||
function add(name, number) {
|
function add(name, codepage, number) {
|
||||||
let entry = {
|
let entry = {
|
||||||
name: name,
|
name: name,
|
||||||
number: number,
|
number: number,
|
||||||
};
|
};
|
||||||
names[number] = entry;
|
if (!names[codepage]) {
|
||||||
|
names[codepage] = {};
|
||||||
|
}
|
||||||
|
names[codepage][number] = entry;
|
||||||
}
|
}
|
||||||
|
|
||||||
add("wap-provisioningdoc", 0x05);
|
// Code page 0
|
||||||
add("characteristic", 0x06);
|
add("wap-provisioningdoc", 0, 0x05);
|
||||||
add("parm", 0x07);
|
add("characteristic", 0, 0x06);
|
||||||
|
add("parm", 0, 0x07);
|
||||||
|
// Code page 1
|
||||||
|
add("characteristic", 1, 0x06);
|
||||||
|
add("parm", 1, 0x07);
|
||||||
|
|
||||||
return names;
|
return names;
|
||||||
})();
|
})();
|
||||||
|
@ -108,155 +116,221 @@ const CP_TAG_FIELDS = (function () {
|
||||||
/**
|
/**
|
||||||
* Attribute Tokens
|
* 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 () {
|
const CP_ATTRIBUTE_FIELDS = (function () {
|
||||||
let names = {};
|
let names = {};
|
||||||
function add(name, value, number) {
|
function add(name, value, codepage, number) {
|
||||||
let entry = {
|
let entry = {
|
||||||
name: name,
|
name: name,
|
||||||
value: value,
|
value: value,
|
||||||
number: number,
|
number: number,
|
||||||
};
|
};
|
||||||
names[number] = entry;
|
if (!names[codepage]) {
|
||||||
|
names[codepage] = {};
|
||||||
|
}
|
||||||
|
names[codepage][number] = entry;
|
||||||
}
|
}
|
||||||
|
|
||||||
add("name", "", 0x05);
|
// Code page 0
|
||||||
add("value", "", 0x06);
|
add("name", "", 0, 0x05);
|
||||||
add("name", "NAME", 0x07);
|
add("value", "", 0, 0x06);
|
||||||
add("name", "NAP-ADDRESS", 0x08);
|
add("name", "NAME", 0, 0x07);
|
||||||
add("name", "NAP-ADDRTYPE", 0x09);
|
add("name", "NAP-ADDRESS", 0, 0x08);
|
||||||
add("name", "CALLTYPE", 0x0A);
|
add("name", "NAP-ADDRTYPE", 0, 0x09);
|
||||||
add("name", "VALIDUNTIL", 0x0B);
|
add("name", "CALLTYPE", 0, 0x0A);
|
||||||
add("name", "AUTHTYPE", 0x0C);
|
add("name", "VALIDUNTIL", 0, 0x0B);
|
||||||
add("name", "AUTHNAME", 0x0D);
|
add("name", "AUTHTYPE", 0, 0x0C);
|
||||||
add("name", "AUTHSECRET", 0x0E);
|
add("name", "AUTHNAME", 0, 0x0D);
|
||||||
add("name", "LINGER", 0x0F);
|
add("name", "AUTHSECRET", 0, 0x0E);
|
||||||
add("name", "BEARER", 0x10);
|
add("name", "LINGER", 0, 0x0F);
|
||||||
add("name", "NAPID", 0x11);
|
add("name", "BEARER", 0, 0x10);
|
||||||
add("name", "COUNTRY", 0x12);
|
add("name", "NAPID", 0, 0x11);
|
||||||
add("name", "NETWORK", 0x13);
|
add("name", "COUNTRY", 0, 0x12);
|
||||||
add("name", "INTERNET", 0x14);
|
add("name", "NETWORK", 0, 0x13);
|
||||||
add("name", "PROXY-ID", 0x15);
|
add("name", "INTERNET", 0, 0x14);
|
||||||
add("name", "PROXY-PROVIDER-ID", 0x16);
|
add("name", "PROXY-ID", 0, 0x15);
|
||||||
add("name", "DOMAIN", 0x17);
|
add("name", "PROXY-PROVIDER-ID", 0, 0x16);
|
||||||
add("name", "PROVURL", 0x18);
|
add("name", "DOMAIN", 0, 0x17);
|
||||||
add("name", "PXAUTH-TYPE", 0x19);
|
add("name", "PROVURL", 0, 0x18);
|
||||||
add("name", "PXAUTH-ID", 0x1A);
|
add("name", "PXAUTH-TYPE", 0, 0x19);
|
||||||
add("name", "PXAUTH-PW", 0x1B);
|
add("name", "PXAUTH-ID", 0, 0x1A);
|
||||||
add("name", "STARTPAGE", 0x1C);
|
add("name", "PXAUTH-PW", 0, 0x1B);
|
||||||
add("name", "BASAUTH-ID", 0x1D);
|
add("name", "STARTPAGE", 0, 0x1C);
|
||||||
add("name", "BASAUTH-PW", 0x1E);
|
add("name", "BASAUTH-ID", 0, 0x1D);
|
||||||
add("name", "PUSHENABLED", 0x1F);
|
add("name", "BASAUTH-PW", 0, 0x1E);
|
||||||
add("name", "PXADDR", 0x20);
|
add("name", "PUSHENABLED", 0, 0x1F);
|
||||||
add("name", "PXADDRTYPE", 0x21);
|
add("name", "PXADDR", 0, 0x20);
|
||||||
add("name", "TO-NAPID", 0x22);
|
add("name", "PXADDRTYPE", 0, 0x21);
|
||||||
add("name", "PORTNBR", 0x23);
|
add("name", "TO-NAPID", 0, 0x22);
|
||||||
add("name", "SERVICE", 0x24);
|
add("name", "PORTNBR", 0, 0x23);
|
||||||
add("name", "LINKSPEED", 0x25);
|
add("name", "SERVICE", 0, 0x24);
|
||||||
add("name", "DNLINKSPEED", 0x26);
|
add("name", "LINKSPEED", 0, 0x25);
|
||||||
add("name", "LOCAL-ADDR", 0x27);
|
add("name", "DNLINKSPEED", 0, 0x26);
|
||||||
add("name", "LOCAL-ADDRTYPE", 0x28);
|
add("name", "LOCAL-ADDR", 0, 0x27);
|
||||||
add("name", "CONTEXT-ALLOW", 0x29);
|
add("name", "LOCAL-ADDRTYPE", 0, 0x28);
|
||||||
add("name", "TRUST", 0x2A);
|
add("name", "CONTEXT-ALLOW", 0, 0x29);
|
||||||
add("name", "MASTER", 0x2B);
|
add("name", "TRUST", 0, 0x2A);
|
||||||
add("name", "SID", 0x2C);
|
add("name", "MASTER", 0, 0x2B);
|
||||||
add("name", "SOC", 0x2D);
|
add("name", "SID", 0, 0x2C);
|
||||||
add("name", "WSP-VERSION", 0x2E);
|
add("name", "SOC", 0, 0x2D);
|
||||||
add("name", "PHYSICAL-PROXY-ID", 0x2F);
|
add("name", "WSP-VERSION", 0, 0x2E);
|
||||||
add("name", "CLIENT-ID", 0x30);
|
add("name", "PHYSICAL-PROXY-ID", 0, 0x2F);
|
||||||
add("name", "DELIVERY-ERR-PDU", 0x31);
|
add("name", "CLIENT-ID", 0, 0x30);
|
||||||
add("name", "DELIVERY-ORDER", 0x32);
|
add("name", "DELIVERY-ERR-PDU", 0, 0x31);
|
||||||
add("name", "TRAFFIC-CLASS", 0x33);
|
add("name", "DELIVERY-ORDER", 0, 0x32);
|
||||||
add("name", "MAX-SDU-SIZE", 0x34);
|
add("name", "TRAFFIC-CLASS", 0, 0x33);
|
||||||
add("name", "MAX-BITRATE-UPLINK", 0x35);
|
add("name", "MAX-SDU-SIZE", 0, 0x34);
|
||||||
add("name", "MAX-BITRATE-DNLINK", 0x36);
|
add("name", "MAX-BITRATE-UPLINK", 0, 0x35);
|
||||||
add("name", "RESIDUAL-BER", 0x37);
|
add("name", "MAX-BITRATE-DNLINK", 0, 0x36);
|
||||||
add("name", "SDU-ERROR-RATIO", 0x38);
|
add("name", "RESIDUAL-BER", 0, 0x37);
|
||||||
add("name", "TRAFFIC-HANDL-PRIO", 0x39);
|
add("name", "SDU-ERROR-RATIO", 0, 0x38);
|
||||||
add("name", "TRANSFER-DELAY", 0x3A);
|
add("name", "TRAFFIC-HANDL-PRIO", 0, 0x39);
|
||||||
add("name", "GUARANTEED-BITRATE-UPLINK", 0x3B);
|
add("name", "TRANSFER-DELAY", 0, 0x3A);
|
||||||
add("name", "GUARANTEED-BITRATE-DNLINK", 0x3C);
|
add("name", "GUARANTEED-BITRATE-UPLINK", 0, 0x3B);
|
||||||
add("version", "", 0x45);
|
add("name", "GUARANTEED-BITRATE-DNLINK", 0, 0x3C);
|
||||||
add("version", "1.0", 0x46);
|
add("version", "", 0, 0x45);
|
||||||
add("type", "", 0x50);
|
add("version", "1.0", 0, 0x46);
|
||||||
add("type", "PXLOGICAL", 0x51);
|
add("type", "", 0, 0x50);
|
||||||
add("type", "PXPHYSICAL", 0x52);
|
add("type", "PXLOGICAL", 0, 0x51);
|
||||||
add("type", "PORT", 0x53);
|
add("type", "PXPHYSICAL", 0, 0x52);
|
||||||
add("type", "VALIDITY", 0x54);
|
add("type", "PORT", 0, 0x53);
|
||||||
add("type", "NAPDEF", 0x55);
|
add("type", "VALIDITY", 0, 0x54);
|
||||||
add("type", "BOOTSTRAP", 0x56);
|
add("type", "NAPDEF", 0, 0x55);
|
||||||
|
add("type", "BOOTSTRAP", 0, 0x56);
|
||||||
/*
|
/*
|
||||||
* Mark out VENDORCONFIG so if it is contained in message, parse
|
* Mark out VENDORCONFIG so if it is contained in message, parse
|
||||||
* will failed and raw data is returned.
|
* will failed and raw data is returned.
|
||||||
*/
|
*/
|
||||||
// add("type", "VENDORCONFIG", 0x57);
|
// add("type", "VENDORCONFIG", 0, 0x57);
|
||||||
add("type", "CLIENTIDENTITY", 0x58);
|
add("type", "CLIENTIDENTITY", 0, 0x58);
|
||||||
add("type", "PXAUTHINFO", 0x59);
|
add("type", "PXAUTHINFO", 0, 0x59);
|
||||||
add("type", "NAPAUTHINFO", 0x5A);
|
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;
|
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 () {
|
const CP_VALUE_FIELDS = (function () {
|
||||||
let names = {};
|
let names = {};
|
||||||
function add(value, number) {
|
function add(value, codepage, number) {
|
||||||
let entry = {
|
let entry = {
|
||||||
value: value,
|
value: value,
|
||||||
number: number,
|
number: number,
|
||||||
};
|
};
|
||||||
names[number] = entry;
|
if (!names[codepage]) {
|
||||||
|
names[codepage] = {};
|
||||||
|
}
|
||||||
|
names[codepage][number] = entry;
|
||||||
}
|
}
|
||||||
|
|
||||||
add("IPV4", 0x85);
|
// Code page 0
|
||||||
add("IPV6", 0x86);
|
add("IPV4", 0, 0x85);
|
||||||
add("E164", 0x87);
|
add("IPV6", 0, 0x86);
|
||||||
add("ALPHA", 0x88);
|
add("E164", 0, 0x87);
|
||||||
add("APN", 0x89);
|
add("ALPHA", 0, 0x88);
|
||||||
add("SCODE", 0x8A);
|
add("APN", 0, 0x89);
|
||||||
add("TETRA-ITSI", 0x8B);
|
add("SCODE", 0, 0x8A);
|
||||||
add("MAN", 0x8C);
|
add("TETRA-ITSI", 0, 0x8B);
|
||||||
add("ANALOG-MODEM", 0x90);
|
add("MAN", 0, 0x8C);
|
||||||
add("V.120", 0x91);
|
add("ANALOG-MODEM", 0, 0x90);
|
||||||
add("V.110", 0x92);
|
add("V.120", 0, 0x91);
|
||||||
add("X.31", 0x93);
|
add("V.110", 0, 0x92);
|
||||||
add("BIT-TRANSPARENT", 0x94);
|
add("X.31", 0, 0x93);
|
||||||
add("DIRECT-ASYNCHRONOUS-DATA-SERVICE", 0x95);
|
add("BIT-TRANSPARENT", 0, 0x94);
|
||||||
add("PAP", 0x9A);
|
add("DIRECT-ASYNCHRONOUS-DATA-SERVICE", 0, 0x95);
|
||||||
add("CHAP", 0x9B);
|
add("PAP", 0, 0x9A);
|
||||||
add("HTTP-BASIC", 0x9C);
|
add("CHAP", 0, 0x9B);
|
||||||
add("HTTP-DIGEST", 0x9D);
|
add("HTTP-BASIC", 0, 0x9C);
|
||||||
add("WTLS-SS", 0x9E);
|
add("HTTP-DIGEST", 0, 0x9D);
|
||||||
add("GSM-USSD", 0xA2);
|
add("WTLS-SS", 0, 0x9E);
|
||||||
add("GSM-SMS", 0xA3);
|
add("MD5", 0, 0x9F); // Added in OMA, 7.3.3
|
||||||
add("ANSI-136-GUTS", 0xA4);
|
add("GSM-USSD", 0, 0xA2);
|
||||||
add("IS-95-CDMA-SMS", 0xA5);
|
add("GSM-SMS", 0, 0xA3);
|
||||||
add("IS-95-CDMA-CSD", 0xA6);
|
add("ANSI-136-GUTS", 0, 0xA4);
|
||||||
add("IS-95-CDMA-PAC", 0xA7);
|
add("IS-95-CDMA-SMS", 0, 0xA5);
|
||||||
add("ANSI-136-CSD", 0xA8);
|
add("IS-95-CDMA-CSD", 0, 0xA6);
|
||||||
add("ANSI-136-GPRS", 0xA9);
|
add("IS-95-CDMA-PAC", 0, 0xA7);
|
||||||
add("GSM-CSD", 0xAA);
|
add("ANSI-136-CSD", 0, 0xA8);
|
||||||
add("GSM-GPRS", 0xAB);
|
add("ANSI-136-GPRS", 0, 0xA9);
|
||||||
add("AMPS-CDPD", 0xAC);
|
add("GSM-CSD", 0, 0xAA);
|
||||||
add("PDC-CSD", 0xAD);
|
add("GSM-GPRS", 0, 0xAB);
|
||||||
add("PDC-PACKET", 0xAE);
|
add("AMPS-CDPD", 0, 0xAC);
|
||||||
add("IDEN-SMS", 0xAF);
|
add("PDC-CSD", 0, 0xAD);
|
||||||
add("IDEN-CSD", 0xB0);
|
add("PDC-PACKET", 0, 0xAE);
|
||||||
add("IDEN-PACKET", 0xB1);
|
add("IDEN-SMS", 0, 0xAF);
|
||||||
add("FLEX/REFLEX", 0xB2);
|
add("IDEN-CSD", 0, 0xB0);
|
||||||
add("PHS-SMS", 0xB3);
|
add("IDEN-PACKET", 0, 0xB1);
|
||||||
add("PHS-CSD", 0xB4);
|
add("FLEX/REFLEX", 0, 0xB2);
|
||||||
add("TETRA-SDS", 0xB5);
|
add("PHS-SMS", 0, 0xB3);
|
||||||
add("TETRA-PACKET", 0xB6);
|
add("PHS-CSD", 0, 0xB4);
|
||||||
add("ANSI-136-GHOST", 0xB7);
|
add("TETRA-SDS", 0, 0xB5);
|
||||||
add("MOBITEX-MPAK", 0xB8);
|
add("TETRA-PACKET", 0, 0xB6);
|
||||||
add("AUTOBOUDING", 0xC5);
|
add("ANSI-136-GHOST", 0, 0xB7);
|
||||||
add("CL-WSP", 0xCA);
|
add("MOBITEX-MPAK", 0, 0xB8);
|
||||||
add("CO-WSP", 0xCB);
|
add("CDMA2000-1X-SIMPLE-IP", 0, 0xB9); // Added in OMA, 7.3.4
|
||||||
add("CL-SEC-WSP", 0xCC);
|
add("CDMA2000-1X-MOBILE-IP", 0, 0xBA); // Added in OMA, 7.3.4
|
||||||
add("CO-SEC-WSP", 0xCD);
|
add("AUTOBOUDING", 0, 0xC5);
|
||||||
add("CL-SEC-WTA", 0xCE);
|
add("CL-WSP", 0, 0xCA);
|
||||||
add("CO-SEC-WTA", 0xCF);
|
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;
|
return names;
|
||||||
})();
|
})();
|
||||||
|
|
|
@ -134,18 +134,21 @@ this.PduHelper = {
|
||||||
*/
|
*/
|
||||||
const SI_TAG_FIELDS = (function () {
|
const SI_TAG_FIELDS = (function () {
|
||||||
let names = {};
|
let names = {};
|
||||||
function add(name, number) {
|
function add(name, codepage, number) {
|
||||||
let entry = {
|
let entry = {
|
||||||
name: name,
|
name: name,
|
||||||
number: number,
|
number: number,
|
||||||
};
|
};
|
||||||
names[number] = entry;
|
if (!names[codepage]) {
|
||||||
|
names[codepage] = {};
|
||||||
|
}
|
||||||
|
names[codepage][number] = entry;
|
||||||
}
|
}
|
||||||
|
|
||||||
add("si", 0x05);
|
add("si", 0, 0x05);
|
||||||
add("indication", 0x06);
|
add("indication", 0, 0x06);
|
||||||
add("info", 0x07);
|
add("info", 0, 0x07);
|
||||||
add("item", 0x08);
|
add("item", 0, 0x08);
|
||||||
|
|
||||||
return names;
|
return names;
|
||||||
})();
|
})();
|
||||||
|
@ -157,47 +160,53 @@ const SI_TAG_FIELDS = (function () {
|
||||||
*/
|
*/
|
||||||
const SI_ATTRIBUTE_FIELDS = (function () {
|
const SI_ATTRIBUTE_FIELDS = (function () {
|
||||||
let names = {};
|
let names = {};
|
||||||
function add(name, value, number) {
|
function add(name, value, codepage, number) {
|
||||||
let entry = {
|
let entry = {
|
||||||
name: name,
|
name: name,
|
||||||
value: value,
|
value: value,
|
||||||
number: number,
|
number: number,
|
||||||
};
|
};
|
||||||
names[number] = entry;
|
if (!names[codepage]) {
|
||||||
|
names[codepage] = {};
|
||||||
|
}
|
||||||
|
names[codepage][number] = entry;
|
||||||
}
|
}
|
||||||
|
|
||||||
add("action", "signal-none", 0x05);
|
add("action", "signal-none", 0, 0x05);
|
||||||
add("action", "signal-low", 0x06);
|
add("action", "signal-low", 0, 0x06);
|
||||||
add("action", "signal-medium", 0x07);
|
add("action", "signal-medium", 0, 0x07);
|
||||||
add("action", "signal-high", 0x08);
|
add("action", "signal-high", 0, 0x08);
|
||||||
add("action", "delete", 0x09);
|
add("action", "delete", 0, 0x09);
|
||||||
add("created", "", 0x0A);
|
add("created", "", 0, 0x0A);
|
||||||
add("href", "", 0x0B);
|
add("href", "", 0, 0x0B);
|
||||||
add("href", "http://", 0x0C);
|
add("href", "http://", 0, 0x0C);
|
||||||
add("href", "http://www.", 0x0D);
|
add("href", "http://www.", 0, 0x0D);
|
||||||
add("href", "https://", 0x0E);
|
add("href", "https://", 0, 0x0E);
|
||||||
add("href", "https://www.", 0x0F);
|
add("href", "https://www.", 0, 0x0F);
|
||||||
add("si-expires", "", 0x10);
|
add("si-expires", "", 0, 0x10);
|
||||||
add("si-id", "", 0x11);
|
add("si-id", "", 0, 0x11);
|
||||||
add("class", "", 0x12);
|
add("class", "", 0, 0x12);
|
||||||
|
|
||||||
return names;
|
return names;
|
||||||
})();
|
})();
|
||||||
|
|
||||||
const SI_VALUE_FIELDS = (function () {
|
const SI_VALUE_FIELDS = (function () {
|
||||||
let names = {};
|
let names = {};
|
||||||
function add(value, number) {
|
function add(value, codepage, number) {
|
||||||
let entry = {
|
let entry = {
|
||||||
value: value,
|
value: value,
|
||||||
number: number,
|
number: number,
|
||||||
};
|
};
|
||||||
names[number] = entry;
|
if (!names[codepage]) {
|
||||||
|
names[codepage] = {};
|
||||||
|
}
|
||||||
|
names[codepage][number] = entry;
|
||||||
}
|
}
|
||||||
|
|
||||||
add(".com/", 0x85);
|
add(".com/", 0, 0x85);
|
||||||
add(".edu/", 0x86);
|
add(".edu/", 0, 0x86);
|
||||||
add(".net/", 0x87);
|
add(".net/", 0, 0x87);
|
||||||
add(".org/", 0x88);
|
add(".org/", 0, 0x88);
|
||||||
|
|
||||||
return names;
|
return names;
|
||||||
})();
|
})();
|
||||||
|
|
|
@ -90,15 +90,18 @@ this.PduHelper = {
|
||||||
*/
|
*/
|
||||||
const SL_TAG_FIELDS = (function () {
|
const SL_TAG_FIELDS = (function () {
|
||||||
let names = {};
|
let names = {};
|
||||||
function add(name, number) {
|
function add(name, codepage, number) {
|
||||||
let entry = {
|
let entry = {
|
||||||
name: name,
|
name: name,
|
||||||
number: number,
|
number: number,
|
||||||
};
|
};
|
||||||
names[number] = entry;
|
if (!names[codepage]) {
|
||||||
|
names[codepage] = {};
|
||||||
|
}
|
||||||
|
names[codepage][number] = entry;
|
||||||
}
|
}
|
||||||
|
|
||||||
add("sl", 0x05);
|
add("sl", 0, 0x05);
|
||||||
|
|
||||||
return names;
|
return names;
|
||||||
})();
|
})();
|
||||||
|
@ -110,41 +113,47 @@ const SL_TAG_FIELDS = (function () {
|
||||||
*/
|
*/
|
||||||
const SL_ATTRIBUTE_FIELDS = (function () {
|
const SL_ATTRIBUTE_FIELDS = (function () {
|
||||||
let names = {};
|
let names = {};
|
||||||
function add(name, value, number) {
|
function add(name, value, codepage, number) {
|
||||||
let entry = {
|
let entry = {
|
||||||
name: name,
|
name: name,
|
||||||
value: value,
|
value: value,
|
||||||
number: number,
|
number: number,
|
||||||
};
|
};
|
||||||
names[number] = entry;
|
if (!names[codepage]) {
|
||||||
|
names[codepage] = {};
|
||||||
|
}
|
||||||
|
names[codepage][number] = entry;
|
||||||
}
|
}
|
||||||
|
|
||||||
add("action", "execute-low", 0x05);
|
add("action", "execute-low", 0, 0x05);
|
||||||
add("action", "execute-high", 0x06);
|
add("action", "execute-high", 0, 0x06);
|
||||||
add("action", "cache", 0x07);
|
add("action", "cache", 0, 0x07);
|
||||||
add("href", "", 0x08);
|
add("href", "", 0, 0x08);
|
||||||
add("href", "http://", 0x09);
|
add("href", "http://", 0, 0x09);
|
||||||
add("href", "http://www.", 0x0A);
|
add("href", "http://www.", 0, 0x0A);
|
||||||
add("href", "https://", 0x0B);
|
add("href", "https://", 0, 0x0B);
|
||||||
add("href", "https://www.", 0x0C);
|
add("href", "https://www.", 0, 0x0C);
|
||||||
|
|
||||||
return names;
|
return names;
|
||||||
})();
|
})();
|
||||||
|
|
||||||
const SL_VALUE_FIELDS = (function () {
|
const SL_VALUE_FIELDS = (function () {
|
||||||
let names = {};
|
let names = {};
|
||||||
function add(value, number) {
|
function add(value, codepage, number) {
|
||||||
let entry = {
|
let entry = {
|
||||||
value: value,
|
value: value,
|
||||||
number: number,
|
number: number,
|
||||||
};
|
};
|
||||||
names[number] = entry;
|
if (!names[codepage]) {
|
||||||
|
names[codepage] = {};
|
||||||
|
}
|
||||||
|
names[codepage][number] = entry;
|
||||||
}
|
}
|
||||||
|
|
||||||
add(".com/", 0x85);
|
add(".com/", 0, 0x85);
|
||||||
add(".edu/", 0x86);
|
add(".edu/", 0, 0x86);
|
||||||
add(".net/", 0x87);
|
add(".net/", 0, 0x87);
|
||||||
add(".org/", 0x88);
|
add(".org/", 0, 0x88);
|
||||||
|
|
||||||
return names;
|
return names;
|
||||||
})();
|
})();
|
||||||
|
|
|
@ -62,8 +62,8 @@ this.WapPushManager = {
|
||||||
|
|
||||||
let appid = options.headers["x-wap-application-id"];
|
let appid = options.headers["x-wap-application-id"];
|
||||||
if (!appid) {
|
if (!appid) {
|
||||||
|
// Assume message without applicatioin ID is WAP Push
|
||||||
debug("Push message doesn't contains X-Wap-Application-Id.");
|
debug("Push message doesn't contains X-Wap-Application-Id.");
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// MMS
|
// MMS
|
||||||
|
|
|
@ -23,6 +23,7 @@ const TAG_TOKEN_VALUE_MASK = 0x3F;
|
||||||
*
|
*
|
||||||
* @see WAP-192-WBXML-20010725-A, clause 7.1
|
* @see WAP-192-WBXML-20010725-A, clause 7.1
|
||||||
*/
|
*/
|
||||||
|
const CODE_PAGE_SWITCH_TOKEN = 0x00;
|
||||||
const TAG_END_TOKEN = 0x01;
|
const TAG_END_TOKEN = 0x01;
|
||||||
const INLINE_STRING_TOKEN = 0x03;
|
const INLINE_STRING_TOKEN = 0x03;
|
||||||
const STRING_TABLE_TOKEN = 0x83;
|
const STRING_TABLE_TOKEN = 0x83;
|
||||||
|
@ -34,11 +35,53 @@ this.DEBUG_ALL = false;
|
||||||
// Enable debug message for WBXML decoder core.
|
// Enable debug message for WBXML decoder core.
|
||||||
this.DEBUG = DEBUG_ALL | false;
|
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.
|
* Parse end WBXML encoded message.
|
||||||
*
|
*
|
||||||
* @param data
|
* @param data
|
||||||
* A wrapped object containing raw PDU 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
|
* @see WAP-192-WBXML-20010725-A, clause 5.8.4.7.1
|
||||||
*
|
*
|
||||||
|
@ -84,6 +127,8 @@ this.WbxmlStringTable = {
|
||||||
*
|
*
|
||||||
* @param data
|
* @param data
|
||||||
* A wrapped object containing raw PDU 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
|
* @see WAP-192-WBXML-20010725-A, clause 5.8.4.1
|
||||||
*
|
*
|
||||||
|
@ -106,6 +151,8 @@ this.WbxmlInlineString = {
|
||||||
*
|
*
|
||||||
* @param data
|
* @param data
|
||||||
* A wrapped object containing raw PDU 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
|
* @see WAP-192-WBXML-20010725-A, clause 5.8.4.6
|
||||||
*
|
*
|
||||||
|
@ -135,11 +182,20 @@ this.PduHelper = {
|
||||||
parseWbxml: function parseWbxml_wbxml(data, decodeInfo, appToken) {
|
parseWbxml: function parseWbxml_wbxml(data, decodeInfo, appToken) {
|
||||||
|
|
||||||
// Parse token definition to my structure.
|
// Parse token definition to my structure.
|
||||||
let tagTokenList = appToken.tagTokenList;
|
decodeInfo.tokenList = {
|
||||||
let attrTokenList = appToken.attrTokenList;
|
tag: appToken.tagTokenList,
|
||||||
let valueTokenList = appToken.valueTokenList;
|
attr: appToken.attrTokenList,
|
||||||
|
value: appToken.valueTokenList
|
||||||
decodeInfo.tagStack = []; // tag decode stack
|
};
|
||||||
|
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
|
// Merge global tag tokens into single list, so we don't have
|
||||||
// to search two lists every time.
|
// 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
|
// Decode content, might be a new tag token, an end of tag token, or an
|
||||||
// inline string.
|
// inline string.
|
||||||
|
|
||||||
|
// Switch to tag domain
|
||||||
|
decodeInfo.currentState = "tag";
|
||||||
|
|
||||||
let tagToken = WSP.Octet.decode(data);
|
let tagToken = WSP.Octet.decode(data);
|
||||||
let tagTokenValue = tagToken & TAG_TOKEN_VALUE_MASK;
|
let tagTokenValue = tagToken & TAG_TOKEN_VALUE_MASK;
|
||||||
|
|
||||||
|
@ -170,7 +229,7 @@ this.PduHelper = {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check if application tag token is valid
|
// Check if application tag token is valid
|
||||||
tagInfo = tagTokenList[tagTokenValue];
|
tagInfo = decodeInfo.currentTokenList.tag[tagTokenValue];
|
||||||
if (!tagInfo) {
|
if (!tagInfo) {
|
||||||
throw new Error("Unsupported WBXML token: " + tagTokenValue + ".");
|
throw new Error("Unsupported WBXML token: " + tagTokenValue + ".");
|
||||||
}
|
}
|
||||||
|
@ -181,6 +240,9 @@ this.PduHelper = {
|
||||||
// Decode attributes, might be a new attribute token, a value token,
|
// Decode attributes, might be a new attribute token, a value token,
|
||||||
// or an inline string
|
// or an inline string
|
||||||
|
|
||||||
|
// Switch to attr/value domain
|
||||||
|
decodeInfo.currentState = "attr";
|
||||||
|
|
||||||
let attrSeperator = "";
|
let attrSeperator = "";
|
||||||
while (data.offset < data.array.length) {
|
while (data.offset < data.array.length) {
|
||||||
let attrToken = WSP.Octet.decode(data);
|
let attrToken = WSP.Octet.decode(data);
|
||||||
|
@ -195,14 +257,14 @@ this.PduHelper = {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check if attribute token is valid
|
// Check if attribute token is valid
|
||||||
attrInfo = attrTokenList[attrToken];
|
attrInfo = decodeInfo.currentTokenList.attr[attrToken];
|
||||||
if (attrInfo) {
|
if (attrInfo) {
|
||||||
content += attrSeperator + " " + attrInfo.name + "=\"" + attrInfo.value;
|
content += attrSeperator + " " + attrInfo.name + "=\"" + attrInfo.value;
|
||||||
attrSeperator = "\"";
|
attrSeperator = "\"";
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
attrInfo = valueTokenList[attrToken];
|
attrInfo = decodeInfo.currentTokenList.value[attrToken];
|
||||||
if (attrInfo) {
|
if (attrInfo) {
|
||||||
content += attrInfo.value;
|
content += attrInfo.value;
|
||||||
continue;
|
continue;
|
||||||
|
@ -325,10 +387,11 @@ const WBXML_GLOBAL_TOKENS = (function () {
|
||||||
names[number] = entry;
|
names[number] = entry;
|
||||||
}
|
}
|
||||||
|
|
||||||
add(TAG_END_TOKEN, WbxmlEnd);
|
add(CODE_PAGE_SWITCH_TOKEN, WbxmlCodePageSwitch);
|
||||||
add(INLINE_STRING_TOKEN, WbxmlInlineString);
|
add(TAG_END_TOKEN, WbxmlEnd);
|
||||||
add(STRING_TABLE_TOKEN, WbxmlStringTable);
|
add(INLINE_STRING_TOKEN, WbxmlInlineString);
|
||||||
add(OPAQUE_TOKEN, WbxmlOpaque);
|
add(STRING_TABLE_TOKEN, WbxmlStringTable);
|
||||||
|
add(OPAQUE_TOKEN, WbxmlOpaque);
|
||||||
|
|
||||||
return names;
|
return names;
|
||||||
})();
|
})();
|
||||||
|
|
|
@ -357,3 +357,143 @@ add_test(function test_cp_parse_wbxml() {
|
||||||
|
|
||||||
run_next_test();
|
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::sBackend = LAYERS_NONE;
|
||||||
/* static */ LayersBackend
|
/* static */ LayersBackend
|
||||||
Compositor::GetBackend()
|
Compositor::GetBackend()
|
||||||
|
{
|
||||||
|
AssertOnCompositorThread();
|
||||||
|
return sBackend;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* static */ void
|
||||||
|
Compositor::AssertOnCompositorThread()
|
||||||
{
|
{
|
||||||
MOZ_ASSERT(CompositorParent::CompositorLoop() ==
|
MOZ_ASSERT(CompositorParent::CompositorLoop() ==
|
||||||
MessageLoop::current(),
|
MessageLoop::current(),
|
||||||
"Can only call this from the compositor thread!");
|
"Can only call this from the compositor thread!");
|
||||||
return sBackend;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
|
|
@ -398,6 +398,12 @@ public:
|
||||||
virtual nsIWidget* GetWidget() const { return nullptr; }
|
virtual nsIWidget* GetWidget() const { return nullptr; }
|
||||||
virtual const nsIntSize& GetWidgetSize() = 0;
|
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
|
* 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
|
* thread at the same time. The backend type in use can be checked with this
|
||||||
|
|
|
@ -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;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
|
@ -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 (RefLayer* ref = aLayer->AsRefLayer()) {
|
||||||
if (const CompositorParent::LayerTreeState* state = CompositorParent::GetIndirectShadowTree(ref->GetReferentId())) {
|
if (const CompositorParent::LayerTreeState* state = CompositorParent::GetIndirectShadowTree(ref->GetReferentId())) {
|
||||||
if (Layer* referent = state->mRoot) {
|
if (Layer* referent = state->mRoot) {
|
||||||
ContainerLayer *referentAsContainer = referent->AsContainerLayer();
|
|
||||||
if (!ref->GetVisibleRegion().IsEmpty()) {
|
if (!ref->GetVisibleRegion().IsEmpty()) {
|
||||||
ScreenOrientation chromeOrientation = aTargetConfig.orientation();
|
ScreenOrientation chromeOrientation = aTargetConfig.orientation();
|
||||||
ScreenOrientation contentOrientation = state->mTargetConfig.orientation();
|
ScreenOrientation contentOrientation = state->mTargetConfig.orientation();
|
||||||
|
@ -63,16 +62,8 @@ WalkTheTree(Layer* aLayer,
|
||||||
|
|
||||||
if (OP == Resolve) {
|
if (OP == Resolve) {
|
||||||
ref->ConnectReferentLayer(referent);
|
ref->ConnectReferentLayer(referent);
|
||||||
if (referentAsContainer) {
|
|
||||||
if (AsyncPanZoomController* apzc = state->mController) {
|
|
||||||
referentAsContainer->SetAsyncPanZoomController(apzc);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
ref->DetachReferentLayer(referent);
|
ref->DetachReferentLayer(referent);
|
||||||
if (referentAsContainer) {
|
|
||||||
referentAsContainer->SetAsyncPanZoomController(nullptr);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -437,7 +428,6 @@ AsyncCompositionManager::ApplyAsyncContentTransformToTree(TimeStamp aCurrentFram
|
||||||
ScreenPoint scrollOffset;
|
ScreenPoint scrollOffset;
|
||||||
*aWantNextFrame |=
|
*aWantNextFrame |=
|
||||||
controller->SampleContentTransformForFrame(aCurrentFrame,
|
controller->SampleContentTransformForFrame(aCurrentFrame,
|
||||||
container,
|
|
||||||
&treeTransform,
|
&treeTransform,
|
||||||
scrollOffset);
|
scrollOffset);
|
||||||
|
|
||||||
|
|
|
@ -106,6 +106,18 @@ static float gYSkateSizeMultiplier = 3.5f;
|
||||||
static float gXStationarySizeMultiplier = 1.5f;
|
static float gXStationarySizeMultiplier = 1.5f;
|
||||||
static float gYStationarySizeMultiplier = 2.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 sFrameTime;
|
||||||
|
|
||||||
static TimeStamp
|
static TimeStamp
|
||||||
|
@ -121,8 +133,16 @@ AsyncPanZoomController::SetFrameTime(const TimeStamp& aTime) {
|
||||||
sFrameTime = 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(&gPanRepaintInterval, "gfx.azpc.pan_repaint_interval", gPanRepaintInterval);
|
||||||
Preferences::AddIntVarCache(&gFlingRepaintInterval, "gfx.azpc.fling_repaint_interval", gFlingRepaintInterval);
|
Preferences::AddIntVarCache(&gFlingRepaintInterval, "gfx.azpc.fling_repaint_interval", gFlingRepaintInterval);
|
||||||
Preferences::AddFloatVarCache(&gMinSkateSpeed, "gfx.azpc.min_skate_speed", gMinSkateSpeed);
|
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(&gYSkateSizeMultiplier, "gfx.azpc.y_skate_size_multiplier", gYSkateSizeMultiplier);
|
||||||
Preferences::AddFloatVarCache(&gXStationarySizeMultiplier, "gfx.azpc.x_stationary_size_multiplier", gXStationarySizeMultiplier);
|
Preferences::AddFloatVarCache(&gXStationarySizeMultiplier, "gfx.azpc.x_stationary_size_multiplier", gXStationarySizeMultiplier);
|
||||||
Preferences::AddFloatVarCache(&gYStationarySizeMultiplier, "gfx.azpc.y_stationary_size_multiplier", gYStationarySizeMultiplier);
|
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 {
|
AsyncPanZoomController::AsyncPanZoomController(uint64_t aLayersId,
|
||||||
public:
|
GeckoContentController* aGeckoContentController,
|
||||||
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,
|
|
||||||
GestureBehavior aGestures)
|
GestureBehavior aGestures)
|
||||||
: mPaintThrottler(GetFrameTime()),
|
: mLayersId(aLayersId),
|
||||||
|
mPaintThrottler(GetFrameTime()),
|
||||||
mGeckoContentController(aGeckoContentController),
|
mGeckoContentController(aGeckoContentController),
|
||||||
|
mRefPtrMonitor("RefPtrMonitor"),
|
||||||
mTouchListenerTimeoutTask(nullptr),
|
mTouchListenerTimeoutTask(nullptr),
|
||||||
mX(this),
|
mX(this),
|
||||||
mY(this),
|
mY(this),
|
||||||
|
@ -176,45 +182,48 @@ AsyncPanZoomController::AsyncPanZoomController(GeckoContentController* aGeckoCon
|
||||||
mLastAsyncScrollOffset(0, 0),
|
mLastAsyncScrollOffset(0, 0),
|
||||||
mCurrentAsyncScrollOffset(0, 0),
|
mCurrentAsyncScrollOffset(0, 0),
|
||||||
mAsyncScrollTimeoutTask(nullptr),
|
mAsyncScrollTimeoutTask(nullptr),
|
||||||
mAsyncScrollThrottleTime(100),
|
|
||||||
mAsyncScrollTimeout(300),
|
|
||||||
mDPI(72),
|
mDPI(72),
|
||||||
mDisableNextTouchBatch(false),
|
mDisableNextTouchBatch(false),
|
||||||
mHandlingTouchQueue(false),
|
mHandlingTouchQueue(false),
|
||||||
mDelayPanning(false)
|
mDelayPanning(false)
|
||||||
{
|
{
|
||||||
MOZ_ASSERT(NS_IsMainThread());
|
|
||||||
MOZ_COUNT_CTOR(AsyncPanZoomController);
|
MOZ_COUNT_CTOR(AsyncPanZoomController);
|
||||||
|
|
||||||
InitAZPCPrefs();
|
|
||||||
|
|
||||||
if (aGestures == USE_GESTURE_DETECTOR) {
|
if (aGestures == USE_GESTURE_DETECTOR) {
|
||||||
mGestureEventListener = new GestureEventListener(this);
|
mGestureEventListener = new GestureEventListener(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
SetDPI(mDPI);
|
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() {
|
AsyncPanZoomController::~AsyncPanZoomController() {
|
||||||
MOZ_COUNT_DTOR(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
|
void
|
||||||
AsyncPanZoomController::Destroy()
|
AsyncPanZoomController::Destroy()
|
||||||
{
|
{
|
||||||
// These memebrs can only be used on the controller/UI thread.
|
{ // scope the lock
|
||||||
mGeckoContentController = nullptr;
|
MonitorAutoLock lock(mRefPtrMonitor);
|
||||||
mGestureEventListener = nullptr;
|
mGeckoContentController = nullptr;
|
||||||
|
mGestureEventListener = nullptr;
|
||||||
|
}
|
||||||
|
mPrevSibling = nullptr;
|
||||||
|
mLastChild = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* static */float
|
/* static */float
|
||||||
|
@ -332,8 +341,9 @@ nsEventStatus AsyncPanZoomController::ReceiveInputEvent(const InputData& aEvent)
|
||||||
nsEventStatus AsyncPanZoomController::HandleInputEvent(const InputData& aEvent) {
|
nsEventStatus AsyncPanZoomController::HandleInputEvent(const InputData& aEvent) {
|
||||||
nsEventStatus rv = nsEventStatus_eIgnore;
|
nsEventStatus rv = nsEventStatus_eIgnore;
|
||||||
|
|
||||||
if (mGestureEventListener && !mDisableNextTouchBatch) {
|
nsRefPtr<GestureEventListener> listener = GetGestureEventListener();
|
||||||
rv = mGestureEventListener->HandleInputEvent(aEvent);
|
if (listener && !mDisableNextTouchBatch) {
|
||||||
|
rv = listener->HandleInputEvent(aEvent);
|
||||||
if (rv == nsEventStatus_eConsumeNoDefault)
|
if (rv == nsEventStatus_eConsumeNoDefault)
|
||||||
return rv;
|
return rv;
|
||||||
}
|
}
|
||||||
|
@ -659,12 +669,13 @@ nsEventStatus AsyncPanZoomController::OnScaleEnd(const PinchGestureInput& aEvent
|
||||||
}
|
}
|
||||||
|
|
||||||
nsEventStatus AsyncPanZoomController::OnLongPress(const TapGestureInput& aEvent) {
|
nsEventStatus AsyncPanZoomController::OnLongPress(const TapGestureInput& aEvent) {
|
||||||
if (mGeckoContentController) {
|
nsRefPtr<GeckoContentController> controller = GetGeckoContentController();
|
||||||
|
if (controller) {
|
||||||
MonitorAutoLock monitor(mMonitor);
|
MonitorAutoLock monitor(mMonitor);
|
||||||
|
|
||||||
CSSToScreenScale resolution = mFrameMetrics.CalculateResolution();
|
CSSToScreenScale resolution = mFrameMetrics.CalculateResolution();
|
||||||
CSSPoint point = WidgetSpaceToCompensatedViewportSpace(aEvent.mPoint, resolution);
|
CSSPoint point = WidgetSpaceToCompensatedViewportSpace(aEvent.mPoint, resolution);
|
||||||
mGeckoContentController->HandleLongTap(gfx::RoundedToInt(point));
|
controller->HandleLongTap(gfx::RoundedToInt(point));
|
||||||
return nsEventStatus_eConsumeNoDefault;
|
return nsEventStatus_eConsumeNoDefault;
|
||||||
}
|
}
|
||||||
return nsEventStatus_eIgnore;
|
return nsEventStatus_eIgnore;
|
||||||
|
@ -675,25 +686,27 @@ nsEventStatus AsyncPanZoomController::OnSingleTapUp(const TapGestureInput& aEven
|
||||||
}
|
}
|
||||||
|
|
||||||
nsEventStatus AsyncPanZoomController::OnSingleTapConfirmed(const TapGestureInput& aEvent) {
|
nsEventStatus AsyncPanZoomController::OnSingleTapConfirmed(const TapGestureInput& aEvent) {
|
||||||
if (mGeckoContentController) {
|
nsRefPtr<GeckoContentController> controller = GetGeckoContentController();
|
||||||
|
if (controller) {
|
||||||
MonitorAutoLock monitor(mMonitor);
|
MonitorAutoLock monitor(mMonitor);
|
||||||
|
|
||||||
CSSToScreenScale resolution = mFrameMetrics.CalculateResolution();
|
CSSToScreenScale resolution = mFrameMetrics.CalculateResolution();
|
||||||
CSSPoint point = WidgetSpaceToCompensatedViewportSpace(aEvent.mPoint, resolution);
|
CSSPoint point = WidgetSpaceToCompensatedViewportSpace(aEvent.mPoint, resolution);
|
||||||
mGeckoContentController->HandleSingleTap(gfx::RoundedToInt(point));
|
controller->HandleSingleTap(gfx::RoundedToInt(point));
|
||||||
return nsEventStatus_eConsumeNoDefault;
|
return nsEventStatus_eConsumeNoDefault;
|
||||||
}
|
}
|
||||||
return nsEventStatus_eIgnore;
|
return nsEventStatus_eIgnore;
|
||||||
}
|
}
|
||||||
|
|
||||||
nsEventStatus AsyncPanZoomController::OnDoubleTap(const TapGestureInput& aEvent) {
|
nsEventStatus AsyncPanZoomController::OnDoubleTap(const TapGestureInput& aEvent) {
|
||||||
if (mGeckoContentController) {
|
nsRefPtr<GeckoContentController> controller = GetGeckoContentController();
|
||||||
|
if (controller) {
|
||||||
MonitorAutoLock monitor(mMonitor);
|
MonitorAutoLock monitor(mMonitor);
|
||||||
|
|
||||||
if (mAllowZoom) {
|
if (mAllowZoom) {
|
||||||
CSSToScreenScale resolution = mFrameMetrics.CalculateResolution();
|
CSSToScreenScale resolution = mFrameMetrics.CalculateResolution();
|
||||||
CSSPoint point = WidgetSpaceToCompensatedViewportSpace(aEvent.mPoint, resolution);
|
CSSPoint point = WidgetSpaceToCompensatedViewportSpace(aEvent.mPoint, resolution);
|
||||||
mGeckoContentController->HandleDoubleTap(gfx::RoundedToInt(point));
|
controller->HandleDoubleTap(gfx::RoundedToInt(point));
|
||||||
}
|
}
|
||||||
|
|
||||||
return nsEventStatus_eConsumeNoDefault;
|
return nsEventStatus_eConsumeNoDefault;
|
||||||
|
@ -1019,12 +1032,15 @@ void AsyncPanZoomController::RequestContentRepaint() {
|
||||||
// This message is compressed, so fire whether or not we already have a paint
|
// 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,
|
// queued up. We need to know whether or not a paint was requested anyways,
|
||||||
// for the purposes of content calling window.scrollTo().
|
// for the purposes of content calling window.scrollTo().
|
||||||
mPaintThrottler.PostTask(
|
nsRefPtr<GeckoContentController> controller = GetGeckoContentController();
|
||||||
FROM_HERE,
|
if (controller) {
|
||||||
NewRunnableMethod(mGeckoContentController.get(),
|
mPaintThrottler.PostTask(
|
||||||
&GeckoContentController::RequestContentRepaint,
|
FROM_HERE,
|
||||||
mFrameMetrics),
|
NewRunnableMethod(controller.get(),
|
||||||
GetFrameTime());
|
&GeckoContentController::RequestContentRepaint,
|
||||||
|
mFrameMetrics),
|
||||||
|
GetFrameTime());
|
||||||
|
}
|
||||||
mFrameMetrics.mPresShellId = mLastContentPaintMetrics.mPresShellId;
|
mFrameMetrics.mPresShellId = mLastContentPaintMetrics.mPresShellId;
|
||||||
mLastPaintRequestMetrics = mFrameMetrics;
|
mLastPaintRequestMetrics = mFrameMetrics;
|
||||||
|
|
||||||
|
@ -1043,7 +1059,6 @@ AsyncPanZoomController::FireAsyncScrollOnTimeout()
|
||||||
}
|
}
|
||||||
|
|
||||||
bool AsyncPanZoomController::SampleContentTransformForFrame(const TimeStamp& aSampleTime,
|
bool AsyncPanZoomController::SampleContentTransformForFrame(const TimeStamp& aSampleTime,
|
||||||
ContainerLayer* aLayer,
|
|
||||||
ViewTransform* aNewTransform,
|
ViewTransform* aNewTransform,
|
||||||
ScreenPoint& aScrollOffset) {
|
ScreenPoint& aScrollOffset) {
|
||||||
// The eventual return value of this function. The compositor needs to know
|
// 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.
|
// responsibility to schedule a composite.
|
||||||
bool requestAnimationFrame = false;
|
bool requestAnimationFrame = false;
|
||||||
|
|
||||||
LayerPoint metricsScrollOffset;
|
|
||||||
CSSPoint scrollOffset;
|
|
||||||
CSSToScreenScale localScale;
|
|
||||||
const FrameMetrics& frame = aLayer->GetFrameMetrics();
|
|
||||||
{
|
{
|
||||||
MonitorAutoLock mon(mMonitor);
|
MonitorAutoLock mon(mMonitor);
|
||||||
|
|
||||||
|
@ -1103,17 +1114,9 @@ bool AsyncPanZoomController::SampleContentTransformForFrame(const TimeStamp& aSa
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Current local transform; this is not what's painted but rather
|
aScrollOffset = mFrameMetrics.mScrollOffset * mFrameMetrics.CalculateResolution();
|
||||||
// what PZC has transformed due to touches like panning or
|
*aNewTransform = GetCurrentAsyncTransformInternal();
|
||||||
// pinching. Eventually, the root layer transform will become this
|
|
||||||
// during runtime, but we must wait for Gecko to repaint.
|
|
||||||
localScale = mFrameMetrics.CalculateResolution();
|
|
||||||
|
|
||||||
if (frame.IsScrollable()) {
|
|
||||||
metricsScrollOffset = frame.GetScrollOffsetInLayerPixels();
|
|
||||||
}
|
|
||||||
|
|
||||||
scrollOffset = mFrameMetrics.mScrollOffset;
|
|
||||||
mCurrentAsyncScrollOffset = mFrameMetrics.mScrollOffset;
|
mCurrentAsyncScrollOffset = mFrameMetrics.mScrollOffset;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1129,7 +1132,7 @@ bool AsyncPanZoomController::SampleContentTransformForFrame(const TimeStamp& aSa
|
||||||
// with the last event.
|
// with the last event.
|
||||||
// Otherwise, start a timer to fire the event sAsyncScrollTimeout ms from now.
|
// Otherwise, start a timer to fire the event sAsyncScrollTimeout ms from now.
|
||||||
TimeDuration delta = aSampleTime - mLastAsyncScrollTime;
|
TimeDuration delta = aSampleTime - mLastAsyncScrollTime;
|
||||||
if (delta.ToMilliseconds() > mAsyncScrollThrottleTime &&
|
if (delta.ToMilliseconds() > gAsyncScrollThrottleTime &&
|
||||||
mCurrentAsyncScrollOffset != mLastAsyncScrollOffset) {
|
mCurrentAsyncScrollOffset != mLastAsyncScrollOffset) {
|
||||||
MonitorAutoLock monitor(mMonitor);
|
MonitorAutoLock monitor(mMonitor);
|
||||||
mLastAsyncScrollTime = aSampleTime;
|
mLastAsyncScrollTime = aSampleTime;
|
||||||
|
@ -1141,25 +1144,35 @@ bool AsyncPanZoomController::SampleContentTransformForFrame(const TimeStamp& aSa
|
||||||
NewRunnableMethod(this, &AsyncPanZoomController::FireAsyncScrollOnTimeout);
|
NewRunnableMethod(this, &AsyncPanZoomController::FireAsyncScrollOnTimeout);
|
||||||
MessageLoop::current()->PostDelayedTask(FROM_HERE,
|
MessageLoop::current()->PostDelayedTask(FROM_HERE,
|
||||||
mAsyncScrollTimeoutTask,
|
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;
|
mLastSampleTime = aSampleTime;
|
||||||
|
|
||||||
return requestAnimationFrame;
|
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);
|
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
|
// TODO: Once a mechanism for calling UpdateScrollOffset() when content does
|
||||||
// a scrollTo() is implemented for B2G (bug 895905), this block can be removed.
|
// 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 FLING:
|
||||||
case TOUCHING:
|
case TOUCHING:
|
||||||
case WAITING_LISTENERS:
|
case WAITING_LISTENERS:
|
||||||
mFrameMetrics.mScrollOffset = aViewportFrame.mScrollOffset;
|
mFrameMetrics.mScrollOffset = aLayerMetrics.mScrollOffset;
|
||||||
break;
|
break;
|
||||||
// Don't clobber if we're in other states.
|
// Don't clobber if we're in other states.
|
||||||
default:
|
default:
|
||||||
|
@ -1187,12 +1200,12 @@ void AsyncPanZoomController::NotifyLayersUpdated(const FrameMetrics& aViewportFr
|
||||||
|
|
||||||
mPaintThrottler.TaskComplete(GetFrameTime());
|
mPaintThrottler.TaskComplete(GetFrameTime());
|
||||||
bool needContentRepaint = false;
|
bool needContentRepaint = false;
|
||||||
if (aViewportFrame.mCompositionBounds.width == mFrameMetrics.mCompositionBounds.width &&
|
if (aLayerMetrics.mCompositionBounds.width == mFrameMetrics.mCompositionBounds.width &&
|
||||||
aViewportFrame.mCompositionBounds.height == mFrameMetrics.mCompositionBounds.height) {
|
aLayerMetrics.mCompositionBounds.height == mFrameMetrics.mCompositionBounds.height) {
|
||||||
// Remote content has sync'd up to the composition geometry
|
// Remote content has sync'd up to the composition geometry
|
||||||
// change, so we can accept the viewport it's calculated.
|
// change, so we can accept the viewport it's calculated.
|
||||||
CSSToScreenScale previousResolution = mFrameMetrics.CalculateResolution();
|
CSSToScreenScale previousResolution = mFrameMetrics.CalculateResolution();
|
||||||
mFrameMetrics.mViewport = aViewportFrame.mViewport;
|
mFrameMetrics.mViewport = aLayerMetrics.mViewport;
|
||||||
CSSToScreenScale newResolution = mFrameMetrics.CalculateResolution();
|
CSSToScreenScale newResolution = mFrameMetrics.CalculateResolution();
|
||||||
needContentRepaint |= (previousResolution != newResolution);
|
needContentRepaint |= (previousResolution != newResolution);
|
||||||
}
|
}
|
||||||
|
@ -1204,11 +1217,15 @@ void AsyncPanZoomController::NotifyLayersUpdated(const FrameMetrics& aViewportFr
|
||||||
mX.CancelTouch();
|
mX.CancelTouch();
|
||||||
mY.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;
|
mState = NOTHING;
|
||||||
} else if (!mFrameMetrics.mScrollableRect.IsEqualEdges(aViewportFrame.mScrollableRect)) {
|
} else if (!mFrameMetrics.mScrollableRect.IsEqualEdges(aLayerMetrics.mScrollableRect)) {
|
||||||
mFrameMetrics.mScrollableRect = aViewportFrame.mScrollableRect;
|
mFrameMetrics.mScrollableRect = aLayerMetrics.mScrollableRect;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (needContentRepaint) {
|
if (needContentRepaint) {
|
||||||
|
@ -1242,8 +1259,9 @@ void AsyncPanZoomController::UpdateCompositionBounds(const ScreenIntRect& aCompo
|
||||||
|
|
||||||
void AsyncPanZoomController::CancelDefaultPanZoom() {
|
void AsyncPanZoomController::CancelDefaultPanZoom() {
|
||||||
mDisableNextTouchBatch = true;
|
mDisableNextTouchBatch = true;
|
||||||
if (mGestureEventListener) {
|
nsRefPtr<GestureEventListener> listener = GetGestureEventListener();
|
||||||
mGestureEventListener->CancelGesture();
|
if (listener) {
|
||||||
|
listener->CancelGesture();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1424,83 +1442,44 @@ void AsyncPanZoomController::UpdateZoomConstraints(bool aAllowZoom,
|
||||||
}
|
}
|
||||||
|
|
||||||
void AsyncPanZoomController::PostDelayedTask(Task* aTask, int aDelayMs) {
|
void AsyncPanZoomController::PostDelayedTask(Task* aTask, int aDelayMs) {
|
||||||
if (!mGeckoContentController) {
|
nsRefPtr<GeckoContentController> controller = GetGeckoContentController();
|
||||||
return;
|
if (controller) {
|
||||||
|
controller->PostDelayedTask(aTask, aDelayMs);
|
||||||
}
|
}
|
||||||
|
|
||||||
mGeckoContentController->PostDelayedTask(aTask, aDelayMs);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void AsyncPanZoomController::SendAsyncScrollEvent() {
|
void AsyncPanZoomController::SendAsyncScrollEvent() {
|
||||||
if (!mGeckoContentController) {
|
nsRefPtr<GeckoContentController> controller = GetGeckoContentController();
|
||||||
|
if (!controller) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
FrameMetrics::ViewID scrollId;
|
||||||
CSSRect contentRect;
|
CSSRect contentRect;
|
||||||
CSSSize scrollableSize;
|
CSSSize scrollableSize;
|
||||||
{
|
{
|
||||||
|
// XXX bug 890932 - there should be a lock here. but it causes a deadlock.
|
||||||
|
scrollId = mFrameMetrics.mScrollId;
|
||||||
scrollableSize = mFrameMetrics.mScrollableRect.Size();
|
scrollableSize = mFrameMetrics.mScrollableRect.Size();
|
||||||
contentRect = mFrameMetrics.CalculateCompositedRectInCssPixels();
|
contentRect = mFrameMetrics.CalculateCompositedRectInCssPixels();
|
||||||
contentRect.MoveTo(mCurrentAsyncScrollOffset);
|
contentRect.MoveTo(mCurrentAsyncScrollOffset);
|
||||||
}
|
}
|
||||||
|
|
||||||
mGeckoContentController->SendAsyncScrollDOMEvent(contentRect, scrollableSize);
|
controller->SendAsyncScrollDOMEvent(scrollId, contentRect, scrollableSize);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void GetAPZCAtPointOnSubtree(const ContainerLayer& aLayerIn,
|
void AsyncPanZoomController::UpdateScrollOffset(const CSSPoint& aScrollOffset)
|
||||||
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)
|
|
||||||
{
|
{
|
||||||
MonitorAutoLock monitor(mMonitor);
|
MonitorAutoLock monitor(mMonitor);
|
||||||
mFrameMetrics.mScrollOffset = aScrollOffset;
|
mFrameMetrics.mScrollOffset = aScrollOffset;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool AsyncPanZoomController::Matches(const ScrollableLayerGuid& aGuid)
|
||||||
|
{
|
||||||
|
// TODO: also check the presShellId and mScrollId, once those are
|
||||||
|
// fully propagated everywhere in RenderFrameParent and AndroidJNI.
|
||||||
|
return aGuid.mLayersId == mLayersId;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,12 +14,14 @@
|
||||||
#include "InputData.h"
|
#include "InputData.h"
|
||||||
#include "Axis.h"
|
#include "Axis.h"
|
||||||
#include "TaskThrottler.h"
|
#include "TaskThrottler.h"
|
||||||
|
#include "mozilla/layers/APZCTreeManager.h"
|
||||||
|
|
||||||
#include "base/message_loop.h"
|
#include "base/message_loop.h"
|
||||||
|
|
||||||
namespace mozilla {
|
namespace mozilla {
|
||||||
namespace layers {
|
namespace layers {
|
||||||
|
|
||||||
|
struct ScrollableLayerGuid;
|
||||||
class CompositorParent;
|
class CompositorParent;
|
||||||
class GestureEventListener;
|
class GestureEventListener;
|
||||||
class ContainerLayer;
|
class ContainerLayer;
|
||||||
|
@ -45,7 +47,7 @@ class ViewTransform;
|
||||||
* asynchronously scrolled subframes, we want to have one AsyncPanZoomController
|
* asynchronously scrolled subframes, we want to have one AsyncPanZoomController
|
||||||
* per frame.
|
* per frame.
|
||||||
*/
|
*/
|
||||||
class AsyncPanZoomController MOZ_FINAL {
|
class AsyncPanZoomController {
|
||||||
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(AsyncPanZoomController)
|
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(AsyncPanZoomController)
|
||||||
|
|
||||||
typedef mozilla::MonitorAutoLock MonitorAutoLock;
|
typedef mozilla::MonitorAutoLock MonitorAutoLock;
|
||||||
|
@ -68,19 +70,25 @@ public:
|
||||||
*/
|
*/
|
||||||
static float GetTouchStartTolerance();
|
static float GetTouchStartTolerance();
|
||||||
|
|
||||||
AsyncPanZoomController(GeckoContentController* aController,
|
AsyncPanZoomController(uint64_t aLayersId,
|
||||||
|
GeckoContentController* aController,
|
||||||
GestureBehavior aGestures = DEFAULT_GESTURES);
|
GestureBehavior aGestures = DEFAULT_GESTURES);
|
||||||
~AsyncPanZoomController();
|
~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
|
* Read the various prefs and do any global initialization for all APZC instances.
|
||||||
* deleted (which may happen from any thread).
|
* 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
|
* 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
|
* idempotent. For example, a fling transform can be applied each time this is
|
||||||
* called (though not necessarily). |aSampleTime| is the time that 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
|
* sampled at; this is used for interpolating animations. Calling this sets a
|
||||||
* new transform in |aNewTransform| which should be applied directly to the
|
* new transform in |aNewTransform| which should be multiplied to the transform
|
||||||
* shadow layer of the frame (do not multiply it in as the code already does
|
* in the shadow layer corresponding to this APZC.
|
||||||
* this internally with |aLayer|'s transform).
|
|
||||||
*
|
*
|
||||||
* Return value indicates whether or not any currently running animation
|
* Return value indicates whether or not any currently running animation
|
||||||
* should continue. That is, if true, the compositor should schedule another
|
* should continue. That is, if true, the compositor should schedule another
|
||||||
* composite.
|
* composite.
|
||||||
*/
|
*/
|
||||||
bool SampleContentTransformForFrame(const TimeStamp& aSampleTime,
|
bool SampleContentTransformForFrame(const TimeStamp& aSampleTime,
|
||||||
ContainerLayer* aLayer,
|
|
||||||
ViewTransform* aNewTransform,
|
ViewTransform* aNewTransform,
|
||||||
ScreenPoint& aScrollOffset);
|
ScreenPoint& aScrollOffset);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A shadow layer update has arrived. |aViewportFrame| is the new FrameMetrics
|
* A shadow layer update has arrived. |aLayerMetrics| is the new FrameMetrics
|
||||||
* for the top-level frame. |aIsFirstPaint| is a flag passed from the shadow
|
* 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
|
* 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.
|
* 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
|
* 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.
|
// 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
|
* 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
|
* a platform responsibility to set this on initialization of this class and
|
||||||
|
@ -234,6 +259,11 @@ public:
|
||||||
*/
|
*/
|
||||||
nsEventStatus HandleInputEvent(const InputData& aEvent);
|
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.
|
* Sync panning and zooming animation using a fixed frame time.
|
||||||
* This will ensure that we animate the APZC correctly with other external
|
* This will ensure that we animate the APZC correctly with other external
|
||||||
|
@ -241,23 +271,12 @@ public:
|
||||||
*/
|
*/
|
||||||
static void SetFrameTime(const TimeStamp& aMilliseconds);
|
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.
|
* Update mFrameMetrics.mScrollOffset to the given offset.
|
||||||
* This is necessary in cases where a scroll is not caused by user
|
* This is necessary in cases where a scroll is not caused by user
|
||||||
* input (for example, a content scrollTo()).
|
* 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
|
* Cancels any currently running animation. Note that all this does is set the
|
||||||
|
@ -492,16 +511,39 @@ private:
|
||||||
*/
|
*/
|
||||||
void SetState(PanZoomState aState);
|
void SetState(PanZoomState aState);
|
||||||
|
|
||||||
|
uint64_t mLayersId;
|
||||||
nsRefPtr<CompositorParent> mCompositorParent;
|
nsRefPtr<CompositorParent> mCompositorParent;
|
||||||
TaskThrottler mPaintThrottler;
|
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<GeckoContentController> mGeckoContentController;
|
||||||
nsRefPtr<GestureEventListener> mGestureEventListener;
|
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
|
// Both |mFrameMetrics| and |mLastContentPaintMetrics| are protected by the
|
||||||
// monitor. Do not read from or modify either of them without locking.
|
// monitor. Do not read from or modify either of them without locking.
|
||||||
FrameMetrics mFrameMetrics;
|
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
|
// 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;
|
FrameMetrics mLastContentPaintMetrics;
|
||||||
// The last metrics that we requested a paint for. These are used to make sure
|
// 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.
|
// that we're not requesting a paint of the same thing that's already drawn.
|
||||||
|
@ -532,14 +574,6 @@ private:
|
||||||
float mMinZoom;
|
float mMinZoom;
|
||||||
float mMaxZoom;
|
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
|
// The last time the compositor has sampled the content transform for this
|
||||||
// frame.
|
// frame.
|
||||||
TimeStamp mLastSampleTime;
|
TimeStamp mLastSampleTime;
|
||||||
|
@ -571,14 +605,6 @@ private:
|
||||||
// ensures the last mozbrowserasyncscroll event is always been fired.
|
// ensures the last mozbrowserasyncscroll event is always been fired.
|
||||||
CancelableTask* mAsyncScrollTimeoutTask;
|
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;
|
int mDPI;
|
||||||
|
|
||||||
// Flag used to determine whether or not we should disable handling of the
|
// Flag used to determine whether or not we should disable handling of the
|
||||||
|
@ -598,6 +624,37 @@ private:
|
||||||
bool mDelayPanning;
|
bool mDelayPanning;
|
||||||
|
|
||||||
friend class Axis;
|
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 "mozilla/DebugOnly.h"
|
||||||
|
|
||||||
#include "AsyncPanZoomController.h"
|
|
||||||
#include "AutoOpenSurface.h"
|
#include "AutoOpenSurface.h"
|
||||||
#include "CompositorParent.h"
|
#include "CompositorParent.h"
|
||||||
#include "mozilla/layers/CompositorOGL.h"
|
#include "mozilla/layers/CompositorOGL.h"
|
||||||
|
@ -155,6 +154,10 @@ CompositorParent::CompositorParent(nsIWidget* aWidget,
|
||||||
CompositorLoop()->PostTask(FROM_HERE, NewRunnableFunction(&AddCompositor,
|
CompositorLoop()->PostTask(FROM_HERE, NewRunnableFunction(&AddCompositor,
|
||||||
this, &mCompositorID));
|
this, &mCompositorID));
|
||||||
|
|
||||||
|
mRootLayerTreeID = AllocateLayerTreeId();
|
||||||
|
sIndirectLayerTrees[mRootLayerTreeID].mParent = this;
|
||||||
|
|
||||||
|
mApzcTreeManager = new APZCTreeManager();
|
||||||
++sCompositorThreadRefCount;
|
++sCompositorThreadRefCount;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -170,6 +173,12 @@ CompositorParent::IsInCompositorThread()
|
||||||
return CompositorThreadID() == PlatformThread::CurrentId();
|
return CompositorThreadID() == PlatformThread::CurrentId();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uint64_t
|
||||||
|
CompositorParent::RootLayerTreeId()
|
||||||
|
{
|
||||||
|
return mRootLayerTreeID;
|
||||||
|
}
|
||||||
|
|
||||||
CompositorParent::~CompositorParent()
|
CompositorParent::~CompositorParent()
|
||||||
{
|
{
|
||||||
MOZ_COUNT_DTOR(CompositorParent);
|
MOZ_COUNT_DTOR(CompositorParent);
|
||||||
|
@ -186,6 +195,9 @@ CompositorParent::Destroy()
|
||||||
// Ensure that the layer manager is destructed on the compositor thread.
|
// Ensure that the layer manager is destructed on the compositor thread.
|
||||||
mLayerManager = nullptr;
|
mLayerManager = nullptr;
|
||||||
mCompositionManager = nullptr;
|
mCompositionManager = nullptr;
|
||||||
|
mApzcTreeManager->ClearTree();
|
||||||
|
mApzcTreeManager = nullptr;
|
||||||
|
sIndirectLayerTrees.erase(mRootLayerTreeID);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -404,8 +416,13 @@ CompositorParent::ScheduleTask(CancelableTask* task, int time)
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
CompositorParent::NotifyShadowTreeTransaction()
|
CompositorParent::NotifyShadowTreeTransaction(uint64_t aId, bool aIsFirstPaint)
|
||||||
{
|
{
|
||||||
|
if (mApzcTreeManager) {
|
||||||
|
AutoResolveRefLayers resolve(mCompositionManager);
|
||||||
|
mApzcTreeManager->UpdatePanZoomControllerTree(this, mLayerManager->GetRoot(), aIsFirstPaint, aId);
|
||||||
|
}
|
||||||
|
|
||||||
if (mLayerManager) {
|
if (mLayerManager) {
|
||||||
LayerManagerComposite* managerComposite = mLayerManager->AsLayerManagerComposite();
|
LayerManagerComposite* managerComposite = mLayerManager->AsLayerManagerComposite();
|
||||||
if (managerComposite) {
|
if (managerComposite) {
|
||||||
|
@ -559,6 +576,12 @@ CompositorParent::ShadowLayersUpdated(LayerTransactionParent* aLayerTree,
|
||||||
mCompositionManager->Updated(isFirstPaint, aTargetConfig);
|
mCompositionManager->Updated(isFirstPaint, aTargetConfig);
|
||||||
Layer* root = aLayerTree->GetRoot();
|
Layer* root = aLayerTree->GetRoot();
|
||||||
mLayerManager->SetRoot(root);
|
mLayerManager->SetRoot(root);
|
||||||
|
|
||||||
|
if (mApzcTreeManager) {
|
||||||
|
AutoResolveRefLayers resolve(mCompositionManager);
|
||||||
|
mApzcTreeManager->UpdatePanZoomControllerTree(this, root, isFirstPaint, mRootLayerTreeID);
|
||||||
|
}
|
||||||
|
|
||||||
if (root) {
|
if (root) {
|
||||||
SetShadowProperties(root);
|
SetShadowProperties(root);
|
||||||
if (mIsTesting) {
|
if (mIsTesting) {
|
||||||
|
@ -704,7 +727,7 @@ CompositorParent::AllocateLayerTreeId()
|
||||||
{
|
{
|
||||||
MOZ_ASSERT(CompositorLoop());
|
MOZ_ASSERT(CompositorLoop());
|
||||||
MOZ_ASSERT(NS_IsMainThread());
|
MOZ_ASSERT(NS_IsMainThread());
|
||||||
static uint64_t ids;
|
static uint64_t ids = 0;
|
||||||
return ++ids;
|
return ++ids;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -724,20 +747,30 @@ CompositorParent::DeallocateLayerTreeId(uint64_t aId)
|
||||||
|
|
||||||
static void
|
static void
|
||||||
UpdateControllerForLayersId(uint64_t aLayersId,
|
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 =
|
sIndirectLayerTrees[aLayersId].mController =
|
||||||
already_AddRefed<AsyncPanZoomController>(aController);
|
already_AddRefed<GeckoContentController>(aController);
|
||||||
|
}
|
||||||
|
|
||||||
// Notify the AsyncPanZoomController about the current compositor so that it
|
ScopedLayerTreeRegistration::ScopedLayerTreeRegistration(uint64_t aLayersId,
|
||||||
// can request composites off the compositor thread.
|
Layer* aRoot,
|
||||||
aController->SetCompositorParent(sIndirectLayerTrees[aLayersId].mParent);
|
GeckoContentController* aController)
|
||||||
|
: mLayersId(aLayersId)
|
||||||
|
{
|
||||||
|
sIndirectLayerTrees[aLayersId].mRoot = aRoot;
|
||||||
|
sIndirectLayerTrees[aLayersId].mController = aController;
|
||||||
|
}
|
||||||
|
|
||||||
|
ScopedLayerTreeRegistration::~ScopedLayerTreeRegistration()
|
||||||
|
{
|
||||||
|
sIndirectLayerTrees.erase(mLayersId);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*static*/ void
|
/*static*/ void
|
||||||
CompositorParent::SetPanZoomControllerForLayerTree(uint64_t aLayersId,
|
CompositorParent::SetControllerForLayerTree(uint64_t aLayersId,
|
||||||
AsyncPanZoomController* aController)
|
GeckoContentController* aController)
|
||||||
{
|
{
|
||||||
// This ref is adopted by UpdateControllerForLayersId().
|
// This ref is adopted by UpdateControllerForLayersId().
|
||||||
aController->AddRef();
|
aController->AddRef();
|
||||||
|
@ -747,6 +780,16 @@ CompositorParent::SetPanZoomControllerForLayerTree(uint64_t aLayersId,
|
||||||
aController));
|
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
|
* This class handles layer updates pushed directly from child
|
||||||
* processes to the compositor thread. It's associated with a
|
* processes to the compositor thread. It's associated with a
|
||||||
|
@ -831,16 +874,10 @@ CompositorParent::Create(Transport* aTransport, ProcessId aOtherProcess)
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
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].mRoot = aRoot;
|
||||||
sIndirectLayerTrees[aId].mTargetConfig = aTargetConfig;
|
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*
|
/* static */ const CompositorParent::LayerTreeState*
|
||||||
|
@ -912,9 +949,9 @@ CrossProcessCompositorParent::ShadowLayersUpdated(
|
||||||
if (shadowRoot) {
|
if (shadowRoot) {
|
||||||
SetShadowProperties(shadowRoot);
|
SetShadowProperties(shadowRoot);
|
||||||
}
|
}
|
||||||
UpdateIndirectTree(id, shadowRoot, aTargetConfig, isFirstPaint);
|
UpdateIndirectTree(id, shadowRoot, aTargetConfig);
|
||||||
|
|
||||||
sIndirectLayerTrees[id].mParent->NotifyShadowTreeTransaction();
|
sIndirectLayerTrees[id].mParent->NotifyShadowTreeTransaction(id, isFirstPaint);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
|
|
@ -17,6 +17,7 @@
|
||||||
|
|
||||||
#include "mozilla/layers/PCompositorParent.h"
|
#include "mozilla/layers/PCompositorParent.h"
|
||||||
#include "mozilla/layers/PLayerTransactionParent.h"
|
#include "mozilla/layers/PLayerTransactionParent.h"
|
||||||
|
#include "mozilla/layers/APZCTreeManager.h"
|
||||||
#include "base/thread.h"
|
#include "base/thread.h"
|
||||||
#include "mozilla/Monitor.h"
|
#include "mozilla/Monitor.h"
|
||||||
#include "mozilla/TimeStamp.h"
|
#include "mozilla/TimeStamp.h"
|
||||||
|
@ -31,12 +32,23 @@ class Thread;
|
||||||
namespace mozilla {
|
namespace mozilla {
|
||||||
namespace layers {
|
namespace layers {
|
||||||
|
|
||||||
class AsyncPanZoomController;
|
class APZCTreeManager;
|
||||||
class Layer;
|
class Layer;
|
||||||
class LayerManagerComposite;
|
class LayerManagerComposite;
|
||||||
class AsyncCompositionManager;
|
class AsyncCompositionManager;
|
||||||
struct TextureFactoryIdentifier;
|
struct TextureFactoryIdentifier;
|
||||||
|
|
||||||
|
struct ScopedLayerTreeRegistration
|
||||||
|
{
|
||||||
|
ScopedLayerTreeRegistration(uint64_t aLayersId,
|
||||||
|
Layer* aRoot,
|
||||||
|
GeckoContentController* aController);
|
||||||
|
~ScopedLayerTreeRegistration();
|
||||||
|
|
||||||
|
private:
|
||||||
|
uint64_t mLayersId;
|
||||||
|
};
|
||||||
|
|
||||||
class CompositorParent : public PCompositorParent,
|
class CompositorParent : public PCompositorParent,
|
||||||
public ShadowLayersManager
|
public ShadowLayersManager
|
||||||
{
|
{
|
||||||
|
@ -89,7 +101,13 @@ public:
|
||||||
bool ScheduleResumeOnCompositorThread(int width, int height);
|
bool ScheduleResumeOnCompositorThread(int width, int height);
|
||||||
|
|
||||||
virtual void ScheduleComposition();
|
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.
|
* Returns a pointer to the compositor corresponding to the given ID.
|
||||||
|
@ -128,13 +146,19 @@ public:
|
||||||
static void DeallocateLayerTreeId(uint64_t aId);
|
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.
|
* to by aLayersId.
|
||||||
*
|
*
|
||||||
* Must run on content main thread.
|
* Must run on content main thread.
|
||||||
*/
|
*/
|
||||||
static void SetPanZoomControllerForLayerTree(uint64_t aLayersId,
|
static void SetControllerForLayerTree(uint64_t aLayersId,
|
||||||
AsyncPanZoomController* aController);
|
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
|
* A new child process has been configured to push transactions
|
||||||
|
@ -154,7 +178,7 @@ public:
|
||||||
|
|
||||||
struct LayerTreeState {
|
struct LayerTreeState {
|
||||||
nsRefPtr<Layer> mRoot;
|
nsRefPtr<Layer> mRoot;
|
||||||
nsRefPtr<AsyncPanZoomController> mController;
|
nsRefPtr<GeckoContentController> mController;
|
||||||
CompositorParent *mParent;
|
CompositorParent *mParent;
|
||||||
TargetConfig mTargetConfig;
|
TargetConfig mTargetConfig;
|
||||||
};
|
};
|
||||||
|
@ -264,10 +288,13 @@ private:
|
||||||
mozilla::Monitor mResumeCompositionMonitor;
|
mozilla::Monitor mResumeCompositionMonitor;
|
||||||
|
|
||||||
uint64_t mCompositorID;
|
uint64_t mCompositorID;
|
||||||
|
uint64_t mRootLayerTreeID;
|
||||||
|
|
||||||
bool mOverrideComposeReadiness;
|
bool mOverrideComposeReadiness;
|
||||||
CancelableTask* mForceCompositionTask;
|
CancelableTask* mForceCompositionTask;
|
||||||
|
|
||||||
|
nsRefPtr<APZCTreeManager> mApzcTreeManager;
|
||||||
|
|
||||||
DISALLOW_EVIL_CONSTRUCTORS(CompositorParent);
|
DISALLOW_EVIL_CONSTRUCTORS(CompositorParent);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -51,7 +51,8 @@ public:
|
||||||
* |aContentRect| is in CSS pixels, relative to the current cssPage.
|
* |aContentRect| is in CSS pixels, relative to the current cssPage.
|
||||||
* |aScrollableSize| is the current content width/height in CSS pixels.
|
* |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;
|
const CSSSize &aScrollableSize) = 0;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -105,6 +105,7 @@ EXPORTS.mozilla.layers += [
|
||||||
'client/ImageClient.h',
|
'client/ImageClient.h',
|
||||||
'client/TextureClient.h',
|
'client/TextureClient.h',
|
||||||
'client/TiledContentClient.h',
|
'client/TiledContentClient.h',
|
||||||
|
'composite/APZCTreeManager.h',
|
||||||
'composite/AsyncCompositionManager.h',
|
'composite/AsyncCompositionManager.h',
|
||||||
'composite/CanvasLayerComposite.h',
|
'composite/CanvasLayerComposite.h',
|
||||||
'composite/ColorLayerComposite.h',
|
'composite/ColorLayerComposite.h',
|
||||||
|
@ -170,6 +171,7 @@ if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'gonk':
|
||||||
]
|
]
|
||||||
|
|
||||||
CPP_SOURCES += [
|
CPP_SOURCES += [
|
||||||
|
'APZCTreeManager.cpp',
|
||||||
'AsyncCompositionManager.cpp',
|
'AsyncCompositionManager.cpp',
|
||||||
'AsyncPanZoomController.cpp',
|
'AsyncPanZoomController.cpp',
|
||||||
'Axis.cpp',
|
'Axis.cpp',
|
||||||
|
|
|
@ -10,6 +10,8 @@
|
||||||
#include "mozilla/layers/AsyncPanZoomController.h"
|
#include "mozilla/layers/AsyncPanZoomController.h"
|
||||||
#include "mozilla/layers/LayerManagerComposite.h"
|
#include "mozilla/layers/LayerManagerComposite.h"
|
||||||
#include "mozilla/layers/GeckoContentController.h"
|
#include "mozilla/layers/GeckoContentController.h"
|
||||||
|
#include "mozilla/layers/CompositorParent.h"
|
||||||
|
#include "mozilla/layers/APZCTreeManager.h"
|
||||||
#include "Layers.h"
|
#include "Layers.h"
|
||||||
#include "TestLayers.h"
|
#include "TestLayers.h"
|
||||||
|
|
||||||
|
@ -24,7 +26,7 @@ public:
|
||||||
MOCK_METHOD1(HandleDoubleTap, void(const CSSIntPoint&));
|
MOCK_METHOD1(HandleDoubleTap, void(const CSSIntPoint&));
|
||||||
MOCK_METHOD1(HandleSingleTap, void(const CSSIntPoint&));
|
MOCK_METHOD1(HandleSingleTap, void(const CSSIntPoint&));
|
||||||
MOCK_METHOD1(HandleLongTap, 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));
|
MOCK_METHOD2(PostDelayedTask, void(Task* aTask, int aDelayMs));
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -39,6 +41,23 @@ class TestAPZCContainerLayer : public ContainerLayer {
|
||||||
void RepositionChild(Layer* aChild, Layer* aAfter) {}
|
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
|
static
|
||||||
FrameMetrics TestFrameMetrics() {
|
FrameMetrics TestFrameMetrics() {
|
||||||
FrameMetrics fm;
|
FrameMetrics fm;
|
||||||
|
@ -90,21 +109,20 @@ void ApzcPan(AsyncPanZoomController* apzc, int& aTime, int aTouchStartY, int aTo
|
||||||
TEST(AsyncPanZoomController, Constructor) {
|
TEST(AsyncPanZoomController, Constructor) {
|
||||||
// RefCounted class can't live in the stack
|
// RefCounted class can't live in the stack
|
||||||
nsRefPtr<MockContentController> mcc = new MockContentController();
|
nsRefPtr<MockContentController> mcc = new MockContentController();
|
||||||
nsRefPtr<AsyncPanZoomController> apzc = new AsyncPanZoomController(mcc);
|
nsRefPtr<TestAsyncPanZoomController> apzc = new TestAsyncPanZoomController(0, mcc);
|
||||||
apzc->NotifyLayersUpdated(TestFrameMetrics(), true);
|
apzc->SetFrameMetrics(TestFrameMetrics());
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(AsyncPanZoomController, SimpleTransform) {
|
TEST(AsyncPanZoomController, SimpleTransform) {
|
||||||
TimeStamp testStartTime = TimeStamp::Now();
|
TimeStamp testStartTime = TimeStamp::Now();
|
||||||
// RefCounted class can't live in the stack
|
// RefCounted class can't live in the stack
|
||||||
nsRefPtr<MockContentController> mcc = new MockContentController();
|
nsRefPtr<MockContentController> mcc = new MockContentController();
|
||||||
nsRefPtr<AsyncPanZoomController> apzc = new AsyncPanZoomController(mcc);
|
nsRefPtr<TestAsyncPanZoomController> apzc = new TestAsyncPanZoomController(0, mcc);
|
||||||
apzc->NotifyLayersUpdated(TestFrameMetrics(), true);
|
apzc->SetFrameMetrics(TestFrameMetrics());
|
||||||
|
|
||||||
TestAPZCContainerLayer layer;
|
|
||||||
ScreenPoint pointOut;
|
ScreenPoint pointOut;
|
||||||
ViewTransform viewTransformOut;
|
ViewTransform viewTransformOut;
|
||||||
apzc->SampleContentTransformForFrame(testStartTime, &layer, &viewTransformOut, pointOut);
|
apzc->SampleContentTransformForFrame(testStartTime, &viewTransformOut, pointOut);
|
||||||
|
|
||||||
EXPECT_EQ(pointOut, ScreenPoint());
|
EXPECT_EQ(pointOut, ScreenPoint());
|
||||||
EXPECT_EQ(viewTransformOut, ViewTransform());
|
EXPECT_EQ(viewTransformOut, ViewTransform());
|
||||||
|
@ -131,7 +149,8 @@ TEST(AsyncPanZoomController, ComplexTransform) {
|
||||||
// sides.
|
// sides.
|
||||||
|
|
||||||
nsRefPtr<MockContentController> mcc = new MockContentController();
|
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)";
|
const char* layerTreeSyntax = "c(c)";
|
||||||
// LayerID 0 1
|
// LayerID 0 1
|
||||||
|
@ -174,39 +193,41 @@ TEST(AsyncPanZoomController, ComplexTransform) {
|
||||||
// the CSS transform on the child layer does not affect the SampleContentTransformForFrame code
|
// the CSS transform on the child layer does not affect the SampleContentTransformForFrame code
|
||||||
|
|
||||||
// initial transform
|
// initial transform
|
||||||
|
apzc->SetFrameMetrics(metrics);
|
||||||
apzc->NotifyLayersUpdated(metrics, true);
|
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(ViewTransform(LayerPoint(), LayoutDeviceToScreenScale(2)), viewTransformOut);
|
||||||
EXPECT_EQ(ScreenPoint(60, 60), pointOut);
|
EXPECT_EQ(ScreenPoint(60, 60), pointOut);
|
||||||
|
|
||||||
apzc->NotifyLayersUpdated(childMetrics, true);
|
childApzc->SetFrameMetrics(childMetrics);
|
||||||
apzc->SampleContentTransformForFrame(testStartTime, layers[1]->AsContainerLayer(), &viewTransformOut, pointOut);
|
childApzc->NotifyLayersUpdated(childMetrics, true);
|
||||||
|
childApzc->SampleContentTransformForFrame(testStartTime, &viewTransformOut, pointOut);
|
||||||
EXPECT_EQ(ViewTransform(LayerPoint(), LayoutDeviceToScreenScale(2)), viewTransformOut);
|
EXPECT_EQ(ViewTransform(LayerPoint(), LayoutDeviceToScreenScale(2)), viewTransformOut);
|
||||||
EXPECT_EQ(ScreenPoint(60, 60), pointOut);
|
EXPECT_EQ(ScreenPoint(60, 60), pointOut);
|
||||||
|
|
||||||
// do an async scroll by 5 pixels and check the transform
|
// do an async scroll by 5 pixels and check the transform
|
||||||
metrics.mScrollOffset += CSSPoint(5, 0);
|
metrics.mScrollOffset += CSSPoint(5, 0);
|
||||||
apzc->NotifyLayersUpdated(metrics, true);
|
apzc->SetFrameMetrics(metrics);
|
||||||
apzc->SampleContentTransformForFrame(testStartTime, layers[0]->AsContainerLayer(), &viewTransformOut, pointOut);
|
apzc->SampleContentTransformForFrame(testStartTime, &viewTransformOut, pointOut);
|
||||||
EXPECT_EQ(ViewTransform(LayerPoint(-30, 0), LayoutDeviceToScreenScale(2)), viewTransformOut);
|
EXPECT_EQ(ViewTransform(LayerPoint(-30, 0), LayoutDeviceToScreenScale(2)), viewTransformOut);
|
||||||
EXPECT_EQ(ScreenPoint(90, 60), pointOut);
|
EXPECT_EQ(ScreenPoint(90, 60), pointOut);
|
||||||
|
|
||||||
childMetrics.mScrollOffset += CSSPoint(5, 0);
|
childMetrics.mScrollOffset += CSSPoint(5, 0);
|
||||||
apzc->NotifyLayersUpdated(childMetrics, true);
|
childApzc->SetFrameMetrics(childMetrics);
|
||||||
apzc->SampleContentTransformForFrame(testStartTime, layers[1]->AsContainerLayer(), &viewTransformOut, pointOut);
|
childApzc->SampleContentTransformForFrame(testStartTime, &viewTransformOut, pointOut);
|
||||||
EXPECT_EQ(ViewTransform(LayerPoint(-30, 0), LayoutDeviceToScreenScale(2)), viewTransformOut);
|
EXPECT_EQ(ViewTransform(LayerPoint(-30, 0), LayoutDeviceToScreenScale(2)), viewTransformOut);
|
||||||
EXPECT_EQ(ScreenPoint(90, 60), pointOut);
|
EXPECT_EQ(ScreenPoint(90, 60), pointOut);
|
||||||
|
|
||||||
// do an async zoom of 1.5x and check the transform
|
// do an async zoom of 1.5x and check the transform
|
||||||
metrics.mZoom.scale *= 1.5f;
|
metrics.mZoom.scale *= 1.5f;
|
||||||
apzc->NotifyLayersUpdated(metrics, true);
|
apzc->SetFrameMetrics(metrics);
|
||||||
apzc->SampleContentTransformForFrame(testStartTime, layers[0]->AsContainerLayer(), &viewTransformOut, pointOut);
|
apzc->SampleContentTransformForFrame(testStartTime, &viewTransformOut, pointOut);
|
||||||
EXPECT_EQ(ViewTransform(LayerPoint(-30, 0), LayoutDeviceToScreenScale(3)), viewTransformOut);
|
EXPECT_EQ(ViewTransform(LayerPoint(-30, 0), LayoutDeviceToScreenScale(3)), viewTransformOut);
|
||||||
EXPECT_EQ(ScreenPoint(135, 90), pointOut);
|
EXPECT_EQ(ScreenPoint(135, 90), pointOut);
|
||||||
|
|
||||||
childMetrics.mZoom.scale *= 1.5f;
|
childMetrics.mZoom.scale *= 1.5f;
|
||||||
apzc->NotifyLayersUpdated(childMetrics, true);
|
childApzc->SetFrameMetrics(childMetrics);
|
||||||
apzc->SampleContentTransformForFrame(testStartTime, layers[0]->AsContainerLayer(), &viewTransformOut, pointOut);
|
childApzc->SampleContentTransformForFrame(testStartTime, &viewTransformOut, pointOut);
|
||||||
EXPECT_EQ(ViewTransform(LayerPoint(-30, 0), LayoutDeviceToScreenScale(3)), viewTransformOut);
|
EXPECT_EQ(ViewTransform(LayerPoint(-30, 0), LayoutDeviceToScreenScale(3)), viewTransformOut);
|
||||||
EXPECT_EQ(ScreenPoint(135, 90), pointOut);
|
EXPECT_EQ(ScreenPoint(135, 90), pointOut);
|
||||||
}
|
}
|
||||||
|
@ -216,28 +237,29 @@ TEST(AsyncPanZoomController, Pan) {
|
||||||
AsyncPanZoomController::SetFrameTime(testStartTime);
|
AsyncPanZoomController::SetFrameTime(testStartTime);
|
||||||
|
|
||||||
nsRefPtr<MockContentController> mcc = new MockContentController();
|
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);
|
apzc->NotifyLayersUpdated(TestFrameMetrics(), true);
|
||||||
|
|
||||||
EXPECT_CALL(*mcc, SendAsyncScrollDOMEvent(_,_)).Times(4);
|
EXPECT_CALL(*mcc, SendAsyncScrollDOMEvent(_,_,_)).Times(4);
|
||||||
EXPECT_CALL(*mcc, RequestContentRepaint(_)).Times(1);
|
EXPECT_CALL(*mcc, RequestContentRepaint(_)).Times(1);
|
||||||
|
|
||||||
int time = 0;
|
int time = 0;
|
||||||
int touchStart = 50;
|
int touchStart = 50;
|
||||||
int touchEnd = 10;
|
int touchEnd = 10;
|
||||||
TestAPZCContainerLayer layer;
|
|
||||||
ScreenPoint pointOut;
|
ScreenPoint pointOut;
|
||||||
ViewTransform viewTransformOut;
|
ViewTransform viewTransformOut;
|
||||||
|
|
||||||
// Pan down
|
// Pan down
|
||||||
ApzcPan(apzc, time, touchStart, touchEnd);
|
ApzcPan(apzc, time, touchStart, touchEnd);
|
||||||
apzc->SampleContentTransformForFrame(testStartTime, &layer, &viewTransformOut, pointOut);
|
apzc->SampleContentTransformForFrame(testStartTime, &viewTransformOut, pointOut);
|
||||||
EXPECT_EQ(pointOut, ScreenPoint(0, -(touchEnd-touchStart)));
|
EXPECT_EQ(pointOut, ScreenPoint(0, -(touchEnd-touchStart)));
|
||||||
EXPECT_NE(viewTransformOut, ViewTransform());
|
EXPECT_NE(viewTransformOut, ViewTransform());
|
||||||
|
|
||||||
// Pan back
|
// Pan back
|
||||||
ApzcPan(apzc, time, touchEnd, touchStart);
|
ApzcPan(apzc, time, touchEnd, touchStart);
|
||||||
apzc->SampleContentTransformForFrame(testStartTime, &layer, &viewTransformOut, pointOut);
|
apzc->SampleContentTransformForFrame(testStartTime, &viewTransformOut, pointOut);
|
||||||
EXPECT_EQ(pointOut, ScreenPoint());
|
EXPECT_EQ(pointOut, ScreenPoint());
|
||||||
EXPECT_EQ(viewTransformOut, ViewTransform());
|
EXPECT_EQ(viewTransformOut, ViewTransform());
|
||||||
}
|
}
|
||||||
|
@ -247,16 +269,17 @@ TEST(AsyncPanZoomController, Fling) {
|
||||||
AsyncPanZoomController::SetFrameTime(testStartTime);
|
AsyncPanZoomController::SetFrameTime(testStartTime);
|
||||||
|
|
||||||
nsRefPtr<MockContentController> mcc = new MockContentController();
|
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);
|
apzc->NotifyLayersUpdated(TestFrameMetrics(), true);
|
||||||
|
|
||||||
EXPECT_CALL(*mcc, SendAsyncScrollDOMEvent(_,_)).Times(2);
|
EXPECT_CALL(*mcc, SendAsyncScrollDOMEvent(_,_,_)).Times(2);
|
||||||
EXPECT_CALL(*mcc, RequestContentRepaint(_)).Times(1);
|
EXPECT_CALL(*mcc, RequestContentRepaint(_)).Times(1);
|
||||||
|
|
||||||
int time = 0;
|
int time = 0;
|
||||||
int touchStart = 50;
|
int touchStart = 50;
|
||||||
int touchEnd = 10;
|
int touchEnd = 10;
|
||||||
TestAPZCContainerLayer layer;
|
|
||||||
ScreenPoint pointOut;
|
ScreenPoint pointOut;
|
||||||
ViewTransform viewTransformOut;
|
ViewTransform viewTransformOut;
|
||||||
|
|
||||||
|
@ -264,7 +287,7 @@ TEST(AsyncPanZoomController, Fling) {
|
||||||
ApzcPan(apzc, time, touchStart, touchEnd);
|
ApzcPan(apzc, time, touchStart, touchEnd);
|
||||||
ScreenPoint lastPoint;
|
ScreenPoint lastPoint;
|
||||||
for (int i = 1; i < 50; i+=1) {
|
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);
|
EXPECT_GT(pointOut.y, lastPoint.y);
|
||||||
lastPoint = pointOut;
|
lastPoint = pointOut;
|
||||||
}
|
}
|
||||||
|
@ -275,23 +298,24 @@ TEST(AsyncPanZoomController, OverScrollPanning) {
|
||||||
AsyncPanZoomController::SetFrameTime(testStartTime);
|
AsyncPanZoomController::SetFrameTime(testStartTime);
|
||||||
|
|
||||||
nsRefPtr<MockContentController> mcc = new MockContentController();
|
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);
|
apzc->NotifyLayersUpdated(TestFrameMetrics(), true);
|
||||||
|
|
||||||
EXPECT_CALL(*mcc, SendAsyncScrollDOMEvent(_,_)).Times(3);
|
EXPECT_CALL(*mcc, SendAsyncScrollDOMEvent(_,_,_)).Times(3);
|
||||||
EXPECT_CALL(*mcc, RequestContentRepaint(_)).Times(1);
|
EXPECT_CALL(*mcc, RequestContentRepaint(_)).Times(1);
|
||||||
|
|
||||||
// Pan sufficiently to hit overscroll behavior
|
// Pan sufficiently to hit overscroll behavior
|
||||||
int time = 0;
|
int time = 0;
|
||||||
int touchStart = 500;
|
int touchStart = 500;
|
||||||
int touchEnd = 10;
|
int touchEnd = 10;
|
||||||
TestAPZCContainerLayer layer;
|
|
||||||
ScreenPoint pointOut;
|
ScreenPoint pointOut;
|
||||||
ViewTransform viewTransformOut;
|
ViewTransform viewTransformOut;
|
||||||
|
|
||||||
// Pan down
|
// Pan down
|
||||||
ApzcPan(apzc, time, touchStart, touchEnd);
|
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));
|
EXPECT_EQ(pointOut, ScreenPoint(0, 90));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -322,124 +346,102 @@ CreateTestLayerTree(nsRefPtr<LayerManager>& aLayerManager, nsTArray<nsRefPtr<Lay
|
||||||
return CreateLayerTree(layerTreeSyntax, layerVisibleRegion, transforms, aLayerManager, aLayers);
|
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;
|
nsTArray<nsRefPtr<Layer> > layers;
|
||||||
nsRefPtr<LayerManager> lm;
|
nsRefPtr<LayerManager> lm;
|
||||||
nsRefPtr<Layer> root = CreateTestLayerTree(lm, layers);
|
nsRefPtr<Layer> root = CreateTestLayerTree(lm, layers);
|
||||||
|
|
||||||
TimeStamp testStartTime = TimeStamp::Now();
|
TimeStamp testStartTime = TimeStamp::Now();
|
||||||
AsyncPanZoomController::SetFrameTime(testStartTime);
|
AsyncPanZoomController::SetFrameTime(testStartTime);
|
||||||
|
|
||||||
nsRefPtr<MockContentController> mcc = new MockContentController();
|
nsRefPtr<MockContentController> mcc = new MockContentController();
|
||||||
nsRefPtr<AsyncPanZoomController> apzcMain = new AsyncPanZoomController(mcc);
|
ScopedLayerTreeRegistration controller(0, root, mcc);
|
||||||
nsRefPtr<AsyncPanZoomController> apzcSub3 = new AsyncPanZoomController(mcc);
|
|
||||||
nsRefPtr<AsyncPanZoomController> apzcSub4 = new AsyncPanZoomController(mcc);
|
|
||||||
nsRefPtr<AsyncPanZoomController> apzcSub7 = new AsyncPanZoomController(mcc);
|
|
||||||
apzcMain->NotifyLayersUpdated(TestFrameMetrics(), true);
|
|
||||||
|
|
||||||
nsIntRect layerBound;
|
nsRefPtr<APZCTreeManager> manager = new TestAPZCTreeManager();
|
||||||
ScreenIntPoint touchPoint(20, 20);
|
|
||||||
AsyncPanZoomController* apzcOut;
|
|
||||||
LayerIntPoint relativePointOut;
|
|
||||||
|
|
||||||
FrameMetrics scrollable;
|
|
||||||
|
|
||||||
// No APZC attached so hit testing will return no APZC at (20,20)
|
// No APZC attached so hit testing will return no APZC at (20,20)
|
||||||
AsyncPanZoomController::GetAPZCAtPoint(*root->AsContainerLayer(), touchPoint,
|
nsRefPtr<AsyncPanZoomController> hit = manager->GetTargetAPZC(ScreenPoint(20, 20));
|
||||||
&apzcOut, &relativePointOut);
|
|
||||||
|
|
||||||
AsyncPanZoomController* nullAPZC = nullptr;
|
AsyncPanZoomController* nullAPZC = nullptr;
|
||||||
EXPECT_EQ(apzcOut, nullAPZC);
|
EXPECT_EQ(nullAPZC, hit.get());
|
||||||
|
|
||||||
// Now we have a root APZC that will match the page
|
// Now we have a root APZC that will match the page
|
||||||
scrollable.mScrollId = FrameMetrics::ROOT_SCROLL_ID;
|
SetScrollableFrameMetrics(root, FrameMetrics::ROOT_SCROLL_ID, mcc);
|
||||||
layerBound = root->GetVisibleRegion().GetBounds();
|
manager->UpdatePanZoomControllerTree(nullptr, root, 0, false);
|
||||||
scrollable.mViewport = CSSRect(layerBound.x, layerBound.y,
|
hit = manager->GetTargetAPZC(ScreenPoint(15, 15));
|
||||||
layerBound.width, layerBound.height);
|
EXPECT_EQ(root->AsContainerLayer()->GetAsyncPanZoomController(), hit.get());
|
||||||
root->AsContainerLayer()->SetFrameMetrics(scrollable);
|
// expect hit point at LayerIntPoint(15, 15)
|
||||||
root->AsContainerLayer()->SetAsyncPanZoomController(apzcMain);
|
|
||||||
AsyncPanZoomController::GetAPZCAtPoint(*root->AsContainerLayer(), touchPoint,
|
|
||||||
&apzcOut, &relativePointOut);
|
|
||||||
EXPECT_EQ(apzcOut, apzcMain.get());
|
|
||||||
EXPECT_EQ(LayerIntPoint(20, 20), relativePointOut);
|
|
||||||
|
|
||||||
// Now we have a sub APZC with a better fit
|
// Now we have a sub APZC with a better fit
|
||||||
scrollable.mScrollId = FrameMetrics::START_SCROLL_ID;
|
SetScrollableFrameMetrics(layers[3], FrameMetrics::START_SCROLL_ID, mcc);
|
||||||
layerBound = layers[3]->GetVisibleRegion().GetBounds();
|
manager->UpdatePanZoomControllerTree(nullptr, root, 0, false);
|
||||||
scrollable.mViewport = CSSRect(layerBound.x, layerBound.y,
|
EXPECT_NE(root->AsContainerLayer()->GetAsyncPanZoomController(), layers[3]->AsContainerLayer()->GetAsyncPanZoomController());
|
||||||
layerBound.width, layerBound.height);
|
hit = manager->GetTargetAPZC(ScreenPoint(15, 15));
|
||||||
layers[3]->AsContainerLayer()->SetFrameMetrics(scrollable);
|
EXPECT_EQ(layers[3]->AsContainerLayer()->GetAsyncPanZoomController(), hit.get());
|
||||||
layers[3]->AsContainerLayer()->SetAsyncPanZoomController(apzcSub3);
|
// expect hit point at LayerIntPoint(15, 15)
|
||||||
AsyncPanZoomController::GetAPZCAtPoint(*root->AsContainerLayer(), touchPoint,
|
|
||||||
&apzcOut, &relativePointOut);
|
|
||||||
EXPECT_EQ(apzcOut, apzcSub3.get());
|
|
||||||
EXPECT_EQ(LayerIntPoint(20, 20), relativePointOut);
|
|
||||||
|
|
||||||
// Now test hit testing when we have two scrollable layers
|
// Now test hit testing when we have two scrollable layers
|
||||||
touchPoint = ScreenIntPoint(15,15);
|
hit = manager->GetTargetAPZC(ScreenPoint(15, 15));
|
||||||
AsyncPanZoomController::GetAPZCAtPoint(*root->AsContainerLayer(), touchPoint,
|
EXPECT_EQ(layers[3]->AsContainerLayer()->GetAsyncPanZoomController(), hit.get());
|
||||||
&apzcOut, &relativePointOut);
|
SetScrollableFrameMetrics(layers[4], FrameMetrics::START_SCROLL_ID + 1, mcc);
|
||||||
EXPECT_EQ(apzcOut, apzcSub3.get()); // We haven't bound apzcSub4 yet
|
manager->UpdatePanZoomControllerTree(nullptr, root, 0, false);
|
||||||
scrollable.mScrollId++;
|
hit = manager->GetTargetAPZC(ScreenPoint(15, 15));
|
||||||
layerBound = layers[4]->GetVisibleRegion().GetBounds();
|
EXPECT_EQ(layers[4]->AsContainerLayer()->GetAsyncPanZoomController(), hit.get());
|
||||||
scrollable.mViewport = CSSRect(layerBound.x, layerBound.y,
|
// expect hit point at LayerIntPoint(15, 15)
|
||||||
layerBound.width, layerBound.height);
|
|
||||||
layers[4]->AsContainerLayer()->SetFrameMetrics(scrollable);
|
|
||||||
layers[4]->AsContainerLayer()->SetAsyncPanZoomController(apzcSub4);
|
|
||||||
AsyncPanZoomController::GetAPZCAtPoint(*root->AsContainerLayer(), touchPoint,
|
|
||||||
&apzcOut, &relativePointOut);
|
|
||||||
EXPECT_EQ(apzcOut, apzcSub4.get());
|
|
||||||
EXPECT_EQ(LayerIntPoint(15, 15), relativePointOut);
|
|
||||||
|
|
||||||
// Hit test ouside the reach of apzc3/4 but inside apzcMain
|
// Hit test ouside the reach of layer[3,4] but inside root
|
||||||
touchPoint = ScreenIntPoint(90,90);
|
hit = manager->GetTargetAPZC(ScreenPoint(90, 90));
|
||||||
AsyncPanZoomController::GetAPZCAtPoint(*root->AsContainerLayer(), touchPoint,
|
EXPECT_EQ(root->AsContainerLayer()->GetAsyncPanZoomController(), hit.get());
|
||||||
&apzcOut, &relativePointOut);
|
// expect hit point at LayerIntPoint(90, 90)
|
||||||
EXPECT_EQ(apzcOut, apzcMain.get());
|
|
||||||
EXPECT_EQ(LayerIntPoint(90, 90), relativePointOut);
|
|
||||||
|
|
||||||
// Hit test ouside the reach of any layer
|
// Hit test ouside the reach of any layer
|
||||||
touchPoint = ScreenIntPoint(1000,10);
|
hit = manager->GetTargetAPZC(ScreenPoint(1000, 10));
|
||||||
AsyncPanZoomController::GetAPZCAtPoint(*root->AsContainerLayer(), touchPoint,
|
EXPECT_EQ(nullAPZC, hit.get());
|
||||||
&apzcOut, &relativePointOut);
|
hit = manager->GetTargetAPZC(ScreenPoint(-1000, 10));
|
||||||
EXPECT_EQ(apzcOut, nullAPZC);
|
EXPECT_EQ(nullAPZC, hit.get());
|
||||||
touchPoint = ScreenIntPoint(-1000,10);
|
|
||||||
AsyncPanZoomController::GetAPZCAtPoint(*root->AsContainerLayer(), touchPoint,
|
|
||||||
&apzcOut, &relativePointOut);
|
|
||||||
EXPECT_EQ(apzcOut, nullAPZC);
|
|
||||||
|
|
||||||
// Test layer transform
|
// Test layer transform
|
||||||
gfx3DMatrix transform;
|
gfx3DMatrix transform;
|
||||||
transform.ScalePost(0.1, 0.1, 1);
|
transform.ScalePost(0.1, 0.1, 1);
|
||||||
root->SetBaseTransform(transform);
|
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
|
hit = manager->GetTargetAPZC(ScreenPoint(2, 2));
|
||||||
AsyncPanZoomController::GetAPZCAtPoint(*root->AsContainerLayer(), touchPoint,
|
EXPECT_EQ(layers[3]->AsContainerLayer()->GetAsyncPanZoomController(), hit.get());
|
||||||
&apzcOut, &relativePointOut);
|
// expect hit point at LayerPoint(20, 20)
|
||||||
EXPECT_EQ(apzcOut, nullAPZC);
|
|
||||||
|
|
||||||
touchPoint = ScreenIntPoint(2,2);
|
|
||||||
AsyncPanZoomController::GetAPZCAtPoint(*root->AsContainerLayer(), touchPoint,
|
|
||||||
&apzcOut, &relativePointOut);
|
|
||||||
EXPECT_EQ(apzcOut, apzcSub4.get());
|
|
||||||
EXPECT_EQ(LayerIntPoint(20, 20), relativePointOut);
|
|
||||||
|
|
||||||
// Scale layer[4] outside the range
|
// Scale layer[4] outside the range
|
||||||
layers[4]->SetBaseTransform(transform);
|
layers[4]->SetBaseTransform(transform);
|
||||||
// layer 4 effective visible screenrect: (0.05, 0.05, 0.2, 0.2)
|
// layer 4 effective visible screenrect: (0.05, 0.05, 0.2, 0.2)
|
||||||
// Does not contain (2, 2)
|
// Does not contain (2, 2)
|
||||||
AsyncPanZoomController::GetAPZCAtPoint(*root->AsContainerLayer(), touchPoint,
|
root->ComputeEffectiveTransforms(gfx3DMatrix());
|
||||||
&apzcOut, &relativePointOut);
|
manager->UpdatePanZoomControllerTree(nullptr, root, 0, false);
|
||||||
EXPECT_EQ(apzcOut, apzcSub3.get());
|
hit = manager->GetTargetAPZC(ScreenPoint(2, 2));
|
||||||
EXPECT_EQ(LayerIntPoint(20, 20), relativePointOut);
|
EXPECT_EQ(layers[3]->AsContainerLayer()->GetAsyncPanZoomController(), hit.get());
|
||||||
|
// expect hit point at LayerPoint(20, 20)
|
||||||
|
|
||||||
// Transformation chain to layer 7
|
// Transformation chain to layer 7
|
||||||
scrollable.mScrollId++;
|
SetScrollableFrameMetrics(layers[7], FrameMetrics::START_SCROLL_ID + 2, mcc);
|
||||||
layerBound = layers[7]->GetVisibleRegion().GetBounds();
|
|
||||||
scrollable.mViewport = CSSRect(layerBound.x, layerBound.y,
|
|
||||||
layerBound.width, layerBound.height);
|
|
||||||
layers[7]->AsContainerLayer()->SetFrameMetrics(scrollable);
|
|
||||||
layers[7]->AsContainerLayer()->SetAsyncPanZoomController(apzcSub7);
|
|
||||||
|
|
||||||
gfx3DMatrix translateTransform;
|
gfx3DMatrix translateTransform;
|
||||||
translateTransform.Translate(gfxPoint3D(10, 10, 0));
|
translateTransform.Translate(gfxPoint3D(10, 10, 0));
|
||||||
|
@ -453,12 +455,14 @@ TEST(AsyncPanZoomController, GetAPZCAtPoint) {
|
||||||
translateTransform3.ScalePost(1,15,1);
|
translateTransform3.ScalePost(1,15,1);
|
||||||
layers[7]->SetBaseTransform(translateTransform3);
|
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
|
// layer 7 effective visible screenrect (0,16,4,60) but clipped by parent layers
|
||||||
AsyncPanZoomController::GetAPZCAtPoint(*root->AsContainerLayer(), touchPoint,
|
hit = manager->GetTargetAPZC(ScreenPoint(1, 45));
|
||||||
&apzcOut, &relativePointOut);
|
EXPECT_EQ(layers[7]->AsContainerLayer()->GetAsyncPanZoomController(), hit.get());
|
||||||
EXPECT_EQ(apzcOut, apzcSub7.get());
|
// expect hit point at LayerPoint(20, 29)
|
||||||
EXPECT_EQ(LayerIntPoint(20, 29), relativePointOut);
|
|
||||||
|
manager->ClearTree();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -48,6 +48,7 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void ComputeEffectiveTransforms(const gfx3DMatrix& aTransformToSurface) {
|
virtual void ComputeEffectiveTransforms(const gfx3DMatrix& aTransformToSurface) {
|
||||||
|
DefaultComputeEffectiveTransforms(aTransformToSurface);
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void RepositionChild(Layer* aChild, Layer* aAfter) {
|
virtual void RepositionChild(Layer* aChild, Layer* aAfter) {
|
||||||
|
@ -92,10 +93,6 @@ public:
|
||||||
return TYPE_THEBES;
|
return TYPE_THEBES;
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void ComputeEffectiveTransforms(const gfx3DMatrix& aTransformToSurface) {
|
|
||||||
MOZ_CRASH();
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual void InvalidateRegion(const nsIntRegion& aRegion) {
|
virtual void InvalidateRegion(const nsIntRegion& aRegion) {
|
||||||
MOZ_CRASH();
|
MOZ_CRASH();
|
||||||
}
|
}
|
||||||
|
@ -236,6 +233,9 @@ already_AddRefed<Layer> CreateLayerTree(
|
||||||
lastLayer = layer;
|
lastLayer = layer;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (rootLayer) {
|
||||||
|
rootLayer->ComputeEffectiveTransforms(gfx3DMatrix());
|
||||||
|
}
|
||||||
return rootLayer.forget();
|
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
|
bool
|
||||||
nsLayoutUtils::GetDisplayPort(nsIContent* aContent, nsRect *aResult)
|
nsLayoutUtils::GetDisplayPort(nsIContent* aContent, nsRect *aResult)
|
||||||
{
|
{
|
||||||
|
|
|
@ -76,6 +76,11 @@ public:
|
||||||
*/
|
*/
|
||||||
static nsIContent* FindContentFor(ViewID aId);
|
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.
|
* Get display port for the given element.
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -15,7 +15,7 @@
|
||||||
#endif //MOZ_ENABLE_D3D9_LAYER
|
#endif //MOZ_ENABLE_D3D9_LAYER
|
||||||
#include "mozilla/BrowserElementParent.h"
|
#include "mozilla/BrowserElementParent.h"
|
||||||
#include "mozilla/dom/TabParent.h"
|
#include "mozilla/dom/TabParent.h"
|
||||||
#include "mozilla/layers/AsyncPanZoomController.h"
|
#include "mozilla/layers/APZCTreeManager.h"
|
||||||
#include "mozilla/layers/CompositorParent.h"
|
#include "mozilla/layers/CompositorParent.h"
|
||||||
#include "mozilla/layers/LayerTransactionParent.h"
|
#include "mozilla/layers/LayerTransactionParent.h"
|
||||||
#include "nsContentUtils.h"
|
#include "nsContentUtils.h"
|
||||||
|
@ -552,7 +552,8 @@ public:
|
||||||
|
|
||||||
void ClearRenderFrame() { mRenderFrame = nullptr; }
|
void ClearRenderFrame() { mRenderFrame = nullptr; }
|
||||||
|
|
||||||
virtual void SendAsyncScrollDOMEvent(const CSSRect& aContentRect,
|
virtual void SendAsyncScrollDOMEvent(FrameMetrics::ViewID aScrollId,
|
||||||
|
const CSSRect& aContentRect,
|
||||||
const CSSSize& aContentSize) MOZ_OVERRIDE
|
const CSSSize& aContentSize) MOZ_OVERRIDE
|
||||||
{
|
{
|
||||||
if (MessageLoop::current() != mUILoop) {
|
if (MessageLoop::current() != mUILoop) {
|
||||||
|
@ -560,10 +561,10 @@ public:
|
||||||
FROM_HERE,
|
FROM_HERE,
|
||||||
NewRunnableMethod(this,
|
NewRunnableMethod(this,
|
||||||
&RemoteContentController::SendAsyncScrollDOMEvent,
|
&RemoteContentController::SendAsyncScrollDOMEvent,
|
||||||
aContentRect, aContentSize));
|
aScrollId, aContentRect, aContentSize));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (mRenderFrame) {
|
if (mRenderFrame && aScrollId == FrameMetrics::ROOT_SCROLL_ID) {
|
||||||
TabParent* browser = static_cast<TabParent*>(mRenderFrame->Manager());
|
TabParent* browser = static_cast<TabParent*>(mRenderFrame->Manager());
|
||||||
BrowserElementParent::DispatchAsyncScrollEvent(browser, aContentRect,
|
BrowserElementParent::DispatchAsyncScrollEvent(browser, aContentRect,
|
||||||
aContentSize);
|
aContentSize);
|
||||||
|
@ -620,14 +621,24 @@ RenderFrameParent::RenderFrameParent(nsFrameLoader* aFrameLoader,
|
||||||
}
|
}
|
||||||
if (aScrollingBehavior == ASYNC_PAN_ZOOM) {
|
if (aScrollingBehavior == ASYNC_PAN_ZOOM) {
|
||||||
mContentController = new RemoteContentController(this);
|
mContentController = new RemoteContentController(this);
|
||||||
mPanZoomController = new AsyncPanZoomController(
|
CompositorParent::SetControllerForLayerTree(mLayersId, mContentController);
|
||||||
mContentController, AsyncPanZoomController::USE_GESTURE_DETECTOR);
|
|
||||||
CompositorParent::SetPanZoomControllerForLayerTree(mLayersId,
|
|
||||||
mPanZoomController);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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()
|
RenderFrameParent::~RenderFrameParent()
|
||||||
{}
|
{}
|
||||||
|
|
||||||
|
@ -787,17 +798,17 @@ void
|
||||||
RenderFrameParent::NotifyInputEvent(const nsInputEvent& aEvent,
|
RenderFrameParent::NotifyInputEvent(const nsInputEvent& aEvent,
|
||||||
nsInputEvent* aOutEvent)
|
nsInputEvent* aOutEvent)
|
||||||
{
|
{
|
||||||
if (mPanZoomController) {
|
if (GetApzcTreeManager()) {
|
||||||
mPanZoomController->ReceiveInputEvent(aEvent, aOutEvent);
|
GetApzcTreeManager()->ReceiveInputEvent(aEvent, aOutEvent);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
RenderFrameParent::NotifyDimensionsChanged(ScreenIntSize size)
|
RenderFrameParent::NotifyDimensionsChanged(ScreenIntSize size)
|
||||||
{
|
{
|
||||||
if (mPanZoomController) {
|
if (GetApzcTreeManager()) {
|
||||||
mPanZoomController->UpdateCompositionBounds(
|
GetApzcTreeManager()->UpdateCompositionBounds(ScrollableLayerGuid(mLayersId),
|
||||||
ScreenIntRect(ScreenIntPoint(), size));
|
ScreenIntRect(ScreenIntPoint(), size));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -810,7 +821,7 @@ RenderFrameParent::ActorDestroy(ActorDestroyReason why)
|
||||||
// Stop our content controller from requesting repaints of our
|
// Stop our content controller from requesting repaints of our
|
||||||
// content.
|
// content.
|
||||||
mContentController->ClearRenderFrame();
|
mContentController->ClearRenderFrame();
|
||||||
mPanZoomController->Destroy();
|
// TODO: notify the compositor?
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -836,8 +847,8 @@ RenderFrameParent::RecvNotifyCompositorTransaction()
|
||||||
bool
|
bool
|
||||||
RenderFrameParent::RecvCancelDefaultPanZoom()
|
RenderFrameParent::RecvCancelDefaultPanZoom()
|
||||||
{
|
{
|
||||||
if (mPanZoomController) {
|
if (GetApzcTreeManager()) {
|
||||||
mPanZoomController->CancelDefaultPanZoom();
|
GetApzcTreeManager()->CancelDefaultPanZoom(ScrollableLayerGuid(mLayersId));
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -845,8 +856,8 @@ RenderFrameParent::RecvCancelDefaultPanZoom()
|
||||||
bool
|
bool
|
||||||
RenderFrameParent::RecvDetectScrollableSubframe()
|
RenderFrameParent::RecvDetectScrollableSubframe()
|
||||||
{
|
{
|
||||||
if (mPanZoomController) {
|
if (GetApzcTreeManager()) {
|
||||||
mPanZoomController->DetectScrollableSubframe();
|
GetApzcTreeManager()->DetectScrollableSubframe(ScrollableLayerGuid(mLayersId));
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -972,24 +983,27 @@ RenderFrameParent::BuildDisplayList(nsDisplayListBuilder* aBuilder,
|
||||||
void
|
void
|
||||||
RenderFrameParent::ZoomToRect(const CSSRect& aRect)
|
RenderFrameParent::ZoomToRect(const CSSRect& aRect)
|
||||||
{
|
{
|
||||||
if (mPanZoomController) {
|
if (GetApzcTreeManager()) {
|
||||||
mPanZoomController->ZoomToRect(aRect);
|
GetApzcTreeManager()->ZoomToRect(ScrollableLayerGuid(mLayersId),
|
||||||
|
aRect);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
RenderFrameParent::ContentReceivedTouch(bool aPreventDefault)
|
RenderFrameParent::ContentReceivedTouch(bool aPreventDefault)
|
||||||
{
|
{
|
||||||
if (mPanZoomController) {
|
if (GetApzcTreeManager()) {
|
||||||
mPanZoomController->ContentReceivedTouch(aPreventDefault);
|
GetApzcTreeManager()->ContentReceivedTouch(ScrollableLayerGuid(mLayersId),
|
||||||
|
aPreventDefault);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
RenderFrameParent::UpdateZoomConstraints(bool aAllowZoom, float aMinZoom, float aMaxZoom)
|
RenderFrameParent::UpdateZoomConstraints(bool aAllowZoom, float aMinZoom, float aMaxZoom)
|
||||||
{
|
{
|
||||||
if (mPanZoomController) {
|
if (GetApzcTreeManager()) {
|
||||||
mPanZoomController->UpdateZoomConstraints(aAllowZoom, aMinZoom, aMaxZoom);
|
GetApzcTreeManager()->UpdateZoomConstraints(ScrollableLayerGuid(mLayersId),
|
||||||
|
aAllowZoom, aMinZoom, aMaxZoom);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -25,7 +25,7 @@ namespace mozilla {
|
||||||
class InputEvent;
|
class InputEvent;
|
||||||
|
|
||||||
namespace layers {
|
namespace layers {
|
||||||
class AsyncPanZoomController;
|
class APZCTreeManager;
|
||||||
class GestureEventListener;
|
class GestureEventListener;
|
||||||
class TargetConfig;
|
class TargetConfig;
|
||||||
class LayerTransactionParent;
|
class LayerTransactionParent;
|
||||||
|
@ -132,11 +132,13 @@ private:
|
||||||
nsRefPtr<nsFrameLoader> mFrameLoader;
|
nsRefPtr<nsFrameLoader> mFrameLoader;
|
||||||
nsRefPtr<ContainerLayer> mContainer;
|
nsRefPtr<ContainerLayer> mContainer;
|
||||||
// When our scrolling behavior is ASYNC_PAN_ZOOM, we have a nonnull
|
// When our scrolling behavior is ASYNC_PAN_ZOOM, we have a nonnull
|
||||||
// AsyncPanZoomController. It's associated with the shadow layer
|
// APZCTreeManager. It's used to manipulate the shadow layer tree
|
||||||
// tree on the compositor thread.
|
// on the compositor thread.
|
||||||
nsRefPtr<layers::AsyncPanZoomController> mPanZoomController;
|
nsRefPtr<layers::APZCTreeManager> mApzcTreeManager;
|
||||||
nsRefPtr<RemoteContentController> mContentController;
|
nsRefPtr<RemoteContentController> mContentController;
|
||||||
|
|
||||||
|
layers::APZCTreeManager* GetApzcTreeManager();
|
||||||
|
|
||||||
// This contains the views for all the scrollable frames currently in the
|
// This contains the views for all the scrollable frames currently in the
|
||||||
// painted region of our remote content.
|
// painted region of our remote content.
|
||||||
ViewMap mContentViews;
|
ViewMap mContentViews;
|
||||||
|
|
|
@ -96,6 +96,9 @@ endif #}
|
||||||
|
|
||||||
ifdef MOZ_B2G_BT #{
|
ifdef MOZ_B2G_BT #{
|
||||||
STATIC_LIBS += mozdbus_s
|
STATIC_LIBS += mozdbus_s
|
||||||
|
ifeq (gonk,$(MOZ_WIDGET_TOOLKIT))
|
||||||
|
OS_LIBS += -ldbus
|
||||||
|
endif
|
||||||
endif #}
|
endif #}
|
||||||
|
|
||||||
ifneq ($(strip $(MOZ_B2G_RIL)$(MOZ_B2G_BT)),) #{
|
ifneq ($(strip $(MOZ_B2G_RIL)$(MOZ_B2G_BT)),) #{
|
||||||
|
@ -446,7 +449,6 @@ OS_LIBS += \
|
||||||
-lsysutils \
|
-lsysutils \
|
||||||
-lcamera_client \
|
-lcamera_client \
|
||||||
-lsensorservice \
|
-lsensorservice \
|
||||||
-ldbus \
|
|
||||||
-lstagefright \
|
-lstagefright \
|
||||||
-lstagefright_foundation \
|
-lstagefright_foundation \
|
||||||
-lstagefright_omx \
|
-lstagefright_omx \
|
||||||
|
|
|
@ -2850,7 +2850,9 @@ AndroidBridge::HandleLongTap(const CSSIntPoint& aPoint)
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
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
|
// FIXME implement this
|
||||||
}
|
}
|
||||||
|
|
|
@ -601,7 +601,9 @@ public:
|
||||||
void HandleDoubleTap(const CSSIntPoint& aPoint) MOZ_OVERRIDE;
|
void HandleDoubleTap(const CSSIntPoint& aPoint) MOZ_OVERRIDE;
|
||||||
void HandleSingleTap(const CSSIntPoint& aPoint) MOZ_OVERRIDE;
|
void HandleSingleTap(const CSSIntPoint& aPoint) MOZ_OVERRIDE;
|
||||||
void HandleLongTap(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;
|
void PostDelayedTask(Task* aTask, int aDelayMs) MOZ_OVERRIDE;
|
||||||
int64_t RunDelayedTasks();
|
int64_t RunDelayedTasks();
|
||||||
};
|
};
|
||||||
|
|
|
@ -35,7 +35,7 @@
|
||||||
#include "mozilla/dom/mobilemessage/Types.h"
|
#include "mozilla/dom/mobilemessage/Types.h"
|
||||||
#include "mozilla/dom/mobilemessage/PSms.h"
|
#include "mozilla/dom/mobilemessage/PSms.h"
|
||||||
#include "mozilla/dom/mobilemessage/SmsParent.h"
|
#include "mozilla/dom/mobilemessage/SmsParent.h"
|
||||||
#include "mozilla/layers/AsyncPanZoomController.h"
|
#include "mozilla/layers/APZCTreeManager.h"
|
||||||
#include "nsIMobileMessageDatabaseService.h"
|
#include "nsIMobileMessageDatabaseService.h"
|
||||||
#include "nsPluginInstanceOwner.h"
|
#include "nsPluginInstanceOwner.h"
|
||||||
#include "nsSurfaceTexture.h"
|
#include "nsSurfaceTexture.h"
|
||||||
|
@ -847,10 +847,10 @@ Java_org_mozilla_gecko_GeckoJavaSampler_getProfilerTime(JNIEnv *jenv, jclass jc)
|
||||||
NS_EXPORT void JNICALL
|
NS_EXPORT void JNICALL
|
||||||
Java_org_mozilla_gecko_gfx_NativePanZoomController_abortAnimation(JNIEnv* env, jobject instance)
|
Java_org_mozilla_gecko_gfx_NativePanZoomController_abortAnimation(JNIEnv* env, jobject instance)
|
||||||
{
|
{
|
||||||
AsyncPanZoomController* controller = nsWindow::GetPanZoomController();
|
APZCTreeManager *controller = nsWindow::GetAPZCTreeManager();
|
||||||
if (controller) {
|
if (controller) {
|
||||||
controller->CancelAnimation();
|
controller->CancelAnimation(ScrollableLayerGuid(nsWindow::RootLayerTreeId()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
NS_EXPORT void JNICALL
|
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");
|
MOZ_ASSERT(false, "Registering a new NPZC when we already have one");
|
||||||
env->DeleteGlobalRef(oldRef);
|
env->DeleteGlobalRef(oldRef);
|
||||||
}
|
}
|
||||||
nsWindow::SetPanZoomController(new AsyncPanZoomController(AndroidBridge::Bridge(), AsyncPanZoomController::USE_GESTURE_DETECTOR));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
NS_EXPORT void JNICALL
|
NS_EXPORT void JNICALL
|
||||||
Java_org_mozilla_gecko_gfx_NativePanZoomController_handleTouchEvent(JNIEnv* env, jobject instance, jobject event)
|
Java_org_mozilla_gecko_gfx_NativePanZoomController_handleTouchEvent(JNIEnv* env, jobject instance, jobject event)
|
||||||
{
|
{
|
||||||
AsyncPanZoomController *controller = nsWindow::GetPanZoomController();
|
APZCTreeManager *controller = nsWindow::GetAPZCTreeManager();
|
||||||
if (controller) {
|
if (controller) {
|
||||||
AndroidGeckoEvent* wrapper = AndroidGeckoEvent::MakeFromJavaObject(env, event);
|
AndroidGeckoEvent* wrapper = AndroidGeckoEvent::MakeFromJavaObject(env, event);
|
||||||
const MultiTouchInput& input = wrapper->MakeMultiTouchInput(nsWindow::TopWindow());
|
const MultiTouchInput& input = wrapper->MakeMultiTouchInput(nsWindow::TopWindow());
|
||||||
|
@ -905,7 +904,6 @@ Java_org_mozilla_gecko_gfx_NativePanZoomController_destroy(JNIEnv* env, jobject
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
nsWindow::SetPanZoomController(nullptr);
|
|
||||||
jobject oldRef = AndroidBridge::Bridge()->SetNativePanZoomController(NULL);
|
jobject oldRef = AndroidBridge::Bridge()->SetNativePanZoomController(NULL);
|
||||||
if (!oldRef) {
|
if (!oldRef) {
|
||||||
MOZ_ASSERT(false, "Clearing a non-existent NPZC");
|
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
|
NS_EXPORT void JNICALL
|
||||||
Java_org_mozilla_gecko_gfx_NativePanZoomController_notifyDefaultActionPrevented(JNIEnv* env, jobject instance, jboolean prevented)
|
Java_org_mozilla_gecko_gfx_NativePanZoomController_notifyDefaultActionPrevented(JNIEnv* env, jobject instance, jboolean prevented)
|
||||||
{
|
{
|
||||||
AsyncPanZoomController *controller = nsWindow::GetPanZoomController();
|
APZCTreeManager *controller = nsWindow::GetAPZCTreeManager();
|
||||||
if (controller) {
|
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
|
NS_EXPORT void JNICALL
|
||||||
Java_org_mozilla_gecko_gfx_NativePanZoomController_updateScrollOffset(JNIEnv* env, jobject instance, jfloat cssX, jfloat cssY)
|
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) {
|
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
|
// off-main-thread compositor fields and functions
|
||||||
|
|
||||||
|
nsRefPtr<mozilla::layers::APZCTreeManager> nsWindow::sApzcTreeManager = 0;
|
||||||
nsRefPtr<mozilla::layers::LayerManager> nsWindow::sLayerManager = 0;
|
nsRefPtr<mozilla::layers::LayerManager> nsWindow::sLayerManager = 0;
|
||||||
nsRefPtr<mozilla::layers::CompositorParent> nsWindow::sCompositorParent = 0;
|
nsRefPtr<mozilla::layers::CompositorParent> nsWindow::sCompositorParent = 0;
|
||||||
nsRefPtr<mozilla::layers::CompositorChild> nsWindow::sCompositorChild = 0;
|
nsRefPtr<mozilla::layers::CompositorChild> nsWindow::sCompositorChild = 0;
|
||||||
bool nsWindow::sCompositorPaused = true;
|
bool nsWindow::sCompositorPaused = true;
|
||||||
nsRefPtr<mozilla::layers::AsyncPanZoomController> nsWindow::sApzc = 0;
|
|
||||||
|
|
||||||
void
|
void
|
||||||
nsWindow::SetCompositor(mozilla::layers::LayerManager* aLayerManager,
|
nsWindow::SetCompositor(mozilla::layers::LayerManager* aLayerManager,
|
||||||
|
@ -2496,52 +2496,30 @@ nsWindow::NeedsPaint()
|
||||||
return nsIWidget::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*
|
CompositorParent*
|
||||||
nsWindow::NewCompositorParent(int aSurfaceWidth, int aSurfaceHeight)
|
nsWindow::NewCompositorParent(int aSurfaceWidth, int aSurfaceHeight)
|
||||||
{
|
{
|
||||||
return new AndroidCompositorParent(this, true, aSurfaceWidth, aSurfaceHeight);
|
return new CompositorParent(this, true, aSurfaceWidth, aSurfaceHeight);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
mozilla::layers::APZCTreeManager*
|
||||||
nsWindow::SetPanZoomController(AsyncPanZoomController* apzc)
|
nsWindow::GetAPZCTreeManager()
|
||||||
{
|
{
|
||||||
if (sApzc) {
|
if (!sApzcTreeManager) {
|
||||||
sApzc->SetCompositorParent(nullptr);
|
CompositorParent* compositor = sCompositorParent;
|
||||||
sApzc = nullptr;
|
if (!compositor) {
|
||||||
}
|
return nullptr;
|
||||||
if (apzc) {
|
}
|
||||||
sApzc = apzc;
|
uint64_t rootLayerTreeId = compositor->RootLayerTreeId();
|
||||||
sApzc->SetCompositorParent(sCompositorParent);
|
CompositorParent::SetControllerForLayerTree(rootLayerTreeId, AndroidBridge::Bridge());
|
||||||
|
sApzcTreeManager = CompositorParent::GetAPZCTreeManager(rootLayerTreeId);
|
||||||
}
|
}
|
||||||
|
return sApzcTreeManager;
|
||||||
}
|
}
|
||||||
|
|
||||||
AsyncPanZoomController*
|
uint64_t
|
||||||
nsWindow::GetPanZoomController()
|
nsWindow::RootLayerTreeId()
|
||||||
{
|
{
|
||||||
return sApzc;
|
MOZ_ASSERT(sCompositorParent);
|
||||||
|
return sCompositorParent->RootLayerTreeId();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -23,7 +23,7 @@ namespace mozilla {
|
||||||
class CompositorParent;
|
class CompositorParent;
|
||||||
class CompositorChild;
|
class CompositorChild;
|
||||||
class LayerManager;
|
class LayerManager;
|
||||||
class AsyncPanZoomController;
|
class APZCTreeManager;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -155,8 +155,9 @@ public:
|
||||||
static void ScheduleResumeComposition(int width, int height);
|
static void ScheduleResumeComposition(int width, int height);
|
||||||
static void ForceIsFirstPaint();
|
static void ForceIsFirstPaint();
|
||||||
static float ComputeRenderIntegrity();
|
static float ComputeRenderIntegrity();
|
||||||
static void SetPanZoomController(mozilla::layers::AsyncPanZoomController* apzc);
|
static mozilla::layers::APZCTreeManager* GetAPZCTreeManager();
|
||||||
static mozilla::layers::AsyncPanZoomController* GetPanZoomController();
|
/* RootLayerTreeId() can only be called when GetAPZCTreeManager() returns non-null */
|
||||||
|
static uint64_t RootLayerTreeId();
|
||||||
|
|
||||||
virtual bool WidgetPaintsBackground();
|
virtual bool WidgetPaintsBackground();
|
||||||
|
|
||||||
|
@ -231,11 +232,11 @@ private:
|
||||||
|
|
||||||
mozilla::AndroidLayerRendererFrame mLayerRendererFrame;
|
mozilla::AndroidLayerRendererFrame mLayerRendererFrame;
|
||||||
|
|
||||||
|
static nsRefPtr<mozilla::layers::APZCTreeManager> sApzcTreeManager;
|
||||||
static nsRefPtr<mozilla::layers::LayerManager> sLayerManager;
|
static nsRefPtr<mozilla::layers::LayerManager> sLayerManager;
|
||||||
static nsRefPtr<mozilla::layers::CompositorParent> sCompositorParent;
|
static nsRefPtr<mozilla::layers::CompositorParent> sCompositorParent;
|
||||||
static nsRefPtr<mozilla::layers::CompositorChild> sCompositorChild;
|
static nsRefPtr<mozilla::layers::CompositorChild> sCompositorChild;
|
||||||
static bool sCompositorPaused;
|
static bool sCompositorPaused;
|
||||||
static nsRefPtr<mozilla::layers::AsyncPanZoomController> sApzc;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /* NSWINDOW_H_ */
|
#endif /* NSWINDOW_H_ */
|
||||||
|
|
|
@ -29,7 +29,6 @@
|
||||||
#include <EGL/egl.h>
|
#include <EGL/egl.h>
|
||||||
|
|
||||||
#include <hardware/hardware.h>
|
#include <hardware/hardware.h>
|
||||||
#include <gui/SurfaceTextureClient.h>
|
|
||||||
#include <ui/GraphicBuffer.h>
|
#include <ui/GraphicBuffer.h>
|
||||||
|
|
||||||
#include "FramebufferSurface.h"
|
#include "FramebufferSurface.h"
|
||||||
|
|
|
@ -14,7 +14,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "GonkDisplayJB.h"
|
#include "GonkDisplayJB.h"
|
||||||
#include <gui/SurfaceTextureClient.h>
|
#include <gui/Surface.h>
|
||||||
|
|
||||||
#include <hardware/hardware.h>
|
#include <hardware/hardware.h>
|
||||||
#include <hardware/hwcomposer.h>
|
#include <hardware/hwcomposer.h>
|
||||||
|
@ -99,7 +99,7 @@ GonkDisplayJB::GonkDisplayJB()
|
||||||
mAlloc = new GraphicBufferAlloc();
|
mAlloc = new GraphicBufferAlloc();
|
||||||
mFBSurface = new FramebufferSurface(0, mWidth, mHeight, surfaceformat, mAlloc);
|
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;
|
mSTClient = stc;
|
||||||
|
|
||||||
mList = (hwc_display_contents_1_t *)malloc(sizeof(*mList) + (sizeof(hwc_layer_1_t)*2));
|
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();
|
StopBootAnimation();
|
||||||
mBootAnimBuffer = nullptr;
|
mBootAnimBuffer = nullptr;
|
||||||
|
|
||||||
mList->dpy = dpy;
|
mList->outbuf = nullptr;
|
||||||
mList->sur = sur;
|
mList->outbufAcquireFenceFd = -1;
|
||||||
eglSwapBuffers(dpy, sur);
|
eglSwapBuffers(dpy, sur);
|
||||||
return Post(mFBSurface->lastHandle, mFBSurface->lastFenceFD);
|
return Post(mFBSurface->lastHandle, mFBSurface->lastFenceFD);
|
||||||
}
|
}
|
||||||
|
@ -189,8 +189,11 @@ GonkDisplayJB::Post(buffer_handle_t buf, int fence)
|
||||||
mList->flags = HWC_GEOMETRY_CHANGED;
|
mList->flags = HWC_GEOMETRY_CHANGED;
|
||||||
mList->hwLayers[0].compositionType = HWC_BACKGROUND;
|
mList->hwLayers[0].compositionType = HWC_BACKGROUND;
|
||||||
mList->hwLayers[0].hints = 0;
|
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};
|
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].compositionType = HWC_FRAMEBUFFER_TARGET;
|
||||||
mList->hwLayers[1].hints = 0;
|
mList->hwLayers[1].hints = 0;
|
||||||
mList->hwLayers[1].flags = 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].sourceCrop = r;
|
||||||
mList->hwLayers[1].displayFrame = r;
|
mList->hwLayers[1].displayFrame = r;
|
||||||
mList->hwLayers[1].visibleRegionScreen.numRects = 1;
|
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].acquireFenceFd = fence;
|
||||||
mList->hwLayers[1].releaseFenceFd = -1;
|
mList->hwLayers[1].releaseFenceFd = -1;
|
||||||
|
mList->hwLayers[1].planeAlpha = 0xFF;
|
||||||
mHwc->prepare(mHwc, HWC_NUM_DISPLAY_TYPES, displays);
|
mHwc->prepare(mHwc, HWC_NUM_DISPLAY_TYPES, displays);
|
||||||
int err = mHwc->set(mHwc, HWC_NUM_DISPLAY_TYPES, displays);
|
int err = mHwc->set(mHwc, HWC_NUM_DISPLAY_TYPES, displays);
|
||||||
mFBSurface->setReleaseFenceFd(mList->hwLayers[1].releaseFenceFd);
|
mFBSurface->setReleaseFenceFd(mList->hwLayers[1].releaseFenceFd);
|
||||||
|
|
|
@ -20,7 +20,7 @@ CPP_SOURCES += [
|
||||||
'BootAnimation.cpp',
|
'BootAnimation.cpp',
|
||||||
]
|
]
|
||||||
|
|
||||||
if CONFIG['ANDROID_VERSION'] == '17':
|
if CONFIG['ANDROID_VERSION'] == '18':
|
||||||
CPP_SOURCES += [
|
CPP_SOURCES += [
|
||||||
'FramebufferSurface.cpp',
|
'FramebufferSurface.cpp',
|
||||||
'GraphicBufferAlloc.cpp',
|
'GraphicBufferAlloc.cpp',
|
||||||
|
|
|
@ -52,6 +52,7 @@
|
||||||
#include "libui/EventHub.h"
|
#include "libui/EventHub.h"
|
||||||
#include "libui/InputReader.h"
|
#include "libui/InputReader.h"
|
||||||
#include "libui/InputDispatcher.h"
|
#include "libui/InputDispatcher.h"
|
||||||
|
#include "cutils/properties.h"
|
||||||
|
|
||||||
#include "GeckoProfiler.h"
|
#include "GeckoProfiler.h"
|
||||||
|
|
||||||
|
@ -78,6 +79,9 @@ bool gDrawRequest = false;
|
||||||
static nsAppShell *gAppShell = NULL;
|
static nsAppShell *gAppShell = NULL;
|
||||||
static int epollfd = 0;
|
static int epollfd = 0;
|
||||||
static int signalfds[2] = {0};
|
static int signalfds[2] = {0};
|
||||||
|
static bool sDevInputAudioJack;
|
||||||
|
static int32_t sHeadphoneState;
|
||||||
|
static int32_t sMicrophoneState;
|
||||||
|
|
||||||
NS_IMPL_ISUPPORTS_INHERITED1(nsAppShell, nsBaseAppShell, nsIObserver)
|
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 {
|
class GeckoPointerController : public PointerControllerInterface {
|
||||||
float mX;
|
float mX;
|
||||||
float mY;
|
float mY;
|
||||||
|
@ -553,6 +592,19 @@ GeckoInputDispatcher::notifyMotion(const NotifyMotionArgs* args)
|
||||||
|
|
||||||
void GeckoInputDispatcher::notifySwitch(const NotifySwitchArgs* 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)
|
void GeckoInputDispatcher::notifyDeviceReset(const NotifyDeviceResetArgs* args)
|
||||||
|
@ -661,6 +713,12 @@ nsAppShell::Observe(nsISupports* aSubject,
|
||||||
return nsBaseAppShell::Observe(aSubject, aTopic, aData);
|
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;
|
mEnableDraw = true;
|
||||||
NotifyEvent();
|
NotifyEvent();
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
|
@ -680,6 +738,12 @@ nsAppShell::Exit()
|
||||||
void
|
void
|
||||||
nsAppShell::InitInputDevices()
|
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();
|
mEventHub = new EventHub();
|
||||||
mReaderPolicy = new GeckoInputReaderPolicy();
|
mReaderPolicy = new GeckoInputReaderPolicy();
|
||||||
mReaderPolicy->setDisplayInfo();
|
mReaderPolicy->setDisplayInfo();
|
||||||
|
|
|
@ -140,7 +140,7 @@ namespace {
|
||||||
NS_IMPL_ISUPPORTS_INHERITED0(MetroWidget, nsBaseWidget)
|
NS_IMPL_ISUPPORTS_INHERITED0(MetroWidget, nsBaseWidget)
|
||||||
|
|
||||||
|
|
||||||
nsRefPtr<mozilla::layers::AsyncPanZoomController> MetroWidget::sAPZC;
|
nsRefPtr<mozilla::layers::APZCTreeManager> MetroWidget::sAPZC;
|
||||||
|
|
||||||
MetroWidget::MetroWidget() :
|
MetroWidget::MetroWidget() :
|
||||||
mTransparencyMode(eTransparencyOpaque),
|
mTransparencyMode(eTransparencyOpaque),
|
||||||
|
@ -166,7 +166,6 @@ MetroWidget::~MetroWidget()
|
||||||
|
|
||||||
// Global shutdown
|
// Global shutdown
|
||||||
if (!gInstanceCount) {
|
if (!gInstanceCount) {
|
||||||
MetroWidget::sAPZC->Destroy();
|
|
||||||
MetroWidget::sAPZC = nullptr;
|
MetroWidget::sAPZC = nullptr;
|
||||||
nsTextStore::Terminate();
|
nsTextStore::Terminate();
|
||||||
} // !gInstanceCount
|
} // !gInstanceCount
|
||||||
|
@ -813,22 +812,8 @@ public:
|
||||||
observerService->AddObserver(this, "viewport-needs-updating", false);
|
observerService->AddObserver(this, "viewport-needs-updating", false);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (MetroWidget::sAPZC) {
|
CompositorParent::SetControllerForLayerTree(RootLayerTreeId(), aMetroWidget);
|
||||||
MetroWidget::sAPZC->SetCompositorParent(this);
|
MetroWidget::sAPZC = CompositorParent::GetAPZCTreeManager(RootLayerTreeId());
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
NS_IMETHODIMP Observe(nsISupports *subject, const char *topic, const PRUnichar *data)
|
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),
|
||||||
mozilla::gfx::Point(0.0f, 0.0f),
|
mozilla::gfx::Point(0.0f, 0.0f),
|
||||||
0.0);
|
0.0);
|
||||||
MetroWidget::sAPZC->NotifyLayersUpdated(frameMetrics, true);
|
|
||||||
mMetroWidget->RequestContentRepaint(frameMetrics);
|
mMetroWidget->RequestContentRepaint(frameMetrics);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -910,10 +894,6 @@ MetroWidget::GetLayerManager(PLayerTransactionChild* aShadowManager,
|
||||||
if (ShouldUseOffMainThreadCompositing()) {
|
if (ShouldUseOffMainThreadCompositing()) {
|
||||||
NS_ASSERTION(aShadowManager == nullptr, "Async Compositor not supported with e10s");
|
NS_ASSERTION(aShadowManager == nullptr, "Async Compositor not supported with e10s");
|
||||||
CreateCompositor();
|
CreateCompositor();
|
||||||
if (ShouldUseAPZC()) {
|
|
||||||
sAPZC = new AsyncPanZoomController(this, AsyncPanZoomController::USE_GESTURE_DETECTOR);
|
|
||||||
sAPZC->SetCompositorParent(mCompositorParent);
|
|
||||||
}
|
|
||||||
} else if (ShouldUseMainThreadD3D10Manager()) {
|
} else if (ShouldUseMainThreadD3D10Manager()) {
|
||||||
nsRefPtr<mozilla::layers::LayerManagerD3D10> layerManager =
|
nsRefPtr<mozilla::layers::LayerManagerD3D10> layerManager =
|
||||||
new mozilla::layers::LayerManagerD3D10(this);
|
new mozilla::layers::LayerManagerD3D10(this);
|
||||||
|
@ -1457,7 +1437,7 @@ MetroWidget::HandleLongTap(const CSSIntPoint& aPoint)
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
MetroWidget::SendAsyncScrollDOMEvent(const CSSRect &aContentRect, const CSSSize &aScrollableSize)
|
MetroWidget::SendAsyncScrollDOMEvent(FrameMetrics::ViewID aScrollId, const CSSRect &aContentRect, const CSSSize &aScrollableSize)
|
||||||
{
|
{
|
||||||
LogFunction();
|
LogFunction();
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,7 +23,7 @@
|
||||||
#endif
|
#endif
|
||||||
#include "mozilla/layers/CompositorParent.h"
|
#include "mozilla/layers/CompositorParent.h"
|
||||||
#include "mozilla/layers/GeckoContentController.h"
|
#include "mozilla/layers/GeckoContentController.h"
|
||||||
#include "mozilla/layers/AsyncPanZoomController.h"
|
#include "mozilla/layers/APZCTreeManager.h"
|
||||||
#include "mozilla/layers/LayerManagerComposite.h"
|
#include "mozilla/layers/LayerManagerComposite.h"
|
||||||
#include "Units.h"
|
#include "Units.h"
|
||||||
#include "MetroInput.h"
|
#include "MetroInput.h"
|
||||||
|
@ -191,7 +191,7 @@ public:
|
||||||
virtual void HandleDoubleTap(const mozilla::CSSIntPoint& aPoint);
|
virtual void HandleDoubleTap(const mozilla::CSSIntPoint& aPoint);
|
||||||
virtual void HandleSingleTap(const mozilla::CSSIntPoint& aPoint);
|
virtual void HandleSingleTap(const mozilla::CSSIntPoint& aPoint);
|
||||||
virtual void HandleLongTap(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 PostDelayedTask(Task* aTask, int aDelayMs);
|
||||||
virtual void HandlePanBegin();
|
virtual void HandlePanBegin();
|
||||||
virtual void HandlePanEnd();
|
virtual void HandlePanEnd();
|
||||||
|
@ -237,5 +237,5 @@ protected:
|
||||||
mozilla::layers::FrameMetrics mFrameMetrics;
|
mozilla::layers::FrameMetrics mFrameMetrics;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
static nsRefPtr<mozilla::layers::AsyncPanZoomController> sAPZC;
|
static nsRefPtr<mozilla::layers::APZCTreeManager> sAPZC;
|
||||||
};
|
};
|
||||||
|
|
Загрузка…
Ссылка в новой задаче