mirror of
https://github.com/tmux/tmux.git
synced 2025-09-01 20:57:00 +00:00
Add support for pausing a pane when the output buffered for a control
mode client gets too far behind. The pause-after flag with a time is set on the pane with refresh-client -f and a paused pane may be resumed with refresh-client -A. GitHub issue 2217.
This commit is contained in:
63
control.c
63
control.c
@ -65,6 +65,7 @@ struct control_pane {
|
||||
|
||||
int flags;
|
||||
#define CONTROL_PANE_OFF 0x1
|
||||
#define CONTROL_PANE_PAUSED 0x2
|
||||
|
||||
int pending_flag;
|
||||
TAILQ_ENTRY(control_pane) pending_entry;
|
||||
@ -153,6 +154,19 @@ control_add_pane(struct client *c, struct window_pane *wp)
|
||||
return (cp);
|
||||
}
|
||||
|
||||
/* Discard output for a pane. */
|
||||
static void
|
||||
control_discard_pane(struct client *c, struct control_pane *cp)
|
||||
{
|
||||
struct control_state *cs = c->control_state;
|
||||
struct control_block *cb, *cb1;
|
||||
|
||||
TAILQ_FOREACH_SAFE(cb, &cp->blocks, entry, cb1) {
|
||||
TAILQ_REMOVE(&cp->blocks, cb, entry);
|
||||
control_free_block(cs, cb);
|
||||
}
|
||||
}
|
||||
|
||||
/* Get actual pane for this client. */
|
||||
static struct window_pane *
|
||||
control_window_pane(struct client *c, u_int pane)
|
||||
@ -197,7 +211,7 @@ control_pane_offset(struct client *c, struct window_pane *wp, int *off)
|
||||
}
|
||||
|
||||
cp = control_get_pane(c, wp);
|
||||
if (cp == NULL) {
|
||||
if (cp == NULL || (cp->flags & CONTROL_PANE_PAUSED)) {
|
||||
*off = 0;
|
||||
return (NULL);
|
||||
}
|
||||
@ -216,7 +230,7 @@ control_set_pane_on(struct client *c, struct window_pane *wp)
|
||||
struct control_pane *cp;
|
||||
|
||||
cp = control_get_pane(c, wp);
|
||||
if (cp != NULL) {
|
||||
if (cp != NULL && (cp->flags & CONTROL_PANE_OFF)) {
|
||||
cp->flags &= ~CONTROL_PANE_OFF;
|
||||
memcpy(&cp->offset, &wp->offset, sizeof cp->offset);
|
||||
memcpy(&cp->queued, &wp->offset, sizeof cp->queued);
|
||||
@ -233,6 +247,21 @@ control_set_pane_off(struct client *c, struct window_pane *wp)
|
||||
cp->flags |= CONTROL_PANE_OFF;
|
||||
}
|
||||
|
||||
/* Continue a paused pane. */
|
||||
void
|
||||
control_continue_pane(struct client *c, struct window_pane *wp)
|
||||
{
|
||||
struct control_pane *cp;
|
||||
|
||||
cp = control_get_pane(c, wp);
|
||||
if (cp != NULL && (cp->flags & CONTROL_PANE_PAUSED)) {
|
||||
cp->flags &= ~CONTROL_PANE_PAUSED;
|
||||
memcpy(&cp->offset, &wp->offset, sizeof cp->offset);
|
||||
memcpy(&cp->queued, &wp->offset, sizeof cp->queued);
|
||||
control_write(c, "%%continue %%%u", wp->id);
|
||||
}
|
||||
}
|
||||
|
||||
/* Write a line. */
|
||||
static void
|
||||
control_vwrite(struct client *c, const char *fmt, va_list ap)
|
||||
@ -285,6 +314,7 @@ control_write_output(struct client *c, struct window_pane *wp)
|
||||
struct control_pane *cp;
|
||||
struct control_block *cb;
|
||||
size_t new_size;
|
||||
uint64_t t;
|
||||
|
||||
if (winlink_find_by_window(&c->session->windows, wp->window) == NULL)
|
||||
return;
|
||||
@ -296,8 +326,22 @@ control_write_output(struct client *c, struct window_pane *wp)
|
||||
return;
|
||||
}
|
||||
cp = control_add_pane(c, wp);
|
||||
if (cp->flags & CONTROL_PANE_OFF)
|
||||
if (cp->flags & (CONTROL_PANE_OFF|CONTROL_PANE_PAUSED))
|
||||
goto ignore;
|
||||
if (c->flags & CLIENT_CONTROL_PAUSEAFTER) {
|
||||
cb = TAILQ_FIRST(&cp->blocks);
|
||||
if (cb != NULL) {
|
||||
t = get_timer();
|
||||
log_debug("%s: %s: %%%u is %lld behind", __func__,
|
||||
c->name, wp->id, (long long)t - cb->t);
|
||||
if (cb->t < t - c->pause_age) {
|
||||
cp->flags |= CONTROL_PANE_PAUSED;
|
||||
control_discard_pane(c, cp);
|
||||
control_write(c, "%%pause %%%u", wp->id);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
window_pane_get_new_data(wp, &cp->queued, &new_size);
|
||||
if (new_size == 0)
|
||||
@ -585,20 +629,15 @@ control_start(struct client *c)
|
||||
}
|
||||
}
|
||||
|
||||
/* Flush all output for a client that is detaching. */
|
||||
/* Discard all output for a client. */
|
||||
void
|
||||
control_flush(struct client *c)
|
||||
control_discard(struct client *c)
|
||||
{
|
||||
struct control_state *cs = c->control_state;
|
||||
struct control_pane *cp;
|
||||
struct control_block *cb, *cb1;
|
||||
|
||||
RB_FOREACH(cp, control_panes, &cs->panes) {
|
||||
TAILQ_FOREACH_SAFE(cb, &cp->blocks, entry, cb1) {
|
||||
TAILQ_REMOVE(&cp->blocks, cb, entry);
|
||||
control_free_block(cs, cb);
|
||||
}
|
||||
}
|
||||
RB_FOREACH(cp, control_panes, &cs->panes)
|
||||
control_discard_pane(c, cp);
|
||||
}
|
||||
|
||||
/* Stop control mode. */
|
||||
|
Reference in New Issue
Block a user