Merge branch 'obsd-master'

pull/2453/head
Thomas Adam 2020-11-03 10:01:21 +00:00
commit dac285c92a
2 changed files with 190 additions and 86 deletions

View File

@ -61,7 +61,7 @@ const struct cmd_entry cmd_display_popup_entry = {
.exec = cmd_display_popup_exec .exec = cmd_display_popup_exec
}; };
static void static int
cmd_display_menu_get_position(struct client *tc, struct cmdq_item *item, cmd_display_menu_get_position(struct client *tc, struct cmdq_item *item,
struct args *args, u_int *px, u_int *py, u_int w, u_int h) struct args *args, u_int *px, u_int *py, u_int w, u_int h)
{ {
@ -71,44 +71,46 @@ cmd_display_menu_get_position(struct client *tc, struct cmdq_item *item,
struct session *s = tc->session; struct session *s = tc->session;
struct winlink *wl = target->wl; struct winlink *wl = target->wl;
struct window_pane *wp = target->wp; struct window_pane *wp = target->wp;
struct style_ranges *ranges; struct style_ranges *ranges = NULL;
struct style_range *sr; struct style_range *sr = NULL;
const char *xp, *yp; const char *xp, *yp;
u_int line, ox, oy, sx, sy, lines; char *p;
int top;
u_int line, ox, oy, sx, sy, lines, position;
long n;
struct format_tree *ft;
lines = status_line_size(tc); /*
for (line = 0; line < lines; line++) { * Work out the position from the -x and -y arguments. This is the
ranges = &tc->status.entries[line].ranges; * bottom-left position.
TAILQ_FOREACH(sr, ranges, entry) { */
if (sr->type == STYLE_RANGE_WINDOW)
break; /* If the popup is too big, stop now. */
} if (w > tty->sx || h > tty->sy)
if (sr != NULL) return (0);
break;
/* Create format with mouse position if any. */
ft = format_create_from_target(item);
if (event->m.valid) {
format_add(ft, "popup_mouse_x", "%u", event->m.x);
format_add(ft, "popup_mouse_y", "%u", event->m.y);
} }
if (line == lines)
ranges = &tc->status.entries[0].ranges;
xp = args_get(args, 'x'); /*
if (xp == NULL || strcmp(xp, "C") == 0) * If there are any status lines, add this window position and the
*px = (tty->sx - 1) / 2 - w / 2; * status line position.
else if (strcmp(xp, "R") == 0) */
*px = tty->sx - 1; top = status_at_line(tc);
else if (strcmp(xp, "P") == 0) { if (top != -1) {
tty_window_offset(&tc->tty, &ox, &oy, &sx, &sy); lines = status_line_size(tc);
if (wp->xoff >= ox) if (top == 0)
*px = wp->xoff - ox; top = lines;
else else
*px = 0; top = 0;
} else if (strcmp(xp, "M") == 0) { position = options_get_number(s->options, "status-position");
if (event->m.valid && event->m.x > w / 2)
*px = event->m.x - w / 2; for (line = 0; line < lines; line++) {
else ranges = &tc->status.entries[line].ranges;
*px = 0;
} else if (strcmp(xp, "W") == 0) {
if (status_at_line(tc) == -1)
*px = 0;
else {
TAILQ_FOREACH(sr, ranges, entry) { TAILQ_FOREACH(sr, ranges, entry) {
if (sr->type != STYLE_RANGE_WINDOW) if (sr->type != STYLE_RANGE_WINDOW)
continue; continue;
@ -116,61 +118,137 @@ cmd_display_menu_get_position(struct client *tc, struct cmdq_item *item,
break; break;
} }
if (sr != NULL) if (sr != NULL)
*px = sr->start; break;
else }
*px = 0; if (line == lines)
ranges = &tc->status.entries[0].ranges;
if (sr != NULL) {
format_add(ft, "popup_window_status_line_x", "%u",
sr->start);
if (position == 0) {
format_add(ft, "popup_window_status_line_y",
"%u", line + 1 + h);
} else {
format_add(ft, "popup_window_status_line_y",
"%u", tty->sy - lines + line);
}
}
if (position == 0)
format_add(ft, "popup_status_line_y", "%u", lines + h);
else {
format_add(ft, "popup_status_line_y", "%u",
tty->sy - lines);
} }
} else } else
*px = strtoul(xp, NULL, 10); top = 0;
if ((*px) + w >= tty->sx)
*px = tty->sx - w;
/* Popup width and height. */
format_add(ft, "popup_width", "%u", w);
format_add(ft, "popup_height", "%u", h);
/* Position so popup is in the centre. */
n = (long)(tty->sx - 1) / 2 - w / 2;
if (n < 0)
format_add(ft, "popup_centre_x", "%u", 0);
else
format_add(ft, "popup_centre_x", "%ld", n);
n = (tty->sy - 1) / 2 + h / 2;
if (n + h >= tty->sy)
format_add(ft, "popup_centre_y", "%u", tty->sy - h);
else
format_add(ft, "popup_centre_y", "%ld", n);
/* Position of popup relative to mouse. */
if (event->m.valid) {
n = (long)event->m.x - w / 2;
if (n < 0)
format_add(ft, "popup_mouse_centre_x", "%u", 0);
else
format_add(ft, "popup_mouse_centre_x", "%ld", n);
n = event->m.y - h / 2;
if (n + h >= tty->sy) {
format_add(ft, "popup_mouse_centre_y", "%u",
tty->sy - h);
} else
format_add(ft, "popup_mouse_centre_y", "%ld", n);
n = (long)event->m.y + h;
if (n + h >= tty->sy)
format_add(ft, "popup_mouse_top", "%u", tty->sy - h);
else
format_add(ft, "popup_mouse_top", "%ld", n);
n = event->m.y - h;
if (n < 0)
format_add(ft, "popup_mouse_bottom", "%u", 0);
else
format_add(ft, "popup_mouse_bottom", "%ld", n);
}
/* Position in pane. */
tty_window_offset(&tc->tty, &ox, &oy, &sx, &sy);
n = top + wp->yoff - oy + h;
if (n >= tty->sy)
format_add(ft, "popup_pane_top", "%u", tty->sy - h);
else
format_add(ft, "popup_pane_top", "%ld", n);
format_add(ft, "popup_pane_bottom", "%u", top + wp->yoff + wp->sy - oy);
format_add(ft, "popup_pane_left", "%u", wp->xoff - ox);
n = (long)wp->xoff + wp->sx - ox - w;
if (n < 0)
format_add(ft, "popup_pane_right", "%u", 0);
else
format_add(ft, "popup_pane_right", "%ld", n);
/* Expand horizontal position. */
xp = args_get(args, 'x');
if (xp == NULL || strcmp(xp, "C") == 0)
xp = "#{popup_centre_x}";
else if (strcmp(xp, "R") == 0)
xp = "#{popup_right}";
else if (strcmp(xp, "P") == 0)
xp = "#{popup_pane_left}";
else if (strcmp(xp, "M") == 0)
xp = "#{popup_mouse_centre_x}";
else if (strcmp(xp, "W") == 0)
xp = "#{popup_window_status_line_x}";
p = format_expand(ft, xp);
n = strtol(p, NULL, 10);
if (n + w >= tty->sx)
n = tty->sx - w;
else if (n < 0)
n = 0;
*px = n;
log_debug("%s: -x: %s = %s = %u", __func__, xp, p, *px);
free(p);
/* Expand vertical position */
yp = args_get(args, 'y'); yp = args_get(args, 'y');
if (yp == NULL || strcmp(yp, "C") == 0) if (yp == NULL || strcmp(yp, "C") == 0)
*py = (tty->sy - 1) / 2 + h / 2; yp = "#{popup_centre_y}";
else if (strcmp(yp, "P") == 0) { else if (strcmp(yp, "P") == 0)
tty_window_offset(&tc->tty, &ox, &oy, &sx, &sy); yp = "#{popup_pane_bottom}";
if (wp->yoff + wp->sy >= oy) else if (strcmp(yp, "M") == 0)
*py = wp->yoff + wp->sy - oy; yp = "#{popup_mouse_top}";
else else if (strcmp(yp, "S") == 0)
*py = 0; yp = "#{popup_status_line_y}";
} else if (strcmp(yp, "M") == 0) { else if (strcmp(yp, "W") == 0)
if (event->m.valid) yp = "#{popup_window_status_line_y}";
*py = event->m.y + h; p = format_expand(ft, yp);
else n = strtol(p, NULL, 10);
*py = 0; if (n < h)
} else if (strcmp(yp, "S") == 0) { n = 0;
if (options_get_number(s->options, "status-position") == 0) {
if (lines != 0)
*py = lines + h;
else
*py = 0;
} else {
if (lines != 0)
*py = tty->sy - lines;
else
*py = tty->sy;
}
} else if (strcmp(yp, "W") == 0) {
if (options_get_number(s->options, "status-position") == 0) {
if (lines != 0)
*py = line + 1 + h;
else
*py = 0;
} else {
if (lines != 0)
*py = tty->sy - lines + line;
else
*py = tty->sy;
}
} else
*py = strtoul(yp, NULL, 10);
if (*py < h)
*py = 0;
else else
*py -= h; n -= h;
if ((*py) + h >= tty->sy) if (n + h >= tty->sy)
*py = tty->sy - h; n = tty->sy - h;
else if (n < 0)
n = 0;
*py = n;
log_debug("%s: -y: %s = %s = %u", __func__, yp, p, *py);
free(p);
return (1);
} }
static enum cmd_retval static enum cmd_retval
@ -226,8 +304,11 @@ cmd_display_menu_exec(struct cmd *self, struct cmdq_item *item)
menu_free(menu); menu_free(menu);
return (CMD_RETURN_NORMAL); return (CMD_RETURN_NORMAL);
} }
cmd_display_menu_get_position(tc, item, args, &px, &py, menu->width + 4, if (!cmd_display_menu_get_position(tc, item, args, &px, &py,
menu->count + 2); menu->width + 4, menu->count + 2)) {
menu_free(menu);
return (CMD_RETURN_NORMAL);
}
if (args_has(args, 'O')) if (args_has(args, 'O'))
flags |= MENU_STAYOPEN; flags |= MENU_STAYOPEN;
@ -296,7 +377,8 @@ cmd_display_popup_exec(struct cmd *self, struct cmdq_item *item)
w = tty->sx - 1; w = tty->sx - 1;
if (h > tty->sy - 1) if (h > tty->sy - 1)
h = tty->sy - 1; h = tty->sy - 1;
cmd_display_menu_get_position(tc, item, args, &px, &py, w, h); if (!cmd_display_menu_get_position(tc, item, args, &px, &py, w, h))
return (CMD_RETURN_NORMAL);
value = args_get(args, 'd'); value = args_get(args, 'd');
if (value != NULL) if (value != NULL)

