Merge branch 'obsd-master'

pull/1731/head
Thomas Adam 2019-05-07 23:02:30 +01:00
commit b24d7d9c95
4 changed files with 289 additions and 270 deletions

View File

@ -20,6 +20,7 @@
#include <ctype.h> #include <ctype.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h>
#include "tmux.h" #include "tmux.h"
@ -30,9 +31,6 @@
static enum cmd_retval cmd_display_panes_exec(struct cmd *, static enum cmd_retval cmd_display_panes_exec(struct cmd *,
struct cmdq_item *); struct cmdq_item *);
static void cmd_display_panes_callback(struct client *,
struct window_pane *);
const struct cmd_entry cmd_display_panes_entry = { const struct cmd_entry cmd_display_panes_entry = {
.name = "display-panes", .name = "display-panes",
.alias = "displayp", .alias = "displayp",
@ -44,46 +42,145 @@ const struct cmd_entry cmd_display_panes_entry = {
.exec = cmd_display_panes_exec .exec = cmd_display_panes_exec
}; };
static enum cmd_retval struct cmd_display_panes_data {
cmd_display_panes_exec(struct cmd *self, struct cmdq_item *item) struct cmdq_item *item;
char *command;
};
static void
cmd_display_panes_draw_pane(struct screen_redraw_ctx *ctx,
struct window_pane *wp)
{ {
struct args *args = self->args; struct client *c = ctx->c;
struct client *c; struct tty *tty = &c->tty;
struct session *s; struct session *s = c->session;
u_int delay; struct options *oo = s->options;
char *cause; struct window *w = wp->window;
struct grid_cell gc;
u_int idx, px, py, i, j, xoff, yoff, sx, sy;
int colour, active_colour;
char buf[16], *ptr;
size_t len;
if ((c = cmd_find_client(item, args_get(args, 't'), 0)) == NULL) if (wp->xoff + wp->sx <= ctx->ox ||
return (CMD_RETURN_ERROR); wp->xoff >= ctx->ox + ctx->sx ||
s = c->session; wp->yoff + wp->sy <= ctx->oy ||
wp->yoff >= ctx->oy + ctx->sy)
return;
if (c->identify_callback != NULL) if (wp->xoff >= ctx->ox && wp->xoff + wp->sx <= ctx->ox + ctx->sx) {
return (CMD_RETURN_NORMAL); /* All visible. */
xoff = wp->xoff - ctx->ox;
sx = wp->sx;
} else if (wp->xoff < ctx->ox &&
wp->xoff + wp->sx > ctx->ox + ctx->sx) {
/* Both left and right not visible. */
xoff = 0;
sx = ctx->sx;
} else if (wp->xoff < ctx->ox) {
/* Left not visible. */
xoff = 0;
sx = wp->sx - (ctx->ox - wp->xoff);
} else {
/* Right not visible. */
xoff = wp->xoff - ctx->ox;
sx = wp->sx - xoff;
}
if (wp->yoff >= ctx->oy && wp->yoff + wp->sy <= ctx->oy + ctx->sy) {
/* All visible. */
yoff = wp->yoff - ctx->oy;
sy = wp->sy;
} else if (wp->yoff < ctx->oy &&
wp->yoff + wp->sy > ctx->oy + ctx->sy) {
/* Both top and bottom not visible. */
yoff = 0;
sy = ctx->sy;
} else if (wp->yoff < ctx->oy) {
/* Top not visible. */
yoff = 0;
sy = wp->sy - (ctx->oy - wp->yoff);
} else {
/* Bottom not visible. */
yoff = wp->yoff - ctx->oy;
sy = wp->sy - yoff;
}
c->identify_callback = cmd_display_panes_callback; if (ctx->statustop)
if (args->argc != 0) yoff += ctx->statuslines;
c->identify_callback_data = xstrdup(args->argv[0]); px = sx / 2;
py = sy / 2;
if (window_pane_index(wp, &idx) != 0)
fatalx("index not found");
len = xsnprintf(buf, sizeof buf, "%u", idx);
if (sx < len)
return;
colour = options_get_number(oo, "display-panes-colour");
active_colour = options_get_number(oo, "display-panes-active-colour");
if (sx < len * 6 || sy < 5) {
tty_cursor(tty, xoff + px - len / 2, yoff + py);
goto draw_text;
}
px -= len * 3;
py -= 2;
memcpy(&gc, &grid_default_cell, sizeof gc);
if (w->active == wp)
gc.bg = active_colour;
else else
c->identify_callback_data = xstrdup("select-pane -t '%%'"); gc.bg = colour;
if (args_has(args, 'b')) gc.flags |= GRID_FLAG_NOPALETTE;
c->identify_callback_item = NULL;
else
c->identify_callback_item = item;
if (args_has(args, 'd')) { tty_attributes(tty, &gc, wp);
delay = args_strtonum(args, 'd', 0, UINT_MAX, &cause); for (ptr = buf; *ptr != '\0'; ptr++) {
if (cause != NULL) { if (*ptr < '0' || *ptr > '9')
cmdq_error(item, "delay %s", cause); continue;
free(cause); idx = *ptr - '0';
return (CMD_RETURN_ERROR);
for (j = 0; j < 5; j++) {
for (i = px; i < px + 5; i++) {
tty_cursor(tty, xoff + i, yoff + py + j);
if (window_clock_table[idx][j][i - px])
tty_putc(tty, ' ');
}
} }
} else px += 6;
delay = options_get_number(s->options, "display-panes-time"); }
server_client_set_identify(c, delay);
if (args_has(args, 'b')) len = xsnprintf(buf, sizeof buf, "%ux%u", wp->sx, wp->sy);
return (CMD_RETURN_NORMAL); if (sx < len || sy < 6)
return (CMD_RETURN_WAIT); return;
tty_cursor(tty, xoff + sx - len, yoff);
draw_text:
memcpy(&gc, &grid_default_cell, sizeof gc);
if (w->active == wp)
gc.fg = active_colour;
else
gc.fg = colour;
gc.flags |= GRID_FLAG_NOPALETTE;
tty_attributes(tty, &gc, wp);
tty_puts(tty, buf);
tty_cursor(tty, 0, 0);
}
static void
cmd_display_panes_draw(struct client *c, struct screen_redraw_ctx *ctx)
{
struct window *w = c->session->curw->window;
struct window_pane *wp;
log_debug("%s: %s @%u", __func__, c->name, w->id);
TAILQ_FOREACH(wp, &w->panes, entry) {
if (window_pane_visible(wp))
cmd_display_panes_draw_pane(ctx, wp);
}
} }
static enum cmd_retval static enum cmd_retval
@ -98,17 +195,36 @@ cmd_display_panes_error(struct cmdq_item *item, void *data)
} }
static void static void
cmd_display_panes_callback(struct client *c, struct window_pane *wp) cmd_display_panes_free(struct client *c)
{ {
struct cmd_list *cmdlist; struct cmd_display_panes_data *cdata = c->overlay_data;
struct cmdq_item *new_item;
char *cmd, *expanded, *cause;
if (cdata->item != NULL)
cdata->item->flags &= ~CMDQ_WAITING;
free(cdata->command);
free(cdata);
}
static int
cmd_display_panes_key(struct client *c, struct key_event *event)
{
struct cmd_display_panes_data *cdata = c->overlay_data;
struct cmd_list *cmdlist;
struct cmdq_item *new_item;
char *cmd, *expanded, *cause;
struct window *w = c->session->curw->window;
struct window_pane *wp;
if (event->key < '0' || event->key > '9')
return (1);
wp = window_pane_at_index(w, event->key - '0');
if (wp == NULL) if (wp == NULL)
goto out; return (1);
window_unzoom(w);
xasprintf(&expanded, "%%%u", wp->id); xasprintf(&expanded, "%%%u", wp->id);
cmd = cmd_template_replace(c->identify_callback_data, expanded, 1); cmd = cmd_template_replace(cdata->command, expanded, 1);
cmdlist = cmd_string_parse(cmd, NULL, 0, &cause); cmdlist = cmd_string_parse(cmd, NULL, 0, &cause);
if (cmdlist == NULL && cause != NULL) if (cmdlist == NULL && cause != NULL)
@ -119,25 +235,59 @@ cmd_display_panes_callback(struct client *c, struct window_pane *wp)
new_item = cmdq_get_command(cmdlist, NULL, NULL, 0); new_item = cmdq_get_command(cmdlist, NULL, NULL, 0);
cmd_list_free(cmdlist); cmd_list_free(cmdlist);
} }
if (new_item != NULL) { if (new_item != NULL) {
if (c->identify_callback_item != NULL) if (cdata->item != NULL)
cmdq_insert_after(c->identify_callback_item, new_item); cmdq_insert_after(cdata->item, new_item);
else else
cmdq_append(c, new_item); cmdq_append(c, new_item);
} }
free(cmd); free(cmd);
free(expanded); free(expanded);
return (1);
out: }
if (c->identify_callback_item != NULL) {
c->identify_callback_item->flags &= ~CMDQ_WAITING; static enum cmd_retval
c->identify_callback_item = NULL; cmd_display_panes_exec(struct cmd *self, struct cmdq_item *item)
} {
struct args *args = self->args;
free(c->identify_callback_data); struct client *c;
c->identify_callback_data = NULL; struct session *s;
u_int delay;
c->identify_callback = NULL; char *cause;
struct cmd_display_panes_data *cdata;
if ((c = cmd_find_client(item, args_get(args, 't'), 0)) == NULL)
return (CMD_RETURN_ERROR);
s = c->session;
if (c->overlay_draw != NULL)
return (CMD_RETURN_NORMAL);
if (args_has(args, 'd')) {
delay = args_strtonum(args, 'd', 0, UINT_MAX, &cause);
if (cause != NULL) {
cmdq_error(item, "delay %s", cause);
free(cause);
return (CMD_RETURN_ERROR);
}
} else
delay = options_get_number(s->options, "display-panes-time");
cdata = xmalloc(sizeof *cdata);
if (args->argc != 0)
cdata->command = xstrdup(args->argv[0]);
else
cdata->command = xstrdup("select-pane -t '%%'");
if (args_has(args, 'b'))
cdata->item = NULL;
else
cdata->item = item;
server_client_set_overlay(c, delay, cmd_display_panes_draw,
cmd_display_panes_key, cmd_display_panes_free, cdata);
if (args_has(args, 'b'))
return (CMD_RETURN_NORMAL);
return (CMD_RETURN_WAIT);
} }

