=================================================================== RCS file: /cvsrepo/anoncvs/cvs/src/usr.bin/tmux/mode-tree.c,v retrieving revision 1.27 retrieving revision 1.28 diff -u -r1.27 -r1.28 --- src/usr.bin/tmux/mode-tree.c 2019/03/18 20:53:33 1.27 +++ src/usr.bin/tmux/mode-tree.c 2019/05/12 08:58:09 1.28 @@ -1,4 +1,4 @@ -/* $OpenBSD: mode-tree.c,v 1.27 2019/03/18 20:53:33 nicm Exp $ */ +/* $OpenBSD: mode-tree.c,v 1.28 2019/05/12 08:58:09 nicm Exp $ */ /* * Copyright (c) 2017 Nicholas Marriott @@ -35,6 +35,7 @@ struct window_pane *wp; void *modedata; + const char *menu; const char **sort_list; u_int sort_size; @@ -43,6 +44,7 @@ mode_tree_build_cb buildcb; mode_tree_draw_cb drawcb; mode_tree_search_cb searchcb; + mode_tree_menu_cb menucb; struct mode_tree_list children; struct mode_tree_list saved; @@ -89,8 +91,21 @@ int flat; }; +struct mode_tree_menu { + struct mode_tree_data *data; + struct client *c; + u_int line; + void *itemdata; +}; + static void mode_tree_free_items(struct mode_tree_list *); +#define MODE_TREE_MENU \ + "Scroll Left,<,|" \ + "Scroll Right,>,|" \ + "|" \ + "Cancel,q," + static struct mode_tree_item * mode_tree_find_item(struct mode_tree_list *mtl, uint64_t tag) { @@ -299,8 +314,9 @@ struct mode_tree_data * mode_tree_start(struct window_pane *wp, struct args *args, mode_tree_build_cb buildcb, mode_tree_draw_cb drawcb, - mode_tree_search_cb searchcb, void *modedata, const char **sort_list, - u_int sort_size, struct screen **s) + mode_tree_search_cb searchcb, mode_tree_menu_cb menucb, void *modedata, + const char *menu, const char **sort_list, u_int sort_size, + struct screen **s) { struct mode_tree_data *mtd; const char *sort; @@ -311,6 +327,7 @@ mtd->wp = wp; mtd->modedata = modedata; + mtd->menu = menu; mtd->sort_list = sort_list; mtd->sort_size = sort_size; @@ -334,6 +351,7 @@ mtd->buildcb = buildcb; mtd->drawcb = drawcb; mtd->searchcb = searchcb; + mtd->menucb = menucb; TAILQ_INIT(&mtd->children); @@ -762,6 +780,71 @@ mode_tree_remove_ref(data); } +static void +mode_tree_menu_callback(__unused struct menu *menu, __unused u_int idx, + key_code key, void *data) +{ + struct mode_tree_menu *mtm = data; + struct mode_tree_data *mtd = mtm->data; + struct mode_tree_item *mti; + + if (mtd->dead || key == KEYC_NONE) + goto out; + + if (mtm->line >= mtd->line_size) + goto out; + mti = mtd->line_list[mtm->line].item; + if (mti->itemdata != mtm->itemdata) + goto out; + mtd->current = mtm->line; + mtd->menucb (mtd->modedata, mtm->c, key); + +out: + mode_tree_remove_ref(mtd); + free(mtm); +} + +static void +mode_tree_display_menu(struct mode_tree_data *mtd, struct client *c, u_int x, + u_int y, int outside) +{ + struct mode_tree_item *mti; + struct menu *menu; + struct mode_tree_menu *mtm; + const char *s; + char *title; + u_int line; + + if (mtd->offset + y > mtd->line_size - 1) + line = mtd->current; + else + line = mtd->offset + y; + mti = mtd->line_list[line].item; + + if (!outside) { + s = mtd->menu; + xasprintf(&title, "#[align=centre]%s", mti->name); + } else { + s = MODE_TREE_MENU; + title = xstrdup(""); + } + menu = menu_create(s, c, NULL, title); + free(title); + if (menu == NULL) + return; + + mtm = xmalloc(sizeof *mtm); + mtm->data = mtd; + mtm->c = c; + mtm->line = line; + mtm->itemdata = mti->itemdata; + mtd->references++; + + if (menu_display(menu, 0, NULL, x, y, c, NULL, mode_tree_menu_callback, + mtm) != 0) + menu_free(menu); +} + int mode_tree_key(struct mode_tree_data *mtd, struct client *c, key_code *key, struct mouse_event *m, u_int *xp, u_int *yp) @@ -772,7 +855,7 @@ int choice; key_code tmp; - if (KEYC_IS_MOUSE(*key)) { + if (KEYC_IS_MOUSE(*key) && m != NULL) { if (cmd_mouse_at(mtd->wp, m, &x, &y, 0) != 0) { *key = KEYC_NONE; return (0); @@ -782,20 +865,29 @@ if (yp != NULL) *yp = y; if (x > mtd->width || y > mtd->height) { + if (*key == KEYC_MOUSEDOWN3_PANE) + mode_tree_display_menu(mtd, c, x, y, 1); if (!mtd->preview) *key = KEYC_NONE; return (0); } if (mtd->offset + y < mtd->line_size) { if (*key == KEYC_MOUSEDOWN1_PANE || + *key == KEYC_MOUSEDOWN3_PANE || *key == KEYC_DOUBLECLICK1_PANE) mtd->current = mtd->offset + y; if (*key == KEYC_DOUBLECLICK1_PANE) *key = '\r'; - else + else { + if (*key == KEYC_MOUSEDOWN3_PANE) + mode_tree_display_menu(mtd, c, x, y, 0); *key = KEYC_NONE; - } else + } + } else { + if (*key == KEYC_MOUSEDOWN3_PANE) + mode_tree_display_menu(mtd, c, x, y, 0); *key = KEYC_NONE; + } return (0); } @@ -879,7 +971,8 @@ current->tagged = 1; } else current->tagged = 0; - mode_tree_down(mtd, 0); + if (m != NULL) + mode_tree_down(mtd, 0); break; case 'T': for (i = 0; i < mtd->line_size; i++)