version 1.108, 2014/04/17 14:45:49 |
version 1.109, 2014/05/08 06:03:30 |
|
|
struct window_pane_tree all_window_panes; |
struct window_pane_tree all_window_panes; |
u_int next_window_pane_id; |
u_int next_window_pane_id; |
u_int next_window_id; |
u_int next_window_id; |
|
u_int next_active_point; |
|
|
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_timer_callback(int, short, void *); |
void window_pane_read_callback(struct bufferevent *, void *); |
void window_pane_read_callback(struct bufferevent *, void *); |
void window_pane_error_callback(struct bufferevent *, short, void *); |
void window_pane_error_callback(struct bufferevent *, short, void *); |
|
|
|
struct window_pane *window_pane_choose_best(struct window_pane_list *); |
|
|
RB_GENERATE(winlinks, winlink, entry, winlink_cmp); |
RB_GENERATE(winlinks, winlink, entry, winlink_cmp); |
|
|
int |
int |
|
|
w->sy = sy; |
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. |
|
*/ |
|
lc = nextwp->layout_cell->parent; |
|
if (lc != NULL && lc->lastwp != NULL) { |
|
lastwp = lc->lastwp; |
|
if (lastwp != wp && window_pane_visible(lastwp)) |
|
return (lastwp); |
|
} |
|
return (nextwp); |
|
} |
|
|
|
/* Remember previously active pane when changing from wp to nextwp. */ |
|
void |
void |
window_pane_active_lost(struct window_pane *wp, struct window_pane *nextwp) |
|
{ |
|
struct layout_cell *lc, *lc2, *lcparent; |
|
|
|
/* Get the parent cell. */ |
|
lcparent = nextwp->layout_cell->parent; |
|
if (lcparent == NULL) |
|
return; |
|
|
|
/* Save the target pane in its parent. */ |
|
lcparent->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) { |
|
for (lc2 = lcparent; lc2 != NULL; lc2 = lc2->parent) { |
|
if (lc == lc2) |
|
return; |
|
} |
|
lc->lastwp = wp; |
|
} |
|
} |
|
|
|
void |
|
window_set_active_pane(struct window *w, struct window_pane *wp) |
window_set_active_pane(struct window *w, struct window_pane *wp) |
{ |
{ |
if (wp == w->active) |
if (wp == w->active) |
return; |
return; |
w->last = w->active; |
w->last = w->active; |
w->active = wp; |
w->active = wp; |
window_pane_active_lost(w->last, wp); |
|
while (!window_pane_visible(w->active)) { |
while (!window_pane_visible(w->active)) { |
w->active = TAILQ_PREV(w->active, window_panes, entry); |
w->active = TAILQ_PREV(w->active, window_panes, entry); |
if (w->active == NULL) |
if (w->active == NULL) |
|
|
if (w->active == wp) |
if (w->active == wp) |
return; |
return; |
} |
} |
|
w->active->active_point = next_active_point++; |
} |
} |
|
|
struct window_pane * |
struct window_pane * |
|
|
void |
void |
window_pane_destroy(struct window_pane *wp) |
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); |
window_pane_reset_mode(wp); |
|
|
if (event_initialized(&wp->changes_timer)) |
if (event_initialized(&wp->changes_timer)) |
|
|
return (msg); |
return (msg); |
} |
} |
|
|
/* Find the pane directly above another. */ |
/* Get MRU pane from a list. */ |
struct window_pane * |
struct window_pane * |
|
window_pane_choose_best(struct window_pane_list *list) |
|
{ |
|
struct window_pane *next, *best; |
|
u_int i; |
|
|
|
if (ARRAY_LENGTH(list) == 0) |
|
return (NULL); |
|
|
|
best = ARRAY_FIRST(list); |
|
for (i = 1; i < ARRAY_LENGTH(list); i++) { |
|
next = ARRAY_ITEM(list, i); |
|
if (next->active_point > best->active_point) |
|
best = next; |
|
} |
|
return (best); |
|
} |
|
|
|
/* |
|
* Find the pane directly above another. We build a list of those adjacent to |
|
* top edge and then choose the best. |
|
*/ |
|
struct window_pane * |
window_pane_find_up(struct window_pane *wp) |
window_pane_find_up(struct window_pane *wp) |
{ |
{ |
struct window_pane *wp2; |
struct window_pane *next, *best; |
u_int left, top; |
u_int edge, left, right, end; |
|
struct window_pane_list list; |
|
int found; |
|
|
if (wp == NULL || !window_pane_visible(wp)) |
if (wp == NULL || !window_pane_visible(wp)) |
return (NULL); |
return (NULL); |
|
ARRAY_INIT(&list); |
|
|
top = wp->yoff; |
edge = wp->yoff; |
if (top == 0) |
if (edge == 0) |
top = wp->window->sy + 1; |
edge = wp->window->sy + 1; |
|
|
left = wp->xoff; |
left = wp->xoff; |
|
right = wp->xoff + wp->sx; |
|
|
TAILQ_FOREACH(wp2, &wp->window->panes, entry) { |
TAILQ_FOREACH(next, &wp->window->panes, entry) { |
if (!window_pane_visible(wp2)) |
if (next == wp || !window_pane_visible(next)) |
continue; |
continue; |
if (wp2->yoff + wp2->sy + 1 != top) |
if (next->yoff + next->sy + 1 != edge) |
continue; |
continue; |
if (left >= wp2->xoff && left <= wp2->xoff + wp2->sx) |
end = next->xoff + next->sx - 1; |
return (window_pane_active_set(wp, wp2)); |
|
|
found = 0; |
|
if (next->xoff < left && end > right) |
|
found = 1; |
|
else if (next->xoff >= left && next->xoff <= right) |
|
found = 1; |
|
else if (end >= left && end <= right) |
|
found = 1; |
|
if (found) |
|
ARRAY_ADD(&list, next); |
} |
} |
return (NULL); |
|
|
best = window_pane_choose_best(&list); |
|
ARRAY_FREE(&list); |
|
return (best); |
} |
} |
|
|
/* Find the pane directly below another. */ |
/* Find the pane directly below another. */ |
struct window_pane * |
struct window_pane * |
window_pane_find_down(struct window_pane *wp) |
window_pane_find_down(struct window_pane *wp) |
{ |
{ |
struct window_pane *wp2; |
struct window_pane *next, *best; |
u_int left, bottom; |
u_int edge, left, right, end; |
|
struct window_pane_list list; |
|
int found; |
|
|
if (wp == NULL || !window_pane_visible(wp)) |
if (wp == NULL || !window_pane_visible(wp)) |
return (NULL); |
return (NULL); |
|
ARRAY_INIT(&list); |
|
|
bottom = wp->yoff + wp->sy + 1; |
edge = wp->yoff + wp->sy + 1; |
if (bottom >= wp->window->sy) |
if (edge >= wp->window->sy) |
bottom = 0; |
edge = 0; |
|
|
left = wp->xoff; |
left = wp->xoff; |
|
right = wp->xoff + wp->sx; |
|
|
TAILQ_FOREACH(wp2, &wp->window->panes, entry) { |
TAILQ_FOREACH(next, &wp->window->panes, entry) { |
if (!window_pane_visible(wp2)) |
if (next == wp || !window_pane_visible(next)) |
continue; |
continue; |
if (wp2->yoff != bottom) |
if (next->yoff != edge) |
continue; |
continue; |
if (left >= wp2->xoff && left <= wp2->xoff + wp2->sx) |
end = next->xoff + next->sx - 1; |
return (window_pane_active_set(wp, wp2)); |
|
|
found = 0; |
|
if (next->xoff < left && end > right) |
|
found = 1; |
|
else if (next->xoff >= left && next->xoff <= right) |
|
found = 1; |
|
else if (end >= left && end <= right) |
|
found = 1; |
|
if (found) |
|
ARRAY_ADD(&list, next); |
} |
} |
return (NULL); |
|
|
best = window_pane_choose_best(&list); |
|
ARRAY_FREE(&list); |
|
return (best); |
} |
} |
|
|
/* |
/* Find the pane directly to the left of another. */ |
* Find the pane directly to the left of another, adjacent to the left side and |
|
* containing the top edge. |
|
*/ |
|
struct window_pane * |
struct window_pane * |
window_pane_find_left(struct window_pane *wp) |
window_pane_find_left(struct window_pane *wp) |
{ |
{ |
struct window_pane *wp2; |
struct window_pane *next, *best; |
u_int left, top; |
u_int edge, top, bottom, end; |
|
struct window_pane_list list; |
|
int found; |
|
|
if (wp == NULL || !window_pane_visible(wp)) |
if (wp == NULL || !window_pane_visible(wp)) |
return (NULL); |
return (NULL); |
|
ARRAY_INIT(&list); |
|
|
left = wp->xoff; |
edge = wp->xoff; |
if (left == 0) |
if (edge == 0) |
left = wp->window->sx + 1; |
edge = wp->window->sx + 1; |
|
|
top = wp->yoff; |
top = wp->yoff; |
|
bottom = wp->yoff + wp->sy; |
|
|
TAILQ_FOREACH(wp2, &wp->window->panes, entry) { |
TAILQ_FOREACH(next, &wp->window->panes, entry) { |
if (!window_pane_visible(wp2)) |
if (next == wp || !window_pane_visible(next)) |
continue; |
continue; |
if (wp2->xoff + wp2->sx + 1 != left) |
if (next->xoff + next->sx + 1 != edge) |
continue; |
continue; |
if (top >= wp2->yoff && top <= wp2->yoff + wp2->sy) |
end = next->yoff + next->sy - 1; |
return (window_pane_active_set(wp, wp2)); |
|
|
found = 0; |
|
if (next->yoff < top && end > bottom) |
|
found = 1; |
|
else if (next->yoff >= top && next->yoff <= bottom) |
|
found = 1; |
|
else if (end >= top && end <= bottom) |
|
found = 1; |
|
if (found) |
|
ARRAY_ADD(&list, next); |
} |
} |
return (NULL); |
|
|
best = window_pane_choose_best(&list); |
|
ARRAY_FREE(&list); |
|
return (best); |
} |
} |
|
|
/* |
/* Find the pane directly to the right of another. */ |
* Find the pane directly to the right of another, that is adjacent to the |
|
* right edge and including the top edge. |
|
*/ |
|
struct window_pane * |
struct window_pane * |
window_pane_find_right(struct window_pane *wp) |
window_pane_find_right(struct window_pane *wp) |
{ |
{ |
struct window_pane *wp2; |
struct window_pane *next, *best; |
u_int right, top; |
u_int edge, top, bottom, end; |
|
struct window_pane_list list; |
|
int found; |
|
|
if (wp == NULL || !window_pane_visible(wp)) |
if (wp == NULL || !window_pane_visible(wp)) |
return (NULL); |
return (NULL); |
|
ARRAY_INIT(&list); |
|
|
right = wp->xoff + wp->sx + 1; |
edge = wp->xoff + wp->sx + 1; |
if (right >= wp->window->sx) |
if (edge >= wp->window->sx) |
right = 0; |
edge = 0; |
|
|
top = wp->yoff; |
top = wp->yoff; |
|
bottom = wp->yoff + wp->sy; |
|
|
TAILQ_FOREACH(wp2, &wp->window->panes, entry) { |
TAILQ_FOREACH(next, &wp->window->panes, entry) { |
if (!window_pane_visible(wp2)) |
if (next == wp || !window_pane_visible(next)) |
continue; |
continue; |
if (wp2->xoff != right) |
if (next->xoff != edge) |
continue; |
continue; |
if (top >= wp2->yoff && top <= wp2->yoff + wp2->sy) |
end = next->yoff + next->sy - 1; |
return (window_pane_active_set(wp, wp2)); |
|
|
found = 0; |
|
if (next->yoff < top && end > bottom) |
|
found = 1; |
|
else if (next->yoff >= top && next->yoff <= bottom) |
|
found = 1; |
|
else if (end >= top && end <= bottom) |
|
found = 1; |
|
if (found) |
|
ARRAY_ADD(&list, next); |
} |
} |
return (NULL); |
|
|
best = window_pane_choose_best(&list); |
|
ARRAY_FREE(&list); |
|
return (best); |
} |
} |
|
|
/* Clear alert flags for a winlink */ |
/* Clear alert flags for a winlink */ |