GUACAMOLE-1256: Fix scrolldown issue on GUAC_CHAR_SET unflushed operation.

This commit is contained in:
Corentin SORIANO 2025-06-05 20:04:53 +02:00
parent 8aa2173c38
commit 5c5fff7cb9
No known key found for this signature in database
3 changed files with 24 additions and 10 deletions

View File

@ -258,6 +258,7 @@ guac_terminal_display* guac_terminal_display_alloc(guac_client* client,
display->width = 0;
display->height = 0;
display->operations = NULL;
display->unflushed_set = false;
/* Initially nothing selected */
display->text_selected = false;
@ -430,6 +431,12 @@ void guac_terminal_display_copy_rows(guac_terminal_display* display,
guac_terminal_operation* src = &(display->operations[src_offset]);
guac_terminal_operation* dst = &(display->operations[dst_offset]);
/* Flush operations if there are any unflushed SET operations. This is
* necessary to ensure that the copy operation does not conflict with any
* SET operations that may have been performed since the last flush. */
if (display->unflushed_set)
guac_terminal_display_flush_operations(display);
/* Copy data */
memmove(dst, src, guac_mem_ckd_mul_or_die(sizeof(guac_terminal_operation),
display->width, (end_row - start_row + 1)));
@ -483,7 +490,7 @@ void guac_terminal_display_set_columns(guac_terminal_display* display, int row,
/* Flush pending copy operation before adding new SET operation. This
* avoid operation conflicts that cause inconsistent display. */
if (current->type == GUAC_CHAR_COPY)
guac_terminal_display_flush(display);
guac_terminal_display_flush_operations(display);
/* Set operation */
current->type = GUAC_CHAR_SET;
@ -494,6 +501,13 @@ void guac_terminal_display_set_columns(guac_terminal_display* display, int row,
}
/* Marks whether there are unflushed GUAC_CHAR_SET operations when the
* operation is not on the first or last row because flushing new lines
* added has a high performance cost. This flag is used to determine
* whether a flush is necessary before performing copy operations. */
if (row > 0 && row < display->height - 1)
display->unflushed_set = true;
}
void guac_terminal_display_resize(guac_terminal_display* display, int width, int height) {
@ -858,6 +872,9 @@ void __guac_terminal_display_flush_set(guac_terminal_display* display) {
}
}
/* Mark that all SET operations have been flushed */
display->unflushed_set = 0;
}
void guac_terminal_display_flush_operations(guac_terminal_display* display) {

View File

@ -868,15 +868,6 @@ void guac_terminal_scroll_up(guac_terminal* term,
void guac_terminal_scroll_down(guac_terminal* term,
int start_row, int end_row, int amount) {
/*
* We must flush all pending operations here because
* guac_terminal_copy_rows will set new GUAC_CHAR_COPY for
* cells of shifted rows meanwhile preceding GUAC_CHAR_SET for these cells
* are not actually done yet. The GUAC_CHAR_COPY operation has the highest
* priority, so if we do not 'flush' here, wrong content will be copied.
*/
guac_terminal_display_flush_operations(term->display);
guac_terminal_copy_rows(term, start_row, end_row - amount, amount);
/* Clear new area */

View File

@ -225,6 +225,12 @@ typedef struct guac_terminal_display {
*/
int selection_end_column;
/**
* Whether there are GUAC_CHAR_SET operations that need to be flushed
* to the display.
*/
bool unflushed_set;
} guac_terminal_display;
/**