View File

@ -23,27 +23,11 @@
#include "tmux.h" #include "tmux.h"
struct screen_redraw_ctx {
struct client *c;
u_int lines;
int top;
int pane_status;
u_int sx;
u_int sy;
u_int ox;
u_int oy;
};
static void screen_redraw_draw_borders(struct screen_redraw_ctx *); static void screen_redraw_draw_borders(struct screen_redraw_ctx *);
static void screen_redraw_draw_panes(struct screen_redraw_ctx *); static void screen_redraw_draw_panes(struct screen_redraw_ctx *);
static void screen_redraw_draw_status(struct screen_redraw_ctx *); static void screen_redraw_draw_status(struct screen_redraw_ctx *);
static void screen_redraw_draw_pane(struct screen_redraw_ctx *, static void screen_redraw_draw_pane(struct screen_redraw_ctx *,
struct window_pane *); struct window_pane *);
static void screen_redraw_draw_number(struct screen_redraw_ctx *,
struct window_pane *);
#define CELL_INSIDE 0 #define CELL_INSIDE 0
#define CELL_LEFTRIGHT 1 #define CELL_LEFTRIGHT 1
@ -374,8 +358,8 @@ screen_redraw_draw_pane_status(struct screen_redraw_ctx *ctx)
width = size - x; width = size - x;
} }
if (ctx->top) if (ctx->statustop)
yoff += ctx->lines; yoff += ctx->statuslines;
tty_draw_line(tty, NULL, s, i, 0, width, x, yoff - ctx->oy); tty_draw_line(tty, NULL, s, i, 0, width, x, yoff - ctx->oy);
} }
tty_cursor(tty, 0, 0); tty_cursor(tty, 0, 0);
@ -419,21 +403,25 @@ screen_redraw_set_context(struct client *c, struct screen_redraw_ctx *ctx)
struct options *oo = s->options; struct options *oo = s->options;
struct window *w = s->curw->window; struct window *w = s->curw->window;
struct options *wo = w->options; struct options *wo = w->options;
u_int lines;
memset(ctx, 0, sizeof *ctx); memset(ctx, 0, sizeof *ctx);
ctx->c = c; ctx->c = c;
ctx->lines = status_line_size(c); lines = status_line_size(c);
if (c->message_string != NULL || c->prompt_string != NULL) if (c->message_string != NULL || c->prompt_string != NULL)
ctx->lines = (ctx->lines == 0) ? 1 : ctx->lines; lines = (lines == 0) ? 1 : lines;
if (ctx->lines != 0 && options_get_number(oo, "status-position") == 0) if (lines != 0 && options_get_number(oo, "status-position") == 0)
ctx->top = 1; ctx->statustop = 1;
ctx->statuslines = lines;
ctx->pane_status = options_get_number(wo, "pane-border-status"); ctx->pane_status = options_get_number(wo, "pane-border-status");
tty_window_offset(&c->tty, &ctx->ox, &ctx->oy, &ctx->sx, &ctx->sy); tty_window_offset(&c->tty, &ctx->ox, &ctx->oy, &ctx->sx, &ctx->sy);
log_debug("%s: %s @%u ox=%u oy=%u sx=%u sy=%u %u/%d", __func__, c->name, log_debug("%s: %s @%u ox=%u oy=%u sx=%u sy=%u %u/%d", __func__, c->name,
w->id, ctx->ox, ctx->oy, ctx->sx, ctx->sy, ctx->lines, ctx->top); w->id, ctx->ox, ctx->oy, ctx->sx, ctx->sy, ctx->statuslines,
ctx->statustop);
} }
/* Redraw entire screen. */ /* Redraw entire screen. */
@ -456,9 +444,11 @@ screen_redraw_screen(struct client *c)
} }
if (flags & CLIENT_REDRAWWINDOW) if (flags & CLIENT_REDRAWWINDOW)
screen_redraw_draw_panes(&ctx); screen_redraw_draw_panes(&ctx);
if (ctx.lines != 0 && if (ctx.statuslines != 0 &&
(flags & (CLIENT_REDRAWSTATUS|CLIENT_REDRAWSTATUSALWAYS))) (flags & (CLIENT_REDRAWSTATUS|CLIENT_REDRAWSTATUSALWAYS)))
screen_redraw_draw_status(&ctx); screen_redraw_draw_status(&ctx);
if (c->overlay_draw != NULL)
c->overlay_draw(c, &ctx);
tty_reset(&c->tty); tty_reset(&c->tty);
} }
@ -508,8 +498,8 @@ screen_redraw_draw_borders_cell(struct screen_redraw_ctx *ctx, u_int i, u_int j,
tty_attributes(tty, active_gc, NULL); tty_attributes(tty, active_gc, NULL);
else else
tty_attributes(tty, other_gc, NULL); tty_attributes(tty, other_gc, NULL);
if (ctx->top) if (ctx->statustop)
tty_cursor(tty, i, ctx->lines + j); tty_cursor(tty, i, ctx->statuslines + j);
else else
tty_cursor(tty, i, j); tty_cursor(tty, i, j);
tty_putc(tty, CELL_BORDERS[type]); tty_putc(tty, CELL_BORDERS[type]);
@ -538,7 +528,7 @@ screen_redraw_draw_borders(struct screen_redraw_ctx *ctx)
memcpy(&m_active_gc, &active_gc, sizeof m_active_gc); memcpy(&m_active_gc, &active_gc, sizeof m_active_gc);
m_active_gc.attr ^= GRID_ATTR_REVERSE; m_active_gc.attr ^= GRID_ATTR_REVERSE;
for (j = 0; j < tty->sy - ctx->lines; j++) { for (j = 0; j < tty->sy - ctx->statuslines; j++) {
for (i = 0; i < tty->sx; i++) { for (i = 0; i < tty->sx; i++) {
screen_redraw_draw_borders_cell(ctx, i, j, screen_redraw_draw_borders_cell(ctx, i, j,
&m_active_gc, &active_gc, &m_other_gc, &other_gc); &m_active_gc, &active_gc, &m_other_gc, &other_gc);
@ -557,11 +547,8 @@ screen_redraw_draw_panes(struct screen_redraw_ctx *ctx)
log_debug("%s: %s @%u", __func__, c->name, w->id); log_debug("%s: %s @%u", __func__, c->name, w->id);
TAILQ_FOREACH(wp, &w->panes, entry) { TAILQ_FOREACH(wp, &w->panes, entry) {
if (!window_pane_visible(wp)) if (window_pane_visible(wp))
continue; screen_redraw_draw_pane(ctx, wp);
screen_redraw_draw_pane(ctx, wp);
if (c->flags & CLIENT_IDENTIFY)
screen_redraw_draw_number(ctx, wp);
} }
} }
@ -577,11 +564,11 @@ screen_redraw_draw_status(struct screen_redraw_ctx *ctx)
log_debug("%s: %s @%u", __func__, c->name, w->id); log_debug("%s: %s @%u", __func__, c->name, w->id);
if (ctx->top) if (ctx->statustop)
y = 0; y = 0;
else else
y = c->tty.sy - ctx->lines; y = c->tty.sy - ctx->statuslines;
for (i = 0; i < ctx->lines; i++) for (i = 0; i < ctx->statuslines; i++)
tty_draw_line(tty, NULL, s, 0, i, UINT_MAX, 0, y + i); tty_draw_line(tty, NULL, s, 0, i, UINT_MAX, 0, y + i);
} }
@ -599,8 +586,8 @@ screen_redraw_draw_pane(struct screen_redraw_ctx *ctx, struct window_pane *wp)
if (wp->xoff + wp->sx <= ctx->ox || wp->xoff >= ctx->ox + ctx->sx) if (wp->xoff + wp->sx <= ctx->ox || wp->xoff >= ctx->ox + ctx->sx)
return; return;
if (ctx->top) if (ctx->statustop)
top = ctx->lines; top = ctx->statuslines;
else else
top = 0; top = 0;
@ -639,125 +626,3 @@ screen_redraw_draw_pane(struct screen_redraw_ctx *ctx, struct window_pane *wp)
tty_draw_line(tty, wp, s, i, j, width, x, y); tty_draw_line(tty, wp, s, i, j, width, x, y);
} }
} }
/* Draw number on a pane. */
static void
screen_redraw_draw_number(struct screen_redraw_ctx *ctx, struct window_pane *wp)
{
struct client *c = ctx->c;
struct tty *tty = &c->tty;
struct session *s = c->session;
struct options *oo = s->options;
struct window *w = wp->window;
struct grid_cell gc;
u_int idx, px, py, i, j, xoff, yoff, sx, sy;
int colour, active_colour;
char buf[16], *ptr;
size_t len;
if (wp->xoff + wp->sx <= ctx->ox ||
wp->xoff >= ctx->ox + ctx->sx ||
wp->yoff + wp->sy <= ctx->oy ||
wp->yoff >= ctx->oy + ctx->sy)
return;
if (wp->xoff >= ctx->ox && wp->xoff + wp->sx <= ctx->ox + ctx->sx) {
/* All visible. */
xoff = wp->xoff - ctx->ox;
sx = wp->sx;
} else if (wp->xoff < ctx->ox &&
wp->xoff + wp->sx > ctx->ox + ctx->sx) {
/* Both left and right not visible. */
xoff = 0;
sx = ctx->sx;
} else if (wp->xoff < ctx->ox) {
/* Left not visible. */
xoff = 0;
sx = wp->sx - (ctx->ox - wp->xoff);
} else {
/* Right not visible. */
xoff = wp->xoff - ctx->ox;
sx = wp->sx - xoff;
}
if (wp->yoff >= ctx->oy && wp->yoff + wp->sy <= ctx->oy + ctx->sy) {
/* All visible. */
yoff = wp->yoff - ctx->oy;
sy = wp->sy;
} else if (wp->yoff < ctx->oy &&
wp->yoff + wp->sy > ctx->oy + ctx->sy) {
/* Both top and bottom not visible. */
yoff = 0;
sy = ctx->sy;
} else if (wp->yoff < ctx->oy) {
/* Top not visible. */
yoff = 0;
sy = wp->sy - (ctx->oy - wp->yoff);
} else {
/* Bottom not visible. */
yoff = wp->yoff - ctx->oy;
sy = wp->sy - yoff;
}
if (ctx->top)
yoff += ctx->lines;
px = sx / 2;
py = sy / 2;
if (window_pane_index(wp, &idx) != 0)
fatalx("index not found");
len = xsnprintf(buf, sizeof buf, "%u", idx);
if (sx < len)
return;
colour = options_get_number(oo, "display-panes-colour");
active_colour = options_get_number(oo, "display-panes-active-colour");
if (sx < len * 6 || sy < 5) {
tty_cursor(tty, xoff + px - len / 2, yoff + py);
goto draw_text;
}
px -= len * 3;
py -= 2;
memcpy(&gc, &grid_default_cell, sizeof gc);
if (w->active == wp)
gc.bg = active_colour;
else
gc.bg = colour;
gc.flags |= GRID_FLAG_NOPALETTE;
tty_attributes(tty, &gc, wp);
for (ptr = buf; *ptr != '\0'; ptr++) {
if (*ptr < '0' || *ptr > '9')
continue;
idx = *ptr - '0';
for (j = 0; j < 5; j++) {
for (i = px; i < px + 5; i++) {
tty_cursor(tty, xoff + i, yoff + py + j);
if (window_clock_table[idx][j][i - px])
tty_putc(tty, ' ');
}
}
px += 6;
}
len = xsnprintf(buf, sizeof buf, "%ux%u", wp->sx, wp->sy);
if (sx < len || sy < 6)
return;
tty_cursor(tty, xoff + sx - len, yoff);
draw_text:
memcpy(&gc, &grid_default_cell, sizeof gc);
if (w->active == wp)
gc.fg = active_colour;
else
gc.fg = colour;
gc.flags |= GRID_FLAG_NOPALETTE;
tty_attributes(tty, &gc, wp);
tty_puts(tty, buf);
tty_cursor(tty, 0, 0);
}

