Skip to content

Commit

Permalink
GUACAMOLE-1633: Add support of alternate screen buffer
Browse files Browse the repository at this point in the history
  • Loading branch information
corentin-soriano committed Jun 5, 2024
1 parent 7d004ce commit da5d866
Show file tree
Hide file tree
Showing 3 changed files with 105 additions and 2 deletions.
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
64 changes: 62 additions & 2 deletions src/terminal/terminal.c
Original file line number Diff line number Diff line change
Expand Up @@ -482,9 +482,12 @@ 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 = guac_terminal_buffer_alloc(initial_scrollback,
&default_char);
term->buffer_switched = false;

/* Init display */
term->display = guac_terminal_display_alloc(client,
Expand Down Expand Up @@ -633,8 +636,9 @@ 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);
guac_terminal_buffer_free(term->buffer_alt);

/* Free scrollbar */
guac_terminal_scrollbar_free(term->scrollbar);
Expand Down Expand Up @@ -2384,3 +2388,59 @@ 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;

/* 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;

/* Clean old alternate buffer 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);

}

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

/**
* Backup of cursor position when using alternate buffer.
*/
int cursor_row_alt, cursor_col_alt, visible_cursor_row_alt, visible_cursor_col_alt;

/**
* The row of the saved cursor (ESC 7).
*/
Expand Down Expand Up @@ -311,6 +316,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 +683,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

0 comments on commit da5d866

Please sign in to comment.