summaryrefslogtreecommitdiffstats
path: root/gfx/doc/B2GInputFlow.svg
diff options
context:
space:
mode:
Diffstat (limited to 'gfx/doc/B2GInputFlow.svg')
-rw-r--r--gfx/doc/B2GInputFlow.svg349
1 files changed, 349 insertions, 0 deletions
diff --git a/gfx/doc/B2GInputFlow.svg b/gfx/doc/B2GInputFlow.svg
new file mode 100644
index 000000000..ee6f4332c
--- /dev/null
+++ b/gfx/doc/B2GInputFlow.svg
@@ -0,0 +1,349 @@
+<?xml version="1.0"?>
+<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="1000" height="800">
+ <title>Touch input event flow on B2G</title>
+ <g id="arrows"></g>
+ <style type="text/css"><![CDATA[
+ text {
+ fill: black;
+ text-anchor: middle;
+ white-space: pre-line;
+ font-size: 14px;
+ }
+ rect {
+ fill: none;
+ }
+ line {
+ stroke: black;
+ }
+ .parentinput rect {
+ stroke: black;
+ }
+ text.parentinput {
+ fill: black;
+ text-anchor: start;
+ }
+ .parentmain rect {
+ stroke: orange;
+ }
+ text.parentmain {
+ fill: orange;
+ text-anchor: start;
+ }
+ .parentcompositor rect {
+ stroke: green;
+ }
+ text.parentcompositor {
+ fill: green;
+ text-anchor: start;
+ }
+ .childmain rect {
+ stroke: red;
+ }
+ text.childmain {
+ fill: red;
+ text-anchor: start;
+ }
+ .bothmain rect {
+ stroke: blue;
+ }
+ text.bothmain {
+ fill: blue;
+ text-anchor: start;
+ }
+ ]]></style>
+ <script type="text/javascript"><![CDATA[
+ var svg = "http://www.w3.org/2000/svg";
+ var maxY = 0;
+
+ function breaks(text) {
+ var count = 0;
+ for (var i = text.length - 1; i >= 0; i--) {
+ if (text.charAt(i) == '\n') {
+ count++;
+ }
+ }
+ return count;
+ }
+
+ function makeAction(text, x, y, thread) {
+ maxY = Math.max(maxY, y);
+ var g = document.createElementNS(svg, "g");
+ g.setAttribute("class", "action " + thread);
+ g.setAttribute("transform", "translate(" + x + ", " + (y + 30) + ")");
+ var r = document.createElementNS(svg, "rect");
+ r.setAttribute("width", "100");
+ r.setAttribute("height", "40");
+ var t = document.createElementNS(svg, "text");
+ t.setAttribute("x", "50");
+ t.setAttribute("y", 25 - (7 * breaks(text)));
+ t.appendChild(document.createTextNode(text));
+ g.appendChild(r);
+ g.appendChild(t);
+ return g;
+ }
+
+ function makeChoice(text, x, y, thread) {
+ maxY = Math.max(maxY, y);
+ var g = document.createElementNS(svg, "g");
+ g.setAttribute("class", "choice " + thread);
+ g.setAttribute("transform", "translate(" + (x + 15) + ", " + (y + 15) + ")");
+ var g2 = document.createElementNS(svg, "g");
+ g2.setAttribute("transform", "rotate(-45, 35, 35)");
+ var r = document.createElementNS(svg, "rect");
+ r.setAttribute("width", "70");
+ r.setAttribute("height", "70");
+ g2.appendChild(r);
+ var t = document.createElementNS(svg, "text");
+ t.setAttribute("x", "35");
+ t.setAttribute("y", 40 - (7 * breaks(text)));
+ t.appendChild(document.createTextNode(text));
+ g.appendChild(g2);
+ g.appendChild(t);
+ return g;
+ }
+
+ function makeLabelChoice(label, point) {
+ var t = document.createElementNS(svg, "text");
+ t.setAttribute("x", point.x);
+ t.setAttribute("y", point.y);
+ t.appendChild(document.createTextNode(label));
+ return t;
+ }
+
+ function makeLine(sx, sy, ex, ey) {
+ maxY = Math.max(maxY, sy, ey);
+ var l = document.createElementNS(svg, "line");
+ l.setAttribute("x1", sx);
+ l.setAttribute("y1", sy);
+ l.setAttribute("x2", ex);
+ l.setAttribute("y2", ey);
+ return l;
+ }
+
+ function makeArrow(start, end) {
+ var g = document.createElementNS(svg, "g");
+ g.appendChild(makeLine(start.x, start.y, end.x, end.y));
+ if (start.x != end.x) {
+ start.x = end.x + (4 * Math.sign(start.x - end.x));
+ g.appendChild(makeLine(start.x, start.y - 4, end.x, end.y));
+ g.appendChild(makeLine(start.x, start.y + 4, end.x, end.y));
+ } else if (start.y != end.y) {
+ start.y = end.y + (4 * Math.sign(start.y - end.y));
+ g.appendChild(makeLine(start.x - 4, start.y, end.x, end.y));
+ g.appendChild(makeLine(start.x + 4, start.y, end.x, end.y));
+ }
+ return g;
+ }
+
+ function makeVHArrow(start, end) {
+ var g = document.createElementNS(svg, "g");
+ g.appendChild(makeLine(start.x, start.y, start.x, end.y));
+ start.y = end.y;
+ g.appendChild(makeArrow(start, end));
+ return g;
+ }
+
+ function makeHVArrow(start, end) {
+ var g = document.createElementNS(svg, "g");
+ g.appendChild(makeLine(start.x, start.y, end.x, start.y));
+ start.x = end.x;
+ g.appendChild(makeArrow(start, end));
+ return g;
+ }
+
+ function makeVHVArrow(start, end, length) {
+ var g = document.createElementNS(svg, "g");
+ g.appendChild(makeLine(start.x, start.y, start.x, start.y + length));
+ start.y += length;
+ g.appendChild(makeLine(start.x, start.y, end.x, start.y));
+ start.x = end.x;
+ g.appendChild(makeArrow(start, end));
+ return g;
+ }
+
+ function makeHVHArrow(start, end, length) {
+ var g = document.createElementNS(svg, "g");
+ g.appendChild(makeLine(start.x, start.y, start.x + length, start.y));
+ start.x += length;
+ g.appendChild(makeLine(start.x, start.y, start.x, end.y));
+ start.y = end.y;
+ g.appendChild(makeArrow(start, end));
+ return g;
+ }
+
+ function translation(group) {
+ var r = new RegExp("translate\\((\\d+), (\\d+)\\)");
+ var result = r.exec(group.getAttribute("transform"));
+ return { x: parseInt(result[1]), y: parseInt(result[2]) };
+ }
+
+ function isAction(group) {
+ return group.classList.contains("action");
+ }
+
+ function isChoice(group) {
+ return group.classList.contains("choice");
+ }
+
+ function offset(point, x, y) {
+ point.x += x;
+ point.y += y;
+ return point;
+ }
+
+ function rightOf(group) {
+ var t = translation(group);
+ if (isAction(group)) {
+ return offset(t, 100, 20);
+ }
+ if (isChoice(group)) {
+ return offset(t, 85, 35);
+ }
+ return t;
+ }
+
+ function leftOf(group) {
+ var t = translation(group);
+ if (isAction(group)) {
+ return offset(t, 0, 20);
+ }
+ if (isChoice(group)) {
+ return offset(t, -15, 35);
+ }
+ return t;
+ }
+
+ function topOf(group) {
+ var t = translation(group);
+ if (isAction(group)) {
+ return offset(t, 50, 0);
+ }
+ if (isChoice(group)) {
+ return offset(t, 35, -15);
+ }
+ return t;
+ }
+
+ function bottomOf(group) {
+ var t = translation(group);
+ if (isAction(group)) {
+ return offset(t, 50, 40);
+ }
+ if (isChoice(group)) {
+ return offset(t, 35, 85);
+ }
+ return t;
+ }
+
+ function midpoint(start, end) {
+ return { x: (start.x + end.x) / 2,
+ y: (start.y + end.y) / 2 };
+ }
+
+ function makeLegend(label, thread) {
+ var t = document.createElementNS(svg, "text");
+ t.setAttribute("x", "10");
+ t.setAttribute("y", maxY);
+ t.setAttribute("class", thread);
+ maxY += 15;
+ t.appendChild(document.createTextNode(label));
+ return t;
+ }
+
+ var android = makeAction("Android/Gonk", 20, 0, "parentinput");
+ var sendNative = makeAction("DOMWindowUtils\nsendNativeTouchPoint", 20, 100, "parentmain");
+ var apzHitTest = makeAction("APZ hit test", 150, 0, "parentcompositor");
+ var apzUntransform = makeAction("APZ\nuntransform", 300, 0, "parentcompositor");
+ var apzGesture = makeAction("APZ gesture\ndetection", 450, 0, "parentcompositor");
+ var apzTransform = makeAction("APZ transform\nupdate", 600, 0, "parentcompositor");
+ var compositor = makeAction("Compositor", 750, 0, "parentcompositor");
+ var nsAppShell = makeAction("nsAppShell", 150, 100, "parentmain");
+ var rootHitTest = makeAction("Gecko hit test\n(root process)", 300, 100, "parentmain");
+ var rootEsm = makeAction("Gecko ESM\n(root process)", 450, 100, "parentmain");
+ var isEdgeGesture = makeChoice("Edge gesture?", 300, 200, "parentmain");
+ var edgeConsume = makeAction("Consume\nevent block", 150, 200, "parentmain");
+ var bepjsm = makeAction("BEParent.jsm\nsendTouchEvent", 450, 200, "parentmain");
+ var iframeSend = makeAction("HTMLIFrameElement\nsendTouchEvent", 20, 275, "parentmain");
+ var isApzTarget = makeChoice("Target\nhas APZ?", 600, 200, "parentmain");
+ var sendTouchEvent = makeAction("Target\nsendTouchEventToWindow", 750, 100, "parentmain");
+ var injectTouch = makeAction("injectTouchEvent", 750, 200, "parentmain");
+ var targetESM = makeAction("Target window\nESM", 750, 450, "bothmain");
+ var tabParent = makeAction("TabParent", 750, 350, "parentmain");
+ var geckoUntransform = makeAction("Gecko\nuntransform", 600, 350, "parentmain");
+ var tabChild = makeAction("TabChild", 450, 350, "childmain");
+ var isApzcEnabled = makeChoice("APZ\nenabled?", 300, 350, "childmain");
+ var tabGesture = makeAction("TabChild gesture\ndetection", 150, 350, "childmain");
+ var childHitTest = makeAction("Gecko hit test\n(child process)", 300, 450, "childmain");
+ var childEsm = makeAction("Gecko ESM\n(child process)", 450, 450, "childmain");
+ var childContent = makeAction("Content\n(child process)", 600, 450, "childmain");
+
+ document.documentElement.appendChild(android);
+ document.documentElement.appendChild(sendNative);
+ document.documentElement.appendChild(apzHitTest);
+ document.documentElement.appendChild(apzUntransform);
+ document.documentElement.appendChild(apzGesture);
+ document.documentElement.appendChild(apzTransform);
+ document.documentElement.appendChild(compositor);
+ document.documentElement.appendChild(nsAppShell);
+ document.documentElement.appendChild(rootHitTest);
+ document.documentElement.appendChild(rootEsm);
+ document.documentElement.appendChild(isEdgeGesture);
+ document.documentElement.appendChild(edgeConsume);
+ document.documentElement.appendChild(bepjsm);
+ document.documentElement.appendChild(iframeSend);
+ document.documentElement.appendChild(isApzTarget);
+ document.documentElement.appendChild(sendTouchEvent);
+ document.documentElement.appendChild(injectTouch);
+ document.documentElement.appendChild(targetESM);
+ document.documentElement.appendChild(tabParent);
+ document.documentElement.appendChild(geckoUntransform);
+ document.documentElement.appendChild(tabChild);
+ document.documentElement.appendChild(isApzcEnabled);
+ document.documentElement.appendChild(tabGesture);
+ document.documentElement.appendChild(childHitTest);
+ document.documentElement.appendChild(childEsm);
+ document.documentElement.appendChild(childContent);
+
+ document.documentElement.appendChild(makeLabelChoice("Y", offset(leftOf(isEdgeGesture), -5, -5)));
+ document.documentElement.appendChild(makeLabelChoice("N", offset(rightOf(isEdgeGesture), 5, -5)));
+ document.documentElement.appendChild(makeLabelChoice("N", offset(topOf(isApzTarget), 8, -10)));
+ document.documentElement.appendChild(makeLabelChoice("Y", offset(rightOf(isApzTarget), 10, 14)));
+ document.documentElement.appendChild(makeLabelChoice("N", offset(leftOf(isApzcEnabled), -5, -5)));
+ document.documentElement.appendChild(makeLabelChoice("Y", offset(bottomOf(isApzcEnabled), 10, 14)));
+
+ var arrows = document.getElementById('arrows');
+ arrows.appendChild(makeArrow(rightOf(android), leftOf(apzHitTest)));
+ arrows.appendChild(makeVHVArrow(topOf(sendNative), midpoint(rightOf(android), leftOf(apzHitTest)), -20));
+ arrows.appendChild(makeArrow(rightOf(apzHitTest), leftOf(apzUntransform)));
+ arrows.appendChild(makeArrow(rightOf(apzUntransform), leftOf(apzGesture)));
+ arrows.appendChild(makeArrow(rightOf(apzGesture), leftOf(apzTransform)));
+ arrows.appendChild(makeArrow(rightOf(apzTransform), leftOf(compositor)));
+ arrows.appendChild(makeVHVArrow(midpoint(leftOf(apzUntransform), rightOf(apzGesture)), topOf(nsAppShell), 40));
+ arrows.appendChild(makeArrow(rightOf(nsAppShell), leftOf(rootHitTest)));
+ arrows.appendChild(makeArrow(rightOf(rootHitTest), leftOf(rootEsm)));
+ arrows.appendChild(makeVHVArrow(bottomOf(rootEsm), topOf(isEdgeGesture), 15));
+ arrows.appendChild(makeArrow(leftOf(isEdgeGesture), rightOf(edgeConsume)));
+ arrows.appendChild(makeArrow(rightOf(isEdgeGesture), leftOf(bepjsm), 20));
+ arrows.appendChild(makeHVArrow(rightOf(iframeSend), bottomOf(bepjsm)));
+ arrows.appendChild(makeArrow(rightOf(bepjsm), leftOf(isApzTarget)));
+ arrows.appendChild(makeArrow(rightOf(isApzTarget), leftOf(injectTouch)));
+ arrows.appendChild(makeArrow(bottomOf(injectTouch), topOf(tabParent)));
+ arrows.appendChild(makeVHArrow(topOf(isApzTarget), leftOf(sendTouchEvent)));
+ arrows.appendChild(makeHVHArrow(rightOf(sendTouchEvent), rightOf(targetESM), 30));
+ arrows.appendChild(makeArrow(leftOf(tabParent), rightOf(geckoUntransform)));
+ arrows.appendChild(makeArrow(leftOf(geckoUntransform), rightOf(tabChild)));
+ arrows.appendChild(makeArrow(leftOf(tabChild), rightOf(isApzcEnabled)));
+ arrows.appendChild(makeArrow(leftOf(isApzcEnabled), rightOf(tabGesture)));
+ arrows.appendChild(makeArrow(bottomOf(isApzcEnabled), topOf(childHitTest)));
+ arrows.appendChild(makeVHArrow(bottomOf(tabGesture), leftOf(childHitTest)));
+ arrows.appendChild(makeArrow(rightOf(childHitTest), leftOf(childEsm)));
+ arrows.appendChild(makeArrow(rightOf(childEsm), leftOf(childContent)));
+ arrows.appendChild(makeVHVArrow(midpoint(leftOf(apzGesture), rightOf(apzTransform)), topOf(tabChild), 300));
+
+ document.documentElement.appendChild(makeLegend("Main process input thread", "parentinput"));
+ document.documentElement.appendChild(makeLegend("Main process main thread", "parentmain"));
+ document.documentElement.appendChild(makeLegend("Main process compositor thread", "parentcompositor"));
+ document.documentElement.appendChild(makeLegend("Child process main thread", "childmain"));
+ document.documentElement.appendChild(makeLegend("Undetermined process main thread", "bothmain"));
+ ]]></script>
+</svg>