mirror of
https://github.com/tmux/tmux.git
synced 2026-08-03 14:08:59 +00:00
Merge branch 'master' into 5211-fix-select-layout-list-windows
This commit is contained in:
@@ -251,10 +251,10 @@ cmd_resize_pane_mouse_resize_move_floating(struct client *c,
|
||||
sb_pos = options_get_number(w->options, "pane-scrollbars-position");
|
||||
left = wp->xoff - 1;
|
||||
right = wp->xoff + sx;
|
||||
if (window_pane_show_scrollbar(wp, scrollbars) &&
|
||||
if (window_pane_scrollbar_reserve(wp, scrollbars) &&
|
||||
sb_pos == PANE_SCROLLBARS_LEFT) {
|
||||
left -= wp->scrollbar_style.width + wp->scrollbar_style.pad;
|
||||
} else if (window_pane_show_scrollbar(wp, scrollbars) &&
|
||||
} else if (window_pane_scrollbar_reserve(wp, scrollbars) &&
|
||||
sb_pos == PANE_SCROLLBARS_RIGHT) {
|
||||
right += wp->scrollbar_style.width + wp->scrollbar_style.pad;
|
||||
}
|
||||
|
||||
@@ -40,8 +40,8 @@ const struct cmd_entry cmd_new_pane_entry = {
|
||||
|
||||
.args = { "bB:c:de:EfF:hIkl:Lm:p:PR:s:S:t:T:vWx:X:y:Y:Z", 0, -1, NULL },
|
||||
.usage = "[-bdefhIklPvWZ] [-B border-lines] "
|
||||
"[-c start-directory] [-e environment] "
|
||||
"[-F format] [-l size] [-m message] [-p percentage] "
|
||||
"[-c start-directory] [-e environment] "
|
||||
"[-F format] [-l size] [-m message] [-p percentage] "
|
||||
"[-s style] [-S active-border-style] "
|
||||
"[-R inactive-border-style] [-T title] [-x width] [-y height] "
|
||||
"[-X x-position] [-Y y-position] " CMD_TARGET_PANE_USAGE " "
|
||||
@@ -95,7 +95,7 @@ cmd_split_window_exec(struct cmd *self, struct cmdq_item *item)
|
||||
if (cmd_get_entry(self) == &cmd_new_pane_entry)
|
||||
is_floating = !args_has(args, 'L');
|
||||
else
|
||||
is_floating = 0;
|
||||
is_floating = window_pane_is_floating(wp);
|
||||
|
||||
flags = is_floating ? SPAWN_FLOATING : 0;
|
||||
if (args_has(args, 'b'))
|
||||
|
||||
49
grid.c
49
grid.c
@@ -18,6 +18,9 @@
|
||||
|
||||
#include <sys/types.h>
|
||||
|
||||
#ifdef __APPLE__
|
||||
#include <assert.h>
|
||||
#endif
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
@@ -56,6 +59,28 @@ static const struct grid_cell_entry grid_cleared_entry = {
|
||||
{ .data = { 0, 8, 8, ' ' } }, GRID_FLAG_CLEARED
|
||||
};
|
||||
|
||||
#ifdef __APPLE__
|
||||
static void
|
||||
grid_check_lines(struct grid *gd)
|
||||
{
|
||||
u_int i, j;
|
||||
|
||||
for (i = 0; i < gd->hsize + gd->sy; i++) {
|
||||
for (j = i + 1; j < gd->hsize + gd->sy; j++) {
|
||||
if (gd->linedata[i].celldata != NULL)
|
||||
assert(gd->linedata[i].celldata != gd->linedata[j].celldata);
|
||||
if (gd->linedata[i].extddata != NULL)
|
||||
assert(gd->linedata[i].extddata != gd->linedata[j].extddata);
|
||||
}
|
||||
}
|
||||
}
|
||||
#else
|
||||
static void
|
||||
grid_check_lines(__unused struct grid *gd)
|
||||
{
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Store cell in entry. */
|
||||
static void
|
||||
grid_store_cell(struct grid_cell_entry *gce, const struct grid_cell *gc,
|
||||
@@ -287,9 +312,17 @@ grid_set_tab(struct grid_cell *gc, u_int width)
|
||||
static void
|
||||
grid_free_line(struct grid *gd, u_int py)
|
||||
{
|
||||
free(gd->linedata[py].celldata);
|
||||
free(gd->linedata[py].extddata);
|
||||
memset(&gd->linedata[py], 0, sizeof gd->linedata[py]);
|
||||
struct grid_line *gl = &gd->linedata[py];
|
||||
|
||||
#ifdef __APPLE__
|
||||
assert(gl->cellused <= gl->cellsize);
|
||||
assert(gl->extdsize == 0 || gl->extddata != NULL);
|
||||
assert(gl->cellsize == 0 || gl->celldata != NULL);
|
||||
#endif
|
||||
|
||||
free(gl->celldata);
|
||||
free(gl->extddata);
|
||||
memset(gl, 0, sizeof *gl);
|
||||
}
|
||||
|
||||
/* Free several lines. */
|
||||
@@ -449,6 +482,8 @@ grid_scroll_history(struct grid *gd, u_int bg)
|
||||
gd->linedata[gd->hsize].time = current_time;
|
||||
gd->hsize++;
|
||||
gd->scroll_added++;
|
||||
|
||||
grid_check_lines(gd);
|
||||
}
|
||||
|
||||
/* Clear the history. */
|
||||
@@ -498,6 +533,8 @@ grid_scroll_history_region(struct grid *gd, u_int upper, u_int lower, u_int bg)
|
||||
gd->hscrolled++;
|
||||
gd->hsize++;
|
||||
gd->scroll_added++;
|
||||
|
||||
grid_check_lines(gd);
|
||||
}
|
||||
|
||||
/* Expand line to fit to cell. */
|
||||
@@ -759,6 +796,8 @@ grid_move_lines(struct grid *gd, u_int dy, u_int py, u_int ny, u_int bg)
|
||||
}
|
||||
if (py != 0 && (py < dy || py >= dy + ny))
|
||||
gd->linedata[py - 1].flags &= ~GRID_LINE_WRAPPED;
|
||||
|
||||
grid_check_lines(gd);
|
||||
}
|
||||
|
||||
/* Move a group of cells. */
|
||||
@@ -1248,6 +1287,8 @@ grid_duplicate_lines(struct grid *dst, u_int dy, struct grid *src, u_int sy,
|
||||
sy++;
|
||||
dy++;
|
||||
}
|
||||
|
||||
grid_check_lines(dst);
|
||||
}
|
||||
|
||||
/* Mark line as dead. */
|
||||
@@ -1544,6 +1585,8 @@ grid_reflow(struct grid *gd, u_int sx)
|
||||
gd->linedata = target->linedata;
|
||||
free(target);
|
||||
gd->scroll_generation++;
|
||||
|
||||
grid_check_lines(gd);
|
||||
}
|
||||
|
||||
/* Convert to position based on wrapped lines. */
|
||||
|
||||
@@ -41,6 +41,7 @@
|
||||
*/
|
||||
|
||||
#define MAX_HYPERLINKS 5000
|
||||
#define MAX_HYPERLINK_URI 1024
|
||||
|
||||
static long long hyperlinks_next_external_id = 1;
|
||||
static u_int global_hyperlinks_count;
|
||||
@@ -145,9 +146,13 @@ hyperlinks_put(struct hyperlinks *hl, const char *uri_in,
|
||||
internal_id_in = "";
|
||||
|
||||
utf8_stravis(&uri, uri_in, VIS_OCTAL|VIS_CSTYLE);
|
||||
utf8_stravis(&internal_id, internal_id_in, VIS_OCTAL|VIS_CSTYLE);
|
||||
if (strlen(uri) > MAX_HYPERLINK_URI) {
|
||||
free(uri);
|
||||
return (0);
|
||||
}
|
||||
|
||||
if (*internal_id_in != '\0') {
|
||||
utf8_stravis(&internal_id, internal_id_in, VIS_OCTAL|VIS_CSTYLE);
|
||||
if (*internal_id != '\0') {
|
||||
find.uri = uri;
|
||||
find.internal_id = internal_id;
|
||||
|
||||
|
||||
@@ -586,7 +586,7 @@ sixel_print(struct sixel_image *si, struct sixel_image *map, size_t *size)
|
||||
len = 8192;
|
||||
buf = xmalloc(len);
|
||||
|
||||
tmplen = xsnprintf(tmp, sizeof tmp, "\033P0;%uq", si->p2);
|
||||
tmplen = xsnprintf(tmp, sizeof tmp, "\033P9;%uq", si->p2);
|
||||
sixel_print_add(&buf, &len, &used, tmp, tmplen);
|
||||
|
||||
if (si->set_ra) {
|
||||
|
||||
280
layout.c
280
layout.c
@@ -31,8 +31,9 @@
|
||||
* a cell which contains a list of cells, and 'leaf' to refer to a cell that
|
||||
* contains a window pane. A leaf is considered to be 'tiled' if it is to be
|
||||
* drawn as a part of the tiled layout. A 'neighbour' is a sibling that is also
|
||||
* tiled. A cell's 'split' size refers to the side that is shortened when
|
||||
* splitting it, determined by the parent's type.
|
||||
* tiled or a node that contains a tiled leaf in a subtree. A cell's 'split'
|
||||
* size refers to the side that is shortened when splitting it, determined by
|
||||
* the parent's type.
|
||||
*
|
||||
* Each window has a pointer to the root of its layout tree (containing its
|
||||
* panes), every pane has a pointer back to the cell containing it, and each
|
||||
@@ -298,6 +299,27 @@ layout_cell_is_first_tiled(struct layout_cell *lc)
|
||||
return (lcchild == lc);
|
||||
}
|
||||
|
||||
static struct layout_cell *
|
||||
layout_cell_get_first_tiled(struct layout_cell *lc)
|
||||
{
|
||||
struct layout_cell *lcchild, *lcchild2;
|
||||
|
||||
if (layout_cell_is_tiled(lc))
|
||||
return (lc);
|
||||
if (lc->type == LAYOUT_WINDOWPANE)
|
||||
return (NULL);
|
||||
|
||||
TAILQ_FOREACH(lcchild, &lc->cells, entry) {
|
||||
if (layout_cell_is_tiled(lcchild))
|
||||
return (lcchild);
|
||||
if (lcchild->type != LAYOUT_WINDOWPANE) {
|
||||
lcchild2 = layout_cell_get_first_tiled(lcchild);
|
||||
if (lcchild2 != NULL)
|
||||
return (lcchild2);
|
||||
}
|
||||
}
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
/* Fix cell offsets for a child cell. */
|
||||
static void
|
||||
@@ -442,7 +464,7 @@ layout_fix_panes(struct window *w, struct window_pane *skip)
|
||||
sy--;
|
||||
}
|
||||
|
||||
if (window_pane_show_scrollbar(wp, scrollbars)) {
|
||||
if (window_pane_scrollbar_reserve(wp, scrollbars)) {
|
||||
sb_w = wp->scrollbar_style.width;
|
||||
sb_pad = wp->scrollbar_style.pad;
|
||||
if (sb_w < 1)
|
||||
@@ -515,7 +537,7 @@ layout_resize_check(struct window *w, struct layout_cell *lc,
|
||||
/* Space available in this cell only. */
|
||||
if (type == LAYOUT_LEFTRIGHT) {
|
||||
available = lc->sx;
|
||||
if (scrollbars)
|
||||
if (scrollbars == PANE_SCROLLBARS_ALWAYS)
|
||||
minimum = PANE_MINIMUM + sb_style->width +
|
||||
sb_style->pad;
|
||||
else
|
||||
@@ -611,6 +633,20 @@ layout_resize_adjust(struct window *w, struct layout_cell *lc,
|
||||
}
|
||||
}
|
||||
|
||||
/* Resizes a cell to a specified size */
|
||||
void
|
||||
layout_resize_set_size(struct window *w, struct layout_cell *lc,
|
||||
enum layout_type type, u_int size)
|
||||
{
|
||||
int change;
|
||||
|
||||
if (type == LAYOUT_LEFTRIGHT)
|
||||
change = size - lc->sx;
|
||||
else
|
||||
change = size - lc->sy;
|
||||
layout_resize_adjust(w, lc, type, change);
|
||||
}
|
||||
|
||||
/* 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)
|
||||
@@ -1186,6 +1222,101 @@ layout_resize_child_cells(struct window *w, struct layout_cell *lc)
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Replaces the provided layout cell with a new node of the specified type and
|
||||
* inserts the cell into it. Used when creating new cells requires a different
|
||||
* layout type, or when the root layout is a window pane.
|
||||
*/
|
||||
struct layout_cell *
|
||||
layout_replace_with_node(struct window *w, struct layout_cell *lc,
|
||||
enum layout_type type)
|
||||
{
|
||||
struct layout_cell *lcparent;
|
||||
|
||||
lcparent = layout_create_cell(lc->parent);
|
||||
layout_make_node(lcparent, type);
|
||||
layout_set_size(lcparent, lc->sx, lc->sy, lc->xoff, lc->yoff);
|
||||
if (lc->parent == NULL)
|
||||
w->layout_root = lcparent;
|
||||
else
|
||||
TAILQ_REPLACE(&lc->parent->cells, lc, lcparent, entry);
|
||||
|
||||
/* Insert the old cell. */
|
||||
lc->parent = lcparent;
|
||||
TAILQ_INSERT_HEAD(&lcparent->cells, lc, entry);
|
||||
|
||||
return (lcparent);
|
||||
}
|
||||
|
||||
/* Checks if there is enough space for two new panes. */
|
||||
int
|
||||
layout_split_check_space(struct window_pane *wp, struct layout_cell *lc,
|
||||
enum layout_type type)
|
||||
{
|
||||
struct style *sb_style = &wp->scrollbar_style;
|
||||
u_int minimum, sx = lc->sx, sy = lc->sy;
|
||||
int scrollbars, status;
|
||||
|
||||
if (lc->flags & LAYOUT_CELL_FLOATING)
|
||||
fatalx("floating cells cannot be split");
|
||||
|
||||
status = window_get_pane_status(wp->window);
|
||||
scrollbars = options_get_number(wp->window->options, "pane-scrollbars");
|
||||
|
||||
switch (type) {
|
||||
case LAYOUT_LEFTRIGHT:
|
||||
if (scrollbars == PANE_SCROLLBARS_ALWAYS) {
|
||||
minimum = PANE_MINIMUM * 2 + sb_style->width +
|
||||
sb_style->pad;
|
||||
} else
|
||||
minimum = PANE_MINIMUM * 2 + 1;
|
||||
if (sx < minimum)
|
||||
return (0);
|
||||
break;
|
||||
case LAYOUT_TOPBOTTOM:
|
||||
if (layout_add_horizontal_border(wp->window, lc, status))
|
||||
minimum = PANE_MINIMUM * 2 + 2;
|
||||
else
|
||||
minimum = PANE_MINIMUM * 2 + 1;
|
||||
if (sy < minimum)
|
||||
return (0);
|
||||
break;
|
||||
default:
|
||||
fatalx("bad layout type");
|
||||
}
|
||||
|
||||
return (1);
|
||||
}
|
||||
|
||||
/* Calculates the new cell sizes when splitting a pane. */
|
||||
void
|
||||
layout_split_sizes(struct layout_cell *lc, int size, int before,
|
||||
enum layout_type type, u_int *size1, u_int *size2, u_int *saved_size)
|
||||
{
|
||||
u_int s1, s2, ss;
|
||||
u_int sx = lc->sx, sy = lc->sy;
|
||||
|
||||
if (type == LAYOUT_LEFTRIGHT)
|
||||
ss = sx;
|
||||
else
|
||||
ss = sy;
|
||||
if (size < 0)
|
||||
s2 = ((ss + 1) / 2) - 1;
|
||||
else if (before)
|
||||
s2 = ss - size - 1;
|
||||
else
|
||||
s2 = size;
|
||||
if (s2 < PANE_MINIMUM)
|
||||
s2 = PANE_MINIMUM;
|
||||
else if (s2 > sx - 2)
|
||||
s2 = ss - 2;
|
||||
s1 = ss - 1 - s2;
|
||||
|
||||
*size1 = s1;
|
||||
*size2 = s2;
|
||||
*saved_size = ss;
|
||||
}
|
||||
|
||||
/*
|
||||
* Split a pane into two. size is a hint, or -1 for default half/half
|
||||
* split. This must be followed by layout_assign_pane before much else happens!
|
||||
@@ -1195,11 +1326,10 @@ layout_split_pane(struct window_pane *wp, enum layout_type type, int size,
|
||||
int flags)
|
||||
{
|
||||
struct layout_cell *lc, *lcparent, *lcnew, *lc1, *lc2;
|
||||
struct style *sb_style = &wp->scrollbar_style;
|
||||
u_int sx, sy, xoff, yoff, size1, size2, minimum;
|
||||
u_int sx, sy, xoff, yoff, size1, size2;
|
||||
u_int new_size, saved_size, resize_first = 0;
|
||||
int full_size = (flags & SPAWN_FULLSIZE), status;
|
||||
int scrollbars;
|
||||
int full_size = (flags & SPAWN_FULLSIZE);
|
||||
int before = (flags & SPAWN_BEFORE);
|
||||
|
||||
/*
|
||||
* If full_size is specified, add a new cell at the top of the window
|
||||
@@ -1209,8 +1339,6 @@ layout_split_pane(struct window_pane *wp, enum layout_type type, int size,
|
||||
lc = wp->window->layout_root;
|
||||
else
|
||||
lc = wp->layout_cell;
|
||||
status = window_get_pane_status(wp->window);
|
||||
scrollbars = options_get_number(wp->window->options, "pane-scrollbars");
|
||||
|
||||
/* Copy the old cell size. */
|
||||
sx = lc->sx;
|
||||
@@ -1219,47 +1347,14 @@ layout_split_pane(struct window_pane *wp, enum layout_type type, int size,
|
||||
yoff = lc->yoff;
|
||||
|
||||
/* Check there is enough space for the two new panes. */
|
||||
switch (type) {
|
||||
case LAYOUT_LEFTRIGHT:
|
||||
if (scrollbars) {
|
||||
minimum = PANE_MINIMUM * 2 + sb_style->width +
|
||||
sb_style->pad;
|
||||
} else
|
||||
minimum = PANE_MINIMUM * 2 + 1;
|
||||
if (sx < minimum)
|
||||
return (NULL);
|
||||
break;
|
||||
case LAYOUT_TOPBOTTOM:
|
||||
if (layout_add_horizontal_border(wp->window, lc, status))
|
||||
minimum = PANE_MINIMUM * 2 + 2;
|
||||
else
|
||||
minimum = PANE_MINIMUM * 2 + 1;
|
||||
if (sy < minimum)
|
||||
return (NULL);
|
||||
break;
|
||||
default:
|
||||
fatalx("bad layout type");
|
||||
}
|
||||
if (!layout_split_check_space(wp, lc, type))
|
||||
return (NULL);
|
||||
|
||||
/*
|
||||
* Calculate new cell sizes. size is the target size or -1 for middle
|
||||
* split, size1 is the size of the top/left and size2 the bottom/right.
|
||||
*/
|
||||
if (type == LAYOUT_LEFTRIGHT)
|
||||
saved_size = sx;
|
||||
else
|
||||
saved_size = sy;
|
||||
if (size < 0)
|
||||
size2 = ((saved_size + 1) / 2) - 1;
|
||||
else if (flags & SPAWN_BEFORE)
|
||||
size2 = saved_size - size - 1;
|
||||
else
|
||||
size2 = size;
|
||||
if (size2 < PANE_MINIMUM)
|
||||
size2 = PANE_MINIMUM;
|
||||
else if (size2 > saved_size - 2)
|
||||
size2 = saved_size - 2;
|
||||
size1 = saved_size - 1 - size2;
|
||||
layout_split_sizes(lc, size, before, type, &size1, &size2, &saved_size);
|
||||
|
||||
/* Which size are we using? */
|
||||
if (flags & SPAWN_BEFORE)
|
||||
@@ -1317,17 +1412,7 @@ layout_split_pane(struct window_pane *wp, enum layout_type type, int size,
|
||||
*/
|
||||
|
||||
/* Create and insert the replacement parent. */
|
||||
lcparent = layout_create_cell(lc->parent);
|
||||
layout_make_node(lcparent, type);
|
||||
layout_set_size(lcparent, sx, sy, xoff, yoff);
|
||||
if (lc->parent == NULL)
|
||||
wp->window->layout_root = lcparent;
|
||||
else
|
||||
TAILQ_REPLACE(&lc->parent->cells, lc, lcparent, entry);
|
||||
|
||||
/* Insert the old cell. */
|
||||
lc->parent = lcparent;
|
||||
TAILQ_INSERT_HEAD(&lcparent->cells, lc, entry);
|
||||
lcparent = layout_replace_with_node(wp->window, lc, type);
|
||||
|
||||
/* Create the new child cell. */
|
||||
lcnew = layout_create_cell(lcparent);
|
||||
@@ -1386,14 +1471,7 @@ layout_floating_pane(struct window *w, struct window_pane *wp, u_int sx,
|
||||
* Adding a pane to a root that isn't node. Must create and
|
||||
* insert a new root.
|
||||
*/
|
||||
lcparent = layout_create_cell(NULL);
|
||||
layout_make_node(lcparent, LAYOUT_TOPBOTTOM);
|
||||
layout_set_size(lcparent, w->sx, w->sy, 0, 0);
|
||||
w->layout_root = lcparent;
|
||||
|
||||
/* Insert the old cell. */
|
||||
lc->parent = lcparent;
|
||||
TAILQ_INSERT_HEAD(&lcparent->cells, lc, entry);
|
||||
lcparent = layout_replace_with_node(w, lc, LAYOUT_TOPBOTTOM);
|
||||
}
|
||||
|
||||
lcnew = layout_create_cell(lcparent);
|
||||
@@ -1714,7 +1792,75 @@ layout_remove_tile(struct window *w, struct layout_cell *lc)
|
||||
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);
|
||||
/*
|
||||
* Zeroing out the cell geometry until the cell is retiled unless this
|
||||
* is the top level node.
|
||||
*/
|
||||
if (lc->parent != NULL)
|
||||
layout_set_size(lc, 0, 0, 0, 0);
|
||||
return (1);
|
||||
}
|
||||
|
||||
/*
|
||||
* Inserts a cell back into the tiled layout by taking half the space from its
|
||||
* nearest neighbour.
|
||||
*/
|
||||
int
|
||||
layout_insert_tile(struct window *w, struct layout_cell *lc)
|
||||
{
|
||||
struct layout_cell *lcneighbour, *lctiled, *lcparent;
|
||||
enum layout_type type;
|
||||
u_int size1, size2, saved_size;
|
||||
|
||||
if (lc == NULL)
|
||||
fatalx("layout cell cannot be null when tiling");
|
||||
|
||||
lcparent = lc->parent;
|
||||
if (lc->flags & LAYOUT_CELL_FLOATING)
|
||||
return (1);
|
||||
|
||||
if (lcparent == NULL) {
|
||||
/* Only pane in the layout. */
|
||||
layout_set_size(lc, w->sx, w->sy, 0, 0);
|
||||
return (1);
|
||||
}
|
||||
|
||||
type = lcparent->type;
|
||||
lcneighbour = layout_cell_get_neighbour(lc);
|
||||
if (lcneighbour == NULL) {
|
||||
/*
|
||||
* This will become the only visible cell in the parent.
|
||||
* Tile the parent, then set the child's 'split' size.
|
||||
*/
|
||||
layout_insert_tile(w, lcparent);
|
||||
if (type == LAYOUT_LEFTRIGHT)
|
||||
size1 = lcparent->sx;
|
||||
else
|
||||
size1 = lcparent->sy;
|
||||
layout_resize_set_size(w, lc, type, size1);
|
||||
} else {
|
||||
/*
|
||||
* If the neighbour is a node, a tiled child in the subtree of
|
||||
* the neighbour is needed to check for space.
|
||||
*/
|
||||
lctiled = layout_cell_get_first_tiled(lcneighbour);
|
||||
if (!layout_split_check_space(lctiled->wp, lcneighbour, type))
|
||||
return (0);
|
||||
layout_split_sizes(lcneighbour, -1, 0, type, &size1, &size2,
|
||||
&saved_size);
|
||||
layout_resize_set_size(w, lc, type, size1);
|
||||
layout_resize_set_size(w, lcneighbour, type, size2);
|
||||
}
|
||||
|
||||
/* Setting opposite of the 'split' size to that of the parent. */
|
||||
if (lcparent->type == LAYOUT_LEFTRIGHT) {
|
||||
size1 = lcparent->sy;
|
||||
type = LAYOUT_TOPBOTTOM;
|
||||
} else {
|
||||
size1 = lcparent->sx;
|
||||
type = LAYOUT_LEFTRIGHT;
|
||||
}
|
||||
layout_resize_set_size(w, lc, type, size1);
|
||||
|
||||
return (1);
|
||||
}
|
||||
|
||||
@@ -64,7 +64,7 @@ static const char *options_table_cursor_style_list[] = {
|
||||
"blinking-bar", "bar", NULL
|
||||
};
|
||||
static const char *options_table_pane_scrollbars_list[] = {
|
||||
"off", "modal", "on", NULL
|
||||
"off", "modal", "on", "auto-hide", NULL
|
||||
};
|
||||
static const char *options_table_pane_scrollbars_position_list[] = {
|
||||
"right", "left", NULL
|
||||
@@ -1594,7 +1594,17 @@ const struct options_table_entry options_table[] = {
|
||||
.scope = OPTIONS_TABLE_WINDOW,
|
||||
.choices = options_table_pane_scrollbars_list,
|
||||
.default_num = PANE_SCROLLBARS_OFF,
|
||||
.text = "Pane scrollbar state."
|
||||
.text = "Pane scrollbar state: off, on, modal, or auto-hide."
|
||||
},
|
||||
|
||||
{ .name = "pane-scrollbars-timeout",
|
||||
.type = OPTIONS_TABLE_NUMBER,
|
||||
.scope = OPTIONS_TABLE_WINDOW,
|
||||
.minimum = 0,
|
||||
.maximum = INT_MAX,
|
||||
.default_num = 500,
|
||||
.unit = "milliseconds",
|
||||
.text = "Time before modal and auto-hide pane scrollbars disappear."
|
||||
},
|
||||
|
||||
{ .name = "pane-scrollbars-style",
|
||||
|
||||
@@ -1264,6 +1264,7 @@ options_push_changes(const char *name)
|
||||
strcmp(name, "pane-border-lines") == 0 ||
|
||||
strcmp(name, "pane-border-status") == 0 ||
|
||||
strcmp(name, "pane-scrollbars") == 0 ||
|
||||
strcmp(name, "pane-scrollbars-timeout") == 0 ||
|
||||
strcmp(name, "pane-scrollbars-position") == 0 ||
|
||||
strcmp(name, "pane-scrollbars-style") == 0)
|
||||
redraw_invalidate_all_scenes();
|
||||
@@ -1288,6 +1289,10 @@ options_push_changes(const char *name)
|
||||
RB_FOREACH(w, windows, &windows)
|
||||
layout_fix_panes(w, NULL);
|
||||
}
|
||||
if (strcmp(name, "pane-scrollbars") == 0) {
|
||||
RB_FOREACH(wp, window_pane_tree, &all_window_panes)
|
||||
window_pane_scrollbar_hide(wp);
|
||||
}
|
||||
if (strcmp(name, "pane-scrollbars-style") == 0) {
|
||||
RB_FOREACH(wp, window_pane_tree, &all_window_panes) {
|
||||
style_set_scrollbar_style_from_option(
|
||||
|
||||
@@ -110,20 +110,26 @@ must_fail $TMUX set-buffer -b "bad${invalid}name" data
|
||||
# Titles set by commands allow '#', ':' and '.'.
|
||||
$TMUX select-pane -T 'title#:.ok' || fail "command title rejected"
|
||||
must_equal "$($TMUX display-message -p '#{pane_title}')" 'title#:.ok'
|
||||
$TMUX send-keys "printf '\\033]2;title#[fg=red]ok\\007'" Enter || exit 1
|
||||
sleep 1
|
||||
must_equal "$($TMUX display-message -p '#{pane_title}')" 'title#[fg=red]ok'
|
||||
$TMUX send-keys "printf '\\033]2;title#(bad)\\007'" Enter || exit 1
|
||||
sleep 1
|
||||
must_equal "$($TMUX display-message -p '#{pane_title}')" 'title_(bad)'
|
||||
|
||||
# Buffer names allow '#', ':' and '.'.
|
||||
$TMUX set-buffer -b 'buffer#:.ok' data || fail "buffer name rejected"
|
||||
must_equal "$($TMUX list-buffers -F '#{buffer_name}')" 'buffer#:.ok'
|
||||
|
||||
# Window names from escape sequences reject '#', ':' and '.' by cleaning them.
|
||||
# Window names from escape sequences allow '#' except in '#('.
|
||||
$TMUX send-keys "printf '\\033kescape#:.ok\\033\\\\'" Enter || exit 1
|
||||
sleep 1
|
||||
must_equal "$($TMUX display-message -p '#{window_name}')" 'escape___ok'
|
||||
must_equal "$($TMUX display-message -p '#{window_name}')" 'escape#__ok'
|
||||
|
||||
# Titles from escape sequences reject only '#'.
|
||||
$TMUX send-keys "printf '\\033]2;escape#:.ok\\007'" Enter || exit 1
|
||||
sleep 1
|
||||
must_equal "$($TMUX display-message -p '#{pane_title}')" 'escape_:.ok'
|
||||
must_equal "$($TMUX display-message -p '#{pane_title}')" 'escape#:.ok'
|
||||
|
||||
# Invalid UTF-8 from escape sequences is ignored.
|
||||
$TMUX rename-window 'before-invalid' || exit 1
|
||||
|
||||
3
regsub.c
3
regsub.c
@@ -24,7 +24,8 @@
|
||||
#include "tmux.h"
|
||||
|
||||
static void
|
||||
regsub_copy(char **buf, ssize_t *len, const char *text, size_t start, size_t end)
|
||||
regsub_copy(char **buf, ssize_t *len, const char *text, size_t start,
|
||||
size_t end)
|
||||
{
|
||||
size_t add = end - start;
|
||||
|
||||
|
||||
@@ -81,6 +81,7 @@ enum redraw_span_type {
|
||||
#define REDRAW_BORDER_IS_ARROW 0x1
|
||||
#define REDRAW_SCROLLBAR_LEFT 0x2
|
||||
#define REDRAW_SCROLLBAR_RIGHT 0x4
|
||||
#define REDRAW_SCROLLBAR_OVERLAY 0x8
|
||||
|
||||
/* Draw operations. */
|
||||
#define REDRAW_PANE 0x1
|
||||
@@ -447,7 +448,7 @@ redraw_mark_pane_inside(struct redraw_build_ctx *bctx, struct window_pane *wp)
|
||||
/* Mark scrollbar data. */
|
||||
static void
|
||||
redraw_mark_pane_scrollbar(struct redraw_build_ctx *bctx,
|
||||
struct window_pane *wp, int sb_w, int sb_left)
|
||||
struct window_pane *wp, int sb_w, int sb_left, int overlay)
|
||||
{
|
||||
struct redraw_build_cell *bc;
|
||||
u_int x, y;
|
||||
@@ -457,7 +458,13 @@ redraw_mark_pane_scrollbar(struct redraw_build_ctx *bctx,
|
||||
if (sb_w == 0)
|
||||
return;
|
||||
|
||||
if (sb_left) {
|
||||
if (overlay && sb_left) {
|
||||
sx = wp->xoff;
|
||||
ex = sx + sb_w - 1;
|
||||
} else if (overlay) {
|
||||
ex = wp->xoff + (int)wp->sx - 1;
|
||||
sx = ex - sb_w + 1;
|
||||
} else if (sb_left) {
|
||||
sx = wp->xoff - sb_w;
|
||||
ex = wp->xoff - 1;
|
||||
} else {
|
||||
@@ -481,6 +488,8 @@ redraw_mark_pane_scrollbar(struct redraw_build_ctx *bctx,
|
||||
bc->data.sb.flags |= REDRAW_SCROLLBAR_LEFT;
|
||||
else
|
||||
bc->data.sb.flags |= REDRAW_SCROLLBAR_RIGHT;
|
||||
if (overlay)
|
||||
bc->data.sb.flags |= REDRAW_SCROLLBAR_OVERLAY;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -755,19 +764,30 @@ redraw_mark_pane_borders(struct redraw_build_ctx *bctx, struct window_pane *wp,
|
||||
static void
|
||||
redraw_mark_pane(struct redraw_build_ctx *bctx, struct window_pane *wp)
|
||||
{
|
||||
int sb_w = 0, sb_left = 0;
|
||||
int sb_w = 0, sb_left = 0, overlay = 0;
|
||||
|
||||
if (!window_pane_is_visible(wp))
|
||||
return;
|
||||
|
||||
if (window_pane_show_scrollbar(wp, bctx->sb))
|
||||
sb_w = wp->scrollbar_style.width + wp->scrollbar_style.pad;
|
||||
if (window_pane_scrollbar_visible(wp, bctx->sb)) {
|
||||
overlay = window_pane_scrollbar_overlay(wp, bctx->sb);
|
||||
if (overlay) {
|
||||
sb_w = wp->scrollbar_style.width +
|
||||
wp->scrollbar_style.pad;
|
||||
if (sb_w > (int)wp->sx) {
|
||||
sb_w = wp->scrollbar_style.width;
|
||||
if (sb_w > (int)wp->sx)
|
||||
sb_w = wp->sx;
|
||||
}
|
||||
} else
|
||||
sb_w = wp->scrollbar_style.width + wp->scrollbar_style.pad;
|
||||
}
|
||||
if (sb_w != 0 && bctx->sbp == PANE_SCROLLBARS_LEFT)
|
||||
sb_left = 1;
|
||||
|
||||
redraw_mark_pane_inside(bctx, wp);
|
||||
redraw_mark_pane_borders(bctx, wp, sb_w, sb_left);
|
||||
redraw_mark_pane_scrollbar(bctx, wp, sb_w, sb_left);
|
||||
redraw_mark_pane_borders(bctx, wp, overlay ? 0 : sb_w, sb_left);
|
||||
redraw_mark_pane_scrollbar(bctx, wp, sb_w, sb_left, overlay);
|
||||
}
|
||||
|
||||
/* Choose the pane that will provide the border style for two-pane layouts. */
|
||||
@@ -1220,7 +1240,7 @@ redraw_draw_scrollbar_span(struct redraw_draw_ctx *dctx,
|
||||
struct screen *s = wp->screen;
|
||||
struct tty *tty = &scene->c->tty;
|
||||
struct style *sb_style = &wp->scrollbar_style;
|
||||
struct grid_cell gc, slgc, *gcp;
|
||||
struct grid_cell gc, slgc, pad_gc, *gcp;
|
||||
double pct_view;
|
||||
u_int total_height, slider_h, slider_y;
|
||||
u_int sb_h = span->data.sb.height;
|
||||
@@ -1260,6 +1280,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);
|
||||
|
||||
sb_w = sb_style->width;
|
||||
sb_pad = sb_style->pad;
|
||||
@@ -1269,12 +1290,12 @@ redraw_draw_scrollbar_span(struct redraw_draw_ctx *dctx,
|
||||
for (i = 0; i < n; i++) {
|
||||
if (span->data.sb.flags & REDRAW_SCROLLBAR_LEFT) {
|
||||
if (off + i >= sb_w && off + i < sb_w + sb_pad) {
|
||||
tty_cell(tty, &grid_default_cell, NULL);
|
||||
tty_cell(tty, &pad_gc, NULL);
|
||||
continue;
|
||||
}
|
||||
} else {
|
||||
if (off + i < sb_pad) {
|
||||
tty_cell(tty, &grid_default_cell, NULL);
|
||||
tty_cell(tty, &pad_gc, NULL);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1524,6 +1524,7 @@ screen_write_clearline(struct screen_write_ctx *ctx, u_int bg)
|
||||
struct grid_line *gl;
|
||||
u_int sx = screen_size_x(s);
|
||||
struct screen_write_citem *ci = ctx->item;
|
||||
u_int flags;
|
||||
|
||||
gl = grid_get_line(s->grid, s->grid->hsize + s->cy);
|
||||
if (gl->cellsize == 0 && COLOUR_DEFAULT(bg))
|
||||
@@ -1534,7 +1535,10 @@ screen_write_clearline(struct screen_write_ctx *ctx, u_int bg)
|
||||
ctx->wp->flags |= PANE_REDRAW;
|
||||
#endif
|
||||
|
||||
flags = gl->flags & (GRID_LINE_START_PROMPT|GRID_LINE_START_OUTPUT);
|
||||
grid_view_clear(s->grid, 0, s->cy, sx, 1, bg);
|
||||
gl = grid_get_line(s->grid, s->grid->hsize + s->cy);
|
||||
gl->flags |= flags;
|
||||
|
||||
screen_write_collect_clear(ctx, s->cy, 1);
|
||||
ci->x = 0;
|
||||
@@ -2178,6 +2182,10 @@ screen_write_collect_flush_scrolled(struct screen_write_ctx *ctx)
|
||||
screen_write_redraw_pane(ctx, &ttyctx);
|
||||
return 0;
|
||||
}
|
||||
if (wp != NULL && window_pane_scrollbar_overlay_visible(wp)) {
|
||||
wp->flags |= PANE_REDRAW;
|
||||
return 0;
|
||||
}
|
||||
|
||||
log_debug("%s: scrolled %u (region %u-%u)", __func__, ctx->scrolled,
|
||||
s->rupper, s->rlower);
|
||||
@@ -2191,7 +2199,7 @@ screen_write_collect_flush_scrolled(struct screen_write_ctx *ctx)
|
||||
tty_write(tty_cmd_scrollup, &ttyctx);
|
||||
|
||||
if (wp != NULL)
|
||||
wp->flags |= PANE_REDRAWSCROLLBAR;
|
||||
window_pane_scrollbar_redraw(wp);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
123
server-client.c
123
server-client.c
@@ -48,6 +48,8 @@ static void server_client_dispatch(struct imsg *, void *);
|
||||
static int server_client_dispatch_command(struct client *, struct imsg *);
|
||||
static int server_client_dispatch_identify(struct client *, struct imsg *);
|
||||
static int server_client_dispatch_shell(struct client *);
|
||||
static void server_client_update_scrollbar_hover(struct client *, int, int,
|
||||
int);
|
||||
static void server_client_report_theme(struct client *, enum client_theme);
|
||||
|
||||
/* Compare client windows. */
|
||||
@@ -601,6 +603,60 @@ server_client_exec(struct client *c, const char *cmd)
|
||||
free(msg);
|
||||
}
|
||||
|
||||
/* Is this point inside the auto-hide scrollbar interaction area? */
|
||||
static int
|
||||
server_client_in_scrollbar_area(struct window_pane *wp, int px, int py)
|
||||
{
|
||||
struct window *w = wp->window;
|
||||
u_int width, pad, total;
|
||||
int sb, sb_pos, start, end;
|
||||
|
||||
sb = options_get_number(w->options, "pane-scrollbars");
|
||||
if (!window_pane_scrollbar_overlay(wp, sb))
|
||||
return (0);
|
||||
if (py < wp->yoff || py >= wp->yoff + (int)wp->sy)
|
||||
return (0);
|
||||
|
||||
width = wp->scrollbar_style.width;
|
||||
pad = wp->scrollbar_style.pad;
|
||||
total = width + pad;
|
||||
if (total == 0 || total > wp->sx)
|
||||
total = wp->sx;
|
||||
|
||||
sb_pos = options_get_number(w->options, "pane-scrollbars-position");
|
||||
if (sb_pos == PANE_SCROLLBARS_LEFT) {
|
||||
start = wp->xoff;
|
||||
end = wp->xoff + (int)total - 1;
|
||||
} else {
|
||||
end = wp->xoff + (int)wp->sx - 1;
|
||||
start = end - (int)total + 1;
|
||||
}
|
||||
return (px >= start && px <= end);
|
||||
}
|
||||
|
||||
/* Update auto-hide scrollbars for a mouse movement. */
|
||||
static void
|
||||
server_client_update_scrollbar_hover(struct client *c, int type, int px, int py)
|
||||
{
|
||||
struct window *w = c->session->curw->window;
|
||||
struct window_pane *wp;
|
||||
|
||||
if (type != KEYC_TYPE_MOUSEMOVE)
|
||||
return;
|
||||
|
||||
TAILQ_FOREACH(wp, &w->panes, entry) {
|
||||
if (!window_pane_is_visible(wp))
|
||||
continue;
|
||||
if (server_client_in_scrollbar_area(wp, px, py)) {
|
||||
wp->sb_auto_hover = 1;
|
||||
window_pane_scrollbar_show(wp, 1);
|
||||
} else {
|
||||
wp->sb_auto_hover = 0;
|
||||
window_pane_scrollbar_start_timer(wp);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Is the mouse inside a pane? */
|
||||
static enum key_code_mouse_location
|
||||
server_client_check_mouse_in_pane(struct window_pane *wp, int px, int py,
|
||||
@@ -611,14 +667,18 @@ server_client_check_mouse_in_pane(struct window_pane *wp, int px, int py,
|
||||
int pane_status, sb, sb_pos, sb_w, sb_pad;
|
||||
int pane_status_line, sl_top, sl_bottom;
|
||||
int bdr_bottom, bdr_top, bdr_left, bdr_right;
|
||||
int sb_start, sb_end, sb_overlay;
|
||||
|
||||
sb = options_get_number(w->options, "pane-scrollbars");
|
||||
sb_pos = options_get_number(w->options, "pane-scrollbars-position");
|
||||
pane_status = window_pane_get_pane_status(wp);
|
||||
sb_overlay = window_pane_scrollbar_overlay(wp, sb);
|
||||
|
||||
if (window_pane_show_scrollbar(wp, sb)) {
|
||||
if (window_pane_scrollbar_visible(wp, sb)) {
|
||||
sb_w = wp->scrollbar_style.width;
|
||||
sb_pad = wp->scrollbar_style.pad;
|
||||
if (sb_overlay && sb_w > (int)wp->sx)
|
||||
sb_w = wp->sx;
|
||||
} else {
|
||||
sb_w = 0;
|
||||
sb_pad = 0;
|
||||
@@ -631,9 +691,34 @@ server_client_check_mouse_in_pane(struct window_pane *wp, int px, int py,
|
||||
else
|
||||
pane_status_line = -1; /* not used */
|
||||
bdr_left = wp->xoff - 1;
|
||||
if (sb_pos == PANE_SCROLLBARS_LEFT)
|
||||
if (!sb_overlay && sb_pos == PANE_SCROLLBARS_LEFT)
|
||||
bdr_left -= sb_pad + sb_w;
|
||||
|
||||
if (sb_overlay && sb_w != 0 &&
|
||||
py >= wp->yoff && py < wp->yoff + (int)wp->sy &&
|
||||
px >= wp->xoff && px < wp->xoff + (int)wp->sx) {
|
||||
if (sb_pos == PANE_SCROLLBARS_LEFT) {
|
||||
sb_start = wp->xoff;
|
||||
sb_end = sb_start + sb_w - 1;
|
||||
} else {
|
||||
sb_end = wp->xoff + (int)wp->sx - 1;
|
||||
sb_start = sb_end - sb_w + 1;
|
||||
}
|
||||
if (px >= sb_start && px <= sb_end) {
|
||||
sl_top = wp->yoff + wp->sb_slider_y;
|
||||
sl_bottom = (wp->yoff + wp->sb_slider_y +
|
||||
wp->sb_slider_h - 1);
|
||||
if (py < sl_top)
|
||||
return (KEYC_MOUSE_LOCATION_SCROLLBAR_UP);
|
||||
else if (py >= sl_top && py <= sl_bottom) {
|
||||
*sl_mpos = (py - wp->sb_slider_y - wp->yoff);
|
||||
return (KEYC_MOUSE_LOCATION_SCROLLBAR_SLIDER);
|
||||
} else
|
||||
return (KEYC_MOUSE_LOCATION_SCROLLBAR_DOWN);
|
||||
}
|
||||
return (KEYC_MOUSE_LOCATION_PANE);
|
||||
}
|
||||
|
||||
/* Check if point is within the pane or scrollbar. */
|
||||
if (((pane_status != PANE_STATUS_OFF &&
|
||||
py != pane_status_line && py != wp->yoff + (int)wp->sy) ||
|
||||
@@ -681,7 +766,7 @@ server_client_check_mouse_in_pane(struct window_pane *wp, int px, int py,
|
||||
if (window_pane_is_floating(fwp) &&
|
||||
window_pane_get_pane_lines(fwp) == PANE_LINES_NONE)
|
||||
continue;
|
||||
if (window_pane_show_scrollbar(fwp, sb)) {
|
||||
if (window_pane_scrollbar_reserve(fwp, sb)) {
|
||||
sb_w = fwp->scrollbar_style.width;
|
||||
sb_pad = fwp->scrollbar_style.pad;
|
||||
} else {
|
||||
@@ -911,10 +996,14 @@ have_event:
|
||||
tty_window_offset(&c->tty, &m->ox, &m->oy, &sx, &sy);
|
||||
log_debug("mouse window @%u at %u,%u (%ux%u)",
|
||||
w->id, m->ox, m->oy, sx, sy);
|
||||
if (px > sx || py > sy)
|
||||
if (px > sx || py > sy) {
|
||||
server_client_update_scrollbar_hover(c, type,
|
||||
-1, -1);
|
||||
return (KEYC_UNKNOWN);
|
||||
}
|
||||
px = px + m->ox;
|
||||
py = py + m->oy;
|
||||
server_client_update_scrollbar_hover(c, type, px, py);
|
||||
|
||||
if (type == KEYC_TYPE_MOUSEDRAG && lwp != NULL) {
|
||||
/* Use pane from last mouse event. */
|
||||
@@ -947,7 +1036,8 @@ have_event:
|
||||
m->wp = wp->id;
|
||||
m->w = wp->window->id;
|
||||
}
|
||||
}
|
||||
} else
|
||||
server_client_update_scrollbar_hover(c, type, -1, -1);
|
||||
|
||||
/* Reset click type or add a click timer if needed. */
|
||||
if (type == KEYC_TYPE_MOUSEDOWN ||
|
||||
@@ -1907,8 +1997,9 @@ server_client_reset_state(struct client *c)
|
||||
struct window_pane *wp = server_client_get_pane(c), *loop;
|
||||
struct screen *s = NULL;
|
||||
struct options *oo = c->session->options;
|
||||
int mode = 0, cursor, flags, pane_mode = 0;
|
||||
int mode = 0, cursor, flags, pane_mode = 0, sb;
|
||||
u_int cx = 0, cy = 0, ox, oy, sx, sy, prompt = 0;
|
||||
u_int sb_w;
|
||||
struct visible_ranges *r;
|
||||
|
||||
if (c->flags & (CLIENT_CONTROL|CLIENT_SUSPENDED))
|
||||
@@ -1961,6 +2052,21 @@ server_client_reset_state(struct client *c)
|
||||
if (!window_position_is_visible(r, cx))
|
||||
cursor = 0;
|
||||
|
||||
if (window_pane_scrollbar_overlay_visible(wp)) {
|
||||
sb_w = wp->scrollbar_style.width;
|
||||
if (sb_w > wp->sx)
|
||||
sb_w = wp->sx;
|
||||
if (sb_w != 0 &&
|
||||
options_get_number(w->options,
|
||||
"pane-scrollbars-position") ==
|
||||
PANE_SCROLLBARS_LEFT) {
|
||||
if (s->cx < sb_w)
|
||||
cursor = 0;
|
||||
} else if (sb_w != 0 &&
|
||||
s->cx >= wp->sx - sb_w)
|
||||
cursor = 0;
|
||||
}
|
||||
|
||||
if (status_at_line(c) == 0)
|
||||
cy += status_line_size(c);
|
||||
}
|
||||
@@ -1988,7 +2094,10 @@ server_client_reset_state(struct client *c)
|
||||
mode |= MODE_MOUSE_ALL;
|
||||
}
|
||||
}
|
||||
if (options_get_number(oo, "focus-follows-mouse"))
|
||||
sb = options_get_number(w->options, "pane-scrollbars");
|
||||
if (options_get_number(oo, "focus-follows-mouse") ||
|
||||
sb == PANE_SCROLLBARS_MODAL ||
|
||||
sb == PANE_SCROLLBARS_AUTOHIDE)
|
||||
mode |= MODE_MOUSE_ALL;
|
||||
else if (~mode & MODE_MOUSE_ALL)
|
||||
mode |= MODE_MOUSE_BUTTON;
|
||||
|
||||
4
sort.c
4
sort.c
@@ -26,8 +26,8 @@
|
||||
static struct sort_criteria *sort_criteria;
|
||||
|
||||
static void
|
||||
sort_qsort(void *l, u_int len, u_int size, int (*cmp)(const void *, const void *),
|
||||
struct sort_criteria *sort_crit)
|
||||
sort_qsort(void *l, u_int len, u_int size, int (*cmp)(const void *,
|
||||
const void *), struct sort_criteria *sort_crit)
|
||||
{
|
||||
u_int i;
|
||||
void *tmp, **ll;
|
||||
|
||||
254
tmux.1
254
tmux.1
@@ -2744,6 +2744,15 @@ and
|
||||
.Fl Y
|
||||
options set the position of the upper-left corner of the pane.
|
||||
If omitted, new floating panes are cascaded from the top-left of the window.
|
||||
The
|
||||
.Fl x ,
|
||||
.Fl y ,
|
||||
.Fl X ,
|
||||
and
|
||||
.Fl Y
|
||||
options may be followed by
|
||||
.Ql %
|
||||
to specify a percentage of the window size.
|
||||
.Pp
|
||||
If the pane had previously been floating, the position and sizes are restored
|
||||
from the saved values not specified by the
|
||||
@@ -3611,7 +3620,7 @@ but a different format may be specified with
|
||||
.Fl F .
|
||||
.Tg newp
|
||||
.It Xo Ic new\-pane
|
||||
.Op Fl bdefhIkPvWZ
|
||||
.Op Fl bdefhIkLPvWZ
|
||||
.Op Fl B Ar border\-lines
|
||||
.Op Fl c Ar start\-directory
|
||||
.Op Fl e Ar environment
|
||||
@@ -3624,101 +3633,49 @@ but a different format may be specified with
|
||||
.Op Fl S Ar active\-border\-style
|
||||
.Op Fl t Ar target\-pane
|
||||
.Op Fl T Ar title
|
||||
.Op Fl x Ar width
|
||||
.Op Fl y Ar height
|
||||
.Op Fl X Ar x-position
|
||||
.Op Fl Y Ar y-position
|
||||
.Op Ar shell\-command Op Ar argument ...
|
||||
.Xc
|
||||
.D1 Pq alias: Ic newp
|
||||
Create a new pane.
|
||||
The new pane is created by splitting
|
||||
.Ar target\-pane .
|
||||
If
|
||||
.Fl d
|
||||
is given, the session does not make the new pane the current pane.
|
||||
.Fl Z
|
||||
zooms if the window is not zoomed, or keeps it zoomed if already zoomed.
|
||||
.Fl s
|
||||
sets the style for the pane content.
|
||||
.Fl S
|
||||
sets the border style when the pane is active and
|
||||
.Fl R
|
||||
sets the border style when the pane is inactive (see
|
||||
.Sx STYLES ) .
|
||||
.Fl T
|
||||
sets the pane title.
|
||||
Creates a new floating pane.
|
||||
The
|
||||
.Fl x
|
||||
and
|
||||
.Fl y
|
||||
options set the width and height of the floating pane in columns and lines
|
||||
respectively.
|
||||
The default is half the window width and a quarter the window height.
|
||||
The
|
||||
.Fl X
|
||||
and
|
||||
.Fl Y
|
||||
options set the position of the upper-left corner of the pane.
|
||||
If omitted, new floating panes are cascaded from the top-left of the window.
|
||||
The
|
||||
.Fl x ,
|
||||
.Fl y ,
|
||||
.Fl X ,
|
||||
and
|
||||
.Fl Y
|
||||
options may be followed by
|
||||
.Ql %
|
||||
to specify a percentage of the window size.
|
||||
.Fl B
|
||||
sets the pane border lines for floating panes; see
|
||||
.Ic pane\-border\-lines .
|
||||
.Pp
|
||||
.Fl h
|
||||
does a horizontal split and
|
||||
.Fl v
|
||||
a vertical split; if neither is specified,
|
||||
.Fl v
|
||||
is assumed.
|
||||
The
|
||||
.Fl l
|
||||
option specifies the size of the new pane in lines (for vertical split) or in
|
||||
columns (for horizontal split);
|
||||
.Ar size
|
||||
may be followed by
|
||||
.Ql %
|
||||
to specify a percentage of the available space.
|
||||
.Fl p
|
||||
is a shorthand option for this.
|
||||
The
|
||||
.Fl b
|
||||
option causes the new pane to be created to the left of or above
|
||||
.Ar target\-pane .
|
||||
The
|
||||
.Fl f
|
||||
option creates a new pane spanning the full window height (with
|
||||
.Fl h )
|
||||
or full window width (with
|
||||
.Fl v ) ,
|
||||
instead of splitting the active pane.
|
||||
.Pp
|
||||
.Fl k
|
||||
keeps the pane open after the optional
|
||||
.Ar shell\-command
|
||||
exits and waits for a key to be pressed before closing it.
|
||||
The message shown is controlled by the
|
||||
.Ic remain\-on\-exit\-format
|
||||
option.
|
||||
.Fl m Ar message
|
||||
is equivalent to
|
||||
.Fl k
|
||||
but also sets the
|
||||
.Ic remain\-on\-exit\-format
|
||||
option for this pane to
|
||||
.Ar message .
|
||||
.Pp
|
||||
.Fl W
|
||||
Waits until
|
||||
.Ar shell\-command
|
||||
exits, then returns its exit status.
|
||||
For example:
|
||||
.Bd -literal -offset indent
|
||||
$ tmux new-pane -W 'vi afile'
|
||||
$ echo $?
|
||||
0
|
||||
.Ed
|
||||
.Pp
|
||||
.Fl E ,
|
||||
or an empty
|
||||
.Ar shell\-command ,
|
||||
(\[aq]\[aq]) will create an empty pane with no command running in it;
|
||||
.Ic display-message
|
||||
.Fl I
|
||||
can write to an empty pane.
|
||||
The
|
||||
.Fl I
|
||||
flag will create an empty pane and forward any output from stdin to it.
|
||||
For example:
|
||||
.Bd -literal -offset indent
|
||||
$ make 2>&1|tmux new\-pane \-dI &
|
||||
.Ed
|
||||
.Fl L
|
||||
option makes
|
||||
.Ic new\-pane
|
||||
behave like
|
||||
.Ic split\-window .
|
||||
.Pp
|
||||
All other options have the same meaning as for the
|
||||
.Ic new\-window
|
||||
.Ic split\-window
|
||||
command.
|
||||
.Tg nextl
|
||||
.It Ic next\-layout Op Fl t Ar target\-window
|
||||
@@ -4209,14 +4166,92 @@ the command behaves like
|
||||
.Op Ar shell\-command Op Ar argument ...
|
||||
.Xc
|
||||
.D1 Pq alias: Ic splitw
|
||||
Creates a new pane by splitting
|
||||
Create a new pane by splitting
|
||||
.Ar target\-pane .
|
||||
Shares behavior with
|
||||
.Ic new\-pane .
|
||||
If
|
||||
.Fl d
|
||||
is given, the session does not make the new pane the current pane.
|
||||
.Fl Z
|
||||
zooms if the window is not zoomed, or keeps it zoomed if already zoomed.
|
||||
.Fl s
|
||||
sets the style for the pane content.
|
||||
.Fl S
|
||||
sets the border style when the pane is active and
|
||||
.Fl R
|
||||
sets the border style when the pane is inactive (see
|
||||
.Sx STYLES ) .
|
||||
.Fl T
|
||||
sets the pane title.
|
||||
.Pp
|
||||
.Fl h
|
||||
does a horizontal split and
|
||||
.Fl v
|
||||
a vertical split; if neither is specified,
|
||||
.Fl v
|
||||
is assumed.
|
||||
The
|
||||
.Fl l
|
||||
option specifies the size of the new pane in lines (for vertical split) or in
|
||||
columns (for horizontal split);
|
||||
.Ar size
|
||||
may be followed by
|
||||
.Ql %
|
||||
to specify a percentage of the available space.
|
||||
.Fl p
|
||||
is a shorthand option for this.
|
||||
The
|
||||
.Fl b
|
||||
option causes the new pane to be created to the left of or above
|
||||
.Ar target\-pane .
|
||||
The
|
||||
.Fl f
|
||||
option creates a new pane spanning the full window height (with
|
||||
.Fl h )
|
||||
or full window width (with
|
||||
.Fl v ) ,
|
||||
instead of splitting the active pane.
|
||||
.Pp
|
||||
.Fl k
|
||||
keeps the pane open after the optional
|
||||
.Ar shell\-command
|
||||
exits and waits for a key to be pressed before closing it.
|
||||
The message shown is controlled by the
|
||||
.Ic remain\-on\-exit\-format
|
||||
option.
|
||||
.Fl m Ar message
|
||||
is equivalent to
|
||||
.Fl k
|
||||
but also sets the
|
||||
.Ic remain\-on\-exit\-format
|
||||
option for this pane to
|
||||
.Ar message .
|
||||
.Pp
|
||||
.Fl W
|
||||
Waits until
|
||||
.Ar shell\-command
|
||||
exits, then returns its exit status.
|
||||
For example:
|
||||
.Bd -literal -offset indent
|
||||
$ tmux new-pane -W 'vi afile'
|
||||
$ echo $?
|
||||
0
|
||||
.Ed
|
||||
.Pp
|
||||
.Fl E ,
|
||||
or an empty
|
||||
.Ar shell\-command ,
|
||||
(\[aq]\[aq]) will create an empty pane with no command running in it;
|
||||
.Ic display-message
|
||||
.Fl I
|
||||
can write to an empty pane.
|
||||
The
|
||||
.Fl I
|
||||
flag will create an empty pane and forward any output from stdin to it.
|
||||
For example:
|
||||
.Bd -literal -offset indent
|
||||
$ make 2>&1|tmux new\-pane \-dI &
|
||||
.Ed
|
||||
.Pp
|
||||
See
|
||||
.Ic new\-pane
|
||||
for more details.
|
||||
.Tg swapp
|
||||
.It Xo Ic swap\-pane
|
||||
.Op Fl dDUZ
|
||||
@@ -6019,7 +6054,7 @@ and
|
||||
will fall back to standard ACS line drawing when UTF\-8 is not supported.
|
||||
.Pp
|
||||
.It Xo Ic pane\-scrollbars
|
||||
.Op Ic off | modal | on
|
||||
.Op Ic off | modal | on | auto\-hide
|
||||
.Xc
|
||||
When enabled, a character based scrollbar appears on the left or right
|
||||
of each pane.
|
||||
@@ -6029,19 +6064,29 @@ represents the position and size of the visible part of the pane content.
|
||||
.Pp
|
||||
If set to
|
||||
.Ic on
|
||||
the scrollbar is visible all the time.
|
||||
the scrollbar is visible all the time and the pane is narrowed by the width of
|
||||
the scrollbar.
|
||||
If set to
|
||||
.Ic modal
|
||||
the scrollbar only appears when the pane is in copy mode or view mode.
|
||||
When the scrollbar is visible, the pane is narrowed by the width of the
|
||||
scrollbar and the text in the pane is reflowed.
|
||||
the scrollbar only appears when the pane is in copy mode or view mode and
|
||||
auto-hides when not in use.
|
||||
If set to
|
||||
.Ic modal ,
|
||||
the pane is narrowed only when the scrollbar is visible.
|
||||
.Ic auto\-hide
|
||||
the scrollbar is available all the time but auto-hides when not in use.
|
||||
With
|
||||
.Ic modal
|
||||
and
|
||||
.Ic auto\-hide ,
|
||||
the scrollbar overlays the pane and does not narrow or reflow the pane.
|
||||
.Pp
|
||||
See also
|
||||
.Ic pane\-scrollbars\-style .
|
||||
.Pp
|
||||
.It Xo Ic pane\-scrollbars\-position
|
||||
.Op Ic left | right
|
||||
.Xc
|
||||
Sets which side of the pane to display pane scrollbars on.
|
||||
.Pp
|
||||
.It Ic pane\-scrollbars\-style Ar style
|
||||
Set the scrollbars style.
|
||||
For how to specify
|
||||
@@ -6058,10 +6103,13 @@ attribute sets the width of the scrollbar and the
|
||||
attribute the padding between the scrollbar and the pane.
|
||||
Other attributes are ignored.
|
||||
.Pp
|
||||
.It Xo Ic pane\-scrollbars\-position
|
||||
.Op Ic left | right
|
||||
.Xc
|
||||
Sets which side of the pane to display pane scrollbars on.
|
||||
.It Ic pane\-scrollbars\-timeout Ar time
|
||||
Set the time in milliseconds before scrollbars are hidden when
|
||||
.Ic pane\-scrollbars
|
||||
is
|
||||
.Ic modal
|
||||
or
|
||||
.Ic auto\-hide .
|
||||
.Pp
|
||||
.It Ic pane\-status\-current\-style Ar style
|
||||
Set status line style for the currently active pane.
|
||||
|
||||
9
tmux.c
9
tmux.c
@@ -286,11 +286,14 @@ clean_name(const char *name, const char* forbid)
|
||||
{
|
||||
char *copy, *cp, *new_name;
|
||||
|
||||
if (*name == '\0' || !utf8_isvalid(name))
|
||||
if (!utf8_isvalid(name))
|
||||
return (NULL);
|
||||
copy = xstrdup(name);
|
||||
for (cp = copy; *cp != '\0'; cp++) {
|
||||
if (strchr(forbid, *cp) != NULL)
|
||||
if (*cp == '#' && strchr(forbid, '#') != NULL) {
|
||||
if (cp[1] == '(')
|
||||
*cp = '_';
|
||||
} else if (strchr(forbid, *cp) != NULL)
|
||||
*cp = '_';
|
||||
}
|
||||
utf8_stravis(&new_name, copy, VIS_OCTAL|VIS_CSTYLE|VIS_TAB|VIS_NL);
|
||||
@@ -308,7 +311,7 @@ check_name(const char *name, const char *forbid)
|
||||
{
|
||||
const char *cp;
|
||||
|
||||
if (*name == '\0' || !utf8_isvalid(name))
|
||||
if (!utf8_isvalid(name))
|
||||
return (0);
|
||||
for (cp = name; *cp != '\0'; cp++) {
|
||||
if (strchr(forbid, *cp) != NULL)
|
||||
|
||||
21
tmux.h
21
tmux.h
@@ -1300,6 +1300,9 @@ struct window_pane {
|
||||
|
||||
u_int sb_slider_y;
|
||||
u_int sb_slider_h;
|
||||
int sb_auto_visible;
|
||||
int sb_auto_hover;
|
||||
struct event sb_auto_timer;
|
||||
|
||||
int argc;
|
||||
char **argv;
|
||||
@@ -1474,6 +1477,7 @@ TAILQ_HEAD(winlink_stack, winlink);
|
||||
#define PANE_SCROLLBARS_OFF 0
|
||||
#define PANE_SCROLLBARS_MODAL 1
|
||||
#define PANE_SCROLLBARS_ALWAYS 2
|
||||
#define PANE_SCROLLBARS_AUTOHIDE 3
|
||||
|
||||
/* Pane scrollbars position option. */
|
||||
#define PANE_SCROLLBARS_RIGHT 0
|
||||
@@ -3636,6 +3640,14 @@ void window_set_fill_character(struct window *);
|
||||
void window_pane_default_cursor(struct window_pane *);
|
||||
int window_pane_mode(struct window_pane *);
|
||||
int window_pane_show_scrollbar(struct window_pane *, int);
|
||||
int window_pane_scrollbar_reserve(struct window_pane *, int);
|
||||
int window_pane_scrollbar_visible(struct window_pane *, int);
|
||||
int window_pane_scrollbar_overlay(struct window_pane *, int);
|
||||
int window_pane_scrollbar_overlay_visible(struct window_pane *);
|
||||
void window_pane_scrollbar_show(struct window_pane *, int);
|
||||
void window_pane_scrollbar_hide(struct window_pane *);
|
||||
void window_pane_scrollbar_start_timer(struct window_pane *);
|
||||
void window_pane_scrollbar_redraw(struct window_pane *);
|
||||
int window_pane_get_bg(struct window_pane *);
|
||||
int window_pane_get_fg(struct window_pane *);
|
||||
int window_pane_get_fg_control_client(struct window_pane *);
|
||||
@@ -3684,6 +3696,8 @@ void layout_fix_offsets(struct window *);
|
||||
void layout_fix_panes(struct window *, struct window_pane *);
|
||||
void layout_resize_adjust(struct window *, struct layout_cell *,
|
||||
enum layout_type, int);
|
||||
void layout_resize_set_size(struct window *, struct layout_cell *,
|
||||
enum layout_type, u_int);
|
||||
struct layout_cell *layout_cell_get_neighbour(struct layout_cell *);
|
||||
void layout_init(struct window *, struct window_pane *);
|
||||
void layout_free(struct window *);
|
||||
@@ -3698,6 +3712,12 @@ int layout_resize_floating_pane_to(struct window_pane *,
|
||||
enum layout_type, u_int, char **);
|
||||
void layout_assign_pane(struct layout_cell *, struct window_pane *,
|
||||
int);
|
||||
int layout_split_check_space(struct window_pane *,
|
||||
struct layout_cell *, enum layout_type);
|
||||
void layout_split_sizes(struct layout_cell *, int, int,
|
||||
enum layout_type, u_int *, u_int *, u_int *);
|
||||
struct layout_cell *layout_replace_with_node(struct window *,
|
||||
struct layout_cell *, enum layout_type);
|
||||
struct layout_cell *layout_split_pane(struct window_pane *, enum layout_type,
|
||||
int, int);
|
||||
struct layout_cell *layout_floating_pane(struct window *, struct window_pane *,
|
||||
@@ -3714,6 +3734,7 @@ int layout_floating_args_parse(struct cmdq_item *, struct args *,
|
||||
enum pane_lines, struct window *, u_int *, u_int *, int *,
|
||||
int *, char **);
|
||||
int layout_remove_tile(struct window *, struct layout_cell *);
|
||||
int layout_insert_tile(struct window *, struct layout_cell *);
|
||||
|
||||
/* layout-custom.c */
|
||||
char *layout_dump(struct window *, struct layout_cell *);
|
||||
|
||||
@@ -61,8 +61,10 @@ static int window_copy_line_number_mode(struct window_mode_entry *);
|
||||
static int window_copy_line_number_is_absolute(struct window_mode_entry *);
|
||||
static int window_copy_line_numbers_active(struct window_mode_entry *);
|
||||
static u_int window_copy_line_number_width(struct window_mode_entry *);
|
||||
static u_int window_copy_cursor_offset(struct window_mode_entry *, u_int, u_int);
|
||||
static u_int window_copy_cursor_unoffset(struct window_mode_entry *, u_int, u_int);
|
||||
static u_int window_copy_cursor_offset(struct window_mode_entry *, u_int,
|
||||
u_int);
|
||||
static u_int window_copy_cursor_unoffset(struct window_mode_entry *, u_int,
|
||||
u_int);
|
||||
static void window_copy_write_line(struct window_mode_entry *,
|
||||
struct screen_write_ctx *, u_int);
|
||||
static void window_copy_write_lines(struct window_mode_entry *,
|
||||
@@ -860,6 +862,7 @@ window_copy_scroll1(struct window_mode_entry *wme, struct window_pane *wp,
|
||||
if (data->searchmark != NULL && !data->timeout)
|
||||
window_copy_search_marks(wme, NULL, data->searchregex, 1);
|
||||
window_copy_update_selection(wme, 1, 0);
|
||||
window_pane_scrollbar_show(wp, 1);
|
||||
window_copy_redraw_screen(wme);
|
||||
}
|
||||
|
||||
@@ -913,6 +916,7 @@ window_copy_pageup1(struct window_mode_entry *wme, int half_page)
|
||||
if (data->searchmark != NULL && !data->timeout)
|
||||
window_copy_search_marks(wme, NULL, data->searchregex, 1);
|
||||
window_copy_update_selection(wme, 1, 0);
|
||||
window_pane_scrollbar_show(wme->wp, 1);
|
||||
window_copy_redraw_screen(wme);
|
||||
}
|
||||
|
||||
@@ -973,6 +977,7 @@ window_copy_pagedown1(struct window_mode_entry *wme, int half_page,
|
||||
if (data->searchmark != NULL && !data->timeout)
|
||||
window_copy_search_marks(wme, NULL, data->searchregex, 1);
|
||||
window_copy_update_selection(wme, 1, 0);
|
||||
window_pane_scrollbar_show(wme->wp, 1);
|
||||
window_copy_redraw_screen(wme);
|
||||
return (0);
|
||||
}
|
||||
@@ -1789,7 +1794,7 @@ window_copy_cmd_history_bottom(struct window_copy_cmd_state *cs)
|
||||
struct window_mode_entry *wme = cs->wme;
|
||||
struct window_copy_mode_data *data = wme->data;
|
||||
struct screen *s = data->backing;
|
||||
u_int oy;
|
||||
u_int oy, old_oy = data->oy;
|
||||
|
||||
oy = screen_hsize(s) + data->cy - data->oy;
|
||||
if (data->lineflag == LINE_SEL_RIGHT_LEFT && oy == data->endsely)
|
||||
@@ -1802,6 +1807,8 @@ window_copy_cmd_history_bottom(struct window_copy_cmd_state *cs)
|
||||
if (data->searchmark != NULL && !data->timeout)
|
||||
window_copy_search_marks(wme, NULL, data->searchregex, 1);
|
||||
window_copy_update_selection(wme, 1, 0);
|
||||
if (data->oy != old_oy)
|
||||
window_pane_scrollbar_show(wme->wp, 1);
|
||||
return (WINDOW_COPY_CMD_REDRAW);
|
||||
}
|
||||
|
||||
@@ -1810,7 +1817,7 @@ window_copy_cmd_history_top(struct window_copy_cmd_state *cs)
|
||||
{
|
||||
struct window_mode_entry *wme = cs->wme;
|
||||
struct window_copy_mode_data *data = wme->data;
|
||||
u_int oy;
|
||||
u_int oy, old_oy = data->oy;
|
||||
|
||||
oy = screen_hsize(data->backing) + data->cy - data->oy;
|
||||
if (data->lineflag == LINE_SEL_LEFT_RIGHT && oy == data->sely)
|
||||
@@ -1823,6 +1830,8 @@ window_copy_cmd_history_top(struct window_copy_cmd_state *cs)
|
||||
if (data->searchmark != NULL && !data->timeout)
|
||||
window_copy_search_marks(wme, NULL, data->searchregex, 1);
|
||||
window_copy_update_selection(wme, 1, 0);
|
||||
if (data->oy != old_oy)
|
||||
window_pane_scrollbar_show(wme->wp, 1);
|
||||
return (WINDOW_COPY_CMD_REDRAW);
|
||||
}
|
||||
|
||||
@@ -3772,7 +3781,7 @@ window_copy_scroll_to(struct window_mode_entry *wme, u_int px, u_int py,
|
||||
{
|
||||
struct window_copy_mode_data *data = wme->data;
|
||||
struct grid *gd = data->backing->grid;
|
||||
u_int offset, gap;
|
||||
u_int offset, gap, old_oy = data->oy;
|
||||
|
||||
data->cx = px;
|
||||
|
||||
@@ -3796,6 +3805,8 @@ window_copy_scroll_to(struct window_mode_entry *wme, u_int px, u_int py,
|
||||
if (!no_redraw && data->searchmark != NULL && !data->timeout)
|
||||
window_copy_search_marks(wme, NULL, data->searchregex, 1);
|
||||
window_copy_update_selection(wme, 1, 0);
|
||||
if (data->oy != old_oy)
|
||||
window_pane_scrollbar_show(wme->wp, 1);
|
||||
if (!no_redraw)
|
||||
window_copy_redraw_screen(wme);
|
||||
}
|
||||
@@ -5154,6 +5165,9 @@ window_copy_write_line(struct window_mode_entry *wme,
|
||||
else
|
||||
content_sx = sx;
|
||||
|
||||
screen_write_cursormove(ctx, 0, py, 0);
|
||||
screen_write_clearline(ctx, 8);
|
||||
|
||||
ft = format_create_defaults(NULL, NULL, NULL, NULL, wp);
|
||||
|
||||
style_apply(&gc, oo, "copy-mode-position-style", ft);
|
||||
@@ -5275,7 +5289,10 @@ window_copy_redraw_lines(struct window_mode_entry *wme, u_int py, u_int ny)
|
||||
return;
|
||||
}
|
||||
|
||||
screen_write_start_pane(&ctx, wp, NULL);
|
||||
if (window_pane_scrollbar_overlay_visible(wp))
|
||||
screen_write_start(&ctx, &data->screen);
|
||||
else
|
||||
screen_write_start_pane(&ctx, wp, NULL);
|
||||
for (i = py; i < py + ny; i++)
|
||||
window_copy_write_line(wme, &ctx, i);
|
||||
screen_write_cursormove(&ctx,
|
||||
@@ -5283,7 +5300,7 @@ window_copy_redraw_lines(struct window_mode_entry *wme, u_int py, u_int ny)
|
||||
0);
|
||||
screen_write_stop(&ctx);
|
||||
|
||||
wp->flags |= PANE_REDRAWSCROLLBAR;
|
||||
window_pane_scrollbar_redraw(wp);
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -6539,6 +6556,7 @@ window_copy_scroll_up(struct window_mode_entry *wme, u_int ny)
|
||||
if (ny == 0)
|
||||
return;
|
||||
data->oy -= ny;
|
||||
window_pane_scrollbar_show(wp, 1);
|
||||
|
||||
if (data->searchmark != NULL && !data->timeout)
|
||||
window_copy_search_marks(wme, NULL, data->searchregex, 1);
|
||||
@@ -6570,7 +6588,10 @@ window_copy_scroll_up(struct window_mode_entry *wme, u_int ny)
|
||||
return;
|
||||
}
|
||||
|
||||
screen_write_start_pane(&ctx, wp, NULL);
|
||||
if (window_pane_scrollbar_overlay_visible(wp))
|
||||
screen_write_start(&ctx, &data->screen);
|
||||
else
|
||||
screen_write_start_pane(&ctx, wp, NULL);
|
||||
screen_write_cursormove(&ctx, 0, 0, 0);
|
||||
screen_write_deleteline(&ctx, ny, 8);
|
||||
window_copy_write_lines(wme, &ctx, screen_size_y(s) - ny, ny);
|
||||
@@ -6585,7 +6606,7 @@ window_copy_scroll_up(struct window_mode_entry *wme, u_int ny)
|
||||
window_copy_cursor_offset(wme, data->cx, screen_size_x(s)), data->cy,
|
||||
0);
|
||||
screen_write_stop(&ctx);
|
||||
wp->flags |= PANE_REDRAWSCROLLBAR;
|
||||
window_pane_scrollbar_redraw(wp);
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -6604,6 +6625,7 @@ window_copy_scroll_down(struct window_mode_entry *wme, u_int ny)
|
||||
if (ny == 0)
|
||||
return;
|
||||
data->oy += ny;
|
||||
window_pane_scrollbar_show(wp, 1);
|
||||
|
||||
if (data->searchmark != NULL && !data->timeout)
|
||||
window_copy_search_marks(wme, NULL, data->searchregex, 1);
|
||||
@@ -6630,7 +6652,10 @@ window_copy_scroll_down(struct window_mode_entry *wme, u_int ny)
|
||||
return;
|
||||
}
|
||||
|
||||
screen_write_start_pane(&ctx, wp, NULL);
|
||||
if (window_pane_scrollbar_overlay_visible(wp))
|
||||
screen_write_start(&ctx, &data->screen);
|
||||
else
|
||||
screen_write_start_pane(&ctx, wp, NULL);
|
||||
screen_write_cursormove(&ctx, 0, 0, 0);
|
||||
screen_write_insertline(&ctx, ny, 8);
|
||||
window_copy_write_lines(wme, &ctx, 0, ny);
|
||||
@@ -6641,7 +6666,7 @@ window_copy_scroll_down(struct window_mode_entry *wme, u_int ny)
|
||||
screen_write_cursormove(&ctx, window_copy_cursor_offset(wme, data->cx,
|
||||
screen_size_x(s)), data->cy, 0);
|
||||
screen_write_stop(&ctx);
|
||||
wp->flags |= PANE_REDRAWSCROLLBAR;
|
||||
window_pane_scrollbar_redraw(wp);
|
||||
}
|
||||
|
||||
static void
|
||||
|
||||
@@ -1138,6 +1138,7 @@ window_tree_init(struct window_mode_entry *wme, struct cmd_find_state *fs,
|
||||
window_tree_get_key, window_tree_swap, window_tree_sort,
|
||||
window_tree_help, data, window_tree_menu_items, &s);
|
||||
mode_tree_zoom(data->data, args);
|
||||
mode_tree_view_name(data->data, "preview");
|
||||
|
||||
mode_tree_build(data->data);
|
||||
mode_tree_draw(data->data);
|
||||
|
||||
@@ -126,7 +126,7 @@ window_visible_ranges(struct window_pane *base_wp, int px, int py, u_int width,
|
||||
continue;
|
||||
|
||||
sb_w = wp->scrollbar_style.width + wp->scrollbar_style.pad;
|
||||
if (!window_pane_show_scrollbar(wp, sb))
|
||||
if (!window_pane_scrollbar_reserve(wp, sb))
|
||||
sb_w = sb_pos = 0;
|
||||
|
||||
for (i = 0; i < r->used; i++) {
|
||||
|
||||
134
window.c
134
window.c
@@ -71,6 +71,7 @@ struct window_pane_input_data {
|
||||
static struct window_pane *window_pane_create(struct window *, u_int, u_int,
|
||||
u_int);
|
||||
static void window_pane_destroy(struct window_pane *);
|
||||
static void window_pane_scrollbar_timer(int, short, void *);
|
||||
static void window_pane_full_size_offset(struct window_pane *wp,
|
||||
int *xoff, int *yoff, u_int *sx, u_int *sy);
|
||||
|
||||
@@ -631,6 +632,7 @@ window_redraw_active_switch(struct window *w, struct window_pane *wp)
|
||||
TAILQ_REMOVE(&w->z_index, wp, zentry);
|
||||
TAILQ_INSERT_HEAD(&w->z_index, wp, zentry);
|
||||
wp->flags |= PANE_REDRAW;
|
||||
redraw_invalidate_scene(w);
|
||||
}
|
||||
|
||||
wp = w->active;
|
||||
@@ -1111,6 +1113,7 @@ window_pane_create(struct window *w, u_int sx, u_int sy, u_int hlimit)
|
||||
|
||||
screen_init(&wp->status_screen, 1, 1, 0);
|
||||
style_ranges_init(&wp->border_status_line.ranges);
|
||||
evtimer_set(&wp->sb_auto_timer, window_pane_scrollbar_timer, wp);
|
||||
|
||||
if (gethostname(host, sizeof host) == 0)
|
||||
screen_set_title(&wp->base, host, 0);
|
||||
@@ -1157,6 +1160,52 @@ window_pane_free_modes(struct window_pane *wp)
|
||||
wp->screen = &wp->base;
|
||||
}
|
||||
|
||||
static void
|
||||
window_pane_scrollbar_timer(__unused int fd, __unused short events, void *arg)
|
||||
{
|
||||
struct window_pane *wp = arg;
|
||||
|
||||
wp->sb_auto_hover = 0;
|
||||
window_pane_scrollbar_hide(wp);
|
||||
}
|
||||
|
||||
static int
|
||||
window_pane_scrollbar_auto_hide(struct window_pane *wp)
|
||||
{
|
||||
int sb;
|
||||
|
||||
sb = options_get_number(wp->window->options, "pane-scrollbars");
|
||||
return (sb == PANE_SCROLLBARS_MODAL || sb == PANE_SCROLLBARS_AUTOHIDE);
|
||||
}
|
||||
|
||||
int
|
||||
window_pane_scrollbar_overlay_visible(struct window_pane *wp)
|
||||
{
|
||||
int sb;
|
||||
|
||||
sb = options_get_number(wp->window->options, "pane-scrollbars");
|
||||
return (window_pane_scrollbar_overlay(wp, sb) &&
|
||||
window_pane_scrollbar_visible(wp, sb));
|
||||
}
|
||||
|
||||
void
|
||||
window_pane_scrollbar_redraw(struct window_pane *wp)
|
||||
{
|
||||
if (window_pane_scrollbar_overlay_visible(wp)) {
|
||||
wp->flags |= PANE_REDRAW;
|
||||
return;
|
||||
}
|
||||
wp->flags |= PANE_REDRAWSCROLLBAR;
|
||||
}
|
||||
|
||||
static void
|
||||
window_pane_scrollbar_redraw_visibility(struct window_pane *wp)
|
||||
{
|
||||
redraw_invalidate_scene(wp->window);
|
||||
wp->flags |= PANE_REDRAW;
|
||||
server_redraw_window(wp->window);
|
||||
}
|
||||
|
||||
static void
|
||||
window_pane_destroy(struct window_pane *wp)
|
||||
{
|
||||
@@ -1192,6 +1241,8 @@ window_pane_destroy(struct window_pane *wp)
|
||||
event_del(&wp->resize_timer);
|
||||
if (event_initialized(&wp->sync_timer))
|
||||
event_del(&wp->sync_timer);
|
||||
if (event_initialized(&wp->sb_auto_timer))
|
||||
event_del(&wp->sb_auto_timer);
|
||||
window_pane_clear_resizes(wp, NULL);
|
||||
|
||||
RB_REMOVE(window_pane_tree, &all_window_panes, wp);
|
||||
@@ -1261,7 +1312,8 @@ window_pane_set_event(struct window_pane *wp)
|
||||
}
|
||||
|
||||
void
|
||||
window_pane_clear_resizes(struct window_pane *wp, struct window_pane_resize *except)
|
||||
window_pane_clear_resizes(struct window_pane *wp,
|
||||
struct window_pane_resize *except)
|
||||
{
|
||||
struct window_pane_resize *r, *r1;
|
||||
|
||||
@@ -1740,7 +1792,7 @@ window_pane_full_size_offset(struct window_pane *wp, int *xoff, int *yoff,
|
||||
pane_scrollbars = options_get_number(w->options, "pane-scrollbars");
|
||||
sb_pos = options_get_number(w->options, "pane-scrollbars-position");
|
||||
|
||||
if (window_pane_show_scrollbar(wp, pane_scrollbars))
|
||||
if (window_pane_scrollbar_reserve(wp, pane_scrollbars))
|
||||
sb_w = wp->scrollbar_style.width + wp->scrollbar_style.pad;
|
||||
else
|
||||
sb_w = 0;
|
||||
@@ -2167,12 +2219,90 @@ window_pane_show_scrollbar(struct window_pane *wp, int sb_option)
|
||||
if (SCREEN_IS_ALTERNATE(&wp->base))
|
||||
return (0);
|
||||
if (sb_option == PANE_SCROLLBARS_ALWAYS ||
|
||||
sb_option == PANE_SCROLLBARS_AUTOHIDE ||
|
||||
(sb_option == PANE_SCROLLBARS_MODAL &&
|
||||
window_pane_mode(wp) != WINDOW_PANE_NO_MODE))
|
||||
return (1);
|
||||
return (0);
|
||||
}
|
||||
|
||||
int
|
||||
window_pane_scrollbar_reserve(struct window_pane *wp, int sb_option)
|
||||
{
|
||||
if (!window_pane_show_scrollbar(wp, sb_option))
|
||||
return (0);
|
||||
return (sb_option == PANE_SCROLLBARS_ALWAYS);
|
||||
}
|
||||
|
||||
int
|
||||
window_pane_scrollbar_overlay(struct window_pane *wp, int sb_option)
|
||||
{
|
||||
if (!window_pane_show_scrollbar(wp, sb_option))
|
||||
return (0);
|
||||
return (window_pane_scrollbar_auto_hide(wp));
|
||||
}
|
||||
|
||||
int
|
||||
window_pane_scrollbar_visible(struct window_pane *wp, int sb_option)
|
||||
{
|
||||
if (!window_pane_show_scrollbar(wp, sb_option))
|
||||
return (0);
|
||||
if (!window_pane_scrollbar_auto_hide(wp))
|
||||
return (1);
|
||||
return (wp->sb_auto_visible);
|
||||
}
|
||||
|
||||
void
|
||||
window_pane_scrollbar_start_timer(struct window_pane *wp)
|
||||
{
|
||||
struct timeval tv;
|
||||
u_int delay;
|
||||
|
||||
if (!window_pane_scrollbar_auto_hide(wp) || !wp->sb_auto_visible)
|
||||
return;
|
||||
|
||||
delay = options_get_number(wp->window->options,
|
||||
"pane-scrollbars-timeout");
|
||||
tv.tv_sec = delay / 1000;
|
||||
tv.tv_usec = (delay % 1000) * 1000L;
|
||||
evtimer_del(&wp->sb_auto_timer);
|
||||
evtimer_add(&wp->sb_auto_timer, &tv);
|
||||
}
|
||||
|
||||
void
|
||||
window_pane_scrollbar_show(struct window_pane *wp, int start_timer)
|
||||
{
|
||||
int changed = 0;
|
||||
int sb;
|
||||
|
||||
if (!window_pane_scrollbar_auto_hide(wp))
|
||||
return;
|
||||
sb = options_get_number(wp->window->options, "pane-scrollbars");
|
||||
if (!window_pane_show_scrollbar(wp, sb))
|
||||
return;
|
||||
if (!wp->sb_auto_visible) {
|
||||
wp->sb_auto_visible = 1;
|
||||
changed = 1;
|
||||
}
|
||||
evtimer_del(&wp->sb_auto_timer);
|
||||
if (start_timer)
|
||||
window_pane_scrollbar_start_timer(wp);
|
||||
if (changed)
|
||||
window_pane_scrollbar_redraw_visibility(wp);
|
||||
}
|
||||
|
||||
void
|
||||
window_pane_scrollbar_hide(struct window_pane *wp)
|
||||
{
|
||||
if (event_initialized(&wp->sb_auto_timer))
|
||||
evtimer_del(&wp->sb_auto_timer);
|
||||
wp->sb_auto_hover = 0;
|
||||
if (!wp->sb_auto_visible)
|
||||
return;
|
||||
wp->sb_auto_visible = 0;
|
||||
window_pane_scrollbar_redraw_visibility(wp);
|
||||
}
|
||||
|
||||
int
|
||||
window_pane_get_bg(struct window_pane *wp)
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user