Annotation of embedaddon/tmux/resize.c, revision 1.1

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

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>