GUACAMOLE-231: Report mouse position using new "mouse" instruction. Rely on client-side cursor layer implementation.

This commit is contained in:
Michael Jumper 2017-03-10 12:28:00 -08:00
parent 1a96c5b415
commit ae7e8d3890
2 changed files with 27 additions and 146 deletions

View File

@ -45,10 +45,9 @@ typedef struct guac_common_cursor {
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.

View File

@ -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 @@ guac_common_cursor* guac_common_cursor_alloc(guac_client* client) {
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 @@ guac_common_cursor* guac_common_cursor_alloc(guac_client* client) {
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 @@ void guac_common_cursor_free(guac_common_cursor* cursor) {
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,89 +91,37 @@ void guac_common_cursor_dup(guac_common_cursor* cursor, guac_user* user,
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);
}
/**
* 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.
*
* @param data
* A pointer to the guac_common_cursor structure describing the cursor to
* be shown.
*
* @return
* Always NULL.
*/
static void* guac_common_cursor_show(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);
guac_socket_flush(user->socket);
}
return NULL;
}
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);
/* Notify of change in cursor position */
guac_protocol_send_mouse(cursor->client->socket, x, y);
guac_socket_flush(cursor->client->socket);
}
@ -217,65 +164,6 @@ static void guac_common_cursor_resize(guac_common_cursor* cursor,
}
/**
* 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 +183,20 @@ void guac_common_cursor_set_argb(guac_common_cursor* cursor, int hx, int hy,
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,