diff --git a/Makefile.am b/Makefile.am index 1836cffa..562d712a 100644 --- a/Makefile.am +++ b/Makefile.am @@ -46,7 +46,7 @@ SUBDIRS += src/common-ssh endif if ENABLE_TERMINAL -#SUBDIRS += src/terminal +SUBDIRS += src/terminal endif if ENABLE_RDP diff --git a/src/terminal/Makefile.am b/src/terminal/Makefile.am index f2cfb550..e14c12cf 100644 --- a/src/terminal/Makefile.am +++ b/src/terminal/Makefile.am @@ -26,15 +26,11 @@ ACLOCAL_AMFLAGS = -I m4 noinst_LTLIBRARIES = libguac_terminal.la noinst_HEADERS = \ - blank.h \ buffer.h \ char_mappings.h \ common.h \ - cursor.h \ display.h \ - ibar.h \ packet.h \ - pointer.h \ scrollbar.h \ terminal.h \ terminal_handlers.h \ @@ -42,15 +38,11 @@ noinst_HEADERS = \ typescript.h libguac_terminal_la_SOURCES = \ - blank.c \ buffer.c \ char_mappings.c \ common.c \ - cursor.c \ display.c \ - ibar.c \ packet.c \ - pointer.c \ scrollbar.c \ terminal.c \ terminal_handlers.c \ diff --git a/src/terminal/blank.c b/src/terminal/blank.c deleted file mode 100644 index f2165275..00000000 --- a/src/terminal/blank.c +++ /dev/null @@ -1,51 +0,0 @@ -/* - * Copyright (C) 2013 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 - -guac_terminal_cursor* guac_terminal_create_blank(guac_client* client) { - - guac_socket* socket = client->socket; - guac_terminal_cursor* cursor = guac_terminal_cursor_alloc(client); - - /* Set buffer to a single 1x1 transparent rectangle */ - guac_protocol_send_rect(socket, cursor->buffer, 0, 0, 1, 1); - guac_protocol_send_cfill(socket, GUAC_COMP_SRC, cursor->buffer, - 0x00, 0x00, 0x00, 0x00); - - /* Initialize cursor properties */ - cursor->width = 1; - cursor->height = 1; - cursor->hotspot_x = 0; - cursor->hotspot_y = 0; - - return cursor; - -} - diff --git a/src/terminal/blank.h b/src/terminal/blank.h deleted file mode 100644 index 0d22797b..00000000 --- a/src/terminal/blank.h +++ /dev/null @@ -1,42 +0,0 @@ -/* - * Copyright (C) 2013 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_BLANK_H -#define _GUAC_TERMINAL_BLANK_H - -#include "config.h" - -#include "cursor.h" - -#include -#include - -/** - * Creates a new blank 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_blank(guac_client* client); - -#endif diff --git a/src/terminal/cursor.c b/src/terminal/cursor.c deleted file mode 100644 index 9bd00264..00000000 --- a/src/terminal/cursor.c +++ /dev/null @@ -1,61 +0,0 @@ -/* - * Copyright (C) 2013 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 - -guac_terminal_cursor* guac_terminal_cursor_alloc(guac_client* client) { - - /* Alloc new cursor, initialize buffer */ - guac_terminal_cursor* cursor = malloc(sizeof(guac_terminal_cursor)); - cursor->buffer = guac_client_alloc_buffer(client); - - return cursor; - -} - -void guac_terminal_cursor_free(guac_client* client, guac_terminal_cursor* cursor) { - - /* Free buffer */ - guac_client_free_buffer(client, cursor->buffer); - - /* Free cursor */ - free(cursor); - -} - -void guac_terminal_set_cursor(guac_client* client, guac_terminal_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/src/terminal/cursor.h b/src/terminal/cursor.h deleted file mode 100644 index ffa5ca8f..00000000 --- a/src/terminal/cursor.h +++ /dev/null @@ -1,78 +0,0 @@ -/* - * Copyright (C) 2013 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_CURSOR_H -#define _GUAC_TERMINAL_CURSOR_H - -#include "config.h" - -#include -#include - -typedef struct guac_terminal_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_terminal_cursor; - -/** - * Allocates a new cursor, pre-populating the cursor with a newly-allocated - * buffer. - */ -guac_terminal_cursor* guac_terminal_cursor_alloc(guac_client* client); - -/** - * Frees the buffer associated with this cursor as well as the cursor itself. - */ -void guac_terminal_cursor_free(guac_client* client, guac_terminal_cursor* cursor); - -/** - * Set the remote cursor. - */ -void guac_terminal_set_cursor(guac_client* client, guac_terminal_cursor* cursor); - -#endif diff --git a/src/terminal/display.c b/src/terminal/display.c index 5a3b40f5..56123bc2 100644 --- a/src/terminal/display.c +++ b/src/terminal/display.c @@ -75,7 +75,7 @@ static void __guac_terminal_display_clear_select(guac_terminal_display* display) guac_protocol_send_cfill(socket, GUAC_COMP_SRC, select_layer, 0x00, 0x00, 0x00, 0x00); - guac_protocol_send_sync(socket, display->client->last_sent_timestamp); + guac_client_end_frame(display->client); guac_socket_flush(socket); /* Text is no longer selected */ @@ -845,6 +845,23 @@ void guac_terminal_display_flush(guac_terminal_display* display) { } +void guac_terminal_display_dup(guac_terminal_display* display, guac_user* user, + guac_socket* socket) { + + /* Create default surface */ + guac_common_surface_dup(display->display_surface, user, socket); + + /* Select layer is a child of the display layer */ + guac_protocol_send_move(socket, display->select_layer, + display->display_layer, 0, 0, 0); + + /* Send select layer size */ + guac_protocol_send_size(socket, display->select_layer, + display->char_width * display->width, + display->char_height * display->height); + +} + void guac_terminal_display_commit_select(guac_terminal_display* display) { display->selection_committed = true; } @@ -935,7 +952,7 @@ void guac_terminal_display_select(guac_terminal_display* display, guac_protocol_send_cfill(socket, GUAC_COMP_SRC, select_layer, 0x00, 0x80, 0xFF, 0x60); - guac_protocol_send_sync(socket, display->client->last_sent_timestamp); + guac_client_end_frame(display->client); guac_socket_flush(socket); } diff --git a/src/terminal/display.h b/src/terminal/display.h index d42d99bd..b11c0509 100644 --- a/src/terminal/display.h +++ b/src/terminal/display.h @@ -333,6 +333,23 @@ void guac_terminal_display_resize(guac_terminal_display* display, int width, int */ void guac_terminal_display_flush(guac_terminal_display* display); +/** + * Initializes and syncs the current terminal display state for the given user + * that has just joined the connection, sending the necessary instructions to + * completely recreate and redraw the terminal rendering over the given socket. + * + * @param display + * The terminal display to sync to the given user. + * + * @param user + * The user that has just joined the connection. + * + * @param socket + * The socket over which any necessary instructions should be sent. + */ +void guac_terminal_display_dup(guac_terminal_display* display, guac_user* user, + guac_socket* socket); + /** * Draws the text selection rectangle from the given coordinates to the given end coordinates. */ diff --git a/src/terminal/ibar.c b/src/terminal/ibar.c deleted file mode 100644 index 7ba69c3b..00000000 --- a/src/terminal/ibar.c +++ /dev/null @@ -1,94 +0,0 @@ -/* - * Copyright (C) 2013 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_ibar_width = 7; -const int guac_terminal_ibar_height = 16; - -/* Format */ -const cairo_format_t guac_terminal_ibar_format = CAIRO_FORMAT_ARGB32; -const int guac_terminal_ibar_stride = 28; - -/* Embedded pointer graphic */ -unsigned char guac_terminal_ibar[] = { - - X,X,X,X,X,X,X, - X,O,O,U,O,O,X, - X,X,X,O,X,X,X, - _,_,X,O,X,_,_, - _,_,X,O,X,_,_, - _,_,X,O,X,_,_, - _,_,X,O,X,_,_, - _,_,X,O,X,_,_, - _,_,X,O,X,_,_, - _,_,X,O,X,_,_, - _,_,X,O,X,_,_, - _,_,X,O,X,_,_, - _,_,X,O,X,_,_, - X,X,X,O,X,X,X, - X,O,O,U,O,O,X, - X,X,X,X,X,X,X - -}; - -guac_terminal_cursor* guac_terminal_create_ibar(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_ibar, - guac_terminal_ibar_format, - guac_terminal_ibar_width, - guac_terminal_ibar_height, - guac_terminal_ibar_stride); - - guac_client_stream_png(client, socket, GUAC_COMP_SRC, cursor->buffer, - 0, 0, graphic); - cairo_surface_destroy(graphic); - - /* Initialize cursor properties */ - cursor->width = guac_terminal_ibar_width; - cursor->height = guac_terminal_ibar_height; - cursor->hotspot_x = guac_terminal_ibar_width / 2; - cursor->hotspot_y = guac_terminal_ibar_height / 2; - - return cursor; - -} - diff --git a/src/terminal/ibar.h b/src/terminal/ibar.h deleted file mode 100644 index bbbc6578..00000000 --- a/src/terminal/ibar.h +++ /dev/null @@ -1,65 +0,0 @@ -/* - * Copyright (C) 2013 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_IBAR_H -#define _GUAC_TERMINAL_IBAR_H - -#include "config.h" - -#include -#include - -/** - * Width of the embedded mouse cursor graphic. - */ -extern const int guac_terminal_ibar_width; - -/** - * Height of the embedded mouse cursor graphic. - */ -extern const int guac_terminal_ibar_height; - -/** - * Number of bytes in each row of the embedded mouse cursor graphic. - */ -extern const int guac_terminal_ibar_stride; - -/** - * The Cairo grapic format of the mouse cursor graphic. - */ -extern const cairo_format_t guac_terminal_ibar_format; - -/** - * Embedded mouse cursor graphic. - */ -extern unsigned char guac_terminal_ibar[]; - -/** - * 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_terminal_cursor_free()/ - */ -guac_terminal_cursor* guac_terminal_create_ibar(guac_client* client); - -#endif diff --git a/src/terminal/pointer.c b/src/terminal/pointer.c deleted file mode 100644 index 72e99e3b..00000000 --- a/src/terminal/pointer.c +++ /dev/null @@ -1,94 +0,0 @@ -/* - * 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_client_stream_png(client, 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 deleted file mode 100644 index aae2f3d2..00000000 --- a/src/terminal/pointer.h +++ /dev/null @@ -1,68 +0,0 @@ -/* - * 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/scrollbar.c b/src/terminal/scrollbar.c index 785e909a..b62dfe0a 100644 --- a/src/terminal/scrollbar.c +++ b/src/terminal/scrollbar.c @@ -89,6 +89,142 @@ void guac_terminal_scrollbar_free(guac_terminal_scrollbar* scrollbar) { } +/** + * Moves the main scrollbar layer to the position indicated within the given + * scrollbar render state, sending any necessary Guacamole instructions over + * the given socket. + * + * @param scrollbar + * The scrollbar to reposition. + * + * @param state + * The guac_terminal_scrollbar_render_state describing the new scrollbar + * position. + * + * @param socket + * The guac_socket over which any instructions necessary to perform the + * render operation should be sent. + */ +static void guac_terminal_scrollbar_move_container( + guac_terminal_scrollbar* scrollbar, + guac_terminal_scrollbar_render_state* state, + guac_socket* socket) { + + /* Send scrollbar position */ + guac_protocol_send_move(socket, + scrollbar->container, scrollbar->parent, + state->container_x, + state->container_y, + 0); + +} + +/** + * Resizes and redraws the main scrollbar layer according to the given + * scrollbar render state, sending any necessary Guacamole instructions over + * the given socket. + * + * @param scrollbar + * The scrollbar to resize and redraw. + * + * @param state + * The guac_terminal_scrollbar_render_state describing the new scrollbar + * size and appearance. + * + * @param socket + * The guac_socket over which any instructions necessary to perform the + * render operation should be sent. + */ +static void guac_terminal_scrollbar_draw_container( + guac_terminal_scrollbar* scrollbar, + guac_terminal_scrollbar_render_state* state, + guac_socket* socket) { + + /* Set container size */ + guac_protocol_send_size(socket, scrollbar->container, + state->container_width, + state->container_height); + + /* Fill container with solid color */ + guac_protocol_send_rect(socket, scrollbar->container, 0, 0, + state->container_width, + state->container_height); + + guac_protocol_send_cfill(socket, GUAC_COMP_SRC, scrollbar->container, + 0x80, 0x80, 0x80, 0x40); + +} + +/** + * Moves the handle layer of the scrollbar to the position indicated within the + * given scrollbar render state, sending any necessary Guacamole instructions + * over the given socket. The handle is the portion of the scrollbar that + * indicates the current scroll value and which the user can click and drag to + * change the value. + * + * @param scrollbar + * The scrollbar associated with the handle being repositioned. + * + * @param state + * The guac_terminal_scrollbar_render_state describing the new scrollbar + * handle position. + * + * @param socket + * The guac_socket over which any instructions necessary to perform the + * render operation should be sent. + */ +static void guac_terminal_scrollbar_move_handle( + guac_terminal_scrollbar* scrollbar, + guac_terminal_scrollbar_render_state* state, + guac_socket* socket) { + + /* Send handle position */ + guac_protocol_send_move(socket, + scrollbar->handle, scrollbar->container, + state->handle_x, + state->handle_y, + 0); + +} + +/** + * Resizes and redraws the handle layer of the scrollbar according to the given + * scrollbar render state, sending any necessary Guacamole instructions over + * the given socket. The handle is the portion of the scrollbar that indicates + * the current scroll value and which the user can click and drag to change the + * value. + * + * @param scrollbar + * The scrollbar associated with the handle being resized and redrawn. + * + * @param state + * The guac_terminal_scrollbar_render_state describing the new scrollbar + * handle size and appearance. + * + * @param socket + * The guac_socket over which any instructions necessary to perform the + * render operation should be sent. + */ +static void guac_terminal_scrollbar_draw_handle( + guac_terminal_scrollbar* scrollbar, + guac_terminal_scrollbar_render_state* state, + guac_socket* socket) { + + /* Set handle size */ + guac_protocol_send_size(socket, scrollbar->handle, + state->handle_width, + state->handle_height); + + /* Fill handle with solid color */ + guac_protocol_send_rect(socket, scrollbar->handle, 0, 0, + state->handle_width, + state->handle_height); + + guac_protocol_send_cfill(socket, GUAC_COMP_SRC, scrollbar->handle, + 0xA0, 0xA0, 0xA0, 0x8F); + +} + /** * Calculates the state of the scroll bar, given its minimum, maximum, current * values, and the state of any dragging operation. The resulting render state @@ -199,6 +335,22 @@ static void calculate_state(guac_terminal_scrollbar* scrollbar, } +void guac_terminal_scrollbar_dup(guac_terminal_scrollbar* scrollbar, + guac_user* user, guac_socket* socket) { + + /* Get old state */ + guac_terminal_scrollbar_render_state* state = &scrollbar->render_state; + + /* Send scrollbar container */ + guac_terminal_scrollbar_draw_container(scrollbar, state, socket); + guac_terminal_scrollbar_move_container(scrollbar, state, socket); + + /* Send handle */ + guac_terminal_scrollbar_draw_handle(scrollbar, state, socket); + guac_terminal_scrollbar_move_handle(scrollbar, state, socket); + +} + void guac_terminal_scrollbar_flush(guac_terminal_scrollbar* scrollbar) { guac_socket* socket = scrollbar->client->socket; @@ -219,63 +371,25 @@ void guac_terminal_scrollbar_flush(guac_terminal_scrollbar* scrollbar) { /* Reposition container if moved */ if (old_state->container_x != new_state.container_x || old_state->container_y != new_state.container_y) { - - guac_protocol_send_move(socket, - scrollbar->container, scrollbar->parent, - new_state.container_x, - new_state.container_y, - 0); - + guac_terminal_scrollbar_move_container(scrollbar, &new_state, socket); } /* Resize and redraw container if size changed */ if (old_state->container_width != new_state.container_width || old_state->container_height != new_state.container_height) { - - /* Set new size */ - guac_protocol_send_size(socket, scrollbar->container, - new_state.container_width, - new_state.container_height); - - /* Fill container with solid color */ - guac_protocol_send_rect(socket, scrollbar->container, 0, 0, - new_state.container_width, - new_state.container_height); - - guac_protocol_send_cfill(socket, GUAC_COMP_SRC, scrollbar->container, - 0x80, 0x80, 0x80, 0x40); - + guac_terminal_scrollbar_draw_container(scrollbar, &new_state, socket); } /* Reposition handle if moved */ if (old_state->handle_x != new_state.handle_x || old_state->handle_y != new_state.handle_y) { - - guac_protocol_send_move(socket, - scrollbar->handle, scrollbar->container, - new_state.handle_x, - new_state.handle_y, - 0); - + guac_terminal_scrollbar_move_handle(scrollbar, &new_state, socket); } /* Resize and redraw handle if size changed */ if (old_state->handle_width != new_state.handle_width || old_state->handle_height != new_state.handle_height) { - - /* Send new size */ - guac_protocol_send_size(socket, scrollbar->handle, - new_state.handle_width, - new_state.handle_height); - - /* Fill and stroke handle with solid color */ - guac_protocol_send_rect(socket, scrollbar->handle, 0, 0, - new_state.handle_width, - new_state.handle_height); - - guac_protocol_send_cfill(socket, GUAC_COMP_SRC, scrollbar->handle, - 0xA0, 0xA0, 0xA0, 0x8F); - + guac_terminal_scrollbar_draw_handle(scrollbar, &new_state, socket); } /* Store current render state */ diff --git a/src/terminal/scrollbar.h b/src/terminal/scrollbar.h index 13c66b12..cd66702b 100644 --- a/src/terminal/scrollbar.h +++ b/src/terminal/scrollbar.h @@ -252,6 +252,24 @@ void guac_terminal_scrollbar_free(guac_terminal_scrollbar* scrollbar); */ void guac_terminal_scrollbar_flush(guac_terminal_scrollbar* scrollbar); +/** + * Forces a complete redraw / resync of scrollbar state for the given user that + * has just joined the connection, sending the necessary instructions to + * completely recreate and redraw the scrollbar rendering over the given + * socket. + * + * @param scrollbar + * The scrollbar to sync to the given user. + * + * @param user + * The user that has just joined the connection. + * + * @param socket + * The socket over which any necessary instructions should be sent. + */ +void guac_terminal_scrollbar_dup(guac_terminal_scrollbar* scrollbar, + guac_user* user, guac_socket* socket); + /** * Sets the minimum and maximum allowed scroll values of the given scrollbar * to the given values. If necessary, the current value of the scrollbar will diff --git a/src/terminal/terminal.c b/src/terminal/terminal.c index d87dfd5a..ccf81603 100644 --- a/src/terminal/terminal.c +++ b/src/terminal/terminal.c @@ -23,14 +23,11 @@ #include "config.h" #include "buffer.h" -#include "blank.h" #include "common.h" -#include "cursor.h" #include "display.h" -#include "ibar.h" #include "guac_clipboard.h" +#include "guac_cursor.h" #include "packet.h" -#include "pointer.h" #include "scrollbar.h" #include "terminal.h" #include "terminal_handlers.h" @@ -202,23 +199,24 @@ void guac_terminal_reset(guac_terminal* term) { * @param terminal * The terminal whose background should be painted or repainted. * - * @param width - * The width of the background to draw, in pixels. - * - * @param height - * The height of the background to draw, in pixels. + * @param socket + * The socket over which instructions required to paint / repaint the + * terminal background should be send. */ -static void guac_terminal_paint_background(guac_terminal* terminal, - int width, int height) { +static void guac_terminal_repaint_default_layer(guac_terminal* terminal, + guac_socket* socket) { + int width = terminal->width; + int height = terminal->height; guac_terminal_display* display = terminal->display; - guac_client* client = display->client; - guac_socket* socket = client->socket; /* Get background color */ const guac_terminal_color* color = &guac_terminal_palette[display->default_background]; + /* Reset size */ + guac_protocol_send_size(socket, GUAC_DEFAULT_LAYER, width, height); + /* Paint background color */ guac_protocol_send_rect(socket, GUAC_DEFAULT_LAYER, 0, 0, width, height); guac_protocol_send_cfill(socket, GUAC_COMP_OVER, GUAC_DEFAULT_LAYER, @@ -226,6 +224,40 @@ static void guac_terminal_paint_background(guac_terminal* terminal, } +/** + * Automatically and continuously renders frames of terminal data while the + * associated guac_client is running. + * + * @param data + * A pointer to the guac_terminal that should be continuously rendered + * while its associated guac_client is running. + * + * @return + * Always NULL. + */ +void* guac_terminal_thread(void* data) { + + guac_terminal* terminal = (guac_terminal*) data; + guac_client* client = terminal->client; + + /* Render frames only while client is running */ + while (client->state == GUAC_CLIENT_RUNNING) { + + /* Stop rendering if an error occurs */ + if (guac_terminal_render_frame(terminal)) + break; + + /* Signal end of frame */ + guac_client_end_frame(client); + guac_socket_flush(client->socket); + + } + + /* The client has stopped or an error has occurred */ + return NULL; + +} + guac_terminal* guac_terminal_create(guac_client* client, const char* font_name, int font_size, int dpi, int width, int height, const char* color_scheme) { @@ -305,10 +337,18 @@ guac_terminal* guac_terminal_create(guac_client* client, return NULL; } + /* Init common cursor */ + term->cursor = guac_common_cursor_alloc(client); + /* Init terminal state */ term->current_attributes = default_char.attributes; term->default_char = default_char; + /* Set pixel size */ + term->width = width; + term->height = height; + + /* Calculate character size */ term->term_width = available_width / term->display->char_width; term->term_height = height / term->display->char_height; @@ -337,16 +377,14 @@ guac_terminal* guac_terminal_create(guac_client* client, /* Init terminal lock */ pthread_mutex_init(&(term->lock), NULL); - /* Size display */ - guac_protocol_send_size(term->display->client->socket, - GUAC_DEFAULT_LAYER, width, height); - guac_terminal_paint_background(term, width, height); + /* Repaint and resize overall display */ + guac_terminal_repaint_default_layer(term, client->socket); guac_terminal_display_resize(term->display, term->term_width, term->term_height); /* Allocate scrollbar */ - term->scrollbar = guac_terminal_scrollbar_alloc(term->client, - GUAC_DEFAULT_LAYER, width, height, term->term_height); + term->scrollbar = guac_terminal_scrollbar_alloc(client, GUAC_DEFAULT_LAYER, + width, height, term->term_height); /* Associate scrollbar with this terminal */ term->scrollbar->data = term; @@ -359,30 +397,26 @@ guac_terminal* guac_terminal_create(guac_client* client, term->mod_ctrl = term->mod_shift = 0; - /* Set up mouse cursors */ - 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; - guac_terminal_set_cursor(term->client, term->current_cursor); + term->current_cursor = GUAC_TERMINAL_CURSOR_BLANK; + guac_common_cursor_set_blank(term->cursor); /* Allocate clipboard */ term->clipboard = guac_common_clipboard_alloc(GUAC_TERMINAL_CLIPBOARD_MAX_LENGTH); + /* Start terminal thread */ + if (pthread_create(&(term->thread), NULL, + guac_terminal_thread, (void*) term)) { + guac_terminal_free(term); + return NULL; + } + return term; } void guac_terminal_free(guac_terminal* term) { - /* Close and flush any open pipe stream */ - guac_terminal_pipe_stream_close(term); - - /* Close and flush any active typescript */ - guac_terminal_typescript_free(term->typescript); - /* Close terminal output pipe */ close(term->stdout_pipe_fd[1]); close(term->stdout_pipe_fd[0]); @@ -391,6 +425,15 @@ void guac_terminal_free(guac_terminal* term) { close(term->stdin_pipe_fd[1]); close(term->stdin_pipe_fd[0]); + /* Wait for render thread to finish */ + pthread_join(term->thread, NULL); + + /* Close and flush any open pipe stream */ + guac_terminal_pipe_stream_close(term); + + /* Close and flush any active typescript */ + guac_terminal_typescript_free(term->typescript); + /* Free display */ guac_terminal_display_free(term->display); @@ -403,10 +446,8 @@ void guac_terminal_free(guac_terminal* term) { /* Free scrollbar */ 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); + /* Free the terminal itself */ + free(term); } @@ -565,7 +606,10 @@ int guac_terminal_printf(guac_terminal* terminal, const char* format, ...) { } -void guac_terminal_prompt(guac_terminal* terminal, const char* title, char* str, int size, bool echo) { +char* guac_terminal_prompt(guac_terminal* terminal, const char* title, + bool echo) { + + char buffer[1024]; int pos; char in_byte; @@ -573,16 +617,12 @@ void guac_terminal_prompt(guac_terminal* terminal, const char* title, char* str, /* Print title */ guac_terminal_printf(terminal, "%s", title); - /* Make room for null terminator */ - size--; - /* Read bytes until newline */ pos = 0; - while (pos < size && guac_terminal_read_stdin(terminal, &in_byte, 1) == 1) { + while (guac_terminal_read_stdin(terminal, &in_byte, 1) == 1) { /* Backspace */ if (in_byte == 0x7F) { - if (pos > 0) { guac_terminal_printf(terminal, "\b \b"); pos--; @@ -595,10 +635,11 @@ void guac_terminal_prompt(guac_terminal* terminal, const char* title, char* str, break; } - else { + /* Otherwise, store byte if there is room */ + else if (pos < sizeof(buffer) - 1) { /* Store character, update buffers */ - str[pos++] = in_byte; + buffer[pos++] = in_byte; /* Print character if echoing */ if (echo) @@ -608,10 +649,15 @@ void guac_terminal_prompt(guac_terminal* terminal, const char* title, char* str, } + /* Ignore all other input */ + } /* Terminate string */ - str[pos] = 0; + buffer[pos] = 0; + + /* Return newly-allocated string containing result */ + return strdup(buffer); } @@ -1315,7 +1361,6 @@ int guac_terminal_resize(guac_terminal* terminal, int width, int height) { guac_terminal_display* display = terminal->display; guac_client* client = display->client; - guac_socket* socket = client->socket; /* Acquire exclusive access to terminal */ guac_terminal_lock(terminal); @@ -1329,9 +1374,12 @@ int guac_terminal_resize(guac_terminal* terminal, int width, int height) { int rows = height / display->char_height; int columns = available_width / display->char_width; + /* Set pixel sizes */ + terminal->width = width; + terminal->height = height; + /* Resize default layer to given pixel dimensions */ - guac_protocol_send_size(socket, GUAC_DEFAULT_LAYER, width, height); - guac_terminal_paint_background(terminal, width, height); + guac_terminal_repaint_default_layer(terminal, client->socket); /* Notify scrollbar of resize */ guac_terminal_scrollbar_parent_resized(terminal->scrollbar, width, height, rows); @@ -1391,9 +1439,9 @@ int guac_terminal_send_string(guac_terminal* term, const char* data) { static int __guac_terminal_send_key(guac_terminal* term, int keysym, int pressed) { /* Hide mouse cursor if not already hidden */ - if (term->current_cursor != term->blank_cursor) { - term->current_cursor = term->blank_cursor; - guac_terminal_set_cursor(term->client, term->blank_cursor); + if (term->current_cursor != GUAC_TERMINAL_CURSOR_BLANK) { + term->current_cursor = GUAC_TERMINAL_CURSOR_BLANK; + guac_common_cursor_set_blank(term->cursor); guac_terminal_notify(term); } @@ -1550,7 +1598,8 @@ int guac_terminal_send_key(guac_terminal* term, int keysym, int pressed) { } -static int __guac_terminal_send_mouse(guac_terminal* term, int x, int y, int mask) { +static int __guac_terminal_send_mouse(guac_terminal* term, guac_user* user, + int x, int y, int mask) { guac_client* client = term->client; guac_socket* socket = client->socket; @@ -1559,13 +1608,17 @@ static int __guac_terminal_send_mouse(guac_terminal* term, int x, int y, int mas 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); + /* 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); + if (term->current_cursor != GUAC_TERMINAL_CURSOR_POINTER) { + term->current_cursor = GUAC_TERMINAL_CURSOR_POINTER; + guac_common_cursor_set_pointer(term->cursor); + guac_terminal_notify(term); } guac_terminal_notify(term); @@ -1576,9 +1629,9 @@ static int __guac_terminal_send_mouse(guac_terminal* term, int x, int y, int mas term->mouse_mask = mask; /* Show mouse cursor if not already shown */ - if (term->current_cursor != term->ibar_cursor) { - term->current_cursor = term->ibar_cursor; - guac_terminal_set_cursor(client, term->ibar_cursor); + if (term->current_cursor != GUAC_TERMINAL_CURSOR_IBAR) { + term->current_cursor = GUAC_TERMINAL_CURSOR_IBAR; + guac_common_cursor_set_ibar(term->cursor); guac_terminal_notify(term); } @@ -1639,12 +1692,13 @@ static int __guac_terminal_send_mouse(guac_terminal* term, int x, int y, int mas } -int guac_terminal_send_mouse(guac_terminal* term, int x, int y, int mask) { +int guac_terminal_send_mouse(guac_terminal* term, guac_user* user, + int x, int y, int mask) { int result; guac_terminal_lock(term); - result = __guac_terminal_send_mouse(term, x, y, mask); + result = __guac_terminal_send_mouse(term, user, x, y, mask); guac_terminal_unlock(term); return result; @@ -1861,3 +1915,18 @@ int guac_terminal_create_typescript(guac_terminal* term, const char* path, } +void guac_terminal_dup(guac_terminal* term, guac_user* user, + guac_socket* socket) { + + /* Synchronize display state with new user */ + guac_terminal_repaint_default_layer(term, socket); + guac_terminal_display_dup(term->display, user, socket); + + /* Synchronize mouse cursor */ + guac_common_cursor_dup(term->cursor, user, socket); + + /* Paint scrollbar for joining user */ + guac_terminal_scrollbar_dup(term->scrollbar, user, socket); + +} + diff --git a/src/terminal/terminal.h b/src/terminal/terminal.h index ea1ac1fe..6bc9f102 100644 --- a/src/terminal/terminal.h +++ b/src/terminal/terminal.h @@ -27,9 +27,9 @@ #include "config.h" #include "buffer.h" -#include "cursor.h" #include "display.h" #include "guac_clipboard.h" +#include "guac_cursor.h" #include "scrollbar.h" #include "types.h" #include "typescript.h" @@ -88,6 +88,28 @@ typedef struct guac_terminal guac_terminal; +/** + * All possible mouse cursors used by the terminal emulator. + */ +typedef enum guac_terminal_cursor_type { + + /** + * A transparent (blank) cursor. + */ + GUAC_TERMINAL_CURSOR_BLANK, + + /** + * A standard I-bar cursor for selecting text, etc. + */ + GUAC_TERMINAL_CURSOR_IBAR, + + /** + * A standard triangular mouse pointer for manipulating non-text objects. + */ + GUAC_TERMINAL_CURSOR_POINTER + +} guac_terminal_cursor_type; + /** * Handler for characters printed to the terminal. When a character is printed, * the current char handler for the terminal is called and given that @@ -112,10 +134,15 @@ typedef guac_stream* guac_terminal_file_download_handler(guac_client* client, ch struct guac_terminal { /** - * The Guacamole client this terminal emulator will use for rendering. + * The Guacamole client associated with this terminal emulator. */ guac_client* client; + /** + * The terminal render thread. + */ + pthread_t thread; + /** * Called whenever the necessary terminal codes are sent to change * the path for future file uploads. @@ -176,6 +203,11 @@ struct guac_terminal { */ guac_terminal_typescript* typescript; + /** + * Terminal-wide mouse cursor, synchronized across all users. + */ + guac_common_cursor* cursor; + /** * Graphical representation of the current scroll state. */ @@ -188,6 +220,16 @@ struct guac_terminal { */ int scroll_offset; + /** + * The width of the terminal, in pixels. + */ + int width; + + /** + * The height of the terminal, in pixels. + */ + int height; + /** * The width of the terminal, in characters. */ @@ -366,24 +408,9 @@ struct guac_terminal { int mouse_mask; /** - * The cached pointer cursor. + * The current mouse cursor, to avoid re-setting the cursor image. */ - guac_terminal_cursor* pointer_cursor; - - /** - * The cached I-bar cursor. - */ - guac_terminal_cursor* ibar_cursor; - - /** - * The cached invisible (blank) cursor. - */ - guac_terminal_cursor* blank_cursor; - - /** - * The current cursor, used to avoid re-setting the cursor. - */ - guac_terminal_cursor* current_cursor; + guac_terminal_cursor_type current_cursor; /** * The current contents of the clipboard. @@ -469,11 +496,29 @@ int guac_terminal_write_stdout(guac_terminal* terminal, const char* c, int size) int guac_terminal_notify(guac_terminal* terminal); /** - * Reads a single line from this terminal's STDIN. Input is retrieved in - * the same manner as guac_terminal_read_stdin() and the same restrictions - * apply. + * Reads a single line from this terminal's STDIN, storing the result in a + * newly-allocated string. Input is retrieved in the same manner as + * guac_terminal_read_stdin() and the same restrictions apply. + * + * @param terminal + * The terminal to which the provided title should be output, and from + * whose STDIN the single line of input should be read. + * + * @param title + * The human-readable title to output to the terminal just prior to reading + * from STDIN. + * + * @param echo + * Non-zero if the characters read from STDIN should be echoed back as + * terminal output, or zero if asterisks should be displayed instead. + * + * @return + * A newly-allocated string containing a single line of input read from the + * provided terminal's STDIN. This string must eventually be manually + * freed with a call to free(). */ -void guac_terminal_prompt(guac_terminal* terminal, const char* title, char* str, int size, bool echo); +char* guac_terminal_prompt(guac_terminal* terminal, const char* title, + bool echo); /** * Writes the given format string and arguments to this terminal's STDOUT in @@ -492,7 +537,8 @@ int guac_terminal_send_key(guac_terminal* term, int keysym, int pressed); * Handles the given mouse event, sending data, scrolling, pasting clipboard * data, etc. as necessary. */ -int guac_terminal_send_mouse(guac_terminal* term, int x, int y, int mask); +int guac_terminal_send_mouse(guac_terminal* term, guac_user* user, + int x, int y, int mask); /** * Handles a scroll event received from the scrollbar associated with a @@ -518,6 +564,23 @@ void guac_terminal_clipboard_reset(guac_terminal* term, const char* mimetype); */ void guac_terminal_clipboard_append(guac_terminal* term, const void* data, int length); +/** + * Replicates the current display state to a user that has just joined the + * connection. All instructions necessary to replicate state are sent over the + * given socket. + * + * @param term + * The terminal emulator associated with the connection being joined. + * + * @param user + * The user joining the connection. + * + * @param socket + * The guac_socket specific to the joining user and across which messages + * synchronizing the current display state should be sent. + */ +void guac_terminal_dup(guac_terminal* term, guac_user* user, + guac_socket* socket); /* INTERNAL FUNCTIONS */ diff --git a/src/terminal/terminal_handlers.c b/src/terminal/terminal_handlers.c index ad943b00..c1d71501 100644 --- a/src/terminal/terminal_handlers.c +++ b/src/terminal/terminal_handlers.c @@ -907,7 +907,7 @@ int guac_terminal_set_directory(guac_terminal* term, unsigned char c) { term->upload_path_handler(term->client, filename); else guac_client_log(term->client, GUAC_LOG_DEBUG, - "Cannot set upload path. File is transfer not enabled."); + "Cannot set upload path. File transfer is not enabled."); length = 0; } @@ -932,7 +932,7 @@ int guac_terminal_download(guac_terminal* term, unsigned char c) { term->file_download_handler(term->client, filename); else guac_client_log(term->client, GUAC_LOG_DEBUG, - "Cannot send file. File is transfer not enabled."); + "Cannot send file. File transfer is not enabled."); length = 0; }