1 /* $OpenBSD: cmd-resize-pane.c,v 1.25 2016/10/10 21:51:39 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 cmd_q *); 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 .tflag = CMD_PANE, 43 44 .flags = 0, 45 .exec = cmd_resize_pane_exec 46 }; 47 48 static enum cmd_retval 49 cmd_resize_pane_exec(struct cmd *self, struct cmd_q *cmdq) 50 { 51 struct args *args = self->args; 52 struct window_pane *wp = cmdq->state.tflag.wp; 53 struct winlink *wl = cmdq->state.tflag.wl; 54 struct window *w = wl->window; 55 struct client *c = cmdq->client; 56 struct session *s = cmdq->state.tflag.s; 57 const char *errstr; 58 char *cause; 59 u_int adjust; 60 int x, y; 61 62 if (args_has(args, 'M')) { 63 if (cmd_mouse_window(&cmdq->item->mouse, &s) == NULL) 64 return (CMD_RETURN_NORMAL); 65 if (c == NULL || c->session != s) 66 return (CMD_RETURN_NORMAL); 67 c->tty.mouse_drag_update = cmd_resize_pane_mouse_update; 68 cmd_resize_pane_mouse_update(c, &cmdq->item->mouse); 69 return (CMD_RETURN_NORMAL); 70 } 71 72 if (args_has(args, 'Z')) { 73 if (w->flags & WINDOW_ZOOMED) 74 window_unzoom(w); 75 else 76 window_zoom(wp); 77 server_redraw_window(w); 78 server_status_window(w); 79 return (CMD_RETURN_NORMAL); 80 } 81 server_unzoom_window(w); 82 83 if (args->argc == 0) 84 adjust = 1; 85 else { 86 adjust = strtonum(args->argv[0], 1, INT_MAX, &errstr); 87 if (errstr != NULL) { 88 cmdq_error(cmdq, "adjustment %s", errstr); 89 return (CMD_RETURN_ERROR); 90 } 91 } 92 93 if (args_has(self->args, 'x')) { 94 x = args_strtonum(self->args, 'x', PANE_MINIMUM, INT_MAX, 95 &cause); 96 if (cause != NULL) { 97 cmdq_error(cmdq, "width %s", cause); 98 free(cause); 99 return (CMD_RETURN_ERROR); 100 } 101 layout_resize_pane_to(wp, LAYOUT_LEFTRIGHT, x); 102 } 103 if (args_has(self->args, 'y')) { 104 y = args_strtonum(self->args, 'y', PANE_MINIMUM, INT_MAX, 105 &cause); 106 if (cause != NULL) { 107 cmdq_error(cmdq, "height %s", cause); 108 free(cause); 109 return (CMD_RETURN_ERROR); 110 } 111 layout_resize_pane_to(wp, LAYOUT_TOPBOTTOM, y); 112 } 113 114 if (args_has(self->args, 'L')) 115 layout_resize_pane(wp, LAYOUT_LEFTRIGHT, -adjust, 1); 116 else if (args_has(self->args, 'R')) 117 layout_resize_pane(wp, LAYOUT_LEFTRIGHT, adjust, 1); 118 else if (args_has(self->args, 'U')) 119 layout_resize_pane(wp, LAYOUT_TOPBOTTOM, -adjust, 1); 120 else if (args_has(self->args, 'D')) 121 layout_resize_pane(wp, LAYOUT_TOPBOTTOM, adjust, 1); 122 server_redraw_window(wl->window); 123 124 return (CMD_RETURN_NORMAL); 125 } 126 127 static void 128 cmd_resize_pane_mouse_update(struct client *c, struct mouse_event *m) 129 { 130 struct winlink *wl; 131 struct window_pane *wp; 132 int found; 133 u_int y, ly; 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; 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; 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 found = 0; 153 TAILQ_FOREACH(wp, &wl->window->panes, entry) { 154 if (!window_pane_visible(wp)) 155 continue; 156 157 if (wp->xoff + wp->sx == m->lx && 158 wp->yoff <= 1 + ly && 159 wp->yoff + wp->sy >= ly) { 160 layout_resize_pane(wp, LAYOUT_LEFTRIGHT, m->x - m->lx, 0); 161 found = 1; 162 } 163 if (wp->yoff + wp->sy == ly && 164 wp->xoff <= 1 + m->lx && 165 wp->xoff + wp->sx >= m->lx) { 166 layout_resize_pane(wp, LAYOUT_TOPBOTTOM, y - ly, 0); 167 found = 1; 168 } 169 } 170 if (found) 171 server_redraw_window(wl->window); 172 else 173 c->tty.mouse_drag_update = NULL; 174 } 175