mirror of
https://github.com/tmux/tmux.git
synced 2026-03-12 03:25:45 +00:00
Compare commits
34 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
3b929f332a | ||
|
|
c827f5092d | ||
|
|
d8feffd2bf | ||
|
|
f48c46a76a | ||
|
|
f06ee2b87b | ||
|
|
9b4c05b6b9 | ||
|
|
3b9b823df5 | ||
|
|
8aa34f616f | ||
|
|
5ea6ccbb7f | ||
|
|
434ac8734a | ||
|
|
47af583a50 | ||
|
|
aaf87abfb4 | ||
|
|
bacb4d1b4d | ||
|
|
ad2f7642f2 | ||
|
|
059580e0f7 | ||
|
|
cb2943faab | ||
|
|
7c28597e0f | ||
|
|
fb52921a86 | ||
|
|
ddc67152a5 | ||
|
|
4cf595a402 | ||
|
|
5107e84897 | ||
|
|
736a276cc9 | ||
|
|
825feac9f8 | ||
|
|
d8c0069254 | ||
|
|
33d4f854c0 | ||
|
|
9865ad27a5 | ||
|
|
16b497e12b | ||
|
|
a25af7d0f3 | ||
|
|
a11aa870b3 | ||
|
|
0431d4d639 | ||
|
|
d863978464 | ||
|
|
57d5f67552 | ||
|
|
bab7a9a085 | ||
|
|
2ab53d30d0 |
23
CHANGES
23
CHANGES
@@ -1,3 +1,16 @@
|
||||
CHANGES FROM 3.2 TO 3.2a
|
||||
|
||||
* Add an "always" value for the "extended-keys" option; if set then tmux will
|
||||
forward extended keys to applications even if they do not request them.
|
||||
|
||||
* Add a "mouse" terminal feature so tmux can enable the mouse on terminals
|
||||
where it is known to be supported even if terminfo(5) says otherwise.
|
||||
|
||||
* Do not expand the filename given to -f so it can contain colons.
|
||||
|
||||
* Fixes for problems with extended keys and modifiers, scroll region,
|
||||
source-file, crosscompiling, format modifiers and other minor issues.
|
||||
|
||||
CHANGES FROM 3.1c TO 3.2
|
||||
|
||||
* Add a flag to disable keys to close a message.
|
||||
@@ -29,7 +42,7 @@ CHANGES FROM 3.1c TO 3.2
|
||||
* Add a -S flag to new-window to make it select the existing window if one
|
||||
with the given name already exists rather than failing with an error.
|
||||
|
||||
* Addd a format modifier to check if a window or session name exists (N/w or
|
||||
* Add a format modifier to check if a window or session name exists (N/w or
|
||||
N/s).
|
||||
|
||||
* Add compat clock_gettime for older macOS.
|
||||
@@ -61,7 +74,7 @@ CHANGES FROM 3.1c TO 3.2
|
||||
an option on all panes.
|
||||
|
||||
* Make replacement of ##s consistent when drawing formats, whether followed by
|
||||
[ or not. Add a flag (e) to the q: format modifier to double up #s
|
||||
[ or not. Add a flag (e) to the q: format modifier to double up #s.
|
||||
|
||||
* Add -N flag to display-panes to ignore keys.
|
||||
|
||||
@@ -265,7 +278,7 @@ CHANGES FROM 3.1c TO 3.2
|
||||
|
||||
* Wait until the initial command sequence is done before sending a device
|
||||
attributes request and other bits that prompt a reply from the terminal. This
|
||||
means that stray relies are not left on the terminal if the command has
|
||||
means that stray replies are not left on the terminal if the command has
|
||||
attached and then immediately detached and tmux will not be around to receive
|
||||
them.
|
||||
|
||||
@@ -280,7 +293,7 @@ CHANGES FROM 3.1c TO 3.2
|
||||
window-renamed
|
||||
window-unlinked
|
||||
|
||||
And these now pane options:
|
||||
And these are now pane options:
|
||||
|
||||
pane-died
|
||||
pane-exited
|
||||
@@ -355,7 +368,7 @@ CHANGES FROM 3.1c TO 3.2
|
||||
* Add a default binding for button 2 to paste.
|
||||
|
||||
* Add -d flag to run-shell to delay before running the command and allow it to
|
||||
run without a command so it just delays.
|
||||
be used without a command so it just delays.
|
||||
|
||||
* Add C-g to cancel command prompt with vi keys as well as emacs, and q in
|
||||
command mode.
|
||||
|
||||
@@ -205,7 +205,7 @@ cmd_display_menu_get_position(struct client *tc, struct cmdq_item *item,
|
||||
if (xp == NULL || strcmp(xp, "C") == 0)
|
||||
xp = "#{popup_centre_x}";
|
||||
else if (strcmp(xp, "R") == 0)
|
||||
xp = "#{popup_right}";
|
||||
xp = "#{popup_pane_right}";
|
||||
else if (strcmp(xp, "P") == 0)
|
||||
xp = "#{popup_pane_left}";
|
||||
else if (strcmp(xp, "M") == 0)
|
||||
|
||||
@@ -165,7 +165,7 @@ cmd_list_keys_exec(struct cmd *self, struct cmdq_item *item)
|
||||
cmdq_error(item, "invalid key: %s", args->argv[0]);
|
||||
return (CMD_RETURN_ERROR);
|
||||
}
|
||||
only &= KEYC_MASK_KEY;
|
||||
only &= (KEYC_MASK_KEY|KEYC_MASK_MODIFIERS);
|
||||
}
|
||||
|
||||
tablename = args_get(args, 'T');
|
||||
|
||||
@@ -269,6 +269,7 @@ cmd_new_session_exec(struct cmd *self, struct cmdq_item *item)
|
||||
memset(&sc, 0, sizeof sc);
|
||||
sc.item = item;
|
||||
sc.s = s;
|
||||
sc.tc = c;
|
||||
|
||||
sc.name = args_get(args, 'n');
|
||||
sc.argc = args->argc;
|
||||
|
||||
@@ -67,7 +67,9 @@ cmd_source_file_complete(struct client *c, struct cmd_source_file_data *cdata)
|
||||
struct cmdq_item *new_item;
|
||||
|
||||
if (cfg_finished) {
|
||||
if (cdata->retval == CMD_RETURN_ERROR && c->session == NULL)
|
||||
if (cdata->retval == CMD_RETURN_ERROR &&
|
||||
c != NULL &&
|
||||
c->session == NULL)
|
||||
c->retval = 1;
|
||||
new_item = cmdq_get_callback(cmd_source_file_complete_cb, NULL);
|
||||
cmdq_insert_after(cdata->after, new_item);
|
||||
|
||||
21
configure.ac
21
configure.ac
@@ -1,6 +1,6 @@
|
||||
# configure.ac
|
||||
|
||||
AC_INIT([tmux], 3.2)
|
||||
AC_INIT([tmux], 3.2a)
|
||||
AC_PREREQ([2.60])
|
||||
|
||||
AC_CONFIG_AUX_DIR(etc)
|
||||
@@ -34,10 +34,10 @@ AC_ARG_VAR(
|
||||
# Set up convenient fuzzing defaults before initializing compiler.
|
||||
if test "x$enable_fuzzing" = xyes; then
|
||||
AC_DEFINE(NEED_FUZZING)
|
||||
test "x$CC" == x && CC=clang
|
||||
test "x$FUZZING_LIBS" == x && \
|
||||
test "x$CC" = x && CC=clang
|
||||
test "x$FUZZING_LIBS" = x && \
|
||||
FUZZING_LIBS="-fsanitize=fuzzer"
|
||||
test "x$SAVED_CFLAGS" == x && \
|
||||
test "x$SAVED_CFLAGS" = x && \
|
||||
AM_CFLAGS="-g -fsanitize=fuzzer-no-link,address"
|
||||
fi
|
||||
|
||||
@@ -150,10 +150,19 @@ AC_REPLACE_FUNCS([ \
|
||||
strlcpy \
|
||||
strndup \
|
||||
strsep \
|
||||
strtonum \
|
||||
])
|
||||
AC_FUNC_STRNLEN
|
||||
|
||||
# Check if strtonum works.
|
||||
AC_MSG_CHECKING([for working strtonum])
|
||||
AC_RUN_IFELSE([AC_LANG_PROGRAM(
|
||||
[#include <stdlib.h>],
|
||||
[return (strtonum("0", 0, 1, NULL) == 0 ? 0 : 1);]
|
||||
)],
|
||||
[AC_DEFINE(HAVE_STRTONUM) AC_MSG_RESULT(yes)],
|
||||
[AC_LIBOBJ(strtonum) AC_MSG_RESULT(no)]
|
||||
)
|
||||
|
||||
# Clang sanitizers wrap reallocarray even if it isn't available on the target
|
||||
# system. When compiled it always returns NULL and crashes the program. To
|
||||
# detect this we need a more complicated test.
|
||||
@@ -163,6 +172,7 @@ AC_RUN_IFELSE([AC_LANG_PROGRAM(
|
||||
[return (reallocarray(NULL, 1, 1) == NULL);]
|
||||
)],
|
||||
AC_MSG_RESULT(yes),
|
||||
[AC_LIBOBJ(reallocarray) AC_MSG_RESULT([no])],
|
||||
[AC_LIBOBJ(reallocarray) AC_MSG_RESULT([no])]
|
||||
)
|
||||
AC_MSG_CHECKING([for working recallocarray])
|
||||
@@ -171,6 +181,7 @@ AC_RUN_IFELSE([AC_LANG_PROGRAM(
|
||||
[return (recallocarray(NULL, 1, 1, 1) == NULL);]
|
||||
)],
|
||||
AC_MSG_RESULT(yes),
|
||||
[AC_LIBOBJ(recallocarray) AC_MSG_RESULT([no])],
|
||||
[AC_LIBOBJ(recallocarray) AC_MSG_RESULT([no])]
|
||||
)
|
||||
|
||||
|
||||
6
file.c
6
file.c
@@ -503,14 +503,14 @@ file_write_error_callback(__unused struct bufferevent *bev, __unused short what,
|
||||
|
||||
log_debug("write error file %d", cf->stream);
|
||||
|
||||
if (cf->cb != NULL)
|
||||
cf->cb(NULL, NULL, 0, -1, NULL, cf->data);
|
||||
|
||||
bufferevent_free(cf->event);
|
||||
cf->event = NULL;
|
||||
|
||||
close(cf->fd);
|
||||
cf->fd = -1;
|
||||
|
||||
if (cf->cb != NULL)
|
||||
cf->cb(NULL, NULL, 0, -1, NULL, cf->data);
|
||||
}
|
||||
|
||||
/* Client file write callback. */
|
||||
|
||||
10
format.c
10
format.c
@@ -103,7 +103,7 @@ format_job_cmp(struct format_job *fj1, struct format_job *fj2)
|
||||
#define FORMAT_CHARACTER 0x10000
|
||||
|
||||
/* Limit on recursion. */
|
||||
#define FORMAT_LOOP_LIMIT 10
|
||||
#define FORMAT_LOOP_LIMIT 100
|
||||
|
||||
/* Format expand flags. */
|
||||
#define FORMAT_EXPAND_TIME 0x1
|
||||
@@ -3991,7 +3991,7 @@ format_replace_expression(struct format_modifier *mexp,
|
||||
result = (mleft < mright);
|
||||
break;
|
||||
case LESS_THAN_EQUAL:
|
||||
result = (mleft > mright);
|
||||
result = (mleft <= mright);
|
||||
break;
|
||||
}
|
||||
if (use_fp)
|
||||
@@ -4199,7 +4199,7 @@ format_replace(struct format_expand_state *es, const char *key, size_t keylen,
|
||||
value = xstrdup("0");
|
||||
} else {
|
||||
format_log(es, "search '%s' pane %%%u", new, wp->id);
|
||||
value = format_search(fm, wp, new);
|
||||
value = format_search(search, wp, new);
|
||||
}
|
||||
free(new);
|
||||
} else if (cmp != NULL) {
|
||||
@@ -4441,8 +4441,10 @@ format_expand1(struct format_expand_state *es, const char *fmt)
|
||||
if (fmt == NULL || *fmt == '\0')
|
||||
return (xstrdup(""));
|
||||
|
||||
if (es->loop == FORMAT_LOOP_LIMIT)
|
||||
if (es->loop == FORMAT_LOOP_LIMIT) {
|
||||
format_log(es, "reached loop limit (%u)", FORMAT_LOOP_LIMIT);
|
||||
return (xstrdup(""));
|
||||
}
|
||||
es->loop++;
|
||||
|
||||
format_log(es, "expanding format: %s", fmt);
|
||||
|
||||
@@ -371,19 +371,26 @@ void
|
||||
grid_reader_cursor_back_to_indentation(struct grid_reader *gr)
|
||||
{
|
||||
struct grid_cell gc;
|
||||
u_int px, py, xx, yy;
|
||||
u_int px, py, xx, yy, oldx, oldy;
|
||||
|
||||
yy = gr->gd->hsize + gr->gd->sy - 1;
|
||||
oldx = gr->cx;
|
||||
oldy = gr->cy;
|
||||
grid_reader_cursor_start_of_line(gr, 1);
|
||||
|
||||
for (py = gr->cy; py <= yy; py++) {
|
||||
xx = grid_line_length(gr->gd, py);
|
||||
for (px = 0; px < xx; px++) {
|
||||
grid_get_cell(gr->gd, px, py, &gc);
|
||||
if (gc.data.size != 1 || *gc.data.data != ' ')
|
||||
break;
|
||||
if (gc.data.size != 1 || *gc.data.data != ' ') {
|
||||
gr->cx = px;
|
||||
gr->cy = py;
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (~grid_get_line(gr->gd, py)->flags & GRID_LINE_WRAPPED)
|
||||
break;
|
||||
}
|
||||
gr->cx = oldx;
|
||||
gr->cy = oldy;
|
||||
}
|
||||
|
||||
26
input-keys.c
26
input-keys.c
@@ -94,30 +94,6 @@ static struct input_key_entry input_key_defaults[] = {
|
||||
{ .key = KEYC_F12,
|
||||
.data = "\033[24~"
|
||||
},
|
||||
{ .key = KEYC_F1|KEYC_SHIFT,
|
||||
.data = "\033[25~"
|
||||
},
|
||||
{ .key = KEYC_F2|KEYC_SHIFT,
|
||||
.data = "\033[26~"
|
||||
},
|
||||
{ .key = KEYC_F3|KEYC_SHIFT,
|
||||
.data = "\033[28~"
|
||||
},
|
||||
{ .key = KEYC_F4|KEYC_SHIFT,
|
||||
.data = "\033[29~"
|
||||
},
|
||||
{ .key = KEYC_F5|KEYC_SHIFT,
|
||||
.data = "\033[31~"
|
||||
},
|
||||
{ .key = KEYC_F6|KEYC_SHIFT,
|
||||
.data = "\033[32~"
|
||||
},
|
||||
{ .key = KEYC_F7|KEYC_SHIFT,
|
||||
.data = "\033[33~"
|
||||
},
|
||||
{ .key = KEYC_F8|KEYC_SHIFT,
|
||||
.data = "\033[34~"
|
||||
},
|
||||
{ .key = KEYC_IC,
|
||||
.data = "\033[2~"
|
||||
},
|
||||
@@ -476,7 +452,7 @@ input_key(struct screen *s, struct bufferevent *bev, key_code key)
|
||||
input_key_write(__func__, bev, &ud.data[0], 1);
|
||||
return (0);
|
||||
}
|
||||
if (justkey > 0x7f && justkey < KEYC_BASE) {
|
||||
if (KEYC_IS_UNICODE(justkey)) {
|
||||
if (key & KEYC_META)
|
||||
input_key_write(__func__, bev, "\033", 1);
|
||||
utf8_to_data(justkey, &ud);
|
||||
|
||||
2
input.c
2
input.c
@@ -1390,6 +1390,8 @@ input_csi_dispatch(struct input_ctx *ictx)
|
||||
case INPUT_CSI_MODSET:
|
||||
n = input_get(ictx, 0, 0, 0);
|
||||
m = input_get(ictx, 1, 0, 0);
|
||||
if (options_get_number(global_options, "extended-keys") == 2)
|
||||
break;
|
||||
if (n == 0 || (n == 4 && m == 0))
|
||||
screen_write_mode_clear(sctx, MODE_KEXTENDED);
|
||||
else if (n == 4 && (m == 1 || m == 2))
|
||||
|
||||
@@ -215,6 +215,9 @@ key_bindings_add(const char *name, key_code key, const char *note, int repeat,
|
||||
if (repeat)
|
||||
bd->flags |= KEY_BINDING_REPEAT;
|
||||
bd->cmdlist = cmdlist;
|
||||
|
||||
log_debug("%s: %#llx %s = %s", __func__, bd->key,
|
||||
key_string_lookup_key(bd->key, 1), cmd_list_print(bd->cmdlist, 0));
|
||||
}
|
||||
|
||||
void
|
||||
@@ -231,6 +234,9 @@ key_bindings_remove(const char *name, key_code key)
|
||||
if (bd == NULL)
|
||||
return;
|
||||
|
||||
log_debug("%s: %#llx %s", __func__, bd->key,
|
||||
key_string_lookup_key(bd->key, 1));
|
||||
|
||||
RB_REMOVE(key_bindings, &table->key_bindings, bd);
|
||||
key_bindings_free(bd);
|
||||
|
||||
|
||||
14
key-string.c
14
key-string.c
@@ -164,7 +164,7 @@ key_string_get_modifiers(const char **string)
|
||||
key_code
|
||||
key_string_lookup_string(const char *string)
|
||||
{
|
||||
static const char *other = "!#()+,-.0123456789:;<=>'\r\t\177";
|
||||
static const char *other = "!#()+,-.0123456789:;<=>'\r\t\177`/";
|
||||
key_code key, modifiers;
|
||||
u_int u, i;
|
||||
struct utf8_data ud, *udp;
|
||||
@@ -238,8 +238,12 @@ key_string_lookup_string(const char *string)
|
||||
}
|
||||
|
||||
/* Convert the standard control keys. */
|
||||
if (key < KEYC_BASE && (modifiers & KEYC_CTRL) &&
|
||||
strchr(other, key) == NULL) {
|
||||
if (key <= 127 &&
|
||||
(modifiers & KEYC_CTRL) &&
|
||||
strchr(other, key) == NULL &&
|
||||
key != 9 &&
|
||||
key != 13 &&
|
||||
key != 27) {
|
||||
if (key >= 97 && key <= 122)
|
||||
key -= 96;
|
||||
else if (key >= 64 && key <= 95)
|
||||
@@ -364,8 +368,8 @@ key_string_lookup_key(key_code key, int with_flags)
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* Is this a UTF-8 key? */
|
||||
if (key > 127 && key < KEYC_BASE) {
|
||||
/* Is this a Unicode key? */
|
||||
if (KEYC_IS_UNICODE(key)) {
|
||||
utf8_to_data(key, &ud);
|
||||
off = strlen(out);
|
||||
memcpy(out + off, ud.data, ud.size);
|
||||
|
||||
@@ -74,6 +74,9 @@ static const char *options_table_remain_on_exit_list[] = {
|
||||
static const char *options_table_detach_on_destroy_list[] = {
|
||||
"off", "on", "no-detached", NULL
|
||||
};
|
||||
static const char *options_table_extended_keys_list[] = {
|
||||
"off", "on", "always", NULL
|
||||
};
|
||||
|
||||
/* Status line format. */
|
||||
#define OPTIONS_TABLE_STATUS_FORMAT1 \
|
||||
@@ -266,8 +269,9 @@ const struct options_table_entry options_table[] = {
|
||||
},
|
||||
|
||||
{ .name = "extended-keys",
|
||||
.type = OPTIONS_TABLE_FLAG,
|
||||
.type = OPTIONS_TABLE_CHOICE,
|
||||
.scope = OPTIONS_TABLE_SERVER,
|
||||
.choices = options_table_extended_keys_list,
|
||||
.default_num = 0,
|
||||
.text = "Whether to request extended key sequences from terminals "
|
||||
"that support it."
|
||||
|
||||
@@ -96,5 +96,17 @@ osdep_get_cwd(int fd)
|
||||
struct event_base *
|
||||
osdep_event_init(void)
|
||||
{
|
||||
return (event_init());
|
||||
struct event_base *base;
|
||||
|
||||
/*
|
||||
* On Illumos, evports don't seem to work properly. It is not clear if
|
||||
* this a problem in libevent, with the way tmux uses file descriptors,
|
||||
* or with some types of file descriptor. But using poll instead is
|
||||
* fine.
|
||||
*/
|
||||
setenv("EVENT_NOEVPORT", "1", 1);
|
||||
|
||||
base = event_init();
|
||||
unsetenv("EVENT_NOEVPORT");
|
||||
return (base);
|
||||
}
|
||||
|
||||
49
resize.c
49
resize.c
@@ -108,17 +108,19 @@ clients_with_window(struct window *w)
|
||||
}
|
||||
|
||||
static int
|
||||
clients_calculate_size(int type, int current, struct session *s,
|
||||
struct window *w, int (*skip_client)(struct client *, int, int,
|
||||
struct session *, struct window *), u_int *sx, u_int *sy, u_int *xpixel,
|
||||
u_int *ypixel)
|
||||
clients_calculate_size(int type, int current, struct client *c,
|
||||
struct session *s, struct window *w, int (*skip_client)(struct client *,
|
||||
int, int, struct session *, struct window *), u_int *sx, u_int *sy,
|
||||
u_int *xpixel, u_int *ypixel)
|
||||
{
|
||||
struct client *loop;
|
||||
u_int cx, cy, n = 0;
|
||||
|
||||
/* Manual windows do not have their size changed based on a client. */
|
||||
if (type == WINDOW_SIZE_MANUAL)
|
||||
if (type == WINDOW_SIZE_MANUAL) {
|
||||
log_debug("%s: type is manual", __func__);
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Start comparing with 0 for largest and UINT_MAX for smallest or
|
||||
@@ -134,23 +136,29 @@ clients_calculate_size(int type, int current, struct session *s,
|
||||
* For latest, count the number of clients with this window. We only
|
||||
* care if there is more than one.
|
||||
*/
|
||||
if (type == WINDOW_SIZE_LATEST)
|
||||
if (type == WINDOW_SIZE_LATEST && w != NULL)
|
||||
n = clients_with_window(w);
|
||||
|
||||
/* Loop over the clients and work out the size. */
|
||||
TAILQ_FOREACH(loop, &clients, entry) {
|
||||
if (ignore_client_size(loop))
|
||||
if (loop != c && ignore_client_size(loop)) {
|
||||
log_debug("%s: ignoring %s", __func__, loop->name);
|
||||
continue;
|
||||
if (skip_client(loop, type, current, s, w))
|
||||
}
|
||||
if (loop != c && skip_client(loop, type, current, s, w)) {
|
||||
log_debug("%s: skipping %s", __func__, loop->name);
|
||||
continue;
|
||||
}
|
||||
|
||||
/*
|
||||
* If there are multiple clients attached, only accept the
|
||||
* latest client; otherwise let the only client be chosen as
|
||||
* for smallest.
|
||||
*/
|
||||
if (type == WINDOW_SIZE_LATEST && n > 1 && loop != w->latest)
|
||||
if (type == WINDOW_SIZE_LATEST && n > 1 && loop != w->latest) {
|
||||
log_debug("%s: %s is not latest", __func__, loop->name);
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Work out this client's size. */
|
||||
cx = loop->tty.sx;
|
||||
@@ -175,16 +183,24 @@ clients_calculate_size(int type, int current, struct session *s,
|
||||
*xpixel = loop->tty.xpixel;
|
||||
*ypixel = loop->tty.ypixel;
|
||||
}
|
||||
log_debug("%s: after %s (%ux%u), size is %ux%u", __func__,
|
||||
loop->name, cx, cy, *sx, *sy);
|
||||
}
|
||||
|
||||
/* Return whether a suitable size was found. */
|
||||
if (type == WINDOW_SIZE_LARGEST)
|
||||
if (type == WINDOW_SIZE_LARGEST) {
|
||||
log_debug("%s: type is largest", __func__);
|
||||
return (*sx != 0 && *sy != 0);
|
||||
}
|
||||
if (type == WINDOW_SIZE_LATEST)
|
||||
log_debug("%s: type is latest", __func__);
|
||||
else
|
||||
log_debug("%s: type is smallest", __func__);
|
||||
return (*sx != UINT_MAX && *sy != UINT_MAX);
|
||||
}
|
||||
|
||||
static int
|
||||
default_window_size_skip_client (struct client *loop, int type,
|
||||
default_window_size_skip_client(struct client *loop, int type,
|
||||
__unused int current, struct session *s, struct window *w)
|
||||
{
|
||||
/*
|
||||
@@ -221,23 +237,25 @@ default_window_size(struct client *c, struct session *s, struct window *w,
|
||||
*sy = c->tty.sy - status_line_size(c);
|
||||
*xpixel = c->tty.xpixel;
|
||||
*ypixel = c->tty.ypixel;
|
||||
log_debug("%s: using %ux%u from %s", __func__, *sx, *sy,
|
||||
c->name);
|
||||
goto done;
|
||||
}
|
||||
if (w == NULL)
|
||||
type = WINDOW_SIZE_MANUAL;
|
||||
}
|
||||
|
||||
/*
|
||||
* Look for a client to base the size on. If none exists (or the type
|
||||
* is manual), use the default-size option.
|
||||
*/
|
||||
if (!clients_calculate_size(type, 0, s, w,
|
||||
if (!clients_calculate_size(type, 0, c, s, w,
|
||||
default_window_size_skip_client, sx, sy, xpixel, ypixel)) {
|
||||
value = options_get_string(s->options, "default-size");
|
||||
if (sscanf(value, "%ux%u", sx, sy) != 2) {
|
||||
*sx = 80;
|
||||
*sy = 24;
|
||||
}
|
||||
log_debug("%s: using %ux%u from default-size", __func__, *sx,
|
||||
*sy);
|
||||
}
|
||||
|
||||
done:
|
||||
@@ -250,6 +268,7 @@ done:
|
||||
*sy = WINDOW_MINIMUM;
|
||||
if (*sy > WINDOW_MAXIMUM)
|
||||
*sy = WINDOW_MAXIMUM;
|
||||
log_debug("%s: resulting size is %ux%u", __func__, *sx, *sy);
|
||||
}
|
||||
|
||||
static int
|
||||
@@ -289,7 +308,7 @@ recalculate_size(struct window *w, int now)
|
||||
current = options_get_number(w->options, "aggressive-resize");
|
||||
|
||||
/* Look for a suitable client and get the new size. */
|
||||
changed = clients_calculate_size(type, current, NULL, w,
|
||||
changed = clients_calculate_size(type, current, NULL, NULL, w,
|
||||
recalculate_size_skip_client, &sx, &sy, &xpixel, &ypixel);
|
||||
|
||||
/*
|
||||
|
||||
4
screen.c
4
screen.c
@@ -100,7 +100,9 @@ screen_reinit(struct screen *s)
|
||||
s->rupper = 0;
|
||||
s->rlower = screen_size_y(s) - 1;
|
||||
|
||||
s->mode = MODE_CURSOR | MODE_WRAP;
|
||||
s->mode = MODE_CURSOR|MODE_WRAP;
|
||||
if (options_get_number(global_options, "extended-keys") == 2)
|
||||
s->mode |= MODE_KEXTENDED;
|
||||
|
||||
if (s->saved_grid != NULL)
|
||||
screen_alternate_off(s, NULL, 0);
|
||||
|
||||
156
server-client.c
156
server-client.c
@@ -43,6 +43,7 @@ static void server_client_check_modes(struct client *);
|
||||
static void server_client_set_title(struct client *);
|
||||
static void server_client_reset_state(struct client *);
|
||||
static int server_client_assume_paste(struct session *);
|
||||
static void server_client_update_latest(struct client *);
|
||||
|
||||
static void server_client_dispatch(struct imsg *, void *);
|
||||
static void server_client_dispatch_command(struct client *, struct imsg *);
|
||||
@@ -271,6 +272,40 @@ server_client_open(struct client *c, char **cause)
|
||||
return (0);
|
||||
}
|
||||
|
||||
/* Lost an attached client. */
|
||||
static void
|
||||
server_client_attached_lost(struct client *c)
|
||||
{
|
||||
struct session *s = c->session;
|
||||
struct window *w;
|
||||
struct client *loop;
|
||||
struct client *found;
|
||||
|
||||
log_debug("lost attached client %p", c);
|
||||
|
||||
/*
|
||||
* By this point the session in the client has been cleared so walk all
|
||||
* windows to find any with this client as the latest.
|
||||
*/
|
||||
RB_FOREACH(w, windows, &windows) {
|
||||
if (w->latest != c)
|
||||
continue;
|
||||
|
||||
found = NULL;
|
||||
TAILQ_FOREACH(loop, &clients, entry) {
|
||||
s = loop->session;
|
||||
if (loop == c || s == NULL || s->curw->window != w)
|
||||
continue;
|
||||
if (found == NULL ||
|
||||
timercmp(&loop->activity_time, &found->activity_time,
|
||||
>))
|
||||
found = loop;
|
||||
}
|
||||
if (found != NULL)
|
||||
server_client_update_latest(found);
|
||||
}
|
||||
}
|
||||
|
||||
/* Lost a client. */
|
||||
void
|
||||
server_client_lost(struct client *c)
|
||||
@@ -296,8 +331,10 @@ server_client_lost(struct client *c)
|
||||
TAILQ_REMOVE(&clients, c, entry);
|
||||
log_debug("lost client %p", c);
|
||||
|
||||
if (c->flags & CLIENT_ATTACHED)
|
||||
if (c->flags & CLIENT_ATTACHED) {
|
||||
server_client_attached_lost(c);
|
||||
notify_client("client-detached", c);
|
||||
}
|
||||
|
||||
if (c->flags & CLIENT_CONTROL)
|
||||
control_stop(c);
|
||||
@@ -1410,84 +1447,79 @@ server_client_resize_timer(__unused int fd, __unused short events, void *data)
|
||||
evtimer_del(&wp->resize_timer);
|
||||
}
|
||||
|
||||
/* Start the resize timer. */
|
||||
static void
|
||||
server_client_start_resize_timer(struct window_pane *wp)
|
||||
{
|
||||
struct timeval tv = { .tv_usec = 250000 };
|
||||
|
||||
log_debug("%s: %%%u resize timer started", __func__, wp->id);
|
||||
evtimer_add(&wp->resize_timer, &tv);
|
||||
}
|
||||
|
||||
/* Force timer event. */
|
||||
static void
|
||||
server_client_force_timer(__unused int fd, __unused short events, void *data)
|
||||
{
|
||||
struct window_pane *wp = data;
|
||||
|
||||
log_debug("%s: %%%u force timer expired", __func__, wp->id);
|
||||
evtimer_del(&wp->force_timer);
|
||||
wp->flags |= PANE_RESIZENOW;
|
||||
}
|
||||
|
||||
/* Start the force timer. */
|
||||
static void
|
||||
server_client_start_force_timer(struct window_pane *wp)
|
||||
{
|
||||
struct timeval tv = { .tv_usec = 10000 };
|
||||
|
||||
log_debug("%s: %%%u force timer started", __func__, wp->id);
|
||||
evtimer_add(&wp->force_timer, &tv);
|
||||
}
|
||||
|
||||
/* Check if pane should be resized. */
|
||||
static void
|
||||
server_client_check_pane_resize(struct window_pane *wp)
|
||||
{
|
||||
struct window_pane_resize *r;
|
||||
struct window_pane_resize *r1;
|
||||
struct window_pane_resize *first;
|
||||
struct window_pane_resize *last;
|
||||
struct timeval tv = { .tv_usec = 250000 };
|
||||
|
||||
if (TAILQ_EMPTY(&wp->resize_queue))
|
||||
return;
|
||||
|
||||
if (!event_initialized(&wp->resize_timer))
|
||||
evtimer_set(&wp->resize_timer, server_client_resize_timer, wp);
|
||||
if (!event_initialized(&wp->force_timer))
|
||||
evtimer_set(&wp->force_timer, server_client_force_timer, wp);
|
||||
|
||||
if (~wp->flags & PANE_RESIZE)
|
||||
if (evtimer_pending(&wp->resize_timer, NULL))
|
||||
return;
|
||||
|
||||
log_debug("%s: %%%u needs to be resized", __func__, wp->id);
|
||||
|
||||
if (evtimer_pending(&wp->resize_timer, NULL)) {
|
||||
log_debug("%s: %%%u resize timer is running", __func__, wp->id);
|
||||
return;
|
||||
TAILQ_FOREACH(r, &wp->resize_queue, entry) {
|
||||
log_debug("queued resize: %ux%u -> %ux%u", r->osx, r->osy,
|
||||
r->sx, r->sy);
|
||||
}
|
||||
server_client_start_resize_timer(wp);
|
||||
|
||||
if (~wp->flags & PANE_RESIZEFORCE) {
|
||||
/*
|
||||
* The timer is not running and we don't need to force a
|
||||
* resize, so just resize immediately.
|
||||
*/
|
||||
log_debug("%s: resizing %%%u now", __func__, wp->id);
|
||||
window_pane_send_resize(wp, 0);
|
||||
wp->flags &= ~PANE_RESIZE;
|
||||
/*
|
||||
* There are three cases that matter:
|
||||
*
|
||||
* - Only one resize. It can just be applied.
|
||||
*
|
||||
* - Multiple resizes and the ending size is different from the
|
||||
* starting size. We can discard all resizes except the most recent.
|
||||
*
|
||||
* - Multiple resizes and the ending size is the same as the starting
|
||||
* size. We must resize at least twice to force the application to
|
||||
* redraw. So apply the first and leave the last on the queue for
|
||||
* next time.
|
||||
*/
|
||||
first = TAILQ_FIRST(&wp->resize_queue);
|
||||
last = TAILQ_LAST(&wp->resize_queue, window_pane_resizes);
|
||||
if (first == last) {
|
||||
/* Only one resize. */
|
||||
window_pane_send_resize(wp, first->sx, first->sy);
|
||||
TAILQ_REMOVE(&wp->resize_queue, first, entry);
|
||||
free(first);
|
||||
} else if (last->sx != first->osx || last->sy != first->osy) {
|
||||
/* Multiple resizes ending up with a different size. */
|
||||
window_pane_send_resize(wp, last->sx, last->sy);
|
||||
TAILQ_FOREACH_SAFE(r, &wp->resize_queue, entry, r1) {
|
||||
TAILQ_REMOVE(&wp->resize_queue, r, entry);
|
||||
free(r);
|
||||
}
|
||||
} else {
|
||||
/*
|
||||
* The timer is not running, but we need to force a resize. If
|
||||
* the force timer has expired, resize to the real size now.
|
||||
* Otherwise resize to the force size and start the timer.
|
||||
* Multiple resizes ending up with the same size. There will
|
||||
* not be more than one to the same size in succession so we
|
||||
* can just use the last-but-one on the list and leave the last
|
||||
* for later. We reduce the time until the next check to avoid
|
||||
* a long delay between the resizes.
|
||||
*/
|
||||
if (wp->flags & PANE_RESIZENOW) {
|
||||
log_debug("%s: resizing %%%u after forced resize",
|
||||
__func__, wp->id);
|
||||
window_pane_send_resize(wp, 0);
|
||||
wp->flags &= ~(PANE_RESIZE|PANE_RESIZEFORCE|PANE_RESIZENOW);
|
||||
} else if (!evtimer_pending(&wp->force_timer, NULL)) {
|
||||
log_debug("%s: forcing resize of %%%u", __func__,
|
||||
wp->id);
|
||||
window_pane_send_resize(wp, 1);
|
||||
server_client_start_force_timer(wp);
|
||||
r = TAILQ_PREV(last, window_pane_resizes, entry);
|
||||
window_pane_send_resize(wp, r->sx, r->sy);
|
||||
TAILQ_FOREACH_SAFE(r, &wp->resize_queue, entry, r1) {
|
||||
if (r == last)
|
||||
break;
|
||||
TAILQ_REMOVE(&wp->resize_queue, r, entry);
|
||||
free(r);
|
||||
}
|
||||
tv.tv_usec = 10000;
|
||||
}
|
||||
evtimer_add(&wp->resize_timer, &tv);
|
||||
}
|
||||
|
||||
|
||||
/* Check pane buffer size. */
|
||||
static void
|
||||
server_client_check_pane_buffer(struct window_pane *wp)
|
||||
|
||||
3
server.c
3
server.c
@@ -163,7 +163,8 @@ server_tidy_event(__unused int fd, __unused short events, __unused void *data)
|
||||
malloc_trim(0);
|
||||
#endif
|
||||
|
||||
log_debug("%s: took %llu milliseconds", __func__, get_timer() - t);
|
||||
log_debug("%s: took %llu milliseconds", __func__,
|
||||
(unsigned long long)(get_timer() - t));
|
||||
evtimer_add(&server_ev_tidy, &tv);
|
||||
}
|
||||
|
||||
|
||||
4
status.c
4
status.c
@@ -226,6 +226,8 @@ status_line_size(struct client *c)
|
||||
|
||||
if (c->flags & (CLIENT_STATUSOFF|CLIENT_CONTROL))
|
||||
return (0);
|
||||
if (s == NULL)
|
||||
return (options_get_number(global_s_options, "status"));
|
||||
return (s->statuslines);
|
||||
}
|
||||
|
||||
@@ -1298,7 +1300,7 @@ process_key:
|
||||
return (0);
|
||||
|
||||
append_key:
|
||||
if (key <= 0x1f || key >= KEYC_BASE)
|
||||
if (key <= 0x1f || (key >= KEYC_BASE && key < KEYC_BASE_END))
|
||||
return (0);
|
||||
if (key <= 0x7f)
|
||||
utf8_set(&tmp, key);
|
||||
|
||||
42
tmux.1
42
tmux.1
@@ -2953,6 +2953,8 @@ Ctrl keys may be prefixed with
|
||||
.Ql C-
|
||||
or
|
||||
.Ql ^ ,
|
||||
Shift keys with
|
||||
.Ql S-
|
||||
and Alt (meta) with
|
||||
.Ql M- .
|
||||
In addition, the following special key names are accepted:
|
||||
@@ -3418,11 +3420,24 @@ sessions.
|
||||
.Xc
|
||||
If enabled, the server will exit when there are no attached clients.
|
||||
.It Xo Ic extended-keys
|
||||
.Op Ic on | off
|
||||
.Op Ic on | off | always
|
||||
.Xc
|
||||
When enabled, extended keys are requested from the terminal and if supported
|
||||
are recognised by
|
||||
.Nm .
|
||||
When
|
||||
.Ic on
|
||||
or
|
||||
.Ic always ,
|
||||
the escape sequence to enable extended keys is sent to the terminal, if
|
||||
.Nm
|
||||
knows that it is supported.
|
||||
.Nm
|
||||
always recognises extended keys itself.
|
||||
If this option is
|
||||
.Ic on ,
|
||||
.Nm
|
||||
will only forward extended keys to applications when they request them; if
|
||||
.Ic always ,
|
||||
.Nm
|
||||
will always forward the keys.
|
||||
.It Xo Ic focus-events
|
||||
.Op Ic on | off
|
||||
.Xc
|
||||
@@ -3501,8 +3516,8 @@ capabilities to be set instead,
|
||||
is intended for classes of functionality supported in a standard way but not
|
||||
reported by
|
||||
.Xr terminfo 5 .
|
||||
Care must be taken only to configure this with features the terminal actually
|
||||
support.
|
||||
Care must be taken to configure this only with features the terminal actually
|
||||
supports.
|
||||
.Pp
|
||||
This is an array option where each entry is a colon-separated string made up
|
||||
of a terminal type pattern (matched using
|
||||
@@ -3524,6 +3539,10 @@ Supports extended keys.
|
||||
Supports focus reporting.
|
||||
.It margins
|
||||
Supports DECSLRM margins.
|
||||
.It mouse
|
||||
Supports
|
||||
.Xr xterm 1
|
||||
mouse sequences.
|
||||
.It overline
|
||||
Supports the overline SGR attribute.
|
||||
.It rectfill
|
||||
@@ -6036,6 +6055,10 @@ Disable and enable focus reporting.
|
||||
These are set automatically if the
|
||||
.Em XT
|
||||
capability is present.
|
||||
.It Em \&Rect
|
||||
Tell
|
||||
.Nm
|
||||
that the terminal supports rectangle operations.
|
||||
.It Em \&Smol
|
||||
Enable the overline attribute.
|
||||
.It Em \&Smulx
|
||||
@@ -6116,12 +6139,13 @@ and matching
|
||||
.Em %end
|
||||
or
|
||||
.Em %error
|
||||
have two arguments: an integer time (as seconds from epoch) and command number.
|
||||
have three arguments: an integer time (as seconds from epoch), command number and
|
||||
flags (currently not used).
|
||||
For example:
|
||||
.Bd -literal -offset indent
|
||||
%begin 1363006971 2
|
||||
%begin 1363006971 2 1
|
||||
0: ksh* (1 panes) [80x24] [layout b25f,80x24,0,0,2] @2 (active)
|
||||
%end 1363006971 2
|
||||
%end 1363006971 2 1
|
||||
.Ed
|
||||
.Pp
|
||||
The
|
||||
|
||||
15
tmux.c
15
tmux.c
@@ -328,7 +328,7 @@ main(int argc, char **argv)
|
||||
char *path = NULL, *label = NULL;
|
||||
char *cause, **var;
|
||||
const char *s, *cwd;
|
||||
int opt, keys, feat = 0;
|
||||
int opt, keys, feat = 0, fflag = 0;
|
||||
uint64_t flags = 0;
|
||||
const struct options_table_entry *oe;
|
||||
u_int i;
|
||||
@@ -373,10 +373,15 @@ main(int argc, char **argv)
|
||||
flags |= CLIENT_CONTROL;
|
||||
break;
|
||||
case 'f':
|
||||
for (i = 0; i < cfg_nfiles; i++)
|
||||
free(cfg_files[i]);
|
||||
free(cfg_files);
|
||||
expand_paths(optarg, &cfg_files, &cfg_nfiles, 0);
|
||||
if (!fflag) {
|
||||
fflag = 1;
|
||||
for (i = 0; i < cfg_nfiles; i++)
|
||||
free(cfg_files[i]);
|
||||
cfg_nfiles = 0;
|
||||
}
|
||||
cfg_files = xreallocarray(cfg_files, cfg_nfiles + 1,
|
||||
sizeof *cfg_files);
|
||||
cfg_files[cfg_nfiles++] = xstrdup(optarg);
|
||||
cfg_quiet = 0;
|
||||
break;
|
||||
case 'V':
|
||||
|
||||
59
tmux.h
59
tmux.h
@@ -109,11 +109,16 @@ struct winlink;
|
||||
#define VISUAL_ON 1
|
||||
#define VISUAL_BOTH 2
|
||||
|
||||
/* Special key codes. */
|
||||
#define KEYC_NONE 0x00ff000000000ULL
|
||||
#define KEYC_UNKNOWN 0x00fe000000000ULL
|
||||
#define KEYC_BASE 0x0001000000000ULL
|
||||
#define KEYC_USER 0x0002000000000ULL
|
||||
/* No key or unknown key. */
|
||||
#define KEYC_NONE 0x000ff000000000ULL
|
||||
#define KEYC_UNKNOWN 0x000fe000000000ULL
|
||||
|
||||
/*
|
||||
* Base for special (that is, not Unicode) keys. An enum must be at most a
|
||||
* signed int, so these are based in the highest Unicode PUA.
|
||||
*/
|
||||
#define KEYC_BASE 0x0000000010e000ULL
|
||||
#define KEYC_USER 0x0000000010f000ULL
|
||||
|
||||
/* Key modifier bits. */
|
||||
#define KEYC_META 0x00100000000000ULL
|
||||
@@ -136,8 +141,15 @@ struct winlink;
|
||||
#define KEYC_NUSER 1000
|
||||
|
||||
/* Is this a mouse key? */
|
||||
#define KEYC_IS_MOUSE(key) (((key) & KEYC_MASK_KEY) >= KEYC_MOUSE && \
|
||||
((key) & KEYC_MASK_KEY) < KEYC_BSPACE)
|
||||
#define KEYC_IS_MOUSE(key) \
|
||||
(((key) & KEYC_MASK_KEY) >= KEYC_MOUSE && \
|
||||
((key) & KEYC_MASK_KEY) < KEYC_BSPACE)
|
||||
|
||||
/* Is this a Unicode key? */
|
||||
#define KEYC_IS_UNICODE(key) \
|
||||
(((key) & KEYC_MASK_KEY) > 0x7f && \
|
||||
(((key) & KEYC_MASK_KEY) < KEYC_BASE || \
|
||||
((key) & KEYC_MASK_KEY) >= KEYC_BASE_END))
|
||||
|
||||
/* Multiple click timeout. */
|
||||
#define KEYC_CLICK_TIMEOUT 300
|
||||
@@ -159,8 +171,8 @@ struct winlink;
|
||||
{ #s "Border", KEYC_ ## name ## _BORDER }
|
||||
|
||||
/*
|
||||
* A single key. This can be ASCII or Unicode or one of the keys starting at
|
||||
* KEYC_BASE.
|
||||
* A single key. This can be ASCII or Unicode or one of the keys between
|
||||
* KEYC_BASE and KEYC_BASE_END.
|
||||
*/
|
||||
typedef unsigned long long key_code;
|
||||
|
||||
@@ -253,6 +265,9 @@ enum {
|
||||
KEYC_KP_ENTER,
|
||||
KEYC_KP_ZERO,
|
||||
KEYC_KP_PERIOD,
|
||||
|
||||
/* End of special keys. */
|
||||
KEYC_BASE_END
|
||||
};
|
||||
|
||||
/* Termcap codes. */
|
||||
@@ -452,6 +467,7 @@ enum tty_code_code {
|
||||
TTYC_MS,
|
||||
TTYC_OL,
|
||||
TTYC_OP,
|
||||
TTYC_RECT,
|
||||
TTYC_REV,
|
||||
TTYC_RGB,
|
||||
TTYC_RI,
|
||||
@@ -918,7 +934,7 @@ struct window_mode_entry {
|
||||
struct screen *screen;
|
||||
u_int prefix;
|
||||
|
||||
TAILQ_ENTRY (window_mode_entry) entry;
|
||||
TAILQ_ENTRY(window_mode_entry) entry;
|
||||
};
|
||||
|
||||
/* Offsets into pane buffer. */
|
||||
@@ -926,6 +942,18 @@ struct window_pane_offset {
|
||||
size_t used;
|
||||
};
|
||||
|
||||
/* Queued pane resize. */
|
||||
struct window_pane_resize {
|
||||
u_int sx;
|
||||
u_int sy;
|
||||
|
||||
u_int osx;
|
||||
u_int osy;
|
||||
|
||||
TAILQ_ENTRY(window_pane_resize) entry;
|
||||
};
|
||||
TAILQ_HEAD(window_pane_resizes, window_pane_resize);
|
||||
|
||||
/* Child window structure. */
|
||||
struct window_pane {
|
||||
u_int id;
|
||||
@@ -950,8 +978,8 @@ struct window_pane {
|
||||
#define PANE_REDRAW 0x1
|
||||
#define PANE_DROP 0x2
|
||||
#define PANE_FOCUSED 0x4
|
||||
#define PANE_RESIZE 0x8
|
||||
#define PANE_RESIZEFORCE 0x10
|
||||
/* 0x8 unused */
|
||||
/* 0x10 unused */
|
||||
#define PANE_FOCUSPUSH 0x20
|
||||
#define PANE_INPUTOFF 0x40
|
||||
#define PANE_CHANGED 0x80
|
||||
@@ -960,7 +988,6 @@ struct window_pane {
|
||||
#define PANE_STATUSDRAWN 0x400
|
||||
#define PANE_EMPTY 0x800
|
||||
#define PANE_STYLECHANGED 0x1000
|
||||
#define PANE_RESIZENOW 0x2000
|
||||
|
||||
int argc;
|
||||
char **argv;
|
||||
@@ -977,8 +1004,8 @@ struct window_pane {
|
||||
struct window_pane_offset offset;
|
||||
size_t base_offset;
|
||||
|
||||
struct window_pane_resizes resize_queue;
|
||||
struct event resize_timer;
|
||||
struct event force_timer;
|
||||
|
||||
struct input_ctx *ictx;
|
||||
|
||||
@@ -996,7 +1023,7 @@ struct window_pane {
|
||||
struct screen status_screen;
|
||||
size_t status_size;
|
||||
|
||||
TAILQ_HEAD (, window_mode_entry) modes;
|
||||
TAILQ_HEAD(, window_mode_entry) modes;
|
||||
|
||||
char *searchstr;
|
||||
int searchregex;
|
||||
@@ -2755,7 +2782,7 @@ void window_redraw_active_switch(struct window *,
|
||||
struct window_pane *window_add_pane(struct window *, struct window_pane *,
|
||||
u_int, int);
|
||||
void window_resize(struct window *, u_int, u_int, int, int);
|
||||
void window_pane_send_resize(struct window_pane *, int);
|
||||
void window_pane_send_resize(struct window_pane *, u_int, u_int);
|
||||
int window_zoom(struct window_pane *);
|
||||
int window_unzoom(struct window *);
|
||||
int window_push_zoom(struct window *, int, int);
|
||||
|
||||
@@ -25,7 +25,6 @@
|
||||
|
||||
/*
|
||||
* Still hardcoded:
|
||||
* - mouse (under kmous capability);
|
||||
* - default colours (under AX or op capabilities);
|
||||
* - AIX colours (under colors >= 16);
|
||||
* - alternate escape (if terminal is VT100-like).
|
||||
@@ -54,6 +53,17 @@ static const struct tty_feature tty_feature_title = {
|
||||
0
|
||||
};
|
||||
|
||||
/* Terminal has mouse support. */
|
||||
static const char *tty_feature_mouse_capabilities[] = {
|
||||
"kmous=\\E[M",
|
||||
NULL
|
||||
};
|
||||
static const struct tty_feature tty_feature_mouse = {
|
||||
"mouse",
|
||||
tty_feature_mouse_capabilities,
|
||||
0
|
||||
};
|
||||
|
||||
/* Terminal can set the clipboard with OSC 52. */
|
||||
static const char *tty_feature_clipboard_capabilities[] = {
|
||||
"Ms=\\E]52;%p1%s;%p2%s\\a",
|
||||
@@ -218,9 +228,13 @@ static const struct tty_feature tty_feature_margins = {
|
||||
};
|
||||
|
||||
/* Terminal supports DECFRA rectangle fill. */
|
||||
static const char *tty_feature_rectfill_capabilities[] = {
|
||||
"Rect",
|
||||
NULL
|
||||
};
|
||||
static const struct tty_feature tty_feature_rectfill = {
|
||||
"rectfill",
|
||||
NULL,
|
||||
tty_feature_rectfill_capabilities,
|
||||
TERM_DECFRA
|
||||
};
|
||||
|
||||
@@ -234,6 +248,7 @@ static const struct tty_feature *tty_features[] = {
|
||||
&tty_feature_extkeys,
|
||||
&tty_feature_focus,
|
||||
&tty_feature_margins,
|
||||
&tty_feature_mouse,
|
||||
&tty_feature_overline,
|
||||
&tty_feature_rectfill,
|
||||
&tty_feature_rgb,
|
||||
@@ -334,7 +349,7 @@ tty_default_features(int *feat, const char *name, u_int version)
|
||||
const char *features;
|
||||
} table[] = {
|
||||
#define TTY_FEATURES_BASE_MODERN_XTERM \
|
||||
"256,RGB,bpaste,clipboard,strikethrough,title"
|
||||
"256,RGB,bpaste,clipboard,mouse,strikethrough,title"
|
||||
{ .name = "mintty",
|
||||
.features = TTY_FEATURES_BASE_MODERN_XTERM
|
||||
",ccolour,cstyle,extkeys,margins,overline,usstyle"
|
||||
@@ -344,15 +359,20 @@ tty_default_features(int *feat, const char *name, u_int version)
|
||||
",ccolour,cstyle,focus,overline,usstyle"
|
||||
},
|
||||
{ .name = "rxvt-unicode",
|
||||
.features = "256,bpaste,ccolour,cstyle,title"
|
||||
.features = "256,bpaste,ccolour,cstyle,mouse,title"
|
||||
},
|
||||
{ .name = "iTerm2",
|
||||
.features = TTY_FEATURES_BASE_MODERN_XTERM
|
||||
",cstyle,extkeys,margins,sync"
|
||||
},
|
||||
{ .name = "XTerm",
|
||||
/*
|
||||
* xterm also supports DECSLRM and DECFRA, but they can be
|
||||
* disabled so not set it here - they will be added if
|
||||
* secondary DA shows VT420.
|
||||
*/
|
||||
.features = TTY_FEATURES_BASE_MODERN_XTERM
|
||||
",ccolour,cstyle,extkeys,focus,margins,rectfill"
|
||||
",ccolour,cstyle,extkeys,focus"
|
||||
}
|
||||
};
|
||||
u_int i;
|
||||
|
||||
39
tty-keys.c
39
tty-keys.c
@@ -252,7 +252,8 @@ static const key_code tty_default_xterm_modifiers[] = {
|
||||
KEYC_CTRL,
|
||||
KEYC_SHIFT|KEYC_CTRL,
|
||||
KEYC_META|KEYC_IMPLIED_META|KEYC_CTRL,
|
||||
KEYC_SHIFT|KEYC_META|KEYC_IMPLIED_META|KEYC_CTRL
|
||||
KEYC_SHIFT|KEYC_META|KEYC_IMPLIED_META|KEYC_CTRL,
|
||||
KEYC_META|KEYC_IMPLIED_META
|
||||
};
|
||||
|
||||
/*
|
||||
@@ -944,6 +945,9 @@ tty_keys_extended_key(struct tty *tty, const char *buf, size_t len,
|
||||
case 8:
|
||||
nkey |= (KEYC_SHIFT|KEYC_META|KEYC_IMPLIED_META|KEYC_CTRL);
|
||||
break;
|
||||
case 9:
|
||||
nkey |= (KEYC_META|KEYC_IMPLIED_META);
|
||||
break;
|
||||
default:
|
||||
*key = KEYC_NONE;
|
||||
break;
|
||||
@@ -955,23 +959,22 @@ tty_keys_extended_key(struct tty *tty, const char *buf, size_t len,
|
||||
*/
|
||||
if (nkey & KEYC_CTRL) {
|
||||
onlykey = (nkey & KEYC_MASK_KEY);
|
||||
if (onlykey < 32) {
|
||||
if (onlykey != 9)
|
||||
onlykey = (nkey & ~KEYC_CTRL);
|
||||
else
|
||||
onlykey = (9|KEYC_CTRL);
|
||||
} else {
|
||||
if (onlykey >= 97 && onlykey <= 122)
|
||||
onlykey -= 96;
|
||||
else if (onlykey >= 64 && onlykey <= 95)
|
||||
onlykey -= 64;
|
||||
else if (onlykey == 32)
|
||||
onlykey = 0;
|
||||
else if (onlykey == 63)
|
||||
onlykey = 127;
|
||||
onlykey |= ((nkey & KEYC_MASK_MODIFIERS) & ~KEYC_CTRL);
|
||||
}
|
||||
nkey = onlykey;
|
||||
if (onlykey < 32 &&
|
||||
onlykey != 9 &&
|
||||
onlykey != 13 &&
|
||||
onlykey != 27)
|
||||
/* nothing */;
|
||||
else if (onlykey >= 97 && onlykey <= 122)
|
||||
onlykey -= 96;
|
||||
else if (onlykey >= 64 && onlykey <= 95)
|
||||
onlykey -= 64;
|
||||
else if (onlykey == 32)
|
||||
onlykey = 0;
|
||||
else if (onlykey == 63)
|
||||
onlykey = 127;
|
||||
else
|
||||
onlykey |= KEYC_CTRL;
|
||||
nkey = onlykey|((nkey & KEYC_MASK_MODIFIERS) & ~KEYC_CTRL);
|
||||
}
|
||||
|
||||
if (log_get_level() != 0) {
|
||||
|
||||
100
tty-term.c
100
tty-term.c
@@ -251,6 +251,7 @@ static const struct tty_term_code_entry tty_term_codes[] = {
|
||||
[TTYC_MS] = { TTYCODE_STRING, "Ms" },
|
||||
[TTYC_OL] = { TTYCODE_STRING, "ol" },
|
||||
[TTYC_OP] = { TTYCODE_STRING, "op" },
|
||||
[TTYC_RECT] = { TTYCODE_STRING, "Rect" },
|
||||
[TTYC_REV] = { TTYCODE_STRING, "rev" },
|
||||
[TTYC_RGB] = { TTYCODE_FLAG, "RGB" },
|
||||
[TTYC_RIN] = { TTYCODE_STRING, "rin" },
|
||||
@@ -434,10 +435,11 @@ tty_term_apply_overrides(struct tty_term *term)
|
||||
struct options_entry *o;
|
||||
struct options_array_item *a;
|
||||
union options_value *ov;
|
||||
const char *s;
|
||||
const char *s, *acs;
|
||||
size_t offset;
|
||||
char *first;
|
||||
|
||||
/* Update capabilities from the option. */
|
||||
o = options_get_only(global_options, "terminal-overrides");
|
||||
a = options_array_first(o);
|
||||
while (a != NULL) {
|
||||
@@ -450,6 +452,64 @@ tty_term_apply_overrides(struct tty_term *term)
|
||||
tty_term_apply(term, s + offset, 0);
|
||||
a = options_array_next(a);
|
||||
}
|
||||
|
||||
/* Update the RGB flag if the terminal has RGB colours. */
|
||||
if (tty_term_has(term, TTYC_SETRGBF) &&
|
||||
tty_term_has(term, TTYC_SETRGBB))
|
||||
term->flags |= TERM_RGBCOLOURS;
|
||||
else
|
||||
term->flags &= ~TERM_RGBCOLOURS;
|
||||
log_debug("RGBCOLOURS flag is %d", !!(term->flags & TERM_RGBCOLOURS));
|
||||
|
||||
/*
|
||||
* Set or clear the DECSLRM flag if the terminal has the margin
|
||||
* capabilities.
|
||||
*/
|
||||
if (tty_term_has(term, TTYC_CMG) && tty_term_has(term, TTYC_CLMG))
|
||||
term->flags |= TERM_DECSLRM;
|
||||
else
|
||||
term->flags &= ~TERM_DECSLRM;
|
||||
log_debug("DECSLRM flag is %d", !!(term->flags & TERM_DECSLRM));
|
||||
|
||||
/*
|
||||
* Set or clear the DECFRA flag if the terminal has the rectangle
|
||||
* capability.
|
||||
*/
|
||||
if (tty_term_has(term, TTYC_RECT))
|
||||
term->flags |= TERM_DECFRA;
|
||||
else
|
||||
term->flags &= ~TERM_DECFRA;
|
||||
log_debug("DECFRA flag is %d", !!(term->flags & TERM_DECFRA));
|
||||
|
||||
/*
|
||||
* Terminals without am (auto right margin) wrap at at $COLUMNS - 1
|
||||
* rather than $COLUMNS (the cursor can never be beyond $COLUMNS - 1).
|
||||
*
|
||||
* Terminals without xenl (eat newline glitch) ignore a newline beyond
|
||||
* the right edge of the terminal, but tmux doesn't care about this -
|
||||
* it always uses absolute only moves the cursor with a newline when
|
||||
* also sending a linefeed.
|
||||
*
|
||||
* This is irritating, most notably because it is painful to write to
|
||||
* the very bottom-right of the screen without scrolling.
|
||||
*
|
||||
* Flag the terminal here and apply some workarounds in other places to
|
||||
* do the best possible.
|
||||
*/
|
||||
if (!tty_term_flag(term, TTYC_AM))
|
||||
term->flags |= TERM_NOAM;
|
||||
else
|
||||
term->flags &= ~TERM_NOAM;
|
||||
log_debug("NOAM flag is %d", !!(term->flags & TERM_NOAM));
|
||||
|
||||
/* Generate ACS table. If none is present, use nearest ASCII. */
|
||||
memset(term->acs, 0, sizeof term->acs);
|
||||
if (tty_term_has(term, TTYC_ACSC))
|
||||
acs = tty_term_string(term, TTYC_ACSC);
|
||||
else
|
||||
acs = "a#j+k+l+m+n+o-p-q-r-s-t+u+v+w+x|y<z>~.";
|
||||
for (; acs[0] != '\0' && acs[1] != '\0'; acs += 2)
|
||||
term->acs[(u_char) acs[0]][0] = acs[1];
|
||||
}
|
||||
|
||||
struct tty_term *
|
||||
@@ -463,7 +523,7 @@ tty_term_create(struct tty *tty, char *name, char **caps, u_int ncaps,
|
||||
struct options_array_item *a;
|
||||
union options_value *ov;
|
||||
u_int i, j;
|
||||
const char *s, *acs, *value;
|
||||
const char *s, *value;
|
||||
size_t offset, namelen;
|
||||
char *first;
|
||||
|
||||
@@ -566,40 +626,10 @@ tty_term_create(struct tty *tty, char *name, char **caps, u_int ncaps,
|
||||
(!tty_term_has(term, TTYC_SETRGBF) ||
|
||||
!tty_term_has(term, TTYC_SETRGBB)))
|
||||
tty_add_features(feat, "RGB", ",");
|
||||
if (tty_term_has(term, TTYC_SETRGBF) &&
|
||||
tty_term_has(term, TTYC_SETRGBB))
|
||||
term->flags |= TERM_RGBCOLOURS;
|
||||
|
||||
/* Apply the features and overrides again. */
|
||||
tty_apply_features(term, *feat);
|
||||
tty_term_apply_overrides(term);
|
||||
|
||||
/*
|
||||
* Terminals without am (auto right margin) wrap at at $COLUMNS - 1
|
||||
* rather than $COLUMNS (the cursor can never be beyond $COLUMNS - 1).
|
||||
*
|
||||
* Terminals without xenl (eat newline glitch) ignore a newline beyond
|
||||
* the right edge of the terminal, but tmux doesn't care about this -
|
||||
* it always uses absolute only moves the cursor with a newline when
|
||||
* also sending a linefeed.
|
||||
*
|
||||
* This is irritating, most notably because it is painful to write to
|
||||
* the very bottom-right of the screen without scrolling.
|
||||
*
|
||||
* Flag the terminal here and apply some workarounds in other places to
|
||||
* do the best possible.
|
||||
*/
|
||||
if (!tty_term_flag(term, TTYC_AM))
|
||||
term->flags |= TERM_NOAM;
|
||||
|
||||
/* Generate ACS table. If none is present, use nearest ASCII. */
|
||||
memset(term->acs, 0, sizeof term->acs);
|
||||
if (tty_term_has(term, TTYC_ACSC))
|
||||
acs = tty_term_string(term, TTYC_ACSC);
|
||||
else
|
||||
acs = "a#j+k+l+m+n+o-p-q-r-s-t+u+v+w+x|y<z>~.";
|
||||
for (; acs[0] != '\0' && acs[1] != '\0'; acs += 2)
|
||||
term->acs[(u_char) acs[0]][0] = acs[1];
|
||||
if (tty_apply_features(term, *feat))
|
||||
tty_term_apply_overrides(term);
|
||||
|
||||
/* Log the capabilities. */
|
||||
for (i = 0; i < tty_term_ncodes(); i++)
|
||||
@@ -667,7 +697,7 @@ tty_term_read_list(const char *name, int fd, char ***caps, u_int *ncaps,
|
||||
ent = &tty_term_codes[i];
|
||||
switch (ent->type) {
|
||||
case TTYCODE_NONE:
|
||||
break;
|
||||
continue;
|
||||
case TTYCODE_STRING:
|
||||
s = tigetstr((char *)ent->name);
|
||||
if (s == NULL || s == (char *)-1)
|
||||
|
||||
9
tty.c
9
tty.c
@@ -958,13 +958,8 @@ tty_redraw_region(struct tty *tty, const struct tty_ctx *ctx)
|
||||
return;
|
||||
}
|
||||
|
||||
if (ctx->ocy < ctx->orupper || ctx->ocy > ctx->orlower) {
|
||||
for (i = ctx->ocy; i < ctx->sy; i++)
|
||||
tty_draw_pane(tty, ctx, i);
|
||||
} else {
|
||||
for (i = ctx->orupper; i <= ctx->orlower; i++)
|
||||
tty_draw_pane(tty, ctx, i);
|
||||
}
|
||||
for (i = ctx->orupper; i <= ctx->orlower; i++)
|
||||
tty_draw_pane(tty, ctx, i);
|
||||
}
|
||||
|
||||
/* Is this position visible in the pane? */
|
||||
|
||||
@@ -294,9 +294,9 @@ window_buffer_get_key(void *modedata, void *itemdata, u_int line)
|
||||
struct window_buffer_modedata *data = modedata;
|
||||
struct window_buffer_itemdata *item = itemdata;
|
||||
struct format_tree *ft;
|
||||
struct session *s;
|
||||
struct winlink *wl;
|
||||
struct window_pane *wp;
|
||||
struct session *s = NULL;
|
||||
struct winlink *wl = NULL;
|
||||
struct window_pane *wp = NULL;
|
||||
struct paste_buffer *pb;
|
||||
char *expanded;
|
||||
key_code key;
|
||||
|
||||
@@ -1102,10 +1102,13 @@ static enum window_copy_cmd_action
|
||||
window_copy_cmd_cursor_right(struct window_copy_cmd_state *cs)
|
||||
{
|
||||
struct window_mode_entry *wme = cs->wme;
|
||||
struct window_copy_mode_data *data = wme->data;
|
||||
u_int np = wme->prefix;
|
||||
|
||||
for (; np != 0; np--)
|
||||
window_copy_cursor_right(wme, 0);
|
||||
for (; np != 0; np--) {
|
||||
window_copy_cursor_right(wme, data->screen.sel != NULL &&
|
||||
data->rectflag);
|
||||
}
|
||||
return (WINDOW_COPY_CMD_NOTHING);
|
||||
}
|
||||
|
||||
@@ -4425,10 +4428,12 @@ window_copy_cursor_up(struct window_mode_entry *wme, int scroll_only)
|
||||
struct window_copy_mode_data *data = wme->data;
|
||||
struct screen *s = &data->screen;
|
||||
u_int ox, oy, px, py;
|
||||
int norectsel;
|
||||
|
||||
norectsel = data->screen.sel == NULL || !data->rectflag;
|
||||
oy = screen_hsize(data->backing) + data->cy - data->oy;
|
||||
ox = window_copy_find_length(wme, oy);
|
||||
if (data->cx != ox) {
|
||||
if (norectsel && data->cx != ox) {
|
||||
data->lastcx = data->cx;
|
||||
data->lastsx = ox;
|
||||
}
|
||||
@@ -4437,7 +4442,8 @@ window_copy_cursor_up(struct window_mode_entry *wme, int scroll_only)
|
||||
window_copy_other_end(wme);
|
||||
|
||||
if (scroll_only || data->cy == 0) {
|
||||
data->cx = data->lastcx;
|
||||
if (norectsel)
|
||||
data->cx = data->lastcx;
|
||||
window_copy_scroll_down(wme, 1);
|
||||
if (scroll_only) {
|
||||
if (data->cy == screen_size_y(s) - 1)
|
||||
@@ -4446,7 +4452,11 @@ window_copy_cursor_up(struct window_mode_entry *wme, int scroll_only)
|
||||
window_copy_redraw_lines(wme, data->cy, 2);
|
||||
}
|
||||
} else {
|
||||
window_copy_update_cursor(wme, data->lastcx, data->cy - 1);
|
||||
if (norectsel) {
|
||||
window_copy_update_cursor(wme, data->lastcx,
|
||||
data->cy - 1);
|
||||
} else
|
||||
window_copy_update_cursor(wme, data->cx, data->cy - 1);
|
||||
if (window_copy_update_selection(wme, 1, 0)) {
|
||||
if (data->cy == screen_size_y(s) - 1)
|
||||
window_copy_redraw_lines(wme, data->cy, 1);
|
||||
@@ -4455,7 +4465,7 @@ window_copy_cursor_up(struct window_mode_entry *wme, int scroll_only)
|
||||
}
|
||||
}
|
||||
|
||||
if (data->screen.sel == NULL || !data->rectflag) {
|
||||
if (norectsel) {
|
||||
py = screen_hsize(data->backing) + data->cy - data->oy;
|
||||
px = window_copy_find_length(wme, py);
|
||||
if ((data->cx >= data->lastsx && data->cx != px) ||
|
||||
@@ -4492,10 +4502,12 @@ window_copy_cursor_down(struct window_mode_entry *wme, int scroll_only)
|
||||
struct window_copy_mode_data *data = wme->data;
|
||||
struct screen *s = &data->screen;
|
||||
u_int ox, oy, px, py;
|
||||
int norectsel;
|
||||
|
||||
norectsel = data->screen.sel == NULL || !data->rectflag;
|
||||
oy = screen_hsize(data->backing) + data->cy - data->oy;
|
||||
ox = window_copy_find_length(wme, oy);
|
||||
if (data->cx != ox) {
|
||||
if (norectsel && data->cx != ox) {
|
||||
data->lastcx = data->cx;
|
||||
data->lastsx = ox;
|
||||
}
|
||||
@@ -4504,17 +4516,22 @@ window_copy_cursor_down(struct window_mode_entry *wme, int scroll_only)
|
||||
window_copy_other_end(wme);
|
||||
|
||||
if (scroll_only || data->cy == screen_size_y(s) - 1) {
|
||||
data->cx = data->lastcx;
|
||||
if (norectsel)
|
||||
data->cx = data->lastcx;
|
||||
window_copy_scroll_up(wme, 1);
|
||||
if (scroll_only && data->cy > 0)
|
||||
window_copy_redraw_lines(wme, data->cy - 1, 2);
|
||||
} else {
|
||||
window_copy_update_cursor(wme, data->lastcx, data->cy + 1);
|
||||
if (norectsel) {
|
||||
window_copy_update_cursor(wme, data->lastcx,
|
||||
data->cy + 1);
|
||||
} else
|
||||
window_copy_update_cursor(wme, data->cx, data->cy + 1);
|
||||
if (window_copy_update_selection(wme, 1, 0))
|
||||
window_copy_redraw_lines(wme, data->cy - 1, 2);
|
||||
}
|
||||
|
||||
if (data->screen.sel == NULL || !data->rectflag) {
|
||||
if (norectsel) {
|
||||
py = screen_hsize(data->backing) + data->cy - data->oy;
|
||||
px = window_copy_find_length(wme, py);
|
||||
if ((data->cx >= data->lastsx && data->cx != px) ||
|
||||
|
||||
53
window.c
53
window.c
@@ -329,6 +329,8 @@ window_create(u_int sx, u_int sy, u_int xpixel, u_int ypixel)
|
||||
|
||||
window_update_activity(w);
|
||||
|
||||
log_debug("%s: @%u create %ux%u (%ux%u)", __func__, w->id, sx, sy,
|
||||
w->xpixel, w->ypixel);
|
||||
return (w);
|
||||
}
|
||||
|
||||
@@ -423,25 +425,18 @@ window_resize(struct window *w, u_int sx, u_int sy, int xpixel, int ypixel)
|
||||
}
|
||||
|
||||
void
|
||||
window_pane_send_resize(struct window_pane *wp, int force)
|
||||
window_pane_send_resize(struct window_pane *wp, u_int sx, u_int sy)
|
||||
{
|
||||
struct window *w = wp->window;
|
||||
struct winsize ws;
|
||||
u_int sy;
|
||||
|
||||
if (wp->fd == -1)
|
||||
return;
|
||||
|
||||
if (!force)
|
||||
sy = wp->sy;
|
||||
else if (wp->sy <= 1)
|
||||
sy = wp->sy + 1;
|
||||
else
|
||||
sy = wp->sy - 1;
|
||||
log_debug("%s: %%%u resize to %u,%u", __func__, wp->id, wp->sx, sy);
|
||||
log_debug("%s: %%%u resize to %u,%u", __func__, wp->id, sx, sy);
|
||||
|
||||
memset(&ws, 0, sizeof ws);
|
||||
ws.ws_col = wp->sx;
|
||||
ws.ws_col = sx;
|
||||
ws.ws_row = sy;
|
||||
ws.ws_xpixel = w->xpixel * ws.ws_col;
|
||||
ws.ws_ypixel = w->ypixel * ws.ws_row;
|
||||
@@ -865,29 +860,19 @@ window_pane_create(struct window *w, u_int sx, u_int sy, u_int hlimit)
|
||||
wp->id = next_window_pane_id++;
|
||||
RB_INSERT(window_pane_tree, &all_window_panes, wp);
|
||||
|
||||
wp->argc = 0;
|
||||
wp->argv = NULL;
|
||||
wp->shell = NULL;
|
||||
wp->cwd = NULL;
|
||||
|
||||
wp->fd = -1;
|
||||
wp->event = NULL;
|
||||
|
||||
wp->fg = 8;
|
||||
wp->bg = 8;
|
||||
|
||||
TAILQ_INIT(&wp->modes);
|
||||
|
||||
wp->layout_cell = NULL;
|
||||
|
||||
wp->xoff = 0;
|
||||
wp->yoff = 0;
|
||||
TAILQ_INIT (&wp->resize_queue);
|
||||
|
||||
wp->sx = sx;
|
||||
wp->sy = sy;
|
||||
|
||||
wp->pipe_fd = -1;
|
||||
wp->pipe_event = NULL;
|
||||
|
||||
screen_init(&wp->base, sx, sy, hlimit);
|
||||
wp->screen = &wp->base;
|
||||
@@ -903,6 +888,9 @@ window_pane_create(struct window *w, u_int sx, u_int sy, u_int hlimit)
|
||||
static void
|
||||
window_pane_destroy(struct window_pane *wp)
|
||||
{
|
||||
struct window_pane_resize *r;
|
||||
struct window_pane_resize *r1;
|
||||
|
||||
window_pane_reset_mode_all(wp);
|
||||
free(wp->searchstr);
|
||||
|
||||
@@ -927,8 +915,10 @@ window_pane_destroy(struct window_pane *wp)
|
||||
|
||||
if (event_initialized(&wp->resize_timer))
|
||||
event_del(&wp->resize_timer);
|
||||
if (event_initialized(&wp->force_timer))
|
||||
event_del(&wp->force_timer);
|
||||
TAILQ_FOREACH_SAFE(r, &wp->resize_queue, entry, r1) {
|
||||
TAILQ_REMOVE(&wp->resize_queue, r, entry);
|
||||
free(r);
|
||||
}
|
||||
|
||||
RB_REMOVE(window_pane_tree, &all_window_panes, wp);
|
||||
|
||||
@@ -997,9 +987,18 @@ void
|
||||
window_pane_resize(struct window_pane *wp, u_int sx, u_int sy)
|
||||
{
|
||||
struct window_mode_entry *wme;
|
||||
struct window_pane_resize *r;
|
||||
|
||||
if (sx == wp->sx && sy == wp->sy)
|
||||
return;
|
||||
|
||||
r = xmalloc (sizeof *r);
|
||||
r->sx = sx;
|
||||
r->sy = sy;
|
||||
r->osx = wp->sx;
|
||||
r->osy = wp->sy;
|
||||
TAILQ_INSERT_TAIL (&wp->resize_queue, r, entry);
|
||||
|
||||
wp->sx = sx;
|
||||
wp->sy = sy;
|
||||
|
||||
@@ -1009,14 +1008,6 @@ window_pane_resize(struct window_pane *wp, u_int sx, u_int sy)
|
||||
wme = TAILQ_FIRST(&wp->modes);
|
||||
if (wme != NULL && wme->mode->resize != NULL)
|
||||
wme->mode->resize(wme, sx, sy);
|
||||
|
||||
/*
|
||||
* If the pane has already been resized, set the force flag and make
|
||||
* the application resize twice to force it to redraw.
|
||||
*/
|
||||
if (wp->flags & PANE_RESIZE)
|
||||
wp->flags |= PANE_RESIZEFORCE;
|
||||
wp->flags |= PANE_RESIZE;
|
||||
}
|
||||
|
||||
void
|
||||
|
||||
Reference in New Issue
Block a user