aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Makefile.am5
-rw-r--r--arguments.c16
-rw-r--r--client.c2
-rw-r--r--cmd-list-clients.c2
-rw-r--r--cmd-refresh-client.c39
-rw-r--r--cmd-resize-pane.c13
-rw-r--r--cmd-show-options.c7
-rw-r--r--cmd-split-window.c31
-rw-r--r--colour.c2
-rw-r--r--compat.h10
-rw-r--r--compat/getpeereid.c59
-rw-r--r--compat/systemd.c58
-rw-r--r--configure.ac43
-rw-r--r--format-draw.c6
-rw-r--r--format.c107
-rw-r--r--grid.c2
-rw-r--r--input-keys.c15
-rw-r--r--input.c53
-rw-r--r--key-string.c42
-rw-r--r--menu.c6
-rw-r--r--notify.c63
-rw-r--r--options-table.c50
-rw-r--r--options.c6
-rw-r--r--osdep-netbsd.c3
-rw-r--r--osdep-openbsd.c3
-rw-r--r--popup.c10
-rw-r--r--proc.c11
-rw-r--r--resize.c1
-rw-r--r--screen-redraw.c17
-rw-r--r--screen-write.c10
-rw-r--r--screen.c2
-rw-r--r--server-client.c666
-rw-r--r--server-fn.c42
-rw-r--r--server.c12
-rw-r--r--session.c5
-rw-r--r--status.c2
-rw-r--r--tmux.157
-rw-r--r--tmux.h304
-rw-r--r--tty-features.c13
-rw-r--r--tty-keys.c37
-rw-r--r--tty-term.c1
-rw-r--r--tty.c44
-rw-r--r--window-customize.c4
-rw-r--r--window.c19
44 files changed, 1616 insertions, 284 deletions
diff --git a/Makefile.am b/Makefile.am
index 68494932..5bdd9d5f 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -204,6 +204,11 @@ if NEED_FORKPTY
nodist_tmux_SOURCES += compat/forkpty-@PLATFORM@.c
endif
+# Add compat file for systemd.
+if HAVE_SYSTEMD
+nodist_tmux_SOURCES += compat/systemd.c
+endif
+
# Add compat file for utf8proc.
if HAVE_UTF8PROC
nodist_tmux_SOURCES += compat/utf8proc.c
diff --git a/arguments.c b/arguments.c
index a27d8e0a..91c470e2 100644
--- a/arguments.c
+++ b/arguments.c
@@ -131,8 +131,9 @@ args_parse(const struct args_parse *parse, struct args_value *values,
u_int i;
enum args_parse_type type;
struct args_value *value, *new;
- u_char flag, argument;
+ u_char flag;
const char *found, *string, *s;
+ int optional_argument;
if (count == 0)
return (args_create());
@@ -169,18 +170,27 @@ args_parse(const struct args_parse *parse, struct args_value *values,
args_free(args);
return (NULL);
}
- argument = *++found;
- if (argument != ':') {
+ if (*++found != ':') {
log_debug("%s: -%c", __func__, flag);
args_set(args, flag, NULL);
continue;
}
+ if (*found == ':') {
+ optional_argument = 1;
+ found++;
+ }
new = xcalloc(1, sizeof *new);
if (*string != '\0') {
new->type = ARGS_STRING;
new->string = xstrdup(string);
} else {
if (i == count) {
+ if (optional_argument) {
+ log_debug("%s: -%c", __func__,
+ flag);
+ args_set(args, flag, NULL);
+ continue;
+ }
xasprintf(cause,
"-%c expects an argument",
flag);
diff --git a/client.c b/client.c
index 8ca08524..08708c21 100644
--- a/client.c
+++ b/client.c
@@ -531,7 +531,7 @@ client_signal(int sig)
if (sig == SIGCHLD)
waitpid(WAIT_ANY, &status, WNOHANG);
else if (!client_attached) {
- if (sig == SIGTERM)
+ if (sig == SIGTERM || sig == SIGHUP)
proc_exit(client_proc);
} else {
switch (sig) {
diff --git a/cmd-list-clients.c b/cmd-list-clients.c
index a5b7d147..53a99178 100644
--- a/cmd-list-clients.c
+++ b/cmd-list-clients.c
@@ -31,6 +31,8 @@
#define LIST_CLIENTS_TEMPLATE \
"#{client_name}: #{session_name} " \
"[#{client_width}x#{client_height} #{client_termname}] " \
+ "#{?#{!=:#{client_uid},#{uid}}," \
+ "[user #{?client_user,#{client_user},#{client_uid},}] ,}" \
"#{?client_flags,(,}#{client_flags}#{?client_flags,),}"
static enum cmd_retval cmd_list_clients_exec(struct cmd *, struct cmdq_item *);
diff --git a/cmd-refresh-client.c b/cmd-refresh-client.c
index 821558ae..b2665ad9 100644
--- a/cmd-refresh-client.c
+++ b/cmd-refresh-client.c
@@ -34,7 +34,7 @@ const struct cmd_entry cmd_refresh_client_entry = {
.name = "refresh-client",
.alias = "refresh",
- .args = { "A:B:cC:Df:F:lLRSt:U", 0, 1, NULL },
+ .args = { "A:B:cC:Df:F:l::LRSt:U", 0, 1, NULL },
.usage = "[-cDlLRSU] [-A pane:state] [-B name:what:format] "
"[-C XxY] [-f flags] " CMD_TARGET_CLIENT_USAGE " [adjustment]",
@@ -163,6 +163,37 @@ out:
}
static enum cmd_retval
+cmd_refresh_client_clipboard(struct cmd *self, struct cmdq_item *item)
+{
+ struct args *args = cmd_get_args(self);
+ struct client *tc = cmdq_get_target_client(item);
+ const char *p;
+ u_int i;
+ struct cmd_find_state fs;
+
+ p = args_get(args, 'l');
+ if (p == NULL) {
+ if (tc->flags & CLIENT_CLIPBOARDBUFFER)
+ return (CMD_RETURN_NORMAL);
+ tc->flags |= CLIENT_CLIPBOARDBUFFER;
+ } else {
+ if (cmd_find_target(&fs, item, p, CMD_FIND_PANE, 0) != 0)
+ return (CMD_RETURN_ERROR);
+ for (i = 0; i < tc->clipboard_npanes; i++) {
+ if (tc->clipboard_panes[i] == fs.wp->id)
+ break;
+ }
+ if (i != tc->clipboard_npanes)
+ return (CMD_RETURN_NORMAL);
+ tc->clipboard_panes = xreallocarray (tc->clipboard_panes,
+ tc->clipboard_npanes + 1, sizeof *tc->clipboard_panes);
+ tc->clipboard_panes[tc->clipboard_npanes++] = fs.wp->id;
+ }
+ tty_clipboard_query(&tc->tty);
+ return (CMD_RETURN_NORMAL);
+}
+
+static enum cmd_retval
cmd_refresh_client_exec(struct cmd *self, struct cmdq_item *item)
{
struct args *args = cmd_get_args(self);
@@ -224,10 +255,8 @@ cmd_refresh_client_exec(struct cmd *self, struct cmdq_item *item)
return (CMD_RETURN_NORMAL);
}
- if (args_has(args, 'l')) {
- tty_putcode_ptr2(&tc->tty, TTYC_MS, "", "?");
- return (CMD_RETURN_NORMAL);
- }
+ if (args_has(args, 'l'))
+ return (cmd_refresh_client_clipboard(self, item));
if (args_has(args, 'F')) /* -F is an alias for -f */
server_client_set_flags(tc, args_get(args, 'F'));
diff --git a/cmd-resize-pane.c b/cmd-resize-pane.c
index 81744f72..c9439441 100644
--- a/cmd-resize-pane.c
+++ b/cmd-resize-pane.c
@@ -60,7 +60,7 @@ cmd_resize_pane_exec(struct cmd *self, struct cmdq_item *item)
const char *errstr;
char *cause;
u_int adjust;
- int x, y;
+ int x, y, status;
struct grid *gd = wp->base.grid;
if (args_has(args, 'T')) {
@@ -121,6 +121,17 @@ cmd_resize_pane_exec(struct cmd *self, struct cmdq_item *item)
free(cause);
return (CMD_RETURN_ERROR);
}
+ status = options_get_number(w->options, "pane-border-status");
+ switch (status) {
+ case PANE_STATUS_TOP:
+ if (y != INT_MAX && wp->yoff == 1)
+ y++;
+ break;
+ case PANE_STATUS_BOTTOM:
+ if (y != INT_MAX && wp->yoff + wp->sy == w->sy - 1)
+ y++;
+ break;
+ }
layout_resize_pane_to(wp, LAYOUT_TOPBOTTOM, y);
}
diff --git a/cmd-show-options.c b/cmd-show-options.c
index 90226ad3..252a33c6 100644
--- a/cmd-show-options.c
+++ b/cmd-show-options.c
@@ -102,7 +102,7 @@ cmd_show_options_exec(struct cmd *self, struct cmdq_item *item)
name = options_match(argument, &idx, &ambiguous);
if (name == NULL) {
if (args_has(args, 'q'))
- goto fail;
+ goto out;
if (ambiguous)
cmdq_error(item, "ambiguous option: %s", argument);
else
@@ -113,7 +113,7 @@ cmd_show_options_exec(struct cmd *self, struct cmdq_item *item)
&cause);
if (scope == OPTIONS_TABLE_NONE) {
if (args_has(args, 'q'))
- goto fail;
+ goto out;
cmdq_error(item, "%s", cause);
free(cause);
goto fail;
@@ -128,11 +128,12 @@ cmd_show_options_exec(struct cmd *self, struct cmdq_item *item)
cmd_show_options_print(self, item, o, idx, parent);
else if (*name == '@') {
if (args_has(args, 'q'))
- goto fail;
+ goto out;
cmdq_error(item, "invalid option: %s", argument);
goto fail;
}
+out:
free(name);
free(argument);
return (CMD_RETURN_NORMAL);
diff --git a/cmd-split-window.c b/cmd-split-window.c
index 888d4106..9947dfd3 100644
--- a/cmd-split-window.c
+++ b/cmd-split-window.c
@@ -60,6 +60,7 @@ cmd_split_window_exec(struct cmd *self, struct cmdq_item *item)
struct client *tc = cmdq_get_target_client(item);
struct session *s = target->s;
struct winlink *wl = target->wl;
+ struct window *w = wl->window;
struct window_pane *wp = target->wp, *new_wp;
enum layout_type type;
struct layout_cell *lc;
@@ -86,10 +87,17 @@ cmd_split_window_exec(struct cmd *self, struct cmdq_item *item)
cmdq_error(item, "percentage %s", errstr);
return (CMD_RETURN_ERROR);
}
- if (type == LAYOUT_TOPBOTTOM)
- size = (wp->sy * percentage) / 100;
- else
- size = (wp->sx * percentage) / 100;
+ if (args_has(args, 'f')) {
+ if (type == LAYOUT_TOPBOTTOM)
+ size = (w->sy * percentage) / 100;
+ else
+ size = (w->sx * percentage) / 100;
+ } else {
+ if (type == LAYOUT_TOPBOTTOM)
+ size = (wp->sy * percentage) / 100;
+ else
+ size = (wp->sx * percentage) / 100;
+ }
} else {
size = args_strtonum(args, 'l', 0, INT_MAX, &cause);
if (cause != NULL) {
@@ -105,10 +113,17 @@ cmd_split_window_exec(struct cmd *self, struct cmdq_item *item)
free(cause);
return (CMD_RETURN_ERROR);
}
- if (type == LAYOUT_TOPBOTTOM)
- size = (wp->sy * percentage) / 100;
- else
- size = (wp->sx * percentage) / 100;
+ if (args_has(args, 'f')) {
+ if (type == LAYOUT_TOPBOTTOM)
+ size = (w->sy * percentage) / 100;
+ else
+ size = (w->sx * percentage) / 100;
+ } else {
+ if (type == LAYOUT_TOPBOTTOM)
+ size = (wp->sy * percentage) / 100;
+ else
+ size = (wp->sx * percentage) / 100;
+ }
} else
size = -1;
diff --git a/colour.c b/colour.c
index 6ede25da..a282d182 100644
--- a/colour.c
+++ b/colour.c
@@ -128,7 +128,7 @@ colour_tostring(int c)
u_char r, g, b;
if (c == -1)
- return ("invalid");
+ return ("none");
if (c & COLOUR_FLAG_RGB) {
colour_split_rgb(c, &r, &g, &b);
diff --git a/compat.h b/compat.h
index 13334ad7..6eb97619 100644
--- a/compat.h
+++ b/compat.h
@@ -334,6 +334,11 @@ char *strndup(const char *, size_t);
void *memmem(const void *, size_t, const void *, size_t);
#endif
+#ifndef HAVE_GETPEEREID
+/* getpeereid.c */
+int getpeereid(int, uid_t *, gid_t *);
+#endif
+
#ifndef HAVE_DAEMON
/* daemon.c */
int daemon(int, int);
@@ -416,6 +421,11 @@ void *reallocarray(void *, size_t, size_t);
void *recallocarray(void *, size_t, size_t, size_t);
#endif
+#ifdef HAVE_SYSTEMD
+/* systemd.c */
+int systemd_create_socket(int, char **);
+#endif
+
#ifdef HAVE_UTF8PROC
/* utf8proc.c */
int utf8proc_wcwidth(wchar_t);
diff --git a/compat/getpeereid.c b/compat/getpeereid.c
new file mode 100644
index 00000000..5a593c07
--- /dev/null
+++ b/compat/getpeereid.c
@@ -0,0 +1,59 @@
+/*
+ * Copyright (c) 2022 Nicholas Marriott <nicholas.marriott@gmail.com>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
+ * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
+ * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <sys/types.h>
+#include <sys/socket.h>
+
+#include <stdio.h>
+
+#ifdef HAVE_UCRED_H
+#include <ucred.h>
+#endif
+
+#include "compat.h"
+
+int
+getpeereid(int s, uid_t *uid, gid_t *gid)
+{
+#ifdef HAVE_SO_PEERCRED
+ struct ucred uc;
+ int len = sizeof uc;
+
+ if (getsockopt(s, SOL_SOCKET, SO_PEERCRED, &uc, &len) == -1)
+ return (-1);
+ *uid = uc.uid;
+ *gid = uc.gid;
+ return (0);
+#elif defined(HAVE_GETPEERUCRED)
+int
+getpeereid(int s, uid_t *uid, gid_t *gid)
+{
+ ucred_t *ucred = NULL;
+
+ if (getpeerucred(s, &ucred) == -1)
+ return (-1);
+ if ((*uid = ucred_geteuid(ucred)) == -1)
+ return (-1);
+ if ((*gid = ucred_getrgid(ucred)) == -1)
+ return (-1);
+ ucred_free(ucred);
+ return (0);
+}
+#else
+ errno = EOPNOTSUPP;
+ return (-1);
+#endif
+}
diff --git a/compat/systemd.c b/compat/systemd.c
new file mode 100644
index 00000000..7317e43a
--- /dev/null
+++ b/compat/systemd.c
@@ -0,0 +1,58 @@
+/* $OpenBSD$ */
+
+/*
+ * Copyright (c) 2022 Nicholas Marriott <nicholas.marriott@gmail.com>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
+ * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
+ * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <sys/types.h>
+#include <sys/un.h>
+
+#include <systemd/sd-daemon.h>
+
+#include "tmux.h"
+
+int
+systemd_create_socket(int flags, char **cause)
+{
+ int fds;
+ int fd;
+ struct sockaddr_un sa;
+ int addrlen = sizeof sa;
+
+ fds = sd_listen_fds(0);
+ if (fds > 1) { /* too many file descriptors */
+ errno = E2BIG;
+ goto fail;
+ }
+
+ if (fds == 1) { /* socket-activated */
+ fd = SD_LISTEN_FDS_START;
+ if (!sd_is_socket_unix(fd, SOCK_STREAM, 1, NULL, 0)) {
+ errno = EPFNOSUPPORT;
+ goto fail;
+ }
+ if (getsockname(fd, (struct sockaddr *)&sa, &addrlen) == -1)
+ goto fail;
+ socket_path = xstrdup(sa.sun_path);
+ return (fd);
+ }
+
+ return (server_create_socket(flags, cause));
+
+fail:
+ if (cause != NULL)
+ xasprintf(cause, "systemd socket error (%s)", strerror(errno));
+ return (-1);
+}
diff --git a/configure.ac b/configure.ac
index c71a54b0..20199515 100644
--- a/configure.ac
+++ b/configure.ac
@@ -69,6 +69,11 @@ AC_ARG_ENABLE(
AS_HELP_STRING(--enable-static, create a static build)
)
if test "x$enable_static" = xyes; then
+ case "$host_os" in
+ *darwin*)
+ AC_MSG_ERROR([static linking is not supported on macOS])
+ ;;
+ esac
test "x$PKG_CONFIG" != x && PKG_CONFIG="$PKG_CONFIG --static"
AM_LDFLAGS="-static $AM_LDFLAGS"
LDFLAGS="$AM_LDFLAGS $SAVED_LDFLAGS"
@@ -123,6 +128,7 @@ AC_CHECK_HEADERS([ \
sys/dir.h \
sys/ndir.h \
sys/tree.h \
+ ucred.h \
util.h \
])
@@ -141,7 +147,8 @@ AC_CHECK_FUNCS([ \
flock \
prctl \
proc_pidinfo \
- sysconf
+ getpeerucred \
+ sysconf \
])
# Check for functions with a compatibility implementation.
@@ -155,6 +162,7 @@ AC_REPLACE_FUNCS([ \
freezero \
getdtablecount \
getdtablesize \
+ getpeereid \
getline \
getprogname \
memmem \
@@ -382,6 +390,31 @@ if test "x$enable_utf8proc" = xyes; then
fi
AM_CONDITIONAL(HAVE_UTF8PROC, [test "x$enable_utf8proc" = xyes])
+# Check for systemd support.
+AC_ARG_ENABLE(
+ systemd,
+ AS_HELP_STRING(--enable-systemd, enable systemd integration)
+)
+if test x"$enable_systemd" = xyes; then
+ PKG_CHECK_MODULES(
+ SYSTEMD,
+ libsystemd,
+ [
+ AM_CPPFLAGS="$SYSTEMD_CFLAGS $AM_CPPFLAGS"
+ CPPFLAGS="$AM_CPPFLAGS $SAVED_CPPFLAGS"
+ LIBS="$SYSTEMD_LIBS $LIBS"
+ found_systemd=yes
+ ],
+ found_systemd=no
+ )
+ if test "x$found_systemd" = xyes; then
+ AC_DEFINE(HAVE_SYSTEMD)
+ else
+ AC_MSG_ERROR("systemd not found")
+ fi
+fi
+AM_CONDITIONAL(HAVE_SYSTEMD, [test "x$found_systemd" = xyes])
+
# Check for b64_ntop. If we have b64_ntop, we assume b64_pton as well.
AC_MSG_CHECKING(for b64_ntop)
AC_LINK_IFELSE([AC_LANG_PROGRAM(
@@ -679,6 +712,14 @@ AC_CHECK_DECL(
[#include <sys/prctl.h>]
)
+# Look for setsockopt(SO_PEERCRED).
+AC_CHECK_DECL(
+ SO_PEERCRED,
+ AC_DEFINE(HAVE_SO_PEERCRED),
+ ,
+ [#include <sys/socket.h>]
+)
+
# Look for fcntl(F_CLOSEM).
AC_CHECK_DECL(
F_CLOSEM,
diff --git a/format-draw.c b/format-draw.c
index 1110535f..1a7e60b3 100644
--- a/format-draw.c
+++ b/format-draw.c
@@ -1154,13 +1154,13 @@ format_trim_right(const char *expanded, u_int limit)
while (*cp != '\0') {
if (*cp == '#') {
end = format_leading_hashes(cp, &n, &leading_width);
+ copy_width = leading_width;
if (width <= skip) {
- if (skip - width >= leading_width)
+ if (skip - width >= copy_width)
copy_width = 0;
else
copy_width -= (skip - width);
- } else
- copy_width = leading_width;
+ }
if (copy_width != 0) {
if (n == 1)
*out++ = '#';
diff --git a/format.c b/format.c
index 2fc0961e..2e4bceb5 100644
--- a/format.c
+++ b/format.c
@@ -24,6 +24,7 @@
#include <fnmatch.h>
#include <libgen.h>
#include <math.h>
+#include <pwd.h>
#include <regex.h>
#include <stdarg.h>
#include <stdlib.h>
@@ -1387,6 +1388,35 @@ format_cb_client_tty(struct format_tree *ft)
return (NULL);
}
+/* Callback for client_uid. */
+static void *
+format_cb_client_uid(struct format_tree *ft)
+{
+ uid_t uid;
+
+ if (ft->c != NULL) {
+ uid = proc_get_peer_uid(ft->c->peer);
+ if (uid != (uid_t)-1)
+ return (format_printf("%ld", (long)uid));
+ }
+ return (NULL);
+}
+
+/* Callback for client_user. */
+static void *
+format_cb_client_user(struct format_tree *ft)
+{
+ uid_t uid;
+ struct passwd *pw;
+
+ if (ft->c != NULL) {
+ uid = proc_get_peer_uid(ft->c->peer);
+ if (uid != (uid_t)-1 && (pw = getpwuid(uid)) != NULL)
+ return (xstrdup(pw->pw_name));
+ }
+ return (NULL);
+}
+
/* Callback for client_utf8. */
static void *
format_cb_client_utf8(struct format_tree *ft)
@@ -1650,6 +1680,13 @@ format_cb_mouse_y(struct format_tree *ft)
return (NULL);
}
+/* Callback for next_session_id. */
+static void *
+format_cb_next_session_id(__unused struct format_tree *ft)
+{
+ return (format_printf("$%u", next_session_id));
+}
+
/* Callback for origin_flag. */
static void *
format_cb_origin_flag(struct format_tree *ft)
@@ -1719,6 +1756,23 @@ format_cb_pane_dead(struct format_tree *ft)
return (NULL);
}
+/* Callback for pane_dead_signal. */
+static void *
+format_cb_pane_dead_signal(struct format_tree *ft)
+{
+ struct window_pane *wp = ft->wp;
+ const char *name;
+
+ if (wp != NULL) {
+ if ((wp->flags & PANE_STATUSREADY) && WIFSIGNALED(wp->status)) {
+ name = sig2name(WTERMSIG(wp->status));
+ return (format_printf("%s", name));
+ }
+ return (NULL);
+ }
+ return (NULL);
+}
+
/* Callback for pane_dead_status. */
static void *
format_cb_pane_dead_status(struct format_tree *ft)
@@ -1733,6 +1787,20 @@ format_cb_pane_dead_status(struct format_tree *ft)
return (NULL);
}
+/* Callback for pane_dead_time. */
+static void *
+format_cb_pane_dead_time(struct format_tree *ft)
+{
+ struct window_pane *wp = ft->wp;
+
+ if (wp != NULL) {
+ if (wp->flags & PANE_STATUSDRAWN)
+ return (&wp->dead_time);
+ return (NULL);
+ }
+ return (NULL);
+}
+
/* Callback for pane_format. */
static void *
format_cb_pane_format(struct format_tree *ft)
@@ -2514,6 +2582,24 @@ format_cb_tree_mode_format(__unused struct format_tree *ft)
return (xstrdup(window_tree_mode.default_format));
}
+/* Callback for uid. */
+static void *
+format_cb_uid(__unused struct format_tree *ft)
+{
+ return (format_printf("%ld", (long)getuid()));
+}
+
+/* Callback for user. */
+static void *
+format_cb_user(__unused struct format_tree *ft)
+{
+ struct passwd *pw;
+
+ if ((pw = getpwuid(getuid())) != NULL)
+ return (xstrdup(pw->pw_name));
+ return NULL;
+}
+
/* Format table type. */
enum format_table_type {
FORMAT_TABLE_STRING,
@@ -2620,6 +2706,12 @@ static const struct format_table_entry format_table[] = {
{ "client_tty", FORMAT_TABLE_STRING,
format_cb_client_tty
},
+ { "client_uid", FORMAT_TABLE_STRING,
+ format_cb_client_uid
+ },
+ { "client_user", FORMAT_TABLE_STRING,
+ format_cb_client_user
+ },
{ "client_utf8", FORMAT_TABLE_STRING,
format_cb_client_utf8
},
@@ -2707,6 +2799,9 @@ static const struct format_table_entry format_table[] = {
{ "mouse_y", FORMAT_TABLE_STRING,
format_cb_mouse_y
},
+ { "next_session_id", FORMAT_TABLE_STRING,
+ format_cb_next_session_id
+ },
{ "origin_flag", FORMAT_TABLE_STRING,
format_cb_origin_flag
},
@@ -2740,9 +2835,15 @@ static const struct format_table_entry format_table[] = {
{ "pane_dead", FORMAT_TABLE_STRING,
format_cb_pane_dead
},
+ { "pane_dead_signal", FORMAT_TABLE_STRING,
+ format_cb_pane_dead_signal
+ },
{ "pane_dead_status", FORMAT_TABLE_STRING,
format_cb_pane_dead_status
},
+ { "pane_dead_time", FORMAT_TABLE_TIME,
+ format_cb_pane_dead_time
+ },
{ "pane_fg", FORMAT_TABLE_STRING,
format_cb_pane_fg
},
@@ -2896,6 +2997,12 @@ static const struct format_table_entry format_table[] = {
{ "tree_mode_format", FORMAT_TABLE_STRING,
format_cb_tree_mode_format
},
+ { "uid", FORMAT_TABLE_STRING,
+ format_cb_uid
+ },
+ { "user", FORMAT_TABLE_STRING,
+ format_cb_user
+ },
{ "version", FORMAT_TABLE_STRING,
format_cb_version
},
diff --git a/grid.c b/grid.c
index 91dc8f42..1109ac58 100644
--- a/grid.c
+++ b/grid.c
@@ -1003,7 +1003,7 @@ grid_string_cells(struct grid *gd, u_int px, u_int py, u_int nx,
gl = grid_peek_line(gd, py);
for (xx = px; xx < px + nx; xx++) {
- if (gl == NULL || xx >= gl->cellsize)
+ if (gl == NULL || xx >= gl->cellused)
break;
grid_get_cell(gd, xx, py, &gc);
if (gc.flags & GRID_FLAG_PADDING)
diff --git a/input-keys.c b/input-keys.c
index b4770808..feb62f6d 100644
--- a/input-keys.c
+++ b/input-keys.c
@@ -417,7 +417,7 @@ int
input_key(struct screen *s, struct bufferevent *bev, key_code key)
{
struct input_key_entry *ike;
- key_code justkey, newkey, outkey;
+ key_code justkey, newkey, outkey, modifiers;
struct utf8_data ud;
char tmp[64], modifier;
@@ -518,7 +518,12 @@ input_key(struct screen *s, struct bufferevent *bev, key_code key)
return (input_key(s, bev, key & ~KEYC_CTRL));
}
outkey = (key & KEYC_MASK_KEY);
- switch (key & KEYC_MASK_MODIFIERS) {
+ modifiers = (key & KEYC_MASK_MODIFIERS);
+ if (outkey < 32 && outkey != 9 && outkey != 13 && outkey != 27) {
+ outkey = 64 + outkey;
+ modifiers |= KEYC_CTRL;
+ }
+ switch (modifiers) {
case KEYC_SHIFT:
modifier = '2';
break;
@@ -577,13 +582,13 @@ input_key_get_mouse(struct screen *s, struct mouse_event *m, u_int x, u_int y,
*/
if (m->sgr_type != ' ') {
if (MOUSE_DRAG(m->sgr_b) &&
- MOUSE_BUTTONS(m->sgr_b) == 3 &&
+ MOUSE_RELEASE(m->sgr_b) &&
(~s->mode & MODE_MOUSE_ALL))
return (0);
} else {
if (MOUSE_DRAG(m->b) &&
- MOUSE_BUTTONS(m->b) == 3 &&
- MOUSE_BUTTONS(m->lb) == 3 &&
+ MOUSE_RELEASE(m->b) &&
+ MOUSE_RELEASE(m->lb) &&
(~s->mode & MODE_MOUSE_ALL))
return (0);
}
diff --git a/input.c b/input.c
index 16f31ad7..b1856538 100644
--- a/input.c
+++ b/input.c
@@ -2235,15 +2235,19 @@ input_enter_dcs(struct input_ctx *ictx)
static int
input_dcs_dispatch(struct input_ctx *ictx)
{
+ struct window_pane *wp = ictx->wp;
struct screen_write_ctx *sctx = &ictx->ctx;
u_char *buf = ictx->input_buf;
size_t len = ictx->input_len;
const char prefix[] = "tmux;";
const u_int prefixlen = (sizeof prefix) - 1;
+ if (wp == NULL)
+ return (0);
if (ictx->flags & INPUT_DISCARD)
return (0);
-
+ if (!options_get_number(ictx->wp->options, "allow-passthrough"))
+ return (0);
log_debug("%s: \"%s\"", __func__, buf);
if (len >= prefixlen && strncmp(buf, prefix, prefixlen) == 0)
@@ -2678,8 +2682,8 @@ input_osc_52(struct input_ctx *ictx, const char *p)
{
struct window_pane *wp = ictx->wp;
char *end;
- const char *buf;
- size_t len;
+ const char *buf = NULL;
+ size_t len = 0;
u_char *out;
int outlen, state;
struct screen_write_ctx ctx;
@@ -2699,26 +2703,12 @@ input_osc_52(struct input_ctx *ictx, const char *p)
log_debug("%s: %s", __func__, end);
if (strcmp(end, "?") == 0) {
- if ((pb = paste_get_top(NULL)) != NULL) {
+ if ((pb = paste_get_top(NULL)) != NULL)
buf = paste_buffer_data(pb, &len);
- outlen = 4 * ((len + 2) / 3) + 1;
- out = xmalloc(outlen);
- if ((outlen = b64_ntop(buf, len, out, outlen)) == -1) {
- free(out);
- return;
- }
- } else {
- outlen = 0;
- out = NULL;
- }
- bufferevent_write(ictx->event, "\033]52;;", 6);
- if (outlen != 0)
- bufferevent_write(ictx->event, out, outlen);
if (ictx->input_end == INPUT_END_BEL)
- bufferevent_write(ictx->event, "\007", 1);
+ input_reply_clipboard(ictx->event, buf, len, "\007");
else
- bufferevent_write(ictx->event, "\033\\", 2);
- free(out);
+ input_reply_clipboard(ictx->event, buf, len, "\033\\");
return;
}
@@ -2776,3 +2766,26 @@ input_osc_104(struct input_ctx *ictx, const char *p)
screen_write_fullredraw(&ictx->ctx);
free(copy);
}
+
+void
+input_reply_clipboard(struct bufferevent *bev, const char *buf, size_t len,
+ const char *end)
+{
+ char *out = NULL;
+ size_t outlen = 0;
+
+ if (buf != NULL && len != 0) {
+ outlen = 4 * ((len + 2) / 3) + 1;
+ out = xmalloc(outlen);
+ if ((outlen = b64_ntop(buf, len, out, outlen)) == -1) {
+ free(out);
+ return;
+ }
+ }
+
+ bufferevent_write(bev, "\033]52;;", 6);
+ if (outlen != 0)
+ bufferevent_write(bev, out, outlen);
+ bufferevent_write(bev, end, strlen(end));
+ free(out);
+}
diff --git a/key-string.c b/key-string.c
index 4f7be858..0ca91306 100644
--- a/key-string.c
+++ b/key-string.c
@@ -91,26 +91,68 @@ static const struct {
KEYC_MOUSE_STRING(MOUSEDOWN1, MouseDown1),
KEYC_MOUSE_STRING(MOUSEDOWN2, MouseDown2),
KEYC_MOUSE_STRING(MOUSEDOWN3, MouseDown3),
+ KEYC_MOUSE_STRING(MOUSEDOWN6, MouseDown6),
+ KEYC_MOUSE_STRING(MOUSEDOWN7, MouseDown7),
+ KEYC_MOUSE_STRING(MOUSEDOWN8, MouseDown8),
+ KEYC_MOUSE_STRING(MOUSEDOWN9, MouseDown9),
+ KEYC_MOUSE_STRING(MOUSEDOWN10, MouseDown10),
+ KEYC_MOUSE_STRING(MOUSEDOWN11, MouseDown11),
KEYC_MOUSE_STRING(MOUSEUP1, MouseUp1),
KEYC_MOUSE_STRING(MOUSEUP2, MouseUp2),
KEYC_MOUSE_STRING(MOUSEUP3, MouseUp3),
+ KEYC_MOUSE_STRING(MOUSEUP6, MouseUp6),
+ KEYC_MOUSE_STRING(MOUSEUP7, MouseUp7),
+ KEYC_MOUSE_STRING(MOUSEUP8, MouseUp8),
+ KEYC_MOUSE_STRING(MOUSEUP9, MouseUp9),
+ KEYC_MOUSE_STRING(MOUSEUP10, MouseUp10),
+ KEYC_MOUSE_STRING(MOUSEUP11, MouseUp11),
KEYC_MOUSE_STRING(MOUSEDRAG1, MouseDrag1),
KEYC_MOUSE_STRING(MOUSEDRAG2, MouseDrag2),
KEYC_MOUSE_STRING(MOUSEDRAG3, MouseDrag3),
+ KEYC_MOUSE_STRING(MOUSEDRAG6, MouseDrag6),
+ KEYC_MOUSE_STRING(MOUSEDRAG7, MouseDrag7),
+ KEYC_MOUSE_STRING(MOUSEDRAG8, MouseDrag8),
+ KEYC_MOUSE_STRING(MOUSEDRAG9, MouseDrag9),
+ KEYC_MOUSE_STRING(MOUSEDRAG10, MouseDrag10),
+ KEYC_MOUSE_STRING(MOUSEDRAG11, MouseDrag11),
KEYC_MOUSE_STRING(MOUSEDRAGEND1, MouseDragEnd1),
KEYC_MOUSE_STRING(MOUSEDRAGEND2, MouseDragEnd2),
KEYC_MOUSE_STRING(MOUSEDRAGEND3, MouseDragEnd3),
+ KEYC_MOUSE_STRING(MOUSEDRAGEND6, MouseDragEnd6),
+ KEYC_MOUSE_STRING(MOUSEDRAGEND7, MouseDragEnd7),
+ KEYC_MOUSE_STRING(MOUSEDRAGEND8, MouseDragEnd8),
+ KEYC_MOUSE_STRING(MOUSEDRAGEND9, MouseDragEnd9),
+ KEYC_MOUSE_STRING(MOUSEDRAGEND10, MouseDragEnd10),
+ KEYC_MOUSE_STRING(MOUSEDRAGEND11, MouseDragEnd11),
KEYC_MOUSE_STRING(WHEELUP, WheelUp),
KEYC_MOUSE_STRING(WHEELDOWN, WheelDown),
KEYC_MOUSE_STRING(SECONDCLICK1, SecondClick1),
KEYC_MOUSE_STRING(SECONDCLICK2, SecondClick2),
KEYC_MOUSE_STRING(SECONDCLICK3, SecondClick3),
+ KEYC_MOUSE_STRING(SECONDCLICK6, SecondClick6),
+ KEYC_MOUSE_STRING(SECONDCLICK7, SecondClick7),
+ KEYC_MOUSE_STRING(SECONDCLICK8, SecondClick8),
+ KEYC_MOUSE_STRING(SECONDCLICK9, SecondClick9),
+ KEYC_MOUSE_STRING(SECONDCLICK10, SecondClick10),
+ KEYC_MOUSE_STRING(SECONDCLICK11, SecondClick11),
KEYC_MOUSE_STRING(DOUBLECLICK1, DoubleClick1),
KEYC_MOUSE_STRING(DOUBLECLICK2, DoubleClick2),
KEYC_MOUSE_STRING(DOUBLECLICK3, DoubleClick3),
+ KEYC_MOUSE_STRING(DOUBLECLICK6, DoubleClick6),
+ KEYC_MOUSE_STRING(DOUBLECLICK7, DoubleClick7),
+ KEYC_MOUSE_STRING(DOUBLECLICK8, DoubleClick8),
+ KEYC_MOUSE_STRING(DOUBLECLICK9, DoubleClick9),
+ KEYC_MOUSE_STRING(DOUBLECLICK10, DoubleClick10),
+ KEYC_MOUSE_STRING(DOUBLECLICK11, DoubleClick11),
KEYC_MOUSE_STRING(TRIPLECLICK1, TripleClick1),
KEYC_MOUSE_STRING(TRIPLECLICK2, TripleClick2),
KEYC_MOUSE_STRING(TRIPLECLICK3, TripleClick3),
+ KEYC_MOUSE_STRING(TRIPLECLICK6, TripleClick6),
+ KEYC_MOUSE_STRING(TRIPLECLICK7, TripleClick7),
+ KEYC_MOUSE_STRING(TRIPLECLICK8, TripleClick8),
+ KEYC_MOUSE_STRING(TRIPLECLICK9, TripleClick9),
+ KEYC_MOUSE_STRING(TRIPLECLICK10, TripleClick10),
+ KEYC_MOUSE_STRING(TRIPLECLICK11, TripleClick11)
};
/* Find key string in table. */
diff --git a/menu.c b/menu.c
index aaa1287e..c17d10b1 100644
--- a/menu.c
+++ b/menu.c
@@ -235,7 +235,7 @@ menu_key_cb(struct client *c, void *data, struct key_event *event)
if (KEYC_IS_MOUSE(event->key)) {
if (md->flags & MENU_NOMOUSE) {
- if (MOUSE_BUTTONS(m->b) != 0)
+ if (MOUSE_BUTTONS(m->b) != MOUSE_BUTTON_1)
return (1);
return (0);
}
@@ -248,7 +248,7 @@ menu_key_cb(struct client *c, void *data, struct key_event *event)
return (1);
} else {
if (!MOUSE_RELEASE(m->b) &&
- MOUSE_WHEEL(m->b) == 0 &&
+ !MOUSE_WHEEL(m->b) &&
!MOUSE_DRAG(m->b))
return (1);
}
@@ -262,7 +262,7 @@ menu_key_cb(struct client *c, void *data, struct key_event *event)
if (MOUSE_RELEASE(m->b))
goto chosen;
} else {
- if (MOUSE_WHEEL(m->b) == 0 && !MOUSE_DRAG(m->b))
+ if (!MOUSE_WHEEL(m->b) && !MOUSE_DRAG(m->b))
goto chosen;
}
md->choice = m->y - (md->py + 1);
diff --git a/notify.c b/notify.c
index 9c55d0b8..baeb0600 100644
--- a/notify.c
+++ b/notify.c
@@ -34,18 +34,37 @@ struct notify_entry {
int pane;
};
+static struct cmdq_item *
+notify_insert_one_hook(struct cmdq_item *item, struct notify_entry *ne,
+ struct cmd_list *cmdlist, struct cmdq_state *state)
+{
+ struct cmdq_item *new_item;
+ char *s;
+
+ if (cmdlist == NULL)
+ return (item);
+ if (log_get_level() != 0) {
+ s = cmd_list_print(cmdlist, 0);
+ log_debug("%s: hook %s is: %s", __func__, ne->name, s);
+ free (s);
+ }
+ new_item = cmdq_get_command(cmdlist, state);
+ return (cmdq_insert_after(item, new_item));
+}
+
static void
notify_insert_hook(struct cmdq_item *item, struct notify_entry *ne)
{
struct cmd_find_state fs;
struct options *oo;
- struct cmdq_item *new_item;
- struct cmdq_state *new_state;
+ struct cmdq_state *state;
struct options_entry *o;
struct options_array_item *a;
struct cmd_list *cmdlist;
+ const char *value;
+ struct cmd_parse_result *pr;
- log_debug("%s: %s", __func__, ne->name);
+ log_debug("%s: inserting hook %s", __func__, ne->name);
cmd_find_clear_state(&fs, 0);
if (cmd_find_empty_state(&ne->fs) || !cmd_find_valid_state(&ne->fs))
@@ -66,23 +85,37 @@ notify_insert_hook(struct cmdq_item *item, struct notify_entry *ne)
oo = fs.wl->window->options;
o = options_get(oo, ne->name);
}
- if (o == NULL)
+ if (o == NULL) {
+ log_debug("%s: hook %s not found", __func__, ne->name);
return;
+ }
- new_state = cmdq_new_state(&fs, NULL, CMDQ_STATE_NOHOOKS);
- cmdq_add_formats(new_state, ne->formats);
-
- a = options_array_first(o);
- while (a != NULL) {
- cmdlist = options_array_item_value(a)->cmdlist;
- if (cmdlist != NULL) {
- new_item = cmdq_get_command(cmdlist, new_state);
- item = cmdq_insert_after(item, new_item);
+ state = cmdq_new_state(&fs, NULL, CMDQ_STATE_NOHOOKS);
+ cmdq_add_formats(state, ne->formats);
+
+ if (*ne->name == '@') {
+ value = options_get_string(oo, ne->name);
+ pr = cmd_parse_from_string(value, NULL);
+ switch (pr->status) {
+ case CMD_PARSE_ERROR:
+ log_debug("%s: can't parse hook %s: %s", __func__,
+ ne->name, pr->error);
+ free(pr->error);
+ break;
+ case CMD_PARSE_SUCCESS:
+ notify_insert_one_hook(item, ne, pr->cmdlist, state);
+ break;
+ }
+ } else {
+ a = options_array_first(o);
+ while (a != NULL) {
+ cmdlist = options_array_item_value(a)->cmdlist;
+ item = notify_insert_one_hook(item, ne, cmdlist, state);
+ a = options_array_next(a);
}
- a = options_array_next(a);
}
- cmdq_free_state(new_state);
+ cmdq_free_state(state);
}
static enum cmd_retval
diff --git a/options-table.c b/options-table.c
index 94f8701e..17be7ec4 100644
--- a/options-table.c
+++ b/options-table.c
@@ -277,6 +277,7 @@ const struct options_table_entry options_table[] = {
.minimum = 0,
.maximum = INT_MAX,
.default_num = 500,
+ .unit = "milliseconds",
.text = "Time to wait before assuming a key is Escape."
},
@@ -301,7 +302,7 @@ const struct options_table_entry options_table[] = {
.choices = options_table_extended_keys_list,
.default_num = 0,
.text = "Whether to request extended key sequences from terminals "
- "that support it."
+ "that support it."
},
{ .name = "focus-events",
@@ -800,6 +801,14 @@ const struct options_table_entry options_table[] = {
"linked to ('off')."
},
+ { .name = "allow-passthrough",
+ .type = OPTIONS_TABLE_FLAG,
+ .scope = OPTIONS_TABLE_WINDOW|OPTIONS_TABLE_PANE,
+ .default_num = 0,
+ .text = "Whether applications are allowed to use the escape sequence "
+ "to bypass tmux."
+ },
+
{ .name = "allow-rename",
.type = OPTIONS_TABLE_FLAG,
.scope = OPTIONS_TABLE_WINDOW|OPTIONS_TABLE_PANE,
@@ -873,6 +882,13 @@ const struct options_table_entry options_table[] = {
.text = "Style of the marked line in copy mode."
},
+ { .name = "fill-character",
+ .type = OPTIONS_TABLE_STRING,
+ .scope = OPTIONS_TABLE_WINDOW,
+ .default_str = "",
+ .text = "Character used to fill unused parts of window."
+ },
+
{ .name = "main-pane-height",
.type = OPTIONS_TABLE_STRING,
.scope = OPTIONS_TABLE_WINDOW,
@@ -988,7 +1004,7 @@ const struct options_table_entry options_table[] = {
.choices = options_table_pane_border_lines_list,
.default_num = PANE_LINES_SINGLE,
.text = "Type of characters used to draw pane border lines. Some of "
- "these are only supported on terminals with UTF-8 support."
+ "these are only supported on terminals with UTF-8 support."
},
{ .name = "pane-border-status",
@@ -1040,7 +1056,7 @@ const struct options_table_entry options_table[] = {
.choices = options_table_popup_border_lines_list,
.default_num = BOX_LINES_SINGLE,
.text = "Type of characters used to draw popup border lines. Some of "
- "these are only supported on terminals with UTF-8 support."
+ "these are only supported on terminals with UTF-8 support."
},
{ .name = "remain-on-exit",
@@ -1052,6 +1068,27 @@ const struct options_table_entry options_table[] = {
"killed ('off' or 'failed') when the program inside exits."
},
+ { .name = "remain-on-exit-format",
+ .type = OPTIONS_TABLE_STRING,
+ .scope = OPTIONS_TABLE_WINDOW|OPTIONS_TABLE_PANE,
+ .default_str = "Pane is dead ("
+ "#{?#{!=:#{pane_dead_status},},"
+ "status #{pane_dead_status},}"
+ "#{?#{!=:#{pane_dead_signal},},"
+ "signal #{pane_dead_signal},}, "
+ "#{t:pane_dead_time})",
+ .text = "Message shown after the program in a pane has exited, if "
+ "remain-on-exit is enabled."
+ },
+
+ { .name = "scroll-on-clear",
+ .type = OPTIONS_TABLE_FLAG,
+ .scope = OPTIONS_TABLE_WINDOW|OPTIONS_TABLE_PANE,
+ .default_num = 1,
+ .text = "Whether the contents of the screen should be scrolled into"
+ "history when clearing the whole screen."
+ },
+
{ .name = "synchronize-panes",
.type = OPTIONS_TABLE_FLAG,
.scope = OPTIONS_TABLE_WINDOW|OPTIONS_TABLE_PANE,
@@ -1170,7 +1207,7 @@ const struct options_table_entry options_table[] = {
.scope = OPTIONS_TABLE_WINDOW,
.default_num = 1,
.text = "Whether xterm-style function key sequences should be sent. "
- "This option is no longer used."
+ "This option is no longer used."
},
/* Hook options. */
@@ -1218,8 +1255,8 @@ const struct options_table_entry options_table[] = {
OPTIONS_TABLE_HOOK("client-active", ""),
OPTIONS_TABLE_HOOK("client-attached", ""),
OPTIONS_TABLE_HOOK("client-detached", ""),
- OPTIONS_TABLE_HOOK("client-focus-in", ""),
- OPTIONS_TABLE_HOOK("client-focus-out", ""),
+ OPTIONS_TABLE_HOOK("client-focus-in", ""),
+ OPTIONS_TABLE_HOOK("client-focus-out", ""),
OPTIONS_TABLE_HOOK("client-resized", ""),
OPTIONS_TABLE_HOOK("client-session-changed", ""),
OPTIONS_TABLE_PANE_HOOK("pane-died", ""),
@@ -1237,6 +1274,7 @@ const struct options_table_entry options_table[] = {
OPTIONS_TABLE_HOOK("window-linked", ""),
OPTIONS_TABLE_WINDOW_HOOK("window-pane-changed", ""),
OPTIONS_TABLE_WINDOW_HOOK("window-renamed", ""),
+ OPTIONS_TABLE_WINDOW_HOOK("window-resized", ""),
OPTIONS_TABLE_HOOK("window-unlinked", ""),
{ .name = NULL }
diff --git a/options.c b/options.c
index 865ab01f..f9cf2afd 100644
--- a/options.c
+++ b/options.c
@@ -1108,6 +1108,8 @@ options_push_changes(const char *name)
struct window_pane *wp;
int c;
+ log_debug("%s: %s", __func__, name);
+
if (strcmp(name, "automatic-rename") == 0) {
RB_FOREACH(w, windows, &windows) {
if (w->active == NULL)
@@ -1130,6 +1132,10 @@ options_push_changes(const char *name)
&wp->screen->default_mode);
}
}
+ if (strcmp(name, "fill-character") == 0) {
+ RB_FOREACH(w, windows, &windows)
+ window_set_fill_character(w);
+ }
if (strcmp(name, "key-table") == 0) {
TAILQ_FOREACH(loop, &clients, entry)
server_client_set_key_table(loop, NULL);
diff --git a/osdep-netbsd.c b/osdep-netbsd.c
index b473e017..6003c035 100644
--- a/osdep-netbsd.c
+++ b/osdep-netbsd.c
@@ -35,9 +35,6 @@
((p)->p_stat == SSTOP || (p)->p_stat == SZOMB)
struct kinfo_proc2 *cmp_procs(struct kinfo_proc2 *, struct kinfo_proc2 *);
-char *osdep_get_name(int, char *);
-char *osdep_get_cwd(int);
-struct event_base *osdep_event_init(void);
struct kinfo_proc2 *
cmp_procs(struct kinfo_proc2 *p1, struct kinfo_proc2 *p2)
diff --git a/osdep-openbsd.c b/osdep-openbsd.c
index 54464753..b4c8fc56 100644
--- a/osdep-openbsd.c
+++ b/osdep-openbsd.c
@@ -16,7 +16,6 @@
* OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
-#include <sys/param.h> /* MAXCOMLEN */
#include <sys/types.h>
#include <sys/signal.h>
#include <sys/proc.h>
@@ -142,7 +141,7 @@ char *
osdep_get_cwd(int fd)
{
int name[] = { CTL_KERN, KERN_PROC_CWD, 0 };
- static char path[MAXPATHLEN];
+ static char path[PATH_MAX];
size_t pathlen = sizeof path;
if ((name[2] = tcgetpgrp(fd)) == -1)
diff --git a/popup.c b/popup.c
index 1048af60..2e57153d 100644
--- a/popup.c
+++ b/popup.c
@@ -508,7 +508,7 @@ popup_key_cb(struct client *c, void *data, struct key_event *event)
m->x > pd->px + pd->sx - 1 ||
m->y < pd->py ||
m->y > pd->py + pd->sy - 1) {
- if (MOUSE_BUTTONS(m->b) == 2)
+ if (MOUSE_BUTTONS(m->b) == MOUSE_BUTTON_3)
goto menu;
return (0);
}
@@ -523,16 +523,16 @@ popup_key_cb(struct client *c, void *data, struct key_event *event)
border = BOTTOM;
}
if ((m->b & MOUSE_MASK_MODIFIERS) == 0 &&
- MOUSE_BUTTONS(m->b) == 2 &&
+ MOUSE_BUTTONS(m->b) == MOUSE_BUTTON_3 &&
(border == LEFT || border == TOP))
goto menu;
if (((m->b & MOUSE_MASK_MODIFIERS) == MOUSE_MASK_META) ||
border != NONE) {
if (!MOUSE_DRAG(m->b))
goto out;
- if (MOUSE_BUTTONS(m->lb) == 0)
+ if (MOUSE_BUTTONS(m->lb) == MOUSE_BUTTON_1)
pd->dragging = MOVE;
- else if (MOUSE_BUTTONS(m->lb) == 2)
+ else if (MOUSE_BUTTONS(m->lb) == MOUSE_BUTTON_3)
pd->dragging = SIZE;
pd->dx = m->lx - pd->px;
pd->dy = m->ly - pd->py;
@@ -689,7 +689,7 @@ popup_display(int flags, enum box_lines lines, struct cmdq_item *item, u_int px,
}
pd->border_cell.attr = 0;
- screen_init(&pd->s, sx - 2, sy - 2, 0);
+ screen_init(&pd->s, jx, jy, 0);
colour_palette_init(&pd->palette);
colour_palette_from_option(&pd->palette, global_w_options);
diff --git a/proc.c b/proc.c
index 958a9483..a9b1473e 100644
--- a/proc.c
+++ b/proc.c
@@ -56,6 +56,7 @@ struct tmuxpeer {
struct imsgbuf ibuf;
struct event event;
+ uid_t uid;
int flags;
#define PEER_BAD 0x1
@@ -308,6 +309,7 @@ proc_add_peer(struct tmuxproc *tp, int fd,
void (*dispatchcb)(struct imsg *, void *), void *arg)
{
struct tmuxpeer *peer;
+ gid_t gid;
peer = xcalloc(1, sizeof *peer);
peer->parent = tp;
@@ -318,6 +320,9 @@ proc_add_peer(struct tmuxproc *tp, int fd,
imsg_init(&peer->ibuf, fd);
event_set(&peer->event, fd, EV_READ, proc_event_cb, peer);
+ if (getpeereid(fd, &peer->uid, &gid) != 0)
+ peer->uid = (uid_t)-1;
+
log_debug("add peer %p: %d (%p)", peer, fd, arg);
TAILQ_INSERT_TAIL(&tp->peers, peer, entry);
@@ -373,3 +378,9 @@ proc_fork_and_daemon(int *fd)
return (pid);
}
}
+
+uid_t
+proc_get_peer_uid(struct tmuxpeer *peer)
+{
+ return (peer->uid);
+}
diff --git a/resize.c b/resize.c
index 18a02adb..457fee0a 100644
--- a/resize.c
+++ b/resize.c
@@ -61,6 +61,7 @@ resize_window(struct window *w, u_int sx, u_int sy, int xpixel, int ypixel)
tty_update_window_offset(w);
server_redraw_window(w);
notify_window("window-layout-changed", w);
+ notify_window("window-resized", w);
w->flags &= ~WINDOW_RESIZE;
}
diff --git a/screen-redraw.c b/screen-redraw.c
index 8dd75f40..c4906ab8 100644
--- a/screen-redraw.c
+++ b/screen-redraw.c
@@ -47,11 +47,16 @@ enum screen_redraw_border_type {
/* Get cell border character. */
static void
-screen_redraw_border_set(struct window_pane *wp, enum pane_lines pane_lines,
- int cell_type, struct grid_cell *gc)
+screen_redraw_border_set(struct window *w, struct window_pane *wp,
+ enum pane_lines pane_lines, int cell_type, struct grid_cell *gc)
{
u_int idx;
+ if (cell_type == CELL_OUTSIDE && w->fill_character != NULL) {
+ utf8_copy(&gc->data, &w->fill_character[0]);
+ return;
+ }
+
switch (pane_lines) {
case PANE_LINES_NUMBER:
if (cell_type == CELL_OUTSIDE) {
@@ -409,7 +414,7 @@ screen_redraw_make_pane_status(struct client *c, struct window_pane *wp,
else
py = wp->yoff + wp->sy;
cell_type = screen_redraw_type_of_cell(c, px, py, pane_status);
- screen_redraw_border_set(wp, pane_lines, cell_type, &gc);
+ screen_redraw_border_set(w, wp, pane_lines, cell_type, &gc);
screen_write_cell(&ctx, &gc);
}
gc.attr &= ~GRID_ATTR_CHARSET;
@@ -690,7 +695,7 @@ screen_redraw_draw_borders_cell(struct screen_redraw_ctx *ctx, u_int i, u_int j)
screen_redraw_check_is(x, y, pane_status, marked_pane.wp))
gc.attr ^= GRID_ATTR_REVERSE;
}
- screen_redraw_border_set(wp, ctx->pane_lines, cell_type, &gc);
+ screen_redraw_border_set(w, wp, ctx->pane_lines, cell_type, &gc);
if (cell_type == CELL_TOPBOTTOM &&
(c->flags & CLIENT_UTF8) &&
@@ -727,8 +732,10 @@ screen_redraw_draw_borders_cell(struct screen_redraw_ctx *ctx, u_int i, u_int j)
border == SCREEN_REDRAW_BORDER_RIGHT) ||
(cell_type == CELL_RIGHTJOIN &&
border == SCREEN_REDRAW_BORDER_LEFT)))) &&
- screen_redraw_check_is(x, y, pane_status, active))
+ screen_redraw_check_is(x, y, pane_status, active)) {
+ gc.attr |= GRID_ATTR_CHARSET;
utf8_set(&gc.data, BORDER_MARKERS[border]);
+ }
}
tty_cell(tty, &gc, &grid_default_cell, NULL);
diff --git a/screen-write.c b/screen-write.c
index 0d70f668..6b6a750e 100644
--- a/screen-write.c
+++ b/screen-write.c
@@ -1427,7 +1427,11 @@ screen_write_clearendofscreen(struct screen_write_ctx *ctx, u_int bg)
ttyctx.bg = bg;
/* Scroll into history if it is enabled and clearing entire screen. */
- if (s->cx == 0 && s->cy == 0 && (gd->flags & GRID_HISTORY))
+ if (s->cx == 0 &&
+ s->cy == 0 &&
+ (gd->flags & GRID_HISTORY) &&
+ ctx->wp != NULL &&
+ options_get_number(ctx->wp->options, "scroll-on-clear"))
grid_view_clear_history(gd, bg);
else {
if (s->cx <= sx - 1)
@@ -1475,7 +1479,9 @@ screen_write_clearscreen(struct screen_write_ctx *ctx, u_int bg)
ttyctx.bg = bg;
/* Scroll into history if it is enabled. */
- if (s->grid->flags & GRID_HISTORY)
+ if ((s->grid->flags & GRID_HISTORY) &&
+ ctx->wp != NULL &&
+ options_get_number(ctx->wp->options, "scroll-on-clear"))
grid_view_clear_history(s->grid, bg);
else
grid_view_clear(s->grid, 0, 0, sx, sy, bg);
diff --git a/screen.c b/screen.c
index 7046e098..62cf4765 100644
--- a/screen.c
+++ b/screen.c
@@ -103,7 +103,7 @@ 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|(s->mode & MODE_CRLF);
if (options_get_number(global_options, "extended-keys") == 2)
s->mode |= MODE_KEXTENDED;
diff --git a/server-client.c b/server-client.c
index 06154be7..2350a982 100644
--- a/server-client.c
+++ b/server-client.c
@@ -40,6 +40,7 @@ static void server_client_check_exit(struct client *);
static void server_client_check_redraw(struct client *);
static void server_client_check_modes(struct client *);
static void server_client_set_title(struct client *);
+static void server_client_set_path(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 *);
@@ -422,6 +423,7 @@ server_client_lost(struct client *c)
if (c->flags & CLIENT_TERMINAL)
tty_free(&c->tty);
free(c->ttyname);
+ free(c->clipboard_panes);
free(c->term_name);
free(c->term_type);
@@ -593,11 +595,11 @@ server_client_check_mouse(struct client *c, struct key_event *event)
log_debug("double-click at %u,%u", x, y);
} else if ((m->sgr_type != ' ' &&
MOUSE_DRAG(m->sgr_b) &&
- MOUSE_BUTTONS(m->sgr_b) == 3) ||
+ MOUSE_RELEASE(m->sgr_b)) ||
(m->sgr_type == ' ' &&
MOUSE_DRAG(m->b) &&
- MOUSE_BUTTONS(m->b) == 3 &&
- MOUSE_BUTTONS(m->lb) == 3)) {
+ MOUSE_RELEASE(m->b) &&
+ MOUSE_RELEASE(m->lb))) {
type = MOVE;
x = m->x, y = m->y, b = 0;
log_debug("move at %u,%u", x, y);
@@ -750,7 +752,7 @@ have_event:
m->wp = -1;
/* Stop dragging if needed. */
- if (type != DRAG && type != WHEEL && c->tty.mouse_drag_flag) {
+ if (type != DRAG && type != WHEEL && c->tty.mouse_drag_flag != 0) {
if (c->tty.mouse_drag_release != NULL)
c->tty.mouse_drag_release(c, m);
@@ -761,8 +763,8 @@ have_event:
* End a mouse drag by passing a MouseDragEnd key corresponding
* to the button that started the drag.
*/
- switch (c->tty.mouse_drag_flag) {
- case 1:
+ switch (c->tty.mouse_drag_flag - 1) {
+ case MOUSE_BUTTON_1:
if (where == PANE)
key = KEYC_MOUSEDRAGEND1_PANE;
if (where == STATUS)
@@ -776,7 +778,7 @@ have_event:
if (where == BORDER)
key = KEYC_MOUSEDRAGEND1_BORDER;
break;
- case 2:
+ case MOUSE_BUTTON_2:
if (where == PANE)
key = KEYC_MOUSEDRAGEND2_PANE;
if (where == STATUS)
@@ -790,7 +792,7 @@ have_event:
if (where == BORDER)
key = KEYC_MOUSEDRAGEND2_BORDER;
break;
- case 3:
+ case MOUSE_BUTTON_3:
if (where == PANE)
key = KEYC_MOUSEDRAGEND3_PANE;
if (where == STATUS)
@@ -804,6 +806,90 @@ have_event:
if (where == BORDER)
key = KEYC_MOUSEDRAGEND3_BORDER;
break;
+ case MOUSE_BUTTON_6:
+ if (where == PANE)
+ key = KEYC_MOUSEDRAGEND6_PANE;
+ if (where == STATUS)
+ key = KEYC_MOUSEDRAGEND6_STATUS;
+ if (where == STATUS_LEFT)
+ key = KEYC_MOUSEDRAGEND6_STATUS_LEFT;
+ if (where == STATUS_RIGHT)
+ key = KEYC_MOUSEDRAGEND6_STATUS_RIGHT;
+ if (where == STATUS_DEFAULT)
+ key = KEYC_MOUSEDRAGEND6_STATUS_DEFAULT;
+ if (where == BORDER)
+ key = KEYC_MOUSEDRAGEND6_BORDER;
+ break;
+ case MOUSE_BUTTON_7:
+ if (where == PANE)
+ key = KEYC_MOUSEDRAGEND7_PANE;
+ if (where == STATUS)
+ key = KEYC_MOUSEDRAGEND7_STATUS;
+ if (where == STATUS_LEFT)
+ key = KEYC_MOUSEDRAGEND7_STATUS_LEFT;
+ if (where == STATUS_RIGHT)
+ key = KEYC_MOUSEDRAGEND7_STATUS_RIGHT;
+ if (where == STATUS_DEFAULT)
+ key = KEYC_MOUSEDRAGEND7_STATUS_DEFAULT;
+ if (where == BORDER)
+ key = KEYC_MOUSEDRAGEND7_BORDER;
+ break;
+ case MOUSE_BUTTON_8:
+ if (where == PANE)
+ key = KEYC_MOUSEDRAGEND8_PANE;
+ if (where == STATUS)
+ key = KEYC_MOUSEDRAGEND8_STATUS;
+ if (where == STATUS_LEFT)
+ key = KEYC_MOUSEDRAGEND8_STATUS_LEFT;
+ if (where == STATUS_RIGHT)
+ key = KEYC_MOUSEDRAGEND8_STATUS_RIGHT;
+ if (where == STATUS_DEFAULT)
+ key = KEYC_MOUSEDRAGEND8_STATUS_DEFAULT;
+ if (where == BORDER)
+ key = KEYC_MOUSEDRAGEND8_BORDER;
+ break;
+ case MOUSE_BUTTON_9:
+ if (where == PANE)
+ key = KEYC_MOUSEDRAGEND9_PANE;
+ if (where == STATUS)
+ key = KEYC_MOUSEDRAGEND9_STATUS;
+ if (where == STATUS_LEFT)
+ key = KEYC_MOUSEDRAGEND9_STATUS_LEFT;
+ if (where == STATUS_RIGHT)
+ key = KEYC_MOUSEDRAGEND9_STATUS_RIGHT;
+ if (where == STATUS_DEFAULT)
+ key = KEYC_MOUSEDRAGEND9_STATUS_DEFAULT;
+ if (where == BORDER)
+ key = KEYC_MOUSEDRAGEND9_BORDER;
+ break;
+ case MOUSE_BUTTON_10:
+ if (where == PANE)
+ key = KEYC_MOUSEDRAGEND10_PANE;
+ if (where == STATUS)
+ key = KEYC_MOUSEDRAGEND10_STATUS;
+ if (where == STATUS_LEFT)
+ key = KEYC_MOUSEDRAGEND10_STATUS_LEFT;
+ if (where == STATUS_RIGHT)
+ key = KEYC_MOUSEDRAGEND10_STATUS_RIGHT;
+ if (where == STATUS_DEFAULT)
+ key = KEYC_MOUSEDRAGEND10_STATUS_DEFAULT;
+ if (where == BORDER)
+ key = KEYC_MOUSEDRAGEND10_BORDER;
+ break;
+ case MOUSE_BUTTON_11:
+ if (where == PANE)
+ key = KEYC_MOUSEDRAGEND11_PANE;
+ if (where == STATUS)
+ key = KEYC_MOUSEDRAGEND11_STATUS;
+ if (where == STATUS_LEFT)
+ key = KEYC_MOUSEDRAGEND11_STATUS_LEFT;
+ if (where == STATUS_RIGHT)
+ key = KEYC_MOUSEDRAGEND11_STATUS_RIGHT;
+ if (where == STATUS_DEFAULT)
+ key = KEYC_MOUSEDRAGEND11_STATUS_DEFAULT;
+ if (where == BORDER)
+ key = KEYC_MOUSEDRAGEND11_BORDER;
+ break;
default:
key = KEYC_MOUSE;
break;
@@ -836,7 +922,7 @@ have_event:
key = KEYC_DRAGGING;
else {
switch (MOUSE_BUTTONS(b)) {
- case 0:
+ case MOUSE_BUTTON_1:
if (where == PANE)
key = KEYC_MOUSEDRAG1_PANE;
if (where == STATUS)
@@ -850,7 +936,7 @@ have_event:
if (where == BORDER)
key = KEYC_MOUSEDRAG1_BORDER;
break;
- case 1:
+ case MOUSE_BUTTON_2:
if (where == PANE)
key = KEYC_MOUSEDRAG2_PANE;
if (where == STATUS)
@@ -864,7 +950,7 @@ have_event:
if (where == BORDER)
key = KEYC_MOUSEDRAG2_BORDER;
break;
- case 2:
+ case MOUSE_BUTTON_3:
if (where == PANE)
key = KEYC_MOUSEDRAG3_PANE;
if (where == STATUS)
@@ -878,6 +964,90 @@ have_event:
if (where == BORDER)
key = KEYC_MOUSEDRAG3_BORDER;
break;
+ case MOUSE_BUTTON_6:
+ if (where == PANE)
+ key = KEYC_MOUSEDRAG6_PANE;
+ if (where == STATUS)
+ key = KEYC_MOUSEDRAG6_STATUS;
+ if (where == STATUS_LEFT)
+ key = KEYC_MOUSEDRAG6_STATUS_LEFT;
+ if (where == STATUS_RIGHT)
+ key = KEYC_MOUSEDRAG6_STATUS_RIGHT;
+ if (where == STATUS_DEFAULT)
+ key = KEYC_MOUSEDRAG6_STATUS_DEFAULT;
+ if (where == BORDER)
+ key = KEYC_MOUSEDRAG6_BORDER;
+ break;
+ case MOUSE_BUTTON_7:
+ if (where == PANE)
+ key = KEYC_MOUSEDRAG7_PANE;
+ if (where == STATUS)
+ key = KEYC_MOUSEDRAG7_STATUS;
+ if (where == STATUS_LEFT)
+ key = KEYC_MOUSEDRAG7_STATUS_LEFT;
+ if (where == STATUS_RIGHT)
+ key = KEYC_MOUSEDRAG7_STATUS_RIGHT;
+ if (where == STATUS_DEFAULT)
+ key = KEYC_MOUSEDRAG7_STATUS_DEFAULT;
+ if (where == BORDER)
+ key = KEYC_MOUSEDRAG7_BORDER;
+ break;
+ case MOUSE_BUTTON_8:
+ if (where == PANE)
+ key = KEYC_MOUSEDRAG8_PANE;
+ if (where == STATUS)
+ key = KEYC_MOUSEDRAG8_STATUS;
+ if (where == STATUS_LEFT)
+ key = KEYC_MOUSEDRAG8_STATUS_LEFT;
+ if (where == STATUS_RIGHT)
+ key = KEYC_MOUSEDRAG8_STATUS_RIGHT;
+ if (where == STATUS_DEFAULT)
+ key = KEYC_MOUSEDRAG8_STATUS_DEFAULT;
+ if (where == BORDER)
+ key = KEYC_MOUSEDRAG8_BORDER;
+ break;
+ case MOUSE_BUTTON_9:
+ if (where == PANE)
+ key = KEYC_MOUSEDRAG9_PANE;
+ if (where == STATUS)
+ key = KEYC_MOUSEDRAG9_STATUS;
+ if (where == STATUS_LEFT)
+ key = KEYC_MOUSEDRAG9_STATUS_LEFT;
+ if (where == STATUS_RIGHT)
+ key = KEYC_MOUSEDRAG9_STATUS_RIGHT;
+ if (where == STATUS_DEFAULT)
+ key = KEYC_MOUSEDRAG9_STATUS_DEFAULT;
+ if (where == BORDER)
+ key = KEYC_MOUSEDRAG9_BORDER;
+ break;
+ case MOUSE_BUTTON_10:
+ if (where == PANE)
+ key = KEYC_MOUSEDRAG10_PANE;
+ if (where == STATUS)
+ key = KEYC_MOUSEDRAG10_STATUS;
+ if (where == STATUS_LEFT)
+ key = KEYC_MOUSEDRAG10_STATUS_LEFT;
+ if (where == STATUS_RIGHT)
+ key = KEYC_MOUSEDRAG10_STATUS_RIGHT;
+ if (where == STATUS_DEFAULT)
+ key = KEYC_MOUSEDRAG10_STATUS_DEFAULT;
+ if (where == BORDER)
+ key = KEYC_MOUSEDRAG10_BORDER;
+ break;
+ case MOUSE_BUTTON_11:
+ if (where == PANE)
+ key = KEYC_MOUSEDRAG11_PANE;
+ if (where == STATUS)
+ key = KEYC_MOUSEDRAG11_STATUS;
+ if (where == STATUS_LEFT)
+ key = KEYC_MOUSEDRAG11_STATUS_LEFT;
+ if (where == STATUS_RIGHT)
+ key = KEYC_MOUSEDRAG11_STATUS_RIGHT;
+ if (where == STATUS_DEFAULT)
+ key = KEYC_MOUSEDRAG11_STATUS_DEFAULT;
+ if (where == BORDER)
+ key = KEYC_MOUSEDRAG11_BORDER;
+ break;
}
}
@@ -918,7 +1088,7 @@ have_event:
break;
case UP:
switch (MOUSE_BUTTONS(b)) {
- case 0:
+ case MOUSE_BUTTON_1:
if (where == PANE)
key = KEYC_MOUSEUP1_PANE;
if (where == STATUS)
@@ -932,7 +1102,7 @@ have_event:
if (where == BORDER)
key = KEYC_MOUSEUP1_BORDER;
break;
- case 1:
+ case MOUSE_BUTTON_2:
if (where == PANE)
key = KEYC_MOUSEUP2_PANE;
if (where == STATUS)
@@ -946,7 +1116,7 @@ have_event:
if (where == BORDER)
key = KEYC_MOUSEUP2_BORDER;
break;
- case 2:
+ case MOUSE_BUTTON_3:
if (where == PANE)
key = KEYC_MOUSEUP3_PANE;
if (where == STATUS)
@@ -960,11 +1130,95 @@ have_event:
if (where == BORDER)
key = KEYC_MOUSEUP3_BORDER;
break;
+ case MOUSE_BUTTON_6:
+ if (where == PANE)
+ key = KEYC_MOUSEUP6_PANE;
+ if (where == STATUS)
+ key = KEYC_MOUSEUP6_STATUS;
+ if (where == STATUS_LEFT)
+ key = KEYC_MOUSEUP6_STATUS_LEFT;
+ if (where == STATUS_RIGHT)
+ key = KEYC_MOUSEUP6_STATUS_RIGHT;
+ if (where == STATUS_DEFAULT)
+ key = KEYC_MOUSEUP6_STATUS_DEFAULT;
+ if (where == BORDER)
+ key = KEYC_MOUSEUP6_BORDER;
+ break;
+ case MOUSE_BUTTON_7:
+ if (where == PANE)
+ key = KEYC_MOUSEUP7_PANE;
+ if (where == STATUS)
+ key = KEYC_MOUSEUP7_STATUS;
+ if (where == STATUS_LEFT)
+ key = KEYC_MOUSEUP7_STATUS_LEFT;
+ if (where == STATUS_RIGHT)
+ key = KEYC_MOUSEUP7_STATUS_RIGHT;
+ if (where == STATUS_DEFAULT)
+ key = KEYC_MOUSEUP7_STATUS_DEFAULT;
+ if (where == BORDER)
+ key = KEYC_MOUSEUP7_BORDER;
+ break;
+ case MOUSE_BUTTON_8:
+ if (where == PANE)
+ key = KEYC_MOUSEUP8_PANE;
+ if (where == STATUS)
+ key = KEYC_MOUSEUP8_STATUS;
+ if (where == STATUS_LEFT)
+ key = KEYC_MOUSEUP8_STATUS_LEFT;
+ if (where == STATUS_RIGHT)
+ key = KEYC_MOUSEUP8_STATUS_RIGHT;
+ if (where == STATUS_DEFAULT)
+ key = KEYC_MOUSEUP8_STATUS_DEFAULT;
+ if (where == BORDER)
+ key = KEYC_MOUSEUP8_BORDER;
+ break;
+ case MOUSE_BUTTON_9:
+ if (where == PANE)
+ key = KEYC_MOUSEUP9_PANE;
+ if (where == STATUS)
+ key = KEYC_MOUSEUP9_STATUS;
+ if (where == STATUS_LEFT)
+ key = KEYC_MOUSEUP9_STATUS_LEFT;
+ if (where == STATUS_RIGHT)
+ key = KEYC_MOUSEUP9_STATUS_RIGHT;
+ if (where == STATUS_DEFAULT)
+ key = KEYC_MOUSEUP9_STATUS_DEFAULT;
+ if (where == BORDER)
+ key = KEYC_MOUSEUP9_BORDER;
+ break;
+ case MOUSE_BUTTON_10:
+ if (where == PANE)
+ key = KEYC_MOUSEUP1_PANE;
+ if (where == STATUS)
+ key = KEYC_MOUSEUP1_STATUS;
+ if (where == STATUS_LEFT)
+ key = KEYC_MOUSEUP1_STATUS_LEFT;
+ if (where == STATUS_RIGHT)
+ key = KEYC_MOUSEUP1_STATUS_RIGHT;
+ if (where == STATUS_DEFAULT)
+ key = KEYC_MOUSEUP1_STATUS_DEFAULT;
+ if (where == BORDER)
+ key = KEYC_MOUSEUP1_BORDER;
+ break;
+ case MOUSE_BUTTON_11:
+ if (where == PANE)
+ key = KEYC_MOUSEUP11_PANE;
+ if (where == STATUS)
+ key = KEYC_MOUSEUP11_STATUS;
+ if (where == STATUS_LEFT)
+ key = KEYC_MOUSEUP11_STATUS_LEFT;
+ if (where == STATUS_RIGHT)
+ key = KEYC_MOUSEUP11_STATUS_RIGHT;
+ if (where == STATUS_DEFAULT)
+ key = KEYC_MOUSEUP11_STATUS_DEFAULT;
+ if (where == BORDER)
+ key = KEYC_MOUSEUP11_BORDER;
+ break;
}
break;
case DOWN:
switch (MOUSE_BUTTONS(b)) {
- case 0:
+ case MOUSE_BUTTON_1:
if (where == PANE)
key = KEYC_MOUSEDOWN1_PANE;
if (where == STATUS)
@@ -978,7 +1232,7 @@ have_event:
if (where == BORDER)
key = KEYC_MOUSEDOWN1_BORDER;
break;
- case 1:
+ case MOUSE_BUTTON_2:
if (where == PANE)
key = KEYC_MOUSEDOWN2_PANE;
if (where == STATUS)
@@ -992,7 +1246,7 @@ have_event:
if (where == BORDER)
key = KEYC_MOUSEDOWN2_BORDER;
break;
- case 2:
+ case MOUSE_BUTTON_3:
if (where == PANE)
key = KEYC_MOUSEDOWN3_PANE;
if (where == STATUS)
@@ -1006,11 +1260,95 @@ have_event:
if (where == BORDER)
key = KEYC_MOUSEDOWN3_BORDER;
break;
+ case MOUSE_BUTTON_6:
+ if (where == PANE)
+ key = KEYC_MOUSEDOWN6_PANE;
+ if (where == STATUS)
+ key = KEYC_MOUSEDOWN6_STATUS;
+ if (where == STATUS_LEFT)
+ key = KEYC_MOUSEDOWN6_STATUS_LEFT;
+ if (where == STATUS_RIGHT)
+ key = KEYC_MOUSEDOWN6_STATUS_RIGHT;
+ if (where == STATUS_DEFAULT)
+ key = KEYC_MOUSEDOWN6_STATUS_DEFAULT;
+ if (where == BORDER)
+ key = KEYC_MOUSEDOWN6_BORDER;
+ break;
+ case MOUSE_BUTTON_7:
+ if (where == PANE)
+ key = KEYC_MOUSEDOWN7_PANE;
+ if (where == STATUS)
+ key = KEYC_MOUSEDOWN7_STATUS;
+ if (where == STATUS_LEFT)
+ key = KEYC_MOUSEDOWN7_STATUS_LEFT;
+ if (where == STATUS_RIGHT)
+ key = KEYC_MOUSEDOWN7_STATUS_RIGHT;
+ if (where == STATUS_DEFAULT)
+ key = KEYC_MOUSEDOWN7_STATUS_DEFAULT;
+ if (where == BORDER)
+ key = KEYC_MOUSEDOWN7_BORDER;
+ break;
+ case MOUSE_BUTTON_8:
+ if (where == PANE)
+ key = KEYC_MOUSEDOWN8_PANE;
+ if (where == STATUS)
+ key = KEYC_MOUSEDOWN8_STATUS;
+ if (where == STATUS_LEFT)
+ key = KEYC_MOUSEDOWN8_STATUS_LEFT;
+ if (where == STATUS_RIGHT)
+ key = KEYC_MOUSEDOWN8_STATUS_RIGHT;
+ if (where == STATUS_DEFAULT)
+ key = KEYC_MOUSEDOWN8_STATUS_DEFAULT;
+ if (where == BORDER)
+ key = KEYC_MOUSEDOWN8_BORDER;
+ break;
+ case MOUSE_BUTTON_9:
+ if (where == PANE)
+ key = KEYC_MOUSEDOWN9_PANE;
+ if (where == STATUS)
+ key = KEYC_MOUSEDOWN9_STATUS;
+ if (where == STATUS_LEFT)
+ key = KEYC_MOUSEDOWN9_STATUS_LEFT;
+ if (where == STATUS_RIGHT)
+ key = KEYC_MOUSEDOWN9_STATUS_RIGHT;
+ if (where == STATUS_DEFAULT)
+ key = KEYC_MOUSEDOWN9_STATUS_DEFAULT;
+ if (where == BORDER)
+ key = KEYC_MOUSEDOWN9_BORDER;
+ break;
+ case MOUSE_BUTTON_10:
+ if (where == PANE)
+ key = KEYC_MOUSEDOWN10_PANE;
+ if (where == STATUS)
+ key = KEYC_MOUSEDOWN10_STATUS;
+ if (where == STATUS_LEFT)
+ key = KEYC_MOUSEDOWN10_STATUS_LEFT;
+ if (where == STATUS_RIGHT)
+ key = KEYC_MOUSEDOWN10_STATUS_RIGHT;
+ if (where == STATUS_DEFAULT)
+ key = KEYC_MOUSEDOWN10_STATUS_DEFAULT;
+ if (where == BORDER)
+ key = KEYC_MOUSEDOWN10_BORDER;
+ break;
+ case MOUSE_BUTTON_11:
+ if (where == PANE)
+ key = KEYC_MOUSEDOWN11_PANE;
+ if (where == STATUS)
+ key = KEYC_MOUSEDOWN11_STATUS;
+ if (where == STATUS_LEFT)
+ key = KEYC_MOUSEDOWN11_STATUS_LEFT;
+ if (where == STATUS_RIGHT)
+ key = KEYC_MOUSEDOWN11_STATUS_RIGHT;
+ if (where == STATUS_DEFAULT)
+ key = KEYC_MOUSEDOWN11_STATUS_DEFAULT;
+ if (where == BORDER)
+ key = KEYC_MOUSEDOWN11_BORDER;
+ break;
}
break;
case SECOND:
switch (MOUSE_BUTTONS(b)) {
- case 0:
+ case MOUSE_BUTTON_1:
if (where == PANE)
key = KEYC_SECONDCLICK1_PANE;
if (where == STATUS)
@@ -1024,7 +1362,7 @@ have_event:
if (where == BORDER)
key = KEYC_SECONDCLICK1_BORDER;
break;
- case 1:
+ case MOUSE_BUTTON_2:
if (where == PANE)
key = KEYC_SECONDCLICK2_PANE;
if (where == STATUS)
@@ -1038,7 +1376,7 @@ have_event:
if (where == BORDER)
key = KEYC_SECONDCLICK2_BORDER;
break;
- case 2:
+ case MOUSE_BUTTON_3:
if (where == PANE)
key = KEYC_SECONDCLICK3_PANE;
if (where == STATUS)
@@ -1052,11 +1390,95 @@ have_event:
if (where == BORDER)
key = KEYC_SECONDCLICK3_BORDER;
break;
+ case MOUSE_BUTTON_6:
+ if (where == PANE)
+ key = KEYC_SECONDCLICK6_PANE;
+ if (where == STATUS)
+ key = KEYC_SECONDCLICK6_STATUS;
+ if (where == STATUS_LEFT)
+ key = KEYC_SECONDCLICK6_STATUS_LEFT;
+ if (where == STATUS_RIGHT)
+ key = KEYC_SECONDCLICK6_STATUS_RIGHT;
+ if (where == STATUS_DEFAULT)
+ key = KEYC_SECONDCLICK6_STATUS_DEFAULT;
+ if (where == BORDER)
+ key = KEYC_SECONDCLICK6_BORDER;
+ break;
+ case MOUSE_BUTTON_7:
+ if (where == PANE)
+ key = KEYC_SECONDCLICK7_PANE;
+ if (where == STATUS)
+ key = KEYC_SECONDCLICK7_STATUS;
+ if (where == STATUS_LEFT)
+ key = KEYC_SECONDCLICK7_STATUS_LEFT;
+ if (where == STATUS_RIGHT)
+ key = KEYC_SECONDCLICK7_STATUS_RIGHT;
+ if (where == STATUS_DEFAULT)
+ key = KEYC_SECONDCLICK7_STATUS_DEFAULT;
+ if (where == BORDER)
+ key = KEYC_SECONDCLICK7_BORDER;
+ break;
+ case MOUSE_BUTTON_8:
+ if (where == PANE)
+ key = KEYC_SECONDCLICK8_PANE;
+ if (where == STATUS)
+ key = KEYC_SECONDCLICK8_STATUS;
+ if (where == STATUS_LEFT)
+ key = KEYC_SECONDCLICK8_STATUS_LEFT;
+ if (where == STATUS_RIGHT)
+ key = KEYC_SECONDCLICK8_STATUS_RIGHT;
+ if (where == STATUS_DEFAULT)
+ key = KEYC_SECONDCLICK8_STATUS_DEFAULT;
+ if (where == BORDER)
+ key = KEYC_SECONDCLICK8_BORDER;
+ break;
+ case MOUSE_BUTTON_9:
+ if (where == PANE)
+ key = KEYC_SECONDCLICK9_PANE;
+ if (where == STATUS)
+ key = KEYC_SECONDCLICK9_STATUS;
+ if (where == STATUS_LEFT)
+ key = KEYC_SECONDCLICK9_STATUS_LEFT;
+ if (where == STATUS_RIGHT)
+ key = KEYC_SECONDCLICK9_STATUS_RIGHT;
+ if (where == STATUS_DEFAULT)
+ key = KEYC_SECONDCLICK9_STATUS_DEFAULT;
+ if (where == BORDER)
+ key = KEYC_SECONDCLICK9_BORDER;
+ break;
+ case MOUSE_BUTTON_10:
+ if (where == PANE)
+ key = KEYC_SECONDCLICK10_PANE;
+ if (where == STATUS)
+ key = KEYC_SECONDCLICK10_STATUS;
+ if (where == STATUS_LEFT)
+ key = KEYC_SECONDCLICK10_STATUS_LEFT;
+ if (where == STATUS_RIGHT)
+ key = KEYC_SECONDCLICK10_STATUS_RIGHT;
+ if (where == STATUS_DEFAULT)
+ key = KEYC_SECONDCLICK10_STATUS_DEFAULT;
+ if (where == BORDER)
+ key = KEYC_SECONDCLICK10_BORDER;
+ break;
+ case MOUSE_BUTTON_11:
+ if (where == PANE)
+ key = KEYC_SECONDCLICK11_PANE;
+ if (where == STATUS)
+ key = KEYC_SECONDCLICK11_STATUS;
+ if (where == STATUS_LEFT)
+ key = KEYC_SECONDCLICK11_STATUS_LEFT;
+ if (where == STATUS_RIGHT)
+ key = KEYC_SECONDCLICK11_STATUS_RIGHT;
+ if (where == STATUS_DEFAULT)
+ key = KEYC_SECONDCLICK11_STATUS_DEFAULT;
+ if (where == BORDER)
+ key = KEYC_SECONDCLICK11_BORDER;
+ break;
}
break;
case DOUBLE:
switch (MOUSE_BUTTONS(b)) {
- case 0:
+ case MOUSE_BUTTON_1:
if (where == PANE)
key = KEYC_DOUBLECLICK1_PANE;
if (where == STATUS)
@@ -1070,7 +1492,7 @@ have_event:
if (where == BORDER)
key = KEYC_DOUBLECLICK1_BORDER;
break;
- case 1:
+ case MOUSE_BUTTON_2:
if (where == PANE)
key = KEYC_DOUBLECLICK2_PANE;
if (where == STATUS)
@@ -1084,7 +1506,7 @@ have_event:
if (where == BORDER)
key = KEYC_DOUBLECLICK2_BORDER;
break;
- case 2:
+ case MOUSE_BUTTON_3:
if (where == PANE)
key = KEYC_DOUBLECLICK3_PANE;
if (where == STATUS)
@@ -1098,11 +1520,95 @@ have_event:
if (where == BORDER)
key = KEYC_DOUBLECLICK3_BORDER;
break;
+ case MOUSE_BUTTON_6:
+ if (where == PANE)
+ key = KEYC_DOUBLECLICK6_PANE;
+ if (where == STATUS)
+ key = KEYC_DOUBLECLICK6_STATUS;
+ if (where == STATUS_LEFT)
+ key = KEYC_DOUBLECLICK6_STATUS_LEFT;
+ if (where == STATUS_RIGHT)
+ key = KEYC_DOUBLECLICK6_STATUS_RIGHT;
+ if (where == STATUS_DEFAULT)
+ key = KEYC_DOUBLECLICK6_STATUS_DEFAULT;
+ if (where == BORDER)
+ key = KEYC_DOUBLECLICK6_BORDER;
+ break;
+ case MOUSE_BUTTON_7:
+ if (where == PANE)
+ key = KEYC_DOUBLECLICK7_PANE;
+ if (where == STATUS)
+ key = KEYC_DOUBLECLICK7_STATUS;
+ if (where == STATUS_LEFT)
+ key = KEYC_DOUBLECLICK7_STATUS_LEFT;
+ if (where == STATUS_RIGHT)
+ key = KEYC_DOUBLECLICK7_STATUS_RIGHT;
+ if (where == STATUS_DEFAULT)
+ key = KEYC_DOUBLECLICK7_STATUS_DEFAULT;
+ if (where == BORDER)
+ key = KEYC_DOUBLECLICK7_BORDER;
+ break;
+ case MOUSE_BUTTON_8:
+ if (where == PANE)
+ key = KEYC_DOUBLECLICK8_PANE;
+ if (where == STATUS)
+ key = KEYC_DOUBLECLICK8_STATUS;
+ if (where == STATUS_LEFT)
+ key = KEYC_DOUBLECLICK8_STATUS_LEFT;
+ if (where == STATUS_RIGHT)
+ key = KEYC_DOUBLECLICK8_STATUS_RIGHT;
+ if (where == STATUS_DEFAULT)
+ key = KEYC_DOUBLECLICK8_STATUS_DEFAULT;
+ if (where == BORDER)
+ key = KEYC_DOUBLECLICK8_BORDER;
+ break;
+ case MOUSE_BUTTON_9:
+ if (where == PANE)
+ key = KEYC_DOUBLECLICK9_PANE;
+ if (where == STATUS)
+ key = KEYC_DOUBLECLICK9_STATUS;
+ if (where == STATUS_LEFT)
+ key = KEYC_DOUBLECLICK9_STATUS_LEFT;
+ if (where == STATUS_RIGHT)
+ key = KEYC_DOUBLECLICK9_STATUS_RIGHT;
+ if (where == STATUS_DEFAULT)
+ key = KEYC_DOUBLECLICK9_STATUS_DEFAULT;
+ if (where == BORDER)
+ key = KEYC_DOUBLECLICK9_BORDER;
+ break;
+ case MOUSE_BUTTON_10:
+ if (where == PANE)
+ key = KEYC_DOUBLECLICK10_PANE;
+ if (where == STATUS)
+ key = KEYC_DOUBLECLICK10_STATUS;
+ if (where == STATUS_LEFT)
+ key = KEYC_DOUBLECLICK10_STATUS_LEFT;
+ if (where == STATUS_RIGHT)
+ key = KEYC_DOUBLECLICK10_STATUS_RIGHT;
+ if (where == STATUS_DEFAULT)
+ key = KEYC_DOUBLECLICK10_STATUS_DEFAULT;
+ if (where == BORDER)
+ key = KEYC_DOUBLECLICK10_BORDER;
+ break;
+ case MOUSE_BUTTON_11:
+ if (where == PANE)
+ key = KEYC_DOUBLECLICK11_PANE;
+ if (where == STATUS)
+ key = KEYC_DOUBLECLICK11_STATUS;
+ if (where == STATUS_LEFT)
+ key = KEYC_DOUBLECLICK11_STATUS_LEFT;
+ if (where == STATUS_RIGHT)
+ key = KEYC_DOUBLECLICK11_STATUS_RIGHT;
+ if (where == STATUS_DEFAULT)
+ key = KEYC_DOUBLECLICK11_STATUS_DEFAULT;
+ if (where == BORDER)
+ key = KEYC_DOUBLECLICK11_BORDER;
+ break;
}
break;
case TRIPLE:
switch (MOUSE_BUTTONS(b)) {
- case 0:
+ case MOUSE_BUTTON_1:
if (where == PANE)
key = KEYC_TRIPLECLICK1_PANE;
if (where == STATUS)
@@ -1116,7 +1622,7 @@ have_event:
if (where == BORDER)
key = KEYC_TRIPLECLICK1_BORDER;
break;
- case 1:
+ case MOUSE_BUTTON_2:
if (where == PANE)
key = KEYC_TRIPLECLICK2_PANE;
if (where == STATUS)
@@ -1130,7 +1636,7 @@ have_event:
if (where == BORDER)
key = KEYC_TRIPLECLICK2_BORDER;
break;
- case 2:
+ case MOUSE_BUTTON_3:
if (where == PANE)
key = KEYC_TRIPLECLICK3_PANE;
if (where == STATUS)
@@ -1144,6 +1650,90 @@ have_event:
if (where == BORDER)
key = KEYC_TRIPLECLICK3_BORDER;
break;
+ case MOUSE_BUTTON_6:
+ if (where == PANE)
+ key = KEYC_TRIPLECLICK6_PANE;
+ if (where == STATUS)
+ key = KEYC_TRIPLECLICK6_STATUS;
+ if (where == STATUS_LEFT)
+ key = KEYC_TRIPLECLICK6_STATUS_LEFT;
+ if (where == STATUS_RIGHT)
+ key = KEYC_TRIPLECLICK6_STATUS_RIGHT;
+ if (where == STATUS_DEFAULT)
+ key = KEYC_TRIPLECLICK6_STATUS_DEFAULT;
+ if (where == BORDER)
+ key = KEYC_TRIPLECLICK6_BORDER;
+ break;
+ case MOUSE_BUTTON_7:
+ if (where == PANE)
+ key = KEYC_TRIPLECLICK7_PANE;
+ if (where == STATUS)
+ key = KEYC_TRIPLECLICK7_STATUS;
+ if (where == STATUS_LEFT)
+ key = KEYC_TRIPLECLICK7_STATUS_LEFT;
+ if (where == STATUS_RIGHT)
+ key = KEYC_TRIPLECLICK7_STATUS_RIGHT;
+ if (where == STATUS_DEFAULT)
+ key = KEYC_TRIPLECLICK7_STATUS_DEFAULT;
+ if (where == BORDER)
+ key = KEYC_TRIPLECLICK7_BORDER;
+ break;
+ case MOUSE_BUTTON_8:
+ if (where == PANE)
+ key = KEYC_TRIPLECLICK8_PANE;
+ if (where == STATUS)
+ key = KEYC_TRIPLECLICK8_STATUS;
+ if (where == STATUS_LEFT)
+ key = KEYC_TRIPLECLICK8_STATUS_LEFT;
+ if (where == STATUS_RIGHT)
+ key = KEYC_TRIPLECLICK8_STATUS_RIGHT;
+ if (where == STATUS_DEFAULT)
+ key = KEYC_TRIPLECLICK8_STATUS_DEFAULT;
+ if (where == BORDER)
+ key = KEYC_TRIPLECLICK8_BORDER;
+ break;
+ case MOUSE_BUTTON_9:
+ if (where == PANE)
+ key = KEYC_TRIPLECLICK9_PANE;
+ if (where == STATUS)
+ key = KEYC_TRIPLECLICK9_STATUS;
+ if (where == STATUS_LEFT)
+ key = KEYC_TRIPLECLICK9_STATUS_LEFT;
+ if (where == STATUS_RIGHT)
+ key = KEYC_TRIPLECLICK9_STATUS_RIGHT;
+ if (where == STATUS_DEFAULT)
+ key = KEYC_TRIPLECLICK9_STATUS_DEFAULT;
+ if (where == BORDER)
+ key = KEYC_TRIPLECLICK9_BORDER;
+ break;
+ case MOUSE_BUTTON_10:
+ if (where == PANE)
+ key = KEYC_TRIPLECLICK10_PANE;
+ if (where == STATUS)
+ key = KEYC_TRIPLECLICK10_STATUS;
+ if (where == STATUS_LEFT)
+ key = KEYC_TRIPLECLICK10_STATUS_LEFT;
+ if (where == STATUS_RIGHT)
+ key = KEYC_TRIPLECLICK10_STATUS_RIGHT;
+ if (where == STATUS_DEFAULT)
+ key = KEYC_TRIPLECLICK10_STATUS_DEFAULT;
+ if (where == BORDER)
+ key = KEYC_TRIPLECLICK10_BORDER;
+ break;
+ case MOUSE_BUTTON_11:
+ if (where == PANE)
+ key = KEYC_TRIPLECLICK11_PANE;
+ if (where == STATUS)
+ key = KEYC_TRIPLECLICK11_STATUS;
+ if (where == STATUS_LEFT)
+ key = KEYC_TRIPLECLICK11_STATUS_LEFT;
+ if (where == STATUS_RIGHT)
+ key = KEYC_TRIPLECLICK11_STATUS_RIGHT;
+ if (where == STATUS_DEFAULT)
+ key = KEYC_TRIPLECLICK11_STATUS_DEFAULT;
+ if (where == BORDER)
+ key = KEYC_TRIPLECLICK11_BORDER;
+ break;
}
break;
}
@@ -2011,8 +2601,10 @@ server_client_check_redraw(struct client *c)
}
if (c->flags & CLIENT_ALLREDRAWFLAGS) {
- if (options_get_number(s->options, "set-titles"))
+ if (options_get_number(s->options, "set-titles")) {
server_client_set_title(c);
+ server_client_set_path(c);
+ }
screen_redraw_screen(c);
}
@@ -2058,6 +2650,26 @@ server_client_set_title(struct client *c)
format_free(ft);
}
+/* Set client path. */
+static void
+server_client_set_path(struct client *c)
+{
+ struct session *s = c->session;
+ const char *path;
+
+ if (s->curw == NULL)
+ return;
+ if (s->curw->window->active->base.path == NULL)
+ path = "";
+ else
+ path = s->curw->window->active->base.path;
+ if (c->path == NULL || strcmp(path, c->path) != 0) {
+ free(c->path);
+ c->path = xstrdup(path);
+ tty_set_path(&c->tty, c->path);
+ }
+}
+
/* Dispatch message from client. */
static void
server_client_dispatch(struct imsg *imsg, void *arg)
diff --git a/server-fn.c b/server-fn.c
index 92793093..2a79f3e3 100644
--- a/server-fn.c
+++ b/server-fn.c
@@ -310,9 +310,11 @@ server_destroy_pane(struct window_pane *wp, int notify)
struct window *w = wp->window;
struct screen_write_ctx ctx;
struct grid_cell gc;
- time_t t;
- char tim[26];
int remain_on_exit;
+ const char *s;
+ char *expanded;
+ u_int sx = screen_size_x(&wp->base);
+ u_int sy = screen_size_y(&wp->base);
if (wp->fd != -1) {
#ifdef HAVE_UTEMPTER
@@ -339,32 +341,26 @@ server_destroy_pane(struct window_pane *wp, int notify)
return;
wp->flags |= PANE_STATUSDRAWN;
+ gettimeofday(&wp->dead_time, NULL);
if (notify)
notify_pane("pane-died", wp);
- screen_write_start_pane(&ctx, wp, &wp->base);
- screen_write_scrollregion(&ctx, 0, screen_size_y(ctx.s) - 1);
- screen_write_cursormove(&ctx, 0, screen_size_y(ctx.s) - 1, 0);
- screen_write_linefeed(&ctx, 1, 8);
- memcpy(&gc, &grid_default_cell, sizeof gc);
-
- time(&t);
- ctime_r(&t, tim);
- tim[strcspn(tim, "\n")] = '\0';
-
- if (WIFEXITED(wp->status)) {
- screen_write_nputs(&ctx, -1, &gc,
- "Pane is dead (status %d, %s)",
- WEXITSTATUS(wp->status),
- tim);
- } else if (WIFSIGNALED(wp->status)) {
- screen_write_nputs(&ctx, -1, &gc,
- "Pane is dead (signal %s, %s)",
- sig2name(WTERMSIG(wp->status)),
- tim);
+ s = options_get_string(wp->options, "remain-on-exit-format");
+ if (*s != '\0') {
+ screen_write_start_pane(&ctx, wp, &wp->base);
+ screen_write_scrollregion(&ctx, 0, sy - 1);
+ screen_write_cursormove(&ctx, 0, sy - 1, 0);
+ screen_write_linefeed(&ctx, 1, 8);
+ memcpy(&gc, &grid_default_cell, sizeof gc);
+
+ expanded = format_single(NULL, s, NULL, NULL, NULL, wp);
+ format_draw(&ctx, &gc, sx, expanded, NULL, 0);
+ free(expanded);
+
+ screen_write_stop(&ctx);
}
+ wp->base.mode &= ~MODE_CURSOR;
- screen_write_stop(&ctx);
wp->flags |= PANE_REDRAW;
return;
}
diff --git a/server.c b/server.c
index 29bcf88a..5b70dcd0 100644
--- a/server.c
+++ b/server.c
@@ -100,7 +100,7 @@ server_check_marked(void)
}
/* Create server socket. */
-static int
+int
server_create_socket(int flags, char **cause)
{
struct sockaddr_un sa;
@@ -214,7 +214,11 @@ server_start(struct tmuxproc *client, int flags, struct event_base *base,
gettimeofday(&start_time, NULL);
+#ifdef HAVE_SYSTEMD
+ server_fd = systemd_create_socket(flags, &cause);
+#else
server_fd = server_create_socket(flags, &cause);
+#endif
if (server_fd != -1)
server_update_socket();
if (~flags & CLIENT_NOFORK)
@@ -230,10 +234,12 @@ server_start(struct tmuxproc *client, int flags, struct event_base *base,
if (cause != NULL) {
if (c != NULL) {
- cmdq_append(c, cmdq_get_error(cause));
+ c->exit_message = cause;
c->flags |= CLIENT_EXIT;
+ } else {
+ fprintf(stderr, "%s\n", cause);
+ exit(1);
}
- free(cause);
}
evtimer_set(&server_ev_tidy, server_tidy_event, NULL);
diff --git a/session.c b/session.c
index f30f6a61..75028882 100644
--- a/session.c
+++ b/session.c
@@ -27,7 +27,7 @@
#include "tmux.h"
struct sessions sessions;
-static u_int next_session_id;
+u_int next_session_id;
struct session_groups session_groups = RB_INITIALIZER(&session_groups);
static void session_free(int, short, void *);
@@ -501,7 +501,8 @@ session_set_current(struct session *s, struct winlink *wl)
winlink_stack_push(&s->lastw, s->curw);
s->curw = wl;
if (options_get_number(global_options, "focus-events")) {
- window_update_focus(old->window);
+ if (old != NULL)
+ window_update_focus(old->window);
window_update_focus(wl->window);
}
winlink_clear_flags(wl);
diff --git a/status.c b/status.c
index 79033242..8d702de1 100644
--- a/status.c
+++ b/status.c
@@ -1798,7 +1798,7 @@ status_prompt_complete_window_menu(struct client *c, struct session *s,
item.name = tmp;
item.key = '0' + size - 1;
item.command = NULL;
- menu_add_item(menu, &item, NULL, NULL, NULL);
+ menu_add_item(menu, &item, NULL, c, NULL);
free(tmp);
if (size == height)
diff --git a/tmux.1 b/tmux.1
index 638c3232..ae6b6fb8 100644
--- a/tmux.1
+++ b/tmux.1
@@ -43,7 +43,7 @@ then later reattached.
.Pp
When
.Nm
-is started it creates a new
+is started, it creates a new
.Em session
with a single
.Em window
@@ -1341,11 +1341,12 @@ and sets an environment variable for the newly created session; it may be
specified multiple times.
.Tg refresh
.It Xo Ic refresh-client
-.Op Fl cDlLRSU
+.Op Fl cDLRSU
.Op Fl A Ar pane:state
.Op Fl B Ar name:what:format
.Op Fl C Ar size
.Op Fl f Ar flags
+.Op Fl l Op Ar target-pane
.Op Fl t Ar target-client
.Op Ar adjustment
.Xc
@@ -1459,7 +1460,11 @@ sets a comma-separated list of client flags, see
.Fl l
requests the clipboard from the client using the
.Xr xterm 1
-escape sequence and stores it in a new paste buffer.
+escape sequence.
+If
+Ar target-pane
+is given, the clipboard is sent (in encoded form), otherwise it is stored in a
+new paste buffer.
.Pp
.Fl L ,
.Fl R ,
@@ -3622,6 +3627,8 @@ Supports DECSLRM margins.
Supports
.Xr xterm 1
mouse sequences.
+.It osc7
+Supports the OSC 7 working directory extension.
.It overline
Supports the overline SGR attribute.
.It rectfill
@@ -4112,6 +4119,9 @@ Set clock colour.
.Xc
Set clock hour format.
.Pp
+.It Ic fill-character Ar character
+Set the character used to fill areas of the terminal unused by a window.
+.Pp
.It Ic main-pane-height Ar height
.It Ic main-pane-width Ar width
Set the width or height of the main (left or top) pane in the
@@ -4406,6 +4416,13 @@ The default is on.
Available pane options are:
.Pp
.Bl -tag -width Ds -compact
+.It Xo Ic allow-passthrough
+.Op Ic on | off
+.Xc
+Allow programs in the pane to bypass
+.Nm
+using a terminal escape sequence (\eePtmux;...\ee\e\e).
+.Pp
.It Xo Ic allow-rename
.Op Ic on | off
.Xc
@@ -4459,6 +4476,17 @@ The pane may be reactivated with the
.Ic respawn-pane
command.
.Pp
+.It Ic remain-on-exit-format Ar string
+Set the text shown at the bottom of exited panes when
+.Ic remain-on-exit
+is enabled.
+.Pp
+.It Xo Ic scroll-on-clear
+.Op Ic on | off
+.Xc
+When the entire screen is cleared and this option is on, scroll the contents of
+the screen into history before clearing it.
+.Pp
.It Xo Ic synchronize-panes
.Op Ic on | off
.Xc
@@ -4585,6 +4613,11 @@ Run when a session is renamed.
Run when a window is linked into a session.
.It window-renamed
Run when a window is renamed.
+.It window-resized
+Run when a window is resized.
+This may be after the
+.Ar client-resized
+hook is run.
.It window-unlinked
Run when a window is unlinked from a session.
.El
@@ -5045,6 +5078,8 @@ The following variables are available, where appropriate:
.It Li "client_termname" Ta "" Ta "Terminal name of client"
.It Li "client_termtype" Ta "" Ta "Terminal type of client, if available"
.It Li "client_tty" Ta "" Ta "Pseudo terminal of client"
+.It Li "client_uid" Ta "" Ta "UID of client process"
+.It Li "client_user" Ta "" Ta "User of client process"
.It Li "client_utf8" Ta "" Ta "1 if client supports UTF-8"
.It Li "client_width" Ta "" Ta "Width of client"
.It Li "client_written" Ta "" Ta "Bytes written to client"
@@ -5089,6 +5124,7 @@ The following variables are available, where appropriate:
.It Li "mouse_word" Ta "" Ta "Word under mouse, if any"
.It Li "mouse_x" Ta "" Ta "Mouse X position, if any"
.It Li "mouse_y" Ta "" Ta "Mouse Y position, if any"
+.It Li "next_session_id" Ta "" Ta "Unique session ID for next new session"
.It Li "origin_flag" Ta "" Ta "Pane origin flag"
.It Li "pane_active" Ta "" Ta "1 if active pane"
.It Li "pane_at_bottom" Ta "" Ta "1 if pane is at the bottom of window"
@@ -5100,7 +5136,9 @@ The following variables are available, where appropriate:
.It Li "pane_current_command" Ta "" Ta "Current command if available"
.It Li "pane_current_path" Ta "" Ta "Current path if available"
.It Li "pane_dead" Ta "" Ta "1 if pane is dead"
+.It Li "pane_dead_signal" Ta "" Ta "Exit signal of process in dead pane"
.It Li "pane_dead_status" Ta "" Ta "Exit status of process in dead pane"
+.It Li "pane_dead_time" Ta "" Ta "Exit time of process in dead pane"
.It Li "pane_fg" Ta "" Ta "Pane foreground colour"
.It Li "pane_format" Ta "" Ta "1 if format is for a pane"
.It Li "pane_height" Ta "" Ta "Height of pane"
@@ -5161,6 +5199,8 @@ The following variables are available, where appropriate:
.It Li "session_windows" Ta "" Ta "Number of windows in session"
.It Li "socket_path" Ta "" Ta "Server socket path"
.It Li "start_time" Ta "" Ta "Server start time"
+.It Li "uid" Ta "" Ta "Server UID"
+.It Li "user" Ta "" Ta "Server user"
.It Li "version" Ta "" Ta "Server version"
.It Li "window_active" Ta "" Ta "1 if window active"
.It Li "window_active_clients" Ta "" Ta "Number of clients viewing this window"
@@ -5175,7 +5215,6 @@ The following variables are available, where appropriate:
.It Li "window_cell_width" Ta "" Ta "Width of each cell in pixels"
.It Li "window_end_flag" Ta "" Ta "1 if window has the highest index"
.It Li "window_flags" Ta "#F" Ta "Window flags with # escaped as ##"
-.It Li "window_raw_flags" Ta "" Ta "Window flags with nothing escaped"
.It Li "window_format" Ta "" Ta "1 if format is for a window"
.It Li "window_height" Ta "" Ta "Height of window"
.It Li "window_id" Ta "" Ta "Unique window ID"
@@ -5190,6 +5229,7 @@ The following variables are available, where appropriate:
.It Li "window_offset_x" Ta "" Ta "X offset into window if larger than client"
.It Li "window_offset_y" Ta "" Ta "Y offset into window if larger than client"
.It Li "window_panes" Ta "" Ta "Number of panes in window"
+.It Li "window_raw_flags" Ta "" Ta "Window flags with nothing escaped"
.It Li "window_silence_flag" Ta "" Ta "1 if window has silence alert"
.It Li "window_stack_index" Ta "" Ta "Index in session most recent stack"
.It Li "window_start_flag" Ta "" Ta "1 if window has the lowest index"
@@ -5878,7 +5918,7 @@ does not surround the popup by a border.
sets the type of border line for the popup.
When
.Fl B
-is specified the
+is specified, the
.Fl b
option is ignored.
See
@@ -6356,6 +6396,11 @@ $ printf '\e033[4 q'
If
.Em Se
is not set, \&Ss with argument 0 will be used to reset the cursor style instead.
+.It Em \&Swd
+Set the opening sequence for the working directory notification.
+The sequence is terminated using the standard
+.Em fsl
+capability.
.It Em \&Sync
Start (parameter is 1) or end (parameter is 2) a synchronized update.
.It Em \&Tc
@@ -6594,7 +6639,7 @@ are replaced with underscores
For input,
.Nm
always runs with a UTF-8 locale.
-If en_US.UTF-8 is provided by the operating system it is used and
+If en_US.UTF-8 is provided by the operating system, it is used and
.Ev LC_CTYPE
is ignored for input.
Otherwise,
diff --git a/tmux.h b/tmux.h
index a4f484eb..f16b5250 100644
--- a/tmux.h
+++ b/tmux.h
@@ -202,26 +202,68 @@ enum {
KEYC_MOUSE_KEY(MOUSEDOWN1),
KEYC_MOUSE_KEY(MOUSEDOWN2),
KEYC_MOUSE_KEY(MOUSEDOWN3),
+ KEYC_MOUSE_KEY(MOUSEDOWN6),
+ KEYC_MOUSE_KEY(MOUSEDOWN7),
+ KEYC_MOUSE_KEY(MOUSEDOWN8),
+ KEYC_MOUSE_KEY(MOUSEDOWN9),
+ KEYC_MOUSE_KEY(MOUSEDOWN10),
+ KEYC_MOUSE_KEY(MOUSEDOWN11),
KEYC_MOUSE_KEY(MOUSEUP1),
KEYC_MOUSE_KEY(MOUSEUP2),
KEYC_MOUSE_KEY(MOUSEUP3),
+ KEYC_MOUSE_KEY(MOUSEUP6),
+ KEYC_MOUSE_KEY(MOUSEUP7),
+ KEYC_MOUSE_KEY(MOUSEUP8),
+ KEYC_MOUSE_KEY(MOUSEUP9),
+ KEYC_MOUSE_KEY(MOUSEUP10),
+ KEYC_MOUSE_KEY(MOUSEUP11),
KEYC_MOUSE_KEY(MOUSEDRAG1),
KEYC_MOUSE_KEY(MOUSEDRAG2),
KEYC_MOUSE_KEY(MOUSEDRAG3),
+ KEYC_MOUSE_KEY(MOUSEDRAG6),
+ KEYC_MOUSE_KEY(MOUSEDRAG7),
+ KEYC_MOUSE_KEY(MOUSEDRAG8),
+ KEYC_MOUSE_KEY(MOUSEDRAG9),
+ KEYC_MOUSE_KEY(MOUSEDRAG10),
+ KEYC_MOUSE_KEY(MOUSEDRAG11),
KEYC_MOUSE_KEY(MOUSEDRAGEND1),
KEYC_MOUSE_KEY(MOUSEDRAGEND2),
KEYC_MOUSE_KEY(MOUSEDRAGEND3),
+ KEYC_MOUSE_KEY(MOUSEDRAGEND6),
+ KEYC_MOUSE_KEY(MOUSEDRAGEND7),
+ KEYC_MOUSE_KEY(MOUSEDRAGEND8),
+ KEYC_MOUSE_KEY(MOUSEDRAGEND9),
+ KEYC_MOUSE_KEY(MOUSEDRAGEND10),
+ KEYC_MOUSE_KEY(MOUSEDRAGEND11),
KEYC_MOUSE_KEY(WHEELUP),
KEYC_MOUSE_KEY(WHEELDOWN),
KEYC_MOUSE_KEY(SECONDCLICK1),
KEYC_MOUSE_KEY(SECONDCLICK2),
KEYC_MOUSE_KEY(SECONDCLICK3),
+ KEYC_MOUSE_KEY(SECONDCLICK6),
+ KEYC_MOUSE_KEY(SECONDCLICK7),
+ KEYC_MOUSE_KEY(SECONDCLICK8),
+ KEYC_MOUSE_KEY(SECONDCLICK9),
+ KEYC_MOUSE_KEY(SECONDCLICK10),
+ KEYC_MOUSE_KEY(SECONDCLICK11),
KEYC_MOUSE_KEY(DOUBLECLICK1),
KEYC_MOUSE_KEY(DOUBLECLICK2),
KEYC_MOUSE_KEY(DOUBLECLICK3),
+ KEYC_MOUSE_KEY(DOUBLECLICK6),
+ KEYC_MOUSE_KEY(DOUBLECLICK7),
+ KEYC_MOUSE_KEY(DOUBLECLICK8),
+ KEYC_MOUSE_KEY(DOUBLECLICK9),
+ KEYC_MOUSE_KEY(DOUBLECLICK10),
+ KEYC_MOUSE_KEY(DOUBLECLICK11),
KEYC_MOUSE_KEY(TRIPLECLICK1),
KEYC_MOUSE_KEY(TRIPLECLICK2),
KEYC_MOUSE_KEY(TRIPLECLICK3),
+ KEYC_MOUSE_KEY(TRIPLECLICK6),
+ KEYC_MOUSE_KEY(TRIPLECLICK7),
+ KEYC_MOUSE_KEY(TRIPLECLICK8),
+ KEYC_MOUSE_KEY(TRIPLECLICK9),
+ KEYC_MOUSE_KEY(TRIPLECLICK10),
+ KEYC_MOUSE_KEY(TRIPLECLICK11),
/* Backspace key. */
KEYC_BSPACE,
@@ -498,6 +540,7 @@ enum tty_code_code {
TTYC_SMULX,
TTYC_SMXX,
TTYC_SS,
+ TTYC_SWD,
TTYC_SYNC,
TTYC_TC,
TTYC_TSL,
@@ -985,6 +1028,7 @@ struct window_pane {
pid_t pid;
char tty[TTY_NAME_MAX];
int status;
+ struct timeval dead_time;
int fd;
struct bufferevent *event;
@@ -1027,40 +1071,41 @@ RB_HEAD(window_pane_tree, window_pane);
/* Window structure. */
struct window {
- u_int id;
- void *latest;
+ u_int id;
+ void *latest;
- char *name;
- struct event name_event;
- struct timeval name_time;
+ char *name;
+ struct event name_event;
+ struct timeval name_time;
- struct event alerts_timer;
- struct event offset_timer;
+ struct event alerts_timer;
+ struct event offset_timer;
- struct timeval activity_time;
+ struct timeval activity_time;
- struct window_pane *active;
- struct window_pane *last;
- struct window_panes panes;
+ struct window_pane *active;
+ struct window_pane *last;
+ struct window_panes panes;
- int lastlayout;
- struct layout_cell *layout_root;
- struct layout_cell *saved_layout_root;
- char *old_layout;
+ int lastlayout;
+ struct layout_cell *layout_root;
+ struct layout_cell *saved_layout_root;
+ char *old_layout;
- u_int sx;
- u_int sy;
- u_int manual_sx;
- u_int manual_sy;
- u_int xpixel;
- u_int ypixel;
+ u_int sx;
+ u_int sy;
+ u_int manual_sx;
+ u_int manual_sy;
+ u_int xpixel;
+ u_int ypixel;
- u_int new_sx;
- u_int new_sy;
- u_int new_xpixel;
- u_int new_ypixel;
+ u_int new_sx;
+ u_int new_sy;
+ u_int new_xpixel;
+ u_int new_ypixel;
- int flags;
+ struct utf8_data *fill_character;
+ int flags;
#define WINDOW_BELL 0x1
#define WINDOW_ACTIVITY 0x2
#define WINDOW_SILENCE 0x4
@@ -1069,15 +1114,15 @@ struct window {
#define WINDOW_RESIZE 0x20
#define WINDOW_ALERTFLAGS (WINDOW_BELL|WINDOW_ACTIVITY|WINDOW_SILENCE)
- int alerts_queued;
- TAILQ_ENTRY(window) alerts_entry;
+ int alerts_queued;
+ TAILQ_ENTRY(window) alerts_entry;
- struct options *options;
+ struct options *options;
- u_int references;
- TAILQ_HEAD(, winlink) winlinks;
+ u_int references;
+ TAILQ_HEAD(, winlink) winlinks;
- RB_ENTRY(window) entry;
+ RB_ENTRY(window) entry;
};
RB_HEAD(windows, window);
@@ -1199,21 +1244,33 @@ struct session {
RB_HEAD(sessions, session);
/* Mouse button masks. */
-#define MOUSE_MASK_BUTTONS 3
+#define MOUSE_MASK_BUTTONS 195
#define MOUSE_MASK_SHIFT 4
#define MOUSE_MASK_META 8
#define MOUSE_MASK_CTRL 16
#define MOUSE_MASK_DRAG 32
-#define MOUSE_MASK_WHEEL 64
#define MOUSE_MASK_MODIFIERS (MOUSE_MASK_SHIFT|MOUSE_MASK_META|MOUSE_MASK_CTRL)
-/* Mouse wheel states. */
-#define MOUSE_WHEEL_UP 0
-#define MOUSE_WHEEL_DOWN 1
+/* Mouse wheel type. */
+#define MOUSE_WHEEL_UP 64
+#define MOUSE_WHEEL_DOWN 65
+
+/* Mouse button type. */
+#define MOUSE_BUTTON_1 0
+#define MOUSE_BUTTON_2 1
+#define MOUSE_BUTTON_3 2
+#define MOUSE_BUTTON_6 66
+#define MOUSE_BUTTON_7 67
+#define MOUSE_BUTTON_8 128
+#define MOUSE_BUTTON_9 129
+#define MOUSE_BUTTON_10 130
+#define MOUSE_BUTTON_11 131
/* Mouse helpers. */
#define MOUSE_BUTTONS(b) ((b) & MOUSE_MASK_BUTTONS)
-#define MOUSE_WHEEL(b) ((b) & MOUSE_MASK_WHEEL)
+#define MOUSE_WHEEL(b) \
+ (((b) & MOUSE_MASK_BUTTONS) == MOUSE_WHEEL_UP || \
+ ((b) & MOUSE_MASK_BUTTONS) == MOUSE_WHEEL_DOWN)
#define MOUSE_DRAG(b) ((b) & MOUSE_MASK_DRAG)
#define MOUSE_RELEASE(b) (((b) & MOUSE_MASK_BUTTONS) == 3)
@@ -1278,6 +1335,7 @@ LIST_HEAD(tty_terms, tty_term);
struct tty {
struct client *client;
struct event start_timer;
+ struct event clipboard_timer;
u_int sx;
u_int sy;
@@ -1321,7 +1379,7 @@ struct tty {
#define TTY_NOBLOCK 0x8
#define TTY_STARTED 0x10
#define TTY_OPENED 0x20
-/* 0x40 unused */
+#define TTY_OSC52QUERY 0x40
#define TTY_BLOCK 0x80
#define TTY_HAVEDA 0x100
#define TTY_HAVEXDA 0x200
@@ -1630,50 +1688,51 @@ typedef int (*overlay_key_cb)(struct client *, void *, struct key_event *);
typedef void (*overlay_free_cb)(struct client *, void *);
typedef void (*overlay_resize_cb)(struct client *, void *);
struct client {
- const char *name;
- struct tmuxpeer *peer;
- struct cmdq_list *queue;
+ const char *name;
+ struct tmuxpeer *peer;
+ struct cmdq_list *queue;
- struct client_windows windows;
+ struct client_windows windows;
- struct control_state *control_state;
- u_int pause_age;
+ struct control_state *control_state;
+ u_int pause_age;
- pid_t pid;
- int fd;
- int out_fd;
- struct event event;
- int retval;
+ pid_t pid;
+ int fd;
+ int out_fd;
+ struct event event;
+ int retval;
- struct timeval creation_time;
- struct timeval activity_time;
+ struct timeval creation_time;
+ struct timeval activity_time;
- struct environ *environ;
+ struct environ *environ;
struct format_job_tree *jobs;
- char *title;
- const char *cwd;
+ char *title;
+ char *path;
+ const char *cwd;
- char *term_name;
- int term_features;
- char *term_type;
- char **term_caps;
- u_int term_ncaps;
+ char *term_name;
+ int term_features;
+ char *term_type;
+ char **term_caps;
+ u_int term_ncaps;
- char *ttyname;
- struct tty tty;
+ char *ttyname;
+ struct tty tty;
- size_t written;
- size_t discarded;
- size_t redraw;
+ size_t written;
+ size_t discarded;
+ size_t redraw;
- struct event repeat_timer;
+ struct event repeat_timer;
- struct event click_timer;
- u_int click_button;
- struct mouse_event click_event;
+ struct event click_timer;
+ u_int click_button;
+ struct mouse_event click_event;
- struct status_line status;
+ struct status_line status;
#define CLIENT_TERMINAL 0x1
#define CLIENT_LOGIN 0x2
@@ -1710,6 +1769,7 @@ struct client {
#define CLIENT_CONTROL_PAUSEAFTER 0x100000000ULL
#define CLIENT_CONTROL_WAITEXIT 0x200000000ULL
#define CLIENT_WINDOWSIZECHANGED 0x400000000ULL
+#define CLIENT_CLIPBOARDBUFFER 0x800000000ULL
#define CLIENT_ALLREDRAWFLAGS \
(CLIENT_REDRAWWINDOW| \
CLIENT_REDRAWSTATUS| \
@@ -1721,73 +1781,79 @@ struct client {
(CLIENT_DEAD| \
CLIENT_SUSPENDED| \
CLIENT_EXIT)
-#define CLIENT_NODETACHFLAGS \
+#define CLIENT_NODETACHFLAGS \
(CLIENT_DEAD| \
CLIENT_EXIT)
#define CLIENT_NOSIZEFLAGS \
(CLIENT_DEAD| \
CLIENT_SUSPENDED| \
CLIENT_EXIT)
- uint64_t flags;
+ uint64_t flags;
enum {
CLIENT_EXIT_RETURN,
CLIENT_EXIT_SHUTDOWN,
CLIENT_EXIT_DETACH
- } exit_type;
- enum msgtype exit_msgtype;
- char *exit_session;
- char *exit_message;
-
- struct key_table *keytable;
-
- uint64_t redraw_panes;
-
- int message_ignore_keys;
- int message_ignore_styles;
- char *message_string;
- struct event message_timer;
-
- char *prompt_string;
- struct utf8_data *prompt_buffer;
- char *prompt_last;
- size_t prompt_index;
- prompt_input_cb prompt_inputcb;
- prompt_free_cb prompt_freecb;
- void *prompt_data;
- u_int prompt_hindex[PROMPT_NTYPES];
- enum { PROMPT_ENTRY, PROMPT_COMMAND } prompt_mode;
- struct utf8_data *prompt_saved;
+ } exit_type;
+ enum msgtype exit_msgtype;
+ char *exit_session;
+ char *exit_message;
+
+ struct key_table *keytable;
+
+ uint64_t redraw_panes;
+
+ int message_ignore_keys;
+ int message_ignore_styles;
+ char *message_string;
+ struct event message_timer;
+
+ char *prompt_string;
+ struct utf8_data *prompt_buffer;
+ char *prompt_last;
+ size_t prompt_index;
+ prompt_input_cb prompt_inputcb;
+ prompt_free_cb prompt_freecb;
+ void *prompt_data;
+ u_int prompt_hindex[PROMPT_NTYPES];
+ enum {
+ PROMPT_ENTRY,
+ PROMPT_COMMAND
+ } prompt_mode;
+ struct utf8_data *prompt_saved;
#define PROMPT_SINGLE 0x1
#define PROMPT_NUMERIC 0x2
#define PROMPT_INCREMENTAL 0x4
#define PROMPT_NOFORMAT 0x8
#define PROMPT_KEY 0x10
- int prompt_flags;
- enum prompt_type prompt_type;
- int prompt_cursor;
+ int prompt_flags;
+ enum prompt_type prompt_type;
+ int prompt_cursor;
- struct session *session;
- struct session *last_session;
+ struct session *session;
+ struct session *last_session;
- int references;
+ int references;
+
+ void *pan_window;
+ u_int pan_ox;
+ u_int pan_oy;
- void *pan_window;
- u_int pan_ox;
- u_int pan_oy;
+ overlay_check_cb overlay_check;
+ overlay_mode_cb overlay_mode;
+ overlay_draw_cb overlay_draw;
+ overlay_key_cb overlay_key;
+ overlay_free_cb overlay_free;
+ overlay_resize_cb overlay_resize;
+ void *overlay_data;
+ struct event overlay_timer;
- overlay_check_cb overlay_check;
- overlay_mode_cb overlay_mode;
- overlay_draw_cb overlay_draw;
- overlay_key_cb overlay_key;
- overlay_free_cb overlay_free;
- overlay_resize_cb overlay_resize;
- void *overlay_data;
- struct event overlay_timer;
+ struct client_files files;
- struct client_files files;
+ u_int *clipboard_panes;
+ u_int clipboard_npanes;
- TAILQ_ENTRY(client) entry;
+ TAILQ_ENTRY(client) entry;
};
TAILQ_HEAD(clients, client);
@@ -1961,6 +2027,7 @@ void proc_remove_peer(struct tmuxpeer *);
void proc_kill_peer(struct tmuxpeer *);
void proc_toggle_log(struct tmuxproc *);
pid_t proc_fork_and_daemon(int *);
+uid_t proc_get_peer_uid(struct tmuxpeer *);
/* cfg.c */
extern int cfg_finished;
@@ -2174,6 +2241,7 @@ void tty_reset(struct tty *);
void tty_region_off(struct tty *);
void tty_margin_off(struct tty *);
void tty_cursor(struct tty *, u_int, u_int);
+void tty_clipboard_query(struct tty *);
void tty_putcode(struct tty *, enum tty_code_code);
void tty_putcode1(struct tty *, enum tty_code_code, int);
void tty_putcode2(struct tty *, enum tty_code_code, int, int);
@@ -2193,6 +2261,7 @@ void tty_start_tty(struct tty *);
void tty_send_requests(struct tty *);
void tty_stop_tty(struct tty *);
void tty_set_title(struct tty *, const char *);
+void tty_set_path(struct tty *, const char *);
void tty_update_mode(struct tty *, int, struct screen *);
void tty_draw_line(struct tty *, struct screen *, u_int, u_int, u_int,
u_int, u_int, const struct grid_cell *, struct colour_palette *);
@@ -2514,6 +2583,7 @@ int server_start(struct tmuxproc *, int, struct event_base *, int, char *);
void server_update_socket(void);
void server_add_accept(int);
void printflike(1, 2) server_add_message(const char *, ...);
+int server_create_socket(int, char **);
/* server-client.c */
RB_PROTOTYPE(client_windows, client_window, entry, server_client_window_cmp);
@@ -2619,6 +2689,8 @@ void input_parse_pane(struct window_pane *);
void input_parse_buffer(struct window_pane *, u_char *, size_t);
void input_parse_screen(struct input_ctx *, struct screen *,
screen_write_init_ctx_cb, void *, u_char *, size_t);
+void input_reply_clipboard(struct bufferevent *, const char *, size_t,
+ const char *);
/* input-key.c */
void input_key_build(void);
@@ -2910,6 +2982,7 @@ void *window_pane_get_new_data(struct window_pane *,
struct window_pane_offset *, size_t *);
void window_pane_update_used_data(struct window_pane *,
struct window_pane_offset *, size_t);
+void window_set_fill_character(struct window *);
/* layout.c */
u_int layout_count_cells(struct layout_cell *);
@@ -3063,6 +3136,7 @@ void control_notify_session_window_changed(struct session *);
/* session.c */
extern struct sessions sessions;
+extern u_int next_session_id;
int session_cmp(struct session *, struct session *);
RB_PROTOTYPE(sessions, session, entry, session_cmp);
int session_alive(struct session *);
diff --git a/tty-features.c b/tty-features.c
index 3aca2520..4d83a465 100644
--- a/tty-features.c
+++ b/tty-features.c
@@ -53,6 +53,18 @@ static const struct tty_feature tty_feature_title = {
0
};
+/* Terminal has OSC 7 working directory. */
+static const char *tty_feature_osc7_capabilities[] = {
+ "Swd=\\E]7;",
+ "fsl=\\a",
+ NULL
+};
+static const struct tty_feature tty_feature_osc7 = {
+ "osc7",
+ tty_feature_osc7_capabilities,
+ 0
+};
+
/* Terminal has mouse support. */
static const char *tty_feature_mouse_capabilities[] = {
"kmous=\\E[M",
@@ -249,6 +261,7 @@ static const struct tty_feature *tty_features[] = {
&tty_feature_focus,
&tty_feature_margins,
&tty_feature_mouse,
+ &tty_feature_osc7,
&tty_feature_overline,
&tty_feature_rectfill,
&tty_feature_rgb,
diff --git a/tty-keys.c b/tty-keys.c
index 65b600c0..8538e74b 100644
--- a/tty-keys.c
+++ b/tty-keys.c
@@ -1118,7 +1118,7 @@ tty_keys_mouse(struct tty *tty, const char *buf, size_t len, size_t *size,
/* Type is M for press, m for release. */
sgr_type = ch;
if (sgr_type == 'm')
- b |= 3;
+ b = 3;
/*
* Some terminals (like PuTTY 0.63) mistakenly send
@@ -1126,7 +1126,7 @@ tty_keys_mouse(struct tty *tty, const char *buf, size_t len, size_t *size,
* Discard it before it reaches any program running inside
* tmux.
*/
- if (sgr_type == 'm' && (sgr_b & 64))
+ if (sgr_type == 'm' && MOUSE_WHEEL(sgr_b))
return (-2);
} else
return (-1);
@@ -1154,12 +1154,14 @@ tty_keys_mouse(struct tty *tty, const char *buf, size_t len, size_t *size,
* partial.
*/
static int
-tty_keys_clipboard(__unused struct tty *tty, const char *buf, size_t len,
- size_t *size)
+tty_keys_clipboard(struct tty *tty, const char *buf, size_t len, size_t *size)
{
- size_t end, terminator, needed;
- char *copy, *out;
- int outlen;
+ struct client *c = tty->client;
+ struct window_pane *wp;
+ size_t end, terminator, needed;
+ char *copy, *out;
+ int outlen;
+ u_int i;
*size = 0;
@@ -1217,6 +1219,12 @@ tty_keys_clipboard(__unused struct tty *tty, const char *buf, size_t len,
buf++;
end--;
+ /* If we did not request this, ignore it. */
+ if (~tty->flags & TTY_OSC52QUERY)
+ return (0);
+ tty->flags &= ~TTY_OSC52QUERY;
+ evtimer_del(&tty->clipboard_timer);
+
/* It has to be a string so copy it. */
copy = xmalloc(end + 1);
memcpy(copy, buf, end);
@@ -1232,9 +1240,20 @@ tty_keys_clipboard(__unused struct tty *tty, const char *buf, size_t len,
}
free(copy);
- /* Create a new paste buffer. */
+ /* Create a new paste buffer and forward to panes. */
log_debug("%s: %.*s", __func__, outlen, out);
- paste_add(NULL, out, outlen);
+ if (c->flags & CLIENT_CLIPBOARDBUFFER) {
+ paste_add(NULL, out, outlen);
+ c->flags &= ~CLIENT_CLIPBOARDBUFFER;
+ }
+ for (i = 0; i < c->clipboard_npanes; i++) {
+ wp = window_pane_find_by_id(c->clipboard_panes[i]);
+ if (wp != NULL)
+ input_reply_clipboard(wp->event, out, outlen, "\033\\");
+ }
+ free(c->clipboard_panes);
+ c->clipboard_panes = NULL;
+ c->clipboard_npanes = 0;
return (0);
}
diff --git a/tty-term.c b/tty-term.c
index 8e07da05..fdf0c4fa 100644
--- a/tty-term.c
+++ b/tty-term.c
@@ -277,6 +277,7 @@ static const struct tty_term_code_entry tty_term_codes[] = {
[TTYC_SMUL] = { TTYCODE_STRING, "smul" },
[TTYC_SMXX] = { TTYCODE_STRING, "smxx" },
[TTYC_SS] = { TTYCODE_STRING, "Ss" },
+ [TTYC_SWD] = { TTYCODE_STRING, "Swd" },
[TTYC_SYNC] = { TTYCODE_STRING, "Sync" },
[TTYC_TC] = { TTYCODE_FLAG, "Tc" },
[TTYC_TSL] = { TTYCODE_STRING, "tsl" },
diff --git a/tty.c b/tty.c
index 8410a64c..ea10e61e 100644
--- a/tty.c
+++ b/tty.c
@@ -83,6 +83,8 @@ static void tty_check_overlay_range(struct tty *, u_int, u_int, u_int,
#define TTY_BLOCK_START(tty) (1 + ((tty)->sx * (tty)->sy) * 8)
#define TTY_BLOCK_STOP(tty) (1 + ((tty)->sx * (tty)->sy) / 8)
+#define TTY_QUERY_TIMEOUT 5
+
void
tty_create_log(void)
{
@@ -307,7 +309,7 @@ tty_start_tty(struct tty *tty)
{
struct client *c = tty->client;
struct termios tio;
- struct timeval tv = { .tv_sec = 3 };
+ struct timeval tv = { .tv_sec = TTY_QUERY_TIMEOUT };
setblocking(c->fd, 0);
event_add(&tty->event_in, NULL);
@@ -653,6 +655,18 @@ tty_set_title(struct tty *tty, const char *title)
tty_putcode(tty, TTYC_FSL);
}
+void
+tty_set_path(struct tty *tty, const char *title)
+{
+ if (!tty_term_has(tty->term, TTYC_SWD) ||
+ !tty_term_has(tty->term, TTYC_FSL))
+ return;
+
+ tty_putcode(tty, TTYC_SWD);
+ tty_puts(tty, title);
+ tty_putcode(tty, TTYC_FSL);
+}
+
static void
tty_force_cursor_colour(struct tty *tty, int c)
{
@@ -2917,3 +2931,31 @@ tty_default_attributes(struct tty *tty, const struct grid_cell *defaults,
gc.bg = bg;
tty_attributes(tty, &gc, defaults, palette);
}
+
+static void
+tty_clipboard_query_callback(__unused int fd, __unused short events, void *data)
+{
+ struct tty *tty = data;
+ struct client *c = tty->client;
+
+ c->flags &= ~CLIENT_CLIPBOARDBUFFER;
+ free(c->clipboard_panes);
+ c->clipboard_panes = NULL;
+ c->clipboard_npanes = 0;
+
+ tty->flags &= ~TTY_OSC52QUERY;
+}
+
+void
+tty_clipboard_query(struct tty *tty)
+{
+ struct timeval tv = { .tv_sec = TTY_QUERY_TIMEOUT };
+
+ if ((~tty->flags & TTY_STARTED) || (tty->flags & TTY_OSC52QUERY))
+ return;
+ tty_putcode_ptr2(tty, TTYC_MS, "", "?");
+
+ tty->flags |= TTY_OSC52QUERY;
+ evtimer_set(&tty->clipboard_timer, tty_clipboard_query_callback, tty);
+ evtimer_add(&tty->clipboard_timer, &tv);
+}
diff --git a/window-customize.c b/window-customize.c
index 98387e50..4a16e90c 100644
--- a/window-customize.c
+++ b/window-customize.c
@@ -680,9 +680,7 @@ window_customize_draw_option(struct window_customize_modedata *data,
}
ft = format_create_from_state(NULL, NULL, &fs);
- if (oe == NULL)
- text = "This is a user option.";
- else if (oe->text == NULL)
+ if (oe == NULL || oe->text == NULL)
text = "This option doesn't have a description.";
else
text = oe->text;
diff --git a/window.c b/window.c
index fcc61c2a..bce8913a 100644
--- a/window.c
+++ b/window.c
@@ -329,6 +329,7 @@ window_create(u_int sx, u_int sy, u_int xpixel, u_int ypixel)
w->id = next_window_id++;
RB_INSERT(windows, &windows, w);
+ window_set_fill_character(w);
window_update_activity(w);
log_debug("%s: @%u create %ux%u (%ux%u)", __func__, w->id, sx, sy,
@@ -360,6 +361,7 @@ window_destroy(struct window *w)
event_del(&w->offset_timer);
options_free(w->options);
+ free(w->fill_character);
free(w->name);
free(w);
@@ -1599,3 +1601,20 @@ window_pane_update_used_data(struct window_pane *wp,
size = EVBUFFER_LENGTH(wp->event->input) - used;
wpo->used += size;
}
+
+void
+window_set_fill_character(struct window *w)
+{
+ const char *value;
+ struct utf8_data *ud;
+
+ free(w->fill_character);
+ w->fill_character = NULL;
+
+ value = options_get_string(w->options, "fill-character");
+ if (*value != '\0' && utf8_isvalid(value)) {
+ ud = utf8_fromcstr(value);
+ if (ud != NULL && ud[0].width == 1)
+ w->fill_character = ud;
+ }
+}