From e21ab8cf335b7f3cf08ee0e3ead8471c7748277d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Sun, 21 Jul 2019 20:11:20 +0200 Subject: [PATCH] blink: implement 'blink' --- main.c | 24 ++++++++++++++++++++++++ render.c | 52 +++++++++++++++++++++++++++++++++++++++++++++++++++- terminal.h | 4 ++++ 3 files changed, 79 insertions(+), 1 deletion(-) diff --git a/main.c b/main.c index d7759c72..320e2595 100644 --- a/main.c +++ b/main.c @@ -328,6 +328,7 @@ main(int argc, char *const *argv) .auto_margin = true, .window_title_stack = tll_init(), .flash_timer_fd = timerfd_create(CLOCK_BOOTTIME, TFD_CLOEXEC), + .blink_timer_fd = timerfd_create(CLOCK_BOOTTIME, TFD_CLOEXEC), .vt = { .state = 1, /* STATE_GROUND */ .attrs = { @@ -685,6 +686,7 @@ main(int argc, char *const *argv) {.fd = term.ptmx, .events = POLLIN}, {.fd = term.kbd.repeat.pipe_read_fd, .events = POLLIN}, {.fd = term.flash_timer_fd, .events = POLLIN}, + {.fd = term.blink_timer_fd, .events = POLLIN}, }; wl_display_flush(term.wl.display); @@ -796,6 +798,26 @@ main(int argc, char *const *argv) if (term.frame_callback == NULL) grid_render(&term); } + + if (fds[4].revents & POLLIN) { + uint64_t expiration_count; + ssize_t ret = read( + term.blink_timer_fd, &expiration_count, sizeof(expiration_count)); + + if (ret < 0) + LOG_ERRNO("failed to read blink timer"); + else + LOG_DBG("blink timer expired %llu times", + (unsigned long long)expiration_count); + + term.blink_mode = term.blink_mode == BLINK_ON + ? BLINK_OFF : BLINK_ON; + term_damage_view(&term); + + if (term.frame_callback == NULL) + grid_render(&term); + } + } out: @@ -885,6 +907,8 @@ out: if (term.flash_timer_fd != -1) close(term.flash_timer_fd); + if (term.blink_timer_fd != -1) + close(term.blink_timer_fd); if (term.ptmx != -1) close(term.ptmx); diff --git a/render.c b/render.c index 9664cd20..b41046b3 100644 --- a/render.c +++ b/render.c @@ -3,6 +3,7 @@ #include #include #include +#include #include #include @@ -117,6 +118,9 @@ render_cell(struct terminal *term, struct buffer *buf, const struct cell *cell, _bg = swap; } + if (cell->attrs.blink && term->blink_mode == BLINK_OFF) + _fg = _bg; + struct rgb fg = color_hex_to_rgb(_fg); struct rgb bg = color_hex_to_rgb(_bg); @@ -128,6 +132,20 @@ render_cell(struct terminal *term, struct buffer *buf, const struct cell *cell, cairo_rectangle(buf->cairo, x, y, width, height); cairo_fill(buf->cairo); + if (cell->attrs.blink && !term->is_blinking) { + /* First cell we see that has blink set - arm blink timer */ + LOG_DBG("arming blink timer"); + struct itimerspec alarm = { + .it_value = {.tv_sec = 0, .tv_nsec = 500 * 1000000}, + .it_interval = {.tv_sec = 0, .tv_nsec = 500 * 1000000}, + }; + + if (timerfd_settime(term->blink_timer_fd, 0, &alarm, NULL) < 0) + LOG_ERRNO("failed to arm blink timer"); + else + term->is_blinking = true; + } + if (cell->c[0] == '\0' || cell->attrs.conceal) return; @@ -365,7 +383,39 @@ grid_render(struct terminal *term) row->dirty = false; all_clean = false; - wl_surface_damage_buffer(term->wl.surface, 0, r * term->cell_height, term->width, term->cell_height); + wl_surface_damage_buffer( + term->wl.surface, + 0, r * term->cell_height, + term->width, term->cell_height); + } + + if (term->is_blinking) { + /* Check if there are still any visible blinking cells */ + bool none_is_blinking = true; + for (int r = 0; r < term->rows; r++) { + struct row *row = grid_row_in_view(term->grid, r); + for (int col = 0; col < term->cols; col++) { + if (row->cells[col].attrs.blink) { + none_is_blinking = false; + break; + } + } + } + + /* No, disarm the blink timer */ + if (none_is_blinking) { + LOG_DBG("disarming blink timer"); + + term->is_blinking = false; + term->blink_mode = BLINK_ON; + + if (timerfd_settime( + term->blink_timer_fd, 0, + &(struct itimerspec){0}, NULL) < 0) + { + LOG_ERRNO("failed to disarm blink timer"); + } + } } /* TODO: break out to function */ diff --git a/terminal.h b/terminal.h index 805e2b99..5ebcbd64 100644 --- a/terminal.h +++ b/terminal.h @@ -246,6 +246,10 @@ struct terminal { bool flash_active; int flash_timer_fd; + bool is_blinking; + enum { BLINK_ON, BLINK_OFF } blink_mode; + int blink_timer_fd; + struct vt vt; struct kbd kbd;