From 614611a8bd65e82efccdf44d4f9c23c0f35ed293 Mon Sep 17 00:00:00 2001 From: nicm Date: Fri, 13 Aug 2021 17:03:29 +0000 Subject: Add -B flag to remove border from popup. --- popup.c | 91 +++++++++++++++++++++++++++++++++++++++++++++++++---------------- 1 file changed, 69 insertions(+), 22 deletions(-) (limited to 'popup.c') diff --git a/popup.c b/popup.c index 57ce80be..f9a8e067 100644 --- a/popup.c +++ b/popup.c @@ -91,8 +91,13 @@ popup_set_client_cb(struct tty_ctx *ttyctx, struct client *c) ttyctx->wsx = c->tty.sx; ttyctx->wsy = c->tty.sy; - ttyctx->xoff = ttyctx->rxoff = pd->px + 1; - ttyctx->yoff = ttyctx->ryoff = pd->py + 1; + if (pd->flags & POPUP_NOBORDER) { + ttyctx->xoff = ttyctx->rxoff = pd->px; + ttyctx->yoff = ttyctx->ryoff = pd->py; + } else { + ttyctx->xoff = ttyctx->rxoff = pd->px + 1; + ttyctx->yoff = ttyctx->ryoff = pd->py + 1; + } return (1); } @@ -113,8 +118,13 @@ popup_mode_cb(struct client *c, u_int *cx, u_int *cy) { struct popup_data *pd = c->overlay_data; - *cx = pd->px + 1 + pd->s.cx; - *cy = pd->py + 1 + pd->s.cy; + if (pd->flags & POPUP_NOBORDER) { + *cx = pd->px + pd->s.cx; + *cy = pd->py + pd->s.cy; + } else { + *cx = pd->px + 1 + pd->s.cx; + *cy = pd->py + 1 + pd->s.cy; + } return (&pd->s); } @@ -145,8 +155,10 @@ popup_draw_cb(struct client *c, __unused struct screen_redraw_ctx *ctx0) screen_write_start(&ctx, &s); screen_write_clearscreen(&ctx, 8); - /* Skip drawing popup if the terminal is too small. */ - if (pd->sx > 2 && pd->sy > 2) { + if (pd->flags & POPUP_NOBORDER) { + screen_write_cursormove(&ctx, 0, 0, 0); + screen_write_fast_copy(&ctx, &pd->s, 0, 0, pd->sx, pd->sy); + } else if (pd->sx > 2 && pd->sy > 2) { screen_write_box(&ctx, pd->sx, pd->sy); screen_write_cursormove(&ctx, 1, 1, 0); screen_write_fast_copy(&ctx, &pd->s, 0, 0, pd->sx - 2, @@ -218,7 +230,11 @@ popup_resize_cb(struct client *c) pd->px = pd->ppx; /* Avoid zero size screens. */ - if (pd->sx > 2 && pd->sy > 2) { + if (pd->flags & POPUP_NOBORDER) { + screen_resize(&pd->s, pd->sx, pd->sy, 0); + if (pd->job != NULL) + job_resize(pd->job, pd->sx, pd->sy ); + } else if (pd->sx > 2 && pd->sy > 2) { screen_resize(&pd->s, pd->sx - 2, pd->sy - 2, 0); if (pd->job != NULL) job_resize(pd->job, pd->sx - 2, pd->sy - 2); @@ -254,18 +270,31 @@ popup_handle_drag(struct client *c, struct popup_data *pd, pd->ppy = py; server_redraw_client(c); } else if (pd->dragging == SIZE) { - if (m->x < pd->px + 3) - return; - if (m->y < pd->py + 3) - return; + if (pd->flags & POPUP_NOBORDER) { + if (m->x < pd->px + 1) + return; + if (m->y < pd->py + 1) + return; + } else { + if (m->x < pd->px + 3) + return; + if (m->y < pd->py + 3) + return; + } pd->sx = m->x - pd->px; pd->sy = m->y - pd->py; pd->psx = pd->sx; pd->psy = pd->sy; - screen_resize(&pd->s, pd->sx - 2, pd->sy - 2, 0); - if (pd->job != NULL) - job_resize(pd->job, pd->sx - 2, pd->sy - 2); + if (pd->flags & POPUP_NOBORDER) { + screen_resize(&pd->s, pd->sx, pd->sy, 0); + if (pd->job != NULL) + job_resize(pd->job, pd->sx, pd->sy); + } else { + screen_resize(&pd->s, pd->sx - 2, pd->sy - 2, 0); + if (pd->job != NULL) + job_resize(pd->job, pd->sx - 2, pd->sy - 2); + } server_redraw_client(c); } } @@ -277,6 +306,7 @@ popup_key_cb(struct client *c, struct key_event *event) struct mouse_event *m = &event->m; const char *buf; size_t len; + u_int px, py; if (KEYC_IS_MOUSE(event->key)) { if (pd->dragging != OFF) { @@ -292,10 +322,11 @@ popup_key_cb(struct client *c, struct key_event *event) return (0); } if ((m->b & MOUSE_MASK_META) || - m->x == pd->px || + ((~pd->flags & POPUP_NOBORDER) && + (m->x == pd->px || m->x == pd->px + pd->sx - 1 || m->y == pd->py || - m->y == pd->py + pd->sy - 1) { + m->y == pd->py + pd->sy - 1))) { if (!MOUSE_DRAG(m->b)) goto out; if (MOUSE_BUTTONS(m->lb) == 0) @@ -315,8 +346,14 @@ popup_key_cb(struct client *c, struct key_event *event) if (pd->job != NULL) { if (KEYC_IS_MOUSE(event->key)) { /* Must be inside, checked already. */ - if (!input_key_get_mouse(&pd->s, m, m->x - pd->px - 1, - m->y - pd->py - 1, &buf, &len)) + if (pd->flags & POPUP_NOBORDER) { + px = m->x - pd->px; + py = m->y - pd->py; + } else { + px = m->x - pd->px - 1; + py = m->y - pd->py - 1; + } + if (!input_key_get_mouse(&pd->s, m, px, py, &buf, &len)) return (0); bufferevent_write(job_get_event(pd->job), buf, len); return (0); @@ -378,9 +415,19 @@ popup_display(int flags, struct cmdq_item *item, u_int px, u_int py, u_int sx, struct client *c, struct session *s, popup_close_cb cb, void *arg) { struct popup_data *pd; - - if (sx < 3 || sy < 3) - return (-1); + u_int jx, jy; + + if (flags & POPUP_NOBORDER) { + if (sx < 1 || sy < 1) + return (-1); + jx = sx; + jy = sy; + } else { + if (sx < 3 || sy < 3) + return (-1); + jx = sx - 2; + jy = sy - 2; + } if (c->tty.sx < sx || c->tty.sy < sy) return (-1); @@ -411,7 +458,7 @@ popup_display(int flags, struct cmdq_item *item, u_int px, u_int py, u_int sx, pd->job = job_run(shellcmd, argc, argv, s, cwd, popup_job_update_cb, popup_job_complete_cb, NULL, pd, - JOB_NOWAIT|JOB_PTY|JOB_KEEPWRITE, pd->sx - 2, pd->sy - 2); + JOB_NOWAIT|JOB_PTY|JOB_KEEPWRITE, jx, jy); pd->ictx = input_init(NULL, job_get_event(pd->job), &pd->palette); server_client_set_overlay(c, 0, popup_check_cb, popup_mode_cb, -- cgit From 7789639b5d1818ebbac7bfab74959e4968d7cdf2 Mon Sep 17 00:00:00 2001 From: nicm Date: Fri, 13 Aug 2021 18:54:54 +0000 Subject: Add a menu when a popup is present (mouse only for now). --- popup.c | 141 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 124 insertions(+), 17 deletions(-) (limited to 'popup.c') diff --git a/popup.c b/popup.c index f9a8e067..0edd5c08 100644 --- a/popup.c +++ b/popup.c @@ -40,6 +40,10 @@ struct popup_data { popup_close_cb cb; void *arg; + struct menu *menu; + struct menu_data *md; + int close; + /* Current position and size. */ u_int px; u_int py; @@ -67,6 +71,16 @@ struct popup_editor { void *arg; }; +static const struct menu_item popup_menu_items[] = { + { "Close", 'q', NULL }, + { "#{?buffer_name,Paste #[underscore]#{buffer_name},}", 'p', NULL }, + { "", KEYC_NONE, NULL }, + { "Fill Space", 'F', NULL }, + { "Centre", 'C', NULL }, + + { NULL, KEYC_NONE, NULL } +}; + static void popup_redraw_cb(const struct tty_ctx *ttyctx) { @@ -114,9 +128,12 @@ popup_init_ctx_cb(struct screen_write_ctx *ctx, struct tty_ctx *ttyctx) } static struct screen * -popup_mode_cb(struct client *c, u_int *cx, u_int *cy) +popup_mode_cb(__unused struct client *c, void *data, u_int *cx, u_int *cy) { - struct popup_data *pd = c->overlay_data; + struct popup_data *pd = data; + + if (pd->md != NULL) + return (menu_mode_cb(c, pd->md, cx, cy)); if (pd->flags & POPUP_NOBORDER) { *cx = pd->px + pd->s.cx; @@ -129,21 +146,23 @@ popup_mode_cb(struct client *c, u_int *cx, u_int *cy) } static int -popup_check_cb(struct client *c, u_int px, u_int py) +popup_check_cb(struct client *c, void *data, u_int px, u_int py) { - struct popup_data *pd = c->overlay_data; + struct popup_data *pd = data; if (px < pd->px || px > pd->px + pd->sx - 1) return (1); if (py < pd->py || py > pd->py + pd->sy - 1) return (1); + if (pd->md != NULL) + return (menu_check_cb(c, pd->md, px, py)); return (0); } static void -popup_draw_cb(struct client *c, __unused struct screen_redraw_ctx *ctx0) +popup_draw_cb(struct client *c, void *data, struct screen_redraw_ctx *rctx) { - struct popup_data *pd = c->overlay_data; + struct popup_data *pd = data; struct tty *tty = &c->tty; struct screen s; struct screen_write_ctx ctx; @@ -170,18 +189,33 @@ popup_draw_cb(struct client *c, __unused struct screen_redraw_ctx *ctx0) gc.fg = pd->palette.fg; gc.bg = pd->palette.bg; - c->overlay_check = NULL; + if (pd->md != NULL) { + c->overlay_check = menu_check_cb; + c->overlay_data = pd->md; + } else { + c->overlay_check = NULL; + c->overlay_data = NULL; + } for (i = 0; i < pd->sy; i++) tty_draw_line(tty, &s, 0, i, pd->sx, px, py + i, &gc, palette); + if (pd->md != NULL) { + c->overlay_check = NULL; + c->overlay_data = NULL; + menu_draw_cb(c, pd->md, rctx); + } c->overlay_check = popup_check_cb; + c->overlay_data = pd; } static void -popup_free_cb(struct client *c) +popup_free_cb(struct client *c, void *data) { - struct popup_data *pd = c->overlay_data; + struct popup_data *pd = data; struct cmdq_item *item = pd->item; + if (pd->md != NULL) + menu_free_cb(c, pd->md); + if (pd->cb != NULL) pd->cb(pd->status, pd->arg); @@ -199,17 +233,20 @@ popup_free_cb(struct client *c) screen_free(&pd->s); colour_palette_free(&pd->palette); + free(pd); } static void -popup_resize_cb(struct client *c) +popup_resize_cb(__unused struct client *c, void *data) { - struct popup_data *pd = c->overlay_data; + struct popup_data *pd = data; struct tty *tty = &c->tty; if (pd == NULL) return; + if (pd->md != NULL) + menu_free_cb(c, pd->md); /* Adjust position and size. */ if (pd->psy > tty->sy) @@ -241,6 +278,46 @@ popup_resize_cb(struct client *c) } } +static void +popup_menu_done(__unused struct menu *menu, __unused u_int choice, + key_code key, void *data) +{ + struct popup_data *pd = data; + struct client *c = pd->c; + struct paste_buffer *pb; + const char *buf; + size_t len; + + pd->md = NULL; + pd->menu = NULL; + server_redraw_client(pd->c); + + switch (key) { + case 'p': + pb = paste_get_top(NULL); + if (pb != NULL) { + buf = paste_buffer_data(pb, &len); + bufferevent_write(job_get_event(pd->job), buf, len); + } + break; + case 'F': + pd->sx = c->tty.sx; + pd->sy = c->tty.sy; + pd->px = 0; + pd->py = 0; + server_redraw_client(c); + break; + case 'C': + pd->px = c->tty.sx / 2 - pd->sx / 2; + pd->py = c->tty.sy / 2 - pd->sy / 2; + server_redraw_client(c); + break; + case 'q': + pd->close = 1; + break; + } +} + static void popup_handle_drag(struct client *c, struct popup_data *pd, struct mouse_event *m) @@ -300,13 +377,25 @@ popup_handle_drag(struct client *c, struct popup_data *pd, } static int -popup_key_cb(struct client *c, struct key_event *event) +popup_key_cb(struct client *c, void *data, struct key_event *event) { - struct popup_data *pd = c->overlay_data; + struct popup_data *pd = data; struct mouse_event *m = &event->m; const char *buf; size_t len; - u_int px, py; + u_int px, py, x; + + if (pd->md != NULL) { + if (menu_key_cb(c, pd->md, event) == 1) { + pd->md = NULL; + pd->menu = NULL; + if (pd->close) + server_client_clear_overlay(c); + else + server_redraw_client(c); + } + return (0); + } if (KEYC_IS_MOUSE(event->key)) { if (pd->dragging != OFF) { @@ -317,10 +406,18 @@ popup_key_cb(struct client *c, struct key_event *event) m->x > pd->px + pd->sx - 1 || m->y < pd->py || m->y > pd->py + pd->sy - 1) { - if (MOUSE_BUTTONS (m->b) == 1) - return (1); + if (MOUSE_BUTTONS(m->b) == 2) + goto menu; return (0); } + if ((~pd->flags & POPUP_NOBORDER) && + (~m->b & MOUSE_MASK_META) && + MOUSE_BUTTONS(m->b) == 2 && + (m->x == pd->px || + m->x == pd->px + pd->sx - 1 || + m->y == pd->py || + m->y == pd->py + pd->sy - 1)) + goto menu; if ((m->b & MOUSE_MASK_META) || ((~pd->flags & POPUP_NOBORDER) && (m->x == pd->px || @@ -338,7 +435,6 @@ popup_key_cb(struct client *c, struct key_event *event) goto out; } } - if ((((pd->flags & (POPUP_CLOSEEXIT|POPUP_CLOSEEXITZERO)) == 0) || pd->job == NULL) && (event->key == '\033' || event->key == '\003')) @@ -362,6 +458,17 @@ popup_key_cb(struct client *c, struct key_event *event) } return (0); +menu: + pd->menu = menu_create(""); + menu_add_items(pd->menu, popup_menu_items, NULL, NULL, NULL); + if (m->x >= (pd->menu->width + 4) / 2) + x = m->x - (pd->menu->width + 4) / 2; + else + x = 0; + pd->md = menu_prepare(pd->menu, 0, NULL, x, m->y, c, NULL, + popup_menu_done, pd); + c->flags |= CLIENT_REDRAWOVERLAY; + out: pd->lx = m->x; pd->ly = m->y; -- cgit From 92615b534a887980ac7b52ca8322b6947cd1a47d Mon Sep 17 00:00:00 2001 From: nicm Date: Fri, 13 Aug 2021 19:25:24 +0000 Subject: Adjust overlay check callback before drawing data from pty. --- popup.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) (limited to 'popup.c') diff --git a/popup.c b/popup.c index 0edd5c08..87aaa69f 100644 --- a/popup.c +++ b/popup.c @@ -489,9 +489,16 @@ popup_job_update_cb(struct job *job) if (size == 0) return; - c->overlay_check = NULL; + if (pd->md != NULL) { + c->overlay_check = menu_check_cb; + c->overlay_data = pd->md; + } else { + c->overlay_check = NULL; + c->overlay_data = NULL; + } input_parse_screen(pd->ictx, s, popup_init_ctx_cb, pd, data, size); c->overlay_check = popup_check_cb; + c->overlay_data = pd; evbuffer_drain(evb, size); } -- cgit From 2588c3e52e24a8726ac3d1277ede6ddf07dd6257 Mon Sep 17 00:00:00 2001 From: nicm Date: Fri, 13 Aug 2021 19:27:25 +0000 Subject: Add menu options to convert a popup into a pane. --- popup.c | 59 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 56 insertions(+), 3 deletions(-) (limited to 'popup.c') diff --git a/popup.c b/popup.c index 87aaa69f..f6867f91 100644 --- a/popup.c +++ b/popup.c @@ -77,6 +77,18 @@ static const struct menu_item popup_menu_items[] = { { "", KEYC_NONE, NULL }, { "Fill Space", 'F', NULL }, { "Centre", 'C', NULL }, + { "", KEYC_NONE, NULL }, + { "Make Pane (H)", 'h', NULL }, + { "Make Pane (V)", 'v', NULL }, + + { NULL, KEYC_NONE, NULL } +}; + +static const struct menu_item popup_internal_menu_items[] = { + { "Close", 'q', NULL }, + { "", KEYC_NONE, NULL }, + { "Fill Space", 'F', NULL }, + { "Centre", 'C', NULL }, { NULL, KEYC_NONE, NULL } }; @@ -278,6 +290,37 @@ popup_resize_cb(__unused struct client *c, void *data) } } +static void +popup_make_pane(struct popup_data *pd, enum layout_type type) +{ + struct client *c = pd->c; + struct session *s = c->session; + struct window *w = s->curw->window; + struct layout_cell *lc; + struct window_pane *wp = w->active, *new_wp; + u_int hlimit; + + window_unzoom(w); + + lc = layout_split_pane(wp, type, -1, 0); + hlimit = options_get_number(s->options, "history-limit"); + new_wp = window_add_pane(wp->window, NULL, hlimit, 0); + layout_assign_pane(lc, new_wp, 0); + + new_wp->fd = job_transfer(pd->job); + pd->job = NULL; + + screen_free(&new_wp->base); + memcpy(&new_wp->base, &pd->s, sizeof wp->base); + screen_resize(&new_wp->base, new_wp->sx, new_wp->sy, 1); + screen_init(&pd->s, 1, 1, 0); + + window_pane_set_event(new_wp); + window_set_active_pane(w, new_wp, 1); + + pd->close = 1; +} + static void popup_menu_done(__unused struct menu *menu, __unused u_int choice, key_code key, void *data) @@ -312,6 +355,12 @@ popup_menu_done(__unused struct menu *menu, __unused u_int choice, pd->py = c->tty.sy / 2 - pd->sy / 2; server_redraw_client(c); break; + case 'h': + popup_make_pane(pd, LAYOUT_LEFTRIGHT); + break; + case 'v': + popup_make_pane(pd, LAYOUT_TOPBOTTOM); + break; case 'q': pd->close = 1; break; @@ -460,7 +509,11 @@ popup_key_cb(struct client *c, void *data, struct key_event *event) menu: pd->menu = menu_create(""); - menu_add_items(pd->menu, popup_menu_items, NULL, NULL, NULL); + if (pd->flags & POPUP_INTERNAL) { + menu_add_items(pd->menu, popup_internal_menu_items, NULL, NULL, + NULL); + } else + menu_add_items(pd->menu, popup_menu_items, NULL, NULL, NULL); if (m->x >= (pd->menu->width + 4) / 2) x = m->x - (pd->menu->width + 4) / 2; else @@ -659,8 +712,8 @@ popup_editor(struct client *c, const char *buf, size_t len, py = (c->tty.sy / 2) - (sy / 2); xasprintf(&cmd, "%s %s", editor, path); - if (popup_display(POPUP_CLOSEEXIT, NULL, px, py, sx, sy, cmd, 0, NULL, - _PATH_TMP, c, NULL, popup_editor_close_cb, pe) != 0) { + if (popup_display(POPUP_INTERNAL|POPUP_CLOSEEXIT, NULL, px, py, sx, sy, + cmd, 0, NULL, _PATH_TMP, c, NULL, popup_editor_close_cb, pe) != 0) { popup_editor_free(pe); free(cmd); return (-1); -- cgit From 7a0cec5ecf0d0a89caaee4a16b629155efe23f22 Mon Sep 17 00:00:00 2001 From: nicm Date: Fri, 13 Aug 2021 19:55:11 +0000 Subject: Fill in some other bits on new panes. --- popup.c | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) (limited to 'popup.c') diff --git a/popup.c b/popup.c index f6867f91..1783411a 100644 --- a/popup.c +++ b/popup.c @@ -78,8 +78,8 @@ static const struct menu_item popup_menu_items[] = { { "Fill Space", 'F', NULL }, { "Centre", 'C', NULL }, { "", KEYC_NONE, NULL }, - { "Make Pane (H)", 'h', NULL }, - { "Make Pane (V)", 'v', NULL }, + { "To Horizontal Pane", 'h', NULL }, + { "To Vertical Pane", 'v', NULL }, { NULL, KEYC_NONE, NULL } }; @@ -299,6 +299,7 @@ popup_make_pane(struct popup_data *pd, enum layout_type type) struct layout_cell *lc; struct window_pane *wp = w->active, *new_wp; u_int hlimit; + const char *shell; window_unzoom(w); @@ -307,16 +308,24 @@ popup_make_pane(struct popup_data *pd, enum layout_type type) new_wp = window_add_pane(wp->window, NULL, hlimit, 0); layout_assign_pane(lc, new_wp, 0); - new_wp->fd = job_transfer(pd->job); + new_wp->fd = job_transfer(pd->job, &new_wp->pid, new_wp->tty, + sizeof new_wp->tty); pd->job = NULL; + screen_set_title(&pd->s, new_wp->base.title); screen_free(&new_wp->base); memcpy(&new_wp->base, &pd->s, sizeof wp->base); screen_resize(&new_wp->base, new_wp->sx, new_wp->sy, 1); screen_init(&pd->s, 1, 1, 0); + shell = options_get_string(s->options, "default-shell"); + if (!checkshell(shell)) + shell = _PATH_BSHELL; + new_wp->shell = xstrdup(shell); + window_pane_set_event(new_wp); window_set_active_pane(w, new_wp, 1); + new_wp->flags |= PANE_CHANGED; pd->close = 1; } -- cgit From 63aa96864280ff07f706ebbae302b7c15abb964f Mon Sep 17 00:00:00 2001 From: nicm Date: Fri, 13 Aug 2021 20:04:45 +0000 Subject: Check callback needs to only return 0 (text should be suppressed) if menu returns 0, otherwise it should check the popup also. --- popup.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'popup.c') diff --git a/popup.c b/popup.c index 1783411a..95de58a9 100644 --- a/popup.c +++ b/popup.c @@ -162,12 +162,12 @@ popup_check_cb(struct client *c, void *data, u_int px, u_int py) { struct popup_data *pd = data; + if (pd->md != NULL && menu_check_cb(c, pd->md, px, py) == 0) + return (0); if (px < pd->px || px > pd->px + pd->sx - 1) return (1); if (py < pd->py || py > pd->py + pd->sy - 1) return (1); - if (pd->md != NULL) - return (menu_check_cb(c, pd->md, px, py)); return (0); } -- cgit