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:
parent
3529bd7664
commit
4018f2c40f
@ -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);
|
||||
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
|
@ -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) {
|
||||
|
Loading…
Reference in New Issue
Block a user