Merge branch 'master' into screen_redraw

This commit is contained in:
Nicholas Marriott
2026-06-18 11:17:20 +01:00
3 changed files with 123 additions and 35 deletions

111
layout.c
View File

@@ -602,12 +602,57 @@ layout_resize_adjust(struct window *w, struct layout_cell *lc,
} }
} }
/* Find and return the nearest neighbour to a cell in a specific direction. */
static struct layout_cell *
layout_cell_get_neighbour_direction(struct layout_cell *lc, int direction)
{
struct layout_cell *lcn = lc;
while (1) {
if (direction)
lcn = TAILQ_NEXT(lcn, entry);
else
lcn = TAILQ_PREV(lcn, layout_cells, entry);
if (lcn == NULL ||
layout_cell_is_tiled(lcn) ||
layout_cell_has_tiled_child(lcn))
return (lcn);
}
}
/*
* Find and return the nearest neighbour. Prefers cells "after" the specified
* cell. This behavior defines how cell dimensions are redistributed when a cell
* is hidden/shown and floated/tiled.
*/
struct layout_cell *
layout_cell_get_neighbour(struct layout_cell *lc)
{
struct layout_cell *lcother, *lcparent = lc->parent;
int direction = 1;
if (lcparent == NULL)
return (NULL);
if (lc == TAILQ_LAST(&lcparent->cells, layout_cells))
direction = !direction;
lcother = layout_cell_get_neighbour_direction(lc, direction);
if (lcother == NULL)
lcother = layout_cell_get_neighbour_direction(lc, !direction);
return (lcother);
}
/* Destroy a cell and redistribute the space. */ /* Destroy a cell and redistribute the space. */
void void
layout_destroy_cell(struct window *w, struct layout_cell *lc, layout_destroy_cell(struct window *w, struct layout_cell *lc,
struct layout_cell **lcroot) struct layout_cell **lcroot)
{ {
struct layout_cell *lcother = NULL, *lcparent; struct layout_cell *lcother = NULL, *lcparent;
int change;
/* If no parent, this is the last pane in a window. */ /* If no parent, this is the last pane in a window. */
lcparent = lc->parent; lcparent = lc->parent;
@@ -618,27 +663,27 @@ layout_destroy_cell(struct window *w, struct layout_cell *lc,
return; return;
} }
if (~lc->flags & LAYOUT_CELL_FLOATING) { if (!layout_cell_is_tiled(lc)) {
/* Merge the space into the previous or next cell. */ TAILQ_REMOVE(&lcparent->cells, lc, entry);
if (lc == TAILQ_FIRST(&lcparent->cells)) layout_free_cell(lc);
lcother = TAILQ_NEXT(lc, entry); goto out;
}
lcother = layout_cell_get_neighbour(lc);
if (lcother != NULL) {
if (lcparent->type == LAYOUT_LEFTRIGHT)
change = lc->sx + 1;
else else
lcother = TAILQ_PREV(lc, layout_cells, entry); change = lc->sy + 1;
} layout_resize_adjust(w, lcother, lcparent->type, change);
if (lcother != NULL && (~lcother->flags & LAYOUT_CELL_FLOATING)) { } else
if (lcparent->type == LAYOUT_LEFTRIGHT) { layout_remove_tile(w, lcparent);
layout_resize_adjust(w, lcother, lcparent->type,
lc->sx + 1);
} else {
layout_resize_adjust(w, lcother, lcparent->type,
lc->sy + 1);
}
}
/* Remove this from the parent's list. */ /* Remove this from the parent's list. */
TAILQ_REMOVE(&lcparent->cells, lc, entry); TAILQ_REMOVE(&lcparent->cells, lc, entry);
layout_free_cell(lc); layout_free_cell(lc);
out:
/* /*
* If the parent now has one cell, remove the parent from the tree and * If the parent now has one cell, remove the parent from the tree and
* replace it by that cell. * replace it by that cell.
@@ -1587,3 +1632,39 @@ layout_get_floating_cell(struct cmdq_item *item, struct args *args,
lcnew = layout_floating_pane(w, sx, sy, ox, oy); lcnew = layout_floating_pane(w, sx, sy, ox, oy);
return (lcnew); return (lcnew);
} }
/*
* Removes a cell from the tiled layout by giving the cell's space to the
* nearest neighbour.
*/
int
layout_remove_tile(struct window *w, struct layout_cell *lc)
{
struct layout_cell *lcneighbour, *lcparent;
enum layout_type type;
int change;
if (lc->flags & LAYOUT_CELL_FLOATING)
return (0);
lcneighbour = layout_cell_get_neighbour(lc);
if (lcneighbour == NULL) {
if (lc->parent != NULL)
layout_remove_tile(w, lc->parent);
} else if ((lcparent = lcneighbour->parent) != NULL) {
type = lcparent->type;
/*
* Adding the size of the layout cell plus its border to the
* neighbour.
*/
if (type == LAYOUT_TOPBOTTOM)
change = lc->sy + 1;
else
change = lc->sx + 1;
layout_resize_adjust(w, lcneighbour, type, change);
}
/* Zeroing out the cell geometry until the cell is retiled. */
layout_set_size(lc, 0, 0, 0, 0);
return (1);
}

View File

@@ -2015,16 +2015,32 @@ server_client_check_modes(struct client *c)
} }
} }
/* Check if any panes need to be redrawn. */
static int
server_client_any_pane_redraw(struct client *c)
{
struct session *s = c->session;
struct window *w = s->curw->window;
struct window_pane *wp;
if (c->flags & CLIENT_REDRAWWINDOW)
return (1);
TAILQ_FOREACH(wp, &w->panes, entry) {
if (wp->flags & (PANE_REDRAW|PANE_REDRAWSCROLLBAR))
return (1);
}
return (0);
}
/* Check for client redraws. */ /* Check for client redraws. */
static void static void
server_client_check_redraw(struct client *c) server_client_check_redraw(struct client *c)
{ {
struct session *s = c->session; struct session *s = c->session;
struct tty *tty = &c->tty; struct tty *tty = &c->tty;
struct window *w = c->session->curw->window; struct window *w = s->curw->window;
struct window_pane *wp; struct window_pane *wp;
int needed, tflags, mode = tty->mode; int needed, tflags, mode = tty->mode;
uint64_t client_flags = 0;
struct timeval tv = { .tv_usec = 1000 }; struct timeval tv = { .tv_usec = 1000 };
static struct event ev; static struct event ev;
size_t n; size_t n;
@@ -2043,20 +2059,8 @@ server_client_check_redraw(struct client *c)
needed = 0; needed = 0;
if (c->flags & CLIENT_ALLREDRAWFLAGS) if (c->flags & CLIENT_ALLREDRAWFLAGS)
needed = 1; needed = 1;
else { else if (server_client_any_pane_redraw(c))
TAILQ_FOREACH(wp, &w->panes, entry) {
if (wp->flags & PANE_REDRAW) {
needed = 1; needed = 1;
client_flags |= CLIENT_REDRAWWINDOW;
break;
}
if (wp->flags & PANE_REDRAWSCROLLBAR) {
needed = 1;
client_flags |= CLIENT_REDRAWWINDOW;
/* no break - later panes may need redraw */
}
}
}
if (!needed) { if (!needed) {
c->flags &= ~CLIENT_STATUSFORCE; c->flags &= ~CLIENT_STATUSFORCE;
return; return;
@@ -2079,7 +2083,8 @@ server_client_check_redraw(struct client *c)
log_debug("redraw timer started"); log_debug("redraw timer started");
evtimer_add(&ev, &tv); evtimer_add(&ev, &tv);
} }
c->flags |= client_flags; if (server_client_any_pane_redraw(c))
c->flags |= CLIENT_REDRAWWINDOW;
return; return;
} }

