diff --git a/cmd-break-pane.c b/cmd-break-pane.c index f13f251ea..6fed599cf 100644 --- a/cmd-break-pane.c +++ b/cmd-break-pane.c @@ -51,10 +51,9 @@ cmd_break_pane_float(struct cmdq_item *item, struct args *args, struct window *w, struct window_pane *wp) { struct layout_cell *lc = wp->layout_cell; - u_int sx = lc->saved_sx, sy = lc->saved_sy; - int ox = lc->saved_xoff, oy = lc->saved_yoff; char *cause = NULL; enum pane_lines lines = window_get_pane_lines(w); + struct layout_geometry *fg = &lc->fg; if (window_pane_is_floating(wp)) { cmdq_error(item, "pane is already floating"); @@ -65,14 +64,13 @@ cmd_break_pane_float(struct cmdq_item *item, struct args *args, return (CMD_RETURN_ERROR); } - if (layout_floating_args_parse(item, args, lines, w, &sx, &sy, &ox, &oy, - &cause) != 0) { + if (layout_floating_args_parse(item, args, lines, w, fg, &cause) != 0) { cmdq_error(item, "failed to float pane: %s", cause); free(cause); return (CMD_RETURN_ERROR); } layout_remove_tile(w, lc); - layout_set_size(lc, sx, sy, ox, oy); + layout_set_size(lc, fg->sx, fg->sy, fg->xoff, fg->yoff); lc->flags |= LAYOUT_CELL_FLOATING; TAILQ_REMOVE(&w->z_index, wp, zentry); diff --git a/cmd-display-menu.c b/cmd-display-menu.c index e1766fc2e..22d4bd503 100644 --- a/cmd-display-menu.c +++ b/cmd-display-menu.c @@ -126,6 +126,10 @@ cmd_display_menu_get_pos(struct client *tc, struct cmdq_item *item, format_add(ft, "popup_mouse_y", "%u", event->m.y); } + /* Position of the previous menu, for -x/-y L. */ + format_add(ft, "popup_last_x", "%u", tc->menu_last_px); + format_add(ft, "popup_last_y", "%u", tc->menu_last_py + h); + /* * If there are any status lines, add this window position and the * status line position. @@ -238,6 +242,8 @@ cmd_display_menu_get_pos(struct client *tc, struct cmdq_item *item, xp = "#{popup_pane_left}"; else if (strcmp(xp, "M") == 0) xp = "#{popup_mouse_centre_x}"; + else if (strcmp(xp, "L") == 0) + xp = "#{popup_last_x}"; else if (strcmp(xp, "W") == 0) xp = "#{popup_window_status_line_x}"; p = format_expand(ft, xp); @@ -258,6 +264,8 @@ cmd_display_menu_get_pos(struct client *tc, struct cmdq_item *item, yp = "#{popup_pane_bottom}"; else if (strcmp(yp, "M") == 0) yp = "#{popup_mouse_top}"; + else if (strcmp(yp, "L") == 0) + yp = "#{popup_last_y}"; else if (strcmp(yp, "S") == 0) yp = "#{popup_status_line_y}"; else if (strcmp(yp, "W") == 0) diff --git a/cmd-join-pane.c b/cmd-join-pane.c index 060e4cdfe..2e8bdf029 100644 --- a/cmd-join-pane.c +++ b/cmd-join-pane.c @@ -71,8 +71,9 @@ cmd_join_pane_place(struct cmdq_item *item, struct winlink *wl, struct window *w = wl->window; struct layout_cell *lc = wp->layout_cell; struct window_pane *owp; - int wx = w->sx, wy = w->sy, px = lc->sx; - int py = lc->sy, xoff = lc->xoff, yoff = lc->yoff; + int wx = w->sx, wy = w->sy; + int px = lc->g.sx, py = lc->g.sy; + int xoff = lc->g.xoff, yoff = lc->g.yoff; int border = 1; if (window_pane_get_pane_lines(wp) == PANE_LINES_NONE) @@ -180,9 +181,9 @@ cmd_join_pane_place(struct cmdq_item *item, struct winlink *wl, return (CMD_RETURN_ERROR); } - if (xoff != lc->xoff || yoff != lc->yoff) { - lc->xoff = xoff; - lc->yoff = yoff; + if (xoff != lc->g.xoff || yoff != lc->g.yoff) { + lc->g.xoff = xoff; + lc->g.yoff = yoff; layout_fix_panes(w, NULL); } events_fire_window("window-layout-changed", w); @@ -200,7 +201,7 @@ cmd_join_pane_move(struct cmdq_item *item, struct args *args, const char *errstr, *argval; const char flags[] = { 'U', 'D', 'L', 'R' }; char *cause = NULL, flag; - int xoff = lc->xoff, yoff = lc->yoff, adjust; + int xoff = lc->g.xoff, yoff = lc->g.yoff, adjust; u_int i; enum pane_lines lines = window_pane_get_pane_lines(wp); @@ -251,9 +252,9 @@ cmd_join_pane_move(struct cmdq_item *item, struct args *args, xoff += adjust; } - if (xoff != lc->xoff || yoff != lc->yoff) { - lc->xoff = xoff; - lc->yoff = yoff; + if (xoff != lc->g.xoff || yoff != lc->g.yoff) { + lc->g.xoff = xoff; + lc->g.yoff = yoff; layout_fix_panes(w, NULL); events_fire_window("window-layout-changed", w); server_redraw_window(w); @@ -319,8 +320,8 @@ cmd_join_pane_mouse_move(struct client *c, struct mouse_event *m) ly = m->statusat - 1; if (x != lx || y != ly) { - lc->xoff += x - lx; - lc->yoff += y - ly; + lc->g.xoff += x - lx; + lc->g.yoff += y - ly; layout_fix_panes(w, NULL); server_redraw_window(w); server_redraw_window_borders(w); @@ -378,10 +379,11 @@ cmd_join_pane_tile(struct cmdq_item *item, struct args *args, struct window *w, return (CMD_RETURN_ERROR); } - lc->saved_sx = lc->sx; - lc->saved_sy = lc->sy; - lc->saved_xoff = lc->xoff; - lc->saved_yoff = lc->yoff; + lc->fg.sx = lc->g.sx; + lc->fg.sy = lc->g.sy; + lc->fg.xoff = lc->g.xoff; + lc->fg.yoff = lc->g.yoff; + if (layout_insert_tile(w, lc) != 0) { cmdq_error(item, "no space for a new pane"); return (CMD_RETURN_ERROR); diff --git a/cmd-resize-pane.c b/cmd-resize-pane.c index 2e605018a..0ab5089a1 100644 --- a/cmd-resize-pane.c +++ b/cmd-resize-pane.c @@ -270,10 +270,10 @@ cmd_resize_pane_mouse_resize_move_floating(struct client *c, if ((lx == left || lx == left + 1) && ly == wp->yoff - 1) { /* Top left corner. */ - new_sx = lc->sx + (lx - x); + new_sx = lc->g.sx + (lx - x); if (new_sx < PANE_MINIMUM) new_sx = PANE_MINIMUM; - new_sy = lc->sy + (ly - y); + new_sy = lc->g.sy + (ly - y); if (new_sy < PANE_MINIMUM) new_sy = PANE_MINIMUM; new_xoff = x + 1; /* because mouse is on border at xoff - 1 */ @@ -283,65 +283,65 @@ cmd_resize_pane_mouse_resize_move_floating(struct client *c, } else if ((lx == right + 1 || lx == right) && ly == wp->yoff - 1) { /* Top right corner. */ - new_sx = x - lc->xoff; + new_sx = x - lc->g.xoff; if (new_sx < PANE_MINIMUM) new_sx = PANE_MINIMUM; - new_sy = lc->sy + (ly - y); + new_sy = lc->g.sy + (ly - y); if (new_sy < PANE_MINIMUM) new_sy = PANE_MINIMUM; new_yoff = y + 1; - layout_set_size(lc, new_sx, new_sy, lc->xoff, new_yoff); + layout_set_size(lc, new_sx, new_sy, lc->g.xoff, new_yoff); resizes++; } else if ((lx == left || lx == left + 1) && ly == wp->yoff + sy) { /* Bottom left corner. */ - new_sx = lc->sx + (lx - x); + new_sx = lc->g.sx + (lx - x); if (new_sx < PANE_MINIMUM) new_sx = PANE_MINIMUM; - new_sy = y - lc->yoff; + new_sy = y - lc->g.yoff; if (new_sy < PANE_MINIMUM) return; new_xoff = x + 1; - layout_set_size(lc, new_sx, new_sy, new_xoff, lc->yoff); + layout_set_size(lc, new_sx, new_sy, new_xoff, lc->g.yoff); resizes++; } else if ((lx == right + 1 || lx == right) && ly == wp->yoff + sy) { /* Bottom right corner. */ - new_sx = x - lc->xoff; + new_sx = x - lc->g.xoff; if (new_sx < PANE_MINIMUM) new_sx = PANE_MINIMUM; - new_sy = y - lc->yoff; + new_sy = y - lc->g.yoff; if (new_sy < PANE_MINIMUM) new_sy = PANE_MINIMUM; - layout_set_size(lc, new_sx, new_sy, lc->xoff, lc->yoff); + layout_set_size(lc, new_sx, new_sy, lc->g.xoff, lc->g.yoff); resizes++; } else if (lx == right) { /* Right border. */ - new_sx = x - lc->xoff; + new_sx = x - lc->g.xoff; if (new_sx < PANE_MINIMUM) return; - layout_set_size(lc, new_sx, lc->sy, lc->xoff, lc->yoff); + layout_set_size(lc, new_sx, lc->g.sy, lc->g.xoff, lc->g.yoff); resizes++; } else if (lx == left) { /* Left border. */ - new_sx = lc->sx + (lx - x); + new_sx = lc->g.sx + (lx - x); if (new_sx < PANE_MINIMUM) return; new_xoff = x + 1; - layout_set_size(lc, new_sx, lc->sy, new_xoff, lc->yoff); + layout_set_size(lc, new_sx, lc->g.sy, new_xoff, lc->g.yoff); resizes++; } else if (ly == wp->yoff + sy) { /* Bottom border. */ - new_sy = y - lc->yoff; + new_sy = y - lc->g.yoff; if (new_sy < PANE_MINIMUM) return; - layout_set_size(lc, lc->sx, new_sy, lc->xoff, lc->yoff); + layout_set_size(lc, lc->g.sx, new_sy, lc->g.xoff, lc->g.yoff); resizes++; } else if (ly == wp->yoff - 1) { /* Top border (move instead of resize). */ - new_xoff = lc->xoff + (x - lx); + new_xoff = lc->g.xoff + (x - lx); new_yoff = y + 1; - layout_set_size(lc, lc->sx, lc->sy, new_xoff, new_yoff); + layout_set_size(lc, lc->g.sx, lc->g.sy, new_xoff, new_yoff); resizes++; } if (resizes != 0) { diff --git a/key-bindings.c b/key-bindings.c index 641957103..27cbb0e86 100644 --- a/key-bindings.c +++ b/key-bindings.c @@ -59,6 +59,8 @@ " '#{?mouse_hyperlink,Type #[underscore]#{=/9/...:mouse_hyperlink},}' 'C-h' {copy-mode -q; send-keys -l -- \"#{q:mouse_hyperlink}\"}" \ " '#{?mouse_hyperlink,Copy #[underscore]#{=/9/...:mouse_hyperlink},}' 'h' {copy-mode -q; set-buffer -- \"#{q:mouse_hyperlink}\"}" \ " ''" \ + " '#{?#{#{pane_floating_flag}},Move,}' '' {display-menu -xL -yL -T '#[align=centre]Move' " DEFAULT_MOVE_MENU " }" \ + " '#{?#{#{pane_floating_flag}},Move & Resize,}' '' {display-menu -xL -yL -T '#[align=centre]Move & Resize' " DEFAULT_MOVE_RESIZE_MENU " }" \ " '#{?#{#{pane_floating_flag}},Tile,}' 't' { join-pane }" \ " '#{?#{!:#{pane_floating_flag}},Float,}' 'f' { break-pane -W }" \ " '#{?#{!:#{pane_floating_flag}},Horizontal Split,}' 'h' {split-window -h}" \ @@ -72,6 +74,30 @@ " 'Respawn' 'R' {respawn-pane -k}" \ " '#{?pane_marked,Unmark,Mark}' 'm' {select-pane -m}" \ " '#{?#{>:#{window_panes},1},,-}#{?window_zoomed_flag,Unzoom,Zoom}' 'z' {resize-pane -Z}" +#define DEFAULT_MOVE_MENU \ + " 'Centre' 'c' {move-pane -P centre}" \ + " ''" \ + " 'Top Left' '1' {move-pane -P top-left}" \ + " 'Top Right' '2' {move-pane -P top-right}" \ + " 'Bottom Left' '3' {move-pane -P bottom-left}" \ + " 'Bottom Right' '4' {move-pane -P bottom-right}" \ + " ''" \ + " 'Top' 't' {move-pane -P top-centre}" \ + " 'Bottom' 'b' {move-pane -P bottom-centre}" \ + " 'Left' 'l' {move-pane -P centre-left}" \ + " 'Right' 'r' {move-pane -P centre-right}" +#define DEFAULT_MOVE_RESIZE_MENU \ + " 'Fill' '0' {resize-pane -x100% -y100%; move-pane -P top-left}" \ + " ''" \ + " 'Top Left' '1' {resize-pane -x50% -y50%; move-pane -P top-left}" \ + " 'Top Right' '2' {resize-pane -x50% -y50%; move-pane -P top-right}" \ + " 'Bottom Left' '3' {resize-pane -x50% -y50%; move-pane -P bottom-left}" \ + " 'Bottom Right' '4' {resize-pane -x50% -y50%; move-pane -P bottom-right}" \ + " ''" \ + " 'Top' 't' {resize-pane -x100% -y50%; move-pane -P top-centre}" \ + " 'Bottom' 'b' {resize-pane -x100% -y50%; move-pane -P bottom-centre}" \ + " 'Left' 'l' {resize-pane -x50% -y100%; move-pane -P centre-left}" \ + " 'Right' 'r' {resize-pane -x50% -y100%; move-pane -P centre-right}" static int key_bindings_cmp(struct key_binding *, struct key_binding *); RB_GENERATE_STATIC(key_bindings, key_binding, entry, key_bindings_cmp); @@ -410,10 +436,8 @@ key_bindings_init(void) "bind -N 'Choose a window from a list' w { choose-tree -Zw }", "bind -N 'Kill the active pane' x { confirm-before -p\"kill-pane #P? (y/n)\" kill-pane }", "bind -N 'Zoom the active pane' z { resize-pane -Z }", - "bind -N 'Move pane to top-left corner' '{' { resize-pane -x50% -y50%; move-pane -P top-left }", - "bind -N 'Move pane to top-right corner' '}' { resize-pane -x50% -y50%; move-pane -P top-right }", - "bind -N 'Move pane to bottom-left corner' 'M-{' { resize-pane -x50% -y50%; move-pane -P bottom-left }", - "bind -N 'Move pane to bottom-right corner' 'M-}' { resize-pane -x50% -y50%; move-pane -P bottom-right }", + "bind -N 'Swap the active pane with the pane above' '{' { swap-pane -U }", + "bind -N 'Swap the active pane with the pane below' '}' { swap-pane -D }", "bind -N 'Show messages' '~' { show-messages }", "bind -N 'Enter copy mode and scroll up' PPage { copy-mode -u }", "bind -N 'Select the pane above the active pane' -r Up { select-pane -U }", @@ -444,6 +468,28 @@ key_bindings_init(void) "bind -N 'Resize the pane left' -r C-Left if -F '#{?floating_pane_flag}' { resizep -R-1 } { resize-pane -L }", "bind -N 'Resize the pane right' -r C-Right { resize-pane -R }", + /* Floating pane movement. */ + "bind -N 'Move a floating pane' g { switch-client -Tmove }", + "bind -Tmove -N 'Move pane to top-left corner' 1 { move-pane -P top-left }", + "bind -Tmove -N 'Move pane to top-right corner' 2 { move-pane -P top-right }", + "bind -Tmove -N 'Move pane to bottom-left corner' 3 { move-pane -P bottom-left }", + "bind -Tmove -N 'Move pane to bottom-right corner' 4 { move-pane -P bottom-right }", + "bind -Tmove -N 'Move pane to top-left corner and resize' M-1 { resize-pane -x50% -y50%; move-pane -P top-left }", + "bind -Tmove -N 'Move pane to top-right corner and resize' M-2 { resize-pane -x50% -y50%; move-pane -P top-right }", + "bind -Tmove -N 'Move pane to bottom-left corner and resize' M-3 { resize-pane -x50% -y50%; move-pane -P bottom-left }", + "bind -Tmove -N 'Move pane to bottom-right corner and resize' M-4 { resize-pane -x50% -y50%; move-pane -P bottom-right }", + "bind -Tmove -N 'Move pane to top' 'Up' { move-pane -P top-centre }", + "bind -Tmove -N 'Move pane to bottom' 'Down' { move-pane -P bottom-centre }", + "bind -Tmove -N 'Move pane to left' 'Left' { move-pane -P centre-left }", + "bind -Tmove -N 'Move pane to right' 'Right' { move-pane -P centre-right }", + "bind -Tmove -N 'Move pane to top and resize' 'M-Up' { resizep -x100% -y50%; move-pane -P top-centre }", + "bind -Tmove -N 'Move pane to bottom and resize' 'M-Down' { resizep -x100% -y50%; move-pane -P bottom-centre }", + "bind -Tmove -N 'Move pane to left and resize' 'M-Left' { resizep -x50% -y100%; move-pane -P centre-left }", + "bind -Tmove -N 'Move pane to right and resize' 'M-Right' { resizep -x50% -y100%; move-pane -P centre-right }", + "bind -Tmove -N 'Move pane to fill the window' 0 { resize-pane -x100% -y100%; move-pane -P top-left }", + "bind -Tmove -N 'Display move menu' , { if -F '#{pane_floating_flag}' { display-menu -xP -yP -T '#[align=centre]Move' " DEFAULT_MOVE_MENU " } }", + "bind -Tmove -N 'Display move and resize menu' . { if -F '#{pane_floating_flag}' { display-menu -xP -yP -T '#[align=centre]Move & Resize' " DEFAULT_MOVE_RESIZE_MENU " } }", + /* Menu keys */ "bind -N 'Display window menu' < { display-menu -xW -yW -T '#[align=centre]#{window_index}:#{window_name}' " DEFAULT_WINDOW_MENU " }", "bind -N 'Display pane menu' > { display-menu -xP -yP -T '#[align=centre]#{pane_index} (#{pane_id})' " DEFAULT_PANE_MENU " }", diff --git a/layout-custom.c b/layout-custom.c index 9ae07f28a..35ef7a44b 100644 --- a/layout-custom.c +++ b/layout-custom.c @@ -101,10 +101,10 @@ layout_append(struct layout_cell *lc, char *buf, size_t len) return (0); if (lc->wp != NULL) { tmplen = xsnprintf(tmp, sizeof tmp, "%ux%u,%d,%d,%u", - lc->sx, lc->sy, lc->xoff, lc->yoff, lc->wp->id); + lc->g.sx, lc->g.sy, lc->g.xoff, lc->g.yoff, lc->wp->id); } else { tmplen = xsnprintf(tmp, sizeof tmp, "%ux%u,%d,%d", - lc->sx, lc->sy, lc->xoff, lc->yoff); + lc->g.sx, lc->g.sy, lc->g.xoff, lc->g.yoff); } if (tmplen > (sizeof tmp) - 1) return (-1); @@ -145,24 +145,24 @@ layout_check(struct layout_cell *lc) break; case LAYOUT_LEFTRIGHT: TAILQ_FOREACH(lcchild, &lc->cells, entry) { - if (lcchild->sy != lc->sy) + if (lcchild->g.sy != lc->g.sy) return (0); if (!layout_check(lcchild)) return (0); - n += lcchild->sx + 1; + n += lcchild->g.sx + 1; } - if (n - 1 != lc->sx) + if (n - 1 != lc->g.sx) return (0); break; case LAYOUT_TOPBOTTOM: TAILQ_FOREACH(lcchild, &lc->cells, entry) { - if (lcchild->sx != lc->sx) + if (lcchild->g.sx != lc->g.sx) return (0); if (!layout_check(lcchild)) return (0); - n += lcchild->sy + 1; + n += lcchild->g.sy + 1; } - if (n - 1 != lc->sy) + if (n - 1 != lc->g.sy) return (0); break; } @@ -237,21 +237,21 @@ layout_parse(struct window *w, const char *layout, char **cause) break; case LAYOUT_LEFTRIGHT: TAILQ_FOREACH(lcchild, &tiled_lc->cells, entry) { - sy = lcchild->sy + 1; - sx += lcchild->sx + 1; + sy = lcchild->g.sy + 1; + sx += lcchild->g.sx + 1; } break; case LAYOUT_TOPBOTTOM: TAILQ_FOREACH(lcchild, &tiled_lc->cells, entry) { - sx = lcchild->sx + 1; - sy += lcchild->sy + 1; + sx = lcchild->g.sx + 1; + sy += lcchild->g.sy + 1; } break; } if (tiled_lc->type != LAYOUT_WINDOWPANE && - (tiled_lc->sx != sx || tiled_lc->sy != sy)) { + (tiled_lc->g.sx != sx || tiled_lc->g.sy != sy)) { layout_print_cell(tiled_lc, __func__, 0); - tiled_lc->sx = sx - 1; tiled_lc->sy = sy - 1; + tiled_lc->g.sx = sx - 1; tiled_lc->g.sy = sy - 1; } /* Check the new layout. */ @@ -262,7 +262,7 @@ layout_parse(struct window *w, const char *layout, char **cause) /* Resize window to the layout size. */ if (sx != 0 && sy != 0) - window_resize(w, tiled_lc->sx, tiled_lc->sy, -1, -1); + window_resize(w, tiled_lc->g.sx, tiled_lc->g.sy, -1, -1); /* Destroy the old layout and swap to the new. */ layout_free_cell(w->layout_root, 0); @@ -358,10 +358,10 @@ layout_construct_cell(struct layout_cell *lcparent, const char **layout) } lc = layout_create_cell(lcparent); - lc->sx = sx; - lc->sy = sy; - lc->xoff = xoff; - lc->yoff = yoff; + lc->g.sx = sx; + lc->g.sy = sy; + lc->g.xoff = xoff; + lc->g.yoff = yoff; return (lc); } diff --git a/layout-set.c b/layout-set.c index 337ee6fc7..0fa0e614d 100644 --- a/layout-set.c +++ b/layout-set.c @@ -170,8 +170,8 @@ layout_set_even(struct window *w, enum layout_type type) TAILQ_INSERT_TAIL(&lcroot->cells, lcchild, entry); lcchild->parent = lcroot; if (layout_cell_is_tiled(lcchild)) { - lcchild->sx = w->sx; - lcchild->sy = w->sy; + lcchild->g.sx = w->sx; + lcchild->g.sy = w->sy; } } @@ -182,7 +182,7 @@ layout_set_even(struct window *w, enum layout_type type) layout_print_cell(w->layout_root, __func__, 1); - window_resize(w, lcroot->sx, lcroot->sy, -1, -1); + window_resize(w, lcroot->g.sx, lcroot->g.sy, -1, -1); events_fire_window("window-layout-changed", w); server_redraw_window(w); } @@ -291,7 +291,7 @@ layout_set_main_h(struct window *w) layout_print_cell(w->layout_root, __func__, 1); - window_resize(w, lcroot->sx, lcroot->sy, -1, -1); + window_resize(w, lcroot->g.sx, lcroot->g.sy, -1, -1); events_fire_window("window-layout-changed", w); server_redraw_window(w); } @@ -388,7 +388,7 @@ layout_set_main_h_mirrored(struct window *w) layout_print_cell(w->layout_root, __func__, 1); - window_resize(w, lcroot->sx, lcroot->sy, -1, -1); + window_resize(w, lcroot->g.sx, lcroot->g.sy, -1, -1); events_fire_window("window-layout-changed", w); server_redraw_window(w); } @@ -485,7 +485,7 @@ layout_set_main_v(struct window *w) layout_print_cell(w->layout_root, __func__, 1); - window_resize(w, lcroot->sx, lcroot->sy, -1, -1); + window_resize(w, lcroot->g.sx, lcroot->g.sy, -1, -1); events_fire_window("window-layout-changed", w); server_redraw_window(w); } @@ -583,7 +583,7 @@ layout_set_main_v_mirrored(struct window *w) layout_print_cell(w->layout_root, __func__, 1); - window_resize(w, lcroot->sx, lcroot->sy, -1, -1); + window_resize(w, lcroot->g.sx, lcroot->g.sy, -1, -1); events_fire_window("window-layout-changed", w); server_redraw_window(w); } @@ -705,7 +705,7 @@ layout_set_tiled(struct window *w) layout_print_cell(w->layout_root, __func__, 1); - window_resize(w, lcroot->sx, lcroot->sy, -1, -1); + window_resize(w, lcroot->g.sx, lcroot->g.sy, -1, -1); events_fire_window("window-layout-changed", w); server_redraw_window(w); } diff --git a/layout.c b/layout.c index c353064ef..9f4519048 100644 --- a/layout.c +++ b/layout.c @@ -56,32 +56,29 @@ static int layout_set_size_check(struct window *, struct layout_cell *, static void layout_resize_child_cells(struct window *, struct layout_cell *); +/* Initializes cell geometry to sentinel values. */ +static void +layout_geometry_init(struct layout_geometry *lg) +{ + lg->sx = UINT_MAX; + lg->sy = UINT_MAX; + lg->xoff = INT_MAX; + lg->yoff = INT_MAX; +} + /* Create a new layout cell. */ struct layout_cell * layout_create_cell(struct layout_cell *lcparent) { struct layout_cell *lc; - lc = xmalloc(sizeof *lc); + lc = xcalloc(1, sizeof *lc); lc->type = LAYOUT_WINDOWPANE; - lc->flags = 0; lc->parent = lcparent; - TAILQ_INIT(&lc->cells); - lc->sx = UINT_MAX; - lc->sy = UINT_MAX; - - lc->xoff = INT_MAX; - lc->yoff = INT_MAX; - - lc->saved_sx = UINT_MAX; - lc->saved_sy = UINT_MAX; - - lc->saved_xoff = INT_MAX; - lc->saved_yoff = INT_MAX; - - lc->wp = NULL; + layout_geometry_init(&lc->g); + layout_geometry_init(&lc->fg); return (lc); } @@ -144,8 +141,8 @@ layout_print_cell(struct layout_cell *lc, const char *hdr, u_int n) break; } log_debug("%s:%*s%p type %s [parent %p] wp=%p [%d,%d %ux%u]", hdr, n, - " ", lc, type, lc->parent, lc->wp, lc->xoff, lc->yoff, lc->sx, - lc->sy); + " ", lc, type, lc->parent, lc->wp, lc->g.xoff, lc->g.yoff, lc->g.sx, + lc->g.sy); switch (lc->type) { case LAYOUT_LEFTRIGHT: case LAYOUT_TOPBOTTOM: @@ -164,10 +161,10 @@ layout_search_by_border(struct layout_cell *lc, u_int x, u_int y) struct layout_cell *lcchild, *last = NULL; TAILQ_FOREACH(lcchild, &lc->cells, entry) { - if ((int)x >= lcchild->xoff && - (int)x < lcchild->xoff + (int)lcchild->sx && - (int)y >= lcchild->yoff && - (int)y < lcchild->yoff + (int)lcchild->sy) { + if ((int)x >= lcchild->g.xoff && + (int)x < lcchild->g.xoff + (int)lcchild->g.sx && + (int)y >= lcchild->g.yoff && + (int)y < lcchild->g.yoff + (int)lcchild->g.sy) { /* Inside the cell - recurse. */ return (layout_search_by_border(lcchild, x, y)); } @@ -179,13 +176,13 @@ layout_search_by_border(struct layout_cell *lc, u_int x, u_int y) switch (lc->type) { case LAYOUT_LEFTRIGHT: - if ((int)x < lcchild->xoff && - (int)x >= last->xoff + (int)last->sx) + if ((int)x < lcchild->g.xoff && + (int)x >= last->g.xoff + (int)last->g.sx) return (last); break; case LAYOUT_TOPBOTTOM: - if ((int)y < lcchild->yoff && - (int)y >= last->yoff + (int)last->sy) + if ((int)y < lcchild->g.yoff && + (int)y >= last->g.yoff + (int)last->g.sy) return (last); break; case LAYOUT_WINDOWPANE: @@ -202,11 +199,11 @@ layout_search_by_border(struct layout_cell *lc, u_int x, u_int y) void layout_set_size(struct layout_cell *lc, u_int sx, u_int sy, int xoff, int yoff) { - lc->sx = sx; - lc->sy = sy; + lc->g.sx = sx; + lc->g.sy = sy; - lc->xoff = xoff; - lc->yoff = yoff; + lc->g.xoff = xoff; + lc->g.yoff = yoff; } /* Make a cell a leaf cell. */ @@ -331,28 +328,28 @@ layout_fix_offsets1(struct layout_cell *lc) int xoff, yoff; if (lc->type == LAYOUT_LEFTRIGHT) { - xoff = lc->xoff; + xoff = lc->g.xoff; TAILQ_FOREACH(lcchild, &lc->cells, entry) { if (!layout_cell_is_tiled(lcchild) && !layout_cell_has_tiled_child(lcchild)) continue; - lcchild->xoff = xoff; - lcchild->yoff = lc->yoff; + lcchild->g.xoff = xoff; + lcchild->g.yoff = lc->g.yoff; if (lcchild->type != LAYOUT_WINDOWPANE) layout_fix_offsets1(lcchild); - xoff += lcchild->sx + 1; + xoff += lcchild->g.sx + 1; } } else { - yoff = lc->yoff; + yoff = lc->g.yoff; TAILQ_FOREACH(lcchild, &lc->cells, entry) { if (!layout_cell_is_tiled(lcchild) && !layout_cell_has_tiled_child(lcchild)) continue; - lcchild->xoff = lc->xoff; - lcchild->yoff = yoff; + lcchild->g.xoff = lc->g.xoff; + lcchild->g.yoff = yoff; if (lcchild->type != LAYOUT_WINDOWPANE) layout_fix_offsets1(lcchild); - yoff += lcchild->sy + 1; + yoff += lcchild->g.sy + 1; } } } @@ -367,8 +364,8 @@ layout_fix_offsets(struct window *w) if (lc->flags & LAYOUT_CELL_FLOATING) return; - lc->xoff = 0; - lc->yoff = 0; + lc->g.xoff = 0; + lc->g.yoff = 0; layout_fix_offsets1(lc); } @@ -452,10 +449,10 @@ layout_fix_panes(struct window *w, struct window_pane *skip) old_sx = wp->sx; old_sy = wp->sy; - wp->xoff = lc->xoff; - wp->yoff = lc->yoff; - sx = lc->sx; - sy = lc->sy; + wp->xoff = lc->g.xoff; + wp->yoff = lc->g.yoff; + sx = lc->g.sx; + sy = lc->g.sy; if (!window_pane_is_floating(wp) && layout_add_horizontal_border(w, lc, status)) { @@ -536,14 +533,14 @@ layout_resize_check(struct window *w, struct layout_cell *lc, if (lc->type == LAYOUT_WINDOWPANE) { /* Space available in this cell only. */ if (type == LAYOUT_LEFTRIGHT) { - available = lc->sx; + available = lc->g.sx; if (w->sb == PANE_SCROLLBARS_ALWAYS) minimum = PANE_MINIMUM + sb_style->width + sb_style->pad; else minimum = PANE_MINIMUM; } else { - available = lc->sy; + available = lc->g.sy; if (layout_add_horizontal_border(w, lc, status)) minimum = PANE_MINIMUM + 1; else @@ -585,9 +582,9 @@ layout_resize_adjust(struct window *w, struct layout_cell *lc, /* Adjust the cell size. */ if (type == LAYOUT_LEFTRIGHT) - lc->sx += change; + lc->g.sx += change; else - lc->sy += change; + lc->g.sy += change; /* If this is a leaf cell, that is all that is necessary. */ if (type == LAYOUT_WINDOWPANE) @@ -647,9 +644,9 @@ layout_resize_set_size(struct window *w, struct layout_cell *lc, int change; if (type == LAYOUT_LEFTRIGHT) - change = size - lc->sx; + change = size - lc->g.sx; else - change = size - lc->sy; + change = size - lc->g.sy; layout_resize_adjust(w, lc, type, change); } @@ -723,9 +720,9 @@ layout_destroy_cell(struct window *w, struct layout_cell *lc, lcother = layout_cell_get_neighbour(lc); if (lcother != NULL) { if (lcparent->type == LAYOUT_LEFTRIGHT) - change = lc->sx + 1; + change = lc->g.sx + 1; else - change = lc->sy + 1; + change = lc->g.sy + 1; layout_resize_adjust(w, lcother, lcparent->type, change); } else layout_remove_tile(w, lcparent); @@ -746,8 +743,8 @@ out: lc->parent = lcparent->parent; if (lc->parent == NULL) { if (layout_cell_is_tiled(lc)) { - lc->xoff = 0; - lc->yoff = 0; + lc->g.xoff = 0; + lc->g.yoff = 0; } *lcroot = lc; } else @@ -798,29 +795,29 @@ layout_resize(struct window *w, u_int sx, u_int sy) */ if (lc->type == LAYOUT_WINDOWPANE && (lc->flags & LAYOUT_CELL_FLOATING)) return; - xchange = sx - lc->sx; + xchange = sx - lc->g.sx; xlimit = layout_resize_check(w, lc, LAYOUT_LEFTRIGHT); if (xchange < 0 && xchange < -xlimit) xchange = -xlimit; if (xlimit == 0) { - if (sx <= lc->sx) /* lc->sx is minimum possible */ + if (sx <= lc->g.sx) /* lc->g.sx is minimum possible */ xchange = 0; else - xchange = sx - lc->sx; + xchange = sx - lc->g.sx; } if (xchange != 0) layout_resize_adjust(w, lc, LAYOUT_LEFTRIGHT, xchange); /* Adjust vertically in a similar fashion. */ - ychange = sy - lc->sy; + ychange = sy - lc->g.sy; ylimit = layout_resize_check(w, lc, LAYOUT_TOPBOTTOM); if (ychange < 0 && ychange < -ylimit) ychange = -ylimit; if (ylimit == 0) { - if (sy <= lc->sy) /* lc->sy is minimum possible */ + if (sy <= lc->g.sy) /* lc->g.sy is minimum possible */ ychange = 0; else - ychange = sy - lc->sy; + ychange = sy - lc->g.sy; } if (ychange != 0) layout_resize_adjust(w, lc, LAYOUT_TOPBOTTOM, ychange); @@ -851,9 +848,9 @@ layout_resize_pane_to(struct window_pane *wp, enum layout_type type, /* Work out the size adjustment. */ if (type == LAYOUT_LEFTRIGHT) - size = lc->sx; + size = lc->g.sx; else - size = lc->sy; + size = lc->g.sy; if (lc == TAILQ_LAST(&lcparent->cells, layout_cells)) change = size - new_size; else @@ -884,13 +881,13 @@ layout_resize_floating_pane_to(struct window_pane *wp, enum layout_type type, } if (type == LAYOUT_TOPBOTTOM) { - if (lc->sy == size) + if (lc->g.sy == size) return (0); - lc->sy = size; + lc->g.sy = size; } else { - if (lc->sx == size) + if (lc->g.sx == size) return (0); - lc->sx = size; + lc->g.sx = size; } redraw_invalidate_scene(wp->window); return (0); @@ -912,23 +909,23 @@ layout_resize_floating_pane(struct window_pane *wp, enum layout_type type, return (0); if (type == LAYOUT_TOPBOTTOM) { - size = lc->sy + change; + size = lc->g.sy + change; if (size < PANE_MINIMUM || size > PANE_MAXIMUM) { *cause = xstrdup("change is too big or too small"); return (-1); } - lc->sy = size; + lc->g.sy = size; if (opposite) - lc->yoff -= change; + lc->g.yoff -= change; } else { - size = lc->sx + change; + size = lc->g.sx + change; if (size < PANE_MINIMUM || size > PANE_MAXIMUM) { *cause = xstrdup("change is too big or too small"); return (-1); } - lc->sx = size; + lc->g.sx = size; if (opposite) - lc->xoff -= change; + lc->g.xoff -= change; } redraw_invalidate_scene(wp->window); return (0); @@ -1094,13 +1091,13 @@ layout_new_pane_size(struct window *w, u_int previous, struct layout_cell *lc, */ min = (PANE_MINIMUM + 1) * (count_left - 1); if (type == LAYOUT_LEFTRIGHT) { - if (lc->sx - available > min) - min = lc->sx - available; - new_size = (lc->sx * size) / previous; + if (lc->g.sx - available > min) + min = lc->g.sx - available; + new_size = (lc->g.sx * size) / previous; } else { - if (lc->sy - available > min) - min = lc->sy - available; - new_size = (lc->sy * size) / previous; + if (lc->g.sy - available > min) + min = lc->g.sy - available; + new_size = (lc->g.sy * size) / previous; } /* Check against the maximum and minimum size. */ @@ -1136,9 +1133,9 @@ layout_set_size_check(struct window *w, struct layout_cell *lc, return (0); if (type == LAYOUT_LEFTRIGHT) - previous = lc->sx; + previous = lc->g.sx; else - previous = lc->sy; + previous = lc->g.sy; idx = 0; TAILQ_FOREACH(lcchild, &lc->cells, entry) { @@ -1174,32 +1171,32 @@ static void layout_resize_child_cells(struct window *w, struct layout_cell *lc) { struct layout_cell *lcchild; - u_int previous, available, count, idx; + u_int prev, available, count, idx; if (lc->type == LAYOUT_WINDOWPANE) return; /* What is the current size used? */ count = 0; - previous = 0; + prev = 0; TAILQ_FOREACH(lcchild, &lc->cells, entry) { if (!layout_cell_is_tiled(lcchild) && !layout_cell_has_tiled_child(lcchild)) continue; count++; if (lc->type == LAYOUT_LEFTRIGHT) - previous += lcchild->sx; + prev += lcchild->g.sx; else if (lc->type == LAYOUT_TOPBOTTOM) - previous += lcchild->sy; + prev += lcchild->g.sy; } - previous += (count - 1); + prev += (count - 1); /* And how much is available? */ available = 0; if (lc->type == LAYOUT_LEFTRIGHT) - available = lc->sx; + available = lc->g.sx; else if (lc->type == LAYOUT_TOPBOTTOM) - available = lc->sy; + available = lc->g.sy; /* Resize children into the new size. */ idx = 0; @@ -1208,20 +1205,20 @@ layout_resize_child_cells(struct window *w, struct layout_cell *lc) !layout_cell_has_tiled_child(lcchild)) continue; if (lc->type == LAYOUT_TOPBOTTOM) { - lcchild->sx = lc->sx; - lcchild->xoff = lc->xoff; + lcchild->g.sx = lc->g.sx; + lcchild->g.xoff = lc->g.xoff; } else { - lcchild->sx = layout_new_pane_size(w, previous, lcchild, - lc->type, lc->sx, count - idx, available); - available -= (lcchild->sx + 1); + lcchild->g.sx = layout_new_pane_size(w, prev, lcchild, + lc->type, lc->g.sx, count - idx, available); + available -= (lcchild->g.sx + 1); } if (lc->type == LAYOUT_LEFTRIGHT) { - lcchild->sy = lc->sy; - lcchild->yoff = lc->yoff; + lcchild->g.sy = lc->g.sy; + lcchild->g.yoff = lc->g.yoff; } else { - lcchild->sy = layout_new_pane_size(w, previous, lcchild, - lc->type, lc->sy, count - idx, available); - available -= (lcchild->sy + 1); + lcchild->g.sy = layout_new_pane_size(w, prev, lcchild, + lc->type, lc->g.sy, count - idx, available); + available -= (lcchild->g.sy + 1); } layout_resize_child_cells(w, lcchild); idx++; @@ -1241,7 +1238,7 @@ layout_replace_with_node(struct window *w, struct layout_cell *lc, lcparent = layout_create_cell(lc->parent); layout_make_node(lcparent, type); - layout_set_size(lcparent, lc->sx, lc->sy, lc->xoff, lc->yoff); + layout_set_size(lcparent, lc->g.sx, lc->g.sy, lc->g.xoff, lc->g.yoff); if (lc->parent == NULL) w->layout_root = lcparent; else @@ -1260,7 +1257,7 @@ layout_split_check_space(struct window_pane *wp, struct layout_cell *lc, enum layout_type type) { struct style *sb_style = &wp->scrollbar_style; - u_int minimum, sx = lc->sx, sy = lc->sy; + u_int minimum, sx = lc->g.sx, sy = lc->g.sy; int status; if (lc->flags & LAYOUT_CELL_FLOATING) @@ -1299,7 +1296,7 @@ layout_split_sizes(struct layout_cell *lc, int size, int before, enum layout_type type, u_int *size1, u_int *size2, u_int *saved_size) { u_int s1, s2, ss; - u_int sx = lc->sx, sy = lc->sy; + u_int sx = lc->g.sx, sy = lc->g.sy; if (type == LAYOUT_LEFTRIGHT) ss = sx; @@ -1346,10 +1343,10 @@ layout_split_pane(struct window_pane *wp, enum layout_type type, int size, lc = wp->layout_cell; /* Copy the old cell size. */ - sx = lc->sx; - sy = lc->sy; - xoff = lc->xoff; - yoff = lc->yoff; + sx = lc->g.sx; + sy = lc->g.sy; + xoff = lc->g.xoff; + yoff = lc->g.yoff; /* Check there is enough space for the two new panes. */ if (!layout_split_check_space(wp, lc, type)) @@ -1390,13 +1387,13 @@ layout_split_pane(struct window_pane *wp, enum layout_type type, int size, * must be resized before inserting the new cell. */ if (lc->type == LAYOUT_LEFTRIGHT) { - lc->sx = new_size; + lc->g.sx = new_size; layout_resize_child_cells(wp->window, lc); - lc->sx = saved_size; + lc->g.sx = saved_size; } else if (lc->type == LAYOUT_TOPBOTTOM) { - lc->sy = new_size; + lc->g.sy = new_size; layout_resize_child_cells(wp->window, lc); - lc->sy = saved_size; + lc->g.sy = saved_size; } resize_first = 1; @@ -1440,10 +1437,10 @@ layout_split_pane(struct window_pane *wp, enum layout_type type, int size, */ if (!resize_first && type == LAYOUT_LEFTRIGHT) { layout_set_size(lc1, size1, sy, xoff, yoff); - layout_set_size(lc2, size2, sy, xoff + lc1->sx + 1, yoff); + layout_set_size(lc2, size2, sy, xoff + lc1->g.sx + 1, yoff); } else if (!resize_first && type == LAYOUT_TOPBOTTOM) { layout_set_size(lc1, sx, size1, xoff, yoff); - layout_set_size(lc2, sx, size2, xoff, yoff + lc1->sy + 1); + layout_set_size(lc2, sx, size2, xoff, yoff + lc1->g.sy + 1); } if (full_size) { if (!resize_first) @@ -1460,8 +1457,8 @@ layout_split_pane(struct window_pane *wp, enum layout_type type, int size, * layout_assign_pane before much else happens! */ struct layout_cell * -layout_floating_pane(struct window *w, struct window_pane *wp, u_int sx, - u_int sy, int ox, int oy) +layout_floating_pane(struct window *w, struct window_pane *wp, + struct layout_geometry *lg) { struct layout_cell *lc, *lcnew, *lcparent; @@ -1473,16 +1470,16 @@ layout_floating_pane(struct window *w, struct window_pane *wp, u_int sx, if (lcparent == NULL) { /* - * Adding a pane to a root that isn't node. Must create and - * insert a new root. - */ + * Adding a pane to a root that isn't a node. Must create and + * insert a new root. + */ lcparent = layout_replace_with_node(w, lc, LAYOUT_TOPBOTTOM); } lcnew = layout_create_cell(lcparent); TAILQ_INSERT_AFTER(&lcparent->cells, lc, lcnew, entry); lcnew->flags |= LAYOUT_CELL_FLOATING; - layout_set_size(lcnew, sx, sy, ox, oy); + layout_set_size(lcnew, lg->sx, lg->sy, lg->xoff, lg->yoff); return (lcnew); } @@ -1525,12 +1522,12 @@ layout_spread_cell(struct window *w, struct layout_cell *parent) status = window_get_pane_status(w); if (parent->type == LAYOUT_LEFTRIGHT) - size = parent->sx; + size = parent->g.sx; else if (parent->type == LAYOUT_TOPBOTTOM) { if (layout_add_horizontal_border(w, parent, status)) - size = parent->sy - 1; + size = parent->g.sy - 1; else - size = parent->sy; + size = parent->g.sy; } else return (0); if (size < number - 1) @@ -1551,7 +1548,7 @@ layout_spread_cell(struct window *w, struct layout_cell *parent) continue; change = 0; if (parent->type == LAYOUT_LEFTRIGHT) { - change = each - (int)lc->sx; + change = each - (int)lc->g.sx; if (remainder > 0) { change++; remainder--; @@ -1566,7 +1563,7 @@ layout_spread_cell(struct window *w, struct layout_cell *parent) this++; remainder--; } - change = this - (int)lc->sy; + change = this - (int)lc->g.sy; layout_resize_adjust(w, lc, LAYOUT_TOPBOTTOM, change); } if (change != 0) @@ -1663,30 +1660,29 @@ layout_get_floating_cell(struct cmdq_item *item, struct args *args, char **cause) { struct layout_cell *lcnew; - u_int sx = UINT_MAX, sy = UINT_MAX; - int ox = INT_MAX, oy = INT_MAX; + struct layout_geometry fg; - if (layout_floating_args_parse(item, args, lines, w, &sx, &sy, &ox, &oy, - cause) != 0) + layout_geometry_init(&fg); + if (layout_floating_args_parse(item, args, lines, w, &fg, cause) != 0) return (NULL); window_push_zoom(wp->window, 1, args_has(args, 'Z')); - lcnew = layout_floating_pane(w, wp, sx, sy, ox, oy); + lcnew = layout_floating_pane(w, wp, &fg); return (lcnew); } int layout_floating_args_parse(struct cmdq_item *item, struct args *args, - enum pane_lines lines, struct window *w, u_int *sxp, u_int *syp, int *oxp, - int *oyp, char **cause) + enum pane_lines lines, struct window *w, struct layout_geometry *lg, + char **cause) { int sx, sy, ox, oy; char *error = NULL; - sx = *sxp == UINT_MAX ? w->sx / 2 : *sxp; - sy = *syp == UINT_MAX ? w->sy / 4 : *syp; - ox = *oxp == INT_MAX ? INT_MAX : *oxp; - oy = *oyp == INT_MAX ? INT_MAX : *oyp; + sx = lg->sx == UINT_MAX ? w->sx / 2 : lg->sx; + sy = lg->sy == UINT_MAX ? w->sy / 4 : lg->sy; + ox = lg->xoff; + oy = lg->yoff; if (args_has(args, 'x')) { sx = args_percentage_and_expand(args, 'x', 0, PANE_MAXIMUM, @@ -1763,10 +1759,10 @@ layout_floating_args_parse(struct cmdq_item *item, struct args *args, return (-1); } - *sxp = sx; - *syp = sy; - *oxp = ox; - *oyp = oy; + lg->sx = sx; + lg->sy = sy; + lg->xoff = ox; + lg->yoff = oy; return (0); } @@ -1795,9 +1791,9 @@ layout_remove_tile(struct window *w, struct layout_cell *lc) * neighbour. */ if (type == LAYOUT_TOPBOTTOM) - change = lc->sy + 1; + change = lc->g.sy + 1; else - change = lc->sx + 1; + change = lc->g.sx + 1; layout_resize_adjust(w, lcneighbour, type, change); } @@ -1843,9 +1839,9 @@ layout_insert_tile(struct window *w, struct layout_cell *lc) */ layout_insert_tile(w, lcparent); if (type == LAYOUT_LEFTRIGHT) - size1 = lcparent->sx; + size1 = lcparent->g.sx; else - size1 = lcparent->sy; + size1 = lcparent->g.sy; layout_resize_set_size(w, lc, type, size1); } else { /* @@ -1863,10 +1859,10 @@ layout_insert_tile(struct window *w, struct layout_cell *lc) /* Setting opposite of the 'split' size to that of the parent. */ if (lcparent->type == LAYOUT_LEFTRIGHT) { - size1 = lcparent->sy; + size1 = lcparent->g.sy; type = LAYOUT_TOPBOTTOM; } else { - size1 = lcparent->sx; + size1 = lcparent->g.sx; type = LAYOUT_LEFTRIGHT; } layout_resize_set_size(w, lc, type, size1); diff --git a/menu.c b/menu.c index 756bb5693..257452fd7 100644 --- a/menu.c +++ b/menu.c @@ -313,6 +313,7 @@ menu_key_cb(struct client *c, void *data, struct key_event *event) struct mouse_event *m = &event->m; u_int i; int count = menu->count, old = md->choice; + int move; const char *name = NULL; const struct menu_item *item; struct cmdq_state *state; @@ -320,6 +321,14 @@ menu_key_cb(struct client *c, void *data, struct key_event *event) char *error; if (KEYC_IS_MOUSE(event->key)) { + /* + * A mouse move with no button held reports as a release, so + * treat it as highlight-only: it must never select or close the + * menu, otherwise a menu opened without a button already down + * (such as a submenu opened from another menu) would vanish as + * soon as the mouse moved over it. + */ + move = MOUSE_DRAG(m->b) && MOUSE_RELEASE(m->b); if (md->flags & MENU_NOMOUSE) { if (MOUSE_BUTTONS(m->b) != MOUSE_BUTTON_1) return (1); @@ -330,7 +339,7 @@ menu_key_cb(struct client *c, void *data, struct key_event *event) m->y < md->py + 1 || m->y > md->py + 1 + count - 1) { if (~md->flags & MENU_STAYOPEN) { - if (MOUSE_RELEASE(m->b)) + if (!move && MOUSE_RELEASE(m->b)) return (1); } else { if (!MOUSE_RELEASE(m->b) && @@ -345,7 +354,7 @@ menu_key_cb(struct client *c, void *data, struct key_event *event) return (0); } if (~md->flags & MENU_STAYOPEN) { - if (MOUSE_RELEASE(m->b)) + if (!move && MOUSE_RELEASE(m->b)) goto chosen; } else { if (!MOUSE_WHEEL(m->b) && !MOUSE_DRAG(m->b)) @@ -558,6 +567,10 @@ menu_prepare(struct menu *menu, int flags, int starting_choice, if (py + menu->count + 2 > c->tty.sy) py = c->tty.sy - menu->count - 2; + /* Remember where this menu is so -x/-y L can reuse the position. */ + c->menu_last_px = px; + c->menu_last_py = py; + if (lines == BOX_LINES_DEFAULT) lines = options_get_number(o, "menu-border-lines"); diff --git a/options.c b/options.c index c5be044a8..bfed9fa31 100644 --- a/options.c +++ b/options.c @@ -667,7 +667,7 @@ options_array_first(struct options_entry *o) struct options_array_item * options_array_next(struct options_array_item *a) { - return (RB_NEXT(options_array, &o->value.array, a)); + return (RB_NEXT(options_array, , a)); } const char * diff --git a/resize.c b/resize.c index 440a27b45..e0011d1f6 100644 --- a/resize.c +++ b/resize.c @@ -46,13 +46,13 @@ resize_window(struct window *w, u_int sx, u_int sy, int xpixel, int ypixel) layout_resize(w, sx, sy); /* Resize the window, it can be no smaller than the layout. */ - if (sx < w->layout_root->sx) - sx = w->layout_root->sx; - if (sy < w->layout_root->sy) - sy = w->layout_root->sy; + if (sx < w->layout_root->g.sx) + sx = w->layout_root->g.sx; + if (sy < w->layout_root->g.sy) + sy = w->layout_root->g.sy; window_resize(w, sx, sy, xpixel, ypixel); log_debug("%s: @%u resized to %ux%u; layout %ux%u", __func__, w->id, - sx, sy, w->layout_root->sx, w->layout_root->sy); + sx, sy, w->layout_root->g.sx, w->layout_root->g.sy); /* Restore the window zoom state. */ if (zoomed) diff --git a/spawn.c b/spawn.c index c42695f06..e3a6bce2d 100644 --- a/spawn.c +++ b/spawn.c @@ -632,13 +632,13 @@ spawn_editor(struct client *c, const char *buf, size_t len, struct window *w = wl->window; struct window_pane *wp; struct layout_cell *lc; + struct layout_geometry lg; struct environ *env; FILE *f; char *cmd, *cause = NULL; char path[] = _PATH_TMP "tmux.XXXXXXXX"; const char *editor; int fd; - u_int px, py, sx, sy; editor = options_get_string(global_options, "editor"); fd = mkstemp(path); @@ -662,12 +662,12 @@ spawn_editor(struct client *c, const char *buf, size_t len, es->cb = cb; es->arg = arg; - sx = w->sx * 9 / 10; - sy = w->sy * 9 / 10; - px = w->sx / 2 - sx / 2; - py = w->sy / 2 - sy / 2; + lg.sx = w->sx * 9 / 10; + lg.sy = w->sy * 9 / 10; + lg.xoff = w->sx / 2 - lg.sx / 2; + lg.yoff = w->sy / 2 - lg.sy / 2; window_push_zoom(w, 1, 0); - lc = layout_floating_pane(w, NULL, sx, sy, px, py); + lc = layout_floating_pane(w, NULL, &lg); if (lc == NULL) { spawn_editor_free(es); return (NULL); diff --git a/tmux.1 b/tmux.1 index 758119aa8..b4a78dbd4 100644 --- a/tmux.1 +++ b/tmux.1 @@ -365,13 +365,13 @@ Toggle zoom state of the current pane. .It Tab Choose a new window and session by fuzzy matching. .It { -Move floating pane to top-left corner. +Swap the current pane with the previous pane. .It } -Move floating pane to top-right corner. -.It M-{ -Move floating pane to bottom-left corner. -.It M-} -Move floating pane to bottom-right corner. +Swap the current pane with the next pane. +.It g 1, 2, 3, 4 +.It g Up, Down, Left, Right +Move floating pane to corners or edges. +Meta resizes the pane as well. .It \[ti] Show previous messages from .Nm , @@ -7959,6 +7959,7 @@ Both may be a row or column number, or one of the following special values: .It Li "R" Ta Fl x Ta "The right side of the terminal" .It Li "P" Ta "Both" Ta "The bottom left of the pane" .It Li "M" Ta "Both" Ta "The mouse position" +.It Li "L" Ta "Both" Ta "The position of the last menu" .It Li "W" Ta "Both" Ta "The window position on the status line" .It Li "S" Ta Fl y Ta "The line above or below the status line" .El @@ -7969,6 +7970,8 @@ Or a format, which is expanded including the following additional variables: .It Li "popup_centre_x" Ta "Centered in the client" .It Li "popup_centre_y" Ta "Centered in the client" .It Li "popup_height" Ta "Height of menu or popup" +.It Li "popup_last_x" Ta "Left of the last menu" +.It Li "popup_last_y" Ta "Bottom of the last menu" .It Li "popup_mouse_bottom" Ta "Bottom of at the mouse" .It Li "popup_mouse_centre_x" Ta "Horizontal centre at the mouse" .It Li "popup_mouse_centre_y" Ta "Vertical centre at the mouse" diff --git a/tmux.h b/tmux.h index a7c22b581..8739b47fa 100644 --- a/tmux.h +++ b/tmux.h @@ -1508,32 +1508,31 @@ enum layout_type { LAYOUT_WINDOWPANE }; +/* Layout cell sizes and position. */ +struct layout_geometry { + u_int sx; + u_int sy; + int xoff; + int yoff; +}; + /* Layout cells queue. */ TAILQ_HEAD(layout_cells, layout_cell); /* Layout cell. */ struct layout_cell { - enum layout_type type; + enum layout_type type; + int flags; #define LAYOUT_CELL_FLOATING 0x1 - int flags; - struct layout_cell *parent; + struct layout_cell *parent; - u_int sx; - u_int sy; + struct layout_geometry g; + struct layout_geometry fg; /* saved floating pane */ - int xoff; - int yoff; - - u_int saved_sx; - u_int saved_sy; - - int saved_xoff; - int saved_yoff; - - struct window_pane *wp; - struct layout_cells cells; + struct window_pane *wp; + struct layout_cells cells; TAILQ_ENTRY(layout_cell) entry; }; @@ -2313,6 +2312,9 @@ struct client { void *overlay_data; struct event overlay_timer; + u_int menu_last_px; + u_int menu_last_py; + struct client_files files; u_int source_file_depth; @@ -3786,7 +3788,7 @@ void layout_destroy_cell(struct window *, struct layout_cell *, void layout_resize_layout(struct window *, struct layout_cell *, enum layout_type, int, int); struct layout_cell *layout_search_by_border(struct layout_cell *, u_int, u_int); -void layout_set_size(struct layout_cell *, u_int, u_int, int, int); +void layout_set_size(struct layout_cell *, u_int, u_int, int, int); void layout_make_leaf(struct layout_cell *, struct window_pane *); void layout_make_node(struct layout_cell *, enum layout_type); void layout_fix_zindexes(struct window *, struct layout_cell *); @@ -3820,7 +3822,7 @@ struct layout_cell *layout_replace_with_node(struct window *, struct layout_cell *layout_split_pane(struct window_pane *, enum layout_type, int, int); struct layout_cell *layout_floating_pane(struct window *, struct window_pane *, - u_int, u_int, int, int); + struct layout_geometry *); void layout_close_pane(struct window_pane *); int layout_spread_cell(struct window *, struct layout_cell *); void layout_spread_out(struct window_pane *); @@ -3828,10 +3830,10 @@ struct layout_cell *layout_get_tiled_cell(struct cmdq_item *, struct args *, struct window *, struct window_pane *, int, char **); struct layout_cell *layout_get_floating_cell(struct cmdq_item *, struct args *, enum pane_lines, struct window *, struct window_pane *, - char **cause); + char **); int layout_floating_args_parse(struct cmdq_item *, struct args *, - enum pane_lines, struct window *, u_int *, u_int *, int *, - int *, char **); + enum pane_lines, struct window *, struct layout_geometry *, + char **); int layout_remove_tile(struct window *, struct layout_cell *); int layout_insert_tile(struct window *, struct layout_cell *); diff --git a/window.c b/window.c index 91c72bfb2..28457da05 100644 --- a/window.c +++ b/window.c @@ -368,6 +368,8 @@ window_create(u_int sx, u_int sy, u_int xpixel, u_int ypixel) w->ypixel = ypixel; w->options = options_create(global_w_options); + w->sb = options_get_number(w->options, "pane-scrollbars"); + w->sb_pos = options_get_number(w->options, "pane-scrollbars-position"); w->references = 0; TAILQ_INIT(&w->winlinks);