aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--cmd-attach-session.c23
-rw-r--r--cmd-new-session.c10
-rw-r--r--cmd-switch-client.c16
-rw-r--r--input.c8
-rw-r--r--server-client.c96
-rw-r--r--server-fn.c16
-rw-r--r--session.c6
-rw-r--r--tmux.h5
-rw-r--r--tty-keys.c6
-rw-r--r--window.c51
10 files changed, 115 insertions, 122 deletions
diff --git a/cmd-attach-session.c b/cmd-attach-session.c
index 6a7ebba7..c2074f4f 100644
--- a/cmd-attach-session.c
+++ b/cmd-attach-session.c
@@ -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);
}
diff --git a/cmd-new-session.c b/cmd-new-session.c
index 033c707f..f3a5de26 100644
--- a/cmd-new-session.c
+++ b/cmd-new-session.c
@@ -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
diff --git a/cmd-switch-client.c b/cmd-switch-client.c
index b10496e3..bc6baa6a 100644
--- a/cmd-switch-client.c
+++ b/cmd-switch-client.c
@@ -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);
}
diff --git a/input.c b/input.c
index 49ed68b7..155144b7 100644
--- a/input.c
+++ b/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);
diff --git a/server-client.c b/server-client.c
index 3b102beb..f4cc7865 100644
--- a/server-client.c
+++ b/server-client.c
@@ -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;
diff --git a/server-fn.c b/server-fn.c
index 4358fa5c..9b2f073b 100644
--- a/server-fn.c
+++ b/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();
}
diff --git a/session.c b/session.c
index cb0093a2..73f44e18 100644
--- a/session.c
+++ b/session.c
@@ -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);
diff --git a/tmux.h b/tmux.h
index 3ac272f8..55df8005 100644
--- a/tmux.h
+++ b/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 *,
diff --git a/tty-keys.c b/tty-keys.c
index 02fba0e5..156fceba 100644
--- a/tty-keys.c
+++ b/tty-keys.c
@@ -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. */
diff --git a/window.c b/window.c
index f94acfcb..446898cb 100644
--- a/window.c
+++ b/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)