summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authornicm <nicm>2018-10-18 08:38:01 +0000
committernicm <nicm>2018-10-18 08:38:01 +0000
commit646995384d695eed9de1b2363fd2b315ca01785e (patch)
treead68f9cbaed6e4c5562763ad5f583faa931ecf9e
parenta51668ca0690b84762c5a2f2dd34b94fa566f559 (diff)
Support for windows larger than visible on the attached client. This has
been a limitation for a long time. There are two new options, window-size and default-size, and a new command, resize-window. The force-width and force-height options and the session_width and session_height formats have been removed. The new window-size option tells tmux how to work out the size of windows: largest means it picks the size of the largest session, smallest the smallest session (similar to the old behaviour) and manual means that it does not automatically resize windows. The default is currently largest but this may change. aggressive-resize modifies the choice of session for largest and smallest as it did before. If a window is in a session attached to a client that is too small, only part of the window is shown. tmux attempts to keep the cursor visible, so the part of the window displayed is changed as the cursor moves (with a small delay, to try and avoid excess redrawing when applications redraw status lines or similar that are not currently visible). The offset of the visible portion of the window is shown in status-right. Drawing windows which are larger than the client is not as efficient as those which fit, particularly when the cursor moves, so it is recommended to avoid using this on slow machines or networks (set window-size to smallest or manual). The resize-window command can be used to resize a window manually. If it is used, the window-size option is automatically set to manual for the window (undo this with "setw -u window-size"). resize-window works in a similar way to resize-pane (-U -D -L -R -x -y flags) but also has -a and -A flags. -a sets the window to the size of the smallest client (what it would be if window-size was smallest) and -A the largest. For the same behaviour as force-width or force-height, use resize-window -x or -y, and "setw -u window-size" to revert to automatic sizing.. If the global window-size option is set to manual, the default-size option is used for new windows. If -x or -y is used with new-session, that sets the default-size option for the new session. The maximum size of a window is 10000x10000. But expect applications to complain and much higher memory use if making a window excessively big. The minimum size is the size required for the current layout including borders. The refresh-client command can be used to pan around a window, -U -D -L -R moves up, down, left or right and -c returns to automatic cursor tracking. The position is reset when the current window is changed.
-rw-r--r--Makefile1
-rw-r--r--cmd-attach-session.c2
-rw-r--r--cmd-break-pane.c2
-rw-r--r--cmd-list-sessions.c3
-rw-r--r--cmd-new-session.c60
-rw-r--r--cmd-refresh-client.c78
-rw-r--r--cmd-resize-window.c109
-rw-r--r--cmd-select-pane.c35
-rw-r--r--cmd-set-option.c15
-rw-r--r--cmd-split-window.c2
-rw-r--r--cmd-swap-pane.c2
-rw-r--r--cmd-switch-client.c1
-rw-r--r--cmd.c2
-rw-r--r--format.c43
-rw-r--r--input-keys.c4
-rw-r--r--key-bindings.c5
-rw-r--r--key-string.c2
-rw-r--r--layout-custom.c2
-rw-r--r--layout-set.c8
-rw-r--r--layout.c65
-rw-r--r--options-table.c37
-rw-r--r--resize.c310
-rw-r--r--screen-redraw.c282
-rw-r--r--screen-write.c150
-rw-r--r--server-client.c71
-rw-r--r--server-fn.c1
-rw-r--r--session.c15
-rw-r--r--status.c20
-rw-r--r--tmux.h78
-rw-r--r--tty.c495
-rw-r--r--window.c60
31 files changed, 1372 insertions, 588 deletions
diff --git a/Makefile b/Makefile
index e6d9e6b3..8947cd53 100644
--- a/Makefile
+++ b/Makefile
@@ -44,6 +44,7 @@ SRCS= alerts.c \
cmd-rename-session.c \
cmd-rename-window.c \
cmd-resize-pane.c \
+ cmd-resize-window.c \
cmd-respawn-pane.c \
cmd-respawn-window.c \
cmd-rotate-window.c \
diff --git a/cmd-attach-session.c b/cmd-attach-session.c
index 0db0d855..73ff530d 100644
--- a/cmd-attach-session.c
+++ b/cmd-attach-session.c
@@ -115,6 +115,7 @@ cmd_attach_session(struct cmdq_item *item, const char *tflag, int dflag,
c->session = s;
if (~item->shared->flags & CMDQ_SHARED_REPEAT)
server_client_set_key_table(c, NULL);
+ tty_update_client_offset(c);
status_timer_start(c);
notify_client("client-session-changed", c);
session_update_activity(s, NULL);
@@ -142,6 +143,7 @@ cmd_attach_session(struct cmdq_item *item, const char *tflag, int dflag,
c->session = s;
server_client_set_key_table(c, NULL);
+ tty_update_client_offset(c);
status_timer_start(c);
notify_client("client-session-changed", c);
session_update_activity(s, NULL);
diff --git a/cmd-break-pane.c b/cmd-break-pane.c
index 74ecce6f..3b929dee 100644
--- a/cmd-break-pane.c
+++ b/cmd-break-pane.c
@@ -76,7 +76,7 @@ cmd_break_pane_exec(struct cmd *self, struct cmdq_item *item)
window_lost_pane(w, wp);
layout_close_pane(wp);
- w = wp->window = window_create(dst_s->sx, dst_s->sy);
+ w = wp->window = window_create(w->sx, w->sy);
TAILQ_INSERT_HEAD(&w->panes, wp, entry);
w->active = wp;
diff --git a/cmd-list-sessions.c b/cmd-list-sessions.c
index df8a25bc..72ff47e8 100644
--- a/cmd-list-sessions.c
+++ b/cmd-list-sessions.c
@@ -30,8 +30,7 @@
#define LIST_SESSIONS_TEMPLATE \
"#{session_name}: #{session_windows} windows " \
- "(created #{t:session_created}) " \
- "[#{session_width}x#{session_height}]" \
+ "(created #{t:session_created})" \
"#{?session_grouped, (group ,}" \
"#{session_group}#{?session_grouped,),}" \
"#{?session_attached, (attached),}"
diff --git a/cmd-new-session.c b/cmd-new-session.c
index e809de24..162a50bd 100644
--- a/cmd-new-session.c
+++ b/cmd-new-session.c
@@ -71,14 +71,15 @@ cmd_new_session_exec(struct cmd *self, struct cmdq_item *item)
struct session *s, *as, *groupwith;
struct window *w;
struct environ *env;
+ struct options *oo;
struct termios tio, *tiop;
struct session_group *sg;
const char *errstr, *template, *group, *prefix;
- const char *path, *cmd, *tmp;
+ const char *path, *cmd, *tmp, *value;
char **argv, *cause, *cp, *newname, *cwd = NULL;
int detached, already_attached, idx, argc;
int is_control = 0;
- u_int sx, sy;
+ u_int sx, sy, dsx = 80, dsy = 24;
struct environ_entry *envent;
struct cmd_find_state fs;
enum cmd_retval retval;
@@ -189,44 +190,53 @@ cmd_new_session_exec(struct cmd *self, struct cmdq_item *item)
}
}
- /* Find new session size. */
- if (!detached) {
- sx = c->tty.sx;
- sy = c->tty.sy;
- if (!is_control &&
- sy > 0 &&
- options_get_number(global_s_options, "status"))
- sy--;
- } else {
- sx = 80;
- sy = 24;
- }
- if ((is_control || detached) && args_has(args, 'x')) {
+ /* Get default session size. */
+ if (args_has(args, 'x')) {
tmp = args_get(args, 'x');
if (strcmp(tmp, "-") == 0) {
if (c != NULL)
- sx = c->tty.sx;
+ dsx = c->tty.sx;
} else {
- sx = strtonum(tmp, 1, USHRT_MAX, &errstr);
+ dsx = strtonum(tmp, 1, USHRT_MAX, &errstr);
if (errstr != NULL) {
cmdq_error(item, "width %s", errstr);
goto error;
}
}
}
- if ((is_control || detached) && args_has(args, 'y')) {
+ if (args_has(args, 'y')) {
tmp = args_get(args, 'y');
if (strcmp(tmp, "-") == 0) {
if (c != NULL)
- sy = c->tty.sy;
+ dsy = c->tty.sy;
} else {
- sy = strtonum(tmp, 1, USHRT_MAX, &errstr);
+ dsy = strtonum(tmp, 1, USHRT_MAX, &errstr);
if (errstr != NULL) {
cmdq_error(item, "height %s", errstr);
goto error;
}
}
}
+
+ /* Find new session size. */
+ if (!detached && !is_control) {
+ sx = c->tty.sx;
+ sy = c->tty.sy;
+ if (!is_control &&
+ sy > 0 &&
+ options_get_number(global_s_options, "status"))
+ sy--;
+ } else {
+ value = options_get_string(global_s_options, "default-size");
+ if (sscanf(value, "%ux%u", &sx, &sy) != 2) {
+ sx = 80;
+ sy = 24;
+ }
+ if (args_has(args, 'x'))
+ sx = dsx;
+ if (args_has(args, 'y'))
+ sy = dsy;
+ }
if (sx == 0)
sx = 1;
if (sy == 0)
@@ -262,10 +272,15 @@ cmd_new_session_exec(struct cmd *self, struct cmdq_item *item)
if (c != NULL && !args_has(args, 'E'))
environ_update(global_s_options, c->environ, env);
+ /* Set up the options. */
+ oo = options_create(global_s_options);
+ if (args_has(args, 'x') || args_has(args, 'y'))
+ options_set_string(oo, "default-size", 0, "%ux%u", dsx, dsy);
+
/* Create the new session. */
idx = -1 - options_get_number(global_s_options, "base-index");
- s = session_create(prefix, newname, argc, argv, path, cwd, env, tiop,
- idx, sx, sy, &cause);
+ s = session_create(prefix, newname, argc, argv, path, cwd, env, oo,
+ tiop, idx, &cause);
environ_free(env);
if (s == NULL) {
cmdq_error(item, "create session failed: %s", cause);
@@ -313,6 +328,7 @@ cmd_new_session_exec(struct cmd *self, struct cmdq_item *item)
c->session = s;
if (~item->shared->flags & CMDQ_SHARED_REPEAT)
server_client_set_key_table(c, NULL);
+ tty_update_client_offset(c);
status_timer_start(c);
notify_client("client-session-changed", c);
session_update_activity(s, NULL);
diff --git a/cmd-refresh-client.c b/cmd-refresh-client.c
index 0f45c2d5..e5ae099f 100644
--- a/cmd-refresh-client.c
+++ b/cmd-refresh-client.c
@@ -18,6 +18,8 @@
#include <sys/types.h>
+#include <stdlib.h>
+
#include "tmux.h"
/*
@@ -31,8 +33,8 @@ const struct cmd_entry cmd_refresh_client_entry = {
.name = "refresh-client",
.alias = "refresh",
- .args = { "C:lSt:", 0, 0 },
- .usage = "[-lS] [-C size] " CMD_TARGET_CLIENT_USAGE,
+ .args = { "cC:DlLRSt:U", 0, 1 },
+ .usage = "[-cDlLRSU] [-C size] " CMD_TARGET_CLIENT_USAGE " [adjustment]",
.flags = CMD_AFTERHOOK,
.exec = cmd_refresh_client_exec
@@ -43,11 +45,64 @@ cmd_refresh_client_exec(struct cmd *self, struct cmdq_item *item)
{
struct args *args = self->args;
struct client *c;
- const char *size;
- u_int w, h;
+ struct tty *tty;
+ struct window *w;
+ const char *size, *errstr;
+ u_int x, y, adjust;
if ((c = cmd_find_client(item, args_get(args, 't'), 0)) == NULL)
return (CMD_RETURN_ERROR);
+ tty = &c->tty;
+
+ if (args_has(args, 'c') ||
+ args_has(args, 'L') ||
+ args_has(args, 'R') ||
+ args_has(args, 'U') ||
+ args_has(args, 'D'))
+ {
+ if (args->argc == 0)
+ adjust = 1;
+ else {
+ adjust = strtonum(args->argv[0], 1, INT_MAX, &errstr);
+ if (errstr != NULL) {
+ cmdq_error(item, "adjustment %s", errstr);
+ return (CMD_RETURN_ERROR);
+ }
+ }
+
+ if (args_has(args, 'c'))
+ c->pan_window = NULL;
+ else {
+ w = c->session->curw->window;
+ if (c->pan_window != w) {
+ c->pan_window = w;
+ c->pan_ox = tty->oox;
+ c->pan_oy = tty->ooy;
+ }
+ if (args_has(args, 'L')) {
+ if (c->pan_ox > adjust)
+ c->pan_ox -= adjust;
+ else
+ c->pan_ox = 0;
+ } else if (args_has(args, 'R')) {
+ c->pan_ox += adjust;
+ if (c->pan_ox > w->sx - tty->osx)
+ c->pan_ox = w->sx - tty->osx;
+ } else if (args_has(args, 'U')) {
+ if (c->pan_oy > adjust)
+ c->pan_oy -= adjust;
+ else
+ c->pan_oy = 0;
+ } else if (args_has(args, 'D')) {
+ c->pan_oy += adjust;
+ if (c->pan_oy > w->sy - tty->osy)
+ c->pan_oy = w->sy - tty->osy;
+ }
+ }
+ tty_update_client_offset(c);
+ server_redraw_client(c);
+ return (CMD_RETURN_NORMAL);
+ }
if (args_has(args, 'l')) {
if (c->session != NULL)
@@ -57,12 +112,13 @@ cmd_refresh_client_exec(struct cmd *self, struct cmdq_item *item)
cmdq_error(item, "missing size");
return (CMD_RETURN_ERROR);
}
- if (sscanf(size, "%u,%u", &w, &h) != 2) {
+ if (sscanf(size, "%u,%u", &x, &y) != 2 &&
+ sscanf(size, "%ux%u", &x, &y)) {
cmdq_error(item, "bad size argument");
return (CMD_RETURN_ERROR);
}
- if (w < PANE_MINIMUM || w > 5000 ||
- h < PANE_MINIMUM || h > 5000) {
+ if (x < WINDOW_MINIMUM || x > WINDOW_MAXIMUM ||
+ y < WINDOW_MINIMUM || y > WINDOW_MAXIMUM) {
cmdq_error(item, "size too small or too big");
return (CMD_RETURN_ERROR);
}
@@ -70,16 +126,18 @@ cmd_refresh_client_exec(struct cmd *self, struct cmdq_item *item)
cmdq_error(item, "not a control client");
return (CMD_RETURN_ERROR);
}
- tty_set_size(&c->tty, w, h);
+ tty_set_size(&c->tty, x, y);
c->flags |= CLIENT_SIZECHANGED;
recalculate_sizes();
- } else if (args_has(args, 'S')) {
+ return (CMD_RETURN_NORMAL);
+ }
+
+ if (args_has(args, 'S')) {
c->flags |= CLIENT_STATUSFORCE;
server_status_client(c);
} else {
c->flags |= CLIENT_STATUSFORCE;
server_redraw_client(c);
}
-
return (CMD_RETURN_NORMAL);
}
diff --git a/cmd-resize-window.c b/cmd-resize-window.c
new file mode 100644
index 00000000..d780b6ee
--- /dev/null
+++ b/cmd-resize-window.c
@@ -0,0 +1,109 @@
+/* $OpenBSD$ */
+
+/*
+ * Copyright (c) 2018 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 <stdlib.h>
+
+#include "tmux.h"
+
+/*
+ * Increase or decrease window size.
+ */
+
+static enum cmd_retval cmd_resize_window_exec(struct cmd *,
+ struct cmdq_item *);
+
+const struct cmd_entry cmd_resize_window_entry = {
+ .name = "resize-window",
+ .alias = "resizew",
+
+ .args = { "aADLRt:Ux:y:", 0, 1 },
+ .usage = "[-aADLRU] [-x width] [-y height] " CMD_TARGET_WINDOW_USAGE " "
+ "[adjustment]",
+
+ .target = { 't', CMD_FIND_WINDOW, 0 },
+
+ .flags = CMD_AFTERHOOK,
+ .exec = cmd_resize_window_exec
+};
+
+static enum cmd_retval
+cmd_resize_window_exec(struct cmd *self, struct cmdq_item *item)
+{
+ struct args *args = self->args;
+ struct winlink *wl = item->target.wl;
+ struct window *w = wl->window;
+ struct session *s = item->target.s;
+ const char *errstr;
+ char *cause;
+ u_int adjust, sx, sy;
+
+ if (args->argc == 0)
+ adjust = 1;
+ else {
+ adjust = strtonum(args->argv[0], 1, INT_MAX, &errstr);
+ if (errstr != NULL) {
+ cmdq_error(item, "adjustment %s", errstr);
+ return (CMD_RETURN_ERROR);
+ }
+ }
+
+ sx = w->sx;
+ sy = w->sy;
+
+ if (args_has(args, 'x')) {
+ sx = args_strtonum(args, 'x', WINDOW_MINIMUM, WINDOW_MAXIMUM,
+ &cause);
+ if (cause != NULL) {
+ cmdq_error(item, "width %s", cause);
+ free(cause);
+ return (CMD_RETURN_ERROR);
+ }
+ }
+ if (args_has(args, 'y')) {
+ sy = args_strtonum(args, 'y', WINDOW_MINIMUM, WINDOW_MAXIMUM,
+ &cause);
+ if (cause != NULL) {
+ cmdq_error(item, "height %s", cause);
+ free(cause);
+ return (CMD_RETURN_ERROR);
+ }
+ }
+
+ if (args_has(args, 'L')) {
+ if (sx >= adjust)
+ sx -= adjust;
+ } else if (args_has(args, 'R'))
+ sx += adjust;
+ else if (args_has(args, 'U')) {
+ if (sy >= adjust)
+ sy -= adjust;
+ } else if (args_has(args, 'D'))
+ sy += adjust;
+
+ if (args_has(args, 'A'))
+ default_window_size(s, w, &sx, &sy, WINDOW_SIZE_LARGEST);
+ else if (args_has(args, 'a'))
+ default_window_size(s, w, &sx, &sy, WINDOW_SIZE_SMALLEST);
+
+ options_set_number(w->options, "window-size", WINDOW_SIZE_MANUAL);
+ resize_window(w, sx, sy);
+
+ return (CMD_RETURN_NORMAL);
+}
diff --git a/cmd-select-pane.c b/cmd-select-pane.c
index a2345fe1..90ca46ba 100644
--- a/cmd-select-pane.c
+++ b/cmd-select-pane.c
@@ -54,6 +54,31 @@ const struct cmd_entry cmd_last_pane_entry = {
.exec = cmd_select_pane_exec
};
+static void
+cmd_select_pane_redraw(struct window *w)
+{
+ struct client *c;
+
+ /*
+ * Redraw entire window if it is bigger than the client (the
+ * offset may change), otherwise just draw borders.
+ */
+
+ TAILQ_FOREACH(c, &clients, entry) {
+ if (c->session == NULL)
+ continue;
+ if (c->session->curw->window == w && tty_window_bigger(&c->tty))
+ server_redraw_client(c);
+ else {
+ if (c->session->curw->window == w)
+ c->flags |= CLIENT_REDRAWBORDERS;
+ if (session_has(c->session, w))
+ c->flags |= CLIENT_REDRAWSTATUS;
+ }
+
+ }
+}
+
static enum cmd_retval
cmd_select_pane_exec(struct cmd *self, struct cmdq_item *item)
{
@@ -87,8 +112,7 @@ cmd_select_pane_exec(struct cmd *self, struct cmdq_item *item)
window_redraw_active_switch(w, lastwp);
if (window_set_active_pane(w, lastwp)) {
cmd_find_from_winlink(current, wl, 0);
- server_status_window(w);
- server_redraw_window_borders(w);
+ cmd_select_pane_redraw(w);
}
}
return (CMD_RETURN_NORMAL);
@@ -168,16 +192,11 @@ cmd_select_pane_exec(struct cmd *self, struct cmdq_item *item)
if (wp == w->active)
return (CMD_RETURN_NORMAL);
server_unzoom_window(wp->window);
- if (!window_pane_visible(wp)) {
- cmdq_error(item, "pane not visible");
- return (CMD_RETURN_ERROR);
- }
window_redraw_active_switch(w, wp);
if (window_set_active_pane(w, wp)) {
cmd_find_from_winlink_pane(current, wl, wp, 0);
hooks_insert(s->hooks, item, current, "after-select-pane");
- server_status_window(w);
- server_redraw_window_borders(w);
+ cmd_select_pane_redraw(w);
}
return (CMD_RETURN_NORMAL);
diff --git a/cmd-set-option.c b/cmd-set-option.c
index bdc42cae..c4b82004 100644
--- a/cmd-set-option.c
+++ b/cmd-set-option.c
@@ -18,6 +18,7 @@
#include <sys/types.h>
+#include <fnmatch.h>
#include <stdlib.h>
#include <string.h>
@@ -260,7 +261,7 @@ cmd_set_option_exec(struct cmd *self, struct cmdq_item *item)
}
if (strcmp(name, "pane-border-status") == 0) {
RB_FOREACH(w, windows, &windows)
- layout_fix_panes(w, w->sx, w->sy);
+ layout_fix_panes(w);
}
RB_FOREACH(s, sessions, &sessions)
status_update_saved(s);
@@ -297,7 +298,8 @@ cmd_set_option_set(struct cmd *self, struct cmdq_item *item, struct options *oo,
int append = args_has(args, 'a');
struct options_entry *o;
long long number;
- const char *errstr;
+ const char *errstr, *new;
+ char *old;
key_code key;
oe = options_table_entry(parent);
@@ -310,7 +312,16 @@ cmd_set_option_set(struct cmd *self, struct cmdq_item *item, struct options *oo,
switch (oe->type) {
case OPTIONS_TABLE_STRING:
+ old = xstrdup(options_get_string(oo, oe->name));
options_set_string(oo, oe->name, append, "%s", value);
+ new = options_get_string(oo, oe->name);
+ if (oe->pattern != NULL && fnmatch(oe->pattern, new, 0) != 0) {
+ options_set_string(oo, oe->name, 0, "%s", old);
+ free(old);
+ cmdq_error(item, "value is invalid: %s", value);
+ return (-1);
+ }
+ free(old);
return (0);
case OPTIONS_TABLE_NUMBER:
number = strtonum(value, oe->minimum, oe->maximum, &errstr);
diff --git a/cmd-split-window.c b/cmd-split-window.c
index 7b58f81f..28821413 100644
--- a/cmd-split-window.c
+++ b/cmd-split-window.c
@@ -148,7 +148,7 @@ cmd_split_window_exec(struct cmd *self, struct cmdq_item *item)
}
environ_free(env);
- layout_fix_panes(w, w->sx, w->sy);
+ layout_fix_panes(w);
server_redraw_window(w);
if (!args_has(args, 'd')) {
diff --git a/cmd-swap-pane.c b/cmd-swap-pane.c
index 7283bf53..1de272c4 100644
--- a/cmd-swap-pane.c
+++ b/cmd-swap-pane.c
@@ -105,8 +105,6 @@ cmd_swap_pane_exec(struct cmd *self, struct cmdq_item *item)
window_set_active_pane(dst_w, src_wp);
} else {
tmp_wp = dst_wp;
- if (!window_pane_visible(tmp_wp))
- tmp_wp = src_wp;
window_set_active_pane(src_w, tmp_wp);
}
} else {
diff --git a/cmd-switch-client.c b/cmd-switch-client.c
index 180635df..6181073d 100644
--- a/cmd-switch-client.c
+++ b/cmd-switch-client.c
@@ -128,6 +128,7 @@ cmd_switch_client_exec(struct cmd *self, struct cmdq_item *item)
c->session = s;
if (~item->shared->flags & CMDQ_SHARED_REPEAT)
server_client_set_key_table(c, NULL);
+ tty_update_client_offset(c);
status_timer_start(c);
notify_client("client-session-changed", c);
session_update_activity(s, NULL);
diff --git a/cmd.c b/cmd.c
index b90d5ea2..9226e6c2 100644
--- a/cmd.c
+++ b/cmd.c
@@ -81,6 +81,7 @@ extern const struct cmd_entry cmd_refresh_client_entry;
extern const struct cmd_entry cmd_rename_session_entry;
extern const struct cmd_entry cmd_rename_window_entry;
extern const struct cmd_entry cmd_resize_pane_entry;
+extern const struct cmd_entry cmd_resize_window_entry;
extern const struct cmd_entry cmd_respawn_pane_entry;
extern const struct cmd_entry cmd_respawn_window_entry;
extern const struct cmd_entry cmd_rotate_window_entry;
@@ -167,6 +168,7 @@ const struct cmd_entry *cmd_table[] = {
&cmd_rename_session_entry,
&cmd_rename_window_entry,
&cmd_resize_pane_entry,
+ &cmd_resize_window_entry,
&cmd_respawn_pane_entry,
&cmd_respawn_window_entry,
&cmd_rotate_window_entry,
diff --git a/format.c b/format.c
index 126bbc14..21365457 100644
--- a/format.c
+++ b/format.c
@@ -52,8 +52,7 @@ static int format_replace(struct format_tree *, const char *, size_t,
static void format_defaults_session(struct format_tree *,
struct session *);
static void format_defaults_client(struct format_tree *, struct client *);
-static void format_defaults_winlink(struct format_tree *,
- struct winlink *);
+static void format_defaults_winlink(struct format_tree *, struct winlink *);
/* Entry in format job tree. */
struct format_job {
@@ -107,9 +106,10 @@ struct format_entry {
/* Format entry tree. */
struct format_tree {
- struct window *w;
- struct winlink *wl;
+ struct client *c;
struct session *s;
+ struct winlink *wl;
+ struct window *w;
struct window_pane *wp;
struct client *client;
@@ -1347,8 +1347,6 @@ format_defaults_session(struct format_tree *ft, struct session *s)
format_add(ft, "session_name", "%s", s->name);
format_add(ft, "session_windows", "%u", winlink_count(&s->windows));
- format_add(ft, "session_width", "%u", s->sx);
- format_add(ft, "session_height", "%u", s->sy);
format_add(ft, "session_id", "$%u", s->id);
sg = session_group_contains(s);
@@ -1383,6 +1381,7 @@ format_defaults_client(struct format_tree *ft, struct client *c)
if (ft->s == NULL)
ft->s = c->session;
+ ft->c = c;
format_add(ft, "client_name", "%s", c->name);
format_add(ft, "client_pid", "%ld", (long) c->pid);
@@ -1451,8 +1450,11 @@ format_defaults_window(struct format_tree *ft, struct window *w)
static void
format_defaults_winlink(struct format_tree *ft, struct winlink *wl)
{
+ struct client *c = ft->c;
struct session *s = wl->session;
struct window *w = wl->window;
+ int flag;
+ u_int ox, oy, sx, sy;
if (ft->w == NULL)
ft->w = wl->window;
@@ -1460,6 +1462,15 @@ format_defaults_winlink(struct format_tree *ft, struct winlink *wl)
format_defaults_window(ft, w);
+ if (c != NULL) {
+ flag = tty_window_offset(&c->tty, &ox, &oy, &sx, &sy);
+ format_add(ft, "window_bigger", "%d", flag);
+ if (flag) {
+ format_add(ft, "window_offset_x", "%u", ox);
+ format_add(ft, "window_offset_y", "%u", oy);
+ }
+ }
+
format_add(ft, "window_index", "%d", wl->idx);
format_add_cb(ft, "window_stack_index", format_cb_window_stack_index);
format_add(ft, "window_flags", "%s", window_printable_flags(wl));
@@ -1509,18 +1520,14 @@ format_defaults_pane(struct format_tree *ft, struct window_pane *wp)
format_add(ft, "pane_dead_status", "%d", WEXITSTATUS(status));
format_add(ft, "pane_dead", "%d", wp->fd == -1);
- if (window_pane_visible(wp)) {
- format_add(ft, "pane_left", "%u", wp->xoff);
- format_add(ft, "pane_top", "%u", wp->yoff);
- format_add(ft, "pane_right", "%u", wp->xoff + wp->sx - 1);
- format_add(ft, "pane_bottom", "%u", wp->yoff + wp->sy - 1);
- format_add(ft, "pane_at_left", "%d", wp->xoff == 0);
- format_add(ft, "pane_at_top", "%d", wp->yoff == 0);
- format_add(ft, "pane_at_right", "%d",
- wp->xoff + wp->sx == w->sx);
- format_add(ft, "pane_at_bottom", "%d",
- wp->yoff + wp->sy == w->sy);
- }
+ format_add(ft, "pane_left", "%u", wp->xoff);
+ format_add(ft, "pane_top", "%u", wp->yoff);
+ format_add(ft, "pane_right", "%u", wp->xoff + wp->sx - 1);
+ format_add(ft, "pane_bottom", "%u", wp->yoff + wp->sy - 1);
+ format_add(ft, "pane_at_left", "%d", wp->xoff == 0);
+ format_add(ft, "pane_at_top", "%d", wp->yoff == 0);
+ format_add(ft, "pane_at_right", "%d", wp->xoff + wp->sx == w->sx);
+ format_add(ft, "pane_at_bottom", "%d", wp->yoff + wp->sy == w->sy);
format_add(ft, "pane_in_mode", "%d", wp->screen != &wp->base);
if (wp->mode != NULL)
diff --git a/input-keys.c b/input-keys.c
index 34710dac..39401a38 100644
--- a/input-keys.c
+++ b/input-keys.c
@@ -248,10 +248,10 @@ input_key_mouse(struct window_pane *wp, struct mouse_event *m)
if ((mode & ALL_MOUSE_MODES) == 0)
return;
- if (!window_pane_visible(wp))
- return;
if (cmd_mouse_at(wp, m, &x, &y, 0) != 0)
return;
+ if (!window_pane_visible(wp))
+ return;
/* If this pane is not in button or all mode, discard motion events. */
if (MOUSE_DRAG(m->b) &&
diff --git a/key-bindings.c b/key-bindings.c
index c717f5ae..fbc54fb8 100644
--- a/key-bindings.c
+++ b/key-bindings.c
@@ -258,6 +258,11 @@ key_bindings_init(void)
"bind M-n next-window -a",
"bind M-o rotate-window -D",
"bind M-p previous-window -a",
+ "bind -r S-Up refresh-client -U 10",
+ "bind -r S-Down refresh-client -D 10",
+ "bind -r S-Left refresh-client -L 10",
+ "bind -r S-Right refresh-client -R 10",
+ "bind -r DC refresh-client -c",
"bind -r M-Up resize-pane -U 5",
"bind -r M-Down resize-pane -D 5",
"bind -r M-Left resize-pane -L 5",
diff --git a/key-string.c b/key-string.c
index bb49b59f..8442727d 100644
--- a/key-string.c
+++ b/key-string.c
@@ -43,7 +43,9 @@ static const struct {
{ "F11", KEYC_F11 },
{ "F12", KEYC_F12 },
{ "IC", KEYC_IC },
+ { "Insert", KEYC_IC },
{ "DC", KEYC_DC },
+ { "Delete", KEYC_DC },
{ "Home", KEYC_HOME },
{ "End", KEYC_END },
{ "NPage", KEYC_NPAGE },
diff --git a/layout-custom.c b/layout-custom.c
index 1b8f576e..9886afe1 100644
--- a/layout-custom.c
+++ b/layout-custom.c
@@ -167,7 +167,7 @@ layout_parse(struct window *w, const char *layout)
/* Update pane offsets and sizes. */
layout_fix_offsets(lc);
- layout_fix_panes(w, lc->sx, lc->sy);
+ layout_fix_panes(w);
/* Then resize the layout back to the original window size. */
layout_resize(w, sx, sy);
diff --git a/layout-set.c b/layout-set.c
index 5055f672..b9769ed5 100644
--- a/layout-set.c
+++ b/layout-set.c
@@ -148,7 +148,7 @@ layout_set_even(struct window *w, enum layout_type type)
/* Fix cell offsets. */
layout_fix_offsets(lc);
- layout_fix_panes(w, w->sx, w->sy);
+ layout_fix_panes(w);
layout_print_cell(w->layout_root, __func__, 1);
@@ -284,7 +284,7 @@ layout_set_main_h(struct window *w)
/* Fix cell offsets. */
layout_fix_offsets(lc);
- layout_fix_panes(w, w->sx, w->sy);
+ layout_fix_panes(w);
layout_print_cell(w->layout_root, __func__, 1);
@@ -408,7 +408,7 @@ layout_set_main_v(struct window *w)
/* Fix cell offsets. */
layout_fix_offsets(lc);
- layout_fix_panes(w, w->sx, w->sy);
+ layout_fix_panes(w);
layout_print_cell(w->layout_root, __func__, 1);
@@ -511,7 +511,7 @@ layout_set_tiled(struct window *w)
/* Fix cell offsets. */
layout_fix_offsets(lc);
- layout_fix_panes(w, w->sx, w->sy);
+ layout_fix_panes(w);
layout_print_cell(w->layout_root, __func__, 1);
diff --git a/layout.c b/layout.c
index 4ad645e0..89026b91 100644
--- a/layout.c
+++ b/