mirror of
https://github.com/tmux/tmux.git
synced 2026-03-14 12:47:24 +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
|
CHANGES FROM 3.1c TO 3.2
|
||||||
|
|
||||||
* Add a flag to disable keys to close a message.
|
* 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
|
* 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.
|
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).
|
N/s).
|
||||||
|
|
||||||
* Add compat clock_gettime for older macOS.
|
* Add compat clock_gettime for older macOS.
|
||||||
@@ -61,7 +74,7 @@ CHANGES FROM 3.1c TO 3.2
|
|||||||
an option on all panes.
|
an option on all panes.
|
||||||
|
|
||||||
* Make replacement of ##s consistent when drawing formats, whether followed by
|
* 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.
|
* 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
|
* 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
|
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
|
attached and then immediately detached and tmux will not be around to receive
|
||||||
them.
|
them.
|
||||||
|
|
||||||
@@ -280,7 +293,7 @@ CHANGES FROM 3.1c TO 3.2
|
|||||||
window-renamed
|
window-renamed
|
||||||
window-unlinked
|
window-unlinked
|
||||||
|
|
||||||
And these now pane options:
|
And these are now pane options:
|
||||||
|
|
||||||
pane-died
|
pane-died
|
||||||
pane-exited
|
pane-exited
|
||||||
@@ -355,7 +368,7 @@ CHANGES FROM 3.1c TO 3.2
|
|||||||
* Add a default binding for button 2 to paste.
|
* 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
|
* 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
|
* Add C-g to cancel command prompt with vi keys as well as emacs, and q in
|
||||||
command mode.
|
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)
|
if (xp == NULL || strcmp(xp, "C") == 0)
|
||||||
xp = "#{popup_centre_x}";
|
xp = "#{popup_centre_x}";
|
||||||
else if (strcmp(xp, "R") == 0)
|
else if (strcmp(xp, "R") == 0)
|
||||||
xp = "#{popup_right}";
|
xp = "#{popup_pane_right}";
|
||||||
else if (strcmp(xp, "P") == 0)
|
else if (strcmp(xp, "P") == 0)
|
||||||
xp = "#{popup_pane_left}";
|
xp = "#{popup_pane_left}";
|
||||||
else if (strcmp(xp, "M") == 0)
|
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]);
|
cmdq_error(item, "invalid key: %s", args->argv[0]);
|
||||||
return (CMD_RETURN_ERROR);
|
return (CMD_RETURN_ERROR);
|
||||||
}
|
}
|
||||||
only &= KEYC_MASK_KEY;
|
only &= (KEYC_MASK_KEY|KEYC_MASK_MODIFIERS);
|
||||||
}
|
}
|
||||||
|
|
||||||
tablename = args_get(args, 'T');
|
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);
|
memset(&sc, 0, sizeof sc);
|
||||||
sc.item = item;
|
sc.item = item;
|
||||||
sc.s = s;
|
sc.s = s;
|
||||||
|
sc.tc = c;
|
||||||
|
|
||||||
sc.name = args_get(args, 'n');
|
sc.name = args_get(args, 'n');
|
||||||
sc.argc = args->argc;
|
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;
|
struct cmdq_item *new_item;
|
||||||
|
|
||||||
if (cfg_finished) {
|
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;
|
c->retval = 1;
|
||||||
new_item = cmdq_get_callback(cmd_source_file_complete_cb, NULL);
|
new_item = cmdq_get_callback(cmd_source_file_complete_cb, NULL);
|
||||||
cmdq_insert_after(cdata->after, new_item);
|
cmdq_insert_after(cdata->after, new_item);
|
||||||
|
|||||||
21
configure.ac
21
configure.ac
@@ -1,6 +1,6 @@
|
|||||||
# configure.ac
|
# configure.ac
|
||||||
|
|
||||||
AC_INIT([tmux], 3.2)
|
AC_INIT([tmux], 3.2a)
|
||||||
AC_PREREQ([2.60])
|
AC_PREREQ([2.60])
|
||||||
|
|
||||||
AC_CONFIG_AUX_DIR(etc)
|
AC_CONFIG_AUX_DIR(etc)
|
||||||
@@ -34,10 +34,10 @@ AC_ARG_VAR(
|
|||||||
# Set up convenient fuzzing defaults before initializing compiler.
|
# Set up convenient fuzzing defaults before initializing compiler.
|
||||||
if test "x$enable_fuzzing" = xyes; then
|
if test "x$enable_fuzzing" = xyes; then
|
||||||
AC_DEFINE(NEED_FUZZING)
|
AC_DEFINE(NEED_FUZZING)
|
||||||
test "x$CC" == x && CC=clang
|
test "x$CC" = x && CC=clang
|
||||||
test "x$FUZZING_LIBS" == x && \
|
test "x$FUZZING_LIBS" = x && \
|
||||||
FUZZING_LIBS="-fsanitize=fuzzer"
|
FUZZING_LIBS="-fsanitize=fuzzer"
|
||||||
test "x$SAVED_CFLAGS" == x && \
|
test "x$SAVED_CFLAGS" = x && \
|
||||||
AM_CFLAGS="-g -fsanitize=fuzzer-no-link,address"
|
AM_CFLAGS="-g -fsanitize=fuzzer-no-link,address"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
@@ -150,10 +150,19 @@ AC_REPLACE_FUNCS([ \
|
|||||||
strlcpy \
|
strlcpy \
|
||||||
strndup \
|
strndup \
|
||||||
strsep \
|
strsep \
|
||||||
strtonum \
|
|
||||||
])
|
])
|
||||||
AC_FUNC_STRNLEN
|
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
|
# 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
|
# system. When compiled it always returns NULL and crashes the program. To
|
||||||
# detect this we need a more complicated test.
|
# detect this we need a more complicated test.
|
||||||
@@ -163,6 +172,7 @@ AC_RUN_IFELSE([AC_LANG_PROGRAM(
|
|||||||
[return (reallocarray(NULL, 1, 1) == NULL);]
|
[return (reallocarray(NULL, 1, 1) == NULL);]
|
||||||
)],
|
)],
|
||||||
AC_MSG_RESULT(yes),
|
AC_MSG_RESULT(yes),
|
||||||
|
[AC_LIBOBJ(reallocarray) AC_MSG_RESULT([no])],
|
||||||
[AC_LIBOBJ(reallocarray) AC_MSG_RESULT([no])]
|
[AC_LIBOBJ(reallocarray) AC_MSG_RESULT([no])]
|
||||||
)
|
)
|
||||||
AC_MSG_CHECKING([for working recallocarray])
|
AC_MSG_CHECKING([for working recallocarray])
|
||||||
@@ -171,6 +181,7 @@ AC_RUN_IFELSE([AC_LANG_PROGRAM(
|
|||||||
[return (recallocarray(NULL, 1, 1, 1) == NULL);]
|
[return (recallocarray(NULL, 1, 1, 1) == NULL);]
|
||||||
)],
|
)],
|
||||||
AC_MSG_RESULT(yes),
|
AC_MSG_RESULT(yes),
|
||||||
|
[AC_LIBOBJ(recallocarray) AC_MSG_RESULT([no])],
|
||||||
[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);
|
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);
|
bufferevent_free(cf->event);
|
||||||
cf->event = NULL;
|
cf->event = NULL;
|
||||||
|
|
||||||
close(cf->fd);
|
close(cf->fd);
|
||||||
cf->fd = -1;
|
cf->fd = -1;
|
||||||
|
|
||||||
|
if (cf->cb != NULL)
|
||||||
|
cf->cb(NULL, NULL, 0, -1, NULL, cf->data);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Client file write callback. */
|
/* 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
|
#define FORMAT_CHARACTER 0x10000
|
||||||
|
|
||||||
/* Limit on recursion. */
|
/* Limit on recursion. */
|
||||||
#define FORMAT_LOOP_LIMIT 10
|
#define FORMAT_LOOP_LIMIT 100
|
||||||
|
|
||||||
/* Format expand flags. */
|
/* Format expand flags. */
|
||||||
#define FORMAT_EXPAND_TIME 0x1
|
#define FORMAT_EXPAND_TIME 0x1
|
||||||
@@ -3991,7 +3991,7 @@ format_replace_expression(struct format_modifier *mexp,
|
|||||||
result = (mleft < mright);
|
result = (mleft < mright);
|
||||||
break;
|
break;
|
||||||
case LESS_THAN_EQUAL:
|
case LESS_THAN_EQUAL:
|
||||||
result = (mleft > mright);
|
result = (mleft <= mright);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (use_fp)
|
if (use_fp)
|
||||||
@@ -4199,7 +4199,7 @@ format_replace(struct format_expand_state *es, const char *key, size_t keylen,
|
|||||||
value = xstrdup("0");
|
value = xstrdup("0");
|
||||||
} else {
|
} else {
|
||||||
format_log(es, "search '%s' pane %%%u", new, wp->id);
|
format_log(es, "search '%s' pane %%%u", new, wp->id);
|
||||||
value = format_search(fm, wp, new);
|
value = format_search(search, wp, new);
|
||||||
}
|
}
|
||||||
free(new);
|
free(new);
|
||||||
} else if (cmp != NULL) {
|
} else if (cmp != NULL) {
|
||||||
@@ -4441,8 +4441,10 @@ format_expand1(struct format_expand_state *es, const char *fmt)
|
|||||||
if (fmt == NULL || *fmt == '\0')
|
if (fmt == NULL || *fmt == '\0')
|
||||||
return (xstrdup(""));
|
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(""));
|
return (xstrdup(""));
|
||||||
|
}
|
||||||
es->loop++;
|
es->loop++;
|
||||||
|
|
||||||
format_log(es, "expanding format: %s", fmt);
|
format_log(es, "expanding format: %s", fmt);
|
||||||
|
|||||||
@@ -371,19 +371,26 @@ void
|
|||||||
grid_reader_cursor_back_to_indentation(struct grid_reader *gr)
|
grid_reader_cursor_back_to_indentation(struct grid_reader *gr)
|
||||||
{
|
{
|
||||||
struct grid_cell gc;
|
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;
|
yy = gr->gd->hsize + gr->gd->sy - 1;
|
||||||
|
oldx = gr->cx;
|
||||||
|
oldy = gr->cy;
|
||||||
grid_reader_cursor_start_of_line(gr, 1);
|
grid_reader_cursor_start_of_line(gr, 1);
|
||||||
|
|
||||||
for (py = gr->cy; py <= yy; py++) {
|
for (py = gr->cy; py <= yy; py++) {
|
||||||
xx = grid_line_length(gr->gd, py);
|
xx = grid_line_length(gr->gd, py);
|
||||||
for (px = 0; px < xx; px++) {
|
for (px = 0; px < xx; px++) {
|
||||||
grid_get_cell(gr->gd, px, py, &gc);
|
grid_get_cell(gr->gd, px, py, &gc);
|
||||||
if (gc.data.size != 1 || *gc.data.data != ' ')
|
if (gc.data.size != 1 || *gc.data.data != ' ') {
|
||||||
break;
|
gr->cx = px;
|
||||||
|
gr->cy = py;
|
||||||
|
return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (~grid_get_line(gr->gd, py)->flags & GRID_LINE_WRAPPED)
|
if (~grid_get_line(gr->gd, py)->flags & GRID_LINE_WRAPPED)
|
||||||
break;
|
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,
|
{ .key = KEYC_F12,
|
||||||
.data = "\033[24~"
|
.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,
|
{ .key = KEYC_IC,
|
||||||
.data = "\033[2~"
|
.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);
|
input_key_write(__func__, bev, &ud.data[0], 1);
|
||||||
return (0);
|
return (0);
|
||||||
}
|
}
|
||||||
if (justkey > 0x7f && justkey < KEYC_BASE) {
|
if (KEYC_IS_UNICODE(justkey)) {
|
||||||
if (key & KEYC_META)
|
if (key & KEYC_META)
|
||||||
input_key_write(__func__, bev, "\033", 1);
|
input_key_write(__func__, bev, "\033", 1);
|
||||||
utf8_to_data(justkey, &ud);
|
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:
|
case INPUT_CSI_MODSET:
|
||||||
n = input_get(ictx, 0, 0, 0);
|
n = input_get(ictx, 0, 0, 0);
|
||||||
m = input_get(ictx, 1, 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))
|
if (n == 0 || (n == 4 && m == 0))
|
||||||
screen_write_mode_clear(sctx, MODE_KEXTENDED);
|
screen_write_mode_clear(sctx, MODE_KEXTENDED);
|
||||||
else if (n == 4 && (m == 1 || m == 2))
|
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)
|
if (repeat)
|
||||||
bd->flags |= KEY_BINDING_REPEAT;
|
bd->flags |= KEY_BINDING_REPEAT;
|
||||||
bd->cmdlist = cmdlist;
|
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
|
void
|
||||||
@@ -231,6 +234,9 @@ key_bindings_remove(const char *name, key_code key)
|
|||||||
if (bd == NULL)
|
if (bd == NULL)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
log_debug("%s: %#llx %s", __func__, bd->key,
|
||||||
|
key_string_lookup_key(bd->key, 1));
|
||||||
|
|
||||||
RB_REMOVE(key_bindings, &table->key_bindings, bd);
|
RB_REMOVE(key_bindings, &table->key_bindings, bd);
|
||||||
key_bindings_free(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_code
|
||||||
key_string_lookup_string(const char *string)
|
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;
|
key_code key, modifiers;
|
||||||
u_int u, i;
|
u_int u, i;
|
||||||
struct utf8_data ud, *udp;
|
struct utf8_data ud, *udp;
|
||||||
@@ -238,8 +238,12 @@ key_string_lookup_string(const char *string)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Convert the standard control keys. */
|
/* Convert the standard control keys. */
|
||||||
if (key < KEYC_BASE && (modifiers & KEYC_CTRL) &&
|
if (key <= 127 &&
|
||||||
strchr(other, key) == NULL) {
|
(modifiers & KEYC_CTRL) &&
|
||||||
|
strchr(other, key) == NULL &&
|
||||||
|
key != 9 &&
|
||||||
|
key != 13 &&
|
||||||
|
key != 27) {
|
||||||
if (key >= 97 && key <= 122)
|
if (key >= 97 && key <= 122)
|
||||||
key -= 96;
|
key -= 96;
|
||||||
else if (key >= 64 && key <= 95)
|
else if (key >= 64 && key <= 95)
|
||||||
@@ -364,8 +368,8 @@ key_string_lookup_key(key_code key, int with_flags)
|
|||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Is this a UTF-8 key? */
|
/* Is this a Unicode key? */
|
||||||
if (key > 127 && key < KEYC_BASE) {
|
if (KEYC_IS_UNICODE(key)) {
|
||||||
utf8_to_data(key, &ud);
|
utf8_to_data(key, &ud);
|
||||||
off = strlen(out);
|
off = strlen(out);
|
||||||
memcpy(out + off, ud.data, ud.size);
|
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[] = {
|
static const char *options_table_detach_on_destroy_list[] = {
|
||||||
"off", "on", "no-detached", NULL
|
"off", "on", "no-detached", NULL
|
||||||
};
|
};
|
||||||
|
static const char *options_table_extended_keys_list[] = {
|
||||||
|
"off", "on", "always", NULL
|
||||||
|
};
|
||||||
|
|
||||||
/* Status line format. */
|
/* Status line format. */
|
||||||
#define OPTIONS_TABLE_STATUS_FORMAT1 \
|
#define OPTIONS_TABLE_STATUS_FORMAT1 \
|
||||||
@@ -266,8 +269,9 @@ const struct options_table_entry options_table[] = {
|
|||||||
},
|
},
|
||||||
|
|
||||||
{ .name = "extended-keys",
|
{ .name = "extended-keys",
|
||||||
.type = OPTIONS_TABLE_FLAG,
|
.type = OPTIONS_TABLE_CHOICE,
|
||||||
.scope = OPTIONS_TABLE_SERVER,
|
.scope = OPTIONS_TABLE_SERVER,
|
||||||
|
.choices = options_table_extended_keys_list,
|
||||||
.default_num = 0,
|
.default_num = 0,
|
||||||
.text = "Whether to request extended key sequences from terminals "
|
.text = "Whether to request extended key sequences from terminals "
|
||||||
"that support it."
|
"that support it."
|
||||||
|
|||||||
@@ -96,5 +96,17 @@ osdep_get_cwd(int fd)
|
|||||||
struct event_base *
|
struct event_base *
|
||||||
osdep_event_init(void)
|
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
|
static int
|
||||||
clients_calculate_size(int type, int current, struct session *s,
|
clients_calculate_size(int type, int current, struct client *c,
|
||||||
struct window *w, int (*skip_client)(struct client *, int, int,
|
struct session *s, struct window *w, int (*skip_client)(struct client *,
|
||||||
struct session *, struct window *), u_int *sx, u_int *sy, u_int *xpixel,
|
int, int, struct session *, struct window *), u_int *sx, u_int *sy,
|
||||||
u_int *ypixel)
|
u_int *xpixel, u_int *ypixel)
|
||||||
{
|
{
|
||||||
struct client *loop;
|
struct client *loop;
|
||||||
u_int cx, cy, n = 0;
|
u_int cx, cy, n = 0;
|
||||||
|
|
||||||
/* Manual windows do not have their size changed based on a client. */
|
/* 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);
|
return (0);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Start comparing with 0 for largest and UINT_MAX for smallest or
|
* 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
|
* For latest, count the number of clients with this window. We only
|
||||||
* care if there is more than one.
|
* care if there is more than one.
|
||||||
*/
|
*/
|
||||||
if (type == WINDOW_SIZE_LATEST)
|
if (type == WINDOW_SIZE_LATEST && w != NULL)
|
||||||
n = clients_with_window(w);
|
n = clients_with_window(w);
|
||||||
|
|
||||||
/* Loop over the clients and work out the size. */
|
/* Loop over the clients and work out the size. */
|
||||||
TAILQ_FOREACH(loop, &clients, entry) {
|
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;
|
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;
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If there are multiple clients attached, only accept the
|
* If there are multiple clients attached, only accept the
|
||||||
* latest client; otherwise let the only client be chosen as
|
* latest client; otherwise let the only client be chosen as
|
||||||
* for smallest.
|
* 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;
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
/* Work out this client's size. */
|
/* Work out this client's size. */
|
||||||
cx = loop->tty.sx;
|
cx = loop->tty.sx;
|
||||||
@@ -175,16 +183,24 @@ clients_calculate_size(int type, int current, struct session *s,
|
|||||||
*xpixel = loop->tty.xpixel;
|
*xpixel = loop->tty.xpixel;
|
||||||
*ypixel = loop->tty.ypixel;
|
*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. */
|
/* 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);
|
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);
|
return (*sx != UINT_MAX && *sy != UINT_MAX);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
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)
|
__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);
|
*sy = c->tty.sy - status_line_size(c);
|
||||||
*xpixel = c->tty.xpixel;
|
*xpixel = c->tty.xpixel;
|
||||||
*ypixel = c->tty.ypixel;
|
*ypixel = c->tty.ypixel;
|
||||||
|
log_debug("%s: using %ux%u from %s", __func__, *sx, *sy,
|
||||||
|
c->name);
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
if (w == NULL)
|
|
||||||
type = WINDOW_SIZE_MANUAL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Look for a client to base the size on. If none exists (or the type
|
* Look for a client to base the size on. If none exists (or the type
|
||||||
* is manual), use the default-size option.
|
* 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)) {
|
default_window_size_skip_client, sx, sy, xpixel, ypixel)) {
|
||||||
value = options_get_string(s->options, "default-size");
|
value = options_get_string(s->options, "default-size");
|
||||||
if (sscanf(value, "%ux%u", sx, sy) != 2) {
|
if (sscanf(value, "%ux%u", sx, sy) != 2) {
|
||||||
*sx = 80;
|
*sx = 80;
|
||||||
*sy = 24;
|
*sy = 24;
|
||||||
}
|
}
|
||||||
|
log_debug("%s: using %ux%u from default-size", __func__, *sx,
|
||||||
|
*sy);
|
||||||
}
|
}
|
||||||
|
|
||||||
done:
|
done:
|
||||||
@@ -250,6 +268,7 @@ done:
|
|||||||
*sy = WINDOW_MINIMUM;
|
*sy = WINDOW_MINIMUM;
|
||||||
if (*sy > WINDOW_MAXIMUM)
|
if (*sy > WINDOW_MAXIMUM)
|
||||||
*sy = WINDOW_MAXIMUM;
|
*sy = WINDOW_MAXIMUM;
|
||||||
|
log_debug("%s: resulting size is %ux%u", __func__, *sx, *sy);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
@@ -289,7 +308,7 @@ recalculate_size(struct window *w, int now)
|
|||||||
current = options_get_number(w->options, "aggressive-resize");
|
current = options_get_number(w->options, "aggressive-resize");
|
||||||
|
|
||||||
/* Look for a suitable client and get the new size. */
|
/* 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);
|
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->rupper = 0;
|
||||||
s->rlower = screen_size_y(s) - 1;
|
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)
|
if (s->saved_grid != NULL)
|
||||||
screen_alternate_off(s, NULL, 0);
|
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_set_title(struct client *);
|
||||||
static void server_client_reset_state(struct client *);
|
static void server_client_reset_state(struct client *);
|
||||||
static int server_client_assume_paste(struct session *);
|
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(struct imsg *, void *);
|
||||||
static void server_client_dispatch_command(struct client *, struct imsg *);
|
static void server_client_dispatch_command(struct client *, struct imsg *);
|
||||||
@@ -271,6 +272,40 @@ server_client_open(struct client *c, char **cause)
|
|||||||
return (0);
|
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. */
|
/* Lost a client. */
|
||||||
void
|
void
|
||||||
server_client_lost(struct client *c)
|
server_client_lost(struct client *c)
|
||||||
@@ -296,8 +331,10 @@ server_client_lost(struct client *c)
|
|||||||
TAILQ_REMOVE(&clients, c, entry);
|
TAILQ_REMOVE(&clients, c, entry);
|
||||||
log_debug("lost client %p", c);
|
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);
|
notify_client("client-detached", c);
|
||||||
|
}
|
||||||
|
|
||||||
if (c->flags & CLIENT_CONTROL)
|
if (c->flags & CLIENT_CONTROL)
|
||||||
control_stop(c);
|
control_stop(c);
|
||||||
@@ -1410,84 +1447,79 @@ server_client_resize_timer(__unused int fd, __unused short events, void *data)
|
|||||||
evtimer_del(&wp->resize_timer);
|
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. */
|
/* Check if pane should be resized. */
|
||||||
static void
|
static void
|
||||||
server_client_check_pane_resize(struct window_pane *wp)
|
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))
|
if (!event_initialized(&wp->resize_timer))
|
||||||
evtimer_set(&wp->resize_timer, server_client_resize_timer, wp);
|
evtimer_set(&wp->resize_timer, server_client_resize_timer, wp);
|
||||||
if (!event_initialized(&wp->force_timer))
|
if (evtimer_pending(&wp->resize_timer, NULL))
|
||||||
evtimer_set(&wp->force_timer, server_client_force_timer, wp);
|
|
||||||
|
|
||||||
if (~wp->flags & PANE_RESIZE)
|
|
||||||
return;
|
return;
|
||||||
|
|
||||||
log_debug("%s: %%%u needs to be resized", __func__, wp->id);
|
log_debug("%s: %%%u needs to be resized", __func__, wp->id);
|
||||||
|
TAILQ_FOREACH(r, &wp->resize_queue, entry) {
|
||||||
if (evtimer_pending(&wp->resize_timer, NULL)) {
|
log_debug("queued resize: %ux%u -> %ux%u", r->osx, r->osy,
|
||||||
log_debug("%s: %%%u resize timer is running", __func__, wp->id);
|
r->sx, r->sy);
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
server_client_start_resize_timer(wp);
|
|
||||||
|
|
||||||
if (~wp->flags & PANE_RESIZEFORCE) {
|
/*
|
||||||
/*
|
* There are three cases that matter:
|
||||||
* The timer is not running and we don't need to force a
|
*
|
||||||
* resize, so just resize immediately.
|
* - Only one resize. It can just be applied.
|
||||||
*/
|
*
|
||||||
log_debug("%s: resizing %%%u now", __func__, wp->id);
|
* - Multiple resizes and the ending size is different from the
|
||||||
window_pane_send_resize(wp, 0);
|
* starting size. We can discard all resizes except the most recent.
|
||||||
wp->flags &= ~PANE_RESIZE;
|
*
|
||||||
|
* - 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 {
|
} else {
|
||||||
/*
|
/*
|
||||||
* The timer is not running, but we need to force a resize. If
|
* Multiple resizes ending up with the same size. There will
|
||||||
* the force timer has expired, resize to the real size now.
|
* not be more than one to the same size in succession so we
|
||||||
* Otherwise resize to the force size and start the timer.
|
* 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) {
|
r = TAILQ_PREV(last, window_pane_resizes, entry);
|
||||||
log_debug("%s: resizing %%%u after forced resize",
|
window_pane_send_resize(wp, r->sx, r->sy);
|
||||||
__func__, wp->id);
|
TAILQ_FOREACH_SAFE(r, &wp->resize_queue, entry, r1) {
|
||||||
window_pane_send_resize(wp, 0);
|
if (r == last)
|
||||||
wp->flags &= ~(PANE_RESIZE|PANE_RESIZEFORCE|PANE_RESIZENOW);
|
break;
|
||||||
} else if (!evtimer_pending(&wp->force_timer, NULL)) {
|
TAILQ_REMOVE(&wp->resize_queue, r, entry);
|
||||||
log_debug("%s: forcing resize of %%%u", __func__,
|
free(r);
|
||||||
wp->id);
|
|
||||||
window_pane_send_resize(wp, 1);
|
|
||||||
server_client_start_force_timer(wp);
|
|
||||||
}
|
}
|
||||||
|
tv.tv_usec = 10000;
|
||||||
}
|
}
|
||||||
|
evtimer_add(&wp->resize_timer, &tv);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* Check pane buffer size. */
|
/* Check pane buffer size. */
|
||||||
static void
|
static void
|
||||||
server_client_check_pane_buffer(struct window_pane *wp)
|
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);
|
malloc_trim(0);
|
||||||
#endif
|
#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);
|
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))
|
if (c->flags & (CLIENT_STATUSOFF|CLIENT_CONTROL))
|
||||||
return (0);
|
return (0);
|
||||||
|
if (s == NULL)
|
||||||
|
return (options_get_number(global_s_options, "status"));
|
||||||
return (s->statuslines);
|
return (s->statuslines);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1298,7 +1300,7 @@ process_key:
|
|||||||
return (0);
|
return (0);
|
||||||
|
|
||||||
append_key:
|
append_key:
|
||||||
if (key <= 0x1f || key >= KEYC_BASE)
|
if (key <= 0x1f || (key >= KEYC_BASE && key < KEYC_BASE_END))
|
||||||
return (0);
|
return (0);
|
||||||
if (key <= 0x7f)
|
if (key <= 0x7f)
|
||||||
utf8_set(&tmp, key);
|
utf8_set(&tmp, key);
|
||||||
|
|||||||
42
tmux.1
42
tmux.1
@@ -2953,6 +2953,8 @@ Ctrl keys may be prefixed with
|
|||||||
.Ql C-
|
.Ql C-
|
||||||
or
|
or
|
||||||
.Ql ^ ,
|
.Ql ^ ,
|
||||||
|
Shift keys with
|
||||||
|
.Ql S-
|
||||||
and Alt (meta) with
|
and Alt (meta) with
|
||||||
.Ql M- .
|
.Ql M- .
|
||||||
In addition, the following special key names are accepted:
|
In addition, the following special key names are accepted:
|
||||||
@@ -3418,11 +3420,24 @@ sessions.
|
|||||||
.Xc
|
.Xc
|
||||||
If enabled, the server will exit when there are no attached clients.
|
If enabled, the server will exit when there are no attached clients.
|
||||||
.It Xo Ic extended-keys
|
.It Xo Ic extended-keys
|
||||||
.Op Ic on | off
|
.Op Ic on | off | always
|
||||||
.Xc
|
.Xc
|
||||||
When enabled, extended keys are requested from the terminal and if supported
|
When
|
||||||
are recognised by
|
.Ic on
|
||||||
.Nm .
|
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
|
.It Xo Ic focus-events
|
||||||
.Op Ic on | off
|
.Op Ic on | off
|
||||||
.Xc
|
.Xc
|
||||||
@@ -3501,8 +3516,8 @@ capabilities to be set instead,
|
|||||||
is intended for classes of functionality supported in a standard way but not
|
is intended for classes of functionality supported in a standard way but not
|
||||||
reported by
|
reported by
|
||||||
.Xr terminfo 5 .
|
.Xr terminfo 5 .
|
||||||
Care must be taken only to configure this with features the terminal actually
|
Care must be taken to configure this only with features the terminal actually
|
||||||
support.
|
supports.
|
||||||
.Pp
|
.Pp
|
||||||
This is an array option where each entry is a colon-separated string made up
|
This is an array option where each entry is a colon-separated string made up
|
||||||
of a terminal type pattern (matched using
|
of a terminal type pattern (matched using
|
||||||
@@ -3524,6 +3539,10 @@ Supports extended keys.
|
|||||||
Supports focus reporting.
|
Supports focus reporting.
|
||||||
.It margins
|
.It margins
|
||||||
Supports DECSLRM margins.
|
Supports DECSLRM margins.
|
||||||
|
.It mouse
|
||||||
|
Supports
|
||||||
|
.Xr xterm 1
|
||||||
|
mouse sequences.
|
||||||
.It overline
|
.It overline
|
||||||
Supports the overline SGR attribute.
|
Supports the overline SGR attribute.
|
||||||
.It rectfill
|
.It rectfill
|
||||||
@@ -6036,6 +6055,10 @@ Disable and enable focus reporting.
|
|||||||
These are set automatically if the
|
These are set automatically if the
|
||||||
.Em XT
|
.Em XT
|
||||||
capability is present.
|
capability is present.
|
||||||
|
.It Em \&Rect
|
||||||
|
Tell
|
||||||
|
.Nm
|
||||||
|
that the terminal supports rectangle operations.
|
||||||
.It Em \&Smol
|
.It Em \&Smol
|
||||||
Enable the overline attribute.
|
Enable the overline attribute.
|
||||||
.It Em \&Smulx
|
.It Em \&Smulx
|
||||||
@@ -6116,12 +6139,13 @@ and matching
|
|||||||
.Em %end
|
.Em %end
|
||||||
or
|
or
|
||||||
.Em %error
|
.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:
|
For example:
|
||||||
.Bd -literal -offset indent
|
.Bd -literal -offset indent
|
||||||
%begin 1363006971 2
|
%begin 1363006971 2 1
|
||||||
0: ksh* (1 panes) [80x24] [layout b25f,80x24,0,0,2] @2 (active)
|
0: ksh* (1 panes) [80x24] [layout b25f,80x24,0,0,2] @2 (active)
|
||||||
%end 1363006971 2
|
%end 1363006971 2 1
|
||||||
.Ed
|
.Ed
|
||||||
.Pp
|
.Pp
|
||||||
The
|
The
|
||||||
|
|||||||
15
tmux.c
15
tmux.c
@@ -328,7 +328,7 @@ main(int argc, char **argv)
|
|||||||
char *path = NULL, *label = NULL;
|
char *path = NULL, *label = NULL;
|
||||||
char *cause, **var;
|
char *cause, **var;
|
||||||
const char *s, *cwd;
|
const char *s, *cwd;
|
||||||
int opt, keys, feat = 0;
|
int opt, keys, feat = 0, fflag = 0;
|
||||||
uint64_t flags = 0;
|
uint64_t flags = 0;
|
||||||
const struct options_table_entry *oe;
|
const struct options_table_entry *oe;
|
||||||
u_int i;
|
u_int i;
|
||||||
@@ -373,10 +373,15 @@ main(int argc, char **argv)
|
|||||||
flags |= CLIENT_CONTROL;
|
flags |= CLIENT_CONTROL;
|
||||||
break;
|
break;
|
||||||
case 'f':
|
case 'f':
|
||||||
for (i = 0; i < cfg_nfiles; i++)
|
if (!fflag) {
|
||||||
free(cfg_files[i]);
|
fflag = 1;
|
||||||
free(cfg_files);
|
for (i = 0; i < cfg_nfiles; i++)
|
||||||
expand_paths(optarg, &cfg_files, &cfg_nfiles, 0);
|
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;
|
cfg_quiet = 0;
|
||||||
break;
|
break;
|
||||||
case 'V':
|
case 'V':
|
||||||
|
|||||||
59
tmux.h
59
tmux.h
@@ -109,11 +109,16 @@ struct winlink;
|
|||||||
#define VISUAL_ON 1
|
#define VISUAL_ON 1
|
||||||
#define VISUAL_BOTH 2
|
#define VISUAL_BOTH 2
|
||||||
|
|
||||||
/* Special key codes. */
|
/* No key or unknown key. */
|
||||||
#define KEYC_NONE 0x00ff000000000ULL
|
#define KEYC_NONE 0x000ff000000000ULL
|
||||||
#define KEYC_UNKNOWN 0x00fe000000000ULL
|
#define KEYC_UNKNOWN 0x000fe000000000ULL
|
||||||
#define KEYC_BASE 0x0001000000000ULL
|
|
||||||
#define KEYC_USER 0x0002000000000ULL
|
/*
|
||||||
|
* 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. */
|
/* Key modifier bits. */
|
||||||
#define KEYC_META 0x00100000000000ULL
|
#define KEYC_META 0x00100000000000ULL
|
||||||
@@ -136,8 +141,15 @@ struct winlink;
|
|||||||
#define KEYC_NUSER 1000
|
#define KEYC_NUSER 1000
|
||||||
|
|
||||||
/* Is this a mouse key? */
|
/* Is this a mouse key? */
|
||||||
#define KEYC_IS_MOUSE(key) (((key) & KEYC_MASK_KEY) >= KEYC_MOUSE && \
|
#define KEYC_IS_MOUSE(key) \
|
||||||
((key) & KEYC_MASK_KEY) < KEYC_BSPACE)
|
(((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. */
|
/* Multiple click timeout. */
|
||||||
#define KEYC_CLICK_TIMEOUT 300
|
#define KEYC_CLICK_TIMEOUT 300
|
||||||
@@ -159,8 +171,8 @@ struct winlink;
|
|||||||
{ #s "Border", KEYC_ ## name ## _BORDER }
|
{ #s "Border", KEYC_ ## name ## _BORDER }
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* A single key. This can be ASCII or Unicode or one of the keys starting at
|
* A single key. This can be ASCII or Unicode or one of the keys between
|
||||||
* KEYC_BASE.
|
* KEYC_BASE and KEYC_BASE_END.
|
||||||
*/
|
*/
|
||||||
typedef unsigned long long key_code;
|
typedef unsigned long long key_code;
|
||||||
|
|
||||||
@@ -253,6 +265,9 @@ enum {
|
|||||||
KEYC_KP_ENTER,
|
KEYC_KP_ENTER,
|
||||||
KEYC_KP_ZERO,
|
KEYC_KP_ZERO,
|
||||||
KEYC_KP_PERIOD,
|
KEYC_KP_PERIOD,
|
||||||
|
|
||||||
|
/* End of special keys. */
|
||||||
|
KEYC_BASE_END
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Termcap codes. */
|
/* Termcap codes. */
|
||||||
@@ -452,6 +467,7 @@ enum tty_code_code {
|
|||||||
TTYC_MS,
|
TTYC_MS,
|
||||||
TTYC_OL,
|
TTYC_OL,
|
||||||
TTYC_OP,
|
TTYC_OP,
|
||||||
|
TTYC_RECT,
|
||||||
TTYC_REV,
|
TTYC_REV,
|
||||||
TTYC_RGB,
|
TTYC_RGB,
|
||||||
TTYC_RI,
|
TTYC_RI,
|
||||||
@@ -918,7 +934,7 @@ struct window_mode_entry {
|
|||||||
struct screen *screen;
|
struct screen *screen;
|
||||||
u_int prefix;
|
u_int prefix;
|
||||||
|
|
||||||
TAILQ_ENTRY (window_mode_entry) entry;
|
TAILQ_ENTRY(window_mode_entry) entry;
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Offsets into pane buffer. */
|
/* Offsets into pane buffer. */
|
||||||
@@ -926,6 +942,18 @@ struct window_pane_offset {
|
|||||||
size_t used;
|
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. */
|
/* Child window structure. */
|
||||||
struct window_pane {
|
struct window_pane {
|
||||||
u_int id;
|
u_int id;
|
||||||
@@ -950,8 +978,8 @@ struct window_pane {
|
|||||||
#define PANE_REDRAW 0x1
|
#define PANE_REDRAW 0x1
|
||||||
#define PANE_DROP 0x2
|
#define PANE_DROP 0x2
|
||||||
#define PANE_FOCUSED 0x4
|
#define PANE_FOCUSED 0x4
|
||||||
#define PANE_RESIZE 0x8
|
/* 0x8 unused */
|
||||||
#define PANE_RESIZEFORCE 0x10
|
/* 0x10 unused */
|
||||||
#define PANE_FOCUSPUSH 0x20
|
#define PANE_FOCUSPUSH 0x20
|
||||||
#define PANE_INPUTOFF 0x40
|
#define PANE_INPUTOFF 0x40
|
||||||
#define PANE_CHANGED 0x80
|
#define PANE_CHANGED 0x80
|
||||||
@@ -960,7 +988,6 @@ struct window_pane {
|
|||||||
#define PANE_STATUSDRAWN 0x400
|
#define PANE_STATUSDRAWN 0x400
|
||||||
#define PANE_EMPTY 0x800
|
#define PANE_EMPTY 0x800
|
||||||
#define PANE_STYLECHANGED 0x1000
|
#define PANE_STYLECHANGED 0x1000
|
||||||
#define PANE_RESIZENOW 0x2000
|
|
||||||
|
|
||||||
int argc;
|
int argc;
|
||||||
char **argv;
|
char **argv;
|
||||||
@@ -977,8 +1004,8 @@ struct window_pane {
|
|||||||
struct window_pane_offset offset;
|
struct window_pane_offset offset;
|
||||||
size_t base_offset;
|
size_t base_offset;
|
||||||
|
|
||||||
|
struct window_pane_resizes resize_queue;
|
||||||
struct event resize_timer;
|
struct event resize_timer;
|
||||||
struct event force_timer;
|
|
||||||
|
|
||||||
struct input_ctx *ictx;
|
struct input_ctx *ictx;
|
||||||
|
|
||||||
@@ -996,7 +1023,7 @@ struct window_pane {
|
|||||||
struct screen status_screen;
|
struct screen status_screen;
|
||||||
size_t status_size;
|
size_t status_size;
|
||||||
|
|
||||||
TAILQ_HEAD (, window_mode_entry) modes;
|
TAILQ_HEAD(, window_mode_entry) modes;
|
||||||
|
|
||||||
char *searchstr;
|
char *searchstr;
|
||||||
int searchregex;
|
int searchregex;
|
||||||
@@ -2755,7 +2782,7 @@ void window_redraw_active_switch(struct window *,
|
|||||||
struct window_pane *window_add_pane(struct window *, struct window_pane *,
|
struct window_pane *window_add_pane(struct window *, struct window_pane *,
|
||||||
u_int, int);
|
u_int, int);
|
||||||
void window_resize(struct window *, u_int, u_int, 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_zoom(struct window_pane *);
|
||||||
int window_unzoom(struct window *);
|
int window_unzoom(struct window *);
|
||||||
int window_push_zoom(struct window *, int, int);
|
int window_push_zoom(struct window *, int, int);
|
||||||
|
|||||||
@@ -25,7 +25,6 @@
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
* Still hardcoded:
|
* Still hardcoded:
|
||||||
* - mouse (under kmous capability);
|
|
||||||
* - default colours (under AX or op capabilities);
|
* - default colours (under AX or op capabilities);
|
||||||
* - AIX colours (under colors >= 16);
|
* - AIX colours (under colors >= 16);
|
||||||
* - alternate escape (if terminal is VT100-like).
|
* - alternate escape (if terminal is VT100-like).
|
||||||
@@ -54,6 +53,17 @@ static const struct tty_feature tty_feature_title = {
|
|||||||
0
|
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. */
|
/* Terminal can set the clipboard with OSC 52. */
|
||||||
static const char *tty_feature_clipboard_capabilities[] = {
|
static const char *tty_feature_clipboard_capabilities[] = {
|
||||||
"Ms=\\E]52;%p1%s;%p2%s\\a",
|
"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. */
|
/* Terminal supports DECFRA rectangle fill. */
|
||||||
|
static const char *tty_feature_rectfill_capabilities[] = {
|
||||||
|
"Rect",
|
||||||
|
NULL
|
||||||
|
};
|
||||||
static const struct tty_feature tty_feature_rectfill = {
|
static const struct tty_feature tty_feature_rectfill = {
|
||||||
"rectfill",
|
"rectfill",
|
||||||
NULL,
|
tty_feature_rectfill_capabilities,
|
||||||
TERM_DECFRA
|
TERM_DECFRA
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -234,6 +248,7 @@ static const struct tty_feature *tty_features[] = {
|
|||||||
&tty_feature_extkeys,
|
&tty_feature_extkeys,
|
||||||
&tty_feature_focus,
|
&tty_feature_focus,
|
||||||
&tty_feature_margins,
|
&tty_feature_margins,
|
||||||
|
&tty_feature_mouse,
|
||||||
&tty_feature_overline,
|
&tty_feature_overline,
|
||||||
&tty_feature_rectfill,
|
&tty_feature_rectfill,
|
||||||
&tty_feature_rgb,
|
&tty_feature_rgb,
|
||||||
@@ -334,7 +349,7 @@ tty_default_features(int *feat, const char *name, u_int version)
|
|||||||
const char *features;
|
const char *features;
|
||||||
} table[] = {
|
} table[] = {
|
||||||
#define TTY_FEATURES_BASE_MODERN_XTERM \
|
#define TTY_FEATURES_BASE_MODERN_XTERM \
|
||||||
"256,RGB,bpaste,clipboard,strikethrough,title"
|
"256,RGB,bpaste,clipboard,mouse,strikethrough,title"
|
||||||
{ .name = "mintty",
|
{ .name = "mintty",
|
||||||
.features = TTY_FEATURES_BASE_MODERN_XTERM
|
.features = TTY_FEATURES_BASE_MODERN_XTERM
|
||||||
",ccolour,cstyle,extkeys,margins,overline,usstyle"
|
",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"
|
",ccolour,cstyle,focus,overline,usstyle"
|
||||||
},
|
},
|
||||||
{ .name = "rxvt-unicode",
|
{ .name = "rxvt-unicode",
|
||||||
.features = "256,bpaste,ccolour,cstyle,title"
|
.features = "256,bpaste,ccolour,cstyle,mouse,title"
|
||||||
},
|
},
|
||||||
{ .name = "iTerm2",
|
{ .name = "iTerm2",
|
||||||
.features = TTY_FEATURES_BASE_MODERN_XTERM
|
.features = TTY_FEATURES_BASE_MODERN_XTERM
|
||||||
",cstyle,extkeys,margins,sync"
|
",cstyle,extkeys,margins,sync"
|
||||||
},
|
},
|
||||||
{ .name = "XTerm",
|
{ .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
|
.features = TTY_FEATURES_BASE_MODERN_XTERM
|
||||||
",ccolour,cstyle,extkeys,focus,margins,rectfill"
|
",ccolour,cstyle,extkeys,focus"
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
u_int i;
|
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_CTRL,
|
||||||
KEYC_SHIFT|KEYC_CTRL,
|
KEYC_SHIFT|KEYC_CTRL,
|
||||||
KEYC_META|KEYC_IMPLIED_META|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:
|
case 8:
|
||||||
nkey |= (KEYC_SHIFT|KEYC_META|KEYC_IMPLIED_META|KEYC_CTRL);
|
nkey |= (KEYC_SHIFT|KEYC_META|KEYC_IMPLIED_META|KEYC_CTRL);
|
||||||
break;
|
break;
|
||||||
|
case 9:
|
||||||
|
nkey |= (KEYC_META|KEYC_IMPLIED_META);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
*key = KEYC_NONE;
|
*key = KEYC_NONE;
|
||||||
break;
|
break;
|
||||||
@@ -955,23 +959,22 @@ tty_keys_extended_key(struct tty *tty, const char *buf, size_t len,
|
|||||||
*/
|
*/
|
||||||
if (nkey & KEYC_CTRL) {
|
if (nkey & KEYC_CTRL) {
|
||||||
onlykey = (nkey & KEYC_MASK_KEY);
|
onlykey = (nkey & KEYC_MASK_KEY);
|
||||||
if (onlykey < 32) {
|
if (onlykey < 32 &&
|
||||||
if (onlykey != 9)
|
onlykey != 9 &&
|
||||||
onlykey = (nkey & ~KEYC_CTRL);
|
onlykey != 13 &&
|
||||||
else
|
onlykey != 27)
|
||||||
onlykey = (9|KEYC_CTRL);
|
/* nothing */;
|
||||||
} else {
|
else if (onlykey >= 97 && onlykey <= 122)
|
||||||
if (onlykey >= 97 && onlykey <= 122)
|
onlykey -= 96;
|
||||||
onlykey -= 96;
|
else if (onlykey >= 64 && onlykey <= 95)
|
||||||
else if (onlykey >= 64 && onlykey <= 95)
|
onlykey -= 64;
|
||||||
onlykey -= 64;
|
else if (onlykey == 32)
|
||||||
else if (onlykey == 32)
|
onlykey = 0;
|
||||||
onlykey = 0;
|
else if (onlykey == 63)
|
||||||
else if (onlykey == 63)
|
onlykey = 127;
|
||||||
onlykey = 127;
|
else
|
||||||
onlykey |= ((nkey & KEYC_MASK_MODIFIERS) & ~KEYC_CTRL);
|
onlykey |= KEYC_CTRL;
|
||||||
}
|
nkey = onlykey|((nkey & KEYC_MASK_MODIFIERS) & ~KEYC_CTRL);
|
||||||
nkey = onlykey;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (log_get_level() != 0) {
|
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_MS] = { TTYCODE_STRING, "Ms" },
|
||||||
[TTYC_OL] = { TTYCODE_STRING, "ol" },
|
[TTYC_OL] = { TTYCODE_STRING, "ol" },
|
||||||
[TTYC_OP] = { TTYCODE_STRING, "op" },
|
[TTYC_OP] = { TTYCODE_STRING, "op" },
|
||||||
|
[TTYC_RECT] = { TTYCODE_STRING, "Rect" },
|
||||||
[TTYC_REV] = { TTYCODE_STRING, "rev" },
|
[TTYC_REV] = { TTYCODE_STRING, "rev" },
|
||||||
[TTYC_RGB] = { TTYCODE_FLAG, "RGB" },
|
[TTYC_RGB] = { TTYCODE_FLAG, "RGB" },
|
||||||
[TTYC_RIN] = { TTYCODE_STRING, "rin" },
|
[TTYC_RIN] = { TTYCODE_STRING, "rin" },
|
||||||
@@ -434,10 +435,11 @@ tty_term_apply_overrides(struct tty_term *term)
|
|||||||
struct options_entry *o;
|
struct options_entry *o;
|
||||||
struct options_array_item *a;
|
struct options_array_item *a;
|
||||||
union options_value *ov;
|
union options_value *ov;
|
||||||
const char *s;
|
const char *s, *acs;
|
||||||
size_t offset;
|
size_t offset;
|
||||||
char *first;
|
char *first;
|
||||||
|
|
||||||
|
/* Update capabilities from the option. */
|
||||||
o = options_get_only(global_options, "terminal-overrides");
|
o = options_get_only(global_options, "terminal-overrides");
|
||||||
a = options_array_first(o);
|
a = options_array_first(o);
|
||||||
while (a != NULL) {
|
while (a != NULL) {
|
||||||
@@ -450,6 +452,64 @@ tty_term_apply_overrides(struct tty_term *term)
|
|||||||
tty_term_apply(term, s + offset, 0);
|
tty_term_apply(term, s + offset, 0);
|
||||||
a = options_array_next(a);
|
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 *
|
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;
|
struct options_array_item *a;
|
||||||
union options_value *ov;
|
union options_value *ov;
|
||||||
u_int i, j;
|
u_int i, j;
|
||||||
const char *s, *acs, *value;
|
const char *s, *value;
|
||||||
size_t offset, namelen;
|
size_t offset, namelen;
|
||||||
char *first;
|
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_SETRGBF) ||
|
||||||
!tty_term_has(term, TTYC_SETRGBB)))
|
!tty_term_has(term, TTYC_SETRGBB)))
|
||||||
tty_add_features(feat, "RGB", ",");
|
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. */
|
/* Apply the features and overrides again. */
|
||||||
tty_apply_features(term, *feat);
|
if (tty_apply_features(term, *feat))
|
||||||
tty_term_apply_overrides(term);
|
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];
|
|
||||||
|
|
||||||
/* Log the capabilities. */
|
/* Log the capabilities. */
|
||||||
for (i = 0; i < tty_term_ncodes(); i++)
|
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];
|
ent = &tty_term_codes[i];
|
||||||
switch (ent->type) {
|
switch (ent->type) {
|
||||||
case TTYCODE_NONE:
|
case TTYCODE_NONE:
|
||||||
break;
|
continue;
|
||||||
case TTYCODE_STRING:
|
case TTYCODE_STRING:
|
||||||
s = tigetstr((char *)ent->name);
|
s = tigetstr((char *)ent->name);
|
||||||
if (s == NULL || s == (char *)-1)
|
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;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ctx->ocy < ctx->orupper || ctx->ocy > ctx->orlower) {
|
for (i = ctx->orupper; i <= ctx->orlower; i++)
|
||||||
for (i = ctx->ocy; i < ctx->sy; i++)
|
tty_draw_pane(tty, ctx, i);
|
||||||
tty_draw_pane(tty, ctx, i);
|
|
||||||
} else {
|
|
||||||
for (i = ctx->orupper; i <= ctx->orlower; i++)
|
|
||||||
tty_draw_pane(tty, ctx, i);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Is this position visible in the pane? */
|
/* 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_modedata *data = modedata;
|
||||||
struct window_buffer_itemdata *item = itemdata;
|
struct window_buffer_itemdata *item = itemdata;
|
||||||
struct format_tree *ft;
|
struct format_tree *ft;
|
||||||
struct session *s;
|
struct session *s = NULL;
|
||||||
struct winlink *wl;
|
struct winlink *wl = NULL;
|
||||||
struct window_pane *wp;
|
struct window_pane *wp = NULL;
|
||||||
struct paste_buffer *pb;
|
struct paste_buffer *pb;
|
||||||
char *expanded;
|
char *expanded;
|
||||||
key_code key;
|
key_code key;
|
||||||
|
|||||||
@@ -1102,10 +1102,13 @@ static enum window_copy_cmd_action
|
|||||||
window_copy_cmd_cursor_right(struct window_copy_cmd_state *cs)
|
window_copy_cmd_cursor_right(struct window_copy_cmd_state *cs)
|
||||||
{
|
{
|
||||||
struct window_mode_entry *wme = cs->wme;
|
struct window_mode_entry *wme = cs->wme;
|
||||||
|
struct window_copy_mode_data *data = wme->data;
|
||||||
u_int np = wme->prefix;
|
u_int np = wme->prefix;
|
||||||
|
|
||||||
for (; np != 0; np--)
|
for (; np != 0; np--) {
|
||||||
window_copy_cursor_right(wme, 0);
|
window_copy_cursor_right(wme, data->screen.sel != NULL &&
|
||||||
|
data->rectflag);
|
||||||
|
}
|
||||||
return (WINDOW_COPY_CMD_NOTHING);
|
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 window_copy_mode_data *data = wme->data;
|
||||||
struct screen *s = &data->screen;
|
struct screen *s = &data->screen;
|
||||||
u_int ox, oy, px, py;
|
u_int ox, oy, px, py;
|
||||||
|
int norectsel;
|
||||||
|
|
||||||
|
norectsel = data->screen.sel == NULL || !data->rectflag;
|
||||||
oy = screen_hsize(data->backing) + data->cy - data->oy;
|
oy = screen_hsize(data->backing) + data->cy - data->oy;
|
||||||
ox = window_copy_find_length(wme, oy);
|
ox = window_copy_find_length(wme, oy);
|
||||||
if (data->cx != ox) {
|
if (norectsel && data->cx != ox) {
|
||||||
data->lastcx = data->cx;
|
data->lastcx = data->cx;
|
||||||
data->lastsx = ox;
|
data->lastsx = ox;
|
||||||
}
|
}
|
||||||
@@ -4437,7 +4442,8 @@ window_copy_cursor_up(struct window_mode_entry *wme, int scroll_only)
|
|||||||
window_copy_other_end(wme);
|
window_copy_other_end(wme);
|
||||||
|
|
||||||
if (scroll_only || data->cy == 0) {
|
if (scroll_only || data->cy == 0) {
|
||||||
data->cx = data->lastcx;
|
if (norectsel)
|
||||||
|
data->cx = data->lastcx;
|
||||||
window_copy_scroll_down(wme, 1);
|
window_copy_scroll_down(wme, 1);
|
||||||
if (scroll_only) {
|
if (scroll_only) {
|
||||||
if (data->cy == screen_size_y(s) - 1)
|
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);
|
window_copy_redraw_lines(wme, data->cy, 2);
|
||||||
}
|
}
|
||||||
} else {
|
} 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 (window_copy_update_selection(wme, 1, 0)) {
|
||||||
if (data->cy == screen_size_y(s) - 1)
|
if (data->cy == screen_size_y(s) - 1)
|
||||||
window_copy_redraw_lines(wme, data->cy, 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;
|
py = screen_hsize(data->backing) + data->cy - data->oy;
|
||||||
px = window_copy_find_length(wme, py);
|
px = window_copy_find_length(wme, py);
|
||||||
if ((data->cx >= data->lastsx && data->cx != px) ||
|
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 window_copy_mode_data *data = wme->data;
|
||||||
struct screen *s = &data->screen;
|
struct screen *s = &data->screen;
|
||||||
u_int ox, oy, px, py;
|
u_int ox, oy, px, py;
|
||||||
|
int norectsel;
|
||||||
|
|
||||||
|
norectsel = data->screen.sel == NULL || !data->rectflag;
|
||||||
oy = screen_hsize(data->backing) + data->cy - data->oy;
|
oy = screen_hsize(data->backing) + data->cy - data->oy;
|
||||||
ox = window_copy_find_length(wme, oy);
|
ox = window_copy_find_length(wme, oy);
|
||||||
if (data->cx != ox) {
|
if (norectsel && data->cx != ox) {
|
||||||
data->lastcx = data->cx;
|
data->lastcx = data->cx;
|
||||||
data->lastsx = ox;
|
data->lastsx = ox;
|
||||||
}
|
}
|
||||||
@@ -4504,17 +4516,22 @@ window_copy_cursor_down(struct window_mode_entry *wme, int scroll_only)
|
|||||||
window_copy_other_end(wme);
|
window_copy_other_end(wme);
|
||||||
|
|
||||||
if (scroll_only || data->cy == screen_size_y(s) - 1) {
|
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);
|
window_copy_scroll_up(wme, 1);
|
||||||
if (scroll_only && data->cy > 0)
|
if (scroll_only && data->cy > 0)
|
||||||
window_copy_redraw_lines(wme, data->cy - 1, 2);
|
window_copy_redraw_lines(wme, data->cy - 1, 2);
|
||||||
} else {
|
} 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 (window_copy_update_selection(wme, 1, 0))
|
||||||
window_copy_redraw_lines(wme, data->cy - 1, 2);
|
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;
|
py = screen_hsize(data->backing) + data->cy - data->oy;
|
||||||
px = window_copy_find_length(wme, py);
|
px = window_copy_find_length(wme, py);
|
||||||
if ((data->cx >= data->lastsx && data->cx != px) ||
|
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);
|
window_update_activity(w);
|
||||||
|
|
||||||
|
log_debug("%s: @%u create %ux%u (%ux%u)", __func__, w->id, sx, sy,
|
||||||
|
w->xpixel, w->ypixel);
|
||||||
return (w);
|
return (w);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -423,25 +425,18 @@ window_resize(struct window *w, u_int sx, u_int sy, int xpixel, int ypixel)
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
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 window *w = wp->window;
|
||||||
struct winsize ws;
|
struct winsize ws;
|
||||||
u_int sy;
|
|
||||||
|
|
||||||
if (wp->fd == -1)
|
if (wp->fd == -1)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (!force)
|
log_debug("%s: %%%u resize to %u,%u", __func__, wp->id, sx, sy);
|
||||||
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);
|
|
||||||
|
|
||||||
memset(&ws, 0, sizeof ws);
|
memset(&ws, 0, sizeof ws);
|
||||||
ws.ws_col = wp->sx;
|
ws.ws_col = sx;
|
||||||
ws.ws_row = sy;
|
ws.ws_row = sy;
|
||||||
ws.ws_xpixel = w->xpixel * ws.ws_col;
|
ws.ws_xpixel = w->xpixel * ws.ws_col;
|
||||||
ws.ws_ypixel = w->ypixel * ws.ws_row;
|
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++;
|
wp->id = next_window_pane_id++;
|
||||||
RB_INSERT(window_pane_tree, &all_window_panes, wp);
|
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->fd = -1;
|
||||||
wp->event = NULL;
|
|
||||||
|
|
||||||
wp->fg = 8;
|
wp->fg = 8;
|
||||||
wp->bg = 8;
|
wp->bg = 8;
|
||||||
|
|
||||||
TAILQ_INIT(&wp->modes);
|
TAILQ_INIT(&wp->modes);
|
||||||
|
|
||||||
wp->layout_cell = NULL;
|
TAILQ_INIT (&wp->resize_queue);
|
||||||
|
|
||||||
wp->xoff = 0;
|
|
||||||
wp->yoff = 0;
|
|
||||||
|
|
||||||
wp->sx = sx;
|
wp->sx = sx;
|
||||||
wp->sy = sy;
|
wp->sy = sy;
|
||||||
|
|
||||||
wp->pipe_fd = -1;
|
wp->pipe_fd = -1;
|
||||||
wp->pipe_event = NULL;
|
|
||||||
|
|
||||||
screen_init(&wp->base, sx, sy, hlimit);
|
screen_init(&wp->base, sx, sy, hlimit);
|
||||||
wp->screen = &wp->base;
|
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
|
static void
|
||||||
window_pane_destroy(struct window_pane *wp)
|
window_pane_destroy(struct window_pane *wp)
|
||||||
{
|
{
|
||||||
|
struct window_pane_resize *r;
|
||||||
|
struct window_pane_resize *r1;
|
||||||
|
|
||||||
window_pane_reset_mode_all(wp);
|
window_pane_reset_mode_all(wp);
|
||||||
free(wp->searchstr);
|
free(wp->searchstr);
|
||||||
|
|
||||||
@@ -927,8 +915,10 @@ window_pane_destroy(struct window_pane *wp)
|
|||||||
|
|
||||||
if (event_initialized(&wp->resize_timer))
|
if (event_initialized(&wp->resize_timer))
|
||||||
event_del(&wp->resize_timer);
|
event_del(&wp->resize_timer);
|
||||||
if (event_initialized(&wp->force_timer))
|
TAILQ_FOREACH_SAFE(r, &wp->resize_queue, entry, r1) {
|
||||||
event_del(&wp->force_timer);
|
TAILQ_REMOVE(&wp->resize_queue, r, entry);
|
||||||
|
free(r);
|
||||||
|
}
|
||||||
|
|
||||||
RB_REMOVE(window_pane_tree, &all_window_panes, wp);
|
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)
|
window_pane_resize(struct window_pane *wp, u_int sx, u_int sy)
|
||||||
{
|
{
|
||||||
struct window_mode_entry *wme;
|
struct window_mode_entry *wme;
|
||||||
|
struct window_pane_resize *r;
|
||||||
|
|
||||||
if (sx == wp->sx && sy == wp->sy)
|
if (sx == wp->sx && sy == wp->sy)
|
||||||
return;
|
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->sx = sx;
|
||||||
wp->sy = sy;
|
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);
|
wme = TAILQ_FIRST(&wp->modes);
|
||||||
if (wme != NULL && wme->mode->resize != NULL)
|
if (wme != NULL && wme->mode->resize != NULL)
|
||||||
wme->mode->resize(wme, sx, sy);
|
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
|
void
|
||||||
|
|||||||
Reference in New Issue
Block a user