GUACAMOLE-231: Merge server-side production of new mouse instruction.
diff --git a/src/common/common/cursor.h b/src/common/common/cursor.h
index 86a7f14..00bc48e 100644
--- a/src/common/common/cursor.h
+++ b/src/common/common/cursor.h
@@ -45,10 +45,9 @@
guac_client* client;
/**
- * The cursor layer. This layer will be available to all connected users,
- * but will be visible only to those users who are not moving the mouse.
+ * The buffer containing the current cursor image.
*/
- guac_layer* layer;
+ guac_layer* buffer;
/**
* The width of the cursor image, in pixels.
diff --git a/src/common/cursor.c b/src/common/cursor.c
index e63ada1..f956f6a 100644
--- a/src/common/cursor.c
+++ b/src/common/cursor.c
@@ -26,7 +26,6 @@
#include <cairo/cairo.h>
#include <guacamole/client.h>
-#include <guacamole/layer.h>
#include <guacamole/protocol.h>
#include <guacamole/socket.h>
#include <guacamole/user.h>
@@ -41,9 +40,9 @@
if (cursor == NULL)
return NULL;
- /* Associate cursor with client and allocate cursor layer */
+ /* Associate cursor with client and allocate cursor buffer */
cursor->client = client;
- cursor->layer= guac_client_alloc_layer(client);
+ cursor->buffer = guac_client_alloc_buffer(client);
/* Allocate initial image buffer */
cursor->image_buffer_size = GUAC_COMMON_CURSOR_DEFAULT_SIZE;
@@ -70,7 +69,7 @@
void guac_common_cursor_free(guac_common_cursor* cursor) {
guac_client* client = cursor->client;
- guac_layer* layer = cursor->layer;
+ guac_layer* buffer = cursor->buffer;
cairo_surface_t* surface = cursor->surface;
/* Free image buffer and surface */
@@ -78,11 +77,11 @@
if (surface != NULL)
cairo_surface_destroy(surface);
- /* Destroy layer within remotely-connected client */
- guac_protocol_send_dispose(client->socket, layer);
+ /* Destroy buffer within remotely-connected client */
+ guac_protocol_send_dispose(client->socket, buffer);
- /* Return layer to pool */
- guac_client_free_layer(client, layer);
+ /* Return buffer to pool */
+ guac_client_free_buffer(client, buffer);
free(cursor);
@@ -92,18 +91,19 @@
guac_socket* socket) {
/* Synchronize location */
- guac_protocol_send_move(socket, cursor->layer, GUAC_DEFAULT_LAYER,
- cursor->x - cursor->hotspot_x,
- cursor->y - cursor->hotspot_y,
- INT_MAX);
+ guac_protocol_send_mouse(socket, cursor->x, cursor->y);
/* Synchronize cursor image */
if (cursor->surface != NULL) {
- guac_protocol_send_size(socket, cursor->layer,
+ guac_protocol_send_size(socket, cursor->buffer,
cursor->width, cursor->height);
guac_user_stream_png(user, socket, GUAC_COMP_SRC,
- cursor->layer, 0, 0, cursor->surface);
+ cursor->buffer, 0, 0, cursor->surface);
+
+ guac_protocol_send_cursor(socket,
+ cursor->hotspot_x, cursor->hotspot_y,
+ cursor->buffer, 0, 0, cursor->width, cursor->height);
}
guac_socket_flush(socket);
@@ -111,28 +111,24 @@
}
/**
- * Callback for guac_client_for_user() which shows the cursor layer for the
- * given user (if they exist). The cursor layer is normally hidden when a user
- * is moving the mouse, and will only be shown if a DIFFERENT user is moving
- * the mouse.
- *
- * @param user
- * The user to show the cursor to, or NULL if that user does not exist.
+ * Callback for guac_client_foreach_user() which sends the current cursor
+ * position to any given user except the user that moved the cursor last.
*
* @param data
- * A pointer to the guac_common_cursor structure describing the cursor to
- * be shown.
+ * A pointer to the guac_common_cursor whose position should be broadcast
+ * to all users except the user that moved the cursor last.
*
* @return
* Always NULL.
*/
-static void* guac_common_cursor_show(guac_user* user, void* data) {
+static void* guac_common_cursor_broadcast_position(guac_user* user,
+ void* data) {
guac_common_cursor* cursor = (guac_common_cursor*) data;
- /* Make cursor layer visible to given user */
- if (user != NULL) {
- guac_protocol_send_shade(user->socket, cursor->layer, 255);
+ /* Send cursor position only if the user is not moving the cursor */
+ if (user != cursor->user) {
+ guac_protocol_send_mouse(user->socket, cursor->x, cursor->y);
guac_socket_flush(user->socket);
}
@@ -143,39 +139,16 @@
void guac_common_cursor_move(guac_common_cursor* cursor, guac_user* user,
int x, int y) {
- guac_user* last_user = cursor->user;
-
/* Update current user of cursor */
- if (last_user != user) {
-
- cursor->user = user;
-
- /* Make cursor layer visible to previous user */
- guac_client_for_user(cursor->client, last_user,
- guac_common_cursor_show, cursor);
-
- /* Show hardware cursor */
- guac_protocol_send_cursor(user->socket,
- cursor->hotspot_x, cursor->hotspot_y,
- cursor->layer, 0, 0, cursor->width, cursor->height);
-
- /* Hide cursor layer from new user */
- guac_protocol_send_shade(user->socket, cursor->layer, 0);
- guac_socket_flush(user->socket);
-
- }
+ cursor->user = user;
/* Update cursor position */
cursor->x = x;
cursor->y = y;
- guac_protocol_send_move(cursor->client->socket, cursor->layer,
- GUAC_DEFAULT_LAYER,
- x - cursor->hotspot_x,
- y - cursor->hotspot_y,
- INT_MAX);
-
- guac_socket_flush(cursor->client->socket);
+ /* Notify all other users of change in cursor position */
+ guac_client_foreach_user(cursor->client,
+ guac_common_cursor_broadcast_position, cursor);
}
@@ -217,65 +190,6 @@
}
-/**
- * Callback for guac_client_foreach_user() which sends the current cursor image
- * as PNG data to each connected client.
- *
- * @param user
- * The user to send the cursor image to.
- *
- * @param data
- * A pointer to the guac_common_cursor structure containing the cursor
- * image that should be sent to the given user.
- *
- * @return
- * Always NULL.
- */
-static void* __send_user_cursor_image(guac_user* user, void* data) {
-
- guac_common_cursor* cursor = (guac_common_cursor*) data;
-
- guac_user_stream_png(user, user->socket, GUAC_COMP_SRC,
- cursor->layer, 0, 0, cursor->surface);
-
- return NULL;
-
-}
-
-/**
- * Callback for guac_client_for_user() which updates the hardware cursor and
- * hotspot for the given user (if they exist). The hardware cursor image is
- * normally hidden when a user is not moving the mouse, and will only be shown
- * if that user begins moving the mouse.
- *
- * @param user
- * The user whose hardware cursor should be updated, or NULL if that user
- * does not exist.
- *
- * @param data
- * A pointer to the guac_common_cursor structure describing the cursor to
- * be sent as the hardware cursor.
- *
- * @return
- * Always NULL.
- */
-static void* guac_common_cursor_update(guac_user* user, void* data) {
-
- guac_common_cursor* cursor = (guac_common_cursor*) data;
-
- /* Update hardware cursor of current user */
- if (user != NULL) {
- guac_protocol_send_cursor(user->socket,
- cursor->hotspot_x, cursor->hotspot_y,
- cursor->layer, 0, 0, cursor->width, cursor->height);
-
- guac_socket_flush(user->socket);
- }
-
- return NULL;
-
-}
-
void guac_common_cursor_set_argb(guac_common_cursor* cursor, int hx, int hy,
unsigned const char* data, int width, int height, int stride) {
@@ -295,26 +209,20 @@
cursor->hotspot_x = hx;
cursor->hotspot_y = hy;
- /* Update location based on new hotspot */
- guac_protocol_send_move(cursor->client->socket, cursor->layer,
- GUAC_DEFAULT_LAYER,
- cursor->x - hx,
- cursor->y - hy,
- INT_MAX);
-
/* Broadcast new cursor image to all users */
- guac_protocol_send_size(cursor->client->socket, cursor->layer,
+ guac_protocol_send_size(cursor->client->socket, cursor->buffer,
width, height);
- guac_client_foreach_user(cursor->client, __send_user_cursor_image, cursor);
+ guac_client_stream_png(cursor->client, cursor->client->socket,
+ GUAC_COMP_SRC, cursor->buffer, 0, 0, cursor->surface);
+
+ /* Update cursor image */
+ guac_protocol_send_cursor(cursor->client->socket,
+ cursor->hotspot_x, cursor->hotspot_y,
+ cursor->buffer, 0, 0, cursor->width, cursor->height);
guac_socket_flush(cursor->client->socket);
- /* Update hardware cursor of current user (if they are indeed valid) */
- if (cursor->user != NULL)
- guac_client_for_user(cursor->client, cursor->user,
- guac_common_cursor_update, cursor);
-
}
void guac_common_cursor_set_surface(guac_common_cursor* cursor, int hx, int hy,
diff --git a/src/libguac/guacamole/protocol.h b/src/libguac/guacamole/protocol.h
index 638d7b2..88a0a18 100644
--- a/src/libguac/guacamole/protocol.h
+++ b/src/libguac/guacamole/protocol.h
@@ -145,6 +145,26 @@
va_list args);
/**
+ * Sends a mouse instruction over the given guac_socket connection.
+ *
+ * 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 x
+ * The X coordinate of the current mouse position.
+ *
+ * @param y
+ * The Y coordinate of the current mouse position.
+ *
+ * @return
+ * Zero on success, non-zero on error.
+ */
+int guac_protocol_send_mouse(guac_socket* socket, int x, int y);
+
+/**
* Sends a nest instruction over the given guac_socket connection.
*
* If an error occurs sending the instruction, a non-zero value is
diff --git a/src/libguac/protocol.c b/src/libguac/protocol.c
index 1040fb1..8da1824 100644
--- a/src/libguac/protocol.c
+++ b/src/libguac/protocol.c
@@ -684,6 +684,23 @@
}
+int guac_protocol_send_mouse(guac_socket* socket, int x, int y) {
+
+ int ret_val;
+
+ guac_socket_instruction_begin(socket);
+ ret_val =
+ guac_socket_write_string(socket, "5.mouse,")
+ || __guac_socket_write_length_int(socket, x)
+ || guac_socket_write_string(socket, ",")
+ || __guac_socket_write_length_int(socket, y)
+ || guac_socket_write_string(socket, ";");
+
+ guac_socket_instruction_end(socket);
+ return ret_val;
+
+}
+
int guac_protocol_send_move(guac_socket* socket, const guac_layer* layer,
const guac_layer* parent, int x, int y, int z) {
diff --git a/src/terminal/terminal.c b/src/terminal/terminal.c
index a65f446..c5df648 100644
--- a/src/terminal/terminal.c
+++ b/src/terminal/terminal.c
@@ -1746,7 +1746,6 @@
result = __guac_terminal_send_mouse(term, user, x, y, mask);
guac_terminal_unlock(term);
- guac_terminal_notify(term);
return result;
}