From 0dd8951cb3d3b260575162ebbd1914c61a10d876 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Sun, 21 Jul 2019 19:14:19 +0200 Subject: [PATCH] flash: implement 'flash' Use our own escape sequence for the 'flash' terminfo entry. Implemented by arming a timer FD and setting a boolean that indicates we're currently "flashing". The renderer draws a semi-transparent yellowish layer over the entire window when "flashing" is active. --- csi.c | 19 ++++++++++++++++++ foot.info | 2 +- main.c | 24 ++++++++++++++++++++++ render.c | 58 ++++++++++++++++++++++++++++++++++-------------------- terminal.h | 3 +++ 5 files changed, 84 insertions(+), 22 deletions(-) diff --git a/csi.c b/csi.c index 12579c27..4d40686d 100644 --- a/csi.c +++ b/csi.c @@ -5,6 +5,8 @@ #include #include +#include + #if defined(_DEBUG) #include #endif @@ -573,6 +575,23 @@ csi_dispatch(struct terminal *term, uint8_t final) break; } + case 1001: { + /* Our own private - flash */ + unsigned duration_ms = vt_param_get(term, 1, 100); + LOG_WARN("FLASH for %ums", duration_ms); + + struct itimerspec alarm = { + .it_value = {.tv_sec = 0, .tv_nsec = duration_ms * 1000000}, + }; + + if (timerfd_settime(term->flash_timer_fd, 0, &alarm, NULL) < 0) + LOG_ERRNO("failed to arm flash timer"); + else { + term->flash_active = true; + } + break; + } + default: LOG_WARN("ignoring %s", csi_as_string(term, final)); break; diff --git a/foot.info b/foot.info index aeb8e044..fc87905f 100644 --- a/foot.info +++ b/foot.info @@ -49,7 +49,7 @@ foot+base|foot base fragment, ed=\E[J, el=\E[K, el1=\E[1K, - flash=\E[?5h$<100/>\E[?5l, + flash=\E[1001;100t, home=\E[H, hpa=\E[%i%p1%dG, ht=^I, diff --git a/main.c b/main.c index 54140fd0..d7759c72 100644 --- a/main.c +++ b/main.c @@ -10,6 +10,8 @@ #include #include +#include + #include #include #include @@ -325,6 +327,7 @@ main(int argc, char *const *argv) .keypad_keys_mode = KEYPAD_NUMERICAL, .auto_margin = true, .window_title_stack = tll_init(), + .flash_timer_fd = timerfd_create(CLOCK_BOOTTIME, TFD_CLOEXEC), .vt = { .state = 1, /* STATE_GROUND */ .attrs = { @@ -681,6 +684,7 @@ main(int argc, char *const *argv) {.fd = wl_display_get_fd(term.wl.display), .events = POLLIN}, {.fd = term.ptmx, .events = POLLIN}, {.fd = term.kbd.repeat.pipe_read_fd, .events = POLLIN}, + {.fd = term.flash_timer_fd, .events = POLLIN}, }; wl_display_flush(term.wl.display); @@ -775,6 +779,23 @@ main(int argc, char *const *argv) if (fds[2].revents & POLLHUP) LOG_ERR("keyboard repeat handling thread died"); + + if (fds[3].revents & POLLIN) { + uint64_t expiration_count; + ssize_t ret = read( + term.flash_timer_fd, &expiration_count, sizeof(expiration_count)); + + if (ret < 0) + LOG_ERRNO("failed to read flash timer"); + else + LOG_DBG("flash timer expired %llu times", + (unsigned long long)expiration_count); + + term.flash_active = false; + term_damage_view(&term); + if (term.frame_callback == NULL) + grid_render(&term); + } } out: @@ -862,6 +883,9 @@ out: cairo_glyph_free(f->glyph_cache[j].glyphs); } + if (term.flash_timer_fd != -1) + close(term.flash_timer_fd); + if (term.ptmx != -1) close(term.ptmx); diff --git a/render.c b/render.c index db9881a3..9664cd20 100644 --- a/render.c +++ b/render.c @@ -296,34 +296,40 @@ grid_render(struct terminal *term) struct buffer *buf = shm_get_buffer(term->wl.shm, term->width, term->height); cairo_set_operator(buf->cairo, CAIRO_OPERATOR_SOURCE); + if (term->flash_active) + term_damage_view(term); + static struct buffer *last_buf = NULL; - if (last_buf != buf || false) { - if (last_buf != NULL) { - LOG_DBG("new buffer"); + static bool last_flash = false; - /* Fill area outside the cell grid with the default background color */ - int rmargin = term->cols * term->cell_width; - int bmargin = term->rows * term->cell_height; - int rmargin_width = term->width - rmargin; - int bmargin_height = term->height - bmargin; + /* If we resized the window, or is flashing, or just stopped flashing */ + if (last_buf != buf || term->flash_active || last_flash) { + LOG_DBG("new buffer"); - uint32_t _bg = !term->reverse ? term->colors.bg : term->colors.fg; - struct rgb bg = color_hex_to_rgb(_bg); - cairo_set_source_rgb(buf->cairo, bg.r, bg.g, bg.b); + /* Fill area outside the cell grid with the default background color */ + int rmargin = term->cols * term->cell_width; + int bmargin = term->rows * term->cell_height; + int rmargin_width = term->width - rmargin; + int bmargin_height = term->height - bmargin; - cairo_rectangle(buf->cairo, rmargin, 0, rmargin_width, term->height); - cairo_rectangle(buf->cairo, 0, bmargin, term->width, bmargin_height); - cairo_fill(buf->cairo); + uint32_t _bg = !term->reverse ? term->colors.bg : term->colors.fg; + struct rgb bg = color_hex_to_rgb(_bg); + cairo_set_source_rgb(buf->cairo, bg.r, bg.g, bg.b); - wl_surface_damage_buffer( - term->wl.surface, rmargin, 0, rmargin_width, term->height); - wl_surface_damage_buffer( - term->wl.surface, 0, bmargin, term->width, bmargin_height); + cairo_rectangle(buf->cairo, rmargin, 0, rmargin_width, term->height); + cairo_rectangle(buf->cairo, 0, bmargin, term->width, bmargin_height); + cairo_fill(buf->cairo); + + wl_surface_damage_buffer( + term->wl.surface, rmargin, 0, rmargin_width, term->height); + wl_surface_damage_buffer( + term->wl.surface, 0, bmargin, term->width, bmargin_height); + + /* Force a full grid refresh */ + term_damage_view(term); - /* Force a full grid refresh */ - term_damage_all(term); - } last_buf = buf; + last_flash = term->flash_active; } bool all_clean = tll_length(term->grid->scroll_damage) == 0; @@ -419,6 +425,16 @@ grid_render(struct terminal *term) if (gseq.count > 0) gseq_flush(term, buf); + if (term->flash_active) { + cairo_set_source_rgba(buf->cairo, 1.0, 1.0, 0.0, 0.5); + cairo_set_operator(buf->cairo, CAIRO_OPERATOR_OVER); + cairo_rectangle(buf->cairo, 0, 0, term->width, term->height); + cairo_fill(buf->cairo); + + wl_surface_damage_buffer( + term->wl.surface, 0, 0, term->width, term->height); + } + assert(term->grid->offset >= 0 && term->grid->offset < term->grid->num_rows); assert(term->grid->view >= 0 && term->grid->view < term->grid->num_rows); diff --git a/terminal.h b/terminal.h index a32f7890..805e2b99 100644 --- a/terminal.h +++ b/terminal.h @@ -243,6 +243,9 @@ struct terminal { char *window_title; tll(char *) window_title_stack; + bool flash_active; + int flash_timer_fd; + struct vt vt; struct kbd kbd;