mirror of
https://github.com/tmux/tmux.git
synced 2025-09-02 13:37:12 +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:
@ -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;
|
||||
|
Reference in New Issue
Block a user