-/* $OpenBSD: cmd.c,v 1.174 2022/05/30 12:48:57 nicm Exp $ */
+/* $OpenBSD: cmd.c,v 1.175 2023/08/17 14:10:28 nicm Exp $ */
/*
* Copyright (c) 2007 Nicholas Marriott <nicholas.marriott@gmail.com>
if ((wl = cmd_mouse_window(m, sp)) == NULL)
return (NULL);
- if ((wp = window_pane_find_by_id(m->wp)) == NULL)
- return (NULL);
- if (!window_has_pane(wl->window, wp))
- return (NULL);
+ if (m->wp == -1)
+ wp = wl->window->active;
+ else {
+ if ((wp = window_pane_find_by_id(m->wp)) == NULL)
+ return (NULL);
+ if (!window_has_pane(wl->window, wp))
+ return (NULL);
+ }
if (wlp != NULL)
*wlp = wl;
-/* $OpenBSD: format-draw.c,v 1.27 2023/08/07 10:04:29 nicm Exp $ */
+/* $OpenBSD: format-draw.c,v 1.28 2023/08/17 14:10:28 nicm Exp $ */
/*
* Copyright (c) 2019 Nicholas Marriott <nicholas.marriott@gmail.com>
enum style_range_type type;
u_int argument;
+ char string[16];
TAILQ_ENTRY(format_range) entry;
};
{
if (fr->type != sy->range_type)
return (0);
- if (fr->type == STYLE_RANGE_WINDOW &&
- fr->argument != sy->range_argument)
- return (0);
+ switch (fr->type) {
+ case STYLE_RANGE_NONE:
+ case STYLE_RANGE_LEFT:
+ case STYLE_RANGE_RIGHT:
+ return (1);
+ case STYLE_RANGE_PANE:
+ case STYLE_RANGE_WINDOW:
+ case STYLE_RANGE_SESSION:
+ return (fr->argument == sy->range_argument);
+ case STYLE_RANGE_USER:
+ return (strcmp(fr->string, sy->range_string) == 0);
+ }
return (1);
}
fr->type = sy.range_type;
fr->argument = sy.range_argument;
+ strlcpy(fr->string, sy.range_string,
+ sizeof fr->string);
}
}
sr = xcalloc(1, sizeof *sr);
sr->type = fr->type;
sr->argument = fr->argument;
+ strlcpy(sr->string, fr->string, sizeof sr->string);
sr->start = fr->start;
sr->end = fr->end;
TAILQ_INSERT_TAIL(srs, sr, entry);
- log_debug("%s: range %d|%u at %u-%u", __func__, sr->type,
- sr->argument, sr->start, sr->end);
-
+ switch (sr->type) {
+ case STYLE_RANGE_NONE:
+ break;
+ case STYLE_RANGE_LEFT:
+ log_debug("%s: range left at %u-%u", __func__,
+ sr->start, sr->end);
+ break;
+ case STYLE_RANGE_RIGHT:
+ log_debug("%s: range right at %u-%u", __func__,
+ sr->start, sr->end);
+ break;
+ case STYLE_RANGE_PANE:
+ log_debug("%s: range pane|%%%u at %u-%u", __func__,
+ sr->argument, sr->start, sr->end);
+ break;
+ case STYLE_RANGE_WINDOW:
+ log_debug("%s: range window|%u at %u-%u", __func__,
+ sr->argument, sr->start, sr->end);
+ break;
+ case STYLE_RANGE_SESSION:
+ log_debug("%s: range session|$%u at %u-%u", __func__,
+ sr->argument, sr->start, sr->end);
+ break;
+ case STYLE_RANGE_USER:
+ log_debug("%s: range user|%u at %u-%u", __func__,
+ sr->argument, sr->start, sr->end);
+ break;
+ }
format_free_range(&frs, fr);
}
-/* $OpenBSD: format.c,v 1.316 2023/07/10 09:24:53 nicm Exp $ */
+/* $OpenBSD: format.c,v 1.317 2023/08/17 14:10:28 nicm Exp $ */
/*
* Copyright (c) 2011 Nicholas Marriott <nicholas.marriott@gmail.com>
return (format_grid_line(gd, gd->hsize + y));
}
+/* Callback for mouse_status_line. */
+static void *
+format_cb_mouse_status_line(struct format_tree *ft)
+{
+ char *value;
+ u_int y;
+
+ if (!ft->m.valid)
+ return (NULL);
+ if (ft->c == NULL || (~ft->c->tty.flags & TTY_STARTED))
+ return (NULL);
+
+ if (ft->m.statusat == 0 && ft->m.y < ft->m.statuslines) {
+ y = ft->m.y;
+ } else if (ft->m.statusat > 0 && ft->m.y >= (u_int)ft->m.statusat) {
+ y = ft->m.y - ft->m.statusat;
+ } else
+ return (NULL);
+ xasprintf(&value, "%u", y);
+ return (value);
+
+}
+
+/* Callback for mouse_status_range. */
+static void *
+format_cb_mouse_status_range(struct format_tree *ft)
+{
+ struct style_range *sr;
+ u_int x, y;
+
+ if (!ft->m.valid)
+ return (NULL);
+ if (ft->c == NULL || (~ft->c->tty.flags & TTY_STARTED))
+ return (NULL);
+
+ if (ft->m.statusat == 0 && ft->m.y < ft->m.statuslines) {
+ x = ft->m.x;
+ y = ft->m.y;
+ } else if (ft->m.statusat > 0 && ft->m.y >= (u_int)ft->m.statusat) {
+ x = ft->m.x;
+ y = ft->m.y - ft->m.statusat;
+ } else
+ return (NULL);
+
+ sr = status_get_range(ft->c, x, y);
+ if (sr == NULL)
+ return (NULL);
+ switch (sr->type) {
+ case STYLE_RANGE_NONE:
+ return (NULL);
+ case STYLE_RANGE_LEFT:
+ return (xstrdup("left"));
+ case STYLE_RANGE_RIGHT:
+ return (xstrdup("right"));
+ case STYLE_RANGE_PANE:
+ return (xstrdup("pane"));
+ case STYLE_RANGE_WINDOW:
+ return (xstrdup("window"));
+ case STYLE_RANGE_SESSION:
+ return (xstrdup("session"));
+ case STYLE_RANGE_USER:
+ return (xstrdup(sr->string));
+ }
+ return (NULL);
+}
+
/* Callback for alternate_on. */
static void *
format_cb_alternate_on(struct format_tree *ft)
{ "mouse_standard_flag", FORMAT_TABLE_STRING,
format_cb_mouse_standard_flag
},
+ { "mouse_status_line", FORMAT_TABLE_STRING,
+ format_cb_mouse_status_line
+ },
+ { "mouse_status_range", FORMAT_TABLE_STRING,
+ format_cb_mouse_status_range
+ },
{ "mouse_utf8_flag", FORMAT_TABLE_STRING,
format_cb_mouse_utf8_flag
},
-/* $OpenBSD: server-client.c,v 1.400 2023/02/05 21:15:32 nicm Exp $ */
+/* $OpenBSD: server-client.c,v 1.401 2023/08/17 14:10:28 nicm Exp $ */
/*
* Copyright (c) 2009 Nicholas Marriott <nicholas.marriott@gmail.com>
server_client_check_mouse(struct client *c, struct key_event *event)
{
struct mouse_event *m = &event->m;
- struct session *s = c->session;
- struct winlink *wl;
- struct window_pane *wp;
+ struct session *s = c->session, *fs;
+ struct winlink *fwl;
+ struct window_pane *wp, *fwp;
u_int x, y, b, sx, sy, px, py;
int ignore = 0;
key_code key;
/* Save the session. */
m->s = s->id;
m->w = -1;
+ m->wp = -1;
m->ignore = ignore;
/* Is this on the status line? */
case STYLE_RANGE_NONE:
return (KEYC_UNKNOWN);
case STYLE_RANGE_LEFT:
+ log_debug("mouse range: left");
where = STATUS_LEFT;
break;
case STYLE_RANGE_RIGHT:
+ log_debug("mouse range: right");
where = STATUS_RIGHT;
break;
+ case STYLE_RANGE_PANE:
+ fwp = window_pane_find_by_id(sr->argument);
+ if (fwp == NULL)
+ return (KEYC_UNKNOWN);
+ m->wp = sr->argument;
+
+ log_debug("mouse range: pane %%%u", m->wp);
+ where = STATUS;
+ break;
case STYLE_RANGE_WINDOW:
- wl = winlink_find_by_index(&s->windows,
+ fwl = winlink_find_by_index(&s->windows,
sr->argument);
- if (wl == NULL)
+ if (fwl == NULL)
return (KEYC_UNKNOWN);
- m->w = wl->window->id;
+ m->w = fwl->window->id;
+ log_debug("mouse range: window @%u", m->w);
+ where = STATUS;
+ break;
+ case STYLE_RANGE_SESSION:
+ fs = session_find_by_id(sr->argument);
+ if (fs == NULL)
+ return (KEYC_UNKNOWN);
+ m->s = sr->argument;
+
+ log_debug("mouse range: session $%u", m->s);
+ where = STATUS;
+ break;
+ case STYLE_RANGE_USER:
where = STATUS;
break;
}
-/* $OpenBSD: style.c,v 1.32 2023/06/26 07:17:40 nicm Exp $ */
+/* $OpenBSD: style.c,v 1.33 2023/08/17 14:10:28 nicm Exp $ */
/*
* Copyright (c) 2007 Nicholas Marriott <nicholas.marriott@gmail.com>
STYLE_ALIGN_DEFAULT,
STYLE_LIST_OFF,
- STYLE_RANGE_NONE, 0,
+ STYLE_RANGE_NONE, 0, "",
STYLE_DEFAULT_BASE
};
+/* Set range string. */
+static void
+style_set_range_string(struct style *sy, const char *s)
+{
+ strlcpy(sy->range_string, s, sizeof sy->range_string);
+}
+
/*
* Parse an embedded style of the form "fg=colour,bg=colour,bright,...". Note
* that this adds onto the given style, so it must have been initialized
} else if (strcasecmp(tmp, "norange") == 0) {
sy->range_type = style_default.range_type;
sy->range_argument = style_default.range_type;
+ strlcpy(sy->range_string, style_default.range_string,
+ sizeof sy->range_string);
} else if (end > 6 && strncasecmp(tmp, "range=", 6) == 0) {
found = strchr(tmp + 6, '|');
if (found != NULL) {
*found++ = '\0';
if (*found == '\0')
goto error;
- for (cp = found; *cp != '\0'; cp++) {
- if (!isdigit((u_char)*cp))
- goto error;
- }
}
if (strcasecmp(tmp + 6, "left") == 0) {
if (found != NULL)
goto error;
sy->range_type = STYLE_RANGE_LEFT;
sy->range_argument = 0;
+ style_set_range_string(sy, "");
} else if (strcasecmp(tmp + 6, "right") == 0) {
if (found != NULL)
goto error;
sy->range_type = STYLE_RANGE_RIGHT;
sy->range_argument = 0;
+ style_set_range_string(sy, "");
+ } else if (strcasecmp(tmp + 6, "pane") == 0) {
+ if (found == NULL)
+ goto error;
+ if (*found != '%' || found[1] == '\0')
+ goto error;
+ for (cp = found + 1; *cp != '\0'; cp++) {
+ if (!isdigit((u_char)*cp))
+ goto error;
+ }
+ sy->range_type = STYLE_RANGE_PANE;
+ sy->range_argument = atoi(found + 1);
+ style_set_range_string(sy, "");
} else if (strcasecmp(tmp + 6, "window") == 0) {
if (found == NULL)
goto error;
+ for (cp = found; *cp != '\0'; cp++) {
+ if (!isdigit((u_char)*cp))
+ goto error;
+ }
sy->range_type = STYLE_RANGE_WINDOW;
sy->range_argument = atoi(found);
+ style_set_range_string(sy, "");
+ } else if (strcasecmp(tmp + 6, "session") == 0) {
+ if (found == NULL)
+ goto error;
+ if (*found != '$' || found[1] == '\0')
+ goto error;
+ for (cp = found + 1; *cp != '\0'; cp++) {
+ if (!isdigit((u_char)*cp))
+ goto error;
+ }
+ sy->range_type = STYLE_RANGE_SESSION;
+ sy->range_argument = atoi(found + 1);
+ style_set_range_string(sy, "");
+ } else if (strcasecmp(tmp + 6, "user") == 0) {
+ if (found == NULL)
+ goto error;
+ sy->range_type = STYLE_RANGE_USER;
+ sy->range_argument = 0;
+ style_set_range_string(sy, found);
}
} else if (strcasecmp(tmp, "noalign") == 0)
sy->align = style_default.align;
tmp = "left";
else if (sy->range_type == STYLE_RANGE_RIGHT)
tmp = "right";
- else if (sy->range_type == STYLE_RANGE_WINDOW) {
+ else if (sy->range_type == STYLE_RANGE_PANE) {
+ snprintf(b, sizeof b, "pane|%%%u", sy->range_argument);
+ tmp = b;
+ } else if (sy->range_type == STYLE_RANGE_WINDOW) {
snprintf(b, sizeof b, "window|%u", sy->range_argument);
tmp = b;
+ } else if (sy->range_type == STYLE_RANGE_SESSION) {
+ snprintf(b, sizeof b, "session|$%u",
+ sy->range_argument);
+ tmp = b;
+ } else if (sy->range_type == STYLE_RANGE_USER) {
+ snprintf(b, sizeof b, "user|%s", sy->range_string);
+ tmp = b;
}
off += xsnprintf(s + off, sizeof s - off, "%srange=%s", comma,
tmp);
-.\" $OpenBSD: tmux.1,v 1.927 2023/08/15 07:01:47 nicm Exp $
+.\" $OpenBSD: tmux.1,v 1.928 2023/08/17 14:10:28 nicm Exp $
.\"
.\" Copyright (c) 2007 Nicholas Marriott <nicholas.marriott@gmail.com>
.\"
.\" IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
.\" OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
.\"
-.Dd $Mdocdate: August 15 2023 $
+.Dd $Mdocdate: August 17 2023 $
.Dt TMUX 1
.Os
.Sh NAME
.It Li "mouse_line" Ta "" Ta "Line under mouse, if any"
.It Li "mouse_sgr_flag" Ta "" Ta "Pane mouse SGR flag"
.It Li "mouse_standard_flag" Ta "" Ta "Pane mouse standard flag"
+.It Li "mouse_status_line" Ta "" Ta "Status line on which mouse event took place"
+.It Li "mouse_status_range" Ta "" Ta "Range type or argument of mouse event on status line"
.It Li "mouse_utf8_flag" Ta "" Ta "Pane mouse UTF-8 flag"
.It Li "mouse_word" Ta "" Ta "Word under mouse, if any"
.It Li "mouse_x" Ta "" Ta "Mouse X position, if any"
replaces the previous saved default).
.It Xo Ic range=left ,
.Ic range=right ,
+.Ic range=session|X ,
.Ic range=window|X ,
+.Ic range=pane|X ,
+.Ic range=user|X ,
.Ic norange
.Xc
-Mark a range in the
+Mark a range for mouse events in the
.Ic status-format
option.
+When a mouse event occurs in the
.Ic range=left
-and
+or
.Ic range=right
-are the text used for the
+range, the
.Ql StatusLeft
and
.Ql StatusRight
-mouse keys.
+key bindings are triggered.
+.Pp
+.Ic range=session|X ,
.Ic range=window|X
-is the range for a window passed to the
+and
+.Ic range=pane|X
+are ranges for a session, window or pane.
+These trigger the
.Ql Status
-mouse key, where
+mouse key with the target session, window or pane given by the
+.Ql X
+argument.
+.Ql X
+is a session ID, window index in the current session or a pane ID.
+For these, the
+.Ic mouse_status_range
+format variable will be set to
+.Ql session ,
+.Ql window
+or
+.Ql pane .
+.Pp
+.Ic range=user|X
+is a user-defined range; it triggers the
+.Ql Status
+mouse key.
+The argument
+.Ql X
+will be available in the
+.Ic mouse_status_range
+format variable.
.Ql X
-is a window index.
+must be at most 15 bytes in length.
.El
.Pp
Examples are:
-/* $OpenBSD: tmux.h,v 1.1205 2023/08/15 07:01:47 nicm Exp $ */
+/* $OpenBSD: tmux.h,v 1.1206 2023/08/17 14:10:28 nicm Exp $ */
/*
* Copyright (c) 2007 Nicholas Marriott <nicholas.marriott@gmail.com>
STYLE_RANGE_NONE,
STYLE_RANGE_LEFT,
STYLE_RANGE_RIGHT,
- STYLE_RANGE_WINDOW
+ STYLE_RANGE_PANE,
+ STYLE_RANGE_WINDOW,
+ STYLE_RANGE_SESSION,
+ STYLE_RANGE_USER
};
struct style_range {
enum style_range_type type;
u_int argument;
+ char string[16];
u_int start;
u_int end; /* not included */
enum style_range_type range_type;
u_int range_argument;
+ char range_string[16];
enum style_default_type default_type;
};