version 1.27, 2016/04/29 15:00:48 |
version 1.28, 2016/08/03 09:07:02 |
|
|
* cell a pointer to its parent cell. |
* cell a pointer to its parent cell. |
*/ |
*/ |
|
|
static int layout_resize_pane_grow(struct layout_cell *, enum layout_type, |
static u_int layout_resize_check(struct window *, struct layout_cell *, |
int); |
enum layout_type); |
static int layout_resize_pane_shrink(struct layout_cell *, |
static int layout_resize_pane_grow(struct window *, struct layout_cell *, |
enum layout_type, int); |
enum layout_type, int); |
|
static int layout_resize_pane_shrink(struct window *, struct layout_cell *, |
|
enum layout_type, int); |
static int layout_need_status(struct layout_cell *, int); |
static int layout_need_status(struct layout_cell *, int); |
|
|
struct layout_cell * |
struct layout_cell * |
|
|
} |
} |
|
|
/* Calculate how much size is available to be removed from a cell. */ |
/* Calculate how much size is available to be removed from a cell. */ |
u_int |
static u_int |
layout_resize_check(struct layout_cell *lc, enum layout_type type) |
layout_resize_check(struct window *w, struct layout_cell *lc, |
|
enum layout_type type) |
{ |
{ |
struct layout_cell *lcchild; |
struct layout_cell *lcchild; |
u_int available, minimum; |
u_int available, minimum; |
|
|
if (lc->type == LAYOUT_WINDOWPANE) { |
if (lc->type == LAYOUT_WINDOWPANE) { |
/* Space available in this cell only. */ |
/* Space available in this cell only. */ |
|
minimum = PANE_MINIMUM; |
if (type == LAYOUT_LEFTRIGHT) |
if (type == LAYOUT_LEFTRIGHT) |
available = lc->sx; |
available = lc->sx; |
else |
else { |
available = lc->sy; |
available = lc->sy; |
|
minimum += layout_need_status(lc, |
if (available > PANE_MINIMUM) |
options_get_number(w->options, |
available -= PANE_MINIMUM; |
"pane-border-status") == 1); |
|
} |
|
if (available > minimum) |
|
available -= minimum; |
else |
else |
available = 0; |
available = 0; |
} else if (lc->type == type) { |
} else if (lc->type == type) { |
/* Same type: total of available space in all child cells. */ |
/* Same type: total of available space in all child cells. */ |
available = 0; |
available = 0; |
TAILQ_FOREACH(lcchild, &lc->cells, entry) |
TAILQ_FOREACH(lcchild, &lc->cells, entry) |
available += layout_resize_check(lcchild, type); |
available += layout_resize_check(w, lcchild, type); |
} else { |
} else { |
/* Different type: minimum of available space in child cells. */ |
/* Different type: minimum of available space in child cells. */ |
minimum = UINT_MAX; |
minimum = UINT_MAX; |
TAILQ_FOREACH(lcchild, &lc->cells, entry) { |
TAILQ_FOREACH(lcchild, &lc->cells, entry) { |
available = layout_resize_check(lcchild, type); |
available = layout_resize_check(w, lcchild, type); |
if (available < minimum) |
if (available < minimum) |
minimum = available; |
minimum = available; |
} |
} |
|
|
* expects the change to have already been bounded to the space available. |
* expects the change to have already been bounded to the space available. |
*/ |
*/ |
void |
void |
layout_resize_adjust(struct layout_cell *lc, enum layout_type type, int change) |
layout_resize_adjust(struct window *w, struct layout_cell *lc, |
|
enum layout_type type, int change) |
{ |
{ |
struct layout_cell *lcchild; |
struct layout_cell *lcchild; |
|
|
|
|
/* Child cell runs in a different direction. */ |
/* Child cell runs in a different direction. */ |
if (lc->type != type) { |
if (lc->type != type) { |
TAILQ_FOREACH(lcchild, &lc->cells, entry) |
TAILQ_FOREACH(lcchild, &lc->cells, entry) |
layout_resize_adjust(lcchild, type, change); |
layout_resize_adjust(w, lcchild, type, change); |
return; |
return; |
} |
} |
|
|
|
|
if (change == 0) |
if (change == 0) |
break; |
break; |
if (change > 0) { |
if (change > 0) { |
layout_resize_adjust(lcchild, type, 1); |
layout_resize_adjust(w, lcchild, type, 1); |
change--; |
change--; |
continue; |
continue; |
} |
} |
if (layout_resize_check(lcchild, type) > 0) { |
if (layout_resize_check(w, lcchild, type) > 0) { |
layout_resize_adjust(lcchild, type, -1); |
layout_resize_adjust(w, lcchild, type, -1); |
change++; |
change++; |
} |
} |
} |
} |
|
|
|
|
/* Destroy a cell and redistribute the space. */ |
/* Destroy a cell and redistribute the space. */ |
void |
void |
layout_destroy_cell(struct layout_cell *lc, struct layout_cell **lcroot) |
layout_destroy_cell(struct window *w, struct layout_cell *lc, |
|
struct layout_cell **lcroot) |
{ |
{ |
struct layout_cell *lcother, *lcparent; |
struct layout_cell *lcother, *lcparent; |
|
|
|
|
else |
else |
lcother = TAILQ_PREV(lc, layout_cells, entry); |
lcother = TAILQ_PREV(lc, layout_cells, entry); |
if (lcparent->type == LAYOUT_LEFTRIGHT) |
if (lcparent->type == LAYOUT_LEFTRIGHT) |
layout_resize_adjust(lcother, lcparent->type, lc->sx + 1); |
layout_resize_adjust(w, lcother, lcparent->type, lc->sx + 1); |
else |
else |
layout_resize_adjust(lcother, lcparent->type, lc->sy + 1); |
layout_resize_adjust(w, lcother, lcparent->type, lc->sy + 1); |
|
|
/* Remove this from the parent's list. */ |
/* Remove this from the parent's list. */ |
TAILQ_REMOVE(&lcparent->cells, lc, entry); |
TAILQ_REMOVE(&lcparent->cells, lc, entry); |
|
|
* window size. |
* window size. |
*/ |
*/ |
xchange = sx - w->sx; |
xchange = sx - w->sx; |
xlimit = layout_resize_check(lc, LAYOUT_LEFTRIGHT); |
xlimit = layout_resize_check(w, lc, LAYOUT_LEFTRIGHT); |
if (xchange < 0 && xchange < -xlimit) |
if (xchange < 0 && xchange < -xlimit) |
xchange = -xlimit; |
xchange = -xlimit; |
if (xlimit == 0) { |
if (xlimit == 0) { |
|
|
xchange = sx - lc->sx; |
xchange = sx - lc->sx; |
} |
} |
if (xchange != 0) |
if (xchange != 0) |
layout_resize_adjust(lc, LAYOUT_LEFTRIGHT, xchange); |
layout_resize_adjust(w, lc, LAYOUT_LEFTRIGHT, xchange); |
|
|
/* Adjust vertically in a similar fashion. */ |
/* Adjust vertically in a similar fashion. */ |
ychange = sy - w->sy; |
ychange = sy - w->sy; |
ylimit = layout_resize_check(lc, LAYOUT_TOPBOTTOM); |
ylimit = layout_resize_check(w, lc, LAYOUT_TOPBOTTOM); |
if (ychange < 0 && ychange < -ylimit) |
if (ychange < 0 && ychange < -ylimit) |
ychange = -ylimit; |
ychange = -ylimit; |
if (ylimit == 0) { |
if (ylimit == 0) { |
|
|
ychange = sy - lc->sy; |
ychange = sy - lc->sy; |
} |
} |
if (ychange != 0) |
if (ychange != 0) |
layout_resize_adjust(lc, LAYOUT_TOPBOTTOM, ychange); |
layout_resize_adjust(w, lc, LAYOUT_TOPBOTTOM, ychange); |
|
|
/* Fix cell offsets. */ |
/* Fix cell offsets. */ |
layout_fix_offsets(lc); |
layout_fix_offsets(lc); |
|
|
void |
void |
layout_resize_pane(struct window_pane *wp, enum layout_type type, int change) |
layout_resize_pane(struct window_pane *wp, enum layout_type type, int change) |
{ |
{ |
struct layout_cell *lc, *lcparent; |
struct window *w = wp->window; |
int needed, size; |
struct layout_cell *lc, *lcparent; |
|
int needed, size; |
|
|
lc = wp->layout_cell; |
lc = wp->layout_cell; |
|
|
|
|
needed = change; |
needed = change; |
while (needed != 0) { |
while (needed != 0) { |
if (change > 0) { |
if (change > 0) { |
size = layout_resize_pane_grow(lc, type, needed); |
size = layout_resize_pane_grow(w, lc, type, needed); |
needed -= size; |
needed -= size; |
} else { |
} else { |
size = layout_resize_pane_shrink(lc, type, needed); |
size = layout_resize_pane_shrink(w, lc, type, needed); |
needed += size; |
needed += size; |
} |
} |
|
|
|
|
|
|
/* Helper function to grow pane. */ |
/* Helper function to grow pane. */ |
static int |
static int |
layout_resize_pane_grow(struct layout_cell *lc, enum layout_type type, |
layout_resize_pane_grow(struct window *w, struct layout_cell *lc, |
int needed) |
enum layout_type type, int needed) |
{ |
{ |
struct layout_cell *lcadd, *lcremove; |
struct layout_cell *lcadd, *lcremove; |
u_int size; |
u_int size; |
|
|
/* Look towards the tail for a suitable cell for reduction. */ |
/* Look towards the tail for a suitable cell for reduction. */ |
lcremove = TAILQ_NEXT(lc, entry); |
lcremove = TAILQ_NEXT(lc, entry); |
while (lcremove != NULL) { |
while (lcremove != NULL) { |
size = layout_resize_check(lcremove, type); |
size = layout_resize_check(w, lcremove, type); |
if (size > 0) |
if (size > 0) |
break; |
break; |
lcremove = TAILQ_NEXT(lcremove, entry); |
lcremove = TAILQ_NEXT(lcremove, entry); |
|
|
if (lcremove == NULL) { |
if (lcremove == NULL) { |
lcremove = TAILQ_PREV(lc, layout_cells, entry); |
lcremove = TAILQ_PREV(lc, layout_cells, entry); |
while (lcremove != NULL) { |
while (lcremove != NULL) { |
size = layout_resize_check(lcremove, type); |
size = layout_resize_check(w, lcremove, type); |
if (size > 0) |
if (size > 0) |
break; |
break; |
lcremove = TAILQ_PREV(lcremove, layout_cells, entry); |
lcremove = TAILQ_PREV(lcremove, layout_cells, entry); |
|
|
/* Change the cells. */ |
/* Change the cells. */ |
if (size > (u_int) needed) |
if (size > (u_int) needed) |
size = needed; |
size = needed; |
layout_resize_adjust(lcadd, type, size); |
layout_resize_adjust(w, lcadd, type, size); |
layout_resize_adjust(lcremove, type, -size); |
layout_resize_adjust(w, lcremove, type, -size); |
return (size); |
return (size); |
} |
} |
|
|
/* Helper function to shrink pane. */ |
/* Helper function to shrink pane. */ |
static int |
static int |
layout_resize_pane_shrink(struct layout_cell *lc, enum layout_type type, |
layout_resize_pane_shrink(struct window *w, struct layout_cell *lc, |
int needed) |
enum layout_type type, int needed) |
{ |
{ |
struct layout_cell *lcadd, *lcremove; |
struct layout_cell *lcadd, *lcremove; |
u_int size; |
u_int size; |
|
|
/* Shrinking. Find cell to remove from by walking towards head. */ |
/* Shrinking. Find cell to remove from by walking towards head. */ |
lcremove = lc; |
lcremove = lc; |
do { |
do { |
size = layout_resize_check(lcremove, type); |
size = layout_resize_check(w, lcremove, type); |
if (size != 0) |
if (size != 0) |
break; |
break; |
lcremove = TAILQ_PREV(lcremove, layout_cells, entry); |
lcremove = TAILQ_PREV(lcremove, layout_cells, entry); |
|
|
/* Change the cells. */ |
/* Change the cells. */ |
if (size > (u_int) -needed) |
if (size > (u_int) -needed) |
size = -needed; |
size = -needed; |
layout_resize_adjust(lcadd, type, size); |
layout_resize_adjust(w, lcadd, type, size); |
layout_resize_adjust(lcremove, type, -size); |
layout_resize_adjust(w, lcremove, type, -size); |
return (size); |
return (size); |
} |
} |
|
|
|
|
void |
void |
layout_close_pane(struct window_pane *wp) |
layout_close_pane(struct window_pane *wp) |
{ |
{ |
|
struct window *w = wp->window; |
|
|
/* Remove the cell. */ |
/* Remove the cell. */ |
layout_destroy_cell(wp->layout_cell, &wp->window->layout_root); |
layout_destroy_cell(w, wp->layout_cell, &w->layout_root); |
|
|
/* Fix pane offsets and sizes. */ |
/* Fix pane offsets and sizes. */ |
if (wp->window->layout_root != NULL) { |
if (w->layout_root != NULL) { |
layout_fix_offsets(wp->window->layout_root); |
layout_fix_offsets(w->layout_root); |
layout_fix_panes(wp->window, wp->window->sx, wp->window->sy); |
layout_fix_panes(w, w->sx, w->sy); |
} |
} |
notify_window_layout_changed(wp->window); |
notify_window_layout_changed(w); |
} |
} |