From 81a0e66d9f3dbd245adc8f4692ffa9e3175463f7 Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Fri, 8 Dec 2017 10:45:09 -0800 Subject: [PATCH] GUACAMOLE-313: Include current button state within mouse update for completeness. --- src/common/common/cursor.h | 40 +++++++++++++++++++++++++++----- src/common/common/recording.h | 17 ++++++++++++-- src/common/cursor.c | 28 +++++++++++----------- src/common/recording.c | 4 ++-- src/guacenc/instruction-mouse.c | 4 ++-- src/libguac/guacamole/protocol.h | 15 +++++++++++- src/libguac/protocol.c | 4 +++- src/protocols/rdp/input.c | 6 ++--- src/protocols/ssh/input.c | 2 +- src/protocols/telnet/input.c | 3 ++- src/protocols/vnc/input.c | 6 ++--- src/terminal/terminal.c | 4 ++-- 12 files changed, 96 insertions(+), 37 deletions(-) diff --git a/src/common/common/cursor.h b/src/common/common/cursor.h index 30316f45..52d93c2a 100644 --- a/src/common/common/cursor.h +++ b/src/common/common/cursor.h @@ -102,6 +102,21 @@ typedef struct guac_common_cursor { */ int y; + /** + * An integer value representing the current state of each button, where + * the Nth bit within the integer is set to 1 if and only if the Nth mouse + * button is currently pressed. The lowest-order bit is the left mouse + * button, followed by the middle button, right button, and finally the up + * and down buttons of the scroll wheel. + * + * @see GUAC_CLIENT_MOUSE_LEFT + * @see GUAC_CLIENT_MOUSE_MIDDLE + * @see GUAC_CLIENT_MOUSE_RIGHT + * @see GUAC_CLIENT_MOUSE_SCROLL_UP + * @see GUAC_CLIENT_MOUSE_SCROLL_DOWN + */ + int button_mask; + /** * The server timestamp representing the point in time when the mousr * location was last updated. @@ -148,12 +163,12 @@ void guac_common_cursor_dup(guac_common_cursor* cursor, guac_user* user, guac_socket* socket); /** - * Moves the mouse cursor, marking the given user as the most recent user of - * the mouse. The remote mouse cursor will be hidden for this user and shown - * for all others. + * Updates the current position and button state of the mouse cursor, marking + * the given user as the most recent user of the mouse. The remote mouse cursor + * will be hidden for this user and shown for all others. * * @param cursor - * The cursor being moved. + * The cursor being updated. * * @param user * The user that moved the cursor. @@ -163,9 +178,22 @@ void guac_common_cursor_dup(guac_common_cursor* cursor, guac_user* user, * * @param y * The new Y coordinate of the cursor. + * + * @param button_mask + * An integer value representing the current state of each button, where + * the Nth bit within the integer is set to 1 if and only if the Nth mouse + * button is currently pressed. The lowest-order bit is the left mouse + * button, followed by the middle button, right button, and finally the up + * and down buttons of the scroll wheel. + * + * @see GUAC_CLIENT_MOUSE_LEFT + * @see GUAC_CLIENT_MOUSE_MIDDLE + * @see GUAC_CLIENT_MOUSE_RIGHT + * @see GUAC_CLIENT_MOUSE_SCROLL_UP + * @see GUAC_CLIENT_MOUSE_SCROLL_DOWN */ -void guac_common_cursor_move(guac_common_cursor* cursor, guac_user* user, - int x, int y); +void guac_common_cursor_update(guac_common_cursor* cursor, guac_user* user, + int x, int y, int button_mask); /** * Sets the cursor image to the given raw image data. This raw image data must diff --git a/src/common/common/recording.h b/src/common/common/recording.h index e03e7881..03d42574 100644 --- a/src/common/common/recording.h +++ b/src/common/common/recording.h @@ -102,7 +102,7 @@ guac_common_recording* guac_common_recording_create(guac_client* client, void guac_common_recording_free(guac_common_recording* recording); /** - * Reports the current mouse position within the recording. + * Reports the current mouse position and button state within the recording. * * @param recording * The guac_common_recording associated with the mouse that has moved. @@ -112,9 +112,22 @@ void guac_common_recording_free(guac_common_recording* recording); * * @param y * The new Y coordinate of the mouse cursor, in pixels. + * + * @param button_mask + * An integer value representing the current state of each button, where + * the Nth bit within the integer is set to 1 if and only if the Nth mouse + * button is currently pressed. The lowest-order bit is the left mouse + * button, followed by the middle button, right button, and finally the up + * and down buttons of the scroll wheel. + * + * @see GUAC_CLIENT_MOUSE_LEFT + * @see GUAC_CLIENT_MOUSE_MIDDLE + * @see GUAC_CLIENT_MOUSE_RIGHT + * @see GUAC_CLIENT_MOUSE_SCROLL_UP + * @see GUAC_CLIENT_MOUSE_SCROLL_DOWN */ void guac_common_recording_report_mouse(guac_common_recording* recording, - int x, int y); + int x, int y, int button_mask); #endif diff --git a/src/common/cursor.c b/src/common/cursor.c index 7f4fb8f6..b70134d8 100644 --- a/src/common/cursor.c +++ b/src/common/cursor.c @@ -103,7 +103,7 @@ void guac_common_cursor_dup(guac_common_cursor* cursor, guac_user* user, guac_socket* socket) { /* Synchronize location */ - guac_protocol_send_mouse(socket, cursor->x, cursor->y, + guac_protocol_send_mouse(socket, cursor->x, cursor->y, cursor->button_mask, cursor->timestamp); /* Synchronize cursor image */ @@ -125,24 +125,25 @@ void guac_common_cursor_dup(guac_common_cursor* cursor, guac_user* user, /** * Callback for guac_client_foreach_user() which sends the current cursor - * position to any given user except the user that moved the cursor last. + * position and button state to any given user except the user that moved the + * cursor last. * * @param data - * A pointer to the guac_common_cursor whose position should be broadcast - * to all users except the user that moved the cursor last. + * A pointer to the guac_common_cursor whose state should be broadcast to + * all users except the user that moved the cursor last. * * @return * Always NULL. */ -static void* guac_common_cursor_broadcast_position(guac_user* user, +static void* guac_common_cursor_broadcast_state(guac_user* user, void* data) { guac_common_cursor* cursor = (guac_common_cursor*) data; - /* Send cursor position only if the user is not moving the cursor */ + /* Send cursor state only if the user is not moving the cursor */ if (user != cursor->user) { guac_protocol_send_mouse(user->socket, cursor->x, cursor->y, - cursor->timestamp); + cursor->button_mask, cursor->timestamp); guac_socket_flush(user->socket); } @@ -150,22 +151,23 @@ static void* guac_common_cursor_broadcast_position(guac_user* user, } -void guac_common_cursor_move(guac_common_cursor* cursor, guac_user* user, - int x, int y) { +void guac_common_cursor_update(guac_common_cursor* cursor, guac_user* user, + int x, int y, int button_mask) { /* Update current user of cursor */ cursor->user = user; - /* Update cursor position */ + /* Update cursor state */ cursor->x = x; cursor->y = y; + cursor->button_mask = button_mask; - /* Store time at which cursor position was updated */ + /* Store time at which cursor was updated */ cursor->timestamp = guac_timestamp_current(); - /* Notify all other users of change in cursor position */ + /* Notify all other users of change in cursor state */ guac_client_foreach_user(cursor->client, - guac_common_cursor_broadcast_position, cursor); + guac_common_cursor_broadcast_state, cursor); } diff --git a/src/common/recording.c b/src/common/recording.c index e7270d68..875dcc3e 100644 --- a/src/common/recording.c +++ b/src/common/recording.c @@ -180,10 +180,10 @@ void guac_common_recording_free(guac_common_recording* recording) { } void guac_common_recording_report_mouse(guac_common_recording* recording, - int x, int y) { + int x, int y, int button_mask) { /* Report mouse location */ - guac_protocol_send_mouse(recording->socket, x, y, + guac_protocol_send_mouse(recording->socket, x, y, button_mask, guac_timestamp_current()); } diff --git a/src/guacenc/instruction-mouse.c b/src/guacenc/instruction-mouse.c index 50952451..9b9c526a 100644 --- a/src/guacenc/instruction-mouse.c +++ b/src/guacenc/instruction-mouse.c @@ -45,11 +45,11 @@ int guacenc_handle_mouse(guacenc_display* display, int argc, char** argv) { cursor->y = y; /* If no timestamp provided, nothing further to do */ - if (argc < 3) + if (argc < 4) return 0; /* Leverage timestamp to render frame */ - guac_timestamp timestamp = guacenc_parse_timestamp(argv[2]); + guac_timestamp timestamp = guacenc_parse_timestamp(argv[3]); return guacenc_display_sync(display, timestamp); } diff --git a/src/libguac/guacamole/protocol.h b/src/libguac/guacamole/protocol.h index 89ad6b28..a3e6c181 100644 --- a/src/libguac/guacamole/protocol.h +++ b/src/libguac/guacamole/protocol.h @@ -159,6 +159,19 @@ int vguac_protocol_send_log(guac_socket* socket, const char* format, * @param y * The Y coordinate of the current mouse position. * + * @param button_mask + * An integer value representing the current state of each button, where + * the Nth bit within the integer is set to 1 if and only if the Nth mouse + * button is currently pressed. The lowest-order bit is the left mouse + * button, followed by the middle button, right button, and finally the up + * and down buttons of the scroll wheel. + * + * @see GUAC_CLIENT_MOUSE_LEFT + * @see GUAC_CLIENT_MOUSE_MIDDLE + * @see GUAC_CLIENT_MOUSE_RIGHT + * @see GUAC_CLIENT_MOUSE_SCROLL_UP + * @see GUAC_CLIENT_MOUSE_SCROLL_DOWN + * * @param timestamp * The server timestamp (in milliseconds) at the point in time this mouse * position was acknowledged. @@ -167,7 +180,7 @@ int vguac_protocol_send_log(guac_socket* socket, const char* format, * Zero on success, non-zero on error. */ int guac_protocol_send_mouse(guac_socket* socket, int x, int y, - guac_timestamp timestamp); + int button_mask, guac_timestamp timestamp); /** * Sends a nest instruction over the given guac_socket connection. diff --git a/src/libguac/protocol.c b/src/libguac/protocol.c index 5e47b8c0..a5fe3e9a 100644 --- a/src/libguac/protocol.c +++ b/src/libguac/protocol.c @@ -685,7 +685,7 @@ int guac_protocol_send_lstroke(guac_socket* socket, } int guac_protocol_send_mouse(guac_socket* socket, int x, int y, - guac_timestamp timestamp) { + int button_mask, guac_timestamp timestamp) { int ret_val; @@ -696,6 +696,8 @@ int guac_protocol_send_mouse(guac_socket* socket, int x, int y, || guac_socket_write_string(socket, ",") || __guac_socket_write_length_int(socket, y) || guac_socket_write_string(socket, ",") + || __guac_socket_write_length_int(socket, button_mask) + || guac_socket_write_string(socket, ",") || __guac_socket_write_length_int(socket, timestamp) || guac_socket_write_string(socket, ";"); diff --git a/src/protocols/rdp/input.c b/src/protocols/rdp/input.c index 7cb3da8f..df9c5439 100644 --- a/src/protocols/rdp/input.c +++ b/src/protocols/rdp/input.c @@ -47,12 +47,12 @@ int guac_rdp_user_mouse_handler(guac_user* user, int x, int y, int mask) { return 0; } - /* Store current mouse location */ - guac_common_cursor_move(rdp_client->display->cursor, user, x, y); + /* Store current mouse location/state */ + guac_common_cursor_update(rdp_client->display->cursor, user, x, y, mask); /* Report mouse position within recording */ if (rdp_client->recording != NULL) - guac_common_recording_report_mouse(rdp_client->recording, x, y); + guac_common_recording_report_mouse(rdp_client->recording, x, y, mask); /* If button mask unchanged, just send move event */ if (mask == rdp_client->mouse_button_mask) diff --git a/src/protocols/ssh/input.c b/src/protocols/ssh/input.c index b4d0cf5c..154c9ab4 100644 --- a/src/protocols/ssh/input.c +++ b/src/protocols/ssh/input.c @@ -43,7 +43,7 @@ int guac_ssh_user_mouse_handler(guac_user* user, int x, int y, int mask) { /* Report mouse position within recording */ if (ssh_client->recording != NULL) - guac_common_recording_report_mouse(ssh_client->recording, x, y); + guac_common_recording_report_mouse(ssh_client->recording, x, y, mask); /* Send mouse event */ guac_terminal_send_mouse(term, user, x, y, mask); diff --git a/src/protocols/telnet/input.c b/src/protocols/telnet/input.c index a6742e42..de551dd0 100644 --- a/src/protocols/telnet/input.c +++ b/src/protocols/telnet/input.c @@ -45,7 +45,8 @@ int guac_telnet_user_mouse_handler(guac_user* user, int x, int y, int mask) { /* Report mouse position within recording */ if (telnet_client->recording != NULL) - guac_common_recording_report_mouse(telnet_client->recording, x, y); + guac_common_recording_report_mouse(telnet_client->recording, x, y, + mask); /* Send mouse if not searching for password or username */ if (settings->password_regex == NULL && settings->username_regex == NULL) diff --git a/src/protocols/vnc/input.c b/src/protocols/vnc/input.c index ab88c43a..1dec1c99 100644 --- a/src/protocols/vnc/input.c +++ b/src/protocols/vnc/input.c @@ -33,12 +33,12 @@ int guac_vnc_user_mouse_handler(guac_user* user, int x, int y, int mask) { guac_vnc_client* vnc_client = (guac_vnc_client*) client->data; rfbClient* rfb_client = vnc_client->rfb_client; - /* Store current mouse location */ - guac_common_cursor_move(vnc_client->display->cursor, user, x, y); + /* Store current mouse location/state */ + guac_common_cursor_update(vnc_client->display->cursor, user, x, y, mask); /* Report mouse position within recording */ if (vnc_client->recording != NULL) - guac_common_recording_report_mouse(vnc_client->recording, x, y); + guac_common_recording_report_mouse(vnc_client->recording, x, y, mask); /* Send VNC event only if finished connecting */ if (rfb_client != NULL) diff --git a/src/terminal/terminal.c b/src/terminal/terminal.c index a253572b..4d2171a0 100644 --- a/src/terminal/terminal.c +++ b/src/terminal/terminal.c @@ -1670,8 +1670,8 @@ static int __guac_terminal_send_mouse(guac_terminal* term, guac_user* user, int released_mask = term->mouse_mask & ~mask; int pressed_mask = ~term->mouse_mask & mask; - /* Store current mouse location */ - guac_common_cursor_move(term->cursor, user, x, y); + /* Store current mouse location/state */ + guac_common_cursor_update(term->cursor, user, x, y, mask); /* Notify scrollbar, do not handle anything handled by scrollbar */ if (guac_terminal_scrollbar_handle_mouse(term->scrollbar, x, y, mask)) {