From 21f109fdeb5f1cbf0631ffa405c0d95301d1a467 Mon Sep 17 00:00:00 2001 From: Michael Jumper Date: Tue, 9 Apr 2013 13:54:23 -0700 Subject: [PATCH] Migrate to cacheable cursors. --- protocols/ssh/Makefile.am | 2 + protocols/ssh/include/cursor.h | 89 ++++++++++++++++++++++++++++++ protocols/ssh/include/ibar.h | 5 +- protocols/ssh/include/ssh_client.h | 11 ++++ protocols/ssh/src/cursor.c | 74 +++++++++++++++++++++++++ protocols/ssh/src/ibar.c | 26 ++++----- protocols/ssh/src/ssh_client.c | 6 +- 7 files changed, 196 insertions(+), 17 deletions(-) create mode 100644 protocols/ssh/include/cursor.h create mode 100644 protocols/ssh/src/cursor.c diff --git a/protocols/ssh/Makefile.am b/protocols/ssh/Makefile.am index 7e9d36bb..283e8305 100644 --- a/protocols/ssh/Makefile.am +++ b/protocols/ssh/Makefile.am @@ -42,12 +42,14 @@ lib_LTLIBRARIES = libguac-client-ssh.la libguac_client_ssh_la_SOURCES = \ src/ibar.c \ + src/cursor.c \ src/ssh_client.c \ src/ssh_handlers.c \ src/terminal.c \ src/terminal_handlers.c noinst_HEADERS = \ + include/cursor.h \ include/ibar.h \ include/ssh_client.h \ include/ssh_handlers.h \ diff --git a/protocols/ssh/include/cursor.h b/protocols/ssh/include/cursor.h new file mode 100644 index 00000000..37d09bed --- /dev/null +++ b/protocols/ssh/include/cursor.h @@ -0,0 +1,89 @@ + +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is libguac-client-ssh. + * + * The Initial Developer of the Original Code is + * Michael Jumper. + * Portions created by the Initial Developer are Copyright (C) 2011 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +#ifndef _GUAC_SSH_CURSOR_H +#define _GUAC_SSH_CURSOR_H + +#include + +typedef struct guac_ssh_cursor { + + /** + * A buffer allocated with guac_client_alloc_buffer() that contains the + * cursor image. + */ + guac_layer* buffer; + + /** + * The width of the cursor in pixels. + */ + int width; + + /** + * The height of the cursor in pixels. + */ + int height; + + /** + * The X coordinate of the cursor hotspot. + */ + int hotspot_x; + + /** + * The Y coordinate of the cursor hotspot. + */ + int hotspot_y; + +} guac_ssh_cursor; + +/** + * Allocates a new cursor, pre-populating the cursor with a newly-allocated + * buffer. + */ +guac_ssh_cursor* guac_ssh_cursor_alloc(guac_client* client); + +/** + * Frees the buffer associated with this cursor as well as the cursor itself. + */ +void guac_ssh_cursor_free(guac_client* client, guac_ssh_cursor* cursor); + +/** + * Set the remote cursor. + */ +void guac_ssh_set_cursor(guac_client* client, guac_ssh_cursor* cursor); + +#endif diff --git a/protocols/ssh/include/ibar.h b/protocols/ssh/include/ibar.h index e86c06a9..66e4ff4f 100644 --- a/protocols/ssh/include/ibar.h +++ b/protocols/ssh/include/ibar.h @@ -67,10 +67,11 @@ extern const cairo_format_t guac_ssh_ibar_format; extern unsigned char guac_ssh_ibar[]; /** - * Set the cursor of the remote display to the embedded cursor graphic. + * Creates a new I-bar cursor, returning the corresponding cursor object. * * @param client The guac_client to send the cursor to. + * @return A new cursor which must be free'd via guac_ssh_cursor_free()/ */ -void guac_ssh_set_ibar(guac_client* client); +guac_ssh_cursor* guac_ssh_create_ibar(guac_client* client); #endif diff --git a/protocols/ssh/include/ssh_client.h b/protocols/ssh/include/ssh_client.h index 2dd3cebd..9da45237 100644 --- a/protocols/ssh/include/ssh_client.h +++ b/protocols/ssh/include/ssh_client.h @@ -46,6 +46,7 @@ #include "ssh_client.h" #include "ssh_handlers.h" #include "terminal.h" +#include "cursor.h" typedef struct ssh_guac_client_data { @@ -62,6 +63,16 @@ typedef struct ssh_guac_client_data { int mod_ctrl; int mouse_mask; + /** + * The cached I-bar cursor. + */ + guac_ssh_cursor* ibar_cursor; + + /** + * The current cursor, used to avoid re-setting the cursor. + */ + guac_ssh_cursor* current_cursor; + } ssh_guac_client_data; int ssh_guac_client_auth(guac_client* client, const char* password); diff --git a/protocols/ssh/src/cursor.c b/protocols/ssh/src/cursor.c new file mode 100644 index 00000000..ea6ad422 --- /dev/null +++ b/protocols/ssh/src/cursor.c @@ -0,0 +1,74 @@ + +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is libguac-client-ssh. + * + * The Initial Developer of the Original Code is + * Michael Jumper. + * Portions created by the Initial Developer are Copyright (C) 2011 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +#include + +#include +#include + +#include "cursor.h" + +guac_ssh_cursor* guac_ssh_cursor_alloc(guac_client* client) { + + /* Alloc new cursor, initialize buffer */ + guac_ssh_cursor* cursor = malloc(sizeof(guac_ssh_cursor)); + cursor->buffer = guac_client_alloc_buffer(client); + + return cursor; + +} + +void guac_ssh_cursor_free(guac_client* client, guac_ssh_cursor* cursor) { + + /* Free buffer */ + guac_client_free_buffer(client, cursor->buffer); + + /* Free cursor */ + free(cursor); + +} + +void guac_ssh_set_cursor(guac_client* client, guac_ssh_cursor* cursor) { + + /* Set cursor */ + guac_protocol_send_cursor(client->socket, + cursor->hotspot_x, cursor->hotspot_y, + cursor->buffer, + 0, 0, cursor->width, cursor->height); + +} + diff --git a/protocols/ssh/src/ibar.c b/protocols/ssh/src/ibar.c index ad17820e..70b969c0 100644 --- a/protocols/ssh/src/ibar.c +++ b/protocols/ssh/src/ibar.c @@ -40,6 +40,8 @@ #include #include +#include "cursor.h" + /* Macros for prettying up the embedded image. */ #define X 0x00,0x00,0x00,0xFF #define U 0x80,0x80,0x80,0xFF @@ -77,13 +79,12 @@ unsigned char guac_ssh_ibar[] = { }; -void guac_ssh_set_ibar(guac_client* client) { +guac_ssh_cursor* guac_ssh_create_ibar(guac_client* client) { guac_socket* socket = client->socket; + guac_ssh_cursor* cursor = guac_ssh_cursor_alloc(client); /* Draw to buffer */ - guac_layer* cursor = guac_client_alloc_buffer(client); - cairo_surface_t* graphic = cairo_image_surface_create_for_data( guac_ssh_ibar, guac_ssh_ibar_format, @@ -91,20 +92,17 @@ void guac_ssh_set_ibar(guac_client* client) { guac_ssh_ibar_height, guac_ssh_ibar_stride); - guac_protocol_send_png(socket, GUAC_COMP_SRC, cursor, 0, 0, graphic); + guac_protocol_send_png(socket, GUAC_COMP_SRC, cursor->buffer, + 0, 0, graphic); cairo_surface_destroy(graphic); - /* Set cursor */ - guac_protocol_send_cursor(socket, - guac_ssh_ibar_width / 2, - guac_ssh_ibar_height / 2, - cursor, - 0, 0, - guac_ssh_ibar_width, - guac_ssh_ibar_height); + /* Initialize cursor properties */ + cursor->width = guac_ssh_ibar_width; + cursor->height = guac_ssh_ibar_height; + cursor->hotspot_x = guac_ssh_ibar_width / 2; + cursor->hotspot_y = guac_ssh_ibar_height / 2; - /* Free buffer */ - guac_client_free_buffer(client, cursor); + return cursor; } diff --git a/protocols/ssh/src/ssh_client.c b/protocols/ssh/src/ssh_client.c index 461548c6..10c567c6 100644 --- a/protocols/ssh/src/ssh_client.c +++ b/protocols/ssh/src/ssh_client.c @@ -116,6 +116,10 @@ int guac_client_init(guac_client* client, int argc, char** argv) { client_data->mod_ctrl = 0; client_data->clipboard_data = NULL; + /* Setup I-bar pointer */ + client_data->current_cursor = + client_data->ibar_cursor = guac_ssh_create_ibar(client); + /* Send name and dimensions */ guac_protocol_send_name(socket, "SSH TEST"); guac_protocol_send_size(socket, @@ -124,7 +128,7 @@ int guac_client_init(guac_client* client, int argc, char** argv) { term->char_height * term->term_height); /* Send I-bar pointer */ - guac_ssh_set_ibar(client); + guac_ssh_set_cursor(client, client_data->ibar_cursor); guac_socket_flush(socket);