From 2bb0b9d6c5edd7c4127c971f5ccebed969f86c1c Mon Sep 17 00:00:00 2001 From: nicm Date: Fri, 13 Aug 2021 06:52:51 +0000 Subject: 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. --- server-client.c | 96 +++++++++++++++++++++++---------------------------------- 1 file changed, 38 insertions(+), 58 deletions(-) (limited to 'server-client.c') 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; -- cgit From 7789639b5d1818ebbac7bfab74959e4968d7cdf2 Mon Sep 17 00:00:00 2001 From: nicm Date: Fri, 13 Aug 2021 18:54:54 +0000 Subject: Add a menu when a popup is present (mouse only for now). --- server-client.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'server-client.c') diff --git a/server-client.c b/server-client.c index f4cc7865..08584e7b 100644 --- a/server-client.c +++ b/server-client.c @@ -134,7 +134,7 @@ server_client_clear_overlay(struct client *c) evtimer_del(&c->overlay_timer); if (c->overlay_free != NULL) - c->overlay_free(c); + c->overlay_free(c, c->overlay_data); c->overlay_check = NULL; c->overlay_mode = NULL; @@ -1390,7 +1390,7 @@ server_client_handle_key(struct client *c, struct key_event *event) status_message_clear(c); } if (c->overlay_key != NULL) { - switch (c->overlay_key(c, event)) { + switch (c->overlay_key(c, c->overlay_data, event)) { case 0: return (0); case 1: @@ -1673,7 +1673,7 @@ server_client_reset_state(struct client *c) /* Get mode from overlay if any, else from screen. */ if (c->overlay_draw != NULL) { if (c->overlay_mode != NULL) - s = c->overlay_mode(c, &cx, &cy); + s = c->overlay_mode(c, c->overlay_data, &cx, &cy); } else s = wp->screen; if (s != NULL) @@ -2050,7 +2050,7 @@ server_client_dispatch(struct imsg *imsg, void *arg) if (c->overlay_resize == NULL) server_client_clear_overlay(c); else - c->overlay_resize(c); + c->overlay_resize(c, c->overlay_data); server_redraw_client(c); if (c->session != NULL) notify_client("client-resized", c); -- cgit