aboutsummaryrefslogtreecommitdiff
path: root/server-client.c
diff options
context:
space:
mode:
authornicm <nicm>2021-08-13 06:52:51 +0000
committernicm <nicm>2021-08-13 06:52:51 +0000
commit2bb0b9d6c5edd7c4127c971f5ccebed969f86c1c (patch)
treedc1ce41c165065e588de274dd754113bd0cb8a3f /server-client.c
parenta2b85069171413aa30c812d44bf8ee4d32a2f834 (diff)
downloadrtmux-2bb0b9d6c5edd7c4127c971f5ccebed969f86c1c.tar.gz
rtmux-2bb0b9d6c5edd7c4127c971f5ccebed969f86c1c.tar.bz2
rtmux-2bb0b9d6c5edd7c4127c971f5ccebed969f86c1c.zip
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.
Diffstat (limited to 'server-client.c')
-rw-r--r--server-client.c96
1 files changed, 38 insertions, 58 deletions
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;