diff --git a/src/common/common/surface.h b/src/common/common/surface.h index c7788837..ca8b3106 100644 --- a/src/common/common/surface.h +++ b/src/common/common/surface.h @@ -120,6 +120,12 @@ typedef struct guac_common_surface { */ guac_socket* socket; + /** + * The number of simultaneous touches that this surface can accept, where 0 + * indicates that the surface does not support touch events at all. + */ + int touches; + /** * The X coordinate of the upper-left corner of this layer, in pixels, * relative to its parent layer. This is only applicable to visible @@ -486,5 +492,23 @@ void guac_common_surface_flush(guac_common_surface* surface); void guac_common_surface_dup(guac_common_surface* surface, guac_user* user, guac_socket* socket); +/** + * Declares that the given surface should receive touch events. By default, + * surfaces are assumed to not expect touch events. This value is advisory, and + * the client is not required to honor the declared level of touch support. + * Implementations are expected to safely handle or ignore any received touch + * events, regardless of the level of touch support declared. regardless of + * the level of touch support declared. + * + * @param surface + * The surface to modify. + * + * @param touches + * The number of simultaneous touches that this surface can accept, where 0 + * indicates that the surface does not support touch events at all. + */ +void guac_common_surface_set_multitouch(guac_common_surface* surface, + int touches); + #endif diff --git a/src/common/surface.c b/src/common/surface.c index c86ca806..183ae11e 100644 --- a/src/common/surface.c +++ b/src/common/surface.c @@ -103,6 +103,19 @@ */ #define GUAC_SURFACE_WEBP_BLOCK_SIZE 8 +void guac_common_surface_set_multitouch(guac_common_surface* surface, + int touches) { + + pthread_mutex_lock(&surface->_lock); + + surface->touches = touches; + guac_protocol_send_set_int(surface->socket, surface->layer, + GUAC_PROTOCOL_LAYER_PARAMETER_MULTI_TOUCH, touches); + + pthread_mutex_unlock(&surface->_lock); + +} + void guac_common_surface_move(guac_common_surface* surface, int x, int y) { pthread_mutex_lock(&surface->_lock); @@ -1981,6 +1994,11 @@ void guac_common_surface_dup(guac_common_surface* surface, guac_user* user, guac_protocol_send_move(socket, surface->layer, surface->parent, surface->x, surface->y, surface->z); + /* Synchronize multi-touch support level */ + guac_protocol_send_set_int(surface->socket, surface->layer, + GUAC_PROTOCOL_LAYER_PARAMETER_MULTI_TOUCH, + surface->touches); + } /* Sync size to new socket */ diff --git a/src/libguac/guacamole/protocol-constants.h b/src/libguac/guacamole/protocol-constants.h index 5bd91b07..13d7f680 100644 --- a/src/libguac/guacamole/protocol-constants.h +++ b/src/libguac/guacamole/protocol-constants.h @@ -49,5 +49,20 @@ */ #define GUAC_PROTOCOL_BLOB_MAX_LENGTH 6048 +/** + * The name of the layer parameter defining the number of simultaneous points + * of contact supported by a layer. This parameter should be set to a non-zero + * value if the associated layer should receive touch events ("touch" + * instructions). + * + * This value specified for this parameter is advisory, and the client is not + * required to honor the declared level of touch support. Implementations are + * expected to safely handle or ignore any received touch events, regardless of + * the level of touch support declared. + * + * @see guac_protocol_send_set_int() + */ +#define GUAC_PROTOCOL_LAYER_PARAMETER_MULTI_TOUCH "multi-touch" + #endif diff --git a/src/libguac/guacamole/protocol.h b/src/libguac/guacamole/protocol.h index c6dbed29..d23da502 100644 --- a/src/libguac/guacamole/protocol.h +++ b/src/libguac/guacamole/protocol.h @@ -271,6 +271,32 @@ int guac_protocol_send_ready(guac_socket* socket, const char* id); int guac_protocol_send_set(guac_socket* socket, const guac_layer* layer, const char* name, const char* value); +/** + * Sends a set instruction over the given guac_socket connection. This function + * behavies identically to guac_protocol_send_set() except that the provided + * parameter value is an integer, rather than a string. + * + * If an error occurs sending the instruction, a non-zero value is + * returned, and guac_error is set appropriately. + * + * @param socket + * The guac_socket connection to use. + * + * @param layer + * The layer to set the parameter of. + * + * @param name + * The name of the parameter to set. + * + * @param value + * The value to set the parameter to. + * + * @return + * Zero on success, non-zero on error. + */ +int guac_protocol_send_set_int(guac_socket* socket, const guac_layer* layer, + const char* name, int value); + /** * Sends a select instruction over the given guac_socket connection. * diff --git a/src/libguac/protocol.c b/src/libguac/protocol.c index 59a46d5b..354adfa1 100644 --- a/src/libguac/protocol.c +++ b/src/libguac/protocol.c @@ -1057,6 +1057,26 @@ int guac_protocol_send_set(guac_socket* socket, const guac_layer* layer, } +int guac_protocol_send_set_int(guac_socket* socket, const guac_layer* layer, + const char* name, int value) { + + int ret_val; + + guac_socket_instruction_begin(socket); + ret_val = + guac_socket_write_string(socket, "3.set,") + || __guac_socket_write_length_int(socket, layer->index) + || guac_socket_write_string(socket, ",") + || __guac_socket_write_length_string(socket, name) + || guac_socket_write_string(socket, ",") + || __guac_socket_write_length_int(socket, value) + || guac_socket_write_string(socket, ";"); + + guac_socket_instruction_end(socket); + return ret_val; + +} + int guac_protocol_send_select(guac_socket* socket, const char* protocol) { int ret_val;