Merge branch 'obsd-master'

pull/2097/head^2
Thomas Adam 2020-03-12 14:01:29 +00:00
commit 6385bd1e08
6 changed files with 95 additions and 26 deletions

View File

@ -30,8 +30,8 @@ const struct cmd_entry cmd_copy_mode_entry = {
.name = "copy-mode", .name = "copy-mode",
.alias = NULL, .alias = NULL,
.args = { "Met:u", 0, 0 }, .args = { "eHMt:u", 0, 0 },
.usage = "[-Mu] " CMD_TARGET_PANE_USAGE, .usage = "[-eHMu] " CMD_TARGET_PANE_USAGE,
.target = { 't', CMD_FIND_PANE, 0 }, .target = { 't', CMD_FIND_PANE, 0 },

View File

@ -31,6 +31,7 @@
static enum cmd_retval cmd_run_shell_exec(struct cmd *, struct cmdq_item *); static enum cmd_retval cmd_run_shell_exec(struct cmd *, struct cmdq_item *);
static void cmd_run_shell_timer(int, short, void *);
static void cmd_run_shell_callback(struct job *); static void cmd_run_shell_callback(struct job *);
static void cmd_run_shell_free(void *); static void cmd_run_shell_free(void *);
static void cmd_run_shell_print(struct job *, const char *); static void cmd_run_shell_print(struct job *, const char *);
@ -39,8 +40,8 @@ const struct cmd_entry cmd_run_shell_entry = {
.name = "run-shell", .name = "run-shell",
.alias = "run", .alias = "run",
.args = { "bt:", 1, 1 }, .args = { "bd:t:", 0, 1 },
.usage = "[-b] " CMD_TARGET_PANE_USAGE " shell-command", .usage = "[-b] [-d delay] " CMD_TARGET_PANE_USAGE " [shell-command]",
.target = { 't', CMD_FIND_PANE, CMD_FIND_CANFAIL }, .target = { 't', CMD_FIND_PANE, CMD_FIND_CANFAIL },
@ -50,8 +51,11 @@ const struct cmd_entry cmd_run_shell_entry = {
struct cmd_run_shell_data { struct cmd_run_shell_data {
char *cmd; char *cmd;
char *cwd;
struct cmdq_item *item; struct cmdq_item *item;
struct session *s;
int wp_id; int wp_id;
struct event timer;
}; };
static void static void
@ -91,9 +95,14 @@ cmd_run_shell_exec(struct cmd *self, struct cmdq_item *item)
struct session *s = item->target.s; struct session *s = item->target.s;
struct winlink *wl = item->target.wl; struct winlink *wl = item->target.wl;
struct window_pane *wp = item->target.wp; struct window_pane *wp = item->target.wp;
const char *delay;
double d;
struct timeval tv;
char *end;
cdata = xcalloc(1, sizeof *cdata); cdata = xcalloc(1, sizeof *cdata);
cdata->cmd = format_single(item, args->argv[0], c, s, wl, wp); if (args->argc != 0)
cdata->cmd = format_single(item, args->argv[0], c, s, wl, wp);
if (args_has(args, 't') && wp != NULL) if (args_has(args, 't') && wp != NULL)
cdata->wp_id = wp->id; cdata->wp_id = wp->id;
@ -103,18 +112,48 @@ cmd_run_shell_exec(struct cmd *self, struct cmdq_item *item)
if (!args_has(args, 'b')) if (!args_has(args, 'b'))
cdata->item = item; cdata->item = item;
if (job_run(cdata->cmd, s, server_client_get_cwd(item->client, s), NULL, cdata->cwd = xstrdup(server_client_get_cwd(item->client, s));
cmd_run_shell_callback, cmd_run_shell_free, cdata, 0) == NULL) { cdata->s = s;
cmdq_error(item, "failed to run command: %s", cdata->cmd); session_add_ref(s, __func__);
free(cdata);
return (CMD_RETURN_ERROR); evtimer_set(&cdata->timer, cmd_run_shell_timer, cdata);
}
if ((delay = args_get(args, 'd')) != NULL) {
d = strtod(delay, &end);
if (*end != '\0') {
cmdq_error(item, "invalid delay time: %s", delay);
cmd_run_shell_free(cdata);
return (CMD_RETURN_ERROR);
}
timerclear(&tv);
tv.tv_sec = (time_t)d;
tv.tv_usec = (d - (double)tv.tv_sec) * 1000000U;
evtimer_add(&cdata->timer, &tv);
} else
cmd_run_shell_timer(-1, 0, cdata);
if (args_has(args, 'b')) if (args_has(args, 'b'))
return (CMD_RETURN_NORMAL); return (CMD_RETURN_NORMAL);
return (CMD_RETURN_WAIT); return (CMD_RETURN_WAIT);
} }
static void
cmd_run_shell_timer(__unused int fd, __unused short events, void* arg)
{
struct cmd_run_shell_data *cdata = arg;
if (cdata->cmd != NULL) {
if (job_run(cdata->cmd, cdata->s, cdata->cwd, NULL,
cmd_run_shell_callback, cmd_run_shell_free, cdata,
0) == NULL)
cmd_run_shell_free(cdata);
} else {
if (cdata->item != NULL)
cmdq_continue(cdata->item);
cmd_run_shell_free(cdata);
}
}
static void static void
cmd_run_shell_callback(struct job *job) cmd_run_shell_callback(struct job *job)
{ {
@ -163,6 +202,9 @@ cmd_run_shell_free(void *data)
{ {
struct cmd_run_shell_data *cdata = data; struct cmd_run_shell_data *cdata = data;
evtimer_del(&cdata->timer);
session_remove_ref(cdata->s, __func__);
free(cdata->cwd);
free(cdata->cmd); free(cdata->cmd);
free(cdata); free(cdata);
} }

View File

@ -417,7 +417,6 @@ server_client_check_mouse(struct client *c, struct key_event *event)
struct winlink *wl; struct winlink *wl;
struct window_pane *wp; struct window_pane *wp;
u_int x, y, b, sx, sy, px, py; u_int x, y, b, sx, sy, px, py;
int flag;
key_code key; key_code key;
struct timeval tv; struct timeval tv;
struct style_range *sr; struct style_range *sr;
@ -441,7 +440,11 @@ server_client_check_mouse(struct client *c, struct key_event *event)
m->x, m->y, m->lx, m->ly, c->tty.mouse_drag_flag); m->x, m->y, m->lx, m->ly, c->tty.mouse_drag_flag);
/* What type of event is this? */ /* What type of event is this? */
if ((m->sgr_type != ' ' && if (event->key == KEYC_DOUBLECLICK) {
type = DOUBLE;
x = m->x, y = m->y, b = m->b;
log_debug("double-click at %u,%u", x, y);
} else if ((m->sgr_type != ' ' &&
MOUSE_DRAG(m->sgr_b) && MOUSE_DRAG(m->sgr_b) &&
MOUSE_BUTTONS(m->sgr_b) == 3) || MOUSE_BUTTONS(m->sgr_b) == 3) ||
(m->sgr_type == ' ' && (m->sgr_type == ' ' &&
@ -475,10 +478,8 @@ server_client_check_mouse(struct client *c, struct key_event *event)
evtimer_del(&c->click_timer); evtimer_del(&c->click_timer);
c->flags &= ~CLIENT_DOUBLECLICK; c->flags &= ~CLIENT_DOUBLECLICK;
if (m->b == c->click_button) { if (m->b == c->click_button) {
type = DOUBLE; type = NOTYPE;
x = m->x, y = m->y, b = m->b; c->flags |= CLIENT_TRIPLECLICK;
log_debug("double-click at %u,%u", x, y);
flag = CLIENT_TRIPLECLICK;
goto add_timer; goto add_timer;
} }
} else if (c->flags & CLIENT_TRIPLECLICK) { } else if (c->flags & CLIENT_TRIPLECLICK) {
@ -495,11 +496,11 @@ server_client_check_mouse(struct client *c, struct key_event *event)
type = DOWN; type = DOWN;
x = m->x, y = m->y, b = m->b; x = m->x, y = m->y, b = m->b;
log_debug("down at %u,%u", x, y); log_debug("down at %u,%u", x, y);
flag = CLIENT_DOUBLECLICK; c->flags |= CLIENT_DOUBLECLICK;
add_timer: add_timer:
if (KEYC_CLICK_TIMEOUT != 0) { if (KEYC_CLICK_TIMEOUT != 0) {
c->flags |= flag; memcpy(&c->click_event, m, sizeof c->click_event);
c->click_button = m->b; c->click_button = m->b;
tv.tv_sec = KEYC_CLICK_TIMEOUT / 1000; tv.tv_sec = KEYC_CLICK_TIMEOUT / 1000;
@ -1045,7 +1046,7 @@ server_client_key_callback(struct cmdq_item *item, void *data)
/* Check for mouse keys. */ /* Check for mouse keys. */
m->valid = 0; m->valid = 0;
if (key == KEYC_MOUSE) { if (key == KEYC_MOUSE || key == KEYC_DOUBLECLICK) {
if (c->flags & CLIENT_READONLY) if (c->flags & CLIENT_READONLY)
goto out; goto out;
key = server_client_check_mouse(c, event); key = server_client_check_mouse(c, event);
@ -1547,8 +1548,22 @@ server_client_repeat_timer(__unused int fd, __unused short events, void *data)
static void static void
server_client_click_timer(__unused int fd, __unused short events, void *data) server_client_click_timer(__unused int fd, __unused short events, void *data)
{ {
struct client *c = data; struct client *c = data;
struct key_event *event;
log_debug("click timer expired");
if (c->flags & CLIENT_TRIPLECLICK) {
/*
* Waiting for a third click that hasn't happened, so this must
* have been a double click.
*/
event = xmalloc(sizeof *event);
event->key = KEYC_DOUBLECLICK;
memcpy(&event->m, &c->click_event, sizeof event->m);
if (!server_client_handle_key(c, event))
free(event);
}
c->flags &= ~(CLIENT_DOUBLECLICK|CLIENT_TRIPLECLICK); c->flags &= ~(CLIENT_DOUBLECLICK|CLIENT_TRIPLECLICK);
} }

16
tmux.1
View File

@ -1565,7 +1565,7 @@ The synopsis for the
command is: command is:
.Bl -tag -width Ds .Bl -tag -width Ds
.It Xo Ic copy-mode .It Xo Ic copy-mode
.Op Fl Meu .Op Fl eHMu
.Op Fl t Ar target-pane .Op Fl t Ar target-pane
.Xc .Xc
Enter copy mode. Enter copy mode.
@ -1575,6 +1575,9 @@ option scrolls one page up.
.Fl M .Fl M
begins a mouse drag (only valid if bound to a mouse key binding, see begins a mouse drag (only valid if bound to a mouse key binding, see
.Sx MOUSE SUPPORT ) . .Sx MOUSE SUPPORT ) .
.Fl H
hides the position indicator in the top right.
.Pp
.Fl e .Fl e
specifies that scrolling to the bottom of the history (to the visible screen) specifies that scrolling to the bottom of the history (to the visible screen)
should exit copy mode. should exit copy mode.
@ -5200,8 +5203,9 @@ Lock each client individually by running the command specified by the
option. option.
.It Xo Ic run-shell .It Xo Ic run-shell
.Op Fl b .Op Fl b
.Op Fl d Ar delay
.Op Fl t Ar target-pane .Op Fl t Ar target-pane
.Ar shell-command .Ar [shell-command]
.Xc .Xc
.D1 (alias: Ic run ) .D1 (alias: Ic run )
Execute Execute
@ -5214,8 +5218,12 @@ section.
With With
.Fl b , .Fl b ,
the command is run in the background. the command is run in the background.
After it finishes, any output to stdout is displayed in copy mode (in the pane .Fl d
specified by waits for
.Ar delay
seconds before starting the command.
After the command finishes, any output to stdout is displayed in view mode (in
the pane specified by
.Fl t .Fl t
or the current pane if omitted). or the current pane if omitted).
If the command doesn't return success, the exit status is also displayed. If the command doesn't return success, the exit status is also displayed.

2
tmux.h
View File

@ -168,6 +168,7 @@ enum {
/* Mouse keys. */ /* Mouse keys. */
KEYC_MOUSE, /* unclassified mouse event */ KEYC_MOUSE, /* unclassified mouse event */
KEYC_DRAGGING, /* dragging in progress */ KEYC_DRAGGING, /* dragging in progress */
KEYC_DOUBLECLICK, /* double click complete */
KEYC_MOUSE_KEY(MOUSEMOVE), KEYC_MOUSE_KEY(MOUSEMOVE),
KEYC_MOUSE_KEY(MOUSEDOWN1), KEYC_MOUSE_KEY(MOUSEDOWN1),
KEYC_MOUSE_KEY(MOUSEDOWN2), KEYC_MOUSE_KEY(MOUSEDOWN2),
@ -1549,6 +1550,7 @@ struct client {
struct event click_timer; struct event click_timer;
u_int click_button; u_int click_button;
struct mouse_event click_event;
struct status_line status; struct status_line status;

View File

@ -230,6 +230,7 @@ struct window_copy_mode_data {
} lineflag; /* line selection mode */ } lineflag; /* line selection mode */
int rectflag; /* in rectangle copy mode? */ int rectflag; /* in rectangle copy mode? */
int scroll_exit; /* exit on scroll to end? */ int scroll_exit; /* exit on scroll to end? */
int hide_position; /* hide position marker */
enum { enum {
SEL_CHAR, /* select one char at a time */ SEL_CHAR, /* select one char at a time */
@ -345,6 +346,7 @@ window_copy_init(struct window_mode_entry *wme,
data->cy = data->backing->cy; data->cy = data->backing->cy;
data->scroll_exit = args_has(args, 'e'); data->scroll_exit = args_has(args, 'e');
data->hide_position = args_has(args, 'H');
data->screen.cx = data->cx; data->screen.cx = data->cx;
data->screen.cy = data->cy; data->screen.cy = data->cy;
@ -2774,7 +2776,7 @@ window_copy_write_line(struct window_mode_entry *wme,
style_apply(&gc, oo, "mode-style"); style_apply(&gc, oo, "mode-style");
gc.flags |= GRID_FLAG_NOPALETTE; gc.flags |= GRID_FLAG_NOPALETTE;
if (py == 0 && s->rupper < s->rlower) { if (py == 0 && s->rupper < s->rlower && !data->hide_position) {
if (data->searchmark == NULL) { if (data->searchmark == NULL) {
size = xsnprintf(hdr, sizeof hdr, size = xsnprintf(hdr, sizeof hdr,
"[%u/%u]", data->oy, screen_hsize(data->backing)); "[%u/%u]", data->oy, screen_hsize(data->backing));