diff options
Diffstat (limited to 'taro')
| -rw-r--r-- | taro/daemon.c | 2 | ||||
| -rw-r--r-- | taro/tests/notcurses_ffmpeg.c | 2 | ||||
| -rw-r--r-- | taro/ui.c | 276 |
3 files changed, 140 insertions, 140 deletions
diff --git a/taro/daemon.c b/taro/daemon.c index a26de8b..6ceba90 100644 --- a/taro/daemon.c +++ b/taro/daemon.c @@ -482,7 +482,7 @@ static void sigint_handler(s32 signum) s32 main(void) { - if (!nn_common_init() || !open_config(&dmon.conf, true)) { + if (!nn_common_init(NULL) || !open_config(&dmon.conf, true)) { return EXIT_FAILURE; } diff --git a/taro/tests/notcurses_ffmpeg.c b/taro/tests/notcurses_ffmpeg.c index adf9689..342d115 100644 --- a/taro/tests/notcurses_ffmpeg.c +++ b/taro/tests/notcurses_ffmpeg.c @@ -5,7 +5,7 @@ s32 main(void) { - if (!nn_common_init()) return EXIT_FAILURE; + if (!nn_common_init(NULL)) return EXIT_FAILURE; struct notcurses *nc = notcurses_init(NULL, stdin); @@ -15,6 +15,7 @@ #define PIXEL_BLIT 1 #define TIMER_UPDATE_BASE 1.f +#define TIMER_TICK(delay) MAX(TIMER_UPDATE_BASE * (delay / 1000000.f), 0.001f) #define TEXT_UPDATE_RATE 0.4f #define FLASH_DURATION 0.4f @@ -75,7 +76,6 @@ struct monitors { array(char *) monitors; s32 selected_monitor; s32 set_monitor; - f32 flash; str selection_path; }; @@ -83,12 +83,13 @@ struct grid { struct ncplane *p; s32 tiles_x; s32 tiles_y; + u32 tiles_per_page; + s32 previous_index; s32 min_index; s32 max_index; s32 selected_index; s32 set_index; f32 flash; - u32 tiles_per_page; array(struct tile) tiles; }; @@ -100,12 +101,11 @@ struct info_prop { struct info { struct ncplane *ip; struct entry *e; - f32 flash; bool blitted; struct scrolling_text text; u32 max_props; - s32 selected_prop; array(struct info_prop) props; + s32 selected_prop; }; enum { @@ -125,6 +125,7 @@ struct ui { u32 term_rows; u32 term_cols; u8 selected_menu; + u8 previous_menu; struct ncplane *p, *mp, *gp, *ip; struct monitors m; struct grid g; @@ -134,9 +135,9 @@ struct ui { struct config conf; }; -// --------- +// ------- // Client -// --------- +// ------- static s32 get_entry_from_config(struct ui *u) { @@ -183,11 +184,7 @@ static void write_selected_entry_to_config(struct ui *u) al_str_from(&config, "||"); } else { al_str_clone(&config, &u->n.e->id); - if (u->n.e->has_package) { - al_str_cat(&config, &al_str_c("_p")); - } else { - al_str_cat(&config, &al_str_c("_d")); - } + al_str_cat(&config, u->n.e->has_package ? &al_str_c("_p") : &al_str_c("_d")); al_str_cat(&config, &al_str_c("|false,100|")); struct prop *p; al_array_foreach_ptr(u->n.e->props, i, p) { @@ -200,16 +197,14 @@ static void write_selected_entry_to_config(struct ui *u) } al_str_cat(&config, &al_str_c(",")); } - if (al_str_at(&config, config.length - 1) == ',') { - config.length--; - } + if (al_str_atr(&config, 1) == ',') config.length--; } nn_file_open_and_replace(&u->m.selection_path, &config, true); } -// --------- -// Interface -// --------- +// --------------- +// User Interface +// --------------- static bool init_info(struct info *n) { @@ -305,14 +300,14 @@ static bool init_ui(struct ui *u) struct image *get_image_from_pool(struct image_pool *pool, str *path) { u32 hash = al_str_hash(path); - struct image *rimg; - al_array_foreach_ptr(pool->images, i, rimg) { - if (rimg->hash == hash) { - return rimg; - } + + struct image *cached; + al_array_foreach_ptr(pool->images, i, cached) { + if (cached->hash == hash) return cached; } if (pool->images.count >= pool->max) { + // This should at least be based on LRU. for (u32 i = 0; i < pool->chunk_size; i++) { ncvisual_destroy(al_array_at(pool->images, i).v); } @@ -320,19 +315,13 @@ struct image *get_image_from_pool(struct image_pool *pool, str *path) } u32 index = al_str_rfind(path, '.'); - bool gif = index != AL_STR_NPOS && al_str_cmp(path, &al_str_c(".gif"), index, 4) == 0; - + bool is_gif = index != AL_STR_NPOS && al_str_cmp(path, &al_str_c(".gif"), index, 4) == 0; char *c_str = al_str_to_c_str(path); - struct image img = { - .hash = hash, - .gif = gif, - .errored = false, - .v = ncvisual_from_file(c_str) - }; + struct ncvisual *v = ncvisual_from_file(c_str); al_free(c_str); - if (!img.v) return NULL; - al_array_push(pool->images, img); + if (!v) return NULL; + al_array_push(pool->images, ((struct image){ hash, is_gif, false, v })); return &al_array_last(pool->images); } @@ -358,8 +347,7 @@ static s32 resize_cb(struct ncplane *p) } u->n.blitted = false; ncplane_erase(u->n.ip); - // To not break images we need to erase them - // then render them in 2 steps. + // To not break images we need to erase then render them in 2 steps. notcurses_refresh(u->nc, NULL, NULL); notcurses_render(u->nc); draw_monitors(u, &u->m); @@ -421,14 +409,15 @@ static void maybe_destroy_info(struct info *n) static void set_info_entry(struct ui *u, struct info *n) { - n->e = &al_array_at(u->db.entries, u->g.selected_index); + struct entry *e = &al_array_at(u->db.entries, u->g.selected_index); + if (e == n->e) return; + n->e = e; n->blitted = false; s32 width = al_wstr_width(&u->n.e->title); s32 tx = 2 + ((width < INFO_TEXT_WIDTH) ? (INFO_TEXT_WIDTH - width) / 2 : 0); set_scrolling_text(&n->text, &u->n.e->title, INFO_IMG_HEIGHT + 1, tx, INFO_TEXT_WIDTH); - n->selected_prop = 0; n->props.count = 0; struct prop *p; struct info_prop *ip; @@ -439,6 +428,7 @@ static void set_info_entry(struct ui *u, struct info *n) s32 ty = INFO_IMG_HEIGHT + 3 + ((i % n->max_props) * 2); set_scrolling_text(&ip->text, &p->title, ty, 0, PROP_TEXT_WIDTH); } + n->selected_prop = 0; } static bool layout_info(struct ui *u, struct info *n, struct ncplane *parent, s32 height) @@ -449,14 +439,11 @@ static bool layout_info(struct ui *u, struct info *n, struct ncplane *parent, s3 if (!n->max_props) return false; struct ncplane_options nopts = { 0 }; - nopts.cols = INFO_IMG_WIDTH; nopts.rows = INFO_IMG_HEIGHT; nopts.x = 0; nopts.y = 1; - - n->ip = ncplane_create(parent, &nopts); - if (!n->ip) { + if (!(n->ip = ncplane_create(parent, &nopts))) { maybe_destroy_info(n); return false; } @@ -486,7 +473,11 @@ static void maybe_destroy_grid(struct grid *g) static void set_grid_tiles(struct ui *u, struct grid *g) { u32 selected = (g->selected_index >= 0) ? g->selected_index : g->set_index; - u32 index = (selected - (selected % g->tiles_per_page)); + u32 index = selected - (selected % g->tiles_per_page); + if (g->previous_index >= 0 && index == (u32)g->previous_index) { + return; + } + g->previous_index = index; g->min_index = index; g->max_index = index; @@ -552,19 +543,16 @@ static bool layout_grid(struct ui *u, struct grid *g, struct ncplane *parent, s3 { maybe_destroy_grid(g); - s32 inner_width = width; - s32 inner_height = height; - g->tiles_x = width / GRID_TILE_WIDTH; g->tiles_y = height / GRID_TILE_HEIGHT; - if (!g->tiles_x || !g->tiles_y) { // Window is too small. return false; } - g->tiles_per_page = g->tiles_x * g->tiles_y; + g->previous_index = -1; + // Reserve space for 4 pages, but never shrink. if (u->pool.chunk_size < g->tiles_per_page) { u->pool.chunk_size = g->tiles_per_page; @@ -572,35 +560,28 @@ static bool layout_grid(struct ui *u, struct grid *g, struct ncplane *parent, s3 al_array_reserve(u->pool.images, u->pool.max); } - while (inner_width && inner_width % g->tiles_x != 0) { - inner_width--; - } - - while (inner_height && inner_height % g->tiles_y != 0) { - inner_height--; - } + s32 inner_width = width; + s32 inner_height = height; + while (inner_width && inner_width % g->tiles_x != 0) inner_width--; + while (inner_height && inner_height % g->tiles_y != 0) inner_height--; struct ncplane_options nopts = { 0 }; - nopts.cols = inner_width; nopts.rows = inner_height; nopts.x = (width - (g->tiles_x * GRID_TILE_WIDTH)) / 2; nopts.y = (height - (g->tiles_y * GRID_TILE_HEIGHT)) / 2; + if (!(g->p = ncplane_create(parent, &nopts))) { + return false; + } - g->p = ncplane_create(parent, &nopts); - if (!g->p) return false; - + struct tile t = { 0 }; for (s32 y = 0; y < g->tiles_y; y++) { for (s32 x = 0; x < g->tiles_x; x++) { - struct tile t = { 0 }; - nopts.cols = GRID_TILE_WIDTH; nopts.rows = GRID_TILE_HEIGHT; nopts.x = x * GRID_TILE_WIDTH; nopts.y = y * GRID_TILE_HEIGHT; - - t.p = ncplane_create(g->p, &nopts); - if (!t.p) { + if (!(t.p = ncplane_create(g->p, &nopts))) { maybe_destroy_grid(g); return false; } @@ -609,9 +590,7 @@ static bool layout_grid(struct ui *u, struct grid *g, struct ncplane *parent, s3 nopts.rows = GRID_TILE_HEIGHT - 2; nopts.x = 1; nopts.y = 1; - - t.ip = ncplane_create(t.p, &nopts); - if (!t.ip) { + if (!(t.ip = ncplane_create(t.p, &nopts))) { maybe_destroy_grid(g); return false; } @@ -655,7 +634,6 @@ bool layout_ui(struct ui *u) u32 rwidth = even ? UI_RESERVE_WIDTH + 1 : UI_RESERVE_WIDTH; u32 rheight = even ? UI_RESERVE_HEIGHT + 1 : UI_RESERVE_HEIGHT; - if (u->term_cols < GRID_TILE_WIDTH + rwidth || u->term_rows < GRID_TILE_HEIGHT + rheight) { return false; } @@ -663,18 +641,14 @@ bool layout_ui(struct ui *u) maybe_destroy_ui(u); struct ncplane_options nopts = { 0 }; - nopts.rows = u->term_rows; nopts.cols = u->term_cols; - - u->p = ncplane_create(notcurses_stdplane(u->nc), &nopts); - if (!u->p) { + if (!(u->p = ncplane_create(notcurses_stdplane(u->nc), &nopts))) { return false; } s32 cols = (s32)u->term_cols - rwidth; s32 rows = (s32)u->term_rows - rheight; - if (cols < 0 || rows < 0) { maybe_destroy_ui(u); return false; @@ -684,9 +658,7 @@ bool layout_ui(struct ui *u) nopts.y = 1; nopts.cols = cols - 1; nopts.rows = 1; - - u->mp = ncplane_create(u->p, &nopts); - if (!u->mp) { + if (!(u->mp = ncplane_create(u->p, &nopts))) { maybe_destroy_ui(u); return false; } @@ -695,9 +667,7 @@ bool layout_ui(struct ui *u) nopts.y = 2; nopts.cols = cols - 1; nopts.rows = rows - 2; - - u->gp = ncplane_create(u->p, &nopts); - if (!u->gp) { + if (!(u->gp = ncplane_create(u->p, &nopts))) { maybe_destroy_ui(u); return false; } @@ -711,9 +681,7 @@ bool layout_ui(struct ui *u) nopts.y = INFO_Y_OFFSET; nopts.cols = INFO_WIDTH; nopts.rows = u->term_rows - rheight; - - u->ip = ncplane_create(u->p, &nopts); - if (!u->ip) { + if (!(u->ip = ncplane_create(u->p, &nopts))) { maybe_destroy_ui(u); return false; } @@ -743,8 +711,7 @@ void draw_monitors(struct ui *u, struct monitors *m) } ncplane_set_styles(u->mp, NCSTYLE_BOLD); - s32 w = ncplane_dim_x(u->mp); - s32 x = ((w - 1) - width) / 2; + s32 x = ((ncplane_dim_x(u->mp) - 1) - width) / 2; ncplane_cursor_move_yx(u->mp, 0, x); if (u->m.selected_monitor == -1) { @@ -758,13 +725,12 @@ void draw_monitors(struct ui *u, struct monitors *m) ncplane_putstr(u->mp, no_monitors); } else { al_array_foreach(m->monitors, i, monitor) { - if (m->flash <= 0.f && u->selected_menu == MENU_MONITORS && i == (u32)m->selected_monitor) { + if (u->selected_menu == MENU_MONITORS && i == (u32)m->selected_monitor) { ncplane_set_bg_palindex(u->mp, 8); ncplane_set_fg_palindex(u->mp, 0); } else if (i == (u32)m->set_monitor) { ncplane_set_bg_palindex(u->mp, 7); ncplane_set_fg_palindex(u->mp, 0); - m->flash -= MAX(TIMER_UPDATE_BASE * (u->delay / 1000000.f), 0.001f); } else { ncplane_set_fg_default(u->mp); ncplane_set_bg_default(u->mp); @@ -781,7 +747,6 @@ void draw_info(struct ui *u, struct info *n, bool update_text) ncplane_erase(u->ip); - struct ncvisual_options vopts = { 0 }; vopts.scaling = PIXEL_BLIT ? NCSCALE_SCALE_HIRES : NCSCALE_STRETCH; vopts.blitter = PIXEL_BLIT ? NCBLIT_PIXEL : NCBLIT_2x1; @@ -806,9 +771,8 @@ void draw_info(struct ui *u, struct info *n, bool update_text) ncplane_set_fg_default(u->ip); draw_scrolling_text(u->ip, &n->text, update_text); - u32 selected_index = n->selected_prop - (n->selected_prop % n->max_props); + u32 i, index, selected_index = n->selected_prop - (n->selected_prop % n->max_props); struct info_prop *ip = NULL; - u32 i, index; for (i = 0; i < n->max_props; i++) { index = i + selected_index; if (index >= n->props.count) { @@ -816,24 +780,17 @@ void draw_info(struct ui *u, struct info *n, bool update_text) } ip = &al_array_at(n->props, index); if (u->selected_menu == MENU_INFO && index == (u32)n->selected_prop) { - if (n->flash > 0.f) { - ncplane_set_fg_palindex(u->ip, 0); - ncplane_set_bg_palindex(u->ip, 7); - n->flash -= MAX(TIMER_UPDATE_BASE * (u->delay / 1000000.f), 0.001f); - } else { - ncplane_set_fg_palindex(u->ip, 8); - ncplane_set_bg_default(u->ip); - } + ncplane_set_fg_palindex(u->ip, 8); } else { ncplane_set_fg_default(u->ip); - ncplane_set_bg_default(u->ip); } draw_scrolling_text(u->ip, &ip->text, update_text); switch (ip->p->type) { - case PROP_TYPE_BOOL: - ncplane_putstr_yx(u->ip, ip->text.y, ip->text.width + 2, - *((bool *)ip->p->value) ? "[x]" : "[ ]"); + case PROP_TYPE_BOOL: { + char *c = *((bool *)ip->p->value) ? "[x]" : "[ ]"; + ncplane_putstr_yx(u->ip, ip->text.y, ip->text.width + 2, c); break; + } case PROP_TYPE_SLIDER: { char c[16]; al_snprintf(c, sizeof(c), "%.2f", ((struct slider_value *)ip->p->value)->value); @@ -847,21 +804,27 @@ void draw_info(struct ui *u, struct info *n, bool update_text) } } -static void set_tile_highlight(struct tile *t, s32 bindex, s32 findex) +static void set_tile_highlight(struct tile *t, s32 findex, s32 bindex) { - ncplane_set_bg_alpha(t->p, NCALPHA_TRANSPARENT); struct nccell ncl; nccell_init(&ncl); nccell_load(t->p, &ncl, " "); nccell_set_bg_palindex(&ncl, bindex); + nccell_set_fg_default(&ncl); ncplane_polyfill_yx(t->p, 1, 0, &ncl); + nccell_release(t->p, &ncl); + ncplane_set_bg_default(t->p); ncplane_set_fg_palindex(t->p, bindex); for (s32 i = 0; i < GRID_TILE_WIDTH; i++) { ncplane_putwc_yx(t->p, 0, i, L'▃'); } - ncplane_set_fg_palindex(t->p, findex); + (void)findex; + //ncplane_set_fg_palindex(t->p, findex); + // If we set both fg and bg palindex here, the fg color + // will carry over to the info prop list for a split second. + // This might be a notcurses bug, I need to look more carefully. + ncplane_set_fg_rgb8(t->p, 0, 0, 0); ncplane_set_bg_palindex(t->p, bindex); - ncplane_set_bg_alpha(t->p, NCALPHA_OPAQUE); ncplane_set_styles(t->p, NCSTYLE_BOLD); } @@ -873,12 +836,9 @@ void draw_grid_tiles(struct ui *u, struct grid *g, bool update_text) vopts.scaling = PIXEL_BLIT ? NCSCALE_SCALE_HIRES : NCSCALE_STRETCH; vopts.blitter = PIXEL_BLIT ? NCBLIT_PIXEL : NCBLIT_2x1; - s32 index = (g->selected_index - (g->selected_index % g->tiles_per_page)); struct tile *t; al_array_foreach_ptr(g->tiles, i, t) { - ncplane_erase(t->p); - if (!t->e) continue; - if (t->e->has_preview) { + if (t->e && t->e->has_preview) { struct image *img = get_image_from_pool(&u->pool, &t->e->preview_path); if (img && !t->blitted && !img->errored) { vopts.n = t->ip; @@ -886,15 +846,19 @@ void draw_grid_tiles(struct ui *u, struct grid *g, bool update_text) t->blitted = true; } } + } + s32 index = g->selected_index - (g->selected_index % g->tiles_per_page); + al_array_foreach_ptr(g->tiles, i, t) { + ncplane_erase(t->p); + if (!t->e) continue; if (index == g->selected_index && g->flash <= 0.f && u->selected_menu == MENU_GRID) { - set_tile_highlight(t, 8, 0); + set_tile_highlight(t, 0, 8); } else if (index == g->set_index && g->set_index >= 0) { - set_tile_highlight(t, 7, 0); - g->flash -= MAX(TIMER_UPDATE_BASE * (u->delay / 1000000.f), 0.001f); + set_tile_highlight(t, 0, 7); + g->flash -= TIMER_TICK(u->delay); } else { ncplane_set_fg_default(t->p); ncplane_set_bg_default(t->p); - ncplane_set_bg_alpha(t->p, NCALPHA_TRANSPARENT); ncplane_set_styles(t->p, NCSTYLE_NONE); } if (t->text.s && !al_wstr_is_empty(t->text.s)) { @@ -928,10 +892,17 @@ static bool handle_input_monitors(struct ui *u, struct monitors *m, struct ncinp should_redraw_monitors = true; break; } + case NCKEY_DOWN: + case 'j': { + u->selected_menu = MENU_GRID; + should_redraw_monitors = true; + should_redraw_grid = true; + break; + } case NCKEY_RETURN: case NCKEY_SPACE: { select_monitor(u); - m->flash = FLASH_DURATION; + u->selected_menu = MENU_GRID; should_redraw_monitors = true; should_redraw_grid = true; should_redraw_info = true; @@ -1055,6 +1026,7 @@ static bool handle_input_grid(struct ui *u, struct grid *g, struct ncinput *inpu bool should_update_grid = false; bool should_redraw_grid = false; bool should_redraw_info = false; + bool should_redraw_monitors = false; switch (input->id) { case NCKEY_LEFT: case 'h': { @@ -1087,10 +1059,12 @@ static bool handle_input_grid(struct ui *u, struct grid *g, struct ncinput *inpu case NCKEY_UP: case 'k': { if (g->selected_index - g->tiles_x < g->min_index) { - return false; + u->selected_menu = MENU_MONITORS; + should_redraw_monitors = true; + } else { + g->selected_index -= g->tiles_x; + should_redraw_info = true; } - g->selected_index -= g->tiles_x; - should_redraw_info = true; should_redraw_grid = true; break; } @@ -1104,6 +1078,18 @@ static bool handle_input_grid(struct ui *u, struct grid *g, struct ncinput *inpu should_redraw_grid = true; break; } + case '0': { + g->selected_index -= g->selected_index % g->tiles_x; + should_redraw_info = true; + should_redraw_grid = true; + break; + } + case '4': { // '$' in vim. + g->selected_index += g->tiles_x - (g->selected_index % g->tiles_x) - 1; + should_redraw_info = true; + should_redraw_grid = true; + break; + } case 'f': { if (grid_next_page(u, &u->g, 0)) { should_update_grid = true; @@ -1160,6 +1146,9 @@ static bool handle_input_grid(struct ui *u, struct grid *g, struct ncinput *inpu set_info_entry(u, &u->n); draw_info(u, &u->n, false); } + if (should_redraw_monitors) { + draw_monitors(u, &u->m); + } return should_redraw_grid || should_redraw_info; } @@ -1172,44 +1161,55 @@ static void input_poll_callback(void *userdata, s32 revents) u32 ret; while (1) { ret = notcurses_get_nblock(u->nc, &input); - if (ret == (u32)-1 || ret == 0) { - break; - } + if (ret == (u32)-1 || ret == 0) break; if (input.evtype == NCTYPE_PRESS || input.evtype == NCTYPE_UNKNOWN) { if (input.id == NCKEY_TAB) { switch (u->selected_menu) { + case MENU_MONITORS: + break; case MENU_GRID: if (u->n.props.count > 0) { u->selected_menu = MENU_INFO; - u->n.flash = FLASH_DURATION; - } else { - u->selected_menu = MENU_MONITORS; } break; case MENU_INFO: - u->selected_menu = MENU_MONITORS; - break; - case MENU_MONITORS: u->selected_menu = MENU_GRID; break; } draw_info(u, &u->n, false); - draw_monitors(u, &u->m); draw_grid_tiles(u, &u->g, false); should_render = true; + } else if (input.id == 'm') { + if (u->selected_menu != MENU_MONITORS) { + u->previous_menu = u->selected_menu; + u->selected_menu = MENU_MONITORS; + } else { + u->selected_menu = u->previous_menu; + } + draw_monitors(u, &u->m); + switch (u->previous_menu) { + case MENU_GRID: + draw_grid_tiles(u, &u->g, false); + break; + case MENU_INFO: + draw_info(u, &u->n, false); + break; + } + should_render = true; } else if (input.id == 'q') { nn_event_loop_break(&u->loop); - } - switch (u->selected_menu) { - case MENU_GRID: - should_render |= handle_input_grid(u, &u->g, &input); - break; - case MENU_INFO: - should_render |= handle_input_info(u, &u->n, &input); - break; - case MENU_MONITORS: - should_render |= handle_input_monitors(u, &u->m, &input); - break; + } else { + switch (u->selected_menu) { + case MENU_GRID: + should_render |= handle_input_grid(u, &u->g, &input); + break; + case MENU_INFO: + should_render |= handle_input_info(u, &u->n, &input); + break; + case MENU_MONITORS: + should_render |= handle_input_monitors(u, &u->m, &input); + break; + } } } } @@ -1231,7 +1231,7 @@ static void timer_callback(void *userdata, struct nn_timer *timer) draw_grid_tiles(u, &u->g, true); draw_info(u, &u->n, true); } else { - u->text_update -= MAX(TIMER_UPDATE_BASE * (u->delay / 1000000.f), 0.001f); + u->text_update -= TIMER_TICK(u->delay); draw_grid_tiles(u, &u->g, false); draw_info(u, &u->n, false); } @@ -1248,7 +1248,7 @@ static struct ui u = { 0 }; s32 main(void) { - if (!nn_common_init()) return EXIT_FAILURE; + if (!nn_common_init(NULL)) return EXIT_FAILURE; if (!open_config(&u.conf, false)) { log_error("failed to open config, run `tarod` at least once to generate needed config"); |