summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorThomas Adam <thomas@xteddy.org>2023-08-17 18:01:09 +0100
committerThomas Adam <thomas@xteddy.org>2023-08-17 18:01:09 +0100
commite3a8b8434cf656164d74ae115ebccd432144ed2c (patch)
tree45b6061279b4b6155e0b6dd921b42a9341d3e98d
parent3d93b0c52ecd6d5b321fef777d49c360c9fbe069 (diff)
parent8636848e6348bb0e38cd6aaaadbe61e15181bc8f (diff)
Merge branch 'obsd-master'
-rw-r--r--cmd.c12
-rw-r--r--format-draw.c50
-rw-r--r--format.c72
-rw-r--r--server-client.c37
-rw-r--r--style.c64
-rw-r--r--tmux.146
-rw-r--r--tmux.h7
7 files changed, 258 insertions, 30 deletions
diff --git a/cmd.c b/cmd.c
index ed4f9940..32c00b4e 100644
--- a/cmd.c
+++ b/cmd.c
@@ -812,10 +812,14 @@ cmd_mouse_pane(struct mouse_event *m, struct session **sp,
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;
diff --git a/format-draw.c b/format-draw.c
index 3ea1f52f..a42dfe1d 100644
--- a/format-draw.c
+++ b/format-draw.c
@@ -33,6 +33,7 @@ struct format_range {
enum style_range_type type;
u_int argument;
+ char string[16];
TAILQ_ENTRY(format_range) entry;
};
@@ -44,9 +45,18 @@ format_is_type(struct format_range *fr, struct style *sy)
{
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);
}
@@ -942,6 +952,8 @@ format_draw(struct screen_write_ctx *octx, const struct grid_cell *base,
fr->type = sy.range_type;
fr->argument = sy.range_argument;
+ strlcpy(fr->string, sy.range_string,
+ sizeof fr->string);
}
}
@@ -1013,13 +1025,39 @@ format_draw(struct screen_write_ctx *octx, const struct grid_cell *base,
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);
}
diff --git a/format.c b/format.c
index b20e90a8..1362486e 100644
--- a/format.c
+++ b/format.c
@@ -1191,6 +1191,72 @@ format_cb_mouse_line(struct format_tree *ft)
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)
@@ -2848,6 +2914,12 @@ static const struct format_table_entry format_table[] = {
{ "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
},
diff --git a/server-client.c b/server-client.c
index 874a3522..b2c355c7 100644
--- a/server-client.c
+++ b/server-client.c
@@ -560,9 +560,9 @@ static key_code
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;
@@ -668,6 +668,7 @@ have_event:
/* Save the session. */
m->s = s->id;
m->w = -1;
+ m->wp = -1;
m->ignore = ignore;
/* Is this on the status line? */
@@ -684,18 +685,42 @@ have_event:
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;
}
diff --git a/style.c b/style.c
index 3d9d317d..0d7ebe86 100644
--- a/style.c
+++ b/style.c
@@ -37,11 +37,18 @@ static struct style style_default = {
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
@@ -104,32 +111,67 @@ style_parse(struct style *sy, const struct grid_cell *base, const char *in)
} 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;
@@ -222,9 +264,19 @@ style_tostring(struct style *sy)
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);
diff --git a/tmux.1 b/tmux.1
index 2adb56f6..97d28e60 100644
--- a/tmux.1
+++ b/tmux.1
@@ -5446,6 +5446,8 @@ The following variables are available, where appropriate:
.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"
@@ -5684,26 +5686,56 @@ Only one default may be pushed (each
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:
diff --git a/tmux.h b/tmux.h
index fd3e261a..88c5f953 100644
--- a/tmux.h
+++ b/tmux.h
@@ -799,11 +799,15 @@ enum style_range_type {
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 */
@@ -830,6 +834,7 @@ struct style {
enum style_range_type range_type;
u_int range_argument;
+ char range_string[16];
enum style_default_type default_type;
};