1 /* $OpenBSD: cmd-swap-pane.c,v 1.33 2019/04/17 14:37:48 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 * Swap two panes. 27 */ 28 29 static enum cmd_retval cmd_swap_pane_exec(struct cmd *, struct cmdq_item *); 30 31 const struct cmd_entry cmd_swap_pane_entry = { 32 .name = "swap-pane", 33 .alias = "swapp", 34 35 .args = { "dDs:t:U", 0, 0 }, 36 .usage = "[-dDU] " CMD_SRCDST_PANE_USAGE, 37 38 .source = { 's', CMD_FIND_PANE, CMD_FIND_DEFAULT_MARKED }, 39 .target = { 't', CMD_FIND_PANE, 0 }, 40 41 .flags = 0, 42 .exec = cmd_swap_pane_exec 43 }; 44 45 static enum cmd_retval 46 cmd_swap_pane_exec(struct cmd *self, struct cmdq_item *item) 47 { 48 struct window *src_w, *dst_w; 49 struct window_pane *tmp_wp, *src_wp, *dst_wp; 50 struct layout_cell *src_lc, *dst_lc; 51 u_int sx, sy, xoff, yoff; 52 53 dst_w = item->target.wl->window; 54 dst_wp = item->target.wp; 55 src_w = item->source.wl->window; 56 src_wp = item->source.wp; 57 server_unzoom_window(dst_w); 58 59 if (args_has(self->args, 'D')) { 60 src_w = dst_w; 61 src_wp = TAILQ_NEXT(dst_wp, entry); 62 if (src_wp == NULL) 63 src_wp = TAILQ_FIRST(&dst_w->panes); 64 } else if (args_has(self->args, 'U')) { 65 src_w = dst_w; 66 src_wp = TAILQ_PREV(dst_wp, window_panes, entry); 67 if (src_wp == NULL) 68 src_wp = TAILQ_LAST(&dst_w->panes, window_panes); 69 } 70 server_unzoom_window(src_w); 71 72 if (src_wp == dst_wp) 73 return (CMD_RETURN_NORMAL); 74 75 tmp_wp = TAILQ_PREV(dst_wp, window_panes, entry); 76 TAILQ_REMOVE(&dst_w->panes, dst_wp, entry); 77 TAILQ_REPLACE(&src_w->panes, src_wp, dst_wp, entry); 78 if (tmp_wp == src_wp) 79 tmp_wp = dst_wp; 80 if (tmp_wp == NULL) 81 TAILQ_INSERT_HEAD(&dst_w->panes, src_wp, entry); 82 else 83 TAILQ_INSERT_AFTER(&dst_w->panes, tmp_wp, src_wp, entry); 84 85 src_lc = src_wp->layout_cell; 86 dst_lc = dst_wp->layout_cell; 87 src_lc->wp = dst_wp; 88 dst_wp->layout_cell = src_lc; 89 dst_lc->wp = src_wp; 90 src_wp->layout_cell = dst_lc; 91 92 src_wp->window = dst_w; 93 dst_wp->window = src_w; 94 95 sx = src_wp->sx; sy = src_wp->sy; 96 xoff = src_wp->xoff; yoff = src_wp->yoff; 97 src_wp->xoff = dst_wp->xoff; src_wp->yoff = dst_wp->yoff; 98 window_pane_resize(src_wp, dst_wp->sx, dst_wp->sy); 99 dst_wp->xoff = xoff; dst_wp->yoff = yoff; 100 window_pane_resize(dst_wp, sx, sy); 101 102 if (!args_has(self->args, 'd')) { 103 if (src_w != dst_w) { 104 window_set_active_pane(src_w, dst_wp, 1); 105 window_set_active_pane(dst_w, src_wp, 1); 106 } else { 107 tmp_wp = dst_wp; 108 window_set_active_pane(src_w, tmp_wp, 1); 109 } 110 } else { 111 if (src_w->active == src_wp) 112 window_set_active_pane(src_w, dst_wp, 1); 113 if (dst_w->active == dst_wp) 114 window_set_active_pane(dst_w, src_wp, 1); 115 } 116 if (src_w != dst_w) { 117 if (src_w->last == src_wp) 118 src_w->last = NULL; 119 if (dst_w->last == dst_wp) 120 dst_w->last = NULL; 121 } 122 server_redraw_window(src_w); 123 server_redraw_window(dst_w); 124 125 return (CMD_RETURN_NORMAL); 126 } 127