Merge branch 'master' into feature-floating-window-panes

This commit is contained in:
Michael Grant
2026-01-07 23:41:29 +01:00
committed by GitHub
22 changed files with 261 additions and 79 deletions

View File

@@ -924,6 +924,7 @@ cmd_find_target(struct cmd_find_state *fs, struct cmdq_item *item,
const char *target, enum cmd_find_type type, int flags)
{
struct mouse_event *m;
struct client *c;
struct cmd_find_state current;
char *colon, *period, *copy = NULL, tmp[256];
const char *session, *window, *pane, *s;
@@ -995,6 +996,20 @@ cmd_find_target(struct cmd_find_state *fs, struct cmdq_item *item,
if (target == NULL || *target == '\0')
goto current;
if (strcmp(target, "@") == 0 ||
strcmp(target, "{active}") == 0 ||
strcmp(target, "{current}") == 0) {
c = cmdq_get_client(item);
if (c == NULL) {
cmdq_error(item, "no current client");
goto error;
}
fs->wl = c->session->curw;
fs->wp = c->session->curw->window->active;
fs->w = c->session->curw->window;
goto found;
}
/* Mouse target is a plain = or {mouse}. */
if (strcmp(target, "=") == 0 || strcmp(target, "{mouse}") == 0) {
m = &cmdq_get_event(item)->m;

View File

@@ -109,7 +109,8 @@ cmd_list_keys_print_notes(struct cmdq_item *item, struct args *args,
key = key_string_lookup_key(bd->key, 0);
if (bd->note == NULL || *bd->note == '\0')
note = cmd_list_print(bd->cmdlist, 1);
note = cmd_list_print(bd->cmdlist,
CMD_LIST_PRINT_ESCAPED|CMD_LIST_PRINT_NO_GROUPS);
else
note = xstrdup(bd->note);
tmp = utf8_padcstr(key, keywidth + 1);
@@ -288,7 +289,8 @@ cmd_list_keys_exec(struct cmd *self, struct cmdq_item *item)
tmpused = strlcat(tmp, " ", tmpsize);
free(cp);
cp = cmd_list_print(bd->cmdlist, 1);
cp = cmd_list_print(bd->cmdlist,
CMD_LIST_PRINT_ESCAPED|CMD_LIST_PRINT_NO_GROUPS);
cplen = strlen(cp);
while (tmpused + cplen + 1 >= tmpsize) {
tmpsize *= 2;

23
cmd.c
View File

@@ -682,11 +682,16 @@ cmd_list_copy(const struct cmd_list *cmdlist, int argc, char **argv)
/* Get a command list as a string. */
char *
cmd_list_print(const struct cmd_list *cmdlist, int escaped)
cmd_list_print(const struct cmd_list *cmdlist, int flags)
{
struct cmd *cmd, *next;
char *buf, *this;
size_t len;
const char *separator;
int escaped = flags & CMD_LIST_PRINT_ESCAPED;
int no_groups = flags & CMD_LIST_PRINT_NO_GROUPS;
const char *single_separator = escaped ? " \\; " : " ; ";
const char *double_separator = escaped ? " \\;\\; " : " ;; ";
len = 1;
buf = xcalloc(1, len);
@@ -701,17 +706,11 @@ cmd_list_print(const struct cmd_list *cmdlist, int escaped)
next = TAILQ_NEXT(cmd, qentry);
if (next != NULL) {
if (cmd->group != next->group) {
if (escaped)
strlcat(buf, " \\;\\; ", len);
else
strlcat(buf, " ;; ", len);
} else {
if (escaped)
strlcat(buf, " \\; ", len);
else
strlcat(buf, " ; ", len);
}
if (!no_groups && cmd->group != next->group)
separator = double_separator;
else
separator = single_separator;
strlcat(buf, separator, len);
}
free(this);

View File

@@ -1,4 +1,4 @@
/* $OpenBSD: imsg-buffer.c,v 1.35 2025/06/04 09:06:56 claudio Exp $ */
/* $OpenBSD: imsg-buffer.c,v 1.36 2025/08/25 08:29:49 claudio Exp $ */
/*
* Copyright (c) 2023 Claudio Jeker <claudio@openbsd.org>
@@ -699,8 +699,6 @@ msgbuf_queuelen(struct msgbuf *msgbuf)
void
msgbuf_clear(struct msgbuf *msgbuf)
{
struct ibuf *buf;
/* write side */
ibufq_flush(&msgbuf->bufs);

View File

@@ -4464,7 +4464,9 @@ format_loop_sessions(struct format_expand_state *es, const char *fmt)
for (i = 0; i < n; i++) {
s = l[i];
format_log(es, "session loop: $%u", s->id);
if (active != NULL && s->id == ft->c->session->id)
if (active != NULL &&
ft->c != NULL &&
s->id == ft->c->session->id)
use = active;
else
use = all;

6
grid.c
View File

@@ -361,9 +361,13 @@ grid_compare(struct grid *ga, struct grid *gb)
static void
grid_trim_history(struct grid *gd, u_int ny)
{
u_int remaining;
grid_free_lines(gd, 0, ny);
remaining = gd->hsize + gd->sy - ny;
memmove(&gd->linedata[0], &gd->linedata[ny],
(gd->hsize + gd->sy - ny) * (sizeof *gd->linedata));
remaining * (sizeof *gd->linedata));
memset(&gd->linedata[remaining], 0, ny * (sizeof *gd->linedata));
}
/*

View File

@@ -313,12 +313,6 @@ static struct input_key_entry input_key_defaults[] = {
{ .key = KEYC_DC|KEYC_BUILD_MODIFIERS,
.data = "\033[3;_~"
},
{ .key = KEYC_REPORT_DARK_THEME,
.data = "\033[?997;1n"
},
{ .key = KEYC_REPORT_LIGHT_THEME,
.data = "\033[?997;2n"
},
};
static const key_code input_key_modifiers[] = {
0,

34
input.c
View File

@@ -63,7 +63,7 @@ struct input_request {
struct input_ctx *ictx;
enum input_request_type type;
time_t t;
uint64_t t;
enum input_end_type end;
int idx;
@@ -72,7 +72,7 @@ struct input_request {
TAILQ_ENTRY(input_request) entry;
TAILQ_ENTRY(input_request) centry;
};
#define INPUT_REQUEST_TIMEOUT 2
#define INPUT_REQUEST_TIMEOUT 500
/* Input parser cell. */
struct input_cell {
@@ -1902,6 +1902,8 @@ input_csi_dispatch_rm_private(struct input_ctx *ictx)
break;
case 2031:
screen_write_mode_clear(sctx, MODE_THEME_UPDATES);
if (ictx->wp != NULL)
ictx->wp->flags &= ~PANE_THEMECHANGED;
break;
case 2026: /* synchronized output */
screen_write_stop_sync(ictx->wp);
@@ -2005,6 +2007,10 @@ input_csi_dispatch_sm_private(struct input_ctx *ictx)
break;
case 2031:
screen_write_mode_set(sctx, MODE_THEME_UPDATES);
if (ictx->wp != NULL) {
ictx->wp->last_theme = window_pane_get_theme(ictx->wp);
ictx->wp->flags &= ~PANE_THEMECHANGED;
}
break;
case 2026: /* synchronized output */
screen_write_start_sync(ictx->wp);
@@ -3237,7 +3243,7 @@ input_request_timer_callback(__unused int fd, __unused short events, void *arg)
{
struct input_ctx *ictx = arg;
struct input_request *ir, *ir1;
time_t t = time(NULL);
uint64_t t = get_timer();
TAILQ_FOREACH_SAFE(ir, &ictx->requests, entry, ir1) {
if (ir->t >= t - INPUT_REQUEST_TIMEOUT)
@@ -3254,7 +3260,7 @@ input_request_timer_callback(__unused int fd, __unused short events, void *arg)
static void
input_start_request_timer(struct input_ctx *ictx)
{
struct timeval tv = { .tv_sec = 0, .tv_usec = 500000 };
struct timeval tv = { .tv_sec = 0, .tv_usec = 100000 };
event_del(&ictx->request_timer);
event_add(&ictx->request_timer, &tv);
@@ -3269,7 +3275,7 @@ input_make_request(struct input_ctx *ictx, enum input_request_type type)
ir = xcalloc (1, sizeof *ir);
ir->type = type;
ir->ictx = ictx;
ir->t = time(NULL);
ir->t = get_timer();
if (++ictx->request_count == 1)
input_start_request_timer(ictx);
@@ -3390,7 +3396,11 @@ input_request_reply(struct client *c, enum input_request_type type, void *data)
input_free_request(ir);
continue;
}
if (type == INPUT_REQUEST_PALETTE && pd->idx == ir->idx) {
if (type == INPUT_REQUEST_PALETTE) {
if (pd->idx != ir->idx) {
input_free_request(ir);
continue;
}
found = ir;
break;
}
@@ -3432,14 +3442,24 @@ input_cancel_requests(struct client *c)
static void
input_report_current_theme(struct input_ctx *ictx)
{
switch (window_pane_get_theme(ictx->wp)) {
struct window_pane *wp = ictx->wp;
if (wp != NULL) {
wp->last_theme = window_pane_get_theme(wp);
wp->flags &= ~PANE_THEMECHANGED;
switch (wp->last_theme) {
case THEME_DARK:
log_debug("%s: %%%u dark theme", __func__, wp->id);
input_reply(ictx, 0, "\033[?997;1n");
break;
case THEME_LIGHT:
log_debug("%s: %%%u light theme", __func__, wp->id);
input_reply(ictx, 0, "\033[?997;2n");
break;
case THEME_UNKNOWN:
log_debug("%s: %%%u unknown theme", __func__, wp->id);
break;
}
}
}

View File

@@ -444,6 +444,7 @@ key_bindings_init(void)
/* Mouse button 1 down on pane. */
"bind -n MouseDown1Pane { select-pane -t=; send -M }",
"bind -n C-MouseDown1Pane { swap-pane -s@ }",
/* Mouse button 1 drag on pane. */
"bind -n MouseDrag1Pane { if -F '#{||:#{pane_in_mode},#{mouse_any_flag}}' { send -M } { copy-mode -M } }",
@@ -468,6 +469,7 @@ key_bindings_init(void)
/* Mouse button 1 down on status line. */
"bind -n MouseDown1Status { switch-client -t= }",
"bind -n C-MouseDown1Status { swap-window -t@ }",
/* Mouse wheel down on status line. */
"bind -n WheelDownStatus { next-window }",

View File

@@ -382,6 +382,14 @@ key_string_lookup_key(key_code key, int with_flags)
s = "PasteEnd";
goto append;
}
if (key == KEYC_REPORT_DARK_THEME) {
s = "ReportDarkTheme";
goto append;
}
if (key == KEYC_REPORT_LIGHT_THEME) {
s = "ReportLightTheme";
goto append;
}
if (key == KEYC_MOUSE) {
s = "Mouse";
goto append;

View File

@@ -664,6 +664,13 @@ const struct options_table_entry options_table[] = {
.text = "Time for which status line messages should appear."
},
{ .name = "focus-follows-mouse",
.type = OPTIONS_TABLE_FLAG,
.scope = OPTIONS_TABLE_SESSION,
.default_num = 0,
.text = "Whether moving the mouse into a pane selects it."
},
{ .name = "history-limit",
.type = OPTIONS_TABLE_NUMBER,
.scope = OPTIONS_TABLE_SESSION,
@@ -970,6 +977,15 @@ const struct options_table_entry options_table[] = {
.text = "Style of the cursor when in the command prompt."
},
{ .name = "prompt-command-cursor-style",
.type = OPTIONS_TABLE_CHOICE,
.scope = OPTIONS_TABLE_SESSION,
.choices = options_table_cursor_style_list,
.default_num = 0,
.text = "Style of the cursor in the command prompt when in command "
"mode, if 'status-keys' is set to 'vi'."
},
{ .name = "session-status-current-style",
.type = OPTIONS_TABLE_STRING,
.scope = OPTIONS_TABLE_WINDOW,

View File

@@ -749,7 +749,7 @@ options_get_number(struct options *oo, const char *name)
return (o->value.number);
}
const struct cmd_list *
struct cmd_list *
options_get_command(struct options *oo, const char *name)
{
struct options_entry *o;

View File

@@ -61,9 +61,9 @@ screen_write_get_citem(void)
ci = TAILQ_FIRST(&screen_write_citem_freelist);
if (ci != NULL) {
TAILQ_REMOVE(&screen_write_citem_freelist, ci, entry);
memset(ci, 0, sizeof *ci);
return (ci);
TAILQ_REMOVE(&screen_write_citem_freelist, ci, entry);
memset(ci, 0, sizeof *ci);
return (ci);
}
return (xcalloc(1, sizeof *ci));
}
@@ -71,7 +71,7 @@ screen_write_get_citem(void)
static void
screen_write_free_citem(struct screen_write_citem *ci)
{
TAILQ_INSERT_TAIL(&screen_write_citem_freelist, ci, entry);
TAILQ_INSERT_TAIL(&screen_write_citem_freelist, ci, entry);
}
static void
@@ -1833,8 +1833,16 @@ screen_write_collect_flush(struct screen_write_ctx *ctx, int scroll_only,
struct visible_ranges *vr;
struct window_pane *wp = ctx->wp;
if (s->mode & MODE_SYNC)
if (s->mode & MODE_SYNC) {
for (y = 0; y < screen_size_y(s); y++) {
cl = &ctx->s->write_list[y];
TAILQ_FOREACH_SAFE(ci, &cl->items, entry, tmp) {
TAILQ_REMOVE(&cl->items, ci, entry);
screen_write_free_citem(ci);
}
}
return;
}
if (ctx->scrolled != 0) {
log_debug("%s: scrolled %u (region %u-%u)", __func__,
@@ -1945,7 +1953,7 @@ void
screen_write_collect_end(struct screen_write_ctx *ctx)
{
struct screen *s = ctx->s;
struct screen_write_citem *ci = ctx->item, *before;
struct screen_write_citem *ci = ctx->item, *nci, *before;
struct screen_write_cline *cl = &s->write_list[s->cy];
struct grid_cell gc;
u_int xx;
@@ -1974,6 +1982,8 @@ screen_write_collect_end(struct screen_write_ctx *ctx)
break;
grid_view_set_cell(s->grid, xx, s->cy,
&grid_default_cell);
log_debug("%s: padding erased (before) at %u",
__func__, xx);
}
if (xx != s->cx) {
if (xx == 0)
@@ -1981,8 +1991,19 @@ screen_write_collect_end(struct screen_write_ctx *ctx)
if (gc.data.width > 1) {
grid_view_set_cell(s->grid, xx, s->cy,
&grid_default_cell);
log_debug("%s: padding erased (before) at %u",
__func__, xx);
}
}
if (xx != s->cx) {
nci = ctx->item;
nci->type = CLEAR;
nci->x = xx;
nci->bg = 8;
nci->used = s->cx - xx;
TAILQ_INSERT_BEFORE(ci, nci, entry);
ctx->item = screen_write_get_citem();
}
}
#ifdef ENABLE_SIXEL
@@ -1999,6 +2020,16 @@ screen_write_collect_end(struct screen_write_ctx *ctx)
if (~gc.flags & GRID_FLAG_PADDING)
break;
grid_view_set_cell(s->grid, xx, s->cy, &grid_default_cell);
log_debug("%s: padding erased (after) at %u", __func__, xx);
}
if (xx != s->cx) {
nci = ctx->item;
nci->type = CLEAR;
nci->x = s->cx;
nci->bg = 8;
nci->used = xx - s->cx;
TAILQ_INSERT_AFTER(&cl->items, ci, nci, entry);
ctx->item = screen_write_get_citem();
}
}
@@ -2069,7 +2100,7 @@ screen_write_cell(struct screen_write_ctx *ctx, const struct grid_cell *gc)
struct tty_ctx ttyctx;
u_int sx = screen_size_x(s), sy = screen_size_y(s);
u_int width = ud->width, xx, not_wrap;
int selected, skip = 1;
int selected, skip = 1, redraw = 0;
/* Ignore padding cells. */
if (gc->flags & GRID_FLAG_PADDING)
@@ -2111,8 +2142,10 @@ screen_write_cell(struct screen_write_ctx *ctx, const struct grid_cell *gc)
gl = grid_get_line(s->grid, s->grid->hsize + s->cy);
if (gl->flags & GRID_LINE_EXTENDED) {
grid_view_get_cell(gd, s->cx, s->cy, &now_gc);
if (screen_write_overwrite(ctx, &now_gc, width))
if (screen_write_overwrite(ctx, &now_gc, width)) {
redraw = 1;
skip = 0;
}
}
/*
@@ -2189,6 +2222,7 @@ screen_write_cell(struct screen_write_ctx *ctx, const struct grid_cell *gc)
ttyctx.cell = &tmp_gc;
} else
ttyctx.cell = gc;
ttyctx.num = redraw ? 2 : 0;
tty_write(tty_cmd_cell, &ttyctx);
}
}
@@ -2483,8 +2517,10 @@ screen_write_alternateon(struct screen_write_ctx *ctx, struct grid_cell *gc,
screen_write_collect_flush(ctx, 0, __func__);
screen_alternate_on(ctx->s, gc, cursor);
if (wp != NULL)
if (wp != NULL) {
layout_fix_panes(wp->window, NULL);
server_redraw_window_borders(wp->window);
}
screen_write_initctx(ctx, &ttyctx, 1);
if (ttyctx.redraw_cb != NULL)
@@ -2505,8 +2541,10 @@ screen_write_alternateoff(struct screen_write_ctx *ctx, struct grid_cell *gc,
screen_write_collect_flush(ctx, 0, __func__);
screen_alternate_off(ctx->s, gc, cursor);
if (wp != NULL)
if (wp != NULL) {
layout_fix_panes(wp->window, NULL);
server_redraw_window_borders(wp->window);
}
screen_write_initctx(ctx, &ttyctx, 1);
if (ttyctx.redraw_cb != NULL)

View File

@@ -765,6 +765,8 @@ screen_mode_to_string(int mode)
strlcat(tmp, "KEYS_EXTENDED,", sizeof tmp);
if (mode & MODE_KEYS_EXTENDED_2)
strlcat(tmp, "KEYS_EXTENDED_2,", sizeof tmp);
if (mode & MODE_THEME_UPDATES)
strlcat(tmp, "THEME_UPDATES,", sizeof tmp);
tmp[strlen(tmp) - 1] = '\0';
return (tmp);
}

View File

@@ -1092,8 +1092,16 @@ have_event:
case NOTYPE:
break;
case MOVE:
if (where == PANE)
if (where == PANE) {
key = KEYC_MOUSEMOVE_PANE;
if (wp != NULL &&
wp != w->active &&
options_get_number(s->options, "focus-follows-mouse")) {
window_set_active_pane(w, wp, 1);
server_redraw_window_borders(w);
server_status_window(w);
}
}
if (where == STATUS)
key = KEYC_MOUSEMOVE_STATUS;
if (where == STATUS_LEFT)
@@ -3012,7 +3020,8 @@ server_client_reset_state(struct client *c)
/*
* Set mouse mode if requested. To support dragging, always use button
* mode.
* mode. For focus-follows-mouse, we need all-motion mode to receive
* movement events.
*/
if (options_get_number(oo, "mouse")) {
if (c->overlay_draw == NULL) {
@@ -3022,7 +3031,9 @@ server_client_reset_state(struct client *c)
mode |= MODE_MOUSE_ALL;
}
}
if (~mode & MODE_MOUSE_ALL)
if (options_get_number(oo, "focus-follows-mouse"))
mode |= MODE_MOUSE_ALL;
else if (~mode & MODE_MOUSE_ALL)
mode |= MODE_MOUSE_BUTTON;
}
@@ -3475,6 +3486,24 @@ server_client_read_only(struct cmdq_item *item, __unused void *data)
return (CMD_RETURN_ERROR);
}
/* Callback for default command. */
static enum cmd_retval
server_client_default_command(struct cmdq_item *item, __unused void *data)
{
struct client *c = cmdq_get_client(item);
struct cmd_list *cmdlist;
struct cmdq_item *new_item;
cmdlist = options_get_command(global_options, "default-client-command");
if ((c->flags & CLIENT_READONLY) &&
!cmd_list_all_have(cmdlist, CMD_READONLY))
new_item = cmdq_get_callback(server_client_read_only, NULL);
else
new_item = cmdq_get_command(cmdlist, NULL);
cmdq_insert_after(item, new_item);
return (CMD_RETURN_NORMAL);
}
/* Callback when command is done. */
static enum cmd_retval
server_client_command_done(struct cmdq_item *item, __unused void *data)
@@ -3503,7 +3532,6 @@ 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 (0);
@@ -3524,8 +3552,8 @@ server_client_dispatch_command(struct client *c, struct imsg *imsg)
argc = data.argc;
if (argc == 0) {
cmdlist = cmd_list_copy(options_get_command(global_options,
"default-client-command"), 0, NULL);
new_item = cmdq_get_callback(server_client_default_command,
NULL);
} else {
values = args_from_vector(argc, argv);
pr = cmd_parse_from_arguments(values, argc, NULL);
@@ -3539,18 +3567,17 @@ server_client_dispatch_command(struct client *c, struct imsg *imsg)
args_free_values(values, argc);
free(values);
cmd_free_argv(argc, argv);
cmdlist = pr->cmdlist;
if ((c->flags & CLIENT_READONLY) &&
!cmd_list_all_have(pr->cmdlist, CMD_READONLY)) {
new_item = cmdq_get_callback(server_client_read_only,
NULL);
} else
new_item = cmdq_get_command(pr->cmdlist, NULL);
cmd_list_free(pr->cmdlist);
}
if ((c->flags & CLIENT_READONLY) &&
!cmd_list_all_have(cmdlist, CMD_READONLY))
new_item = cmdq_get_callback(server_client_read_only, NULL);
else
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(cmdlist);
return (0);
error:

View File

@@ -804,7 +804,10 @@ status_prompt_redraw(struct client *c)
n = options_get_number(s->options, "prompt-cursor-colour");
sl->active->default_ccolour = n;
n = options_get_number(s->options, "prompt-cursor-style");
if (c->prompt_mode == PROMPT_COMMAND)
n = options_get_number(s->options, "prompt-command-cursor-style");
else
n = options_get_number(s->options, "prompt-cursor-style");
screen_set_cursor_style(n, &sl->active->default_cstyle,
&sl->active->default_mode);
@@ -936,6 +939,8 @@ status_prompt_translate_key(struct client *c, key_code key, key_code *new_key)
return (1);
case '\033': /* Escape */
c->prompt_mode = PROMPT_COMMAND;
if (c->prompt_index != 0)
c->prompt_index--;
c->flags |= CLIENT_REDRAWSTATUS;
return (0);
}
@@ -961,10 +966,11 @@ status_prompt_translate_key(struct client *c, key_code key, key_code *new_key)
*new_key = 'u'|KEYC_CTRL;
return (1);
case 'i':
case '\033': /* Escape */
c->prompt_mode = PROMPT_ENTRY;
c->flags |= CLIENT_REDRAWSTATUS;
return (0);
case '\033': /* Escape */
return (0);
}
switch (key) {

15
tmux.1
View File

@@ -841,6 +841,7 @@ Each has a single-character alternative form.
.It Li "{last}" Ta "!" Ta "The last (previously current) window"
.It Li "{next}" Ta "+" Ta "The next window by number"
.It Li "{previous}" Ta "-" Ta "The previous window by number"
.It Li "{current}" Ta "@" Ta "The current window"
.El
.Pp
.Ar target-pane
@@ -873,6 +874,7 @@ The following special tokens are available for the pane index:
.It Li "{down-of}" Ta "" Ta "The pane below the active pane"
.It Li "{left-of}" Ta "" Ta "The pane to the left of the active pane"
.It Li "{right-of}" Ta "" Ta "The pane to the right of the active pane"
.It Li "{active}" Ta "@" Ta "The active pane"
.El
.Pp
The tokens
@@ -4242,6 +4244,12 @@ passed through to applications running in
.Nm .
Attached clients should be detached and attached again after changing this
option.
.It Xo Ic focus-follows-mouse
.Op Ic on | off
.Xc
When enabled and
.Ic mouse
is on, moving the mouse into a pane selects it.
.It Xo Ic get-clipboard
.Op Ic both | request | buffer | off
.Xc
@@ -4696,6 +4704,12 @@ Set the style of the cursor in the command prompt.
See the
.Ic cursor-style
options for available styles.
.It Ic prompt-command-cursor-style Ar style
Set the style of the cursor in the command prompt when vi keys are enabled and
the prompt is in command mode.
See the
.Ic cursor-style
options for available styles.
.It Xo Ic renumber-windows
.Op Ic on | off
.Xc
@@ -6232,6 +6246,7 @@ The following variables are available, where appropriate:
.It Li "selection_active" Ta "" Ta "1 if selection started and changes with the cursor in copy mode"
.It Li "selection_end_x" Ta "" Ta "X position of the end of the selection"
.It Li "selection_end_y" Ta "" Ta "Y position of the end of the selection"
.It Li "selection_mode" Ta "" Ta "Selection mode"
.It Li "selection_present" Ta "" Ta "1 if selection started in copy mode"
.It Li "selection_start_x" Ta "" Ta "X position of the start of the selection"
.It Li "selection_start_y" Ta "" Ta "Y position of the start of the selection"

25
tmux.h
View File

@@ -1167,6 +1167,16 @@ struct window_pane_resize {
};
TAILQ_HEAD(window_pane_resizes, window_pane_resize);
/*
* Client theme, this is worked out from the background colour if not reported
* by terminal.
*/
enum client_theme {
THEME_UNKNOWN,
THEME_LIGHT,
THEME_DARK
};
/* Child window structure. */
struct window_pane {
u_int id;
@@ -1233,6 +1243,7 @@ struct window_pane {
struct grid_cell cached_gc;
struct grid_cell cached_active_gc;
struct colour_palette palette;
enum client_theme last_theme;
int pipe_fd;
struct bufferevent *pipe_event;
@@ -1918,16 +1929,6 @@ struct overlay_ranges {
u_int nx[OVERLAY_MAX_RANGES];
};
/*
* Client theme, this is worked out from the background colour if not reported
* by terminal.
*/
enum client_theme {
THEME_UNKNOWN,
THEME_LIGHT,
THEME_DARK
};
/* Client connection. */
typedef int (*prompt_input_cb)(struct client *, void *, const char *, int);
typedef void (*prompt_free_cb)(void *);
@@ -2453,7 +2454,7 @@ 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 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 *,
@@ -2750,6 +2751,8 @@ 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 *);
#define CMD_LIST_PRINT_ESCAPED 0x1
#define CMD_LIST_PRINT_NO_GROUPS 0x2
char *cmd_list_print(const struct cmd_list *, int);
struct cmd *cmd_list_first(struct cmd_list *);
struct cmd *cmd_list_next(struct cmd *);

View File

@@ -956,7 +956,8 @@ partial_key:
if (delay == 0)
delay = 1;
if ((tty->flags & (TTY_WAITFG|TTY_WAITBG) ||
(tty->flags & TTY_ALL_REQUEST_FLAGS) != TTY_ALL_REQUEST_FLAGS)) {
(tty->flags & TTY_ALL_REQUEST_FLAGS) != TTY_ALL_REQUEST_FLAGS) ||
!TAILQ_EMPTY(&c->input_requests)) {
log_debug("%s: increasing delay for active query", c->name);
if (delay < 500)
delay = 500;
@@ -1750,7 +1751,9 @@ tty_keys_palette(struct tty *tty, const char *buf, size_t len, size_t *size)
/* Copy the rest up to \033\ or \007. */
start = (endptr - buf) + 1;
for (i = start; i < len && i - start < sizeof tmp; i++) {
for (i = start; i - start < sizeof tmp; i++) {
if (i == len)
return (1);
if (buf[i - 1] == '\033' && buf[i] == '\\')
break;
if (buf[i] == '\007')

9
tty.c
View File

@@ -2288,6 +2288,13 @@ tty_cmd_cell(struct tty *tty, const struct tty_ctx *ctx)
vr = screen_redraw_get_visible_ranges(wp, px, py,
gcp->data.width);
if (ctx->num == 2) {
/* xxxx need to check visible range */
tty_draw_line(tty, s, 0, s->cy, screen_size_x(s),
ctx->xoff - ctx->wox, py, &ctx->defaults, ctx->palette);
return;
}
/* Handle partially obstructed wide characters. */
if (gcp->data.width > 1) {
@@ -2297,7 +2304,7 @@ tty_cmd_cell(struct tty *tty, const struct tty_ctx *ctx)
for (i = 0; i < OVERLAY_MAX_RANGES; i++)
vis += r.nx[i];
if (vis < gcp->data.width ||
vis2 < gcp->data.width) { /* xxxx check visible range */
vis2 < gcp->data.width) { /* xxxx need to check visible range */
tty_draw_line(tty, s, s->cx, s->cy, gcp->data.width,
px, py, &ctx->defaults, ctx->palette);
return;

View File

@@ -956,6 +956,18 @@ window_copy_formats(struct window_mode_entry *wme, struct format_tree *ft)
format_add(ft, "selection_present", "0");
}
switch (data->selflag) {
case SEL_CHAR:
format_add(ft, "selection_mode", "char");
break;
case SEL_WORD:
format_add(ft, "selection_mode", "word");
break;
case SEL_LINE:
format_add(ft, "selection_mode", "line");
break;
}
format_add(ft, "search_present", "%d", data->searchmark != NULL);
format_add(ft, "search_timed_out", "%d", data->timeout);
if (data->searchcount != -1) {

View File

@@ -1036,7 +1036,7 @@ window_pane_create(struct window *w, u_int sx, u_int sy, u_int hlimit)
wp = xcalloc(1, sizeof *wp);
wp->window = w;
wp->options = options_create(w->options);
wp->flags = (PANE_STYLECHANGED|PANE_THEMECHANGED);
wp->flags = PANE_STYLECHANGED;
wp->id = next_window_pane_id++;
RB_INSERT(window_pane_tree, &all_window_panes, wp);
@@ -2051,6 +2051,8 @@ window_pane_get_theme(struct window_pane *wp)
void
window_pane_send_theme_update(struct window_pane *wp)
{
enum client_theme theme;
if (wp == NULL || window_pane_exited(wp))
return;
if (~wp->flags & PANE_THEMECHANGED)
@@ -2058,16 +2060,23 @@ window_pane_send_theme_update(struct window_pane *wp)
if (~wp->screen->mode & MODE_THEME_UPDATES)
return;
switch (window_pane_get_theme(wp)) {
theme = window_pane_get_theme(wp);
if (theme == wp->last_theme)
return;
wp->last_theme = theme;
wp->flags &= ~PANE_THEMECHANGED;
switch (theme) {
case THEME_LIGHT:
input_key_pane(wp, KEYC_REPORT_LIGHT_THEME, NULL);
log_debug("%s: %%%u light theme", __func__, wp->id);
bufferevent_write(wp->event, "\033[?997;2n", 9);
break;
case THEME_DARK:
input_key_pane(wp, KEYC_REPORT_DARK_THEME, NULL);
log_debug("%s: %%%u dark theme", __func__, wp->id);
bufferevent_write(wp->event, "\033[?997;1n", 9);
break;
case THEME_UNKNOWN:
log_debug("%s: %%%u unknown theme", __func__, wp->id);
break;
}
wp->flags &= ~PANE_THEMECHANGED;
}