GUACAMOLE-176: Support layer location and opacity for guac_common_surface.

This commit is contained in:
Michael Jumper 2016-09-11 16:52:22 -07:00
parent a1886f51bd
commit 6bd19b6ac6
3 changed files with 190 additions and 4 deletions

View File

@ -118,6 +118,40 @@ typedef struct guac_common_surface {
*/ */
guac_socket* socket; guac_socket* socket;
/**
* The X coordinate of the upper-left corner of this layer, in pixels,
* relative to its parent layer. This is only applicable to visible
* (non-buffer) layers which are not the default layer.
*/
int x;
/**
* The Y coordinate of the upper-left corner of this layer, in pixels,
* relative to its parent layer. This is only applicable to visible
* (non-buffer) layers which are not the default layer.
*/
int y;
/**
* The Z-order of this layer, relative to sibling layers. This is only
* applicable to visible (non-buffer) layers which are not the default
* layer.
*/
int z;
/**
* The level of opacity applied to this layer. Fully opaque is 255, while
* fully transparent is 0. This is only applicable to visible (non-buffer)
* layers which are not the default layer.
*/
int opacity;
/**
* The layer which contains this layer. This is only applicable to visible
* (non-buffer) layers which are not the default layer.
*/
const guac_layer* parent;
/** /**
* The width of this layer, in pixels. * The width of this layer, in pixels.
*/ */
@ -138,6 +172,18 @@ typedef struct guac_common_surface {
*/ */
unsigned char* buffer; unsigned char* buffer;
/**
* Non-zero if the location or parent layer of this surface has been
* changed and needs to be flushed, 0 otherwise.
*/
int location_dirty;
/**
* Non-zero if the opacity of this surface has been changed and needs to be
* flushed, 0 otherwise.
*/
int opacity_dirty;
/** /**
* Non-zero if this surface is dirty and needs to be flushed, 0 otherwise. * Non-zero if this surface is dirty and needs to be flushed, 0 otherwise.
*/ */
@ -317,10 +363,77 @@ void guac_common_surface_clip(guac_common_surface* surface, int x, int y, int w,
void guac_common_surface_reset_clip(guac_common_surface* surface); void guac_common_surface_reset_clip(guac_common_surface* surface);
/** /**
* Flushes the given surface, drawing any pending operations on the remote * Changes the location of the surface relative to its parent layer. If the
* display. * surface does not represent a non-default visible layer, then this function
* has no effect.
* *
* @param surface The surface to flush. * @param surface
* The surface to move relative to its parent layer.
*
* @param x
* The new X coordinate for the upper-left corner of the layer, in pixels.
*
* @param y
* The new Y coordinate for the upper-left corner of the layer, in pixels.
*/
void guac_common_surface_move(guac_common_surface* surface, int x, int y);
/**
* Changes the stacking order of the surface relative to other surfaces within
* the same parent layer. If the surface does not represent a non-default
* visible layer, then this function has no effect.
*
* @param surface
* The surface to reorder relative to sibling layers.
*
* @param z
* The new Z-order for this layer, relative to sibling layers.
*/
void guac_common_surface_stack(guac_common_surface* surface, int z);
/**
* Changes the parent layer of ths given surface. By default, layers will be
* children of the default layer. If the surface does not represent a
* non-default visible layer, then this function has no effect.
*
* @param surface
* The surface whose parent layer should be changed.
*
* @param parent
* The layer which should be set as the new parent of the given surface.
*/
void guac_common_surface_set_parent(guac_common_surface* surface,
const guac_layer* parent);
/**
* Sets the opacity of the surface. If the surface does not represent a
* non-default visible layer, then this function has no effect.
*
* @param surface
* The surface whose opacity should be changed.
*
* @param opacity
* The level of opacity applied to this surface, where fully opaque is 255,
* and fully transparent is 0.
*/
void guac_common_surface_set_opacity(guac_common_surface* surface, int opacity);
/**
* Flushes only the properties of the given surface, such as layer location or
* opacity. Image state is not flushed. If the surface represents a buffer or
* the default layer, this function has no effect.
*
* @param surface
* The surface to flush.
*/
void guac_common_surface_flush_properties(guac_common_surface* surface);
/**
* Flushes the given surface, including any applicable properties, drawing any
* pending operations on the remote display.
*
* @param surface
* The surface to flush.
*/ */
void guac_common_surface_flush(guac_common_surface* surface); void guac_common_surface_flush(guac_common_surface* surface);

View File

@ -155,7 +155,17 @@ void guac_common_display_dup(guac_common_display* display, guac_user* user,
} }
void guac_common_display_flush(guac_common_display* display) { void guac_common_display_flush(guac_common_display* display) {
guac_common_display_layer* current = display->layers;
/* Flush all surfaces */
while (current != NULL) {
guac_common_surface_flush(current->surface);
current = current->next;
}
guac_common_surface_flush(display->default_surface); guac_common_surface_flush(display->default_surface);
} }
/** /**

View File

@ -116,6 +116,29 @@
*/ */
#define GUAC_SURFACE_WEBP_BLOCK_SIZE 8 #define GUAC_SURFACE_WEBP_BLOCK_SIZE 8
void guac_common_surface_move(guac_common_surface* surface, int x, int y) {
surface->x = x;
surface->y = y;
surface->location_dirty = 1;
}
void guac_common_surface_stack(guac_common_surface* surface, int z) {
surface->z = z;
surface->location_dirty = 1;
}
void guac_common_surface_set_parent(guac_common_surface* surface,
const guac_layer* parent) {
surface->parent = parent;
surface->location_dirty = 1;
}
void guac_common_surface_set_opacity(guac_common_surface* surface,
int opacity) {
surface->opacity = opacity;
surface->opacity_dirty = 1;
}
/** /**
* Updates the coordinates of the given rectangle to be within the bounds of * Updates the coordinates of the given rectangle to be within the bounds of
* the given surface. * the given surface.
@ -990,6 +1013,7 @@ guac_common_surface* guac_common_surface_alloc(guac_client* client,
surface->client = client; surface->client = client;
surface->socket = socket; surface->socket = socket;
surface->layer = layer; surface->layer = layer;
surface->parent = GUAC_DEFAULT_LAYER;
surface->width = w; surface->width = w;
surface->height = h; surface->height = h;
@ -1443,6 +1467,29 @@ static int __guac_common_surface_bitmap_rect_compare(const void* a, const void*
} }
void guac_common_surface_flush_properties(guac_common_surface* surface) {
guac_socket* socket = surface->socket;
/* Only applicable to non-default visible layers */
if (surface->layer->index <= 0)
return;
/* Flush opacity */
if (surface->opacity_dirty) {
guac_protocol_send_shade(socket, surface->layer, surface->opacity);
surface->opacity_dirty = 0;
}
/* Flush location and hierarchy */
if (surface->location_dirty) {
guac_protocol_send_move(socket, surface->layer,
surface->parent, surface->x, surface->y, surface->z);
surface->location_dirty = 0;
}
}
void guac_common_surface_flush(guac_common_surface* surface) { void guac_common_surface_flush(guac_common_surface* surface) {
/* Flush final dirty rectangle to queue. */ /* Flush final dirty rectangle to queue. */
@ -1523,6 +1570,9 @@ void guac_common_surface_flush(guac_common_surface* surface) {
} }
/* Flush any applicable layer properties */
guac_common_surface_flush_properties(surface);
/* Flush complete */ /* Flush complete */
surface->bitmap_queue_length = 0; surface->bitmap_queue_length = 0;
@ -1535,8 +1585,21 @@ void guac_common_surface_dup(guac_common_surface* surface, guac_user* user,
if (!surface->realized) if (!surface->realized)
return; return;
/* Synchronize layer-specific properties if applicable */
if (surface->layer->index > 0) {
/* Synchronize opacity */
guac_protocol_send_shade(socket, surface->layer, surface->opacity);
/* Synchronize location and hierarchy */
guac_protocol_send_move(socket, surface->layer,
surface->parent, surface->x, surface->y, surface->z);
}
/* Sync size to new socket */ /* Sync size to new socket */
guac_protocol_send_size(socket, surface->layer, surface->width, surface->height); guac_protocol_send_size(socket, surface->layer,
surface->width, surface->height);
/* Get entire surface */ /* Get entire surface */
cairo_surface_t* rect = cairo_image_surface_create_for_data( cairo_surface_t* rect = cairo_image_surface_create_for_data(