Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

GUACAMOLE-1633: Add support of alternate screen buffer #521

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 13 additions & 0 deletions src/terminal/terminal-handlers.c
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,11 @@
*/
#define GUAC_TERMINAL_OK "\x1B[0n"

/**
* Alternative buffer CSI sequence.
*/
#define GUAC_TERMINAL_ALT_BUFFER 1049

/**
* Advances the cursor to the next row, scrolling if the cursor would otherwise
* leave the scrolling region. If the cursor is already outside the scrolling
Expand Down Expand Up @@ -885,6 +890,10 @@ int guac_terminal_csi(guac_terminal* term, unsigned char c) {
if (flag != NULL)
*flag = true;

/* Open alternate screen buffer */
if (argv[0] == GUAC_TERMINAL_ALT_BUFFER)
guac_terminal_switch_buffers(term, true);

break;

/* l: Reset Mode */
Expand All @@ -894,6 +903,10 @@ int guac_terminal_csi(guac_terminal* term, unsigned char c) {
flag = __guac_terminal_get_flag(term, argv[0], private_mode_character);
if (flag != NULL)
*flag = false;

/* Close alternate screen buffer */
if (argv[0] == GUAC_TERMINAL_ALT_BUFFER)
guac_terminal_switch_buffers(term, false);

break;

Expand Down
73 changes: 71 additions & 2 deletions src/terminal/terminal.c
Original file line number Diff line number Diff line change
Expand Up @@ -482,9 +482,11 @@ guac_terminal* guac_terminal_create(guac_client* client,
if (initial_scrollback < GUAC_TERMINAL_MAX_ROWS)
initial_scrollback = GUAC_TERMINAL_MAX_ROWS;

/* Init buffer */
/* Init current and alternate buffer */
term->buffer = guac_terminal_buffer_alloc(initial_scrollback,
&default_char);
term->buffer_alt = NULL;
term->buffer_switched = false;

/* Init display */
term->display = guac_terminal_display_alloc(client,
Expand Down Expand Up @@ -633,8 +635,10 @@ void guac_terminal_free(guac_terminal* term) {
/* Free display */
guac_terminal_display_free(term->display);

/* Free buffer */
/* Free buffers */
guac_terminal_buffer_free(term->buffer);
if (term->buffer_alt != NULL)
guac_terminal_buffer_free(term->buffer_alt);

/* Free scrollbar */
guac_terminal_scrollbar_free(term->scrollbar);
Expand Down Expand Up @@ -2384,3 +2388,68 @@ void guac_terminal_remove_user(guac_terminal* terminal, guac_user* user) {
/* Remove the user from the terminal cursor */
guac_common_cursor_remove_user(terminal->cursor, user);
}

void guac_terminal_switch_buffers(guac_terminal* terminal, bool to_alt) {

/* Already on requested buffer */
if (terminal->buffer_switched == to_alt)
return;

/* Allocate alternate buffer */
if (terminal->buffer_alt == NULL)
terminal->buffer_alt = guac_terminal_buffer_alloc(
terminal->display->height, &terminal->default_char);

/* Keep new buffer state */
terminal->buffer_switched = to_alt;

/* Inversion of buffers pointers to switch to alternate */
guac_terminal_buffer* temp_buffer = terminal->buffer;
terminal->buffer = terminal->buffer_alt;
terminal->buffer_alt = temp_buffer;

/* Switch to alternate buffer */
if (to_alt) {

/* Backup cursor position before switching alternate buffer */
terminal->visible_cursor_col_alt = terminal->visible_cursor_col;
terminal->visible_cursor_row_alt = terminal->visible_cursor_row;
terminal->cursor_col_alt = terminal->cursor_col;
terminal->cursor_row_alt = terminal->cursor_row;

/* Clear screen content and selection */
guac_terminal_reset(terminal);

}

/* Switch to normal buffer */
else {

/* Restore cursor position before switching normal buffer */
terminal->visible_cursor_col = terminal->visible_cursor_col_alt;
terminal->visible_cursor_row = terminal->visible_cursor_row_alt;
terminal->cursor_col = terminal->cursor_col_alt;
terminal->cursor_row = terminal->cursor_row_alt;

/* Repaint and resize overall display */
guac_terminal_repaint_default_layer(terminal, terminal->client->socket);
__guac_terminal_redraw_rect(terminal, 0, 0,
terminal->term_height - 1,
terminal->term_width - 1);

/* Restore scrollbar state */
guac_terminal_scrollbar_set_bounds(terminal->scrollbar,
-guac_terminal_get_available_scroll(terminal), 0);

/* Clear selection */
terminal->text_selected = false;
terminal->selection_committed = false;
guac_terminal_notify(terminal);

/* Free alternate buffer when unused */
guac_terminal_buffer_free(terminal->buffer_alt);
terminal->buffer_alt = NULL;

}

}
45 changes: 45 additions & 0 deletions src/terminal/terminal/terminal-priv.h
Original file line number Diff line number Diff line change
Expand Up @@ -243,6 +243,11 @@ struct guac_terminal {
*/
int cursor_row;

/**
* Backup of cursor_row when using alternate buffer.
*/
int cursor_row_alt;

/**
* The current column location of the cursor. Note that while most
* terminal operations will clip the cursor location within the bounds
Expand All @@ -252,6 +257,11 @@ struct guac_terminal {
*/
int cursor_col;

/**
* Backup of cursor_col when using alternate buffer.
*/
int cursor_col_alt;

/**
* The desired visibility state of the cursor.
*/
Expand All @@ -263,12 +273,22 @@ struct guac_terminal {
*/
int visible_cursor_row;

/**
* Backup of visible_cursor_row when using alternate buffer.
*/
int visible_cursor_row_alt;

/**
* The column of the rendered cursor.
* Will be set to -1 if the cursor is not visible.
*/
int visible_cursor_col;

/**
* Backup of visible_cursor_col when using alternate buffer.
*/
int visible_cursor_col_alt;

/**
* The row of the saved cursor (ESC 7).
*/
Expand Down Expand Up @@ -311,6 +331,18 @@ struct guac_terminal {
*/
guac_terminal_buffer* buffer;

/**
* Alternate buffer.
*/
guac_terminal_buffer* buffer_alt;

/**
* Actual state of the buffer:
* - true if switched to alternate buffer.
* - false if normal buffer.
*/
bool buffer_switched;

/**
* Automatically place a tabstop every N characters. If zero, then no
* tabstops exist automatically.
Expand Down Expand Up @@ -666,5 +698,18 @@ void guac_terminal_copy_rows(guac_terminal* terminal,
*/
void guac_terminal_flush(guac_terminal* terminal);

/**
* Swith betwen normal and alternate buffer.
*
* @param terminal
* Terminal on which we switch buffers.
*
* @param to_alt
* Direction of buffer inversion.
* True if normal to alternate buffer.
* False if alternate to normal buffer.
*/
void guac_terminal_switch_buffers(guac_terminal* terminal, bool to_alt);

#endif

Loading