mirror of
https://gitlab.gnome.org/GNOME/gtk.git
synced 2025-01-05 02:11:08 +00:00
Merge branch 'wip/alexl/broadway7' into 'master'
Even more broadway updates See merge request GNOME/gtk!680
This commit is contained in:
commit
7c369f309a
@ -8,6 +8,7 @@
|
|||||||
#include "broadway-output.h"
|
#include "broadway-output.h"
|
||||||
|
|
||||||
//#define DEBUG_NODE_SENDING
|
//#define DEBUG_NODE_SENDING
|
||||||
|
//#define DEBUG_NODE_SENDING_REMOVE
|
||||||
|
|
||||||
/************************************************************************
|
/************************************************************************
|
||||||
* Basic I/O primitives *
|
* Basic I/O primitives *
|
||||||
@ -113,7 +114,7 @@ broadway_output_set_next_serial (BroadwayOutput *output,
|
|||||||
************************************************************************/
|
************************************************************************/
|
||||||
|
|
||||||
static void
|
static void
|
||||||
append_char (BroadwayOutput *output, char c)
|
append_uint8 (BroadwayOutput *output, guint8 c)
|
||||||
{
|
{
|
||||||
g_string_append_c (output->buf, c);
|
g_string_append_c (output->buf, c);
|
||||||
}
|
}
|
||||||
@ -172,7 +173,7 @@ patch_uint32 (BroadwayOutput *output, guint32 v, gsize offset)
|
|||||||
static void
|
static void
|
||||||
write_header(BroadwayOutput *output, char op)
|
write_header(BroadwayOutput *output, char op)
|
||||||
{
|
{
|
||||||
append_char (output, op);
|
append_uint8 (output, op);
|
||||||
append_uint32 (output, output->serial++);
|
append_uint32 (output, output->serial++);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -317,15 +318,25 @@ static void
|
|||||||
append_type (BroadwayOutput *output, guint32 type, BroadwayNode *node)
|
append_type (BroadwayOutput *output, guint32 type, BroadwayNode *node)
|
||||||
{
|
{
|
||||||
#ifdef DEBUG_NODE_SENDING
|
#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)
|
if (type == BROADWAY_NODE_TEXTURE)
|
||||||
g_print (" %u", node->data[4]);
|
g_print (" tx=%u", node->data[4]);
|
||||||
g_print ("\n");
|
g_print ("\n");
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
append_uint32 (output, type);
|
append_uint32 (output, type);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static BroadwayNode *
|
||||||
|
lookup_old_node (GHashTable *old_node_lookup,
|
||||||
|
guint32 id)
|
||||||
|
{
|
||||||
|
if (old_node_lookup)
|
||||||
|
return g_hash_table_lookup (old_node_lookup, GINT_TO_POINTER (id));
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/***********************************
|
/***********************************
|
||||||
* This outputs the tree to the client, while at the same time diffing
|
* This outputs the tree to the client, while at the same time diffing
|
||||||
@ -347,59 +358,230 @@ append_type (BroadwayOutput *output, guint32 type, BroadwayNode *node)
|
|||||||
static void
|
static void
|
||||||
append_node (BroadwayOutput *output,
|
append_node (BroadwayOutput *output,
|
||||||
BroadwayNode *node,
|
BroadwayNode *node,
|
||||||
BroadwayNode *old_node,
|
GHashTable *old_node_lookup)
|
||||||
gboolean all_parents_are_kept)
|
|
||||||
{
|
{
|
||||||
guint32 i;
|
guint32 i;
|
||||||
|
BroadwayNode *reused_node;
|
||||||
|
|
||||||
append_node_depth++;
|
append_node_depth++;
|
||||||
|
|
||||||
if (old_node != NULL && broadway_node_equal (node, old_node))
|
reused_node = lookup_old_node (old_node_lookup, node->id);
|
||||||
|
if (reused_node)
|
||||||
{
|
{
|
||||||
if (broadway_node_deep_equal (node, old_node))
|
broadway_node_mark_deep_consumed (reused_node, TRUE);
|
||||||
{
|
append_type (output, BROADWAY_NODE_REUSE, node);
|
||||||
append_type (output, BROADWAY_NODE_KEEP_ALL, node);
|
append_uint32 (output, node->output_id);
|
||||||
goto out;
|
}
|
||||||
}
|
else
|
||||||
|
{
|
||||||
if (all_parents_are_kept)
|
append_type (output, node->type, node);
|
||||||
{
|
append_uint32 (output, node->output_id);
|
||||||
append_type (output, BROADWAY_NODE_KEEP_THIS, node);
|
for (i = 0; i < node->n_data; i++)
|
||||||
append_uint32 (output, node->n_children);
|
append_uint32 (output, node->data[i]);
|
||||||
for (i = 0; i < node->n_children; i++)
|
for (i = 0; i < node->n_children; i++)
|
||||||
append_node (output, node->children[i],
|
append_node (output,
|
||||||
i < old_node->n_children ? old_node->children[i] : NULL,
|
node->children[i],
|
||||||
TRUE);
|
old_node_lookup);
|
||||||
|
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
append_type (output, node->type, node);
|
|
||||||
for (i = 0; i < node->n_data; i++)
|
|
||||||
append_uint32 (output, node->data[i]);
|
|
||||||
for (i = 0; i < node->n_children; i++)
|
|
||||||
append_node (output,
|
|
||||||
node->children[i],
|
|
||||||
(old_node != NULL && i < old_node->n_children) ? old_node->children[i] : NULL,
|
|
||||||
FALSE);
|
|
||||||
|
|
||||||
out:
|
|
||||||
append_node_depth--;
|
append_node_depth--;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
should_reuse_node (BroadwayOutput *output,
|
||||||
|
BroadwayNode *node,
|
||||||
|
BroadwayNode *old_node)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
guint32 new_texture;
|
||||||
|
|
||||||
|
if (old_node->reused)
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
if (node->type != old_node->type)
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
if (broadway_node_equal (node, old_node))
|
||||||
|
return TRUE;
|
||||||
|
|
||||||
|
switch (node->type) {
|
||||||
|
case BROADWAY_NODE_TRANSFORM:
|
||||||
|
#ifdef DEBUG_NODE_SENDING
|
||||||
|
g_print ("Patching transform node %d/%d\n",
|
||||||
|
old_node->id, old_node->output_id);
|
||||||
|
#endif
|
||||||
|
append_uint32 (output, BROADWAY_NODE_OP_PATCH_TRANSFORM);
|
||||||
|
append_uint32 (output, old_node->output_id);
|
||||||
|
for (i = 0; i < node->n_data; i++)
|
||||||
|
append_uint32 (output, node->data[i]);
|
||||||
|
return TRUE;
|
||||||
|
|
||||||
|
case BROADWAY_NODE_TEXTURE:
|
||||||
|
/* Check that the size, etc is the same */
|
||||||
|
for (i = 0; i < 4; i++)
|
||||||
|
if (node->data[i] != old_node->data[i])
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
new_texture = node->data[4];
|
||||||
|
|
||||||
|
#ifdef DEBUG_NODE_SENDING
|
||||||
|
g_print ("Patching texture node %d/%d to tx=%d\n",
|
||||||
|
old_node->id, old_node->output_id,
|
||||||
|
new_texture);
|
||||||
|
#endif
|
||||||
|
append_uint32 (output, BROADWAY_NODE_OP_PATCH_TEXTURE);
|
||||||
|
append_uint32 (output, old_node->output_id);
|
||||||
|
append_uint32 (output, new_texture);
|
||||||
|
return TRUE;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static BroadwayNode *
|
||||||
|
append_node_ops (BroadwayOutput *output,
|
||||||
|
BroadwayNode *node,
|
||||||
|
BroadwayNode *parent,
|
||||||
|
BroadwayNode *previous_sibling,
|
||||||
|
BroadwayNode *old_node,
|
||||||
|
GHashTable *old_node_lookup)
|
||||||
|
{
|
||||||
|
BroadwayNode *reused_node;
|
||||||
|
guint32 i;
|
||||||
|
|
||||||
|
/* 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 */
|
||||||
|
|
||||||
|
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 && should_reuse_node (output, node, old_node))
|
||||||
|
{
|
||||||
|
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);
|
||||||
|
|
||||||
|
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
|
void
|
||||||
broadway_output_surface_set_nodes (BroadwayOutput *output,
|
broadway_output_surface_set_nodes (BroadwayOutput *output,
|
||||||
int id,
|
int id,
|
||||||
BroadwayNode *root,
|
BroadwayNode *root,
|
||||||
BroadwayNode *old_root)
|
BroadwayNode *old_root,
|
||||||
|
GHashTable *old_node_lookup)
|
||||||
{
|
{
|
||||||
gsize size_pos, start, end;
|
gsize size_pos, start, end;
|
||||||
|
|
||||||
/* Early return if nothing changed */
|
|
||||||
if (old_root != NULL &&
|
if (old_root)
|
||||||
broadway_node_deep_equal (root, old_root))
|
{
|
||||||
return;
|
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);
|
write_header (output, BROADWAY_OP_SET_NODES);
|
||||||
|
|
||||||
@ -410,9 +592,11 @@ broadway_output_surface_set_nodes (BroadwayOutput *output,
|
|||||||
|
|
||||||
start = output->buf->len;
|
start = output->buf->len;
|
||||||
#ifdef DEBUG_NODE_SENDING
|
#ifdef DEBUG_NODE_SENDING
|
||||||
g_print ("====== node tree for %d =======\n", id);
|
g_print ("====== node ops for surface %d =======\n", id);
|
||||||
#endif
|
#endif
|
||||||
append_node (output, root, old_root, TRUE);
|
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;
|
end = output->buf->len;
|
||||||
patch_uint32 (output, (end - start) / 4, size_pos);
|
patch_uint32 (output, (end - start) / 4, size_pos);
|
||||||
}
|
}
|
||||||
|
@ -60,7 +60,8 @@ void broadway_output_set_transient_for (BroadwayOutput *output,
|
|||||||
void broadway_output_surface_set_nodes (BroadwayOutput *output,
|
void broadway_output_surface_set_nodes (BroadwayOutput *output,
|
||||||
int id,
|
int id,
|
||||||
BroadwayNode *root,
|
BroadwayNode *root,
|
||||||
BroadwayNode *old_root);
|
BroadwayNode *old_root,
|
||||||
|
GHashTable *old_node_lookup);
|
||||||
void broadway_output_upload_texture (BroadwayOutput *output,
|
void broadway_output_upload_texture (BroadwayOutput *output,
|
||||||
guint32 id,
|
guint32 id,
|
||||||
GBytes *texture);
|
GBytes *texture);
|
||||||
|
@ -20,13 +20,19 @@ typedef enum { /* Sync changes with broadway.js */
|
|||||||
BROADWAY_NODE_SHADOW = 8,
|
BROADWAY_NODE_SHADOW = 8,
|
||||||
BROADWAY_NODE_OPACITY = 9,
|
BROADWAY_NODE_OPACITY = 9,
|
||||||
BROADWAY_NODE_CLIP = 10,
|
BROADWAY_NODE_CLIP = 10,
|
||||||
BROADWAY_NODE_KEEP_ALL = 11,
|
BROADWAY_NODE_TRANSFORM = 11,
|
||||||
BROADWAY_NODE_KEEP_THIS = 12,
|
BROADWAY_NODE_DEBUG = 12,
|
||||||
BROADWAY_NODE_TRANSFORM = 13,
|
BROADWAY_NODE_REUSE = 13,
|
||||||
BROADWAY_NODE_DEBUG = 14,
|
|
||||||
BROADWAY_NODE_REUSE = 15,
|
|
||||||
} BroadwayNodeType;
|
} BroadwayNodeType;
|
||||||
|
|
||||||
|
typedef enum { /* Sync changes with broadway.js */
|
||||||
|
BROADWAY_NODE_OP_INSERT_NODE = 0,
|
||||||
|
BROADWAY_NODE_OP_REMOVE_NODE = 1,
|
||||||
|
BROADWAY_NODE_OP_MOVE_AFTER_CHILD = 2,
|
||||||
|
BROADWAY_NODE_OP_PATCH_TEXTURE = 3,
|
||||||
|
BROADWAY_NODE_OP_PATCH_TRANSFORM = 4,
|
||||||
|
} BroadwayNodeOpType;
|
||||||
|
|
||||||
static const char *broadway_node_type_names[] G_GNUC_UNUSED = {
|
static const char *broadway_node_type_names[] G_GNUC_UNUSED = {
|
||||||
"TEXTURE",
|
"TEXTURE",
|
||||||
"CONTAINER",
|
"CONTAINER",
|
||||||
@ -39,51 +45,47 @@ static const char *broadway_node_type_names[] G_GNUC_UNUSED = {
|
|||||||
"SHADOW",
|
"SHADOW",
|
||||||
"OPACITY",
|
"OPACITY",
|
||||||
"CLIP",
|
"CLIP",
|
||||||
"KEEP_ALL",
|
"TRANSFORM",
|
||||||
"KEEP_THIS",
|
|
||||||
"TRANSLATE",
|
|
||||||
"DEBUG",
|
"DEBUG",
|
||||||
|
"REUSE",
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
BROADWAY_EVENT_ENTER = 'e',
|
BROADWAY_EVENT_ENTER = 0,
|
||||||
BROADWAY_EVENT_LEAVE = 'l',
|
BROADWAY_EVENT_LEAVE = 1,
|
||||||
BROADWAY_EVENT_POINTER_MOVE = 'm',
|
BROADWAY_EVENT_POINTER_MOVE = 2,
|
||||||
BROADWAY_EVENT_BUTTON_PRESS = 'b',
|
BROADWAY_EVENT_BUTTON_PRESS = 3,
|
||||||
BROADWAY_EVENT_BUTTON_RELEASE = 'B',
|
BROADWAY_EVENT_BUTTON_RELEASE = 4,
|
||||||
BROADWAY_EVENT_TOUCH = 't',
|
BROADWAY_EVENT_TOUCH = 5,
|
||||||
BROADWAY_EVENT_SCROLL = 's',
|
BROADWAY_EVENT_SCROLL = 6,
|
||||||
BROADWAY_EVENT_KEY_PRESS = 'k',
|
BROADWAY_EVENT_KEY_PRESS = 7,
|
||||||
BROADWAY_EVENT_KEY_RELEASE = 'K',
|
BROADWAY_EVENT_KEY_RELEASE = 8,
|
||||||
BROADWAY_EVENT_GRAB_NOTIFY = 'g',
|
BROADWAY_EVENT_GRAB_NOTIFY = 9,
|
||||||
BROADWAY_EVENT_UNGRAB_NOTIFY = 'u',
|
BROADWAY_EVENT_UNGRAB_NOTIFY = 10,
|
||||||
BROADWAY_EVENT_CONFIGURE_NOTIFY = 'w',
|
BROADWAY_EVENT_CONFIGURE_NOTIFY = 11,
|
||||||
BROADWAY_EVENT_SCREEN_SIZE_CHANGED = 'd',
|
BROADWAY_EVENT_SCREEN_SIZE_CHANGED = 12,
|
||||||
BROADWAY_EVENT_FOCUS = 'f',
|
BROADWAY_EVENT_FOCUS = 13,
|
||||||
BROADWAY_EVENT_ROUNDTRIP_NOTIFY = 'F',
|
BROADWAY_EVENT_ROUNDTRIP_NOTIFY = 14,
|
||||||
} BroadwayEventType;
|
} BroadwayEventType;
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
BROADWAY_OP_GRAB_POINTER = 'g',
|
BROADWAY_OP_GRAB_POINTER = 0,
|
||||||
BROADWAY_OP_UNGRAB_POINTER = 'u',
|
BROADWAY_OP_UNGRAB_POINTER = 1,
|
||||||
BROADWAY_OP_NEW_SURFACE = 's',
|
BROADWAY_OP_NEW_SURFACE = 2,
|
||||||
BROADWAY_OP_SHOW_SURFACE = 'S',
|
BROADWAY_OP_SHOW_SURFACE = 3,
|
||||||
BROADWAY_OP_HIDE_SURFACE = 'H',
|
BROADWAY_OP_HIDE_SURFACE = 4,
|
||||||
BROADWAY_OP_RAISE_SURFACE = 'r',
|
BROADWAY_OP_RAISE_SURFACE = 5,
|
||||||
BROADWAY_OP_LOWER_SURFACE = 'R',
|
BROADWAY_OP_LOWER_SURFACE = 6,
|
||||||
BROADWAY_OP_DESTROY_SURFACE = 'd',
|
BROADWAY_OP_DESTROY_SURFACE = 7,
|
||||||
BROADWAY_OP_MOVE_RESIZE = 'm',
|
BROADWAY_OP_MOVE_RESIZE = 8,
|
||||||
BROADWAY_OP_SET_TRANSIENT_FOR = 'p',
|
BROADWAY_OP_SET_TRANSIENT_FOR = 9,
|
||||||
BROADWAY_OP_PUT_RGB = 'i',
|
BROADWAY_OP_DISCONNECTED = 10,
|
||||||
BROADWAY_OP_REQUEST_AUTH = 'l',
|
BROADWAY_OP_SURFACE_UPDATE = 11,
|
||||||
BROADWAY_OP_AUTH_OK = 'L',
|
BROADWAY_OP_SET_SHOW_KEYBOARD = 12,
|
||||||
BROADWAY_OP_DISCONNECTED = 'D',
|
BROADWAY_OP_UPLOAD_TEXTURE = 13,
|
||||||
BROADWAY_OP_SURFACE_UPDATE = 'b',
|
BROADWAY_OP_RELEASE_TEXTURE = 14,
|
||||||
BROADWAY_OP_SET_SHOW_KEYBOARD = 'k',
|
BROADWAY_OP_SET_NODES = 15,
|
||||||
BROADWAY_OP_UPLOAD_TEXTURE = 't',
|
BROADWAY_OP_ROUNDTRIP = 16,
|
||||||
BROADWAY_OP_RELEASE_TEXTURE = 'T',
|
|
||||||
BROADWAY_OP_SET_NODES = 'n',
|
|
||||||
BROADWAY_OP_ROUNDTRIP = 'F',
|
|
||||||
} BroadwayOpType;
|
} BroadwayOpType;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
|
@ -115,6 +115,7 @@ struct BroadwayInput {
|
|||||||
};
|
};
|
||||||
|
|
||||||
struct BroadwaySurface {
|
struct BroadwaySurface {
|
||||||
|
guint32 owner;
|
||||||
gint32 id;
|
gint32 id;
|
||||||
gint32 x;
|
gint32 x;
|
||||||
gint32 y;
|
gint32 y;
|
||||||
@ -224,6 +225,33 @@ broadway_node_deep_equal (BroadwayNode *a,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
broadway_node_mark_deep_reused (BroadwayNode *node,
|
||||||
|
gboolean reused)
|
||||||
|
{
|
||||||
|
node->reused = reused;
|
||||||
|
for (int i = 0; i < node->n_children; i++)
|
||||||
|
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
|
||||||
|
broadway_node_add_to_lookup (BroadwayNode *node,
|
||||||
|
GHashTable *node_lookup)
|
||||||
|
{
|
||||||
|
g_hash_table_insert (node_lookup, GINT_TO_POINTER(node->id), node);
|
||||||
|
for (int i = 0; i < node->n_children; i++)
|
||||||
|
broadway_node_add_to_lookup (node->children[i], node_lookup);
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
broadway_server_init (BroadwayServer *server)
|
broadway_server_init (BroadwayServer *server)
|
||||||
{
|
{
|
||||||
@ -444,9 +472,46 @@ process_input_message (BroadwayServer *server,
|
|||||||
BroadwayInputMsg *message)
|
BroadwayInputMsg *message)
|
||||||
{
|
{
|
||||||
gint32 client;
|
gint32 client;
|
||||||
|
BroadwaySurface *surface;
|
||||||
|
|
||||||
update_event_state (server, message);
|
update_event_state (server, message);
|
||||||
client = -1;
|
|
||||||
|
|
||||||
|
switch (message->base.type) {
|
||||||
|
case BROADWAY_EVENT_ENTER:
|
||||||
|
case BROADWAY_EVENT_LEAVE:
|
||||||
|
case BROADWAY_EVENT_POINTER_MOVE:
|
||||||
|
case BROADWAY_EVENT_BUTTON_PRESS:
|
||||||
|
case BROADWAY_EVENT_BUTTON_RELEASE:
|
||||||
|
case BROADWAY_EVENT_SCROLL:
|
||||||
|
case BROADWAY_EVENT_GRAB_NOTIFY:
|
||||||
|
case BROADWAY_EVENT_UNGRAB_NOTIFY:
|
||||||
|
surface = broadway_server_lookup_surface (server, message->pointer.event_surface_id);
|
||||||
|
break;
|
||||||
|
case BROADWAY_EVENT_TOUCH:
|
||||||
|
surface = broadway_server_lookup_surface (server, message->touch.event_surface_id);
|
||||||
|
break;
|
||||||
|
case BROADWAY_EVENT_CONFIGURE_NOTIFY:
|
||||||
|
surface = broadway_server_lookup_surface (server, message->configure_notify.id);
|
||||||
|
break;
|
||||||
|
case BROADWAY_EVENT_ROUNDTRIP_NOTIFY:
|
||||||
|
surface = broadway_server_lookup_surface (server, message->roundtrip_notify.id);
|
||||||
|
break;
|
||||||
|
case BROADWAY_EVENT_KEY_PRESS:
|
||||||
|
case BROADWAY_EVENT_KEY_RELEASE:
|
||||||
|
/* TODO: Send to keys focused clients only... */
|
||||||
|
case BROADWAY_EVENT_FOCUS:
|
||||||
|
case BROADWAY_EVENT_SCREEN_SIZE_CHANGED:
|
||||||
|
default:
|
||||||
|
surface = NULL;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (surface)
|
||||||
|
client = surface->owner;
|
||||||
|
else
|
||||||
|
client = -1;
|
||||||
|
|
||||||
if (is_pointer_event (message) &&
|
if (is_pointer_event (message) &&
|
||||||
server->pointer_grab_surface_id != -1)
|
server->pointer_grab_surface_id != -1)
|
||||||
client = server->pointer_grab_client_id;
|
client = server->pointer_grab_client_id;
|
||||||
@ -557,6 +622,7 @@ parse_input_message (BroadwayInput *input, const unsigned char *message)
|
|||||||
|
|
||||||
msg.base.type = ntohl (*p++);
|
msg.base.type = ntohl (*p++);
|
||||||
msg.base.serial = ntohl (*p++);
|
msg.base.serial = ntohl (*p++);
|
||||||
|
|
||||||
time_ = ntohl (*p++);
|
time_ = ntohl (*p++);
|
||||||
|
|
||||||
if (time_ == 0) {
|
if (time_ == 0) {
|
||||||
@ -638,12 +704,19 @@ parse_input_message (BroadwayInput *input, const unsigned char *message)
|
|||||||
|
|
||||||
if (rt->id == msg.roundtrip_notify.id &&
|
if (rt->id == msg.roundtrip_notify.id &&
|
||||||
rt->tag == msg.roundtrip_notify.tag)
|
rt->tag == msg.roundtrip_notify.tag)
|
||||||
{
|
break;
|
||||||
server->outstanding_roundtrips = g_list_delete_link (server->outstanding_roundtrips, l);
|
|
||||||
g_free (rt);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (l == NULL)
|
||||||
|
g_warning ("Got unexpected rountrip reply for id %d, tag %d\n", msg.roundtrip_notify.id, msg.roundtrip_notify.tag);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
BroadwayOutstandingRoundtrip *rt = l->data;
|
||||||
|
|
||||||
|
server->outstanding_roundtrips = g_list_delete_link (server->outstanding_roundtrips, l);
|
||||||
|
g_free (rt);
|
||||||
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case BROADWAY_EVENT_SCREEN_SIZE_CHANGED:
|
case BROADWAY_EVENT_SCREEN_SIZE_CHANGED:
|
||||||
@ -1753,6 +1826,7 @@ decode_nodes (BroadwayServer *server,
|
|||||||
g_ref_count_init (&node->refcount);
|
g_ref_count_init (&node->refcount);
|
||||||
node->type = type;
|
node->type = type;
|
||||||
node->id = id;
|
node->id = id;
|
||||||
|
node->output_id = id;
|
||||||
node->texture_id = 0;
|
node->texture_id = 0;
|
||||||
node->n_children = n_children;
|
node->n_children = n_children;
|
||||||
node->children = (BroadwayNode **)((char *)node + sizeof(BroadwayNode) + (size - 1) * sizeof(guint32));
|
node->children = (BroadwayNode **)((char *)node + sizeof(BroadwayNode) + (size - 1) * sizeof(guint32));
|
||||||
@ -1784,17 +1858,6 @@ decode_nodes (BroadwayServer *server,
|
|||||||
return node;
|
return node;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
|
||||||
init_node_lookup (BroadwaySurface *surface,
|
|
||||||
BroadwayNode *node)
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
|
|
||||||
g_hash_table_insert (surface->node_lookup, GINT_TO_POINTER(node->id), node);
|
|
||||||
for (i = 0; i < node->n_children; i++)
|
|
||||||
init_node_lookup (surface, node->children[i]);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* passes ownership of nodes */
|
/* passes ownership of nodes */
|
||||||
void
|
void
|
||||||
broadway_server_surface_update_nodes (BroadwayServer *server,
|
broadway_server_surface_update_nodes (BroadwayServer *server,
|
||||||
@ -1816,7 +1879,8 @@ broadway_server_surface_update_nodes (BroadwayServer *server,
|
|||||||
if (server->output != NULL)
|
if (server->output != NULL)
|
||||||
broadway_output_surface_set_nodes (server->output, surface->id,
|
broadway_output_surface_set_nodes (server->output, surface->id,
|
||||||
root,
|
root,
|
||||||
surface->nodes);
|
surface->nodes,
|
||||||
|
surface->node_lookup);
|
||||||
|
|
||||||
if (surface->nodes)
|
if (surface->nodes)
|
||||||
broadway_node_unref (server, surface->nodes);
|
broadway_node_unref (server, surface->nodes);
|
||||||
@ -1824,8 +1888,7 @@ broadway_server_surface_update_nodes (BroadwayServer *server,
|
|||||||
surface->nodes = root;
|
surface->nodes = root;
|
||||||
|
|
||||||
g_hash_table_remove_all (surface->node_lookup);
|
g_hash_table_remove_all (surface->node_lookup);
|
||||||
|
broadway_node_add_to_lookup (root, surface->node_lookup);
|
||||||
init_node_lookup (surface, surface->nodes);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
guint32
|
guint32
|
||||||
@ -2003,6 +2066,7 @@ broadway_server_ungrab_pointer (BroadwayServer *server,
|
|||||||
|
|
||||||
guint32
|
guint32
|
||||||
broadway_server_new_surface (BroadwayServer *server,
|
broadway_server_new_surface (BroadwayServer *server,
|
||||||
|
guint32 client,
|
||||||
int x,
|
int x,
|
||||||
int y,
|
int y,
|
||||||
int width,
|
int width,
|
||||||
@ -2012,6 +2076,7 @@ broadway_server_new_surface (BroadwayServer *server,
|
|||||||
BroadwaySurface *surface;
|
BroadwaySurface *surface;
|
||||||
|
|
||||||
surface = g_new0 (BroadwaySurface, 1);
|
surface = g_new0 (BroadwaySurface, 1);
|
||||||
|
surface->owner = client;
|
||||||
surface->id = server->id_counter++;
|
surface->id = server->id_counter++;
|
||||||
surface->x = x;
|
surface->x = x;
|
||||||
surface->y = y;
|
surface->y = y;
|
||||||
@ -2097,7 +2162,8 @@ broadway_server_resync_surfaces (BroadwayServer *server)
|
|||||||
|
|
||||||
if (surface->nodes)
|
if (surface->nodes)
|
||||||
broadway_output_surface_set_nodes (server->output, surface->id,
|
broadway_output_surface_set_nodes (server->output, surface->id,
|
||||||
surface->nodes, NULL);
|
surface->nodes,
|
||||||
|
NULL, NULL);
|
||||||
|
|
||||||
if (surface->visible)
|
if (surface->visible)
|
||||||
broadway_output_show_surface (server->output, surface->id);
|
broadway_output_show_surface (server->output, surface->id);
|
||||||
|
@ -25,10 +25,16 @@ struct _BroadwayNode {
|
|||||||
grefcount refcount;
|
grefcount refcount;
|
||||||
guint32 type;
|
guint32 type;
|
||||||
guint32 id;
|
guint32 id;
|
||||||
|
guint32 output_id;
|
||||||
guint32 hash; /* deep hash */
|
guint32 hash; /* deep hash */
|
||||||
guint32 n_children;
|
guint32 n_children;
|
||||||
BroadwayNode **children;
|
BroadwayNode **children;
|
||||||
guint32 texture_id;
|
guint32 texture_id;
|
||||||
|
|
||||||
|
/* Scratch stuff used during diff */
|
||||||
|
gboolean reused;
|
||||||
|
gboolean consumed;
|
||||||
|
|
||||||
guint32 n_data;
|
guint32 n_data;
|
||||||
guint32 data[1];
|
guint32 data[1];
|
||||||
};
|
};
|
||||||
@ -37,6 +43,12 @@ gboolean broadway_node_equal (BroadwayNode *
|
|||||||
BroadwayNode *b);
|
BroadwayNode *b);
|
||||||
gboolean broadway_node_deep_equal (BroadwayNode *a,
|
gboolean broadway_node_deep_equal (BroadwayNode *a,
|
||||||
BroadwayNode *b);
|
BroadwayNode *b);
|
||||||
|
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,
|
BroadwayServer *broadway_server_new (char *address,
|
||||||
int port,
|
int port,
|
||||||
const char *ssl_cert,
|
const char *ssl_cert,
|
||||||
@ -74,6 +86,7 @@ gint32 broadway_server_get_mouse_surface (BroadwayServer *
|
|||||||
void broadway_server_set_show_keyboard (BroadwayServer *server,
|
void broadway_server_set_show_keyboard (BroadwayServer *server,
|
||||||
gboolean show);
|
gboolean show);
|
||||||
guint32 broadway_server_new_surface (BroadwayServer *server,
|
guint32 broadway_server_new_surface (BroadwayServer *server,
|
||||||
|
guint32 client,
|
||||||
int x,
|
int x,
|
||||||
int y,
|
int y,
|
||||||
int width,
|
int width,
|
||||||
|
@ -11,59 +11,63 @@ const BROADWAY_NODE_LINEAR_GRADIENT = 7;
|
|||||||
const BROADWAY_NODE_SHADOW = 8;
|
const BROADWAY_NODE_SHADOW = 8;
|
||||||
const BROADWAY_NODE_OPACITY = 9;
|
const BROADWAY_NODE_OPACITY = 9;
|
||||||
const BROADWAY_NODE_CLIP = 10;
|
const BROADWAY_NODE_CLIP = 10;
|
||||||
const BROADWAY_NODE_KEEP_ALL = 11;
|
const BROADWAY_NODE_TRANSFORM = 11;
|
||||||
const BROADWAY_NODE_KEEP_THIS = 12;
|
const BROADWAY_NODE_DEBUG = 12;
|
||||||
const BROADWAY_NODE_TRANSFORM = 13;
|
const BROADWAY_NODE_REUSE = 13;
|
||||||
const BROADWAY_NODE_DEBUG = 14;
|
|
||||||
const BROADWAY_NODE_REUSE = 15;
|
|
||||||
|
|
||||||
const BROADWAY_OP_GRAB_POINTER = 'g';
|
const BROADWAY_NODE_OP_INSERT_NODE = 0;
|
||||||
const BROADWAY_OP_UNGRAB_POINTER = 'u';
|
const BROADWAY_NODE_OP_REMOVE_NODE = 1;
|
||||||
const BROADWAY_OP_NEW_SURFACE = 's';
|
const BROADWAY_NODE_OP_MOVE_AFTER_CHILD = 2;
|
||||||
const BROADWAY_OP_SHOW_SURFACE = 'S';
|
const BROADWAY_NODE_OP_PATCH_TEXTURE = 3;
|
||||||
const BROADWAY_OP_HIDE_SURFACE = 'H';
|
const BROADWAY_NODE_OP_PATCH_TRANSFORM = 4;
|
||||||
const BROADWAY_OP_RAISE_SURFACE = 'r';
|
|
||||||
const BROADWAY_OP_LOWER_SURFACE = 'R';
|
|
||||||
const BROADWAY_OP_DESTROY_SURFACE = 'd';
|
|
||||||
const BROADWAY_OP_MOVE_RESIZE = 'm';
|
|
||||||
const BROADWAY_OP_SET_TRANSIENT_FOR = 'p';
|
|
||||||
const BROADWAY_OP_PUT_RGB = 'i';
|
|
||||||
const BROADWAY_OP_REQUEST_AUTH = 'l';
|
|
||||||
const BROADWAY_OP_AUTH_OK = 'L';
|
|
||||||
const BROADWAY_OP_DISCONNECTED = 'D';
|
|
||||||
const BROADWAY_OP_SURFACE_UPDATE = 'b';
|
|
||||||
const BROADWAY_OP_SET_SHOW_KEYBOARD = 'k';
|
|
||||||
const BROADWAY_OP_UPLOAD_TEXTURE = 't';
|
|
||||||
const BROADWAY_OP_RELEASE_TEXTURE = 'T';
|
|
||||||
const BROADWAY_OP_SET_NODES = 'n';
|
|
||||||
const BROADWAY_OP_ROUNDTRIP = 'F';
|
|
||||||
|
|
||||||
const BROADWAY_EVENT_ENTER = 'e';
|
const BROADWAY_OP_GRAB_POINTER = 0;
|
||||||
const BROADWAY_EVENT_LEAVE = 'l';
|
const BROADWAY_OP_UNGRAB_POINTER = 1;
|
||||||
const BROADWAY_EVENT_POINTER_MOVE = 'm';
|
const BROADWAY_OP_NEW_SURFACE = 2;
|
||||||
const BROADWAY_EVENT_BUTTON_PRESS = 'b';
|
const BROADWAY_OP_SHOW_SURFACE = 3;
|
||||||
const BROADWAY_EVENT_BUTTON_RELEASE = 'B';
|
const BROADWAY_OP_HIDE_SURFACE = 4;
|
||||||
const BROADWAY_EVENT_TOUCH = 't';
|
const BROADWAY_OP_RAISE_SURFACE = 5;
|
||||||
const BROADWAY_EVENT_SCROLL = 's';
|
const BROADWAY_OP_LOWER_SURFACE = 6;
|
||||||
const BROADWAY_EVENT_KEY_PRESS = 'k';
|
const BROADWAY_OP_DESTROY_SURFACE = 7;
|
||||||
const BROADWAY_EVENT_KEY_RELEASE = 'K';
|
const BROADWAY_OP_MOVE_RESIZE = 8;
|
||||||
const BROADWAY_EVENT_GRAB_NOTIFY = 'g';
|
const BROADWAY_OP_SET_TRANSIENT_FOR = 9;
|
||||||
const BROADWAY_EVENT_UNGRAB_NOTIFY = 'u';
|
const BROADWAY_OP_DISCONNECTED = 10;
|
||||||
const BROADWAY_EVENT_CONFIGURE_NOTIFY = 'w';
|
const BROADWAY_OP_SURFACE_UPDATE = 11;
|
||||||
const BROADWAY_EVENT_SCREEN_SIZE_CHANGED = 'd';
|
const BROADWAY_OP_SET_SHOW_KEYBOARD = 12;
|
||||||
const BROADWAY_EVENT_FOCUS = 'f';
|
const BROADWAY_OP_UPLOAD_TEXTURE = 13;
|
||||||
const BROADWAY_EVENT_ROUNDTRIP_NOTIFY = 'F';
|
const BROADWAY_OP_RELEASE_TEXTURE = 14;
|
||||||
|
const BROADWAY_OP_SET_NODES = 15;
|
||||||
|
const BROADWAY_OP_ROUNDTRIP = 16;
|
||||||
|
|
||||||
|
const BROADWAY_EVENT_ENTER = 0;
|
||||||
|
const BROADWAY_EVENT_LEAVE = 1;
|
||||||
|
const BROADWAY_EVENT_POINTER_MOVE = 2;
|
||||||
|
const BROADWAY_EVENT_BUTTON_PRESS = 3;
|
||||||
|
const BROADWAY_EVENT_BUTTON_RELEASE = 4;
|
||||||
|
const BROADWAY_EVENT_TOUCH = 5;
|
||||||
|
const BROADWAY_EVENT_SCROLL = 6;
|
||||||
|
const BROADWAY_EVENT_KEY_PRESS = 7;
|
||||||
|
const BROADWAY_EVENT_KEY_RELEASE = 8;
|
||||||
|
const BROADWAY_EVENT_GRAB_NOTIFY = 9;
|
||||||
|
const BROADWAY_EVENT_UNGRAB_NOTIFY = 10;
|
||||||
|
const BROADWAY_EVENT_CONFIGURE_NOTIFY = 11;
|
||||||
|
const BROADWAY_EVENT_SCREEN_SIZE_CHANGED = 12;
|
||||||
|
const BROADWAY_EVENT_FOCUS = 13;
|
||||||
|
const BROADWAY_EVENT_ROUNDTRIP_NOTIFY = 14;
|
||||||
|
|
||||||
const DISPLAY_OP_REPLACE_CHILD = 0;
|
const DISPLAY_OP_REPLACE_CHILD = 0;
|
||||||
const DISPLAY_OP_APPEND_CHILD = 1;
|
const DISPLAY_OP_APPEND_CHILD = 1;
|
||||||
const DISPLAY_OP_APPEND_ROOT = 2;
|
const DISPLAY_OP_INSERT_AFTER_CHILD = 2;
|
||||||
const DISPLAY_OP_SHOW_SURFACE = 3;
|
const DISPLAY_OP_APPEND_ROOT = 3;
|
||||||
const DISPLAY_OP_HIDE_SURFACE = 4;
|
const DISPLAY_OP_SHOW_SURFACE = 4;
|
||||||
const DISPLAY_OP_DELETE_NODE = 5;
|
const DISPLAY_OP_HIDE_SURFACE = 5;
|
||||||
const DISPLAY_OP_MOVE_NODE = 6;
|
const DISPLAY_OP_DELETE_NODE = 6;
|
||||||
const DISPLAY_OP_RESIZE_NODE = 7;
|
const DISPLAY_OP_MOVE_NODE = 7;
|
||||||
const DISPLAY_OP_RESTACK_SURFACES = 8;
|
const DISPLAY_OP_RESIZE_NODE = 8;
|
||||||
const DISPLAY_OP_DELETE_SURFACE = 9;
|
const DISPLAY_OP_RESTACK_SURFACES = 9;
|
||||||
|
const DISPLAY_OP_DELETE_SURFACE = 10;
|
||||||
|
const DISPLAY_OP_CHANGE_TEXTURE = 11;
|
||||||
|
const DISPLAY_OP_CHANGE_TRANSFORM = 12;
|
||||||
|
|
||||||
// GdkCrossingMode
|
// GdkCrossingMode
|
||||||
const GDK_CROSSING_NORMAL = 0;
|
const GDK_CROSSING_NORMAL = 0;
|
||||||
@ -89,6 +93,63 @@ const GDK_HYPER_MASK = 1 << 27;
|
|||||||
const GDK_META_MASK = 1 << 28;
|
const GDK_META_MASK = 1 << 28;
|
||||||
const GDK_RELEASE_MASK = 1 << 30;
|
const GDK_RELEASE_MASK = 1 << 30;
|
||||||
|
|
||||||
|
|
||||||
|
var useDataUrls = window.location.search.includes("datauri");
|
||||||
|
|
||||||
|
/* This base64code is based on https://github.com/beatgammit/base64-js/blob/master/index.js which is MIT licensed */
|
||||||
|
|
||||||
|
var b64_lookup = [];
|
||||||
|
var base64_code = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';
|
||||||
|
for (var i = 0, len = base64_code.length; i < len; ++i) {
|
||||||
|
b64_lookup[i] = base64_code[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
function tripletToBase64 (num) {
|
||||||
|
return b64_lookup[num >> 18 & 0x3F] +
|
||||||
|
b64_lookup[num >> 12 & 0x3F] +
|
||||||
|
b64_lookup[num >> 6 & 0x3F] +
|
||||||
|
b64_lookup[num & 0x3F];
|
||||||
|
}
|
||||||
|
|
||||||
|
function encodeBase64Chunk (uint8, start, end) {
|
||||||
|
var tmp;
|
||||||
|
var output = [];
|
||||||
|
for (var i = start; i < end; i += 3) {
|
||||||
|
tmp =
|
||||||
|
((uint8[i] << 16) & 0xFF0000) +
|
||||||
|
((uint8[i + 1] << 8) & 0xFF00) +
|
||||||
|
(uint8[i + 2] & 0xFF);
|
||||||
|
output.push(tripletToBase64(tmp));
|
||||||
|
}
|
||||||
|
return output.join('');
|
||||||
|
}
|
||||||
|
|
||||||
|
function bytesToDataUri(uint8) {
|
||||||
|
var tmp;
|
||||||
|
var len = uint8.length;
|
||||||
|
var extraBytes = len % 3; // if we have 1 byte left, pad 2 bytes
|
||||||
|
var parts = [];
|
||||||
|
var maxChunkLength = 16383; // must be multiple of 3
|
||||||
|
|
||||||
|
parts.push("data:image/png;base64,");
|
||||||
|
|
||||||
|
// go through the array every three bytes, we'll deal with trailing stuff later
|
||||||
|
for (var i = 0, len2 = len - extraBytes; i < len2; i += maxChunkLength) {
|
||||||
|
parts.push(encodeBase64Chunk(uint8, i, (i + maxChunkLength) > len2 ? len2 : (i + maxChunkLength)));
|
||||||
|
}
|
||||||
|
|
||||||
|
// pad the end with zeros, but make sure to not forget the extra bytes
|
||||||
|
if (extraBytes === 1) {
|
||||||
|
tmp = uint8[len - 1];
|
||||||
|
parts.push(b64_lookup[tmp >> 2] + b64_lookup[(tmp << 4) & 0x3F] + '==');
|
||||||
|
} else if (extraBytes === 2) {
|
||||||
|
tmp = (uint8[len - 2] << 8) + uint8[len - 1];
|
||||||
|
parts.push(b64_lookup[tmp >> 10] + b64_lookup[(tmp >> 4) & 0x3F] + b64_lookup[(tmp << 2) & 0x3F] + '=');
|
||||||
|
}
|
||||||
|
|
||||||
|
return parts.join('');
|
||||||
|
}
|
||||||
|
|
||||||
/* Helper functions for debugging */
|
/* Helper functions for debugging */
|
||||||
var logDiv = null;
|
var logDiv = null;
|
||||||
function log(str) {
|
function log(str) {
|
||||||
@ -198,8 +259,15 @@ function getButtonMask (button) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function Texture(id, data) {
|
function Texture(id, data) {
|
||||||
var blob = new Blob([data],{type: "image/png"});
|
var url;
|
||||||
this.url = window.URL.createObjectURL(blob);
|
if (useDataUrls) {
|
||||||
|
url = bytesToDataUri(data);
|
||||||
|
} else {
|
||||||
|
var blob = new Blob([data],{type: "image/png"});
|
||||||
|
url = window.URL.createObjectURL(blob);
|
||||||
|
}
|
||||||
|
|
||||||
|
this.url = url;
|
||||||
this.refcount = 1;
|
this.refcount = 1;
|
||||||
this.id = id;
|
this.id = id;
|
||||||
|
|
||||||
@ -217,7 +285,9 @@ Texture.prototype.ref = function() {
|
|||||||
Texture.prototype.unref = function() {
|
Texture.prototype.unref = function() {
|
||||||
this.refcount -= 1;
|
this.refcount -= 1;
|
||||||
if (this.refcount == 0) {
|
if (this.refcount == 0) {
|
||||||
window.URL.revokeObjectURL(this.url);
|
if (this.url.startsWith("blob")) {
|
||||||
|
window.URL.revokeObjectURL(this.url);
|
||||||
|
}
|
||||||
delete textures[this.id];
|
delete textures[this.id];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -234,6 +304,7 @@ function cmdCreateSurface(id, x, y, width, height, isTemp)
|
|||||||
surface.transientParent = 0;
|
surface.transientParent = 0;
|
||||||
surface.visible = false;
|
surface.visible = false;
|
||||||
surface.imageData = null;
|
surface.imageData = null;
|
||||||
|
surface.nodes = {};
|
||||||
|
|
||||||
var div = document.createElement('div');
|
var div = document.createElement('div');
|
||||||
div.surface = surface;
|
div.surface = surface;
|
||||||
@ -296,12 +367,13 @@ function cmdLowerSurface(id)
|
|||||||
moveToHelper(surface, 0);
|
moveToHelper(surface, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
function TransformNodes(node_data, div, display_commands) {
|
function TransformNodes(node_data, div, nodes, display_commands) {
|
||||||
this.node_data = node_data;
|
this.node_data = node_data;
|
||||||
this.display_commands = display_commands;
|
this.display_commands = display_commands;
|
||||||
this.data_pos = 0;
|
this.data_pos = 0;
|
||||||
this.div = div;
|
this.div = div;
|
||||||
this.outstanding = 1;
|
this.outstanding = 1;
|
||||||
|
this.nodes = nodes;
|
||||||
}
|
}
|
||||||
|
|
||||||
TransformNodes.prototype.decode_uint32 = function() {
|
TransformNodes.prototype.decode_uint32 = function() {
|
||||||
@ -441,6 +513,28 @@ TransformNodes.prototype.decode_string = function() {
|
|||||||
return utf8_to_string (utf8);
|
return utf8_to_string (utf8);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TransformNodes.prototype.decode_transform = function() {
|
||||||
|
var transform_type = this.decode_uint32();
|
||||||
|
|
||||||
|
if (transform_type == 0) {
|
||||||
|
var point = this.decode_point();
|
||||||
|
return "translate(" + px(point.x) + "," + px(point.y) + ")";
|
||||||
|
} else if (transform_type == 1) {
|
||||||
|
var m = new Array();
|
||||||
|
for (var i = 0; i < 16; i++) {
|
||||||
|
m[i] = this.decode_float ();
|
||||||
|
}
|
||||||
|
|
||||||
|
return "matrix3d(" +
|
||||||
|
m[0] + "," + m[1] + "," + m[2] + "," + m[3]+ "," +
|
||||||
|
m[4] + "," + m[5] + "," + m[6] + "," + m[7] + "," +
|
||||||
|
m[8] + "," + m[9] + "," + m[10] + "," + m[11] + "," +
|
||||||
|
m[12] + "," + m[13] + "," + m[14] + "," + m[15] + ")";
|
||||||
|
} else {
|
||||||
|
alert("Unexpected transform type " + transform_type);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
function args() {
|
function args() {
|
||||||
var argsLength = arguments.length;
|
var argsLength = arguments.length;
|
||||||
var strings = [];
|
var strings = [];
|
||||||
@ -474,27 +568,44 @@ function set_rrect_style (div, rrect) {
|
|||||||
div.style["border-bottom-left-radius"] = args(px(rrect.sizes[3].width), px(rrect.sizes[3].height));
|
div.style["border-bottom-left-radius"] = args(px(rrect.sizes[3].width), px(rrect.sizes[3].height));
|
||||||
}
|
}
|
||||||
|
|
||||||
TransformNodes.prototype.insertNode = function(parent, posInParent, oldNode)
|
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)
|
||||||
{
|
{
|
||||||
var type = this.decode_uint32();
|
var type = this.decode_uint32();
|
||||||
|
var id = this.decode_uint32();
|
||||||
var newNode = null;
|
var newNode = null;
|
||||||
|
var oldNode = 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)
|
switch (type)
|
||||||
{
|
{
|
||||||
|
/* Reuse divs from last frame */
|
||||||
|
case BROADWAY_NODE_REUSE:
|
||||||
|
{
|
||||||
|
oldNode = this.nodes[id];
|
||||||
|
}
|
||||||
|
break;
|
||||||
/* Leaf nodes */
|
/* Leaf nodes */
|
||||||
|
|
||||||
case BROADWAY_NODE_TEXTURE:
|
case BROADWAY_NODE_TEXTURE:
|
||||||
{
|
{
|
||||||
var rect = this.decode_rect();
|
var rect = this.decode_rect();
|
||||||
var texture_id = this.decode_uint32();
|
var texture_id = this.decode_uint32();
|
||||||
var image = new Image();
|
var image = this.createImage(id);
|
||||||
image.width = rect.width;
|
image.width = rect.width;
|
||||||
image.height = rect.height;
|
image.height = rect.height;
|
||||||
image.style["position"] = "absolute";
|
image.style["position"] = "absolute";
|
||||||
@ -511,7 +622,7 @@ TransformNodes.prototype.insertNode = function(parent, posInParent, oldNode)
|
|||||||
{
|
{
|
||||||
var rect = this.decode_rect();
|
var rect = this.decode_rect();
|
||||||
var c = this.decode_color ();
|
var c = this.decode_color ();
|
||||||
var div = document.createElement('div');
|
var div = this.createDiv(id);
|
||||||
div.style["position"] = "absolute";
|
div.style["position"] = "absolute";
|
||||||
set_rect_style(div, rect);
|
set_rect_style(div, rect);
|
||||||
div.style["background-color"] = c;
|
div.style["background-color"] = c;
|
||||||
@ -529,7 +640,7 @@ TransformNodes.prototype.insertNode = function(parent, posInParent, oldNode)
|
|||||||
for (var i = 0; i < 4; i++)
|
for (var i = 0; i < 4; i++)
|
||||||
border_colors[i] = this.decode_color();
|
border_colors[i] = this.decode_color();
|
||||||
|
|
||||||
var div = document.createElement('div');
|
var div = this.createDiv(id);
|
||||||
div.style["position"] = "absolute";
|
div.style["position"] = "absolute";
|
||||||
rrect.bounds.width -= border_widths[1] + border_widths[3];
|
rrect.bounds.width -= border_widths[1] + border_widths[3];
|
||||||
rrect.bounds.height -= border_widths[0] + border_widths[2];
|
rrect.bounds.height -= border_widths[0] + border_widths[2];
|
||||||
@ -556,7 +667,7 @@ TransformNodes.prototype.insertNode = function(parent, posInParent, oldNode)
|
|||||||
var spread = this.decode_float();
|
var spread = this.decode_float();
|
||||||
var blur = this.decode_float();
|
var blur = this.decode_float();
|
||||||
|
|
||||||
var div = document.createElement('div');
|
var div = this.createDiv(id);
|
||||||
div.style["position"] = "absolute";
|
div.style["position"] = "absolute";
|
||||||
set_rrect_style(div, rrect);
|
set_rrect_style(div, rrect);
|
||||||
div.style["box-shadow"] = args(px(dx), px(dy), px(blur), px(spread), color);
|
div.style["box-shadow"] = args(px(dx), px(dy), px(blur), px(spread), color);
|
||||||
@ -573,7 +684,7 @@ TransformNodes.prototype.insertNode = function(parent, posInParent, oldNode)
|
|||||||
var spread = this.decode_float();
|
var spread = this.decode_float();
|
||||||
var blur = this.decode_float();
|
var blur = this.decode_float();
|
||||||
|
|
||||||
var div = document.createElement('div');
|
var div = this.createDiv(id);
|
||||||
div.style["position"] = "absolute";
|
div.style["position"] = "absolute";
|
||||||
set_rrect_style(div, rrect);
|
set_rrect_style(div, rrect);
|
||||||
div.style["box-shadow"] = args("inset", px(dx), px(dy), px(blur), px(spread), color);
|
div.style["box-shadow"] = args("inset", px(dx), px(dy), px(blur), px(spread), color);
|
||||||
@ -588,7 +699,7 @@ TransformNodes.prototype.insertNode = function(parent, posInParent, oldNode)
|
|||||||
var start = this.decode_point ();
|
var start = this.decode_point ();
|
||||||
var end = this.decode_point ();
|
var end = this.decode_point ();
|
||||||
var stops = this.decode_color_stops ();
|
var stops = this.decode_color_stops ();
|
||||||
var div = document.createElement('div');
|
var div = this.createDiv(id);
|
||||||
div.style["position"] = "absolute";
|
div.style["position"] = "absolute";
|
||||||
set_rect_style(div, rect);
|
set_rect_style(div, rect);
|
||||||
|
|
||||||
@ -632,31 +743,13 @@ TransformNodes.prototype.insertNode = function(parent, posInParent, oldNode)
|
|||||||
|
|
||||||
case BROADWAY_NODE_TRANSFORM:
|
case BROADWAY_NODE_TRANSFORM:
|
||||||
{
|
{
|
||||||
var transform_type = this.decode_uint32();
|
var transform_string = this.decode_transform();
|
||||||
var transform_string;
|
|
||||||
|
|
||||||
if (transform_type == 0) {
|
var div = this.createDiv(id);
|
||||||
var point = this.decode_point();
|
|
||||||
transform_string = "translate(" + px(point.x) + "," + px(point.y) + ")";
|
|
||||||
} else if (transform_type == 1) {
|
|
||||||
var m = new Array();
|
|
||||||
for (var i = 0; i < 16; i++) {
|
|
||||||
m[i] = this.decode_float ();
|
|
||||||
}
|
|
||||||
|
|
||||||
transform_string =
|
|
||||||
"matrix3d(" +
|
|
||||||
m[0] + "," + m[1] + "," + m[2] + "," + m[3]+ "," +
|
|
||||||
m[4] + "," + m[5] + "," + m[6] + "," + m[7] + "," +
|
|
||||||
m[8] + "," + m[9] + "," + m[10] + "," + m[11] + "," +
|
|
||||||
m[12] + "," + m[13] + "," + m[14] + "," + m[15] + ")";
|
|
||||||
}
|
|
||||||
|
|
||||||
var div = document.createElement('div');
|
|
||||||
div.style["transform"] = transform_string;
|
div.style["transform"] = transform_string;
|
||||||
div.style["transform-origin"] = "0px 0px";
|
div.style["transform-origin"] = "0px 0px";
|
||||||
|
|
||||||
this.insertNode(div, -1, oldChildren[0]);
|
this.insertNode(div, null, false);
|
||||||
newNode = div;
|
newNode = div;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@ -664,11 +757,11 @@ TransformNodes.prototype.insertNode = function(parent, posInParent, oldNode)
|
|||||||
case BROADWAY_NODE_CLIP:
|
case BROADWAY_NODE_CLIP:
|
||||||
{
|
{
|
||||||
var rect = this.decode_rect();
|
var rect = this.decode_rect();
|
||||||
var div = document.createElement('div');
|
var div = this.createDiv(id);
|
||||||
div.style["position"] = "absolute";
|
div.style["position"] = "absolute";
|
||||||
set_rect_style(div, rect);
|
set_rect_style(div, rect);
|
||||||
div.style["overflow"] = "hidden";
|
div.style["overflow"] = "hidden";
|
||||||
this.insertNode(div, -1, oldChildren[0]);
|
this.insertNode(div, null, false);
|
||||||
newNode = div;
|
newNode = div;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@ -676,11 +769,11 @@ TransformNodes.prototype.insertNode = function(parent, posInParent, oldNode)
|
|||||||
case BROADWAY_NODE_ROUNDED_CLIP:
|
case BROADWAY_NODE_ROUNDED_CLIP:
|
||||||
{
|
{
|
||||||
var rrect = this.decode_rounded_rect();
|
var rrect = this.decode_rounded_rect();
|
||||||
var div = document.createElement('div');
|
var div = this.createDiv(id);
|
||||||
div.style["position"] = "absolute";
|
div.style["position"] = "absolute";
|
||||||
set_rrect_style(div, rrect);
|
set_rrect_style(div, rrect);
|
||||||
div.style["overflow"] = "hidden";
|
div.style["overflow"] = "hidden";
|
||||||
this.insertNode(div, -1, oldChildren[0]);
|
this.insertNode(div, null, false);
|
||||||
newNode = div;
|
newNode = div;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@ -688,13 +781,13 @@ TransformNodes.prototype.insertNode = function(parent, posInParent, oldNode)
|
|||||||
case BROADWAY_NODE_OPACITY:
|
case BROADWAY_NODE_OPACITY:
|
||||||
{
|
{
|
||||||
var opacity = this.decode_float();
|
var opacity = this.decode_float();
|
||||||
var div = document.createElement('div');
|
var div = this.createDiv(id);
|
||||||
div.style["position"] = "absolute";
|
div.style["position"] = "absolute";
|
||||||
div.style["left"] = px(0);
|
div.style["left"] = px(0);
|
||||||
div.style["top"] = px(0);
|
div.style["top"] = px(0);
|
||||||
div.style["opacity"] = opacity;
|
div.style["opacity"] = opacity;
|
||||||
|
|
||||||
this.insertNode(div, -1, oldChildren[0]);
|
this.insertNode(div, null, false);
|
||||||
newNode = div;
|
newNode = div;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@ -710,13 +803,13 @@ TransformNodes.prototype.insertNode = function(parent, posInParent, oldNode)
|
|||||||
var blur = this.decode_float();
|
var blur = this.decode_float();
|
||||||
filters = filters + "drop-shadow(" + args (px(dx), px(dy), px(blur), color) + ")";
|
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["position"] = "absolute";
|
||||||
div.style["left"] = px(0);
|
div.style["left"] = px(0);
|
||||||
div.style["top"] = px(0);
|
div.style["top"] = px(0);
|
||||||
div.style["filter"] = filters;
|
div.style["filter"] = filters;
|
||||||
|
|
||||||
this.insertNode(div, -1, oldChildren[0]);
|
this.insertNode(div, null, false);
|
||||||
newNode = div;
|
newNode = div;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@ -724,9 +817,9 @@ TransformNodes.prototype.insertNode = function(parent, posInParent, oldNode)
|
|||||||
case 14: // DEBUG
|
case 14: // DEBUG
|
||||||
{
|
{
|
||||||
var str = this.decode_string();
|
var str = this.decode_string();
|
||||||
var div = document.createElement('div');
|
var div = this.createDiv(id);
|
||||||
div.setAttribute('debug', str);
|
div.setAttribute('debug', str);
|
||||||
this.insertNode(div, -1, oldChildren[0]);
|
this.insertNode(div, null, false);
|
||||||
newNode = div;
|
newNode = div;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@ -735,73 +828,98 @@ TransformNodes.prototype.insertNode = function(parent, posInParent, oldNode)
|
|||||||
|
|
||||||
case BROADWAY_NODE_CONTAINER:
|
case BROADWAY_NODE_CONTAINER:
|
||||||
{
|
{
|
||||||
var div = document.createElement('div');
|
var div = this.createDiv(id);
|
||||||
var len = this.decode_uint32();
|
var len = this.decode_uint32();
|
||||||
|
var lastChild = null;
|
||||||
for (var i = 0; i < len; i++) {
|
for (var i = 0; i < len; i++) {
|
||||||
this.insertNode(div, -1, oldChildren[i]);
|
lastChild = this.insertNode(div, lastChild, false);
|
||||||
}
|
}
|
||||||
newNode = div;
|
newNode = div;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case BROADWAY_NODE_KEEP_ALL:
|
|
||||||
{
|
|
||||||
if (!oldNode)
|
|
||||||
alert("KEEP_ALL with no oldNode");
|
|
||||||
|
|
||||||
if (oldNode.parentNode != parent)
|
|
||||||
newNode = oldNode;
|
|
||||||
else
|
|
||||||
newNode = null;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case BROADWAY_NODE_KEEP_THIS:
|
|
||||||
{
|
|
||||||
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--)
|
|
||||||
this.display_commands.push([DISPLAY_OP_DELETE_NODE, oldChildren[i]]);
|
|
||||||
|
|
||||||
/* NOTE: No need to modify the parent, we're keeping this node as is */
|
|
||||||
newNode = null;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
default:
|
||||||
alert("Unexpected node type " + type);
|
alert("Unexpected node type " + type);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (newNode) {
|
if (newNode) {
|
||||||
if (posInParent >= 0 && parent.children[posInParent])
|
if (is_toplevel)
|
||||||
this.display_commands.push([DISPLAY_OP_REPLACE_CHILD, parent, newNode, parent.children[posInParent]]);
|
this.display_commands.push([DISPLAY_OP_INSERT_AFTER_CHILD, parent, previousSibling, newNode]);
|
||||||
else
|
else // It is safe to display directly because we have not added the toplevel to the document yet
|
||||||
this.display_commands.push([DISPLAY_OP_APPEND_CHILD, parent, newNode]);
|
parent.appendChild(newNode);
|
||||||
|
return newNode;
|
||||||
|
} else if (oldNode) {
|
||||||
|
// 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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
TransformNodes.prototype.execute = function(display_commands)
|
TransformNodes.prototype.execute = function(display_commands)
|
||||||
{
|
{
|
||||||
var div = this.div;
|
var root = this.div;
|
||||||
this.insertNode(div, 0, div.firstChild, display_commands);
|
|
||||||
if (this.data_pos != this.node_data.byteLength)
|
|
||||||
alert ("Did not consume entire array (len " + this.node_data.byteLength + ")");
|
|
||||||
}
|
|
||||||
|
|
||||||
|
while (this.data_pos < this.node_data.byteLength) {
|
||||||
|
var op = this.decode_uint32();
|
||||||
|
var parentId, parent;
|
||||||
|
|
||||||
|
switch (op) {
|
||||||
|
case BROADWAY_NODE_OP_INSERT_NODE:
|
||||||
|
parentId = this.decode_uint32();
|
||||||
|
if (parentId == 0)
|
||||||
|
parent = root;
|
||||||
|
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.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;
|
||||||
|
case BROADWAY_NODE_OP_PATCH_TEXTURE:
|
||||||
|
var textureNodeId = this.decode_uint32();
|
||||||
|
var textureNode = this.nodes[textureNodeId];
|
||||||
|
var textureId = this.decode_uint32();
|
||||||
|
var texture = textures[textureId].ref();
|
||||||
|
this.display_commands.push([DISPLAY_OP_CHANGE_TEXTURE, textureNode, texture]);
|
||||||
|
break;
|
||||||
|
case BROADWAY_NODE_OP_PATCH_TRANSFORM:
|
||||||
|
var transformNodeId = this.decode_uint32();
|
||||||
|
var transformNode = this.nodes[transformNodeId];
|
||||||
|
var transformString = this.decode_transform();
|
||||||
|
this.display_commands.push([DISPLAY_OP_CHANGE_TRANSFORM, transformNode, transformString]);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
function cmdGrabPointer(id, ownerEvents)
|
function cmdGrabPointer(id, ownerEvents)
|
||||||
{
|
{
|
||||||
@ -818,7 +936,7 @@ function cmdUngrabPointer()
|
|||||||
|
|
||||||
function handleDisplayCommands(display_commands)
|
function handleDisplayCommands(display_commands)
|
||||||
{
|
{
|
||||||
var div;
|
var div, parent;
|
||||||
var len = display_commands.length;
|
var len = display_commands.length;
|
||||||
for (var i = 0; i < len; i++) {
|
for (var i = 0; i < len; i++) {
|
||||||
var cmd = display_commands[i];
|
var cmd = display_commands[i];
|
||||||
@ -830,6 +948,15 @@ function handleDisplayCommands(display_commands)
|
|||||||
case DISPLAY_OP_APPEND_CHILD:
|
case DISPLAY_OP_APPEND_CHILD:
|
||||||
cmd[1].appendChild(cmd[2]);
|
cmd[1].appendChild(cmd[2]);
|
||||||
break;
|
break;
|
||||||
|
case DISPLAY_OP_INSERT_AFTER_CHILD:
|
||||||
|
parent = cmd[1];
|
||||||
|
var afterThis = cmd[2];
|
||||||
|
div = cmd[3];
|
||||||
|
if (afterThis == null) // First
|
||||||
|
parent.insertBefore(div, parent.firstChild);
|
||||||
|
else
|
||||||
|
parent.insertBefore(div, afterThis.nextSibling);
|
||||||
|
break;
|
||||||
case DISPLAY_OP_APPEND_ROOT:
|
case DISPLAY_OP_APPEND_ROOT:
|
||||||
document.body.appendChild(cmd[1]);
|
document.body.appendChild(cmd[1]);
|
||||||
break;
|
break;
|
||||||
@ -867,7 +994,21 @@ function handleDisplayCommands(display_commands)
|
|||||||
var id = cmd[1];
|
var id = cmd[1];
|
||||||
delete surfaces[id];
|
delete surfaces[id];
|
||||||
break;
|
break;
|
||||||
|
case DISPLAY_OP_CHANGE_TEXTURE:
|
||||||
|
var image = cmd[1];
|
||||||
|
var texture = cmd[2];
|
||||||
|
// We need a new closure here to have a separate copy of "template" for each iteration...
|
||||||
|
function a_block(t) {
|
||||||
|
image.src = t.url;
|
||||||
|
// Unref blob url when loaded
|
||||||
|
image.onload = function() { t.unref(); };
|
||||||
|
}(texture);
|
||||||
|
break;
|
||||||
|
case DISPLAY_OP_CHANGE_TRANSFORM:
|
||||||
|
var div = cmd[1];
|
||||||
|
var transform_string = cmd[2];
|
||||||
|
div.style["transform"] = transform_string;
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
alert("Unknown display op " + command);
|
alert("Unknown display op " + command);
|
||||||
}
|
}
|
||||||
@ -882,7 +1023,7 @@ function handleCommands(cmd, display_commands, new_textures, modified_trees)
|
|||||||
while (res && cmd.pos < cmd.length) {
|
while (res && cmd.pos < cmd.length) {
|
||||||
var id, x, y, w, h, q, surface;
|
var id, x, y, w, h, q, surface;
|
||||||
var saved_pos = cmd.pos;
|
var saved_pos = cmd.pos;
|
||||||
var command = cmd.get_char();
|
var command = cmd.get_uint8();
|
||||||
lastSerial = cmd.get_32();
|
lastSerial = cmd.get_32();
|
||||||
switch (command) {
|
switch (command) {
|
||||||
case BROADWAY_OP_DISCONNECTED:
|
case BROADWAY_OP_DISCONNECTED:
|
||||||
@ -976,6 +1117,7 @@ function handleCommands(cmd, display_commands, new_textures, modified_trees)
|
|||||||
display_commands.push([DISPLAY_OP_RESIZE_NODE, surface.div, surface.width, surface.height]);
|
display_commands.push([DISPLAY_OP_RESIZE_NODE, surface.div, surface.width, surface.height]);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
sendConfigureNotify(surface);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case BROADWAY_OP_RAISE_SURFACE:
|
case BROADWAY_OP_RAISE_SURFACE:
|
||||||
@ -1013,7 +1155,7 @@ function handleCommands(cmd, display_commands, new_textures, modified_trees)
|
|||||||
|
|
||||||
var node_data = cmd.get_nodes ();
|
var node_data = cmd.get_nodes ();
|
||||||
surface = surfaces[id];
|
surface = surfaces[id];
|
||||||
var transform_nodes = new TransformNodes (node_data, surface.div, display_commands);
|
var transform_nodes = new TransformNodes (node_data, surface.div, surface.nodes, display_commands);
|
||||||
transform_nodes.execute();
|
transform_nodes.execute();
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@ -1117,8 +1259,8 @@ function BinCommands(message) {
|
|||||||
this.pos = 0;
|
this.pos = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
BinCommands.prototype.get_char = function() {
|
BinCommands.prototype.get_uint8 = function() {
|
||||||
return String.fromCharCode(this.dataview.getUint8(this.pos++));
|
return this.dataview.getUint8(this.pos++);
|
||||||
};
|
};
|
||||||
BinCommands.prototype.get_bool = function() {
|
BinCommands.prototype.get_bool = function() {
|
||||||
return this.dataview.getUint8(this.pos++) != 0;
|
return this.dataview.getUint8(this.pos++) != 0;
|
||||||
@ -1185,7 +1327,7 @@ function sendInput(cmd, args)
|
|||||||
if (inputSocket == null)
|
if (inputSocket == null)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
var fullArgs = [cmd.charCodeAt(0), lastSerial, lastTimeStamp].concat(args);
|
var fullArgs = [cmd, lastSerial, lastTimeStamp].concat(args);
|
||||||
var buffer = new ArrayBuffer(fullArgs.length * 4);
|
var buffer = new ArrayBuffer(fullArgs.length * 4);
|
||||||
var view = new DataView(buffer);
|
var view = new DataView(buffer);
|
||||||
fullArgs.forEach(function(arg, i) {
|
fullArgs.forEach(function(arg, i) {
|
||||||
|
@ -234,7 +234,7 @@ client_handle_request (BroadwayClient *client,
|
|||||||
{
|
{
|
||||||
case BROADWAY_REQUEST_NEW_SURFACE:
|
case BROADWAY_REQUEST_NEW_SURFACE:
|
||||||
reply_new_surface.id =
|
reply_new_surface.id =
|
||||||
broadway_server_new_surface (server,
|
broadway_server_new_surface (server, client->id,
|
||||||
request->new_surface.x,
|
request->new_surface.x,
|
||||||
request->new_surface.y,
|
request->new_surface.y,
|
||||||
request->new_surface.width,
|
request->new_surface.width,
|
||||||
|
@ -38,6 +38,7 @@ typedef struct BroadwayInput BroadwayInput;
|
|||||||
|
|
||||||
struct _GdkBroadwayServer {
|
struct _GdkBroadwayServer {
|
||||||
GObject parent_instance;
|
GObject parent_instance;
|
||||||
|
GdkDisplay *display;
|
||||||
|
|
||||||
guint32 next_serial;
|
guint32 next_serial;
|
||||||
guint32 next_texture_id;
|
guint32 next_texture_id;
|
||||||
@ -96,7 +97,9 @@ _gdk_broadway_server_get_next_serial (GdkBroadwayServer *server)
|
|||||||
}
|
}
|
||||||
|
|
||||||
GdkBroadwayServer *
|
GdkBroadwayServer *
|
||||||
_gdk_broadway_server_new (const char *display, GError **error)
|
_gdk_broadway_server_new (GdkDisplay *display,
|
||||||
|
const char *display_name,
|
||||||
|
GError **error)
|
||||||
{
|
{
|
||||||
GdkBroadwayServer *server;
|
GdkBroadwayServer *server;
|
||||||
GSocketClient *client;
|
GSocketClient *client;
|
||||||
@ -108,14 +111,14 @@ _gdk_broadway_server_new (const char *display, GError **error)
|
|||||||
char *local_socket_type = NULL;
|
char *local_socket_type = NULL;
|
||||||
int port;
|
int port;
|
||||||
|
|
||||||
if (display == NULL)
|
if (display_name == NULL)
|
||||||
display = ":0";
|
display_name = ":0";
|
||||||
|
|
||||||
if (display[0] == ':' && g_ascii_isdigit(display[1]))
|
if (display_name[0] == ':' && g_ascii_isdigit(display_name[1]))
|
||||||
{
|
{
|
||||||
char *path, *basename;
|
char *path, *basename;
|
||||||
|
|
||||||
port = strtol (display + strlen (":"), NULL, 10);
|
port = strtol (display_name + strlen (":"), NULL, 10);
|
||||||
basename = g_strdup_printf ("broadway%d.socket", port + 1);
|
basename = g_strdup_printf ("broadway%d.socket", port + 1);
|
||||||
path = g_build_filename (g_get_user_runtime_dir (), basename, NULL);
|
path = g_build_filename (g_get_user_runtime_dir (), basename, NULL);
|
||||||
g_free (basename);
|
g_free (basename);
|
||||||
@ -127,7 +130,7 @@ _gdk_broadway_server_new (const char *display, GError **error)
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
g_set_error (error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED,
|
g_set_error (error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED,
|
||||||
_("Broadway display type not supported: %s"), display);
|
_("Broadway display type not supported: %s"), display_name);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -145,6 +148,7 @@ _gdk_broadway_server_new (const char *display, GError **error)
|
|||||||
|
|
||||||
server = g_object_new (GDK_TYPE_BROADWAY_SERVER, NULL);
|
server = g_object_new (GDK_TYPE_BROADWAY_SERVER, NULL);
|
||||||
server->connection = connection;
|
server->connection = connection;
|
||||||
|
server->display = display;
|
||||||
|
|
||||||
in = g_io_stream_get_input_stream (G_IO_STREAM (server->connection));
|
in = g_io_stream_get_input_stream (G_IO_STREAM (server->connection));
|
||||||
pollable = G_POLLABLE_INPUT_STREAM (in);
|
pollable = G_POLLABLE_INPUT_STREAM (in);
|
||||||
@ -346,7 +350,7 @@ process_input_messages (GdkBroadwayServer *server)
|
|||||||
server->incomming);
|
server->incomming);
|
||||||
|
|
||||||
if (reply->base.type == BROADWAY_REPLY_EVENT)
|
if (reply->base.type == BROADWAY_REPLY_EVENT)
|
||||||
_gdk_broadway_events_got_input (&reply->event.msg);
|
_gdk_broadway_events_got_input (server->display, &reply->event.msg);
|
||||||
else
|
else
|
||||||
g_warning ("Unhandled reply type %d", reply->base.type);
|
g_warning ("Unhandled reply type %d", reply->base.type);
|
||||||
g_free (reply);
|
g_free (reply);
|
||||||
|
@ -14,7 +14,8 @@ typedef struct _GdkBroadwayServerClass GdkBroadwayServerClass;
|
|||||||
#define GDK_IS_BROADWAY_SERVER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GDK_TYPE_BROADWAY_SERVER))
|
#define GDK_IS_BROADWAY_SERVER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GDK_TYPE_BROADWAY_SERVER))
|
||||||
#define GDK_BROADWAY_SERVER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GDK_TYPE_BROADWAY_SERVER, GdkBroadwayServerClass))
|
#define GDK_BROADWAY_SERVER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GDK_TYPE_BROADWAY_SERVER, GdkBroadwayServerClass))
|
||||||
|
|
||||||
GdkBroadwayServer *_gdk_broadway_server_new (const char *display,
|
GdkBroadwayServer *_gdk_broadway_server_new (GdkDisplay *display,
|
||||||
|
const char *display_name,
|
||||||
GError **error);
|
GError **error);
|
||||||
void _gdk_broadway_server_flush (GdkBroadwayServer *server);
|
void _gdk_broadway_server_flush (GdkBroadwayServer *server);
|
||||||
void _gdk_broadway_server_sync (GdkBroadwayServer *server);
|
void _gdk_broadway_server_sync (GdkBroadwayServer *server);
|
||||||
|
@ -174,7 +174,7 @@ _gdk_broadway_display_open (const gchar *display_name)
|
|||||||
if (display_name == NULL)
|
if (display_name == NULL)
|
||||||
display_name = g_getenv ("BROADWAY_DISPLAY");
|
display_name = g_getenv ("BROADWAY_DISPLAY");
|
||||||
|
|
||||||
broadway_display->server = _gdk_broadway_server_new (display_name, &error);
|
broadway_display->server = _gdk_broadway_server_new (display, display_name, &error);
|
||||||
if (broadway_display->server == NULL)
|
if (broadway_display->server == NULL)
|
||||||
{
|
{
|
||||||
g_printerr ("Unable to init Broadway server: %s\n", error->message);
|
g_printerr ("Unable to init Broadway server: %s\n", error->message);
|
||||||
@ -386,6 +386,31 @@ gdk_broadway_display_ensure_texture (GdkDisplay *display,
|
|||||||
return data->id;
|
return data->id;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
flush_idle (gpointer data)
|
||||||
|
{
|
||||||
|
GdkDisplay *display = data;
|
||||||
|
GdkBroadwayDisplay *broadway_display = GDK_BROADWAY_DISPLAY (display);
|
||||||
|
|
||||||
|
broadway_display->idle_flush_id = 0;
|
||||||
|
gdk_display_flush (display);
|
||||||
|
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
gdk_broadway_display_flush_in_idle (GdkDisplay *display)
|
||||||
|
{
|
||||||
|
GdkBroadwayDisplay *broadway_display = GDK_BROADWAY_DISPLAY (display);
|
||||||
|
|
||||||
|
if (broadway_display->idle_flush_id == 0)
|
||||||
|
{
|
||||||
|
broadway_display->idle_flush_id = g_idle_add (flush_idle, g_object_ref (display));
|
||||||
|
g_source_set_name_by_id (broadway_display->idle_flush_id, "[gtk] flush_idle");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
gdk_broadway_display_class_init (GdkBroadwayDisplayClass * class)
|
gdk_broadway_display_class_init (GdkBroadwayDisplayClass * class)
|
||||||
{
|
{
|
||||||
|
@ -56,6 +56,8 @@ struct _GdkBroadwayDisplay
|
|||||||
GdkMonitor *monitor;
|
GdkMonitor *monitor;
|
||||||
|
|
||||||
GHashTable *texture_cache;
|
GHashTable *texture_cache;
|
||||||
|
|
||||||
|
guint idle_flush_id;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct _GdkBroadwayDisplayClass
|
struct _GdkBroadwayDisplayClass
|
||||||
|
@ -83,30 +83,14 @@ gdk_event_source_check (GSource *source)
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
_gdk_broadway_events_got_input (BroadwayInputMsg *message)
|
_gdk_broadway_events_got_input (GdkDisplay *display,
|
||||||
|
BroadwayInputMsg *message)
|
||||||
{
|
{
|
||||||
GdkDisplay *display;
|
|
||||||
GdkBroadwayDisplay *display_broadway;
|
GdkBroadwayDisplay *display_broadway;
|
||||||
GdkSeat *seat;
|
GdkSeat *seat;
|
||||||
GdkSurface *surface;
|
GdkSurface *surface;
|
||||||
GdkEvent *event = NULL;
|
GdkEvent *event = NULL;
|
||||||
GList *node;
|
GList *node;
|
||||||
GSList *list, *d;
|
|
||||||
|
|
||||||
display = NULL;
|
|
||||||
|
|
||||||
list = gdk_display_manager_list_displays (gdk_display_manager_get ());
|
|
||||||
for (d = list; d; d = d->next)
|
|
||||||
{
|
|
||||||
if (GDK_IS_BROADWAY_DISPLAY (d->data))
|
|
||||||
{
|
|
||||||
display = d->data;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
g_slist_free (list);
|
|
||||||
|
|
||||||
g_assert (display != NULL);
|
|
||||||
|
|
||||||
display_broadway = GDK_BROADWAY_DISPLAY (display);
|
display_broadway = GDK_BROADWAY_DISPLAY (display);
|
||||||
seat = gdk_display_get_default_seat (display);
|
seat = gdk_display_get_default_seat (display);
|
||||||
@ -176,14 +160,14 @@ _gdk_broadway_events_got_input (BroadwayInputMsg *message)
|
|||||||
break;
|
break;
|
||||||
case BROADWAY_EVENT_BUTTON_PRESS:
|
case BROADWAY_EVENT_BUTTON_PRESS:
|
||||||
case BROADWAY_EVENT_BUTTON_RELEASE:
|
case BROADWAY_EVENT_BUTTON_RELEASE:
|
||||||
if (message->base.type != 'b' &&
|
if (message->base.type != BROADWAY_EVENT_BUTTON_PRESS &&
|
||||||
_gdk_broadway_moveresize_handle_event (display, message))
|
_gdk_broadway_moveresize_handle_event (display, message))
|
||||||
break;
|
break;
|
||||||
|
|
||||||
surface = g_hash_table_lookup (display_broadway->id_ht, GINT_TO_POINTER (message->pointer.event_surface_id));
|
surface = g_hash_table_lookup (display_broadway->id_ht, GINT_TO_POINTER (message->pointer.event_surface_id));
|
||||||
if (surface)
|
if (surface)
|
||||||
{
|
{
|
||||||
event = gdk_event_new (message->base.type == 'b' ? GDK_BUTTON_PRESS : GDK_BUTTON_RELEASE);
|
event = gdk_event_new (message->base.type == BROADWAY_EVENT_BUTTON_PRESS ? GDK_BUTTON_PRESS : GDK_BUTTON_RELEASE);
|
||||||
event->any.surface = g_object_ref (surface);
|
event->any.surface = g_object_ref (surface);
|
||||||
event->button.time = message->base.time;
|
event->button.time = message->base.time;
|
||||||
event->button.x = message->pointer.win_x;
|
event->button.x = message->pointer.win_x;
|
||||||
@ -278,7 +262,7 @@ _gdk_broadway_events_got_input (BroadwayInputMsg *message)
|
|||||||
GINT_TO_POINTER (message->key.surface_id));
|
GINT_TO_POINTER (message->key.surface_id));
|
||||||
if (surface)
|
if (surface)
|
||||||
{
|
{
|
||||||
event = gdk_event_new (message->base.type == 'k' ? GDK_KEY_PRESS : GDK_KEY_RELEASE);
|
event = gdk_event_new (message->base.type == BROADWAY_EVENT_KEY_PRESS ? GDK_KEY_PRESS : GDK_KEY_RELEASE);
|
||||||
event->any.surface = g_object_ref (surface);
|
event->any.surface = g_object_ref (surface);
|
||||||
event->key.time = message->base.time;
|
event->key.time = message->base.time;
|
||||||
event->key.keyval = message->key.key;
|
event->key.keyval = message->key.key;
|
||||||
|
@ -41,6 +41,8 @@
|
|||||||
guint32 gdk_broadway_display_ensure_texture (GdkDisplay *display,
|
guint32 gdk_broadway_display_ensure_texture (GdkDisplay *display,
|
||||||
GdkTexture *texture);
|
GdkTexture *texture);
|
||||||
|
|
||||||
|
void gdk_broadway_display_flush_in_idle (GdkDisplay *display);
|
||||||
|
|
||||||
void gdk_broadway_surface_set_nodes (GdkSurface *surface,
|
void gdk_broadway_surface_set_nodes (GdkSurface *surface,
|
||||||
GArray *nodes,
|
GArray *nodes,
|
||||||
GPtrArray *node_textures);
|
GPtrArray *node_textures);
|
||||||
@ -78,7 +80,8 @@ gboolean _gdk_keymap_key_is_modifier (GdkKeymap *keymap,
|
|||||||
void _gdk_broadway_display_size_changed (GdkDisplay *display,
|
void _gdk_broadway_display_size_changed (GdkDisplay *display,
|
||||||
BroadwayInputScreenResizeNotify *msg);
|
BroadwayInputScreenResizeNotify *msg);
|
||||||
|
|
||||||
void _gdk_broadway_events_got_input (BroadwayInputMsg *message);
|
void _gdk_broadway_events_got_input (GdkDisplay *display,
|
||||||
|
BroadwayInputMsg *message);
|
||||||
|
|
||||||
void _gdk_broadway_display_init_root_window (GdkDisplay *display);
|
void _gdk_broadway_display_init_root_window (GdkDisplay *display);
|
||||||
void _gdk_broadway_display_init_dnd (GdkDisplay *display);
|
void _gdk_broadway_display_init_dnd (GdkDisplay *display);
|
||||||
|
@ -73,39 +73,6 @@ G_DEFINE_TYPE (GdkSurfaceImplBroadway,
|
|||||||
gdk_surface_impl_broadway,
|
gdk_surface_impl_broadway,
|
||||||
GDK_TYPE_SURFACE_IMPL)
|
GDK_TYPE_SURFACE_IMPL)
|
||||||
|
|
||||||
static GdkDisplay *
|
|
||||||
find_broadway_display (void)
|
|
||||||
{
|
|
||||||
GdkDisplay *display;
|
|
||||||
GSList *list, *l;
|
|
||||||
|
|
||||||
display = NULL;
|
|
||||||
|
|
||||||
list = gdk_display_manager_list_displays (gdk_display_manager_get ());
|
|
||||||
for (l = list; l; l = l->next)
|
|
||||||
{
|
|
||||||
if (GDK_IS_BROADWAY_DISPLAY (l->data))
|
|
||||||
{
|
|
||||||
display = l->data;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
g_slist_free (list);
|
|
||||||
|
|
||||||
return display;
|
|
||||||
}
|
|
||||||
|
|
||||||
static guint flush_id = 0;
|
|
||||||
|
|
||||||
static gboolean
|
|
||||||
flush_idle (gpointer data)
|
|
||||||
{
|
|
||||||
flush_id = 0;
|
|
||||||
|
|
||||||
gdk_display_flush (find_broadway_display ());
|
|
||||||
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* We need to flush in an idle rather than AFTER_PAINT, as the clock
|
/* We need to flush in an idle rather than AFTER_PAINT, as the clock
|
||||||
is frozen during e.g. surface resizes so the paint will not happen
|
is frozen during e.g. surface resizes so the paint will not happen
|
||||||
@ -113,11 +80,7 @@ flush_idle (gpointer data)
|
|||||||
static void
|
static void
|
||||||
queue_flush (GdkSurface *surface)
|
queue_flush (GdkSurface *surface)
|
||||||
{
|
{
|
||||||
if (flush_id == 0)
|
gdk_broadway_display_flush_in_idle (gdk_surface_get_display (surface));
|
||||||
{
|
|
||||||
flush_id = g_idle_add (flush_idle, NULL);
|
|
||||||
g_source_set_name_by_id (flush_id, "[gtk] flush_idle");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@ -165,13 +128,32 @@ _gdk_broadway_roundtrip_notify (GdkSurface *surface,
|
|||||||
guint32 tag,
|
guint32 tag,
|
||||||
gboolean local_reply)
|
gboolean local_reply)
|
||||||
{
|
{
|
||||||
|
GdkSurfaceImplBroadway *impl = GDK_SURFACE_IMPL_BROADWAY (surface->impl);
|
||||||
GdkFrameClock *clock = gdk_surface_get_frame_clock (surface);
|
GdkFrameClock *clock = gdk_surface_get_frame_clock (surface);
|
||||||
|
GdkFrameTimings *timings;
|
||||||
|
|
||||||
|
timings = gdk_frame_clock_get_timings (clock, impl->pending_frame_counter);
|
||||||
|
impl->pending_frame_counter = 0;
|
||||||
|
|
||||||
/* If there is no remove web client, rate limit update to once a second */
|
/* If there is no remove web client, rate limit update to once a second */
|
||||||
if (local_reply)
|
if (local_reply)
|
||||||
g_timeout_add_seconds (1, (GSourceFunc)thaw_clock_cb, g_object_ref (clock));
|
g_timeout_add_seconds (1, (GSourceFunc)thaw_clock_cb, g_object_ref (clock));
|
||||||
else
|
else
|
||||||
_gdk_frame_clock_thaw (clock);
|
_gdk_frame_clock_thaw (clock);
|
||||||
|
|
||||||
|
if (timings)
|
||||||
|
{
|
||||||
|
timings->refresh_interval = 33333; /* default to 1/30th of a second */
|
||||||
|
// This isn't quite right, since we've done a rountrip back too, can we do better?
|
||||||
|
timings->presentation_time = g_get_monotonic_time ();
|
||||||
|
timings->complete = TRUE;
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef G_ENABLE_DEBUG
|
||||||
|
if ((_gdk_debug_flags & GDK_DEBUG_FRAMES) != 0)
|
||||||
|
_gdk_frame_clock_debug_print_timings (clock, timings);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@ -182,6 +164,7 @@ on_frame_clock_after_paint (GdkFrameClock *clock,
|
|||||||
GdkSurfaceImplBroadway *impl = GDK_SURFACE_IMPL_BROADWAY (surface->impl);
|
GdkSurfaceImplBroadway *impl = GDK_SURFACE_IMPL_BROADWAY (surface->impl);
|
||||||
GdkBroadwayDisplay *broadway_display;
|
GdkBroadwayDisplay *broadway_display;
|
||||||
|
|
||||||
|
impl->pending_frame_counter = gdk_frame_clock_get_frame_counter (clock);
|
||||||
_gdk_frame_clock_freeze (gdk_surface_get_frame_clock (surface));
|
_gdk_frame_clock_freeze (gdk_surface_get_frame_clock (surface));
|
||||||
|
|
||||||
broadway_display = GDK_BROADWAY_DISPLAY (display);
|
broadway_display = GDK_BROADWAY_DISPLAY (display);
|
||||||
@ -191,6 +174,30 @@ on_frame_clock_after_paint (GdkFrameClock *clock,
|
|||||||
gdk_display_flush (display);
|
gdk_display_flush (display);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
on_frame_clock_before_paint (GdkFrameClock *clock,
|
||||||
|
GdkSurface *surface)
|
||||||
|
{
|
||||||
|
GdkFrameTimings *timings = gdk_frame_clock_get_current_timings (clock);
|
||||||
|
gint64 presentation_time;
|
||||||
|
gint64 refresh_interval;
|
||||||
|
|
||||||
|
if (surface->update_freeze_count > 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
gdk_frame_clock_get_refresh_info (clock,
|
||||||
|
timings->frame_time,
|
||||||
|
&refresh_interval, &presentation_time);
|
||||||
|
if (presentation_time != 0)
|
||||||
|
{
|
||||||
|
timings->predicted_presentation_time = presentation_time + refresh_interval;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
timings->predicted_presentation_time = timings->frame_time + refresh_interval / 2 + refresh_interval;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
connect_frame_clock (GdkSurface *surface)
|
connect_frame_clock (GdkSurface *surface)
|
||||||
{
|
{
|
||||||
@ -198,6 +205,8 @@ connect_frame_clock (GdkSurface *surface)
|
|||||||
{
|
{
|
||||||
GdkFrameClock *frame_clock = gdk_surface_get_frame_clock (surface);
|
GdkFrameClock *frame_clock = gdk_surface_get_frame_clock (surface);
|
||||||
|
|
||||||
|
g_signal_connect (frame_clock, "before-paint",
|
||||||
|
G_CALLBACK (on_frame_clock_before_paint), surface);
|
||||||
g_signal_connect (frame_clock, "after-paint",
|
g_signal_connect (frame_clock, "after-paint",
|
||||||
G_CALLBACK (on_frame_clock_after_paint), surface);
|
G_CALLBACK (on_frame_clock_after_paint), surface);
|
||||||
}
|
}
|
||||||
@ -1208,8 +1217,8 @@ gdk_broadway_surface_begin_resize_drag (GdkSurface *surface,
|
|||||||
GdkSurfaceEdge edge,
|
GdkSurfaceEdge edge,
|
||||||
GdkDevice *device,
|
GdkDevice *device,
|
||||||
gint button,
|
gint button,
|
||||||
gint root_x,
|
gint x,
|
||||||
gint root_y,
|
gint y,
|
||||||
guint32 timestamp)
|
guint32 timestamp)
|
||||||
{
|
{
|
||||||
MoveResizeData *mv_resize;
|
MoveResizeData *mv_resize;
|
||||||
@ -1232,8 +1241,8 @@ gdk_broadway_surface_begin_resize_drag (GdkSurface *surface,
|
|||||||
mv_resize->is_resize = TRUE;
|
mv_resize->is_resize = TRUE;
|
||||||
mv_resize->moveresize_button = button;
|
mv_resize->moveresize_button = button;
|
||||||
mv_resize->resize_edge = edge;
|
mv_resize->resize_edge = edge;
|
||||||
mv_resize->moveresize_x = root_x;
|
mv_resize->moveresize_x = x + impl->wrapper->x;
|
||||||
mv_resize->moveresize_y = root_y;
|
mv_resize->moveresize_y = y + impl->wrapper->y;
|
||||||
mv_resize->moveresize_surface = g_object_ref (surface);
|
mv_resize->moveresize_surface = g_object_ref (surface);
|
||||||
|
|
||||||
mv_resize->moveresize_orig_width = gdk_surface_get_width (surface);
|
mv_resize->moveresize_orig_width = gdk_surface_get_width (surface);
|
||||||
@ -1251,8 +1260,8 @@ static void
|
|||||||
gdk_broadway_surface_begin_move_drag (GdkSurface *surface,
|
gdk_broadway_surface_begin_move_drag (GdkSurface *surface,
|
||||||
GdkDevice *device,
|
GdkDevice *device,
|
||||||
gint button,
|
gint button,
|
||||||
gint root_x,
|
gint x,
|
||||||
gint root_y,
|
gint y,
|
||||||
guint32 timestamp)
|
guint32 timestamp)
|
||||||
{
|
{
|
||||||
MoveResizeData *mv_resize;
|
MoveResizeData *mv_resize;
|
||||||
@ -1274,8 +1283,8 @@ gdk_broadway_surface_begin_move_drag (GdkSurface *surface,
|
|||||||
|
|
||||||
mv_resize->is_resize = FALSE;
|
mv_resize->is_resize = FALSE;
|
||||||
mv_resize->moveresize_button = button;
|
mv_resize->moveresize_button = button;
|
||||||
mv_resize->moveresize_x = root_x;
|
mv_resize->moveresize_x = x + impl->wrapper->x;
|
||||||
mv_resize->moveresize_y = root_y;
|
mv_resize->moveresize_y = y + impl->wrapper->y;
|
||||||
mv_resize->moveresize_surface = g_object_ref (surface);
|
mv_resize->moveresize_surface = g_object_ref (surface);
|
||||||
|
|
||||||
mv_resize->moveresize_orig_width = gdk_surface_get_width (surface);
|
mv_resize->moveresize_orig_width = gdk_surface_get_width (surface);
|
||||||
|
@ -61,6 +61,8 @@ struct _GdkSurfaceImplBroadway
|
|||||||
int pre_maximize_width;
|
int pre_maximize_width;
|
||||||
int pre_maximize_height;
|
int pre_maximize_height;
|
||||||
|
|
||||||
|
gint64 pending_frame_counter;
|
||||||
|
|
||||||
gboolean dirty;
|
gboolean dirty;
|
||||||
gboolean last_synced;
|
gboolean last_synced;
|
||||||
|
|
||||||
|
@ -326,6 +326,145 @@ add_new_node (GskRenderer *renderer,
|
|||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
typedef struct ColorizedTexture {
|
||||||
|
GdkTexture *texture;
|
||||||
|
graphene_matrix_t color_matrix;
|
||||||
|
graphene_vec4_t color_offset;
|
||||||
|
} ColorizedTexture;
|
||||||
|
|
||||||
|
static void
|
||||||
|
colorized_texture_free (ColorizedTexture *colorized)
|
||||||
|
{
|
||||||
|
g_object_unref (colorized->texture);
|
||||||
|
g_free (colorized);
|
||||||
|
}
|
||||||
|
|
||||||
|
static ColorizedTexture *
|
||||||
|
colorized_texture_new (GdkTexture *texture,
|
||||||
|
const graphene_matrix_t *color_matrix,
|
||||||
|
const graphene_vec4_t *color_offset)
|
||||||
|
{
|
||||||
|
ColorizedTexture *colorized = g_new0 (ColorizedTexture, 1);
|
||||||
|
colorized->texture = g_object_ref (texture);
|
||||||
|
colorized->color_matrix = *color_matrix;
|
||||||
|
colorized->color_offset = *color_offset;
|
||||||
|
return colorized;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
colorized_texture_free_list (GList *list)
|
||||||
|
{
|
||||||
|
g_list_free_full (list, (GDestroyNotify)colorized_texture_free);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
matrix_equal (const graphene_matrix_t *a,
|
||||||
|
const graphene_matrix_t *b)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < 4; i ++)
|
||||||
|
{
|
||||||
|
graphene_vec4_t ra, rb;
|
||||||
|
graphene_matrix_get_row (a, i, &ra);
|
||||||
|
graphene_matrix_get_row (b, i, &rb);
|
||||||
|
if (!graphene_vec4_equal (&ra, &rb))
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static GdkTexture *
|
||||||
|
get_colorized_texture (GdkTexture *texture,
|
||||||
|
const graphene_matrix_t *color_matrix,
|
||||||
|
const graphene_vec4_t *color_offset)
|
||||||
|
{
|
||||||
|
cairo_surface_t *surface = gdk_texture_download_surface (texture);
|
||||||
|
cairo_surface_t *image_surface;
|
||||||
|
graphene_vec4_t pixel;
|
||||||
|
guint32* pixel_data;
|
||||||
|
guchar *data;
|
||||||
|
gsize x, y, width, height, stride;
|
||||||
|
float alpha;
|
||||||
|
GdkTexture *colorized_texture;
|
||||||
|
GList *colorized_list, *l;
|
||||||
|
ColorizedTexture *colorized;
|
||||||
|
|
||||||
|
colorized_list = g_object_get_data (G_OBJECT (texture), "broadway-colorized");
|
||||||
|
|
||||||
|
for (l = colorized_list; l != NULL; l = l->next)
|
||||||
|
{
|
||||||
|
colorized = l->data;
|
||||||
|
|
||||||
|
if (graphene_vec4_equal (&colorized->color_offset, color_offset) &&
|
||||||
|
matrix_equal (&colorized->color_matrix, color_matrix))
|
||||||
|
return g_object_ref (colorized->texture);
|
||||||
|
}
|
||||||
|
|
||||||
|
image_surface = cairo_surface_map_to_image (surface, NULL);
|
||||||
|
data = cairo_image_surface_get_data (image_surface);
|
||||||
|
width = cairo_image_surface_get_width (image_surface);
|
||||||
|
height = cairo_image_surface_get_height (image_surface);
|
||||||
|
stride = cairo_image_surface_get_stride (image_surface);
|
||||||
|
|
||||||
|
for (y = 0; y < height; y++)
|
||||||
|
{
|
||||||
|
pixel_data = (guint32 *) data;
|
||||||
|
for (x = 0; x < width; x++)
|
||||||
|
{
|
||||||
|
alpha = ((pixel_data[x] >> 24) & 0xFF) / 255.0;
|
||||||
|
|
||||||
|
if (alpha == 0)
|
||||||
|
{
|
||||||
|
graphene_vec4_init (&pixel, 0.0, 0.0, 0.0, 0.0);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
graphene_vec4_init (&pixel,
|
||||||
|
((pixel_data[x] >> 16) & 0xFF) / (255.0 * alpha),
|
||||||
|
((pixel_data[x] >> 8) & 0xFF) / (255.0 * alpha),
|
||||||
|
( pixel_data[x] & 0xFF) / (255.0 * alpha),
|
||||||
|
alpha);
|
||||||
|
graphene_matrix_transform_vec4 (color_matrix, &pixel, &pixel);
|
||||||
|
}
|
||||||
|
|
||||||
|
graphene_vec4_add (&pixel, color_offset, &pixel);
|
||||||
|
|
||||||
|
alpha = graphene_vec4_get_w (&pixel);
|
||||||
|
if (alpha > 0.0)
|
||||||
|
{
|
||||||
|
alpha = MIN (alpha, 1.0);
|
||||||
|
pixel_data[x] = (((guint32) (alpha * 255)) << 24) |
|
||||||
|
(((guint32) (CLAMP (graphene_vec4_get_x (&pixel), 0, 1) * alpha * 255)) << 16) |
|
||||||
|
(((guint32) (CLAMP (graphene_vec4_get_y (&pixel), 0, 1) * alpha * 255)) << 8) |
|
||||||
|
((guint32) (CLAMP (graphene_vec4_get_z (&pixel), 0, 1) * alpha * 255));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
pixel_data[x] = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
data += stride;
|
||||||
|
}
|
||||||
|
|
||||||
|
cairo_surface_mark_dirty (image_surface);
|
||||||
|
cairo_surface_unmap_image (surface, image_surface);
|
||||||
|
|
||||||
|
colorized_texture = gdk_texture_new_for_surface (surface);
|
||||||
|
|
||||||
|
colorized = colorized_texture_new (colorized_texture, color_matrix, color_offset);
|
||||||
|
if (colorized_list)
|
||||||
|
colorized_list = g_list_append (colorized_list, colorized);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
colorized_list = g_list_append (NULL, colorized);
|
||||||
|
g_object_set_data_full (G_OBJECT (texture), "broadway-colorized",
|
||||||
|
colorized_list, (GDestroyNotify)colorized_texture_free_list);
|
||||||
|
}
|
||||||
|
|
||||||
|
return colorized_texture;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/* Note: This tracks the offset so that we can convert
|
/* Note: This tracks the offset so that we can convert
|
||||||
the absolute coordinates of the GskRenderNodes to
|
the absolute coordinates of the GskRenderNodes to
|
||||||
parent-relative which is what the dom uses, and
|
parent-relative which is what the dom uses, and
|
||||||
@ -571,6 +710,26 @@ gsk_broadway_renderer_add_node (GskRenderer *renderer,
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
case GSK_COLOR_MATRIX_NODE:
|
case GSK_COLOR_MATRIX_NODE:
|
||||||
|
{
|
||||||
|
GskRenderNode *child = gsk_color_matrix_node_get_child (node);
|
||||||
|
if (gsk_render_node_get_node_type (child) == GSK_TEXTURE_NODE)
|
||||||
|
{
|
||||||
|
const graphene_matrix_t *color_matrix = gsk_color_matrix_node_peek_color_matrix (node);
|
||||||
|
const graphene_vec4_t *color_offset = gsk_color_matrix_node_peek_color_offset (node);
|
||||||
|
GdkTexture *texture = gsk_texture_node_get_texture (child);
|
||||||
|
GdkTexture *colorized_texture = get_colorized_texture (texture, color_matrix, color_offset);
|
||||||
|
if (add_new_node (renderer, node, BROADWAY_NODE_TEXTURE))
|
||||||
|
{
|
||||||
|
guint32 texture_id = gdk_broadway_display_ensure_texture (display, colorized_texture);
|
||||||
|
add_rect (nodes, &child->bounds, offset_x, offset_y);
|
||||||
|
add_uint32 (nodes, texture_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break; /* Fallback */
|
||||||
|
|
||||||
case GSK_TEXT_NODE:
|
case GSK_TEXT_NODE:
|
||||||
case GSK_REPEATING_LINEAR_GRADIENT_NODE:
|
case GSK_REPEATING_LINEAR_GRADIENT_NODE:
|
||||||
case GSK_REPEAT_NODE:
|
case GSK_REPEAT_NODE:
|
@ -55,7 +55,7 @@
|
|||||||
#include <gdk/wayland/gdkwayland.h>
|
#include <gdk/wayland/gdkwayland.h>
|
||||||
#endif
|
#endif
|
||||||
#ifdef GDK_WINDOWING_BROADWAY
|
#ifdef GDK_WINDOWING_BROADWAY
|
||||||
#include "gskbroadwayrendererprivate.h"
|
#include "broadway/gskbroadwayrendererprivate.h"
|
||||||
#endif
|
#endif
|
||||||
#ifdef GDK_RENDERING_VULKAN
|
#ifdef GDK_RENDERING_VULKAN
|
||||||
#include "vulkan/gskvulkanrendererprivate.h"
|
#include "vulkan/gskvulkanrendererprivate.h"
|
||||||
|
@ -97,7 +97,7 @@ endif # have_vulkan
|
|||||||
|
|
||||||
if get_variable('broadway_enabled')
|
if get_variable('broadway_enabled')
|
||||||
gsk_private_sources += files([
|
gsk_private_sources += files([
|
||||||
'gskbroadwayrenderer.c',
|
'broadway/gskbroadwayrenderer.c',
|
||||||
])
|
])
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user