diff --git a/cmd-display-menu.c b/cmd-display-menu.c index 5e742ce1..12b30123 100644 --- a/cmd-display-menu.c +++ b/cmd-display-menu.c @@ -54,7 +54,7 @@ const struct cmd_entry cmd_display_popup_entry = { .name = "display-popup", .alias = "popup", - .args = { "Bb:Cc:d:e:Eh:s:S:t:T:w:x:y:", 0, -1, NULL }, + .args = { "Bb:Cc:Dd:e:Eh:s:S:t:T:w:x:y:", 0, -1, NULL }, .usage = "[-BCE] [-b border-lines] [-c target-client] " "[-d start-directory] [-e environment] [-h height] " "[-s style] [-S border-style] " CMD_TARGET_PANE_USAGE @@ -498,5 +498,8 @@ cmd_display_popup_exec(struct cmd *self, struct cmdq_item *item) free(cwd); free(title); cmd_free_argv(argc, argv); - return (CMD_RETURN_WAIT); + if (args_has(args, 'D')) + return (CMD_RETURN_NORMAL); + else + return (CMD_RETURN_WAIT); } diff --git a/popup.c b/popup.c index 4cd147e1..ca1f9a3f 100644 --- a/popup.c +++ b/popup.c @@ -513,8 +513,10 @@ popup_key_cb(struct client *c, void *data, struct key_event *event) m->y > pd->py + pd->sy - 1) { if (MOUSE_BUTTONS(m->b) == MOUSE_BUTTON_3) goto menu; + c->flags &= ~CLIENT_OVERLAYFOCUSED; return (0); } + c->flags |= CLIENT_OVERLAYFOCUSED; if (pd->border_lines != BOX_LINES_NONE) { if (m->x == pd->px) border = LEFT; @@ -561,7 +563,8 @@ popup_key_cb(struct client *c, void *data, struct key_event *event) bufferevent_write(job_get_event(pd->job), buf, len); return (0); } - input_key(&pd->s, job_get_event(pd->job), event->key); + if (c->flags & CLIENT_OVERLAYFOCUSED) + input_key(&pd->s, job_get_event(pd->job), event->key); } return (0); @@ -725,6 +728,7 @@ popup_display(int flags, enum box_lines lines, struct cmdq_item *item, u_int px, server_client_set_overlay(c, 0, popup_check_cb, popup_mode_cb, popup_draw_cb, popup_key_cb, popup_free_cb, popup_resize_cb, pd); + c->flags |= CLIENT_OVERLAYFOCUSED; return (0); } diff --git a/screen-redraw.c b/screen-redraw.c index 0d2acad6..9cf01fc4 100644 --- a/screen-redraw.c +++ b/screen-redraw.c @@ -1005,6 +1005,7 @@ screen_redraw_draw_scrollbar(struct screen_redraw_ctx *ctx, struct tty *tty = &c->tty; struct grid_cell gc, slgc, *gcp; struct style *sb_style = &wp->scrollbar_style; + struct overlay_ranges r; u_int i, j, imax, jmax; u_int sb_w = sb_style->width, sb_pad = sb_style->pad; int px, py, ox = ctx->ox, oy = ctx->oy; @@ -1033,6 +1034,11 @@ screen_redraw_draw_scrollbar(struct screen_redraw_ctx *ctx, py < yoff - oy - 1 || py >= sy || py < 0) continue; + if (c->overlay_check != NULL) { + c->overlay_check(c, c->overlay_data, px, py, 1, &r); + if (r.nx[0] + r.nx[1] == 0) + continue; + } tty_cursor(tty, px, py); if ((sb_pos == PANE_SCROLLBARS_LEFT && i >= sb_w && i < sb_w + sb_pad) || diff --git a/server-client.c b/server-client.c index ae2e54f9..09e65a18 100644 --- a/server-client.c +++ b/server-client.c @@ -2609,6 +2609,8 @@ server_client_handle_key(struct client *c, struct key_event *event) { struct session *s = c->session; struct cmdq_item *item; + struct window_pane *wp; + int done; /* Check the client is good to accept input. */ if (s == NULL || (c->flags & CLIENT_UNATTACHEDFLAGS)) @@ -2626,16 +2628,18 @@ server_client_handle_key(struct client *c, struct key_event *event) status_message_clear(c); } if (c->overlay_key != NULL) { - switch (c->overlay_key(c, c->overlay_data, event)) { - case 0: - return (0); - case 1: + done = c->overlay_key(c, c->overlay_data, event); + if (done) server_client_clear_overlay(c); - return (0); + else { + TAILQ_FOREACH(wp, &c->session->curw->window->panes, entry) { + if (~c->flags & CLIENT_OVERLAYFOCUSED) + goto focused; + } } + return (0); } - server_client_clear_overlay(c); - if (c->prompt_string != NULL) { +focused: if (c->prompt_string != NULL) { if (status_prompt_key(c, event->key) == 0) return (0); } @@ -2885,6 +2889,23 @@ out: bufferevent_enable(wp->event, EV_READ); } + +static int +server_client_check_overlay(struct client *c, u_int px, u_int py) +{ + struct overlay_ranges r; + + /* + * A unit width range will always return nx[2] == 0 from a check, even + * with multiple overlays, so it's sufficient to check just the first + * two entries. + */ + c->overlay_check(c, c->overlay_data, px, py, 1, &r); + if (r.nx[0] + r.nx[1] == 0) + return (0); + return (1); +} + /* * Update cursor position and mode settings. The scroll region and attributes * are cleared when idle (waiting for an event) as this is the most likely time @@ -2894,6 +2915,7 @@ out: * tty_region/tty_reset/tty_update_mode already take care of not resetting * things that are already in their default state. */ + static void server_client_reset_state(struct client *c) { @@ -2913,7 +2935,7 @@ server_client_reset_state(struct client *c) tty->flags &= ~TTY_BLOCK; /* Get mode from overlay if any, else from screen. */ - if (c->overlay_draw != NULL) { + if (c->overlay_draw != NULL && c->flags & CLIENT_OVERLAYFOCUSED) { if (c->overlay_mode != NULL) s = c->overlay_mode(c, c->overlay_data, &cx, &cy); } else if (c->prompt_string == NULL) @@ -2944,18 +2966,22 @@ server_client_reset_state(struct client *c) cy = tty->sy - n; } cx = c->prompt_cursor; - } else if (c->overlay_draw == NULL) { + } else if (c->overlay_draw == NULL || ~c->flags & CLIENT_OVERLAYFOCUSED) { cursor = 0; tty_window_offset(tty, &ox, &oy, &sx, &sy); if (wp->xoff + s->cx >= ox && wp->xoff + s->cx <= ox + sx && wp->yoff + s->cy >= oy && wp->yoff + s->cy <= oy + sy) { - cursor = 1; - cx = wp->xoff + s->cx - ox; cy = wp->yoff + s->cy - oy; if (status_at_line(c) == 0) cy += status_line_size(c); + + if (c->overlay_draw != NULL && + !server_client_check_overlay(c, cx, cy)) + cursor = 0; + else + cursor = 1; } if (!cursor) mode &= ~MODE_CURSOR; diff --git a/tmux.h b/tmux.h index 0753cb27..2bae04eb 100644 --- a/tmux.h +++ b/tmux.h @@ -1982,6 +1982,7 @@ struct client { #define CLIENT_ASSUMEPASTING 0x2000000000ULL #define CLIENT_REDRAWSCROLLBARS 0x4000000000ULL #define CLIENT_NO_DETACH_ON_DESTROY 0x8000000000ULL +#define CLIENT_OVERLAYFOCUSED 0x10000000000ULL #define CLIENT_ALLREDRAWFLAGS \ (CLIENT_REDRAWWINDOW| \ CLIENT_REDRAWSTATUS| \