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