6
tmux.h
View File

@@ -3551,6 +3551,7 @@ void layout_fix_offsets(struct window *);
void layout_fix_panes(struct window *, struct window_pane *); void layout_fix_panes(struct window *, struct window_pane *);
void layout_resize_adjust(struct window *, struct layout_cell *, void layout_resize_adjust(struct window *, struct layout_cell *,
enum layout_type, int); enum layout_type, int);
struct layout_cell *layout_cell_get_neighbour(struct layout_cell *);
void layout_init(struct window *, struct window_pane *); void layout_init(struct window *, struct window_pane *);
void layout_free(struct window *); void layout_free(struct window *);
void layout_resize(struct window *, u_int, u_int); void layout_resize(struct window *, u_int, u_int);
@@ -3571,10 +3572,11 @@ struct layout_cell *layout_floating_pane(struct window *, u_int, u_int, int,
void layout_close_pane(struct window_pane *); void layout_close_pane(struct window_pane *);
int layout_spread_cell(struct window *, struct layout_cell *); int layout_spread_cell(struct window *, struct layout_cell *);
void layout_spread_out(struct window_pane *); void layout_spread_out(struct window_pane *);
struct layout_cell *layout_get_floating_cell(struct cmdq_item *, struct args *,
struct window *, struct window_pane *, char **);
struct layout_cell *layout_get_tiled_cell(struct cmdq_item *, struct args *, struct layout_cell *layout_get_tiled_cell(struct cmdq_item *, struct args *,
struct window *, struct window_pane *, int, char **); struct window *, struct window_pane *, int, char **);
struct layout_cell *layout_get_floating_cell(struct cmdq_item *, struct args *,
struct window *, struct window_pane *, char **);
int layout_remove_tile(struct window *, struct layout_cell *);
/* layout-custom.c */ /* layout-custom.c */
char *layout_dump(struct window *, struct layout_cell *); char *layout_dump(struct window *, struct layout_cell *);