1 /* $OpenBSD: cmd-resize-pane.c,v 1.21 2015/12/14 00:31:54 nicm Exp $ */ 2 3 /* 4 * Copyright (c) 2009 Nicholas Marriott <nicm@users.sourceforge.net> 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 w = wl->window; 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); 116 else if (args_has(self->args, 'R')) 117 layout_resize_pane(wp, LAYOUT_LEFTRIGHT, adjust); 118 else if (args_has(self->args, 'U')) 119 layout_resize_pane(wp, LAYOUT_TOPBOTTOM, -adjust); 120 else if (args_has(self->args, 'D')) 121 layout_resize_pane(wp, LAYOUT_TOPBOTTOM, adjust); 122 server_redraw_window(wl->window); 123 124 return (CMD_RETURN_NORMAL); 125 } 126 127 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 && wp->yoff + wp->sy >= ly) { 159 layout_resize_pane(wp, LAYOUT_LEFTRIGHT, m->x - m->lx); 160 found = 1; 161 } 162 if (wp->yoff + wp->sy == ly && 163 wp->xoff <= 1 + m->lx && wp->xoff + wp->sx >= m->lx) { 164 layout_resize_pane(wp, LAYOUT_TOPBOTTOM, y - ly); 165 found = 1; 166 } 167 } 168 if (found) 169 server_redraw_window(wl->window); 170 else 171 c->tty.mouse_drag_update = NULL; 172 } 173