aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNicholas Marriott <nicholas.marriott@gmail.com>2018-08-20 15:22:14 +0100
committerNicholas Marriott <nicholas.marriott@gmail.com>2018-08-20 15:22:14 +0100
commit641191ab2047d1437d46dc0ae787346b74fddca5 (patch)
tree21844a1ed3a4b3bc987f8d967457d74f10c888d5
parentbf03197e185b8f274fa6681fbaf6d4237c2bfe4f (diff)
downloadrtmux-641191ab2047d1437d46dc0ae787346b74fddca5.tar.gz
rtmux-641191ab2047d1437d46dc0ae787346b74fddca5.tar.bz2
rtmux-641191ab2047d1437d46dc0ae787346b74fddca5.zip
Support for windows larger than the client.
This adds 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. 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). 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-width -x or -y. 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 higher memory use if you make a window that big. The minimum size is the size required for the current layout including borders. This change allows some code improvements, most notably that since windows can now never be cropped, that code can be removed from the layout code, and since panes can now never be outside the size of the window, window_pane_visible can be removed.
-rw-r--r--Makefile.am1
-rw-r--r--TODO12
-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-resize-window.c109
-rw-r--r--cmd-select-pane.c37
-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.c22
-rw-r--r--input-keys.c2
-rw-r--r--layout-custom.c2
-rw-r--r--layout-set.c8
-rw-r--r--layout.c65
-rw-r--r--options-table.c33
-rw-r--r--resize.c306
-rw-r--r--screen-redraw.c294
-rw-r--r--screen-write.c142
-rw-r--r--server-client.c48
-rw-r--r--server-fn.c1
-rw-r--r--session.c15
-rw-r--r--tmux.1104
-rw-r--r--tmux.h53
-rw-r--r--tty.c448
-rw-r--r--window.c54
29 files changed, 1276 insertions, 569 deletions
diff --git a/Makefile.am b/Makefile.am
index a57baa42..e62a161a 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -100,6 +100,7 @@ dist_tmux_SOURCES = \
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/TODO b/TODO
index 32afa197..4a92eee9 100644
--- a/TODO
+++ b/TODO
@@ -61,7 +61,6 @@
not attached to a cell at all. this could be the time to introduce
panelink to replace layout_cell
* way to set hints/limits about pane size for resizing
- * panning over window (window larger than visible)
* a mode where one application can cross two panes (ie x|y, width =
COLUMNS/2 but height = ROWS * 2)
* separate active panes for different clients
@@ -131,3 +130,14 @@
* finish hooks for notifys
* for session_closed, if no sessions at all, perhaps fake up a
temporary one
+
+- pan
+ * tty_window_offset should try to keep as much as active pane
+ visible as possible
+ * rather than centering cursor it might be better if only
+ moved offset when it gets close to an edge?
+ * a way to force offset to a particular part of window, scroll
+ around the window -- command resize-window -d -l -r -u to
+ move offset and a flag to go back to tracking - but there
+ is no per-client window data structure so it will have
+ to forget when the window is changed
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-resize-window.c b/cmd-resize-window.c
new file mode 100644
index 00000000..8c4bc3f6
--- /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_PANE_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..5cec82f2 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,15 +112,14 @@ 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);
}
if (args_has(args, 'm') || args_has(args, 'M')) {
- if (args_has(args, 'm') && !window_pane_visible(wp))
+ if (args_has(args, 'm'))
return (CMD_RETURN_NORMAL);
lastwp = marked_pane.wp;
@@ -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 378576ff..f5dde751 100644
--- a/cmd-split-window.c
+++ b/cmd-split-window.c
@@ -147,7 +147,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 e432ae4a..5df30798 100644
--- a/cmd.c
+++ b/cmd.c
@@ -80,6 +80,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;
@@ -166,6 +167,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 d3da9eb7..cea338a1 100644
--- a/format.c
+++ b/format.c
@@ -1330,8 +1330,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);
@@ -1492,18 +1490,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 85dc2591..d3ff0dc0 100644
--- a/input-keys.c
+++ b/input-keys.c
@@ -247,8 +247,6 @@ 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;
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 e1112ffa..c71dc7e5 100644
--- a/layout.c
+++ b/layout.c
@@ -253,71 +253,29 @@ layout_need_status(struct layout_cell *lc, int at_top)
/* Update pane offsets and sizes based on their cells. */
void
-layout_fix_panes(struct window *w, u_int wsx, u_int wsy)
+layout_fix_panes(struct window *w)
{
struct window_pane *wp;
struct layout_cell *lc;
- u_int sx, sy;
- int shift, status, at_top;
+ int shift, status;
status = options_get_number(w->options, "pane-border-status");
- at_top = (status == 1);
TAILQ_FOREACH(wp, &w->panes, entry) {
if ((lc = wp->layout_cell) == NULL)
continue;
if (status != 0)
- shift = layout_need_status(lc, at_top);
+ shift = layout_need_status(lc, status == 1);
else
shift = 0;
wp->xoff = lc->xoff;
wp->yoff = lc->yoff;
- if (shift && at_top)
+ if (shift && status == 1)
wp->yoff += 1;
- /*
- * Layout cells are limited by the smallest size of other cells
- * within the same row or column; if this isn't the case
- * resizing becomes difficult.
- *
- * However, panes do not have to take up their entire cell, so
- * they can be cropped to the window edge if the layout
- * overflows and they are partly visible.
- *
- * This stops cells being hidden unnecessarily.
- */
-
- /*
- * Work out the horizontal size. If the pane is actually
- * outside the window or the entire pane is already visible,
- * don't crop.
- */
- if (lc->xoff >= wsx || lc->xoff + lc->sx < wsx)
- sx = lc->sx;
- else {
- sx = wsx - lc->xoff;
- if (sx < 1)
- sx = lc->sx;
- }
-
- /*
- * Similarly for the vertical size; the minimum vertical size
- * is two because scroll regions cannot be one line.
- */
- if (lc->yoff >= wsy || lc->yoff + lc->sy < wsy)
- sy = lc->sy;
- else {
- sy = wsy - lc->yoff;
- if (sy < 2)
- sy = lc->sy;
- }
-
- if (shift)
- sy -= 1;
-
- window_pane_resize(wp, sx, sy);
+ window_pane_resize(wp, lc->sx, lc->sy - shift);
}
}
@@ -491,8 +449,7 @@ layout_init(struct window *w, struct window_pane *wp)
lc = w->layout_root = layout_create_cell(NULL);
layout_set_size(lc, w->sx, w->sy, 0, 0);
layout_make_leaf(lc, wp);
-
- layout_fix_panes(w, w->sx, w->sy);
+ layout_fix_panes(w);
}
void
@@ -550,7 +507,7 @@ layout_resize(struct window *w, u_int sx, u_int sy)
/* Fix cell offsets. */
layout_fix_offsets(lc);
- layout_fix_panes(w, sx, sy);
+ layout_fix_panes(w);
}
/* Resize a pane to an absolute size. */
@@ -610,7 +567,7 @@ layout_resize_layout(struct window *w, struct layout_cell *lc,
/* Fix cell offsets. */
layout_fix_offsets(w->layout_root);
- layout_fix_panes(w, w->sx, w->sy);
+ layout_fix_panes(w);
notify_window("window-layout-changed", w);
}
@@ -717,7 +674,7 @@ void
layout_assign_pane(struct layout_cell *lc, struct window_pane *wp)
{
layout_make_leaf(lc, wp);
- layout_fix_panes(wp->window, wp->window->sx, wp->window->sy);
+ layout_fix_panes(wp->window);
}
/* Calculate the new pane size for resized parent. */
@@ -1037,7 +994,7 @@ layout_close_pane(struct window_pane *wp)
/* Fix pane offsets and sizes. */
if (w->layout_root != NULL) {
layout_fix_offsets(w->layout_root);
- layout_fix_panes(w, w->sx, w->sy);
+ layout_fix_panes(w);
}
notify_window("window-layout-changed", w);
}
@@ -1094,7 +1051,7 @@ layout_spread_out(struct window_pane *wp)
do {
if (layout_spread_cell(w, parent)) {
layout_fix_offsets(parent);
- layout_fix_panes(w, w->sx, w->sy);
+ layout_fix_panes(w);
break;
}
} while ((parent = parent->parent) != NULL);
diff --git a/options-table.c b/options-table.c
index 2b6b794b..0776f0b7 100644
--- a/options-table.c
+++ b/options-table.c
@@ -59,6 +59,9 @@ static const char *options_table_pane_status_list[] = {
static const char *options_table_set_clipboard_list[] = {
"off", "external", "on", NULL
};
+static const char *options_table_window_size_list[] = {
+ "largest", "smallest", "manual", NULL
+};
/* Top-level options. */
const struct options_table_entry options_table[] = {
@@ -193,6 +196,13 @@ const struct options_table_entry options_table[] = {
.default_str = _PATH_BSHELL
},
+ { .name = "default-size",
+ .type = OPTIONS_TABLE_STRING,
+ .scope = OPTIONS_TABLE_SESSION,
+ .pattern = "[0-9]*x[0-9]*",
+ .default_str = "80x24"
+ },
+
{ .name = "destroy-unattached",
.type = OPTIONS_TABLE_FLAG,
.scope = OPTIONS_TABLE_SESSION,
@@ -588,22 +598,6 @@ const struct options_table_entry options_table[] = {
.default_num = 1
},
- { .name = "force-height",
- .type = OPTIONS_TABLE_NUMBER,
- .scope = OPTIONS_TABLE_WINDOW,
- .minimum = 0,
- .maximum = INT_MAX,
- .default_num = 0
- },
-
- { .name = "force-width",
- .type = OPTIONS_TABLE_NUMBER,
- .scope = OPTIONS_TABLE_WINDOW,
- .minimum = 0,
- .maximum = INT_MAX,
- .default_num = 0
- },
-
{ .name = "main-pane-height",
.type = OPTIONS_TABLE_NUMBER,
.scope = OPTIONS_TABLE_WINDOW,
@@ -770,6 +764,13 @@ const struct options_table_entry options_table[] = {
.default_str = "default"
},
+ { .name = "window-size",
+ .type = OPTIONS_TABLE_CHOICE,
+ .scope = OPTIONS_TABLE_WINDOW,
+ .choices = options_table_window_size_list,
+ .default_num = WINDOW_SIZE_LARGEST
+ },
+
{ .name = "window-style",
.type = OPTIONS_TABLE_STYLE,
.scope = OPTIONS_TABLE_WINDOW,
diff --git a/resize.c b/resize.c
index 1c9694da..faaa044d 100644
--- a/resize.c
+++ b/resize.c
@@ -22,144 +22,224 @@
#include "tmux.h"
-/*
- * Recalculate window and session sizes.
- *
- * Every session has the size of the smallest client it is attached to and
- * every window the size of the smallest session it is attached to.
- *
- * So, when a client is resized or a session attached to or detached from a
- * client, the window sizes must be recalculated. For each session, find the
- * small