summaryrefslogtreecommitdiffstats
path: root/window.c
diff options
context:
space:
mode:
authornicm <nicm>2019-03-12 11:16:49 +0000
committernicm <nicm>2019-03-12 11:16:49 +0000
commit3f6bfbaf2babcc7f08f628a82ff31b0b52014e58 (patch)
treece4bf0c954cdfede0c2e86905bd85a9f565ed370 /window.c
parentff4c80d53df96bb46eaa64107673e42d402f0d49 (diff)
Allow multiple modes to be open in a pane. A stack of open modes is kept
and the previous restored when the top is exited. If a mode that is already on the stack is entered, the existing instance is moved to the top as the active mode rather than being opened new.
Diffstat (limited to 'window.c')
-rw-r--r--window.c87
1 files changed, 61 insertions, 26 deletions
diff --git a/window.c b/window.c
index 366df797..05adc586 100644
--- a/window.c
+++ b/window.c
@@ -810,7 +810,7 @@ window_pane_create(struct window *w, u_int sx, u_int sy, u_int hlimit)
wp->fd = -1;
wp->event = NULL;
- wp->mode = NULL;
+ TAILQ_INIT(&wp->modes);
wp->layout_cell = NULL;
@@ -844,7 +844,7 @@ window_pane_create(struct window *w, u_int sx, u_int sy, u_int hlimit)
static void
window_pane_destroy(struct window_pane *wp)
{
- window_pane_reset_mode(wp);
+ window_pane_reset_mode_all(wp);
free(wp->searchstr);
if (wp->fd != -1) {
@@ -1047,14 +1047,18 @@ window_pane_error_callback(__unused struct bufferevent *bufev,
void
window_pane_resize(struct window_pane *wp, u_int sx, u_int sy)
{
+ struct window_mode_entry *wme;
+
if (sx == wp->sx && sy == wp->sy)
return;
wp->sx = sx;
wp->sy = sy;
screen_resize(&wp->base, sx, sy, wp->saved_grid == NULL);
- if (wp->mode != NULL && wp->mode->mode->resize != NULL)
- wp->mode->mode->resize(wp->mode, sx, sy);
+
+ wme = TAILQ_FIRST(&wp->modes);
+ if (wme != NULL && wme->mode->resize != NULL)
+ wme->mode->resize(wme, sx, sy);
wp->flags |= PANE_RESIZE;
}
@@ -1208,7 +1212,7 @@ window_pane_mode_timer(__unused int fd, __unused short events, void *arg)
if (wp->modelast < time(NULL) - WINDOW_MODE_TIMEOUT) {
if (ioctl(wp->fd, FIONREAD, &n) == -1 || n > 0)
- window_pane_reset_mode(wp);
+ window_pane_reset_mode_all(wp);
}
}
@@ -1216,43 +1220,66 @@ int
window_pane_set_mode(struct window_pane *wp, const struct window_mode *mode,
struct cmd_find_state *fs, struct args *args)
{
- struct screen *s;
- struct timeval tv = { .tv_sec = 10 };
+ struct timeval tv = { .tv_sec = 10 };
+ struct window_mode_entry *wme;
- if (wp->mode != NULL)
+ if (!TAILQ_EMPTY(&wp->modes) && TAILQ_FIRST(&wp->modes)->mode == mode)
return (1);
- wp->mode = xcalloc(1, sizeof *wp->mode);
- wp->mode->wp = wp;
- wp->mode->mode = mode;
- wp->mode->prefix = 1;
-
wp->modelast = time(NULL);
- evtimer_set(&wp->modetimer, window_pane_mode_timer, wp);
- evtimer_add(&wp->modetimer, &tv);
+ if (TAILQ_EMPTY(&wp->modes)) {
+ evtimer_set(&wp->modetimer, window_pane_mode_timer, wp);
+ evtimer_add(&wp->modetimer, &tv);
+ }
- if ((s = wp->mode->mode->init(wp->mode, fs, args)) != NULL)
- wp->screen = s;
+ TAILQ_FOREACH(wme, &wp->modes, entry) {
+ if (wme->mode == mode)
+ break;
+ }
+ if (wme != NULL)
+ TAILQ_REMOVE(&wp->modes, wme, entry);
+ else {
+ wme = xcalloc(1, sizeof *wme);
+ wme->wp = wp;
+ wme->mode = mode;
+ wme->prefix = 1;
+ wme->screen = wme->mode->init(wme, fs, args);
+ }
+ TAILQ_INSERT_HEAD(&wp->modes, wme, entry);
+
+ wp->screen = wme->screen;
wp->flags |= (PANE_REDRAW|PANE_CHANGED);
server_status_window(wp->window);
notify_pane("pane-mode-changed", wp);
+
return (0);
}
void
window_pane_reset_mode(struct window_pane *wp)
{
- if (wp->mode == NULL)
- return;
+ struct window_mode_entry *wme, *next;
- evtimer_del(&wp->modetimer);
+ if (TAILQ_EMPTY(&wp->modes))
+ return;
- wp->mode->mode->free(wp->mode);
- free(wp->mode);
- wp->mode = NULL;
+ wme = TAILQ_FIRST(&wp->modes);
+ TAILQ_REMOVE(&wp->modes, wme, entry);
+ wme->mode->free(wme);
+ free(wme);
- wp->screen = &wp->base;
+ next = TAILQ_FIRST(&wp->modes);
+ if (next == NULL) {
+ log_debug("%s: no next mode", __func__);
+ evtimer_del(&wp->modetimer);
+ wp->screen = &wp->base;
+ } else {
+ log_debug("%s: next mode is %s", __func__, next->mode->name);
+ wp->screen = next->screen;
+ if (next != NULL && next->mode->resize != NULL)
+ next->mode->resize(next, wp->sx, wp->sy);
+ }
wp->flags |= (PANE_REDRAW|PANE_CHANGED);
server_status_window(wp->window);
@@ -1260,15 +1287,23 @@ window_pane_reset_mode(struct window_pane *wp)
}
void
+window_pane_reset_mode_all(struct window_pane *wp)
+{
+ while (!TAILQ_EMPTY(&wp->modes))
+ window_pane_reset_mode(wp);
+}
+
+void
window_pane_key(struct window_pane *wp, struct client *c, struct session *s,
struct winlink *wl, key_code key, struct mouse_event *m)
{
- struct window_mode_entry *wme = wp->mode;
+ struct window_mode_entry *wme;
struct window_pane *wp2;
if (KEYC_IS_MOUSE(key) && m == NULL)
return;
+ wme = TAILQ_FIRST(&wp->modes);
if (wme != NULL) {
wp->modelast = time(NULL);
if (wme->mode->key != NULL)
@@ -1286,7 +1321,7 @@ window_pane_key(struct window_pane *wp, struct client *c, struct session *s,
if (options_get_number(wp->window->options, "synchronize-panes")) {
TAILQ_FOREACH(wp2, &wp->window->panes, entry) {
if (wp2 != wp &&
- wp2->mode == NULL &&
+ TAILQ_EMPTY(&wp2->modes) &&
wp2->fd != -1 &&
(~wp2->flags & PANE_INPUTOFF) &&
window_pane_visible(wp2))