22
tmux.1
View File

@ -5388,6 +5388,28 @@ Both may be a row or column number, or one of the following special values:
.It Li "S" Ta Fl y Ta "The line above or below the status line" .It Li "S" Ta Fl y Ta "The line above or below the status line"
.El .El
.Pp .Pp
Or a format, which is expanded including the following additional variables:
.Bl -column "XXXXXXXXXXXXXXXXXXXXXXXXXX" -offset indent
.It Sy "Variable name" Ta Sy "Replaced with"
.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_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"
.It Li "popup_mouse_top" Ta "Top at the mouse"
.It Li "popup_mouse_x" Ta "Mouse X position"
.It Li "popup_mouse_y" Ta "Mouse Y position"
.It Li "popup_pane_bottom" Ta "Bottom of the pane"
.It Li "popup_pane_left" Ta "Left of the pane"
.It Li "popup_pane_right" Ta "Right of the pane"
.It Li "popup_pane_top" Ta "Top of the pane"
.It Li "popup_status_line_y" Ta "Above or below the status line"
.It Li "popup_width" Ta "Width of menu or popup"
.It Li "popup_window_status_line_x" Ta "At the window position in status line"
.It Li "popup_window_status_line_y" Ta "At the status line showing the window"
.El
.Pp
Each menu consists of items followed by a key shortcut shown in brackets. Each menu consists of items followed by a key shortcut shown in brackets.
If the menu is too large to fit on the terminal, it is not displayed. If the menu is too large to fit on the terminal, it is not displayed.
Pressing the key shortcut chooses the corresponding item. Pressing the key shortcut chooses the corresponding item.