diff --git a/src/terminal/Makefile.am b/src/terminal/Makefile.am index 9e2781eb..0fb19264 100644 --- a/src/terminal/Makefile.am +++ b/src/terminal/Makefile.am @@ -34,6 +34,7 @@ noinst_HEADERS = \ cursor.h \ display.h \ ibar.h \ + pointer.h \ scrollbar.h \ terminal.h \ terminal_handlers.h \ @@ -47,6 +48,7 @@ libguac_terminal_la_SOURCES = \ cursor.c \ display.c \ ibar.c \ + pointer.c \ scrollbar.c \ terminal.c \ terminal_handlers.c diff --git a/src/terminal/pointer.c b/src/terminal/pointer.c new file mode 100644 index 00000000..1b7ea272 --- /dev/null +++ b/src/terminal/pointer.c @@ -0,0 +1,94 @@ +/* + * Copyright (C) 2015 Glyptodon LLC + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include "config.h" + +#include "cursor.h" + +#include +#include +#include +#include + +/* Macros for prettying up the embedded image. */ +#define X 0x00,0x00,0x00,0xFF +#define U 0x80,0x80,0x80,0xFF +#define O 0xFF,0xFF,0xFF,0xFF +#define _ 0x00,0x00,0x00,0x00 + +/* Dimensions */ +const int guac_terminal_pointer_width = 11; +const int guac_terminal_pointer_height = 16; + +/* Format */ +const cairo_format_t guac_terminal_pointer_format = CAIRO_FORMAT_ARGB32; +const int guac_terminal_pointer_stride = 44; + +/* Embedded pointer graphic */ +unsigned char guac_terminal_pointer[] = { + + O,_,_,_,_,_,_,_,_,_,_, + O,O,_,_,_,_,_,_,_,_,_, + O,X,O,_,_,_,_,_,_,_,_, + O,X,X,O,_,_,_,_,_,_,_, + O,X,X,X,O,_,_,_,_,_,_, + O,X,X,X,X,O,_,_,_,_,_, + O,X,X,X,X,X,O,_,_,_,_, + O,X,X,X,X,X,X,O,_,_,_, + O,X,X,X,X,X,X,X,O,_,_, + O,X,X,X,X,X,X,X,X,O,_, + O,X,X,X,X,X,O,O,O,O,O, + O,X,X,O,X,X,O,_,_,_,_, + O,X,O,_,O,X,X,O,_,_,_, + O,O,_,_,O,X,X,O,_,_,_, + O,_,_,_,_,O,X,X,O,_,_, + _,_,_,_,_,O,O,O,O,_,_ + +}; + +guac_terminal_cursor* guac_terminal_create_pointer(guac_client* client) { + + guac_socket* socket = client->socket; + guac_terminal_cursor* cursor = guac_terminal_cursor_alloc(client); + + /* Draw to buffer */ + cairo_surface_t* graphic = cairo_image_surface_create_for_data( + guac_terminal_pointer, + guac_terminal_pointer_format, + guac_terminal_pointer_width, + guac_terminal_pointer_height, + guac_terminal_pointer_stride); + + guac_protocol_send_png(socket, GUAC_COMP_SRC, cursor->buffer, + 0, 0, graphic); + cairo_surface_destroy(graphic); + + /* Initialize cursor properties */ + cursor->width = guac_terminal_pointer_width; + cursor->height = guac_terminal_pointer_height; + cursor->hotspot_x = 0; + cursor->hotspot_y = 0; + + return cursor; + +} + diff --git a/src/terminal/pointer.h b/src/terminal/pointer.h new file mode 100644 index 00000000..aae2f3d2 --- /dev/null +++ b/src/terminal/pointer.h @@ -0,0 +1,68 @@ +/* + * Copyright (C) 2015 Glyptodon LLC + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + + +#ifndef GUAC_TERMINAL_POINTER_H +#define GUAC_TERMINAL_POINTER_H + +#include "config.h" + +#include +#include + +/** + * Width of the embedded mouse cursor graphic. + */ +extern const int guac_terminal_pointer_width; + +/** + * Height of the embedded mouse cursor graphic. + */ +extern const int guac_terminal_pointer_height; + +/** + * Number of bytes in each row of the embedded mouse cursor graphic. + */ +extern const int guac_terminal_pointer_stride; + +/** + * The Cairo grapic format of the mouse cursor graphic. + */ +extern const cairo_format_t guac_terminal_pointer_format; + +/** + * Embedded mouse cursor graphic. + */ +extern unsigned char guac_terminal_pointer[]; + +/** + * Creates a new pointer 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_terminal_cursor_free(). + */ +guac_terminal_cursor* guac_terminal_create_pointer(guac_client* client); + +#endif diff --git a/src/terminal/terminal.c b/src/terminal/terminal.c index 48d9842b..4f24ec5a 100644 --- a/src/terminal/terminal.c +++ b/src/terminal/terminal.c @@ -29,6 +29,7 @@ #include "display.h" #include "ibar.h" #include "guac_clipboard.h" +#include "pointer.h" #include "scrollbar.h" #include "terminal.h" #include "terminal_handlers.h" @@ -276,8 +277,9 @@ guac_terminal* guac_terminal_create(guac_client* client, term->mod_shift = 0; /* Set up mouse cursors */ - term->ibar_cursor = guac_terminal_create_ibar(client); - term->blank_cursor = guac_terminal_create_blank(client); + term->pointer_cursor = guac_terminal_create_pointer(client); + term->ibar_cursor = guac_terminal_create_ibar(client); + term->blank_cursor = guac_terminal_create_blank(client); /* Initialize mouse cursor */ term->current_cursor = term->blank_cursor; @@ -313,6 +315,7 @@ void guac_terminal_free(guac_terminal* term) { guac_terminal_scrollbar_free(term->scrollbar); /* Free cursors */ + guac_terminal_cursor_free(term->client, term->pointer_cursor); guac_terminal_cursor_free(term->client, term->ibar_cursor); guac_terminal_cursor_free(term->client, term->blank_cursor); @@ -1392,10 +1395,20 @@ static int __guac_terminal_send_mouse(guac_terminal* term, int x, int y, int mas /* Notify scrollbar, do not handle anything handled by scrollbar */ if (guac_terminal_scrollbar_handle_mouse(term->scrollbar, x, y, mask)) { + + /* Set pointer cursor if mouse is over scrollbar */ + if (term->current_cursor != term->pointer_cursor) { + term->current_cursor = term->pointer_cursor; + guac_terminal_set_cursor(client, term->pointer_cursor); + } + + /* Flush scrollbar */ guac_terminal_scrollbar_flush(term->scrollbar); guac_protocol_send_sync(socket, client->last_sent_timestamp); guac_socket_flush(socket); + return 0; + } term->mouse_mask = mask; @@ -1404,6 +1417,7 @@ static int __guac_terminal_send_mouse(guac_terminal* term, int x, int y, int mas if (term->current_cursor != term->ibar_cursor) { term->current_cursor = term->ibar_cursor; guac_terminal_set_cursor(client, term->ibar_cursor); + guac_protocol_send_sync(socket, client->last_sent_timestamp); guac_socket_flush(socket); } diff --git a/src/terminal/terminal.h b/src/terminal/terminal.h index 3619ae15..60d959d3 100644 --- a/src/terminal/terminal.h +++ b/src/terminal/terminal.h @@ -307,6 +307,11 @@ struct guac_terminal { */ int mouse_mask; + /** + * The cached pointer cursor. + */ + guac_terminal_cursor* pointer_cursor; + /** * The cached I-bar cursor. */