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