mirror of
https://github.com/tmux/tmux.git
synced 2025-09-02 13:37:12 +00:00
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.
This commit is contained in:
87
window.c
87
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,59 +1220,90 @@ 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)
|
||||
struct window_mode_entry *wme, *next;
|
||||
|
||||
if (TAILQ_EMPTY(&wp->modes))
|
||||
return;
|
||||
|
||||
evtimer_del(&wp->modetimer);
|
||||
wme = TAILQ_FIRST(&wp->modes);
|
||||
TAILQ_REMOVE(&wp->modes, wme, entry);
|
||||
wme->mode->free(wme);
|
||||
free(wme);
|
||||
|
||||
wp->mode->mode->free(wp->mode);
|
||||
free(wp->mode);
|
||||
wp->mode = NULL;
|
||||
|
||||
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);
|
||||
notify_pane("pane-mode-changed", 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))
|
||||
|
Reference in New Issue
Block a user