version 1.37, 2020/06/02 08:17:27 |
version 1.38, 2020/06/05 07:33:57 |
|
|
|
|
int flags; |
int flags; |
#define CONTROL_PANE_OFF 0x1 |
#define CONTROL_PANE_OFF 0x1 |
|
#define CONTROL_PANE_PAUSED 0x2 |
|
|
int pending_flag; |
int pending_flag; |
TAILQ_ENTRY(control_pane) pending_entry; |
TAILQ_ENTRY(control_pane) pending_entry; |
|
|
return (cp); |
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. */ |
/* Get actual pane for this client. */ |
static struct window_pane * |
static struct window_pane * |
control_window_pane(struct client *c, u_int pane) |
control_window_pane(struct client *c, u_int pane) |
|
|
} |
} |
|
|
cp = control_get_pane(c, wp); |
cp = control_get_pane(c, wp); |
if (cp == NULL) { |
if (cp == NULL || (cp->flags & CONTROL_PANE_PAUSED)) { |
*off = 0; |
*off = 0; |
return (NULL); |
return (NULL); |
} |
} |
|
|
struct control_pane *cp; |
struct control_pane *cp; |
|
|
cp = control_get_pane(c, wp); |
cp = control_get_pane(c, wp); |
if (cp != NULL) { |
if (cp != NULL && (cp->flags & CONTROL_PANE_OFF)) { |
cp->flags &= ~CONTROL_PANE_OFF; |
cp->flags &= ~CONTROL_PANE_OFF; |
memcpy(&cp->offset, &wp->offset, sizeof cp->offset); |
memcpy(&cp->offset, &wp->offset, sizeof cp->offset); |
memcpy(&cp->queued, &wp->offset, sizeof cp->queued); |
memcpy(&cp->queued, &wp->offset, sizeof cp->queued); |
|
|
cp->flags |= CONTROL_PANE_OFF; |
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. */ |
/* Write a line. */ |
static void |
static void |
control_vwrite(struct client *c, const char *fmt, va_list ap) |
control_vwrite(struct client *c, const char *fmt, va_list ap) |
|
|
struct control_pane *cp; |
struct control_pane *cp; |
struct control_block *cb; |
struct control_block *cb; |
size_t new_size; |
size_t new_size; |
|
uint64_t t; |
|
|
if (winlink_find_by_window(&c->session->windows, wp->window) == NULL) |
if (winlink_find_by_window(&c->session->windows, wp->window) == NULL) |
return; |
return; |
|
|
return; |
return; |
} |
} |
cp = control_add_pane(c, wp); |
cp = control_add_pane(c, wp); |
if (cp->flags & CONTROL_PANE_OFF) |
if (cp->flags & (CONTROL_PANE_OFF|CONTROL_PANE_PAUSED)) |
goto ignore; |
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); |
window_pane_get_new_data(wp, &cp->queued, &new_size); |
if (new_size == 0) |
if (new_size == 0) |
|
|
} |
} |
} |
} |
|
|
/* Flush all output for a client that is detaching. */ |
/* Discard all output for a client. */ |
void |
void |
control_flush(struct client *c) |
control_discard(struct client *c) |
{ |
{ |
struct control_state *cs = c->control_state; |
struct control_state *cs = c->control_state; |
struct control_pane *cp; |
struct control_pane *cp; |
struct control_block *cb, *cb1; |
|
|
|
RB_FOREACH(cp, control_panes, &cs->panes) { |
RB_FOREACH(cp, control_panes, &cs->panes) |
TAILQ_FOREACH_SAFE(cb, &cp->blocks, entry, cb1) { |
control_discard_pane(c, cp); |
TAILQ_REMOVE(&cp->blocks, cb, entry); |
|
control_free_block(cs, cb); |
|
} |
|
} |
|
} |
} |
|
|
/* Stop control mode. */ |
/* Stop control mode. */ |