forked from AuroraMiddleware/gtk
broadway: Reintroduce smarter diffing
We now send very minimal diff operations.
This commit is contained in:
parent
4dfe2e6e2f
commit
f30ba56323
@ -8,6 +8,7 @@
|
||||
#include "broadway-output.h"
|
||||
|
||||
//#define DEBUG_NODE_SENDING
|
||||
//#define DEBUG_NODE_SENDING_REMOVE
|
||||
|
||||
/************************************************************************
|
||||
* Basic I/O primitives *
|
||||
@ -317,9 +318,9 @@ static void
|
||||
append_type (BroadwayOutput *output, guint32 type, BroadwayNode *node)
|
||||
{
|
||||
#ifdef DEBUG_NODE_SENDING
|
||||
g_print ("%*s%s", append_node_depth*2, "", broadway_node_type_names[type]);
|
||||
g_print ("%*s%s(%d/%d)", append_node_depth*2, "", broadway_node_type_names[type], node->id, node->output_id);
|
||||
if (type == BROADWAY_NODE_TEXTURE)
|
||||
g_print (" %u", node->data[4]);
|
||||
g_print (" tx=%u", node->data[4]);
|
||||
g_print ("\n");
|
||||
#endif
|
||||
|
||||
@ -367,13 +368,14 @@ append_node (BroadwayOutput *output,
|
||||
reused_node = lookup_old_node (old_node_lookup, node->id);
|
||||
if (reused_node)
|
||||
{
|
||||
broadway_node_mark_deep_consumed (reused_node, TRUE);
|
||||
append_type (output, BROADWAY_NODE_REUSE, node);
|
||||
append_uint32 (output, node->id);
|
||||
append_uint32 (output, node->output_id);
|
||||
}
|
||||
else
|
||||
{
|
||||
append_type (output, node->type, node);
|
||||
append_uint32 (output, node->id);
|
||||
append_uint32 (output, node->output_id);
|
||||
for (i = 0; i < node->n_data; i++)
|
||||
append_uint32 (output, node->data[i]);
|
||||
for (i = 0; i < node->n_children; i++)
|
||||
@ -386,36 +388,130 @@ append_node (BroadwayOutput *output,
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
static BroadwayNode *
|
||||
append_node_ops (BroadwayOutput *output,
|
||||
BroadwayNode *node,
|
||||
BroadwayNode *parent,
|
||||
BroadwayNode *previous_sibling,
|
||||
BroadwayNode *old_node,
|
||||
GHashTable *old_node_lookup)
|
||||
{
|
||||
GPtrArray *to_remove = g_ptr_array_new ();
|
||||
BroadwayNode *reused_node;
|
||||
guint32 i;
|
||||
|
||||
if (old_node != NULL)
|
||||
g_ptr_array_add (to_remove, old_node);
|
||||
/* Maybe can be reused from the last tree. */
|
||||
reused_node = lookup_old_node (old_node_lookup, node->id);
|
||||
if (reused_node)
|
||||
{
|
||||
g_assert (node == reused_node);
|
||||
g_assert (reused_node->reused);
|
||||
g_assert (!reused_node->consumed); /* Should only be once in the tree, and not consumed otherwise */
|
||||
|
||||
append_uint32 (output, BROADWAY_NODE_OP_APPEND_NODE);
|
||||
append_uint32 (output, 0); /* Parent */
|
||||
broadway_node_mark_deep_consumed (reused_node, TRUE);
|
||||
|
||||
if (node == old_node)
|
||||
{
|
||||
/* The node in the old tree at the current position is the same, so
|
||||
we need to do nothing, just don't delete it (which we won't since
|
||||
its marked used) */
|
||||
}
|
||||
else
|
||||
{
|
||||
/* We can reuse it, bu it comes from a different place or
|
||||
order, if so we need to move it in place */
|
||||
#ifdef DEBUG_NODE_SENDING
|
||||
g_print ("Move old node %d/%d to parent %d/%d after %d/%d\n",
|
||||
reused_node->id, reused_node->output_id,
|
||||
parent ? parent->id : 0,
|
||||
parent ? parent->output_id : 0,
|
||||
previous_sibling ? previous_sibling->id : 0,
|
||||
previous_sibling ? previous_sibling->output_id : 0);
|
||||
#endif
|
||||
append_uint32 (output, BROADWAY_NODE_OP_MOVE_AFTER_CHILD);
|
||||
append_uint32 (output, parent ? parent->output_id : 0);
|
||||
append_uint32 (output, previous_sibling ? previous_sibling->output_id : 0);
|
||||
append_uint32 (output, reused_node->output_id);
|
||||
}
|
||||
|
||||
return reused_node;
|
||||
}
|
||||
|
||||
/* If the next node in place is shallowly equal (but not necessarily
|
||||
* deep equal) we reuse it and tweak its children as needed.
|
||||
* Except we avoid this for reused node as those make more sense to reuse deeply.
|
||||
*/
|
||||
|
||||
if (old_node && broadway_node_equal (node, old_node) && !old_node->reused)
|
||||
{
|
||||
int old_i = 0;
|
||||
BroadwayNode *last_child = NULL;
|
||||
|
||||
old_node->consumed = TRUE; // Don't reuse again
|
||||
|
||||
// We rewrite this new node as it now represents the old node in the browser
|
||||
node->output_id = old_node->output_id;
|
||||
|
||||
/* However, we might need to rewrite then children of old_node */
|
||||
for (i = 0; i < node->n_children; i++)
|
||||
{
|
||||
BroadwayNode *child = node->children[i];
|
||||
|
||||
/* Find the next (or first) non-consumed old child, if any */
|
||||
while (old_i < old_node->n_children &&
|
||||
old_node->children[old_i]->consumed)
|
||||
old_i++;
|
||||
|
||||
last_child =
|
||||
append_node_ops (output,
|
||||
child,
|
||||
node, /* parent */
|
||||
last_child,
|
||||
(old_i < old_node->n_children) ? old_node->children[old_i] : NULL,
|
||||
old_node_lookup);
|
||||
}
|
||||
|
||||
/* Remaining old nodes are either reused elsewhere, or end up marked not consumed so are deleted at the end */
|
||||
return old_node;
|
||||
}
|
||||
|
||||
/* Fallback to create a new tree */
|
||||
#ifdef DEBUG_NODE_SENDING
|
||||
g_print ("Insert nodes in parent %d/%d, after sibling %d/%d\n",
|
||||
parent ? parent->id : 0,
|
||||
parent ? parent->output_id : 0,
|
||||
previous_sibling ? previous_sibling->id : 0,
|
||||
previous_sibling ? previous_sibling->output_id : 0);
|
||||
#endif
|
||||
append_uint32 (output, BROADWAY_NODE_OP_INSERT_NODE);
|
||||
append_uint32 (output, parent ? parent->output_id : 0);
|
||||
append_uint32 (output, previous_sibling ? previous_sibling->output_id : 0);
|
||||
|
||||
append_node(output, node, old_node_lookup);
|
||||
|
||||
for (i = 0; i < to_remove->len; i++)
|
||||
{
|
||||
BroadwayNode *removed_node = g_ptr_array_index (to_remove, i);
|
||||
if (!removed_node->used)
|
||||
{
|
||||
// TODO: Use an array of nodes instead
|
||||
append_uint32 (output, BROADWAY_NODE_OP_REMOVE_NODE);
|
||||
append_uint32 (output, old_node->id);
|
||||
}
|
||||
}
|
||||
g_ptr_array_unref (to_remove);
|
||||
return node;
|
||||
}
|
||||
|
||||
/* Remove non-consumed nodes */
|
||||
static void
|
||||
append_node_removes (BroadwayOutput *output,
|
||||
BroadwayNode *node)
|
||||
{
|
||||
// TODO: Use an array of nodes instead
|
||||
if (!node->consumed)
|
||||
{
|
||||
#ifdef DEBUG_NODE_SENDING_REMOVE
|
||||
g_print ("Remove old node non-consumed node %d/%d\n",
|
||||
node->id, node->output_id);
|
||||
#endif
|
||||
append_uint32 (output, BROADWAY_NODE_OP_REMOVE_NODE);
|
||||
append_uint32 (output, node->output_id);
|
||||
}
|
||||
|
||||
for (int i = 0; i < node->n_children; i++)
|
||||
append_node_removes (output, node->children[i]);
|
||||
}
|
||||
|
||||
|
||||
|
||||
void
|
||||
broadway_output_surface_set_nodes (BroadwayOutput *output,
|
||||
@ -426,14 +522,14 @@ broadway_output_surface_set_nodes (BroadwayOutput *output,
|
||||
{
|
||||
gsize size_pos, start, end;
|
||||
|
||||
/* Mark old nodes as unused, so we can use them once */
|
||||
|
||||
if (old_root)
|
||||
broadway_node_mark_deep_used (old_root, FALSE);
|
||||
/* Mark new nodes as used, causing any shared nodes to be marked as
|
||||
unused. This way we won't accidentally reuse them for something
|
||||
else. However, this means that is safe to reuse nodes marked as
|
||||
used for the specific case of where the id matches. */
|
||||
broadway_node_mark_deep_used (root, TRUE);
|
||||
{
|
||||
broadway_node_mark_deep_consumed (old_root, FALSE);
|
||||
broadway_node_mark_deep_reused (old_root, FALSE);
|
||||
/* This will modify children of old_root if any are shared */
|
||||
broadway_node_mark_deep_reused (root, TRUE);
|
||||
}
|
||||
|
||||
write_header (output, BROADWAY_OP_SET_NODES);
|
||||
|
||||
@ -444,9 +540,11 @@ broadway_output_surface_set_nodes (BroadwayOutput *output,
|
||||
|
||||
start = output->buf->len;
|
||||
#ifdef DEBUG_NODE_SENDING
|
||||
g_print ("====== node tree for %d =======\n", id);
|
||||
g_print ("====== node ops for surface %d =======\n", id);
|
||||
#endif
|
||||
append_node_ops (output, root, old_root, old_node_lookup);
|
||||
append_node_ops (output, root, NULL, NULL, old_root, old_node_lookup);
|
||||
if (old_root)
|
||||
append_node_removes (output, old_root);
|
||||
end = output->buf->len;
|
||||
patch_uint32 (output, (end - start) / 4, size_pos);
|
||||
}
|
||||
|
@ -26,8 +26,9 @@ typedef enum { /* Sync changes with broadway.js */
|
||||
} BroadwayNodeType;
|
||||
|
||||
typedef enum { /* Sync changes with broadway.js */
|
||||
BROADWAY_NODE_OP_APPEND_NODE = 0,
|
||||
BROADWAY_NODE_OP_INSERT_NODE = 0,
|
||||
BROADWAY_NODE_OP_REMOVE_NODE = 1,
|
||||
BROADWAY_NODE_OP_MOVE_AFTER_CHILD = 2,
|
||||
} BroadwayNodeOpType;
|
||||
|
||||
static const char *broadway_node_type_names[] G_GNUC_UNUSED = {
|
||||
|
@ -183,10 +183,6 @@ broadway_node_equal (BroadwayNode *a,
|
||||
{
|
||||
int i;
|
||||
|
||||
// Early fast return for reused nodes
|
||||
if (a == b)
|
||||
return TRUE;
|
||||
|
||||
if (a->type != b->type)
|
||||
return FALSE;
|
||||
|
||||
@ -211,10 +207,6 @@ broadway_node_deep_equal (BroadwayNode *a,
|
||||
{
|
||||
int i;
|
||||
|
||||
// Early fast return for reused nodes
|
||||
if (a == b)
|
||||
return TRUE;
|
||||
|
||||
if (a->hash != b->hash)
|
||||
return FALSE;
|
||||
|
||||
@ -233,12 +225,21 @@ broadway_node_deep_equal (BroadwayNode *a,
|
||||
|
||||
|
||||
void
|
||||
broadway_node_mark_deep_used (BroadwayNode *node,
|
||||
gboolean used)
|
||||
broadway_node_mark_deep_reused (BroadwayNode *node,
|
||||
gboolean reused)
|
||||
{
|
||||
node->used = used;
|
||||
node->reused = reused;
|
||||
for (int i = 0; i < node->n_children; i++)
|
||||
broadway_node_mark_deep_used (node->children[i], used);
|
||||
broadway_node_mark_deep_reused (node->children[i], reused);
|
||||
}
|
||||
|
||||
void
|
||||
broadway_node_mark_deep_consumed (BroadwayNode *node,
|
||||
gboolean consumed)
|
||||
{
|
||||
node->consumed = consumed;
|
||||
for (int i = 0; i < node->n_children; i++)
|
||||
broadway_node_mark_deep_consumed (node->children[i], consumed);
|
||||
}
|
||||
|
||||
void
|
||||
@ -1779,6 +1780,7 @@ decode_nodes (BroadwayServer *server,
|
||||
g_ref_count_init (&node->refcount);
|
||||
node->type = type;
|
||||
node->id = id;
|
||||
node->output_id = id;
|
||||
node->texture_id = 0;
|
||||
node->n_children = n_children;
|
||||
node->children = (BroadwayNode **)((char *)node + sizeof(BroadwayNode) + (size - 1) * sizeof(guint32));
|
||||
|
@ -25,13 +25,15 @@ struct _BroadwayNode {
|
||||
grefcount refcount;
|
||||
guint32 type;
|
||||
guint32 id;
|
||||
guint32 output_id;
|
||||
guint32 hash; /* deep hash */
|
||||
guint32 n_children;
|
||||
BroadwayNode **children;
|
||||
guint32 texture_id;
|
||||
|
||||
/* Scratch stuff used during diff */
|
||||
gboolean used;
|
||||
gboolean reused;
|
||||
gboolean consumed;
|
||||
|
||||
guint32 n_data;
|
||||
guint32 data[1];
|
||||
@ -41,8 +43,10 @@ gboolean broadway_node_equal (BroadwayNode *
|
||||
BroadwayNode *b);
|
||||
gboolean broadway_node_deep_equal (BroadwayNode *a,
|
||||
BroadwayNode *b);
|
||||
void broadway_node_mark_deep_used (BroadwayNode *node,
|
||||
gboolean used);
|
||||
void broadway_node_mark_deep_reused (BroadwayNode *node,
|
||||
gboolean reused);
|
||||
void broadway_node_mark_deep_consumed (BroadwayNode *node,
|
||||
gboolean consumed);
|
||||
void broadway_node_add_to_lookup (BroadwayNode *node,
|
||||
GHashTable *node_lookup);
|
||||
BroadwayServer *broadway_server_new (char *address,
|
||||
|
@ -15,8 +15,9 @@ const BROADWAY_NODE_TRANSFORM = 11;
|
||||
const BROADWAY_NODE_DEBUG = 12;
|
||||
const BROADWAY_NODE_REUSE = 13;
|
||||
|
||||
const BROADWAY_NODE_OP_APPEND_NODE = 0;
|
||||
const BROADWAY_NODE_OP_INSERT_NODE = 0;
|
||||
const BROADWAY_NODE_OP_REMOVE_NODE = 1;
|
||||
const BROADWAY_NODE_OP_MOVE_AFTER_CHILD = 2;
|
||||
|
||||
const BROADWAY_OP_GRAB_POINTER = 'g';
|
||||
const BROADWAY_OP_UNGRAB_POINTER = 'u';
|
||||
@ -236,7 +237,7 @@ function cmdCreateSurface(id, x, y, width, height, isTemp)
|
||||
surface.transientParent = 0;
|
||||
surface.visible = false;
|
||||
surface.imageData = null;
|
||||
surface.old_nodes = {};
|
||||
surface.nodes = {};
|
||||
|
||||
var div = document.createElement('div');
|
||||
div.surface = surface;
|
||||
@ -299,14 +300,13 @@ function cmdLowerSurface(id)
|
||||
moveToHelper(surface, 0);
|
||||
}
|
||||
|
||||
function TransformNodes(node_data, div, old_nodes, display_commands) {
|
||||
function TransformNodes(node_data, div, nodes, display_commands) {
|
||||
this.node_data = node_data;
|
||||
this.display_commands = display_commands;
|
||||
this.data_pos = 0;
|
||||
this.div = div;
|
||||
this.outstanding = 1;
|
||||
this.old_nodes = old_nodes;
|
||||
this.new_nodes = {};
|
||||
this.nodes = nodes;
|
||||
}
|
||||
|
||||
TransformNodes.prototype.decode_uint32 = function() {
|
||||
@ -479,16 +479,21 @@ function set_rrect_style (div, rrect) {
|
||||
div.style["border-bottom-left-radius"] = args(px(rrect.sizes[3].width), px(rrect.sizes[3].height));
|
||||
}
|
||||
|
||||
function addOldIds(node, node_map) {
|
||||
node_map[node.node_id] = node;
|
||||
|
||||
var child = node.firstChild;
|
||||
while (child) {
|
||||
addOldIds(child, node_map);
|
||||
child = child.nextSibling;
|
||||
}
|
||||
TransformNodes.prototype.createDiv = function(id)
|
||||
{
|
||||
var div = document.createElement('div');
|
||||
div.node_id = id;
|
||||
this.nodes[id] = div;
|
||||
return div;
|
||||
}
|
||||
|
||||
TransformNodes.prototype.createImage = function(id)
|
||||
{
|
||||
var image = new Image();
|
||||
image.node_id = id;
|
||||
this.nodes[id] = image;
|
||||
return image;
|
||||
}
|
||||
|
||||
TransformNodes.prototype.insertNode = function(parent, previousSibling, is_toplevel)
|
||||
{
|
||||
@ -502,7 +507,7 @@ TransformNodes.prototype.insertNode = function(parent, previousSibling, is_tople
|
||||
/* Reuse divs from last frame */
|
||||
case BROADWAY_NODE_REUSE:
|
||||
{
|
||||
oldNode = this.old_nodes[id];
|
||||
oldNode = this.nodes[id];
|
||||
}
|
||||
break;
|
||||
/* Leaf nodes */
|
||||
@ -511,7 +516,7 @@ TransformNodes.prototype.insertNode = function(parent, previousSibling, is_tople
|
||||
{
|
||||
var rect = this.decode_rect();
|
||||
var texture_id = this.decode_uint32();
|
||||
var image = new Image();
|
||||
var image = this.createImage(id);
|
||||
image.width = rect.width;
|
||||
image.height = rect.height;
|
||||
image.style["position"] = "absolute";
|
||||
@ -528,7 +533,7 @@ TransformNodes.prototype.insertNode = function(parent, previousSibling, is_tople
|
||||
{
|
||||
var rect = this.decode_rect();
|
||||
var c = this.decode_color ();
|
||||
var div = document.createElement('div');
|
||||
var div = this.createDiv(id);
|
||||
div.style["position"] = "absolute";
|
||||
set_rect_style(div, rect);
|
||||
div.style["background-color"] = c;
|
||||
@ -546,7 +551,7 @@ TransformNodes.prototype.insertNode = function(parent, previousSibling, is_tople
|
||||
for (var i = 0; i < 4; i++)
|
||||
border_colors[i] = this.decode_color();
|
||||
|
||||
var div = document.createElement('div');
|
||||
var div = this.createDiv(id);
|
||||
div.style["position"] = "absolute";
|
||||
rrect.bounds.width -= border_widths[1] + border_widths[3];
|
||||
rrect.bounds.height -= border_widths[0] + border_widths[2];
|
||||
@ -573,7 +578,7 @@ TransformNodes.prototype.insertNode = function(parent, previousSibling, is_tople
|
||||
var spread = this.decode_float();
|
||||
var blur = this.decode_float();
|
||||
|
||||
var div = document.createElement('div');
|
||||
var div = this.createDiv(id);
|
||||
div.style["position"] = "absolute";
|
||||
set_rrect_style(div, rrect);
|
||||
div.style["box-shadow"] = args(px(dx), px(dy), px(blur), px(spread), color);
|
||||
@ -590,7 +595,7 @@ TransformNodes.prototype.insertNode = function(parent, previousSibling, is_tople
|
||||
var spread = this.decode_float();
|
||||
var blur = this.decode_float();
|
||||
|
||||
var div = document.createElement('div');
|
||||
var div = this.createDiv(id);
|
||||
div.style["position"] = "absolute";
|
||||
set_rrect_style(div, rrect);
|
||||
div.style["box-shadow"] = args("inset", px(dx), px(dy), px(blur), px(spread), color);
|
||||
@ -605,7 +610,7 @@ TransformNodes.prototype.insertNode = function(parent, previousSibling, is_tople
|
||||
var start = this.decode_point ();
|
||||
var end = this.decode_point ();
|
||||
var stops = this.decode_color_stops ();
|
||||
var div = document.createElement('div');
|
||||
var div = this.createDiv(id);
|
||||
div.style["position"] = "absolute";
|
||||
set_rect_style(div, rect);
|
||||
|
||||
@ -669,7 +674,7 @@ TransformNodes.prototype.insertNode = function(parent, previousSibling, is_tople
|
||||
m[12] + "," + m[13] + "," + m[14] + "," + m[15] + ")";
|
||||
}
|
||||
|
||||
var div = document.createElement('div');
|
||||
var div = this.createDiv(id);
|
||||
div.style["transform"] = transform_string;
|
||||
div.style["transform-origin"] = "0px 0px";
|
||||
|
||||
@ -681,7 +686,7 @@ TransformNodes.prototype.insertNode = function(parent, previousSibling, is_tople
|
||||
case BROADWAY_NODE_CLIP:
|
||||
{
|
||||
var rect = this.decode_rect();
|
||||
var div = document.createElement('div');
|
||||
var div = this.createDiv(id);
|
||||
div.style["position"] = "absolute";
|
||||
set_rect_style(div, rect);
|
||||
div.style["overflow"] = "hidden";
|
||||
@ -693,7 +698,7 @@ TransformNodes.prototype.insertNode = function(parent, previousSibling, is_tople
|
||||
case BROADWAY_NODE_ROUNDED_CLIP:
|
||||
{
|
||||
var rrect = this.decode_rounded_rect();
|
||||
var div = document.createElement('div');
|
||||
var div = this.createDiv(id);
|
||||
div.style["position"] = "absolute";
|
||||
set_rrect_style(div, rrect);
|
||||
div.style["overflow"] = "hidden";
|
||||
@ -705,7 +710,7 @@ TransformNodes.prototype.insertNode = function(parent, previousSibling, is_tople
|
||||
case BROADWAY_NODE_OPACITY:
|
||||
{
|
||||
var opacity = this.decode_float();
|
||||
var div = document.createElement('div');
|
||||
var div = this.createDiv(id);
|
||||
div.style["position"] = "absolute";
|
||||
div.style["left"] = px(0);
|
||||
div.style["top"] = px(0);
|
||||
@ -727,7 +732,7 @@ TransformNodes.prototype.insertNode = function(parent, previousSibling, is_tople
|
||||
var blur = this.decode_float();
|
||||
filters = filters + "drop-shadow(" + args (px(dx), px(dy), px(blur), color) + ")";
|
||||
}
|
||||
var div = document.createElement('div');
|
||||
var div = this.createDiv(id);
|
||||
div.style["position"] = "absolute";
|
||||
div.style["left"] = px(0);
|
||||
div.style["top"] = px(0);
|
||||
@ -741,7 +746,7 @@ TransformNodes.prototype.insertNode = function(parent, previousSibling, is_tople
|
||||
case 14: // DEBUG
|
||||
{
|
||||
var str = this.decode_string();
|
||||
var div = document.createElement('div');
|
||||
var div = this.createDiv(id);
|
||||
div.setAttribute('debug', str);
|
||||
this.insertNode(div, null, false);
|
||||
newNode = div;
|
||||
@ -752,7 +757,7 @@ TransformNodes.prototype.insertNode = function(parent, previousSibling, is_tople
|
||||
|
||||
case BROADWAY_NODE_CONTAINER:
|
||||
{
|
||||
var div = document.createElement('div');
|
||||
var div = this.createDiv(id);
|
||||
var len = this.decode_uint32();
|
||||
var lastChild = null;
|
||||
for (var i = 0; i < len; i++) {
|
||||
@ -767,15 +772,12 @@ TransformNodes.prototype.insertNode = function(parent, previousSibling, is_tople
|
||||
}
|
||||
|
||||
if (newNode) {
|
||||
newNode.node_id = id;
|
||||
this.new_nodes[id] = newNode;
|
||||
if (is_toplevel)
|
||||
this.display_commands.push([DISPLAY_OP_APPEND_CHILD, parent, newNode]);
|
||||
else // Here it is safe to display directly because we have not added the toplevel to the document yet
|
||||
this.display_commands.push([DISPLAY_OP_INSERT_AFTER_CHILD, parent, previousSibling, newNode]);
|
||||
else // It is safe to display directly because we have not added the toplevel to the document yet
|
||||
parent.appendChild(newNode);
|
||||
return newNode;
|
||||
} else if (oldNode) {
|
||||
addOldIds(oldNode, this.new_nodes);
|
||||
// This must be delayed until display ops, because it will remove from the old parent
|
||||
this.display_commands.push([DISPLAY_OP_INSERT_AFTER_CHILD, parent, previousSibling, oldNode]);
|
||||
return oldNode;
|
||||
@ -788,22 +790,48 @@ TransformNodes.prototype.execute = function(display_commands)
|
||||
|
||||
while (this.data_pos < this.node_data.byteLength) {
|
||||
var op = this.decode_uint32();
|
||||
var parentId, parent;
|
||||
|
||||
switch (op) {
|
||||
case BROADWAY_NODE_OP_APPEND_NODE:
|
||||
var parentId = this.decode_uint32();
|
||||
var parent;
|
||||
case BROADWAY_NODE_OP_INSERT_NODE:
|
||||
parentId = this.decode_uint32();
|
||||
if (parentId == 0)
|
||||
parent = root;
|
||||
else
|
||||
parent = this.old_nodes[parentId];
|
||||
this.insertNode(parent, null, true);
|
||||
else {
|
||||
parent = this.nodes[parentId];
|
||||
if (parent == null)
|
||||
console.log("Wanted to insert into parent " + parentId + " but it is unknown");
|
||||
}
|
||||
|
||||
var previousChildId = this.decode_uint32();
|
||||
var previousChild = null;
|
||||
if (previousChildId != 0)
|
||||
previousChild = this.nodes[previousChildId];
|
||||
this.insertNode(parent, previousChild, true);
|
||||
break;
|
||||
case BROADWAY_NODE_OP_REMOVE_NODE:
|
||||
var removeId = this.decode_uint32();
|
||||
var remove = this.old_nodes[removeId];
|
||||
var remove = this.nodes[removeId];
|
||||
delete this.nodes[removeId];
|
||||
if (remove == null)
|
||||
console.log("Wanted to delete node " + removeId + " but it is unknown");
|
||||
|
||||
this.display_commands.push([DISPLAY_OP_DELETE_NODE, remove]);
|
||||
break;
|
||||
case BROADWAY_NODE_OP_MOVE_AFTER_CHILD:
|
||||
parentId = this.decode_uint32();
|
||||
if (parentId == 0)
|
||||
parent = root;
|
||||
else
|
||||
parent = this.nodes[parentId];
|
||||
var previousChildId = this.decode_uint32();
|
||||
var previousChild = null;
|
||||
if (previousChildId != 0)
|
||||
previousChild = this.nodes[previousChildId];
|
||||
var toMoveId = this.decode_uint32();
|
||||
var toMove = this.nodes[toMoveId];
|
||||
this.display_commands.push([DISPLAY_OP_INSERT_AFTER_CHILD, parent, previousChild, toMove]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1028,9 +1056,8 @@ function handleCommands(cmd, display_commands, new_textures, modified_trees)
|
||||
|
||||
var node_data = cmd.get_nodes ();
|
||||
surface = surfaces[id];
|
||||
var transform_nodes = new TransformNodes (node_data, surface.div, surface.old_nodes, display_commands);
|
||||
var transform_nodes = new TransformNodes (node_data, surface.div, surface.nodes, display_commands);
|
||||
transform_nodes.execute();
|
||||
surface.old_nodes = transform_nodes.new_nodes;
|
||||
}
|
||||
break;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user