1 /* $OpenBSD: cmd-resize-pane.c,v 1.31 2017/05/11 07:24:42 nicm Exp $ */ 2 3 /* 4 * Copyright (c) 2009 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 <stdlib.h> 22 23 #include "tmux.h" 24 25 /* 26 * Increase or decrease pane size. 27 */ 28 29 static enum cmd_retval cmd_resize_pane_exec(struct cmd *, struct cmdq_item *); 30 31 static void cmd_resize_pane_mouse_update(struct client *, 32 struct mouse_event *); 33 34 const struct cmd_entry cmd_resize_pane_entry = { 35 .name = "resize-pane", 36 .alias = "resizep", 37 38 .args = { "DLMRt:Ux:y:Z", 0, 1 }, 39 .usage = "[-DLMRUZ] [-x width] [-y height] " CMD_TARGET_PANE_USAGE " " 40 "[adjustment]", 41 42 .target = { 't', CMD_FIND_PANE, 0 }, 43 44 .flags = CMD_AFTERHOOK, 45 .exec = cmd_resize_pane_exec 46 }; 47 48 static enum cmd_retval 49 cmd_resize_pane_exec(struct cmd *self, struct cmdq_item *item) 50 { 51 struct args *args = self->args; 52 struct cmdq_shared *shared = item->shared; 53 struct window_pane *wp = item->target.wp; 54 struct winlink *wl = item->target.wl; 55 struct window *w = wl->window; 56 struct client *c = item->client; 57 struct session *s = item->target.s; 58 const char *errstr; 59 char *cause; 60 u_int adjust; 61 int x, y; 62 63 if (args_has(args, 'M')) { 64 if (cmd_mouse_window(&shared->mouse, &s) == NULL) 65 return (CMD_RETURN_NORMAL); 66 if (c == NULL || c->session != s) 67 return (CMD_RETURN_NORMAL); 68 c->tty.mouse_drag_update = cmd_resize_pane_mouse_update; 69 cmd_resize_pane_mouse_update(c, &shared->mouse); 70 return (CMD_RETURN_NORMAL); 71 } 72 73 if (args_has(args, 'Z')) { 74 if (w->flags & WINDOW_ZOOMED) 75 window_unzoom(w); 76 else 77 window_zoom(wp); 78 server_redraw_window(w); 79 server_status_window(w); 80 return (CMD_RETURN_NORMAL); 81 } 82 server_unzoom_window(w); 83 84 if (args->argc == 0) 85 adjust = 1; 86 else { 87 adjust = strtonum(args->argv[0], 1, INT_MAX, &errstr); 88 if (errstr != NULL) { 89 cmdq_error(item, "adjustment %s", errstr); 90 return (CMD_RETURN_ERROR); 91 } 92 } 93 94 if (args_has(self->args, 'x')) { 95 x = args_strtonum(self->args, 'x', PANE_MINIMUM, INT_MAX, 96 &cause); 97 if (cause != NULL) { 98 cmdq_error(item, "width %s", cause); 99 free(cause); 100 return (CMD_RETURN_ERROR); 101 } 102 layout_resize_pane_to(wp, LAYOUT_LEFTRIGHT, x); 103 } 104 if (args_has(self->args, 'y')) { 105 y = args_strtonum(self->args, 'y', PANE_MINIMUM, INT_MAX, 106 &cause); 107 if (cause != NULL) { 108 cmdq_error(item, "height %s", cause); 109 free(cause); 110 return (CMD_RETURN_ERROR); 111 } 112 layout_resize_pane_to(wp, LAYOUT_TOPBOTTOM, y); 113 } 114 115 if (args_has(self->args, 'L')) 116 layout_resize_pane(wp, LAYOUT_LEFTRIGHT, -adjust, 1); 117 else if (args_has(self->args, 'R')) 118 layout_resize_pane(wp, LAYOUT_LEFTRIGHT, adjust, 1); 119 else if (args_has(self->args, 'U')) 120 layout_resize_pane(wp, LAYOUT_TOPBOTTOM, -adjust, 1); 121 else if (args_has(self->args, 'D')) 122 layout_resize_pane(wp, LAYOUT_TOPBOTTOM, adjust, 1); 123 server_redraw_window(wl->window); 124 125 return (CMD_RETURN_NORMAL); 126 } 127 128 static void 129 cmd_resize_pane_mouse_update(struct client *c, struct mouse_event *m) 130 { 131 struct winlink *wl; 132 struct window_pane *loop, *wp_x, *wp_y; 133 u_int y, ly, x, lx, sx, sy, ex, ey; 134 135 wl = cmd_mouse_window(m, NULL); 136 if (wl == NULL) { 137 c->tty.mouse_drag_update = NULL; 138 return; 139 } 140 141 y = m->y; x = m->x; 142 if (m->statusat == 0 && y > 0) 143 y--; 144 else if (m->statusat > 0 && y >= (u_int)m->statusat) 145 y = m->statusat - 1; 146 ly = m->ly; lx = m->lx; 147 if (m->statusat == 0 && ly > 0) 148 ly--; 149 else if (m->statusat > 0 && ly >= (u_int)m->statusat) 150 ly = m->statusat - 1; 151 152 wp_x = wp_y = NULL; 153 TAILQ_FOREACH(loop, &wl->window->panes, entry) { 154 if (!window_pane_visible(loop)) 155 continue; 156 157 sx = loop->xoff; 158 if (sx != 0) 159 sx--; 160 ex = loop->xoff + loop->sx; 161 162 sy = loop->yoff; 163 if (sy != 0) 164 sy--; 165 ey = loop->yoff + loop->sy; 166 167 if ((lx == sx || lx == ex) && 168 (ly >= sy && ly <= ey) && 169 (wp_x == NULL || loop->sy > wp_x->sy)) 170 wp_x = loop; 171 if ((ly == sy || ly == ey) && 172 (lx >= sx && lx <= ex) && 173 (wp_y == NULL || loop->sx > wp_y->sx)) 174 wp_y = loop; 175 } 176 if (wp_x == NULL && wp_y == NULL) { 177 c->tty.mouse_drag_update = NULL; 178 return; 179 } 180 if (wp_x != NULL) 181 layout_resize_pane(wp_x, LAYOUT_LEFTRIGHT, x - lx, 0); 182 if (wp_y != NULL) 183 layout_resize_pane(wp_y, LAYOUT_TOPBOTTOM, y - ly, 0); 184 server_redraw_window(wl->window); 185 } 186