Sorry for the late reply.  I totally missed this thread (again) in my inbox.

These changes seem fine to me... whatever gets my patch accepted! ;)

I re-used *wp instead of adding a new member because I wanted to
minimize the amount of changes I made to the codebase.  The less
changes I make, the easier it is for a developer like you to review my
patch and the higher the chances of my patch being accepted.

Also, re-using *wp had the nice effect of keeping memory usage down
(no extra member in the struct), but I doubt that matters in these
days of multi-gigabyte RAM modules. :)

Thanks for your consideration.

On Wed, Jan 22, 2014 at 3:10 PM, Nicholas Marriott
<nicholas.marri...@gmail.com> wrote:
> hi
>
> take a look at this please - tweaked style and naming somewhat,
> particularly we have never used focus for anything apart from the focus
> events before so no reason to start now
>
> also used a new member of layout_cell otherwise it changes the layout
> string
>
> (this seems like another thing that should really be part of the layout
> code but there is already other stuff like that and your way is
> simpler. a revamp of layouts has been on the todo list for a while :-).)
>
> Index: tmux.h
> ===================================================================
> RCS file: /cvs/src/usr.bin/tmux/tmux.h,v
> retrieving revision 1.433
> diff -u -p -r1.433 tmux.h
> --- tmux.h      9 Jan 2014 14:20:55 -0000       1.433
> +++ tmux.h      22 Jan 2014 23:10:34 -0000
> @@ -1028,6 +1028,8 @@ struct layout_cell {
>         u_int            yoff;
>
>         struct window_pane *wp;
> +       struct window_pane *lastwp;
> +
>         struct layout_cells cells;
>
>         TAILQ_ENTRY(layout_cell) entry;
> Index: window.c
> ===================================================================
> RCS file: /cvs/src/usr.bin/tmux/window.c,v
> retrieving revision 1.99
> diff -u -p -r1.99 window.c
> --- window.c    10 Oct 2013 12:26:37 -0000      1.99
> +++ window.c    22 Jan 2014 23:10:34 -0000
> @@ -61,6 +61,10 @@ struct window_pane_tree all_window_panes
>  u_int  next_window_pane_id;
>  u_int  next_window_id;
>
> +struct window_pane *window_pane_active_set(struct window_pane *,
> +           struct window_pane *);
> +void   window_pane_active_lost(struct window_pane *, struct window_pane *);
> +
>  void   window_pane_timer_callback(int, short, void *);
>  void   window_pane_read_callback(struct bufferevent *, void *);
>  void   window_pane_error_callback(struct bufferevent *, short, void *);
> @@ -386,6 +390,59 @@ window_resize(struct window *w, u_int sx
>         w->sy = sy;
>  }
>
> +/*
> + * Restore previously active pane when changing from wp to nextwp. The 
> intended
> + * pane is in nextwp and it returns the previously focused pane.
> + */
> +struct window_pane *
> +window_pane_active_set(struct window_pane *wp, struct window_pane *nextwp)
> +{
> +       struct layout_cell      *lc;
> +       struct window_pane      *lastwp;
> +
> +       /* Target pane's parent must not be an ancestor of source pane. */
> +       for (lc = wp->layout_cell->parent; lc != NULL; lc = lc->parent) {
> +               if (lc == nextwp->layout_cell->parent)
> +                       return (nextwp);
> +       }
> +
> +       /*
> +        * Previously active pane, if any, must not be the same as the source
> +        * pane.
> +        */
> +       if (nextwp->layout_cell->parent != NULL) {
> +               lastwp = nextwp->layout_cell->parent->lastwp;
> +               if (lastwp != wp && window_pane_visible(lastwp))
> +                       return (lastwp);
> +       }
> +       return (nextwp);
> +}
> +
> +/* Remember previously active pane when changing from wp to nextwp. */
> +void
> +window_pane_active_lost(struct window_pane *wp, struct window_pane *nextwp)
> +{
> +       struct layout_cell      *lc, *lc2;
> +
> +       /* Save the target pane in its parent. */
> +       nextwp->layout_cell->parent->lastwp = nextwp;
> +
> +       /*
> +        * Save the source pane in all of its parents up to, but not 
> including,
> +        * the common ancestor of itself and the target panes.
> +        */
> +       if (wp == NULL)
> +               return;
> +       for (lc = wp->layout_cell->parent; lc != NULL; lc = lc->parent) {
> +               lc2 = nextwp->layout_cell->parent;
> +               for (; lc2 != NULL; lc2 = lc2->parent) {
> +                       if (lc == lc2)
> +                               return;
> +               }
> +               lc->lastwp = wp;
> +       }
> +}
> +
>  void
>  window_set_active_pane(struct window *w, struct window_pane *wp)
>  {
> @@ -393,6 +450,7 @@ window_set_active_pane(struct window *w,
>                 return;
>         w->last = w->active;
>         w->active = wp;
> +       window_pane_active_lost(w->last, wp);
>         while (!window_pane_visible(w->active)) {
>                 w->active = TAILQ_PREV(w->active, window_panes, entry);
>                 if (w->active == NULL)
> @@ -707,6 +765,16 @@ window_pane_create(struct window *w, u_i
>  void
>  window_pane_destroy(struct window_pane *wp)
>  {
> +       struct window_pane      *wp2;
> +
> +       /* Forget removed pane in all layout cells that remember it. */
> +       RB_FOREACH(wp2, window_pane_tree, &all_window_panes) {
> +               if (wp2->layout_cell != NULL &&
> +                   wp2->layout_cell->parent != NULL &&
> +                   wp2->layout_cell->parent->lastwp == wp)
> +                       wp2->layout_cell->parent->lastwp = NULL;
> +       }
> +
>         window_pane_reset_mode(wp);
>
>         if (event_initialized(&wp->changes_timer))
> @@ -1130,7 +1198,7 @@ window_pane_find_up(struct window_pane *
>                 if (wp2->yoff + wp2->sy + 1 != top)
>                         continue;
>                 if (left >= wp2->xoff && left <= wp2->xoff + wp2->sx)
> -                       return (wp2);
> +                       return (window_pane_active_set(wp, wp2));
>         }
>         return (NULL);
>  }
> @@ -1156,7 +1224,7 @@ window_pane_find_down(struct window_pane
>                 if (wp2->yoff != bottom)
>                         continue;
>                 if (left >= wp2->xoff && left <= wp2->xoff + wp2->sx)
> -                       return (wp2);
> +                       return (window_pane_active_set(wp, wp2));
>         }
>         return (NULL);
>  }
> @@ -1185,7 +1253,7 @@ window_pane_find_left(struct window_pane
>                 if (wp2->xoff + wp2->sx + 1 != left)
>                         continue;
>                 if (top >= wp2->yoff && top <= wp2->yoff + wp2->sy)
> -                       return (wp2);
> +                       return (window_pane_active_set(wp, wp2));
>         }
>         return (NULL);
>  }
> @@ -1214,7 +1282,7 @@ window_pane_find_right(struct window_pan
>                 if (wp2->xoff != right)
>                         continue;
>                 if (top >= wp2->yoff && top <= wp2->yoff + wp2->sy)
> -                       return (wp2);
> +                       return (window_pane_active_set(wp, wp2));
>         }
>         return (NULL);
>  }
>
>
>
> On Tue, Jan 14, 2014 at 10:10:00AM -0800, Suraj N. Kurapati wrote:
>> This patch makes non-window-pane layout cells remember which of their
>> descendant window panes previously had focus (or was "active" in tmux
>> parlance) so that the focus may be restored later on, when applicable.
>>
>> For example, consider the following scenario created by steps 1-5:
>>
>>         1            2            3            4            5
>>
>>     @@@@@@@@@    +---@@@@@    +---+---+    @@@@@---+    +---+---+
>>     @       @    |   @   @    |   | Y |    @   @ Y |    |   | Y |
>>     @   X   @    | X @ Y @    | X @@@@@    @ X @---+    | X @@@@@
>>     @       @    |   @   @    |   @ Z @    @   @ Z |    |   @ Z @
>>     @@@@@@@@@    +---@@@@@    +---@@@@@    @@@@@---+    +---@@@@@
>>
>> 1. We run `tmux new-window` to create pane X.
>> 2. We run `tmux split-window -h` to create and focus pane Y.
>> 3. We run `tmux split-window` to create and focus pane Z.
>> 4. We run `tmux select-pane -L` to focus pane X.
>> 5. We run `tmux select-pane -R` to focus pane Z, thanks to this patch.
>>    Without this patch, this step would focus pane Y instead of pane Z.
>>
>> Although this example illustrates a rather simple scenario, note that
>> this patch can handle more complex (nested cell) layouts just as well.
>> ---
>>  window.c | 70 
>> ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++----
>>  1 file changed, 66 insertions(+), 4 deletions(-)
>>
>> diff --git a/window.c b/window.c
>> index 7678adc..adb67e0 100644
>> --- a/window.c
>> +++ b/window.c
>> @@ -383,6 +383,34 @@ window_resize(struct window *w, u_int sx, u_int sy)
>>       w->sy = sy;
>>  }
>>
>> +/*
>> + * Commandeers the transfer of focus from `wp` to `wp2` in order to mark 
>> `wp`
>> + * so that window_pane_refocus is able to restore focus to it when 
>> necessary.
>> + */
>> +static void
>> +window_pane_defocus(struct window_pane *wp, struct window_pane *wp2)
>> +{
>> +     struct layout_cell *lc, *lc2;
>> +
>> +     /* remember the target pane's focus in its parent */
>> +     wp2->layout_cell->parent->wp = wp2;
>> +
>> +     if (wp == NULL)
>> +             return;
>> +
>> +     /* remember the source pane's focus in all of its parents up to, but
>> +      * not including, the common ancestor of itself and the target pane */
>> +     for(lc = wp->layout_cell->parent; lc != NULL; lc = lc->parent) {
>> +             /* search for a common ancestor in the target's lineage */
>> +             for(lc2 = wp2->layout_cell->parent; lc2 != NULL; lc2 = 
>> lc2->parent)
>> +                     if (lc == lc2)
>> +                             /* found a common ancestor so stop here */
>> +                             return;
>> +             /* remember the source pane's focus in its uncommon parent */
>> +             lc->wp = wp;
>> +     }
>> +}
>> +
>>  void
>>  window_set_active_pane(struct window *w, struct window_pane *wp)
>>  {
>> @@ -390,6 +418,7 @@ window_set_active_pane(struct window *w, struct 
>> window_pane *wp)
>>               return;
>>       w->last = w->active;
>>       w->active = wp;
>> +     window_pane_defocus(w->last, wp);
>>       while (!window_pane_visible(w->active)) {
>>               w->active = TAILQ_PREV(w->active, window_panes, entry);
>>               if (w->active == NULL)
>> @@ -704,6 +733,14 @@ window_pane_create(struct window *w, u_int sx, u_int 
>> sy, u_int hlimit)
>>  void
>>  window_pane_destroy(struct window_pane *wp)
>>  {
>> +     /* forget removed pane's focus in all layout cells that remember it */
>> +     struct window_pane *wp2;
>> +     RB_FOREACH(wp2, window_pane_tree, &all_window_panes)
>> +             if (wp2->layout_cell != NULL &&
>> +                 wp2->layout_cell->parent != NULL &&
>> +                 wp2->layout_cell->parent->wp == wp)
>> +                     wp2->layout_cell->parent->wp = NULL; /* forget pane */
>> +
>>       window_pane_reset_mode(wp);
>>
>>       if (event_initialized(&wp->changes_timer))
>> @@ -1110,6 +1147,31 @@ window_pane_search(struct window_pane *wp, const char 
>> *searchstr, u_int *lineno)
>>       return (msg);
>>  }
>>
>> +/*
>> + * Commandeers the transfer of focus from `wp` to `wp2` in order to restore
>> + * focus to a previously focused window pane marked by window_pane_defocus.
>> + * If this is not possible, the transfer proceeds as originally intended.
>> + */
>> +static struct window_pane *
>> +window_pane_refocus(struct window_pane *wp, struct window_pane *wp2)
>> +{
>> +     struct layout_cell *lc;
>> +     struct window_pane *fp; /* pane marked by window_pane_defocus */
>> +
>> +     /* target pane's parent must not be an ancestor of source pane */
>> +     for (lc = wp->layout_cell->parent; lc != NULL; lc = lc->parent)
>> +             if (lc == wp2->layout_cell->parent)
>> +                     return (wp2);
>> +
>> +     /* focused pane, if any, must not be the same as source pane */
>> +     lc = wp2->layout_cell->parent;
>> +     fp = lc != NULL ? lc->wp : NULL;
>> +     if (fp != NULL && fp != wp && window_pane_visible(fp))
>> +             return (fp);
>> +     else
>> +             return (wp2);
>> +}
>> +
>>  /* Find the pane directly above another. */
>>  struct window_pane *
>>  window_pane_find_up(struct window_pane *wp)
>> @@ -1131,7 +1193,7 @@ window_pane_find_up(struct window_pane *wp)
>>               if (wp2->yoff + wp2->sy + 1 != top)
>>                       continue;
>>               if (left >= wp2->xoff && left <= wp2->xoff + wp2->sx)
>> -                     return (wp2);
>> +                     return window_pane_refocus(wp, wp2);
>>       }
>>       return (NULL);
>>  }
>> @@ -1157,7 +1219,7 @@ window_pane_find_down(struct window_pane *wp)
>>               if (wp2->yoff != bottom)
>>                       continue;
>>               if (left >= wp2->xoff && left <= wp2->xoff + wp2->sx)
>> -                     return (wp2);
>> +                     return window_pane_refocus(wp, wp2);
>>       }
>>       return (NULL);
>>  }
>> @@ -1186,7 +1248,7 @@ window_pane_find_left(struct window_pane *wp)
>>               if (wp2->xoff + wp2->sx + 1 != left)
>>                       continue;
>>               if (top >= wp2->yoff && top <= wp2->yoff + wp2->sy)
>> -                     return (wp2);
>> +                     return window_pane_refocus(wp, wp2);
>>       }
>>       return (NULL);
>>  }
>> @@ -1215,7 +1277,7 @@ window_pane_find_right(struct window_pane *wp)
>>               if (wp2->xoff != right)
>>                       continue;
>>               if (top >= wp2->yoff && top <= wp2->yoff + wp2->sy)
>> -                     return (wp2);
>> +                     return window_pane_refocus(wp, wp2);
>>       }
>>       return (NULL);
>>  }
>> --
>> 1.8.5.2
>>

------------------------------------------------------------------------------
WatchGuard Dimension instantly turns raw network data into actionable 
security intelligence. It gives you real-time visual feedback on key
security issues and trends.  Skip the complicated setup - simply import
a virtual appliance and go from zero to informed in seconds.
http://pubads.g.doubleclick.net/gampad/clk?id=123612991&iu=/4140/ostg.clktrk
_______________________________________________
tmux-users mailing list
tmux-users@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/tmux-users

Reply via email to