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