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>
|
#include <stdlib.h>
|
||||||
|
|
||||||
guac_terminal_scrollbar* guac_terminal_scrollbar_alloc(guac_client* client,
|
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 */
|
/* Allocate scrollbar */
|
||||||
guac_terminal_scrollbar* scrollbar =
|
guac_terminal_scrollbar* scrollbar =
|
||||||
@ -49,6 +49,7 @@ guac_terminal_scrollbar* guac_terminal_scrollbar_alloc(guac_client* client,
|
|||||||
scrollbar->parent = parent;
|
scrollbar->parent = parent;
|
||||||
scrollbar->parent_width = 0;
|
scrollbar->parent_width = 0;
|
||||||
scrollbar->parent_height = 0;
|
scrollbar->parent_height = 0;
|
||||||
|
scrollbar->visible_area = 0;
|
||||||
|
|
||||||
/* Allocate and init layers */
|
/* Allocate and init layers */
|
||||||
scrollbar->container = guac_client_alloc_layer(client);
|
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 */
|
/* Reposition and resize to fit parent */
|
||||||
guac_terminal_scrollbar_parent_resized(scrollbar,
|
guac_terminal_scrollbar_parent_resized(scrollbar,
|
||||||
parent_width, parent_height);
|
parent_width, parent_height, visible_area);
|
||||||
|
|
||||||
return scrollbar;
|
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) {
|
* Updates the position and size of the scrollbar inner box relative to the
|
||||||
/* STUB */
|
* current scrollbar value, bounds, and parent layer dimensions.
|
||||||
}
|
*
|
||||||
|
* @param scrollbar
|
||||||
void guac_terminal_scrollbar_set_value(guac_terminal_scrollbar* scrollbar,
|
* The scrollbar whose inner box should be updated.
|
||||||
int value) {
|
*/
|
||||||
/* STUB */
|
static void __update_box(guac_terminal_scrollbar* scrollbar) {
|
||||||
}
|
|
||||||
|
|
||||||
void guac_terminal_scrollbar_parent_resized(guac_terminal_scrollbar* scrollbar,
|
|
||||||
int parent_width, int parent_height) {
|
|
||||||
|
|
||||||
guac_socket* socket = scrollbar->client->socket;
|
guac_socket* socket = scrollbar->client->socket;
|
||||||
|
|
||||||
/* Calculate container position and dimensions */
|
/* Skip if no scrolling region at all */
|
||||||
int container_x = parent_width - GUAC_TERMINAL_SCROLLBAR_WIDTH;
|
if (scrollbar->min >= scrollbar->max)
|
||||||
int container_y = 0;
|
return;
|
||||||
int container_width = GUAC_TERMINAL_SCROLLBAR_WIDTH;
|
|
||||||
int container_height = parent_height;
|
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 */
|
/* Calculate box position and dimensions */
|
||||||
int box_x = GUAC_TERMINAL_SCROLLBAR_PADDING;
|
int box_x = GUAC_TERMINAL_SCROLLBAR_PADDING;
|
||||||
int box_y = GUAC_TERMINAL_SCROLLBAR_PADDING;
|
int box_y = GUAC_TERMINAL_SCROLLBAR_PADDING
|
||||||
int box_width = GUAC_TERMINAL_SCROLLBAR_WIDTH - GUAC_TERMINAL_SCROLLBAR_PADDING*2;
|
+ (padded_container_height - box_height) * (scrollbar->value - scrollbar->min) / region_size;
|
||||||
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);
|
|
||||||
|
|
||||||
/* Reposition box relative to container and current value */
|
/* Reposition box relative to container and current value */
|
||||||
guac_protocol_send_move(socket,
|
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_rect(socket, scrollbar->box, 0, 0, box_width, box_height);
|
||||||
guac_protocol_send_cfill(socket, GUAC_COMP_SRC, scrollbar->box, 0xFF, 0xFF, 0xFF, 0x80);
|
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;
|
int max;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The size of the visible area, in the same units as min and max.
|
||||||
|
*/
|
||||||
|
int visible_area;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The current scroll value.
|
* The current scroll value.
|
||||||
*/
|
*/
|
||||||
@ -119,11 +124,17 @@ typedef struct guac_terminal_scrollbar {
|
|||||||
* @param parent_height
|
* @param parent_height
|
||||||
* The height of the parent layer, in pixels.
|
* 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
|
* @return
|
||||||
* A newly allocated scrollbar.
|
* A newly allocated scrollbar.
|
||||||
*/
|
*/
|
||||||
guac_terminal_scrollbar* guac_terminal_scrollbar_alloc(guac_client* client,
|
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.
|
* Frees the given scrollbar.
|
||||||
@ -186,8 +197,13 @@ void guac_terminal_scrollbar_set_value(guac_terminal_scrollbar* scrollbar,
|
|||||||
*
|
*
|
||||||
* @param parent_height
|
* @param parent_height
|
||||||
* The new height of the parent layer, in pixels.
|
* 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,
|
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
|
#endif
|
||||||
|
@ -167,6 +167,10 @@ void guac_terminal_reset(guac_terminal* term) {
|
|||||||
term->scroll_end = term->term_height - 1;
|
term->scroll_end = term->term_height - 1;
|
||||||
term->scroll_offset = 0;
|
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 */
|
/* Reset flags */
|
||||||
term->text_selected = false;
|
term->text_selected = false;
|
||||||
term->application_cursor_keys = false;
|
term->application_cursor_keys = false;
|
||||||
@ -251,6 +255,10 @@ guac_terminal* guac_terminal_create(guac_client* client,
|
|||||||
guac_terminal_display_resize(term->display,
|
guac_terminal_display_resize(term->display,
|
||||||
term->term_width, term->term_height);
|
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 */
|
/* Init terminal */
|
||||||
guac_terminal_reset(term);
|
guac_terminal_reset(term);
|
||||||
|
|
||||||
@ -269,10 +277,6 @@ guac_terminal* guac_terminal_create(guac_client* client,
|
|||||||
/* Allocate clipboard */
|
/* Allocate clipboard */
|
||||||
term->clipboard = guac_common_clipboard_alloc(GUAC_TERMINAL_CLIPBOARD_MAX_LENGTH);
|
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;
|
return term;
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -524,6 +528,9 @@ int guac_terminal_scroll_up(guac_terminal* term,
|
|||||||
if (term->buffer->length > term->buffer->available)
|
if (term->buffer->length > term->buffer->available)
|
||||||
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 */
|
/* Update cursor location if within region */
|
||||||
if (term->visible_cursor_row >= start_row &&
|
if (term->visible_cursor_row >= start_row &&
|
||||||
term->visible_cursor_row <= end_row)
|
term->visible_cursor_row <= end_row)
|
||||||
@ -639,6 +646,7 @@ void guac_terminal_scroll_display_down(guac_terminal* terminal,
|
|||||||
|
|
||||||
/* Advance by scroll amount */
|
/* Advance by scroll amount */
|
||||||
terminal->scroll_offset -= scroll_amount;
|
terminal->scroll_offset -= scroll_amount;
|
||||||
|
guac_terminal_scrollbar_set_value(terminal->scrollbar, -terminal->scroll_offset);
|
||||||
|
|
||||||
/* Get row range */
|
/* Get row range */
|
||||||
end_row = terminal->term_height - terminal->scroll_offset - 1;
|
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 */
|
/* Advance by scroll amount */
|
||||||
terminal->scroll_offset += scroll_amount;
|
terminal->scroll_offset += scroll_amount;
|
||||||
|
guac_terminal_scrollbar_set_value(terminal->scrollbar, -terminal->scroll_offset);
|
||||||
|
|
||||||
/* Get row range */
|
/* Get row range */
|
||||||
start_row = -terminal->scroll_offset;
|
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) {
|
if (term->scroll_offset >= shift_amount) {
|
||||||
|
|
||||||
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 */
|
/* Draw characters from scroll at bottom */
|
||||||
__guac_terminal_redraw_rect(term, term->term_height, 0, term->term_height + shift_amount - 1, width-1);
|
__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 */
|
/* Update shift_amount and scroll based on new rows */
|
||||||
shift_amount -= term->scroll_offset;
|
shift_amount -= term->scroll_offset;
|
||||||
term->scroll_offset = 0;
|
term->scroll_offset = 0;
|
||||||
|
guac_terminal_scrollbar_set_value(term->scrollbar, -term->scroll_offset);
|
||||||
|
|
||||||
/* If anything remains, move screen as necessary */
|
/* If anything remains, move screen as necessary */
|
||||||
if (shift_amount > 0) {
|
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);
|
guac_protocol_send_size(socket, GUAC_DEFAULT_LAYER, width, height);
|
||||||
|
|
||||||
/* Notify scrollbar of resize */
|
/* 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 */
|
/* Resize terminal if row/column dimensions have changed */
|
||||||
if (columns != terminal->term_width || rows != terminal->term_height) {
|
if (columns != terminal->term_width || rows != terminal->term_height) {
|
||||||
|
Loading…
Reference in New Issue
Block a user