Actually I think this is the wrong approach because there are too many
corner cases (you missed out at least attach, detach and linked
windows).

Please try this instead which just checks the panes at the end of the
server loop.

I think this will work better when you are listening for the keys in and
know which clients are focused as well, it will just be necessary to
check if the attached session is also attached to a focused client.



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;




On Thu, Feb 21, 2013 at 05:28:40PM +0000, Nicholas Marriott 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?
> - Renamed window_pane_focus_notify to just window_pane_focus.
> - Some other renaming and style nits.
> - Send \033[I if needed when first enabled.
> - Send \033[?1004l in tty.c if the terminal has XT flag.
> 
> 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. 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
al> 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);
> +     }
> +
>       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;
> +
> +     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)
>  {

------------------------------------------------------------------------------
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