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)
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 */
int scrollback_start = term->grid->offset + term->rows;
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
* 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
? 100
: 100 * rebased_view / term->grid->num_rows;
int next_row_no = term->grid->view + term->rows;
next_row_no &= term->grid->num_rows - 1;
const int scale = term->scale;
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? */
bool at_bottom = rebased_view + term->rows == term->grid->num_rows ||
term->grid->rows[next_row_no] == NULL;
unsigned long cookie = shm_cookie_scrollback_indicator(term);
struct buffer *buf = shm_get_buffer(
term->wl->shm, width, height, cookie, false, 1);
LOG_DBG("scrollback position: %d/%d (%d%%), at-bottom: %d",
rebased_view, term->grid->num_rows, percentage, at_bottom);
pixman_color_t bg = color_hex_to_pixman(term->colors.table[4]);
pixman_image_fill_rectangles(
PIXMAN_OP_SRC, buf->pix[0], &bg, 1,
&(pixman_rectangle16_t){0, 0, width, height});
if (!at_bottom) {
/* TODO: insert rendering code here */
struct fcft_font *font = term->fonts[0];
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(