Something in your mail system is mangling patches both in and out I
guess because mine was fine when it left here and this one is mangled
too :-).
http://www.kernel.org/pub/software/scm/git/docs/git-format-patch.html
has some bits about configuring various MUAs (Under "MUA-SPECIFIC
HINTS"). Or just send them as an attachment.
Anyway take a look at my most recent email, I've attached it as well in
case you can't read it.
On Thu, Feb 21, 2013 at 10:35:34AM -0800, Aaron Jensen wrote:
> New patch, inline for comments and attached for applying. I wasn't able to
> apply your patch (same problem of tabs vs space mangling).
>
> From 4fb9858b710ed4b8cec816ea11063466806a29fa Mon Sep 17 00:00:00 2001
> From: Aaron Jensen <[1]aaronjen...@gmail.com>
> Date: Thu, 21 Feb 2013 10:33:22 -0800
> Subject: [PATCH] Add focus notify
>
> ---
> *cmd-break-pane.c* | 15 ++++++++++++++-
> *examples/tmux.vim |* 2 +-
> *input-keys.c***** |* 2 ++
> *input.c********** |* 8 ++++++++
> *options-table.c** |* 5 +++++
> *session.c******** |* 6 ++++++
> *tmux.h*********** |* 6 ++++++
> *tty-keys.c******* |* 2 ++
> *tty.c************ |* 2 +-
> *window.c********* | 34 +++++++++++++++++++++++++++++++++-
> *10 files changed, 78 insertions(+), 4 deletions(-)
>
> diff --git a/cmd-break-pane.c b/cmd-break-pane.c
> index a4350fe..b53265b 100644
> --- a/cmd-break-pane.c
> +++ b/cmd-break-pane.c
> @@ -44,7 +44,7 @@ cmd_break_pane_exec(struct cmd *self, struct cmd_ctx
> *ctx)
> **** struct args*** *** *args = self->args;
> **** struct winlink*** *** *wl;
> **** struct session*** *** *s;
> -*** struct window_pane*** *wp;
> +*** struct window_pane*** *wp, *out_wp, *in_wp;
> **** struct window*** *** *w;
> **** char*** *** *** *name;
> **** char*** *** *** *cause;
> @@ -64,6 +64,7 @@ cmd_break_pane_exec(struct cmd *self, struct cmd_ctx
> *ctx)
> *
> **** w = wl->window;
> **** TAILQ_REMOVE(&w->panes, wp, entry);
> +*** out_wp = w->active;
> **** if (wp == w->active) {
> **** *** w->active = w->last;
> **** *** w->last = NULL;
> @@ -74,6 +75,13 @@ cmd_break_pane_exec(struct cmd *self, struct cmd_ctx
> *ctx)
> **** *** }
> **** } else if (wp == w->last)
> **** *** w->last = NULL;
> +
> +*** if (args_has(self->args, 'd'))
> +*** *** in_wp = w->active;
> +*** else
> +*** *** in_wp = wp;
> +
> +
> **** layout_close_pane(wp);
> *
> **** w = wp->window = window_create1(s->sx, s->sy);
> @@ -89,6 +97,11 @@ cmd_break_pane_exec(struct cmd *self, struct cmd_ctx
> *ctx)
> **** if (!args_has(self->args, 'd'))
> **** *** session_select(s, wl->idx);
> *
> +*** if (out_wp != in_wp) {
> +*** *** window_pane_focus(out_wp, 0);
> +*** *** window_pane_focus(in_wp, 1);
> +*** }
> +
> **** server_redraw_session(s);
> **** server_status_session_group(s);
> *
> diff --git a/examples/tmux.vim b/examples/tmux.vim
> index 076115c..9200f8d 100644
> --- a/examples/tmux.vim
> +++ b/examples/tmux.vim
> @@ -64,7 +64,7 @@ syn keyword tmuxOptsSet
> **** \ base-index bell-action bell-on-alert default-command default-path
> **** \ default-shell default-terminal destroy-unattached detach-on-destroy
> **** \ display-panes-active-colour display-panes-colour display-panes-time
> -*** \ display-time history-limit
> +*** \ display-time focus-filter history-limit
> **** \ lock-after-time lock-command lock-server
> **** \ message-command-attr message-attr message-command-bg message-bg
> **** \ message-command-fg message-fg message-limit
> diff --git a/input-keys.c b/input-keys.c
> index d57926a..0b73301 100644
> --- a/input-keys.c
> +++ b/input-keys.c
> @@ -130,6 +130,8 @@ const struct input_key_ent input_keys[] = {
> **** { KEYC_KP_ENTER,*** "\n",*** *** 0 },
> **** { KEYC_KP_ZERO,*** *** "0",*** *** 0 },
> **** { KEYC_KP_PERIOD,*** ".",*** *** 0 },
> +*** { KEYC_FOCUS_IN,*** "\033[I",*** 0 },
> +*** { KEYC_FOCUS_OUT,*** "\033[O",*** 0 },
> *};
> *
> */* Translate a key code into an output key sequence. */
> diff --git a/input.c b/input.c
> index 4cf90ec..855ee8a 100644
> --- a/input.c
> +++ b/input.c
> @@ -1260,6 +1260,9 @@ input_csi_dispatch(struct input_ctx *ictx)
> **** *** case 1003:
> **** *** *** screen_write_mode_clear(&ictx->ctx, ALL_MOUSE_MODES);
> **** *** *** break;
> +*** *** case 1004:
> +*** *** *** screen_write_mode_clear(&ictx->ctx, MODE_FOCUSON);
> +*** *** *** break;
> **** *** case 1005:
> **** *** *** screen_write_mode_clear(&ictx->ctx, MODE_MOUSE_UTF8);
> **** *** *** break;
> @@ -1326,6 +1329,11 @@ input_csi_dispatch(struct input_ctx *ictx)
> **** *** *** screen_write_mode_clear(&ictx->ctx, ALL_MOUSE_MODES);
> **** *** *** screen_write_mode_set(&ictx->ctx, MODE_MOUSE_ANY);
> **** *** *** break;
> +*** *** case 1004:
> +*** *** *** screen_write_mode_set(&ictx->ctx, MODE_FOCUSON);
> +*** *** *** if (s->mode & MODE_FOCUSED)
> +*** *** *** *** bufferevent_write(wp->event, "\033[I", 3);
> +*** *** *** break;
> **** *** case 1005:
> **** *** *** screen_write_mode_set(&ictx->ctx, MODE_MOUSE_UTF8);
> **** *** *** break;
> diff --git a/options-table.c b/options-table.c
> index 37b3b10..2fa2689 100644
> --- a/options-table.c
> +++ b/options-table.c
> @@ -169,6 +169,11 @@ const struct options_table_entry
> session_options_table[] = {
> **** * .default_num = 750
> **** },
> *
> +*** { .name = "focus-filter",
> +*** * .type = OPTIONS_TABLE_FLAG,
> +*** * .default_num = 0
> +*** },
> +
> **** { .name = "history-limit",
> **** * .type = OPTIONS_TABLE_NUMBER,
> **** * .minimum = 0,
> diff --git a/session.c b/session.c
> index 72e8fb0..c7a01fd 100644
> --- a/session.c
> +++ b/session.c
> @@ -413,10 +413,16 @@ session_set_current(struct session *s, struct
> winlink *wl)
> **** if (wl == s->curw)
> **** *** return (1);
> *
> +*** if (s->curw != NULL && s->curw->window != NULL)
> +*** *** window_pane_focus(s->curw->window->active, 0);
> +
> **** winlink_stack_remove(&s->lastw, wl);
> **** winlink_stack_push(&s->lastw, s->curw);
> **** s->curw = wl;
> **** winlink_clear_flags(wl);
> +
> +*** window_pane_focus(s->curw->window->active, 1);
> +
> **** return (0);
> *}
> *
> diff --git a/tmux.h b/tmux.h
> index 18e692f..5194cb6 100644
> --- a/tmux.h
> +++ b/tmux.h
> @@ -237,6 +237,9 @@ enum key_code {
> **** KEYC_KP_ENTER,
> **** KEYC_KP_ZERO,
> **** KEYC_KP_PERIOD,
> +
> +*** KEYC_FOCUS_IN,
> +*** KEYC_FOCUS_OUT,
> *};
> *
> */* Termcap codes. */
> @@ -665,6 +668,8 @@ struct mode_key_table {
> *#define MODE_MOUSE_UTF8 0x100
> *#define MODE_MOUSE_SGR 0x200
> *#define MODE_BRACKETPASTE 0x400
> +#define MODE_FOCUSON 0x800
> +#define MODE_FOCUSED 0x1000
> *
> *#define ALL_MOUSE_MODES
> (MODE_MOUSE_STANDARD|MODE_MOUSE_BUTTON|MODE_MOUSE_ANY)
> *
> @@ -2132,6 +2137,7 @@ void*** *** *window_pane_alternate_on(struct
> window_pane *,
> **** *** **** struct grid_cell *, int);
> *void*** *** *window_pane_alternate_off(struct window_pane *,
> **** *** **** struct grid_cell *, int);
> +void*** *** *window_pane_focus(struct window_pane *, int);
> *int*** *** *window_pane_set_mode(
> **** *** **** struct window_pane *, const struct window_mode *);
> *void*** *** *window_pane_reset_mode(struct window_pane *);
> diff --git a/tty-keys.c b/tty-keys.c
> index 00327bb..87109c6 100644
> --- a/tty-keys.c
> +++ b/tty-keys.c
> @@ -174,6 +174,8 @@ const struct tty_default_key_raw
> tty_default_raw_keys[] = {
> **** { "\033[8@", KEYC_END|KEYC_CTRL|KEYC_SHIFT },
> **** { "\033[6@", KEYC_NPAGE|KEYC_CTRL|KEYC_SHIFT },
> **** { "\033[5@", KEYC_PPAGE|KEYC_CTRL|KEYC_SHIFT },
> +*** { "\033[I",*** KEYC_FOCUS_IN },
> +*** { "\033[O",*** KEYC_FOCUS_OUT },
> *};
> *
> */* Default terminfo(5) keys. */
> diff --git a/tty.c b/tty.c
> index 1abaea4..b5dcf6d 100644
> --- a/tty.c
> +++ b/tty.c
> @@ -221,7 +221,7 @@ tty_start_tty(struct tty *tty)
> **** *** tty_puts(tty, "\033[?1000l\033[?1006l\033[?1005l");
> *
> **** if (tty_term_has(tty->term, TTYC_XT))
> -*** *** tty_puts(tty, "\033[c\033[>4;1m");
> +*** *** tty_puts(tty, "\033[c\033[>4;1m\033[?1004l");
> *
> **** tty->cx = UINT_MAX;
> **** tty->cy = UINT_MAX;
> diff --git a/window.c b/window.c
> index 77f06f8..72ee4b5 100644
> --- a/window.c
> +++ b/window.c
> @@ -390,8 +390,10 @@ window_set_active_pane(struct window *w, struct
> window_pane *wp)
> **** *** if (w->active == NULL)
> **** *** *** w->active = TAILQ_LAST(&w->panes, window_panes);
> **** *** if (w->active == wp)
> -*** *** *** return;
> +*** *** *** break;
> **** }
> +*** window_pane_focus(w->last, 0);
> +*** window_pane_focus(wp, 1);
> *}
> *
> *struct window_pane *
> @@ -484,6 +486,8 @@ window_remove_pane(struct window *w, struct
> window_pane *wp)
> *
> **** TAILQ_REMOVE(&w->panes, wp, entry);
> **** window_pane_destroy(wp);
> +*** if (w != NULL)
> +*** *** window_pane_focus(w->active, 1);
> *}
> *
> *struct window_pane *
> @@ -950,6 +954,28 @@ window_pane_alternate_off(struct window_pane *wp,
> struct grid_cell *gc,
> **** wp->flags |= PANE_REDRAW;
> *}
> *
> +void
> +window_pane_focus(struct window_pane *wp, int focused)
> +{
> +*** int already_focused;
> +
> +*** if (wp == NULL || wp->event == NULL)
> +*** *** return;
> +
> +*** already_focused = (wp->screen->mode & MODE_FOCUSED);
> +*** if (focused && !already_focused) {
> +*** *** wp->screen->mode |= MODE_FOCUSED;
> +
> +*** *** if (wp->screen->mode & MODE_FOCUSON)
> +*** *** *** bufferevent_write(wp->event, "\033[I", 3);
> +*** } else if (!focused && already_focused) {
> +*** *** wp->screen->mode &= ~MODE_FOCUSED;
> +
> +*** *** if (wp->screen->mode & MODE_FOCUSON)
> +*** *** *** bufferevent_write(wp->event, "\033[O", 3);
> +*** }
> +}
> +
> *int
> *window_pane_set_mode(struct window_pane *wp, const struct window_mode
> *mode)
> *{
> @@ -994,6 +1020,12 @@ window_pane_key(struct window_pane *wp, struct
> session *sess, int key)
> *
> **** if (wp->fd == -1)
> **** *** return;
> +
> +*** if ((key == KEYC_FOCUS_IN || key == KEYC_FOCUS_OUT) &&
> +*** *** options_get_number(&sess->options, "focus-filter") &&
> +*** *** !(wp->screen->mode & MODE_FOCUSON))
> +*** *** return;
> +
> **** input_key(wp, key);
> **** if (options_get_number(&wp->window->options, "synchronize-panes")) {
> **** *** TAILQ_FOREACH(wp2, &wp->window->panes, entry) {
> --
> 1.8.0.2
>
> On Thu, Feb 21, 2013 at 10:12 AM, Aaron Jensen <[2]aaronjen...@gmail.com>
> wrote:
>
> Inlline...
> On Thu, Feb 21, 2013 at 9:28 AM, Nicholas Marriott
> <[3]nicholas.marri...@gmail.com> wrote:
>
> Ok the session_set_current_winlink idea is good so I have applied that
> bit but renamed to session_set_current.
>
> Here is an updated diff with a few changes:
>
> - Spacing fixes. Looks like your mailer mangles spaces. Can you fix
> that
> * or send the diffs as an attachment instead?
>
> Will do, sorry about that.
>
> - Renamed window_pane_focus_notify to just window_pane_focus.
> - Some other renaming and style nits.
> - Send \033[I if needed when first enabled.
>
> Interesting, if this is the expected behavior then this seems like a
> good change.
> *
>
> - Send \033[?1004l in tty.c if the terminal has XT flag.
>
> I did some googling but it's still not clear what this flag represents
> or why this is needed, could you explain please? I don't see this flag
> in my infocmp, so I'm guessing iterm2* does not have this so it won't
> affect me?
> *
>
> Please take a look at the diff below and let me know if you spot any
> errors before I commit it.
>
> I was thinking about the external focus reporting and I think just
> forwarding through the input will be fine. It will mean that the most
> recent state is the current state. So if you have two terminals and
> you
> enter them both and then exit one, you will lose focus. But most
> people
> don't use two computers simulatenously so I think this will not be a
> problem.
>
> Are you talking about the focus filtering here? If so, the problem with
> the external focus is not* things getting out of sync, but reporting
> happening to panes that do not want it. It's a hack of sorts to work
> around the fact that the external terminal doesn't understand the
> different panes in your tmux session. In other words, I would enable
> focus reporting in my terminal (iterm) and tmux both in pane 1. Then if
> I switch to pane 2, and leave focus of iterm, iterm would send ^[[O,
> which I do not actually want in pane 2, so the idea is to have tmux,
> which does have knowledge of who wants those events, discard those if
> they're not appropriate.
>
> Some more comments inline...
> *
>
> So when the bits below are in if you could update your other
> changes on top of them it would be great.
>
> diff --git a/cmd-break-pane.c b/cmd-break-pane.c
> index a4350fe..8e2a375 100644
> --- a/cmd-break-pane.c
> +++ b/cmd-break-pane.c
> @@ -44,7 +44,7 @@ cmd_break_pane_exec(struct cmd *self, struct cmd_ctx
> *ctx)
> * * * * struct args * * * * * * *args = self->args;
> * * * * struct winlink * * * * **wl;
> * * * * struct session * * * * **s;
> - * * * struct window_pane * * **wp;
> + * * * struct window_pane * * **wp, *out_wp, *in_wp;
> * * * * struct window * * * * * *w;
> * * * * char * * * * * * * * * **name;
> * * * * char * * * * * * * * * **cause;
> @@ -63,6 +63,7 @@ cmd_break_pane_exec(struct cmd *self, struct cmd_ctx
> *ctx)
> * * * * }
>
> * * * * w = wl->window;
> + * * * out_wp = w->active;
> * * * * TAILQ_REMOVE(&w->panes, wp, entry);
> * * * * if (wp == w->active) {
> * * * * * * * * w->active = w->last;
> @@ -74,6 +75,12 @@ cmd_break_pane_exec(struct cmd *self, struct
> cmd_ctx *ctx)
> * * * * * * * * }
> * * * * } else if (wp == w->last)
> * * * * * * * * w->last = NULL;
> +
> + * * * if (args_has(self->args, 'd'))
> + * * * * * * * in_wp = w->active;
> + * * * else
> + * * * * * * * in_wp = wp;
> +
> * * * * layout_close_pane(wp);
>
> * * * * w = wp->window = window_create1(s->sx, s->sy);
> @@ -89,6 +96,11 @@ cmd_break_pane_exec(struct cmd *self, struct
> cmd_ctx *ctx)
> * * * * if (!args_has(self->args, 'd'))
> * * * * * * * * session_select(s, wl->idx);
>
> + * * * if (out_wp != in_wp) {
> + * * * * * * * window_pane_focus(out_wp, 0);
> + * * * * * * * window_pane_focus(in_wp, 1);
> + * * * }
> +
>
> I think there's still a bug here, but I haven't tested these changes yet
> (they look only cosmetic). The problem is that if you break-pane the
> pane you're on will get a focus out.
> *
>
> * * * * server_redraw_session(s);
> * * * * server_status_session_group(s);
>
> diff --git a/input.c b/input.c
> index 4cf90ec..855ee8a 100644
> --- a/input.c
> +++ b/input.c
> @@ -1260,6 +1260,9 @@ input_csi_dispatch(struct input_ctx *ictx)
> * * * * * * * * case 1003:
> * * * * * * * * * * * * screen_write_mode_clear(&ictx->ctx,
> ALL_MOUSE_MODES);
> * * * * * * * * * * * * break;
> + * * * * * * * case 1004:
> + * * * * * * * * * * * screen_write_mode_clear(&ictx->ctx,
> MODE_FOCUSON);
> + * * * * * * * * * * * break;
> * * * * * * * * case 1005:
> * * * * * * * * * * * * screen_write_mode_clear(&ictx->ctx,
> MODE_MOUSE_UTF8);
> * * * * * * * * * * * * break;
> @@ -1326,6 +1329,11 @@ input_csi_dispatch(struct input_ctx *ictx)
> * * * * * * * * * * * * screen_write_mode_clear(&ictx->ctx,
> ALL_MOUSE_MODES);
> * * * * * * * * * * * * screen_write_mode_set(&ictx->ctx,
> MODE_MOUSE_ANY);
> * * * * * * * * * * * * break;
> + * * * * * * * case 1004:
> + * * * * * * * * * * * screen_write_mode_set(&ictx->ctx,
> MODE_FOCUSON);
> + * * * * * * * * * * * if (s->mode & MODE_FOCUSED)
> + * * * * * * * * * * * * * * * bufferevent_write(wp->event, "\033[I",
> 3);
> + * * * * * * * * * * * break;
> * * * * * * * * case 1005:
> * * * * * * * * * * * * screen_write_mode_set(&ictx->ctx,
> MODE_MOUSE_UTF8);
> * * * * * * * * * * * * break;
> diff --git a/session.c b/session.c
> index 72e8fb0..c7a01fd 100644
> --- a/session.c
> +++ b/session.c
> @@ -413,10 +413,16 @@ session_set_current(struct session *s, struct
> winlink *wl)
> * * * * if (wl == s->curw)
> * * * * * * * * return (1);
>
> + * * * if (s->curw != NULL && s->curw->window != NULL)
> + * * * * * * * window_pane_focus(s->curw->window->active, 0);
> +
> * * * * winlink_stack_remove(&s->lastw, wl);
> * * * * winlink_stack_push(&s->lastw, s->curw);
> * * * * s->curw = wl;
> * * * * winlink_clear_flags(wl);
> +
> + * * * window_pane_focus(s->curw->window->active, 1);
> +
> * * * * return (0);
> *}
>
> diff --git a/tmux.h b/tmux.h
> index 18e692f..2322b5b 100644
> --- a/tmux.h
> +++ b/tmux.h
> @@ -665,6 +665,8 @@ struct mode_key_table {
> *#define MODE_MOUSE_UTF8 0x100
> *#define MODE_MOUSE_SGR 0x200
> *#define MODE_BRACKETPASTE 0x400
> +#define MODE_FOCUSON 0x800
> +#define MODE_FOCUSED 0x1000
>
> *#define ALL_MOUSE_MODES
> (MODE_MOUSE_STANDARD|MODE_MOUSE_BUTTON|MODE_MOUSE_ANY)
>
> @@ -2132,6 +2134,7 @@ void * * * * * * *
> window_pane_alternate_on(struct window_pane *,
> * * * * * * * * * * *struct grid_cell *, int);
> *void * * * * * *window_pane_alternate_off(struct window_pane *,
> * * * * * * * * * * *struct grid_cell *, int);
> +void * * * * * *window_pane_focus(struct window_pane *, int);
> *int * * * * * * window_pane_set_mode(
> * * * * * * * * * * *struct window_pane *, const struct window_mode
> *);
> *void * * * * * *window_pane_reset_mode(struct window_pane *);
> diff --git a/tty.c b/tty.c
> index 1abaea4..b5dcf6d 100644
> --- a/tty.c
> +++ b/tty.c
> @@ -221,7 +221,7 @@ tty_start_tty(struct tty *tty)
> * * * * * * * * tty_puts(tty, "\033[?1000l\033[?1006l\033[?1005l");
>
> * * * * if (tty_term_has(tty->term, TTYC_XT))
> - * * * * * * * tty_puts(tty, "\033[c\033[>4;1m");
> + * * * * * * * tty_puts(tty, "\033[c\033[>4;1m\033[?1004l");
>
> * * * * tty->cx = UINT_MAX;
> * * * * tty->cy = UINT_MAX;
> diff --git a/window.c b/window.c
> index 77f06f8..457e3e1 100644
> --- a/window.c
> +++ b/window.c
> @@ -390,8 +390,10 @@ window_set_active_pane(struct window *w, struct
> window_pane *wp)
> * * * * * * * * if (w->active == NULL)
> * * * * * * * * * * * * w->active = TAILQ_LAST(&w->panes,
> window_panes);
> * * * * * * * * if (w->active == wp)
> - * * * * * * * * * * * return;
> + * * * * * * * * * * * break;
> * * * * }
> + * * * window_pane_focus(w->last, 0);
> + * * * window_pane_focus(wp, 1);
> *}
>
> *struct window_pane *
> @@ -484,6 +486,8 @@ window_remove_pane(struct window *w, struct
> window_pane *wp)
>
> * * * * TAILQ_REMOVE(&w->panes, wp, entry);
> * * * * window_pane_destroy(wp);
> + * * * if (w != NULL)
> + * * * * * * * window_pane_focus(w->active, 1);
> *}
>
> *struct window_pane *
> @@ -950,6 +954,30 @@ window_pane_alternate_off(struct window_pane *wp,
> struct grid_cell *gc,
> * * * * wp->flags |= PANE_REDRAW;
> *}
>
> +void
> +window_pane_focus(struct window_pane *wp, int focused)
> +{
> + * * * int * * already_focused;
> +
> + * * * if (wp == NULL)
> + * * * * * * * return;
>
> If I remember correctly, wp->event is NULL in some cases (closing the
> last pane for example) which is why I added that check. It crashed on
> exit.
> *
>
> +
> + * * * already_focused = (wp->screen->mode & MODE_FOCUSED);
> + * * * if (focused && !already_focused) {
> + * * * * * * * wp->screen->mode |= MODE_FOCUSED;
> +
> + * * * * * * * if (wp->screen->mode & MODE_FOCUSON)
> + * * * * * * * * * * * bufferevent_write(wp->event, "\033[I", 3);
> + * * * }
> +
> + * * * if (!focused && already_focused) {
> + * * * * * * * wp->screen->mode &= ~MODE_FOCUSED;
> +
> + * * * * * * * if (wp->screen->mode & MODE_FOCUSON)
> + * * * * * * * * * * * bufferevent_write(wp->event, "\033[O", 3);
> + * * * }
> +}
> +
> *int
> *window_pane_set_mode(struct window_pane *wp, const struct window_mode
> *mode)
> *{
>
> References
>
> Visible links
> 1. mailto:aaronjen...@gmail.com
> 2. mailto:aaronjen...@gmail.com
> 3. mailto:nicholas.marri...@gmail.com
diff --git a/input.c b/input.c
index 4cf90ec..4aa02e9 100644
--- a/input.c
+++ b/input.c
@@ -1260,6 +1260,9 @@ input_csi_dispatch(struct input_ctx *ictx)
case 1003:
screen_write_mode_clear(&ictx->ctx, ALL_MOUSE_MODES);
break;
+ case 1004:
+ screen_write_mode_clear(&ictx->ctx, MODE_FOCUSON);
+ break;
case 1005:
screen_write_mode_clear(&ictx->ctx, MODE_MOUSE_UTF8);
break;
@@ -1326,6 +1329,12 @@ input_csi_dispatch(struct input_ctx *ictx)
screen_write_mode_clear(&ictx->ctx, ALL_MOUSE_MODES);
screen_write_mode_set(&ictx->ctx, MODE_MOUSE_ANY);
break;
+ case 1004:
+ if (s->mode & MODE_FOCUSON)
+ break;
+ screen_write_mode_set(&ictx->ctx, MODE_FOCUSON);
+ wp->flags &= ~PANE_FOCUSED; /* force update if needed */
+ break;
case 1005:
screen_write_mode_set(&ictx->ctx, MODE_MOUSE_UTF8);
break;
diff --git a/server-client.c b/server-client.c
index 56dd379..a6f6bdb 100644
--- a/server-client.c
+++ b/server-client.c
@@ -27,6 +27,7 @@
#include "tmux.h"
+void server_client_check_focus(struct window_pane *);
void server_client_check_mouse(struct client *, struct window_pane *);
void server_client_repeat_timer(int, short, void *);
void server_client_check_exit(struct client *);
@@ -494,7 +495,7 @@ server_client_loop(void)
/*
* Any windows will have been redrawn as part of clients, so clear
- * their flags now.
+ * their flags now. Also check and update pane focus.
*/
for (i = 0; i < ARRAY_LENGTH(&windows); i++) {
w = ARRAY_ITEM(&windows, i);
@@ -502,9 +503,52 @@ server_client_loop(void)
continue;
w->flags &= ~WINDOW_REDRAW;
- TAILQ_FOREACH(wp, &w->panes, entry)
+ TAILQ_FOREACH(wp, &w->panes, entry) {
+ server_client_check_focus(wp);
wp->flags &= ~PANE_REDRAW;
+ }
+ }
+}
+
+/* Check whether pane should be focused. */
+void
+server_client_check_focus(struct window_pane *wp)
+{
+ struct session *s;
+
+ /* If we don't care about focus, forget it. */
+ if (!(wp->base.mode & MODE_FOCUSON))
+ return;
+
+ /* If we're not the active pane in our window, we're not focused. */
+ if (wp->window->active != wp)
+ goto not_focused;
+
+ /* If we're in a mode, we're not focused. */
+ if (wp->saved_grid != NULL)
+ goto not_focused;
+
+ /*
+ * If our window is the current window in any attached sessions, we're
+ * focused.
+ */
+ RB_FOREACH(s, sessions, &sessions) {
+ if (s->flags & SESSION_UNATTACHED)
+ continue;
+ if (s->curw->window == wp->window)
+ goto focused;
}
+
+not_focused:
+ if (wp->flags & PANE_FOCUSED)
+ bufferevent_write(wp->event, "\033[O", 3);
+ wp->flags &= ~PANE_FOCUSED;
+ return;
+
+focused:
+ if (!(wp->flags & PANE_FOCUSED))
+ bufferevent_write(wp->event, "\033[I", 3);
+ wp->flags |= PANE_FOCUSED;
}
/*
diff --git a/tmux.h b/tmux.h
index 18e692f..8c06197 100644
--- a/tmux.h
+++ b/tmux.h
@@ -665,6 +665,7 @@ struct mode_key_table {
#define MODE_MOUSE_UTF8 0x100
#define MODE_MOUSE_SGR 0x200
#define MODE_BRACKETPASTE 0x400
+#define MODE_FOCUSON 0x800
#define ALL_MOUSE_MODES (MODE_MOUSE_STANDARD|MODE_MOUSE_BUTTON|MODE_MOUSE_ANY)
@@ -926,6 +927,7 @@ struct window_pane {
int flags;
#define PANE_REDRAW 0x1
#define PANE_DROP 0x2
+#define PANE_FOCUSED 0x4
char *cmd;
char *shell;
diff --git a/tty.c b/tty.c
index 1abaea4..b5dcf6d 100644
--- a/tty.c
+++ b/tty.c
@@ -221,7 +221,7 @@ tty_start_tty(struct tty *tty)
tty_puts(tty, "\033[?1000l\033[?1006l\033[?1005l");
if (tty_term_has(tty->term, TTYC_XT))
- tty_puts(tty, "\033[c\033[>4;1m");
+ tty_puts(tty, "\033[c\033[>4;1m\033[?1004l");
tty->cx = UINT_MAX;
tty->cy = UINT_MAX;
------------------------------------------------------------------------------
Everyone hates slow websites. So do we.
Make your web apps faster with AppDynamics
Download AppDynamics Lite for free today:
http://p.sf.net/sfu/appdyn_d2d_feb
_______________________________________________
tmux-users mailing list
tmux-users@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/tmux-users