Add local panes as well.

This commit is contained in:
Nicholas Marriott
2026-07-17 16:30:02 +01:00
parent 38808509d5
commit fde879c347
19 changed files with 742 additions and 140 deletions

478
active.c
View File

@@ -43,6 +43,26 @@ struct active_window {
};
RB_HEAD(active_windows, active_window);
/* Pane entry in a client-local last-pane stack. */
struct active_pane_entry {
struct window_pane *wp;
TAILQ_ENTRY(active_pane_entry) entry;
};
TAILQ_HEAD(active_pane_stack, active_pane_entry);
/* Per-client and per-window local active pane state. */
struct active_pane {
struct client *client;
struct window *window;
enum active_mode mode;
struct window_pane *pane;
struct active_pane_stack last_panes;
RB_ENTRY(active_pane) entry;
};
RB_HEAD(active_panes, active_pane);
/* Compare local active window states by client and session. */
static int
active_window_cmp(struct active_window *aw1, struct active_window *aw2)
{
@@ -63,22 +83,36 @@ active_window_cmp(struct active_window *aw1, struct active_window *aw2)
}
RB_GENERATE_STATIC(active_windows, active_window, entry, active_window_cmp);
static struct active_window *active_get(struct client *, struct session *);
static struct active_window *active_add(struct client *, struct session *,
struct winlink *);
static void active_free(struct active_window *);
static struct winlink *active_resolve(struct active_window *);
static void active_stack_remove(struct active_window_stack *, u_int);
static void active_stack_push(struct active_window_stack *, u_int);
static void active_changed(struct client *, struct session *,
struct winlink *, struct winlink *);
/* Compare local active pane states by client and window. */
static int
active_pane_cmp(struct active_pane *ap1, struct active_pane *ap2)
{
uintptr_t c1 = (uintptr_t)ap1->client;
uintptr_t c2 = (uintptr_t)ap2->client;
uintptr_t w1 = (uintptr_t)ap1->window;
uintptr_t w2 = (uintptr_t)ap2->window;
if (c1 < c2)
return (-1);
if (c1 > c2)
return (1);
if (w1 < w2)
return (-1);
if (w1 > w2)
return (1);
return (0);
}
RB_GENERATE_STATIC(active_panes, active_pane, entry, active_pane_cmp);
/* All local active window states. */
static struct active_windows active_windows = RB_INITIALIZER(&active_windows);
/* All local active pane states. */
static struct active_panes active_panes = RB_INITIALIZER(&active_panes);
/* Find local active window state for a client and session. */
static struct active_window *
active_get(struct client *c, struct session *s)
active_window_get(struct client *c, struct session *s)
{
struct active_window aw;
@@ -91,11 +125,11 @@ active_get(struct client *c, struct session *s)
/* Add local active window state for a client and session. */
static struct active_window *
active_add(struct client *c, struct session *s, struct winlink *wl)
active_window_add(struct client *c, struct session *s, struct winlink *wl)
{
struct active_window *aw;
aw = active_get(c, s);
aw = active_window_get(c, s);
if (aw == NULL) {
aw = xcalloc(1, sizeof *aw);
aw->client = c;
@@ -108,9 +142,35 @@ active_add(struct client *c, struct session *s, struct winlink *wl)
return (aw);
}
/* Remove a window from a local last-window stack. */
static void
active_window_stack_remove(struct active_window_stack *stack, u_int window)
{
struct active_window_entry *awe, *awe1;
TAILQ_FOREACH_SAFE(awe, stack, entry, awe1) {
if (awe->window == window) {
TAILQ_REMOVE(stack, awe, entry);
free(awe);
}
}
}
/* Push a window onto a local last-window stack. */
static void
active_window_stack_push(struct active_window_stack *stack, u_int window)
{
struct active_window_entry *awe;
active_window_stack_remove(stack, window);
awe = xcalloc(1, sizeof *awe);
awe->window = window;
TAILQ_INSERT_HEAD(stack, awe, entry);
}
/* Free local active window state. */
static void
active_free(struct active_window *aw)
active_window_free(struct active_window *aw)
{
struct active_window_entry *awe;
@@ -125,7 +185,7 @@ active_free(struct active_window *aw)
/* Resolve local active window state to a valid winlink. */
static struct winlink *
active_resolve(struct active_window *aw)
active_window_resolve(struct active_window *aw)
{
struct winlink *wl, *next;
u_int window;
@@ -141,7 +201,7 @@ active_resolve(struct active_window *aw)
window = TAILQ_FIRST(&aw->lastw)->window;
next = winlink_find_by_window_id(&aw->session->windows, window);
active_stack_remove(&aw->lastw, window);
active_window_stack_remove(&aw->lastw, window);
if (next != NULL) {
aw->window = next->window->id;
return (next);
@@ -152,35 +212,9 @@ active_resolve(struct active_window *aw)
return (aw->session->curw);
}
/* Remove a window from a local last-window stack. */
static void
active_stack_remove(struct active_window_stack *stack, u_int window)
{
struct active_window_entry *awe, *awe1;
TAILQ_FOREACH_SAFE(awe, stack, entry, awe1) {
if (awe->window == window) {
TAILQ_REMOVE(stack, awe, entry);
free(awe);
}
}
}
/* Push a window onto a local last-window stack. */
static void
active_stack_push(struct active_window_stack *stack, u_int window)
{
struct active_window_entry *awe;
active_stack_remove(stack, window);
awe = xcalloc(1, sizeof *awe);
awe->window = window;
TAILQ_INSERT_HEAD(stack, awe, entry);
}
/* Notify the server that a client's effective window changed. */
static void
active_changed(struct client *c, struct session *s, struct winlink *wl,
active_window_changed(struct client *c, struct session *s, struct winlink *wl,
struct winlink *old)
{
struct event_payload *ep;
@@ -225,17 +259,114 @@ active_changed(struct client *c, struct session *s, struct winlink *wl,
recalculate_sizes();
}
/* Find local active pane state for a client and window. */
static struct active_pane *
active_pane_get(struct client *c, struct window *w)
{
struct active_pane ap;
if (c == NULL || w == NULL)
return (NULL);
ap.client = c;
ap.window = w;
return (RB_FIND(active_panes, &active_panes, &ap));
}
/* Add local active pane state for a client and window. */
static struct active_pane *
active_pane_add(struct client *c, struct window *w)
{
struct active_pane *ap;
ap = active_pane_get(c, w);
if (ap == NULL) {
ap = xcalloc(1, sizeof *ap);
ap->client = c;
ap->window = w;
TAILQ_INIT(&ap->last_panes);
RB_INSERT(active_panes, &active_panes, ap);
}
return (ap);
}
/* Remove a pane from a client-local last-pane stack. */
static void
active_pane_stack_remove(struct active_pane *ap,
struct window_pane *wp)
{
struct active_pane_entry *ape, *ape1;
TAILQ_FOREACH_SAFE(ape, &ap->last_panes, entry, ape1) {
if (ape->wp == wp) {
TAILQ_REMOVE(&ap->last_panes, ape, entry);
free(ape);
}
}
}
/* Push a pane onto a client-local last-pane stack. */
static void
active_pane_stack_push(struct active_pane *ap, struct window_pane *wp)
{
struct active_pane_entry *ape;
if (wp == NULL)
return;
active_pane_stack_remove(ap, wp);
ape = xcalloc(1, sizeof *ape);
ape->wp = wp;
TAILQ_INSERT_HEAD(&ap->last_panes, ape, entry);
}
/* Free local active pane state. */
static void
active_pane_free(struct active_pane *ap)
{
struct active_pane_entry *ape, *ape1;
RB_REMOVE(active_panes, &active_panes, ap);
TAILQ_FOREACH_SAFE(ape, &ap->last_panes, entry, ape1) {
TAILQ_REMOVE(&ap->last_panes, ape, entry);
free(ape);
}
free(ap);
}
/* Check whether a pane can be the effective pane for a window. */
static int
active_pane_valid(struct window *w, struct window_pane *wp)
{
if (w == NULL || wp == NULL || wp->window != w)
return (0);
if (!window_has_pane(w, wp))
return (0);
if (w->modal != NULL && wp != w->modal)
return (0);
return (1);
}
/* Get the shared pane for a window, accounting for modal panes. */
static struct window_pane *
active_pane_default(struct window *w)
{
if (w == NULL)
return (NULL);
if (w->modal != NULL)
return (w->modal);
return (w->active);
}
/* Return if a client has local window selection for a session. */
int
active_is_local_window(struct client *c, struct session *s)
{
return (active_get(c, s) != NULL);
return (active_window_get(c, s) != NULL);
}
/* Make a client use local or shared window selection for a session. */
void
active_set_local_window(struct client *c, struct session *s,
enum active_window_mode mode)
enum active_mode mode)
{
struct active_window *aw;
struct winlink *wl, *old;
@@ -245,17 +376,17 @@ active_set_local_window(struct client *c, struct session *s,
old = active_get_effective_winlink(c, s);
if (mode == ACTIVE_LOCAL) {
active_add(c, s, old);
active_window_add(c, s, old);
if (c != NULL && c->session == s)
c->flags |= CLIENT_REDRAWSTATUS;
return;
}
aw = active_get(c, s);
aw = active_window_get(c, s);
if (aw != NULL) {
active_free(aw);
active_window_free(aw);
wl = active_get_effective_winlink(c, s);
active_changed(c, s, wl, old);
active_window_changed(c, s, wl, old);
if (c != NULL && c->session == s)
c->flags |= CLIENT_REDRAWSTATUS;
}
@@ -269,9 +400,9 @@ active_get_effective_winlink(struct client *c, struct session *s)
if (s == NULL)
return (NULL);
aw = active_get(c, s);
aw = active_window_get(c, s);
if (aw != NULL)
return (active_resolve(aw));
return (active_window_resolve(aw));
return (s->curw);
}
@@ -297,19 +428,19 @@ active_select_window(struct client *c, struct session *s, struct winlink *wl)
if (wl == NULL)
return (-1);
aw = active_get(c, s);
aw = active_window_get(c, s);
if (aw == NULL)
return (session_set_current(s, wl));
old = active_resolve(aw);
old = active_window_resolve(aw);
if (old == wl)
return (1);
if (old != NULL)
active_stack_push(&aw->lastw, old->window->id);
active_stack_remove(&aw->lastw, wl->window->id);
active_window_stack_push(&aw->lastw, old->window->id);
active_window_stack_remove(&aw->lastw, wl->window->id);
aw->window = wl->window->id;
changed = (old != wl);
active_changed(c, s, wl, old);
active_window_changed(c, s, wl, old);
return (changed ? 0 : 1);
}
@@ -369,7 +500,7 @@ active_last_window(struct client *c, struct session *s)
struct winlink *wl;
u_int window;
aw = active_get(c, s);
aw = active_window_get(c, s);
if (aw == NULL)
return (session_last(s));
while (!TAILQ_EMPTY(&aw->lastw)) {
@@ -378,48 +509,11 @@ active_last_window(struct client *c, struct session *s)
wl = winlink_find_by_window_id(&s->windows, window);
if (wl != NULL)
return (active_select_window(c, s, wl));
active_stack_remove(&aw->lastw, window);
active_window_stack_remove(&aw->lastw, window);
}
return (-1);
}
/* Remove all state for a client. */
void
active_remove_client(struct client *c)
{
struct active_window *aw, *aw1;
RB_FOREACH_SAFE(aw, active_windows, &active_windows, aw1) {
if (aw->client == c)
active_free(aw);
}
}
/* Remove all state for a session. */
void
active_remove_session(struct session *s)
{
struct active_window *aw, *aw1;
RB_FOREACH_SAFE(aw, active_windows, &active_windows, aw1) {
if (aw->session == s)
active_free(aw);
}
}
/* Remove a window from all local state. */
void
active_remove_window(struct window *w)
{
struct active_window *aw;
RB_FOREACH(aw, active_windows, &active_windows) {
active_stack_remove(&aw->lastw, w->id);
if (aw->window == w->id && aw->session->curw != NULL)
aw->window = aw->session->curw->window->id;
}
}
/* Return if this winlink is the effective winlink. */
int
active_is_effective_window(struct client *c, struct session *s,
@@ -437,7 +531,7 @@ active_is_last_window(struct client *c, struct session *s, struct winlink *wl)
if (wl == NULL)
return (0);
aw = active_get(c, s);
aw = active_window_get(c, s);
if (aw == NULL)
return (wl == TAILQ_FIRST(&s->lastw));
TAILQ_FOREACH(awe, &aw->lastw, entry) {
@@ -447,3 +541,197 @@ active_is_last_window(struct client *c, struct session *s, struct winlink *wl)
}
return (0);
}
/* Return if a client has local pane selection for a window. */
int
active_has_local_pane(struct client *c, struct window *w)
{
struct active_pane *ap;
ap = active_pane_get(c, w);
return (ap != NULL && ap->mode == ACTIVE_LOCAL);
}
/* Make a client use local or shared pane selection for a window. */
void
active_set_pane_mode(struct client *c, struct window *w, enum active_mode mode)
{
struct active_pane *ap;
struct window_pane *wp;
if (c == NULL || w == NULL)
return;
if (mode == ACTIVE_SHARED) {
ap = active_pane_get(c, w);
if (ap != NULL)
ap->mode = ACTIVE_SHARED;
server_redraw_client(c);
server_status_client(c);
return;
}
if (server_client_how_many() < 2) {
ap = active_pane_get(c, w);
if (ap != NULL)
ap->mode = ACTIVE_SHARED;
server_redraw_client(c);
server_status_client(c);
return;
}
wp = active_get_effective_pane(c, w);
if (wp == NULL)
wp = active_pane_default(w);
ap = active_pane_add(c, w);
ap->mode = ACTIVE_LOCAL;
ap->pane = wp;
server_redraw_client(c);
server_status_client(c);
}
/* Return the effective active pane for a client and window. */
struct window_pane *
active_get_effective_pane(struct client *c, struct window *w)
{
struct active_pane *ap;
struct window_pane *wp;
wp = active_pane_default(w);
ap = active_pane_get(c, w);
if (ap == NULL || ap->mode != ACTIVE_LOCAL)
return (wp);
if (!active_pane_valid(w, ap->pane)) {
ap->pane = wp;
if (wp != NULL)
active_pane_stack_remove(ap, wp);
return (wp);
}
return (ap->pane);
}
/* Return the effective last pane for a client and window. */
struct window_pane *
active_get_last_pane(struct client *c, struct window *w)
{
struct active_pane *ap;
struct active_pane_entry *ape, *ape1;
if (!active_has_local_pane(c, w))
return (w == NULL ? NULL : TAILQ_FIRST(&w->last_panes));
ap = active_pane_get(c, w);
TAILQ_FOREACH_SAFE(ape, &ap->last_panes, entry, ape1) {
if (active_pane_valid(w, ape->wp))
return (ape->wp);
TAILQ_REMOVE(&ap->last_panes, ape, entry);
free(ape);
}
return (NULL);
}
/* Select a pane using either shared or local state. */
int
active_set_pane(struct client *c, struct window *w, struct window_pane *wp,
int notify)
{
struct active_pane *ap;
struct window_pane *lastwp;
if (!active_pane_valid(w, wp))
return (0);
if (!active_has_local_pane(c, w))
return (window_set_active_pane(w, wp, notify));
lastwp = active_get_effective_pane(c, w);
if (wp == lastwp)
return (0);
ap = active_pane_add(c, w);
active_pane_stack_remove(ap, wp);
active_pane_stack_push(ap, lastwp);
ap->pane = wp;
if (c != NULL) {
server_redraw_client(c);
server_status_client(c);
}
return (1);
}
/* Remove all local pane state if fewer than two clients remain. */
void
active_check_clients(void)
{
struct active_pane *ap, *ap1;
if (server_client_how_many() >= 2)
return;
RB_FOREACH_SAFE(ap, active_panes, &active_panes, ap1) {
if (ap->mode == ACTIVE_LOCAL) {
server_redraw_client(ap->client);
server_status_client(ap->client);
}
active_pane_free(ap);
}
}
/* Remove all state for a client. */
void
active_remove_client(struct client *c)
{
struct active_window *aw, *aw1;
struct active_pane *ap, *ap1;
RB_FOREACH_SAFE(aw, active_windows, &active_windows, aw1) {
if (aw->client == c)
active_window_free(aw);
}
RB_FOREACH_SAFE(ap, active_panes, &active_panes, ap1) {
if (ap->client == c)
active_pane_free(ap);
}
}
/* Remove all window state for a session. */
void
active_remove_session(struct session *s)
{
struct active_window *aw, *aw1;
RB_FOREACH_SAFE(aw, active_windows, &active_windows, aw1) {
if (aw->session == s)
active_window_free(aw);
}
}
/* Remove a window from all local state. */
void
active_remove_window(struct window *w)
{
struct active_window *aw;
struct active_pane *ap, *ap1;
RB_FOREACH(aw, active_windows, &active_windows) {
active_window_stack_remove(&aw->lastw, w->id);
if (aw->window == w->id && aw->session->curw != NULL)
aw->window = aw->session->curw->window->id;
}
RB_FOREACH_SAFE(ap, active_panes, &active_panes, ap1) {
if (ap->window == w)
active_pane_free(ap);
}
}
/* Remove a pane from all local pane state. */
void
active_remove_pane(struct window_pane *wp)
{
struct active_pane *ap, *ap1;
RB_FOREACH_SAFE(ap, active_panes, &active_panes, ap1) {
active_pane_stack_remove(ap, wp);
if (ap->pane == wp)
ap->pane = NULL;
}
}

View File

@@ -885,7 +885,7 @@ cmd_find_from_client(struct cmd_find_state *fs, struct client *c, int flags)
cmd_find_clear_state(fs, flags);
fs->wl = active_get_effective_winlink(c, c->session);
fs->wp = fs->wl->window->active;
fs->wp = active_get_effective_pane(c, fs->wl->window);
if (fs->wp == NULL) {
cmd_find_from_session(fs, c->session, flags);
return (0);

View File

@@ -186,6 +186,7 @@ cmd_join_pane_place(struct cmdq_item *item, struct winlink *wl,
lc->g.yoff = yoff;
layout_fix_panes(w, NULL);
}
redraw_invalidate_scene(w);
events_fire_window("window-layout-changed", w);
server_redraw_window(w);
@@ -358,6 +359,7 @@ cmd_join_pane_zindex(struct cmdq_item *item, struct winlink *wl,
else
TAILQ_INSERT_TAIL(&w->z_index, wp, zentry);
redraw_invalidate_scene(w);
events_fire_window("window-layout-changed", w);
server_redraw_window(w);
@@ -397,6 +399,7 @@ cmd_join_pane_tile(struct cmdq_item *item, struct args *args, struct window *w,
window_set_active_pane(w, wp, 1);
layout_fix_offsets(w);
layout_fix_panes(w, NULL);
redraw_invalidate_scene(w);
events_fire_window("window-layout-changed", w);
server_redraw_window(w);

View File

@@ -79,7 +79,7 @@ static void
cmd_run_shell_print(struct job *job, const char *msg)
{
struct cmd_run_shell_data *cdata = job_get_data(job);
struct client *c;
struct client *c = cdata->client;
struct session *s;
struct window_pane *wp = NULL;
struct window *w;
@@ -93,11 +93,10 @@ cmd_run_shell_print(struct job *job, const char *msg)
cmdq_print(cdata->item, "%s", msg);
return;
}
c = cdata->client;
if (c != NULL && c->session != NULL) {
s = c->session;
w = active_get_effective_window(c, s);
wp = w->active;
wp = active_get_effective_pane(c, w);
}
if (wp == NULL && cmd_find_from_nothing(&fs, 0) == 0)
wp = fs.wp;

View File

@@ -33,8 +33,8 @@ const struct cmd_entry cmd_select_pane_entry = {
.name = "select-pane",
.alias = "selectp",
.args = { "DdegLlMmP:RT:t:UZ", 0, 0, NULL }, /* -P and -g deprecated */
.usage = "[-DdeLlMmRUZ] [-T title] " CMD_TARGET_PANE_USAGE,
.args = { "DdegLlMmP:RsST:t:UZ", 0, 0, NULL }, /* -P and -g deprecated */
.usage = "[-DdeLlMmRsSUZ] [-T title] " CMD_TARGET_PANE_USAGE,
.target = { 't', CMD_FIND_PANE, 0 },
@@ -85,6 +85,7 @@ static enum cmd_retval
cmd_select_pane_marked_pane(struct cmd *self, struct cmdq_item *item)
{
struct args *args = cmd_get_args(self);
struct client *c = cmdq_get_client(item);
struct cmd_find_state *target = cmdq_get_target(item);
struct event_payload *ep;
struct cmd_find_state fs;
@@ -138,8 +139,9 @@ cmd_select_pane_marked_pane(struct cmd *self, struct cmdq_item *item)
server_status_window(mwp->window);
}
if (window_pane_is_floating(wp)) {
window_redraw_active_switch(wp->window, wp);
window_set_active_pane(wp->window, wp, 1);
if (!active_has_local_pane(c, wp->window))
window_redraw_active_switch(wp->window, wp);
active_set_pane(c, wp->window, wp, 1);
}
return (CMD_RETURN_NORMAL);
}
@@ -153,25 +155,39 @@ cmd_select_pane_exec(struct cmd *self, struct cmdq_item *item)
struct cmd_find_state *target = cmdq_get_target(item);
struct event_payload *ep;
struct cmd_find_state fs;
struct client *c = cmdq_get_client(item);
struct winlink *wl = target->wl;
struct window *w = wl->window;
struct session *s = target->s;
struct window_pane *wp = target->wp, *lastwp;
struct window_pane *wp = target->wp, *lastwp, *activewp;
struct options *oo = wp->options;
char *title;
const char *style;
struct options_entry *o;
if (args_has(args, 's') || args_has(args, 'S')) {
if (c == NULL || c->session == NULL) {
cmdq_error(item, "no current client");
return (CMD_RETURN_ERROR);
}
if (args_has(args, 's'))
active_set_pane_mode(c, w, ACTIVE_LOCAL);
else
active_set_pane_mode(c, w, ACTIVE_SHARED);
return (CMD_RETURN_NORMAL);
}
if (entry == &cmd_last_pane_entry || args_has(args, 'l')) {
/*
* Check for no last pane found in case the other pane was
* spawned without being visited (for example split-window -d).
*/
lastwp = TAILQ_FIRST(&w->last_panes);
lastwp = active_get_last_pane(c, w);
if (lastwp == NULL && window_count_panes(w, 1) == 2) {
lastwp = TAILQ_PREV(w->active, window_panes, entry);
activewp = active_get_effective_pane(c, w);
lastwp = TAILQ_PREV(activewp, window_panes, entry);
if (lastwp == NULL)
lastwp = TAILQ_NEXT(w->active, entry);
lastwp = TAILQ_NEXT(activewp, entry);
}
if (lastwp == NULL) {
cmdq_error(item, "no last pane");
@@ -188,8 +204,9 @@ cmd_select_pane_exec(struct cmd *self, struct cmdq_item *item)
} else {
if (window_push_zoom(w, 0, args_has(args, 'Z')))
server_redraw_window(w);
window_redraw_active_switch(w, lastwp);
if (window_set_active_pane(w, lastwp, 1)) {
if (!active_has_local_pane(c, w))
window_redraw_active_switch(w, lastwp);
if (active_set_pane(c, w, lastwp, 1)) {
cmd_find_from_winlink(current, wl, 0);
cmd_select_pane_redraw(w);
}
@@ -267,12 +284,14 @@ cmd_select_pane_exec(struct cmd *self, struct cmdq_item *item)
return (CMD_RETURN_NORMAL);
}
if (wp == w->active)
activewp = active_get_effective_pane(c, w);
if (wp == activewp)
return (CMD_RETURN_NORMAL);
if (window_push_zoom(w, 0, args_has(args, 'Z')))
server_redraw_window(w);
window_redraw_active_switch(w, wp);
if (window_set_active_pane(w, wp, 1))
if (!active_has_local_pane(c, w))
window_redraw_active_switch(w, wp);
if (active_set_pane(c, w, wp, 1))
cmd_find_from_winlink_pane(current, wl, wp, 0);
cmdq_insert_hook(s, item, current, "after-select-pane");
cmd_select_pane_redraw(w);

View File

@@ -90,7 +90,7 @@ cmd_select_window_exec(struct cmd *self, struct cmdq_item *item)
struct cmd_find_state *target = cmdq_get_target(item);
struct winlink *wl = target->wl, *current_wl;
struct session *s = target->s;
enum active_window_mode mode;
enum active_mode mode;
int next, previous, last, activity;
next = (cmd_get_entry(self) == &cmd_next_window_entry);

View File

@@ -1061,7 +1061,8 @@ format_cb_pane_fg(struct format_tree *ft)
if (wp == NULL)
return (NULL);
tty_default_colours(&gc, wp, NULL);
tty_default_colours(&gc, wp,
active_get_effective_pane(ft->c, wp->window), NULL);
return (xstrdup(colour_tostring(gc.fg)));
}
@@ -1112,7 +1113,8 @@ format_cb_pane_bg(struct format_tree *ft)
if (wp == NULL)
return (NULL);
tty_default_colours(&gc, wp, NULL);
tty_default_colours(&gc, wp,
active_get_effective_pane(ft->c, wp->window), NULL);
return (xstrdup(colour_tostring(gc.bg)));
}
@@ -2099,14 +2101,45 @@ format_cb_synchronized_output_flag(struct format_tree *ft)
static void *
format_cb_pane_active(struct format_tree *ft)
{
struct window_pane *active;
if (ft->wp != NULL) {
if (ft->wp == ft->wp->window->active)
active = active_get_effective_pane(ft->c, ft->wp->window);
if (ft->wp == active)
return (xstrdup("1"));
return (xstrdup("0"));
}
return (NULL);
}
/* Callback for pane_local_active. */
static void *
format_cb_pane_local_active(struct format_tree *ft)
{
struct window_pane *active;
if (ft->wp != NULL && active_has_local_pane(ft->c, ft->wp->window)) {
active = active_get_effective_pane(ft->c, ft->wp->window);
if (ft->wp == active)
return (xstrdup("1"));
return (xstrdup("0"));
}
return (NULL);
}
/* Callback for pane_local_mode. */
static void *
format_cb_pane_local_mode(struct format_tree *ft)
{
struct window *w = ft->w;
if (ft->wp != NULL)
w = ft->wp->window;
if (active_has_local_pane(ft->c, w))
return (xstrdup("1"));
return (xstrdup("0"));
}
/* Callback for pane_at_left. */
static void *
format_cb_pane_at_left(struct format_tree *ft)
@@ -2385,7 +2418,7 @@ static void *
format_cb_pane_last(struct format_tree *ft)
{
if (ft->wp != NULL) {
if (ft->wp == TAILQ_FIRST(&ft->wp->window->last_panes))
if (ft->wp == active_get_last_pane(ft->c, ft->wp->window))
return (xstrdup("1"));
return (xstrdup("0"));
}
@@ -3750,6 +3783,12 @@ static const struct format_table_entry format_table[] = {
{ "pane_left", FORMAT_TABLE_STRING,
format_cb_pane_left
},
{ "pane_local_active", FORMAT_TABLE_STRING,
format_cb_pane_local_active
},
{ "pane_local_mode", FORMAT_TABLE_STRING,
format_cb_pane_local_mode
},
{ "pane_marked", FORMAT_TABLE_STRING,
format_cb_pane_marked
},
@@ -6746,7 +6785,7 @@ format_defaults(struct format_tree *ft, struct client *c, struct session *s,
if (wl == NULL && s != NULL)
wl = active_get_effective_winlink(c, s);
if (wp == NULL && wl != NULL)
wp = wl->window->active;
wp = active_get_effective_pane(c, wl->window);
if (c != NULL)
format_defaults_client(ft, c);

View File

@@ -3078,7 +3078,8 @@ input_osc_10(struct input_ctx *ictx, const char *p)
return;
c = window_pane_get_fg_control_client(wp);
if (c == -1) {
tty_default_colours(&defaults, wp, NULL);
tty_default_colours(&defaults, wp, wp->window->active,
NULL);
if (COLOUR_DEFAULT(defaults.fg))
c = window_pane_get_fg(wp);
else

View File

@@ -71,6 +71,8 @@
" '#{?#{!:#{pane_floating_flag}},Horizontal Split,}' 'h' {split-window -h}" \
" '#{?#{!:#{pane_floating_flag}},Vertical Split,}' 'v' {split-window -v}" \
" ''" \
" '#{?#{>=:#{window_active_clients},2},#{?pane_local_mode,Shared Active Pane,Local Active Pane},}' 'a' {if -F '#{pane_local_mode}' {select-pane -S} {select-pane -s}}" \
" ''" \
" '#{?#{&&:#{!:#{pane_floating_flag}},#{>:#{window_panes},1}},Swap Up,}' 'u' {swap-pane -U}" \
" '#{?#{&&:#{!:#{pane_floating_flag}},#{>:#{window_panes},1}},Swap Down,}' 'd' {swap-pane -D}" \
" '#{?pane_marked_set,,-}Swap Marked' 's' {swap-pane}" \
@@ -501,6 +503,7 @@ key_bindings_init(void)
/* Mouse button 1 down on pane. */
"bind -n MouseDown1Pane { select-pane -t=; send -M }",
"bind -n M-MouseDown1Pane { move-pane -P front -t= }",
/* Mouse button 1 drag on pane. */
"bind -n MouseDrag1Pane { if -F '#{||:#{pane_in_mode},#{mouse_any_flag}}' { send -M } { copy-mode -M } }",
@@ -522,6 +525,7 @@ key_bindings_init(void)
/* Mouse button 1 on border. */
"bind -n MouseDown1Border { select-pane -M }",
"bind -n M-MouseDown1Border { move-pane -P front -t= }",
/* Mouse button 1 drag on border. */
"bind -n MouseDrag1Border { resize-pane -M }",

View File

@@ -1533,8 +1533,9 @@ const struct options_table_entry options_table[] = {
.scope = OPTIONS_TABLE_WINDOW|OPTIONS_TABLE_PANE,
.default_str = "fg=#{?pane_modal_flag,themeblue,"
"#{?pane_marked,thememagenta,"
"#{?pane_local_active,themecyan,"
"#{?synchronize-panes,themered,"
"#{?pane_in_mode,themeyellow,themegreen}}}}",
"#{?pane_in_mode,themeyellow,themegreen}}}}}",
.flags = OPTIONS_TABLE_IS_STYLE,
.separator = ",",
.text = "Style of the active pane border."

View File

@@ -0,0 +1,201 @@
#!/bin/sh
PATH=/bin:/usr/bin
TERM=screen
LANG=C.UTF-8
LC_ALL=C.UTF-8
export TERM LANG LC_ALL
[ -z "$TEST_TMUX" ] && TEST_TMUX=$(readlink -f ../tmux)
TMUX="$TEST_TMUX -LtestA$$ -f/dev/null"
TMPDIR=${TMPDIR:-/tmp}/tmux-local-pane.$$
mkdir -p "$TMPDIR" || exit 1
IN1="$TMPDIR/in1"
IN2="$TMPDIR/in2"
OUT1="$TMPDIR/out1"
OUT2="$TMPDIR/out2"
cleanup()
{
$TMUX kill-server 2>/dev/null
rm -rf "$TMPDIR"
}
trap cleanup 0 1 15
fail()
{
echo "$1"
exit 1
}
wait_for()
{
file=$1
pattern=$2
i=0
while [ "$i" -lt 20 ]; do
if grep -q "$pattern" "$file"; then
return 0
fi
sleep 1
i=$((i + 1))
done
echo "missing '$pattern' in $file"
cat "$file"
return 1
}
send1()
{
printf '%s\n' "$*" >&3
}
send2()
{
printf '%s\n' "$*" >&4
}
check_fmt()
{
out=$($TMUX display-message -p -t "$1" "$2" 2>&1)
if [ "$out" != "$3" ]; then
echo "Format '$2' for '$1' wrong."
echo "Expected: '$3'"
echo "But got: '$out'"
exit 1
fi
}
$TMUX kill-server 2>/dev/null
$TMUX new-session -d -s active -x 80 -y 24 || exit 1
$TMUX split-window -d -h -t active:0 || exit 1
$TMUX split-window -d -v -t active:0.0 || exit 1
style=$($TMUX show-options -wgv pane-active-border-style) || exit 1
case "$style" in
*pane_local_active*themecyan*) ;;
*) fail "pane-active-border-style does not include local active colour" ;;
esac
p0=$($TMUX display-message -p -t active:0.0 '#{pane_id}') || exit 1
p1=$($TMUX display-message -p -t active:0.1 '#{pane_id}') || exit 1
p2=$($TMUX display-message -p -t active:0.2 '#{pane_id}') || exit 1
$TMUX select-pane -t "$p0" || exit 1
check_fmt active:0 '#{pane_id}' "$p0"
mkfifo "$IN1" "$IN2" || exit 1
: >"$OUT1"
: >"$OUT2"
$TMUX -C attach-session -t active <"$IN1" >"$OUT1" 2>&1 &
PID1=$!
exec 3>"$IN1"
send1 'display-message -p C1_READY'
wait_for "$OUT1" 'C1_READY' || exit 1
# One attached client cannot enter local mode.
send1 'select-pane -s'
send1 "select-pane -t $p1"
send1 'display-message -p "C1_SINGLE:#{pane_id}:#{pane_active}:#{pane_local_active}"'
wait_for "$OUT1" "C1_SINGLE:$p1:1:" || exit 1
check_fmt active:0 '#{pane_id}' "$p1"
send1 "select-pane -t $p0"
check_fmt active:0 '#{pane_id}' "$p0"
$TMUX -C attach-session -t active <"$IN2" >"$OUT2" 2>&1 &
PID2=$!
exec 4>"$IN2"
send2 'display-message -p C2_READY'
wait_for "$OUT2" 'C2_READY' || exit 1
# Both clients start in shared mode and see the window active pane.
send1 'display-message -p "C1_START:#{pane_id}:#{pane_active}:#{pane_local_active}"'
send2 'display-message -p "C2_START:#{pane_id}:#{pane_active}:#{pane_local_active}"'
wait_for "$OUT1" "C1_START:$p0:1:" || exit 1
wait_for "$OUT2" "C2_START:$p0:1:" || exit 1
# Client 1 enters local mode and selects a pane without changing shared state.
send1 'select-pane -s'
send1 "select-pane -t $p1"
send1 'display-message -p "C1_LOCAL:#{pane_id}:#{pane_active}:#{pane_local_active}:#{pane_local_mode}"'
send1 "display-message -p -t $p0 \"C1_LOCAL_INACTIVE:#{pane_id}:#{pane_active}:#{pane_local_active}\""
wait_for "$OUT1" "C1_LOCAL:$p1:1:1:1" || exit 1
wait_for "$OUT1" "C1_LOCAL_INACTIVE:$p0:0:0" || exit 1
check_fmt active:0 '#{pane_id}' "$p0"
send2 'display-message -p "C2_SHARED:#{pane_id}:#{pane_active}:#{pane_local_active}"'
wait_for "$OUT2" "C2_SHARED:$p0:1:" || exit 1
# Client 2 can keep an independent local pane in the same window.
send2 'select-pane -s'
send2 "select-pane -t $p2"
send2 'display-message -p "C2_LOCAL:#{pane_id}:#{pane_active}:#{pane_local_active}"'
wait_for "$OUT2" "C2_LOCAL:$p2:1:1" || exit 1
send1 'display-message -p "C1_STILL:#{pane_id}:#{pane_active}:#{pane_local_active}"'
wait_for "$OUT1" "C1_STILL:$p1:1:1" || exit 1
# Local last-pane history is independent of the shared window history.
send1 "select-pane -t $p2"
send1 'last-pane'
send1 'display-message -p "C1_LAST:#{pane_id}:#{pane_last}"'
wait_for "$OUT1" "C1_LAST:$p1:0" || exit 1
check_fmt active:0 '#{pane_id}' "$p0"
# Switching back to shared mode immediately follows window->active.
send1 'select-pane -S'
send1 'display-message -p "C1_SHARED_AGAIN:#{pane_id}:#{pane_active}"'
wait_for "$OUT1" "C1_SHARED_AGAIN:$p0:1" || exit 1
send1 "select-pane -t $p1"
check_fmt active:0 '#{pane_id}' "$p1"
send2 'display-message -p "C2_STILL_LOCAL:#{pane_id}:#{pane_active}"'
wait_for "$OUT2" "C2_STILL_LOCAL:$p2:1" || exit 1
# Local selection survives switching away and back to the window.
send2 'new-window -n other'
send2 'previous-window'
send2 'display-message -p "C2_AFTER_WINDOW_SWITCH:#{pane_id}:#{pane_active}"'
wait_for "$OUT2" "C2_AFTER_WINDOW_SWITCH:$p2:1" || exit 1
# Removing a locally active pane recovers to the shared active pane.
$TMUX kill-pane -t "$p2" || exit 1
send2 'display-message -p "C2_AFTER_KILL:#{pane_id}:#{pane_active}"'
wait_for "$OUT2" "C2_AFTER_KILL:$p1:1" || exit 1
# Local selection of a floating pane does not raise it unless requested.
f1=$($TMUX new-pane -dPF '#{pane_id}' -x 20 -y 6 -X 8 -Y 3 \
-t active:0 'sleep 100') || exit 1
f2=$($TMUX new-pane -dPF '#{pane_id}' -x 20 -y 6 -X 12 -Y 5 \
-t active:0 'sleep 100') || exit 1
check_fmt "$f1" '#{pane_z}' 1
check_fmt "$f2" '#{pane_z}' 0
send1 'select-pane -s'
send1 "select-pane -t $f1"
send1 "display-message -p -t $f1 \"C1_FLOAT_LOCAL:#{pane_id}:#{pane_active}:#{pane_z}\""
wait_for "$OUT1" "C1_FLOAT_LOCAL:$f1:1:1" || exit 1
check_fmt "$f1" '#{pane_z}' 1
send1 "select-pane -M -t $f1"
send1 "display-message -p -t $f1 \"C1_FLOAT_BORDER:#{pane_id}:#{pane_active}:#{pane_z}\""
wait_for "$OUT1" "C1_FLOAT_BORDER:$f1:1:1" || exit 1
check_fmt "$f1" '#{pane_z}' 1
send1 "move-pane -P front -t $f1"
send1 "display-message -p -t $f1 \"C1_FLOAT_RAISE:#{pane_z}\""
wait_for "$OUT1" "C1_FLOAT_RAISE:0" || exit 1
check_fmt "$f1" '#{pane_z}' 0
$TMUX kill-pane -t "$f1" || exit 1
$TMUX kill-pane -t "$f2" || exit 1
# When only one client remains, local mode is cleared.
send1 'select-pane -s'
send1 "select-pane -t $p0"
send1 'display-message -p "C1_LOCAL_BEFORE_DETACH:#{pane_id}:#{pane_local_active}"'
wait_for "$OUT1" "C1_LOCAL_BEFORE_DETACH:$p0:1" || exit 1
kill "$PID2" 2>/dev/null
wait "$PID2" 2>/dev/null
send1 'display-message -p "C1_AFTER_DETACH:#{pane_id}:#{pane_local_active}"'
wait_for "$OUT1" "C1_AFTER_DETACH:$p1:" || exit 1
kill "$PID1" 2>/dev/null
wait "$PID1" 2>/dev/null
$TMUX display-message -p alive >/dev/null 2>&1 || fail "server died"
exit 0

View File

@@ -1114,7 +1114,7 @@ redraw_draw_pane_span(struct redraw_draw_ctx *dctx,
struct tty_style_ctx style_ctx;
u_int px, py;
tty_default_colours(&defaults, wp, &style_ctx.dim);
tty_default_colours(&defaults, wp, dctx->active, &style_ctx.dim);
style_ctx.defaults = &defaults;
style_ctx.palette = &wp->palette;
style_ctx.hyperlinks = s->hyperlinks;
@@ -1323,7 +1323,7 @@ redraw_draw_scrollbar_span(struct redraw_draw_ctx *dctx,
memcpy(&slgc, &gc, sizeof slgc);
slgc.fg = gc.bg;
slgc.bg = gc.fg;
tty_default_colours(&pad_gc, wp, NULL);
tty_default_colours(&pad_gc, wp, dctx->active, NULL);
sb_w = sb_style->width;
sb_pad = sb_style->pad;
@@ -1601,7 +1601,7 @@ redraw_set_draw_context(struct redraw_draw_ctx *dctx,
wl = active_get_effective_winlink(c, s);
if (server_is_marked(s, wl, marked_pane.wp))
dctx->marked = marked_pane.wp;
dctx->active = active_get_effective_window(c, s)->active;
dctx->active = active_get_effective_pane(c, wl->window);
lines = status_line_size(c);
if (options_get_number(oo, "status-position") == 0)

View File

@@ -134,7 +134,7 @@ screen_write_redraw_cb(const struct tty_ctx *ttyctx)
static int
screen_write_set_client_cb(struct tty_ctx *ttyctx, struct client *c)
{
struct window_pane *wp = ttyctx->arg;
struct window_pane *wp = ttyctx->arg, *active;
if (ttyctx->flags & TTY_CTX_INVISIBLE_PANES) {
if (session_has(c->session, wp->window))
@@ -160,11 +160,14 @@ screen_write_set_client_cb(struct tty_ctx *ttyctx, struct client *c)
return (-1);
}
active = active_get_effective_pane(c, wp->window);
if (tty_window_offset(&c->tty, &ttyctx->wox, &ttyctx->woy, &ttyctx->wsx,
&ttyctx->wsy))
ttyctx->flags |= TTY_CTX_WINDOW_BIGGER;
else
ttyctx->flags &= ~TTY_CTX_WINDOW_BIGGER;
tty_default_colours(&ttyctx->defaults, wp, active,
&ttyctx->style_ctx.dim);
ttyctx->xoff = ttyctx->rxoff = wp->xoff;
ttyctx->yoff = ttyctx->ryoff = wp->yoff;
@@ -296,7 +299,7 @@ screen_write_initctx(struct screen_write_ctx *ctx, struct tty_ctx *ttyctx,
ttyctx->redraw_cb = screen_write_redraw_cb;
if (ctx->wp != NULL) {
tty_default_colours(&ttyctx->defaults, ctx->wp,
&ttyctx->style_ctx.dim);
ctx->wp->window->active, &ttyctx->style_ctx.dim);
ttyctx->style_ctx.palette = &ctx->wp->palette;
ttyctx->set_client_cb = screen_write_set_client_cb;
ttyctx->arg = ctx->wp;

View File

@@ -505,6 +505,7 @@ server_client_lost(struct client *c)
server_client_attached_lost(c);
events_fire_client("client-detached", c);
}
active_check_clients();
if (c->name != NULL && (c->flags & (CLIENT_CONTROL|CLIENT_TERMINAL)))
events_fire_client("client-closed", c);
@@ -2105,7 +2106,7 @@ server_client_reset_state(struct client *c)
{
struct tty *tty = &c->tty;
struct window *w = active_get_effective_window(c, c->session);
struct window_pane *wp = w->active, *loop;
struct window_pane *wp, *loop;
struct screen *s = NULL;
struct options *oo = c->session->options;
int mode = 0, cursor, flags, pane_mode = 0;
@@ -2113,6 +2114,7 @@ server_client_reset_state(struct client *c)
u_int sb_w;
struct visible_ranges *r;
wp = active_get_effective_pane(c, w);
if (c->flags & (CLIENT_CONTROL|CLIENT_SUSPENDED))
return;
@@ -3074,6 +3076,7 @@ server_client_remove_pane(struct window_pane *wp)
{
struct client *c;
active_remove_pane(wp);
TAILQ_FOREACH(c, &clients, entry) {
if (c->tty.mouse_last_pane == (int)wp->id) {
c->tty.mouse_last_pane = -1;
@@ -3089,6 +3092,7 @@ server_client_print(struct client *c, int parse, struct evbuffer *evb)
{
void *data = EVBUFFER_DATA(evb);
size_t size = EVBUFFER_LENGTH(evb);
struct window *w;
struct window_pane *wp;
struct window_mode_entry *wme;
char *sanitized, *msg, *line, empty = '\0';
@@ -3127,7 +3131,8 @@ server_client_print(struct client *c, int parse, struct evbuffer *evb)
goto out;
}
wp = active_get_effective_window(c, c->session)->active;
w = active_get_effective_window(c, c->session);
wp = active_get_effective_pane(c, w);
wme = TAILQ_FIRST(&wp->modes);
if (wme == NULL || wme->mode != &window_view_mode)
window_pane_set_mode(wp, NULL, &window_view_mode, NULL, NULL,

15
tmux.1
View File

@@ -3981,7 +3981,7 @@ applies the last set layout if possible (undoes the most recent layout change).
spreads the current pane and any panes next to it out evenly.
.Tg selectp
.It Xo Ic select\-pane
.Op Fl DdeLlMmRUZ
.Op Fl ADdeLlMmRsSUZ
.Op Fl T Ar title
.Op Fl t Ar target\-pane
.Xc
@@ -3989,6 +3989,8 @@ spreads the current pane and any panes next to it out evenly.
Make pane
.Ar target\-pane
the active pane in its window.
.Fl A
raises the pane if it is floating.
If one of
.Fl D ,
.Fl L ,
@@ -4003,6 +4005,15 @@ keeps the window zoomed if it was zoomed.
is the same as using the
.Ic last\-pane
command.
.Fl s
switches the client to local pane selection for the target window when more
than one client is attached; the pane currently active for the client is
retained.
Local pane selection is disabled automatically when fewer than two clients
remain attached.
.Fl S
switches the client back to shared pane selection for the target window, so the
window's active pane is used.
.Fl e
enables or
.Fl d
@@ -7326,6 +7337,8 @@ The following variables are available, where appropriate:
.It Li "pane_last" Ta "" Ta "1 if last pane"
.It Li "pane_last_output_time" Ta "" Ta "Time pane last produced output"
.It Li "pane_last_prompt_time" Ta "" Ta "Time most recent OSC 133 prompt began"
.It Li "pane_local_active" Ta "" Ta "1 if active pane is client-local"
.It Li "pane_local_mode" Ta "" Ta "1 if client has local pane selection"
.It Li "pane_left" Ta "" Ta "Left of pane"
.It Li "pane_marked" Ta "" Ta "1 if this is the marked pane"
.It Li "pane_marked_set" Ta "" Ta "1 if a marked pane is set"

17
tmux.h
View File

@@ -2742,13 +2742,13 @@ void events_fire_pane(const char *, struct window_pane *);
void events_fire_winlink(const char *, struct winlink *);
/* active.c */
enum active_window_mode {
enum active_mode {
ACTIVE_SHARED,
ACTIVE_LOCAL
};
int active_is_local_window(struct client *, struct session *);
void active_set_local_window(struct client *, struct session *,
enum active_window_mode);
enum active_mode);
struct winlink *active_get_effective_winlink(struct client *,
struct session *);
struct window *active_get_effective_window(struct client *,
@@ -2766,6 +2766,16 @@ int active_is_effective_window(struct client *, struct session *,
struct winlink *);
int active_is_last_window(struct client *, struct session *,
struct winlink *);
int active_has_local_pane(struct client *, struct window *);
void active_set_pane_mode(struct client *, struct window *,
enum active_mode);
struct window_pane *active_get_effective_pane(struct client *,
struct window *);
struct window_pane *active_get_last_pane(struct client *, struct window *);
int active_set_pane(struct client *, struct window *,
struct window_pane *, int);
void active_check_clients(void);
void active_remove_pane(struct window_pane *);
/* format-draw.c */
void format_draw(struct screen_write_ctx *, const struct grid_cell *,
@@ -2982,7 +2992,8 @@ void tty_cmd_sixelimage(struct tty *, const struct tty_ctx *);
void tty_draw_images(struct client *, struct window_pane *);
#endif
void tty_cmd_syncstart(struct tty *, const struct tty_ctx *);
void tty_default_colours(struct grid_cell *, struct window_pane *, u_int *);
void tty_default_colours(struct grid_cell *, struct window_pane *,
struct window_pane *, u_int *);
/* tty-term.c */
extern struct tty_terms tty_terms;

12
tty.c
View File

@@ -960,9 +960,10 @@ tty_window_offset1(struct tty *tty, u_int *ox, u_int *oy, u_int *sx, u_int *sy)
{
struct client *c = tty->client;
struct window *w = active_get_effective_window(c, c->session);
struct window_pane *wp = w->active;
struct window_pane *wp;
u_int cx, cy, lines;
wp = active_get_effective_pane(c, w);
lines = status_line_size(c);
if (tty->sx >= w->sx && tty->sy - lines >= w->sy) {
@@ -3140,23 +3141,24 @@ tty_style_changed(struct window_pane *wp)
}
void
tty_default_colours(struct grid_cell *gc, struct window_pane *wp, u_int *dim)
tty_default_colours(struct grid_cell *gc, struct window_pane *wp,
struct window_pane *active, u_int *dim)
{
if (wp->flags & PANE_STYLECHANGED)
tty_style_changed (wp);
memcpy(gc, &grid_default_cell, sizeof *gc);
if (wp == wp->window->active && wp->cached_active_gc.fg != 8)
if (wp == active && wp->cached_active_gc.fg != 8)
gc->fg = wp->cached_active_gc.fg;
else
gc->fg = wp->cached_gc.fg;
if (wp == wp->window->active && wp->cached_active_gc.bg != 8)
if (wp == active && wp->cached_active_gc.bg != 8)
gc->bg = wp->cached_active_gc.bg;
else
gc->bg = wp->cached_gc.bg;
if (dim != NULL) {
if (wp == wp->window->active)
if (wp == active)
*dim = wp->cached_active_dim;
else
*dim = wp->cached_dim;

View File

@@ -91,9 +91,14 @@ window_pane_get_border_style(struct window_pane *wp, struct client *c,
struct format_tree *ft;
const char *option;
struct grid_cell *saved;
int *flag;
struct window *w;
struct window_pane *active;
int local, *flag;
if (wp == active_get_effective_window(c, c->session)->active) {
w = active_get_effective_window(c, c->session);
active = active_get_effective_pane(c, w);
local = (wp == active && active_has_local_pane(c, wp->window));
if (wp == active) {
flag = &wp->active_border_gc_set;
saved = &wp->active_border_gc;
option = "pane-active-border-style";
@@ -103,6 +108,13 @@ window_pane_get_border_style(struct window_pane *wp, struct client *c,
option = "pane-border-style";
}
if (local) {
ft = format_create_defaults(NULL, c, s, s->curw, wp);
style_apply(gc, wp->options, option, ft);
format_free(ft);
return;
}
if (!*flag) {
ft = format_create_defaults(NULL, c, s, NULL, wp);
style_apply(saved, wp->options, option, ft);

View File

@@ -795,7 +795,8 @@ window_redraw_active_switch(struct window *w, struct window_pane *wp)
break;
/* If the pane is floating, move to the front. */
if (window_pane_is_floating(wp)) {
if (window_pane_is_floating(wp) &&
TAILQ_FIRST(&w->z_index) != wp) {
TAILQ_REMOVE(&w->z_index, wp, zentry);
TAILQ_INSERT_HEAD(&w->z_index, wp, zentry);
wp->flags |= PANE_REDRAW;
@@ -2578,7 +2579,7 @@ window_pane_get_bg(struct window_pane *wp)
c = window_pane_get_bg_control_client(wp);
if (c == -1) {
tty_default_colours(&defaults, wp, NULL);
tty_default_colours(&defaults, wp, wp->window->active, NULL);
if (COLOUR_DEFAULT(defaults.bg))
c = window_get_bg_client(wp);
else