From bcd111d203f9e421b43e4e31fc750b0515b10d61 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Tue, 9 Jul 2019 16:26:36 +0200 Subject: [PATCH 01/15] wip: initial scroll back support Can scroll up and down, and stops when the beginning/end of history is reached. However, it probably breaks when the entire scrollback buffer has been filled - we need to detect when the view has wrapped around to the current terminal offset. The detection of when we've reached the bottom of the history is also flawed, and only works when we overshoot the bottom with at least a page. Resizing the windows while in a view most likely doesn't work. The view will not detect a wrapped around scrollback buffer. I.e. if the user has scrolled back, and is stationary at a view, but there is still output being produced. Then eventually the scrollback buffer will wrap around. In this case, the correct thing to do is make the view start following the beginning of the history. Right now it doesn't, meaning once the scrollback buffer wraps around, you'll start seeing command output... --- commands.c | 61 +++++++++++++++++++++++++++++++++++++++++++++++++++++ commands.h | 6 ++++++ grid.h | 7 ++++++ input.c | 27 ++++++++++++++++++++++++ meson.build | 1 + render.c | 34 +++++++++++++++++++++++------ terminal.c | 16 ++++++++++++-- terminal.h | 2 ++ 8 files changed, 146 insertions(+), 8 deletions(-) create mode 100644 commands.c create mode 100644 commands.h diff --git a/commands.c b/commands.c new file mode 100644 index 00000000..dea9b36e --- /dev/null +++ b/commands.c @@ -0,0 +1,61 @@ +#include "commands.h" + +#define LOG_MODULE "commands" +#define LOG_ENABLE_DBG 1 +#include "log.h" +#include "terminal.h" +#include "render.h" +#include "grid.h" + +#define max(x, y) ((x) > (y) ? (x) : (y)) + +void +cmd_scrollback_up(struct terminal *term) +{ + assert(term->grid->offset >= 0); + int new_view = (term->grid->view + term->grid->num_rows - term->rows) % term->grid->num_rows; + + LOG_WARN("%d" ,new_view); + assert(new_view >= 0); + assert(new_view < term->grid->num_rows); + + while (!term->grid->rows[new_view]->initialized) + new_view = (new_view + 1) % term->grid->num_rows; + + LOG_DBG("scrollback UP: %d -> %d (offset = %d, rows = %d)", + term->grid->view, new_view, term->grid->offset, term->grid->num_rows); + term->grid->view = new_view; + + for (int i = 0; i < term->rows; i++) + grid_row_in_view(term->grid, i)->dirty = true; + + if (term->frame_callback == NULL) + grid_render(term); +} + +void +cmd_scrollback_down(struct terminal *term) +{ + assert(term->grid->offset >= 0); + int new_view = (term->grid->view + term->rows) % term->grid->num_rows; + + LOG_WARN("%d" ,new_view); + assert(new_view >= 0); + assert(new_view < term->grid->num_rows); + + if (!term->grid->rows[new_view]->initialized) { + while (!term->grid->rows[new_view]->initialized) + new_view = (new_view + term->grid->num_rows - 1) % term->grid->num_rows; + new_view = (new_view + term->grid->num_rows - term->rows + 1) % term->grid->num_rows; + } + + LOG_DBG("scrollback DOWN: %d -> %d (offset = %d, rows = %d)", + term->grid->view, new_view, term->grid->offset, term->grid->num_rows); + term->grid->view = new_view; + + for (int i = 0; i < term->rows; i++) + grid_row_in_view(term->grid, i)->dirty = true; + + if (term->frame_callback == NULL) + grid_render(term); +} diff --git a/commands.h b/commands.h new file mode 100644 index 00000000..865cd83f --- /dev/null +++ b/commands.h @@ -0,0 +1,6 @@ +#pragma once + +#include "terminal.h" + +void cmd_scrollback_up(struct terminal *term); +void cmd_scrollback_down(struct terminal *term); diff --git a/grid.h b/grid.h index d6ddabee..e170f6dd 100644 --- a/grid.h +++ b/grid.h @@ -10,6 +10,13 @@ grid_row(struct grid *grid, int row) return grid->rows[(grid->offset + row + grid->num_rows) % grid->num_rows]; } +static inline struct row * +grid_row_in_view(struct grid *grid, int row) +{ + assert(grid->view >= 0); + return grid->rows[(grid->view + row + grid->num_rows) % grid->num_rows]; +} + static inline void grid_swap_row(struct grid *grid, int row_a, int row_b) { diff --git a/input.c b/input.c index 4ac45bbe..a7aba971 100644 --- a/input.c +++ b/input.c @@ -17,6 +17,7 @@ #include "terminal.h" #include "render.h" #include "keymap.h" +#include "commands.h" static void keyboard_keymap(void *data, struct wl_keyboard *wl_keyboard, @@ -140,6 +141,18 @@ keyboard_key(void *data, struct wl_keyboard *wl_keyboard, uint32_t serial, keymap_mods |= term->kbd.alt ? MOD_ALT : MOD_NONE; keymap_mods |= term->kbd.ctrl ? MOD_CTRL : MOD_NONE; + if (effective_mods == shift) { + if (sym == XKB_KEY_Page_Up) { + cmd_scrollback_up(term); + found_map = true; + } + + else if (sym == XKB_KEY_Page_Down) { + cmd_scrollback_down(term); + found_map = true; + } + } + for (size_t i = 0; i < sizeof(key_map) / sizeof(key_map[0]) && !found_map; i++) { const struct key_map *k = &key_map[i]; if (k->sym != sym) @@ -160,6 +173,13 @@ keyboard_key(void *data, struct wl_keyboard *wl_keyboard, uint32_t serial, write(term->ptmx, info->seq, strlen(info->seq)); found_map = true; + + if (term->grid->view != term->grid->offset) { + term->grid->view = term->grid->offset; + /* TODO: damage view */ + term_damage_all(term); + } + break; } } @@ -182,6 +202,13 @@ keyboard_key(void *data, struct wl_keyboard *wl_keyboard, uint32_t serial, write(term->ptmx, "\x1b", 1); write(term->ptmx, buf, count); + + if (term->grid->view != term->grid->offset) { + term->grid->view = term->grid->offset; + /* TODO: damage view */ + term_damage_all(term); + } + } } diff --git a/meson.build b/meson.build index c55938b1..7cb057bf 100644 --- a/meson.build +++ b/meson.build @@ -58,6 +58,7 @@ endforeach executable( 'f00ter', + 'commands.c', 'commands.h', 'csi.c', 'csi.h', 'font.c', 'font.h', 'grid.c', 'grid.h', diff --git a/render.c b/render.c index d42a04ec..685a9031 100644 --- a/render.c +++ b/render.c @@ -243,7 +243,7 @@ grid_render(struct terminal *term) gseq.count = 0; for (int r = 0; r < term->rows; r++) { - struct row *row = grid_row(term->grid, r); + struct row *row = grid_row_in_view(term->grid, r); if (!row->dirty) continue; @@ -266,10 +266,10 @@ grid_render(struct terminal *term) = (term->grid->offset + term->cursor.row) * term->cols + term->cursor.col; if (last_cursor != cursor_as_linear) { - int row = last_cursor / term->cols - term->grid->offset; + int row = last_cursor / term->cols - term->grid->view; int col = last_cursor % term->cols; if (row >= 0 && row < term->rows) { - render_cell(term, buf, &grid_row(term->grid, row)->cells[col], col, row); + render_cell(term, buf, &grid_row_in_view(term->grid, row)->cells[col], col, row); all_clean = false; wl_surface_damage_buffer( @@ -286,7 +286,7 @@ grid_render(struct terminal *term) render_cell( term, buf, - &grid_row(term->grid, term->cursor.row)->cells[term->cursor.col], + &grid_row_in_view(term->grid, term->cursor.row)->cells[term->cursor.col], term->cursor.col, term->cursor.row); wl_surface_damage_buffer( @@ -304,6 +304,7 @@ grid_render(struct terminal *term) } assert(term->grid->offset >= 0 && term->grid->offset < term->grid->num_rows); + assert(term->grid->view >= 0 && term->grid->view < term->grid->num_rows); cairo_surface_flush(buf->cairo_surface); wl_surface_attach(term->wl.surface, buf->wl_buf, 0, 0); @@ -338,12 +339,18 @@ reflow(struct row **new_grid, int new_cols, int new_rows, struct cell *new_cells = new_grid[r]->cells; const struct cell *old_cells = old_grid[r]->cells; + new_grid[r]->initialized = old_grid[r]->initialized; + new_grid[r]->dirty = old_grid[r]->dirty; + memcpy(new_cells, old_cells, copy_cols * sizeof(new_cells[0])); memset(&new_cells[copy_cols], 0, clear_cols * sizeof(new_cells[0])); } - for (int r = min(new_rows, old_rows); r < new_rows; r++) + for (int r = min(new_rows, old_rows); r < new_rows; r++) { + new_grid[r]->initialized = false; + new_grid[r]->dirty = false; memset(new_grid[r]->cells, 0, new_cols * sizeof(new_grid[r]->cells[0])); + } } /* Move to terminal.c? */ @@ -356,6 +363,8 @@ render_resize(struct terminal *term, int width, int height) term->width = width; term->height = height; + const int scrollback_lines = 10000; + const int old_cols = term->cols; const int old_rows = term->rows; const int old_normal_grid_rows = term->normal.num_rows; @@ -363,7 +372,7 @@ render_resize(struct terminal *term, int width, int height) const int new_cols = term->width / term->cell_width; const int new_rows = term->height / term->cell_height; - const int new_normal_grid_rows = new_rows; + const int new_normal_grid_rows = new_rows + scrollback_lines; const int new_alt_grid_rows = new_rows; /* Allocate new 'normal' grid */ @@ -388,6 +397,11 @@ render_resize(struct terminal *term, int width, int height) reflow(alt, new_cols, new_alt_grid_rows, term->alt.rows, old_cols, old_alt_grid_rows); + for (int r = 0; r < new_rows; r++) { + normal[r]->initialized = true; + alt[r]->initialized = true; + } + /* Free old 'normal' grid */ for (int r = 0; r < term->normal.num_rows; r++) { free(term->normal.rows[r]->cells); @@ -430,10 +444,18 @@ render_resize(struct terminal *term, int width, int height) if (term->scroll_region.end >= old_rows) term->scroll_region.end = term->rows; + term->normal.offset %= term->normal.num_rows; + term->normal.view %= term->alt.num_rows; + + term->alt.offset %= term->alt.num_rows; + term->alt.view %= term->alt.num_rows; + term_cursor_to( term, min(term->cursor.row, term->rows - 1), min(term->cursor.col, term->cols - 1)); + + /* TODO: damage view */ term_damage_all(term); if (term->frame_callback == NULL) diff --git a/terminal.c b/terminal.c index 1cf15cfb..56ac6cee 100644 --- a/terminal.c +++ b/terminal.c @@ -152,11 +152,18 @@ term_scroll_partial(struct terminal *term, struct scroll_region region, int rows grid_swap_row(term->grid, i, i + rows); /* Offset grid origin */ + bool view_follows = term->grid->view == term->grid->offset; term->grid->offset += rows; term->grid->offset %= term->grid->num_rows; - for (int r = max(region.end - rows, 0); r < region.end; r++) - erase_line(term, grid_row(term->grid, r)); + if (view_follows) + term->grid->view = term->grid->offset; + + for (int r = max(region.end - rows, 0); r < region.end; r++) { + struct row *row = grid_row(term->grid, r); + erase_line(term, row); + row->initialized = true; + } term_damage_scroll(term, DAMAGE_SCROLL, region, rows); term->grid->cur_row = grid_row(term->grid, term->cursor.row); @@ -174,9 +181,14 @@ term_scroll_reverse_partial(struct terminal *term, { assert(rows < term->rows && "unimplemented"); + bool view_follows = term->grid->view == term->grid->offset; + term->grid->offset += term->grid->num_rows - rows; term->grid->offset %= term->grid->num_rows; + if (view_follows) + term->grid->view = term->grid->offset; + /* Bottom non-scrolling region */ for (int i = region.end + rows; i < term->rows + rows; i++) grid_swap_row(term->grid, i, i - rows); diff --git a/terminal.h b/terminal.h index 6f42398a..35a1fae7 100644 --- a/terminal.h +++ b/terminal.h @@ -94,11 +94,13 @@ struct damage { struct row { struct cell *cells; bool dirty; + bool initialized; }; struct grid { int num_rows; int offset; + int view; struct row **rows; struct row *cur_row; From b058e6384ab5349cbf78bf471d581a83f531e30a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Wed, 10 Jul 2019 09:15:37 +0200 Subject: [PATCH 02/15] scrollback: initial support for mouse scrolling --- commands.c | 34 +++++++++++++++++++++++++--------- commands.h | 4 ++-- input.c | 16 ++++++++++++++-- 3 files changed, 41 insertions(+), 13 deletions(-) diff --git a/commands.c b/commands.c index dea9b36e..47bbb4a8 100644 --- a/commands.c +++ b/commands.c @@ -10,15 +10,19 @@ #define max(x, y) ((x) > (y) ? (x) : (y)) void -cmd_scrollback_up(struct terminal *term) +cmd_scrollback_up(struct terminal *term, int rows) { + if (term->grid == &term->alt) + return; + assert(term->grid->offset >= 0); - int new_view = (term->grid->view + term->grid->num_rows - term->rows) % term->grid->num_rows; + int new_view = (term->grid->view + term->grid->num_rows - rows) % term->grid->num_rows; LOG_WARN("%d" ,new_view); assert(new_view >= 0); assert(new_view < term->grid->num_rows); + /* Avoid scrolling in uninitialized rows */ while (!term->grid->rows[new_view]->initialized) new_view = (new_view + 1) % term->grid->num_rows; @@ -34,20 +38,32 @@ cmd_scrollback_up(struct terminal *term) } void -cmd_scrollback_down(struct terminal *term) +cmd_scrollback_down(struct terminal *term, int rows) { + if (term->grid == &term->alt) + return; + assert(term->grid->offset >= 0); - int new_view = (term->grid->view + term->rows) % term->grid->num_rows; + int new_view = (term->grid->view + rows) % term->grid->num_rows; LOG_WARN("%d" ,new_view); assert(new_view >= 0); assert(new_view < term->grid->num_rows); - if (!term->grid->rows[new_view]->initialized) { - while (!term->grid->rows[new_view]->initialized) - new_view = (new_view + term->grid->num_rows - 1) % term->grid->num_rows; - new_view = (new_view + term->grid->num_rows - term->rows + 1) % term->grid->num_rows; - } + /* Prevent scrolling in uninitialized rows */ + bool all_initialized = false; + do { + all_initialized = true; + + for (int i = 0; i < term->rows; i++) { + int row_no = (new_view + i) % term->grid->num_rows; + if (!term->grid->rows[row_no]->initialized) { + all_initialized = false; + new_view--; + break; + } + } + } while (!all_initialized); LOG_DBG("scrollback DOWN: %d -> %d (offset = %d, rows = %d)", term->grid->view, new_view, term->grid->offset, term->grid->num_rows); diff --git a/commands.h b/commands.h index 865cd83f..644523b0 100644 --- a/commands.h +++ b/commands.h @@ -2,5 +2,5 @@ #include "terminal.h" -void cmd_scrollback_up(struct terminal *term); -void cmd_scrollback_down(struct terminal *term); +void cmd_scrollback_up(struct terminal *term, int rows); +void cmd_scrollback_down(struct terminal *term, int rows); diff --git a/input.c b/input.c index a7aba971..f9e7f92b 100644 --- a/input.c +++ b/input.c @@ -143,12 +143,12 @@ keyboard_key(void *data, struct wl_keyboard *wl_keyboard, uint32_t serial, if (effective_mods == shift) { if (sym == XKB_KEY_Page_Up) { - cmd_scrollback_up(term); + cmd_scrollback_up(term, term->rows); found_map = true; } else if (sym == XKB_KEY_Page_Down) { - cmd_scrollback_down(term); + cmd_scrollback_down(term, term->rows); found_map = true; } } @@ -342,6 +342,18 @@ static void wl_pointer_axis(void *data, struct wl_pointer *wl_pointer, uint32_t time, uint32_t axis, wl_fixed_t value) { + struct terminal *term = data; + + /* TODO: generate button event for BTN_FORWARD/BTN_BACK? */ + + if (axis != WL_POINTER_AXIS_VERTICAL_SCROLL) + return; + + int amount = wl_fixed_to_int(value); + if (amount < 0) + cmd_scrollback_up(term, -amount); + else + cmd_scrollback_down(term, amount); } static void From 1d338f8477d64502c71d06e2ee994084f5935054 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Wed, 10 Jul 2019 09:29:36 +0200 Subject: [PATCH 03/15] scrollback: don't scroll past scrollback history --- commands.c | 39 +++++++++++++++++++++++++++++++++------ 1 file changed, 33 insertions(+), 6 deletions(-) diff --git a/commands.c b/commands.c index 47bbb4a8..7e29c6e5 100644 --- a/commands.c +++ b/commands.c @@ -8,6 +8,7 @@ #include "grid.h" #define max(x, y) ((x) > (y) ? (x) : (y)) +#define min(x, y) ((x) < (y) ? (x) : (y)) void cmd_scrollback_up(struct terminal *term, int rows) @@ -15,10 +16,12 @@ cmd_scrollback_up(struct terminal *term, int rows) if (term->grid == &term->alt) return; - assert(term->grid->offset >= 0); - int new_view = (term->grid->view + term->grid->num_rows - rows) % term->grid->num_rows; + rows = min(rows, term->grid->num_rows - term->rows); - LOG_WARN("%d" ,new_view); + assert(term->grid->offset >= 0); + assert(rows <= term->rows); + + int new_view = (term->grid->view + term->grid->num_rows - rows) % term->grid->num_rows; assert(new_view >= 0); assert(new_view < term->grid->num_rows); @@ -26,6 +29,17 @@ cmd_scrollback_up(struct terminal *term, int rows) while (!term->grid->rows[new_view]->initialized) new_view = (new_view + 1) % term->grid->num_rows; + /* Don't scroll past scrollback history */ + int end = (term->grid->offset + term->rows) % term->grid->num_rows; + if (end >= term->grid->offset) { + /* Not wrapped */ + if (new_view >= term->grid->offset && new_view < end) + new_view = end; + } else { + if (new_view >= term->grid->offset || new_view < end) + new_view = end; + } + LOG_DBG("scrollback UP: %d -> %d (offset = %d, rows = %d)", term->grid->view, new_view, term->grid->offset, term->grid->num_rows); term->grid->view = new_view; @@ -43,10 +57,11 @@ cmd_scrollback_down(struct terminal *term, int rows) if (term->grid == &term->alt) return; - assert(term->grid->offset >= 0); - int new_view = (term->grid->view + rows) % term->grid->num_rows; + rows = min(rows, term->grid->num_rows - term->rows); - LOG_WARN("%d" ,new_view); + assert(term->grid->offset >= 0); + + int new_view = (term->grid->view + rows) % term->grid->num_rows; assert(new_view >= 0); assert(new_view < term->grid->num_rows); @@ -65,6 +80,18 @@ cmd_scrollback_down(struct terminal *term, int rows) } } while (!all_initialized); + /* Don't scroll past scrollback history */ + int end = (term->grid->offset + term->rows) % term->grid->num_rows; + if (end >= term->grid->offset) { + /* Not wrapped */ + if (new_view >= term->grid->offset && new_view < end) + new_view = term->grid->offset; + } else { + if (new_view >= term->grid->offset || new_view < end) + new_view = term->grid->offset; + } + + LOG_DBG("scrollback DOWN: %d -> %d (offset = %d, rows = %d)", term->grid->view, new_view, term->grid->offset, term->grid->num_rows); term->grid->view = new_view; From ed0fd2d4427748309e8a66d2d2dc20e7fb04a4e5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Wed, 10 Jul 2019 09:30:35 +0200 Subject: [PATCH 04/15] scrollback: don't redraw if view doesn't change --- commands.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/commands.c b/commands.c index 7e29c6e5..f66609cb 100644 --- a/commands.c +++ b/commands.c @@ -42,6 +42,10 @@ cmd_scrollback_up(struct terminal *term, int rows) LOG_DBG("scrollback UP: %d -> %d (offset = %d, rows = %d)", term->grid->view, new_view, term->grid->offset, term->grid->num_rows); + + if (new_view == term->grid->view) + return; + term->grid->view = new_view; for (int i = 0; i < term->rows; i++) @@ -94,6 +98,10 @@ cmd_scrollback_down(struct terminal *term, int rows) LOG_DBG("scrollback DOWN: %d -> %d (offset = %d, rows = %d)", term->grid->view, new_view, term->grid->offset, term->grid->num_rows); + + if (new_view == term->grid->view) + return; + term->grid->view = new_view; for (int i = 0; i < term->rows; i++) From 1bb5afeb0a239ac5ecf3d31c2ae323494c36bf6e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Wed, 10 Jul 2019 09:51:42 +0200 Subject: [PATCH 05/15] render: don't render cursor if it is not in view --- render.c | 46 ++++++++++++++++++++++++++++------------------ 1 file changed, 28 insertions(+), 18 deletions(-) diff --git a/render.c b/render.c index 685a9031..1d3090ac 100644 --- a/render.c +++ b/render.c @@ -35,13 +35,8 @@ static struct glyph_sequence gseq; static void render_cell(struct terminal *term, struct buffer *buf, const struct cell *cell, - int col, int row) + int col, int row, bool has_cursor) { - /* Cursor here? */ - bool has_cursor - = (!term->hide_cursor && - (term->cursor.col == col && term->cursor.row == row)); - double width = term->cell_width; double height = term->cell_height; double x = col * width; @@ -251,7 +246,7 @@ grid_render(struct terminal *term) //LOG_WARN("rendering line: %d", r); for (int col = 0; col < term->cols; col++) - render_cell(term, buf, &row->cells[col], col, r); + render_cell(term, buf, &row->cells[col], col, r, false); row->dirty = false; all_clean = false; @@ -266,10 +261,10 @@ grid_render(struct terminal *term) = (term->grid->offset + term->cursor.row) * term->cols + term->cursor.col; if (last_cursor != cursor_as_linear) { - int row = last_cursor / term->cols - term->grid->view; + int row = last_cursor / term->cols - term->grid->offset; int col = last_cursor % term->cols; if (row >= 0 && row < term->rows) { - render_cell(term, buf, &grid_row_in_view(term->grid, row)->cells[col], col, row); + render_cell(term, buf, &grid_row_in_view(term->grid, row)->cells[col], col, row, false); all_clean = false; wl_surface_damage_buffer( @@ -284,16 +279,31 @@ grid_render(struct terminal *term) return; } - render_cell( - term, buf, - &grid_row_in_view(term->grid, term->cursor.row)->cells[term->cursor.col], - term->cursor.col, term->cursor.row); + bool cursor_is_visible = false; + int view_end = (term->grid->view + term->rows - 1) % term->grid->num_rows; + int cursor_row = (term->grid->offset + term->cursor.row) % term->grid->num_rows; + if (view_end >= term->grid->view) { + /* Not wrapped */ + if (cursor_row >= term->grid->view && cursor_row <= view_end) + cursor_is_visible = true; + } else { + /* Wrapped */ + if (cursor_row >= term->grid->view || cursor_row <= view_end) + cursor_is_visible = true; + } - wl_surface_damage_buffer( - term->wl.surface, - term->cursor.col * term->cell_width, - term->cursor.row * term->cell_height, - term->cell_width, term->cell_height); + if (cursor_is_visible) { + render_cell( + term, buf, + &grid_row_in_view(term->grid, term->cursor.row)->cells[term->cursor.col], + term->cursor.col, term->cursor.row, true); + + wl_surface_damage_buffer( + term->wl.surface, + term->cursor.col * term->cell_width, + term->cursor.row * term->cell_height, + term->cell_width, term->cell_height); + } if (gseq.count > 0) { cairo_set_scaled_font(buf->cairo, attrs_to_font(term, &gseq.attrs)); From 18c61a9a2abddf1688fcbe6ac2c63d7faffcf7f2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Wed, 10 Jul 2019 09:55:53 +0200 Subject: [PATCH 06/15] scrollback: fix off-by-one when grid size matches terminal/window size --- commands.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/commands.c b/commands.c index f66609cb..006e537c 100644 --- a/commands.c +++ b/commands.c @@ -30,13 +30,13 @@ cmd_scrollback_up(struct terminal *term, int rows) new_view = (new_view + 1) % term->grid->num_rows; /* Don't scroll past scrollback history */ - int end = (term->grid->offset + term->rows) % term->grid->num_rows; + int end = (term->grid->offset + term->rows - 1) % term->grid->num_rows; if (end >= term->grid->offset) { /* Not wrapped */ - if (new_view >= term->grid->offset && new_view < end) + if (new_view >= term->grid->offset && new_view <= end) new_view = end; } else { - if (new_view >= term->grid->offset || new_view < end) + if (new_view >= term->grid->offset || new_view <= end) new_view = end; } @@ -85,13 +85,13 @@ cmd_scrollback_down(struct terminal *term, int rows) } while (!all_initialized); /* Don't scroll past scrollback history */ - int end = (term->grid->offset + term->rows) % term->grid->num_rows; + int end = (term->grid->offset + term->rows - 1) % term->grid->num_rows; if (end >= term->grid->offset) { /* Not wrapped */ - if (new_view >= term->grid->offset && new_view < end) + if (new_view >= term->grid->offset && new_view <= end) new_view = term->grid->offset; } else { - if (new_view >= term->grid->offset || new_view < end) + if (new_view >= term->grid->offset || new_view <= end) new_view = term->grid->offset; } From 94fdde3da7a2f5311032dc1e0d6886eff756630d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Wed, 10 Jul 2019 09:56:15 +0200 Subject: [PATCH 07/15] main: hopefully fix logical error in delayed rendering We want the timeout_ms to *not* be -1 (i.e. someone has requested delayed rendering), while we're *not* getting client output. --- main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/main.c b/main.c index e454e103..dd16d277 100644 --- a/main.c +++ b/main.c @@ -495,7 +495,7 @@ main(int argc, char *const *argv) break; } - if (ret == 0 || !(timeout_ms != -1 && fds[1].revents & POLLIN)) { + if (ret == 0 || (timeout_ms != -1 && !(fds[1].revents & POLLIN))) { /* Delayed rendering */ if (term.frame_callback == NULL) grid_render(&term); From 7594edb89bef777b02177b7c82f7231fac4e2528 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Wed, 10 Jul 2019 14:17:44 +0200 Subject: [PATCH 08/15] input: generate BTN_BACK/BTN_FORWARD mouse down events when scrolling --- input.c | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/input.c b/input.c index f9e7f92b..33547fcd 100644 --- a/input.c +++ b/input.c @@ -7,6 +7,8 @@ #include #include +#include + #include #include #include @@ -350,10 +352,20 @@ wl_pointer_axis(void *data, struct wl_pointer *wl_pointer, return; int amount = wl_fixed_to_int(value); - if (amount < 0) + + if (amount < 0) { + for (int i = 0; i < -amount; i++) { + term_mouse_down(term, BTN_BACK, term->mouse.row, term->mouse.col, + term->kbd.shift, term->kbd.alt, term->kbd.ctrl); + } cmd_scrollback_up(term, -amount); - else + } else { + for (int i = 0; i < amount; i++) { + term_mouse_down(term, BTN_FORWARD, term->mouse.row, term->mouse.col, + term->kbd.shift, term->kbd.alt, term->kbd.ctrl); + } cmd_scrollback_down(term, amount); + } } static void From d8d4b343626807e421ff95c032041165bae65597 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Wed, 10 Jul 2019 14:28:20 +0200 Subject: [PATCH 09/15] scrollback: fix scrolling outside initialized lines in new terminal --- commands.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/commands.c b/commands.c index 006e537c..dcf2a3f6 100644 --- a/commands.c +++ b/commands.c @@ -29,6 +29,16 @@ cmd_scrollback_up(struct terminal *term, int rows) while (!term->grid->rows[new_view]->initialized) new_view = (new_view + 1) % term->grid->num_rows; + if (new_view == term->grid->view) { + /* + * This happens when scrolling up in a newly opened terminal; + * every single line (except those already visible) are + * uninitalized, and the loop above will bring us back to + * where we started. + */ + return; + } + /* Don't scroll past scrollback history */ int end = (term->grid->offset + term->rows - 1) % term->grid->num_rows; if (end >= term->grid->offset) { From 8a65d52b215dfe1288a6dfc650b0b38acbc4434f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Wed, 10 Jul 2019 14:32:40 +0200 Subject: [PATCH 10/15] terminal: add term_damage_view() This ensures everything *visible* (i.e. maybe scrolled back content) is re-rendered. --- terminal.c | 7 +++++++ terminal.h | 1 + 2 files changed, 8 insertions(+) diff --git a/terminal.c b/terminal.c index 56ac6cee..8804140b 100644 --- a/terminal.c +++ b/terminal.c @@ -21,6 +21,13 @@ term_damage_all(struct terminal *term) grid_row(term->grid, i)->dirty = true; } +void +term_damage_view(struct terminal *term) +{ + for (int i = 0; i < term->rows; i++) + grid_row_in_view(term->grid, i)->dirty = true; +} + void term_damage_scroll(struct terminal *term, enum damage_type damage_type, struct scroll_region region, int lines) diff --git a/terminal.h b/terminal.h index 35a1fae7..7d379229 100644 --- a/terminal.h +++ b/terminal.h @@ -250,6 +250,7 @@ struct terminal { }; void term_damage_all(struct terminal *term); +void term_damage_view(struct terminal *term); void term_damage_scroll( struct terminal *term, enum damage_type damage_type, struct scroll_region region, int lines); From 4cef8ed2cc76becc725e511c24dc93ef56bd8d9e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Wed, 10 Jul 2019 14:34:32 +0200 Subject: [PATCH 11/15] render: reset 'normal' grid's view correctly --- render.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/render.c b/render.c index 1d3090ac..bed7de0d 100644 --- a/render.c +++ b/render.c @@ -455,7 +455,7 @@ render_resize(struct terminal *term, int width, int height) term->scroll_region.end = term->rows; term->normal.offset %= term->normal.num_rows; - term->normal.view %= term->alt.num_rows; + term->normal.view %= term->normal.num_rows; term->alt.offset %= term->alt.num_rows; term->alt.view %= term->alt.num_rows; From e01060caf91dde118d0346441e3763be0d24731a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Wed, 10 Jul 2019 14:34:43 +0200 Subject: [PATCH 12/15] render: damage the *view* too, when resizing --- render.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/render.c b/render.c index bed7de0d..209d8f6f 100644 --- a/render.c +++ b/render.c @@ -465,8 +465,8 @@ render_resize(struct terminal *term, int width, int height) min(term->cursor.row, term->rows - 1), min(term->cursor.col, term->cols - 1)); - /* TODO: damage view */ term_damage_all(term); + term_damage_view(term); if (term->frame_callback == NULL) grid_render(term); From a01efd07e36d1eb5180b70cd6aa21984337c5aba Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Wed, 10 Jul 2019 14:42:48 +0200 Subject: [PATCH 13/15] scrollback: don't allow more scrolling when already at the top or bottom --- commands.c | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/commands.c b/commands.c index dcf2a3f6..19b2100c 100644 --- a/commands.c +++ b/commands.c @@ -44,14 +44,14 @@ cmd_scrollback_up(struct terminal *term, int rows) if (end >= term->grid->offset) { /* Not wrapped */ if (new_view >= term->grid->offset && new_view <= end) - new_view = end; + new_view = end + 1; } else { if (new_view >= term->grid->offset || new_view <= end) - new_view = end; + new_view = end + 1; } - LOG_DBG("scrollback UP: %d -> %d (offset = %d, rows = %d)", - term->grid->view, new_view, term->grid->offset, term->grid->num_rows); + LOG_DBG("scrollback UP: %d -> %d (offset = %d, end = %d, rows = %d)", + term->grid->view, new_view, term->grid->offset, end, term->grid->num_rows); if (new_view == term->grid->view) return; @@ -71,6 +71,9 @@ cmd_scrollback_down(struct terminal *term, int rows) if (term->grid == &term->alt) return; + if (term->grid->view == term->grid->offset) + return; + rows = min(rows, term->grid->num_rows - term->rows); assert(term->grid->offset >= 0); @@ -106,8 +109,8 @@ cmd_scrollback_down(struct terminal *term, int rows) } - LOG_DBG("scrollback DOWN: %d -> %d (offset = %d, rows = %d)", - term->grid->view, new_view, term->grid->offset, term->grid->num_rows); + LOG_DBG("scrollback DOWN: %d -> %d (offset = %d, end = %d, rows = %d)", + term->grid->view, new_view, term->grid->offset, end, term->grid->num_rows); if (new_view == term->grid->view) return; From 607755536f85eb3506adf63ec59df54fb8dc4021 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Wed, 10 Jul 2019 14:43:46 +0200 Subject: [PATCH 14/15] scrollback: use term_damage_view() --- commands.c | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/commands.c b/commands.c index 19b2100c..db316f82 100644 --- a/commands.c +++ b/commands.c @@ -58,9 +58,7 @@ cmd_scrollback_up(struct terminal *term, int rows) term->grid->view = new_view; - for (int i = 0; i < term->rows; i++) - grid_row_in_view(term->grid, i)->dirty = true; - + term_damage_view(term); if (term->frame_callback == NULL) grid_render(term); } @@ -117,9 +115,7 @@ cmd_scrollback_down(struct terminal *term, int rows) term->grid->view = new_view; - for (int i = 0; i < term->rows; i++) - grid_row_in_view(term->grid, i)->dirty = true; - + term_damage_view(term); if (term->frame_callback == NULL) grid_render(term); } From 5144fcba0c261a2164321a573b9a591a33f9fc44 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Wed, 10 Jul 2019 14:45:00 +0200 Subject: [PATCH 15/15] scrollback: disable debug logging --- commands.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/commands.c b/commands.c index db316f82..472cf880 100644 --- a/commands.c +++ b/commands.c @@ -1,7 +1,7 @@ #include "commands.h" #define LOG_MODULE "commands" -#define LOG_ENABLE_DBG 1 +#define LOG_ENABLE_DBG 0 #include "log.h" #include "terminal.h" #include "render.h"