summaryrefslogtreecommitdiff
path: root/gdk/broadway/broadway.js
diff options
context:
space:
mode:
authorAlexander Larsson <alexl@redhat.com>2017-11-30 10:36:30 +0100
committerAlexander Larsson <alexl@redhat.com>2017-11-30 21:57:42 +0100
commit521b09cc964346e1eb5c3c9241cc68bef42f860c (patch)
tree2a9e1654c50bc73e9e898728f14757238958beb8 /gdk/broadway/broadway.js
parent3d4a9324e62b5ae106c335b20261f471ae8fba6b (diff)
downloadgtk+-521b09cc964346e1eb5c3c9241cc68bef42f860c.tar.gz
broadway: Send diffs of node trees
Reusing pre-created nodes is a lot faster both in terms of dom modifications and of transfer sizes.
Diffstat (limited to 'gdk/broadway/broadway.js')
-rw-r--r--gdk/broadway/broadway.js204
1 files changed, 121 insertions, 83 deletions
diff --git a/gdk/broadway/broadway.js b/gdk/broadway/broadway.js
index 0f85c7aaf4..5474960bc7 100644
--- a/gdk/broadway/broadway.js
+++ b/gdk/broadway/broadway.js
@@ -301,31 +301,9 @@ function SwapNodes(node_data, div) {
this.node_data_signed = new Int32Array(node_data);
this.data_pos = 0;
this.div = div;
- this.div2 = document.createElement('div');
this.outstanding = 1;
}
-SwapNodes.prototype.did_one = function(image) {
- this.outstanding--;
- if (this.outstanding == 0) {
- var oldDiv2 = null;
- if (this.div.hasChildNodes())
- oldDiv2 = this.div.lastChild;
-
- this.div.appendChild(this.div2);
- if (oldDiv2)
- this.div.removeChild(oldDiv2);
- }
-}
-
-SwapNodes.prototype.add_image = function(image) {
- this.outstanding++;
- var v = this;
- image.addEventListener('load', function() {
- v.did_one ();
- }, false);
-};
-
SwapNodes.prototype.decode_uint32 = function() {
return this.node_data[this.data_pos++];
}
@@ -421,26 +399,37 @@ function px(x) {
return x + "px";
}
-function set_rect_style (div, rect, offset_x, offset_y) {
- div.style["left"] = px(rect.x - offset_x);
- div.style["top"] = px(rect.y - offset_y);
+function set_rect_style (div, rect) {
+ div.style["left"] = px(rect.x);
+ div.style["top"] = px(rect.y);
div.style["width"] = px(rect.width);
div.style["height"] = px(rect.height);
}
-function set_rrect_style (div, rrect, offset_x, offset_y) {
- set_rect_style(div, rrect.bounds, offset_x, offset_y);
+function set_rrect_style (div, rrect) {
+ set_rect_style(div, rrect.bounds);
div.style["border-top-left-radius"] = args(px(rrect.sizes[0].width), px(rrect.sizes[0].height));
div.style["border-top-right-radius"] = args(px(rrect.sizes[1].width), px(rrect.sizes[1].height));
div.style["border-bottom-right-radius"] = args(px(rrect.sizes[2].width), px(rrect.sizes[2].height));
div.style["border-bottom-left-radius"] = args(px(rrect.sizes[3].width), px(rrect.sizes[3].height));
}
-SwapNodes.prototype.handle_node = function(parent, offset_x, offset_y)
+SwapNodes.prototype.insertNode = function(parent, posInParent, oldNode)
{
var type = this.decode_uint32();
+ var newNode = null;
+
+ // We need to dup this because as we reuse children the original order is lost
+ var oldChildren = [];
+ if (oldNode) {
+ for (var i = 0; i < oldNode.children.length; i++)
+ oldChildren[i] = oldNode.children[i];
+ }
+
switch (type)
{
+ /* Leaf nodes */
+
case 0: // TEXTURE
{
var rect = this.decode_rect();
@@ -449,22 +438,10 @@ SwapNodes.prototype.handle_node = function(parent, offset_x, offset_y)
image.width = rect.width;
image.height = rect.height;
image.style["position"] = "absolute";
- set_rect_style(image, rect, offset_x, offset_y);
+ set_rect_style(image, rect);
var texture_url = textures[texture_id];
- this.add_image(image);
image.src = texture_url;
- parent.appendChild(image);
- }
- break;
-
- case 1: // CONTAINER
- {
- var div = document.createElement('div');
- var len = this.decode_uint32();
- for (var i = 0; i < len; i++) {
- this.handle_node(div, offset_x, offset_y);
- }
- parent.appendChild(div);
+ newNode = image;
}
break;
@@ -474,9 +451,9 @@ SwapNodes.prototype.handle_node = function(parent, offset_x, offset_y)
var c = this.decode_color ();
var div = document.createElement('div');
div.style["position"] = "absolute";
- set_rect_style(div, rect, offset_x, offset_y);
+ set_rect_style(div, rect);
div.style["background-color"] = c;
- parent.appendChild(div);
+ newNode = div;
}
break;
@@ -494,7 +471,7 @@ SwapNodes.prototype.handle_node = function(parent, offset_x, offset_y)
div.style["position"] = "absolute";
rrect.bounds.width -= border_widths[1] + border_widths[3];
rrect.bounds.height -= border_widths[0] + border_widths[2];
- set_rrect_style(div, rrect, offset_x, offset_y);
+ set_rrect_style(div, rrect);
div.style["border-style"] = "solid";
div.style["border-top-color"] = border_colors[0];
div.style["border-top-width"] = px(border_widths[0]);
@@ -504,7 +481,7 @@ SwapNodes.prototype.handle_node = function(parent, offset_x, offset_y)
div.style["border-bottom-width"] = px(border_widths[2]);
div.style["border-left-color"] = border_colors[3];
div.style["border-left-width"] = px(border_widths[3]);
- parent.appendChild(div);
+ newNode = div;
}
break;
@@ -519,9 +496,9 @@ SwapNodes.prototype.handle_node = function(parent, offset_x, offset_y)
var div = document.createElement('div');
div.style["position"] = "absolute";
- set_rrect_style(div, rrect, offset_x, offset_y);
+ set_rrect_style(div, rrect);
div.style["box-shadow"] = args(px(dx), px(dy), px(blur), px(spread), color);
- parent.appendChild(div);
+ newNode = div;
}
break;
@@ -536,23 +513,12 @@ SwapNodes.prototype.handle_node = function(parent, offset_x, offset_y)
var div = document.createElement('div');
div.style["position"] = "absolute";
- set_rrect_style(div, rrect, offset_x, offset_y);
+ set_rrect_style(div, rrect);
div.style["box-shadow"] = args("inset", px(dx), px(dy), px(blur), px(spread), color);
- parent.appendChild(div);
+ newNode = div;
}
break;
- case 6: // ROUNDED_CLIP
- {
- var rrect = this.decode_rounded_rect();
- var div = document.createElement('div');
- div.style["position"] = "absolute";
- set_rrect_style(div, rrect, offset_x, offset_y);
- div.style["overflow"] = "hidden";
- parent.appendChild(div);
- this.handle_node(div, rrect.bounds.x, rrect.bounds.y);
- }
- break;
case 7: // LINEAR_GRADIENT
{
@@ -562,7 +528,7 @@ SwapNodes.prototype.handle_node = function(parent, offset_x, offset_y)
var stops = this.decode_color_stops ();
var div = document.createElement('div');
div.style["position"] = "absolute";
- set_rect_style(div, rect, offset_x, offset_y);
+ set_rect_style(div, rect);
// direction:
var dx = end.x - start.x;
@@ -595,7 +561,48 @@ SwapNodes.prototype.handle_node = function(parent, offset_x, offset_y)
gradient = gradient + ")";
div.style["background-image"] = gradient;
- parent.appendChild(div);
+ newNode = div;
+ }
+ break;
+
+
+ /* Bin nodes */
+
+ case 10: // CLIP
+ {
+ var rect = this.decode_rect();
+ var div = document.createElement('div');
+ div.style["position"] = "absolute";
+ set_rect_style(div, rect);
+ div.style["overflow"] = "hidden";
+ this.insertNode(div, -1, oldChildren[0]);
+ newNode = div;
+ }
+ break;
+
+ case 6: // ROUNDED_CLIP
+ {
+ var rrect = this.decode_rounded_rect();
+ var div = document.createElement('div');
+ div.style["position"] = "absolute";
+ set_rrect_style(div, rrect);
+ div.style["overflow"] = "hidden";
+ this.insertNode(div, -1, oldChildren[0]);
+ newNode = div;
+ }
+ break;
+
+ case 9: // OPACITY
+ {
+ var opacity = this.decode_float();
+ var div = document.createElement('div');
+ div.style["position"] = "absolute";
+ div.style["left"] = px(0);
+ div.style["top"] = px(0);
+ div.style["opacity"] = opacity;
+
+ this.insertNode(div, -1, oldChildren[0]);
+ newNode = div;
}
break;
@@ -616,40 +623,72 @@ SwapNodes.prototype.handle_node = function(parent, offset_x, offset_y)
div.style["top"] = px(0);
div.style["filter"] = filters;
- parent.appendChild(div);
- this.handle_node(div, offset_x, offset_y);
+ this.insertNode(div, -1, oldChildren[0]);
+ newNode = div;
}
break;
- case 9: // OPACITY
+ /* Generic nodes */
+
+ case 1: // CONTAINER
{
- var opacity = this.decode_float();
var div = document.createElement('div');
- div.style["position"] = "absolute";
- div.style["left"] = px(0);
- div.style["top"] = px(0);
- div.style["opacity"] = opacity;
+ var len = this.decode_uint32();
+ for (var i = 0; i < len; i++) {
+ this.insertNode(div, -1, oldChildren[i]);
+ }
+ newNode = div;
+ }
+ break;
+
+ case 11: // KEEP_ALL
+ {
+ if (!oldNode)
+ alert("KEEP_ALL with no oldNode");
- parent.appendChild(div);
- this.handle_node(div, offset_x, offset_y);
+ if (oldNode.parentNode != parent)
+ newNode = oldNode;
+ else
+ newNode = null;
}
break;
- case 10: // CLIP
+ case 12: // KEEP_THIS
{
- var rect = this.decode_rect();
- var div = document.createElement('div');
- div.style["position"] = "absolute";
- set_rect_style(div, rect, offset_x, offset_y);
- div.style["overflow"] = "hidden";
- parent.appendChild(div);
- this.handle_node(div, rect.x, rect.y);
+ if (!oldNode)
+ alert("KEEP_THIS with no oldNode ");
+
+ /* We only get keep-this if all parents were kept, check this */
+ if (oldNode.parentNode != parent)
+ alert("Got KEEP_THIS for non-kept parent");
+
+ var len = this.decode_uint32();
+ var i;
+
+ for (i = 0; i < len; i++) {
+ this.insertNode(oldNode, i,
+ oldChildren[i]);
+ }
+
+ /* Remove children that are after the new length */
+ for (i = oldChildren.length - 1; i > len - 1; i--)
+ oldNode.removeChild(oldChildren[i]);
+
+ /* NOTE: No need to modify the parent, we're keeping this node as is */
+ newNode = null;
}
break;
default:
alert("Unexpected node type " + type);
}
+
+ if (newNode) {
+ if (posInParent >= 0 && parent.children[posInParent])
+ parent.replaceChild(newNode, parent.children[posInParent]);
+ else
+ parent.appendChild(newNode);
+ }
}
function cmdWindowSetNodes(id, node_data)
@@ -662,10 +701,9 @@ function cmdWindowSetNodes(id, node_data)
/* We use a secondary div so that we can remove all previous children in one go */
var swap = new SwapNodes (node_data, div);
- swap.handle_node(swap.div2, 0, 0);
+ swap.insertNode(div, 0, div.firstChild);
if (swap.data_pos != node_data.length)
alert ("Did not consume entire array (len " + node_data.length + " end " + end + ")");
- swap.did_one ();
}
function cmdUploadTexture(id, data)