GUAC-803: Update rendering of scrollbar as terminal display is scrolled or resized. Position and scale inner box of scrollbar appropriately.

This commit is contained in:
Michael Jumper 2015-01-26 15:51:50 -08:00
parent 3529bd7664
commit 4018f2c40f
3 changed files with 128 additions and 42 deletions

View File

@ -31,7 +31,7 @@
#include <stdlib.h>
guac_terminal_scrollbar* guac_terminal_scrollbar_alloc(guac_client* client,
const guac_layer* parent, int parent_width, int parent_height) {
const guac_layer* parent, int parent_width, int parent_height, int visible_area) {
/* Allocate scrollbar */
guac_terminal_scrollbar* scrollbar =
@ -49,6 +49,7 @@ guac_terminal_scrollbar* guac_terminal_scrollbar_alloc(guac_client* client,
scrollbar->parent = parent;
scrollbar->parent_width = 0;
scrollbar->parent_height = 0;
scrollbar->visible_area = 0;
/* Allocate and init layers */
scrollbar->container = guac_client_alloc_layer(client);
@ -56,7 +57,7 @@ guac_terminal_scrollbar* guac_terminal_scrollbar_alloc(guac_client* client,
/* Reposition and resize to fit parent */
guac_terminal_scrollbar_parent_resized(scrollbar,
parent_width, parent_height);
parent_width, parent_height, visible_area);
return scrollbar;
@ -73,41 +74,37 @@ void guac_terminal_scrollbar_free(guac_terminal_scrollbar* scrollbar) {
}
void guac_terminal_scrollbar_set_bounds(guac_terminal_scrollbar* scrollbar,
int min, int max) {
/* STUB */
}
void guac_terminal_scrollbar_set_value(guac_terminal_scrollbar* scrollbar,
int value) {
/* STUB */
}
void guac_terminal_scrollbar_parent_resized(guac_terminal_scrollbar* scrollbar,
int parent_width, int parent_height) {
/**
* Updates the position and size of the scrollbar inner box relative to the
* current scrollbar value, bounds, and parent layer dimensions.
*
* @param scrollbar
* The scrollbar whose inner box should be updated.
*/
static void __update_box(guac_terminal_scrollbar* scrollbar) {
guac_socket* socket = scrollbar->client->socket;
/* Calculate container position and dimensions */
int container_x = parent_width - GUAC_TERMINAL_SCROLLBAR_WIDTH;
int container_y = 0;
int container_width = GUAC_TERMINAL_SCROLLBAR_WIDTH;
int container_height = parent_height;
/* Skip if no scrolling region at all */
if (scrollbar->min >= scrollbar->max)
return;
int region_size = scrollbar->max - scrollbar->min;
/* Calculate box dimensions */
int box_width = GUAC_TERMINAL_SCROLLBAR_WIDTH - GUAC_TERMINAL_SCROLLBAR_PADDING*2;
int box_height = GUAC_TERMINAL_SCROLLBAR_MIN_HEIGHT;
/* Size box relative to visible area */
int padded_container_height = (scrollbar->parent_height - GUAC_TERMINAL_SCROLLBAR_PADDING*2);
int proportional_height = padded_container_height * scrollbar->visible_area / (region_size + scrollbar->visible_area);
if (proportional_height > box_height)
box_height = proportional_height;
/* Calculate box position and dimensions */
int box_x = GUAC_TERMINAL_SCROLLBAR_PADDING;
int box_y = GUAC_TERMINAL_SCROLLBAR_PADDING;
int box_width = GUAC_TERMINAL_SCROLLBAR_WIDTH - GUAC_TERMINAL_SCROLLBAR_PADDING*2;
int box_height = 64; /* STUB */
/* Reposition container relative to parent dimensions */
guac_protocol_send_move(socket,
scrollbar->container, scrollbar->parent,
container_x, container_y, 0);
/* Resize to fit within parent */
guac_protocol_send_size(socket, scrollbar->container,
container_width, container_height);
int box_y = GUAC_TERMINAL_SCROLLBAR_PADDING
+ (padded_container_height - box_height) * (scrollbar->value - scrollbar->min) / region_size;
/* Reposition box relative to container and current value */
guac_protocol_send_move(socket,
@ -122,9 +119,70 @@ void guac_terminal_scrollbar_parent_resized(guac_terminal_scrollbar* scrollbar,
guac_protocol_send_rect(socket, scrollbar->box, 0, 0, box_width, box_height);
guac_protocol_send_cfill(socket, GUAC_COMP_SRC, scrollbar->box, 0xFF, 0xFF, 0xFF, 0x80);
/* Assign new dimensions */
scrollbar->parent_width = parent_width;
scrollbar->parent_height = parent_height;
}
void guac_terminal_scrollbar_set_bounds(guac_terminal_scrollbar* scrollbar,
int min, int max) {
/* Fit value within bounds */
if (scrollbar->value > max)
scrollbar->value = max;
else if (scrollbar->value < min)
scrollbar->value = min;
/* Update bounds */
scrollbar->min = min;
scrollbar->max = max;
/* Update box position and size */
__update_box(scrollbar);
}
void guac_terminal_scrollbar_set_value(guac_terminal_scrollbar* scrollbar,
int value) {
/* Fit value within bounds */
if (value > scrollbar->max)
value = scrollbar->max;
else if (value < scrollbar->min)
value = scrollbar->min;
/* Update value */
scrollbar->value = value;
/* Update box position and size */
__update_box(scrollbar);
}
void guac_terminal_scrollbar_parent_resized(guac_terminal_scrollbar* scrollbar,
int parent_width, int parent_height, int visible_area) {
guac_socket* socket = scrollbar->client->socket;
/* Calculate container position and dimensions */
int container_x = parent_width - GUAC_TERMINAL_SCROLLBAR_WIDTH;
int container_y = 0;
int container_width = GUAC_TERMINAL_SCROLLBAR_WIDTH;
int container_height = parent_height;
/* Reposition container relative to parent dimensions */
guac_protocol_send_move(socket,
scrollbar->container, scrollbar->parent,
container_x, container_y, 0);
/* Resize to fit within parent */
guac_protocol_send_size(socket, scrollbar->container,
container_width, container_height);
/* Assign new dimensions */
scrollbar->parent_width = parent_width;
scrollbar->parent_height = parent_height;
scrollbar->visible_area = visible_area;
/* Update box position and size */
__update_box(scrollbar);
}

View File

@ -91,6 +91,11 @@ typedef struct guac_terminal_scrollbar {
*/
int max;
/**
* The size of the visible area, in the same units as min and max.
*/
int visible_area;
/**
* The current scroll value.
*/
@ -119,11 +124,17 @@ typedef struct guac_terminal_scrollbar {
* @param parent_height
* The height of the parent layer, in pixels.
*
* @param visible_area
* The amount of scrollable data that can be shown within the parent layer
* at any given time. This value uses the same units as min, max, and the
* current scroll value.
*
* @return
* A newly allocated scrollbar.
*/
guac_terminal_scrollbar* guac_terminal_scrollbar_alloc(guac_client* client,
const guac_layer* parent, int parent_width, int parent_height);
const guac_layer* parent, int parent_width, int parent_height,
int visible_area);
/**
* Frees the given scrollbar.
@ -186,8 +197,13 @@ void guac_terminal_scrollbar_set_value(guac_terminal_scrollbar* scrollbar,
*
* @param parent_height
* The new height of the parent layer, in pixels.
*
* @param visible_area
* The amount of scrollable data that can be shown within the parent layer
* at any given time. This value uses the same units as min, max, and the
* current scroll value.
*/
void guac_terminal_scrollbar_parent_resized(guac_terminal_scrollbar* scrollbar,
int parent_width, int parent_height);
int parent_width, int parent_height, int visible_area);
#endif

View File

@ -167,6 +167,10 @@ void guac_terminal_reset(guac_terminal* term) {
term->scroll_end = term->term_height - 1;
term->scroll_offset = 0;
/* Reset scrollbar bounds */
guac_terminal_scrollbar_set_bounds(term->scrollbar, term->term_height - term->buffer->length, 0);
guac_terminal_scrollbar_set_value(term->scrollbar, -term->scroll_offset);
/* Reset flags */
term->text_selected = false;
term->application_cursor_keys = false;
@ -251,6 +255,10 @@ guac_terminal* guac_terminal_create(guac_client* client,
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);
/* Init terminal */
guac_terminal_reset(term);
@ -269,10 +277,6 @@ guac_terminal* guac_terminal_create(guac_client* client,
/* Allocate clipboard */
term->clipboard = guac_common_clipboard_alloc(GUAC_TERMINAL_CLIPBOARD_MAX_LENGTH);
/* Allocate scrollbar */
term->scrollbar = guac_terminal_scrollbar_alloc(term->client,
GUAC_DEFAULT_LAYER, width, height);
return term;
}
@ -524,6 +528,9 @@ int guac_terminal_scroll_up(guac_terminal* term,
if (term->buffer->length > term->buffer->available)
term->buffer->length = term->buffer->available;
/* Reset scrollbar bounds */
guac_terminal_scrollbar_set_bounds(term->scrollbar, term->term_height - term->buffer->length, 0);
/* Update cursor location if within region */
if (term->visible_cursor_row >= start_row &&
term->visible_cursor_row <= end_row)
@ -639,6 +646,7 @@ void guac_terminal_scroll_display_down(guac_terminal* terminal,
/* Advance by scroll amount */
terminal->scroll_offset -= scroll_amount;
guac_terminal_scrollbar_set_value(terminal->scrollbar, -terminal->scroll_offset);
/* Get row range */
end_row = terminal->term_height - terminal->scroll_offset - 1;
@ -703,6 +711,7 @@ void guac_terminal_scroll_display_up(guac_terminal* terminal,
/* Advance by scroll amount */
terminal->scroll_offset += scroll_amount;
guac_terminal_scrollbar_set_value(terminal->scrollbar, -terminal->scroll_offset);
/* Get row range */
start_row = -terminal->scroll_offset;
@ -1080,6 +1089,7 @@ static void __guac_terminal_resize(guac_terminal* term, int width, int height) {
if (term->scroll_offset >= shift_amount) {
term->scroll_offset -= shift_amount;
guac_terminal_scrollbar_set_value(term->scrollbar, -term->scroll_offset);
/* Draw characters from scroll at bottom */
__guac_terminal_redraw_rect(term, term->term_height, 0, term->term_height + shift_amount - 1, width-1);
@ -1095,6 +1105,7 @@ static void __guac_terminal_resize(guac_terminal* term, int width, int height) {
/* Update shift_amount and scroll based on new rows */
shift_amount -= term->scroll_offset;
term->scroll_offset = 0;
guac_terminal_scrollbar_set_value(term->scrollbar, -term->scroll_offset);
/* If anything remains, move screen as necessary */
if (shift_amount > 0) {
@ -1139,7 +1150,8 @@ int guac_terminal_resize(guac_terminal* terminal, int width, int height) {
guac_protocol_send_size(socket, GUAC_DEFAULT_LAYER, width, height);
/* Notify scrollbar of resize */
guac_terminal_scrollbar_parent_resized(terminal->scrollbar, width, height);
guac_terminal_scrollbar_parent_resized(terminal->scrollbar, width, height, rows);
guac_terminal_scrollbar_set_bounds(terminal->scrollbar, rows - terminal->buffer->length, 0);
/* Resize terminal if row/column dimensions have changed */
if (columns != terminal->term_width || rows != terminal->term_height) {