Hi Nicholas,

The discussion in ticket #97 http://sourceforge.net/p/tmux/tickets/97/
seems to validate my patch.

That makes me wonder... has it already been accepted into the tmux codebase?

If so, could you please tell me the commit SHA so I can verify?

Thanks for your consideration.

On Wed, Jan 29, 2014 at 2:17 PM, Suraj Kurapati <sun...@gmail.com> wrote:
> 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
>>>

------------------------------------------------------------------------------
Managing the Performance of Cloud-Based Applications
Take advantage of what the Cloud has to offer - Avoid Common Pitfalls.
Read the Whitepaper.
http://pubads.g.doubleclick.net/gampad/clk?id=121051231&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