mirror of
https://github.com/tmux/tmux.git
synced 2024-12-24 18:21:33 +00:00
Change focus to be driven by events rather than walking all panes at end
of event loop, this way the ordering of in and out can be enforced. GitHub issue 2808.
This commit is contained in:
parent
a2b8506917
commit
2bb0b9d6c5
@ -124,17 +124,9 @@ cmd_attach_session(struct cmdq_item *item, const char *tflag, int dflag,
|
||||
if (!Eflag)
|
||||
environ_update(s->options, c->environ, s->environ);
|
||||
|
||||
c->session = s;
|
||||
server_client_set_session(c, s);
|
||||
if (~cmdq_get_flags(item) & CMDQ_STATE_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);
|
||||
gettimeofday(&s->last_attached_time, NULL);
|
||||
server_redraw_client(c);
|
||||
s->curw->flags &= ~WINLINK_ALERTFLAGS;
|
||||
s->curw->window->latest = c;
|
||||
} else {
|
||||
if (server_client_open(c, &cause) != 0) {
|
||||
cmdq_error(item, "open terminal failed: %s", cause);
|
||||
@ -156,25 +148,14 @@ cmd_attach_session(struct cmdq_item *item, const char *tflag, int dflag,
|
||||
if (!Eflag)
|
||||
environ_update(s->options, c->environ, s->environ);
|
||||
|
||||
c->session = s;
|
||||
server_client_set_session(c, 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);
|
||||
gettimeofday(&s->last_attached_time, NULL);
|
||||
server_redraw_client(c);
|
||||
s->curw->flags &= ~WINLINK_ALERTFLAGS;
|
||||
s->curw->window->latest = c;
|
||||
|
||||
if (~c->flags & CLIENT_CONTROL)
|
||||
proc_send(c->peer, MSG_READY, -1, NULL, 0);
|
||||
notify_client("client-attached", c);
|
||||
c->flags |= CLIENT_ATTACHED;
|
||||
}
|
||||
recalculate_sizes();
|
||||
alerts_check_session(s);
|
||||
server_update_socket();
|
||||
|
||||
return (CMD_RETURN_NORMAL);
|
||||
}
|
||||
|
@ -329,18 +329,10 @@ cmd_new_session_exec(struct cmd *self, struct cmdq_item *item)
|
||||
proc_send(c->peer, MSG_READY, -1, NULL, 0);
|
||||
} else if (c->session != NULL)
|
||||
c->last_session = c->session;
|
||||
c->session = s;
|
||||
server_client_set_session(c, s);
|
||||
if (~cmdq_get_flags(item) & CMDQ_STATE_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);
|
||||
gettimeofday(&s->last_attached_time, NULL);
|
||||
server_redraw_client(c);
|
||||
}
|
||||
recalculate_sizes();
|
||||
server_update_socket();
|
||||
|
||||
/*
|
||||
* If there are still configuration file errors to display, put the new
|
||||
|
@ -134,23 +134,9 @@ cmd_switch_client_exec(struct cmd *self, struct cmdq_item *item)
|
||||
if (!args_has(args, 'E'))
|
||||
environ_update(s->options, tc->environ, s->environ);
|
||||
|
||||
if (tc->session != NULL && tc->session != s)
|
||||
tc->last_session = tc->session;
|
||||
tc->session = s;
|
||||
server_client_set_session(tc, s);
|
||||
if (~cmdq_get_flags(item) & CMDQ_STATE_REPEAT)
|
||||
server_client_set_key_table(tc, NULL);
|
||||
tty_update_client_offset(tc);
|
||||
status_timer_start(tc);
|
||||
notify_client("client-session-changed", tc);
|
||||
session_update_activity(s, NULL);
|
||||
gettimeofday(&s->last_attached_time, NULL);
|
||||
|
||||
server_check_unattached();
|
||||
server_redraw_client(tc);
|
||||
s->curw->flags &= ~WINLINK_ALERTFLAGS;
|
||||
s->curw->window->latest = tc;
|
||||
recalculate_sizes();
|
||||
alerts_check_session(s);
|
||||
|
||||
return (CMD_RETURN_NORMAL);
|
||||
}
|
||||
|
8
input.c
8
input.c
@ -1792,8 +1792,12 @@ input_csi_dispatch_sm_private(struct input_ctx *ictx)
|
||||
if (sctx->s->mode & MODE_FOCUSON)
|
||||
break;
|
||||
screen_write_mode_set(sctx, MODE_FOCUSON);
|
||||
if (wp != NULL)
|
||||
wp->flags |= PANE_FOCUSPUSH; /* force update */
|
||||
if (wp == NULL)
|
||||
break;
|
||||
if (wp->flags & PANE_FOCUSED)
|
||||
bufferevent_write(wp->event, "\033[I", 3);
|
||||
else
|
||||
bufferevent_write(wp->event, "\033[O", 3);
|
||||
break;
|
||||
case 1005:
|
||||
screen_write_mode_set(sctx, MODE_MOUSE_UTF8);
|
||||
|
@ -33,7 +33,6 @@
|
||||
#include "tmux.h"
|
||||
|
||||
static void server_client_free(int, short, void *);
|
||||
static void server_client_check_pane_focus(struct window_pane *);
|
||||
static void server_client_check_pane_resize(struct window_pane *);
|
||||
static void server_client_check_pane_buffer(struct window_pane *);
|
||||
static void server_client_check_window_resize(struct window *);
|
||||
@ -301,9 +300,8 @@ server_client_attached_lost(struct client *c)
|
||||
s = loop->session;
|
||||
if (loop == c || s == NULL || s->curw->window != w)
|
||||
continue;
|
||||
if (found == NULL ||
|
||||
timercmp(&loop->activity_time, &found->activity_time,
|
||||
>))
|
||||
if (found == NULL || timercmp(&loop->activity_time,
|
||||
&found->activity_time, >))
|
||||
found = loop;
|
||||
}
|
||||
if (found != NULL)
|
||||
@ -311,6 +309,40 @@ server_client_attached_lost(struct client *c)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Set client session. */
|
||||
void
|
||||
server_client_set_session(struct client *c, struct session *s)
|
||||
{
|
||||
struct session *old = c->session;
|
||||
|
||||
if (s != NULL && c->session != NULL && c->session != s)
|
||||
c->last_session = c->session;
|
||||
else if (s == NULL)
|
||||
c->last_session = NULL;
|
||||
c->session = s;
|
||||
c->flags |= CLIENT_FOCUSED;
|
||||
recalculate_sizes();
|
||||
|
||||
if (old != NULL && old->curw != NULL)
|
||||
window_update_focus(old->curw->window);
|
||||
if (s != NULL) {
|
||||
window_update_focus(s->curw->window);
|
||||
session_update_activity(s, NULL);
|
||||
gettimeofday(&s->last_attached_time, NULL);
|
||||
s->curw->flags &= ~WINLINK_ALERTFLAGS;
|
||||
s->curw->window->latest = c;
|
||||
alerts_check_session(s);
|
||||
tty_update_client_offset(c);
|
||||
status_timer_start(c);
|
||||
notify_client("client-session-changed", c);
|
||||
server_redraw_client(c);
|
||||
}
|
||||
|
||||
server_check_unattached();
|
||||
server_update_socket();
|
||||
}
|
||||
|
||||
/* Lost a client. */
|
||||
void
|
||||
server_client_lost(struct client *c)
|
||||
@ -1389,7 +1421,6 @@ server_client_loop(void)
|
||||
struct client *c;
|
||||
struct window *w;
|
||||
struct window_pane *wp;
|
||||
int focus;
|
||||
|
||||
/* Check for window resize. This is done before redrawing. */
|
||||
RB_FOREACH(w, windows, &windows)
|
||||
@ -1407,14 +1438,11 @@ server_client_loop(void)
|
||||
|
||||
/*
|
||||
* Any windows will have been redrawn as part of clients, so clear
|
||||
* their flags now. Also check pane focus and resize.
|
||||
* their flags now.
|
||||
*/
|
||||
focus = options_get_number(global_options, "focus-events");
|
||||
RB_FOREACH(w, windows, &windows) {
|
||||
TAILQ_FOREACH(wp, &w->panes, entry) {
|
||||
if (wp->fd != -1) {
|
||||
if (focus)
|
||||
server_client_check_pane_focus(wp);
|
||||
server_client_check_pane_resize(wp);
|
||||
server_client_check_pane_buffer(wp);
|
||||
}
|
||||
@ -1615,54 +1643,6 @@ out:
|
||||
bufferevent_enable(wp->event, EV_READ);
|
||||
}
|
||||
|
||||
/* Check whether pane should be focused. */
|
||||
static void
|
||||
server_client_check_pane_focus(struct window_pane *wp)
|
||||
{
|
||||
struct client *c;
|
||||
int push;
|
||||
|
||||
/* Do we need to push the focus state? */
|
||||
push = wp->flags & PANE_FOCUSPUSH;
|
||||
wp->flags &= ~PANE_FOCUSPUSH;
|
||||
|
||||
/* If we're not the active pane in our window, we're not focused. */
|
||||
if (wp->window->active != wp)
|
||||
goto not_focused;
|
||||
|
||||
/*
|
||||
* If our window is the current window in any focused clients with an
|
||||
* attached session, we're focused.
|
||||
*/
|
||||
TAILQ_FOREACH(c, &clients, entry) {
|
||||
if (c->session == NULL || !(c->flags & CLIENT_FOCUSED))
|
||||
continue;
|
||||
if (c->session->attached == 0)
|
||||
continue;
|
||||
|
||||
if (c->session->curw->window == wp->window)
|
||||
goto focused;
|
||||
}
|
||||
|
||||
not_focused:
|
||||
if (push || (wp->flags & PANE_FOCUSED)) {
|
||||
if (wp->base.mode & MODE_FOCUSON)
|
||||
bufferevent_write(wp->event, "\033[O", 3);
|
||||
notify_pane("pane-focus-out", wp);
|
||||
}
|
||||
wp->flags &= ~PANE_FOCUSED;
|
||||
return;
|
||||
|
||||
focused:
|
||||
if (push || !(wp->flags & PANE_FOCUSED)) {
|
||||
if (wp->base.mode & MODE_FOCUSON)
|
||||
bufferevent_write(wp->event, "\033[I", 3);
|
||||
notify_pane("pane-focus-in", wp);
|
||||
session_update_activity(c->session, NULL);
|
||||
}
|
||||
wp->flags |= PANE_FOCUSED;
|
||||
}
|
||||
|
||||
/*
|
||||
* Update cursor position and mode settings. The scroll region and attributes
|
||||
* are cleared when idle (waiting for an event) as this is the most likely time
|
||||
@ -2078,7 +2058,7 @@ server_client_dispatch(struct imsg *imsg, void *arg)
|
||||
case MSG_EXITING:
|
||||
if (datalen != 0)
|
||||
fatalx("bad MSG_EXITING size");
|
||||
c->session = NULL;
|
||||
server_client_set_session(c, NULL);
|
||||
tty_close(&c->tty);
|
||||
proc_send(c->peer, MSG_EXITED, -1, NULL, 0);
|
||||
break;
|
||||
|
16
server-fn.c
16
server-fn.c
@ -445,21 +445,9 @@ server_destroy_session(struct session *s)
|
||||
TAILQ_FOREACH(c, &clients, entry) {
|
||||
if (c->session != s)
|
||||
continue;
|
||||
if (s_new == NULL) {
|
||||
c->session = NULL;
|
||||
server_client_set_session(c, NULL);
|
||||
if (s_new == NULL)
|
||||
c->flags |= CLIENT_EXIT;
|
||||
} else {
|
||||
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);
|
||||
gettimeofday(&s_new->last_attached_time, NULL);
|
||||
server_redraw_client(c);
|
||||
alerts_check_session(s_new);
|
||||
}
|
||||
}
|
||||
recalculate_sizes();
|
||||
}
|
||||
|
@ -489,6 +489,8 @@ session_last(struct session *s)
|
||||
int
|
||||
session_set_current(struct session *s, struct winlink *wl)
|
||||
{
|
||||
struct winlink *old = s->curw;
|
||||
|
||||
if (wl == NULL)
|
||||
return (-1);
|
||||
if (wl == s->curw)
|
||||
@ -497,6 +499,10 @@ session_set_current(struct session *s, struct winlink *wl)
|
||||
winlink_stack_remove(&s->lastw, wl);
|
||||
winlink_stack_push(&s->lastw, s->curw);
|
||||
s->curw = wl;
|
||||
if (options_get_number(global_options, "focus-events")) {
|
||||
window_update_focus(old->window);
|
||||
window_update_focus(wl->window);
|
||||
}
|
||||
winlink_clear_flags(wl);
|
||||
window_update_activity(wl->window);
|
||||
tty_update_window_offset(wl->window);
|
||||
|
5
tmux.h
5
tmux.h
@ -1004,7 +1004,7 @@ struct window_pane {
|
||||
#define PANE_FOCUSED 0x4
|
||||
/* 0x8 unused */
|
||||
/* 0x10 unused */
|
||||
#define PANE_FOCUSPUSH 0x20
|
||||
/* 0x20 unused */
|
||||
#define PANE_INPUTOFF 0x40
|
||||
#define PANE_CHANGED 0x80
|
||||
#define PANE_EXITED 0x100
|
||||
@ -2506,6 +2506,7 @@ int server_client_handle_key(struct client *, struct key_event *);
|
||||
struct client *server_client_create(int);
|
||||
int server_client_open(struct client *, char **);
|
||||
void server_client_unref(struct client *);
|
||||
void server_client_set_session(struct client *, struct session *);
|
||||
void server_client_lost(struct client *);
|
||||
void server_client_suspend(struct client *);
|
||||
void server_client_detach(struct client *, enum msgtype);
|
||||
@ -2826,6 +2827,8 @@ struct window_pane *window_find_string(struct window *, const char *);
|
||||
int window_has_pane(struct window *, struct window_pane *);
|
||||
int window_set_active_pane(struct window *, struct window_pane *,
|
||||
int);
|
||||
void window_update_focus(struct window *);
|
||||
void window_pane_update_focus(struct window_pane *);
|
||||
void window_redraw_active_switch(struct window *,
|
||||
struct window_pane *);
|
||||
struct window_pane *window_add_pane(struct window *, struct window_pane *,
|
||||
|
@ -821,11 +821,13 @@ complete_key:
|
||||
|
||||
/* Check for focus events. */
|
||||
if (key == KEYC_FOCUS_OUT) {
|
||||
tty->client->flags &= ~CLIENT_FOCUSED;
|
||||
c->flags &= ~CLIENT_FOCUSED;
|
||||
window_update_focus(c->session->curw->window);
|
||||
notify_client("client-focus-out", c);
|
||||
} else if (key == KEYC_FOCUS_IN) {
|
||||
tty->client->flags |= CLIENT_FOCUSED;
|
||||
c->flags |= CLIENT_FOCUSED;
|
||||
notify_client("client-focus-in", c);
|
||||
window_update_focus(c->session->curw->window);
|
||||
}
|
||||
|
||||
/* Fire the key. */
|
||||
|
51
window.c
51
window.c
@ -458,6 +458,52 @@ window_has_pane(struct window *w, struct window_pane *wp)
|
||||
return (0);
|
||||
}
|
||||
|
||||
void
|
||||
window_update_focus(struct window *w)
|
||||
{
|
||||
if (w != NULL) {
|
||||
log_debug("%s: @%u", __func__, w->id);
|
||||
window_pane_update_focus(w->active);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
window_pane_update_focus(struct window_pane *wp)
|
||||
{
|
||||
struct client *c;
|
||||
int focused = 0;
|
||||
|
||||
if (wp != NULL) {
|
||||
if (wp != wp->window->active)
|
||||
focused = 0;
|
||||
else {
|
||||
TAILQ_FOREACH(c, &clients, entry) {
|
||||
if (c->session != NULL &&
|
||||
c->session->attached != 0 &&
|
||||
(c->flags & CLIENT_FOCUSED) &&
|
||||
c->session->curw->window == wp->window) {
|
||||
focused = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!focused && (wp->flags & PANE_FOCUSED)) {
|
||||
log_debug("%s: %%%u focus out", __func__, wp->id);
|
||||
if (wp->base.mode & MODE_FOCUSON)
|
||||
bufferevent_write(wp->event, "\033[O", 3);
|
||||
notify_pane("pane-focus-out", wp);
|
||||
wp->flags &= ~PANE_FOCUSED;
|
||||
} else if (focused && (~wp->flags & PANE_FOCUSED)) {
|
||||
log_debug("%s: %%%u focus in", __func__, wp->id);
|
||||
if (wp->base.mode & MODE_FOCUSON)
|
||||
bufferevent_write(wp->event, "\033[I", 3);
|
||||
notify_pane("pane-focus-in", wp);
|
||||
wp->flags |= PANE_FOCUSED;
|
||||
} else
|
||||
log_debug("%s: %%%u focus unchanged", __func__, wp->id);
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
window_set_active_pane(struct window *w, struct window_pane *wp, int notify)
|
||||
{
|
||||
@ -471,6 +517,11 @@ window_set_active_pane(struct window *w, struct window_pane *wp, int notify)
|
||||
w->active->active_point = next_active_point++;
|
||||
w->active->flags |= PANE_CHANGED;
|
||||
|
||||
if (options_get_number(global_options, "focus-events")) {
|
||||
window_pane_update_focus(w->last);
|
||||
window_pane_update_focus(w->active);
|
||||
}
|
||||
|
||||
tty_update_window_offset(w);
|
||||
|
||||
if (notify)
|
||||
|
Loading…
Reference in New Issue
Block a user