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

Reply via email to