render: scrollback indicator: wip: implement 'fixed:percent' indicator

When scrollback indicator has been enabled, and the viewport isn't at
the bottom, we now render a *static* indicator with the position in
percent.

We use the color scheme's blue color as background, and it's white
color as foreground. This is subject to change... Should maybe be
configurable as well.

The Wayland surface + sub-surface are instantiated on-demand, and
automatically destroyed when no longer used.
This commit is contained in:
Daniel Eklöf 2020-07-26 10:01:26 +02:00
parent c2362c10f1
commit 67758a7cb7
No known key found for this signature in database
GPG key ID: 5BBD4992C116573F

110
render.c
View file

@ -1293,6 +1293,53 @@ render_scrollback_position(struct terminal *term)
if (term->conf->scrollback.indicator.style == SCROLLBACK_INDICATOR_STYLE_NONE) if (term->conf->scrollback.indicator.style == SCROLLBACK_INDICATOR_STYLE_NONE)
return; return;
struct wayland *wayl = term->wl;
struct wl_window *win = term->window;
if (term->grid->view == term->grid->offset) {
if (win->scrollback_indicator_surface != NULL) {
wl_subsurface_destroy(win->scrollback_indicator_sub_surface);
wl_surface_destroy(win->scrollback_indicator_surface);
win->scrollback_indicator_surface = NULL;
win->scrollback_indicator_sub_surface = NULL;
LOG_INFO("destroyed indicator surfaces");
}
return;
}
if (win->scrollback_indicator_surface == NULL) {
win->scrollback_indicator_surface
= wl_compositor_create_surface(wayl->compositor);
if (win->scrollback_indicator_surface == NULL) {
LOG_ERR("failed to create scrollback indicator surface");
return;
}
wl_surface_set_user_data(win->scrollback_indicator_surface, win);
term->window->scrollback_indicator_sub_surface
= wl_subcompositor_get_subsurface(
wayl->sub_compositor,
win->scrollback_indicator_surface,
win->surface);
if (win->scrollback_indicator_sub_surface == NULL) {
LOG_ERR("failed to create scrollback indicator sub-surface");
wl_surface_destroy(win->scrollback_indicator_surface);
win->scrollback_indicator_surface = NULL;
return;
}
wl_subsurface_set_sync(win->scrollback_indicator_sub_surface);
LOG_INFO("instantiated indicator surfaces");
}
assert(win->scrollback_indicator_surface != NULL);
assert(win->scrollback_indicator_sub_surface != NULL);
/* Find absolute row number of the scrollback start */ /* Find absolute row number of the scrollback start */
int scrollback_start = term->grid->offset + term->rows; int scrollback_start = term->grid->offset + term->rows;
while (term->grid->rows[scrollback_start & (term->grid->num_rows - 1)] == NULL) while (term->grid->rows[scrollback_start & (term->grid->num_rows - 1)] == NULL)
@ -1309,24 +1356,67 @@ render_scrollback_position(struct terminal *term)
* 0% -> at the beginning of the scrollback * 0% -> at the beginning of the scrollback
* 100% -> at the bottom, i.e. where new lines are inserted * 100% -> at the bottom, i.e. where new lines are inserted
*/ */
int percentage __attribute__((unused)) = int percentage =
rebased_view + term->rows == term->grid->num_rows rebased_view + term->rows == term->grid->num_rows
? 100 ? 100
: 100 * rebased_view / term->grid->num_rows; : 100 * rebased_view / term->grid->num_rows;
int next_row_no = term->grid->view + term->rows; const int scale = term->scale;
next_row_no &= term->grid->num_rows - 1; const int margin = 3 * scale;
const int width = 2 * margin + 3 * term->cell_width; /* TODO: this is percent only */
const int height = 2 * margin + term->cell_height;
/* Are we at the end of the scrollback? */ unsigned long cookie = shm_cookie_scrollback_indicator(term);
bool at_bottom = rebased_view + term->rows == term->grid->num_rows || struct buffer *buf = shm_get_buffer(
term->grid->rows[next_row_no] == NULL; term->wl->shm, width, height, cookie, false, 1);
LOG_DBG("scrollback position: %d/%d (%d%%), at-bottom: %d", pixman_color_t bg = color_hex_to_pixman(term->colors.table[4]);
rebased_view, term->grid->num_rows, percentage, at_bottom); pixman_image_fill_rectangles(
PIXMAN_OP_SRC, buf->pix[0], &bg, 1,
&(pixman_rectangle16_t){0, 0, width, height});
if (!at_bottom) { struct fcft_font *font = term->fonts[0];
/* TODO: insert rendering code here */ pixman_color_t fg = color_hex_to_pixman(term->colors.table[7]);
wchar_t text[64];
swprintf(text, sizeof(text) / sizeof(text[0]), L"%d%%", percentage);
unsigned x = width - margin - wcslen(text) * term->cell_width;
const unsigned y = margin;
for (size_t i = 0; i < wcslen(text); i++) {
const struct fcft_glyph *glyph = fcft_glyph_rasterize(
font, text[i], term->font_subpixel);
if (glyph == NULL)
continue;
pixman_image_t *src = pixman_image_create_solid_fill(&fg);
pixman_image_composite32(
PIXMAN_OP_OVER, src, glyph->pix, buf->pix[0], 0, 0, 0, 0,
x + glyph->x, y + font_baseline(term) - glyph->y,
glyph->width, glyph->height);
pixman_image_unref(src);
x += term->cell_width;
} }
wl_subsurface_set_position(
win->scrollback_indicator_sub_surface,
(term->width - term->margins.right - width) / scale,
term->margins.top / scale + term->cell_height);
wl_surface_attach(win->scrollback_indicator_surface, buf->wl_buf, 0, 0);
wl_surface_damage_buffer(win->scrollback_indicator_surface, 0, 0, width, height);
wl_surface_set_buffer_scale(win->scrollback_indicator_surface, scale);
struct wl_region *region = wl_compositor_create_region(wayl->compositor);
if (region != NULL) {
wl_region_add(region, 0, 0, width, height);
wl_surface_set_opaque_region(win->scrollback_indicator_surface, region);
wl_region_destroy(region);
}
wl_surface_commit(win->scrollback_indicator_surface);
} }
static void frame_callback( static void frame_callback(