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