1*eda6f593SDavid van Moolenbroek /* $Id: resize.c,v 1.1.1.2 2011/08/17 18:40:05 jmmv Exp $ */ 2*eda6f593SDavid van Moolenbroek 3*eda6f593SDavid van Moolenbroek /* 4*eda6f593SDavid van Moolenbroek * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net> 5*eda6f593SDavid van Moolenbroek * 6*eda6f593SDavid van Moolenbroek * Permission to use, copy, modify, and distribute this software for any 7*eda6f593SDavid van Moolenbroek * purpose with or without fee is hereby granted, provided that the above 8*eda6f593SDavid van Moolenbroek * copyright notice and this permission notice appear in all copies. 9*eda6f593SDavid van Moolenbroek * 10*eda6f593SDavid van Moolenbroek * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 11*eda6f593SDavid van Moolenbroek * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 12*eda6f593SDavid van Moolenbroek * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 13*eda6f593SDavid van Moolenbroek * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 14*eda6f593SDavid van Moolenbroek * WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER 15*eda6f593SDavid van Moolenbroek * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING 16*eda6f593SDavid van Moolenbroek * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 17*eda6f593SDavid van Moolenbroek */ 18*eda6f593SDavid van Moolenbroek 19*eda6f593SDavid van Moolenbroek #include <sys/types.h> 20*eda6f593SDavid van Moolenbroek 21*eda6f593SDavid van Moolenbroek #include <string.h> 22*eda6f593SDavid van Moolenbroek 23*eda6f593SDavid van Moolenbroek #include "tmux.h" 24*eda6f593SDavid van Moolenbroek 25*eda6f593SDavid van Moolenbroek /* 26*eda6f593SDavid van Moolenbroek * Recalculate window and session sizes. 27*eda6f593SDavid van Moolenbroek * 28*eda6f593SDavid van Moolenbroek * Every session has the size of the smallest client it is attached to and 29*eda6f593SDavid van Moolenbroek * every window the size of the smallest session it is attached to. 30*eda6f593SDavid van Moolenbroek * 31*eda6f593SDavid van Moolenbroek * So, when a client is resized or a session attached to or detached from a 32*eda6f593SDavid van Moolenbroek * client, the window sizes must be recalculated. For each session, find the 33*eda6f593SDavid van Moolenbroek * smallest client it is attached to, and resize it to that size. Then for 34*eda6f593SDavid van Moolenbroek * every window, find the smallest session it is attached to, resize it to that 35*eda6f593SDavid van Moolenbroek * size and clear and redraw every client with it as the current window. 36*eda6f593SDavid van Moolenbroek * 37*eda6f593SDavid van Moolenbroek * This is quite inefficient - better/additional data structures are needed 38*eda6f593SDavid van Moolenbroek * to make it better. 39*eda6f593SDavid van Moolenbroek * 40*eda6f593SDavid van Moolenbroek * As a side effect, this function updates the SESSION_UNATTACHED flag. This 41*eda6f593SDavid van Moolenbroek * flag is necessary to make sure unattached sessions do not limit the size of 42*eda6f593SDavid van Moolenbroek * windows that are attached both to them and to other (attached) sessions. 43*eda6f593SDavid van Moolenbroek */ 44*eda6f593SDavid van Moolenbroek 45*eda6f593SDavid van Moolenbroek void 46*eda6f593SDavid van Moolenbroek recalculate_sizes(void) 47*eda6f593SDavid van Moolenbroek { 48*eda6f593SDavid van Moolenbroek struct session *s; 49*eda6f593SDavid van Moolenbroek struct client *c; 50*eda6f593SDavid van Moolenbroek struct window *w; 51*eda6f593SDavid van Moolenbroek struct window_pane *wp; 52*eda6f593SDavid van Moolenbroek u_int i, j, ssx, ssy, has, limit; 53*eda6f593SDavid van Moolenbroek int flag; 54*eda6f593SDavid van Moolenbroek 55*eda6f593SDavid van Moolenbroek RB_FOREACH(s, sessions, &sessions) { 56*eda6f593SDavid van Moolenbroek ssx = ssy = UINT_MAX; 57*eda6f593SDavid van Moolenbroek for (j = 0; j < ARRAY_LENGTH(&clients); j++) { 58*eda6f593SDavid van Moolenbroek c = ARRAY_ITEM(&clients, j); 59*eda6f593SDavid van Moolenbroek if (c == NULL || c->flags & CLIENT_SUSPENDED) 60*eda6f593SDavid van Moolenbroek continue; 61*eda6f593SDavid van Moolenbroek if (c->session == s) { 62*eda6f593SDavid van Moolenbroek if (c->tty.sx < ssx) 63*eda6f593SDavid van Moolenbroek ssx = c->tty.sx; 64*eda6f593SDavid van Moolenbroek if (c->tty.sy < ssy) 65*eda6f593SDavid van Moolenbroek ssy = c->tty.sy; 66*eda6f593SDavid van Moolenbroek } 67*eda6f593SDavid van Moolenbroek } 68*eda6f593SDavid van Moolenbroek if (ssx == UINT_MAX || ssy == UINT_MAX) { 69*eda6f593SDavid van Moolenbroek s->flags |= SESSION_UNATTACHED; 70*eda6f593SDavid van Moolenbroek continue; 71*eda6f593SDavid van Moolenbroek } 72*eda6f593SDavid van Moolenbroek s->flags &= ~SESSION_UNATTACHED; 73*eda6f593SDavid van Moolenbroek 74*eda6f593SDavid van Moolenbroek if (options_get_number(&s->options, "status")) { 75*eda6f593SDavid van Moolenbroek if (ssy == 0) 76*eda6f593SDavid van Moolenbroek ssy = 1; 77*eda6f593SDavid van Moolenbroek else 78*eda6f593SDavid van Moolenbroek ssy--; 79*eda6f593SDavid van Moolenbroek } 80*eda6f593SDavid van Moolenbroek if (s->sx == ssx && s->sy == ssy) 81*eda6f593SDavid van Moolenbroek continue; 82*eda6f593SDavid van Moolenbroek 83*eda6f593SDavid van Moolenbroek log_debug( 84*eda6f593SDavid van Moolenbroek "session size %u,%u (was %u,%u)", ssx, ssy, s->sx, s->sy); 85*eda6f593SDavid van Moolenbroek 86*eda6f593SDavid van Moolenbroek s->sx = ssx; 87*eda6f593SDavid van Moolenbroek s->sy = ssy; 88*eda6f593SDavid van Moolenbroek } 89*eda6f593SDavid van Moolenbroek 90*eda6f593SDavid van Moolenbroek for (i = 0; i < ARRAY_LENGTH(&windows); i++) { 91*eda6f593SDavid van Moolenbroek w = ARRAY_ITEM(&windows, i); 92*eda6f593SDavid van Moolenbroek if (w == NULL) 93*eda6f593SDavid van Moolenbroek continue; 94*eda6f593SDavid van Moolenbroek flag = options_get_number(&w->options, "aggressive-resize"); 95*eda6f593SDavid van Moolenbroek 96*eda6f593SDavid van Moolenbroek ssx = ssy = UINT_MAX; 97*eda6f593SDavid van Moolenbroek RB_FOREACH(s, sessions, &sessions) { 98*eda6f593SDavid van Moolenbroek if (s->flags & SESSION_UNATTACHED) 99*eda6f593SDavid van Moolenbroek continue; 100*eda6f593SDavid van Moolenbroek if (flag) 101*eda6f593SDavid van Moolenbroek has = s->curw->window == w; 102*eda6f593SDavid van Moolenbroek else 103*eda6f593SDavid van Moolenbroek has = session_has(s, w) != NULL; 104*eda6f593SDavid van Moolenbroek if (has) { 105*eda6f593SDavid van Moolenbroek if (s->sx < ssx) 106*eda6f593SDavid van Moolenbroek ssx = s->sx; 107*eda6f593SDavid van Moolenbroek if (s->sy < ssy) 108*eda6f593SDavid van Moolenbroek ssy = s->sy; 109*eda6f593SDavid van Moolenbroek } 110*eda6f593SDavid van Moolenbroek } 111*eda6f593SDavid van Moolenbroek if (ssx == UINT_MAX || ssy == UINT_MAX) 112*eda6f593SDavid van Moolenbroek continue; 113*eda6f593SDavid van Moolenbroek 114*eda6f593SDavid van Moolenbroek limit = options_get_number(&w->options, "force-width"); 115*eda6f593SDavid van Moolenbroek if (limit != 0 && ssx > limit) 116*eda6f593SDavid van Moolenbroek ssx = limit; 117*eda6f593SDavid van Moolenbroek limit = options_get_number(&w->options, "force-height"); 118*eda6f593SDavid van Moolenbroek if (limit != 0 && ssy > limit) 119*eda6f593SDavid van Moolenbroek ssy = limit; 120*eda6f593SDavid van Moolenbroek 121*eda6f593SDavid van Moolenbroek if (w->sx == ssx && w->sy == ssy) 122*eda6f593SDavid van Moolenbroek continue; 123*eda6f593SDavid van Moolenbroek 124*eda6f593SDavid van Moolenbroek log_debug( 125*eda6f593SDavid van Moolenbroek "window size %u,%u (was %u,%u)", ssx, ssy, w->sx, w->sy); 126*eda6f593SDavid van Moolenbroek 127*eda6f593SDavid van Moolenbroek layout_resize(w, ssx, ssy); 128*eda6f593SDavid van Moolenbroek window_resize(w, ssx, ssy); 129*eda6f593SDavid van Moolenbroek 130*eda6f593SDavid van Moolenbroek /* 131*eda6f593SDavid van Moolenbroek * If the current pane is now not visible, move to the next 132*eda6f593SDavid van Moolenbroek * that is. 133*eda6f593SDavid van Moolenbroek */ 134*eda6f593SDavid van Moolenbroek wp = w->active; 135*eda6f593SDavid van Moolenbroek while (!window_pane_visible(w->active)) { 136*eda6f593SDavid van Moolenbroek w->active = TAILQ_PREV(w->active, window_panes, entry); 137*eda6f593SDavid van Moolenbroek if (w->active == NULL) 138*eda6f593SDavid van Moolenbroek w->active = TAILQ_LAST(&w->panes, window_panes); 139*eda6f593SDavid van Moolenbroek if (w->active == wp) 140*eda6f593SDavid van Moolenbroek break; 141*eda6f593SDavid van Moolenbroek } 142*eda6f593SDavid van Moolenbroek 143*eda6f593SDavid van Moolenbroek server_redraw_window(w); 144*eda6f593SDavid van Moolenbroek } 145*eda6f593SDavid van Moolenbroek } 146