aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-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
- * smallest client it is attached to, and resize it to that size. Then for
- * every window, find the smallest session it is attached to, resize it to that
- * size and clear and redraw every client with it as the current window.
- *
- * This is quite inefficient - better/additional data structures are needed
- * to make it better.
- */
+void
+resize_window(struct window *w, u_int sx, u_int sy)
+{
+ int zoomed;
+
+ /* Check size limits. */
+ if (sx < WINDOW_MINIMUM)
+ sx = WINDOW_MINIMUM;
+ if (sx > WINDOW_MAXIMUM)
+ sx = WINDOW_MAXIMUM;
+ if (sy < WINDOW_MINIMUM)
+ sy = WINDOW_MINIMUM;
+ if (sy > WINDOW_MAXIMUM)
+ sy = WINDOW_MAXIMUM;
+
+ /* If the window is zoomed, unzoom. */
+ zoomed = w->flags & WINDOW_ZOOMED;
+ if (zoomed)
+ window_unzoom(w);
+
+ /* Resize the layout first. */
+ layout_resize(w, sx, sy);
+
+ /* Resize the window, it can be no smaller than the layout. */
+ if (sx < w->layout_root->sx)
+ sx = w->layout_root->sx;
+ if (sy < w->layout_root->sy)
+ sy = w->layout_root->sy;
+ window_resize(w, sx, sy);
+
+ /* Restore the window zoom state. */
+ if (zoomed)
+ window_zoom(w->active);
+
+ tty_update_window_offset(w);
+ server_redraw_window(w);
+ notify_window("window-layout-changed", w);
+}
void
-recalculate_sizes(void)
+default_window_size(struct session *s, struct window *w, u_int *sx, u_int *sy,
+ int type)
{
- struct session *s;
- struct client *c;
- struct window *w;
- struct window_pane *wp;
- u_int ssx, ssy, has, limit, lines;
- int flag, is_zoomed, forced;
+ struct client *c;
+ u_int cx, cy;
+ const char *value;
- RB_FOREACH(s, sessions, &sessions) {
- lines = status_line_size(s);
+ if (type == -1)
+ type = options_get_number(global_w_options, "window-size");
+ if (type == WINDOW_SIZE_MANUAL)
+ goto manual;
- s->attached = 0;
- ssx = ssy = UINT_MAX;
+ if (type == WINDOW_SIZE_LARGEST) {
+ *sx = *sy = 0;
TAILQ_FOREACH(c, &clients, entry) {
- if (c->flags & CLIENT_SUSPENDED)
+ if (c->session == NULL)
continue;
- if ((c->flags & (CLIENT_CONTROL|CLIENT_SIZECHANGED)) ==
- CLIENT_CONTROL)
+ if (w != NULL && !session_has(c->session, w))
continue;
- if (c->session == s) {
- if (c->tty.sx < ssx)
- ssx = c->tty.sx;
- c->flags &= ~CLIENT_STATUSOFF;
- if (lines != 0 && lines + PANE_MINIMUM > c->tty.sy)
- c->flags |= CLIENT_STATUSOFF;
- if ((~c->flags & CLIENT_STATUSOFF) &&
- !(c->flags & CLIENT_CONTROL) &&
- c->tty.sy > lines &&
- c->tty.sy - lines < ssy)
- ssy = c->tty.sy - lines;
- else if (c->tty.sy < ssy)
- ssy = c->tty.sy;
- s->attached++;
- }
+ if (w == NULL && c->session != s)
+ continue;
+
+ cx = c->tty.sx;
+ cy = c->tty.sy - tty_status_lines(&c->tty);
+
+ if (cx > *sx)
+ *sx = cx;
+ if (cy > *sy)
+ *sy = cy;
}
- if (ssx == UINT_MAX || ssy == UINT_MAX)
- continue;
+ if (*sx == 0 || *sy == 0)
+ goto manual;
+ } else if (type == WINDOW_SIZE_SMALLEST) {
+ *sx = *sy = UINT_MAX;
+ TAILQ_FOREACH(c, &clients, entry) {
+ if (c->session == NULL)
+ continue;
+ if (w != NULL && !session_has(c->session, w))
+ continue;
+ if (w == NULL && c->session != s)
+ continue;
- if (lines != 0 && ssy == 0)
- ssy = lines;
+ cx = c->tty.sx;
+ cy = c->tty.sy - tty_status_lines(&c->tty);
- if (s->sx == ssx && s->sy == ssy)
- continue;
+ if (cx < *sx)
+ *sx = cx;
+ if (cy < *sy)
+ *sy = cy;
+ }
+ if (*sx == UINT_MAX || *sy == UINT_MAX)
+ goto manual;
+ }
+ goto done;
- log_debug("session $%u size %u,%u (was %u,%u)", s->id, ssx, ssy,
- s->sx, s->sy);
+manual:
+ value = options_get_string(s->options, "default-size");
+ if (sscanf(value, "%ux%u", sx, sy) != 2) {
+ *sx = 80;
+ *sy = 24;
+ }
- s->sx = ssx;
- s->sy = ssy;
+done:
+ if (*sx < WINDOW_MINIMUM)
+ *sx = WINDOW_MINIMUM;
+ if (*sx > WINDOW_MAXIMUM)
+ *sx = WINDOW_MAXIMUM;
+ if (*sy < WINDOW_MINIMUM)
+ *sy = WINDOW_MINIMUM;
+ if (*sy > WINDOW_MAXIMUM)
+ *sy = WINDOW_MAXIMUM;
+}
+void
+recalculate_sizes(void)
+{
+ struct session *s;
+ struct client *c;
+ struct window *w;
+ u_int sx, sy, cx, cy;
+ int flags, type, current, has, changed;
+
+ /*
+ * Clear attached count and update saved status line information for
+ * each session.
+ */
+ RB_FOREACH(s, sessions, &sessions) {
+ s->attached = 0;
status_update_saved(s);
}
+ /*
+ * Increment attached count and check the status line size for each
+ * client.
+ */
+ TAILQ_FOREACH(c, &clients, entry) {
+ if ((s = c->session) == NULL)
+ continue;
+
+ flags = c->flags;
+ if (flags & CLIENT_SUSPENDED)
+ continue;
+ if ((flags & CLIENT_CONTROL) && (~flags & CLIENT_SIZECHANGED))
+ continue;
+
+ if (c->tty.sy <= tty_status_lines(&c->tty))
+ c->flags |= CLIENT_STATUSOFF;
+ else
+ c->flags &= ~CLIENT_STATUSOFF;
+
+ s->attached++;
+ }
+
+ /* Walk each window and adjust the size. */
RB_FOREACH(w, windows, &windows) {
if (w->active == NULL)
continue;
- flag = options_get_number(w->options, "aggressive-resize");
+ log_debug("%s: @%u is %u,%u", __func__, w->id, w->sx, w->sy);
- ssx = ssy = UINT_MAX;
- RB_FOREACH(s, sessions, &sessions) {
- if (s->attached == 0)
- continue;
- if (flag)
- has = s->curw->window == w;
- else
- has = session_has(s, w);
- if (has) {
- if (s->sx < ssx)
- ssx = s->sx;
- if (s->sy < ssy)
- ssy = s->sy;
- }
- }
- if (ssx == UINT_MAX || ssy == UINT_MAX)
+ type = options_get_number(w->options, "window-size");
+ if (type == WINDOW_SIZE_MANUAL)
continue;
-
- forced = 0;
- limit = options_get_number(w->options, "force-width");
- if (limit >= PANE_MINIMUM && ssx > limit) {
- ssx = limit;
- forced |= WINDOW_FORCEWIDTH;
- }
- limit = options_get_number(w->options, "force-height");
- if (limit >= PANE_MINIMUM && ssy > limit) {
- ssy = limit;
- forced |= WINDOW_FORCEHEIGHT;
+ current = !options_get_number(w->options, "aggressive-resize");
+
+ changed = 1;
+ if (type == WINDOW_SIZE_LARGEST) {
+ sx = sy = 0;
+ TAILQ_FOREACH(c, &clients, entry) {
+ if ((s = c->session) == NULL)
+ continue;
+ if (current)
+ has = (s->curw->window == w);
+ else
+ has = session_has(s, w);
+ if (!has)
+ continue;
+
+ cx = c->tty.sx;
+ cy = c->tty.sy - tty_status_lines(&c->tty);
+
+ if (cx > sx)
+ sx = cx;
+ if (cy > sy)
+ sy = cy;
+ }
+ if (sx == 0 || sy == 0)
+ changed = 0;
+ } else if (type == WINDOW_SIZE_SMALLEST) {
+ sx = sy = UINT_MAX;
+ TAILQ_FOREACH(c, &clients, entry) {
+ if ((s = c->session) == NULL)
+ continue;
+ if (current)
+ has = (s->curw->window == w);
+ else
+ has = session_has(s, w);
+ if (!has)
+ continue;
+
+ cx = c->tty.sx;
+ cy = c->tty.sy - tty_status_lines(&c->tty);
+
+ if (cx < sx)
+ sx = cx;
+ if (cy < sy)
+ sy = cy;
+ }
+ if (sx == UINT_MAX || sy == UINT_MAX)
+ changed = 0;
}
+ if (w->sx == sx && w->sy == sy)
+ changed = 0;
- if (w->sx == ssx && w->sy == ssy)
+ if (!changed) {
+ tty_update_window_offset(w);
continue;
- log_debug("window @%u size %u,%u (was %u,%u)", w->id, ssx, ssy,
- w->sx, w->sy);
-
- w->flags &= ~(WINDOW_FORCEWIDTH|WINDOW_FORCEHEIGHT);
- w->flags |= forced;
-
- is_zoomed = w->flags & WINDOW_ZOOMED;
- if (is_zoomed)
- window_unzoom(w);
- layout_resize(w, ssx, ssy);
- window_resize(w, ssx, ssy);
- if (is_zoomed && window_pane_visible(w->active))
- window_zoom(w->active);
-
- /*
- * If the current pane is now not visible, move to the next
- * that is.
- */
- wp = w->active;
- while (!window_pane_visible(w->active)) {
- w->active = TAILQ_PREV(w->active, window_panes, entry);
- if (w->active == NULL)
- w->active = TAILQ_LAST(&w->panes, window_panes);
- if (w->active == wp)
- break;
}
- if (w->active == w->last)
- w->last = NULL;
-
- server_redraw_window(w);
- notify_window("window-layout-changed", w);
+ log_debug("%s: @%u changed to %u,%u", __func__, w->id, sx, sy);
+ resize_window(w, sx, sy);
}
}
diff --git a/screen-redraw.c b/screen-redraw.c
index 95774633..118830c7 100644
--- a/screen-redraw.c
+++ b/screen-redraw.c
@@ -33,11 +33,15 @@ struct screen_redraw_ctx {
u_int sx;
u_int sy;
+ u_int ox;
+ u_int oy;
};
static void screen_redraw_draw_borders(struct screen_redraw_ctx *);
static void screen_redraw_draw_panes(struct screen_redraw_ctx *);
static void screen_redraw_draw_status(struct screen_redraw_ctx *);
+static void screen_redraw_draw_pane(struct screen_redraw_ctx *,
+ struct window_pane *);
static void screen_redraw_draw_number(struct screen_redraw_ctx *,
struct window_pane *);
@@ -100,8 +104,6 @@ screen_redraw_cell_border(struct client *c, u_int px, u_int py)
/* Check all the panes. */
TAILQ_FOREACH(wp, &w->panes, entry) {
- if (!window_pane_visible(wp))
- continue;
if ((retval = screen_redraw_cell_border1(wp, px, py)) != -1)
return (!!retval);
}
@@ -126,9 +128,6 @@ screen_redraw_check_cell(struct client *c, u_int px, u_int py, int pane_status,
if (pane_status != CELL_STATUS_OFF) {
TAILQ_FOREACH(wp, &w->panes, entry) {
- if (!window_pane_visible(wp))
- continue;
-
if (pane_status == CELL_STATUS_TOP)
line = wp->yoff - 1;
else
@@ -141,8 +140,6 @@ screen_redraw_check_cell(struct client *c, u_int px, u_int py, int pane_status,
}
TAILQ_FOREACH(wp, &w->panes, entry) {
- if (!window_pane_visible(wp))
- continue;
*wpp = wp;
/* If outside the pane and its border, skip it. */
@@ -320,25 +317,54 @@ screen_redraw_draw_pane_status(struct screen_redraw_ctx *ctx)
{
struct client *c = ctx->c;
struct window *w = c->session->curw->window;
- struct options *oo = c->session->options;
struct tty *tty = &c->tty;
struct window_pane *wp;
- int spos;
- u_int yoff;
+ struct screen *s;
+ u_int i, x, width, xoff, yoff, size;
+
+ log_debug("%s: %s @%u", __func__, c->name, w->id);
- spos = options_get_number(oo, "status-position");
TAILQ_FOREACH(wp, &w->panes, entry) {
- if (!window_pane_visible(wp))
- continue;
+ s = &wp->status_screen;
+
+ size = wp->status_size;
if (ctx->pane_status == CELL_STATUS_TOP)
yoff = wp->yoff - 1;
else
yoff = wp->yoff + wp->sy;
- if (spos == 0)
- yoff += 1;
+ xoff = wp->xoff + 2;
+
+ if (xoff + size <= ctx->ox ||
+ xoff >= ctx->ox + ctx->sx ||
+ yoff < ctx->oy ||
+ yoff >= ctx->oy + ctx->sy)
+ continue;
+
+ if (xoff >= ctx->ox && xoff + size <= ctx->ox + ctx->sx) {
+ /* All visible. */
+ i = 0;
+ x = xoff - ctx->ox;
+ width = size;
+ } else if (xoff < ctx->ox && xoff + size > ctx->ox + ctx->sx) {
+ /* Both left and right not visible. */
+ i = ctx->ox;
+ x = 0;
+ width = ctx->sx;
+ } else if (xoff < ctx->ox) {
+ /* Left not visible. */
+ i = ctx->ox - xoff;
+ x = 0;
+ width = size - i;
+ } else {
+ /* Right not visible. */
+ i = 0;
+ x = xoff - ctx->ox;
+ width = size - (xoff + size - ctx->sx);
+ }
- tty_draw_line(tty, NULL, &wp->status_screen, 0, wp->xoff + 2,
- yoff);
+ if (ctx->top)
+ yoff += ctx->lines;
+ tty_draw_line(tty, NULL, s, i, 0, width, x, yoff - ctx->oy);
}
tty_cursor(tty, 0, 0);
}
@@ -385,13 +411,15 @@ screen_redraw_set_context(struct client *c, struct screen_redraw_ctx *ctx)
memset(ctx, 0, sizeof *ctx);
ctx->c = c;
- ctx->lines = tty_status_lines(c);
+ ctx->lines = tty_status_lines(&c->tty);
if (ctx->lines != 0 && options_get_number(oo, "status-position") == 0)
ctx->top = 1;
ctx->pane_status = options_get_number(wo, "pane-border-status");
- ctx->sx = c->tty.sx;
- ctx->sy = c->tty.sy - ctx->lines;
+ tty_window_offset(&c->tty, &ctx->ox, &ctx->oy, &ctx->sx, &ctx->sy);
+
+ log_debug("%s: %s @%u ox=%u oy=%u sx=%u sy=%u %u/%d", __func__, c->name,
+ w->id, ctx->ox, ctx->oy, ctx->sx, ctx->sy, ctx->lines, ctx->top);
}
/* Redraw entire screen. */
@@ -420,33 +448,23 @@ screen_redraw_screen(struct client *c)
tty_reset(&c->tty);
}
-/* Draw a single pane. */
+/* Redraw a single pane. */
void
screen_redraw_pane(struct client *c, struct window_pane *wp)
{
- u_int i, yoff;
-
- if (!window_pane_visible(wp))
- return;
-
- yoff = wp->yoff;
- if (status_at_line(c) == 0)
- yoff += status_line_size(c->session);
+ struct screen_redraw_ctx ctx;
- log_debug("%s: redraw pane %%%u (at %u,%u)", c->name, wp->id,
- wp->xoff, yoff);
+ screen_redraw_set_context(c, &ctx);
- for (i = 0; i < wp->sy; i++)
- tty_draw_pane(&c->tty, wp, i, wp->xoff, yoff);
+ screen_redraw_draw_pane(&ctx, wp);
tty_reset(&c->tty);
}
/* Draw a border cell. */
static void
-screen_redraw_draw_borders_cell(struct screen_redraw_ctx *ctx, u_int x, u_int y,
- int small, u_int msgx, u_int msgy, struct grid_cell *m_active_gc,
- struct grid_cell *active_gc, struct grid_cell *m_other_gc,
- struct grid_cell *other_gc)
+screen_redraw_draw_borders_cell(struct screen_redraw_ctx *ctx, u_int i, u_int j,
+ struct grid_cell *m_active_gc, struct grid_cell *active_gc,
+ struct grid_cell *m_other_gc, struct grid_cell *other_gc)
{
struct client *c = ctx->c;
struct session *s = c->session;
@@ -455,14 +473,12 @@ screen_redraw_draw_borders_cell(struct screen_redraw_ctx *ctx, u_int x, u_int y,
struct window_pane *wp;
struct window_pane *active = w->active;
struct window_pane *marked = marked_pane.wp;
- u_int type;
+ u_int type, x = ctx->ox + i, y = ctx->oy + j;
int flag, pane_status = ctx->pane_status;
type = screen_redraw_check_cell(c, x, y, pane_status, &wp);
if (type == CELL_INSIDE)
return;
- if (type == CELL_OUTSIDE && small && x > msgx && y == msgy)
- return;
flag = screen_redraw_check_is(x, y, type, pane_status, w, active, wp);
if (server_is_marked(s, s->curw, marked_pane.wp) &&
@@ -476,9 +492,9 @@ screen_redraw_draw_borders_cell(struct screen_redraw_ctx *ctx, u_int x, u_int y,
else
tty_attributes(tty, other_gc, NULL);
if (ctx->top)
- tty_cursor(tty, x, ctx->lines + y);
+ tty_cursor(tty, i, ctx->lines + j);
else
- tty_cursor(tty, x, y);
+ tty_cursor(tty, i, j);
tty_putc(tty, CELL_BORDERS[type]);
}
@@ -489,42 +505,12 @@ screen_redraw_draw_borders(struct screen_redraw_ctx *ctx)
struct client *c = ctx->c;
struct session *s = c->session;
struct window *w = s->curw->window;
- struct options *oo = w->options;
struct tty *tty = &c->tty;
+ struct options *oo = w->options;
struct grid_cell m_active_gc, active_gc, m_other_gc, other_gc;
- struct grid_cell msg_gc;
- u_int i, j, msgx = 0, msgy = 0;
- int small, flags;
- char msg[256];
- const char *tmp;
- size_t msglen = 0;
-
- small = (ctx->sy + ctx->top > w->sy) || (ctx->sx > w->sx);
- if (small) {
- flags = w->flags & (WINDOW_FORCEWIDTH|WINDOW_FORCEHEIGHT);
- if (flags == (WINDOW_FORCEWIDTH|WINDOW_FORCEHEIGHT))
- tmp = "force-width, force-height";
- else if (flags == WINDOW_FORCEWIDTH)
- tmp = "force-width";
- else if (flags == WINDOW_FORCEHEIGHT)
- tmp = "force-height";
- else if (c->flags & CLIENT_STATUSOFF)
- tmp = "status line";
- else
- tmp = "a smaller client";
- xsnprintf(msg, sizeof msg, "(size %ux%u from %s)",
- w->sx, w->sy, tmp);
- msglen = strlen(msg);
-
- if (ctx->sy - 1 + ctx->top > w->sy && ctx->sx >= msglen) {
- msgx = ctx->sx - msglen;
- msgy = ctx->sy - 1 + ctx->top;
- } else if (ctx->sx - w->sx > msglen) {
- msgx = ctx->sx - msglen;
- msgy = ctx->sy - 1 + ctx->top;
- } else
- small = 0;
- }
+ u_int i, j;
+
+ log_debug("%s: %s @%u", __func__, c->name, w->id);
style_apply(&other_gc, oo, "pane-border-style");
style_apply(&active_gc, oo, "pane-active-border-style");
@@ -535,20 +521,12 @@ screen_redraw_draw_borders(struct screen_redraw_ctx *ctx)
memcpy(&m_active_gc, &active_gc, sizeof m_active_gc);
m_active_gc.attr ^= GRID_ATTR_REVERSE;
- for (j = 0; j < ctx->sy; j++) {
- for (i = 0; i < ctx->sx; i++) {
- screen_redraw_draw_borders_cell(ctx, i, j, small,
- msgx, msgy, &m_active_gc, &active_gc, &m_other_gc,
- &other_gc);
+ for (j = 0; j < tty->sy - ctx->lines; j++) {
+ for (i = 0; i < tty->sx; i++) {
+ screen_redraw_draw_borders_cell(ctx, i, j,
+ &m_active_gc, &active_gc, &m_other_gc, &other_gc);
}
}
-
- if (small) {
- memcpy(&msg_gc, &grid_default_cell, sizeof msg_gc);
- tty_attributes(tty, &msg_gc, NULL);
- tty_cursor(tty, msgx, msgy);
- tty_puts(tty, msg);
- }
}
/* Draw the panes. */
@@ -557,19 +535,12 @@ screen_redraw_draw_panes(struct screen_redraw_ctx *ctx)
{
struct client *c = ctx->c;
struct window *w = c->session->curw->window;
- struct tty *tty = &c->tty;
struct window_pane *wp;
- u_int i, y;
- if (ctx->top)
- y = ctx->lines;
- else
- y = 0;
+ log_debug("%s: %s @%u", __func__, c->name, w->id);
+
TAILQ_FOREACH(wp, &w->panes, entry) {
- if (!window_pane_visible(wp))
- continue;
- for (i = 0; i < wp->sy; i++)
- tty_draw_pane(tty, wp, i, wp->xoff, y + wp->yoff);
+ screen_redraw_draw_pane(ctx, wp);
if (c->flags & CLIENT_IDENTIFY)
screen_redraw_draw_number(ctx, wp);
}
@@ -580,15 +551,74 @@ static void
screen_redraw_draw_status(struct screen_redraw_ctx *ctx)
{
struct client *c = ctx->c;
+ struct window *w = c->session->curw->window;
struct tty *tty = &c->tty;
+ struct screen *s = &c->status.status;
u_int i, y;
+ log_debug("%s: %s @%u", __func__, c->name, w->id);
+
if (ctx->top)
y = 0;
else
- y = ctx->sy;
+ y = c->tty.sy - ctx->lines;
for (i = 0; i < ctx->lines; i++)
- tty_draw_line(tty, NULL, &c->status.status, i, 0, y);
+ tty_draw_line(tty, NULL, s, 0, i, UINT_MAX, 0, y + i);
+}
+
+/* Draw one pane. */
+static void
+screen_redraw_draw_pane(struct screen_redraw_ctx *ctx, struct window_pane *wp)
+{
+ struct client *c = ctx->c;
+ struct window *w = c->session->curw->window;
+ struct tty *tty = &c->tty;
+ struct screen *s;
+ u_int i, j, top, x, y, width;
+
+ log_debug("%s: %s @%u %%%u", __func__, c->name, w->id, wp->id);
+
+ if (wp->xoff + wp->sx <= ctx->ox || wp->xoff >= ctx->ox + ctx->sx)
+ return;
+ if (ctx->top)
+ top = ctx->lines;
+ else
+ top = 0;
+
+ s = wp->screen;
+ for (j = 0; j < wp->sy; j++) {
+ if (wp->yoff + j < ctx->oy || wp->yoff + j >= ctx->oy + ctx->sy)
+ continue;
+ y = top + wp->yoff + j - ctx->oy;
+
+ if (wp->xoff >= ctx->ox &&
+ wp->xoff + wp->sx <= ctx->ox + ctx->sx) {
+ /* All visible. */
+ i = 0;
+ x = wp->xoff - ctx->ox;
+ width = wp->sx;
+ } else if (wp->xoff < ctx->ox &&
+ wp->xoff + wp->sx > ctx->ox + ctx->sx) {
+ /* Both left and right not visible. */
+ i = ctx->ox;
+ x = 0;
+ width = ctx->sx;
+ } else if (wp->xoff < ctx->ox) {
+ /* Left not visible. */
+ i = ctx->ox - wp->xoff;
+ x = 0;
+ width = wp->sx - i;
+ } else {
+ /* Right not visible. */
+ i = 0;
+ x = wp->xoff - ctx->ox;
+ width = wp->sx - (wp->xoff + wp->sx - ctx->sx);
+ }
+ log_debug("%s: %s %%%u line %u,%u at %u,%u, width %u",
+ __func__, c->name, wp->id, i, j, x, y, width);
+
+ tty_draw_line(tty, wp, s, i, j, width, x, y);
+ }
}
/* Draw number on a pane. */
@@ -601,27 +631,69 @@ screen_redraw_draw_number(struct screen_redraw_ctx *ctx, struct window_pane *wp)
struct options *oo = s->options;
struct window *w = wp->window;
struct grid_cell gc;
- u_int idx, px, py, i, j, xoff, yoff;
+ u_int idx, px, py, i, j, xoff, yoff, sx, sy;
int colour, active_colour;
char buf[16], *ptr;
size_t len;
+ if (wp->xoff + wp->sx <= ctx->ox ||
+ wp->xoff >= ctx->ox + ctx->sx ||
+ wp->yoff + wp->sy <= ctx->oy ||
+ wp->yoff >= ctx->oy + ctx->sy)
+ return;
+
+ if (wp->xoff >= ctx->ox && wp->xoff + wp->sx <= ctx->ox + ctx->sx) {
+ /* All visible. */
+ xoff = wp->xoff - ctx->ox;
+ sx = wp->sx;
+ } else if (wp->xoff < ctx->ox &&
+ wp->xoff + wp->sx > ctx->ox + ctx->sx) {
+ /* Both left and right not visible. */
+ xoff = 0;
+ sx = ctx->sx;
+ } else if (wp->xoff < ctx->ox) {
+ /* Left not visible. */
+ xoff = 0;
+ sx = wp->sx - (ctx->ox - wp->xoff);
+ } else {
+ /* Right not visible. */
+ xoff = wp->xoff - ctx->ox;
+ sx = wp->sx - (wp->xoff + wp->sx - ctx->sx);
+ }
+ if (wp->yoff >= ctx->oy && wp->yoff + wp->sy <= ctx->oy + ctx->sy) {
+ /* All visible. */
+ yoff = wp->yoff - ctx->oy;
+ sy = wp->sy;
+ } else if (wp->yoff < ctx->oy &&
+ wp->yoff + wp->sy > ctx->oy + ctx->sy) {
+ /* Both top and bottom not visible. */
+ yoff = 0;
+ sy = ctx->sy;
+ } else if (wp->yoff < ctx->oy) {
+ /* Top not visible. */
+ yoff = 0;
+ sy = wp->sy - (ctx->oy - wp->yoff);
+ } else {
+ /* Bottom not visible. */
+ yoff = wp->yoff - ctx->oy;
+ sy = wp->sy - (wp->yoff + wp->sy - ctx->sy);
+ }
+
+ if (ctx->top)
+ yoff += ctx->lines;
+ px = sx / 2;
+ py = sy / 2;
+
if (window_pane_index(wp, &idx) != 0)
fatalx("index not found");
len = xsnprintf(buf, sizeof buf, "%u", idx);
- if (wp->sx < len)
+ if (sx < len)
return;
colour = options_get_number(oo, "display-panes-colour");
active_colour = options_get_number(oo, "display-panes-active-colour");
- px = wp->sx / 2; py = wp->sy / 2;
- xoff = wp->xoff; yoff = wp->yoff;
-
- if (ctx->top)
- yoff += ctx->lines;
-
- if (wp->sx < len * 6 || wp->sy < 5) {
+ if (sx < len * 6 || sy < 5) {
tty_cursor(tty, xoff + px - len / 2, yoff + py);
goto draw_text;
}
@@ -653,9 +725,9 @@ screen_redraw_draw_number(struct screen_redraw_ctx *ctx, struct window_pane *wp)
}
len = xsnprintf(buf, sizeof buf, "%ux%u", wp->sx, wp->sy);
- if (wp->sx < len || wp->sy < 6)
+ if (sx < len || sy < 6)
return;
- tty_cursor(tty, xoff + wp->sx - len, yoff);
+ tty_cursor(tty, xoff + sx - len, yoff);
draw_text:
memcpy(&gc, &grid_default_cell, sizeof gc);
diff --git a/screen-write.c b/screen-write.c
index fac5229e..b9db16a9 100644
--- a/screen-write.c
+++ b/screen-write.c
@@ -54,6 +54,41 @@ struct screen_write_collect_line {
TAILQ_HEAD(, screen_write_collect_item) items;
};
+static void
+screen_write_offset_timer(__unused int fd, __unused short events, void *data)
+{
+ struct window *w = data;
+
+ tty_update_window_offset(w);
+}
+
+/* Set cursor position. */
+static void
+screen_write_set_cursor(struct screen_write_ctx *ctx, int cx, int cy)
+{
+ struct window_pane *wp = ctx->wp;
+ struct window *w;
+ struct screen *s = ctx->s;
+ struct timeval tv = { .tv_usec = 10000 };
+
+ if (cx != -1 && (u_int)cx == s->cx && cy != -1 && (u_int)cy == s->cy)
+ return;
+
+ if (cx != -1)
+ s->cx = cx;
+ if (cy != -1)
+ s->cy = cy;
+
+ if (wp == NULL)
+ return;
+ w = wp->window;
+
+ if (!event_initialized(&w->offset_timer))
+ evtimer_set(&w->offset_timer, screen_write_offset_timer, w);
+ if (!evtimer_pending(&w->offset_timer, NULL))
+ evtimer_add(&w->offset_timer, &tv);
+}
+
/* Initialize writing with a window. */
void
screen_write_start(struct screen_write_ctx *ctx, struct window_pane *wp,
@@ -603,25 +638,26 @@ void
screen_write_cursorup(struct screen_write_ctx *ctx, u_int ny)
{
struct screen *s = ctx->s;
+ u_int cx = s->cx, cy = s->cy;
if (ny == 0)
ny = 1;
- if (s->cy < s->rupper) {
+ if (cy < s->rupper) {
/* Above region. */
- if (ny > s->cy)
- ny = s->cy;
+ if (ny > cy)
+ ny = cy;
} else {
/* Below region. */
- if (ny > s->cy - s->rupper)
- ny = s->cy - s->rupper;
+ if (ny > cy - s->rupper)
+ ny = cy - s->rupper;
}
- if (s->cx == screen_size_x(s))
- s->cx--;
- if (ny == 0)
- return;
+ if (cx == screen_size_x(s))
+ cx--;
+
+ cy -= ny;
- s->cy -= ny;
+ screen_write_set_cursor(ctx, cx, cy);
}
/* Cursor down by ny. */
@@ -629,25 +665,28 @@ void
screen_write_cursordown(struct screen_write_ctx *ctx, u_int ny)
{
struct screen *s = ctx->s;
+ u_int cx = s->cx, cy = s->cy;
if (ny == 0)
ny = 1;
- if (s->cy > s->rlower) {
+ if (cy > s->rlower) {
/* Below region. */
- if (ny > screen_size_y(s) - 1 - s->cy)
- ny = screen_size_y(s) - 1 - s->cy;
+ if (ny > screen_size_y(s) - 1 - cy)
+ ny = screen_size_y(s) - 1 - cy;
} else {
/* Above region. */
- if (ny > s->rlower - s->cy)
- ny = s->rlower - s->cy;
+ if (ny > s->rlower - cy)
+ ny = s->rlower - cy;
}
- if (s->cx == screen_size_x(s))
- s->cx--;
- if (ny == 0)
+ if (cx == screen_size_x(s))
+ cx--;
+ else if (ny == 0)
return;
- s->cy += ny;
+ cy += ny;
+
+ screen_write_set_cursor(ctx, cx, cy);
}
/* Cursor right by nx. */
@@ -655,16 +694,19 @@ void
screen_write_cursorright(struct screen_write_ctx *ctx, u_int nx)
{
struct screen *s = ctx->s;
+ u_int cx = s->cx, cy = s->cy;
if (nx == 0)
nx = 1;
- if (nx > screen_size_x(s) - 1 - s->cx)
- nx = screen_size_x(s) - 1 - s->cx;
+ if (nx > screen_size_x(s) - 1 - cx)
+ nx = screen_size_x(s) - 1 - cx;
if (nx == 0)
return;
- s->cx += nx;
+ cx += nx;
+
+ screen_write_set_cursor(ctx, cx, cy);
}
/* Cursor left by nx. */
@@ -672,16 +714,19 @@ void
screen_write_cursorleft(struct screen_write_ctx *ctx, u_int nx)
{
struct screen *s = ctx->s;
+ u_int cx = s->cx, cy = s->cy;
if (nx == 0)
nx = 1;
- if (nx > s->cx)
- nx = s->cx;
+ if (nx > cx)
+ nx = cx;
if (nx == 0)
return;
- s->cx -= nx;
+ cx -= nx;
+
+ screen_write_set_cursor(ctx, cx, cy);
}
/* Backspace; cursor left unless at start of wrapped line when can move up. */
@@ -690,17 +735,20 @@ screen_write_backspace(struct screen_write_ctx *ctx)
{
struct screen *s = ctx->s;
struct grid_line *gl;
+ u_int cx = s->cx, cy = s->cy;
- if (s->cx == 0) {
- if (s->cy == 0)
+ if (cx == 0) {
+ if (cy == 0)
return;
- gl = grid_get_line(s->grid, s->grid->hsize + s->cy - 1);
+ gl = grid_get_line(s->grid, s->grid->hsize + cy - 1);
if (gl->flags & GRID_LINE_WRAPPED) {
- s->cy--;
- s->cx = screen_size_x(s) - 1;
+ cy--;
+ cx = screen_size_x(s) - 1;
}
} else
- s->cx--;
+ cx--;
+
+ screen_write_set_cursor(ctx, cx, cy);
}
/* VT100 alignment test. */
@@ -712,8 +760,6 @@ screen_write_alignmenttest(struct screen_write_ctx *ctx)
struct grid_cell gc;
u_int xx, yy;
- screen_write_initctx(ctx, &ttyctx);
-
memcpy(&gc, &grid_default_cell, sizeof gc);
utf8_set(&gc.data, 'E');
@@ -722,8 +768,7 @@ screen_write_alignmenttest(struct screen_write_ctx *ctx)
grid_view_set_cell(s->grid, xx, yy, &gc);
}
- s->cx = 0;
- s->cy = 0;
+ screen_write_set_cursor(ctx, 0, 0);
s->rupper = 0;
s->rlower = screen_size_y(s) - 1;
@@ -988,8 +1033,7 @@ screen_write_cursormove(struct screen_write_ctx *ctx, u_int px, u_int py)
if (py > screen_size_y(s) - 1)
py = screen_size_y(s) - 1;
- s->cx = px;
- s->cy = py;
+ screen_write_set_cursor(ctx, px, py);
}
/* Reverse index (up with scroll). */
@@ -1005,7 +1049,7 @@ screen_write_reverseindex(struct screen_write_ctx *ctx, u_int bg)
if (s->cy == s->rupper)
grid_view_scroll_region_down(s->grid, s->rupper, s->rlower, bg);
else if (s->cy > 0)
- s->cy--;
+ screen_write_set_cursor(ctx, -1, s->cy - 1);
screen_write_collect_flush(ctx, 0);
tty_write(tty_cmd_reverseindex, &ttyctx);
@@ -1028,8 +1072,7 @@ screen_write_scrollregion(struct screen_write_ctx *ctx, u_int rupper,
screen_write_collect_flush(ctx, 0);
/* Cursor moves to top-left. */
- s->cx = 0;
- s->cy = 0;
+ screen_write_set_cursor(ctx, 0, 0);
s->rupper = rupper;
s->rlower = rlower;
@@ -1062,7 +1105,7 @@ screen_write_linefeed(struct screen_write_ctx *ctx, int wrapped, u_int bg)
screen_write_collect_scroll(ctx);
ctx->scrolled++;
} else if (s->cy < screen_size_y(s) - 1)
- s->cy++;
+ screen_write_set_cursor(ctx, -1, s->cy + 1);
}
/* Scroll up. */
@@ -1094,9 +1137,7 @@ screen_write_scrollup(struct screen_write_ctx *ctx, u_int lines, u_int bg)
void
screen_write_carriagereturn(struct screen_write_ctx *ctx)
{
- struct screen *s = ctx->s;
-
- s->cx = 0;
+ screen_write_set_cursor(ctx, 0, -1);
}
/* Clear to end of screen from cursor. */
@@ -1300,14 +1341,15 @@ screen_write_collect_end(struct screen_write_ctx *ctx)
grid_view_set_cell(s->grid, xx, s->cy,
&grid_default_cell);
}
- if (gc.data.width > 1)
+ if (gc.data.width > 1) {
grid_view_set_cell(s->grid, xx, s->cy,
&grid_default_cell);
+ }
}
memcpy(&gc, &ci->gc, sizeof gc);
grid_view_set_cells(s->grid, s->cx, s->cy, &gc, ci->data, ci->used);
- s->cx += ci->used;
+ screen_write_set_cursor(ctx, s->cx + ci->used, -1);
for (xx = s->cx; xx < screen_size_x(s); xx++) {
grid_view_get_cell(s->grid, xx, s->cy, &gc);
@@ -1361,7 +1403,7 @@ screen_write_collect_add(struct screen_write_ctx *ctx,
log_debug("%s: wrapped at %u,%u", __func__, s->cx, s->cy);
ci->wrapped = 1;
screen_write_linefeed(ctx, 1, 8);
- s->cx = 0;
+ screen_write_set_cursor(ctx, 0, -1);
}
if (ci->used == 0)
@@ -1423,7 +1465,7 @@ screen_write_cell(struct screen_write_ctx *ctx, const struct grid_cell *gc)
if ((s->mode & MODE_WRAP) && s->cx > sx - width) {
log_debug("%s: wrapped at %u,%u", __func__, s->cx, s->cy);
screen_write_linefeed(ctx, 1, 8);
- s->cx = 0;
+ screen_write_set_cursor(ctx, 0, -1);
screen_write_collect_flush(ctx, 1);
}
@@ -1496,9 +1538,9 @@ screen_write_cell(struct screen_write_ctx *ctx, const struct grid_cell *gc)
*/
last = !(s->mode & MODE_WRAP);
if (s->cx <= sx - last - width)
- s->cx += width;
+ screen_write_set_cursor(ctx, s->cx + width, -1);
else
- s->cx = sx - last;
+ screen_write_set_cursor(ctx, sx - last, -1);
/* Create space for character in insert mode. */
if (s->mode & MODE_INSERT) {
diff --git a/server-client.c b/server-client.c
index 72efe736..49a4b37d 100644
--- a/server-client.c
+++ b/server-client.c
@@ -192,6 +192,7 @@ server_client_create(int fd)
c->session = NULL;
c->last_session = NULL;
+
c->tty.sx = 80;
c->tty.sy = 24;
@@ -409,7 +410,7 @@ server_client_check_mouse(struct client *c)
struct mouse_event *m = &c->tty.mouse;
struct window *w;
struct window_pane *wp;
- u_int x, y, b;
+ u_int x, y, b, sx, sy;
int flag;
key_code key;
struct timeval tv;
@@ -419,8 +420,8 @@ server_client_check_mouse(struct client *c)
type = NOTYPE;
where = NOWHERE;
- log_debug("mouse %02x at %u,%u (last %u,%u) (%d)", m->b, m->x, m->y,
- m->lx, m->ly, c->tty.mouse_drag_flag);
+ log_debug("%s mouse %02x at %u,%u (last %u,%u) (%d)", c->name, m->b,
+ m->x, m->y, m->lx, m->ly, c->tty.mouse_drag_flag);
/* What type of event is this? */
if ((m->sgr_type != ' ' &&
@@ -439,7 +440,7 @@ server_client_check_mouse(struct client *c)
x = m->x, y = m->y, b = m->b;
log_debug("drag update at %u,%u", x, y);
} else {
- x = m->lx, y = m->ly, b = m->lb;
+ x = m->lx - m->ox, y = m->ly - m->oy, b = m->lb;
log_debug("drag start at %u,%u", x, y);
}
} else if (MOUSE_WHEEL(m->b)) {
@@ -514,6 +515,14 @@ have_event:
else if (m->statusat > 0 && y >= (u_int)m->statusat)
y = m->statusat - 1;
+ tty_window_offset(&c->tty, &m->ox, &m->oy, &sx, &sy);
+ log_debug("mouse window @%u at %u,%u (%ux%u)",
+ s->curw->window->id, m->ox, m->oy, sx, sy);
+ if (x > sx || y > sy)
+ return (KEYC_UNKNOWN);
+ x = m->x = x + m->ox;
+ y = m->y = y + m->oy;
+
TAILQ_FOREACH(wp, &s->curw->window->panes, entry) {
if ((wp->xoff + wp->sx == x &&
wp->yoff <= 1 + y &&
@@ -836,8 +845,6 @@ server_client_handle_key(struct client *c, key_code key)
return;
window_unzoom(w);
wp = window_pane_at_index(w, key - '0');
- if (wp != NULL && !window_pane_visible(wp))
- wp = NULL;
server_client_clear_identify(c, wp);
return;
}
@@ -1224,28 +1231,37 @@ server_client_reset_state(struct client *c)
struct window_pane *wp = w->active, *loop;
struct screen *s = wp->screen;
struct options *oo = c->session->options;
- int lines, mode;
+ int mode, cursor = 0;
+ u_int cx = 0, cy = 0, ox, oy, sx, sy;
if (c->flags & (CLIENT_CONTROL|CLIENT_SUSPENDED))
return;
+ mode = s->mode;
tty_region_off(&c->tty);
tty_margin_off(&c->tty);
- if (status_at_line(c) != 0)
- lines = 0;
- else
- lines = status_line_size(c->session);
- if (!window_pane_visible(wp) || wp->yoff + s->cy >= c->tty.sy - lines)
- tty_cursor(&c->tty, 0, 0);
- else
- tty_cursor(&c->tty, wp->xoff + s->cx, lines + wp->yoff + s->cy);
+ /* Move cursor to pane cursor and offset. */
+ cursor = 0;
+ tty_window_offset(&c->tty, &ox, &oy, &sx, &sy);
+ if (wp->xoff + s->cx >= ox && wp->xoff + s->cx <= ox + sx &&
+ wp->yoff + s->cy >= oy && wp->yoff + s->cy <= oy + sy) {
+ cursor = 1;
+
+ cx = wp->xoff + s->cx - ox;
+ cy = wp->yoff + s->cy - oy;
+
+ if (status_at_line(c) == 0)
+ cy += status_line_size(c->session);
+ }
+ if (!cursor)
+ mode &= ~MODE_CURSOR;
+ tty_cursor(&c->tty, cx, cy);
/*
* Set mouse mode if requested. To support dragging, always use button
* mode.
*/
- mode = s->mode;
if (options_get_number(oo, "mouse")) {
mode &= ~ALL_MOUSE_MODES;
TAILQ_FOREACH(loop, &w->panes, entry) {
diff --git a/server-fn.c b/server-fn.c
index a434c53e..9c348341 100644
--- a/server-fn.c
+++ b/server-fn.c
@@ -410,6 +410,7 @@ server_destroy_session(struct session *s)
c->last_session = NULL;
c->session = s_new;
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_new, NULL);
diff --git a/session.c b/session.c
index 2075abe5..a1c8ddae 100644
--- a/session.c
+++ b/session.c
@@ -112,8 +112,8 @@ session_find_by_id(u_int id)
/* Create a new session. */
struct session *
session_create(const char *prefix, const char *name, int argc, char **argv,
- const char *path, const char *cwd, struct environ *env, struct termios *tio,
- int idx, u_int sx, u_int sy, char **cause)
+ const char *path, const char *cwd, struct environ *env, struct options *oo,
+ struct termios *tio, int idx, char **cause)
{
struct session *s;
struct winlink *wl;
@@ -132,7 +132,7 @@ session_create(const char *prefix, const char *name, int argc, char **argv,
if (env != NULL)
environ_copy(env, s->environ);
- s->options = options_create(global_s_options);
+ s->options = oo;
s->hooks = hooks_create(global_hooks);
status_update_saved(s);
@@ -143,9 +143,6 @@ session_create(const char *prefix, const char *name, int argc, char **argv,
memcpy(s->tio, tio, sizeof *s->tio);
}
- s->sx = sx;
- s->sy = sy;
-
if (name != NULL) {
s->name = xstrdup(name);
s->id = next_session_id++;
@@ -349,7 +346,7 @@ session_new(struct session *s, const char *name, int argc, char **argv,
struct winlink *wl;
struct environ *env;
const char *shell;
- u_int hlimit;
+ u_int hlimit, sx, sy;
if ((wl = winlink_add(&s->windows, idx)) == NULL) {
xasprintf(cause, "index in use: %d", idx);
@@ -361,10 +358,11 @@ session_new(struct session *s, const char *name, int argc, char **argv,
if (*shell == '\0' || areshell(shell))
shell = _PATH_BSHELL;
+ default_window_size(s, NULL, &sx, &sy, -1);
hlimit = options_get_number(s->options, "history-limit");
env = environ_for_session(s, 0);
w = window_create_spawn(name, argc, argv, path, shell, cwd, env, s->tio,
- s->sx, s->sy, hlimit, cause);
+ sx, sy, hlimit, cause);
if (w == NULL) {
winlink_remove(&s->windows, wl);
environ_free(env);
@@ -547,6 +545,7 @@ session_set_current(struct session *s, struct winlink *wl)
s->curw = wl;
winlink_clear_flags(wl);
window_update_activity(wl->window);
+ tty_update_window_offset(wl->window);
notify_session("session-window-changed", s);
return (0);
}
diff --git a/tmux.1 b/tmux.1
index ca7d0c52..fd81cc22 100644
--- a/tmux.1
+++ b/tmux.1
@@ -628,13 +628,13 @@ refers to a
.Nm
command, passed with the command and arguments separately, for example:
.Bd -literal -offset indent
-bind-key F1 set-window-option force-width 81
+bind-key F1 set-window-option synchronize-panes on
.Ed
.Pp
Or if using
.Xr sh 1 :
.Bd -literal -offset indent
-$ tmux bind-key F1 set-window-option force-width 81
+$ tmux bind-key F1 set-window-option synchronize-panes on
.Ed
.Pp
Multiple commands may be specified together as part of a
@@ -850,13 +850,22 @@ and
are the name of and shell command to execute in the initial window.
With
.Fl d ,
-the initial size is 80 x 24;
+the initial size comes from the global
+.Ar default-size
+option;
.Fl x
and
.Fl y
can be used to specify a different size.
.Ql -
uses the size of the current client if any.
+If
+.Fl x
+or
+.Fl y
+is given, the
+.Ar default-size
+option is set for the session.
.Pp
If run from a terminal, any
.Xr termios 4
@@ -1916,6 +1925,40 @@ and unzoomed (its normal position in the layout).
.Fl M
begins mouse resizing (only valid if bound to a mouse key binding, see
.Sx MOUSE SUPPORT ) .
+.It Xo Ic resize-window
+.Op Fl aADLU
+.Op Fl t Ar target-window
+.Op Fl x Ar width
+.Op Fl y Ar height
+.Op Ar adjustment
+.Xc
+.D1 (alias: Ic resizew )
+Resize a window, up, down, left or right by
+.Ar adjustment
+with
+.Fl U ,
+.Fl D ,
+.Fl L
+or
+.Fl R ,
+to an absolute size
+with
+.Fl x
+or
+.Fl y ,
+or to the size of the smallest or largest session (with
+.Fl a
+or
+.Fl A ) .
+The
+.Ar adjustment
+is given in lines or cells (the default is 1).
+.Pp
+This command automatically sets the
+.Ic window-size
+option to
+.Ar manual
+for the window.
.It Xo Ic respawn-pane
.Op Fl c Ar start-directory
.Op Fl k
@@ -2659,6 +2702,16 @@ The default is an empty string, which instructs
to create a login shell using the value of the
.Ic default-shell
option.
+.It Ic default-size Ar XxY
+Set the default size of new windows when the
+.Ar window-size
+option is set to manual or when a session is created with
+.Ic new-session
+.Fl d .
+The value is the width and height separated by an
+.Ql x
+character.
+The default is 80x24.
.It Ic default-shell Ar path
Specify the default shell.
This is used as the login shell for new windows when the
@@ -3055,10 +3108,13 @@ Supported window options are:
Aggressively resize the chosen window.
This means that
.Nm
-will resize the window to the size of the smallest session for which it is the
-current window, rather than the smallest session to which it is attached.
-The window may resize when the current window is changed on another sessions;
-this option is good for full-screen programs which support
+will resize the window to the size of the smallest or largest session
+(see the
+.Ic window-size
+option) for which it is the current window, rather than the session to
+which it is attached.
+The window may resize when the current window is changed on another
+session; this option is good for full-screen programs which support
.Dv SIGWINCH
and poor for interactive programs such as shells.
.Pp
@@ -3121,16 +3177,6 @@ Set clock colour.
.Xc
Set clock hour format.
.Pp
-.It Ic force-height Ar height
-.It Ic force-width Ar width
-Prevent
-.Nm
-from resizing a window to greater than
-.Ar width
-or
-.Ar height .
-A value of zero restores the default unlimited setting.
-.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
@@ -3310,6 +3356,28 @@ see the
.Ic message-command-style
option.
.Pp
+.It Xo Ic Ic window-size
+.Ar largest | Ar smallest | Ar manual
+.Xc
+Configure how
+.Nm
+determines the window size.
+If set to
+.Ar largest ,
+the size of the largest attached session is used; if
+.Ar smallest ,
+the size of the smallest.
+If
+.Ar manual ,
+the size of a new window is set from the
+.Ic default-size
+option and windows are resized automatically.
+See also the
+.Ic resize-window
+command and the
+.Ic aggressive-resize
+option.
+.Pp
.It Ic window-style Ar style
Set the default window style.
For how to specify
@@ -3801,12 +3869,10 @@ The following variables are available, where appropriate:
.It Li "session_group_size" Ta "" Ta "Size of session group"
.It Li "session_group_list" Ta "" Ta "List of sessions in group"
.It Li "session_grouped" Ta "" Ta "1 if session in a group"
-.It Li "session_height" Ta "" Ta "Height of session"
.It Li "session_id" Ta "" Ta "Unique session ID"
.It Li "session_many_attached" Ta "" Ta "1 if multiple clients attached"
.It Li "session_name" Ta "#S" Ta "Name of session"
.It Li "session_stack" Ta "" Ta "Window indexes in most recent order"
-.It Li "session_width" Ta "" Ta "Width of session"
.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"
diff --git a/tmux.h b/tmux.h
index 5f6d3050..2ae71af9 100644
--- a/tmux.h
+++ b/tmux.h
@@ -68,6 +68,10 @@ struct tmuxproc;
*/
#define PANE_MINIMUM 2
+/* Minimum and maximum window size. */
+#define WINDOW_MINIMUM PANE_MINIMUM
+#define WINDOW_MAXIMUM 10000
+
/* Automatic name refresh interval, in microseconds. Must be < 1 second. */
#define NAME_INTERVAL 500000
@@ -809,6 +813,7 @@ struct window {
struct timeval name_time;
struct event alerts_timer;
+ struct event offset_timer;
struct timeval activity_time;
@@ -829,9 +834,7 @@ struct window {
#define WINDOW_ACTIVITY 0x2
#define WINDOW_SILENCE 0x4
#define WINDOW_ZOOMED 0x8
-#define WINDOW_FORCEWIDTH 0x10
-#define WINDOW_FORCEHEIGHT 0x20
-#define WINDOW_STYLECHANGED 0x40
+#define WINDOW_STYLECHANGED 0x10
#define WINDOW_ALERTFLAGS (WINDOW_BELL|WINDOW_ACTIVITY|WINDOW_SILENCE)
int alerts_queued;
@@ -872,6 +875,11 @@ struct winlink {
RB_HEAD(winlinks, winlink);
TAILQ_HEAD(winlink_stack, winlink);
+/* Window size option. */
+#define WINDOW_SIZE_LARGEST 0
+#define WINDOW_SIZE_SMALLEST 1
+#define WINDOW_SIZE_MANUAL 2
+
/* Layout direction. */
enum layout_type {
LAYOUT_LEFTRIGHT,
@@ -930,9 +938,6 @@ struct session {
struct event lock_timer;
- u_int sx;
- u_int sy;
-
struct winlink *curw;
struct winlink_stack lastw;
struct winlinks windows;
@@ -992,6 +997,9 @@ struct mouse_event {
u_int ly;
u_int lb;
+ u_int ox;
+ u_int oy;
+
int s;
int w;
int wp;
@@ -1039,6 +1047,12 @@ struct tty {
u_int cstyle;
char *ccolour;
+ int oflag;
+ u_int oox;
+ u_int ooy;
+ u_int osx;
+ u_int osy;
+
int mode;
u_int rlower;
@@ -1119,11 +1133,19 @@ struct tty_ctx {
u_int orupper;
u_int orlower;
+ /* Pane offset. */
u_int xoff;
u_int yoff;
/* The background colour used for clearing (erasing). */
u_int bg;
+
+ /* Window offset and size. */
+ int bigger;
+ u_int ox;
+ u_int oy;
+ u_int sx;
+ u_int sy;
};
/* Saved message entry. */
@@ -1456,6 +1478,7 @@ struct options_table_entry {
const char *separator;
const char *style;
+ const char *pattern;
};
/* Common command usages. */
@@ -1647,7 +1670,11 @@ struct environ *environ_for_session(struct session *, int);
/* tty.c */
void tty_create_log(void);
-u_int tty_status_lines(struct client *);
+int tty_window_bigger(struct tty *);
+int tty_window_offset(struct tty *, u_int *, u_int *, u_int *, u_int *);
+void tty_update_window_offset(struct window *);
+void tty_update_client_offset(struct client *);
+u_int tty_status_lines(struct tty *);
void tty_raw(struct tty *, const char *);
void tty_attributes(struct tty *, const struct grid_cell *,
const struct window_pane *);
@@ -1672,10 +1699,8 @@ void tty_start_tty(struct tty *);
void tty_stop_tty(struct tty *);
void tty_set_title(struct tty *, const char *);
void tty_update_mode(struct tty *, int, struct screen *);
-void tty_draw_pane(struct tty *, const struct window_pane *, u_int, u_int,
- u_int);
void tty_draw_line(struct tty *, const struct window_pane *, struct screen *,
- u_int, u_int, u_int);
+ u_int, u_int, u_int, u_int, u_int);
int tty_open(struct tty *, char **);
void tty_close(struct tty *);
void tty_free(struct tty *);
@@ -1926,6 +1951,9 @@ void status_prompt_load_history(void);
void status_prompt_save_history(void);
/* resize.c */
+void resize_window(struct window *, u_int, u_int);
+void default_window_size(struct session *, struct window *, u_int *,
+ u_int *, int);
void recalculate_sizes(void);
/* input.c */
@@ -2156,7 +2184,6 @@ int window_pane_set_mode(struct window_pane *,
void window_pane_reset_mode(struct window_pane *);
void window_pane_key(struct window_pane *, struct client *,
struct session *, key_code, struct mouse_event *);
-int window_pane_visible(struct window_pane *);
u_int window_pane_search(struct window_pane *, const char *);
const char *window_printable_flags(struct winlink *);
struct window_pane *window_pane_find_up(struct window_pane *);
@@ -2184,7 +2211,7 @@ void layout_set_size(struct layout_cell *, u_int, u_int, u_int,
void layout_make_leaf(struct layout_cell *, struct window_pane *);
void layout_make_node(struct layout_cell *, enum layout_type);
void layout_fix_offsets(struct layout_cell *);
-void layout_fix_panes(struct window *, u_int, u_int);
+void layout_fix_panes(struct window *);
void layout_resize_adjust(struct window *, struct layout_cell *,
enum layout_type, int);
void layout_init(struct window *, struct window_pane *);
@@ -2300,7 +2327,7 @@ struct session *session_find_by_id_str(const char *);
struct session *session_find_by_id(u_int);
struct session *session_create(const char *, const char *, int, char **,
const char *, const char *, struct environ *,
- struct termios *, int, u_int, u_int, char **);
+ struct options *, struct termios *, int, char **);
void session_destroy(struct session *, const char *);
void session_add_ref(struct session *, const char *);
void session_remove_ref(struct session *, const char *);
diff --git a/tty.c b/tty.c
index 2397f8c4..b6339266 100644
--- a/tty.c
+++ b/tty.c
@@ -64,6 +64,7 @@ static void tty_redraw_region(struct tty *, const struct tty_ctx *);
static void tty_emulate_repeat(struct tty *, enum tty_code_code,
enum tty_code_code, u_int);
static void tty_repeat_space(struct tty *, u_int);
+static void tty_draw_pane(struct tty *, const struct tty_ctx *, u_int);
static void tty_cell(struct tty *, const struct grid_cell *,
const struct window_pane *);
static void tty_default_colours(struct grid_cell *,
@@ -698,11 +699,117 @@ tty_repeat_space(struct tty *tty, u_int n)
tty_putn(tty, s, n, n);
}
+/* Is this window bigger than the terminal? */
+int
+tty_window_bigger(struct tty *tty)
+{
+ struct window *w = tty->client->session->curw->window;
+ u_int lines;
+
+ lines = tty_status_lines(tty);
+ return (tty->sx < w->sx || tty->sy - lines < w->sy);
+}
+
+/* What offset should this window be drawn at? */
+int
+tty_window_offset(struct tty *tty, u_int *ox, u_int *oy, u_int *sx, u_int *sy)
+{
+ *ox = tty->oox;
+ *oy = tty->ooy;
+ *sx = tty->osx;
+ *sy = tty->osy;
+
+ return (tty->oflag);
+}
+
+/* What offset should this window be drawn at? */
+static int
+tty_window_offset1(struct tty *tty, u_int *ox, u_int *oy, u_int *sx, u_int *sy)
+{
+ struct window *w = tty->client->session->curw->window;
+ struct window_pane *wp = w->active;
+ u_int cx, cy, lines;
+
+ lines = tty_status_lines(tty);
+ if (tty->sx >= w->sx && tty->sy - lines >= w->sy) {
+ *ox = 0;
+ *oy = 0;
+ *sx = w->sx;
+ *sy = w->sy;
+ return (0);
+ }
+
+ *sx = tty->sx;
+ *sy = tty->sy - lines;
+
+ if (~wp->screen->mode & MODE_CURSOR) {
+ *ox = 0;
+ *oy = 0;
+ } else {
+ cx = wp->xoff + wp->screen->cx;
+ cy = wp->yoff + wp->screen->cy;
+
+ if (cx < *sx)
+ *ox = 0;
+ else if (cx > w->sx - *sx)
+ *ox = w->sx - *sx;
+ else
+ *ox = cx - *sx / 2;
+
+ if (cy < *sy)
+ *oy = 0;
+ else if (cy > w->sy - *sy)
+ *oy = w->sy - *sy;
+ else
+ *oy = cy - *sy / 2;
+ }
+
+ return (1);
+}
+
+/* Update stored offsets for a window and redraw if necessary. */
+void
+tty_update_window_offset(struct window *w)
+{
+ struct client *c;
+
+ TAILQ_FOREACH(c, &clients, entry) {
+ if (c->session != NULL && c->session->curw->window == w)
+ tty_update_client_offset(c);
+ }
+}
+
+/* Update stored offsets for a client and redraw if necessary. */
+void
+tty_update_client_offset(struct client *c)
+{
+ u_int ox, oy, sx, sy;
+
+ c->tty.oflag = tty_window_offset1(&c->tty, &ox, &oy, &sx, &sy);
+ if (ox == c->tty.oox &&
+ oy == c->tty.ooy &&
+ sx == c->tty.osx &&
+ sy == c->tty.osy)
+ return;
+
+ log_debug ("%s: %s offset has changed (%u,%u %ux%u -> %u,%u %ux%u)",
+ __func__, c->name, c->tty.oox, c->tty.ooy, c->tty.osx, c->tty.osy,
+ ox, oy, sx, sy);
+
+ c->tty.oox = ox;
+ c->tty.ooy = oy;
+ c->tty.osx = sx;
+ c->tty.osy = sy;
+
+ c->flags |= CLIENT_REDRAWWINDOW;
+}
+
/* How many lines are taken up by the status line on this client? */
u_int
-tty_status_lines(struct client *c)
+tty_status_lines(struct tty *tty)
{
- u_int lines;
+ struct client *c = tty->client;
+ u_int lines;
if (c->flags & CLIENT_STATUSOFF)
lines = 0;
@@ -770,18 +877,73 @@ tty_redraw_region(struct tty *tty, const struct tty_ctx *ctx)
if (ctx->ocy < ctx->orupper || ctx->ocy > ctx->orlower) {
for (i = ctx->ocy; i < screen_size_y(s); i++)
- tty_draw_pane(tty, wp, i, ctx->xoff, ctx->yoff);
+ tty_draw_pane(tty, ctx, i);
} else {
for (i = ctx->orupper; i <= ctx->orlower; i++)
- tty_draw_pane(tty, wp, i, ctx->xoff, ctx->yoff);
+ tty_draw_pane(tty, ctx, i);
+ }
+}
+
+/* Is this position visible in the pane? */
+static int
+tty_is_visible(const struct tty_ctx *ctx, u_int px, u_int py, u_int nx,
+ u_int ny)
+{
+ struct window_pane *wp = ctx->wp;
+ u_int xoff = wp->xoff + px, yoff = wp->yoff + py;
+
+ if (!ctx->bigger)
+ return (1);
+ if (xoff + nx <= ctx->ox || xoff >= ctx->ox + ctx->sx ||
+ yoff + ny <= ctx->oy || yoff >= ctx->oy + ctx->sy) {
+ return (0);
+ }
+ return (1);
+}
+
+/* Clamp line position to visible part of pane. */
+static int
+tty_clamp_line(const struct tty_ctx *ctx, u_int px, u_int py, u_int nx,
+ u_int *i, u_int *x, u_int *rx)
+{
+ struct window_pane *wp = ctx->wp;
+ u_int xoff = wp->xoff + px;
+
+ if (!tty_is_visible(ctx, px, py, nx, 1))
+ return (0);
+
+ if (xoff >= ctx->ox && xoff + nx <= ctx->ox + ctx->sx) {
+ /* All visible. */
+ *i = 0;
+ *x = xoff - ctx->ox;
+ *rx = nx;
+ } else if (xoff < ctx->ox && xoff + nx > ctx->ox + ctx->sx) {
+ /* Both left and right not visible. */
+ *i = ctx->ox;
+ *x = 0;
+ *rx = ctx->sx;
+ } else if (xoff < ctx->ox) {
+ /* Left not visible. */
+ *i = ctx->ox - xoff;
+ *x = 0;
+ *rx = nx - *i;
+ } else {
+ /* Right not visible. */
+ *i = 0;
+ *x = xoff - ctx->ox;
+ *rx = nx - (xoff + nx - ctx->sx);
}
+ return (1);
}
+/* Clear a line. */
static void
tty_clear_line(struct tty *tty, const struct window_pane *wp, u_int py,
u_int px, u_int nx, u_int bg)
{
- log_debug("%s: %u at %u,%u", __func__, nx, px, py);
+ struct client *c = tty->client;
+
+ log_debug("%s: %s, %u at %u,%u", __func__, c->name, nx, px, py);
/* Nothing to clear. */
if (nx == 0)
@@ -816,14 +978,84 @@ tty_clear_line(struct tty *tty, const struct window_pane *wp, u_int py,
tty_repeat_space(tty, nx);
}
+/* Clear a line, adjusting to visible part of pane. */
+static void
+tty_clear_pane_line(struct tty *tty, const struct tty_ctx *ctx, u_int py,
+ u_int px, u_int nx, u_int bg)
+{
+ u_int i, x, rx;
+
+ if (tty_clamp_line(ctx, px, py, nx, &i, &x, &rx))
+ tty_clear_line(tty, ctx->wp, py - ctx->oy, x, rx, bg);
+}
+
+/* Clamp area position to visible part of pane. */
+static int
+tty_clamp_area(const struct tty_ctx *ctx, u_int px, u_int py, u_int nx,
+ u_int ny, u_int *i, u_int *j, u_int *x, u_int *y, u_int *rx, u_int *ry)
+{
+ struct window_pane *wp = ctx->wp;
+ u_int xoff = wp->xoff + px, yoff = wp->yoff + py;
+
+ if (xoff + nx <= ctx->ox || xoff >= ctx->ox + ctx->sx ||
+ yoff + ny <= ctx->oy || yoff >= ctx->oy + ctx->sy)
+ return (0);
+
+ if (xoff >= ctx->ox && xoff + nx <= ctx->ox + ctx->sx) {
+ /* All visible. */
+ *i = 0;
+ *x = xoff - ctx->ox;
+ *rx = nx;
+ } else if (xoff < ctx->ox && xoff + nx > ctx->ox + ctx->sx) {
+ /* Both left and right not visible. */
+ *i = ctx->ox;
+ *x = 0;
+ *rx = ctx->sx;
+ } else if (xoff < ctx->ox) {
+ /* Left not visible. */
+ *i = ctx->ox - xoff;
+ *x = 0;
+ *rx = nx - *i;
+ } else {
+ /* Right not visible. */
+ *i = 0;
+ *x = xoff - ctx->ox;
+ *rx = nx - (xoff + nx - ctx->sx);
+ }
+ if (yoff >= ctx->oy && yoff + ny <= ctx->oy + ctx->sy) {
+ /* All visible. */
+ *j = 0;
+ *y = yoff - ctx->oy;
+ *ry = ny;
+ } else if (yoff < ctx->oy && yoff + ny > ctx->oy + ctx->sy) {
+ /* Both left and right not visible. */
+ *j = ctx->oy;
+ *y = 0;
+ *ry = ctx->sy;
+ } else if (yoff < ctx->oy) {
+ /* Left not visible. */
+ *j = ctx->oy - yoff;
+ *y = 0;
+ *ry = ny - *j;
+ } else {
+ /* Right not visible. */
+ *j = 0;
+ *y = yoff - ctx->oy;
+ *ry = ny - (yoff + ny - ctx->sy);
+ }
+ return (1);
+}
+
+/* Clear an area, adjusting to visible part of pane. */
static void
tty_clear_area(struct tty *tty, const struct window_pane *wp, u_int py,
u_int ny, u_int px, u_int nx, u_int bg)
{
- u_int yy;
- char tmp[64];
+ struct client *c = tty->client;
+ u_int yy;
+ char tmp[64];
- log_debug("%s: %u,%u at %u,%u", __func__, nx, ny, px, py);
+ log_debug("%s: %s, %u,%u at %u,%u", __func__, c->name, nx, ny, px, py);
/* Nothing to clear. */
if (nx == 0 || ny == 0)
@@ -886,11 +1118,33 @@ tty_clear_area(struct tty *tty, const struct window_pane *wp, u_int py,
tty_clear_line(tty, wp, yy, px, nx, bg);
}
-void
-tty_draw_pane(struct tty *tty, const struct window_pane *wp, u_int py, u_int ox,
- u_int oy)
+/* Clear an area in a pane. */
+static void
+tty_clear_pane_area(struct tty *tty, const struct tty_ctx *ctx, u_int py,
+ u_int ny, u_int px, u_int nx, u_int bg)
+{
+ u_int i, j, x, y, rx, ry;
+
+ if (tty_clamp_area(ctx, px, py, nx, ny, &i, &j, &x, &y, &rx, &ry))
+ tty_clear_area(tty, ctx->wp, y, ry, x, rx, bg);
+}
+
+static void
+tty_draw_pane(struct tty *tty, const struct tty_ctx *ctx, u_int py)
{
- tty_draw_line(tty, wp, wp->screen, py, ox, oy);
+ struct window_pane *wp = ctx->wp;
+ struct screen *s = wp->screen;
+ u_int xoff = ctx->xoff, yoff = ctx->yoff;
+ u_int nx = screen_size_x(s), i, x, rx;
+
+ log_debug("%s: %s %u %d", __func__, tty->client->name, py, ctx->bigger);
+
+ if (!ctx->bigger) {
+ tty_draw_line(tty, wp, s, 0, py, nx, xoff, yoff + py);
+ return;
+ }
+ if (tty_clamp_line(ctx, 0, py, nx, &i, &x, &rx))
+ tty_draw_line(tty, wp, s, i, py, rx, x, yoff + py - ctx->oy);
}
static const struct grid_cell *
@@ -919,17 +1173,27 @@ tty_check_codeset(struct tty *tty, const struct grid_cell *gc)
void
tty_draw_line(struct tty *tty, const struct window_pane *wp,
- struct screen *s, u_int py, u_int ox, u_int oy)
+ struct screen *s, u_int px, u_int py, u_int nx, u_int atx, u_int aty)
{
struct grid *gd = s->grid;
struct grid_cell gc, last;
const struct grid_cell *gcp;
- u_int i, j, ux, sx, nx, width;
+ struct grid_line *gl;
+ u_int i, j, ux, sx, width;
int flags, cleared = 0;
char buf[512];
size_t len, old_len;
u_int cellsize;
+ log_debug("%s: px=%u py=%u nx=%u atx=%u aty=%u", __func__,
+ px, py, nx, atx, aty);
+
+ /*
+ * py is the line in the screen to draw.
+ * px is the start x and nx is the width to draw.
+ * atx,aty is the line on the terminal to draw it.
+ */
+
flags = (tty->flags & TTY_NOCURSOR);
tty->flags |= TTY_NOCURSOR;
tty_update_mode(tty, tty->mode, s);
@@ -942,41 +1206,48 @@ tty_draw_line(struct tty *tty, const struct window_pane *wp,
* there may be empty background cells after it (from BCE).
*/
sx = screen_size_x(s);
-
+ if (nx > sx)
+ nx = sx;
cellsize = grid_get_line(gd, gd->hsize + py)->cellsize;
if (sx > cellsize)
sx = cellsize;
if (sx > tty->sx)
sx = tty->sx;
+ if (sx > nx)
+ sx = nx;
ux = 0;
+ if (py == 0)
+ gl = NULL;
+ else
+ gl = grid_get_line(gd, gd->hsize + py - 1);
if (wp == NULL ||
- py == 0 ||
- (~grid_get_line(gd, gd->hsize + py - 1)->flags & GRID_LINE_WRAPPED) ||
- ox != 0 ||
+ gl == NULL ||
+ (~gl->flags & GRID_LINE_WRAPPED) ||
+ atx != 0 ||
tty->cx < tty->sx ||
- screen_size_x(s) < tty->sx) {
- if (screen_size_x(s) < tty->sx &&
- ox == 0 &&
- sx != screen_size_x(s) &&
+ nx < tty->sx) {
+ if (nx < tty->sx &&
+ atx == 0 &&
+ px + sx != nx &&
tty_term_has(tty->term, TTYC_EL1) &&
!tty_fake_bce(tty, wp, 8)) {
tty_default_attributes(tty, wp, 8);
- tty_cursor(tty, screen_size_x(s) - 1, oy + py);
+ tty_cursor(tty, nx - 1, aty);
tty_putcode(tty, TTYC_EL1);
cleared = 1;
}
- if (sx != 0)
- tty_cursor(tty, ox, oy + py);
+ if (px + sx != 0)
+ tty_cursor(tty, atx, aty);
} else
- log_debug("%s: wrapped line %u", __func__, oy + py);
+ log_debug("%s: wrapped line %u", __func__, aty);
memcpy(&last, &grid_default_cell, sizeof last);
len = 0;
width = 0;
for (i = 0; i < sx; i++) {
- grid_view_get_cell(gd, i, py, &gc);
+ grid_view_get_cell(gd, px + i, py, &gc);
gcp = tty_check_codeset(tty, &gc);
if (len != 0 &&
((gcp->attr & GRID_ATTR_CHARSET) ||
@@ -984,7 +1255,7 @@ tty_draw_line(struct tty *tty, const struct window_pane *wp,
gcp->attr != last.attr ||
gcp->fg != last.fg ||
gcp->bg != last.bg ||
- ux + width + gcp->data.width >= screen_size_x(s) ||
+ ux + width + gcp->data.width >= nx ||
(sizeof buf) - len < gcp->data.size)) {
tty_attributes(tty, &last, wp);
tty_putn(tty, buf, len, width);
@@ -998,10 +1269,10 @@ tty_draw_line(struct tty *tty, const struct window_pane *wp,
screen_select_cell(s, &last, gcp);
else
memcpy(&last, gcp, sizeof last);
- if (ux + gcp->data.width > screen_size_x(s)) {
+ if (ux + gcp->data.width > nx) {
tty_attributes(tty, &last, wp);
for (j = 0; j < gcp->data.width; j++) {
- if (ux + j > screen_size_x(s))
+ if (ux + j > nx)
break;
tty_putc(tty, ' ');
ux++;
@@ -1034,10 +1305,9 @@ tty_draw_line(struct tty *tty, const struct window_pane *wp,
}
}
- if (!cleared && ux < screen_size_x(s)) {
- nx = screen_size_x(s) - ux;
+ if (!cleared && ux < nx) {
tty_default_attributes(tty, wp, 8);
- tty_clear_line(tty, wp, oy + py, ox + ux, nx, 8);
+ tty_clear_line(tty, wp, aty, atx + ux, nx - ux, 8);
}
tty->flags = (tty->flags & ~TTY_NOCURSOR) | flags;
@@ -1065,17 +1335,18 @@ tty_write(void (*cmdfn)(struct tty *, const struct tty_ctx *),
struct window_pane *wp = ctx->wp;
struct client *c;
- /* wp can be NULL if updating the screen but not the terminal. */
if (wp == NULL)
return;
-
- if ((wp->flags & (PANE_REDRAW|PANE_DROP)) || !window_pane_visible(wp))
+ if (wp->flags & (PANE_REDRAW|PANE_DROP))
return;
TAILQ_FOREACH(c, &clients, entry) {
if (!tty_client_ready(c, wp))
continue;
+ ctx->bigger = tty_window_offset(&c->tty, &ctx->ox, &ctx->oy,
+ &ctx->sx, &ctx->sy);
+
ctx->xoff = wp->xoff;
ctx->yoff = wp->yoff;
if (status_at_line(c) == 0)
@@ -1090,11 +1361,12 @@ tty_cmd_insertcharacter(struct tty *tty, const struct tty_ctx *ctx)
{
struct window_pane *wp = ctx->wp;
- if (!tty_pane_full_width(tty, ctx) ||
+ if (ctx->bigger ||
+ !tty_pane_full_width(tty, ctx) ||
tty_fake_bce(tty, wp, ctx->bg) ||
(!tty_term_has(tty->term, TTYC_ICH) &&
!tty_term_has(tty->term, TTYC_ICH1))) {
- tty_draw_pane(tty, wp, ctx->ocy, ctx->xoff, ctx->yoff);
+ tty_draw_pane(tty, ctx, ctx->ocy);
return;
}
@@ -1110,11 +1382,12 @@ tty_cmd_deletecharacter(struct tty *tty, const struct tty_ctx *ctx)
{
struct window_pane *wp = ctx->wp;
- if (!tty_pane_full_width(tty, ctx) ||
+ if (ctx->bigger ||
+ !tty_pane_full_width(tty, ctx) ||
tty_fake_bce(tty, wp, ctx->bg) ||
(!tty_term_has(tty->term, TTYC_DCH) &&
!tty_term_has(tty->term, TTYC_DCH1))) {
- tty_draw_pane(tty, wp, ctx->ocy, ctx->xoff, ctx->yoff);
+ tty_draw_pane(tty, ctx, ctx->ocy);
return;
}
@@ -1128,6 +1401,11 @@ tty_cmd_deletecharacter(struct tty *tty, const struct tty_ctx *ctx)
void
tty_cmd_clearcharacter(struct tty *tty, const struct tty_ctx *ctx)
{
+ if (ctx->bigger) {
+ tty_draw_pane(tty, ctx, ctx->ocy);
+ return;
+ }
+
tty_default_attributes(tty, ctx->wp, ctx->bg);
tty_cursor_pane(tty, ctx, ctx->ocx, ctx->ocy);
@@ -1142,7 +1420,8 @@ tty_cmd_clearcharacter(struct tty *tty, const struct tty_ctx *ctx)
void
tty_cmd_insertline(struct tty *tty, const struct tty_ctx *ctx)
{
- if (!tty_pane_full_width(tty, ctx) ||
+ if (ctx->bigger ||
+ !tty_pane_full_width(tty, ctx) ||
tty_fake_bce(tty, ctx->wp, ctx->bg) ||
!tty_term_has(tty->term, TTYC_CSR) ||
!tty_term_has(tty->term, TTYC_IL1)) {
@@ -1163,7 +1442,8 @@ tty_cmd_insertline(struct tty *tty, const struct tty_ctx *ctx)
void
tty_cmd_deleteline(struct tty *tty, const struct tty_ctx *ctx)
{
- if (!tty_pane_full_width(tty, ctx) ||
+ if (ctx->bigger ||
+ !tty_pane_full_width(tty, ctx) ||
tty_fake_bce(tty, ctx->wp, ctx->bg) ||
!tty_term_has(tty->term, TTYC_CSR) ||
!tty_term_has(tty->term, TTYC_DL1)) {
@@ -1190,7 +1470,7 @@ tty_cmd_clearline(struct tty *tty, const struct tty_ctx *ctx)
tty_default_attributes(tty, wp, ctx->bg);
nx = screen_size_x(wp->screen);
- tty_clear_line(tty, wp, py, ctx->xoff, nx, ctx->bg);
+ tty_clear_pane_line(tty, ctx, py, 0, nx, ctx->bg);
}
void
@@ -1202,7 +1482,7 @@ tty_cmd_clearendofline(struct tty *tty, const struct tty_ctx *ctx)
tty_default_attributes(tty, wp, ctx->bg);
nx = screen_size_x(wp->screen) - ctx->ocx;
- tty_clear_line(tty, wp, py, ctx->xoff + ctx->ocx, nx, ctx->bg);
+ tty_clear_pane_line(tty, ctx, py, ctx->ocx, nx, ctx->bg);
}
void
@@ -1213,7 +1493,7 @@ tty_cmd_clearstartofline(struct tty *tty, const struct tty_ctx *ctx)
tty_default_attributes(tty, wp, ctx->bg);
- tty_clear_line(tty, wp, py, ctx->xoff, ctx->ocx + 1, ctx->bg);
+ tty_clear_pane_line(tty, ctx, py, 0, ctx->ocx + 1, ctx->bg);
}
void
@@ -1224,7 +1504,8 @@ tty_cmd_reverseindex(struct tty *tty, const struct tty_ctx *ctx)
if (ctx->ocy != ctx->orupper)
return;
- if (!tty_pane_full_width(tty, ctx) ||
+ if (ctx->bigger ||
+ !tty_pane_full_width(tty, ctx) ||
tty_fake_bce(tty, wp, 8) ||
!tty_term_has(tty->term, TTYC_CSR) ||
!tty_term_has(tty->term, TTYC_RI)) {
@@ -1249,7 +1530,8 @@ tty_cmd_linefeed(struct tty *tty, const struct tty_ctx *ctx)
if (ctx->ocy != ctx->orlower)
return;
- if ((!tty_pane_full_width(tty, ctx) && !tty_use_margin(tty)) ||
+ if (ctx->bigger ||
+ (!tty_pane_full_width(tty, ctx) && !tty_use_margin(tty)) ||
tty_fake_bce(tty, wp, 8) ||
!tty_term_has(tty->term, TTYC_CSR)) {
tty_redraw_region(tty, ctx);
@@ -1285,7 +1567,8 @@ tty_cmd_scrollup(struct tty *tty, const struct tty_ctx *ctx)
struct window_pane *wp = ctx->wp;
u_int i;
- if ((!tty_pane_full_width(tty, ctx) && !tty_use_margin(tty)) ||
+ if (ctx->bigger ||
+ (!tty_pane_full_width(tty, ctx) && !tty_use_margin(tty)) ||
tty_fake_bce(tty, wp, 8) ||
!tty_term_has(tty->term, TTYC_CSR)) {
tty_redraw_region(tty, ctx);
@@ -1321,18 +1604,18 @@ tty_cmd_clearendofscreen(struct tty *tty, const struct tty_ctx *ctx)
tty_region_pane(tty, ctx, 0, screen_size_y(wp->screen) - 1);
tty_margin_off(tty);
- px = ctx->xoff;
+ px = 0;
nx = screen_size_x(wp->screen);
- py = ctx->yoff + ctx->ocy + 1;
+ py = ctx->ocy + 1;
ny = screen_size_y(wp->screen) - ctx->ocy - 1;
- tty_clear_area(tty, wp, py, ny, px, nx, ctx->bg);
+ tty_clear_pane_area(tty, ctx, py, ny, px, nx, ctx->bg);
- px = ctx->xoff + ctx->ocx;
+ px = ctx->ocx;
nx = screen_size_x(wp->screen) - ctx->ocx;
- py = ctx->yoff + ctx->ocy;
+ py = ctx->ocy;
- tty_clear_line(tty, wp, py, px, nx, ctx->bg);
+ tty_clear_pane_line(tty, ctx, py, px, nx, ctx->bg);
}
void
@@ -1346,18 +1629,18 @@ tty_cmd_clearstartofscreen(struct tty *tty, const struct tty_ctx *ctx)
tty_region_pane(tty, ctx, 0, screen_size_y(wp->screen) - 1);
tty_margin_off(tty);
- px = ctx->xoff;
+ px = 0;
nx = screen_size_x(wp->screen);
- py = ctx->yoff;
+ py = 0;
ny = ctx->ocy - 1;
- tty_clear_area(tty, wp, py, ny, px, nx, ctx->bg);
+ tty_clear_pane_area(tty, ctx, py, ny, px, nx, ctx->bg);
- px = ctx->xoff;
+ px = 0;
nx = ctx->ocx + 1;
- py = ctx->yoff + ctx->ocy;
+ py = ctx->ocy;
- tty_clear_line(tty, wp, py, px, nx, ctx->bg);
+ tty_clear_pane_line(tty, ctx, py, px, nx, ctx->bg);
}
void
@@ -1371,12 +1654,12 @@ tty_cmd_clearscreen(struct tty *tty, const struct tty_ctx *ctx)
tty_region_pane(tty, ctx, 0, screen_size_y(wp->screen) - 1);
tty_margin_off(tty);
- px = ctx->xoff;
+ px = 0;
nx = screen_size_x(wp->screen);
- py = ctx->yoff;
+ py = 0;
ny = screen_size_y(wp->screen);
- tty_clear_area(tty, wp, py, ny, px, nx, ctx->bg);
+ tty_clear_pane_area(tty, ctx, py, ny, px, nx, ctx->bg);
}
void
@@ -1386,6 +1669,11 @@ tty_cmd_alignmenttest(struct tty *tty, const struct tty_ctx *ctx)
struct screen *s = wp->screen;
u_int i, j;
+ if (ctx->bigger) {
+ wp->flags |= PANE_REDRAW;
+ return;
+ }
+
tty_attributes(tty, &grid_default_cell, wp);
tty_region_pane(tty, ctx, 0, screen_size_y(s) - 1);
@@ -1401,7 +1689,11 @@ tty_cmd_alignmenttest(struct tty *tty, const struct tty_ctx *ctx)
void
tty_cmd_cell(struct tty *tty, const struct tty_ctx *ctx)
{
- if (ctx->xoff + ctx->ocx > tty->sx - 1 && ctx->ocy == ctx->orlower) {
+ if (!tty_is_visible(ctx, ctx->ocx, ctx->ocy, 1, 1))
+ return;
+
+ if (ctx->xoff + ctx->ocx - ctx->ox > tty->sx - 1 &&
+ ctx->ocy == ctx->orlower) {
if (tty_pane_full_width(tty, ctx))
tty_region_pane(tty, ctx, ctx->orupper, ctx->orlower);
else
@@ -1416,6 +1708,26 @@ tty_cmd_cell(struct tty *tty, const struct tty_ctx *ctx)
void
tty_cmd_cells(struct tty *tty, const struct tty_ctx *ctx)
{
+ struct window_pane *wp = ctx->wp;
+
+ if (!tty_is_visible(ctx, ctx->ocx, ctx->ocy, ctx->num, 1))
+ return;
+
+ if (ctx->bigger &&
+ (ctx->ocx < ctx->ox || ctx->ocx + ctx->num > ctx->ox + ctx->sx)) {
+ if (!ctx->wrapped ||
+ !tty_pane_full_width(tty, ctx) ||
+ (tty->term->flags & TERM_EARLYWRAP) ||
+ ctx->xoff + ctx->ocx != 0 ||
+ ctx->yoff + ctx->ocy != tty->cy + 1 ||
+ tty->cx < tty->sx ||
+ tty->cy == tty->rlower)
+ tty_draw_pane(tty, ctx, ctx->ocy);
+ else
+ wp->flags |= PANE_REDRAW;
+ return;
+ }
+
tty_cursor_pane_unless_wrap(tty, ctx, ctx->ocx, ctx->ocy);
tty_attributes(tty, ctx->cell, ctx->wp);
@@ -1533,7 +1845,8 @@ static void
tty_region_pane(struct tty *tty, const struct tty_ctx *ctx, u_int rupper,
u_int rlower)
{
- tty_region(tty, ctx->yoff + rupper, ctx->yoff + rlower);
+ tty_region(tty, ctx->yoff + rupper - ctx->oy,
+ ctx->yoff + rlower - ctx->oy);
}
/* Set region at absolute position. */
@@ -1572,7 +1885,8 @@ tty_margin_off(struct tty *tty)
static void
tty_margin_pane(struct tty *tty, const struct tty_ctx *ctx)
{
- tty_margin(tty, ctx->xoff, ctx->xoff + ctx->wp->sx - 1);
+ tty_margin(tty, ctx->xoff - ctx->ox,
+ ctx->xoff + ctx->wp->sx - 1 - ctx->ox);
}
/* Set margin at absolute position. */
@@ -1623,7 +1937,7 @@ tty_cursor_pane_unless_wrap(struct tty *tty, const struct tty_ctx *ctx,
static void
tty_cursor_pane(struct tty *tty, const struct tty_ctx *ctx, u_int cx, u_int cy)
{
- tty_cursor(tty, ctx->xoff + cx, ctx->yoff + cy);
+ tty_cursor(tty, ctx->xoff + cx - ctx->ox, ctx->yoff + cy - ctx->oy);
}
/* Move cursor to absolute position. */
diff --git a/window.c b/window.c
index 16c973b2..cf29ae48 100644
--- a/window.c
+++ b/window.c
@@ -378,6 +378,8 @@ window_destroy(struct window *w)
if (event_initialized(&w->alerts_timer))
evtimer_del(&w->alerts_timer);
+ if (event_initialized(&w->offset_timer))
+ event_del(&w->offset_timer);
options_free(w->options);
@@ -456,17 +458,9 @@ window_set_active_pane(struct window *w, struct window_pane *wp)
return (0);
w->last = w->active;
w->active = wp;
- while (!window_pane_visible(w->active)) {
- w->active = TAILQ_PREV(w->active, window_panes, entry);
- if (w->active == NULL)
- w->active = TAILQ_LAST(&w->panes, window_panes);
- if (w->active == wp) {
- notify_window("window-pane-changed", w);
- return (1);
- }
- }
w->active->active_point = next_active_point++;
w->active->flags |= PANE_CHANGED;
+ tty_update_window_offset(w);
notify_window("window-pane-changed", w);
return (1);
}
@@ -507,8 +501,6 @@ window_get_active_at(struct window *w, u_int x, u_int y)
struct window_pane *wp;
TAILQ_FOREACH(wp, &w->panes, entry) {
- if (!window_pane_visible(wp))
- continue;
if (x < wp->xoff || x > wp->xoff + wp->sx)
continue;
if (y < wp->yoff || y > wp->yoff + wp->sy)
@@ -561,9 +553,6 @@ window_zoom(struct window_pane *wp)
if (w->flags & WINDOW_ZOOMED)
return (-1);
- if (!window_pane_visible(wp))
- return (-1);
-
if (window_count_panes(w) == 1)
return (-1);
@@ -600,7 +589,7 @@ window_unzoom(struct window *w)
wp->layout_cell = wp->saved_layout_cell;
wp->saved_layout_cell = NULL;
}
- layout_fix_panes(w, w->sx, w->sy);
+ layout_fix_panes(w);
notify_window("window-layout-changed", w);
return (0);
@@ -898,7 +887,6 @@ window_pane_spawn(struct window_pane *wp, int argc, char **argv,
#ifdef HAVE_UTEMPTER
char s[32];
#endif
- int i;
sigset_t set, oldset;
if (wp->fd != -1) {
@@ -1302,27 +1290,11 @@ window_pane_key(struct window_pane *wp, struct client *c, struct session *s,
continue;
if (wp2->fd == -1 || wp2->flags & PANE_INPUTOFF)
continue;
- if (window_pane_visible(wp2))
- input_key(wp2, key, NULL);
+ input_key(wp2, key, NULL);
}
}
}
-int
-window_pane_visible(struct window_pane *wp)
-{
- struct window *w = wp->window;
-
- if (wp->layout_cell == NULL)
- return (0);
-
- if (wp->xoff >= w->sx || wp->yoff >= w->sy)
- return (0);
- if (wp->xoff + wp->sx > w->sx || wp->yoff + wp->sy > w->sy)
- return (0);
- return (1);
-}
-
u_int
window_pane_search(struct window_pane *wp, const char *searchstr)
{
@@ -1377,7 +1349,7 @@ window_pane_find_up(struct window_pane *wp)
u_int edge, left, right, end, size;
int status, found;
- if (wp == NULL || !window_pane_visible(wp))
+ if (wp == NULL)
return (NULL);
status = options_get_number(wp->window->options, "pane-border-status");
@@ -1392,7 +1364,7 @@ window_pane_find_up(struct window_pane *wp)
right = wp->xoff + wp->sx;
TAILQ_FOREACH(next, &wp->window->panes, entry) {
- if (next == wp || !window_pane_visible(next))
+ if (next == wp)
continue;
if (next->yoff + next->sy + 1 != edge)
continue;
@@ -1424,7 +1396,7 @@ window_pane_find_down(struct window_pane *wp)
u_int edge, left, right, end, size;
int status, found;
- if (wp == NULL || !window_pane_visible(wp))
+ if (wp == NULL)
return (NULL);
status = options_get_number(wp->window->options, "pane-border-status");
@@ -1439,7 +1411,7 @@ window_pane_find_down(struct window_pane *wp)
right = wp->xoff + wp->sx;
TAILQ_FOREACH(next, &wp->window->panes, entry) {
- if (next == wp || !window_pane_visible(next))
+ if (next == wp)
continue;
if (next->yoff != edge)
continue;
@@ -1471,7 +1443,7 @@ window_pane_find_left(struct window_pane *wp)
u_int edge, top, bottom, end, size;
int found;
- if (wp == NULL || !window_pane_visible(wp))
+ if (wp == NULL)
return (NULL);
list = NULL;
@@ -1485,7 +1457,7 @@ window_pane_find_left(struct window_pane *wp)
bottom = wp->yoff + wp->sy;
TAILQ_FOREACH(next, &wp->window->panes, entry) {
- if (next == wp || !window_pane_visible(next))
+ if (next == wp)
continue;
if (next->xoff + next->sx + 1 != edge)
continue;
@@ -1517,7 +1489,7 @@ window_pane_find_right(struct window_pane *wp)
u_int edge, top, bottom, end, size;
int found;
- if (wp == NULL || !window_pane_visible(wp))
+ if (wp == NULL)
return (NULL);
list = NULL;
@@ -1531,7 +1503,7 @@ window_pane_find_right(struct window_pane *wp)
bottom = wp->yoff + wp->sy;
TAILQ_FOREACH(next, &wp->window->panes, entry) {
- if (next == wp || !window_pane_visible(next))
+ if (next == wp)
continue;
if (next->xoff != edge)
continue;