View File

@ -41,8 +41,7 @@ static void server_client_check_redraw(struct client *);
static void server_client_set_title(struct client *); static void server_client_set_title(struct client *);
static void server_client_reset_state(struct client *); static void server_client_reset_state(struct client *);
static int server_client_assume_paste(struct session *); static int server_client_assume_paste(struct session *);
static void server_client_clear_identify(struct client *, static void server_client_clear_overlay(struct client *);
struct window_pane *);
static void server_client_dispatch(struct imsg *, void *); static void server_client_dispatch(struct imsg *, void *);
static void server_client_dispatch_command(struct client *, struct imsg *); static void server_client_dispatch_command(struct client *, struct imsg *);
@ -64,44 +63,53 @@ server_client_how_many(void)
return (n); return (n);
} }
/* Identify mode callback. */ /* Overlay timer callback. */
static void static void
server_client_callback_identify(__unused int fd, __unused short events, server_client_overlay_timer(__unused int fd, __unused short events, void *data)
void *data)
{ {
server_client_clear_identify(data, NULL); server_client_clear_overlay(data);
} }
/* Set identify mode on client. */ /* Set an overlay on client. */
void void
server_client_set_identify(struct client *c, u_int delay) server_client_set_overlay(struct client *c, u_int delay, overlay_draw_cb drawcb,
overlay_key_cb keycb, overlay_free_cb freecb, void *data)
{ {
struct timeval tv; struct timeval tv;
tv.tv_sec = delay / 1000; tv.tv_sec = delay / 1000;
tv.tv_usec = (delay % 1000) * 1000L; tv.tv_usec = (delay % 1000) * 1000L;
if (event_initialized(&c->identify_timer)) if (event_initialized(&c->overlay_timer))
evtimer_del(&c->identify_timer); evtimer_del(&c->overlay_timer);
evtimer_set(&c->identify_timer, server_client_callback_identify, c); evtimer_set(&c->overlay_timer, server_client_overlay_timer, c);
if (delay != 0) if (delay != 0)
evtimer_add(&c->identify_timer, &tv); evtimer_add(&c->overlay_timer, &tv);
c->overlay_draw = drawcb;
c->overlay_key = keycb;
c->overlay_free = freecb;
c->overlay_data = data;
c->flags |= CLIENT_IDENTIFY;
c->tty.flags |= (TTY_FREEZE|TTY_NOCURSOR); c->tty.flags |= (TTY_FREEZE|TTY_NOCURSOR);
server_redraw_client(c); server_redraw_client(c);
} }
/* Clear identify mode on client. */ /* Clear overlay mode on client. */
static void static void
server_client_clear_identify(struct client *c, struct window_pane *wp) server_client_clear_overlay(struct client *c)
{ {
if (~c->flags & CLIENT_IDENTIFY) if (c->overlay_draw == NULL)
return; return;
c->flags &= ~CLIENT_IDENTIFY;
if (c->identify_callback != NULL) if (event_initialized(&c->overlay_timer))
c->identify_callback(c, wp); evtimer_del(&c->overlay_timer);
if (c->overlay_free != NULL)
c->overlay_free(c);
c->overlay_draw = NULL;
c->overlay_key = NULL;
c->tty.flags &= ~(TTY_FREEZE|TTY_NOCURSOR); c->tty.flags &= ~(TTY_FREEZE|TTY_NOCURSOR);
server_redraw_client(c); server_redraw_client(c);
@ -255,7 +263,7 @@ server_client_lost(struct client *c)
c->flags |= CLIENT_DEAD; c->flags |= CLIENT_DEAD;
server_client_clear_identify(c, NULL); server_client_clear_overlay(c);
status_prompt_clear(c); status_prompt_clear(c);
status_message_clear(c); status_message_clear(c);
@ -289,9 +297,6 @@ server_client_lost(struct client *c)
key_bindings_unref_table(c->keytable); key_bindings_unref_table(c->keytable);
if (event_initialized(&c->identify_timer))
evtimer_del(&c->identify_timer);
free(c->message_string); free(c->message_string);
if (event_initialized(&c->message_timer)) if (event_initialized(&c->message_timer))
evtimer_del(&c->message_timer); evtimer_del(&c->message_timer);
@ -1014,21 +1019,9 @@ server_client_key_callback(struct cmdq_item *item, void *data)
fatal("gettimeofday failed"); fatal("gettimeofday failed");
session_update_activity(s, &c->activity_time); session_update_activity(s, &c->activity_time);
/* Number keys jump to pane in identify mode. */
if (c->flags & CLIENT_IDENTIFY && key >= '0' && key <= '9') {
if (c->flags & CLIENT_READONLY)
goto out;
window_unzoom(w);
wp = window_pane_at_index(w, key - '0');
server_client_clear_identify(c, wp);
goto out;
}
/* Handle status line. */ /* Handle status line. */
if (!(c->flags & CLIENT_READONLY)) { if (~c->flags & CLIENT_READONLY)
status_message_clear(c); status_message_clear(c);
server_client_clear_identify(c, NULL);
}
if (c->prompt_string != NULL) { if (c->prompt_string != NULL) {
if (c->flags & CLIENT_READONLY) if (c->flags & CLIENT_READONLY)
goto out; goto out;
@ -1209,27 +1202,19 @@ int
server_client_handle_key(struct client *c, struct key_event *event) server_client_handle_key(struct client *c, struct key_event *event)
{ {
struct session *s = c->session; struct session *s = c->session;
struct window *w;
struct window_pane *wp = NULL;
struct cmdq_item *item; struct cmdq_item *item;
/* Check the client is good to accept input. */ /* Check the client is good to accept input. */
if (s == NULL || (c->flags & (CLIENT_DEAD|CLIENT_SUSPENDED)) != 0) if (s == NULL || (c->flags & (CLIENT_DEAD|CLIENT_SUSPENDED)) != 0)
return (0); return (0);
w = s->curw->window;
/* /*
* Key presses in identify mode are a special case. The queue might be * Key presses in overlay mode are a special case. The queue might be
* blocked so they need to be processed immediately rather than queued. * blocked so they need to be processed immediately rather than queued.
*/ */
if (c->flags & CLIENT_IDENTIFY) { if ((~c->flags & CLIENT_READONLY) && c->overlay_key != NULL) {
if (c->flags & CLIENT_READONLY) if (c->overlay_key(c, event) != 0)
return (0); server_client_clear_overlay(c);
if (event->key >= '0' && event->key <= '9') {
window_unzoom(w);
wp = window_pane_at_index(w, event->key - '0');
}
server_client_clear_identify(c, wp);
return (0); return (0);
} }

35
tmux.h
View File

@ -729,6 +729,21 @@ struct screen_write_ctx {
u_int skipped; u_int skipped;
}; };
/* Screen redraw context. */
struct screen_redraw_ctx {
struct client *c;
u_int statuslines;
int statustop;
int pane_status;
u_int sx;
u_int sy;
u_int ox;
u_int oy;
};
/* Screen size. */ /* Screen size. */
#define screen_size_x(s) ((s)->grid->sx) #define screen_size_x(s) ((s)->grid->sx)
#define screen_size_y(s) ((s)->grid->sy) #define screen_size_y(s) ((s)->grid->sy)
@ -1376,6 +1391,9 @@ struct status_line {
/* Client connection. */ /* Client connection. */
typedef int (*prompt_input_cb)(struct client *, void *, const char *, int); typedef int (*prompt_input_cb)(struct client *, void *, const char *, int);
typedef void (*prompt_free_cb)(void *); typedef void (*prompt_free_cb)(void *);
typedef void (*overlay_draw_cb)(struct client *, struct screen_redraw_ctx *);
typedef int (*overlay_key_cb)(struct client *, struct key_event *);
typedef void (*overlay_free_cb)(struct client *);
struct client { struct client {
const char *name; const char *name;
struct tmuxpeer *peer; struct tmuxpeer *peer;
@ -1425,7 +1443,7 @@ struct client {
#define CLIENT_REPEAT 0x20 #define CLIENT_REPEAT 0x20
#define CLIENT_SUSPENDED 0x40 #define CLIENT_SUSPENDED 0x40
#define CLIENT_ATTACHED 0x80 #define CLIENT_ATTACHED 0x80
#define CLIENT_IDENTIFY 0x100 /* 0x100 unused */
#define CLIENT_DEAD 0x200 #define CLIENT_DEAD 0x200
#define CLIENT_REDRAWBORDERS 0x400 #define CLIENT_REDRAWBORDERS 0x400
#define CLIENT_READONLY 0x800 #define CLIENT_READONLY 0x800
@ -1454,12 +1472,6 @@ struct client {
int flags; int flags;
struct key_table *keytable; struct key_table *keytable;
struct event identify_timer;
void (*identify_callback)(struct client *,
struct window_pane *);
void *identify_callback_data;
struct cmdq_item *identify_callback_item;
char *message_string; char *message_string;
struct event message_timer; struct event message_timer;
u_int message_next; u_int message_next;
@ -1490,6 +1502,12 @@ struct client {
u_int pan_ox; u_int pan_ox;
u_int pan_oy; u_int pan_oy;
overlay_draw_cb overlay_draw;
overlay_key_cb overlay_key;
overlay_free_cb overlay_free;
void *overlay_data;
struct event overlay_timer;
TAILQ_ENTRY(client) entry; TAILQ_ENTRY(client) entry;
}; };
TAILQ_HEAD(clients, client); TAILQ_HEAD(clients, client);
@ -2010,7 +2028,8 @@ void server_add_accept(int);
/* server-client.c */ /* server-client.c */
u_int server_client_how_many(void); u_int server_client_how_many(void);
void server_client_set_identify(struct client *, u_int); void server_client_set_overlay(struct client *, u_int, overlay_draw_cb,
overlay_key_cb, overlay_free_cb, void *);
void server_client_set_key_table(struct client *, const char *); void server_client_set_key_table(struct client *, const char *);
const char *server_client_get_key_table(struct client *); const char *server_client_get_key_table(struct client *);
int server_client_check_nested(struct client *); int server_client_check_nested(struct client *);