1
0
mirror of https://github.com/tmux/tmux.git synced 2025-04-04 23:28:51 +00:00

Merge branch 'tmux:master' into non-blocking-popup-windows

This commit is contained in:
Michael Grant 2025-03-26 12:53:30 -04:00 committed by GitHub
commit f6818a097f
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
15 changed files with 343 additions and 63 deletions

32
SYNCING
View File

@ -1,17 +1,17 @@
Preamble
========
Tmux portable relies on repositories "tmux" and "tmux-openbsd".
Tmux portable relies on repositories "tmux" and "tmux-obsd".
Here's a description of them:
* "tmux" is the portable version, the one which contains code for other
operating systems, and autotools, etc., which isn't found or needed in the
OpenBSD base system.
* "tmux-openbsd" is the version of tmux in OpenBSD base system which provides
* "tmux-obsd" is the version of tmux in OpenBSD base system which provides
the basis of the portable tmux version.
Note: The "tmux-openbsd" repository is actually handled by "git cvsimport"
Note: The "tmux-obsd" repository is actually handled by "git cvsimport"
running at 15 minute intervals, so a commit made to OpenBSD's tmux CVS
repository will take at least that long to appear in this git repository.
(It might take longer, depending on the CVS mirror used to import the
@ -34,11 +34,11 @@ this information has ever been set before.
Cloning repositories
====================
This involves having both tmux and tmux-openbsd cloned, as in:
This involves having both tmux and tmux-obsd cloned, as in:
% cd /some/where/useful
% git clone https://github.com/tmux/tmux.git
% git clone https://github.com/ThomasAdam/tmux-openbsd.git
% git clone https://github.com/ThomasAdam/tmux-obsd.git
Note that you do not need additional checkouts to manage the sync -- an
existing clone of either repositories will suffice. So if you already have
@ -47,30 +47,30 @@ these checkouts existing, skip that.
Adding in git-remotes
=====================
Because the portable "tmux" git repository and the "tmux-openbsd"
Because the portable "tmux" git repository and the "tmux-obsd"
repository do not inherently share any history between each other, the
history has been faked between them. This "faking of history" is something
which has to be told to git for the purposes of comparing the "tmux" and
"tmux-openbsd" repositories for syncing. To do this, we must reference the
clone of the "tmux-openbsd" repository from the "tmux" repository, as
"tmux-obsd" repositories for syncing. To do this, we must reference the
clone of the "tmux-obsd" repository from the "tmux" repository, as
shown by the following command:
% cd /path/to/tmux
% git remote add obsd-tmux file:///path/to/tmux-openbsd
% git remote add obsd-tmux file:///path/to/tmux-obsd
So that now, the remote "obsd-tmux" can be used to reference branches and
commits from the "tmux-openbsd" repository, but from the context of the
commits from the "tmux-obsd" repository, but from the context of the
portable "tmux" repository, which makes sense because it's the "tmux"
repository which will have the updates applied to them.
Fetching updates
================
To ensure the latest commits from "tmux-openbsd" can be found from within
"tmux", we have to ensure the "master" branch from "tmux-openbsd" is
To ensure the latest commits from "tmux-obsd" can be found from within
"tmux", we have to ensure the "master" branch from "tmux-obsd" is
up-to-date first, and then reference that update in "tmux", as in:
% cd /path/to/tmux-openbsd
% cd /path/to/tmux-obsd
% git checkout master
% git pull
@ -82,9 +82,9 @@ Then back in "tmux":
Creating the necessary branches
===============================
Now that "tmux" can see commits and branches from "tmux-openbsd" by way
Now that "tmux" can see commits and branches from "tmux-obsd" by way
of the remote name "obsd-tmux", we can now create the master branch from
"tmux-openbsd" in the "tmux" repository:
"tmux-obsd" in the "tmux" repository:
% git checkout -b obsd-master obsd-tmux/master
@ -92,7 +92,7 @@ Adding in the fake history points
=================================
To tie both the "master" branch from "tmux" and the "obsd-master"
branch from "tmux-openbsd" together, the fake history points added to the
branch from "tmux-obsd" together, the fake history points added to the
"tmux" repository need to be added. To do this, we must add an
additional refspec line, as in:

4
cmd.c
View File

@ -636,7 +636,7 @@ cmd_list_free(struct cmd_list *cmdlist)
/* Copy a command list, expanding %s in arguments. */
struct cmd_list *
cmd_list_copy(struct cmd_list *cmdlist, int argc, char **argv)
cmd_list_copy(const struct cmd_list *cmdlist, int argc, char **argv)
{
struct cmd *cmd;
struct cmd_list *new_cmdlist;
@ -667,7 +667,7 @@ cmd_list_copy(struct cmd_list *cmdlist, int argc, char **argv)
/* Get a command list as a string. */
char *
cmd_list_print(struct cmd_list *cmdlist, int escaped)
cmd_list_print(const struct cmd_list *cmdlist, int escaped)
{
struct cmd *cmd, *next;
char *buf, *this;

View File

@ -1119,6 +1119,20 @@ format_cb_cursor_character(struct format_tree *ft)
return (value);
}
/* Callback for cursor_colour. */
static void *
format_cb_cursor_colour(struct format_tree *ft)
{
struct window_pane *wp = ft->wp;
if (wp == NULL || wp->screen == NULL)
return (NULL);
if (wp->screen->ccolour != -1)
return (xstrdup(colour_tostring(wp->screen->ccolour)));
return (xstrdup(colour_tostring(wp->screen->default_ccolour)));
}
/* Callback for mouse_word. */
static void *
format_cb_mouse_word(struct format_tree *ft)
@ -1159,6 +1173,12 @@ format_cb_mouse_hyperlink(struct format_tree *ft)
return (NULL);
if (cmd_mouse_at(wp, &ft->m, &x, &y, 0) != 0)
return (NULL);
if (!TAILQ_EMPTY(&wp->modes)) {
if (window_pane_mode(wp) != WINDOW_PANE_NO_MODE)
return (window_copy_get_hyperlink(wp, x, y));
return (NULL);
}
gd = wp->base.grid;
return (format_grid_hyperlink(gd, x, gd->hsize + y, wp->screen));
}
@ -1593,6 +1613,37 @@ format_cb_cursor_flag(struct format_tree *ft)
return (NULL);
}
/* Callback for cursor_shape. */
static void *
format_cb_cursor_shape(struct format_tree *ft)
{
if (ft->wp != NULL && ft->wp->screen != NULL) {
switch (ft->wp->screen->cstyle) {
case SCREEN_CURSOR_BLOCK:
return (xstrdup("block"));
case SCREEN_CURSOR_UNDERLINE:
return (xstrdup("underline"));
case SCREEN_CURSOR_BAR:
return (xstrdup("bar"));
default:
return (xstrdup("default"));
}
}
return (NULL);
}
/* Callback for cursor_very_visible. */
static void *
format_cb_cursor_very_visible(struct format_tree *ft)
{
if (ft->wp != NULL && ft->wp->screen != NULL) {
if (ft->wp->screen->mode & MODE_CURSOR_VERY_VISIBLE)
return (xstrdup("1"));
return (xstrdup("0"));
}
return (NULL);
}
/* Callback for cursor_x. */
static void *
format_cb_cursor_x(struct format_tree *ft)
@ -1611,6 +1662,18 @@ format_cb_cursor_y(struct format_tree *ft)
return (NULL);
}
/* Callback for cursor_blinking. */
static void *
format_cb_cursor_blinking(struct format_tree *ft)
{
if (ft->wp != NULL && ft->wp->screen != NULL) {
if (ft->wp->screen->mode & MODE_CURSOR_BLINKING)
return (xstrdup("1"));
return (xstrdup("0"));
}
return (NULL);
}
/* Callback for history_limit. */
static void *
format_cb_history_limit(struct format_tree *ft)
@ -2922,12 +2985,24 @@ static const struct format_table_entry format_table[] = {
{ "config_files", FORMAT_TABLE_STRING,
format_cb_config_files
},
{ "cursor_blinking", FORMAT_TABLE_STRING,
format_cb_cursor_blinking
},
{ "cursor_character", FORMAT_TABLE_STRING,
format_cb_cursor_character
},
{ "cursor_colour", FORMAT_TABLE_STRING,
format_cb_cursor_colour
},
{ "cursor_flag", FORMAT_TABLE_STRING,
format_cb_cursor_flag
},
{ "cursor_shape", FORMAT_TABLE_STRING,
format_cb_cursor_shape
},
{ "cursor_very_visible", FORMAT_TABLE_STRING,
format_cb_cursor_very_visible
},
{ "cursor_x", FORMAT_TABLE_STRING,
format_cb_cursor_x
},
@ -5357,9 +5432,14 @@ format_grid_hyperlink(struct grid *gd, u_int x, u_int y, struct screen* s)
const char *uri;
struct grid_cell gc;
grid_get_cell(gd, x, y, &gc);
if (gc.flags & GRID_FLAG_PADDING)
return (NULL);
for (;;) {
grid_get_cell(gd, x, y, &gc);
if (~gc.flags & GRID_FLAG_PADDING)
break;
if (x == 0)
return (NULL);
x--;
}
if (s->hyperlinks == NULL || gc.link == 0)
return (NULL);
if (!hyperlinks_get(s->hyperlinks, gc.link, &uri, NULL, NULL))

View File

@ -58,6 +58,7 @@ struct mode_tree_data {
mode_tree_menu_cb menucb;
mode_tree_height_cb heightcb;
mode_tree_key_cb keycb;
mode_tree_swap_cb swapcb;
struct mode_tree_list children;
struct mode_tree_list saved;
@ -287,6 +288,35 @@ mode_tree_down(struct mode_tree_data *mtd, int wrap)
return (1);
}
static void
mode_tree_swap(struct mode_tree_data *mtd, int direction)
{
u_int current_depth = mtd->line_list[mtd->current].depth;
u_int swap_with, swap_with_depth;
if (mtd->swapcb == NULL)
return;
/* Find the next line at the same depth with the same parent . */
swap_with = mtd->current;
do {
if (direction < 0 && swap_with < (u_int)-direction)
return;
if (direction > 0 && swap_with + direction >= mtd->line_size)
return;
swap_with += direction;
swap_with_depth = mtd->line_list[swap_with].depth;
} while (swap_with_depth > current_depth);
if (swap_with_depth != current_depth)
return;
if (mtd->swapcb(mtd->line_list[mtd->current].item->itemdata,
mtd->line_list[swap_with].item->itemdata)) {
mtd->current = swap_with;
mode_tree_build(mtd);
}
}
void *
mode_tree_get_current(struct mode_tree_data *mtd)
{
@ -410,9 +440,9 @@ struct mode_tree_data *
mode_tree_start(struct window_pane *wp, struct args *args,
mode_tree_build_cb buildcb, mode_tree_draw_cb drawcb,
mode_tree_search_cb searchcb, mode_tree_menu_cb menucb,
mode_tree_height_cb heightcb, mode_tree_key_cb keycb, void *modedata,
const struct menu_item *menu, const char **sort_list, u_int sort_size,
struct screen **s)
mode_tree_height_cb heightcb, mode_tree_key_cb keycb,
mode_tree_swap_cb swapcb, void *modedata, const struct menu_item *menu,
const char **sort_list, u_int sort_size, struct screen **s)
{
struct mode_tree_data *mtd;
const char *sort;
@ -455,6 +485,7 @@ mode_tree_start(struct window_pane *wp, struct args *args,
mtd->menucb = menucb;
mtd->heightcb = heightcb;
mtd->keycb = keycb;
mtd->swapcb = swapcb;
TAILQ_INIT(&mtd->children);
@ -1147,6 +1178,14 @@ mode_tree_key(struct mode_tree_data *mtd, struct client *c, key_code *key,
case 'n'|KEYC_CTRL:
mode_tree_down(mtd, 1);
break;
case KEYC_UP|KEYC_SHIFT:
case 'K':
mode_tree_swap(mtd, -1);
break;
case KEYC_DOWN|KEYC_SHIFT:
case 'J':
mode_tree_swap(mtd, 1);
break;
case KEYC_PPAGE:
case 'b'|KEYC_CTRL:
for (i = 0; i < mtd->height; i++) {

View File

@ -285,6 +285,13 @@ const struct options_table_entry options_table[] = {
.text = "Style of the cursor."
},
{ .name = "default-client-command",
.type = OPTIONS_TABLE_COMMAND,
.scope = OPTIONS_TABLE_SERVER,
.default_str = "new-session",
.text = "Default command to run when tmux is run without a command."
},
{ .name = "default-terminal",
.type = OPTIONS_TABLE_STRING,
.scope = OPTIONS_TABLE_SERVER,

View File

@ -260,6 +260,7 @@ options_default(struct options *oo, const struct options_table_entry *oe)
struct options_entry *o;
union options_value *ov;
u_int i;
struct cmd_parse_result *pr;
o = options_empty(oo, oe);
ov = &o->value;
@ -278,6 +279,17 @@ options_default(struct options *oo, const struct options_table_entry *oe)
case OPTIONS_TABLE_STRING:
ov->string = xstrdup(oe->default_str);
break;
case OPTIONS_TABLE_COMMAND:
pr = cmd_parse_from_string(oe->default_str, NULL);
switch (pr->status) {
case CMD_PARSE_ERROR:
free(pr->error);
break;
case CMD_PARSE_SUCCESS:
ov->cmdlist = pr->cmdlist;
break;
}
break;
default:
ov->number = oe->default_num;
break;
@ -737,6 +749,19 @@ options_get_number(struct options *oo, const char *name)
return (o->value.number);
}
const struct cmd_list *
options_get_command(struct options *oo, const char *name)
{
struct options_entry *o;
o = options_get(oo, name);
if (o == NULL)
fatalx("missing option %s", name);
if (!OPTIONS_IS_COMMAND(o))
fatalx("option %s is not a command", name);
return (o->value.cmdlist);
}
struct options_entry *
options_set_string(struct options *oo, const char *name, int append,
const char *fmt, ...)
@ -798,6 +823,30 @@ options_set_number(struct options *oo, const char *name, long long value)
return (o);
}
struct options_entry *
options_set_command(struct options *oo, const char *name,
struct cmd_list *value)
{
struct options_entry *o;
if (*name == '@')
fatalx("user option %s must be a string", name);
o = options_get_only(oo, name);
if (o == NULL) {
o = options_default(oo, options_parent_table_entry(oo, name));
if (o == NULL)
return (NULL);
}
if (!OPTIONS_IS_COMMAND(o))
fatalx("option %s is not a command", name);
if (o->value.cmdlist != NULL)
cmd_list_free(o->value.cmdlist);
o->value.cmdlist = value;
return (o);
}
int
options_scope_from_name(struct args *args, int window,
const char *name, struct cmd_find_state *fs, struct options **oo,
@ -1054,6 +1103,7 @@ options_from_string(struct options *oo, const struct options_table_entry *oe,
const char *errstr, *new;
char *old;
key_code key;
struct cmd_parse_result *pr;
if (oe != NULL) {
if (value == NULL &&
@ -1112,6 +1162,15 @@ options_from_string(struct options *oo, const struct options_table_entry *oe,
case OPTIONS_TABLE_CHOICE:
return (options_from_string_choice(oe, oo, name, value, cause));
case OPTIONS_TABLE_COMMAND:
pr = cmd_parse_from_string(value, NULL);
switch (pr->status) {
case CMD_PARSE_ERROR:
*cause = pr->error;
return (-1);
case CMD_PARSE_SUCCESS:
options_set_command(oo, name, pr->cmdlist);
return (0);
}
break;
}
return (-1);

View File

@ -3472,6 +3472,7 @@ server_client_dispatch_command(struct client *c, struct imsg *imsg)
struct cmd_parse_result *pr;
struct args_value *values;
struct cmdq_item *new_item;
struct cmd_list *cmdlist;
if (c->flags & CLIENT_EXIT)
return;
@ -3492,33 +3493,33 @@ server_client_dispatch_command(struct client *c, struct imsg *imsg)
}
if (argc == 0) {
argc = 1;
argv = xcalloc(1, sizeof *argv);
*argv = xstrdup("new-session");
cmdlist = cmd_list_copy(options_get_command(global_options,
"default-client-command"), 0, NULL);
} else {
values = args_from_vector(argc, argv);
pr = cmd_parse_from_arguments(values, argc, NULL);
switch (pr->status) {
case CMD_PARSE_ERROR:
cause = pr->error;
goto error;
case CMD_PARSE_SUCCESS:
break;
}
args_free_values(values, argc);
free(values);
cmd_free_argv(argc, argv);
cmdlist = pr->cmdlist;
}
values = args_from_vector(argc, argv);
pr = cmd_parse_from_arguments(values, argc, NULL);
switch (pr->status) {
case CMD_PARSE_ERROR:
cause = pr->error;
goto error;
case CMD_PARSE_SUCCESS:
break;
}
args_free_values(values, argc);
free(values);
cmd_free_argv(argc, argv);
if ((c->flags & CLIENT_READONLY) &&
!cmd_list_all_have(pr->cmdlist, CMD_READONLY))
!cmd_list_all_have(cmdlist, CMD_READONLY))
new_item = cmdq_get_callback(server_client_read_only, NULL);
else
new_item = cmdq_get_command(pr->cmdlist, NULL);
new_item = cmdq_get_command(cmdlist, NULL);
cmdq_append(c, new_item);
cmdq_append(c, cmdq_get_callback(server_client_command_done, NULL));
cmd_list_free(pr->cmdlist);
cmd_list_free(cmdlist);
return;
error:

17
tmux.1
View File

@ -254,9 +254,10 @@ was given) and off.
This specifies one of a set of commands used to control
.Nm ,
as described in the following sections.
If no commands are specified, the
.Ic new-session
command is assumed.
If no commands are specified, the command in
.Ic default-client-command
is assumed, which defaults to
.Ic new-session .
.El
.Sh DEFAULT KEY BINDINGS
.Nm
@ -2715,6 +2716,8 @@ The following keys may be used in tree mode:
.It Li "Enter" Ta "Choose selected item"
.It Li "Up" Ta "Select previous item"
.It Li "Down" Ta "Select next item"
.It Li "S-Up" Ta "Swap the current window with the previous one"
.It Li "S-Down" Ta "Swap the current window with the next one"
.It Li "+" Ta "Expand selected item"
.It Li "-" Ta "Collapse selected item"
.It Li "M-+" Ta "Expand all items"
@ -4083,6 +4086,10 @@ where the number is a hexadecimal number.
Give the command to pipe to if the
.Ic copy-pipe
copy mode command is used without arguments.
.It Ic default-client-command Ar command
Set the default command to run when tmux is called without a command.
The default is
.Ic new-session .
.It Ic default-terminal Ar terminal
Set the default terminal for new windows created in this session - the
default value of the
@ -5944,6 +5951,7 @@ The following variables are available, where appropriate:
.It Li "command_list_name" Ta "" Ta "Command name if listing commands"
.It Li "command_list_usage" Ta "" Ta "Command usage if listing commands"
.It Li "config_files" Ta "" Ta "List of configuration files loaded"
.It Li "cursor_blinking" Ta "" Ta "1 if the cursor is blinking"
.It Li "copy_cursor_hyperlink" Ta "" Ta "Hyperlink under cursor in copy mode"
.It Li "copy_cursor_line" Ta "" Ta "Line the cursor is on in copy mode"
.It Li "copy_cursor_word" Ta "" Ta "Word under cursor in copy mode"
@ -5951,7 +5959,10 @@ The following variables are available, where appropriate:
.It Li "copy_cursor_y" Ta "" Ta "Cursor Y position in copy mode"
.It Li "current_file" Ta "" Ta "Current configuration file"
.It Li "cursor_character" Ta "" Ta "Character at cursor in pane"
.It Li "cursor_colour" Ta "" Ta "Cursor colour in pane"
.It Li "cursor_flag" Ta "" Ta "Pane cursor flag"
.It Li "cursor_shape" Ta "" Ta "Cursor shape in pane"
.It Li "cursor_very_visible" Ta "" Ta "1 if the cursor is in very visible mode"
.It Li "cursor_x" Ta "" Ta "Cursor X position in pane"
.It Li "cursor_y" Ta "" Ta "Cursor Y position in pane"
.It Li "history_bytes" Ta "" Ta "Number of bytes in window history"

17
tmux.h
View File

@ -2394,10 +2394,13 @@ struct options_entry *options_match_get(struct options *, const char *, int *,
int, int *);
const char *options_get_string(struct options *, const char *);
long long options_get_number(struct options *, const char *);
const struct cmd_list *options_get_command(struct options *, const char *);
struct options_entry * printflike(4, 5) options_set_string(struct options *,
const char *, int, const char *, ...);
struct options_entry *options_set_number(struct options *, const char *,
long long);
struct options_entry *options_set_command(struct options *, const char *,
struct cmd_list *);
int options_scope_from_name(struct args *, int,
const char *, struct cmd_find_state *, struct options **,
char **);
@ -2681,12 +2684,12 @@ struct cmd *cmd_copy(struct cmd *, int, char **);
void cmd_free(struct cmd *);
char *cmd_print(struct cmd *);
struct cmd_list *cmd_list_new(void);
struct cmd_list *cmd_list_copy(struct cmd_list *, int, char **);
struct cmd_list *cmd_list_copy(const struct cmd_list *, int, char **);
void cmd_list_append(struct cmd_list *, struct cmd *);
void cmd_list_append_all(struct cmd_list *, struct cmd_list *);
void cmd_list_move(struct cmd_list *, struct cmd_list *);
void cmd_list_free(struct cmd_list *);
char *cmd_list_print(struct cmd_list *, int);
char *cmd_list_print(const struct cmd_list *, int);
struct cmd *cmd_list_first(struct cmd_list *);
struct cmd *cmd_list_next(struct cmd *);
int cmd_list_all_have(struct cmd_list *, int);
@ -2949,8 +2952,6 @@ void input_parse_screen(struct input_ctx *, struct screen *,
void input_reply_clipboard(struct bufferevent *, const char *, size_t,
const char *);
void input_set_buffer_size(size_t);
int input_get_bg_client(struct window_pane *);
int input_get_bg_control_client(struct window_pane *);
/* input-key.c */
void input_key_build(void);
@ -3327,6 +3328,7 @@ typedef int (*mode_tree_search_cb)(void *, void *, const char *);
typedef void (*mode_tree_menu_cb)(void *, struct client *, key_code);
typedef u_int (*mode_tree_height_cb)(void *, u_int);
typedef key_code (*mode_tree_key_cb)(void *, void *, u_int);
typedef int (*mode_tree_swap_cb)(void *, void *);
typedef void (*mode_tree_each_cb)(void *, void *, struct client *, key_code);
u_int mode_tree_count_tagged(struct mode_tree_data *);
void *mode_tree_get_current(struct mode_tree_data *);
@ -3341,8 +3343,9 @@ void mode_tree_up(struct mode_tree_data *, int);
int mode_tree_down(struct mode_tree_data *, int);
struct mode_tree_data *mode_tree_start(struct window_pane *, struct args *,
mode_tree_build_cb, mode_tree_draw_cb, mode_tree_search_cb,
mode_tree_menu_cb, mode_tree_height_cb, mode_tree_key_cb, void *,
const struct menu_item *, const char **, u_int, struct screen **);
mode_tree_menu_cb, mode_tree_height_cb, mode_tree_key_cb,
mode_tree_swap_cb, void *, const struct menu_item *, const char **,
u_int, struct screen **);
void mode_tree_zoom(struct mode_tree_data *, struct args *);
void mode_tree_build(struct mode_tree_data *);
void mode_tree_free(struct mode_tree_data *);
@ -3387,6 +3390,7 @@ char *window_copy_get_word(struct window_pane *, u_int, u_int);
char *window_copy_get_line(struct window_pane *, u_int);
int window_copy_get_current_offset(struct window_pane *, u_int *,
u_int *);
char *window_copy_get_hyperlink(struct window_pane *, u_int, u_int);
/* window-option.c */
extern const struct window_mode window_customize_mode;
@ -3476,7 +3480,6 @@ void session_theme_changed(struct session *);
/* utf8.c */
enum utf8_state utf8_towc (const struct utf8_data *, wchar_t *);
enum utf8_state utf8_fromwc(wchar_t wc, struct utf8_data *);
int utf8_in_table(wchar_t, const wchar_t *, u_int);
void utf8_update_width_cache(void);
utf8_char utf8_build_one(u_char);
enum utf8_state utf8_from_data(const struct utf8_data *, utf8_char *);

View File

@ -937,6 +937,11 @@ partial_key:
delay = options_get_number(global_options, "escape-time");
if (delay == 0)
delay = 1;
if ((tty->flags & TTY_ALL_REQUEST_FLAGS) != TTY_ALL_REQUEST_FLAGS) {
log_debug("%s: increasing delay for active DA query", c->name);
if (delay < 500)
delay = 500;
}
tv.tv_sec = delay / 1000;
tv.tv_usec = (delay % 1000) * 1000L;

View File

@ -350,7 +350,7 @@ window_buffer_init(struct window_mode_entry *wme, struct cmd_find_state *fs,
data->data = mode_tree_start(wp, args, window_buffer_build,
window_buffer_draw, window_buffer_search, window_buffer_menu, NULL,
window_buffer_get_key, data, window_buffer_menu_items,
window_buffer_get_key, NULL, data, window_buffer_menu_items,
window_buffer_sort_list, nitems(window_buffer_sort_list), &s);
mode_tree_zoom(data->data, args);

View File

@ -310,7 +310,7 @@ window_client_init(struct window_mode_entry *wme,
data->data = mode_tree_start(wp, args, window_client_build,
window_client_draw, NULL, window_client_menu, NULL,
window_client_get_key, data, window_client_menu_items,
window_client_get_key, NULL, data, window_client_menu_items,
window_client_sort_list, nitems(window_client_sort_list), &s);
mode_tree_zoom(data->data, args);

View File

@ -884,6 +884,16 @@ window_copy_get_line(struct window_pane *wp, u_int y)
return (format_grid_line(gd, gd->hsize + y));
}
char *
window_copy_get_hyperlink(struct window_pane *wp, u_int x, u_int y)
{
struct window_mode_entry *wme = TAILQ_FIRST(&wp->modes);
struct window_copy_mode_data *data = wme->data;
struct grid *gd = data->screen.grid;
return (format_grid_hyperlink(gd, x, gd->hsize + y, wp->screen));
}
static void *
window_copy_cursor_hyperlink_cb(struct format_tree *ft)
{
@ -4263,6 +4273,8 @@ window_copy_match_at_cursor(struct window_copy_mode_data *data)
buf = xrealloc(buf, len + 2);
buf[len] = '\t';
len++;
} else if (gc.flags & GRID_FLAG_PADDING) {
/* nothing to do */
} else {
buf = xrealloc(buf, len + gc.data.size + 1);
memcpy(buf + len, gc.data.data, gc.data.size);

View File

@ -891,8 +891,8 @@ window_customize_init(struct window_mode_entry *wme, struct cmd_find_state *fs,
data->data = mode_tree_start(wp, args, window_customize_build,
window_customize_draw, NULL, window_customize_menu,
window_customize_height, NULL, data, window_customize_menu_items,
NULL, 0, &s);
window_customize_height, NULL, NULL, data,
window_customize_menu_items, NULL, 0, &s);
mode_tree_zoom(data->data, args);
mode_tree_build(data->data);

View File

@ -302,6 +302,7 @@ window_tree_build_pane(struct session *s, struct winlink *wl,
struct window_tree_itemdata *item;
char *name, *text;
u_int idx;
struct format_tree *ft;
window_pane_index(wp, &idx);
@ -311,8 +312,11 @@ window_tree_build_pane(struct session *s, struct winlink *wl,
item->winlink = wl->idx;
item->pane = wp->id;
text = format_single(NULL, data->format, NULL, s, wl, wp);
ft = format_create(NULL, NULL, FORMAT_PANE|wp->id, 0);
format_defaults(ft, NULL, s, wl, wp);
text = format_expand(ft, data->format);
xasprintf(&name, "%u", idx);
format_free(ft);
mode_tree_add(data->data, parent, item, (uint64_t)wp, name, text, -1);
free(text);
@ -348,6 +352,7 @@ window_tree_build_window(struct session *s, struct winlink *wl,
struct window_pane *wp, **l;
u_int n, i;
int expanded;
struct format_tree *ft;
item = window_tree_add_item(data);
item->type = WINDOW_TREE_WINDOW;
@ -355,8 +360,11 @@ window_tree_build_window(struct session *s, struct winlink *wl,
item->winlink = wl->idx;
item->pane = -1;
text = format_single(NULL, data->format, NULL, s, wl, NULL);
ft = format_create(NULL, NULL, FORMAT_PANE|wl->window->active->id, 0);
format_defaults(ft, NULL, s, wl, NULL);
text = format_expand(ft, data->format);
xasprintf(&name, "%u", wl->idx);
format_free(ft);
if (data->type == WINDOW_TREE_SESSION ||
data->type == WINDOW_TREE_WINDOW)
@ -373,7 +381,6 @@ window_tree_build_window(struct session *s, struct winlink *wl,
if (TAILQ_NEXT(wp, entry) == NULL) {
if (!window_tree_filter_pane(s, wl, wp, filter))
goto empty;
return (1);
}
l = NULL;
@ -411,9 +418,10 @@ window_tree_build_session(struct session *s, void *modedata,
struct window_tree_itemdata *item;
struct mode_tree_item *mti;
char *text;
struct winlink *wl, **l;
struct winlink *wl = s->curw, **l;
u_int n, i, empty;
int expanded;
struct format_tree *ft;
item = window_tree_add_item(data);
item->type = WINDOW_TREE_SESSION;
@ -421,7 +429,10 @@ window_tree_build_session(struct session *s, void *modedata,
item->winlink = -1;
item->pane = -1;
text = format_single(NULL, data->format, NULL, s, NULL, NULL);
ft = format_create(NULL, NULL, FORMAT_PANE|wl->window->active->id, 0);
format_defaults(ft, NULL, s, NULL, NULL);
text = format_expand(ft, data->format);
format_free(ft);
if (data->type == WINDOW_TREE_SESSION)
expanded = 0;
@ -902,6 +913,58 @@ window_tree_get_key(void *modedata, void *itemdata, u_int line)
return (key);
}
static int
window_tree_swap(void *cur_itemdata, void *other_itemdata)
{
struct window_tree_itemdata *cur = cur_itemdata;
struct window_tree_itemdata *other = other_itemdata;
struct session *cur_session, *other_session;
struct winlink *cur_winlink, *other_winlink;
struct window *cur_window, *other_window;
struct window_pane *cur_pane, *other_pane;
if (cur->type != other->type)
return (0);
if (cur->type != WINDOW_TREE_WINDOW)
return (0);
window_tree_pull_item(cur, &cur_session, &cur_winlink, &cur_pane);
window_tree_pull_item(other, &other_session, &other_winlink,
&other_pane);
if (cur_session != other_session)
return (0);
if (window_tree_sort->field != WINDOW_TREE_BY_INDEX &&
window_tree_cmp_window(&cur_winlink, &other_winlink) != 0) {
/*
* Swapping indexes would not swap positions in the tree, so
* prevent swapping to avoid confusing the user.
*/
return (0);
}
other_window = other_winlink->window;
TAILQ_REMOVE(&other_window->winlinks, other_winlink, wentry);
cur_window = cur_winlink->window;
TAILQ_REMOVE(&cur_window->winlinks, cur_winlink, wentry);
other_winlink->window = cur_window;
TAILQ_INSERT_TAIL(&cur_window->winlinks, other_winlink, wentry);
cur_winlink->window = other_window;
TAILQ_INSERT_TAIL(&other_window->winlinks, cur_winlink, wentry);
if (cur_session->curw == cur_winlink)
session_set_current(cur_session, other_winlink);
else if (cur_session->curw == other_winlink)
session_set_current(cur_session, cur_winlink);
session_group_synchronize_from(cur_session);
server_redraw_session_group(cur_session);
recalculate_sizes();
return (1);
}
static struct screen *
window_tree_init(struct window_mode_entry *wme, struct cmd_find_state *fs,
struct args *args)
@ -940,7 +1003,7 @@ window_tree_init(struct window_mode_entry *wme, struct cmd_find_state *fs,
data->data = mode_tree_start(wp, args, window_tree_build,
window_tree_draw, window_tree_search, window_tree_menu, NULL,
window_tree_get_key, data, window_tree_menu_items,
window_tree_get_key, window_tree_swap, data, window_tree_menu_items,
window_tree_sort_list, nitems(window_tree_sort_list), &s);
mode_tree_zoom(data->data, args);